From b28d13b3befaf8153f35962a2707975fb6782172 Mon Sep 17 00:00:00 2001 From: Fangliding Date: Wed, 14 Aug 2024 04:42:06 +0000 Subject: [PATCH] deploy: XTLS/Xray-docs-next@ea9920f65c4ab0ee6e5d25f8958580fb8edaaa65 --- 404.html | 8 ++++---- about/news.html | 6 +++--- assets/{404.html-C-V38gH_.js => 404.html-C7hQR_kQ.js} | 2 +- assets/{Mermaid-OQLZrVC0.js => Mermaid-DaLi44oU.js} | 4 ++-- assets/{Tab-Qnm7JOWy.js => Tab-Ci2eJWYz.js} | 2 +- assets/{Tabs-BWBTQACZ.js => Tabs-CXHA-R7W.js} | 2 +- assets/{api.html-DiYJU8Rg.js => api.html-Dh_ndM7D.js} | 2 +- assets/{api.html-Dimd9sC-.js => api.html-Dt8W2IKn.js} | 2 +- assets/{api.html-D-Q2V6zb.js => api.html-LpVUq3p6.js} | 2 +- assets/{app-5SoadDYS.js => app-Bw2NG-QJ.js} | 4 ++-- assets/{arc-xLaeEKkr.js => arc-C5d-KvsZ.js} | 2 +- ...ckhole.html-CeYMksfi.js => blackhole.html-BCTuFe4v.js} | 2 +- ...ckhole.html-CobmF86r.js => blackhole.html-BqrDbtFw.js} | 2 +- ...ckhole.html-EGsblD7s.js => blackhole.html-CBPzXtbg.js} | 2 +- ...6865-QPsisUYk.js => blockDiagram-9f4a6865-BqKpDrqb.js} | 2 +- ...r.html-C3dkn1hN.js => browser_dialer.html-B00Yg-45.js} | 2 +- ...r.html-BIzbQgRR.js => browser_dialer.html-C_TsP8h-.js} | 2 +- ...r.html-D_VAS8oa.js => browser_dialer.html-DTufXirY.js} | 2 +- ...e766693-TOZe-7Pl.js => c4Diagram-ae766693-DVn8Dofm.js} | 2 +- ...ace.html-D5988Uh0.js => ch01-preface.html-Bts5JwT1.js} | 2 +- ...ace.html-D5NO_n3E.js => ch01-preface.html-C6vuCTiJ.js} | 2 +- ...ace.html-CtiGatzy.js => ch01-preface.html-CVJyR7B9.js} | 2 +- ...html-zWJTI2fh.js => ch02-preparation.html-3rYGUPF0.js} | 2 +- ...html-DOc8B9wn.js => ch02-preparation.html-Bux35H5q.js} | 2 +- ...html-CBryXq1M.js => ch02-preparation.html-BuxrUsmj.js} | 2 +- ...h03-ssh.html-B-PYaYYd.js => ch03-ssh.html-10pGoOUk.js} | 2 +- ...h03-ssh.html-xo_x6se1.js => ch03-ssh.html-9CSgBxsO.js} | 2 +- ...h03-ssh.html-CKpEhhik.js => ch03-ssh.html-Bbgd91VB.js} | 2 +- ...ty.html-CDDodZLn.js => ch04-security.html-CR6Uh8v_.js} | 2 +- ...ty.html-BzzIgsFs.js => ch04-security.html-CRFoFiSw.js} | 2 +- ...ty.html-DDDnSxfv.js => ch04-security.html-DyDK2hA6.js} | 2 +- ...age.html-BHBAeKP6.js => ch05-webpage.html-3v0I9fWw.js} | 2 +- ...age.html-DR79qyrD.js => ch05-webpage.html-D09gDc8i.js} | 2 +- ...age.html-CWPEvHEd.js => ch05-webpage.html-XNRjbxse.js} | 2 +- ...tml-D3AQTy0p.js => ch06-certificates.html-BCM-NNIg.js} | 2 +- ...tml-DUHSveME.js => ch06-certificates.html-Cjl3-nTJ.js} | 2 +- ...tml-K5oNRMFq.js => ch06-certificates.html-DQoStl8T.js} | 2 +- ...html-C-3gFLNQ.js => ch07-xray-server.html-BqO-iTQU.js} | 2 +- ...html-D_AT7DH0.js => ch07-xray-server.html-DWmdh7MW.js} | 2 +- ...html-BCFis-sE.js => ch07-xray-server.html-xXsQBQ03.js} | 2 +- ...tml-DueTm8m2.js => ch08-xray-clients.html-BNAUVuV_.js} | 2 +- ...tml-CJXEK9-Y.js => ch08-xray-clients.html-Bcxw8xnI.js} | 2 +- ...tml-CxcURVTg.js => ch08-xray-clients.html-Bqf0blkP.js} | 2 +- ...ix.html-DsxMf9Eu.js => ch09-appendix.html-BP917XpD.js} | 2 +- ...ix.html-DQIQbM0Q.js => ch09-appendix.html-DHpTAQmp.js} | 2 +- ...ix.html-CCG5ZhR3.js => ch09-appendix.html-cJZrrwi6.js} | 2 +- assets/channel-C_7gBDjR.js | 1 - assets/channel-DIeeoF-2.js | 1 + ...d2a0-C9zXAHzr.js => classDiagram-fb54d2a0-CnVcQW-t.js} | 2 +- ...d-ChHu4we1.js => classDiagram-v2-a2b738ad-D4iAgbOW.js} | 2 +- assets/clone-BjoOJyl6.js | 1 + assets/clone-D0wOyyCk.js | 1 - ...{command.html-Bto6ikLY.js => command.html-C5O9QrFP.js} | 2 +- ...{command.html-D8s_eq69.js => command.html-DiZIQO57.js} | 2 +- ...{command.html-BIuE6LDM.js => command.html-wqNPUGxk.js} | 2 +- ...{compile.html-BcVx6NTs.js => compile.html-Bm6vm5gG.js} | 2 +- ...{compile.html-BmYWzF7l.js => compile.html-Csfc2z7k.js} | 2 +- ...{compile.html-C3Y8utqQ.js => compile.html-D0_Ut9wS.js} | 2 +- .../{config.html-BRKvbU_c.js => config.html-B_bOsf-2.js} | 2 +- .../{config.html-B1P46wfI.js => config.html-D5Tr_5W7.js} | 2 +- .../{config.html-BeNJtLqo.js => config.html-DXicnlDr.js} | 2 +- ...0c5216-X7RVUogw.js => createText-ca0c5216-xyt9uAlz.js} | 2 +- .../{design.html-gV_s-8kE.js => design.html-BTffej_N.js} | 2 +- .../{design.html-nD32aykc.js => design.html-Buz8frIk.js} | 2 +- .../{design.html-B4pWfzca.js => design.html-DhXmb5CJ.js} | 2 +- assets/{dns.html-DVJjxkIY.js => dns.html-CfUMjcx_.js} | 2 +- assets/{dns.html-5Ofmmx3O.js => dns.html-D-rYzT__.js} | 2 +- assets/{dns.html-DdV6b7iZ.js => dns.html-Db5UBVvD.js} | 2 +- assets/{dns.html-Rm3Jy1-p.js => dns.html-Dc7rS11a.js} | 2 +- assets/{dns.html-YTRgF6GX.js => dns.html-Dh-LYENQ.js} | 2 +- assets/{dns.html-Bv4y0xp3.js => dns.html-fTI6Udl3.js} | 2 +- ...ocument.html-DzcEysYS.js => document.html-BgS7tOmx.js} | 2 +- ...ocument.html-BoquODLh.js => document.html-DhUVedrJ.js} | 2 +- ...ocument.html-Bi2pgjPr.js => document.html-uNBJD12O.js} | 2 +- ...okodemo.html-Bt8oAJZq.js => dokodemo.html-BdfcwHNb.js} | 2 +- ...okodemo.html-DgSj7rLG.js => dokodemo.html-BeyAN9oF.js} | 2 +- ...okodemo.html-D2iCUcXO.js => dokodemo.html-C06CbLuo.js} | 2 +- ...ket.html-DOaqP0Hi.js => domainsocket.html-BAuPukib.js} | 2 +- ...ket.html-D3nBLz-F.js => domainsocket.html-CudQIOhr.js} | 2 +- ...ket.html-CaKSedJK.js => domainsocket.html-Dl3H8vlJ.js} | 2 +- ...es-066a5561-BnmFWp88.js => edges-066a5561-CIBMFaLO.js} | 2 +- assets/{env.html-CjyJA0Yb.js => env.html-5Sl2lv4f.js} | 2 +- assets/{env.html-X4QtRUwr.js => env.html-BaUecgO2.js} | 2 +- assets/{env.html-DzAnx11j.js => env.html-aOvx_pi1.js} | 2 +- ...9d1c15f-DTI3Ywn0.js => erDiagram-09d1c15f-CxugSXM3.js} | 2 +- ...{fakedns.html-BInfP9sg.js => fakedns.html-C-g4Cxj-.js} | 2 +- ...{fakedns.html-CAdn95B6.js => fakedns.html-CZTe-tiD.js} | 2 +- ...{fakedns.html-C_E8DnIz.js => fakedns.html-Dh-VkFFO.js} | 2 +- ...allback.html-P3OM7a42.js => fallback.html-BuLRpbj4.js} | 2 +- ...allback.html-DxkOyMwP.js => fallback.html-DKu1U9AN.js} | 2 +- ...allback.html-BUzHu26K.js => fallback.html-O3X9XOSg.js} | 2 +- ...v1.html-CogqnjdA.js => fallbacks-lv1.html-BCtwtJCw.js} | 2 +- ...v1.html-R7zbt45s.js => fallbacks-lv1.html-CI6CRNYF.js} | 2 +- ...v1.html-3a74qZ1k.js => fallbacks-lv1.html-DYToMiS6.js} | 2 +- ...ml-BAchho5z.js => fallbacks-with-sni.html-B0wSUJmq.js} | 2 +- ...ml-B2NZf_xW.js => fallbacks-with-sni.html-B3snUr7L.js} | 2 +- ...ml-BO2m1L8j.js => fallbacks-with-sni.html-iAcmmVov.js} | 2 +- ...b-c1833063-8FVnhkY0.js => flowDb-c1833063-Csuwz1ip.js} | 2 +- ...2e15a-ClSO8xjE.js => flowDiagram-b222e15a-CRKbP293.js} | 2 +- assets/flowDiagram-v2-13329dc7-CD3itvv-.js | 1 - assets/flowDiagram-v2-13329dc7-CUX8GDMK.js | 1 + ...o.js => flowchart-elk-definition-ae0efee6-H9NB2Lq2.js} | 2 +- ...{freedom.html-D3yZYD_4.js => freedom.html-CBf9uuEF.js} | 2 +- ...{freedom.html-DW3aa4An.js => freedom.html-CxIu6tCF.js} | 2 +- ...{freedom.html-Dxeb5oma.js => freedom.html-D6jTnnzE.js} | 2 +- ...793e-B3546ou_.js => ganttDiagram-b62c793e-BY6nXXtR.js} | 2 +- ...e-DOX28HzV.js => gitGraphDiagram-942e62fe-CmfeKiv3.js} | 2 +- assets/{graph-D2qW7eTj.js => graph-C-EgwjAv.js} | 2 +- assets/{grpc.html-mPuqwjqH.js => grpc.html-3wMb5fVh.js} | 2 +- assets/{grpc.html-BiVb6JVN.js => grpc.html-BpDUzsty.js} | 2 +- assets/{grpc.html-C_Kg2sXl.js => grpc.html-DnIgTPpb.js} | 2 +- assets/{guide.html-DPanWeGq.js => guide.html-BjshCdoe.js} | 2 +- assets/{guide.html-B3137Mcd.js => guide.html-CBLCKraa.js} | 2 +- assets/{guide.html-B4lgRyoL.js => guide.html-DIzxSc4p.js} | 2 +- assets/{h2.html-B8YU87YB.js => h2.html-BoytWKP0.js} | 2 +- assets/{h2.html-CVsBKDCJ.js => h2.html-DCbNjdYm.js} | 2 +- assets/{h2.html-OyF7YRkr.js => h2.html-llZ-kVKl.js} | 2 +- assets/{http.html-C1EqlRMw.js => http.html-BR_9tg5w.js} | 2 +- assets/{http.html-cSNMwEku.js => http.html-B_cAur_J.js} | 2 +- assets/{http.html-n_9GtPPz.js => http.html-Bp5JIQRB.js} | 2 +- assets/{http.html-_MHU72Uy.js => http.html-DXeEJWXm.js} | 2 +- assets/{http.html-DQMd16Bw.js => http.html-uCWbp3V-.js} | 2 +- assets/{http.html-DpWvFZW_.js => http.html-z9-pCapv.js} | 2 +- ...rade.html-DOscHx-c.js => httpupgrade.html-BraFT-Ya.js} | 2 +- ...rade.html-Fq7D8MW3.js => httpupgrade.html-CEqqB19n.js} | 2 +- ...rade.html-8iiyF6S8.js => httpupgrade.html-D3FZSi1K.js} | 2 +- ...{inbound.html-BPtpNn0q.js => inbound.html-BZUQiKQt.js} | 2 +- ...{inbound.html-U-YczWsT.js => inbound.html-CdeJ4snV.js} | 2 +- ...{inbound.html-xQYNwVL-.js => inbound.html-CqfgrN_A.js} | 2 +- ...ex-01f381cb-fgk8rzsW.js => index-01f381cb-DWGV-_zg.js} | 2 +- assets/{index.html-BB8VT9K-.js => index.html-B-Zn3LDM.js} | 2 +- assets/{index.html-CuC5URKY.js => index.html-B3mfyWQt.js} | 2 +- assets/{index.html-DM9ULzw6.js => index.html-BNTb1uEP.js} | 2 +- assets/{index.html-CiIdsSO_.js => index.html-Bf7-nv__.js} | 2 +- assets/{index.html-C4BsmZBc.js => index.html-BghSFULx.js} | 2 +- assets/{index.html-DKrDxjJk.js => index.html-BiwlIXs1.js} | 2 +- assets/{index.html-D5d6Z4Xz.js => index.html-BkqXAF2a.js} | 2 +- assets/{index.html-COrJaVx-.js => index.html-Bn9iOydn.js} | 2 +- assets/{index.html-Dd9_Hlk-.js => index.html-Bt40bz30.js} | 2 +- assets/{index.html-DZgNInr6.js => index.html-CH7QpluO.js} | 2 +- assets/{index.html-BIFt4COA.js => index.html-COWQPvSj.js} | 2 +- assets/{index.html--jsJa64m.js => index.html-CUkf34zC.js} | 2 +- assets/{index.html-BIpYD3t-.js => index.html-Cskgq1zk.js} | 2 +- assets/{index.html-LItYxUPJ.js => index.html-Cy2gOIhe.js} | 2 +- assets/{index.html-DdVCvmM2.js => index.html-D3N0ZGw7.js} | 2 +- assets/{index.html-ivJHL5hH.js => index.html-D9C7rXyK.js} | 2 +- assets/{index.html-BGNLRPzE.js => index.html-DAmXAAuC.js} | 2 +- assets/{index.html-BmR8xWDg.js => index.html-DLfjpS8M.js} | 2 +- assets/{index.html-CeWvtNHc.js => index.html-DPZpGJBw.js} | 2 +- assets/{index.html-YDY07G7e.js => index.html-DYkoE7_u.js} | 2 +- assets/{index.html-NLmGgv-K.js => index.html-DyQaOch3.js} | 2 +- ...d232f-I6ioXWcf.js => infoDiagram-94cd232f-Don6DG4Z.js} | 2 +- assets/install.html-7roQVGaJ.js | 1 + assets/install.html-Bqug4cnA.js | 1 - ...{install.html-f63Sv7SS.js => install.html-C6eLysya.js} | 2 +- assets/install.html-CJaw-WJD.js | 1 - ...{install.html-BrHImMB4.js => install.html-CX7I48Il.js} | 2 +- ...{install.html-DvdIFSLJ.js => install.html-Cmyvi2cp.js} | 2 +- assets/install.html-nEQK2zvn.js | 1 + ...{install.html-B3katEMP.js => install.html-xlRH6Hy9.js} | 2 +- ...gid.html-DfoRMg8P.js => iptables_gid.html-D1piuJf5.js} | 2 +- ...gid.html-C7KP3nA5.js => iptables_gid.html-DlCxBcK6.js} | 2 +- ...gid.html-BzWg4Lzk.js => iptables_gid.html-KGEztY8A.js} | 2 +- ...56-CHnHUPp6.js => journeyDiagram-6625b456-Bh6Njlro.js} | 2 +- assets/{layout-BlaWeSu5.js => layout-DSxgfneE.js} | 2 +- assets/{line-BIqtvXUi.js => line-DY_oMjHu.js} | 2 +- assets/{linear-DFdMY4Xo.js => linear-CopLvHML.js} | 2 +- assets/{log.html-QQtue8CH.js => log.html-AttB6lyK.js} | 2 +- assets/{log.html-BAb49rK4.js => log.html-BXxmwSQO.js} | 2 +- assets/{log.html-DguB3WSi.js => log.html-cALz2gHA.js} | 2 +- ...oopback.html-DZPmfXB9.js => loopback.html-BA_UAuXs.js} | 2 +- ...oopback.html-D7n84f8k.js => loopback.html-BvfOuAZH.js} | 2 +- ...oopback.html-CL9lvq8v.js => loopback.html-CsIs91x3.js} | 2 +- ...{mermaid.core-CArNAncI.js => mermaid.core-Bq0kX0MS.js} | 8 ++++---- ...{metrics.html-DAUbFlMB.js => metrics.html-Bg3SRRpG.js} | 2 +- ...{metrics.html-DtVeDNWQ.js => metrics.html-BhYJwMrZ.js} | 2 +- ...{metrics.html-DZDkDmh2.js => metrics.html-Cd9LVZWS.js} | 2 +- ...9Lm6G_A.js => mindmap-definition-307c710a-DRTTE_TY.js} | 2 +- assets/{mkcp.html-DlmPRG7s.js => mkcp.html-BC2K7D4N.js} | 2 +- assets/{mkcp.html-ET0VyK1t.js => mkcp.html-BYbEm1gj.js} | 2 +- assets/{mkcp.html-DQUcXkzK.js => mkcp.html-Clzx5P9b.js} | 2 +- assets/{mkcp.html-DVsV0BBF.js => mkcp.html-D6gGU4SN.js} | 2 +- assets/{mkcp.html-TS7-PC53.js => mkcp.html-DpdBDDHy.js} | 2 +- assets/{mkcp.html-DrAEdayP.js => mkcp.html-gKNEMwS8.js} | 2 +- ...ultiple.html-BQ0iFIBh.js => multiple.html-BhUjtgl7.js} | 2 +- ...ultiple.html-CNbc9k4q.js => multiple.html-D2THR0Xm.js} | 2 +- ...ultiple.html-d0Rz6O9q.js => multiple.html-DZg36_LG.js} | 2 +- ...{muxcool.html-BRUL_FdO.js => muxcool.html-Ch_u4leD.js} | 2 +- ...{muxcool.html-Owf2QQIZ.js => muxcool.html-DyQfxg_9.js} | 2 +- ...{muxcool.html-CDZVHREe.js => muxcool.html-hxuFgme0.js} | 2 +- assets/{news.html-IY4e89V6.js => news.html-23-ihBAh.js} | 2 +- assets/{news.html-CD7xPbzv.js => news.html-B87U8xn2.js} | 2 +- assets/{news.html-rpPeZ0HC.js => news.html-BrzeG0HS.js} | 2 +- ...AM.js => nginx_or_haproxy_tls_tunnel.html-CBNtMx0V.js} | 2 +- ...Pa.js => nginx_or_haproxy_tls_tunnel.html-CTP6KXYR.js} | 2 +- ...lJ.js => nginx_or_haproxy_tls_tunnel.html-KJNaWU2X.js} | 2 +- ...tory.html-BJ2zcm9w.js => observatory.html-BzG-DGQ7.js} | 2 +- ...tory.html-DG1jqJm8.js => observatory.html-CPlTxJvy.js} | 2 +- ...tory.html-BOdfknrn.js => observatory.html-CgCiDU6P.js} | 2 +- ...utbound.html-B1Wp8iU4.js => outbound.html-Bztbl0lH.js} | 2 +- ...utbound.html-CxLNkOG0.js => outbound.html-CGmYQFef.js} | 2 +- ...utbound.html-bdM8vFfU.js => outbound.html-DWjB8mz5.js} | 2 +- ...1d19e5-BQuVNcMJ.js => pieDiagram-bb1d19e5-CBxnSt2_.js} | 2 +- .../{policy.html-D1uwT0yS.js => policy.html-B9TBd0jy.js} | 2 +- .../{policy.html-Bq1Nx697.js => policy.html-D7HzBw03.js} | 2 +- .../{policy.html-fqGpJICm.js => policy.html-DiLfrWDT.js} | 2 +- ...2-B16G3h9g.js => quadrantDiagram-c759a472-DYqUNjWH.js} | 2 +- assets/{quic.html-DpxBi39d.js => quic.html-BSX-VjGs.js} | 2 +- assets/{quic.html-CXwWfMPP.js => quic.html-C3baIL5C.js} | 2 +- assets/{quic.html-But08Sia.js => quic.html-C8pXs3js.js} | 2 +- ...edirect.html-Mplb4Dtz.js => redirect.html-DdM9qz1d.js} | 2 +- ...edirect.html-BDtVJCJP.js => redirect.html-ZgxF37Mu.js} | 2 +- ...edirect.html-CcdbISF0.js => redirect.html-u-FkUyZi.js} | 2 +- ...4iL_vop.js => requirementDiagram-87253d64-CetQ2-l9.js} | 2 +- ...{reverse.html-DFbLOQPN.js => reverse.html-BNqd15YN.js} | 2 +- ...{reverse.html-bKcExnAb.js => reverse.html-WbzNOTcU.js} | 2 +- ...{reverse.html-By4y7JyT.js => reverse.html-xPEDZtAc.js} | 2 +- ...tml-ClnBy2hd.js => routing-lv1-part1.html-Bwge_E9k.js} | 2 +- ...tml-DGAFkfW-.js => routing-lv1-part1.html-DxoI7gBO.js} | 2 +- ...tml-WNvWtpj6.js => routing-lv1-part1.html-cn16P49Z.js} | 2 +- ...tml-BJbHs2YK.js => routing-lv1-part2.html-CfufGIyP.js} | 2 +- ...tml-B6ObFc5O.js => routing-lv1-part2.html-D-nULKCp.js} | 2 +- ...tml-d3I02cv4.js => routing-lv1-part2.html-n2aETtQH.js} | 2 +- ...{routing.html-XztNj6nv.js => routing.html-B34g5Zqk.js} | 2 +- ...{routing.html-BMa5pEvD.js => routing.html-DYlVNKuL.js} | 2 +- ...{routing.html-BFdIFNzE.js => routing.html-Diz_GMQp.js} | 2 +- ...c0f-CYIZhz1m.js => sankeyDiagram-707fac0f-Dqx64UnQ.js} | 2 +- ...3-BOatradp.js => sequenceDiagram-6894f283-CpWWhZ69.js} | 2 +- ...ocks.html-PFxiOWHW.js => shadowsocks.html-6NbUGUcS.js} | 2 +- ...ocks.html-BQWMkmYl.js => shadowsocks.html-CO6uYWSO.js} | 2 +- ...ocks.html-BRNfQWR7.js => shadowsocks.html-CvgM8qZ3.js} | 2 +- ...ocks.html-ZD0TQjd7.js => shadowsocks.html-D1p_O6W-.js} | 2 +- ...ocks.html-DAtIli5Q.js => shadowsocks.html-D9uClIut.js} | 2 +- ...ocks.html-Cdp8fuJA.js => shadowsocks.html-RjOSr0jT.js} | 2 +- assets/{socks.html-BVR1MsG-.js => socks.html-ByoOjVOD.js} | 2 +- assets/{socks.html-DRrXLc9g.js => socks.html-CBuC3RpY.js} | 2 +- assets/{socks.html-DLTwr0bp.js => socks.html-D7ljHe8-.js} | 2 +- assets/{socks.html-D9s5DGJl.js => socks.html-DRkc0qRu.js} | 2 +- assets/{socks.html-D9zJ0rmt.js => socks.html-a5bSQH2X.js} | 2 +- assets/{socks.html-CBCl0kQ3.js => socks.html-vsa94d6J.js} | 2 +- ...ithttp.html-Klo-EToo.js => splithttp.html-6TiHvgAh.js} | 2 +- ...ithttp.html-9SkrgDgl.js => splithttp.html-AYHmdotS.js} | 2 +- ...ithttp.html-C_OBv89U.js => splithttp.html-BazFP1k9.js} | 2 +- ...940d-BYrroPY3.js => stateDiagram-5dee940d-RM57nRSF.js} | 2 +- ...a-BZne08Mr.js => stateDiagram-v2-1992cada-DbY1jnSh.js} | 2 +- assets/{stats.html-Cte6ShpG.js => stats.html-DsefVpMC.js} | 2 +- assets/{stats.html-CkvTAU5q.js => stats.html-MnnldZmL.js} | 2 +- assets/{stats.html-B-9-Cpn9.js => stats.html-zgGzE1Xt.js} | 2 +- ...s-0784dbeb-C3hL6HKk.js => styles-0784dbeb-38-7TehO.js} | 2 +- ...s-483fbfea-B2onFAKT.js => styles-483fbfea-BRNgjsWa.js} | 2 +- ...s-b83b31c9-BypRRRwZ.js => styles-b83b31c9-BItTogIC.js} | 2 +- ...d1d-BWP2bQZS.js => svgDrawCommon-5e1cfd1d-CX_gVtbt.js} | 2 +- assets/{tcp.html-BV6lGrTj.js => tcp.html-BnHzgywc.js} | 2 +- assets/{tcp.html-BHSzdt5L.js => tcp.html-C8HjBlLu.js} | 2 +- assets/{tcp.html-VJNns-C5.js => tcp.html-vEvGx-7r.js} | 2 +- ...E2CBeX.js => timeline-definition-bf702344-B4DJzmYO.js} | 2 +- .../{tproxy.html-DzexlIqp.js => tproxy.html-CfIjaip9.js} | 2 +- .../{tproxy.html-BewclJzl.js => tproxy.html-DWkdG7BH.js} | 2 +- .../{tproxy.html-BR9yhgN8.js => tproxy.html-DjX-7RSF.js} | 2 +- ...-3o8j0gtN.js => tproxy_ipv4_and_ipv6.html-Cd8pbG7a.js} | 2 +- ...-D1MYaJ5_.js => tproxy_ipv4_and_ipv6.html-D9QvwytN.js} | 2 +- ...-Bk7Lv8iD.js => tproxy_ipv4_and_ipv6.html-QYKhgI6r.js} | 2 +- ...ts.html-DykdoOew.js => traffic_stats.html-Ci6G_ygz.js} | 2 +- ...ts.html-CUSefiEt.js => traffic_stats.html-DamLfymb.js} | 2 +- ...ts.html-YbH2kcvo.js => traffic_stats.html-DmKVUaJl.js} | 2 +- ...tml-Bq-tBj5F.js => transparent_proxy.html-Bml0Br0H.js} | 2 +- ...tml-DRs0jlcN.js => transparent_proxy.html-DDjaWLfB.js} | 2 +- ...tml-BpVZ3iLf.js => transparent_proxy.html-sYVo5ZWT.js} | 2 +- ...nsport.html-DBN2ZByF.js => transport.html-CMtV0LnR.js} | 2 +- ...nsport.html-BshIocQ3.js => transport.html-COHavdZy.js} | 2 +- ...nsport.html-Dzmzsfae.js => transport.html-CUhGNa4n.js} | 2 +- .../{trojan.html-CGfwGdDo.js => trojan.html-C2jCtoPN.js} | 2 +- .../{trojan.html-DmgOhScb.js => trojan.html-CSDiydOe.js} | 2 +- .../{trojan.html-D2PfY2T3.js => trojan.html-Cs7YEsIb.js} | 2 +- .../{trojan.html-CgBPDtHB.js => trojan.html-WsfP1d7V.js} | 2 +- .../{trojan.html-DvVg8oOZ.js => trojan.html-ZC1LUXUu.js} | 2 +- .../{trojan.html-GLPr9L0R.js => trojan.html-a1Coa5-Z.js} | 2 +- assets/{vless.html-CTPUBSmN.js => vless.html-B7O7xjrb.js} | 2 +- assets/{vless.html-BL9BeTeh.js => vless.html-BM3ph8gg.js} | 2 +- assets/{vless.html-CDOsAnQk.js => vless.html-BWup8Xzq.js} | 2 +- assets/{vless.html-BZ48J9S_.js => vless.html-C6f9K51N.js} | 2 +- assets/{vless.html-daOoULRK.js => vless.html-CASW7iOO.js} | 2 +- assets/{vless.html-Be1YpEZ1.js => vless.html-CxxO1Anm.js} | 2 +- assets/{vless.html-CccEA1M4.js => vless.html-D2jxsPHC.js} | 2 +- assets/{vless.html-D_sclD0U.js => vless.html-XJTROLo0.js} | 2 +- assets/{vless.html-CIaM0KTd.js => vless.html-gWexYZDk.js} | 2 +- assets/{vmess.html-DBKgR8RL.js => vmess.html-Blynvi6-.js} | 2 +- assets/{vmess.html-j0DrtN75.js => vmess.html-Bnv13XwA.js} | 2 +- assets/{vmess.html-D9LxQYXS.js => vmess.html-BtwOPh9t.js} | 2 +- assets/{vmess.html-BRWJ5o8r.js => vmess.html-CWgbIYSO.js} | 2 +- assets/{vmess.html-BNuNWfIe.js => vmess.html-CeLsjjaY.js} | 2 +- assets/{vmess.html-Dt2MIkqN.js => vmess.html-CzAuOHQq.js} | 2 +- assets/{vmess.html-DArYh1N-.js => vmess.html-Ds4NV6pk.js} | 2 +- assets/{vmess.html-D8czgnar.js => vmess.html-dZZBrBA9.js} | 2 +- assets/{vmess.html-Dw5jQJR5.js => vmess.html-gu8tRDOO.js} | 2 +- assets/{warp.html-DVfMNHe2.js => warp.html-9hKZfp2I.js} | 2 +- assets/{warp.html-CkXwKg50.js => warp.html-Bzz-XxvP.js} | 2 +- assets/{warp.html-7HQyZ8uD.js => warp.html-CO5RmDTS.js} | 2 +- ...socket.html-CQ0wGOkU.js => websocket.html-DJjmBrAj.js} | 2 +- ...socket.html-DsKOF98s.js => websocket.html-DzGXVtRP.js} | 2 +- ...socket.html-CjNLVOTf.js => websocket.html-w8ndqht7.js} | 2 +- ...eguard.html-BMXSEvNc.js => wireguard.html-CW0kotGE.js} | 2 +- ...eguard.html-CYsQqFv0.js => wireguard.html-DORXKtWu.js} | 2 +- ...eguard.html-BUaJgccu.js => wireguard.html-WCdNFPZm.js} | 2 +- assets/{work.html-CkI961Qb.js => work.html-DMYsHmaw.js} | 2 +- assets/{work.html-D1MRDeII.js => work.html-DkQ-NI9U.js} | 2 +- assets/{work.html-nHfveOL9.js => work.html-hEheaKUD.js} | 2 +- assets/{xtls.html-CNzfvmap.js => xtls.html-0Synm2Bl.js} | 2 +- assets/{xtls.html-BWSKIYgJ.js => xtls.html-BljC82lz.js} | 2 +- assets/{xtls.html-D7puBcBG.js => xtls.html-CDQXBW21.js} | 2 +- ...a6-BfE2Gore.js => xychartDiagram-f11f50a6-D1hL1lgg.js} | 2 +- config/api.html | 6 +++--- config/dns.html | 6 +++--- config/fakedns.html | 6 +++--- config/features/browser_dialer.html | 6 +++--- config/features/env.html | 6 +++--- config/features/fallback.html | 6 +++--- config/features/multiple.html | 6 +++--- config/features/xtls.html | 6 +++--- config/inbound.html | 6 +++--- config/inbounds/dokodemo.html | 6 +++--- config/inbounds/http.html | 6 +++--- config/inbounds/shadowsocks.html | 6 +++--- config/inbounds/socks.html | 6 +++--- config/inbounds/trojan.html | 6 +++--- config/inbounds/vless.html | 6 +++--- config/inbounds/vmess.html | 6 +++--- config/index.html | 6 +++--- config/log.html | 6 +++--- config/metrics.html | 6 +++--- config/observatory.html | 6 +++--- config/outbound.html | 6 +++--- config/outbounds/blackhole.html | 6 +++--- config/outbounds/dns.html | 6 +++--- config/outbounds/freedom.html | 6 +++--- config/outbounds/http.html | 6 +++--- config/outbounds/loopback.html | 6 +++--- config/outbounds/shadowsocks.html | 6 +++--- config/outbounds/socks.html | 6 +++--- config/outbounds/trojan.html | 6 +++--- config/outbounds/vless.html | 6 +++--- config/outbounds/vmess.html | 6 +++--- config/outbounds/wireguard.html | 6 +++--- config/policy.html | 6 +++--- config/reverse.html | 6 +++--- config/routing.html | 6 +++--- config/stats.html | 6 +++--- config/transport.html | 6 +++--- config/transports/domainsocket.html | 6 +++--- config/transports/grpc.html | 6 +++--- config/transports/h2.html | 6 +++--- config/transports/httpupgrade.html | 6 +++--- config/transports/mkcp.html | 6 +++--- config/transports/quic.html | 6 +++--- config/transports/splithttp.html | 6 +++--- config/transports/tcp.html | 6 +++--- config/transports/websocket.html | 6 +++--- development/index.html | 6 +++--- development/intro/compile.html | 6 +++--- development/intro/design.html | 6 +++--- development/intro/guide.html | 6 +++--- development/protocols/mkcp.html | 6 +++--- development/protocols/muxcool.html | 6 +++--- development/protocols/vless.html | 6 +++--- development/protocols/vmess.html | 6 +++--- document/command.html | 6 +++--- document/config.html | 6 +++--- document/document.html | 6 +++--- document/index.html | 6 +++--- document/install.html | 8 ++++---- document/level-0/ch01-preface.html | 6 +++--- document/level-0/ch02-preparation.html | 6 +++--- document/level-0/ch03-ssh.html | 6 +++--- document/level-0/ch04-security.html | 6 +++--- document/level-0/ch05-webpage.html | 6 +++--- document/level-0/ch06-certificates.html | 6 +++--- document/level-0/ch07-xray-server.html | 6 +++--- document/level-0/ch08-xray-clients.html | 6 +++--- document/level-0/ch09-appendix.html | 6 +++--- document/level-0/index.html | 6 +++--- document/level-1/fallbacks-lv1.html | 6 +++--- document/level-1/fallbacks-with-sni.html | 6 +++--- document/level-1/index.html | 6 +++--- document/level-1/routing-lv1-part1.html | 6 +++--- document/level-1/routing-lv1-part2.html | 6 +++--- document/level-1/work.html | 6 +++--- document/level-2/index.html | 6 +++--- document/level-2/iptables_gid.html | 6 +++--- document/level-2/nginx_or_haproxy_tls_tunnel.html | 6 +++--- document/level-2/redirect.html | 6 +++--- document/level-2/tproxy.html | 6 +++--- document/level-2/tproxy_ipv4_and_ipv6.html | 6 +++--- document/level-2/traffic_stats.html | 6 +++--- document/level-2/transparent_proxy/transparent_proxy.html | 6 +++--- document/level-2/warp.html | 6 +++--- en/about/news.html | 6 +++--- en/config/api.html | 6 +++--- en/config/dns.html | 6 +++--- en/config/fakedns.html | 6 +++--- en/config/features/browser_dialer.html | 6 +++--- en/config/features/env.html | 6 +++--- en/config/features/fallback.html | 6 +++--- en/config/features/multiple.html | 6 +++--- en/config/features/xtls.html | 6 +++--- en/config/inbound.html | 6 +++--- en/config/inbounds/dokodemo.html | 6 +++--- en/config/inbounds/http.html | 6 +++--- en/config/inbounds/shadowsocks.html | 6 +++--- en/config/inbounds/socks.html | 6 +++--- en/config/inbounds/trojan.html | 6 +++--- en/config/inbounds/vless.html | 6 +++--- en/config/inbounds/vmess.html | 6 +++--- en/config/index.html | 6 +++--- en/config/log.html | 6 +++--- en/config/metrics.html | 6 +++--- en/config/observatory.html | 6 +++--- en/config/outbound.html | 6 +++--- en/config/outbounds/blackhole.html | 6 +++--- en/config/outbounds/dns.html | 6 +++--- en/config/outbounds/freedom.html | 6 +++--- en/config/outbounds/http.html | 6 +++--- en/config/outbounds/loopback.html | 6 +++--- en/config/outbounds/shadowsocks.html | 6 +++--- en/config/outbounds/socks.html | 6 +++--- en/config/outbounds/trojan.html | 6 +++--- en/config/outbounds/vless.html | 6 +++--- en/config/outbounds/vmess.html | 6 +++--- en/config/outbounds/wireguard.html | 6 +++--- en/config/policy.html | 6 +++--- en/config/reverse.html | 6 +++--- en/config/routing.html | 6 +++--- en/config/stats.html | 6 +++--- en/config/transport.html | 6 +++--- en/config/transports/domainsocket.html | 6 +++--- en/config/transports/grpc.html | 6 +++--- en/config/transports/h2.html | 6 +++--- en/config/transports/httpupgrade.html | 6 +++--- en/config/transports/mkcp.html | 6 +++--- en/config/transports/quic.html | 6 +++--- en/config/transports/splithttp.html | 6 +++--- en/config/transports/tcp.html | 6 +++--- en/config/transports/websocket.html | 6 +++--- en/development/index.html | 6 +++--- en/development/intro/compile.html | 6 +++--- en/development/intro/design.html | 6 +++--- en/development/intro/guide.html | 6 +++--- en/development/protocols/mkcp.html | 6 +++--- en/development/protocols/muxcool.html | 6 +++--- en/development/protocols/vless.html | 6 +++--- en/development/protocols/vmess.html | 6 +++--- en/document/command.html | 6 +++--- en/document/config.html | 6 +++--- en/document/document.html | 6 +++--- en/document/index.html | 6 +++--- en/document/install.html | 8 ++++---- en/document/level-0/ch01-preface.html | 6 +++--- en/document/level-0/ch02-preparation.html | 6 +++--- en/document/level-0/ch03-ssh.html | 6 +++--- en/document/level-0/ch04-security.html | 6 +++--- en/document/level-0/ch05-webpage.html | 6 +++--- en/document/level-0/ch06-certificates.html | 6 +++--- en/document/level-0/ch07-xray-server.html | 6 +++--- en/document/level-0/ch08-xray-clients.html | 6 +++--- en/document/level-0/ch09-appendix.html | 6 +++--- en/document/level-0/index.html | 6 +++--- en/document/level-1/fallbacks-lv1.html | 6 +++--- en/document/level-1/fallbacks-with-sni.html | 6 +++--- en/document/level-1/index.html | 6 +++--- en/document/level-1/routing-lv1-part1.html | 6 +++--- en/document/level-1/routing-lv1-part2.html | 6 +++--- en/document/level-1/work.html | 6 +++--- en/document/level-2/index.html | 6 +++--- en/document/level-2/iptables_gid.html | 6 +++--- en/document/level-2/nginx_or_haproxy_tls_tunnel.html | 6 +++--- en/document/level-2/redirect.html | 6 +++--- en/document/level-2/tproxy.html | 6 +++--- en/document/level-2/tproxy_ipv4_and_ipv6.html | 6 +++--- en/document/level-2/traffic_stats.html | 6 +++--- .../level-2/transparent_proxy/transparent_proxy.html | 6 +++--- en/document/level-2/warp.html | 6 +++--- en/index.html | 6 +++--- index.html | 6 +++--- ru/about/news.html | 6 +++--- ru/config/api.html | 6 +++--- ru/config/dns.html | 6 +++--- ru/config/fakedns.html | 6 +++--- ru/config/features/browser_dialer.html | 6 +++--- ru/config/features/env.html | 6 +++--- ru/config/features/fallback.html | 6 +++--- ru/config/features/multiple.html | 6 +++--- ru/config/features/xtls.html | 6 +++--- ru/config/inbound.html | 6 +++--- ru/config/inbounds/dokodemo.html | 6 +++--- ru/config/inbounds/http.html | 6 +++--- ru/config/inbounds/shadowsocks.html | 6 +++--- ru/config/inbounds/socks.html | 6 +++--- ru/config/inbounds/trojan.html | 6 +++--- ru/config/inbounds/vless.html | 6 +++--- ru/config/inbounds/vmess.html | 6 +++--- ru/config/index.html | 6 +++--- ru/config/log.html | 6 +++--- ru/config/metrics.html | 6 +++--- ru/config/observatory.html | 6 +++--- ru/config/outbound.html | 6 +++--- ru/config/outbounds/blackhole.html | 6 +++--- ru/config/outbounds/dns.html | 6 +++--- ru/config/outbounds/freedom.html | 6 +++--- ru/config/outbounds/http.html | 6 +++--- ru/config/outbounds/loopback.html | 6 +++--- ru/config/outbounds/shadowsocks.html | 6 +++--- ru/config/outbounds/socks.html | 6 +++--- ru/config/outbounds/trojan.html | 6 +++--- ru/config/outbounds/vless.html | 6 +++--- ru/config/outbounds/vmess.html | 6 +++--- ru/config/outbounds/wireguard.html | 6 +++--- ru/config/policy.html | 6 +++--- ru/config/reverse.html | 6 +++--- ru/config/routing.html | 6 +++--- ru/config/stats.html | 6 +++--- ru/config/transport.html | 6 +++--- ru/config/transports/domainsocket.html | 6 +++--- ru/config/transports/grpc.html | 6 +++--- ru/config/transports/h2.html | 6 +++--- ru/config/transports/httpupgrade.html | 6 +++--- ru/config/transports/mkcp.html | 6 +++--- ru/config/transports/quic.html | 6 +++--- ru/config/transports/splithttp.html | 6 +++--- ru/config/transports/tcp.html | 6 +++--- ru/config/transports/websocket.html | 6 +++--- ru/development/index.html | 6 +++--- ru/development/intro/compile.html | 6 +++--- ru/development/intro/design.html | 6 +++--- ru/development/intro/guide.html | 6 +++--- ru/development/protocols/mkcp.html | 6 +++--- ru/development/protocols/muxcool.html | 6 +++--- ru/development/protocols/vless.html | 6 +++--- ru/development/protocols/vmess.html | 6 +++--- ru/document/command.html | 6 +++--- ru/document/config.html | 6 +++--- ru/document/document.html | 6 +++--- ru/document/index.html | 6 +++--- ru/document/install.html | 8 ++++---- ru/document/level-0/ch01-preface.html | 6 +++--- ru/document/level-0/ch02-preparation.html | 6 +++--- ru/document/level-0/ch03-ssh.html | 6 +++--- ru/document/level-0/ch04-security.html | 6 +++--- ru/document/level-0/ch05-webpage.html | 6 +++--- ru/document/level-0/ch06-certificates.html | 6 +++--- ru/document/level-0/ch07-xray-server.html | 6 +++--- ru/document/level-0/ch08-xray-clients.html | 6 +++--- ru/document/level-0/ch09-appendix.html | 6 +++--- ru/document/level-0/index.html | 6 +++--- ru/document/level-1/fallbacks-lv1.html | 6 +++--- ru/document/level-1/fallbacks-with-sni.html | 6 +++--- ru/document/level-1/index.html | 6 +++--- ru/document/level-1/routing-lv1-part1.html | 6 +++--- ru/document/level-1/routing-lv1-part2.html | 6 +++--- ru/document/level-1/work.html | 6 +++--- ru/document/level-2/index.html | 6 +++--- ru/document/level-2/iptables_gid.html | 6 +++--- ru/document/level-2/nginx_or_haproxy_tls_tunnel.html | 6 +++--- ru/document/level-2/redirect.html | 6 +++--- ru/document/level-2/tproxy.html | 6 +++--- ru/document/level-2/tproxy_ipv4_and_ipv6.html | 6 +++--- ru/document/level-2/traffic_stats.html | 6 +++--- .../level-2/transparent_proxy/transparent_proxy.html | 6 +++--- ru/document/level-2/warp.html | 6 +++--- ru/index.html | 6 +++--- 568 files changed, 1090 insertions(+), 1090 deletions(-) rename assets/{404.html-C-V38gH_.js => 404.html-C7hQR_kQ.js} (63%) rename assets/{Mermaid-OQLZrVC0.js => Mermaid-DaLi44oU.js} (89%) rename assets/{Tab-Qnm7JOWy.js => Tab-Ci2eJWYz.js} (89%) rename assets/{Tabs-BWBTQACZ.js => Tabs-CXHA-R7W.js} (95%) rename assets/{api.html-DiYJU8Rg.js => api.html-Dh_ndM7D.js} (99%) rename assets/{api.html-Dimd9sC-.js => api.html-Dt8W2IKn.js} (99%) rename assets/{api.html-D-Q2V6zb.js => api.html-LpVUq3p6.js} (99%) rename assets/{app-5SoadDYS.js => app-Bw2NG-QJ.js} (95%) rename assets/{arc-xLaeEKkr.js => arc-C5d-KvsZ.js} (96%) rename assets/{blackhole.html-CeYMksfi.js => blackhole.html-BCTuFe4v.js} (97%) rename assets/{blackhole.html-CobmF86r.js => blackhole.html-BqrDbtFw.js} (97%) rename assets/{blackhole.html-EGsblD7s.js => blackhole.html-CBPzXtbg.js} (98%) rename assets/{blockDiagram-9f4a6865-QPsisUYk.js => blockDiagram-9f4a6865-BqKpDrqb.js} (98%) rename assets/{browser_dialer.html-C3dkn1hN.js => browser_dialer.html-B00Yg-45.js} (99%) rename assets/{browser_dialer.html-BIzbQgRR.js => browser_dialer.html-C_TsP8h-.js} (98%) rename assets/{browser_dialer.html-D_VAS8oa.js => browser_dialer.html-DTufXirY.js} (99%) rename assets/{c4Diagram-ae766693-TOZe-7Pl.js => c4Diagram-ae766693-DVn8Dofm.js} (99%) rename assets/{ch01-preface.html-D5988Uh0.js => ch01-preface.html-Bts5JwT1.js} (99%) rename assets/{ch01-preface.html-D5NO_n3E.js => ch01-preface.html-C6vuCTiJ.js} (99%) rename assets/{ch01-preface.html-CtiGatzy.js => ch01-preface.html-CVJyR7B9.js} (99%) rename assets/{ch02-preparation.html-zWJTI2fh.js => ch02-preparation.html-3rYGUPF0.js} (98%) rename assets/{ch02-preparation.html-DOc8B9wn.js => ch02-preparation.html-Bux35H5q.js} (99%) rename assets/{ch02-preparation.html-CBryXq1M.js => ch02-preparation.html-BuxrUsmj.js} (98%) rename assets/{ch03-ssh.html-B-PYaYYd.js => ch03-ssh.html-10pGoOUk.js} (99%) rename assets/{ch03-ssh.html-xo_x6se1.js => ch03-ssh.html-9CSgBxsO.js} (99%) rename assets/{ch03-ssh.html-CKpEhhik.js => ch03-ssh.html-Bbgd91VB.js} (99%) rename assets/{ch04-security.html-CDDodZLn.js => ch04-security.html-CR6Uh8v_.js} (99%) rename assets/{ch04-security.html-BzzIgsFs.js => ch04-security.html-CRFoFiSw.js} (99%) rename assets/{ch04-security.html-DDDnSxfv.js => ch04-security.html-DyDK2hA6.js} (99%) rename assets/{ch05-webpage.html-BHBAeKP6.js => ch05-webpage.html-3v0I9fWw.js} (99%) rename assets/{ch05-webpage.html-DR79qyrD.js => ch05-webpage.html-D09gDc8i.js} (99%) rename assets/{ch05-webpage.html-CWPEvHEd.js => ch05-webpage.html-XNRjbxse.js} (99%) rename assets/{ch06-certificates.html-D3AQTy0p.js => ch06-certificates.html-BCM-NNIg.js} (99%) rename assets/{ch06-certificates.html-DUHSveME.js => ch06-certificates.html-Cjl3-nTJ.js} (99%) rename assets/{ch06-certificates.html-K5oNRMFq.js => ch06-certificates.html-DQoStl8T.js} (99%) rename assets/{ch07-xray-server.html-C-3gFLNQ.js => ch07-xray-server.html-BqO-iTQU.js} (99%) rename assets/{ch07-xray-server.html-D_AT7DH0.js => ch07-xray-server.html-DWmdh7MW.js} (99%) rename assets/{ch07-xray-server.html-BCFis-sE.js => ch07-xray-server.html-xXsQBQ03.js} (99%) rename assets/{ch08-xray-clients.html-DueTm8m2.js => ch08-xray-clients.html-BNAUVuV_.js} (99%) rename assets/{ch08-xray-clients.html-CJXEK9-Y.js => ch08-xray-clients.html-Bcxw8xnI.js} (99%) rename assets/{ch08-xray-clients.html-CxcURVTg.js => ch08-xray-clients.html-Bqf0blkP.js} (99%) rename assets/{ch09-appendix.html-DsxMf9Eu.js => ch09-appendix.html-BP917XpD.js} (99%) rename assets/{ch09-appendix.html-DQIQbM0Q.js => ch09-appendix.html-DHpTAQmp.js} (99%) rename assets/{ch09-appendix.html-CCG5ZhR3.js => ch09-appendix.html-cJZrrwi6.js} (99%) delete mode 100644 assets/channel-C_7gBDjR.js create mode 100644 assets/channel-DIeeoF-2.js rename assets/{classDiagram-fb54d2a0-C9zXAHzr.js => classDiagram-fb54d2a0-CnVcQW-t.js} (97%) rename assets/{classDiagram-v2-a2b738ad-ChHu4we1.js => classDiagram-v2-a2b738ad-D4iAgbOW.js} (92%) create mode 100644 assets/clone-BjoOJyl6.js delete mode 100644 assets/clone-D0wOyyCk.js rename assets/{command.html-Bto6ikLY.js => command.html-C5O9QrFP.js} (99%) rename assets/{command.html-D8s_eq69.js => command.html-DiZIQO57.js} (99%) rename assets/{command.html-BIuE6LDM.js => command.html-wqNPUGxk.js} (99%) rename assets/{compile.html-BcVx6NTs.js => compile.html-Bm6vm5gG.js} (99%) rename assets/{compile.html-BmYWzF7l.js => compile.html-Csfc2z7k.js} (99%) rename assets/{compile.html-C3Y8utqQ.js => compile.html-D0_Ut9wS.js} (99%) rename assets/{config.html-BRKvbU_c.js => config.html-B_bOsf-2.js} (99%) rename assets/{config.html-B1P46wfI.js => config.html-D5Tr_5W7.js} (99%) rename assets/{config.html-BeNJtLqo.js => config.html-DXicnlDr.js} (99%) rename assets/{createText-ca0c5216-X7RVUogw.js => createText-ca0c5216-xyt9uAlz.js} (99%) rename assets/{design.html-gV_s-8kE.js => design.html-BTffej_N.js} (97%) rename assets/{design.html-nD32aykc.js => design.html-Buz8frIk.js} (98%) rename assets/{design.html-B4pWfzca.js => design.html-DhXmb5CJ.js} (97%) rename assets/{dns.html-DVJjxkIY.js => dns.html-CfUMjcx_.js} (99%) rename assets/{dns.html-5Ofmmx3O.js => dns.html-D-rYzT__.js} (98%) rename assets/{dns.html-DdV6b7iZ.js => dns.html-Db5UBVvD.js} (99%) rename assets/{dns.html-Rm3Jy1-p.js => dns.html-Dc7rS11a.js} (98%) rename assets/{dns.html-YTRgF6GX.js => dns.html-Dh-LYENQ.js} (99%) rename assets/{dns.html-Bv4y0xp3.js => dns.html-fTI6Udl3.js} (98%) rename assets/{document.html-DzcEysYS.js => document.html-BgS7tOmx.js} (98%) rename assets/{document.html-BoquODLh.js => document.html-DhUVedrJ.js} (98%) rename assets/{document.html-Bi2pgjPr.js => document.html-uNBJD12O.js} (98%) rename assets/{dokodemo.html-Bt8oAJZq.js => dokodemo.html-BdfcwHNb.js} (99%) rename assets/{dokodemo.html-DgSj7rLG.js => dokodemo.html-BeyAN9oF.js} (98%) rename assets/{dokodemo.html-D2iCUcXO.js => dokodemo.html-C06CbLuo.js} (99%) rename assets/{domainsocket.html-DOaqP0Hi.js => domainsocket.html-BAuPukib.js} (98%) rename assets/{domainsocket.html-D3nBLz-F.js => domainsocket.html-CudQIOhr.js} (98%) rename assets/{domainsocket.html-CaKSedJK.js => domainsocket.html-Dl3H8vlJ.js} (97%) rename assets/{edges-066a5561-BnmFWp88.js => edges-066a5561-CIBMFaLO.js} (99%) rename assets/{env.html-CjyJA0Yb.js => env.html-5Sl2lv4f.js} (97%) rename assets/{env.html-X4QtRUwr.js => env.html-BaUecgO2.js} (98%) rename assets/{env.html-DzAnx11j.js => env.html-aOvx_pi1.js} (97%) rename assets/{erDiagram-09d1c15f-DTI3Ywn0.js => erDiagram-09d1c15f-CxugSXM3.js} (99%) rename assets/{fakedns.html-BInfP9sg.js => fakedns.html-C-g4Cxj-.js} (99%) rename assets/{fakedns.html-CAdn95B6.js => fakedns.html-CZTe-tiD.js} (99%) rename assets/{fakedns.html-C_E8DnIz.js => fakedns.html-Dh-VkFFO.js} (99%) rename assets/{fallback.html-P3OM7a42.js => fallback.html-BuLRpbj4.js} (99%) rename assets/{fallback.html-DxkOyMwP.js => fallback.html-DKu1U9AN.js} (99%) rename assets/{fallback.html-BUzHu26K.js => fallback.html-O3X9XOSg.js} (99%) rename assets/{fallbacks-lv1.html-CogqnjdA.js => fallbacks-lv1.html-BCtwtJCw.js} (99%) rename assets/{fallbacks-lv1.html-R7zbt45s.js => fallbacks-lv1.html-CI6CRNYF.js} (99%) rename assets/{fallbacks-lv1.html-3a74qZ1k.js => fallbacks-lv1.html-DYToMiS6.js} (99%) rename assets/{fallbacks-with-sni.html-BAchho5z.js => fallbacks-with-sni.html-B0wSUJmq.js} (99%) rename assets/{fallbacks-with-sni.html-B2NZf_xW.js => fallbacks-with-sni.html-B3snUr7L.js} (99%) rename assets/{fallbacks-with-sni.html-BO2m1L8j.js => fallbacks-with-sni.html-iAcmmVov.js} (99%) rename assets/{flowDb-c1833063-8FVnhkY0.js => flowDb-c1833063-Csuwz1ip.js} (99%) rename assets/{flowDiagram-b222e15a-ClSO8xjE.js => flowDiagram-b222e15a-CRKbP293.js} (97%) delete mode 100644 assets/flowDiagram-v2-13329dc7-CD3itvv-.js create mode 100644 assets/flowDiagram-v2-13329dc7-CUX8GDMK.js rename assets/{flowchart-elk-definition-ae0efee6-Df6_ziIo.js => flowchart-elk-definition-ae0efee6-H9NB2Lq2.js} (99%) rename assets/{freedom.html-D3yZYD_4.js => freedom.html-CBf9uuEF.js} (99%) rename assets/{freedom.html-DW3aa4An.js => freedom.html-CxIu6tCF.js} (98%) rename assets/{freedom.html-Dxeb5oma.js => freedom.html-D6jTnnzE.js} (99%) rename assets/{ganttDiagram-b62c793e-B3546ou_.js => ganttDiagram-b62c793e-BY6nXXtR.js} (99%) rename assets/{gitGraphDiagram-942e62fe-DOX28HzV.js => gitGraphDiagram-942e62fe-CmfeKiv3.js} (99%) rename assets/{graph-D2qW7eTj.js => graph-C-EgwjAv.js} (99%) rename assets/{grpc.html-mPuqwjqH.js => grpc.html-3wMb5fVh.js} (99%) rename assets/{grpc.html-BiVb6JVN.js => grpc.html-BpDUzsty.js} (99%) rename assets/{grpc.html-C_Kg2sXl.js => grpc.html-DnIgTPpb.js} (99%) rename assets/{guide.html-DPanWeGq.js => guide.html-BjshCdoe.js} (99%) rename assets/{guide.html-B3137Mcd.js => guide.html-CBLCKraa.js} (99%) rename assets/{guide.html-B4lgRyoL.js => guide.html-DIzxSc4p.js} (99%) rename assets/{h2.html-B8YU87YB.js => h2.html-BoytWKP0.js} (98%) rename assets/{h2.html-CVsBKDCJ.js => h2.html-DCbNjdYm.js} (98%) rename assets/{h2.html-OyF7YRkr.js => h2.html-llZ-kVKl.js} (99%) rename assets/{http.html-C1EqlRMw.js => http.html-BR_9tg5w.js} (98%) rename assets/{http.html-cSNMwEku.js => http.html-B_cAur_J.js} (99%) rename assets/{http.html-n_9GtPPz.js => http.html-Bp5JIQRB.js} (98%) rename assets/{http.html-_MHU72Uy.js => http.html-DXeEJWXm.js} (98%) rename assets/{http.html-DQMd16Bw.js => http.html-uCWbp3V-.js} (98%) rename assets/{http.html-DpWvFZW_.js => http.html-z9-pCapv.js} (98%) rename assets/{httpupgrade.html-DOscHx-c.js => httpupgrade.html-BraFT-Ya.js} (98%) rename assets/{httpupgrade.html-Fq7D8MW3.js => httpupgrade.html-CEqqB19n.js} (98%) rename assets/{httpupgrade.html-8iiyF6S8.js => httpupgrade.html-D3FZSi1K.js} (98%) rename assets/{inbound.html-BPtpNn0q.js => inbound.html-BZUQiKQt.js} (99%) rename assets/{inbound.html-U-YczWsT.js => inbound.html-CdeJ4snV.js} (99%) rename assets/{inbound.html-xQYNwVL-.js => inbound.html-CqfgrN_A.js} (99%) rename assets/{index-01f381cb-fgk8rzsW.js => index-01f381cb-DWGV-_zg.js} (96%) rename assets/{index.html-BB8VT9K-.js => index.html-B-Zn3LDM.js} (97%) rename assets/{index.html-CuC5URKY.js => index.html-B3mfyWQt.js} (98%) rename assets/{index.html-DM9ULzw6.js => index.html-BNTb1uEP.js} (98%) rename assets/{index.html-CiIdsSO_.js => index.html-Bf7-nv__.js} (98%) rename assets/{index.html-C4BsmZBc.js => index.html-BghSFULx.js} (97%) rename assets/{index.html-DKrDxjJk.js => index.html-BiwlIXs1.js} (98%) rename assets/{index.html-D5d6Z4Xz.js => index.html-BkqXAF2a.js} (98%) rename assets/{index.html-COrJaVx-.js => index.html-Bn9iOydn.js} (99%) rename assets/{index.html-Dd9_Hlk-.js => index.html-Bt40bz30.js} (98%) rename assets/{index.html-DZgNInr6.js => index.html-CH7QpluO.js} (94%) rename assets/{index.html-BIFt4COA.js => index.html-COWQPvSj.js} (98%) rename assets/{index.html--jsJa64m.js => index.html-CUkf34zC.js} (98%) rename assets/{index.html-BIpYD3t-.js => index.html-Cskgq1zk.js} (98%) rename assets/{index.html-LItYxUPJ.js => index.html-Cy2gOIhe.js} (98%) rename assets/{index.html-DdVCvmM2.js => index.html-D3N0ZGw7.js} (97%) rename assets/{index.html-ivJHL5hH.js => index.html-D9C7rXyK.js} (99%) rename assets/{index.html-BGNLRPzE.js => index.html-DAmXAAuC.js} (98%) rename assets/{index.html-BmR8xWDg.js => index.html-DLfjpS8M.js} (94%) rename assets/{index.html-CeWvtNHc.js => index.html-DPZpGJBw.js} (99%) rename assets/{index.html-YDY07G7e.js => index.html-DYkoE7_u.js} (96%) rename assets/{index.html-NLmGgv-K.js => index.html-DyQaOch3.js} (99%) rename assets/{infoDiagram-94cd232f-I6ioXWcf.js => infoDiagram-94cd232f-Don6DG4Z.js} (98%) create mode 100644 assets/install.html-7roQVGaJ.js delete mode 100644 assets/install.html-Bqug4cnA.js rename assets/{install.html-f63Sv7SS.js => install.html-C6eLysya.js} (65%) delete mode 100644 assets/install.html-CJaw-WJD.js rename assets/{install.html-BrHImMB4.js => install.html-CX7I48Il.js} (99%) rename assets/{install.html-DvdIFSLJ.js => install.html-Cmyvi2cp.js} (96%) create mode 100644 assets/install.html-nEQK2zvn.js rename assets/{install.html-B3katEMP.js => install.html-xlRH6Hy9.js} (70%) rename assets/{iptables_gid.html-DfoRMg8P.js => iptables_gid.html-D1piuJf5.js} (99%) rename assets/{iptables_gid.html-C7KP3nA5.js => iptables_gid.html-DlCxBcK6.js} (99%) rename assets/{iptables_gid.html-BzWg4Lzk.js => iptables_gid.html-KGEztY8A.js} (99%) rename assets/{journeyDiagram-6625b456-CHnHUPp6.js => journeyDiagram-6625b456-Bh6Njlro.js} (98%) rename assets/{layout-BlaWeSu5.js => layout-DSxgfneE.js} (99%) rename assets/{line-BIqtvXUi.js => line-DY_oMjHu.js} (93%) rename assets/{linear-DFdMY4Xo.js => linear-CopLvHML.js} (99%) rename assets/{log.html-QQtue8CH.js => log.html-AttB6lyK.js} (96%) rename assets/{log.html-BAb49rK4.js => log.html-BXxmwSQO.js} (96%) rename assets/{log.html-DguB3WSi.js => log.html-cALz2gHA.js} (98%) rename assets/{loopback.html-DZPmfXB9.js => loopback.html-BA_UAuXs.js} (96%) rename assets/{loopback.html-D7n84f8k.js => loopback.html-BvfOuAZH.js} (99%) rename assets/{loopback.html-CL9lvq8v.js => loopback.html-CsIs91x3.js} (99%) rename assets/{mermaid.core-CArNAncI.js => mermaid.core-Bq0kX0MS.js} (98%) rename assets/{metrics.html-DAUbFlMB.js => metrics.html-Bg3SRRpG.js} (99%) rename assets/{metrics.html-DtVeDNWQ.js => metrics.html-BhYJwMrZ.js} (99%) rename assets/{metrics.html-DZDkDmh2.js => metrics.html-Cd9LVZWS.js} (99%) rename assets/{mindmap-definition-307c710a-C9Lm6G_A.js => mindmap-definition-307c710a-DRTTE_TY.js} (99%) rename assets/{mkcp.html-DlmPRG7s.js => mkcp.html-BC2K7D4N.js} (98%) rename assets/{mkcp.html-ET0VyK1t.js => mkcp.html-BYbEm1gj.js} (99%) rename assets/{mkcp.html-DQUcXkzK.js => mkcp.html-Clzx5P9b.js} (99%) rename assets/{mkcp.html-DVsV0BBF.js => mkcp.html-D6gGU4SN.js} (98%) rename assets/{mkcp.html-TS7-PC53.js => mkcp.html-DpdBDDHy.js} (98%) rename assets/{mkcp.html-DrAEdayP.js => mkcp.html-gKNEMwS8.js} (99%) rename assets/{multiple.html-BQ0iFIBh.js => multiple.html-BhUjtgl7.js} (99%) rename assets/{multiple.html-CNbc9k4q.js => multiple.html-D2THR0Xm.js} (99%) rename assets/{multiple.html-d0Rz6O9q.js => multiple.html-DZg36_LG.js} (99%) rename assets/{muxcool.html-BRUL_FdO.js => muxcool.html-Ch_u4leD.js} (99%) rename assets/{muxcool.html-Owf2QQIZ.js => muxcool.html-DyQfxg_9.js} (98%) rename assets/{muxcool.html-CDZVHREe.js => muxcool.html-hxuFgme0.js} (99%) rename assets/{news.html-IY4e89V6.js => news.html-23-ihBAh.js} (99%) rename assets/{news.html-CD7xPbzv.js => news.html-B87U8xn2.js} (99%) rename assets/{news.html-rpPeZ0HC.js => news.html-BrzeG0HS.js} (99%) rename assets/{nginx_or_haproxy_tls_tunnel.html-DNk6WbAM.js => nginx_or_haproxy_tls_tunnel.html-CBNtMx0V.js} (99%) rename assets/{nginx_or_haproxy_tls_tunnel.html-DOgxvrPa.js => nginx_or_haproxy_tls_tunnel.html-CTP6KXYR.js} (99%) rename assets/{nginx_or_haproxy_tls_tunnel.html-DatcYtlJ.js => nginx_or_haproxy_tls_tunnel.html-KJNaWU2X.js} (99%) rename assets/{observatory.html-BJ2zcm9w.js => observatory.html-BzG-DGQ7.js} (99%) rename assets/{observatory.html-DG1jqJm8.js => observatory.html-CPlTxJvy.js} (99%) rename assets/{observatory.html-BOdfknrn.js => observatory.html-CgCiDU6P.js} (99%) rename assets/{outbound.html-B1Wp8iU4.js => outbound.html-Bztbl0lH.js} (99%) rename assets/{outbound.html-CxLNkOG0.js => outbound.html-CGmYQFef.js} (99%) rename assets/{outbound.html-bdM8vFfU.js => outbound.html-DWjB8mz5.js} (99%) rename assets/{pieDiagram-bb1d19e5-BQuVNcMJ.js => pieDiagram-bb1d19e5-CBxnSt2_.js} (98%) rename assets/{policy.html-D1uwT0yS.js => policy.html-B9TBd0jy.js} (99%) rename assets/{policy.html-Bq1Nx697.js => policy.html-D7HzBw03.js} (98%) rename assets/{policy.html-fqGpJICm.js => policy.html-DiLfrWDT.js} (98%) rename assets/{quadrantDiagram-c759a472-B16G3h9g.js => quadrantDiagram-c759a472-DYqUNjWH.js} (99%) rename assets/{quic.html-DpxBi39d.js => quic.html-BSX-VjGs.js} (97%) rename assets/{quic.html-CXwWfMPP.js => quic.html-C3baIL5C.js} (98%) rename assets/{quic.html-But08Sia.js => quic.html-C8pXs3js.js} (98%) rename assets/{redirect.html-Mplb4Dtz.js => redirect.html-DdM9qz1d.js} (99%) rename assets/{redirect.html-BDtVJCJP.js => redirect.html-ZgxF37Mu.js} (99%) rename assets/{redirect.html-CcdbISF0.js => redirect.html-u-FkUyZi.js} (99%) rename assets/{requirementDiagram-87253d64-K4iL_vop.js => requirementDiagram-87253d64-CetQ2-l9.js} (98%) rename assets/{reverse.html-DFbLOQPN.js => reverse.html-BNqd15YN.js} (99%) rename assets/{reverse.html-bKcExnAb.js => reverse.html-WbzNOTcU.js} (99%) rename assets/{reverse.html-By4y7JyT.js => reverse.html-xPEDZtAc.js} (99%) rename assets/{routing-lv1-part1.html-ClnBy2hd.js => routing-lv1-part1.html-Bwge_E9k.js} (99%) rename assets/{routing-lv1-part1.html-DGAFkfW-.js => routing-lv1-part1.html-DxoI7gBO.js} (99%) rename assets/{routing-lv1-part1.html-WNvWtpj6.js => routing-lv1-part1.html-cn16P49Z.js} (99%) rename assets/{routing-lv1-part2.html-BJbHs2YK.js => routing-lv1-part2.html-CfufGIyP.js} (99%) rename assets/{routing-lv1-part2.html-B6ObFc5O.js => routing-lv1-part2.html-D-nULKCp.js} (99%) rename assets/{routing-lv1-part2.html-d3I02cv4.js => routing-lv1-part2.html-n2aETtQH.js} (99%) rename assets/{routing.html-XztNj6nv.js => routing.html-B34g5Zqk.js} (99%) rename assets/{routing.html-BMa5pEvD.js => routing.html-DYlVNKuL.js} (99%) rename assets/{routing.html-BFdIFNzE.js => routing.html-Diz_GMQp.js} (99%) rename assets/{sankeyDiagram-707fac0f-CYIZhz1m.js => sankeyDiagram-707fac0f-Dqx64UnQ.js} (99%) rename assets/{sequenceDiagram-6894f283-BOatradp.js => sequenceDiagram-6894f283-CpWWhZ69.js} (99%) rename assets/{shadowsocks.html-PFxiOWHW.js => shadowsocks.html-6NbUGUcS.js} (99%) rename assets/{shadowsocks.html-BQWMkmYl.js => shadowsocks.html-CO6uYWSO.js} (99%) rename assets/{shadowsocks.html-BRNfQWR7.js => shadowsocks.html-CvgM8qZ3.js} (99%) rename assets/{shadowsocks.html-ZD0TQjd7.js => shadowsocks.html-D1p_O6W-.js} (99%) rename assets/{shadowsocks.html-DAtIli5Q.js => shadowsocks.html-D9uClIut.js} (99%) rename assets/{shadowsocks.html-Cdp8fuJA.js => shadowsocks.html-RjOSr0jT.js} (99%) rename assets/{socks.html-BVR1MsG-.js => socks.html-ByoOjVOD.js} (99%) rename assets/{socks.html-DRrXLc9g.js => socks.html-CBuC3RpY.js} (99%) rename assets/{socks.html-DLTwr0bp.js => socks.html-D7ljHe8-.js} (99%) rename assets/{socks.html-D9s5DGJl.js => socks.html-DRkc0qRu.js} (98%) rename assets/{socks.html-D9zJ0rmt.js => socks.html-a5bSQH2X.js} (98%) rename assets/{socks.html-CBCl0kQ3.js => socks.html-vsa94d6J.js} (99%) rename assets/{splithttp.html-Klo-EToo.js => splithttp.html-6TiHvgAh.js} (99%) rename assets/{splithttp.html-9SkrgDgl.js => splithttp.html-AYHmdotS.js} (99%) rename assets/{splithttp.html-C_OBv89U.js => splithttp.html-BazFP1k9.js} (99%) rename assets/{stateDiagram-5dee940d-BYrroPY3.js => stateDiagram-5dee940d-RM57nRSF.js} (97%) rename assets/{stateDiagram-v2-1992cada-BZne08Mr.js => stateDiagram-v2-1992cada-DbY1jnSh.js} (90%) rename assets/{stats.html-Cte6ShpG.js => stats.html-DsefVpMC.js} (98%) rename assets/{stats.html-CkvTAU5q.js => stats.html-MnnldZmL.js} (97%) rename assets/{stats.html-B-9-Cpn9.js => stats.html-zgGzE1Xt.js} (97%) rename assets/{styles-0784dbeb-C3hL6HKk.js => styles-0784dbeb-38-7TehO.js} (99%) rename assets/{styles-483fbfea-B2onFAKT.js => styles-483fbfea-BRNgjsWa.js} (98%) rename assets/{styles-b83b31c9-BypRRRwZ.js => styles-b83b31c9-BItTogIC.js} (99%) rename assets/{svgDrawCommon-5e1cfd1d-BWP2bQZS.js => svgDrawCommon-5e1cfd1d-CX_gVtbt.js} (95%) rename assets/{tcp.html-BV6lGrTj.js => tcp.html-BnHzgywc.js} (99%) rename assets/{tcp.html-BHSzdt5L.js => tcp.html-C8HjBlLu.js} (99%) rename assets/{tcp.html-VJNns-C5.js => tcp.html-vEvGx-7r.js} (99%) rename assets/{timeline-definition-bf702344-D6E2CBeX.js => timeline-definition-bf702344-B4DJzmYO.js} (99%) rename assets/{tproxy.html-DzexlIqp.js => tproxy.html-CfIjaip9.js} (99%) rename assets/{tproxy.html-BewclJzl.js => tproxy.html-DWkdG7BH.js} (99%) rename assets/{tproxy.html-BR9yhgN8.js => tproxy.html-DjX-7RSF.js} (99%) rename assets/{tproxy_ipv4_and_ipv6.html-3o8j0gtN.js => tproxy_ipv4_and_ipv6.html-Cd8pbG7a.js} (99%) rename assets/{tproxy_ipv4_and_ipv6.html-D1MYaJ5_.js => tproxy_ipv4_and_ipv6.html-D9QvwytN.js} (99%) rename assets/{tproxy_ipv4_and_ipv6.html-Bk7Lv8iD.js => tproxy_ipv4_and_ipv6.html-QYKhgI6r.js} (99%) rename assets/{traffic_stats.html-DykdoOew.js => traffic_stats.html-Ci6G_ygz.js} (99%) rename assets/{traffic_stats.html-CUSefiEt.js => traffic_stats.html-DamLfymb.js} (99%) rename assets/{traffic_stats.html-YbH2kcvo.js => traffic_stats.html-DmKVUaJl.js} (99%) rename assets/{transparent_proxy.html-Bq-tBj5F.js => transparent_proxy.html-Bml0Br0H.js} (99%) rename assets/{transparent_proxy.html-DRs0jlcN.js => transparent_proxy.html-DDjaWLfB.js} (99%) rename assets/{transparent_proxy.html-BpVZ3iLf.js => transparent_proxy.html-sYVo5ZWT.js} (99%) rename assets/{transport.html-DBN2ZByF.js => transport.html-CMtV0LnR.js} (99%) rename assets/{transport.html-BshIocQ3.js => transport.html-COHavdZy.js} (99%) rename assets/{transport.html-Dzmzsfae.js => transport.html-CUhGNa4n.js} (99%) rename assets/{trojan.html-CGfwGdDo.js => trojan.html-C2jCtoPN.js} (98%) rename assets/{trojan.html-DmgOhScb.js => trojan.html-CSDiydOe.js} (98%) rename assets/{trojan.html-D2PfY2T3.js => trojan.html-Cs7YEsIb.js} (98%) rename assets/{trojan.html-CgBPDtHB.js => trojan.html-WsfP1d7V.js} (99%) rename assets/{trojan.html-DvVg8oOZ.js => trojan.html-ZC1LUXUu.js} (98%) rename assets/{trojan.html-GLPr9L0R.js => trojan.html-a1Coa5-Z.js} (98%) rename assets/{vless.html-CTPUBSmN.js => vless.html-B7O7xjrb.js} (99%) rename assets/{vless.html-BL9BeTeh.js => vless.html-BM3ph8gg.js} (99%) rename assets/{vless.html-CDOsAnQk.js => vless.html-BWup8Xzq.js} (99%) rename assets/{vless.html-BZ48J9S_.js => vless.html-C6f9K51N.js} (99%) rename assets/{vless.html-daOoULRK.js => vless.html-CASW7iOO.js} (99%) rename assets/{vless.html-Be1YpEZ1.js => vless.html-CxxO1Anm.js} (99%) rename assets/{vless.html-CccEA1M4.js => vless.html-D2jxsPHC.js} (99%) rename assets/{vless.html-D_sclD0U.js => vless.html-XJTROLo0.js} (99%) rename assets/{vless.html-CIaM0KTd.js => vless.html-gWexYZDk.js} (99%) rename assets/{vmess.html-DBKgR8RL.js => vmess.html-Blynvi6-.js} (99%) rename assets/{vmess.html-j0DrtN75.js => vmess.html-Bnv13XwA.js} (99%) rename assets/{vmess.html-D9LxQYXS.js => vmess.html-BtwOPh9t.js} (99%) rename assets/{vmess.html-BRWJ5o8r.js => vmess.html-CWgbIYSO.js} (99%) rename assets/{vmess.html-BNuNWfIe.js => vmess.html-CeLsjjaY.js} (99%) rename assets/{vmess.html-Dt2MIkqN.js => vmess.html-CzAuOHQq.js} (99%) rename assets/{vmess.html-DArYh1N-.js => vmess.html-Ds4NV6pk.js} (99%) rename assets/{vmess.html-D8czgnar.js => vmess.html-dZZBrBA9.js} (99%) rename assets/{vmess.html-Dw5jQJR5.js => vmess.html-gu8tRDOO.js} (99%) rename assets/{warp.html-DVfMNHe2.js => warp.html-9hKZfp2I.js} (99%) rename assets/{warp.html-CkXwKg50.js => warp.html-Bzz-XxvP.js} (99%) rename assets/{warp.html-7HQyZ8uD.js => warp.html-CO5RmDTS.js} (99%) rename assets/{websocket.html-CQ0wGOkU.js => websocket.html-DJjmBrAj.js} (98%) rename assets/{websocket.html-DsKOF98s.js => websocket.html-DzGXVtRP.js} (98%) rename assets/{websocket.html-CjNLVOTf.js => websocket.html-w8ndqht7.js} (98%) rename assets/{wireguard.html-BMXSEvNc.js => wireguard.html-CW0kotGE.js} (99%) rename assets/{wireguard.html-CYsQqFv0.js => wireguard.html-DORXKtWu.js} (99%) rename assets/{wireguard.html-BUaJgccu.js => wireguard.html-WCdNFPZm.js} (99%) rename assets/{work.html-CkI961Qb.js => work.html-DMYsHmaw.js} (98%) rename assets/{work.html-D1MRDeII.js => work.html-DkQ-NI9U.js} (98%) rename assets/{work.html-nHfveOL9.js => work.html-hEheaKUD.js} (98%) rename assets/{xtls.html-CNzfvmap.js => xtls.html-0Synm2Bl.js} (83%) rename assets/{xtls.html-BWSKIYgJ.js => xtls.html-BljC82lz.js} (79%) rename assets/{xtls.html-D7puBcBG.js => xtls.html-CDQXBW21.js} (77%) rename assets/{xychartDiagram-f11f50a6-BfE2Gore.js => xychartDiagram-f11f50a6-D1hL1lgg.js} (99%) diff --git a/404.html b/404.html index 0e0503a3f2..b880a05a24 100644 --- a/404.html +++ b/404.html @@ -24,11 +24,11 @@ Project X - - + + -

404

There's nothing here.
- +

404

How did we get here?
+ diff --git a/about/news.html b/about/news.html index 5d4b8e0324..ebbac8bf6d 100644 --- a/about/news.html +++ b/about/news.html @@ -24,11 +24,11 @@ 大史记 | Project X - - + +

大史记

2021.4.6

  • VuePress Next.
  • With Dark Mode.

2021.4.4

  • 本文档迎来的新的首页。
  • 本文档迎来了暗黑模式。
  • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
  • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
  • 🎉🎉🎉

2021.4.1 v1.4.2open in new tag

  • 不是愚人节玩笑,今天更新。
  • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
  • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
  • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

2021.3.25

没错还在变。 -_-

2021.3.15

文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

2021.3.14 v1.4.0open in new tag

  • Happy Pi-Day!
  • 这次是个大更新:
    • 为链式代理引入了传输层支持。
    • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
    • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
    • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
    • 添加了 FakeDNS。
    • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
  • 还是 VuePress 比较爽啊(

2021.3.3 1.3.1open in new tag

  • 这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。
  • 同时修复了一个会导致 Panic 的 bug。Holmium_认为这是在骗、在偷袭。
  • 修复了几个遗留问题。

2021.2.14 1.3.0open in new tag

  • Happy 🐮 Year 🎉!
  • v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。
  • OHHHHHHHHHHHH!

2021.01.31 1.2.4open in new tag

  • 解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。
  • 似乎这个版本没有什么改变,但这只是暴风雨前的宁静。
  • (没错我就是先知)

    你个傻子,你拿的是 UNO 牌。

2021.01.25

  • 全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载秘籍第一层咯...
  • 英文版文档网站逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!

2021.01.22 1.2.3open in new tag

  • 对 SS 协议的支持变强了, 支持单端口多用户!
  • 对 trojan 协议的支持也变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!
  • (VLESS: 嘤嘤嘤)
  • UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".
  • 嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.
  • 向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 a @Bohan Yangopen in new tag 致敬!
  • 其他美味小樱桃, 惯例更新品尝就对啦.

2021.01.19

  • 一些数字
    • 版本发布了 10   个 tag
    • 解决掉了 100  个 issue
    • 复刻了 300  个 fork
    • 点了 2000 个 star
    • 群 3000 个 人

2021.01.17

2021.01.15 1.2.2open in new tag

  • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
  • 之前预告的 UUID 修改正式上线.(往下看往下看)
  • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
  • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
  • 当然还有其他各种小糖果.(更新品尝就对了)
  • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

2021.01.12

  • 将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户.
    • 客户端写 "id": "我爱 🍉 老师 1314",
    • 服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 我爱🍉老师1314 的 UUID 映射)
  • 🍉 老师的小小白白话文大结局, 撒花.

2021.01.10 1.2.1open in new tag

  • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
  • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
  • 日志现在看起来更顺眼.

2021.01.07

  • 礼貌和尊重本应是社区不需要明说的准则之一。

2021.01.05

  • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

2021.01.03

2021.01.01

【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 1.2.0open in new tag

🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!

  • 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
  • (UDP 还会继续增强!)
  • 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
  • (不,下面不是广告,是里程碑。)
  • Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
    • 一人扛起了所有!支持各大主流协议!
    • 一骑绝尘的性能!
    • 日趋完善的功能!
    • 可怕的生命力与社区亲和力!
  • Xray 将继续保持前行! 因此 Xray 需要更多的英雄!!open in new tag
  • PS:请品,请细品release notesopen in new tag每一句。似乎有一个小秘密小彩蛋 (啊,有人敲门...我一会和你们说)

2020.12.29

透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, TG 群open in new tag火热测试中

2020.12.25 1.1.5open in new tag

圣诞节快乐!

  • 游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone
  • 你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...
  • (VLESS 的 UDP fullcone 和更多增强很快就到!)
  • 无须再担心证书验证被墙,OCSP stapling 已经上线!
  • kirin 带来了一大波 脚本更新.脚本在此open in new tag
  • 还有更多美味小樱桃!(不用问,更新品尝就对了)

2020.12.24

因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:没错你正在看的就是open in new tag

大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)

文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 文档的仓库open in new tag

仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。

2020.12.23

Xray-core Shadowsocks UDP FullCone 测试版, TG 群open in new tag火热测试中

2020.12.21

  • Project X 群人数 2000+
  • 群消息(含游戏群) 日均破万

2020.12.18 1.1.4open in new tag

  • 更低的启动内占用和内存使用优化
  • 随意定制的 TLS 提高你的 SSL 评级
  • 支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS
  • 还有在您路由器上使用的 Splice 最佳使用模式建议

2020.12.17

鉴于日益增长群人数和游戏需求, 开启了TG 游戏群open in new tag

2020.12.15

安装脚本 dev 分支open in new tag开启, 持续更新功能中.

2020.12.11 1.1.3open in new tag

  • 完整版本的 REDIRECT 透明代理模式.
  • 软路由 splice 流控模式的优化建议.

2020.12.06 1.1.2open in new tag

  • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
  • 增强了 API 兼容

2020.12.04

增加 splice 模式

2020.11.27

  • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
  • 登上了 GitHub Trending
  • Project X 群人数破千,频道订阅数 500+

2020.11.25 1.0.0open in new tag

Xray 的第一个版本.

  • 基于 v2ray-core 修改而来,改动较大
  • 全面增强, 性能卓越, 完全兼容

2020.11.23

project X start

梦开始的时候

- + diff --git a/assets/404.html-C-V38gH_.js b/assets/404.html-C7hQR_kQ.js similarity index 63% rename from assets/404.html-C-V38gH_.js rename to assets/404.html-C7hQR_kQ.js index f15ac74e4c..49514b24f1 100644 --- a/assets/404.html-C-V38gH_.js +++ b/assets/404.html-C7hQR_kQ.js @@ -1 +1 @@ -import{_ as e,o as c,c as t}from"./app-5SoadDYS.js";const _={};function o(r,n){return c(),t("div")}const a=e(_,[["render",o],["__file","404.html.vue"]]);export{a as default}; +import{_ as e,o as c,c as t}from"./app-Bw2NG-QJ.js";const _={};function o(r,n){return c(),t("div")}const a=e(_,[["render",o],["__file","404.html.vue"]]);export{a as default}; diff --git a/assets/Mermaid-OQLZrVC0.js b/assets/Mermaid-DaLi44oU.js similarity index 89% rename from assets/Mermaid-OQLZrVC0.js rename to assets/Mermaid-DaLi44oU.js index ff16faef9e..e27a2e4ba6 100644 --- a/assets/Mermaid-OQLZrVC0.js +++ b/assets/Mermaid-DaLi44oU.js @@ -1,7 +1,7 @@ -import{u as y,g as M,f as S,h as m,i as v,j as _,k as h,l as g,m as E,n as O,t as f,p as D,q as H,_ as L,o as R,c as T}from"./app-5SoadDYS.js";function $(e){return M()?(S(e),!0):!1}function w(e){return typeof e=="function"?e():y(e)}const A=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const C=e=>e!=null;function I(e){var t;const o=w(e);return(t=o==null?void 0:o.$el)!=null?t:o}const W=A?window:void 0;function q(){const e=_(!1),t=g();return t&&h(()=>{e.value=!0},t),e}function x(e){const t=q();return m(()=>(t.value,!!e()))}function B(e,t,o={}){const{window:i=W,...r}=o;let n;const u=x(()=>i&&"MutationObserver"in i),a=()=>{n&&(n.disconnect(),n=void 0)},d=m(()=>{const s=w(e),c=(Array.isArray(s)?s:[s]).map(I).filter(C);return new Set(c)}),b=v(()=>d.value,s=>{a(),u.value&&s.size&&(n=new MutationObserver(t),s.forEach(c=>n.observe(c,r)))},{immediate:!0,flush:"post"}),k=()=>n==null?void 0:n.takeRecords(),l=()=>{a(),b()};return $(l),{isSupported:u,stop:l,takeRecords:k}}const p=()=>{const e=document.documentElement;return e.classList.contains("dark")||e.getAttribute("data-theme")==="dark"},G=E({name:"Mermaid",props:{id:{type:String,required:!0},code:{type:String,required:!0}},setup(e){const t=O({innerHtml:""}),o=f(e,"id"),i=f(e,"code"),r=_(!1),n=async()=>{const u=await H(()=>import("./mermaid.core-CArNAncI.js").then(a=>a.b8),__vite__mapDeps([0,1]));u.default.initialize({theme:r.value?"dark":"default",startOnLoad:!1}),u.default.render(o.value,decodeURI(i.value)).then(({svg:a,bindFunctions:d})=>{t.innerHtml=a})};return h(()=>{r.value=p(),D(n)}),typeof document<"u"&&B(document.documentElement,()=>{r.value=p()},{attributeFilter:["class","data-theme"],attributes:!0}),v(r,()=>n()),{tag:o,payload:t}}}),z=["innerHTML"];function F(e,t,o,i,r,n){return R(),T("div",{innerHTML:e.payload.innerHtml},null,8,z)}const V=L(G,[["render",F],["__file","Mermaid.vue"]]);export{V as default}; +import{u as y,g as M,f as S,h as m,i as v,j as _,k as h,l as g,m as E,n as O,t as f,p as D,q as H,_ as L,o as R,c as T}from"./app-Bw2NG-QJ.js";function $(e){return M()?(S(e),!0):!1}function w(e){return typeof e=="function"?e():y(e)}const A=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const C=e=>e!=null;function I(e){var t;const o=w(e);return(t=o==null?void 0:o.$el)!=null?t:o}const W=A?window:void 0;function q(){const e=_(!1),t=g();return t&&h(()=>{e.value=!0},t),e}function x(e){const t=q();return m(()=>(t.value,!!e()))}function B(e,t,o={}){const{window:i=W,...r}=o;let n;const u=x(()=>i&&"MutationObserver"in i),a=()=>{n&&(n.disconnect(),n=void 0)},d=m(()=>{const s=w(e),c=(Array.isArray(s)?s:[s]).map(I).filter(C);return new Set(c)}),b=v(()=>d.value,s=>{a(),u.value&&s.size&&(n=new MutationObserver(t),s.forEach(c=>n.observe(c,r)))},{immediate:!0,flush:"post"}),k=()=>n==null?void 0:n.takeRecords(),l=()=>{a(),b()};return $(l),{isSupported:u,stop:l,takeRecords:k}}const p=()=>{const e=document.documentElement;return e.classList.contains("dark")||e.getAttribute("data-theme")==="dark"},G=E({name:"Mermaid",props:{id:{type:String,required:!0},code:{type:String,required:!0}},setup(e){const t=O({innerHtml:""}),o=f(e,"id"),i=f(e,"code"),r=_(!1),n=async()=>{const u=await H(()=>import("./mermaid.core-Bq0kX0MS.js").then(a=>a.b8),__vite__mapDeps([0,1]));u.default.initialize({theme:r.value?"dark":"default",startOnLoad:!1}),u.default.render(o.value,decodeURI(i.value)).then(({svg:a,bindFunctions:d})=>{t.innerHtml=a})};return h(()=>{r.value=p(),D(n)}),typeof document<"u"&&B(document.documentElement,()=>{r.value=p()},{attributeFilter:["class","data-theme"],attributes:!0}),v(r,()=>n()),{tag:o,payload:t}}}),z=["innerHTML"];function F(e,t,o,i,r,n){return R(),T("div",{innerHTML:e.payload.innerHtml},null,8,z)}const V=L(G,[["render",F],["__file","Mermaid.vue"]]);export{V as default}; function __vite__mapDeps(indexes) { if (!__vite__mapDeps.viteFileDeps) { - __vite__mapDeps.viteFileDeps = ["assets/mermaid.core-CArNAncI.js","assets/app-5SoadDYS.js"] + __vite__mapDeps.viteFileDeps = ["assets/mermaid.core-Bq0kX0MS.js","assets/app-Bw2NG-QJ.js"] } return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) } diff --git a/assets/Tab-Qnm7JOWy.js b/assets/Tab-Ci2eJWYz.js similarity index 89% rename from assets/Tab-Qnm7JOWy.js rename to assets/Tab-Ci2eJWYz.js index b0ffe17c9a..d6d5974b8e 100644 --- a/assets/Tab-Qnm7JOWy.js +++ b/assets/Tab-Ci2eJWYz.js @@ -1 +1 @@ -import{m as e,_ as a,o as s,c as l,s as r}from"./app-5SoadDYS.js";const i=e({props:{title:{type:String}},data(){return{tabID:this.title}},mounted(){this.tabID="tab-"+Math.random().toString(36).substring(2),this.$parent.$data.children.push({id:this.tabID,title:this.title})},computed:{labelID(){return this.tabID+"-label"}}}),o=["id","aria-labelledby"];function n(t,d,b,p,c,u){return s(),l("div",{class:"tab-pane fade",id:t.tabID,role:"tabpanel","aria-labelledby":t.labelID},[r(t.$slots,"default",{},void 0,!0)],8,o)}const h=a(i,[["render",n],["__scopeId","data-v-88372a6c"],["__file","Tab.vue"]]);export{h as default}; +import{m as e,_ as a,o as s,c as l,s as r}from"./app-Bw2NG-QJ.js";const i=e({props:{title:{type:String}},data(){return{tabID:this.title}},mounted(){this.tabID="tab-"+Math.random().toString(36).substring(2),this.$parent.$data.children.push({id:this.tabID,title:this.title})},computed:{labelID(){return this.tabID+"-label"}}}),o=["id","aria-labelledby"];function n(t,d,b,p,c,u){return s(),l("div",{class:"tab-pane fade",id:t.tabID,role:"tabpanel","aria-labelledby":t.labelID},[r(t.$slots,"default",{},void 0,!0)],8,o)}const h=a(i,[["render",n],["__scopeId","data-v-88372a6c"],["__file","Tab.vue"]]);export{h as default}; diff --git a/assets/Tabs-BWBTQACZ.js b/assets/Tabs-CXHA-R7W.js similarity index 95% rename from assets/Tabs-BWBTQACZ.js rename to assets/Tabs-CXHA-R7W.js index e5ad899995..620d28b104 100644 --- a/assets/Tabs-BWBTQACZ.js +++ b/assets/Tabs-CXHA-R7W.js @@ -1,4 +1,4 @@ -import{m as i,q as r,_ as d,o as a,c as n,b as s,F as l,v as c,s as u,x as _}from"./app-5SoadDYS.js";const p=i({props:{title:{type:String}},data(){return{children:[]}},beforeMount(){this.children=[]},mounted(){this.$nextTick(async function(){const t=await r(()=>import("./bootstrap.esm-DrZxKEFm.js"),__vite__mapDeps([]));let o=document.getElementById(this.children[0].id+"-label");new t.Tab(o).show()})},computed:{tag:function(){return"tabs-"+this.title},contentTag:function(){return"tabs-"+this.title+"-content"}}}),b={class:"container"},h=["id"],f=["id","aria-controls","data-bs-target"],g=["id"];function v(t,o,m,T,$,y){return a(),n("div",b,[s("nav",null,[s("div",{id:t.tag,class:"nav nav-pills",role:"tablist"},[(a(!0),n(l,null,c(t.children,e=>(a(),n("button",{id:e.id+"-label","aria-controls":e.id,"data-bs-target":"#"+e.id,"aria-selected":"false",class:"nav-link","data-bs-toggle":"tab",role:"tab",type:"button"},_(e.title),9,f))),256))],8,h)]),s("div",{id:t.contentTag,class:"tab-content"},[u(t.$slots,"default",{},void 0,!0)],8,g)])}const k=d(p,[["render",v],["__scopeId","data-v-b533ae34"],["__file","Tabs.vue"]]);export{k as default}; +import{m as i,q as r,_ as d,o as a,c as n,b as s,F as l,v as c,s as u,x as _}from"./app-Bw2NG-QJ.js";const p=i({props:{title:{type:String}},data(){return{children:[]}},beforeMount(){this.children=[]},mounted(){this.$nextTick(async function(){const t=await r(()=>import("./bootstrap.esm-DrZxKEFm.js"),__vite__mapDeps([]));let o=document.getElementById(this.children[0].id+"-label");new t.Tab(o).show()})},computed:{tag:function(){return"tabs-"+this.title},contentTag:function(){return"tabs-"+this.title+"-content"}}}),b={class:"container"},h=["id"],f=["id","aria-controls","data-bs-target"],g=["id"];function v(t,o,m,T,$,y){return a(),n("div",b,[s("nav",null,[s("div",{id:t.tag,class:"nav nav-pills",role:"tablist"},[(a(!0),n(l,null,c(t.children,e=>(a(),n("button",{id:e.id+"-label","aria-controls":e.id,"data-bs-target":"#"+e.id,"aria-selected":"false",class:"nav-link","data-bs-toggle":"tab",role:"tab",type:"button"},_(e.title),9,f))),256))],8,h)]),s("div",{id:t.contentTag,class:"tab-content"},[u(t.$slots,"default",{},void 0,!0)],8,g)])}const k=d(p,[["render",v],["__scopeId","data-v-b533ae34"],["__file","Tabs.vue"]]);export{k as default}; function __vite__mapDeps(indexes) { if (!__vite__mapDeps.viteFileDeps) { __vite__mapDeps.viteFileDeps = [] diff --git a/assets/api.html-DiYJU8Rg.js b/assets/api.html-Dh_ndM7D.js similarity index 99% rename from assets/api.html-DiYJU8Rg.js rename to assets/api.html-Dh_ndM7D.js index 18156b2e2e..1c443829de 100644 --- a/assets/api.html-DiYJU8Rg.js +++ b/assets/api.html-Dh_ndM7D.js @@ -1,4 +1,4 @@ -import{_ as c,r as t,o as l,c as u,a,b as s,d as n,w as p,e as i}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"api-接口",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#api-接口"},[s("span",null,"API 接口")])],-1),k={href:"https://grpc.io/",target:"_blank",rel:"noopener noreferrer"},b=s("a",{href:"#%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE"},"相关配置",-1),h={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.8.12",target:"_blank",rel:"noopener noreferrer"},m=i(`

注意

大多数用户并不会用到此 API,新手可以直接忽略这一项。

ApiObject

ApiObject 对应配置文件的 api 项。

{
+import{_ as c,r as t,o as l,c as u,a,b as s,d as n,w as p,e as i}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"api-接口",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#api-接口"},[s("span",null,"API 接口")])],-1),k={href:"https://grpc.io/",target:"_blank",rel:"noopener noreferrer"},b=s("a",{href:"#%E7%9B%B8%E5%85%B3%E9%85%8D%E7%BD%AE"},"相关配置",-1),h={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.8.12",target:"_blank",rel:"noopener noreferrer"},m=i(`

注意

大多数用户并不会用到此 API,新手可以直接忽略这一项。

ApiObject

ApiObject 对应配置文件的 api 项。

{
   "api": {
     "tag": "api",
     "listen": "127.0.0.1:8080",
diff --git a/assets/api.html-Dimd9sC-.js b/assets/api.html-Dt8W2IKn.js
similarity index 99%
rename from assets/api.html-Dimd9sC-.js
rename to assets/api.html-Dt8W2IKn.js
index 9022272859..9ff162ae05 100644
--- a/assets/api.html-Dimd9sC-.js
+++ b/assets/api.html-Dt8W2IKn.js
@@ -1,4 +1,4 @@
-import{_ as l,r as s,o as c,c as u,a as e,b as a,d as n,w as i,e as r}from"./app-5SoadDYS.js";const d={},v=a("h1",{id:"api-interface",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#api-interface"},[a("span",null,"API Interface")])],-1),h={href:"https://grpc.io/",target:"_blank",rel:"noopener noreferrer"},b=r(`

Please refer to the related configuration in this section.

Warning

Most users do not need to use this API. Novices can ignore this page entirely.

ApiObject

ApiObject corresponds to the api item in the configuration file.

{
+import{_ as l,r as s,o as c,c as u,a as e,b as a,d as n,w as i,e as r}from"./app-Bw2NG-QJ.js";const d={},v=a("h1",{id:"api-interface",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#api-interface"},[a("span",null,"API Interface")])],-1),h={href:"https://grpc.io/",target:"_blank",rel:"noopener noreferrer"},b=r(`

Please refer to the related configuration in this section.

Warning

Most users do not need to use this API. Novices can ignore this page entirely.

ApiObject

ApiObject corresponds to the api item in the configuration file.

{
   "api": {
     "tag": "api",
     "listen": "127.0.0.1:8080",
diff --git a/assets/api.html-D-Q2V6zb.js b/assets/api.html-LpVUq3p6.js
similarity index 99%
rename from assets/api.html-D-Q2V6zb.js
rename to assets/api.html-LpVUq3p6.js
index cc4d8811e5..74e7dfbc95 100644
--- a/assets/api.html-D-Q2V6zb.js
+++ b/assets/api.html-LpVUq3p6.js
@@ -1,4 +1,4 @@
-import{_ as l,r as t,o as c,c as u,a,b as s,d as n,w as p,e as i}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"api",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#api"},[s("span",null,"API")])],-1),k={href:"https://grpc.io/",target:"_blank",rel:"noopener noreferrer"},b=s("br",null,null,-1),h=s("br",null,null,-1),m=s("a",{href:"#%D1%81%D0%B2%D1%8F%D0%B7%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8"},"Связанные настройки",-1),g={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.8.12",target:"_blank",rel:"noopener noreferrer"},q=s("br",null,null,-1),D=i(`

Внимание

Большинству пользователей не нужен этот API, новички могут просто пропустить этот раздел.

ApiObject

ApiObject соответствует полю api в конфигурационном файле.

{
+import{_ as l,r as t,o as c,c as u,a,b as s,d as n,w as p,e as i}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"api",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#api"},[s("span",null,"API")])],-1),k={href:"https://grpc.io/",target:"_blank",rel:"noopener noreferrer"},b=s("br",null,null,-1),h=s("br",null,null,-1),m=s("a",{href:"#%D1%81%D0%B2%D1%8F%D0%B7%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8"},"Связанные настройки",-1),g={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.8.12",target:"_blank",rel:"noopener noreferrer"},q=s("br",null,null,-1),D=i(`

Внимание

Большинству пользователей не нужен этот API, новички могут просто пропустить этот раздел.

ApiObject

ApiObject соответствует полю api в конфигурационном файле.

{
   "api": {
     "tag": "api",
     "listen": "127.0.0.1:8080",
diff --git a/assets/app-5SoadDYS.js b/assets/app-Bw2NG-QJ.js
similarity index 95%
rename from assets/app-5SoadDYS.js
rename to assets/app-Bw2NG-QJ.js
index f7915241bd..78e43859fb 100644
--- a/assets/app-5SoadDYS.js
+++ b/assets/app-Bw2NG-QJ.js
@@ -1,4 +1,4 @@
-function bi(e,t){const l=Object.create(null),n=e.split(",");for(let i=0;i!!l[i]}const ye={},nl=[],ut=()=>{},ec=()=>!1,Bl=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),ki=e=>e.startsWith("onUpdate:"),Ie=Object.assign,Ei=(e,t)=>{const l=e.indexOf(t);l>-1&&e.splice(l,1)},tc=Object.prototype.hasOwnProperty,de=(e,t)=>tc.call(e,t),te=Array.isArray,il=e=>Pn(e)==="[object Map]",mo=e=>Pn(e)==="[object Set]",oe=e=>typeof e=="function",we=e=>typeof e=="string",fl=e=>typeof e=="symbol",Ee=e=>e!==null&&typeof e=="object",bo=e=>(Ee(e)||oe(e))&&oe(e.then)&&oe(e.catch),ko=Object.prototype.toString,Pn=e=>ko.call(e),lc=e=>Pn(e).slice(8,-1),Eo=e=>Pn(e)==="[object Object]",yi=e=>we(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Al=bi(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),An=e=>{const t=Object.create(null);return l=>t[l]||(t[l]=e(l))},nc=/-(\w)/g,dt=An(e=>e.replace(nc,(t,l)=>l?l.toUpperCase():"")),ic=/\B([A-Z])/g,Qt=An(e=>e.replace(ic,"-$1").toLowerCase()),wn=An(e=>e.charAt(0).toUpperCase()+e.slice(1)),$n=An(e=>e?`on${wn(e)}`:""),Yt=(e,t)=>!Object.is(e,t),Bn=(e,t)=>{for(let l=0;l{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:l})},rc=e=>{const t=parseFloat(e);return isNaN(t)?e:t},oc=e=>{const t=we(e)?Number(e):NaN;return isNaN(t)?e:t};let tr;const ni=()=>tr||(tr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Wl(e){if(te(e)){const t={};for(let l=0;l{if(l){const n=l.split(cc);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function $e(e){let t="";if(we(e))t=e;else if(te(e))for(let l=0;lwe(e)?e:e==null?"":te(e)||Ee(e)&&(e.toString===ko||!oe(e.toString))?JSON.stringify(e,xo,2):String(e),xo=(e,t)=>t&&t.__v_isRef?xo(e,t.value):il(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((l,[n,i],r)=>(l[Wn(n,r)+" =>"]=i,l),{})}:mo(t)?{[`Set(${t.size})`]:[...t.values()].map(l=>Wn(l))}:fl(t)?Wn(t):Ee(t)&&!te(t)&&!Eo(t)?String(t):t,Wn=(e,t="")=>{var l;return fl(e)?`Symbol(${(l=e.description)!=null?l:t})`:e};let qe;class vc{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=qe,!t&&qe&&(this.index=(qe.scopes||(qe.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const l=qe;try{return qe=this,t()}finally{qe=l}}}on(){qe=this}off(){qe=this.parent}stop(t){if(this._active){let l,n;for(l=0,n=this.effects.length;l{const t=new Set(e);return t.w=0,t.n=0,t},To=e=>(e.w&jt)>0,Oo=e=>(e.n&jt)>0,pc=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let l=0;for(let n=0;n{(d==="length"||!fl(d)&&d>=a)&&c.push(u)})}else switch(l!==void 0&&c.push(o.get(l)),t){case"add":te(e)?yi(l)&&c.push(o.get("length")):(c.push(o.get(zt)),il(e)&&c.push(o.get(ri)));break;case"delete":te(e)||(c.push(o.get(zt)),il(e)&&c.push(o.get(ri)));break;case"set":il(e)&&c.push(o.get(zt));break}if(c.length===1)c[0]&&oi(c[0]);else{const a=[];for(const u of c)u&&a.push(...u);oi(xi(a))}}function oi(e,t){const l=te(e)?e:[...e];for(const n of l)n.computed&&nr(n);for(const n of l)n.computed||nr(n)}function nr(e,t){(e!==lt||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}function mc(e,t){var l;return(l=pn.get(e))==null?void 0:l.get(t)}const bc=bi("__proto__,__v_isRef,__isVue"),wo=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(fl)),ir=kc();function kc(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...l){const n=ve(this);for(let r=0,o=this.length;r{e[t]=function(...l){pl();const n=ve(this)[t].apply(this,l);return gl(),n}}),e}function Ec(e){const t=ve(this);return Xe(t,"has",e),t.hasOwnProperty(e)}class Ro{constructor(t=!1,l=!1){this._isReadonly=t,this._shallow=l}get(t,l,n){const i=this._isReadonly,r=this._shallow;if(l==="__v_isReactive")return!i;if(l==="__v_isReadonly")return i;if(l==="__v_isShallow")return r;if(l==="__v_raw")return n===(i?r?Sc:So:r?jo:Do).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const o=te(t);if(!i){if(o&&de(ir,l))return Reflect.get(ir,l,n);if(l==="hasOwnProperty")return Ec}const c=Reflect.get(t,l,n);return(fl(l)?wo.has(l):bc(l))||(i||Xe(t,"get",l),r)?c:Ne(c)?o&&yi(l)?c:c.value:Ee(c)?i?In(c):Ul(c):c}}class Io extends Ro{constructor(t=!1){super(!1,t)}set(t,l,n,i){let r=t[l];if(!this._shallow){const a=cl(r);if(!gn(n)&&!cl(n)&&(r=ve(r),n=ve(n)),!te(t)&&Ne(r)&&!Ne(n))return a?!1:(r.value=n,!0)}const o=te(t)&&yi(l)?Number(l)e,Rn=e=>Reflect.getPrototypeOf(e);function Jl(e,t,l=!1,n=!1){e=e.__v_raw;const i=ve(e),r=ve(t);l||(Yt(t,r)&&Xe(i,"get",t),Xe(i,"get",r));const{has:o}=Rn(i),c=n?Ti:l?Ai:Sl;if(o.call(i,t))return c(e.get(t));if(o.call(i,r))return c(e.get(r));e!==i&&e.get(t)}function Zl(e,t=!1){const l=this.__v_raw,n=ve(l),i=ve(e);return t||(Yt(e,i)&&Xe(n,"has",e),Xe(n,"has",i)),e===i?l.has(e):l.has(e)||l.has(i)}function en(e,t=!1){return e=e.__v_raw,!t&&Xe(ve(e),"iterate",zt),Reflect.get(e,"size",e)}function rr(e){e=ve(e);const t=ve(this);return Rn(t).has.call(t,e)||(t.add(e),pt(t,"add",e,e)),this}function or(e,t){t=ve(t);const l=ve(this),{has:n,get:i}=Rn(l);let r=n.call(l,e);r||(e=ve(e),r=n.call(l,e));const o=i.call(l,e);return l.set(e,t),r?Yt(t,o)&&pt(l,"set",e,t):pt(l,"add",e,t),this}function sr(e){const t=ve(this),{has:l,get:n}=Rn(t);let i=l.call(t,e);i||(e=ve(e),i=l.call(t,e)),n&&n.call(t,e);const r=t.delete(e);return i&&pt(t,"delete",e,void 0),r}function cr(){const e=ve(this),t=e.size!==0,l=e.clear();return t&&pt(e,"clear",void 0,void 0),l}function tn(e,t){return function(n,i){const r=this,o=r.__v_raw,c=ve(o),a=t?Ti:e?Ai:Sl;return!e&&Xe(c,"iterate",zt),o.forEach((u,d)=>n.call(i,a(u),a(d),r))}}function ln(e,t,l){return function(...n){const i=this.__v_raw,r=ve(i),o=il(r),c=e==="entries"||e===Symbol.iterator&&o,a=e==="keys"&&o,u=i[e](...n),d=l?Ti:t?Ai:Sl;return!t&&Xe(r,"iterate",a?ri:zt),{next(){const{value:v,done:_}=u.next();return _?{value:v,done:_}:{value:c?[d(v[0]),d(v[1])]:d(v),done:_}},[Symbol.iterator](){return this}}}}function Lt(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Oc(){const e={get(r){return Jl(this,r)},get size(){return en(this)},has:Zl,add:rr,set:or,delete:sr,clear:cr,forEach:tn(!1,!1)},t={get(r){return Jl(this,r,!1,!0)},get size(){return en(this)},has:Zl,add:rr,set:or,delete:sr,clear:cr,forEach:tn(!1,!0)},l={get(r){return Jl(this,r,!0)},get size(){return en(this,!0)},has(r){return Zl.call(this,r,!0)},add:Lt("add"),set:Lt("set"),delete:Lt("delete"),clear:Lt("clear"),forEach:tn(!0,!1)},n={get(r){return Jl(this,r,!0,!0)},get size(){return en(this,!0)},has(r){return Zl.call(this,r,!0)},add:Lt("add"),set:Lt("set"),delete:Lt("delete"),clear:Lt("clear"),forEach:tn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(r=>{e[r]=ln(r,!1,!1),l[r]=ln(r,!0,!1),t[r]=ln(r,!1,!0),n[r]=ln(r,!0,!0)}),[e,l,t,n]}const[Pc,Ac,wc,Rc]=Oc();function Oi(e,t){const l=t?e?Rc:wc:e?Ac:Pc;return(n,i,r)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(de(l,i)&&i in n?l:n,i,r)}const Ic={get:Oi(!1,!1)},Dc={get:Oi(!1,!0)},jc={get:Oi(!0,!1)},Do=new WeakMap,jo=new WeakMap,So=new WeakMap,Sc=new WeakMap;function Cc(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Vc(e){return e.__v_skip||!Object.isExtensible(e)?0:Cc(lc(e))}function Ul(e){return cl(e)?e:Pi(e,!1,xc,Ic,Do)}function Co(e){return Pi(e,!1,Tc,Dc,jo)}function In(e){return Pi(e,!0,Lc,jc,So)}function Pi(e,t,l,n,i){if(!Ee(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=i.get(e);if(r)return r;const o=Vc(e);if(o===0)return e;const c=new Proxy(e,o===2?n:l);return i.set(e,c),c}function rl(e){return cl(e)?rl(e.__v_raw):!!(e&&e.__v_isReactive)}function cl(e){return!!(e&&e.__v_isReadonly)}function gn(e){return!!(e&&e.__v_isShallow)}function Vo(e){return rl(e)||cl(e)}function ve(e){const t=e&&e.__v_raw;return t?ve(t):e}function Fo(e){return fn(e,"__v_skip",!0),e}const Sl=e=>Ee(e)?Ul(e):e,Ai=e=>Ee(e)?In(e):e;function wi(e){It&<&&(e=ve(e),Ao(e.dep||(e.dep=xi())))}function Ri(e,t){e=ve(e);const l=e.dep;l&&oi(l)}function Ne(e){return!!(e&&e.__v_isRef===!0)}function pe(e){return Ho(e,!1)}function No(e){return Ho(e,!0)}function Ho(e,t){return Ne(e)?e:new Fc(e,t)}class Fc{constructor(t,l){this.__v_isShallow=l,this.dep=void 0,this.__v_isRef=!0,this._rawValue=l?t:ve(t),this._value=l?t:Sl(t)}get value(){return wi(this),this._value}set value(t){const l=this.__v_isShallow||gn(t)||cl(t);t=l?t:ve(t),Yt(t,this._rawValue)&&(this._rawValue=t,this._value=l?t:Sl(t),Ri(this))}}function Xt(e){return Ne(e)?e.value:e}const Nc={get:(e,t,l)=>Xt(Reflect.get(e,t,l)),set:(e,t,l,n)=>{const i=e[t];return Ne(i)&&!Ne(l)?(i.value=l,!0):Reflect.set(e,t,l,n)}};function Mo(e){return rl(e)?e:new Proxy(e,Nc)}class Hc{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:l,set:n}=t(()=>wi(this),()=>Ri(this));this._get=l,this._set=n}get value(){return this._get()}set value(t){this._set(t)}}function Mc(e){return new Hc(e)}function Dn(e){const t=te(e)?new Array(e.length):{};for(const l in e)t[l]=$o(e,l);return t}class $c{constructor(t,l,n){this._object=t,this._key=l,this._defaultValue=n,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return mc(ve(this._object),this._key)}}class Bc{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function Ep(e,t,l){return Ne(e)?e:oe(e)?new Bc(e):Ee(e)&&arguments.length>1?$o(e,t,l):pe(e)}function $o(e,t,l){const n=e[t];return Ne(n)?n:new $c(e,t,l)}class Wc{constructor(t,l,n,i){this._setter=l,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new Li(t,()=>{this._dirty||(this._dirty=!0,Ri(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!i,this.__v_isReadonly=n}get value(){const t=ve(this);return wi(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function Uc(e,t,l=!1){let n,i;const r=oe(e);return r?(n=e,i=ut):(n=e.get,i=e.set),new Wc(n,i,r||!i,l)}function Dt(e,t,l,n){let i;try{i=n?e(...n):e()}catch(r){zl(r,t,l)}return i}function Ze(e,t,l,n){if(oe(e)){const r=Dt(e,t,l,n);return r&&bo(r)&&r.catch(o=>{zl(o,t,l)}),r}const i=[];for(let r=0;r>>1,i=Me[n],r=Vl(i);rat&&Me.splice(t,1)}function qc(e){te(e)?ol.push(...e):(!ft||!ft.includes(e,e.allowRecurse?$t+1:$t))&&ol.push(e),Wo()}function ar(e,t,l=Cl?at+1:0){for(;lVl(l)-Vl(n)),$t=0;$te.id==null?1/0:e.id,Gc=(e,t)=>{const l=Vl(e)-Vl(t);if(l===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return l};function Uo(e){si=!1,Cl=!0,Me.sort(Gc);try{for(at=0;atwe(g)?g.trim():g)),v&&(i=l.map(rc))}let c,a=n[c=$n(t)]||n[c=$n(dt(t))];!a&&r&&(a=n[c=$n(Qt(t))]),a&&Ze(a,e,6,i);const u=n[c+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[c])return;e.emitted[c]=!0,Ze(u,e,6,i)}}function zo(e,t,l=!1){const n=t.emitsCache,i=n.get(e);if(i!==void 0)return i;const r=e.emits;let o={},c=!1;if(!oe(e)){const a=u=>{const d=zo(u,t,!0);d&&(c=!0,Ie(o,d))};!l&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!r&&!c?(Ee(e)&&n.set(e,null),null):(te(r)?r.forEach(a=>o[a]=null):Ie(o,r),Ee(e)&&n.set(e,o),o)}function Sn(e,t){return!e||!Bl(t)?!1:(t=t.slice(2).replace(/Once$/,""),de(e,t[0].toLowerCase()+t.slice(1))||de(e,Qt(t))||de(e,t))}let Ve=null,Xo=null;function bn(e){const t=Ve;return Ve=e,Xo=e&&e.type.__scopeId||null,t}function Ce(e,t=Ve,l){if(!t||e._n)return e;const n=(...i)=>{n._d&&Er(-1);const r=bn(t);let o;try{o=e(...i)}finally{bn(r),n._d&&Er(1)}return o};return n._n=!0,n._c=!0,n._d=!0,n}function Un(e){const{type:t,vnode:l,proxy:n,withProxy:i,props:r,propsOptions:[o],slots:c,attrs:a,emit:u,render:d,renderCache:v,data:_,setupState:g,ctx:m,inheritAttrs:x}=e;let A,D;const O=bn(e);try{if(l.shapeFlag&4){const y=i||n,H=y;A=tt(d.call(H,y,v,r,g,_,m)),D=a}else{const y=t;A=tt(y.length>1?y(r,{attrs:a,slots:c,emit:u}):y(r,null)),D=t.props?a:Qc(a)}}catch(y){Il.length=0,zl(y,e,1),A=ie(Ye)}let b=A;if(D&&x!==!1){const y=Object.keys(D),{shapeFlag:H}=b;y.length&&H&7&&(o&&y.some(ki)&&(D=Jc(D,o)),b=Ct(b,D))}return l.dirs&&(b=Ct(b),b.dirs=b.dirs?b.dirs.concat(l.dirs):l.dirs),l.transition&&(b.transition=l.transition),A=b,bn(O),A}const Qc=e=>{let t;for(const l in e)(l==="class"||l==="style"||Bl(l))&&((t||(t={}))[l]=e[l]);return t},Jc=(e,t)=>{const l={};for(const n in e)(!ki(n)||!(n.slice(9)in t))&&(l[n]=e[n]);return l};function Zc(e,t,l){const{props:n,children:i,component:r}=e,{props:o,children:c,patchFlag:a}=t,u=r.emitsOptions;if(t.dirs||t.transition)return!0;if(l&&a>=0){if(a&1024)return!0;if(a&16)return n?ur(n,o,u):!!o;if(a&8){const d=t.dynamicProps;for(let v=0;ve.__isSuspense;function Ko(e,t){t&&t.pendingBranch?te(e)?t.effects.push(...e):t.effects.push(e):qc(e)}function ra(e,t){return Di(e,null,t)}const nn={};function Ge(e,t,l){return Di(e,t,l)}function Di(e,t,{immediate:l,deep:n,flush:i,onTrack:r,onTrigger:o}=ye){var c;const a=Lo()===((c=Re)==null?void 0:c.scope)?Re:null;let u,d=!1,v=!1;if(Ne(e)?(u=()=>e.value,d=gn(e)):rl(e)?(u=()=>e,n=!0):te(e)?(v=!0,d=e.some(y=>rl(y)||gn(y)),u=()=>e.map(y=>{if(Ne(y))return y.value;if(rl(y))return Ut(y);if(oe(y))return Dt(y,a,2)})):oe(e)?t?u=()=>Dt(e,a,2):u=()=>{if(!(a&&a.isUnmounted))return _&&_(),Ze(e,a,3,[g])}:u=ut,t&&n){const y=u;u=()=>Ut(y())}let _,g=y=>{_=O.onStop=()=>{Dt(y,a,4),_=O.onStop=void 0}},m;if(dl)if(g=ut,t?l&&Ze(t,a,3,[u(),v?[]:void 0,g]):u(),i==="sync"){const y=Ja();m=y.__watcherHandles||(y.__watcherHandles=[])}else return ut;let x=v?new Array(e.length).fill(nn):nn;const A=()=>{if(O.active)if(t){const y=O.run();(n||d||(v?y.some((H,G)=>Yt(H,x[G])):Yt(y,x)))&&(_&&_(),Ze(t,a,3,[y,x===nn?void 0:v&&x[0]===nn?[]:x,g]),x=y)}else O.run()};A.allowRecurse=!!t;let D;i==="sync"?D=A:i==="post"?D=()=>ze(A,a&&a.suspense):(A.pre=!0,a&&(A.id=a.uid),D=()=>jn(A));const O=new Li(u,D);t?l?A():x=O.run():i==="post"?ze(O.run.bind(O),a&&a.suspense):O.run();const b=()=>{O.stop(),a&&a.scope&&Ei(a.scope.effects,O)};return m&&m.push(b),b}function oa(e,t,l){const n=this.proxy,i=we(e)?e.includes(".")?qo(n,e):()=>n[e]:e.bind(n,n);let r;oe(t)?r=t:(r=t.handler,l=t);const o=Re;ul(this);const c=Di(i,r.bind(n),l);return o?ul(o):qt(),c}function qo(e,t){const l=t.split(".");return()=>{let n=e;for(let i=0;i{Ut(l,t)});else if(Eo(e))for(const l in e)Ut(e[l],t);return e}function kn(e,t){const l=Ve;if(l===null)return e;const n=Nn(l)||l.proxy,i=e.dirs||(e.dirs=[]);for(let r=0;r{e.isMounted=!0}),ql(()=>{e.isUnmounting=!0}),e}const Qe=[Function,Array],Go={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Qe,onEnter:Qe,onAfterEnter:Qe,onEnterCancelled:Qe,onBeforeLeave:Qe,onLeave:Qe,onAfterLeave:Qe,onLeaveCancelled:Qe,onBeforeAppear:Qe,onAppear:Qe,onAfterAppear:Qe,onAppearCancelled:Qe},ca={name:"BaseTransition",props:Go,setup(e,{slots:t}){const l=Vi(),n=sa();let i;return()=>{const r=t.default&&Qo(t.default(),!0);if(!r||!r.length)return;let o=r[0];if(r.length>1){for(const x of r)if(x.type!==Ye){o=x;break}}const c=ve(e),{mode:a}=c;if(n.isLeaving)return zn(o);const u=hr(o);if(!u)return zn(o);const d=ci(u,c,n,l);ai(u,d);const v=l.subTree,_=v&&hr(v);let g=!1;const{getTransitionKey:m}=u.type;if(m){const x=m();i===void 0?i=x:x!==i&&(i=x,g=!0)}if(_&&_.type!==Ye&&(!Bt(u,_)||g)){const x=ci(_,c,n,l);if(ai(_,x),a==="out-in")return n.isLeaving=!0,x.afterLeave=()=>{n.isLeaving=!1,l.update.active!==!1&&l.update()},zn(o);a==="in-out"&&u.type!==Ye&&(x.delayLeave=(A,D,O)=>{const b=Yo(n,_);b[String(_.key)]=_,A[At]=()=>{D(),A[At]=void 0,delete d.delayedLeave},d.delayedLeave=O})}return o}}},aa=ca;function Yo(e,t){const{leavingVNodes:l}=e;let n=l.get(t.type);return n||(n=Object.create(null),l.set(t.type,n)),n}function ci(e,t,l,n){const{appear:i,mode:r,persisted:o=!1,onBeforeEnter:c,onEnter:a,onAfterEnter:u,onEnterCancelled:d,onBeforeLeave:v,onLeave:_,onAfterLeave:g,onLeaveCancelled:m,onBeforeAppear:x,onAppear:A,onAfterAppear:D,onAppearCancelled:O}=t,b=String(e.key),y=Yo(l,e),H=(E,K)=>{E&&Ze(E,n,9,K)},G=(E,K)=>{const w=K[1];H(E,K),te(E)?E.every(z=>z.length<=1)&&w():E.length<=1&&w()},N={mode:r,persisted:o,beforeEnter(E){let K=c;if(!l.isMounted)if(i)K=x||c;else return;E[At]&&E[At](!0);const w=y[b];w&&Bt(e,w)&&w.el[At]&&w.el[At](),H(K,[E])},enter(E){let K=a,w=u,z=d;if(!l.isMounted)if(i)K=A||a,w=D||u,z=O||d;else return;let L=!1;const V=E[rn]=le=>{L||(L=!0,le?H(z,[E]):H(w,[E]),N.delayedLeave&&N.delayedLeave(),E[rn]=void 0)};K?G(K,[E,V]):V()},leave(E,K){const w=String(e.key);if(E[rn]&&E[rn](!0),l.isUnmounting)return K();H(v,[E]);let z=!1;const L=E[At]=V=>{z||(z=!0,K(),V?H(m,[E]):H(g,[E]),E[At]=void 0,y[w]===e&&delete y[w])};y[w]=e,_?G(_,[E,L]):L()},clone(E){return ci(E,t,l,n)}};return N}function zn(e){if(Kl(e))return e=Ct(e),e.children=null,e}function hr(e){return Kl(e)?e.children?e.children[0]:void 0:e}function ai(e,t){e.shapeFlag&6&&e.component?ai(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Qo(e,t=!1,l){let n=[],i=0;for(let r=0;r1)for(let r=0;r!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function h(e){oe(e)&&(e={loader:e});const{loader:t,loadingComponent:l,errorComponent:n,delay:i=200,timeout:r,suspensible:o=!0,onError:c}=e;let a=null,u,d=0;const v=()=>(d++,a=null,_()),_=()=>{let g;return a||(g=a=t().catch(m=>{if(m=m instanceof Error?m:new Error(String(m)),c)return new Promise((x,A)=>{c(m,()=>x(v()),()=>A(m),d+1)});throw m}).then(m=>g!==a&&a?a:(m&&(m.__esModule||m[Symbol.toStringTag]==="Module")&&(m=m.default),u=m,m)))};return _e({name:"AsyncComponentWrapper",__asyncLoader:_,get __asyncResolved(){return u},setup(){const g=Re;if(u)return()=>Xn(u,g);const m=O=>{a=null,zl(O,g,13,!n)};if(o&&g.suspense||dl)return _().then(O=>()=>Xn(O,g)).catch(O=>(m(O),()=>n?ie(n,{error:O}):null));const x=pe(!1),A=pe(),D=pe(!!i);return i&&setTimeout(()=>{D.value=!1},i),r!=null&&setTimeout(()=>{if(!x.value&&!A.value){const O=new Error(`Async component timed out after ${r}ms.`);m(O),A.value=O}},r),_().then(()=>{x.value=!0,g.parent&&Kl(g.parent.vnode)&&jn(g.parent.update)}).catch(O=>{m(O),A.value=O}),()=>{if(x.value&&u)return Xn(u,g);if(A.value&&n)return ie(n,{error:A.value});if(l&&!D.value)return ie(l)}}})}function Xn(e,t){const{ref:l,props:n,children:i,ce:r}=t.vnode,o=ie(e,n,i);return o.ref=l,o.ce=r,delete t.vnode.ce,o}const Kl=e=>e.type.__isKeepAlive;function ua(e,t){Jo(e,"a",t)}function da(e,t){Jo(e,"da",t)}function Jo(e,t,l=Re){const n=e.__wdc||(e.__wdc=()=>{let i=l;for(;i;){if(i.isDeactivated)return;i=i.parent}return e()});if(Cn(t,n,l),l){let i=l.parent;for(;i&&i.parent;)Kl(i.parent.vnode)&&ha(n,t,l,i),i=i.parent}}function ha(e,t,l,n){const i=Cn(t,e,n,!0);Vn(()=>{Ei(n[t],i)},l)}function Cn(e,t,l=Re,n=!1){if(l){const i=l[e]||(l[e]=[]),r=t.__weh||(t.__weh=(...o)=>{if(l.isUnmounted)return;pl(),ul(l);const c=Ze(t,l,e,o);return qt(),gl(),c});return n?i.unshift(r):i.push(r),r}}const kt=e=>(t,l=Re)=>(!dl||e==="sp")&&Cn(e,(...n)=>t(...n),l),va=kt("bm"),We=kt("m"),_a=kt("bu"),fa=kt("u"),ql=kt("bum"),Vn=kt("um"),pa=kt("sp"),ga=kt("rtg"),ma=kt("rtc");function ba(e,t=Re){Cn("ec",e,t)}function St(e,t,l,n){let i;const r=l;if(te(e)||we(e)){i=new Array(e.length);for(let o=0,c=e.length;ot(o,c,void 0,r));else{const o=Object.keys(e);i=new Array(o.length);for(let c=0,a=o.length;cLn(t)?!(t.type===Ye||t.type===ke&&!Zo(t.children)):!0)?e:null}const ui=e=>e?ds(e)?Nn(e)||e.proxy:ui(e.parent):null,wl=Ie(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>ui(e.parent),$root:e=>ui(e.root),$emit:e=>e.emit,$options:e=>ji(e),$forceUpdate:e=>e.f||(e.f=()=>jn(e.update)),$nextTick:e=>e.n||(e.n=Xl.bind(e.proxy)),$watch:e=>oa.bind(e)}),Kn=(e,t)=>e!==ye&&!e.__isScriptSetup&&de(e,t),ka={get({_:e},t){const{ctx:l,setupState:n,data:i,props:r,accessCache:o,type:c,appContext:a}=e;let u;if(t[0]!=="$"){const g=o[t];if(g!==void 0)switch(g){case 1:return n[t];case 2:return i[t];case 4:return l[t];case 3:return r[t]}else{if(Kn(n,t))return o[t]=1,n[t];if(i!==ye&&de(i,t))return o[t]=2,i[t];if((u=e.propsOptions[0])&&de(u,t))return o[t]=3,r[t];if(l!==ye&&de(l,t))return o[t]=4,l[t];di&&(o[t]=0)}}const d=wl[t];let v,_;if(d)return t==="$attrs"&&Xe(e,"get",t),d(e);if((v=c.__cssModules)&&(v=v[t]))return v;if(l!==ye&&de(l,t))return o[t]=4,l[t];if(_=a.config.globalProperties,de(_,t))return _[t]},set({_:e},t,l){const{data:n,setupState:i,ctx:r}=e;return Kn(i,t)?(i[t]=l,!0):n!==ye&&de(n,t)?(n[t]=l,!0):de(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=l,!0)},has({_:{data:e,setupState:t,accessCache:l,ctx:n,appContext:i,propsOptions:r}},o){let c;return!!l[o]||e!==ye&&de(e,o)||Kn(t,o)||(c=r[0])&&de(c,o)||de(n,o)||de(wl,o)||de(i.config.globalProperties,o)},defineProperty(e,t,l){return l.get!=null?e._.accessCache[t]=0:de(l,"value")&&this.set(e,t,l.value,null),Reflect.defineProperty(e,t,l)}};function vr(e){return te(e)?e.reduce((t,l)=>(t[l]=null,t),{}):e}let di=!0;function Ea(e){const t=ji(e),l=e.proxy,n=e.ctx;di=!1,t.beforeCreate&&_r(t.beforeCreate,e,"bc");const{data:i,computed:r,methods:o,watch:c,provide:a,inject:u,created:d,beforeMount:v,mounted:_,beforeUpdate:g,updated:m,activated:x,deactivated:A,beforeDestroy:D,beforeUnmount:O,destroyed:b,unmounted:y,render:H,renderTracked:G,renderTriggered:N,errorCaptured:E,serverPrefetch:K,expose:w,inheritAttrs:z,components:L,directives:V,filters:le}=t;if(u&&ya(u,n,null),o)for(const Q in o){const X=o[Q];oe(X)&&(n[Q]=X.bind(l))}if(i){const Q=i.call(l,l);Ee(Q)&&(e.data=Ul(Q))}if(di=!0,r)for(const Q in r){const X=r[Q],De=oe(X)?X.bind(l,l):oe(X.get)?X.get.bind(l,l):ut,Se=!oe(X)&&oe(X.set)?X.set.bind(l):ut,Ue=C({get:De,set:Se});Object.defineProperty(n,Q,{enumerable:!0,configurable:!0,get:()=>Ue.value,set:He=>Ue.value=He})}if(c)for(const Q in c)es(c[Q],n,l,Q);if(a){const Q=oe(a)?a.call(l):a;Reflect.ownKeys(Q).forEach(X=>{Kt(X,Q[X])})}d&&_r(d,e,"c");function S(Q,X){te(X)?X.forEach(De=>Q(De.bind(l))):X&&Q(X.bind(l))}if(S(va,v),S(We,_),S(_a,g),S(fa,m),S(ua,x),S(da,A),S(ba,E),S(ma,G),S(ga,N),S(ql,O),S(Vn,y),S(pa,K),te(w))if(w.length){const Q=e.exposed||(e.exposed={});w.forEach(X=>{Object.defineProperty(Q,X,{get:()=>l[X],set:De=>l[X]=De})})}else e.exposed||(e.exposed={});H&&e.render===ut&&(e.render=H),z!=null&&(e.inheritAttrs=z),L&&(e.components=L),V&&(e.directives=V)}function ya(e,t,l=ut){te(e)&&(e=hi(e));for(const n in e){const i=e[n];let r;Ee(i)?"default"in i?r=Te(i.from||n,i.default,!0):r=Te(i.from||n):r=Te(i),Ne(r)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>r.value,set:o=>r.value=o}):t[n]=r}}function _r(e,t,l){Ze(te(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,l)}function es(e,t,l,n){const i=n.includes(".")?qo(l,n):()=>l[n];if(we(e)){const r=t[e];oe(r)&&Ge(i,r)}else if(oe(e))Ge(i,e.bind(l));else if(Ee(e))if(te(e))e.forEach(r=>es(r,t,l,n));else{const r=oe(e.handler)?e.handler.bind(l):t[e.handler];oe(r)&&Ge(i,r,e)}}function ji(e){const t=e.type,{mixins:l,extends:n}=t,{mixins:i,optionsCache:r,config:{optionMergeStrategies:o}}=e.appContext,c=r.get(t);let a;return c?a=c:!i.length&&!l&&!n?a=t:(a={},i.length&&i.forEach(u=>En(a,u,o,!0)),En(a,t,o)),Ee(t)&&r.set(t,a),a}function En(e,t,l,n=!1){const{mixins:i,extends:r}=t;r&&En(e,r,l,!0),i&&i.forEach(o=>En(e,o,l,!0));for(const o in t)if(!(n&&o==="expose")){const c=xa[o]||l&&l[o];e[o]=c?c(e[o],t[o]):t[o]}return e}const xa={data:fr,props:pr,emits:pr,methods:Pl,computed:Pl,beforeCreate:Be,created:Be,beforeMount:Be,mounted:Be,beforeUpdate:Be,updated:Be,beforeDestroy:Be,beforeUnmount:Be,destroyed:Be,unmounted:Be,activated:Be,deactivated:Be,errorCaptured:Be,serverPrefetch:Be,components:Pl,directives:Pl,watch:Ta,provide:fr,inject:La};function fr(e,t){return t?e?function(){return Ie(oe(e)?e.call(this,this):e,oe(t)?t.call(this,this):t)}:t:e}function La(e,t){return Pl(hi(e),hi(t))}function hi(e){if(te(e)){const t={};for(let l=0;l1)return l&&oe(t)?t.call(n&&n.proxy):t}}function Aa(e,t,l,n=!1){const i={},r={};fn(r,Fn,1),e.propsDefaults=Object.create(null),ls(e,t,i,r);for(const o in e.propsOptions[0])o in i||(i[o]=void 0);l?e.props=n?i:Co(i):e.type.props?e.props=i:e.props=r,e.attrs=r}function wa(e,t,l,n){const{props:i,attrs:r,vnode:{patchFlag:o}}=e,c=ve(i),[a]=e.propsOptions;let u=!1;if((n||o>0)&&!(o&16)){if(o&8){const d=e.vnode.dynamicProps;for(let v=0;v{a=!0;const[_,g]=ns(v,t,!0);Ie(o,_),g&&c.push(...g)};!l&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!r&&!a)return Ee(e)&&n.set(e,nl),nl;if(te(r))for(let d=0;d-1,g[1]=x<0||m-1||de(g,"default"))&&c.push(v)}}}const u=[o,c];return Ee(e)&&n.set(e,u),u}function gr(e){return e[0]!=="$"}function mr(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function br(e,t){return mr(e)===mr(t)}function kr(e,t){return te(t)?t.findIndex(l=>br(l,e)):oe(t)&&br(t,e)?0:-1}const is=e=>e[0]==="_"||e==="$stable",Si=e=>te(e)?e.map(tt):[tt(e)],Ra=(e,t,l)=>{if(t._n)return t;const n=Ce((...i)=>Si(t(...i)),l);return n._c=!1,n},rs=(e,t,l)=>{const n=e._ctx;for(const i in e){if(is(i))continue;const r=e[i];if(oe(r))t[i]=Ra(i,r,n);else if(r!=null){const o=Si(r);t[i]=()=>o}}},os=(e,t)=>{const l=Si(t);e.slots.default=()=>l},Ia=(e,t)=>{if(e.vnode.shapeFlag&32){const l=t._;l?(e.slots=ve(t),fn(t,"_",l)):rs(t,e.slots={})}else e.slots={},t&&os(e,t);fn(e.slots,Fn,1)},Da=(e,t,l)=>{const{vnode:n,slots:i}=e;let r=!0,o=ye;if(n.shapeFlag&32){const c=t._;c?l&&c===1?r=!1:(Ie(i,t),!l&&c===1&&delete i._):(r=!t.$stable,rs(t,i)),o=t}else t&&(os(e,t),o={default:1});if(r)for(const c in i)!is(c)&&o[c]==null&&delete i[c]};function xn(e,t,l,n,i=!1){if(te(e)){e.forEach((_,g)=>xn(_,t&&(te(t)?t[g]:t),l,n,i));return}if(sl(n)&&!i)return;const r=n.shapeFlag&4?Nn(n.component)||n.component.proxy:n.el,o=i?null:r,{i:c,r:a}=e,u=t&&t.r,d=c.refs===ye?c.refs={}:c.refs,v=c.setupState;if(u!=null&&u!==a&&(we(u)?(d[u]=null,de(v,u)&&(v[u]=null)):Ne(u)&&(u.value=null)),oe(a))Dt(a,c,12,[o,d]);else{const _=we(a),g=Ne(a);if(_||g){const m=()=>{if(e.f){const x=_?de(v,a)?v[a]:d[a]:a.value;i?te(x)&&Ei(x,r):te(x)?x.includes(r)||x.push(r):_?(d[a]=[r],de(v,a)&&(v[a]=d[a])):(a.value=[r],e.k&&(d[e.k]=a.value))}else _?(d[a]=o,de(v,a)&&(v[a]=o)):g&&(a.value=o,e.k&&(d[e.k]=o))};o?(m.id=-1,ze(m,l)):m()}}}let Tt=!1;const on=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",sn=e=>e.nodeType===8;function ja(e){const{mt:t,p:l,o:{patchProp:n,createText:i,nextSibling:r,parentNode:o,remove:c,insert:a,createComment:u}}=e,d=(b,y)=>{if(!y.hasChildNodes()){l(null,b,y),mn(),y._vnode=b;return}Tt=!1,v(y.firstChild,b,null,null,null),mn(),y._vnode=b,Tt&&console.error("Hydration completed but contains mismatches.")},v=(b,y,H,G,N,E=!1)=>{const K=sn(b)&&b.data==="[",w=()=>x(b,y,H,G,N,K),{type:z,ref:L,shapeFlag:V,patchFlag:le}=y;let ne=b.nodeType;y.el=b,le===-2&&(E=!1,y.dynamicChildren=null);let S=null;switch(z){case al:ne!==3?y.children===""?(a(y.el=i(""),o(b),b),S=b):S=w():(b.data!==y.children&&(Tt=!0,b.data=y.children),S=r(b));break;case Ye:O(b)?(S=r(b),D(y.el=b.content.firstChild,b,H)):ne!==8||K?S=w():S=r(b);break;case Rl:if(K&&(b=r(b),ne=b.nodeType),ne===1||ne===3){S=b;const Q=!y.children.length;for(let X=0;X{E=E||!!y.dynamicChildren;const{type:K,props:w,patchFlag:z,shapeFlag:L,dirs:V,transition:le}=y,ne=K==="input"||K==="option";if(ne||z!==-1){V&&ct(y,null,H,"created");let S=!1;if(O(b)){S=ss(G,le)&&H&&H.vnode.props&&H.vnode.props.appear;const X=b.content.firstChild;S&&le.beforeEnter(X),D(X,b,H),y.el=b=X}if(w)if(ne||!E||z&48)for(const X in w)(ne&&(X.endsWith("value")||X==="indeterminate")||Bl(X)&&!Al(X)||X[0]===".")&&n(b,X,null,w[X],!1,void 0,H);else w.onClick&&n(b,"onClick",null,w.onClick,!1,void 0,H);let Q;if((Q=w&&w.onVnodeBeforeMount)&&Je(Q,H,y),V&&ct(y,null,H,"beforeMount"),((Q=w&&w.onVnodeMounted)||V||S)&&Ko(()=>{Q&&Je(Q,H,y),S&&le.enter(b),V&&ct(y,null,H,"mounted")},G),L&16&&!(w&&(w.innerHTML||w.textContent))){let X=g(b.firstChild,y,b,H,G,N,E);for(;X;){Tt=!0;const De=X;X=X.nextSibling,c(De)}}else L&8&&b.textContent!==y.children&&(Tt=!0,b.textContent=y.children)}return b.nextSibling},g=(b,y,H,G,N,E,K)=>{K=K||!!y.dynamicChildren;const w=y.children,z=w.length;for(let L=0;L{const{slotScopeIds:K}=y;K&&(N=N?N.concat(K):K);const w=o(b),z=g(r(b),y,w,H,G,N,E);return z&&sn(z)&&z.data==="]"?r(y.anchor=z):(Tt=!0,a(y.anchor=u("]"),w,z),z)},x=(b,y,H,G,N,E)=>{if(Tt=!0,y.el=null,E){const z=A(b);for(;;){const L=r(b);if(L&&L!==z)c(L);else break}}const K=r(b),w=o(b);return c(b),l(null,y,w,K,H,G,on(w),N),K},A=(b,y="[",H="]")=>{let G=0;for(;b;)if(b=r(b),b&&sn(b)&&(b.data===y&&G++,b.data===H)){if(G===0)return r(b);G--}return b},D=(b,y,H)=>{const G=y.parentNode;G&&G.replaceChild(b,y);let N=H;for(;N;)N.vnode.el===y&&(N.vnode.el=N.subTree.el=b),N=N.parent},O=b=>b.nodeType===1&&b.tagName.toLowerCase()==="template";return[d,v]}const ze=Ko;function Sa(e){return Ca(e,ja)}function Ca(e,t){const l=ni();l.__VUE__=!0;const{insert:n,remove:i,patchProp:r,createElement:o,createText:c,createComment:a,setText:u,setElementText:d,parentNode:v,nextSibling:_,setScopeId:g=ut,insertStaticContent:m}=e,x=(f,p,k,T=null,R=null,I=null,B=!1,F=null,$=!!p.dynamicChildren)=>{if(f===p)return;f&&!Bt(f,p)&&(T=P(f),He(f,R,I,!0),f=null),p.patchFlag===-2&&($=!1,p.dynamicChildren=null);const{type:j,ref:J,shapeFlag:q}=p;switch(j){case al:A(f,p,k,T);break;case Ye:D(f,p,k,T);break;case Rl:f==null&&O(p,k,T,B);break;case ke:L(f,p,k,T,R,I,B,F,$);break;default:q&1?H(f,p,k,T,R,I,B,F,$):q&6?V(f,p,k,T,R,I,B,F,$):(q&64||q&128)&&j.process(f,p,k,T,R,I,B,F,$,M)}J!=null&&R&&xn(J,f&&f.ref,I,p||f,!p)},A=(f,p,k,T)=>{if(f==null)n(p.el=c(p.children),k,T);else{const R=p.el=f.el;p.children!==f.children&&u(R,p.children)}},D=(f,p,k,T)=>{f==null?n(p.el=a(p.children||""),k,T):p.el=f.el},O=(f,p,k,T)=>{[f.el,f.anchor]=m(f.children,p,k,T,f.el,f.anchor)},b=({el:f,anchor:p},k,T)=>{let R;for(;f&&f!==p;)R=_(f),n(f,k,T),f=R;n(p,k,T)},y=({el:f,anchor:p})=>{let k;for(;f&&f!==p;)k=_(f),i(f),f=k;i(p)},H=(f,p,k,T,R,I,B,F,$)=>{B=B||p.type==="svg",f==null?G(p,k,T,R,I,B,F,$):K(f,p,R,I,B,F,$)},G=(f,p,k,T,R,I,B,F)=>{let $,j;const{type:J,props:q,shapeFlag:Z,transition:re,dirs:se}=f;if($=f.el=o(f.type,I,q&&q.is,q),Z&8?d($,f.children):Z&16&&E(f.children,$,null,T,R,I&&J!=="foreignObject",B,F),se&&ct(f,null,T,"created"),N($,f,f.scopeId,B,T),q){for(const ge in q)ge!=="value"&&!Al(ge)&&r($,ge,null,q[ge],I,f.children,T,R,je);"value"in q&&r($,"value",null,q.value),(j=q.onVnodeBeforeMount)&&Je(j,T,f)}se&&ct(f,null,T,"beforeMount");const me=ss(R,re);me&&re.beforeEnter($),n($,p,k),((j=q&&q.onVnodeMounted)||me||se)&&ze(()=>{j&&Je(j,T,f),me&&re.enter($),se&&ct(f,null,T,"mounted")},R)},N=(f,p,k,T,R)=>{if(k&&g(f,k),T)for(let I=0;I{for(let j=$;j{const F=p.el=f.el;let{patchFlag:$,dynamicChildren:j,dirs:J}=p;$|=f.patchFlag&16;const q=f.props||ye,Z=p.props||ye;let re;k&&Ft(k,!1),(re=Z.onVnodeBeforeUpdate)&&Je(re,k,p,f),J&&ct(p,f,k,"beforeUpdate"),k&&Ft(k,!0);const se=R&&p.type!=="foreignObject";if(j?w(f.dynamicChildren,j,F,k,T,se,I):B||X(f,p,F,null,k,T,se,I,!1),$>0){if($&16)z(F,p,q,Z,k,T,R);else if($&2&&q.class!==Z.class&&r(F,"class",null,Z.class,R),$&4&&r(F,"style",q.style,Z.style,R),$&8){const me=p.dynamicProps;for(let ge=0;ge{re&&Je(re,k,p,f),J&&ct(p,f,k,"updated")},T)},w=(f,p,k,T,R,I,B)=>{for(let F=0;F{if(k!==T){if(k!==ye)for(const F in k)!Al(F)&&!(F in T)&&r(f,F,k[F],null,B,p.children,R,I,je);for(const F in T){if(Al(F))continue;const $=T[F],j=k[F];$!==j&&F!=="value"&&r(f,F,j,$,B,p.children,R,I,je)}"value"in T&&r(f,"value",k.value,T.value)}},L=(f,p,k,T,R,I,B,F,$)=>{const j=p.el=f?f.el:c(""),J=p.anchor=f?f.anchor:c("");let{patchFlag:q,dynamicChildren:Z,slotScopeIds:re}=p;re&&(F=F?F.concat(re):re),f==null?(n(j,k,T),n(J,k,T),E(p.children,k,J,R,I,B,F,$)):q>0&&q&64&&Z&&f.dynamicChildren?(w(f.dynamicChildren,Z,k,R,I,B,F),(p.key!=null||R&&p===R.subTree)&&cs(f,p,!0)):X(f,p,k,J,R,I,B,F,$)},V=(f,p,k,T,R,I,B,F,$)=>{p.slotScopeIds=F,f==null?p.shapeFlag&512?R.ctx.activate(p,k,T,B,$):le(p,k,T,R,I,B,$):ne(f,p,$)},le=(f,p,k,T,R,I,B)=>{const F=f.component=Ua(f,T,R);if(Kl(f)&&(F.ctx.renderer=M),za(F),F.asyncDep){if(R&&R.registerDep(F,S),!f.el){const $=F.subTree=ie(Ye);D(null,$,p,k)}return}S(F,f,p,k,R,I,B)},ne=(f,p,k)=>{const T=p.component=f.component;if(Zc(f,p,k))if(T.asyncDep&&!T.asyncResolved){Q(T,p,k);return}else T.next=p,Kc(T.update),T.update();else p.el=f.el,T.vnode=p},S=(f,p,k,T,R,I,B)=>{const F=()=>{if(f.isMounted){let{next:J,bu:q,u:Z,parent:re,vnode:se}=f,me=J,ge;Ft(f,!1),J?(J.el=se.el,Q(f,J,B)):J=se,q&&Bn(q),(ge=J.props&&J.props.onVnodeBeforeUpdate)&&Je(ge,re,J,se),Ft(f,!0);const Oe=Un(f),et=f.subTree;f.subTree=Oe,x(et,Oe,v(et.el),P(et),f,R,I),J.el=Oe.el,me===null&&ea(f,Oe.el),Z&&ze(Z,R),(ge=J.props&&J.props.onVnodeUpdated)&&ze(()=>Je(ge,re,J,se),R)}else{let J;const{el:q,props:Z}=p,{bm:re,m:se,parent:me}=f,ge=sl(p);if(Ft(f,!1),re&&Bn(re),!ge&&(J=Z&&Z.onVnodeBeforeMount)&&Je(J,me,p),Ft(f,!0),q&&ae){const Oe=()=>{f.subTree=Un(f),ae(q,f.subTree,f,R,null)};ge?p.type.__asyncLoader().then(()=>!f.isUnmounted&&Oe()):Oe()}else{const Oe=f.subTree=Un(f);x(null,Oe,k,T,f,R,I),p.el=Oe.el}if(se&&ze(se,R),!ge&&(J=Z&&Z.onVnodeMounted)){const Oe=p;ze(()=>Je(J,me,Oe),R)}(p.shapeFlag&256||me&&sl(me.vnode)&&me.vnode.shapeFlag&256)&&f.a&&ze(f.a,R),f.isMounted=!0,p=k=T=null}},$=f.effect=new Li(F,()=>jn(j),f.scope),j=f.update=()=>$.run();j.id=f.uid,Ft(f,!0),j()},Q=(f,p,k)=>{p.component=f;const T=f.vnode.props;f.vnode=p,f.next=null,wa(f,p.props,T,k),Da(f,p.children,k),pl(),ar(f),gl()},X=(f,p,k,T,R,I,B,F,$=!1)=>{const j=f&&f.children,J=f?f.shapeFlag:0,q=p.children,{patchFlag:Z,shapeFlag:re}=p;if(Z>0){if(Z&128){Se(j,q,k,T,R,I,B,F,$);return}else if(Z&256){De(j,q,k,T,R,I,B,F,$);return}}re&8?(J&16&&je(j,R,I),q!==j&&d(k,q)):J&16?re&16?Se(j,q,k,T,R,I,B,F,$):je(j,R,I,!0):(J&8&&d(k,""),re&16&&E(q,k,T,R,I,B,F,$))},De=(f,p,k,T,R,I,B,F,$)=>{f=f||nl,p=p||nl;const j=f.length,J=p.length,q=Math.min(j,J);let Z;for(Z=0;ZJ?je(f,R,I,!0,!1,q):E(p,k,T,R,I,B,F,$,q)},Se=(f,p,k,T,R,I,B,F,$)=>{let j=0;const J=p.length;let q=f.length-1,Z=J-1;for(;j<=q&&j<=Z;){const re=f[j],se=p[j]=$?wt(p[j]):tt(p[j]);if(Bt(re,se))x(re,se,k,null,R,I,B,F,$);else break;j++}for(;j<=q&&j<=Z;){const re=f[q],se=p[Z]=$?wt(p[Z]):tt(p[Z]);if(Bt(re,se))x(re,se,k,null,R,I,B,F,$);else break;q--,Z--}if(j>q){if(j<=Z){const re=Z+1,se=reZ)for(;j<=q;)He(f[j],R,I,!0),j++;else{const re=j,se=j,me=new Map;for(j=se;j<=Z;j++){const Ke=p[j]=$?wt(p[j]):tt(p[j]);Ke.key!=null&&me.set(Ke.key,j)}let ge,Oe=0;const et=Z-se+1;let Jt=!1,Ji=0;const kl=new Array(et);for(j=0;j=et){He(Ke,R,I,!0);continue}let st;if(Ke.key!=null)st=me.get(Ke.key);else for(ge=se;ge<=Z;ge++)if(kl[ge-se]===0&&Bt(Ke,p[ge])){st=ge;break}st===void 0?He(Ke,R,I,!0):(kl[st-se]=j+1,st>=Ji?Ji=st:Jt=!0,x(Ke,p[st],k,null,R,I,B,F,$),Oe++)}const Zi=Jt?Va(kl):nl;for(ge=Zi.length-1,j=et-1;j>=0;j--){const Ke=se+j,st=p[Ke],er=Ke+1{const{el:I,type:B,transition:F,children:$,shapeFlag:j}=f;if(j&6){Ue(f.component.subTree,p,k,T);return}if(j&128){f.suspense.move(p,k,T);return}if(j&64){B.move(f,p,k,M);return}if(B===ke){n(I,p,k);for(let q=0;q<$.length;q++)Ue($[q],p,k,T);n(f.anchor,p,k);return}if(B===Rl){b(f,p,k);return}if(T!==2&&j&1&&F)if(T===0)F.beforeEnter(I),n(I,p,k),ze(()=>F.enter(I),R);else{const{leave:q,delayLeave:Z,afterLeave:re}=F,se=()=>n(I,p,k),me=()=>{q(I,()=>{se(),re&&re()})};Z?Z(I,se,me):me()}else n(I,p,k)},He=(f,p,k,T=!1,R=!1)=>{const{type:I,props:B,ref:F,children:$,dynamicChildren:j,shapeFlag:J,patchFlag:q,dirs:Z}=f;if(F!=null&&xn(F,null,k,f,!0),J&256){p.ctx.deactivate(f);return}const re=J&1&&Z,se=!sl(f);let me;if(se&&(me=B&&B.onVnodeBeforeUnmount)&&Je(me,p,f),J&6)ot(f.component,k,T);else{if(J&128){f.suspense.unmount(k,T);return}re&&ct(f,null,p,"beforeUnmount"),J&64?f.type.remove(f,p,k,R,M,T):j&&(I!==ke||q>0&&q&64)?je(j,p,k,!1,!0):(I===ke&&q&384||!R&&J&16)&&je($,p,k),T&&yt(f)}(se&&(me=B&&B.onVnodeUnmounted)||re)&&ze(()=>{me&&Je(me,p,f),re&&ct(f,null,p,"unmounted")},k)},yt=f=>{const{type:p,el:k,anchor:T,transition:R}=f;if(p===ke){xt(k,T);return}if(p===Rl){y(f);return}const I=()=>{i(k),R&&!R.persisted&&R.afterLeave&&R.afterLeave()};if(f.shapeFlag&1&&R&&!R.persisted){const{leave:B,delayLeave:F}=R,$=()=>B(k,I);F?F(f.el,I,$):$()}else I()},xt=(f,p)=>{let k;for(;f!==p;)k=_(f),i(f),f=k;i(p)},ot=(f,p,k)=>{const{bum:T,scope:R,update:I,subTree:B,um:F}=f;T&&Bn(T),R.stop(),I&&(I.active=!1,He(B,f,p,k)),F&&ze(F,p),ze(()=>{f.isUnmounted=!0},p),p&&p.pendingBranch&&!p.isUnmounted&&f.asyncDep&&!f.asyncResolved&&f.suspenseId===p.pendingId&&(p.deps--,p.deps===0&&p.resolve())},je=(f,p,k,T=!1,R=!1,I=0)=>{for(let B=I;Bf.shapeFlag&6?P(f.component.subTree):f.shapeFlag&128?f.suspense.next():_(f.anchor||f.el),U=(f,p,k)=>{f==null?p._vnode&&He(p._vnode,null,null,!0):x(p._vnode||null,f,p,null,null,null,k),ar(),mn(),p._vnode=f},M={p:x,um:He,m:Ue,r:yt,mt:le,mc:E,pc:X,pbc:w,n:P,o:e};let Y,ae;return t&&([Y,ae]=t(M)),{render:U,hydrate:Y,createApp:Pa(U,Y)}}function Ft({effect:e,update:t},l){e.allowRecurse=t.allowRecurse=l}function ss(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function cs(e,t,l=!1){const n=e.children,i=t.children;if(te(n)&&te(i))for(let r=0;r>1,e[l[c]]0&&(t[n]=l[r-1]),l[r]=n)}}for(r=l.length,o=l[r-1];r-- >0;)l[r]=o,o=t[o];return l}const Fa=e=>e.__isTeleport,ke=Symbol.for("v-fgt"),al=Symbol.for("v-txt"),Ye=Symbol.for("v-cmt"),Rl=Symbol.for("v-stc"),Il=[];let nt=null;function W(e=!1){Il.push(nt=e?null:[])}function Na(){Il.pop(),nt=Il[Il.length-1]||null}let Fl=1;function Er(e){Fl+=e}function as(e){return e.dynamicChildren=Fl>0?nt||nl:null,Na(),Fl>0&&nt&&nt.push(e),e}function ee(e,t,l,n,i,r){return as(ce(e,t,l,n,i,r,!0))}function Ae(e,t,l,n,i){return as(ie(e,t,l,n,i,!0))}function Ln(e){return e?e.__v_isVNode===!0:!1}function Bt(e,t){return e.type===t.type&&e.key===t.key}const Fn="__vInternal",us=({key:e})=>e??null,vn=({ref:e,ref_key:t,ref_for:l})=>(typeof e=="number"&&(e=""+e),e!=null?we(e)||Ne(e)||oe(e)?{i:Ve,r:e,k:t,f:!!l}:e:null);function ce(e,t=null,l=null,n=0,i=null,r=e===ke?0:1,o=!1,c=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&us(t),ref:t&&vn(t),scopeId:Xo,slotScopeIds:null,children:l,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:n,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:Ve};return c?(Ci(a,l),r&128&&e.normalize(a)):l&&(a.shapeFlag|=we(l)?8:16),Fl>0&&!o&&nt&&(a.patchFlag>0||r&6)&&a.patchFlag!==32&&nt.push(a),a}const ie=Ha;function Ha(e,t=null,l=null,n=0,i=null,r=!1){if((!e||e===la)&&(e=Ye),Ln(e)){const c=Ct(e,t,!0);return l&&Ci(c,l),Fl>0&&!r&&nt&&(c.shapeFlag&6?nt[nt.indexOf(e)]=c:nt.push(c)),c.patchFlag|=-2,c}if(Ya(e)&&(e=e.__vccOpts),t){t=Ma(t);let{class:c,style:a}=t;c&&!we(c)&&(t.class=$e(c)),Ee(a)&&(Vo(a)&&!te(a)&&(a=Ie({},a)),t.style=Wl(a))}const o=we(e)?1:ia(e)?128:Fa(e)?64:Ee(e)?4:oe(e)?2:0;return ce(e,t,l,n,i,o,r,!0)}function Ma(e){return e?Vo(e)||Fn in e?Ie({},e):e:null}function Ct(e,t,l=!1){const{props:n,ref:i,patchFlag:r,children:o}=e,c=t?_i(n||{},t):n;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:c,key:c&&us(c),ref:t&&t.ref?l&&i?te(i)?i.concat(vn(t)):[i,vn(t)]:vn(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ke?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Ct(e.ssContent),ssFallback:e.ssFallback&&Ct(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function Vt(e=" ",t=0){return ie(al,null,e,t)}function $a(e,t){const l=ie(Rl,null,e);return l.staticCount=t,l}function Le(e="",t=!1){return t?(W(),Ae(Ye,null,e)):ie(Ye,null,e)}function tt(e){return e==null||typeof e=="boolean"?ie(Ye):te(e)?ie(ke,null,e.slice()):typeof e=="object"?wt(e):ie(al,null,String(e))}function wt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Ct(e)}function Ci(e,t){let l=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(te(t))l=16;else if(typeof t=="object")if(n&65){const i=t.default;i&&(i._c&&(i._d=!1),Ci(e,i()),i._c&&(i._d=!0));return}else{l=32;const i=t._;!i&&!(Fn in t)?t._ctx=Ve:i===3&&Ve&&(Ve.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else oe(t)?(t={default:t,_ctx:Ve},l=32):(t=String(t),n&64?(l=16,t=[Vt(t)]):l=8);e.children=t,e.shapeFlag|=l}function _i(...e){const t={};for(let l=0;lRe||Ve;let Fi,Zt,yr="__VUE_INSTANCE_SETTERS__";(Zt=ni()[yr])||(Zt=ni()[yr]=[]),Zt.push(e=>Re=e),Fi=e=>{Zt.length>1?Zt.forEach(t=>t(e)):Zt[0](e)};const ul=e=>{Fi(e),e.scope.on()},qt=()=>{Re&&Re.scope.off(),Fi(null)};function ds(e){return e.vnode.shapeFlag&4}let dl=!1;function za(e,t=!1){dl=t;const{props:l,children:n}=e.vnode,i=ds(e);Aa(e,l,i,t),Ia(e,n);const r=i?Xa(e,t):void 0;return dl=!1,r}function Xa(e,t){const l=e.type;e.accessCache=Object.create(null),e.proxy=Fo(new Proxy(e.ctx,ka));const{setup:n}=l;if(n){const i=e.setupContext=n.length>1?qa(e):null;ul(e),pl();const r=Dt(n,e,0,[e.props,i]);if(gl(),qt(),bo(r)){if(r.then(qt,qt),t)return r.then(o=>{xr(e,o,t)}).catch(o=>{zl(o,e,0)});e.asyncDep=r}else xr(e,r,t)}else hs(e,t)}function xr(e,t,l){oe(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Ee(t)&&(e.setupState=Mo(t)),hs(e,l)}let Lr;function hs(e,t,l){const n=e.type;if(!e.render){if(!t&&Lr&&!n.render){const i=n.template||ji(e).template;if(i){const{isCustomElement:r,compilerOptions:o}=e.appContext.config,{delimiters:c,compilerOptions:a}=n,u=Ie(Ie({isCustomElement:r,delimiters:c},o),a);n.render=Lr(i,u)}}e.render=n.render||ut}{ul(e),pl();try{Ea(e)}finally{gl(),qt()}}}function Ka(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,l){return Xe(e,"get","$attrs"),t[l]}}))}function qa(e){const t=l=>{e.exposed=l||{}};return{get attrs(){return Ka(e)},slots:e.slots,emit:e.emit,expose:t}}function Nn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Mo(Fo(e.exposed)),{get(t,l){if(l in t)return t[l];if(l in wl)return wl[l](e)},has(t,l){return l in t||l in wl}}))}function Ga(e,t=!0){return oe(e)?e.displayName||e.name:e.name||t&&e.__name}function Ya(e){return oe(e)&&"__vccOpts"in e}const C=(e,t)=>Uc(e,t,dl);function he(e,t,l){const n=arguments.length;return n===2?Ee(t)&&!te(t)?Ln(t)?ie(e,null,[t]):ie(e,t):ie(e,null,t):(n>3?l=Array.prototype.slice.call(arguments,2):n===3&&Ln(l)&&(l=[l]),ie(e,t,l))}const Qa=Symbol.for("v-scx"),Ja=()=>Te(Qa),Za="3.3.13",eu="http://www.w3.org/2000/svg",Wt=typeof document<"u"?document:null,Tr=Wt&&Wt.createElement("template"),tu={insert:(e,t,l)=>{t.insertBefore(e,l||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,l,n)=>{const i=t?Wt.createElementNS(eu,e):Wt.createElement(e,l?{is:l}:void 0);return e==="select"&&n&&n.multiple!=null&&i.setAttribute("multiple",n.multiple),i},createText:e=>Wt.createTextNode(e),createComment:e=>Wt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Wt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,l,n,i,r){const o=l?l.previousSibling:t.lastChild;if(i&&(i===r||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),l),!(i===r||!(i=i.nextSibling)););else{Tr.innerHTML=n?`${e}`:e;const c=Tr.content;if(n){const a=c.firstChild;for(;a.firstChild;)c.appendChild(a.firstChild);c.removeChild(a)}t.insertBefore(c,l)}return[o?o.nextSibling:t.firstChild,l?l.previousSibling:t.lastChild]}},Ot="transition",El="animation",Nl=Symbol("_vtc"),Gl=(e,{slots:t})=>he(aa,lu(e),t);Gl.displayName="Transition";const vs={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};Gl.props=Ie({},Go,vs);const Nt=(e,t=[])=>{te(e)?e.forEach(l=>l(...t)):e&&e(...t)},Or=e=>e?te(e)?e.some(t=>t.length>1):e.length>1:!1;function lu(e){const t={};for(const L in e)L in vs||(t[L]=e[L]);if(e.css===!1)return t;const{name:l="v",type:n,duration:i,enterFromClass:r=`${l}-enter-from`,enterActiveClass:o=`${l}-enter-active`,enterToClass:c=`${l}-enter-to`,appearFromClass:a=r,appearActiveClass:u=o,appearToClass:d=c,leaveFromClass:v=`${l}-leave-from`,leaveActiveClass:_=`${l}-leave-active`,leaveToClass:g=`${l}-leave-to`}=e,m=nu(i),x=m&&m[0],A=m&&m[1],{onBeforeEnter:D,onEnter:O,onEnterCancelled:b,onLeave:y,onLeaveCancelled:H,onBeforeAppear:G=D,onAppear:N=O,onAppearCancelled:E=b}=t,K=(L,V,le)=>{Ht(L,V?d:c),Ht(L,V?u:o),le&&le()},w=(L,V)=>{L._isLeaving=!1,Ht(L,v),Ht(L,g),Ht(L,_),V&&V()},z=L=>(V,le)=>{const ne=L?N:O,S=()=>K(V,L,le);Nt(ne,[V,S]),Pr(()=>{Ht(V,L?a:r),Pt(V,L?d:c),Or(ne)||Ar(V,n,x,S)})};return Ie(t,{onBeforeEnter(L){Nt(D,[L]),Pt(L,r),Pt(L,o)},onBeforeAppear(L){Nt(G,[L]),Pt(L,a),Pt(L,u)},onEnter:z(!1),onAppear:z(!0),onLeave(L,V){L._isLeaving=!0;const le=()=>w(L,V);Pt(L,v),ou(),Pt(L,_),Pr(()=>{L._isLeaving&&(Ht(L,v),Pt(L,g),Or(y)||Ar(L,n,A,le))}),Nt(y,[L,le])},onEnterCancelled(L){K(L,!1),Nt(b,[L])},onAppearCancelled(L){K(L,!0),Nt(E,[L])},onLeaveCancelled(L){w(L),Nt(H,[L])}})}function nu(e){if(e==null)return null;if(Ee(e))return[qn(e.enter),qn(e.leave)];{const t=qn(e);return[t,t]}}function qn(e){return oc(e)}function Pt(e,t){t.split(/\s+/).forEach(l=>l&&e.classList.add(l)),(e[Nl]||(e[Nl]=new Set)).add(t)}function Ht(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.remove(n));const l=e[Nl];l&&(l.delete(t),l.size||(e[Nl]=void 0))}function Pr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let iu=0;function Ar(e,t,l,n){const i=e._endId=++iu,r=()=>{i===e._endId&&n()};if(l)return setTimeout(r,l);const{type:o,timeout:c,propCount:a}=ru(e,t);if(!o)return n();const u=o+"end";let d=0;const v=()=>{e.removeEventListener(u,_),r()},_=g=>{g.target===e&&++d>=a&&v()};setTimeout(()=>{d(l[m]||"").split(", "),i=n(`${Ot}Delay`),r=n(`${Ot}Duration`),o=wr(i,r),c=n(`${El}Delay`),a=n(`${El}Duration`),u=wr(c,a);let d=null,v=0,_=0;t===Ot?o>0&&(d=Ot,v=o,_=r.length):t===El?u>0&&(d=El,v=u,_=a.length):(v=Math.max(o,u),d=v>0?o>u?Ot:El:null,_=d?d===Ot?r.length:a.length:0);const g=d===Ot&&/\b(transform|all)(,|$)/.test(n(`${Ot}Property`).toString());return{type:d,timeout:v,propCount:_,hasTransform:g}}function wr(e,t){for(;e.lengthRr(l)+Rr(e[n])))}function Rr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function ou(){return document.body.offsetHeight}function su(e,t,l){const n=e[Nl];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):l?e.setAttribute("class",t):e.className=t}const Ni=Symbol("_vod"),Tn={beforeMount(e,{value:t},{transition:l}){e[Ni]=e.style.display==="none"?"":e.style.display,l&&t?l.beforeEnter(e):yl(e,t)},mounted(e,{value:t},{transition:l}){l&&t&&l.enter(e)},updated(e,{value:t,oldValue:l},{transition:n}){!t!=!l&&(n?t?(n.beforeEnter(e),yl(e,!0),n.enter(e)):n.leave(e,()=>{yl(e,!1)}):yl(e,t))},beforeUnmount(e,{value:t}){yl(e,t)}};function yl(e,t){e.style.display=t?e[Ni]:"none"}const cu=Symbol("");function au(e,t,l){const n=e.style,i=we(l);if(l&&!i){if(t&&!we(t))for(const r in t)l[r]==null&&fi(n,r,"");for(const r in l)fi(n,r,l[r])}else{const r=n.display;if(i){if(t!==l){const o=n[cu];o&&(l+=";"+o),n.cssText=l}}else t&&e.removeAttribute("style");Ni in e&&(n.display=r)}}const Ir=/\s*!important$/;function fi(e,t,l){if(te(l))l.forEach(n=>fi(e,t,n));else if(l==null&&(l=""),t.startsWith("--"))e.setProperty(t,l);else{const n=uu(e,t);Ir.test(l)?e.setProperty(Qt(n),l.replace(Ir,""),"important"):e[n]=l}}const Dr=["Webkit","Moz","ms"],Gn={};function uu(e,t){const l=Gn[t];if(l)return l;let n=dt(t);if(n!=="filter"&&n in e)return Gn[t]=n;n=wn(n);for(let i=0;iYn||(gu.then(()=>Yn=0),Yn=Date.now());function bu(e,t){const l=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=l.attached)return;Ze(ku(n,l.value),t,5,[n])};return l.value=e,l.attached=mu(),l}function ku(e,t){if(te(t)){const l=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{l.call(e),e._stopped=!0},t.map(n=>i=>!i._stopped&&n&&n(i))}else return t}const Vr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Eu=(e,t,l,n,i=!1,r,o,c,a)=>{t==="class"?su(e,n,i):t==="style"?au(e,l,n):Bl(t)?ki(t)||fu(e,t,l,n,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):yu(e,t,n,i))?hu(e,t,n,r,o,c,a):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),du(e,t,n,i))};function yu(e,t,l,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&Vr(t)&&oe(l));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return Vr(t)&&we(l)?!1:t in e}const xu={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},Lu=(e,t)=>{const l=e._withKeys||(e._withKeys={}),n=t.join(".");return l[n]||(l[n]=i=>{if(!("key"in i))return;const r=Qt(i.key);if(t.some(o=>o===r||xu[o]===r))return e(i)})},Tu=Ie({patchProp:Eu},tu);let Qn,Fr=!1;function Ou(){return Qn=Fr?Qn:Sa(Tu),Fr=!0,Qn}const Pu=(...e)=>{const t=Ou().createApp(...e),{mount:l}=t;return t.mount=n=>{const i=Au(n);if(i)return l(i,!0,i instanceof SVGElement)},t};function Au(e){return we(e)?document.querySelector(e):e}const wu="modulepreload",Ru=function(e){return"/"+e},Nr={},s=function(t,l,n){let i=Promise.resolve();return l&&l.length>0&&(document.getElementsByTagName("link"),i=Promise.all(l.map(r=>{if(r=Ru(r),r in Nr)return;Nr[r]=!0;const o=r.endsWith(".css"),c=o?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${r}"]${c}`))return;const a=document.createElement("link");if(a.rel=o?"stylesheet":wu,o||(a.as="script",a.crossOrigin=""),a.href=r,document.head.appendChild(a),o)return new Promise((u,d)=>{a.addEventListener("load",u),a.addEventListener("error",()=>d(new Error(`Unable to preload CSS for ${r}`)))})}))),i.then(()=>t()).catch(r=>{const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=r,window.dispatchEvent(o),!o.defaultPrevented)throw r})},Iu={"v-8daa1a0e":()=>s(()=>import("./index.html-D9G6CNbk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-aad48c6a":()=>s(()=>import("./news.html-C-ufwDLv.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ba934fd8":()=>s(()=>import("./index.html-B2ETL5pY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41ade9da":()=>s(()=>import("./api.html-5y-QWEO9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-83dedd38":()=>s(()=>import("./dns.html-BfPt-22g.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-192a19b9":()=>s(()=>import("./fakedns.html-BSHcVJMt.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7f6279d8":()=>s(()=>import("./inbound.html-DyiGLTJ2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1d860c29":()=>s(()=>import("./log.html-De0YGftm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fbaf47ec":()=>s(()=>import("./metrics.html-C1kvghj5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-24956213":()=>s(()=>import("./observatory.html-Dkgoiajw.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2367d756":()=>s(()=>import("./outbound.html-C5ktgOxG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4ebec35a":()=>s(()=>import("./policy.html-CErsqhDk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-31b7756a":()=>s(()=>import("./reverse.html-BzUnx5j0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-70677432":()=>s(()=>import("./routing.html-D0dccOVI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7e21d6ae":()=>s(()=>import("./stats.html-DHCl8ess.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e3dfff38":()=>s(()=>import("./transport.html-CXI2SbwO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f7496066":()=>s(()=>import("./index.html-CTbMiGG2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-36b1a79b":()=>s(()=>import("./index.html-CA-WluU-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-09a64f89":()=>s(()=>import("./command.html-opo_NLX2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2b1adf48":()=>s(()=>import("./config.html-O0hv2z0b.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-86ee963a":()=>s(()=>import("./document.html-vroedGik.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0e5d7b39":()=>s(()=>import("./install.html-f63Sv7SS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2d0a870d":()=>s(()=>import("./index.html-QftOk6LQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2d0ab8b3":()=>s(()=>import("./index.html-CshDtg4G.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d714d87":()=>s(()=>import("./browser_dialer.html-DYjgEhDN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0da7880a":()=>s(()=>import("./env.html-x3PGFNW0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2aeb21f9":()=>s(()=>import("./fallback.html-BCz8baOr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3acf20ea":()=>s(()=>import("./multiple.html-CA4IQdBs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-792e28f8":()=>s(()=>import("./xtls.html-DTQkH1EU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b50d2334":()=>s(()=>import("./dokodemo.html-BVzbqjRe.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-593408b0":()=>s(()=>import("./http.html-BIzz1n6q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-802a842a":()=>s(()=>import("./shadowsocks.html-Bog2IQ_X.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-29995cea":()=>s(()=>import("./socks.html-DSlw2Tvo.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2a1b3d72":()=>s(()=>import("./trojan.html-BkQCt-32.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fb92e8aa":()=>s(()=>import("./vless.html-CxK3eXqB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-167afaac":()=>s(()=>import("./vmess.html-BSAH9EwQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-749ad71a":()=>s(()=>import("./blackhole.html-C3j-gtFm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6d39b970":()=>s(()=>import("./dns.html-R1M3D1VY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d76e893a":()=>s(()=>import("./freedom.html-Q-WXO_3C.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c6b4b59e":()=>s(()=>import("./http.html-CqFywJ_o.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41ec0e0e":()=>s(()=>import("./loopback.html-CYltRkS6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7b293e4a":()=>s(()=>import("./shadowsocks.html-BdSAub8s.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-15f5452a":()=>s(()=>import("./socks.html-C_Ryg_Zn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5797bdb3":()=>s(()=>import("./trojan.html-_aC10_zp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a60f016c":()=>s(()=>import("./vless.html-sPPpqcW_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-413cee4b":()=>s(()=>import("./vmess.html-3bHG9IEs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-208ca3b9":()=>s(()=>import("./wireguard.html-DMp0Htsq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-775db7b1":()=>s(()=>import("./domainsocket.html-DZc5AOZh.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2877542a":()=>s(()=>import("./grpc.html-BOwRBc6V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-03a28284":()=>s(()=>import("./h2.html-B-_cdxSw.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-04158536":()=>s(()=>import("./httpupgrade.html-DNm5DiZb.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3167b1dd":()=>s(()=>import("./mkcp.html-CmaMJX_Q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8f08dbec":()=>s(()=>import("./quic.html-t3RvaIkj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-eeea2fb0":()=>s(()=>import("./splithttp.html-DHcDbGo9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-33b1b709":()=>s(()=>import("./tcp.html-tAb-Rdu-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ff57bba":()=>s(()=>import("./websocket.html-J4zD0ZXr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a9e8054":()=>s(()=>import("./compile.html-C08Er0mK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-95e3eaea":()=>s(()=>import("./design.html-JvR3o2wW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-61e7eea6":()=>s(()=>import("./guide.html-CIw6ZqK-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6e6c37e6":()=>s(()=>import("./mkcp.html-BECLirWp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-13168a21":()=>s(()=>import("./muxcool.html-DxsTQuoq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5c48c82b":()=>s(()=>import("./vless.html-bx0zLtjU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ee591a8":()=>s(()=>import("./vmess.html-DH5KSkx4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f09dcfa":()=>s(()=>import("./index.html-CpLT_ZsY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fb444906":()=>s(()=>import("./ch01-preface.html-DmNJxKif.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-075f3ae5":()=>s(()=>import("./ch02-preparation.html-BTKGqj9u.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-726d0633":()=>s(()=>import("./ch03-ssh.html-Bs4sxOG7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-430c6ab8":()=>s(()=>import("./ch04-security.html-BgZQf6Zy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-717c6376":()=>s(()=>import("./ch05-webpage.html-C3ISjTL0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-278039be":()=>s(()=>import("./ch06-certificates.html-g-a588dM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a0c7f88e":()=>s(()=>import("./ch07-xray-server.html-CL7ODUGu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-86586ca2":()=>s(()=>import("./ch08-xray-clients.html-D0DH-0jR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3eb62514":()=>s(()=>import("./ch09-appendix.html-B-sOxmCt.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f09dcbc":()=>s(()=>import("./index.html-Z8xBvZ8J.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b21a2a20":()=>s(()=>import("./fallbacks-lv1.html-Dyr_PhvB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-da623318":()=>s(()=>import("./fallbacks-with-sni.html-V5VzGt_a.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fdd722ac":()=>s(()=>import("./routing-lv1-part1.html-DsPriwu4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fa6d716e":()=>s(()=>import("./routing-lv1-part2.html-Shikx9Ih.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2f29e106":()=>s(()=>import("./work.html-CEe4qs2X.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f09dc7e":()=>s(()=>import("./index.html-DC6-KGmE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1c17916e":()=>s(()=>import("./iptables_gid.html-BMSyFQlC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a001cfa6":()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-BRMPCdti.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-46333b48":()=>s(()=>import("./redirect.html-qKHxqUqo.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-338bc63e":()=>s(()=>import("./tproxy.html-ByDe25dh.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d68f7d58":()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-D-5zdr32.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e533e2c6":()=>s(()=>import("./traffic_stats.html-0T5V4GoX.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1e465ab0":()=>s(()=>import("./warp.html-BDXJx2co.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1080fb37":()=>s(()=>import("./news.html-Cct6yV3F.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-317fc580":()=>s(()=>import("./index.html-CVcFP_qj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-45144c7f":()=>s(()=>import("./api.html-Kao4_KiT.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-23fbd2d0":()=>s(()=>import("./dns.html-CvTCwYNS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2b7ec525":()=>s(()=>import("./fakedns.html-Dvu3AZyj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5ab92300":()=>s(()=>import("./inbound.html-YO29XvIi.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f91d64d6":()=>s(()=>import("./log.html-IZnUGgyl.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d705f114":()=>s(()=>import("./metrics.html-BLJ8GVn6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-268cd669":()=>s(()=>import("./outbound.html-DEfIgkBm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4492d567":()=>s(()=>import("./policy.html-C8ASaUzS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d0e1e92":()=>s(()=>import("./reverse.html-BnnvxzqT.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4bbe1d5a":()=>s(()=>import("./routing.html-FLu7YnPx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-16426d1a":()=>s(()=>import("./stats.html-DGZuatV1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5de780d0":()=>s(()=>import("./transport.html-HJMM8SAW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f88d343e":()=>s(()=>import("./index.html-CFqc6OBy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-38d56a07":()=>s(()=>import("./index.html-C3JYr0X_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d046016":()=>s(()=>import("./command.html-CnAfnl0M.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22b35270":()=>s(()=>import("./config.html-DrlSKA0W.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-30bd7c12":()=>s(()=>import("./document.html-CBY4dmVD.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-439608b6":()=>s(()=>import("./install.html-B3katEMP.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-408e88d1":()=>s(()=>import("./news.html-CHwot1ez.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b1cce5cc":()=>s(()=>import("./index.html-Br3dj_2c.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7521da19":()=>s(()=>import("./api.html-DLDnYtg0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5409606a":()=>s(()=>import("./dns.html-DfoiH0ad.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5877f5bf":()=>s(()=>import("./fakedns.html-DFAPe69C.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-00c6c1cc":()=>s(()=>import("./inbound.html-BrzkUvMu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-990249a2":()=>s(()=>import("./log.html-DcQn41R9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d138fe0":()=>s(()=>import("./metrics.html-wNzErJVc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-11e9cb19":()=>s(()=>import("./observatory.html-CQ1B9WMF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ce8c8de2":()=>s(()=>import("./outbound.html-DS1UueDj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3dc4298d":()=>s(()=>import("./policy.html-CZXmUkYI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-26722151":()=>s(()=>import("./reverse.html-B5DaFRsx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-071a21ed":()=>s(()=>import("./routing.html-CSEUsncX.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7922fc34":()=>s(()=>import("./stats.html-CkQuuoBx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3156f2ea":()=>s(()=>import("./transport.html-BiA5MGQV.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-40ee4e87":()=>s(()=>import("./index.html-BBMcLiPC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a1c899be":()=>s(()=>import("./index.html-B-J-mqnv.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a6257be2":()=>s(()=>import("./command.html-DLT-4XC7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d63f95d4":()=>s(()=>import("./config.html-CpMF1H3m.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fbbfd9c6":()=>s(()=>import("./document.html-Cv2iGxpB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9cb72482":()=>s(()=>import("./install.html-DvdIFSLJ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-51a51d87":()=>s(()=>import("./transparent_proxy.html-DZNi96TQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-76b9a0f3":()=>s(()=>import("./browser_dialer.html-Bdbrov2m.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-565dbfc4":()=>s(()=>import("./env.html-kVBaIisu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0fbd1336":()=>s(()=>import("./fallback.html-Cz26Rtbk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a0627812":()=>s(()=>import("./multiple.html-672DYUik.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d190d938":()=>s(()=>import("./xtls.html-enE-oLop.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-72afc2d2":()=>s(()=>import("./dokodemo.html-tumWX5uf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-773d731c":()=>s(()=>import("./http.html-Dk_GJXk3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f555fc02":()=>s(()=>import("./shadowsocks.html-nKE9-JwE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e35196c2":()=>s(()=>import("./socks.html-DxBaX8G5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-29188644":()=>s(()=>import("./trojan.html-2VAwem9J.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-255a6ebf":()=>s(()=>import("./vless.html-BCCfQS7T.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8cc24480":()=>s(()=>import("./vmess.html-DmF6uMmY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-64e47ef4":()=>s(()=>import("./blackhole.html-Cv99Ln_e.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e979b848":()=>s(()=>import("./dns.html-B4Qc1gmf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-617f0fcf":()=>s(()=>import("./freedom.html-uHQ6fg4W.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3fc98845":()=>s(()=>import("./http.html-BW71su7G.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1b804722":()=>s(()=>import("./loopback.html-DBZDnpde.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-63077cb6":()=>s(()=>import("./shadowsocks.html-Cfe33M9q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-516476d4":()=>s(()=>import("./socks.html-ZsLxpdI_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d61a872":()=>s(()=>import("./trojan.html-C_OdgAQH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6e50feb6":()=>s(()=>import("./vless.html-DNT9jIbN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-02956db7":()=>s(()=>import("./vmess.html-BnKkO-oz.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-797f8d25":()=>s(()=>import("./wireguard.html-B1zHQq-E.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3eb3e9c6":()=>s(()=>import("./domainsocket.html-DIVEYZMl.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2c6058d4":()=>s(()=>import("./grpc.html-D7nAIvyK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1c38292a":()=>s(()=>import("./h2.html-9I7eRGud.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-17ff144a":()=>s(()=>import("./httpupgrade.html-DpYANPWG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1a7f9d6e":()=>s(()=>import("./mkcp.html-D1BaSNsx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-79d41176":()=>s(()=>import("./quic.html-0dkTOtLC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4df52c3c":()=>s(()=>import("./splithttp.html-CESvjk_m.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5254cbc6":()=>s(()=>import("./tcp.html-Dvv-qFsr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9520f392":()=>s(()=>import("./websocket.html-CDgG-JKn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b7760e2c":()=>s(()=>import("./compile.html-CSlVqiWd.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fb774212":()=>s(()=>import("./design.html-CnO0gj1h.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-38c376c1":()=>s(()=>import("./guide.html-C1S7IA49.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21bccd79":()=>s(()=>import("./mkcp.html-VU4-Z4x2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-27001935":()=>s(()=>import("./muxcool.html-CEJDgOyw.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21b30c3f":()=>s(()=>import("./vless.html-DH9DXlDy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-94110980":()=>s(()=>import("./vmess.html-DRYwVgEC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-789ba7ef":()=>s(()=>import("./index.html-B7FLw-wS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d3712ade":()=>s(()=>import("./ch01-preface.html-CpS2RBBO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41f9c00e":()=>s(()=>import("./ch02-preparation.html-nD3-r55P.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4c013f47":()=>s(()=>import("./ch03-ssh.html-6Lvt6PUL.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a75683b8":()=>s(()=>import("./ch04-security.html-B6qoKme-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f5341aec":()=>s(()=>import("./ch05-webpage.html-DzsY94d_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4458f72a":()=>s(()=>import("./ch06-certificates.html-BznpCurY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f1802e66":()=>s(()=>import("./ch07-xray-server.html-DJ8-Sypk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4ca6f1ca":()=>s(()=>import("./ch08-xray-clients.html-DQ22p1_O.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b0030f00":()=>s(()=>import("./ch09-appendix.html-CgxfJw0n.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-789ba80e":()=>s(()=>import("./index.html-NEtYQEGC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-103b3e5c":()=>s(()=>import("./fallbacks-lv1.html-DzqMpBvO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-110dd688":()=>s(()=>import("./fallbacks-with-sni.html--6P9o5e1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c425a7d4":()=>s(()=>import("./routing-lv1-part1.html-GsbV156D.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c0bbf696":()=>s(()=>import("./routing-lv1-part2.html-BeZDTPEs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5b6477cc":()=>s(()=>import("./work.html-bZWwnav2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-789ba82d":()=>s(()=>import("./index.html-CL_S8-vB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-05ddc65d":()=>s(()=>import("./iptables_gid.html-C-yflUZU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-474afe99":()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-D4Pr38b-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-930ac920":()=>s(()=>import("./redirect.html-CkD_E0gF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c579975c":()=>s(()=>import("./tproxy.html-BW6K5LzA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7efb7c68":()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-BQJ6GusY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-12a33bee":()=>s(()=>import("./traffic_stats.html-DD1S40Up.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d2b8478":()=>s(()=>import("./warp.html-C4DFBgRI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1cfb44e6":()=>s(()=>import("./browser_dialer.html-DHvZocHd.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a3f8078":()=>s(()=>import("./env.html-BcRLB4iC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-74f22e7f":()=>s(()=>import("./fallback.html-BtkFw_Xq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2c9f7c11":()=>s(()=>import("./multiple.html-L9QltWwj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-630c687e":()=>s(()=>import("./xtls.html-ByQJIYGC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-20ff0a28":()=>s(()=>import("./dokodemo.html-B3AutCKN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-43124836":()=>s(()=>import("./http.html-wmoV0Z5H.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a351ba5":()=>s(()=>import("./shadowsocks.html-Dq6vO-NY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3d1d02c5":()=>s(()=>import("./socks.html-DOyZIvi6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1567b378":()=>s(()=>import("./trojan.html-ur2ZEK_x.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-57bf8636":()=>s(()=>import("./vless.html-Dp7gCWtk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6864abe6":()=>s(()=>import("./vmess.html-BtGpHvfz.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5910da20":()=>s(()=>import("./blackhole.html-DWoVmjiZ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5717f8f6":()=>s(()=>import("./dns.html-QSFk3MG9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4360702e":()=>s(()=>import("./freedom.html-BE_zomJr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22e1532a":()=>s(()=>import("./http.html-o0wpiHQf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-38c69248":()=>s(()=>import("./loopback.html-BcZmhFf5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1a2a97d0":()=>s(()=>import("./shadowsocks.html-S-jhNF8h.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0141bb30":()=>s(()=>import("./socks.html-zyIZHHJ4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-544bef26":()=>s(()=>import("./trojan.html-2ngT_7cs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cf761560":()=>s(()=>import("./vless.html-CNa_dakW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2c896451":()=>s(()=>import("./vmess.html-D5q0vDPy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0502a6bf":()=>s(()=>import("./wireguard.html-DILhdRFk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5b6ec7b7":()=>s(()=>import("./domainsocket.html-DUhqh-j5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-13c3ca30":()=>s(()=>import("./grpc.html-1JoA2je9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2fe60378":()=>s(()=>import("./h2.html-BOxtTm8R.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-453f5c70":()=>s(()=>import("./httpupgrade.html-C5iPswVE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1cb427e3":()=>s(()=>import("./mkcp.html-DILru_l-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b86fefe0":()=>s(()=>import("./quic.html-Grd-KxcO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-32d545e2":()=>s(()=>import("./splithttp.html-CQc8OFxI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f4c92f7a":()=>s(()=>import("./tcp.html-BgZgnk7j.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cb60c046":()=>s(()=>import("./websocket.html-DNoxTZYE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7ce977e0":()=>s(()=>import("./compile.html-D59MH5rf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-01d5d1de":()=>s(()=>import("./design.html-Ddh8g14z.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d4e5367":()=>s(()=>import("./guide.html-BdEYZrHF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a58031da":()=>s(()=>import("./mkcp.html-DAmKBEn3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5440615b":()=>s(()=>import("./muxcool.html-mhoEooTk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-069325e5":()=>s(()=>import("./vless.html-CkQDajpI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ca50d634":()=>s(()=>import("./vmess.html-DtwTJf0_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-490791ee":()=>s(()=>import("./index.html-CpXf73_p.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-78f09a92":()=>s(()=>import("./ch01-preface.html-w7EJag-g.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-64f6e51f":()=>s(()=>import("./ch02-preparation.html-Dgjcbj9R.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-69478a6d":()=>s(()=>import("./ch03-ssh.html-SW0FgDU9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-271d7abe":()=>s(()=>import("./ch04-security.html-DMyIYFbc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9ab38aa0":()=>s(()=>import("./ch05-webpage.html-BJ9Dh4eq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7cddd6c4":()=>s(()=>import("./ch06-certificates.html-CYpwWYQK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d33adf3":()=>s(()=>import("./ch07-xray-server.html-BMC39V_R.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-123166b5":()=>s(()=>import("./ch08-xray-clients.html-DiJ6a_Z3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22c7351a":()=>s(()=>import("./ch09-appendix.html-CaY0Q2De.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-490791b0":()=>s(()=>import("./index.html-DIt_Qwmg.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e9f80a14":()=>s(()=>import("./fallbacks-lv1.html-Cj8_C__Y.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2db62ba4":()=>s(()=>import("./fallbacks-with-sni.html-UrPS3PK0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-531be8a0":()=>s(()=>import("./routing-lv1-part1.html-ZKuR2lvb.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4fb23762":()=>s(()=>import("./routing-lv1-part2.html-BNHKIWxf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fdd8db80":()=>s(()=>import("./work.html-nNVb3F6P.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-49079172":()=>s(()=>import("./index.html-nyT_8_ff.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-331e0e83":()=>s(()=>import("./iptables_gid.html-5z8dtoE5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7418a5b3":()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-VAv26tAr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-587e32d4":()=>s(()=>import("./redirect.html-IdxcHO8c.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9c63de10":()=>s(()=>import("./tproxy.html-BHj4GcZZ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a4c782e4":()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-D9HsaVXj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-71771ea3":()=>s(()=>import("./traffic_stats.html-D5bPdgjj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-70300bea":()=>s(()=>import("./warp.html-Dj49TU1P.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7689d7f3":()=>s(()=>import("./transparent_proxy.html-C4cGXidp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-39b3c50d":()=>s(()=>import("./transparent_proxy.html-CdU0iNrm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3706649a":()=>s(()=>import("./404.html-CnfmQthm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5c8e777f":()=>s(()=>import("./observatory.html-CSc-qsnJ.js"),__vite__mapDeps([])).then(({data:e})=>e)},Du=JSON.parse('{"base":"/","lang":"en-US","title":"","description":"","head":[["link",{"rel":"icon","href":"/logo.png"}]],"locales":{"/":{"lang":"zh-CN","title":"Project X","description":"Xray 官方文档"},"/en/":{"lang":"en-US","title":"Project X","description":"Official document of Xray"},"/ru/":{"lang":"ru-RU","title":"Project X","description":"Официальная документация Xray"}}}');var ju=["link","meta","script","style","noscript","template"],Su=["title","base"],Cu=([e,t,l])=>Su.includes(e)?e:ju.includes(e)?e==="meta"&&t.name?`${e}.${t.name}`:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,Object.entries(t).map(([n,i])=>typeof i=="boolean"?i?[n,""]:null:[n,i]).filter(n=>n!=null).sort(([n],[i])=>n.localeCompare(i)),l]):null,Vu=e=>{const t=new Set,l=[];return e.forEach(n=>{const i=Cu(n);i&&!t.has(i)&&(t.add(i),l.push(n))}),l},Yl=e=>/^(https?:)?\/\//.test(e),Fu=e=>/^[a-z][a-z0-9+.-]*:/.test(e),Hi=e=>Object.prototype.toString.call(e)==="[object Object]",_s=e=>e[e.length-1]==="/"?e.slice(0,-1):e,fs=e=>e[0]==="/"?e.slice(1):e,ps=(e,t)=>{const l=Object.keys(e).sort((n,i)=>{const r=i.split("/").length-n.split("/").length;return r!==0?r:i.length-n.length});for(const n of l)if(t.startsWith(n))return n;return"/"},Nu=e=>typeof e=="function",it=e=>typeof e=="string";const gs={"v-8daa1a0e":h(()=>s(()=>import("./index.html--jsJa64m.js"),__vite__mapDeps([]))),"v-aad48c6a":h(()=>s(()=>import("./news.html-rpPeZ0HC.js"),__vite__mapDeps([]))),"v-ba934fd8":h(()=>s(()=>import("./index.html-ivJHL5hH.js"),__vite__mapDeps([]))),"v-41ade9da":h(()=>s(()=>import("./api.html-DiYJU8Rg.js"),__vite__mapDeps([]))),"v-83dedd38":h(()=>s(()=>import("./dns.html-YTRgF6GX.js"),__vite__mapDeps([]))),"v-192a19b9":h(()=>s(()=>import("./fakedns.html-BInfP9sg.js"),__vite__mapDeps([]))),"v-7f6279d8":h(()=>s(()=>import("./inbound.html-U-YczWsT.js"),__vite__mapDeps([]))),"v-1d860c29":h(()=>s(()=>import("./log.html-BAb49rK4.js"),__vite__mapDeps([]))),"v-fbaf47ec":h(()=>s(()=>import("./metrics.html-DAUbFlMB.js"),__vite__mapDeps([]))),"v-24956213":h(()=>s(()=>import("./observatory.html-BOdfknrn.js"),__vite__mapDeps([]))),"v-2367d756":h(()=>s(()=>import("./outbound.html-bdM8vFfU.js"),__vite__mapDeps([]))),"v-4ebec35a":h(()=>s(()=>import("./policy.html-Bq1Nx697.js"),__vite__mapDeps([]))),"v-31b7756a":h(()=>s(()=>import("./reverse.html-By4y7JyT.js"),__vite__mapDeps([]))),"v-70677432":h(()=>s(()=>import("./routing.html-BFdIFNzE.js"),__vite__mapDeps([]))),"v-7e21d6ae":h(()=>s(()=>import("./stats.html-B-9-Cpn9.js"),__vite__mapDeps([]))),"v-e3dfff38":h(()=>s(()=>import("./transport.html-DBN2ZByF.js"),__vite__mapDeps([]))),"v-f7496066":h(()=>s(()=>import("./index.html-BGNLRPzE.js"),__vite__mapDeps([]))),"v-36b1a79b":h(()=>s(()=>import("./index.html-D5d6Z4Xz.js"),__vite__mapDeps([]))),"v-09a64f89":h(()=>s(()=>import("./command.html-BIuE6LDM.js"),__vite__mapDeps([]))),"v-2b1adf48":h(()=>s(()=>import("./config.html-BRKvbU_c.js"),__vite__mapDeps([]))),"v-86ee963a":h(()=>s(()=>import("./document.html-BoquODLh.js"),__vite__mapDeps([]))),"v-0e5d7b39":h(()=>s(()=>import("./install.html-CJaw-WJD.js"),__vite__mapDeps([]))),"v-2d0a870d":h(()=>s(()=>import("./index.html-DKrDxjJk.js"),__vite__mapDeps([]))),"v-2d0ab8b3":h(()=>s(()=>import("./index.html-CeWvtNHc.js"),__vite__mapDeps([]))),"v-0d714d87":h(()=>s(()=>import("./browser_dialer.html-BIzbQgRR.js"),__vite__mapDeps([]))),"v-0da7880a":h(()=>s(()=>import("./env.html-DzAnx11j.js"),__vite__mapDeps([]))),"v-2aeb21f9":h(()=>s(()=>import("./fallback.html-DxkOyMwP.js"),__vite__mapDeps([]))),"v-3acf20ea":h(()=>s(()=>import("./multiple.html-BQ0iFIBh.js"),__vite__mapDeps([]))),"v-792e28f8":h(()=>s(()=>import("./xtls.html-D7puBcBG.js"),__vite__mapDeps([]))),"v-b50d2334":h(()=>s(()=>import("./dokodemo.html-D2iCUcXO.js"),__vite__mapDeps([]))),"v-593408b0":h(()=>s(()=>import("./http.html-n_9GtPPz.js"),__vite__mapDeps([]))),"v-802a842a":h(()=>s(()=>import("./shadowsocks.html-BRNfQWR7.js"),__vite__mapDeps([]))),"v-29995cea":h(()=>s(()=>import("./socks.html-D9zJ0rmt.js"),__vite__mapDeps([]))),"v-2a1b3d72":h(()=>s(()=>import("./trojan.html-D2PfY2T3.js"),__vite__mapDeps([]))),"v-fb92e8aa":h(()=>s(()=>import("./vless.html-daOoULRK.js"),__vite__mapDeps([]))),"v-167afaac":h(()=>s(()=>import("./vmess.html-j0DrtN75.js"),__vite__mapDeps([]))),"v-749ad71a":h(()=>s(()=>import("./blackhole.html-CeYMksfi.js"),__vite__mapDeps([]))),"v-6d39b970":h(()=>s(()=>import("./dns.html-5Ofmmx3O.js"),__vite__mapDeps([]))),"v-d76e893a":h(()=>s(()=>import("./freedom.html-D3yZYD_4.js"),__vite__mapDeps([]))),"v-c6b4b59e":h(()=>s(()=>import("./http.html-_MHU72Uy.js"),__vite__mapDeps([]))),"v-41ec0e0e":h(()=>s(()=>import("./loopback.html-D7n84f8k.js"),__vite__mapDeps([]))),"v-7b293e4a":h(()=>s(()=>import("./shadowsocks.html-BQWMkmYl.js"),__vite__mapDeps([]))),"v-15f5452a":h(()=>s(()=>import("./socks.html-CBCl0kQ3.js"),__vite__mapDeps([]))),"v-5797bdb3":h(()=>s(()=>import("./trojan.html-GLPr9L0R.js"),__vite__mapDeps([]))),"v-a60f016c":h(()=>s(()=>import("./vless.html-D_sclD0U.js"),__vite__mapDeps([]))),"v-413cee4b":h(()=>s(()=>import("./vmess.html-BRWJ5o8r.js"),__vite__mapDeps([]))),"v-208ca3b9":h(()=>s(()=>import("./wireguard.html-CYsQqFv0.js"),__vite__mapDeps([]))),"v-775db7b1":h(()=>s(()=>import("./domainsocket.html-CaKSedJK.js"),__vite__mapDeps([]))),"v-2877542a":h(()=>s(()=>import("./grpc.html-C_Kg2sXl.js"),__vite__mapDeps([]))),"v-03a28284":h(()=>s(()=>import("./h2.html-CVsBKDCJ.js"),__vite__mapDeps([]))),"v-04158536":h(()=>s(()=>import("./httpupgrade.html-Fq7D8MW3.js"),__vite__mapDeps([]))),"v-3167b1dd":h(()=>s(()=>import("./mkcp.html-ET0VyK1t.js"),__vite__mapDeps([]))),"v-8f08dbec":h(()=>s(()=>import("./quic.html-DpxBi39d.js"),__vite__mapDeps([]))),"v-eeea2fb0":h(()=>s(()=>import("./splithttp.html-Klo-EToo.js"),__vite__mapDeps([]))),"v-33b1b709":h(()=>s(()=>import("./tcp.html-VJNns-C5.js"),__vite__mapDeps([]))),"v-1ff57bba":h(()=>s(()=>import("./websocket.html-DsKOF98s.js"),__vite__mapDeps([]))),"v-6a9e8054":h(()=>s(()=>import("./compile.html-BcVx6NTs.js"),__vite__mapDeps([]))),"v-95e3eaea":h(()=>s(()=>import("./design.html-gV_s-8kE.js"),__vite__mapDeps([]))),"v-61e7eea6":h(()=>s(()=>import("./guide.html-B4lgRyoL.js"),__vite__mapDeps([]))),"v-6e6c37e6":h(()=>s(()=>import("./mkcp.html-DVsV0BBF.js"),__vite__mapDeps([]))),"v-13168a21":h(()=>s(()=>import("./muxcool.html-BRUL_FdO.js"),__vite__mapDeps([]))),"v-5c48c82b":h(()=>s(()=>import("./vless.html-CccEA1M4.js"),__vite__mapDeps([]))),"v-1ee591a8":h(()=>s(()=>import("./vmess.html-Dt2MIkqN.js"),__vite__mapDeps([]))),"v-3f09dcfa":h(()=>s(()=>import("./index.html-BB8VT9K-.js"),__vite__mapDeps([]))),"v-fb444906":h(()=>s(()=>import("./ch01-preface.html-D5NO_n3E.js"),__vite__mapDeps([]))),"v-075f3ae5":h(()=>s(()=>import("./ch02-preparation.html-zWJTI2fh.js"),__vite__mapDeps([]))),"v-726d0633":h(()=>s(()=>import("./ch03-ssh.html-B-PYaYYd.js"),__vite__mapDeps([]))),"v-430c6ab8":h(()=>s(()=>import("./ch04-security.html-DDDnSxfv.js"),__vite__mapDeps([]))),"v-717c6376":h(()=>s(()=>import("./ch05-webpage.html-BHBAeKP6.js"),__vite__mapDeps([]))),"v-278039be":h(()=>s(()=>import("./ch06-certificates.html-D3AQTy0p.js"),__vite__mapDeps([]))),"v-a0c7f88e":h(()=>s(()=>import("./ch07-xray-server.html-BCFis-sE.js"),__vite__mapDeps([]))),"v-86586ca2":h(()=>s(()=>import("./ch08-xray-clients.html-CxcURVTg.js"),__vite__mapDeps([]))),"v-3eb62514":h(()=>s(()=>import("./ch09-appendix.html-DQIQbM0Q.js"),__vite__mapDeps([]))),"v-3f09dcbc":h(()=>s(()=>import("./index.html-DZgNInr6.js"),__vite__mapDeps([]))),"v-b21a2a20":h(()=>s(()=>import("./fallbacks-lv1.html-CogqnjdA.js"),__vite__mapDeps([]))),"v-da623318":h(()=>s(()=>import("./fallbacks-with-sni.html-BO2m1L8j.js"),__vite__mapDeps([]))),"v-fdd722ac":h(()=>s(()=>import("./routing-lv1-part1.html-ClnBy2hd.js"),__vite__mapDeps([]))),"v-fa6d716e":h(()=>s(()=>import("./routing-lv1-part2.html-BJbHs2YK.js"),__vite__mapDeps([]))),"v-2f29e106":h(()=>s(()=>import("./work.html-CkI961Qb.js"),__vite__mapDeps([]))),"v-3f09dc7e":h(()=>s(()=>import("./index.html-Dd9_Hlk-.js"),__vite__mapDeps([]))),"v-1c17916e":h(()=>s(()=>import("./iptables_gid.html-C7KP3nA5.js"),__vite__mapDeps([]))),"v-a001cfa6":h(()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-DOgxvrPa.js"),__vite__mapDeps([]))),"v-46333b48":h(()=>s(()=>import("./redirect.html-BDtVJCJP.js"),__vite__mapDeps([]))),"v-338bc63e":h(()=>s(()=>import("./tproxy.html-DzexlIqp.js"),__vite__mapDeps([]))),"v-d68f7d58":h(()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-D1MYaJ5_.js"),__vite__mapDeps([]))),"v-e533e2c6":h(()=>s(()=>import("./traffic_stats.html-YbH2kcvo.js"),__vite__mapDeps([]))),"v-1e465ab0":h(()=>s(()=>import("./warp.html-DVfMNHe2.js"),__vite__mapDeps([]))),"v-1080fb37":h(()=>s(()=>import("./news.html-CD7xPbzv.js"),__vite__mapDeps([]))),"v-317fc580":h(()=>s(()=>import("./index.html-COrJaVx-.js"),__vite__mapDeps([]))),"v-45144c7f":h(()=>s(()=>import("./api.html-Dimd9sC-.js"),__vite__mapDeps([]))),"v-23fbd2d0":h(()=>s(()=>import("./dns.html-DdV6b7iZ.js"),__vite__mapDeps([]))),"v-2b7ec525":h(()=>s(()=>import("./fakedns.html-C_E8DnIz.js"),__vite__mapDeps([]))),"v-5ab92300":h(()=>s(()=>import("./inbound.html-BPtpNn0q.js"),__vite__mapDeps([]))),"v-f91d64d6":h(()=>s(()=>import("./log.html-QQtue8CH.js"),__vite__mapDeps([]))),"v-d705f114":h(()=>s(()=>import("./metrics.html-DtVeDNWQ.js"),__vite__mapDeps([]))),"v-268cd669":h(()=>s(()=>import("./outbound.html-CxLNkOG0.js"),__vite__mapDeps([]))),"v-4492d567":h(()=>s(()=>import("./policy.html-fqGpJICm.js"),__vite__mapDeps([]))),"v-0d0e1e92":h(()=>s(()=>import("./reverse.html-bKcExnAb.js"),__vite__mapDeps([]))),"v-4bbe1d5a":h(()=>s(()=>import("./routing.html-XztNj6nv.js"),__vite__mapDeps([]))),"v-16426d1a":h(()=>s(()=>import("./stats.html-CkvTAU5q.js"),__vite__mapDeps([]))),"v-5de780d0":h(()=>s(()=>import("./transport.html-BshIocQ3.js"),__vite__mapDeps([]))),"v-f88d343e":h(()=>s(()=>import("./index.html-BIFt4COA.js"),__vite__mapDeps([]))),"v-38d56a07":h(()=>s(()=>import("./index.html-DM9ULzw6.js"),__vite__mapDeps([]))),"v-4d046016":h(()=>s(()=>import("./command.html-D8s_eq69.js"),__vite__mapDeps([]))),"v-22b35270":h(()=>s(()=>import("./config.html-B1P46wfI.js"),__vite__mapDeps([]))),"v-30bd7c12":h(()=>s(()=>import("./document.html-Bi2pgjPr.js"),__vite__mapDeps([]))),"v-439608b6":h(()=>s(()=>import("./install.html-Bqug4cnA.js"),__vite__mapDeps([]))),"v-408e88d1":h(()=>s(()=>import("./news.html-IY4e89V6.js"),__vite__mapDeps([]))),"v-b1cce5cc":h(()=>s(()=>import("./index.html-NLmGgv-K.js"),__vite__mapDeps([]))),"v-7521da19":h(()=>s(()=>import("./api.html-D-Q2V6zb.js"),__vite__mapDeps([]))),"v-5409606a":h(()=>s(()=>import("./dns.html-DVJjxkIY.js"),__vite__mapDeps([]))),"v-5877f5bf":h(()=>s(()=>import("./fakedns.html-CAdn95B6.js"),__vite__mapDeps([]))),"v-00c6c1cc":h(()=>s(()=>import("./inbound.html-xQYNwVL-.js"),__vite__mapDeps([]))),"v-990249a2":h(()=>s(()=>import("./log.html-DguB3WSi.js"),__vite__mapDeps([]))),"v-7d138fe0":h(()=>s(()=>import("./metrics.html-DZDkDmh2.js"),__vite__mapDeps([]))),"v-11e9cb19":h(()=>s(()=>import("./observatory.html-BJ2zcm9w.js"),__vite__mapDeps([]))),"v-ce8c8de2":h(()=>s(()=>import("./outbound.html-B1Wp8iU4.js"),__vite__mapDeps([]))),"v-3dc4298d":h(()=>s(()=>import("./policy.html-D1uwT0yS.js"),__vite__mapDeps([]))),"v-26722151":h(()=>s(()=>import("./reverse.html-DFbLOQPN.js"),__vite__mapDeps([]))),"v-071a21ed":h(()=>s(()=>import("./routing.html-BMa5pEvD.js"),__vite__mapDeps([]))),"v-7922fc34":h(()=>s(()=>import("./stats.html-Cte6ShpG.js"),__vite__mapDeps([]))),"v-3156f2ea":h(()=>s(()=>import("./transport.html-Dzmzsfae.js"),__vite__mapDeps([]))),"v-40ee4e87":h(()=>s(()=>import("./index.html-BIpYD3t-.js"),__vite__mapDeps([]))),"v-a1c899be":h(()=>s(()=>import("./index.html-LItYxUPJ.js"),__vite__mapDeps([]))),"v-a6257be2":h(()=>s(()=>import("./command.html-Bto6ikLY.js"),__vite__mapDeps([]))),"v-d63f95d4":h(()=>s(()=>import("./config.html-BeNJtLqo.js"),__vite__mapDeps([]))),"v-fbbfd9c6":h(()=>s(()=>import("./document.html-DzcEysYS.js"),__vite__mapDeps([]))),"v-9cb72482":h(()=>s(()=>import("./install.html-BrHImMB4.js"),__vite__mapDeps([]))),"v-51a51d87":h(()=>s(()=>import("./transparent_proxy.html-DRs0jlcN.js"),__vite__mapDeps([]))),"v-76b9a0f3":h(()=>s(()=>import("./browser_dialer.html-D_VAS8oa.js"),__vite__mapDeps([]))),"v-565dbfc4":h(()=>s(()=>import("./env.html-CjyJA0Yb.js"),__vite__mapDeps([]))),"v-0fbd1336":h(()=>s(()=>import("./fallback.html-BUzHu26K.js"),__vite__mapDeps([]))),"v-a0627812":h(()=>s(()=>import("./multiple.html-CNbc9k4q.js"),__vite__mapDeps([]))),"v-d190d938":h(()=>s(()=>import("./xtls.html-BWSKIYgJ.js"),__vite__mapDeps([]))),"v-72afc2d2":h(()=>s(()=>import("./dokodemo.html-DgSj7rLG.js"),__vite__mapDeps([]))),"v-773d731c":h(()=>s(()=>import("./http.html-DQMd16Bw.js"),__vite__mapDeps([]))),"v-f555fc02":h(()=>s(()=>import("./shadowsocks.html-DAtIli5Q.js"),__vite__mapDeps([]))),"v-e35196c2":h(()=>s(()=>import("./socks.html-D9s5DGJl.js"),__vite__mapDeps([]))),"v-29188644":h(()=>s(()=>import("./trojan.html-CGfwGdDo.js"),__vite__mapDeps([]))),"v-255a6ebf":h(()=>s(()=>import("./vless.html-BL9BeTeh.js"),__vite__mapDeps([]))),"v-8cc24480":h(()=>s(()=>import("./vmess.html-D8czgnar.js"),__vite__mapDeps([]))),"v-64e47ef4":h(()=>s(()=>import("./blackhole.html-CobmF86r.js"),__vite__mapDeps([]))),"v-e979b848":h(()=>s(()=>import("./dns.html-Rm3Jy1-p.js"),__vite__mapDeps([]))),"v-617f0fcf":h(()=>s(()=>import("./freedom.html-DW3aa4An.js"),__vite__mapDeps([]))),"v-3fc98845":h(()=>s(()=>import("./http.html-DpWvFZW_.js"),__vite__mapDeps([]))),"v-1b804722":h(()=>s(()=>import("./loopback.html-DZPmfXB9.js"),__vite__mapDeps([]))),"v-63077cb6":h(()=>s(()=>import("./shadowsocks.html-PFxiOWHW.js"),__vite__mapDeps([]))),"v-516476d4":h(()=>s(()=>import("./socks.html-BVR1MsG-.js"),__vite__mapDeps([]))),"v-7d61a872":h(()=>s(()=>import("./trojan.html-DmgOhScb.js"),__vite__mapDeps([]))),"v-6e50feb6":h(()=>s(()=>import("./vless.html-BZ48J9S_.js"),__vite__mapDeps([]))),"v-02956db7":h(()=>s(()=>import("./vmess.html-DArYh1N-.js"),__vite__mapDeps([]))),"v-797f8d25":h(()=>s(()=>import("./wireguard.html-BUaJgccu.js"),__vite__mapDeps([]))),"v-3eb3e9c6":h(()=>s(()=>import("./domainsocket.html-D3nBLz-F.js"),__vite__mapDeps([]))),"v-2c6058d4":h(()=>s(()=>import("./grpc.html-mPuqwjqH.js"),__vite__mapDeps([]))),"v-1c38292a":h(()=>s(()=>import("./h2.html-B8YU87YB.js"),__vite__mapDeps([]))),"v-17ff144a":h(()=>s(()=>import("./httpupgrade.html-DOscHx-c.js"),__vite__mapDeps([]))),"v-1a7f9d6e":h(()=>s(()=>import("./mkcp.html-DQUcXkzK.js"),__vite__mapDeps([]))),"v-79d41176":h(()=>s(()=>import("./quic.html-But08Sia.js"),__vite__mapDeps([]))),"v-4df52c3c":h(()=>s(()=>import("./splithttp.html-9SkrgDgl.js"),__vite__mapDeps([]))),"v-5254cbc6":h(()=>s(()=>import("./tcp.html-BHSzdt5L.js"),__vite__mapDeps([]))),"v-9520f392":h(()=>s(()=>import("./websocket.html-CQ0wGOkU.js"),__vite__mapDeps([]))),"v-b7760e2c":h(()=>s(()=>import("./compile.html-BmYWzF7l.js"),__vite__mapDeps([]))),"v-fb774212":h(()=>s(()=>import("./design.html-nD32aykc.js"),__vite__mapDeps([]))),"v-38c376c1":h(()=>s(()=>import("./guide.html-B3137Mcd.js"),__vite__mapDeps([]))),"v-21bccd79":h(()=>s(()=>import("./mkcp.html-TS7-PC53.js"),__vite__mapDeps([]))),"v-27001935":h(()=>s(()=>import("./muxcool.html-Owf2QQIZ.js"),__vite__mapDeps([]))),"v-21b30c3f":h(()=>s(()=>import("./vless.html-CDOsAnQk.js"),__vite__mapDeps([]))),"v-94110980":h(()=>s(()=>import("./vmess.html-DBKgR8RL.js"),__vite__mapDeps([]))),"v-789ba7ef":h(()=>s(()=>import("./index.html-DdVCvmM2.js"),__vite__mapDeps([]))),"v-d3712ade":h(()=>s(()=>import("./ch01-preface.html-D5988Uh0.js"),__vite__mapDeps([]))),"v-41f9c00e":h(()=>s(()=>import("./ch02-preparation.html-CBryXq1M.js"),__vite__mapDeps([]))),"v-4c013f47":h(()=>s(()=>import("./ch03-ssh.html-CKpEhhik.js"),__vite__mapDeps([]))),"v-a75683b8":h(()=>s(()=>import("./ch04-security.html-BzzIgsFs.js"),__vite__mapDeps([]))),"v-f5341aec":h(()=>s(()=>import("./ch05-webpage.html-CWPEvHEd.js"),__vite__mapDeps([]))),"v-4458f72a":h(()=>s(()=>import("./ch06-certificates.html-DUHSveME.js"),__vite__mapDeps([]))),"v-f1802e66":h(()=>s(()=>import("./ch07-xray-server.html-D_AT7DH0.js"),__vite__mapDeps([]))),"v-4ca6f1ca":h(()=>s(()=>import("./ch08-xray-clients.html-DueTm8m2.js"),__vite__mapDeps([]))),"v-b0030f00":h(()=>s(()=>import("./ch09-appendix.html-DsxMf9Eu.js"),__vite__mapDeps([]))),"v-789ba80e":h(()=>s(()=>import("./index.html-BmR8xWDg.js"),__vite__mapDeps([]))),"v-103b3e5c":h(()=>s(()=>import("./fallbacks-lv1.html-R7zbt45s.js"),__vite__mapDeps([]))),"v-110dd688":h(()=>s(()=>import("./fallbacks-with-sni.html-BAchho5z.js"),__vite__mapDeps([]))),"v-c425a7d4":h(()=>s(()=>import("./routing-lv1-part1.html-DGAFkfW-.js"),__vite__mapDeps([]))),"v-c0bbf696":h(()=>s(()=>import("./routing-lv1-part2.html-d3I02cv4.js"),__vite__mapDeps([]))),"v-5b6477cc":h(()=>s(()=>import("./work.html-D1MRDeII.js"),__vite__mapDeps([]))),"v-789ba82d":h(()=>s(()=>import("./index.html-CuC5URKY.js"),__vite__mapDeps([]))),"v-05ddc65d":h(()=>s(()=>import("./iptables_gid.html-BzWg4Lzk.js"),__vite__mapDeps([]))),"v-474afe99":h(()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-DatcYtlJ.js"),__vite__mapDeps([]))),"v-930ac920":h(()=>s(()=>import("./redirect.html-Mplb4Dtz.js"),__vite__mapDeps([]))),"v-c579975c":h(()=>s(()=>import("./tproxy.html-BR9yhgN8.js"),__vite__mapDeps([]))),"v-7efb7c68":h(()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-Bk7Lv8iD.js"),__vite__mapDeps([]))),"v-12a33bee":h(()=>s(()=>import("./traffic_stats.html-CUSefiEt.js"),__vite__mapDeps([]))),"v-7d2b8478":h(()=>s(()=>import("./warp.html-7HQyZ8uD.js"),__vite__mapDeps([]))),"v-1cfb44e6":h(()=>s(()=>import("./browser_dialer.html-C3dkn1hN.js"),__vite__mapDeps([]))),"v-6a3f8078":h(()=>s(()=>import("./env.html-X4QtRUwr.js"),__vite__mapDeps([]))),"v-74f22e7f":h(()=>s(()=>import("./fallback.html-P3OM7a42.js"),__vite__mapDeps([]))),"v-2c9f7c11":h(()=>s(()=>import("./multiple.html-d0Rz6O9q.js"),__vite__mapDeps([]))),"v-630c687e":h(()=>s(()=>import("./xtls.html-CNzfvmap.js"),__vite__mapDeps([]))),"v-20ff0a28":h(()=>s(()=>import("./dokodemo.html-Bt8oAJZq.js"),__vite__mapDeps([]))),"v-43124836":h(()=>s(()=>import("./http.html-cSNMwEku.js"),__vite__mapDeps([]))),"v-6a351ba5":h(()=>s(()=>import("./shadowsocks.html-Cdp8fuJA.js"),__vite__mapDeps([]))),"v-3d1d02c5":h(()=>s(()=>import("./socks.html-DLTwr0bp.js"),__vite__mapDeps([]))),"v-1567b378":h(()=>s(()=>import("./trojan.html-CgBPDtHB.js"),__vite__mapDeps([]))),"v-57bf8636":h(()=>s(()=>import("./vless.html-CTPUBSmN.js"),__vite__mapDeps([]))),"v-6864abe6":h(()=>s(()=>import("./vmess.html-Dw5jQJR5.js"),__vite__mapDeps([]))),"v-5910da20":h(()=>s(()=>import("./blackhole.html-EGsblD7s.js"),__vite__mapDeps([]))),"v-5717f8f6":h(()=>s(()=>import("./dns.html-Bv4y0xp3.js"),__vite__mapDeps([]))),"v-4360702e":h(()=>s(()=>import("./freedom.html-Dxeb5oma.js"),__vite__mapDeps([]))),"v-22e1532a":h(()=>s(()=>import("./http.html-C1EqlRMw.js"),__vite__mapDeps([]))),"v-38c69248":h(()=>s(()=>import("./loopback.html-CL9lvq8v.js"),__vite__mapDeps([]))),"v-1a2a97d0":h(()=>s(()=>import("./shadowsocks.html-ZD0TQjd7.js"),__vite__mapDeps([]))),"v-0141bb30":h(()=>s(()=>import("./socks.html-DRrXLc9g.js"),__vite__mapDeps([]))),"v-544bef26":h(()=>s(()=>import("./trojan.html-DvVg8oOZ.js"),__vite__mapDeps([]))),"v-cf761560":h(()=>s(()=>import("./vless.html-CIaM0KTd.js"),__vite__mapDeps([]))),"v-2c896451":h(()=>s(()=>import("./vmess.html-BNuNWfIe.js"),__vite__mapDeps([]))),"v-0502a6bf":h(()=>s(()=>import("./wireguard.html-BMXSEvNc.js"),__vite__mapDeps([]))),"v-5b6ec7b7":h(()=>s(()=>import("./domainsocket.html-DOaqP0Hi.js"),__vite__mapDeps([]))),"v-13c3ca30":h(()=>s(()=>import("./grpc.html-BiVb6JVN.js"),__vite__mapDeps([]))),"v-2fe60378":h(()=>s(()=>import("./h2.html-OyF7YRkr.js"),__vite__mapDeps([]))),"v-453f5c70":h(()=>s(()=>import("./httpupgrade.html-8iiyF6S8.js"),__vite__mapDeps([]))),"v-1cb427e3":h(()=>s(()=>import("./mkcp.html-DrAEdayP.js"),__vite__mapDeps([]))),"v-b86fefe0":h(()=>s(()=>import("./quic.html-CXwWfMPP.js"),__vite__mapDeps([]))),"v-32d545e2":h(()=>s(()=>import("./splithttp.html-C_OBv89U.js"),__vite__mapDeps([]))),"v-f4c92f7a":h(()=>s(()=>import("./tcp.html-BV6lGrTj.js"),__vite__mapDeps([]))),"v-cb60c046":h(()=>s(()=>import("./websocket.html-CjNLVOTf.js"),__vite__mapDeps([]))),"v-7ce977e0":h(()=>s(()=>import("./compile.html-C3Y8utqQ.js"),__vite__mapDeps([]))),"v-01d5d1de":h(()=>s(()=>import("./design.html-B4pWfzca.js"),__vite__mapDeps([]))),"v-4d4e5367":h(()=>s(()=>import("./guide.html-DPanWeGq.js"),__vite__mapDeps([]))),"v-a58031da":h(()=>s(()=>import("./mkcp.html-DlmPRG7s.js"),__vite__mapDeps([]))),"v-5440615b":h(()=>s(()=>import("./muxcool.html-CDZVHREe.js"),__vite__mapDeps([]))),"v-069325e5":h(()=>s(()=>import("./vless.html-Be1YpEZ1.js"),__vite__mapDeps([]))),"v-ca50d634":h(()=>s(()=>import("./vmess.html-D9LxQYXS.js"),__vite__mapDeps([]))),"v-490791ee":h(()=>s(()=>import("./index.html-C4BsmZBc.js"),__vite__mapDeps([]))),"v-78f09a92":h(()=>s(()=>import("./ch01-preface.html-CtiGatzy.js"),__vite__mapDeps([]))),"v-64f6e51f":h(()=>s(()=>import("./ch02-preparation.html-DOc8B9wn.js"),__vite__mapDeps([]))),"v-69478a6d":h(()=>s(()=>import("./ch03-ssh.html-xo_x6se1.js"),__vite__mapDeps([]))),"v-271d7abe":h(()=>s(()=>import("./ch04-security.html-CDDodZLn.js"),__vite__mapDeps([]))),"v-9ab38aa0":h(()=>s(()=>import("./ch05-webpage.html-DR79qyrD.js"),__vite__mapDeps([]))),"v-7cddd6c4":h(()=>s(()=>import("./ch06-certificates.html-K5oNRMFq.js"),__vite__mapDeps([]))),"v-0d33adf3":h(()=>s(()=>import("./ch07-xray-server.html-C-3gFLNQ.js"),__vite__mapDeps([]))),"v-123166b5":h(()=>s(()=>import("./ch08-xray-clients.html-CJXEK9-Y.js"),__vite__mapDeps([]))),"v-22c7351a":h(()=>s(()=>import("./ch09-appendix.html-CCG5ZhR3.js"),__vite__mapDeps([]))),"v-490791b0":h(()=>s(()=>import("./index.html-YDY07G7e.js"),__vite__mapDeps([]))),"v-e9f80a14":h(()=>s(()=>import("./fallbacks-lv1.html-3a74qZ1k.js"),__vite__mapDeps([]))),"v-2db62ba4":h(()=>s(()=>import("./fallbacks-with-sni.html-B2NZf_xW.js"),__vite__mapDeps([]))),"v-531be8a0":h(()=>s(()=>import("./routing-lv1-part1.html-WNvWtpj6.js"),__vite__mapDeps([]))),"v-4fb23762":h(()=>s(()=>import("./routing-lv1-part2.html-B6ObFc5O.js"),__vite__mapDeps([]))),"v-fdd8db80":h(()=>s(()=>import("./work.html-nHfveOL9.js"),__vite__mapDeps([]))),"v-49079172":h(()=>s(()=>import("./index.html-CiIdsSO_.js"),__vite__mapDeps([]))),"v-331e0e83":h(()=>s(()=>import("./iptables_gid.html-DfoRMg8P.js"),__vite__mapDeps([]))),"v-7418a5b3":h(()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-DNk6WbAM.js"),__vite__mapDeps([]))),"v-587e32d4":h(()=>s(()=>import("./redirect.html-CcdbISF0.js"),__vite__mapDeps([]))),"v-9c63de10":h(()=>s(()=>import("./tproxy.html-BewclJzl.js"),__vite__mapDeps([]))),"v-a4c782e4":h(()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-3o8j0gtN.js"),__vite__mapDeps([]))),"v-71771ea3":h(()=>s(()=>import("./traffic_stats.html-DykdoOew.js"),__vite__mapDeps([]))),"v-70300bea":h(()=>s(()=>import("./warp.html-CkXwKg50.js"),__vite__mapDeps([]))),"v-7689d7f3":h(()=>s(()=>import("./transparent_proxy.html-BpVZ3iLf.js"),__vite__mapDeps([]))),"v-39b3c50d":h(()=>s(()=>import("./transparent_proxy.html-Bq-tBj5F.js"),__vite__mapDeps([]))),"v-3706649a":h(()=>s(()=>import("./404.html-C-V38gH_.js"),__vite__mapDeps([]))),"v-5c8e777f":h(()=>s(()=>import("./observatory.html-DG1jqJm8.js"),__vite__mapDeps([])))};var Hu=Symbol(""),ms=Symbol(""),Mu=In({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),Gt=()=>{const e=Te(ms);if(!e)throw new Error("pageData() is called without provider.");return e},bs=Symbol(""),gt=()=>{const e=Te(bs);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},ks=Symbol(""),$u=()=>{const e=Te(ks);if(!e)throw new Error("usePageHead() is called without provider.");return e},Bu=Symbol(""),Es=Symbol(""),Wu=()=>{const e=Te(Es);if(!e)throw new Error("usePageLang() is called without provider.");return e},ys=Symbol(""),Uu=()=>{const e=Te(ys);if(!e)throw new Error("usePageLayout() is called without provider.");return e},zu=pe(Iu),Mi=Symbol(""),Ql=()=>{const e=Te(Mi);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},ll=pe(Du),xs=()=>ll,Ls=Symbol(""),$i=()=>{const e=Te(Ls);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},Xu=Symbol(""),Ku="Layout",qu="NotFound",vt=Ul({resolveLayouts:e=>e.reduce((t,l)=>({...t,...l.layouts}),{}),resolvePageData:async e=>{const t=zu.value[e];return await(t==null?void 0:t())??Mu},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,l)=>{const n=it(t.description)?t.description:l.description,i=[...Array.isArray(t.head)?t.head:[],...l.head,["title",{},e],["meta",{name:"description",content:n}]];return Vu(i)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(l=>!!l).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||"en-US",resolvePageLayout:(e,t)=>{let l;if(e.path){const n=e.frontmatter.layout;it(n)?l=n:l=Ku}else l=qu;return t[l]},resolveRouteLocale:(e,t)=>ps(e,t),resolveSiteLocaleData:(e,t)=>{var l;return{...e,...e.locales[t],head:[...((l=e.locales[t])==null?void 0:l.head)??[],...e.head??[]]}}}),Bi=_e({name:"ClientOnly",setup(e,t){const l=pe(!1);return We(()=>{l.value=!0}),()=>{var n,i;return l.value?(i=(n=t.slots).default)==null?void 0:i.call(n):null}}}),Gu=_e({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=Gt(),l=C(()=>gs[e.pageKey||t.value.key]);return()=>l.value?he(l.value):he("div","404 Not Found")}}),Et=(e={})=>e,Wi=e=>Yl(e)?e:`/${fs(e)}`;function Ts(e,t,l){var n,i,r;t===void 0&&(t=50),l===void 0&&(l={});var o=(n=l.isImmediate)!=null&&n,c=(i=l.callback)!=null&&i,a=l.maxWait,u=Date.now(),d=[];function v(){if(a!==void 0){var g=Date.now()-u;if(g+t>=a)return a-g}return t}var _=function(){var g=[].slice.call(arguments),m=this;return new Promise(function(x,A){var D=o&&r===void 0;if(r!==void 0&&clearTimeout(r),r=setTimeout(function(){if(r=void 0,u=Date.now(),!o){var b=e.apply(m,g);c&&c(b),d.forEach(function(y){return(0,y.resolve)(b)}),d=[]}},v()),D){var O=e.apply(m,g);return c&&c(O),x(O)}d.push({resolve:x,reject:A})})};return _.cancel=function(g){r!==void 0&&clearTimeout(r),d.forEach(function(m){return(0,m.reject)(g)}),d=[]},_}/*!
+function bi(e,t){const l=Object.create(null),n=e.split(",");for(let i=0;i!!l[i]}const ye={},nl=[],ut=()=>{},ec=()=>!1,Bl=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),ki=e=>e.startsWith("onUpdate:"),Ie=Object.assign,Ei=(e,t)=>{const l=e.indexOf(t);l>-1&&e.splice(l,1)},tc=Object.prototype.hasOwnProperty,de=(e,t)=>tc.call(e,t),te=Array.isArray,il=e=>Pn(e)==="[object Map]",mo=e=>Pn(e)==="[object Set]",oe=e=>typeof e=="function",we=e=>typeof e=="string",fl=e=>typeof e=="symbol",Ee=e=>e!==null&&typeof e=="object",bo=e=>(Ee(e)||oe(e))&&oe(e.then)&&oe(e.catch),ko=Object.prototype.toString,Pn=e=>ko.call(e),lc=e=>Pn(e).slice(8,-1),Eo=e=>Pn(e)==="[object Object]",yi=e=>we(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Al=bi(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),An=e=>{const t=Object.create(null);return l=>t[l]||(t[l]=e(l))},nc=/-(\w)/g,dt=An(e=>e.replace(nc,(t,l)=>l?l.toUpperCase():"")),ic=/\B([A-Z])/g,Qt=An(e=>e.replace(ic,"-$1").toLowerCase()),wn=An(e=>e.charAt(0).toUpperCase()+e.slice(1)),$n=An(e=>e?`on${wn(e)}`:""),Yt=(e,t)=>!Object.is(e,t),Bn=(e,t)=>{for(let l=0;l{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:l})},rc=e=>{const t=parseFloat(e);return isNaN(t)?e:t},oc=e=>{const t=we(e)?Number(e):NaN;return isNaN(t)?e:t};let tr;const ni=()=>tr||(tr=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});function Wl(e){if(te(e)){const t={};for(let l=0;l{if(l){const n=l.split(cc);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function $e(e){let t="";if(we(e))t=e;else if(te(e))for(let l=0;lwe(e)?e:e==null?"":te(e)||Ee(e)&&(e.toString===ko||!oe(e.toString))?JSON.stringify(e,xo,2):String(e),xo=(e,t)=>t&&t.__v_isRef?xo(e,t.value):il(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((l,[n,i],r)=>(l[Wn(n,r)+" =>"]=i,l),{})}:mo(t)?{[`Set(${t.size})`]:[...t.values()].map(l=>Wn(l))}:fl(t)?Wn(t):Ee(t)&&!te(t)&&!Eo(t)?String(t):t,Wn=(e,t="")=>{var l;return fl(e)?`Symbol(${(l=e.description)!=null?l:t})`:e};let qe;class vc{constructor(t=!1){this.detached=t,this._active=!0,this.effects=[],this.cleanups=[],this.parent=qe,!t&&qe&&(this.index=(qe.scopes||(qe.scopes=[])).push(this)-1)}get active(){return this._active}run(t){if(this._active){const l=qe;try{return qe=this,t()}finally{qe=l}}}on(){qe=this}off(){qe=this.parent}stop(t){if(this._active){let l,n;for(l=0,n=this.effects.length;l{const t=new Set(e);return t.w=0,t.n=0,t},To=e=>(e.w&jt)>0,Oo=e=>(e.n&jt)>0,pc=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let l=0;for(let n=0;n{(d==="length"||!fl(d)&&d>=a)&&c.push(u)})}else switch(l!==void 0&&c.push(o.get(l)),t){case"add":te(e)?yi(l)&&c.push(o.get("length")):(c.push(o.get(zt)),il(e)&&c.push(o.get(ri)));break;case"delete":te(e)||(c.push(o.get(zt)),il(e)&&c.push(o.get(ri)));break;case"set":il(e)&&c.push(o.get(zt));break}if(c.length===1)c[0]&&oi(c[0]);else{const a=[];for(const u of c)u&&a.push(...u);oi(xi(a))}}function oi(e,t){const l=te(e)?e:[...e];for(const n of l)n.computed&&nr(n);for(const n of l)n.computed||nr(n)}function nr(e,t){(e!==lt||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}function mc(e,t){var l;return(l=pn.get(e))==null?void 0:l.get(t)}const bc=bi("__proto__,__v_isRef,__isVue"),wo=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(fl)),ir=kc();function kc(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...l){const n=ve(this);for(let r=0,o=this.length;r{e[t]=function(...l){pl();const n=ve(this)[t].apply(this,l);return gl(),n}}),e}function Ec(e){const t=ve(this);return Xe(t,"has",e),t.hasOwnProperty(e)}class Ro{constructor(t=!1,l=!1){this._isReadonly=t,this._shallow=l}get(t,l,n){const i=this._isReadonly,r=this._shallow;if(l==="__v_isReactive")return!i;if(l==="__v_isReadonly")return i;if(l==="__v_isShallow")return r;if(l==="__v_raw")return n===(i?r?Sc:So:r?jo:Do).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(n)?t:void 0;const o=te(t);if(!i){if(o&&de(ir,l))return Reflect.get(ir,l,n);if(l==="hasOwnProperty")return Ec}const c=Reflect.get(t,l,n);return(fl(l)?wo.has(l):bc(l))||(i||Xe(t,"get",l),r)?c:Ne(c)?o&&yi(l)?c:c.value:Ee(c)?i?In(c):Ul(c):c}}class Io extends Ro{constructor(t=!1){super(!1,t)}set(t,l,n,i){let r=t[l];if(!this._shallow){const a=cl(r);if(!gn(n)&&!cl(n)&&(r=ve(r),n=ve(n)),!te(t)&&Ne(r)&&!Ne(n))return a?!1:(r.value=n,!0)}const o=te(t)&&yi(l)?Number(l)e,Rn=e=>Reflect.getPrototypeOf(e);function Jl(e,t,l=!1,n=!1){e=e.__v_raw;const i=ve(e),r=ve(t);l||(Yt(t,r)&&Xe(i,"get",t),Xe(i,"get",r));const{has:o}=Rn(i),c=n?Ti:l?Ai:Sl;if(o.call(i,t))return c(e.get(t));if(o.call(i,r))return c(e.get(r));e!==i&&e.get(t)}function Zl(e,t=!1){const l=this.__v_raw,n=ve(l),i=ve(e);return t||(Yt(e,i)&&Xe(n,"has",e),Xe(n,"has",i)),e===i?l.has(e):l.has(e)||l.has(i)}function en(e,t=!1){return e=e.__v_raw,!t&&Xe(ve(e),"iterate",zt),Reflect.get(e,"size",e)}function rr(e){e=ve(e);const t=ve(this);return Rn(t).has.call(t,e)||(t.add(e),pt(t,"add",e,e)),this}function or(e,t){t=ve(t);const l=ve(this),{has:n,get:i}=Rn(l);let r=n.call(l,e);r||(e=ve(e),r=n.call(l,e));const o=i.call(l,e);return l.set(e,t),r?Yt(t,o)&&pt(l,"set",e,t):pt(l,"add",e,t),this}function sr(e){const t=ve(this),{has:l,get:n}=Rn(t);let i=l.call(t,e);i||(e=ve(e),i=l.call(t,e)),n&&n.call(t,e);const r=t.delete(e);return i&&pt(t,"delete",e,void 0),r}function cr(){const e=ve(this),t=e.size!==0,l=e.clear();return t&&pt(e,"clear",void 0,void 0),l}function tn(e,t){return function(n,i){const r=this,o=r.__v_raw,c=ve(o),a=t?Ti:e?Ai:Sl;return!e&&Xe(c,"iterate",zt),o.forEach((u,d)=>n.call(i,a(u),a(d),r))}}function ln(e,t,l){return function(...n){const i=this.__v_raw,r=ve(i),o=il(r),c=e==="entries"||e===Symbol.iterator&&o,a=e==="keys"&&o,u=i[e](...n),d=l?Ti:t?Ai:Sl;return!t&&Xe(r,"iterate",a?ri:zt),{next(){const{value:v,done:_}=u.next();return _?{value:v,done:_}:{value:c?[d(v[0]),d(v[1])]:d(v),done:_}},[Symbol.iterator](){return this}}}}function Lt(e){return function(...t){return e==="delete"?!1:e==="clear"?void 0:this}}function Oc(){const e={get(r){return Jl(this,r)},get size(){return en(this)},has:Zl,add:rr,set:or,delete:sr,clear:cr,forEach:tn(!1,!1)},t={get(r){return Jl(this,r,!1,!0)},get size(){return en(this)},has:Zl,add:rr,set:or,delete:sr,clear:cr,forEach:tn(!1,!0)},l={get(r){return Jl(this,r,!0)},get size(){return en(this,!0)},has(r){return Zl.call(this,r,!0)},add:Lt("add"),set:Lt("set"),delete:Lt("delete"),clear:Lt("clear"),forEach:tn(!0,!1)},n={get(r){return Jl(this,r,!0,!0)},get size(){return en(this,!0)},has(r){return Zl.call(this,r,!0)},add:Lt("add"),set:Lt("set"),delete:Lt("delete"),clear:Lt("clear"),forEach:tn(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(r=>{e[r]=ln(r,!1,!1),l[r]=ln(r,!0,!1),t[r]=ln(r,!1,!0),n[r]=ln(r,!0,!0)}),[e,l,t,n]}const[Pc,Ac,wc,Rc]=Oc();function Oi(e,t){const l=t?e?Rc:wc:e?Ac:Pc;return(n,i,r)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(de(l,i)&&i in n?l:n,i,r)}const Ic={get:Oi(!1,!1)},Dc={get:Oi(!1,!0)},jc={get:Oi(!0,!1)},Do=new WeakMap,jo=new WeakMap,So=new WeakMap,Sc=new WeakMap;function Cc(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Vc(e){return e.__v_skip||!Object.isExtensible(e)?0:Cc(lc(e))}function Ul(e){return cl(e)?e:Pi(e,!1,xc,Ic,Do)}function Co(e){return Pi(e,!1,Tc,Dc,jo)}function In(e){return Pi(e,!0,Lc,jc,So)}function Pi(e,t,l,n,i){if(!Ee(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const r=i.get(e);if(r)return r;const o=Vc(e);if(o===0)return e;const c=new Proxy(e,o===2?n:l);return i.set(e,c),c}function rl(e){return cl(e)?rl(e.__v_raw):!!(e&&e.__v_isReactive)}function cl(e){return!!(e&&e.__v_isReadonly)}function gn(e){return!!(e&&e.__v_isShallow)}function Vo(e){return rl(e)||cl(e)}function ve(e){const t=e&&e.__v_raw;return t?ve(t):e}function Fo(e){return fn(e,"__v_skip",!0),e}const Sl=e=>Ee(e)?Ul(e):e,Ai=e=>Ee(e)?In(e):e;function wi(e){It&<&&(e=ve(e),Ao(e.dep||(e.dep=xi())))}function Ri(e,t){e=ve(e);const l=e.dep;l&&oi(l)}function Ne(e){return!!(e&&e.__v_isRef===!0)}function pe(e){return Ho(e,!1)}function No(e){return Ho(e,!0)}function Ho(e,t){return Ne(e)?e:new Fc(e,t)}class Fc{constructor(t,l){this.__v_isShallow=l,this.dep=void 0,this.__v_isRef=!0,this._rawValue=l?t:ve(t),this._value=l?t:Sl(t)}get value(){return wi(this),this._value}set value(t){const l=this.__v_isShallow||gn(t)||cl(t);t=l?t:ve(t),Yt(t,this._rawValue)&&(this._rawValue=t,this._value=l?t:Sl(t),Ri(this))}}function Xt(e){return Ne(e)?e.value:e}const Nc={get:(e,t,l)=>Xt(Reflect.get(e,t,l)),set:(e,t,l,n)=>{const i=e[t];return Ne(i)&&!Ne(l)?(i.value=l,!0):Reflect.set(e,t,l,n)}};function Mo(e){return rl(e)?e:new Proxy(e,Nc)}class Hc{constructor(t){this.dep=void 0,this.__v_isRef=!0;const{get:l,set:n}=t(()=>wi(this),()=>Ri(this));this._get=l,this._set=n}get value(){return this._get()}set value(t){this._set(t)}}function Mc(e){return new Hc(e)}function Dn(e){const t=te(e)?new Array(e.length):{};for(const l in e)t[l]=$o(e,l);return t}class $c{constructor(t,l,n){this._object=t,this._key=l,this._defaultValue=n,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}get dep(){return mc(ve(this._object),this._key)}}class Bc{constructor(t){this._getter=t,this.__v_isRef=!0,this.__v_isReadonly=!0}get value(){return this._getter()}}function Ep(e,t,l){return Ne(e)?e:oe(e)?new Bc(e):Ee(e)&&arguments.length>1?$o(e,t,l):pe(e)}function $o(e,t,l){const n=e[t];return Ne(n)?n:new $c(e,t,l)}class Wc{constructor(t,l,n,i){this._setter=l,this.dep=void 0,this.__v_isRef=!0,this.__v_isReadonly=!1,this._dirty=!0,this.effect=new Li(t,()=>{this._dirty||(this._dirty=!0,Ri(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!i,this.__v_isReadonly=n}get value(){const t=ve(this);return wi(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function Uc(e,t,l=!1){let n,i;const r=oe(e);return r?(n=e,i=ut):(n=e.get,i=e.set),new Wc(n,i,r||!i,l)}function Dt(e,t,l,n){let i;try{i=n?e(...n):e()}catch(r){zl(r,t,l)}return i}function Ze(e,t,l,n){if(oe(e)){const r=Dt(e,t,l,n);return r&&bo(r)&&r.catch(o=>{zl(o,t,l)}),r}const i=[];for(let r=0;r>>1,i=Me[n],r=Vl(i);rat&&Me.splice(t,1)}function qc(e){te(e)?ol.push(...e):(!ft||!ft.includes(e,e.allowRecurse?$t+1:$t))&&ol.push(e),Wo()}function ar(e,t,l=Cl?at+1:0){for(;lVl(l)-Vl(n)),$t=0;$te.id==null?1/0:e.id,Gc=(e,t)=>{const l=Vl(e)-Vl(t);if(l===0){if(e.pre&&!t.pre)return-1;if(t.pre&&!e.pre)return 1}return l};function Uo(e){si=!1,Cl=!0,Me.sort(Gc);try{for(at=0;atwe(g)?g.trim():g)),v&&(i=l.map(rc))}let c,a=n[c=$n(t)]||n[c=$n(dt(t))];!a&&r&&(a=n[c=$n(Qt(t))]),a&&Ze(a,e,6,i);const u=n[c+"Once"];if(u){if(!e.emitted)e.emitted={};else if(e.emitted[c])return;e.emitted[c]=!0,Ze(u,e,6,i)}}function zo(e,t,l=!1){const n=t.emitsCache,i=n.get(e);if(i!==void 0)return i;const r=e.emits;let o={},c=!1;if(!oe(e)){const a=u=>{const d=zo(u,t,!0);d&&(c=!0,Ie(o,d))};!l&&t.mixins.length&&t.mixins.forEach(a),e.extends&&a(e.extends),e.mixins&&e.mixins.forEach(a)}return!r&&!c?(Ee(e)&&n.set(e,null),null):(te(r)?r.forEach(a=>o[a]=null):Ie(o,r),Ee(e)&&n.set(e,o),o)}function Sn(e,t){return!e||!Bl(t)?!1:(t=t.slice(2).replace(/Once$/,""),de(e,t[0].toLowerCase()+t.slice(1))||de(e,Qt(t))||de(e,t))}let Ve=null,Xo=null;function bn(e){const t=Ve;return Ve=e,Xo=e&&e.type.__scopeId||null,t}function Ce(e,t=Ve,l){if(!t||e._n)return e;const n=(...i)=>{n._d&&Er(-1);const r=bn(t);let o;try{o=e(...i)}finally{bn(r),n._d&&Er(1)}return o};return n._n=!0,n._c=!0,n._d=!0,n}function Un(e){const{type:t,vnode:l,proxy:n,withProxy:i,props:r,propsOptions:[o],slots:c,attrs:a,emit:u,render:d,renderCache:v,data:_,setupState:g,ctx:m,inheritAttrs:x}=e;let A,D;const O=bn(e);try{if(l.shapeFlag&4){const y=i||n,H=y;A=tt(d.call(H,y,v,r,g,_,m)),D=a}else{const y=t;A=tt(y.length>1?y(r,{attrs:a,slots:c,emit:u}):y(r,null)),D=t.props?a:Qc(a)}}catch(y){Il.length=0,zl(y,e,1),A=ie(Ye)}let b=A;if(D&&x!==!1){const y=Object.keys(D),{shapeFlag:H}=b;y.length&&H&7&&(o&&y.some(ki)&&(D=Jc(D,o)),b=Ct(b,D))}return l.dirs&&(b=Ct(b),b.dirs=b.dirs?b.dirs.concat(l.dirs):l.dirs),l.transition&&(b.transition=l.transition),A=b,bn(O),A}const Qc=e=>{let t;for(const l in e)(l==="class"||l==="style"||Bl(l))&&((t||(t={}))[l]=e[l]);return t},Jc=(e,t)=>{const l={};for(const n in e)(!ki(n)||!(n.slice(9)in t))&&(l[n]=e[n]);return l};function Zc(e,t,l){const{props:n,children:i,component:r}=e,{props:o,children:c,patchFlag:a}=t,u=r.emitsOptions;if(t.dirs||t.transition)return!0;if(l&&a>=0){if(a&1024)return!0;if(a&16)return n?ur(n,o,u):!!o;if(a&8){const d=t.dynamicProps;for(let v=0;ve.__isSuspense;function Ko(e,t){t&&t.pendingBranch?te(e)?t.effects.push(...e):t.effects.push(e):qc(e)}function ra(e,t){return Di(e,null,t)}const nn={};function Ge(e,t,l){return Di(e,t,l)}function Di(e,t,{immediate:l,deep:n,flush:i,onTrack:r,onTrigger:o}=ye){var c;const a=Lo()===((c=Re)==null?void 0:c.scope)?Re:null;let u,d=!1,v=!1;if(Ne(e)?(u=()=>e.value,d=gn(e)):rl(e)?(u=()=>e,n=!0):te(e)?(v=!0,d=e.some(y=>rl(y)||gn(y)),u=()=>e.map(y=>{if(Ne(y))return y.value;if(rl(y))return Ut(y);if(oe(y))return Dt(y,a,2)})):oe(e)?t?u=()=>Dt(e,a,2):u=()=>{if(!(a&&a.isUnmounted))return _&&_(),Ze(e,a,3,[g])}:u=ut,t&&n){const y=u;u=()=>Ut(y())}let _,g=y=>{_=O.onStop=()=>{Dt(y,a,4),_=O.onStop=void 0}},m;if(dl)if(g=ut,t?l&&Ze(t,a,3,[u(),v?[]:void 0,g]):u(),i==="sync"){const y=Ja();m=y.__watcherHandles||(y.__watcherHandles=[])}else return ut;let x=v?new Array(e.length).fill(nn):nn;const A=()=>{if(O.active)if(t){const y=O.run();(n||d||(v?y.some((H,G)=>Yt(H,x[G])):Yt(y,x)))&&(_&&_(),Ze(t,a,3,[y,x===nn?void 0:v&&x[0]===nn?[]:x,g]),x=y)}else O.run()};A.allowRecurse=!!t;let D;i==="sync"?D=A:i==="post"?D=()=>ze(A,a&&a.suspense):(A.pre=!0,a&&(A.id=a.uid),D=()=>jn(A));const O=new Li(u,D);t?l?A():x=O.run():i==="post"?ze(O.run.bind(O),a&&a.suspense):O.run();const b=()=>{O.stop(),a&&a.scope&&Ei(a.scope.effects,O)};return m&&m.push(b),b}function oa(e,t,l){const n=this.proxy,i=we(e)?e.includes(".")?qo(n,e):()=>n[e]:e.bind(n,n);let r;oe(t)?r=t:(r=t.handler,l=t);const o=Re;ul(this);const c=Di(i,r.bind(n),l);return o?ul(o):qt(),c}function qo(e,t){const l=t.split(".");return()=>{let n=e;for(let i=0;i{Ut(l,t)});else if(Eo(e))for(const l in e)Ut(e[l],t);return e}function kn(e,t){const l=Ve;if(l===null)return e;const n=Nn(l)||l.proxy,i=e.dirs||(e.dirs=[]);for(let r=0;r{e.isMounted=!0}),ql(()=>{e.isUnmounting=!0}),e}const Qe=[Function,Array],Go={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:Qe,onEnter:Qe,onAfterEnter:Qe,onEnterCancelled:Qe,onBeforeLeave:Qe,onLeave:Qe,onAfterLeave:Qe,onLeaveCancelled:Qe,onBeforeAppear:Qe,onAppear:Qe,onAfterAppear:Qe,onAppearCancelled:Qe},ca={name:"BaseTransition",props:Go,setup(e,{slots:t}){const l=Vi(),n=sa();let i;return()=>{const r=t.default&&Qo(t.default(),!0);if(!r||!r.length)return;let o=r[0];if(r.length>1){for(const x of r)if(x.type!==Ye){o=x;break}}const c=ve(e),{mode:a}=c;if(n.isLeaving)return zn(o);const u=hr(o);if(!u)return zn(o);const d=ci(u,c,n,l);ai(u,d);const v=l.subTree,_=v&&hr(v);let g=!1;const{getTransitionKey:m}=u.type;if(m){const x=m();i===void 0?i=x:x!==i&&(i=x,g=!0)}if(_&&_.type!==Ye&&(!Bt(u,_)||g)){const x=ci(_,c,n,l);if(ai(_,x),a==="out-in")return n.isLeaving=!0,x.afterLeave=()=>{n.isLeaving=!1,l.update.active!==!1&&l.update()},zn(o);a==="in-out"&&u.type!==Ye&&(x.delayLeave=(A,D,O)=>{const b=Yo(n,_);b[String(_.key)]=_,A[At]=()=>{D(),A[At]=void 0,delete d.delayedLeave},d.delayedLeave=O})}return o}}},aa=ca;function Yo(e,t){const{leavingVNodes:l}=e;let n=l.get(t.type);return n||(n=Object.create(null),l.set(t.type,n)),n}function ci(e,t,l,n){const{appear:i,mode:r,persisted:o=!1,onBeforeEnter:c,onEnter:a,onAfterEnter:u,onEnterCancelled:d,onBeforeLeave:v,onLeave:_,onAfterLeave:g,onLeaveCancelled:m,onBeforeAppear:x,onAppear:A,onAfterAppear:D,onAppearCancelled:O}=t,b=String(e.key),y=Yo(l,e),H=(E,K)=>{E&&Ze(E,n,9,K)},G=(E,K)=>{const w=K[1];H(E,K),te(E)?E.every(z=>z.length<=1)&&w():E.length<=1&&w()},N={mode:r,persisted:o,beforeEnter(E){let K=c;if(!l.isMounted)if(i)K=x||c;else return;E[At]&&E[At](!0);const w=y[b];w&&Bt(e,w)&&w.el[At]&&w.el[At](),H(K,[E])},enter(E){let K=a,w=u,z=d;if(!l.isMounted)if(i)K=A||a,w=D||u,z=O||d;else return;let L=!1;const V=E[rn]=le=>{L||(L=!0,le?H(z,[E]):H(w,[E]),N.delayedLeave&&N.delayedLeave(),E[rn]=void 0)};K?G(K,[E,V]):V()},leave(E,K){const w=String(e.key);if(E[rn]&&E[rn](!0),l.isUnmounting)return K();H(v,[E]);let z=!1;const L=E[At]=V=>{z||(z=!0,K(),V?H(m,[E]):H(g,[E]),E[At]=void 0,y[w]===e&&delete y[w])};y[w]=e,_?G(_,[E,L]):L()},clone(E){return ci(E,t,l,n)}};return N}function zn(e){if(Kl(e))return e=Ct(e),e.children=null,e}function hr(e){return Kl(e)?e.children?e.children[0]:void 0:e}function ai(e,t){e.shapeFlag&6&&e.component?ai(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Qo(e,t=!1,l){let n=[],i=0;for(let r=0;r1)for(let r=0;r!!e.type.__asyncLoader;/*! #__NO_SIDE_EFFECTS__ */function h(e){oe(e)&&(e={loader:e});const{loader:t,loadingComponent:l,errorComponent:n,delay:i=200,timeout:r,suspensible:o=!0,onError:c}=e;let a=null,u,d=0;const v=()=>(d++,a=null,_()),_=()=>{let g;return a||(g=a=t().catch(m=>{if(m=m instanceof Error?m:new Error(String(m)),c)return new Promise((x,A)=>{c(m,()=>x(v()),()=>A(m),d+1)});throw m}).then(m=>g!==a&&a?a:(m&&(m.__esModule||m[Symbol.toStringTag]==="Module")&&(m=m.default),u=m,m)))};return _e({name:"AsyncComponentWrapper",__asyncLoader:_,get __asyncResolved(){return u},setup(){const g=Re;if(u)return()=>Xn(u,g);const m=O=>{a=null,zl(O,g,13,!n)};if(o&&g.suspense||dl)return _().then(O=>()=>Xn(O,g)).catch(O=>(m(O),()=>n?ie(n,{error:O}):null));const x=pe(!1),A=pe(),D=pe(!!i);return i&&setTimeout(()=>{D.value=!1},i),r!=null&&setTimeout(()=>{if(!x.value&&!A.value){const O=new Error(`Async component timed out after ${r}ms.`);m(O),A.value=O}},r),_().then(()=>{x.value=!0,g.parent&&Kl(g.parent.vnode)&&jn(g.parent.update)}).catch(O=>{m(O),A.value=O}),()=>{if(x.value&&u)return Xn(u,g);if(A.value&&n)return ie(n,{error:A.value});if(l&&!D.value)return ie(l)}}})}function Xn(e,t){const{ref:l,props:n,children:i,ce:r}=t.vnode,o=ie(e,n,i);return o.ref=l,o.ce=r,delete t.vnode.ce,o}const Kl=e=>e.type.__isKeepAlive;function ua(e,t){Jo(e,"a",t)}function da(e,t){Jo(e,"da",t)}function Jo(e,t,l=Re){const n=e.__wdc||(e.__wdc=()=>{let i=l;for(;i;){if(i.isDeactivated)return;i=i.parent}return e()});if(Cn(t,n,l),l){let i=l.parent;for(;i&&i.parent;)Kl(i.parent.vnode)&&ha(n,t,l,i),i=i.parent}}function ha(e,t,l,n){const i=Cn(t,e,n,!0);Vn(()=>{Ei(n[t],i)},l)}function Cn(e,t,l=Re,n=!1){if(l){const i=l[e]||(l[e]=[]),r=t.__weh||(t.__weh=(...o)=>{if(l.isUnmounted)return;pl(),ul(l);const c=Ze(t,l,e,o);return qt(),gl(),c});return n?i.unshift(r):i.push(r),r}}const kt=e=>(t,l=Re)=>(!dl||e==="sp")&&Cn(e,(...n)=>t(...n),l),va=kt("bm"),We=kt("m"),_a=kt("bu"),fa=kt("u"),ql=kt("bum"),Vn=kt("um"),pa=kt("sp"),ga=kt("rtg"),ma=kt("rtc");function ba(e,t=Re){Cn("ec",e,t)}function St(e,t,l,n){let i;const r=l;if(te(e)||we(e)){i=new Array(e.length);for(let o=0,c=e.length;ot(o,c,void 0,r));else{const o=Object.keys(e);i=new Array(o.length);for(let c=0,a=o.length;cLn(t)?!(t.type===Ye||t.type===ke&&!Zo(t.children)):!0)?e:null}const ui=e=>e?ds(e)?Nn(e)||e.proxy:ui(e.parent):null,wl=Ie(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>ui(e.parent),$root:e=>ui(e.root),$emit:e=>e.emit,$options:e=>ji(e),$forceUpdate:e=>e.f||(e.f=()=>jn(e.update)),$nextTick:e=>e.n||(e.n=Xl.bind(e.proxy)),$watch:e=>oa.bind(e)}),Kn=(e,t)=>e!==ye&&!e.__isScriptSetup&&de(e,t),ka={get({_:e},t){const{ctx:l,setupState:n,data:i,props:r,accessCache:o,type:c,appContext:a}=e;let u;if(t[0]!=="$"){const g=o[t];if(g!==void 0)switch(g){case 1:return n[t];case 2:return i[t];case 4:return l[t];case 3:return r[t]}else{if(Kn(n,t))return o[t]=1,n[t];if(i!==ye&&de(i,t))return o[t]=2,i[t];if((u=e.propsOptions[0])&&de(u,t))return o[t]=3,r[t];if(l!==ye&&de(l,t))return o[t]=4,l[t];di&&(o[t]=0)}}const d=wl[t];let v,_;if(d)return t==="$attrs"&&Xe(e,"get",t),d(e);if((v=c.__cssModules)&&(v=v[t]))return v;if(l!==ye&&de(l,t))return o[t]=4,l[t];if(_=a.config.globalProperties,de(_,t))return _[t]},set({_:e},t,l){const{data:n,setupState:i,ctx:r}=e;return Kn(i,t)?(i[t]=l,!0):n!==ye&&de(n,t)?(n[t]=l,!0):de(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(r[t]=l,!0)},has({_:{data:e,setupState:t,accessCache:l,ctx:n,appContext:i,propsOptions:r}},o){let c;return!!l[o]||e!==ye&&de(e,o)||Kn(t,o)||(c=r[0])&&de(c,o)||de(n,o)||de(wl,o)||de(i.config.globalProperties,o)},defineProperty(e,t,l){return l.get!=null?e._.accessCache[t]=0:de(l,"value")&&this.set(e,t,l.value,null),Reflect.defineProperty(e,t,l)}};function vr(e){return te(e)?e.reduce((t,l)=>(t[l]=null,t),{}):e}let di=!0;function Ea(e){const t=ji(e),l=e.proxy,n=e.ctx;di=!1,t.beforeCreate&&_r(t.beforeCreate,e,"bc");const{data:i,computed:r,methods:o,watch:c,provide:a,inject:u,created:d,beforeMount:v,mounted:_,beforeUpdate:g,updated:m,activated:x,deactivated:A,beforeDestroy:D,beforeUnmount:O,destroyed:b,unmounted:y,render:H,renderTracked:G,renderTriggered:N,errorCaptured:E,serverPrefetch:K,expose:w,inheritAttrs:z,components:L,directives:V,filters:le}=t;if(u&&ya(u,n,null),o)for(const Q in o){const X=o[Q];oe(X)&&(n[Q]=X.bind(l))}if(i){const Q=i.call(l,l);Ee(Q)&&(e.data=Ul(Q))}if(di=!0,r)for(const Q in r){const X=r[Q],De=oe(X)?X.bind(l,l):oe(X.get)?X.get.bind(l,l):ut,Se=!oe(X)&&oe(X.set)?X.set.bind(l):ut,Ue=C({get:De,set:Se});Object.defineProperty(n,Q,{enumerable:!0,configurable:!0,get:()=>Ue.value,set:He=>Ue.value=He})}if(c)for(const Q in c)es(c[Q],n,l,Q);if(a){const Q=oe(a)?a.call(l):a;Reflect.ownKeys(Q).forEach(X=>{Kt(X,Q[X])})}d&&_r(d,e,"c");function S(Q,X){te(X)?X.forEach(De=>Q(De.bind(l))):X&&Q(X.bind(l))}if(S(va,v),S(We,_),S(_a,g),S(fa,m),S(ua,x),S(da,A),S(ba,E),S(ma,G),S(ga,N),S(ql,O),S(Vn,y),S(pa,K),te(w))if(w.length){const Q=e.exposed||(e.exposed={});w.forEach(X=>{Object.defineProperty(Q,X,{get:()=>l[X],set:De=>l[X]=De})})}else e.exposed||(e.exposed={});H&&e.render===ut&&(e.render=H),z!=null&&(e.inheritAttrs=z),L&&(e.components=L),V&&(e.directives=V)}function ya(e,t,l=ut){te(e)&&(e=hi(e));for(const n in e){const i=e[n];let r;Ee(i)?"default"in i?r=Te(i.from||n,i.default,!0):r=Te(i.from||n):r=Te(i),Ne(r)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>r.value,set:o=>r.value=o}):t[n]=r}}function _r(e,t,l){Ze(te(e)?e.map(n=>n.bind(t.proxy)):e.bind(t.proxy),t,l)}function es(e,t,l,n){const i=n.includes(".")?qo(l,n):()=>l[n];if(we(e)){const r=t[e];oe(r)&&Ge(i,r)}else if(oe(e))Ge(i,e.bind(l));else if(Ee(e))if(te(e))e.forEach(r=>es(r,t,l,n));else{const r=oe(e.handler)?e.handler.bind(l):t[e.handler];oe(r)&&Ge(i,r,e)}}function ji(e){const t=e.type,{mixins:l,extends:n}=t,{mixins:i,optionsCache:r,config:{optionMergeStrategies:o}}=e.appContext,c=r.get(t);let a;return c?a=c:!i.length&&!l&&!n?a=t:(a={},i.length&&i.forEach(u=>En(a,u,o,!0)),En(a,t,o)),Ee(t)&&r.set(t,a),a}function En(e,t,l,n=!1){const{mixins:i,extends:r}=t;r&&En(e,r,l,!0),i&&i.forEach(o=>En(e,o,l,!0));for(const o in t)if(!(n&&o==="expose")){const c=xa[o]||l&&l[o];e[o]=c?c(e[o],t[o]):t[o]}return e}const xa={data:fr,props:pr,emits:pr,methods:Pl,computed:Pl,beforeCreate:Be,created:Be,beforeMount:Be,mounted:Be,beforeUpdate:Be,updated:Be,beforeDestroy:Be,beforeUnmount:Be,destroyed:Be,unmounted:Be,activated:Be,deactivated:Be,errorCaptured:Be,serverPrefetch:Be,components:Pl,directives:Pl,watch:Ta,provide:fr,inject:La};function fr(e,t){return t?e?function(){return Ie(oe(e)?e.call(this,this):e,oe(t)?t.call(this,this):t)}:t:e}function La(e,t){return Pl(hi(e),hi(t))}function hi(e){if(te(e)){const t={};for(let l=0;l1)return l&&oe(t)?t.call(n&&n.proxy):t}}function Aa(e,t,l,n=!1){const i={},r={};fn(r,Fn,1),e.propsDefaults=Object.create(null),ls(e,t,i,r);for(const o in e.propsOptions[0])o in i||(i[o]=void 0);l?e.props=n?i:Co(i):e.type.props?e.props=i:e.props=r,e.attrs=r}function wa(e,t,l,n){const{props:i,attrs:r,vnode:{patchFlag:o}}=e,c=ve(i),[a]=e.propsOptions;let u=!1;if((n||o>0)&&!(o&16)){if(o&8){const d=e.vnode.dynamicProps;for(let v=0;v{a=!0;const[_,g]=ns(v,t,!0);Ie(o,_),g&&c.push(...g)};!l&&t.mixins.length&&t.mixins.forEach(d),e.extends&&d(e.extends),e.mixins&&e.mixins.forEach(d)}if(!r&&!a)return Ee(e)&&n.set(e,nl),nl;if(te(r))for(let d=0;d-1,g[1]=x<0||m-1||de(g,"default"))&&c.push(v)}}}const u=[o,c];return Ee(e)&&n.set(e,u),u}function gr(e){return e[0]!=="$"}function mr(e){const t=e&&e.toString().match(/^\s*(function|class) (\w+)/);return t?t[2]:e===null?"null":""}function br(e,t){return mr(e)===mr(t)}function kr(e,t){return te(t)?t.findIndex(l=>br(l,e)):oe(t)&&br(t,e)?0:-1}const is=e=>e[0]==="_"||e==="$stable",Si=e=>te(e)?e.map(tt):[tt(e)],Ra=(e,t,l)=>{if(t._n)return t;const n=Ce((...i)=>Si(t(...i)),l);return n._c=!1,n},rs=(e,t,l)=>{const n=e._ctx;for(const i in e){if(is(i))continue;const r=e[i];if(oe(r))t[i]=Ra(i,r,n);else if(r!=null){const o=Si(r);t[i]=()=>o}}},os=(e,t)=>{const l=Si(t);e.slots.default=()=>l},Ia=(e,t)=>{if(e.vnode.shapeFlag&32){const l=t._;l?(e.slots=ve(t),fn(t,"_",l)):rs(t,e.slots={})}else e.slots={},t&&os(e,t);fn(e.slots,Fn,1)},Da=(e,t,l)=>{const{vnode:n,slots:i}=e;let r=!0,o=ye;if(n.shapeFlag&32){const c=t._;c?l&&c===1?r=!1:(Ie(i,t),!l&&c===1&&delete i._):(r=!t.$stable,rs(t,i)),o=t}else t&&(os(e,t),o={default:1});if(r)for(const c in i)!is(c)&&o[c]==null&&delete i[c]};function xn(e,t,l,n,i=!1){if(te(e)){e.forEach((_,g)=>xn(_,t&&(te(t)?t[g]:t),l,n,i));return}if(sl(n)&&!i)return;const r=n.shapeFlag&4?Nn(n.component)||n.component.proxy:n.el,o=i?null:r,{i:c,r:a}=e,u=t&&t.r,d=c.refs===ye?c.refs={}:c.refs,v=c.setupState;if(u!=null&&u!==a&&(we(u)?(d[u]=null,de(v,u)&&(v[u]=null)):Ne(u)&&(u.value=null)),oe(a))Dt(a,c,12,[o,d]);else{const _=we(a),g=Ne(a);if(_||g){const m=()=>{if(e.f){const x=_?de(v,a)?v[a]:d[a]:a.value;i?te(x)&&Ei(x,r):te(x)?x.includes(r)||x.push(r):_?(d[a]=[r],de(v,a)&&(v[a]=d[a])):(a.value=[r],e.k&&(d[e.k]=a.value))}else _?(d[a]=o,de(v,a)&&(v[a]=o)):g&&(a.value=o,e.k&&(d[e.k]=o))};o?(m.id=-1,ze(m,l)):m()}}}let Tt=!1;const on=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",sn=e=>e.nodeType===8;function ja(e){const{mt:t,p:l,o:{patchProp:n,createText:i,nextSibling:r,parentNode:o,remove:c,insert:a,createComment:u}}=e,d=(b,y)=>{if(!y.hasChildNodes()){l(null,b,y),mn(),y._vnode=b;return}Tt=!1,v(y.firstChild,b,null,null,null),mn(),y._vnode=b,Tt&&console.error("Hydration completed but contains mismatches.")},v=(b,y,H,G,N,E=!1)=>{const K=sn(b)&&b.data==="[",w=()=>x(b,y,H,G,N,K),{type:z,ref:L,shapeFlag:V,patchFlag:le}=y;let ne=b.nodeType;y.el=b,le===-2&&(E=!1,y.dynamicChildren=null);let S=null;switch(z){case al:ne!==3?y.children===""?(a(y.el=i(""),o(b),b),S=b):S=w():(b.data!==y.children&&(Tt=!0,b.data=y.children),S=r(b));break;case Ye:O(b)?(S=r(b),D(y.el=b.content.firstChild,b,H)):ne!==8||K?S=w():S=r(b);break;case Rl:if(K&&(b=r(b),ne=b.nodeType),ne===1||ne===3){S=b;const Q=!y.children.length;for(let X=0;X{E=E||!!y.dynamicChildren;const{type:K,props:w,patchFlag:z,shapeFlag:L,dirs:V,transition:le}=y,ne=K==="input"||K==="option";if(ne||z!==-1){V&&ct(y,null,H,"created");let S=!1;if(O(b)){S=ss(G,le)&&H&&H.vnode.props&&H.vnode.props.appear;const X=b.content.firstChild;S&&le.beforeEnter(X),D(X,b,H),y.el=b=X}if(w)if(ne||!E||z&48)for(const X in w)(ne&&(X.endsWith("value")||X==="indeterminate")||Bl(X)&&!Al(X)||X[0]===".")&&n(b,X,null,w[X],!1,void 0,H);else w.onClick&&n(b,"onClick",null,w.onClick,!1,void 0,H);let Q;if((Q=w&&w.onVnodeBeforeMount)&&Je(Q,H,y),V&&ct(y,null,H,"beforeMount"),((Q=w&&w.onVnodeMounted)||V||S)&&Ko(()=>{Q&&Je(Q,H,y),S&&le.enter(b),V&&ct(y,null,H,"mounted")},G),L&16&&!(w&&(w.innerHTML||w.textContent))){let X=g(b.firstChild,y,b,H,G,N,E);for(;X;){Tt=!0;const De=X;X=X.nextSibling,c(De)}}else L&8&&b.textContent!==y.children&&(Tt=!0,b.textContent=y.children)}return b.nextSibling},g=(b,y,H,G,N,E,K)=>{K=K||!!y.dynamicChildren;const w=y.children,z=w.length;for(let L=0;L{const{slotScopeIds:K}=y;K&&(N=N?N.concat(K):K);const w=o(b),z=g(r(b),y,w,H,G,N,E);return z&&sn(z)&&z.data==="]"?r(y.anchor=z):(Tt=!0,a(y.anchor=u("]"),w,z),z)},x=(b,y,H,G,N,E)=>{if(Tt=!0,y.el=null,E){const z=A(b);for(;;){const L=r(b);if(L&&L!==z)c(L);else break}}const K=r(b),w=o(b);return c(b),l(null,y,w,K,H,G,on(w),N),K},A=(b,y="[",H="]")=>{let G=0;for(;b;)if(b=r(b),b&&sn(b)&&(b.data===y&&G++,b.data===H)){if(G===0)return r(b);G--}return b},D=(b,y,H)=>{const G=y.parentNode;G&&G.replaceChild(b,y);let N=H;for(;N;)N.vnode.el===y&&(N.vnode.el=N.subTree.el=b),N=N.parent},O=b=>b.nodeType===1&&b.tagName.toLowerCase()==="template";return[d,v]}const ze=Ko;function Sa(e){return Ca(e,ja)}function Ca(e,t){const l=ni();l.__VUE__=!0;const{insert:n,remove:i,patchProp:r,createElement:o,createText:c,createComment:a,setText:u,setElementText:d,parentNode:v,nextSibling:_,setScopeId:g=ut,insertStaticContent:m}=e,x=(f,p,k,T=null,R=null,I=null,B=!1,F=null,$=!!p.dynamicChildren)=>{if(f===p)return;f&&!Bt(f,p)&&(T=P(f),He(f,R,I,!0),f=null),p.patchFlag===-2&&($=!1,p.dynamicChildren=null);const{type:j,ref:J,shapeFlag:q}=p;switch(j){case al:A(f,p,k,T);break;case Ye:D(f,p,k,T);break;case Rl:f==null&&O(p,k,T,B);break;case ke:L(f,p,k,T,R,I,B,F,$);break;default:q&1?H(f,p,k,T,R,I,B,F,$):q&6?V(f,p,k,T,R,I,B,F,$):(q&64||q&128)&&j.process(f,p,k,T,R,I,B,F,$,M)}J!=null&&R&&xn(J,f&&f.ref,I,p||f,!p)},A=(f,p,k,T)=>{if(f==null)n(p.el=c(p.children),k,T);else{const R=p.el=f.el;p.children!==f.children&&u(R,p.children)}},D=(f,p,k,T)=>{f==null?n(p.el=a(p.children||""),k,T):p.el=f.el},O=(f,p,k,T)=>{[f.el,f.anchor]=m(f.children,p,k,T,f.el,f.anchor)},b=({el:f,anchor:p},k,T)=>{let R;for(;f&&f!==p;)R=_(f),n(f,k,T),f=R;n(p,k,T)},y=({el:f,anchor:p})=>{let k;for(;f&&f!==p;)k=_(f),i(f),f=k;i(p)},H=(f,p,k,T,R,I,B,F,$)=>{B=B||p.type==="svg",f==null?G(p,k,T,R,I,B,F,$):K(f,p,R,I,B,F,$)},G=(f,p,k,T,R,I,B,F)=>{let $,j;const{type:J,props:q,shapeFlag:Z,transition:re,dirs:se}=f;if($=f.el=o(f.type,I,q&&q.is,q),Z&8?d($,f.children):Z&16&&E(f.children,$,null,T,R,I&&J!=="foreignObject",B,F),se&&ct(f,null,T,"created"),N($,f,f.scopeId,B,T),q){for(const ge in q)ge!=="value"&&!Al(ge)&&r($,ge,null,q[ge],I,f.children,T,R,je);"value"in q&&r($,"value",null,q.value),(j=q.onVnodeBeforeMount)&&Je(j,T,f)}se&&ct(f,null,T,"beforeMount");const me=ss(R,re);me&&re.beforeEnter($),n($,p,k),((j=q&&q.onVnodeMounted)||me||se)&&ze(()=>{j&&Je(j,T,f),me&&re.enter($),se&&ct(f,null,T,"mounted")},R)},N=(f,p,k,T,R)=>{if(k&&g(f,k),T)for(let I=0;I{for(let j=$;j{const F=p.el=f.el;let{patchFlag:$,dynamicChildren:j,dirs:J}=p;$|=f.patchFlag&16;const q=f.props||ye,Z=p.props||ye;let re;k&&Ft(k,!1),(re=Z.onVnodeBeforeUpdate)&&Je(re,k,p,f),J&&ct(p,f,k,"beforeUpdate"),k&&Ft(k,!0);const se=R&&p.type!=="foreignObject";if(j?w(f.dynamicChildren,j,F,k,T,se,I):B||X(f,p,F,null,k,T,se,I,!1),$>0){if($&16)z(F,p,q,Z,k,T,R);else if($&2&&q.class!==Z.class&&r(F,"class",null,Z.class,R),$&4&&r(F,"style",q.style,Z.style,R),$&8){const me=p.dynamicProps;for(let ge=0;ge{re&&Je(re,k,p,f),J&&ct(p,f,k,"updated")},T)},w=(f,p,k,T,R,I,B)=>{for(let F=0;F{if(k!==T){if(k!==ye)for(const F in k)!Al(F)&&!(F in T)&&r(f,F,k[F],null,B,p.children,R,I,je);for(const F in T){if(Al(F))continue;const $=T[F],j=k[F];$!==j&&F!=="value"&&r(f,F,j,$,B,p.children,R,I,je)}"value"in T&&r(f,"value",k.value,T.value)}},L=(f,p,k,T,R,I,B,F,$)=>{const j=p.el=f?f.el:c(""),J=p.anchor=f?f.anchor:c("");let{patchFlag:q,dynamicChildren:Z,slotScopeIds:re}=p;re&&(F=F?F.concat(re):re),f==null?(n(j,k,T),n(J,k,T),E(p.children,k,J,R,I,B,F,$)):q>0&&q&64&&Z&&f.dynamicChildren?(w(f.dynamicChildren,Z,k,R,I,B,F),(p.key!=null||R&&p===R.subTree)&&cs(f,p,!0)):X(f,p,k,J,R,I,B,F,$)},V=(f,p,k,T,R,I,B,F,$)=>{p.slotScopeIds=F,f==null?p.shapeFlag&512?R.ctx.activate(p,k,T,B,$):le(p,k,T,R,I,B,$):ne(f,p,$)},le=(f,p,k,T,R,I,B)=>{const F=f.component=Ua(f,T,R);if(Kl(f)&&(F.ctx.renderer=M),za(F),F.asyncDep){if(R&&R.registerDep(F,S),!f.el){const $=F.subTree=ie(Ye);D(null,$,p,k)}return}S(F,f,p,k,R,I,B)},ne=(f,p,k)=>{const T=p.component=f.component;if(Zc(f,p,k))if(T.asyncDep&&!T.asyncResolved){Q(T,p,k);return}else T.next=p,Kc(T.update),T.update();else p.el=f.el,T.vnode=p},S=(f,p,k,T,R,I,B)=>{const F=()=>{if(f.isMounted){let{next:J,bu:q,u:Z,parent:re,vnode:se}=f,me=J,ge;Ft(f,!1),J?(J.el=se.el,Q(f,J,B)):J=se,q&&Bn(q),(ge=J.props&&J.props.onVnodeBeforeUpdate)&&Je(ge,re,J,se),Ft(f,!0);const Oe=Un(f),et=f.subTree;f.subTree=Oe,x(et,Oe,v(et.el),P(et),f,R,I),J.el=Oe.el,me===null&&ea(f,Oe.el),Z&&ze(Z,R),(ge=J.props&&J.props.onVnodeUpdated)&&ze(()=>Je(ge,re,J,se),R)}else{let J;const{el:q,props:Z}=p,{bm:re,m:se,parent:me}=f,ge=sl(p);if(Ft(f,!1),re&&Bn(re),!ge&&(J=Z&&Z.onVnodeBeforeMount)&&Je(J,me,p),Ft(f,!0),q&&ae){const Oe=()=>{f.subTree=Un(f),ae(q,f.subTree,f,R,null)};ge?p.type.__asyncLoader().then(()=>!f.isUnmounted&&Oe()):Oe()}else{const Oe=f.subTree=Un(f);x(null,Oe,k,T,f,R,I),p.el=Oe.el}if(se&&ze(se,R),!ge&&(J=Z&&Z.onVnodeMounted)){const Oe=p;ze(()=>Je(J,me,Oe),R)}(p.shapeFlag&256||me&&sl(me.vnode)&&me.vnode.shapeFlag&256)&&f.a&&ze(f.a,R),f.isMounted=!0,p=k=T=null}},$=f.effect=new Li(F,()=>jn(j),f.scope),j=f.update=()=>$.run();j.id=f.uid,Ft(f,!0),j()},Q=(f,p,k)=>{p.component=f;const T=f.vnode.props;f.vnode=p,f.next=null,wa(f,p.props,T,k),Da(f,p.children,k),pl(),ar(f),gl()},X=(f,p,k,T,R,I,B,F,$=!1)=>{const j=f&&f.children,J=f?f.shapeFlag:0,q=p.children,{patchFlag:Z,shapeFlag:re}=p;if(Z>0){if(Z&128){Se(j,q,k,T,R,I,B,F,$);return}else if(Z&256){De(j,q,k,T,R,I,B,F,$);return}}re&8?(J&16&&je(j,R,I),q!==j&&d(k,q)):J&16?re&16?Se(j,q,k,T,R,I,B,F,$):je(j,R,I,!0):(J&8&&d(k,""),re&16&&E(q,k,T,R,I,B,F,$))},De=(f,p,k,T,R,I,B,F,$)=>{f=f||nl,p=p||nl;const j=f.length,J=p.length,q=Math.min(j,J);let Z;for(Z=0;ZJ?je(f,R,I,!0,!1,q):E(p,k,T,R,I,B,F,$,q)},Se=(f,p,k,T,R,I,B,F,$)=>{let j=0;const J=p.length;let q=f.length-1,Z=J-1;for(;j<=q&&j<=Z;){const re=f[j],se=p[j]=$?wt(p[j]):tt(p[j]);if(Bt(re,se))x(re,se,k,null,R,I,B,F,$);else break;j++}for(;j<=q&&j<=Z;){const re=f[q],se=p[Z]=$?wt(p[Z]):tt(p[Z]);if(Bt(re,se))x(re,se,k,null,R,I,B,F,$);else break;q--,Z--}if(j>q){if(j<=Z){const re=Z+1,se=reZ)for(;j<=q;)He(f[j],R,I,!0),j++;else{const re=j,se=j,me=new Map;for(j=se;j<=Z;j++){const Ke=p[j]=$?wt(p[j]):tt(p[j]);Ke.key!=null&&me.set(Ke.key,j)}let ge,Oe=0;const et=Z-se+1;let Jt=!1,Ji=0;const kl=new Array(et);for(j=0;j=et){He(Ke,R,I,!0);continue}let st;if(Ke.key!=null)st=me.get(Ke.key);else for(ge=se;ge<=Z;ge++)if(kl[ge-se]===0&&Bt(Ke,p[ge])){st=ge;break}st===void 0?He(Ke,R,I,!0):(kl[st-se]=j+1,st>=Ji?Ji=st:Jt=!0,x(Ke,p[st],k,null,R,I,B,F,$),Oe++)}const Zi=Jt?Va(kl):nl;for(ge=Zi.length-1,j=et-1;j>=0;j--){const Ke=se+j,st=p[Ke],er=Ke+1{const{el:I,type:B,transition:F,children:$,shapeFlag:j}=f;if(j&6){Ue(f.component.subTree,p,k,T);return}if(j&128){f.suspense.move(p,k,T);return}if(j&64){B.move(f,p,k,M);return}if(B===ke){n(I,p,k);for(let q=0;q<$.length;q++)Ue($[q],p,k,T);n(f.anchor,p,k);return}if(B===Rl){b(f,p,k);return}if(T!==2&&j&1&&F)if(T===0)F.beforeEnter(I),n(I,p,k),ze(()=>F.enter(I),R);else{const{leave:q,delayLeave:Z,afterLeave:re}=F,se=()=>n(I,p,k),me=()=>{q(I,()=>{se(),re&&re()})};Z?Z(I,se,me):me()}else n(I,p,k)},He=(f,p,k,T=!1,R=!1)=>{const{type:I,props:B,ref:F,children:$,dynamicChildren:j,shapeFlag:J,patchFlag:q,dirs:Z}=f;if(F!=null&&xn(F,null,k,f,!0),J&256){p.ctx.deactivate(f);return}const re=J&1&&Z,se=!sl(f);let me;if(se&&(me=B&&B.onVnodeBeforeUnmount)&&Je(me,p,f),J&6)ot(f.component,k,T);else{if(J&128){f.suspense.unmount(k,T);return}re&&ct(f,null,p,"beforeUnmount"),J&64?f.type.remove(f,p,k,R,M,T):j&&(I!==ke||q>0&&q&64)?je(j,p,k,!1,!0):(I===ke&&q&384||!R&&J&16)&&je($,p,k),T&&yt(f)}(se&&(me=B&&B.onVnodeUnmounted)||re)&&ze(()=>{me&&Je(me,p,f),re&&ct(f,null,p,"unmounted")},k)},yt=f=>{const{type:p,el:k,anchor:T,transition:R}=f;if(p===ke){xt(k,T);return}if(p===Rl){y(f);return}const I=()=>{i(k),R&&!R.persisted&&R.afterLeave&&R.afterLeave()};if(f.shapeFlag&1&&R&&!R.persisted){const{leave:B,delayLeave:F}=R,$=()=>B(k,I);F?F(f.el,I,$):$()}else I()},xt=(f,p)=>{let k;for(;f!==p;)k=_(f),i(f),f=k;i(p)},ot=(f,p,k)=>{const{bum:T,scope:R,update:I,subTree:B,um:F}=f;T&&Bn(T),R.stop(),I&&(I.active=!1,He(B,f,p,k)),F&&ze(F,p),ze(()=>{f.isUnmounted=!0},p),p&&p.pendingBranch&&!p.isUnmounted&&f.asyncDep&&!f.asyncResolved&&f.suspenseId===p.pendingId&&(p.deps--,p.deps===0&&p.resolve())},je=(f,p,k,T=!1,R=!1,I=0)=>{for(let B=I;Bf.shapeFlag&6?P(f.component.subTree):f.shapeFlag&128?f.suspense.next():_(f.anchor||f.el),U=(f,p,k)=>{f==null?p._vnode&&He(p._vnode,null,null,!0):x(p._vnode||null,f,p,null,null,null,k),ar(),mn(),p._vnode=f},M={p:x,um:He,m:Ue,r:yt,mt:le,mc:E,pc:X,pbc:w,n:P,o:e};let Y,ae;return t&&([Y,ae]=t(M)),{render:U,hydrate:Y,createApp:Pa(U,Y)}}function Ft({effect:e,update:t},l){e.allowRecurse=t.allowRecurse=l}function ss(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function cs(e,t,l=!1){const n=e.children,i=t.children;if(te(n)&&te(i))for(let r=0;r>1,e[l[c]]0&&(t[n]=l[r-1]),l[r]=n)}}for(r=l.length,o=l[r-1];r-- >0;)l[r]=o,o=t[o];return l}const Fa=e=>e.__isTeleport,ke=Symbol.for("v-fgt"),al=Symbol.for("v-txt"),Ye=Symbol.for("v-cmt"),Rl=Symbol.for("v-stc"),Il=[];let nt=null;function W(e=!1){Il.push(nt=e?null:[])}function Na(){Il.pop(),nt=Il[Il.length-1]||null}let Fl=1;function Er(e){Fl+=e}function as(e){return e.dynamicChildren=Fl>0?nt||nl:null,Na(),Fl>0&&nt&&nt.push(e),e}function ee(e,t,l,n,i,r){return as(ce(e,t,l,n,i,r,!0))}function Ae(e,t,l,n,i){return as(ie(e,t,l,n,i,!0))}function Ln(e){return e?e.__v_isVNode===!0:!1}function Bt(e,t){return e.type===t.type&&e.key===t.key}const Fn="__vInternal",us=({key:e})=>e??null,vn=({ref:e,ref_key:t,ref_for:l})=>(typeof e=="number"&&(e=""+e),e!=null?we(e)||Ne(e)||oe(e)?{i:Ve,r:e,k:t,f:!!l}:e:null);function ce(e,t=null,l=null,n=0,i=null,r=e===ke?0:1,o=!1,c=!1){const a={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&us(t),ref:t&&vn(t),scopeId:Xo,slotScopeIds:null,children:l,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:r,patchFlag:n,dynamicProps:i,dynamicChildren:null,appContext:null,ctx:Ve};return c?(Ci(a,l),r&128&&e.normalize(a)):l&&(a.shapeFlag|=we(l)?8:16),Fl>0&&!o&&nt&&(a.patchFlag>0||r&6)&&a.patchFlag!==32&&nt.push(a),a}const ie=Ha;function Ha(e,t=null,l=null,n=0,i=null,r=!1){if((!e||e===la)&&(e=Ye),Ln(e)){const c=Ct(e,t,!0);return l&&Ci(c,l),Fl>0&&!r&&nt&&(c.shapeFlag&6?nt[nt.indexOf(e)]=c:nt.push(c)),c.patchFlag|=-2,c}if(Ya(e)&&(e=e.__vccOpts),t){t=Ma(t);let{class:c,style:a}=t;c&&!we(c)&&(t.class=$e(c)),Ee(a)&&(Vo(a)&&!te(a)&&(a=Ie({},a)),t.style=Wl(a))}const o=we(e)?1:ia(e)?128:Fa(e)?64:Ee(e)?4:oe(e)?2:0;return ce(e,t,l,n,i,o,r,!0)}function Ma(e){return e?Vo(e)||Fn in e?Ie({},e):e:null}function Ct(e,t,l=!1){const{props:n,ref:i,patchFlag:r,children:o}=e,c=t?_i(n||{},t):n;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:c,key:c&&us(c),ref:t&&t.ref?l&&i?te(i)?i.concat(vn(t)):[i,vn(t)]:vn(t):i,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:o,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==ke?r===-1?16:r|16:r,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Ct(e.ssContent),ssFallback:e.ssFallback&&Ct(e.ssFallback),el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce}}function Vt(e=" ",t=0){return ie(al,null,e,t)}function $a(e,t){const l=ie(Rl,null,e);return l.staticCount=t,l}function Le(e="",t=!1){return t?(W(),Ae(Ye,null,e)):ie(Ye,null,e)}function tt(e){return e==null||typeof e=="boolean"?ie(Ye):te(e)?ie(ke,null,e.slice()):typeof e=="object"?wt(e):ie(al,null,String(e))}function wt(e){return e.el===null&&e.patchFlag!==-1||e.memo?e:Ct(e)}function Ci(e,t){let l=0;const{shapeFlag:n}=e;if(t==null)t=null;else if(te(t))l=16;else if(typeof t=="object")if(n&65){const i=t.default;i&&(i._c&&(i._d=!1),Ci(e,i()),i._c&&(i._d=!0));return}else{l=32;const i=t._;!i&&!(Fn in t)?t._ctx=Ve:i===3&&Ve&&(Ve.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else oe(t)?(t={default:t,_ctx:Ve},l=32):(t=String(t),n&64?(l=16,t=[Vt(t)]):l=8);e.children=t,e.shapeFlag|=l}function _i(...e){const t={};for(let l=0;lRe||Ve;let Fi,Zt,yr="__VUE_INSTANCE_SETTERS__";(Zt=ni()[yr])||(Zt=ni()[yr]=[]),Zt.push(e=>Re=e),Fi=e=>{Zt.length>1?Zt.forEach(t=>t(e)):Zt[0](e)};const ul=e=>{Fi(e),e.scope.on()},qt=()=>{Re&&Re.scope.off(),Fi(null)};function ds(e){return e.vnode.shapeFlag&4}let dl=!1;function za(e,t=!1){dl=t;const{props:l,children:n}=e.vnode,i=ds(e);Aa(e,l,i,t),Ia(e,n);const r=i?Xa(e,t):void 0;return dl=!1,r}function Xa(e,t){const l=e.type;e.accessCache=Object.create(null),e.proxy=Fo(new Proxy(e.ctx,ka));const{setup:n}=l;if(n){const i=e.setupContext=n.length>1?qa(e):null;ul(e),pl();const r=Dt(n,e,0,[e.props,i]);if(gl(),qt(),bo(r)){if(r.then(qt,qt),t)return r.then(o=>{xr(e,o,t)}).catch(o=>{zl(o,e,0)});e.asyncDep=r}else xr(e,r,t)}else hs(e,t)}function xr(e,t,l){oe(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Ee(t)&&(e.setupState=Mo(t)),hs(e,l)}let Lr;function hs(e,t,l){const n=e.type;if(!e.render){if(!t&&Lr&&!n.render){const i=n.template||ji(e).template;if(i){const{isCustomElement:r,compilerOptions:o}=e.appContext.config,{delimiters:c,compilerOptions:a}=n,u=Ie(Ie({isCustomElement:r,delimiters:c},o),a);n.render=Lr(i,u)}}e.render=n.render||ut}{ul(e),pl();try{Ea(e)}finally{gl(),qt()}}}function Ka(e){return e.attrsProxy||(e.attrsProxy=new Proxy(e.attrs,{get(t,l){return Xe(e,"get","$attrs"),t[l]}}))}function qa(e){const t=l=>{e.exposed=l||{}};return{get attrs(){return Ka(e)},slots:e.slots,emit:e.emit,expose:t}}function Nn(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Mo(Fo(e.exposed)),{get(t,l){if(l in t)return t[l];if(l in wl)return wl[l](e)},has(t,l){return l in t||l in wl}}))}function Ga(e,t=!0){return oe(e)?e.displayName||e.name:e.name||t&&e.__name}function Ya(e){return oe(e)&&"__vccOpts"in e}const C=(e,t)=>Uc(e,t,dl);function he(e,t,l){const n=arguments.length;return n===2?Ee(t)&&!te(t)?Ln(t)?ie(e,null,[t]):ie(e,t):ie(e,null,t):(n>3?l=Array.prototype.slice.call(arguments,2):n===3&&Ln(l)&&(l=[l]),ie(e,t,l))}const Qa=Symbol.for("v-scx"),Ja=()=>Te(Qa),Za="3.3.13",eu="http://www.w3.org/2000/svg",Wt=typeof document<"u"?document:null,Tr=Wt&&Wt.createElement("template"),tu={insert:(e,t,l)=>{t.insertBefore(e,l||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,l,n)=>{const i=t?Wt.createElementNS(eu,e):Wt.createElement(e,l?{is:l}:void 0);return e==="select"&&n&&n.multiple!=null&&i.setAttribute("multiple",n.multiple),i},createText:e=>Wt.createTextNode(e),createComment:e=>Wt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Wt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,l,n,i,r){const o=l?l.previousSibling:t.lastChild;if(i&&(i===r||i.nextSibling))for(;t.insertBefore(i.cloneNode(!0),l),!(i===r||!(i=i.nextSibling)););else{Tr.innerHTML=n?`${e}`:e;const c=Tr.content;if(n){const a=c.firstChild;for(;a.firstChild;)c.appendChild(a.firstChild);c.removeChild(a)}t.insertBefore(c,l)}return[o?o.nextSibling:t.firstChild,l?l.previousSibling:t.lastChild]}},Ot="transition",El="animation",Nl=Symbol("_vtc"),Gl=(e,{slots:t})=>he(aa,lu(e),t);Gl.displayName="Transition";const vs={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};Gl.props=Ie({},Go,vs);const Nt=(e,t=[])=>{te(e)?e.forEach(l=>l(...t)):e&&e(...t)},Or=e=>e?te(e)?e.some(t=>t.length>1):e.length>1:!1;function lu(e){const t={};for(const L in e)L in vs||(t[L]=e[L]);if(e.css===!1)return t;const{name:l="v",type:n,duration:i,enterFromClass:r=`${l}-enter-from`,enterActiveClass:o=`${l}-enter-active`,enterToClass:c=`${l}-enter-to`,appearFromClass:a=r,appearActiveClass:u=o,appearToClass:d=c,leaveFromClass:v=`${l}-leave-from`,leaveActiveClass:_=`${l}-leave-active`,leaveToClass:g=`${l}-leave-to`}=e,m=nu(i),x=m&&m[0],A=m&&m[1],{onBeforeEnter:D,onEnter:O,onEnterCancelled:b,onLeave:y,onLeaveCancelled:H,onBeforeAppear:G=D,onAppear:N=O,onAppearCancelled:E=b}=t,K=(L,V,le)=>{Ht(L,V?d:c),Ht(L,V?u:o),le&&le()},w=(L,V)=>{L._isLeaving=!1,Ht(L,v),Ht(L,g),Ht(L,_),V&&V()},z=L=>(V,le)=>{const ne=L?N:O,S=()=>K(V,L,le);Nt(ne,[V,S]),Pr(()=>{Ht(V,L?a:r),Pt(V,L?d:c),Or(ne)||Ar(V,n,x,S)})};return Ie(t,{onBeforeEnter(L){Nt(D,[L]),Pt(L,r),Pt(L,o)},onBeforeAppear(L){Nt(G,[L]),Pt(L,a),Pt(L,u)},onEnter:z(!1),onAppear:z(!0),onLeave(L,V){L._isLeaving=!0;const le=()=>w(L,V);Pt(L,v),ou(),Pt(L,_),Pr(()=>{L._isLeaving&&(Ht(L,v),Pt(L,g),Or(y)||Ar(L,n,A,le))}),Nt(y,[L,le])},onEnterCancelled(L){K(L,!1),Nt(b,[L])},onAppearCancelled(L){K(L,!0),Nt(E,[L])},onLeaveCancelled(L){w(L),Nt(H,[L])}})}function nu(e){if(e==null)return null;if(Ee(e))return[qn(e.enter),qn(e.leave)];{const t=qn(e);return[t,t]}}function qn(e){return oc(e)}function Pt(e,t){t.split(/\s+/).forEach(l=>l&&e.classList.add(l)),(e[Nl]||(e[Nl]=new Set)).add(t)}function Ht(e,t){t.split(/\s+/).forEach(n=>n&&e.classList.remove(n));const l=e[Nl];l&&(l.delete(t),l.size||(e[Nl]=void 0))}function Pr(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let iu=0;function Ar(e,t,l,n){const i=e._endId=++iu,r=()=>{i===e._endId&&n()};if(l)return setTimeout(r,l);const{type:o,timeout:c,propCount:a}=ru(e,t);if(!o)return n();const u=o+"end";let d=0;const v=()=>{e.removeEventListener(u,_),r()},_=g=>{g.target===e&&++d>=a&&v()};setTimeout(()=>{d(l[m]||"").split(", "),i=n(`${Ot}Delay`),r=n(`${Ot}Duration`),o=wr(i,r),c=n(`${El}Delay`),a=n(`${El}Duration`),u=wr(c,a);let d=null,v=0,_=0;t===Ot?o>0&&(d=Ot,v=o,_=r.length):t===El?u>0&&(d=El,v=u,_=a.length):(v=Math.max(o,u),d=v>0?o>u?Ot:El:null,_=d?d===Ot?r.length:a.length:0);const g=d===Ot&&/\b(transform|all)(,|$)/.test(n(`${Ot}Property`).toString());return{type:d,timeout:v,propCount:_,hasTransform:g}}function wr(e,t){for(;e.lengthRr(l)+Rr(e[n])))}function Rr(e){return e==="auto"?0:Number(e.slice(0,-1).replace(",","."))*1e3}function ou(){return document.body.offsetHeight}function su(e,t,l){const n=e[Nl];n&&(t=(t?[t,...n]:[...n]).join(" ")),t==null?e.removeAttribute("class"):l?e.setAttribute("class",t):e.className=t}const Ni=Symbol("_vod"),Tn={beforeMount(e,{value:t},{transition:l}){e[Ni]=e.style.display==="none"?"":e.style.display,l&&t?l.beforeEnter(e):yl(e,t)},mounted(e,{value:t},{transition:l}){l&&t&&l.enter(e)},updated(e,{value:t,oldValue:l},{transition:n}){!t!=!l&&(n?t?(n.beforeEnter(e),yl(e,!0),n.enter(e)):n.leave(e,()=>{yl(e,!1)}):yl(e,t))},beforeUnmount(e,{value:t}){yl(e,t)}};function yl(e,t){e.style.display=t?e[Ni]:"none"}const cu=Symbol("");function au(e,t,l){const n=e.style,i=we(l);if(l&&!i){if(t&&!we(t))for(const r in t)l[r]==null&&fi(n,r,"");for(const r in l)fi(n,r,l[r])}else{const r=n.display;if(i){if(t!==l){const o=n[cu];o&&(l+=";"+o),n.cssText=l}}else t&&e.removeAttribute("style");Ni in e&&(n.display=r)}}const Ir=/\s*!important$/;function fi(e,t,l){if(te(l))l.forEach(n=>fi(e,t,n));else if(l==null&&(l=""),t.startsWith("--"))e.setProperty(t,l);else{const n=uu(e,t);Ir.test(l)?e.setProperty(Qt(n),l.replace(Ir,""),"important"):e[n]=l}}const Dr=["Webkit","Moz","ms"],Gn={};function uu(e,t){const l=Gn[t];if(l)return l;let n=dt(t);if(n!=="filter"&&n in e)return Gn[t]=n;n=wn(n);for(let i=0;iYn||(gu.then(()=>Yn=0),Yn=Date.now());function bu(e,t){const l=n=>{if(!n._vts)n._vts=Date.now();else if(n._vts<=l.attached)return;Ze(ku(n,l.value),t,5,[n])};return l.value=e,l.attached=mu(),l}function ku(e,t){if(te(t)){const l=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{l.call(e),e._stopped=!0},t.map(n=>i=>!i._stopped&&n&&n(i))}else return t}const Vr=e=>e.charCodeAt(0)===111&&e.charCodeAt(1)===110&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123,Eu=(e,t,l,n,i=!1,r,o,c,a)=>{t==="class"?su(e,n,i):t==="style"?au(e,l,n):Bl(t)?ki(t)||fu(e,t,l,n,o):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):yu(e,t,n,i))?hu(e,t,n,r,o,c,a):(t==="true-value"?e._trueValue=n:t==="false-value"&&(e._falseValue=n),du(e,t,n,i))};function yu(e,t,l,n){if(n)return!!(t==="innerHTML"||t==="textContent"||t in e&&Vr(t)&&oe(l));if(t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA")return!1;if(t==="width"||t==="height"){const i=e.tagName;if(i==="IMG"||i==="VIDEO"||i==="CANVAS"||i==="SOURCE")return!1}return Vr(t)&&we(l)?!1:t in e}const xu={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},Lu=(e,t)=>{const l=e._withKeys||(e._withKeys={}),n=t.join(".");return l[n]||(l[n]=i=>{if(!("key"in i))return;const r=Qt(i.key);if(t.some(o=>o===r||xu[o]===r))return e(i)})},Tu=Ie({patchProp:Eu},tu);let Qn,Fr=!1;function Ou(){return Qn=Fr?Qn:Sa(Tu),Fr=!0,Qn}const Pu=(...e)=>{const t=Ou().createApp(...e),{mount:l}=t;return t.mount=n=>{const i=Au(n);if(i)return l(i,!0,i instanceof SVGElement)},t};function Au(e){return we(e)?document.querySelector(e):e}const wu="modulepreload",Ru=function(e){return"/"+e},Nr={},s=function(t,l,n){let i=Promise.resolve();return l&&l.length>0&&(document.getElementsByTagName("link"),i=Promise.all(l.map(r=>{if(r=Ru(r),r in Nr)return;Nr[r]=!0;const o=r.endsWith(".css"),c=o?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${r}"]${c}`))return;const a=document.createElement("link");if(a.rel=o?"stylesheet":wu,o||(a.as="script",a.crossOrigin=""),a.href=r,document.head.appendChild(a),o)return new Promise((u,d)=>{a.addEventListener("load",u),a.addEventListener("error",()=>d(new Error(`Unable to preload CSS for ${r}`)))})}))),i.then(()=>t()).catch(r=>{const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=r,window.dispatchEvent(o),!o.defaultPrevented)throw r})},Iu={"v-8daa1a0e":()=>s(()=>import("./index.html-D9G6CNbk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-aad48c6a":()=>s(()=>import("./news.html-C-ufwDLv.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ba934fd8":()=>s(()=>import("./index.html-B2ETL5pY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41ade9da":()=>s(()=>import("./api.html-5y-QWEO9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-83dedd38":()=>s(()=>import("./dns.html-BfPt-22g.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-192a19b9":()=>s(()=>import("./fakedns.html-BSHcVJMt.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7f6279d8":()=>s(()=>import("./inbound.html-DyiGLTJ2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1d860c29":()=>s(()=>import("./log.html-De0YGftm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fbaf47ec":()=>s(()=>import("./metrics.html-C1kvghj5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-24956213":()=>s(()=>import("./observatory.html-Dkgoiajw.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2367d756":()=>s(()=>import("./outbound.html-C5ktgOxG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4ebec35a":()=>s(()=>import("./policy.html-CErsqhDk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-31b7756a":()=>s(()=>import("./reverse.html-BzUnx5j0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-70677432":()=>s(()=>import("./routing.html-D0dccOVI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7e21d6ae":()=>s(()=>import("./stats.html-DHCl8ess.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e3dfff38":()=>s(()=>import("./transport.html-CXI2SbwO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f7496066":()=>s(()=>import("./index.html-CTbMiGG2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-36b1a79b":()=>s(()=>import("./index.html-CA-WluU-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-09a64f89":()=>s(()=>import("./command.html-opo_NLX2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2b1adf48":()=>s(()=>import("./config.html-O0hv2z0b.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-86ee963a":()=>s(()=>import("./document.html-vroedGik.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0e5d7b39":()=>s(()=>import("./install.html-C6eLysya.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2d0a870d":()=>s(()=>import("./index.html-QftOk6LQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2d0ab8b3":()=>s(()=>import("./index.html-CshDtg4G.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d714d87":()=>s(()=>import("./browser_dialer.html-DYjgEhDN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0da7880a":()=>s(()=>import("./env.html-x3PGFNW0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2aeb21f9":()=>s(()=>import("./fallback.html-BCz8baOr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3acf20ea":()=>s(()=>import("./multiple.html-CA4IQdBs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-792e28f8":()=>s(()=>import("./xtls.html-DTQkH1EU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b50d2334":()=>s(()=>import("./dokodemo.html-BVzbqjRe.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-593408b0":()=>s(()=>import("./http.html-BIzz1n6q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-802a842a":()=>s(()=>import("./shadowsocks.html-Bog2IQ_X.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-29995cea":()=>s(()=>import("./socks.html-DSlw2Tvo.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2a1b3d72":()=>s(()=>import("./trojan.html-BkQCt-32.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fb92e8aa":()=>s(()=>import("./vless.html-CxK3eXqB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-167afaac":()=>s(()=>import("./vmess.html-BSAH9EwQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-749ad71a":()=>s(()=>import("./blackhole.html-C3j-gtFm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6d39b970":()=>s(()=>import("./dns.html-R1M3D1VY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d76e893a":()=>s(()=>import("./freedom.html-Q-WXO_3C.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c6b4b59e":()=>s(()=>import("./http.html-CqFywJ_o.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41ec0e0e":()=>s(()=>import("./loopback.html-CYltRkS6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7b293e4a":()=>s(()=>import("./shadowsocks.html-BdSAub8s.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-15f5452a":()=>s(()=>import("./socks.html-C_Ryg_Zn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5797bdb3":()=>s(()=>import("./trojan.html-_aC10_zp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a60f016c":()=>s(()=>import("./vless.html-sPPpqcW_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-413cee4b":()=>s(()=>import("./vmess.html-3bHG9IEs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-208ca3b9":()=>s(()=>import("./wireguard.html-DMp0Htsq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-775db7b1":()=>s(()=>import("./domainsocket.html-DZc5AOZh.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2877542a":()=>s(()=>import("./grpc.html-BOwRBc6V.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-03a28284":()=>s(()=>import("./h2.html-B-_cdxSw.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-04158536":()=>s(()=>import("./httpupgrade.html-DNm5DiZb.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3167b1dd":()=>s(()=>import("./mkcp.html-CmaMJX_Q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8f08dbec":()=>s(()=>import("./quic.html-t3RvaIkj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-eeea2fb0":()=>s(()=>import("./splithttp.html-DHcDbGo9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-33b1b709":()=>s(()=>import("./tcp.html-tAb-Rdu-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ff57bba":()=>s(()=>import("./websocket.html-J4zD0ZXr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a9e8054":()=>s(()=>import("./compile.html-C08Er0mK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-95e3eaea":()=>s(()=>import("./design.html-JvR3o2wW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-61e7eea6":()=>s(()=>import("./guide.html-CIw6ZqK-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6e6c37e6":()=>s(()=>import("./mkcp.html-BECLirWp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-13168a21":()=>s(()=>import("./muxcool.html-DxsTQuoq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5c48c82b":()=>s(()=>import("./vless.html-bx0zLtjU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1ee591a8":()=>s(()=>import("./vmess.html-DH5KSkx4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f09dcfa":()=>s(()=>import("./index.html-CpLT_ZsY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fb444906":()=>s(()=>import("./ch01-preface.html-DmNJxKif.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-075f3ae5":()=>s(()=>import("./ch02-preparation.html-BTKGqj9u.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-726d0633":()=>s(()=>import("./ch03-ssh.html-Bs4sxOG7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-430c6ab8":()=>s(()=>import("./ch04-security.html-BgZQf6Zy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-717c6376":()=>s(()=>import("./ch05-webpage.html-C3ISjTL0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-278039be":()=>s(()=>import("./ch06-certificates.html-g-a588dM.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a0c7f88e":()=>s(()=>import("./ch07-xray-server.html-CL7ODUGu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-86586ca2":()=>s(()=>import("./ch08-xray-clients.html-D0DH-0jR.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3eb62514":()=>s(()=>import("./ch09-appendix.html-B-sOxmCt.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f09dcbc":()=>s(()=>import("./index.html-Z8xBvZ8J.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b21a2a20":()=>s(()=>import("./fallbacks-lv1.html-Dyr_PhvB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-da623318":()=>s(()=>import("./fallbacks-with-sni.html-V5VzGt_a.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fdd722ac":()=>s(()=>import("./routing-lv1-part1.html-DsPriwu4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fa6d716e":()=>s(()=>import("./routing-lv1-part2.html-Shikx9Ih.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2f29e106":()=>s(()=>import("./work.html-CEe4qs2X.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3f09dc7e":()=>s(()=>import("./index.html-DC6-KGmE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1c17916e":()=>s(()=>import("./iptables_gid.html-BMSyFQlC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a001cfa6":()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-BRMPCdti.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-46333b48":()=>s(()=>import("./redirect.html-qKHxqUqo.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-338bc63e":()=>s(()=>import("./tproxy.html-ByDe25dh.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d68f7d58":()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-D-5zdr32.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e533e2c6":()=>s(()=>import("./traffic_stats.html-0T5V4GoX.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1e465ab0":()=>s(()=>import("./warp.html-BDXJx2co.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1080fb37":()=>s(()=>import("./news.html-Cct6yV3F.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-317fc580":()=>s(()=>import("./index.html-CVcFP_qj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-45144c7f":()=>s(()=>import("./api.html-Kao4_KiT.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-23fbd2d0":()=>s(()=>import("./dns.html-CvTCwYNS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2b7ec525":()=>s(()=>import("./fakedns.html-Dvu3AZyj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5ab92300":()=>s(()=>import("./inbound.html-YO29XvIi.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f91d64d6":()=>s(()=>import("./log.html-IZnUGgyl.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d705f114":()=>s(()=>import("./metrics.html-BLJ8GVn6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-268cd669":()=>s(()=>import("./outbound.html-DEfIgkBm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4492d567":()=>s(()=>import("./policy.html-C8ASaUzS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d0e1e92":()=>s(()=>import("./reverse.html-BnnvxzqT.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4bbe1d5a":()=>s(()=>import("./routing.html-FLu7YnPx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-16426d1a":()=>s(()=>import("./stats.html-DGZuatV1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5de780d0":()=>s(()=>import("./transport.html-HJMM8SAW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f88d343e":()=>s(()=>import("./index.html-CFqc6OBy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-38d56a07":()=>s(()=>import("./index.html-C3JYr0X_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d046016":()=>s(()=>import("./command.html-CnAfnl0M.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22b35270":()=>s(()=>import("./config.html-DrlSKA0W.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-30bd7c12":()=>s(()=>import("./document.html-CBY4dmVD.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-439608b6":()=>s(()=>import("./install.html-xlRH6Hy9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-408e88d1":()=>s(()=>import("./news.html-CHwot1ez.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b1cce5cc":()=>s(()=>import("./index.html-Br3dj_2c.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7521da19":()=>s(()=>import("./api.html-DLDnYtg0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5409606a":()=>s(()=>import("./dns.html-DfoiH0ad.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5877f5bf":()=>s(()=>import("./fakedns.html-DFAPe69C.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-00c6c1cc":()=>s(()=>import("./inbound.html-BrzkUvMu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-990249a2":()=>s(()=>import("./log.html-DcQn41R9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d138fe0":()=>s(()=>import("./metrics.html-wNzErJVc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-11e9cb19":()=>s(()=>import("./observatory.html-CQ1B9WMF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ce8c8de2":()=>s(()=>import("./outbound.html-DS1UueDj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3dc4298d":()=>s(()=>import("./policy.html-CZXmUkYI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-26722151":()=>s(()=>import("./reverse.html-B5DaFRsx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-071a21ed":()=>s(()=>import("./routing.html-CSEUsncX.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7922fc34":()=>s(()=>import("./stats.html-CkQuuoBx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3156f2ea":()=>s(()=>import("./transport.html-BiA5MGQV.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-40ee4e87":()=>s(()=>import("./index.html-BBMcLiPC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a1c899be":()=>s(()=>import("./index.html-B-J-mqnv.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a6257be2":()=>s(()=>import("./command.html-DLT-4XC7.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d63f95d4":()=>s(()=>import("./config.html-CpMF1H3m.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fbbfd9c6":()=>s(()=>import("./document.html-Cv2iGxpB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9cb72482":()=>s(()=>import("./install.html-Cmyvi2cp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-51a51d87":()=>s(()=>import("./transparent_proxy.html-DZNi96TQ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-76b9a0f3":()=>s(()=>import("./browser_dialer.html-Bdbrov2m.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-565dbfc4":()=>s(()=>import("./env.html-kVBaIisu.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0fbd1336":()=>s(()=>import("./fallback.html-Cz26Rtbk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a0627812":()=>s(()=>import("./multiple.html-672DYUik.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d190d938":()=>s(()=>import("./xtls.html-enE-oLop.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-72afc2d2":()=>s(()=>import("./dokodemo.html-tumWX5uf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-773d731c":()=>s(()=>import("./http.html-Dk_GJXk3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f555fc02":()=>s(()=>import("./shadowsocks.html-nKE9-JwE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e35196c2":()=>s(()=>import("./socks.html-DxBaX8G5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-29188644":()=>s(()=>import("./trojan.html-2VAwem9J.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-255a6ebf":()=>s(()=>import("./vless.html-BCCfQS7T.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-8cc24480":()=>s(()=>import("./vmess.html-DmF6uMmY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-64e47ef4":()=>s(()=>import("./blackhole.html-Cv99Ln_e.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e979b848":()=>s(()=>import("./dns.html-B4Qc1gmf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-617f0fcf":()=>s(()=>import("./freedom.html-uHQ6fg4W.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3fc98845":()=>s(()=>import("./http.html-BW71su7G.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1b804722":()=>s(()=>import("./loopback.html-DBZDnpde.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-63077cb6":()=>s(()=>import("./shadowsocks.html-Cfe33M9q.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-516476d4":()=>s(()=>import("./socks.html-ZsLxpdI_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d61a872":()=>s(()=>import("./trojan.html-C_OdgAQH.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6e50feb6":()=>s(()=>import("./vless.html-DNT9jIbN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-02956db7":()=>s(()=>import("./vmess.html-BnKkO-oz.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-797f8d25":()=>s(()=>import("./wireguard.html-B1zHQq-E.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3eb3e9c6":()=>s(()=>import("./domainsocket.html-DIVEYZMl.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2c6058d4":()=>s(()=>import("./grpc.html-D7nAIvyK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1c38292a":()=>s(()=>import("./h2.html-9I7eRGud.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-17ff144a":()=>s(()=>import("./httpupgrade.html-DpYANPWG.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1a7f9d6e":()=>s(()=>import("./mkcp.html-D1BaSNsx.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-79d41176":()=>s(()=>import("./quic.html-0dkTOtLC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4df52c3c":()=>s(()=>import("./splithttp.html-CESvjk_m.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5254cbc6":()=>s(()=>import("./tcp.html-Dvv-qFsr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9520f392":()=>s(()=>import("./websocket.html-CDgG-JKn.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b7760e2c":()=>s(()=>import("./compile.html-CSlVqiWd.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fb774212":()=>s(()=>import("./design.html-CnO0gj1h.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-38c376c1":()=>s(()=>import("./guide.html-C1S7IA49.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21bccd79":()=>s(()=>import("./mkcp.html-VU4-Z4x2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-27001935":()=>s(()=>import("./muxcool.html-CEJDgOyw.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-21b30c3f":()=>s(()=>import("./vless.html-DH9DXlDy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-94110980":()=>s(()=>import("./vmess.html-DRYwVgEC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-789ba7ef":()=>s(()=>import("./index.html-B7FLw-wS.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-d3712ade":()=>s(()=>import("./ch01-preface.html-CpS2RBBO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-41f9c00e":()=>s(()=>import("./ch02-preparation.html-nD3-r55P.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4c013f47":()=>s(()=>import("./ch03-ssh.html-6Lvt6PUL.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a75683b8":()=>s(()=>import("./ch04-security.html-B6qoKme-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f5341aec":()=>s(()=>import("./ch05-webpage.html-DzsY94d_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4458f72a":()=>s(()=>import("./ch06-certificates.html-BznpCurY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f1802e66":()=>s(()=>import("./ch07-xray-server.html-DJ8-Sypk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4ca6f1ca":()=>s(()=>import("./ch08-xray-clients.html-DQ22p1_O.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b0030f00":()=>s(()=>import("./ch09-appendix.html-CgxfJw0n.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-789ba80e":()=>s(()=>import("./index.html-NEtYQEGC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-103b3e5c":()=>s(()=>import("./fallbacks-lv1.html-DzqMpBvO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-110dd688":()=>s(()=>import("./fallbacks-with-sni.html--6P9o5e1.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c425a7d4":()=>s(()=>import("./routing-lv1-part1.html-GsbV156D.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c0bbf696":()=>s(()=>import("./routing-lv1-part2.html-BeZDTPEs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5b6477cc":()=>s(()=>import("./work.html-bZWwnav2.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-789ba82d":()=>s(()=>import("./index.html-CL_S8-vB.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-05ddc65d":()=>s(()=>import("./iptables_gid.html-C-yflUZU.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-474afe99":()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-D4Pr38b-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-930ac920":()=>s(()=>import("./redirect.html-CkD_E0gF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-c579975c":()=>s(()=>import("./tproxy.html-BW6K5LzA.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7efb7c68":()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-BQJ6GusY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-12a33bee":()=>s(()=>import("./traffic_stats.html-DD1S40Up.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7d2b8478":()=>s(()=>import("./warp.html-C4DFBgRI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1cfb44e6":()=>s(()=>import("./browser_dialer.html-DHvZocHd.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a3f8078":()=>s(()=>import("./env.html-BcRLB4iC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-74f22e7f":()=>s(()=>import("./fallback.html-BtkFw_Xq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2c9f7c11":()=>s(()=>import("./multiple.html-L9QltWwj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-630c687e":()=>s(()=>import("./xtls.html-ByQJIYGC.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-20ff0a28":()=>s(()=>import("./dokodemo.html-B3AutCKN.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-43124836":()=>s(()=>import("./http.html-wmoV0Z5H.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6a351ba5":()=>s(()=>import("./shadowsocks.html-Dq6vO-NY.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3d1d02c5":()=>s(()=>import("./socks.html-DOyZIvi6.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1567b378":()=>s(()=>import("./trojan.html-ur2ZEK_x.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-57bf8636":()=>s(()=>import("./vless.html-Dp7gCWtk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-6864abe6":()=>s(()=>import("./vmess.html-BtGpHvfz.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5910da20":()=>s(()=>import("./blackhole.html-DWoVmjiZ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5717f8f6":()=>s(()=>import("./dns.html-QSFk3MG9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4360702e":()=>s(()=>import("./freedom.html-BE_zomJr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22e1532a":()=>s(()=>import("./http.html-o0wpiHQf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-38c69248":()=>s(()=>import("./loopback.html-BcZmhFf5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1a2a97d0":()=>s(()=>import("./shadowsocks.html-S-jhNF8h.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0141bb30":()=>s(()=>import("./socks.html-zyIZHHJ4.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-544bef26":()=>s(()=>import("./trojan.html-2ngT_7cs.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cf761560":()=>s(()=>import("./vless.html-CNa_dakW.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2c896451":()=>s(()=>import("./vmess.html-D5q0vDPy.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0502a6bf":()=>s(()=>import("./wireguard.html-DILhdRFk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5b6ec7b7":()=>s(()=>import("./domainsocket.html-DUhqh-j5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-13c3ca30":()=>s(()=>import("./grpc.html-1JoA2je9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2fe60378":()=>s(()=>import("./h2.html-BOxtTm8R.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-453f5c70":()=>s(()=>import("./httpupgrade.html-C5iPswVE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-1cb427e3":()=>s(()=>import("./mkcp.html-DILru_l-.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-b86fefe0":()=>s(()=>import("./quic.html-Grd-KxcO.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-32d545e2":()=>s(()=>import("./splithttp.html-CQc8OFxI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-f4c92f7a":()=>s(()=>import("./tcp.html-BgZgnk7j.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-cb60c046":()=>s(()=>import("./websocket.html-DNoxTZYE.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7ce977e0":()=>s(()=>import("./compile.html-D59MH5rf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-01d5d1de":()=>s(()=>import("./design.html-Ddh8g14z.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4d4e5367":()=>s(()=>import("./guide.html-BdEYZrHF.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a58031da":()=>s(()=>import("./mkcp.html-DAmKBEn3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5440615b":()=>s(()=>import("./muxcool.html-mhoEooTk.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-069325e5":()=>s(()=>import("./vless.html-CkQDajpI.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-ca50d634":()=>s(()=>import("./vmess.html-DtwTJf0_.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-490791ee":()=>s(()=>import("./index.html-CpXf73_p.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-78f09a92":()=>s(()=>import("./ch01-preface.html-w7EJag-g.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-64f6e51f":()=>s(()=>import("./ch02-preparation.html-Dgjcbj9R.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-69478a6d":()=>s(()=>import("./ch03-ssh.html-SW0FgDU9.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-271d7abe":()=>s(()=>import("./ch04-security.html-DMyIYFbc.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9ab38aa0":()=>s(()=>import("./ch05-webpage.html-BJ9Dh4eq.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7cddd6c4":()=>s(()=>import("./ch06-certificates.html-CYpwWYQK.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-0d33adf3":()=>s(()=>import("./ch07-xray-server.html-BMC39V_R.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-123166b5":()=>s(()=>import("./ch08-xray-clients.html-DiJ6a_Z3.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-22c7351a":()=>s(()=>import("./ch09-appendix.html-CaY0Q2De.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-490791b0":()=>s(()=>import("./index.html-DIt_Qwmg.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-e9f80a14":()=>s(()=>import("./fallbacks-lv1.html-Cj8_C__Y.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-2db62ba4":()=>s(()=>import("./fallbacks-with-sni.html-UrPS3PK0.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-531be8a0":()=>s(()=>import("./routing-lv1-part1.html-ZKuR2lvb.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-4fb23762":()=>s(()=>import("./routing-lv1-part2.html-BNHKIWxf.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-fdd8db80":()=>s(()=>import("./work.html-nNVb3F6P.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-49079172":()=>s(()=>import("./index.html-nyT_8_ff.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-331e0e83":()=>s(()=>import("./iptables_gid.html-5z8dtoE5.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7418a5b3":()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-VAv26tAr.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-587e32d4":()=>s(()=>import("./redirect.html-IdxcHO8c.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-9c63de10":()=>s(()=>import("./tproxy.html-BHj4GcZZ.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-a4c782e4":()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-D9HsaVXj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-71771ea3":()=>s(()=>import("./traffic_stats.html-D5bPdgjj.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-70300bea":()=>s(()=>import("./warp.html-Dj49TU1P.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-7689d7f3":()=>s(()=>import("./transparent_proxy.html-C4cGXidp.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-39b3c50d":()=>s(()=>import("./transparent_proxy.html-CdU0iNrm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-3706649a":()=>s(()=>import("./404.html-CnfmQthm.js"),__vite__mapDeps([])).then(({data:e})=>e),"v-5c8e777f":()=>s(()=>import("./observatory.html-CSc-qsnJ.js"),__vite__mapDeps([])).then(({data:e})=>e)},Du=JSON.parse('{"base":"/","lang":"en-US","title":"","description":"","head":[["link",{"rel":"icon","href":"/logo.png"}]],"locales":{"/":{"lang":"zh-CN","title":"Project X","description":"Xray 官方文档"},"/en/":{"lang":"en-US","title":"Project X","description":"Official document of Xray"},"/ru/":{"lang":"ru-RU","title":"Project X","description":"Официальная документация Xray"}}}');var ju=["link","meta","script","style","noscript","template"],Su=["title","base"],Cu=([e,t,l])=>Su.includes(e)?e:ju.includes(e)?e==="meta"&&t.name?`${e}.${t.name}`:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,Object.entries(t).map(([n,i])=>typeof i=="boolean"?i?[n,""]:null:[n,i]).filter(n=>n!=null).sort(([n],[i])=>n.localeCompare(i)),l]):null,Vu=e=>{const t=new Set,l=[];return e.forEach(n=>{const i=Cu(n);i&&!t.has(i)&&(t.add(i),l.push(n))}),l},Yl=e=>/^(https?:)?\/\//.test(e),Fu=e=>/^[a-z][a-z0-9+.-]*:/.test(e),Hi=e=>Object.prototype.toString.call(e)==="[object Object]",_s=e=>e[e.length-1]==="/"?e.slice(0,-1):e,fs=e=>e[0]==="/"?e.slice(1):e,ps=(e,t)=>{const l=Object.keys(e).sort((n,i)=>{const r=i.split("/").length-n.split("/").length;return r!==0?r:i.length-n.length});for(const n of l)if(t.startsWith(n))return n;return"/"},Nu=e=>typeof e=="function",it=e=>typeof e=="string";const gs={"v-8daa1a0e":h(()=>s(()=>import("./index.html-CUkf34zC.js"),__vite__mapDeps([]))),"v-aad48c6a":h(()=>s(()=>import("./news.html-BrzeG0HS.js"),__vite__mapDeps([]))),"v-ba934fd8":h(()=>s(()=>import("./index.html-D9C7rXyK.js"),__vite__mapDeps([]))),"v-41ade9da":h(()=>s(()=>import("./api.html-Dh_ndM7D.js"),__vite__mapDeps([]))),"v-83dedd38":h(()=>s(()=>import("./dns.html-Dh-LYENQ.js"),__vite__mapDeps([]))),"v-192a19b9":h(()=>s(()=>import("./fakedns.html-C-g4Cxj-.js"),__vite__mapDeps([]))),"v-7f6279d8":h(()=>s(()=>import("./inbound.html-CdeJ4snV.js"),__vite__mapDeps([]))),"v-1d860c29":h(()=>s(()=>import("./log.html-BXxmwSQO.js"),__vite__mapDeps([]))),"v-fbaf47ec":h(()=>s(()=>import("./metrics.html-Bg3SRRpG.js"),__vite__mapDeps([]))),"v-24956213":h(()=>s(()=>import("./observatory.html-CgCiDU6P.js"),__vite__mapDeps([]))),"v-2367d756":h(()=>s(()=>import("./outbound.html-DWjB8mz5.js"),__vite__mapDeps([]))),"v-4ebec35a":h(()=>s(()=>import("./policy.html-D7HzBw03.js"),__vite__mapDeps([]))),"v-31b7756a":h(()=>s(()=>import("./reverse.html-xPEDZtAc.js"),__vite__mapDeps([]))),"v-70677432":h(()=>s(()=>import("./routing.html-Diz_GMQp.js"),__vite__mapDeps([]))),"v-7e21d6ae":h(()=>s(()=>import("./stats.html-zgGzE1Xt.js"),__vite__mapDeps([]))),"v-e3dfff38":h(()=>s(()=>import("./transport.html-CMtV0LnR.js"),__vite__mapDeps([]))),"v-f7496066":h(()=>s(()=>import("./index.html-DAmXAAuC.js"),__vite__mapDeps([]))),"v-36b1a79b":h(()=>s(()=>import("./index.html-BkqXAF2a.js"),__vite__mapDeps([]))),"v-09a64f89":h(()=>s(()=>import("./command.html-wqNPUGxk.js"),__vite__mapDeps([]))),"v-2b1adf48":h(()=>s(()=>import("./config.html-B_bOsf-2.js"),__vite__mapDeps([]))),"v-86ee963a":h(()=>s(()=>import("./document.html-DhUVedrJ.js"),__vite__mapDeps([]))),"v-0e5d7b39":h(()=>s(()=>import("./install.html-7roQVGaJ.js"),__vite__mapDeps([]))),"v-2d0a870d":h(()=>s(()=>import("./index.html-BiwlIXs1.js"),__vite__mapDeps([]))),"v-2d0ab8b3":h(()=>s(()=>import("./index.html-DPZpGJBw.js"),__vite__mapDeps([]))),"v-0d714d87":h(()=>s(()=>import("./browser_dialer.html-C_TsP8h-.js"),__vite__mapDeps([]))),"v-0da7880a":h(()=>s(()=>import("./env.html-aOvx_pi1.js"),__vite__mapDeps([]))),"v-2aeb21f9":h(()=>s(()=>import("./fallback.html-DKu1U9AN.js"),__vite__mapDeps([]))),"v-3acf20ea":h(()=>s(()=>import("./multiple.html-BhUjtgl7.js"),__vite__mapDeps([]))),"v-792e28f8":h(()=>s(()=>import("./xtls.html-CDQXBW21.js"),__vite__mapDeps([]))),"v-b50d2334":h(()=>s(()=>import("./dokodemo.html-C06CbLuo.js"),__vite__mapDeps([]))),"v-593408b0":h(()=>s(()=>import("./http.html-Bp5JIQRB.js"),__vite__mapDeps([]))),"v-802a842a":h(()=>s(()=>import("./shadowsocks.html-CvgM8qZ3.js"),__vite__mapDeps([]))),"v-29995cea":h(()=>s(()=>import("./socks.html-a5bSQH2X.js"),__vite__mapDeps([]))),"v-2a1b3d72":h(()=>s(()=>import("./trojan.html-Cs7YEsIb.js"),__vite__mapDeps([]))),"v-fb92e8aa":h(()=>s(()=>import("./vless.html-CASW7iOO.js"),__vite__mapDeps([]))),"v-167afaac":h(()=>s(()=>import("./vmess.html-Bnv13XwA.js"),__vite__mapDeps([]))),"v-749ad71a":h(()=>s(()=>import("./blackhole.html-BCTuFe4v.js"),__vite__mapDeps([]))),"v-6d39b970":h(()=>s(()=>import("./dns.html-D-rYzT__.js"),__vite__mapDeps([]))),"v-d76e893a":h(()=>s(()=>import("./freedom.html-CBf9uuEF.js"),__vite__mapDeps([]))),"v-c6b4b59e":h(()=>s(()=>import("./http.html-DXeEJWXm.js"),__vite__mapDeps([]))),"v-41ec0e0e":h(()=>s(()=>import("./loopback.html-BvfOuAZH.js"),__vite__mapDeps([]))),"v-7b293e4a":h(()=>s(()=>import("./shadowsocks.html-CO6uYWSO.js"),__vite__mapDeps([]))),"v-15f5452a":h(()=>s(()=>import("./socks.html-vsa94d6J.js"),__vite__mapDeps([]))),"v-5797bdb3":h(()=>s(()=>import("./trojan.html-a1Coa5-Z.js"),__vite__mapDeps([]))),"v-a60f016c":h(()=>s(()=>import("./vless.html-XJTROLo0.js"),__vite__mapDeps([]))),"v-413cee4b":h(()=>s(()=>import("./vmess.html-CWgbIYSO.js"),__vite__mapDeps([]))),"v-208ca3b9":h(()=>s(()=>import("./wireguard.html-DORXKtWu.js"),__vite__mapDeps([]))),"v-775db7b1":h(()=>s(()=>import("./domainsocket.html-Dl3H8vlJ.js"),__vite__mapDeps([]))),"v-2877542a":h(()=>s(()=>import("./grpc.html-DnIgTPpb.js"),__vite__mapDeps([]))),"v-03a28284":h(()=>s(()=>import("./h2.html-DCbNjdYm.js"),__vite__mapDeps([]))),"v-04158536":h(()=>s(()=>import("./httpupgrade.html-CEqqB19n.js"),__vite__mapDeps([]))),"v-3167b1dd":h(()=>s(()=>import("./mkcp.html-BYbEm1gj.js"),__vite__mapDeps([]))),"v-8f08dbec":h(()=>s(()=>import("./quic.html-BSX-VjGs.js"),__vite__mapDeps([]))),"v-eeea2fb0":h(()=>s(()=>import("./splithttp.html-6TiHvgAh.js"),__vite__mapDeps([]))),"v-33b1b709":h(()=>s(()=>import("./tcp.html-vEvGx-7r.js"),__vite__mapDeps([]))),"v-1ff57bba":h(()=>s(()=>import("./websocket.html-DzGXVtRP.js"),__vite__mapDeps([]))),"v-6a9e8054":h(()=>s(()=>import("./compile.html-Bm6vm5gG.js"),__vite__mapDeps([]))),"v-95e3eaea":h(()=>s(()=>import("./design.html-BTffej_N.js"),__vite__mapDeps([]))),"v-61e7eea6":h(()=>s(()=>import("./guide.html-BjshCdoe.js"),__vite__mapDeps([]))),"v-6e6c37e6":h(()=>s(()=>import("./mkcp.html-BC2K7D4N.js"),__vite__mapDeps([]))),"v-13168a21":h(()=>s(()=>import("./muxcool.html-Ch_u4leD.js"),__vite__mapDeps([]))),"v-5c48c82b":h(()=>s(()=>import("./vless.html-CxxO1Anm.js"),__vite__mapDeps([]))),"v-1ee591a8":h(()=>s(()=>import("./vmess.html-CzAuOHQq.js"),__vite__mapDeps([]))),"v-3f09dcfa":h(()=>s(()=>import("./index.html-B-Zn3LDM.js"),__vite__mapDeps([]))),"v-fb444906":h(()=>s(()=>import("./ch01-preface.html-C6vuCTiJ.js"),__vite__mapDeps([]))),"v-075f3ae5":h(()=>s(()=>import("./ch02-preparation.html-3rYGUPF0.js"),__vite__mapDeps([]))),"v-726d0633":h(()=>s(()=>import("./ch03-ssh.html-10pGoOUk.js"),__vite__mapDeps([]))),"v-430c6ab8":h(()=>s(()=>import("./ch04-security.html-DyDK2hA6.js"),__vite__mapDeps([]))),"v-717c6376":h(()=>s(()=>import("./ch05-webpage.html-3v0I9fWw.js"),__vite__mapDeps([]))),"v-278039be":h(()=>s(()=>import("./ch06-certificates.html-BCM-NNIg.js"),__vite__mapDeps([]))),"v-a0c7f88e":h(()=>s(()=>import("./ch07-xray-server.html-xXsQBQ03.js"),__vite__mapDeps([]))),"v-86586ca2":h(()=>s(()=>import("./ch08-xray-clients.html-Bqf0blkP.js"),__vite__mapDeps([]))),"v-3eb62514":h(()=>s(()=>import("./ch09-appendix.html-DHpTAQmp.js"),__vite__mapDeps([]))),"v-3f09dcbc":h(()=>s(()=>import("./index.html-CH7QpluO.js"),__vite__mapDeps([]))),"v-b21a2a20":h(()=>s(()=>import("./fallbacks-lv1.html-BCtwtJCw.js"),__vite__mapDeps([]))),"v-da623318":h(()=>s(()=>import("./fallbacks-with-sni.html-iAcmmVov.js"),__vite__mapDeps([]))),"v-fdd722ac":h(()=>s(()=>import("./routing-lv1-part1.html-Bwge_E9k.js"),__vite__mapDeps([]))),"v-fa6d716e":h(()=>s(()=>import("./routing-lv1-part2.html-CfufGIyP.js"),__vite__mapDeps([]))),"v-2f29e106":h(()=>s(()=>import("./work.html-DMYsHmaw.js"),__vite__mapDeps([]))),"v-3f09dc7e":h(()=>s(()=>import("./index.html-Bt40bz30.js"),__vite__mapDeps([]))),"v-1c17916e":h(()=>s(()=>import("./iptables_gid.html-DlCxBcK6.js"),__vite__mapDeps([]))),"v-a001cfa6":h(()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-KJNaWU2X.js"),__vite__mapDeps([]))),"v-46333b48":h(()=>s(()=>import("./redirect.html-ZgxF37Mu.js"),__vite__mapDeps([]))),"v-338bc63e":h(()=>s(()=>import("./tproxy.html-DjX-7RSF.js"),__vite__mapDeps([]))),"v-d68f7d58":h(()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-D9QvwytN.js"),__vite__mapDeps([]))),"v-e533e2c6":h(()=>s(()=>import("./traffic_stats.html-DmKVUaJl.js"),__vite__mapDeps([]))),"v-1e465ab0":h(()=>s(()=>import("./warp.html-9hKZfp2I.js"),__vite__mapDeps([]))),"v-1080fb37":h(()=>s(()=>import("./news.html-B87U8xn2.js"),__vite__mapDeps([]))),"v-317fc580":h(()=>s(()=>import("./index.html-Bn9iOydn.js"),__vite__mapDeps([]))),"v-45144c7f":h(()=>s(()=>import("./api.html-Dt8W2IKn.js"),__vite__mapDeps([]))),"v-23fbd2d0":h(()=>s(()=>import("./dns.html-Db5UBVvD.js"),__vite__mapDeps([]))),"v-2b7ec525":h(()=>s(()=>import("./fakedns.html-Dh-VkFFO.js"),__vite__mapDeps([]))),"v-5ab92300":h(()=>s(()=>import("./inbound.html-BZUQiKQt.js"),__vite__mapDeps([]))),"v-f91d64d6":h(()=>s(()=>import("./log.html-AttB6lyK.js"),__vite__mapDeps([]))),"v-d705f114":h(()=>s(()=>import("./metrics.html-BhYJwMrZ.js"),__vite__mapDeps([]))),"v-268cd669":h(()=>s(()=>import("./outbound.html-CGmYQFef.js"),__vite__mapDeps([]))),"v-4492d567":h(()=>s(()=>import("./policy.html-DiLfrWDT.js"),__vite__mapDeps([]))),"v-0d0e1e92":h(()=>s(()=>import("./reverse.html-WbzNOTcU.js"),__vite__mapDeps([]))),"v-4bbe1d5a":h(()=>s(()=>import("./routing.html-B34g5Zqk.js"),__vite__mapDeps([]))),"v-16426d1a":h(()=>s(()=>import("./stats.html-MnnldZmL.js"),__vite__mapDeps([]))),"v-5de780d0":h(()=>s(()=>import("./transport.html-COHavdZy.js"),__vite__mapDeps([]))),"v-f88d343e":h(()=>s(()=>import("./index.html-COWQPvSj.js"),__vite__mapDeps([]))),"v-38d56a07":h(()=>s(()=>import("./index.html-BNTb1uEP.js"),__vite__mapDeps([]))),"v-4d046016":h(()=>s(()=>import("./command.html-DiZIQO57.js"),__vite__mapDeps([]))),"v-22b35270":h(()=>s(()=>import("./config.html-D5Tr_5W7.js"),__vite__mapDeps([]))),"v-30bd7c12":h(()=>s(()=>import("./document.html-uNBJD12O.js"),__vite__mapDeps([]))),"v-439608b6":h(()=>s(()=>import("./install.html-nEQK2zvn.js"),__vite__mapDeps([]))),"v-408e88d1":h(()=>s(()=>import("./news.html-23-ihBAh.js"),__vite__mapDeps([]))),"v-b1cce5cc":h(()=>s(()=>import("./index.html-DyQaOch3.js"),__vite__mapDeps([]))),"v-7521da19":h(()=>s(()=>import("./api.html-LpVUq3p6.js"),__vite__mapDeps([]))),"v-5409606a":h(()=>s(()=>import("./dns.html-CfUMjcx_.js"),__vite__mapDeps([]))),"v-5877f5bf":h(()=>s(()=>import("./fakedns.html-CZTe-tiD.js"),__vite__mapDeps([]))),"v-00c6c1cc":h(()=>s(()=>import("./inbound.html-CqfgrN_A.js"),__vite__mapDeps([]))),"v-990249a2":h(()=>s(()=>import("./log.html-cALz2gHA.js"),__vite__mapDeps([]))),"v-7d138fe0":h(()=>s(()=>import("./metrics.html-Cd9LVZWS.js"),__vite__mapDeps([]))),"v-11e9cb19":h(()=>s(()=>import("./observatory.html-BzG-DGQ7.js"),__vite__mapDeps([]))),"v-ce8c8de2":h(()=>s(()=>import("./outbound.html-Bztbl0lH.js"),__vite__mapDeps([]))),"v-3dc4298d":h(()=>s(()=>import("./policy.html-B9TBd0jy.js"),__vite__mapDeps([]))),"v-26722151":h(()=>s(()=>import("./reverse.html-BNqd15YN.js"),__vite__mapDeps([]))),"v-071a21ed":h(()=>s(()=>import("./routing.html-DYlVNKuL.js"),__vite__mapDeps([]))),"v-7922fc34":h(()=>s(()=>import("./stats.html-DsefVpMC.js"),__vite__mapDeps([]))),"v-3156f2ea":h(()=>s(()=>import("./transport.html-CUhGNa4n.js"),__vite__mapDeps([]))),"v-40ee4e87":h(()=>s(()=>import("./index.html-Cskgq1zk.js"),__vite__mapDeps([]))),"v-a1c899be":h(()=>s(()=>import("./index.html-Cy2gOIhe.js"),__vite__mapDeps([]))),"v-a6257be2":h(()=>s(()=>import("./command.html-C5O9QrFP.js"),__vite__mapDeps([]))),"v-d63f95d4":h(()=>s(()=>import("./config.html-DXicnlDr.js"),__vite__mapDeps([]))),"v-fbbfd9c6":h(()=>s(()=>import("./document.html-BgS7tOmx.js"),__vite__mapDeps([]))),"v-9cb72482":h(()=>s(()=>import("./install.html-CX7I48Il.js"),__vite__mapDeps([]))),"v-51a51d87":h(()=>s(()=>import("./transparent_proxy.html-DDjaWLfB.js"),__vite__mapDeps([]))),"v-76b9a0f3":h(()=>s(()=>import("./browser_dialer.html-DTufXirY.js"),__vite__mapDeps([]))),"v-565dbfc4":h(()=>s(()=>import("./env.html-5Sl2lv4f.js"),__vite__mapDeps([]))),"v-0fbd1336":h(()=>s(()=>import("./fallback.html-O3X9XOSg.js"),__vite__mapDeps([]))),"v-a0627812":h(()=>s(()=>import("./multiple.html-D2THR0Xm.js"),__vite__mapDeps([]))),"v-d190d938":h(()=>s(()=>import("./xtls.html-BljC82lz.js"),__vite__mapDeps([]))),"v-72afc2d2":h(()=>s(()=>import("./dokodemo.html-BeyAN9oF.js"),__vite__mapDeps([]))),"v-773d731c":h(()=>s(()=>import("./http.html-uCWbp3V-.js"),__vite__mapDeps([]))),"v-f555fc02":h(()=>s(()=>import("./shadowsocks.html-D9uClIut.js"),__vite__mapDeps([]))),"v-e35196c2":h(()=>s(()=>import("./socks.html-DRkc0qRu.js"),__vite__mapDeps([]))),"v-29188644":h(()=>s(()=>import("./trojan.html-C2jCtoPN.js"),__vite__mapDeps([]))),"v-255a6ebf":h(()=>s(()=>import("./vless.html-BM3ph8gg.js"),__vite__mapDeps([]))),"v-8cc24480":h(()=>s(()=>import("./vmess.html-dZZBrBA9.js"),__vite__mapDeps([]))),"v-64e47ef4":h(()=>s(()=>import("./blackhole.html-BqrDbtFw.js"),__vite__mapDeps([]))),"v-e979b848":h(()=>s(()=>import("./dns.html-Dc7rS11a.js"),__vite__mapDeps([]))),"v-617f0fcf":h(()=>s(()=>import("./freedom.html-CxIu6tCF.js"),__vite__mapDeps([]))),"v-3fc98845":h(()=>s(()=>import("./http.html-z9-pCapv.js"),__vite__mapDeps([]))),"v-1b804722":h(()=>s(()=>import("./loopback.html-BA_UAuXs.js"),__vite__mapDeps([]))),"v-63077cb6":h(()=>s(()=>import("./shadowsocks.html-6NbUGUcS.js"),__vite__mapDeps([]))),"v-516476d4":h(()=>s(()=>import("./socks.html-ByoOjVOD.js"),__vite__mapDeps([]))),"v-7d61a872":h(()=>s(()=>import("./trojan.html-CSDiydOe.js"),__vite__mapDeps([]))),"v-6e50feb6":h(()=>s(()=>import("./vless.html-C6f9K51N.js"),__vite__mapDeps([]))),"v-02956db7":h(()=>s(()=>import("./vmess.html-Ds4NV6pk.js"),__vite__mapDeps([]))),"v-797f8d25":h(()=>s(()=>import("./wireguard.html-WCdNFPZm.js"),__vite__mapDeps([]))),"v-3eb3e9c6":h(()=>s(()=>import("./domainsocket.html-CudQIOhr.js"),__vite__mapDeps([]))),"v-2c6058d4":h(()=>s(()=>import("./grpc.html-3wMb5fVh.js"),__vite__mapDeps([]))),"v-1c38292a":h(()=>s(()=>import("./h2.html-BoytWKP0.js"),__vite__mapDeps([]))),"v-17ff144a":h(()=>s(()=>import("./httpupgrade.html-BraFT-Ya.js"),__vite__mapDeps([]))),"v-1a7f9d6e":h(()=>s(()=>import("./mkcp.html-Clzx5P9b.js"),__vite__mapDeps([]))),"v-79d41176":h(()=>s(()=>import("./quic.html-C8pXs3js.js"),__vite__mapDeps([]))),"v-4df52c3c":h(()=>s(()=>import("./splithttp.html-AYHmdotS.js"),__vite__mapDeps([]))),"v-5254cbc6":h(()=>s(()=>import("./tcp.html-C8HjBlLu.js"),__vite__mapDeps([]))),"v-9520f392":h(()=>s(()=>import("./websocket.html-DJjmBrAj.js"),__vite__mapDeps([]))),"v-b7760e2c":h(()=>s(()=>import("./compile.html-Csfc2z7k.js"),__vite__mapDeps([]))),"v-fb774212":h(()=>s(()=>import("./design.html-Buz8frIk.js"),__vite__mapDeps([]))),"v-38c376c1":h(()=>s(()=>import("./guide.html-CBLCKraa.js"),__vite__mapDeps([]))),"v-21bccd79":h(()=>s(()=>import("./mkcp.html-DpdBDDHy.js"),__vite__mapDeps([]))),"v-27001935":h(()=>s(()=>import("./muxcool.html-DyQfxg_9.js"),__vite__mapDeps([]))),"v-21b30c3f":h(()=>s(()=>import("./vless.html-BWup8Xzq.js"),__vite__mapDeps([]))),"v-94110980":h(()=>s(()=>import("./vmess.html-Blynvi6-.js"),__vite__mapDeps([]))),"v-789ba7ef":h(()=>s(()=>import("./index.html-D3N0ZGw7.js"),__vite__mapDeps([]))),"v-d3712ade":h(()=>s(()=>import("./ch01-preface.html-Bts5JwT1.js"),__vite__mapDeps([]))),"v-41f9c00e":h(()=>s(()=>import("./ch02-preparation.html-BuxrUsmj.js"),__vite__mapDeps([]))),"v-4c013f47":h(()=>s(()=>import("./ch03-ssh.html-Bbgd91VB.js"),__vite__mapDeps([]))),"v-a75683b8":h(()=>s(()=>import("./ch04-security.html-CRFoFiSw.js"),__vite__mapDeps([]))),"v-f5341aec":h(()=>s(()=>import("./ch05-webpage.html-XNRjbxse.js"),__vite__mapDeps([]))),"v-4458f72a":h(()=>s(()=>import("./ch06-certificates.html-Cjl3-nTJ.js"),__vite__mapDeps([]))),"v-f1802e66":h(()=>s(()=>import("./ch07-xray-server.html-DWmdh7MW.js"),__vite__mapDeps([]))),"v-4ca6f1ca":h(()=>s(()=>import("./ch08-xray-clients.html-BNAUVuV_.js"),__vite__mapDeps([]))),"v-b0030f00":h(()=>s(()=>import("./ch09-appendix.html-BP917XpD.js"),__vite__mapDeps([]))),"v-789ba80e":h(()=>s(()=>import("./index.html-DLfjpS8M.js"),__vite__mapDeps([]))),"v-103b3e5c":h(()=>s(()=>import("./fallbacks-lv1.html-CI6CRNYF.js"),__vite__mapDeps([]))),"v-110dd688":h(()=>s(()=>import("./fallbacks-with-sni.html-B0wSUJmq.js"),__vite__mapDeps([]))),"v-c425a7d4":h(()=>s(()=>import("./routing-lv1-part1.html-DxoI7gBO.js"),__vite__mapDeps([]))),"v-c0bbf696":h(()=>s(()=>import("./routing-lv1-part2.html-n2aETtQH.js"),__vite__mapDeps([]))),"v-5b6477cc":h(()=>s(()=>import("./work.html-DkQ-NI9U.js"),__vite__mapDeps([]))),"v-789ba82d":h(()=>s(()=>import("./index.html-B3mfyWQt.js"),__vite__mapDeps([]))),"v-05ddc65d":h(()=>s(()=>import("./iptables_gid.html-KGEztY8A.js"),__vite__mapDeps([]))),"v-474afe99":h(()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-CTP6KXYR.js"),__vite__mapDeps([]))),"v-930ac920":h(()=>s(()=>import("./redirect.html-DdM9qz1d.js"),__vite__mapDeps([]))),"v-c579975c":h(()=>s(()=>import("./tproxy.html-CfIjaip9.js"),__vite__mapDeps([]))),"v-7efb7c68":h(()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-QYKhgI6r.js"),__vite__mapDeps([]))),"v-12a33bee":h(()=>s(()=>import("./traffic_stats.html-DamLfymb.js"),__vite__mapDeps([]))),"v-7d2b8478":h(()=>s(()=>import("./warp.html-CO5RmDTS.js"),__vite__mapDeps([]))),"v-1cfb44e6":h(()=>s(()=>import("./browser_dialer.html-B00Yg-45.js"),__vite__mapDeps([]))),"v-6a3f8078":h(()=>s(()=>import("./env.html-BaUecgO2.js"),__vite__mapDeps([]))),"v-74f22e7f":h(()=>s(()=>import("./fallback.html-BuLRpbj4.js"),__vite__mapDeps([]))),"v-2c9f7c11":h(()=>s(()=>import("./multiple.html-DZg36_LG.js"),__vite__mapDeps([]))),"v-630c687e":h(()=>s(()=>import("./xtls.html-0Synm2Bl.js"),__vite__mapDeps([]))),"v-20ff0a28":h(()=>s(()=>import("./dokodemo.html-BdfcwHNb.js"),__vite__mapDeps([]))),"v-43124836":h(()=>s(()=>import("./http.html-B_cAur_J.js"),__vite__mapDeps([]))),"v-6a351ba5":h(()=>s(()=>import("./shadowsocks.html-RjOSr0jT.js"),__vite__mapDeps([]))),"v-3d1d02c5":h(()=>s(()=>import("./socks.html-D7ljHe8-.js"),__vite__mapDeps([]))),"v-1567b378":h(()=>s(()=>import("./trojan.html-WsfP1d7V.js"),__vite__mapDeps([]))),"v-57bf8636":h(()=>s(()=>import("./vless.html-B7O7xjrb.js"),__vite__mapDeps([]))),"v-6864abe6":h(()=>s(()=>import("./vmess.html-gu8tRDOO.js"),__vite__mapDeps([]))),"v-5910da20":h(()=>s(()=>import("./blackhole.html-CBPzXtbg.js"),__vite__mapDeps([]))),"v-5717f8f6":h(()=>s(()=>import("./dns.html-fTI6Udl3.js"),__vite__mapDeps([]))),"v-4360702e":h(()=>s(()=>import("./freedom.html-D6jTnnzE.js"),__vite__mapDeps([]))),"v-22e1532a":h(()=>s(()=>import("./http.html-BR_9tg5w.js"),__vite__mapDeps([]))),"v-38c69248":h(()=>s(()=>import("./loopback.html-CsIs91x3.js"),__vite__mapDeps([]))),"v-1a2a97d0":h(()=>s(()=>import("./shadowsocks.html-D1p_O6W-.js"),__vite__mapDeps([]))),"v-0141bb30":h(()=>s(()=>import("./socks.html-CBuC3RpY.js"),__vite__mapDeps([]))),"v-544bef26":h(()=>s(()=>import("./trojan.html-ZC1LUXUu.js"),__vite__mapDeps([]))),"v-cf761560":h(()=>s(()=>import("./vless.html-gWexYZDk.js"),__vite__mapDeps([]))),"v-2c896451":h(()=>s(()=>import("./vmess.html-CeLsjjaY.js"),__vite__mapDeps([]))),"v-0502a6bf":h(()=>s(()=>import("./wireguard.html-CW0kotGE.js"),__vite__mapDeps([]))),"v-5b6ec7b7":h(()=>s(()=>import("./domainsocket.html-BAuPukib.js"),__vite__mapDeps([]))),"v-13c3ca30":h(()=>s(()=>import("./grpc.html-BpDUzsty.js"),__vite__mapDeps([]))),"v-2fe60378":h(()=>s(()=>import("./h2.html-llZ-kVKl.js"),__vite__mapDeps([]))),"v-453f5c70":h(()=>s(()=>import("./httpupgrade.html-D3FZSi1K.js"),__vite__mapDeps([]))),"v-1cb427e3":h(()=>s(()=>import("./mkcp.html-gKNEMwS8.js"),__vite__mapDeps([]))),"v-b86fefe0":h(()=>s(()=>import("./quic.html-C3baIL5C.js"),__vite__mapDeps([]))),"v-32d545e2":h(()=>s(()=>import("./splithttp.html-BazFP1k9.js"),__vite__mapDeps([]))),"v-f4c92f7a":h(()=>s(()=>import("./tcp.html-BnHzgywc.js"),__vite__mapDeps([]))),"v-cb60c046":h(()=>s(()=>import("./websocket.html-w8ndqht7.js"),__vite__mapDeps([]))),"v-7ce977e0":h(()=>s(()=>import("./compile.html-D0_Ut9wS.js"),__vite__mapDeps([]))),"v-01d5d1de":h(()=>s(()=>import("./design.html-DhXmb5CJ.js"),__vite__mapDeps([]))),"v-4d4e5367":h(()=>s(()=>import("./guide.html-DIzxSc4p.js"),__vite__mapDeps([]))),"v-a58031da":h(()=>s(()=>import("./mkcp.html-D6gGU4SN.js"),__vite__mapDeps([]))),"v-5440615b":h(()=>s(()=>import("./muxcool.html-hxuFgme0.js"),__vite__mapDeps([]))),"v-069325e5":h(()=>s(()=>import("./vless.html-D2jxsPHC.js"),__vite__mapDeps([]))),"v-ca50d634":h(()=>s(()=>import("./vmess.html-BtwOPh9t.js"),__vite__mapDeps([]))),"v-490791ee":h(()=>s(()=>import("./index.html-BghSFULx.js"),__vite__mapDeps([]))),"v-78f09a92":h(()=>s(()=>import("./ch01-preface.html-CVJyR7B9.js"),__vite__mapDeps([]))),"v-64f6e51f":h(()=>s(()=>import("./ch02-preparation.html-Bux35H5q.js"),__vite__mapDeps([]))),"v-69478a6d":h(()=>s(()=>import("./ch03-ssh.html-9CSgBxsO.js"),__vite__mapDeps([]))),"v-271d7abe":h(()=>s(()=>import("./ch04-security.html-CR6Uh8v_.js"),__vite__mapDeps([]))),"v-9ab38aa0":h(()=>s(()=>import("./ch05-webpage.html-D09gDc8i.js"),__vite__mapDeps([]))),"v-7cddd6c4":h(()=>s(()=>import("./ch06-certificates.html-DQoStl8T.js"),__vite__mapDeps([]))),"v-0d33adf3":h(()=>s(()=>import("./ch07-xray-server.html-BqO-iTQU.js"),__vite__mapDeps([]))),"v-123166b5":h(()=>s(()=>import("./ch08-xray-clients.html-Bcxw8xnI.js"),__vite__mapDeps([]))),"v-22c7351a":h(()=>s(()=>import("./ch09-appendix.html-cJZrrwi6.js"),__vite__mapDeps([]))),"v-490791b0":h(()=>s(()=>import("./index.html-DYkoE7_u.js"),__vite__mapDeps([]))),"v-e9f80a14":h(()=>s(()=>import("./fallbacks-lv1.html-DYToMiS6.js"),__vite__mapDeps([]))),"v-2db62ba4":h(()=>s(()=>import("./fallbacks-with-sni.html-B3snUr7L.js"),__vite__mapDeps([]))),"v-531be8a0":h(()=>s(()=>import("./routing-lv1-part1.html-cn16P49Z.js"),__vite__mapDeps([]))),"v-4fb23762":h(()=>s(()=>import("./routing-lv1-part2.html-D-nULKCp.js"),__vite__mapDeps([]))),"v-fdd8db80":h(()=>s(()=>import("./work.html-hEheaKUD.js"),__vite__mapDeps([]))),"v-49079172":h(()=>s(()=>import("./index.html-Bf7-nv__.js"),__vite__mapDeps([]))),"v-331e0e83":h(()=>s(()=>import("./iptables_gid.html-D1piuJf5.js"),__vite__mapDeps([]))),"v-7418a5b3":h(()=>s(()=>import("./nginx_or_haproxy_tls_tunnel.html-CBNtMx0V.js"),__vite__mapDeps([]))),"v-587e32d4":h(()=>s(()=>import("./redirect.html-u-FkUyZi.js"),__vite__mapDeps([]))),"v-9c63de10":h(()=>s(()=>import("./tproxy.html-DWkdG7BH.js"),__vite__mapDeps([]))),"v-a4c782e4":h(()=>s(()=>import("./tproxy_ipv4_and_ipv6.html-Cd8pbG7a.js"),__vite__mapDeps([]))),"v-71771ea3":h(()=>s(()=>import("./traffic_stats.html-Ci6G_ygz.js"),__vite__mapDeps([]))),"v-70300bea":h(()=>s(()=>import("./warp.html-Bzz-XxvP.js"),__vite__mapDeps([]))),"v-7689d7f3":h(()=>s(()=>import("./transparent_proxy.html-sYVo5ZWT.js"),__vite__mapDeps([]))),"v-39b3c50d":h(()=>s(()=>import("./transparent_proxy.html-Bml0Br0H.js"),__vite__mapDeps([]))),"v-3706649a":h(()=>s(()=>import("./404.html-C7hQR_kQ.js"),__vite__mapDeps([]))),"v-5c8e777f":h(()=>s(()=>import("./observatory.html-CPlTxJvy.js"),__vite__mapDeps([])))};var Hu=Symbol(""),ms=Symbol(""),Mu=In({key:"",path:"",title:"",lang:"",frontmatter:{},headers:[]}),Gt=()=>{const e=Te(ms);if(!e)throw new Error("pageData() is called without provider.");return e},bs=Symbol(""),gt=()=>{const e=Te(bs);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},ks=Symbol(""),$u=()=>{const e=Te(ks);if(!e)throw new Error("usePageHead() is called without provider.");return e},Bu=Symbol(""),Es=Symbol(""),Wu=()=>{const e=Te(Es);if(!e)throw new Error("usePageLang() is called without provider.");return e},ys=Symbol(""),Uu=()=>{const e=Te(ys);if(!e)throw new Error("usePageLayout() is called without provider.");return e},zu=pe(Iu),Mi=Symbol(""),Ql=()=>{const e=Te(Mi);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},ll=pe(Du),xs=()=>ll,Ls=Symbol(""),$i=()=>{const e=Te(Ls);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},Xu=Symbol(""),Ku="Layout",qu="NotFound",vt=Ul({resolveLayouts:e=>e.reduce((t,l)=>({...t,...l.layouts}),{}),resolvePageData:async e=>{const t=zu.value[e];return await(t==null?void 0:t())??Mu},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,l)=>{const n=it(t.description)?t.description:l.description,i=[...Array.isArray(t.head)?t.head:[],...l.head,["title",{},e],["meta",{name:"description",content:n}]];return Vu(i)},resolvePageHeadTitle:(e,t)=>[e.title,t.title].filter(l=>!!l).join(" | "),resolvePageLang:(e,t)=>e.lang||t.lang||"en-US",resolvePageLayout:(e,t)=>{let l;if(e.path){const n=e.frontmatter.layout;it(n)?l=n:l=Ku}else l=qu;return t[l]},resolveRouteLocale:(e,t)=>ps(e,t),resolveSiteLocaleData:(e,t)=>{var l;return{...e,...e.locales[t],head:[...((l=e.locales[t])==null?void 0:l.head)??[],...e.head??[]]}}}),Bi=_e({name:"ClientOnly",setup(e,t){const l=pe(!1);return We(()=>{l.value=!0}),()=>{var n,i;return l.value?(i=(n=t.slots).default)==null?void 0:i.call(n):null}}}),Gu=_e({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=Gt(),l=C(()=>gs[e.pageKey||t.value.key]);return()=>l.value?he(l.value):he("div","404 Not Found")}}),Et=(e={})=>e,Wi=e=>Yl(e)?e:`/${fs(e)}`;function Ts(e,t,l){var n,i,r;t===void 0&&(t=50),l===void 0&&(l={});var o=(n=l.isImmediate)!=null&&n,c=(i=l.callback)!=null&&i,a=l.maxWait,u=Date.now(),d=[];function v(){if(a!==void 0){var g=Date.now()-u;if(g+t>=a)return a-g}return t}var _=function(){var g=[].slice.call(arguments),m=this;return new Promise(function(x,A){var D=o&&r===void 0;if(r!==void 0&&clearTimeout(r),r=setTimeout(function(){if(r=void 0,u=Date.now(),!o){var b=e.apply(m,g);c&&c(b),d.forEach(function(y){return(0,y.resolve)(b)}),d=[]}},v()),D){var O=e.apply(m,g);return c&&c(O),x(O)}d.push({resolve:x,reject:A})})};return _.cancel=function(g){r!==void 0&&clearTimeout(r),d.forEach(function(m){return(0,m.reject)(g)}),d=[]},_}/*!
   * vue-router v4.3.2
   * (c) 2024 Eduardo San Martin Morote
   * @license MIT
@@ -7,7 +7,7 @@ Expects a CSS selector, a Node element, a NodeList or an array.
 See: https://github.com/francoischalifour/medium-zoom`)}},vh=function(t){var l=document.createElement("div");return l.classList.add("medium-zoom-overlay"),l.style.background=t,l},_h=function(t){var l=t.getBoundingClientRect(),n=l.top,i=l.left,r=l.width,o=l.height,c=t.cloneNode(),a=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,u=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;return c.removeAttribute("id"),c.style.position="absolute",c.style.top=n+a+"px",c.style.left=i+u+"px",c.style.width=r+"px",c.style.height=o+"px",c.style.transform="",c},el=function(t,l){var n=Mt({bubbles:!1,cancelable:!1,detail:void 0},l);if(typeof window.CustomEvent=="function")return new CustomEvent(t,n);var i=document.createEvent("CustomEvent");return i.initCustomEvent(t,n.bubbles,n.cancelable,n.detail),i},fh=function e(t){var l=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=window.Promise||function(L){function V(){}L(V,V)},i=function(L){var V=L.target;if(V===K){m();return}b.indexOf(V)!==-1&&x({target:V})},r=function(){if(!(H||!E.original)){var L=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(G-L)>N.scrollOffset&&setTimeout(m,150)}},o=function(L){var V=L.key||L.keyCode;(V==="Escape"||V==="Esc"||V===27)&&m()},c=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},V=L;if(L.background&&(K.style.background=L.background),L.container&&L.container instanceof Object&&(V.container=Mt({},N.container,L.container)),L.template){var le=_n(L.template)?L.template:document.querySelector(L.template);V.template=le}return N=Mt({},N,V),b.forEach(function(ne){ne.dispatchEvent(el("medium-zoom:update",{detail:{zoom:w}}))}),w},a=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return e(Mt({},N,L))},u=function(){for(var L=arguments.length,V=Array(L),le=0;le0?V.reduce(function(S,Q){return[].concat(S,io(Q))},[]):b;return ne.forEach(function(S){S.classList.remove("medium-zoom-image"),S.dispatchEvent(el("medium-zoom:detach",{detail:{zoom:w}}))}),b=b.filter(function(S){return ne.indexOf(S)===-1}),w},v=function(L,V){var le=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return b.forEach(function(ne){ne.addEventListener("medium-zoom:"+L,V,le)}),y.push({type:"medium-zoom:"+L,listener:V,options:le}),w},_=function(L,V){var le=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return b.forEach(function(ne){ne.removeEventListener("medium-zoom:"+L,V,le)}),y=y.filter(function(ne){return!(ne.type==="medium-zoom:"+L&&ne.listener.toString()===V.toString())}),w},g=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},V=L.target,le=function(){var S={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},Q=void 0,X=void 0;if(N.container)if(N.container instanceof Object)S=Mt({},S,N.container),Q=S.width-S.left-S.right-N.margin*2,X=S.height-S.top-S.bottom-N.margin*2;else{var De=_n(N.container)?N.container:document.querySelector(N.container),Se=De.getBoundingClientRect(),Ue=Se.width,He=Se.height,yt=Se.left,xt=Se.top;S=Mt({},S,{width:Ue,height:He,left:yt,top:xt})}Q=Q||S.width-N.margin*2,X=X||S.height-N.margin*2;var ot=E.zoomedHd||E.original,je=no(ot)?Q:ot.naturalWidth||Q,P=no(ot)?X:ot.naturalHeight||X,U=ot.getBoundingClientRect(),M=U.top,Y=U.left,ae=U.width,f=U.height,p=Math.min(Math.max(ae,je),Q)/ae,k=Math.min(Math.max(f,P),X)/f,T=Math.min(p,k),R=(-Y+(Q-ae)/2+N.margin+S.left)/T,I=(-M+(X-f)/2+N.margin+S.top)/T,B="scale("+T+") translate3d("+R+"px, "+I+"px, 0)";E.zoomed.style.transform=B,E.zoomedHd&&(E.zoomedHd.style.transform=B)};return new n(function(ne){if(V&&b.indexOf(V)===-1){ne(w);return}var S=function Ue(){H=!1,E.zoomed.removeEventListener("transitionend",Ue),E.original.dispatchEvent(el("medium-zoom:opened",{detail:{zoom:w}})),ne(w)};if(E.zoomed){ne(w);return}if(V)E.original=V;else if(b.length>0){var Q=b;E.original=Q[0]}else{ne(w);return}if(E.original.dispatchEvent(el("medium-zoom:open",{detail:{zoom:w}})),G=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,H=!0,E.zoomed=_h(E.original),document.body.appendChild(K),N.template){var X=_n(N.template)?N.template:document.querySelector(N.template);E.template=document.createElement("div"),E.template.appendChild(X.content.cloneNode(!0)),document.body.appendChild(E.template)}if(E.original.parentElement&&E.original.parentElement.tagName==="PICTURE"&&E.original.currentSrc&&(E.zoomed.src=E.original.currentSrc),document.body.appendChild(E.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),E.original.classList.add("medium-zoom-image--hidden"),E.zoomed.classList.add("medium-zoom-image--opened"),E.zoomed.addEventListener("click",m),E.zoomed.addEventListener("transitionend",S),E.original.getAttribute("data-zoom-src")){E.zoomedHd=E.zoomed.cloneNode(),E.zoomedHd.removeAttribute("srcset"),E.zoomedHd.removeAttribute("sizes"),E.zoomedHd.removeAttribute("loading"),E.zoomedHd.src=E.zoomed.getAttribute("data-zoom-src"),E.zoomedHd.onerror=function(){clearInterval(De),console.warn("Unable to reach the zoom image target "+E.zoomedHd.src),E.zoomedHd=null,le()};var De=setInterval(function(){E.zoomedHd.complete&&(clearInterval(De),E.zoomedHd.classList.add("medium-zoom-image--opened"),E.zoomedHd.addEventListener("click",m),document.body.appendChild(E.zoomedHd),le())},10)}else if(E.original.hasAttribute("srcset")){E.zoomedHd=E.zoomed.cloneNode(),E.zoomedHd.removeAttribute("sizes"),E.zoomedHd.removeAttribute("loading");var Se=E.zoomedHd.addEventListener("load",function(){E.zoomedHd.removeEventListener("load",Se),E.zoomedHd.classList.add("medium-zoom-image--opened"),E.zoomedHd.addEventListener("click",m),document.body.appendChild(E.zoomedHd),le()})}else le()})},m=function(){return new n(function(L){if(H||!E.original){L(w);return}var V=function le(){E.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(E.zoomed),E.zoomedHd&&document.body.removeChild(E.zoomedHd),document.body.removeChild(K),E.zoomed.classList.remove("medium-zoom-image--opened"),E.template&&document.body.removeChild(E.template),H=!1,E.zoomed.removeEventListener("transitionend",le),E.original.dispatchEvent(el("medium-zoom:closed",{detail:{zoom:w}})),E.original=null,E.zoomed=null,E.zoomedHd=null,E.template=null,L(w)};H=!0,document.body.classList.remove("medium-zoom--opened"),E.zoomed.style.transform="",E.zoomedHd&&(E.zoomedHd.style.transform=""),E.template&&(E.template.style.transition="opacity 150ms",E.template.style.opacity=0),E.original.dispatchEvent(el("medium-zoom:close",{detail:{zoom:w}})),E.zoomed.addEventListener("transitionend",V)})},x=function(){var L=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},V=L.target;return E.original?m():g({target:V})},A=function(){return N},D=function(){return b},O=function(){return E.original},b=[],y=[],H=!1,G=0,N=l,E={original:null,zoomed:null,zoomedHd:null,template:null};Object.prototype.toString.call(t)==="[object Object]"?N=t:(t||typeof t=="string")&&u(t),N=Mt({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},N);var K=vh(N.background);document.addEventListener("click",i),document.addEventListener("keyup",o),document.addEventListener("scroll",r),window.addEventListener("resize",m);var w={open:g,close:m,toggle:x,update:c,clone:a,attach:u,detach:d,on:v,off:_,getOptions:A,getImages:D,getZoomedImage:O};return w};function ph(e,t){t===void 0&&(t={});var l=t.insertAt;if(!(typeof document>"u")){var n=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style");i.type="text/css",l==="top"&&n.firstChild?n.insertBefore(i,n.firstChild):n.appendChild(i),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(document.createTextNode(e))}}var gh=".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";ph(gh);const mh=Symbol("mediumZoom");var bh={};const kh=".theme-default-content > img, .theme-default-content :not(a) > img",Eh=bh,yh=300,xh=Et({enhance({app:e,router:t}){const l=fh(Eh);l.refresh=(n=kh)=>{l.detach(),l.attach(n)},e.provide(mh,l),t.afterEach(()=>{setTimeout(()=>l.refresh(),yh)})}});/**
  * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
  * @license MIT
- */const ue={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},status:null,set:e=>{const t=ue.isStarted();e=ti(e,ue.settings.minimum,1),ue.status=e===1?null:e;const l=ue.render(!t),n=l.querySelector(ue.settings.barSelector),i=ue.settings.speed,r=ue.settings.easing;return l.offsetWidth,Lh(o=>{an(n,{transform:"translate3d("+ro(e)+"%,0,0)",transition:"all "+i+"ms "+r}),e===1?(an(l,{transition:"none",opacity:"1"}),l.offsetWidth,setTimeout(function(){an(l,{transition:"all "+i+"ms linear",opacity:"0"}),setTimeout(function(){ue.remove(),o()},i)},i)):setTimeout(()=>o(),i)}),ue},isStarted:()=>typeof ue.status=="number",start:()=>{ue.status||ue.set(0);const e=()=>{setTimeout(()=>{ue.status&&(ue.trickle(),e())},ue.settings.trickleSpeed)};return ue.settings.trickle&&e(),ue},done:e=>!e&&!ue.status?ue:ue.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=ue.status;return t?(typeof e!="number"&&(e=(1-t)*ti(Math.random()*t,.1,.95)),t=ti(t+e,0,.994),ue.set(t)):ue.start()},trickle:()=>ue.inc(Math.random()*ue.settings.trickleRate),render:e=>{if(ue.isRendered())return document.getElementById("nprogress");oo(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=ue.settings.template;const l=t.querySelector(ue.settings.barSelector),n=e?"-100":ro(ue.status||0),i=document.querySelector(ue.settings.parent);return an(l,{transition:"all 0 linear",transform:"translate3d("+n+"%,0,0)"}),i!==document.body&&oo(i,"nprogress-custom-parent"),i==null||i.appendChild(t),t},remove:()=>{so(document.documentElement,"nprogress-busy"),so(document.querySelector(ue.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&Th(e)},isRendered:()=>!!document.getElementById("nprogress")},ti=(e,t,l)=>el?l:e,ro=e=>(-1+e)*100,Lh=function(){const e=[];function t(){const l=e.shift();l&&l(t)}return function(l){e.push(l),e.length===1&&t()}}(),an=function(){const e=["Webkit","O","Moz","ms"],t={};function l(o){return o.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(c,a){return a.toUpperCase()})}function n(o){const c=document.body.style;if(o in c)return o;let a=e.length;const u=o.charAt(0).toUpperCase()+o.slice(1);let d;for(;a--;)if(d=e[a]+u,d in c)return d;return o}function i(o){return o=l(o),t[o]??(t[o]=n(o))}function r(o,c,a){c=i(c),o.style[c]=a}return function(o,c){for(const a in c){const u=c[a];u!==void 0&&Object.prototype.hasOwnProperty.call(c,a)&&r(o,a,u)}}}(),Fs=(e,t)=>(typeof e=="string"?e:Xi(e)).indexOf(" "+t+" ")>=0,oo=(e,t)=>{const l=Xi(e),n=l+t;Fs(l,t)||(e.className=n.substring(1))},so=(e,t)=>{const l=Xi(e);if(!Fs(e,t))return;const n=l.replace(" "+t+" "," ");e.className=n.substring(1,n.length-1)},Xi=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),Th=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},Oh=()=>{We(()=>{const e=bt(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(l=>{t.has(l.path)||ue.start()}),e.afterEach(l=>{t.add(l.path),ue.done()})})},Ph=Et({setup(){Oh()}}),Ah=JSON.parse(`{"name":"vuepress-theme-xray","smoothScroll":true,"repo":"xtls/xray-core","docsDir":"docs","docsRepo":"xtls/Xray-docs-next","docsBranch":"main","editLinks":true,"enableToggle":true,"locales":{"/":{"navbar":[{"text":"首页","link":"/"},{"text":"大史记","link":"/about/news.md"},{"text":"配置指南","link":"/config/"},{"text":"开发指南","link":"/development/"},{"text":"使用指南","link":"/document/"}],"sidebar":{"/config/":[{"text":"特性详解","children":["/config/features/xtls.md","/config/features/fallback.md","/config/features/browser_dialer.md","/config/features/env.md","/config/features/multiple.md"]},{"text":"基础配置","children":["/config/README.md","/config/log.md","/config/api.md","/config/dns.md","/config/fakedns.md","/config/inbound.md","/config/outbound.md","/config/policy.md","/config/reverse.md","/config/routing.md","/config/stats.md","/config/transport.md","/config/metrics.md","/config/observatory.md"]},{"text":"入站代理","children":["/config/inbounds/dokodemo.md","/config/inbounds/http.md","/config/inbounds/shadowsocks.md","/config/inbounds/socks.md","/config/inbounds/trojan.md","/config/inbounds/vless.md","/config/inbounds/vmess.md"]},{"text":"出站代理","children":["/config/outbounds/blackhole.md","/config/outbounds/dns.md","/config/outbounds/freedom.md","/config/outbounds/http.md","/config/outbounds/loopback.md","/config/outbounds/shadowsocks.md","/config/outbounds/socks.md","/config/outbounds/trojan.md","/config/outbounds/vless.md","/config/outbounds/vmess.md","/config/outbounds/wireguard.md"]},{"text":"底层传输","children":["/config/transports/domainsocket.md","/config/transports/grpc.md","/config/transports/h2.md","/config/transports/mkcp.md","/config/transports/quic.md","/config/transports/tcp.md","/config/transports/websocket.md","/config/transports/httpupgrade.md","/config/transports/splithttp.md"]}],"/document/":[{"text":"快速入门文档","children":["/document/README.md","/document/install.md","/document/config.md","/document/command.md","/document/document.md"]},{"text":"小小白白话文","children":["/document/level-0/README.md","/document/level-0/ch01-preface.md","/document/level-0/ch02-preparation.md","/document/level-0/ch03-ssh.md","/document/level-0/ch04-security.md","/document/level-0/ch05-webpage.md","/document/level-0/ch06-certificates.md","/document/level-0/ch07-xray-server.md","/document/level-0/ch08-xray-clients.md","/document/level-0/ch09-appendix.md"]},{"text":"入门技巧","children":["/document/level-1/README.md","/document/level-1/fallbacks-lv1.md","/document/level-1/routing-lv1-part1.md","/document/level-1/routing-lv1-part2.md","/document/level-1/work.md","/document/level-1/fallbacks-with-sni.md"]},{"text":"进阶技巧","children":["/document/level-2/README.md","/document/level-2/transparent_proxy/transparent_proxy.md","/document/level-2/tproxy.md","/document/level-2/tproxy_ipv4_and_ipv6.md","/document/level-2/nginx_or_haproxy_tls_tunnel.md","/document/level-2/iptables_gid.md","/document/level-2/redirect.md","/document/level-2/warp.md","/document/level-2/traffic_stats.md"]}],"/development/":[{"text":"开发指南","children":["/development/README.md","/development/intro/compile.md","/development/intro/design.md","/development/intro/guide.md"]},{"text":"协议详解","children":["/development/protocols/vless.md","/development/protocols/vmess.md","/development/protocols/muxcool.md","/development/protocols/mkcp.md"]}]},"repoLabel":"查看源码","editLinkText":"帮助我们改善此页面!","tip":"提示","warning":"注意","danger":"警告","lastUpdatedText":"最近更改","selectLanguageName":"简体中文","selectLanguageText":"🌏 简体中文 / Change language","selectLanguageAriaLabel":"简体中文 / Change language","docsDir":"docs","backToHome":"back to home","openInNewWindow":"open in new tag","toggleColorMode":"toggle color mode","toggleSidebar":"toggle side bar"},"/en/":{"sidebar":{"/en/config/":[{"text":"feature","children":["/en/config/features/xtls.md","/en/config/features/fallback.md","/en/config/features/browser_dialer.md","/en/config/features/env.md","/en/config/features/multiple.md"]},{"text":"config","children":["/en/config/README.md","/en/config/log.md","/en/config/api.md","/en/config/dns.md","/en/config/fakedns.md","/en/config/inbound.md","/en/config/outbound.md","/en/config/policy.md","/en/config/reverse.md","/en/config/routing.md","/en/config/stats.md","/en/config/transport.md","/en/config/metrics.md","/en/config/observatory.md"]},{"text":"inbound","children":["/en/config/inbounds/dokodemo.md","/en/config/inbounds/http.md","/en/config/inbounds/shadowsocks.md","/en/config/inbounds/socks.md","/en/config/inbounds/trojan.md","/en/config/inbounds/vless.md","/en/config/inbounds/vmess.md"]},{"text":"outbound","children":["/en/config/outbounds/blackhole.md","/en/config/outbounds/dns.md","/en/config/outbounds/freedom.md","/en/config/outbounds/http.md","/en/config/outbounds/loopback.md","/en/config/outbounds/shadowsocks.md","/en/config/outbounds/socks.md","/en/config/outbounds/trojan.md","/en/config/outbounds/vless.md","/en/config/outbounds/vmess.md","/en/config/outbounds/wireguard.md"]},{"text":"transport","children":["/en/config/transports/domainsocket.md","/en/config/transports/grpc.md","/en/config/transports/h2.md","/en/config/transports/mkcp.md","/en/config/transports/quic.md","/en/config/transports/tcp.md","/en/config/transports/websocket.md","/en/config/transports/httpupgrade.md","/en/config/transports/splithttp.md"]}],"/en/document/":[{"text":"Quick Start","children":["/en/document/README.md","/en/document/install.md","/en/document/config.md","/en/document/command.md","/en/document/document.md"]},{"text":"Beginner Tutorial","children":["/en/document/level-0/README.md","/en/document/level-0/ch01-preface.md","/en/document/level-0/ch02-preparation.md","/en/document/level-0/ch03-ssh.md","/en/document/level-0/ch04-security.md","/en/document/level-0/ch05-webpage.md","/en/document/level-0/ch06-certificates.md","/en/document/level-0/ch07-xray-server.md","/en/document/level-0/ch08-xray-clients.md","/en/document/level-0/ch09-appendix.md"]},{"text":"Getting Started Tips","children":["/en/document/level-1/README.md","/en/document/level-1/fallbacks-lv1.md","/en/document/level-1/routing-lv1-part1.md","/en/document/level-1/routing-lv1-part2.md","/en/document/level-1/work.md","/en/document/level-1/fallbacks-with-sni.md"]},{"text":"Advanced Documentation","children":["/en/document/level-2/README.md","/en/document/level-2/transparent_proxy/transparent_proxy.md","/en/document/level-2/tproxy.md","/en/document/level-2/tproxy_ipv4_and_ipv6.md","/en/document/level-2/nginx_or_haproxy_tls_tunnel.md","/en/document/level-2/iptables_gid.md","/en/document/level-2/redirect.md","/en/document/level-2/warp.md","/en/document/level-2/traffic_stats.md"]}],"/en/development/":[{"text":"Developer Guide","children":["/en/development/README.md","/en/development/intro/compile.md","/en/development/intro/design.md","/en/development/intro/guide.md"]},{"text":"Protocol Details","children":["/en/development/protocols/vless.md","/en/development/protocols/vmess.md","/en/development/protocols/muxcool.md","/en/development/protocols/mkcp.md"]}]},"navbar":[{"text":"Homepage","link":"/en"},{"text":"Website History","link":"/en/about/news.md"},{"text":"Config Reference","link":"/en/config/"},{"text":"Developer Guide","link":"/en/development/"},{"text":"Quick Start","link":"/en/document/"}],"selectLanguageName":"English (WIP)","selectLanguageText":"🌎 English / Change language","selectLanguageAriaLabel":"English / Change language","editLinkText":"Help us improve this page on GitHub!","lastUpdatedText":"Last Updated","contributorsText":"contributors","tip":"Tip","warning":"Warning","danger":"Danger","notFound":["这里什么都没有","我们怎么到这来了?","这是一个 404 页面","看起来我们进入了错误的链接"],"backToHome":"back to home","openInNewWindow":"open in new tag","toggleColorMode":"toggle color mode","toggleSidebar":"toggle side bar"},"/ru/":{"navbar":[{"text":"Главная","link":"/ru"},{"text":"История сайта","link":"/ru/about/news.md"},{"text":"Справочник по конфигурации","link":"/ru/config/"},{"text":"Руководство разработчика","link":"/ru/development/"},{"text":"Быстрый старт","link":"/ru/document/"}],"sidebar":{"/ru/config/":[{"text":"Описание функций","children":["/ru/config/features/xtls.md","/ru/config/features/fallback.md","/ru/config/features/browser_dialer.md","/ru/config/features/env.md","/ru/config/features/multiple.md"]},{"text":"Базовая конфигурация","children":["/ru/config/README.md","/ru/config/log.md","/ru/config/api.md","/ru/config/dns.md","/ru/config/fakedns.md","/ru/config/inbound.md","/ru/config/outbound.md","/ru/config/policy.md","/ru/config/reverse.md","/ru/config/routing.md","/ru/config/stats.md","/ru/config/transport.md","/ru/config/metrics.md","/ru/config/observatory.md"]},{"text":"Входящие подключения","children":["/ru/config/inbounds/dokodemo.md","/ru/config/inbounds/http.md","/ru/config/inbounds/shadowsocks.md","/ru/config/inbounds/socks.md","/ru/config/inbounds/trojan.md","/ru/config/inbounds/vless.md","/ru/config/inbounds/vmess.md"]},{"text":"Исходящие подключения","children":["/ru/config/outbounds/blackhole.md","/ru/config/outbounds/dns.md","/ru/config/outbounds/freedom.md","/ru/config/outbounds/http.md","/ru/config/outbounds/loopback.md","/ru/config/outbounds/shadowsocks.md","/ru/config/outbounds/socks.md","/ru/config/outbounds/trojan.md","/ru/config/outbounds/vless.md","/ru/config/outbounds/vmess.md","/ru/config/outbounds/wireguard.md"]},{"text":"Транспортный уровень","children":["/ru/config/transports/domainsocket.md","/ru/config/transports/grpc.md","/ru/config/transports/h2.md","/ru/config/transports/mkcp.md","/ru/config/transports/quic.md","/ru/config/transports/tcp.md","/ru/config/transports/websocket.md","/ru/config/transports/httpupgrade.md","/ru/config/transports/splithttp.md"]}],"/ru/document/":[{"text":"Быстрый старт","children":["/ru/document/README.md","/ru/document/install.md","/ru/document/config.md","/ru/document/command.md","/ru/document/document.md"]},{"text":"Простыми словами","children":["/ru/document/level-0/README.md","/ru/document/level-0/ch01-preface.md","/ru/document/level-0/ch02-preparation.md","/ru/document/level-0/ch03-ssh.md","/ru/document/level-0/ch04-security.md","/ru/document/level-0/ch05-webpage.md","/ru/document/level-0/ch06-certificates.md","/ru/document/level-0/ch07-xray-server.md","/ru/document/level-0/ch08-xray-clients.md","/ru/document/level-0/ch09-appendix.md"]},{"text":"Базовые навыки","children":["/ru/document/level-1/README.md","/ru/document/level-1/fallbacks-lv1.md","/ru/document/level-1/routing-lv1-part1.md","/ru/document/level-1/routing-lv1-part2.md","/ru/document/level-1/work.md","/ru/document/level-1/fallbacks-with-sni.md"]},{"text":"Продвинутые навыки","children":["/ru/document/level-2/README.md","/ru/document/level-2/transparent_proxy/transparent_proxy.md","/ru/document/level-2/tproxy.md","/ru/document/level-2/tproxy_ipv4_and_ipv6.md","/ru/document/level-2/nginx_or_haproxy_tls_tunnel.md","/ru/document/level-2/iptables_gid.md","/ru/document/level-2/redirect.md","/ru/document/level-2/warp.md","/ru/document/level-2/traffic_stats.md"]}],"/ru/development/":[{"text":"Руководство разработчика","children":["/ru/development/README.md","/ru/development/intro/compile.md","/ru/development/intro/design.md","/ru/development/intro/guide.md"]},{"text":"Описание протоколов","children":["/ru/development/protocols/vless.md","/ru/development/protocols/vmess.md","/ru/development/protocols/muxcool.md","/ru/development/protocols/mkcp.md"]}]},"repoLabel":"Посмотреть исходный код","editLinkText":"Помогите нам улучшить эту страницу!","tip":"Подсказка","warning":"Внимание","danger":"Предупреждение","lastUpdatedText":"Последние изменения","selectLanguageName":"Русский (WIP)","selectLanguageText":"🌍 Русский / Change language","selectLanguageAriaLabel":"Русский / Change language","docsDir":"docs","backToHome":"На главную","openInNewWindow":"Открыть в новой вкладке","toggleColorMode":"Переключить цветовую схему","toggleSidebar":"Переключить боковую панель"},"themePlugins":{"git":true}},"colorMode":"auto","colorModeSwitch":true,"navbar":[],"logo":null,"selectLanguageText":"Languages","selectLanguageAriaLabel":"Select language","sidebar":"auto","sidebarDepth":2,"editLink":true,"editLinkText":"Edit this page","lastUpdated":true,"lastUpdatedText":"Last Updated","contributors":true,"contributorsText":"Contributors","notFound":["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],"backToHome":"Take me home","openInNewWindow":"open in new window","toggleColorMode":"toggle color mode","toggleSidebar":"toggle sidebar"}`),wh=pe(Ah),Ns=()=>wh,Hs=Symbol(""),Rh=()=>{const e=Te(Hs);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},Ih=(e,t)=>{const{locales:l,...n}=e;return{...n,...l==null?void 0:l[t]}},Dh=Et({enhance({app:e}){const t=Ns(),l=e._context.provides[Mi],n=C(()=>Ih(t.value,l.value));e.provide(Hs,n),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return n.value}}})}}),jh=_e({__name:"Badge",props:{type:{type:String,required:!1,default:"tip"},text:{type:String,required:!1,default:""},vertical:{type:String,required:!1,default:void 0}},setup(e,{expose:t}){t();const l={};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),xe=(e,t)=>{const l=e.__vccOpts||e;for(const[n,i]of t)l[n]=i;return l};function Sh(e,t,l,n,i,r){return W(),ee("span",{class:$e(["badge",l.type]),style:Wl({verticalAlign:l.vertical})},[be(e.$slots,"default",{},()=>[Vt(Pe(l.text),1)])],6)}const Ch=xe(jh,[["render",Sh],["__file","Badge.vue"]]);function Vh(e,t){let l,n,i;const r=pe(!0),o=()=>{r.value=!0,i()};Ge(e,o,{flush:"sync"});const c=typeof t=="function"?t:t.get,a=typeof t=="function"?void 0:t.set,u=Mc((d,v)=>(n=d,i=v,{get(){return r.value&&(l=c(),r.value=!1),n(),l},set(_){a==null||a(_)}}));return Object.isExtensible(u)&&(u.trigger=o),u}function Ms(e){return Lo()?(fc(e),!0):!1}function _l(e){return typeof e=="function"?e():Xt(e)}const Fh=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Nh=Object.prototype.toString,Hh=e=>Nh.call(e)==="[object Object]",Mh=()=>{};function $h(e,t){function l(...n){return new Promise((i,r)=>{Promise.resolve(e(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(i).catch(r)})}return l}const $s=e=>e();function Bh(e=$s){const t=pe(!0);function l(){t.value=!1}function n(){t.value=!0}const i=(...r)=>{t.value&&e(...r)};return{isActive:In(t),pause:l,resume:n,eventFilter:i}}function Wh(e){return Vi()}function Uh(e,t,l={}){const{eventFilter:n=$s,...i}=l;return Ge(e,$h(n,t),i)}function zh(e,t,l={}){const{eventFilter:n,...i}=l,{eventFilter:r,pause:o,resume:c,isActive:a}=Bh(n);return{stop:Uh(e,t,{...i,eventFilter:r}),pause:o,resume:c,isActive:a}}function Xh(e,t=!0,l){Wh()?We(e,l):t?e():Xl(e)}function Kh(e=!1,t={}){const{truthyValue:l=!0,falsyValue:n=!1}=t,i=Ne(e),r=pe(e);function o(c){if(arguments.length)return r.value=c,r.value;{const a=_l(l);return r.value=r.value===a?_l(n):a,r.value}}return i?o:[r,o]}function qh(e){var t;const l=_l(e);return(t=l==null?void 0:l.$el)!=null?t:l}const On=Fh?window:void 0;function co(...e){let t,l,n,i;if(typeof e[0]=="string"||Array.isArray(e[0])?([l,n,i]=e,t=On):[t,l,n,i]=e,!t)return Mh;Array.isArray(l)||(l=[l]),Array.isArray(n)||(n=[n]);const r=[],o=()=>{r.forEach(d=>d()),r.length=0},c=(d,v,_,g)=>(d.addEventListener(v,_,g),()=>d.removeEventListener(v,_,g)),a=Ge(()=>[qh(t),_l(i)],([d,v])=>{if(o(),!d)return;const _=Hh(v)?{...v}:v;r.push(...l.flatMap(g=>n.map(m=>c(d,g,m,_))))},{immediate:!0,flush:"post"}),u=()=>{a(),o()};return Ms(u),u}function Gh(){const e=pe(!1),t=Vi();return t&&We(()=>{e.value=!0},t),e}function Yh(e){const t=Gh();return C(()=>(t.value,!!e()))}function Qh(e,t={}){const{window:l=On}=t,n=Yh(()=>l&&"matchMedia"in l&&typeof l.matchMedia=="function");let i;const r=pe(!1),o=u=>{r.value=u.matches},c=()=>{i&&("removeEventListener"in i?i.removeEventListener("change",o):i.removeListener(o))},a=ra(()=>{n.value&&(c(),i=l.matchMedia(_l(e)),"addEventListener"in i?i.addEventListener("change",o):i.addListener(o),r.value=i.matches)});return Ms(()=>{a(),c(),i=void 0}),r}const un=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},dn="__vueuse_ssr_handlers__",Jh=Zh();function Zh(){return dn in un||(un[dn]=un[dn]||{}),un[dn]}function ev(e,t){return Jh[e]||t}function tv(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const lv={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},ao="vueuse-storage";function Bs(e,t,l,n={}){var i;const{flush:r="pre",deep:o=!0,listenToStorageChanges:c=!0,writeDefaults:a=!0,mergeDefaults:u=!1,shallow:d,window:v=On,eventFilter:_,onError:g=w=>{console.error(w)},initOnMounted:m}=n,x=(d?No:pe)(typeof t=="function"?t():t);if(!l)try{l=ev("getDefaultStorage",()=>{var w;return(w=On)==null?void 0:w.localStorage})()}catch(w){g(w)}if(!l)return x;const A=_l(t),D=tv(A),O=(i=n.serializer)!=null?i:lv[D],{pause:b,resume:y}=zh(x,()=>G(x.value),{flush:r,deep:o,eventFilter:_});v&&c&&Xh(()=>{co(v,"storage",E),co(v,ao,K),m&&E()}),m||E();function H(w,z){v&&v.dispatchEvent(new CustomEvent(ao,{detail:{key:e,oldValue:w,newValue:z,storageArea:l}}))}function G(w){try{const z=l.getItem(e);if(w==null)H(z,null),l.removeItem(e);else{const L=O.write(w);z!==L&&(l.setItem(e,L),H(z,L))}}catch(z){g(z)}}function N(w){const z=w?w.newValue:l.getItem(e);if(z==null)return a&&A!=null&&l.setItem(e,O.write(A)),A;if(!w&&u){const L=O.read(z);return typeof u=="function"?u(L,A):D==="object"&&!Array.isArray(L)?{...A,...L}:L}else return typeof z!="string"?z:O.read(z)}function E(w){if(!(w&&w.storageArea!==l)){if(w&&w.key==null){x.value=A;return}if(!(w&&w.key!==e)){b();try{(w==null?void 0:w.newValue)!==O.write(x.value)&&(x.value=N(w))}catch(z){g(z)}finally{w?Xl(y):y()}}}}function K(w){E(w.detail)}return x}function nv(e){return Qh("(prefers-color-scheme: dark)",e)}const iv=_e({name:"CodeGroup",slots:Object,setup(e,{slots:t}){const l=pe([]),n=pe(-1),i=Bs("vuepress-code-group",{}),r=C(()=>l.value.map(u=>u.innerText).join(","));We(()=>{Ge(()=>i.value[r.value],(u=-1)=>{n.value!==u&&(n.value=u)},{immediate:!0}),Ge(n,u=>{i.value[r.value]!==u&&(i.value[r.value]=u)})});const o=(u=n.value)=>{u{u>0?n.value=u-1:n.value=l.value.length-1,l.value[n.value].focus()},a=(u,d)=>{u.key===" "||u.key==="Enter"?(u.preventDefault(),n.value=d):u.key==="ArrowRight"?(u.preventDefault(),o(d)):u.key==="ArrowLeft"&&(u.preventDefault(),c(d))};return()=>{var d;const u=(((d=t.default)==null?void 0:d.call(t))||[]).filter(v=>v.type.name==="CodeGroupItem").map(v=>(v.props===null&&(v.props={}),v));return u.length===0?null:(n.value<0||n.value>u.length-1?(n.value=u.findIndex(v=>v.props.active===""||v.props.active===!0),n.value===-1&&(n.value=0)):u.forEach((v,_)=>{v.props.active=_===n.value}),he("div",{class:"code-group"},[he("div",{class:"code-group__nav",role:"tablist"},u.map((v,_)=>{const g=_===n.value;return he("button",{ref:m=>{m&&(l.value[_]=m)},class:{"code-group__nav-tab":!0,"code-group__nav-tab-active":g},role:"tab",ariaSelected:g,onClick:()=>n.value=_,onKeydown:m=>a(m,_)},v.props.title)})),u]))}}}),rv=_e({name:"CodeGroupItem",__name:"CodeGroupItem",props:{title:{type:String,required:!0},active:{type:Boolean,required:!1,default:!1}},setup(e,{expose:t}){t();const l={};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}});function ov(e,t,l,n,i,r){return W(),ee("div",{class:$e(["code-group-item",{"code-group-item__active":l.active}]),role:"tabpanel"},[be(e.$slots,"default")],2)}const sv=xe(rv,[["render",ov],["__file","CodeGroupItem.vue"]]),cv=()=>Ns(),Fe=()=>Rh(),Ws=Symbol(""),Ki=()=>{const e=Te(Ws);if(!e)throw new Error("useDarkMode() is called without provider.");return e},av=()=>{const e=Fe(),t=nv(),l=Bs("vuepress-color-scheme",e.value.colorMode),n=C({get(){return e.value.colorModeSwitch?l.value==="auto"?t.value:l.value==="dark":e.value.colorMode==="dark"},set(i){i===t.value?l.value="auto":l.value=i?"dark":"light"}});Kt(Ws,n),uv(n)},uv=e=>{const t=(l=e.value)=>{const n=window==null?void 0:window.document.querySelector("html");n==null||n.classList.toggle("dark",l)};We(()=>{Ge(e,t,{immediate:!0})}),Vn(()=>t())};let li=null,Ll=null;const dv={wait:()=>li,pending:()=>{li=new Promise(e=>Ll=e)},resolve:()=>{Ll==null||Ll(),li=null,Ll=null}},Us=()=>dv,zs=(e,...t)=>{const l=e.resolve(...t),n=l.matched[l.matched.length-1];if(!(n!=null&&n.redirect))return l;const{redirect:i}=n,r=Nu(i)?i(l):i,o=it(r)?{path:r}:r;return zs(e,{hash:l.hash,query:l.query,params:l.params,...o})},qi=(e,t)=>{const l=zs(e,encodeURI(t));return{text:l.meta.title||t,link:l.name==="404"?t:l.fullPath}},uo=e=>decodeURI(e).replace(/#.*$/,"").replace(/(index)?\.(md|html)$/,""),hv=(e,t)=>{if(t.hash===e)return!0;const l=uo(t.path),n=uo(e);return l===n},Xs=(e,t)=>e.link&&hv(e.link,t)?!0:e.children?e.children.some(l=>Xs(l,t)):!1,Ks=e=>!Yl(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,vv={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},_v=({docsRepo:e,editLinkPattern:t})=>{if(t)return t;const l=Ks(e);return l!==null?vv[l]:null},fv=({docsRepo:e,docsBranch:t,docsDir:l,filePathRelative:n,editLinkPattern:i})=>{if(!n)return null;const r=_v({docsRepo:e,editLinkPattern:i});return r?r.replace(/:repo/,Yl(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,fs(`${_s(l)}/${n}`)):null},qs=Symbol("sidebarItems"),Gi=()=>{const e=Te(qs);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},pv=()=>{const e=Fe(),t=gt(),l=Gt(),n=ml(),i=bt(),r=C(()=>gv(t.value,e.value,l.value,i,n.path));Kt(qs,r)},gv=(e,t,l,n,i)=>{const r=e.sidebar??t.sidebar??"auto",o=e.sidebarDepth??t.sidebarDepth??2;return e.home||r===!1?[]:r==="auto"?Gs(l,o):Array.isArray(r)?Ys(l,n,i,r,o):Hi(r)?bv(l,n,i,r,o):[]},mv=(e,t)=>({text:e.title,link:e.link,children:Yi(e.children,t)}),Yi=(e,t)=>t>0?e.map(l=>mv(l,t-1)):[],Gs=(e,t)=>[{text:e.title,children:Yi(e.headers,t)}],Ys=(e,t,l,n,i)=>{const r=o=>{var a;let c;if(it(o)?c=qi(t,o):c=o,c.children)return{...c,children:c.children.map(u=>r(u))};if(c.link===l){const u=((a=e.headers[0])==null?void 0:a.level)===1?e.headers[0].children:e.headers;return{...c,children:Yi(u,i)}}return c};return n.map(o=>r(o))},bv=(e,t,l,n,i)=>{const r=ps(n,l),o=n[r]??[];return o==="heading"?Gs(e,i):Ys(e,t,l,o,i)},kv="719px",Ev={mobile:kv};var $l;(function(e){e.MOBILE="mobile"})($l||($l={}));var go;const yv={[$l.MOBILE]:Number.parseInt((go=Ev.mobile)==null?void 0:go.replace("px",""),10)},Qs=(e,t)=>{const l=yv[e];Number.isInteger(l)&&We(()=>{t(l),window.addEventListener("resize",()=>t(l),!1),window.addEventListener("orientationchange",()=>t(l),!1)})},xv={},Lv={class:"theme-default-content"};function Tv(e,t){const l=mt("Content");return W(),ee("div",Lv,[ie(l)])}const Ov=xe(xv,[["render",Tv],["__file","HomeContent.vue"]]),Pv=_e({__name:"HomeFeatures",setup(e,{expose:t}){t();const l=gt(),n=C(()=>Array.isArray(l.value.features)?l.value.features:[]),i={frontmatter:l,features:n};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}}),Av={key:0,class:"features"};function wv(e,t,l,n,i,r){return n.features.length?(W(),ee("div",Av,[(W(!0),ee(ke,null,St(n.features,o=>(W(),ee("div",{key:o.title,class:"feature"},[ce("h2",null,Pe(o.title),1),ce("p",null,Pe(o.details),1)]))),128))])):Le("",!0)}const Rv=xe(Pv,[["render",wv],["__file","HomeFeatures.vue"]]),Iv=_e({__name:"HomeFooter",setup(e,{expose:t}){t();const l=gt(),n=C(()=>l.value.footer),i=C(()=>l.value.footerHtml),r={frontmatter:l,footer:n,footerHtml:i};return Object.defineProperty(r,"__isScriptSetup",{enumerable:!1,value:!0}),r}}),Dv=["innerHTML"],jv=["textContent"];function Sv(e,t,l,n,i,r){return n.footer?(W(),ee(ke,{key:0},[n.footerHtml?(W(),ee("div",{key:0,class:"footer",innerHTML:n.footer},null,8,Dv)):(W(),ee("div",{key:1,class:"footer",textContent:Pe(n.footer)},null,8,jv))],64)):Le("",!0)}const Cv=xe(Iv,[["render",Sv],["__file","HomeFooter.vue"]]),Vv=_e({inheritAttrs:!1,__name:"AutoLink",props:{item:{type:Object,required:!0}},setup(e,{expose:t}){t();const l=e,n=ml(),i=xs(),{item:r}=Dn(l),o=C(()=>Yl(r.value.link)),c=C(()=>!o.value&&Fu(r.value.link)),a=C(()=>{if(!c.value){if(r.value.target)return r.value.target;if(o.value)return"_blank"}}),u=C(()=>a.value==="_blank"),d=C(()=>!o.value&&!c.value&&!u.value),v=C(()=>{if(!c.value){if(r.value.rel)return r.value.rel;if(u.value)return"noopener noreferrer"}}),_=C(()=>r.value.ariaLabel||r.value.text),g=C(()=>{const D=Object.keys(i.value.locales);return D.length?!D.some(O=>O===r.value.link):r.value.link!=="/"}),m=C(()=>g.value?n.path.startsWith(r.value.link):!1),x=C(()=>d.value?r.value.activeMatch?new RegExp(r.value.activeMatch).test(n.path):m.value:!1),A={props:l,route:n,site:i,item:r,hasHttpProtocol:o,hasNonHttpProtocol:c,linkTarget:a,isBlankTarget:u,isRouterLink:d,linkRel:v,linkAriaLabel:_,shouldBeActiveInSubpath:g,isActiveInSubpath:m,isActive:x};return Object.defineProperty(A,"__isScriptSetup",{enumerable:!1,value:!0}),A}}),Fv=["href","rel","target","aria-label"];function Nv(e,t,l,n,i,r){const o=mt("RouterLink"),c=mt("AutoLinkExternalIcon");return n.isRouterLink?(W(),Ae(o,_i({key:0,class:{"router-link-active":n.isActive},to:n.item.link,"aria-label":n.linkAriaLabel},e.$attrs),{default:Ce(()=>[be(e.$slots,"before"),Vt(" "+Pe(n.item.text)+" ",1),be(e.$slots,"after")]),_:3},16,["class","to","aria-label"])):(W(),ee("a",_i({key:1,class:"external-link",href:n.item.link,rel:n.linkRel,target:n.linkTarget,"aria-label":n.linkAriaLabel},e.$attrs),[be(e.$slots,"before"),Vt(" "+Pe(n.item.text)+" ",1),n.isBlankTarget?(W(),Ae(c,{key:0})):Le("",!0),be(e.$slots,"after")],16,Fv))}const bl=xe(Vv,[["render",Nv],["__file","AutoLink.vue"]]),Hv=_e({__name:"HomeHero",setup(e,{expose:t}){t();const l=gt(),n=$i(),i=Ki(),r=C(()=>i.value&&l.value.heroImageDark!==void 0?l.value.heroImageDark:l.value.heroImage),o=C(()=>l.value.heroAlt||a.value||"hero"),c=C(()=>l.value.heroHeight||280),a=C(()=>l.value.heroText===null?null:l.value.heroText||n.value.title||"Hello"),u=C(()=>l.value.tagline===null?null:l.value.tagline||n.value.description||"Welcome to your VuePress site"),d=C(()=>Array.isArray(l.value.actions)?l.value.actions.map(({text:g,link:m,type:x="primary"})=>({text:g,link:m,type:x})):[]),_={frontmatter:l,siteLocale:n,isDarkMode:i,heroImage:r,heroAlt:o,heroHeight:c,heroText:a,tagline:u,actions:d,HomeHeroImage:()=>{if(!r.value)return null;const g=he("img",{src:Wi(r.value),alt:o.value,height:c.value});return l.value.heroImageDark===void 0?g:he(Bi,()=>g)},AutoLink:bl};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),Mv={class:"hero"},$v={key:0,id:"main-title"},Bv={key:1,class:"description"},Wv={key:2,class:"actions"};function Uv(e,t,l,n,i,r){return W(),ee("header",Mv,[ie(n.HomeHeroImage),n.heroText?(W(),ee("h1",$v,Pe(n.heroText),1)):Le("",!0),n.tagline?(W(),ee("p",Bv,Pe(n.tagline),1)):Le("",!0),n.actions.length?(W(),ee("p",Wv,[(W(!0),ee(ke,null,St(n.actions,o=>(W(),Ae(n.AutoLink,{key:o.text,class:$e(["action-button",[o.type]]),item:o},null,8,["class","item"]))),128))])):Le("",!0)])}const zv=xe(Hv,[["render",Uv],["__file","HomeHero.vue"]]),Xv=_e({__name:"Home",setup(e,{expose:t}){t();const l={HomeContent:Ov,HomeFeatures:Rv,HomeFooter:Cv,HomeHero:zv};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),Kv={class:"home"};function qv(e,t,l,n,i,r){return W(),ee("main",Kv,[ie(n.HomeHero),ie(n.HomeFeatures),ie(n.HomeContent),ie(n.HomeFooter)])}const Gv=xe(Xv,[["render",qv],["__file","Home.vue"]]),Yv=_e({__name:"NavbarBrand",setup(e,{expose:t}){t();const l=Ql(),n=$i(),i=Fe(),r=Ki(),o=C(()=>i.value.home||l.value),c=C(()=>n.value.title),a=C(()=>r.value&&i.value.logoDark!==void 0?i.value.logoDark:i.value.logo),u=C(()=>i.value.logoAlt??c.value),d=C(()=>c.value.toLocaleUpperCase().trim()===u.value.toLocaleUpperCase().trim()),_={routeLocale:l,siteLocale:n,themeLocale:i,isDarkMode:r,navbarBrandLink:o,navbarBrandTitle:c,navbarBrandLogo:a,navbarBrandLogoAlt:u,navBarLogoAltMatchesTitle:d,NavbarBrandLogo:()=>{if(!a.value)return null;const g=he("img",{class:"logo",src:Wi(a.value),alt:u.value});return i.value.logoDark===void 0?g:he(Bi,()=>g)}};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),Qv=["aria-hidden"];function Jv(e,t,l,n,i,r){const o=mt("RouterLink");return W(),Ae(o,{to:n.navbarBrandLink},{default:Ce(()=>[ie(n.NavbarBrandLogo),n.navbarBrandTitle?(W(),ee("span",{key:0,class:$e(["site-name",{"can-hide":n.navbarBrandLogo}]),"aria-hidden":n.navBarLogoAltMatchesTitle},Pe(n.navbarBrandTitle),11,Qv)):Le("",!0)]),_:1},8,["to"])}const Zv=xe(Yv,[["render",Jv],["__file","NavbarBrand.vue"]]),e_=_e({__name:"DropdownTransition",setup(e,{expose:t}){t();const i={setHeight:r=>{r.style.height=r.scrollHeight+"px"},unsetHeight:r=>{r.style.height=""}};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}});function t_(e,t,l,n,i,r){return W(),Ae(Gl,{name:"dropdown",onEnter:n.setHeight,onAfterEnter:n.unsetHeight,onBeforeLeave:n.setHeight},{default:Ce(()=>[be(e.$slots,"default")]),_:3})}const Js=xe(e_,[["render",t_],["__file","DropdownTransition.vue"]]),l_=_e({__name:"NavbarDropdown",props:{item:{type:Object,required:!0}},setup(e,{expose:t}){t();const l=e,{item:n}=Dn(l),i=C(()=>n.value.ariaLabel||n.value.text),r=pe(!1),o=ml();Ge(()=>o.path,()=>{r.value=!1});const u={props:l,item:n,dropdownAriaLabel:i,open:r,route:o,handleDropdown:d=>{d.detail===0?r.value=!r.value:r.value=!1},isLastItemOfArray:(d,v)=>v[v.length-1]===d,AutoLink:bl,DropdownTransition:Js};return Object.defineProperty(u,"__isScriptSetup",{enumerable:!1,value:!0}),u}}),n_=["aria-label"],i_={class:"title"},r_=ce("span",{class:"arrow down"},null,-1),o_=["aria-label"],s_={class:"title"},c_={class:"navbar-dropdown"},a_={class:"navbar-dropdown-subtitle"},u_={key:1},d_={class:"navbar-dropdown-subitem-wrapper"};function h_(e,t,l,n,i,r){return W(),ee("div",{class:$e(["navbar-dropdown-wrapper",{open:n.open}])},[ce("button",{class:"navbar-dropdown-title",type:"button","aria-label":n.dropdownAriaLabel,onClick:n.handleDropdown},[ce("span",i_,Pe(n.item.text),1),r_],8,n_),ce("button",{class:"navbar-dropdown-title-mobile",type:"button","aria-label":n.dropdownAriaLabel,onClick:t[0]||(t[0]=o=>n.open=!n.open)},[ce("span",s_,Pe(n.item.text),1),ce("span",{class:$e(["arrow",n.open?"down":"right"])},null,2)],8,o_),ie(n.DropdownTransition,null,{default:Ce(()=>[kn(ce("ul",c_,[(W(!0),ee(ke,null,St(n.item.children,o=>(W(),ee("li",{key:o.text,class:"navbar-dropdown-item"},[o.children?(W(),ee(ke,{key:0},[ce("h4",a_,[o.link?(W(),Ae(n.AutoLink,{key:0,item:o,onFocusout:c=>n.isLastItemOfArray(o,n.item.children)&&o.children.length===0&&(n.open=!1)},null,8,["item","onFocusout"])):(W(),ee("span",u_,Pe(o.text),1))]),ce("ul",d_,[(W(!0),ee(ke,null,St(o.children,c=>(W(),ee("li",{key:c.link,class:"navbar-dropdown-subitem"},[ie(n.AutoLink,{item:c,onFocusout:a=>n.isLastItemOfArray(c,o.children)&&n.isLastItemOfArray(o,n.item.children)&&(n.open=!1)},null,8,["item","onFocusout"])]))),128))])],64)):(W(),Ae(n.AutoLink,{key:1,item:o,onFocusout:c=>n.isLastItemOfArray(o,n.item.children)&&(n.open=!1)},null,8,["item","onFocusout"]))]))),128))],512),[[Tn,n.open]])]),_:1})],2)}const v_=xe(l_,[["render",h_],["__file","NavbarDropdown.vue"]]),__=_e({__name:"NavbarItems",setup(e,{expose:t}){t();const l=()=>{const g=bt(),m=Ql(),x=xs(),A=$i(),D=cv(),O=Fe();return C(()=>{const b=Object.keys(x.value.locales);if(b.length<2)return[];const y=g.currentRoute.value.path,H=g.currentRoute.value.fullPath;return[{text:`${O.value.selectLanguageText}`,ariaLabel:`${O.value.selectLanguageAriaLabel??O.value.selectLanguageText}`,children:b.map(N=>{var V,le;const E=((V=x.value.locales)==null?void 0:V[N])??{},K=((le=D.value.locales)==null?void 0:le[N])??{},w=`${E.lang}`,z=K.selectLanguageName??w;let L;if(w===A.value.lang)L=H;else{const ne=y.replace(m.value,N);g.getRoutes().some(S=>S.path===ne)?L=H.replace(y,ne):L=K.home??N}return{text:z,link:L}})}]})},n=()=>{const g=Fe(),m=C(()=>g.value.repo),x=C(()=>m.value?Ks(m.value):null),A=C(()=>m.value&&!Yl(m.value)?`https://github.com/${m.value}`:m.value),D=C(()=>A.value?g.value.repoLabel?g.value.repoLabel:x.value===null?"Source":x.value:null);return C(()=>!A.value||!D.value?[]:[{text:D.value,link:A.value}])},i=(g,m)=>it(m)?qi(g,m):m.children?{...m,children:m.children.map(x=>i(g,x))}:m,r=()=>{const g=bt(),m=Fe();return C(()=>(m.value.navbar||[]).map(x=>i(g,x)))},o=pe(!1),c=r(),a=l(),u=n(),d=C(()=>[...c.value,...a.value,...u.value]);Qs($l.MOBILE,g=>{window.innerWidthFe().value.navbarLabel??"site navigation"),_={useNavbarSelectLanguage:l,useNavbarRepo:n,resolveNavbarItem:i,useNavbarConfig:r,isMobile:o,navbarConfig:c,navbarSelectLanguage:a,navbarRepo:u,navbarLinks:d,navbarLabel:v,AutoLink:bl,NavbarDropdown:v_};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),f_=["aria-label"];function p_(e,t,l,n,i,r){return n.navbarLinks.length?(W(),ee("nav",{key:0,class:"navbar-items","aria-label":n.navbarLabel},[(W(!0),ee(ke,null,St(n.navbarLinks,o=>(W(),ee("div",{key:o.text,class:"navbar-item"},[o.children?(W(),Ae(n.NavbarDropdown,{key:0,item:o,class:$e(n.isMobile?"mobile":"")},null,8,["item","class"])):(W(),Ae(n.AutoLink,{key:1,item:o},null,8,["item"]))]))),128))],8,f_)):Le("",!0)}const Zs=xe(__,[["render",p_],["__file","NavbarItems.vue"]]),g_=_e({__name:"ToggleColorModeButton",setup(e,{expose:t}){t();const l=Fe(),n=Ki(),r={themeLocale:l,isDarkMode:n,toggleColorMode:()=>{n.value=!n.value}};return Object.defineProperty(r,"__isScriptSetup",{enumerable:!1,value:!0}),r}}),m_=["title"],b_={class:"icon",focusable:"false",viewBox:"0 0 32 32"},k_=$a('',9),E_=[k_],y_={class:"icon",focusable:"false",viewBox:"0 0 32 32"},x_=ce("path",{d:"M13.502 5.414a15.075 15.075 0 0 0 11.594 18.194a11.113 11.113 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1.002 1.002 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.072 13.072 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3z",fill:"currentColor"},null,-1),L_=[x_];function T_(e,t,l,n,i,r){return W(),ee("button",{class:"toggle-color-mode-button",title:n.themeLocale.toggleColorMode,onClick:n.toggleColorMode},[kn((W(),ee("svg",b_,E_,512)),[[Tn,!n.isDarkMode]]),kn((W(),ee("svg",y_,L_,512)),[[Tn,n.isDarkMode]])],8,m_)}const O_=xe(g_,[["render",T_],["__file","ToggleColorModeButton.vue"]]),P_=_e({__name:"ToggleSidebarButton",emits:["toggle"],setup(e,{expose:t}){t();const n={themeLocale:Fe()};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}}),A_=["title"],w_=ce("div",{class:"icon","aria-hidden":"true"},[ce("span"),ce("span"),ce("span")],-1),R_=[w_];function I_(e,t,l,n,i,r){return W(),ee("div",{class:"toggle-sidebar-button",title:n.themeLocale.toggleSidebar,"aria-expanded":"false",role:"button",tabindex:"0",onClick:t[0]||(t[0]=o=>e.$emit("toggle"))},R_,8,A_)}const D_=xe(P_,[["render",I_],["__file","ToggleSidebarButton.vue"]]),j_=_e({__name:"Navbar",emits:["toggle-sidebar"],setup(e,{expose:t}){t();const l=Fe(),n=pe(null),i=pe(null),r=pe(0),o=C(()=>r.value?{maxWidth:r.value+"px"}:{});Qs($l.MOBILE,u=>{var v;const d=c(n.value,"paddingLeft")+c(n.value,"paddingRight");window.innerWidthe.$emit("toggle-sidebar"))}),ce("span",C_,[ie(n.NavbarBrand)],512),ce("div",{class:"navbar-items-wrapper",style:Wl(n.linksWrapperStyle)},[be(e.$slots,"before"),ie(n.NavbarItems,{class:"can-hide"}),be(e.$slots,"after"),n.themeLocale.colorModeSwitch?(W(),Ae(n.ToggleColorModeButton,{key:0})):Le("",!0),ie(o)],4)],512)}const F_=xe(j_,[["render",V_],["__file","Navbar.vue"]]),N_=_e({__name:"PageMeta",setup(e,{expose:t}){t();const l=()=>{const d=Fe(),v=Gt(),_=gt();return C(()=>{if(!(_.value.editLink??d.value.editLink??!0))return null;const{repo:m,docsRepo:x=m,docsBranch:A="main",docsDir:D="",editLinkText:O}=d.value;if(!x)return null;const b=fv({docsRepo:x,docsBranch:A,docsDir:D,filePathRelative:v.value.filePathRelative,editLinkPattern:_.value.editLinkPattern??d.value.editLinkPattern});return b?{text:O??"Edit this page",link:b}:null})},n=()=>{const d=Fe(),v=Gt(),_=gt();return C(()=>{var x,A;return!(_.value.lastUpdated??d.value.lastUpdated??!0)||!((x=v.value.git)!=null&&x.updatedTime)?null:new Date((A=v.value.git)==null?void 0:A.updatedTime).toLocaleString()})},i=()=>{const d=Fe(),v=Gt(),_=gt();return C(()=>{var m;return _.value.contributors??d.value.contributors??!0?((m=v.value.git)==null?void 0:m.contributors)??null:null})},r=Fe(),o=l(),c=n(),a=i(),u={useEditNavLink:l,useLastUpdated:n,useContributors:i,themeLocale:r,editNavLink:o,lastUpdated:c,contributors:a,AutoLink:bl};return Object.defineProperty(u,"__isScriptSetup",{enumerable:!1,value:!0}),u}}),H_={class:"page-meta"},M_={key:0,class:"meta-item edit-link"},$_={key:1,class:"meta-item last-updated"},B_={class:"meta-item-label"},W_={class:"meta-item-info"},U_={key:2,class:"meta-item contributors"},z_={class:"meta-item-label"},X_={class:"meta-item-info"},K_=["title"];function q_(e,t,l,n,i,r){const o=mt("ClientOnly");return W(),ee("footer",H_,[n.editNavLink?(W(),ee("div",M_,[ie(n.AutoLink,{class:"meta-item-label",item:n.editNavLink},null,8,["item"])])):Le("",!0),n.lastUpdated?(W(),ee("div",$_,[ce("span",B_,Pe(n.themeLocale.lastUpdatedText)+": ",1),ie(o,null,{default:Ce(()=>[ce("span",W_,Pe(n.lastUpdated),1)]),_:1})])):Le("",!0),n.contributors&&n.contributors.length?(W(),ee("div",U_,[ce("span",z_,Pe(n.themeLocale.contributorsText)+": ",1),ce("span",X_,[(W(!0),ee(ke,null,St(n.contributors,(c,a)=>(W(),ee(ke,{key:a},[ce("span",{class:"contributor",title:`email: ${c.email}`},Pe(c.name),9,K_),a!==n.contributors.length-1?(W(),ee(ke,{key:0},[Vt(", ")],64)):Le("",!0)],64))),128))])])):Le("",!0)])}const G_=xe(N_,[["render",q_],["__file","PageMeta.vue"]]),Y_=_e({__name:"PageNav",setup(e,{expose:t}){t();const l=(_,g)=>g===!1?null:it(g)?qi(_,g):Hi(g)?g:!1,n=(_,g,m)=>{const x=_.findIndex(A=>A.link===g);if(x!==-1){const A=_[x+m];return A!=null&&A.link?A:null}for(const A of _)if(A.children){const D=n(A.children,g,m);if(D)return D}return null},i=gt(),r=Gi(),o=ml(),c=bt(),a=C(()=>{const _=l(c,i.value.prev);return _!==!1?_:n(r.value,o.path,-1)}),u=C(()=>{const _=l(c,i.value.next);return _!==!1?_:n(r.value,o.path,1)}),d=C(()=>Fe().value.pageNavbarLabel??"page navigation"),v={resolveFromFrontmatterConfig:l,resolveFromSidebarItems:n,frontmatter:i,sidebarItems:r,route:o,router:c,prevNavLink:a,nextNavLink:u,navbarLabel:d,AutoLink:bl};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}}),Q_=["aria-label"],J_={class:"inner"},Z_={key:0,class:"prev"},ef={key:1,class:"next"};function tf(e,t,l,n,i,r){return n.prevNavLink||n.nextNavLink?(W(),ee("nav",{key:0,class:"page-nav","aria-label":n.navbarLabel},[ce("p",J_,[n.prevNavLink?(W(),ee("span",Z_,[ie(n.AutoLink,{item:n.prevNavLink},null,8,["item"])])):Le("",!0),n.nextNavLink?(W(),ee("span",ef,[ie(n.AutoLink,{item:n.nextNavLink},null,8,["item"])])):Le("",!0)])],8,Q_)):Le("",!0)}const lf=xe(Y_,[["render",tf],["__file","PageNav.vue"]]),nf=_e({__name:"Page",setup(e,{expose:t}){t();const l={PageMeta:G_,PageNav:lf};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),rf={class:"page"},of={class:"theme-default-content"};function sf(e,t,l,n,i,r){const o=mt("Content");return W(),ee("main",rf,[be(e.$slots,"top"),ce("div",of,[be(e.$slots,"content-top"),ie(o),be(e.$slots,"content-bottom")]),ie(n.PageMeta),ie(n.PageNav),be(e.$slots,"bottom")])}const cf=xe(nf,[["render",sf],["__file","Page.vue"]]),af=_e({__name:"SidebarItem",props:{item:{type:Object,required:!0},depth:{type:Number,required:!1,default:0}},setup(e,{expose:t}){t();const l=e,{item:n,depth:i}=Dn(l),r=ml(),o=bt(),c=C(()=>Xs(n.value,r)),a=C(()=>({"sidebar-item":!0,"sidebar-heading":i.value===0,active:c.value,collapsible:n.value.collapsible})),u=C(()=>n.value.collapsible?c.value:!0),[d,v]=Kh(u.value),_=x=>{n.value.collapsible&&(x.preventDefault(),v())},g=o.afterEach(x=>{Xl(()=>{d.value=u.value})});ql(()=>{g()});const m={props:l,item:n,depth:i,route:r,router:o,isActive:c,itemClass:a,isOpenDefault:u,isOpen:d,toggleIsOpen:v,onClick:_,unregisterRouterHook:g,AutoLink:bl,DropdownTransition:Js};return Object.defineProperty(m,"__isScriptSetup",{enumerable:!1,value:!0}),m}}),uf={class:"sidebar-item-children"};function df(e,t,l,n,i,r){var c;const o=mt("SidebarItem",!0);return W(),ee("li",null,[n.item.link?(W(),Ae(n.AutoLink,{key:0,class:$e(n.itemClass),item:n.item},null,8,["class","item"])):(W(),ee("p",{key:1,tabindex:"0",class:$e(n.itemClass),onClick:n.onClick,onKeydown:Lu(n.onClick,["enter"])},[Vt(Pe(n.item.text)+" ",1),n.item.collapsible?(W(),ee("span",{key:0,class:$e(["arrow",n.isOpen?"down":"right"])},null,2)):Le("",!0)],34)),(c=n.item.children)!=null&&c.length?(W(),Ae(n.DropdownTransition,{key:2},{default:Ce(()=>[kn(ce("ul",uf,[(W(!0),ee(ke,null,St(n.item.children,a=>(W(),Ae(o,{key:`${n.depth}${a.text}${a.link}`,item:a,depth:n.depth+1},null,8,["item","depth"]))),128))],512),[[Tn,n.isOpen]])]),_:1})):Le("",!0)])}const hf=xe(af,[["render",df],["__file","SidebarItem.vue"]]),vf=_e({__name:"SidebarItems",setup(e,{expose:t}){t();const l=ml(),n=Gi();We(()=>{Ge(()=>l.hash,r=>{const o=document.querySelector(".sidebar");if(!o)return;const c=document.querySelector(`.sidebar a.sidebar-item[href="${l.path}${r}"]`);if(!c)return;const{top:a,height:u}=o.getBoundingClientRect(),{top:d,height:v}=c.getBoundingClientRect();da+u&&c.scrollIntoView(!1)})});const i={route:l,sidebarItems:n,SidebarItem:hf};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}}),_f={key:0,class:"sidebar-items"};function ff(e,t,l,n,i,r){return n.sidebarItems.length?(W(),ee("ul",_f,[(W(!0),ee(ke,null,St(n.sidebarItems,o=>(W(),Ae(n.SidebarItem,{key:`${o.text}${o.link}`,item:o},null,8,["item"]))),128))])):Le("",!0)}const pf=xe(vf,[["render",ff],["__file","SidebarItems.vue"]]),gf=_e({__name:"Sidebar",setup(e,{expose:t}){t();const l={NavbarItems:Zs,SidebarItems:pf};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),mf={class:"sidebar"};function bf(e,t,l,n,i,r){return W(),ee("aside",mf,[ie(n.NavbarItems),be(e.$slots,"top"),ie(n.SidebarItems),be(e.$slots,"bottom")])}const kf=xe(gf,[["render",bf],["__file","Sidebar.vue"]]),Ef=_e({__name:"Layout",setup(e,{expose:t}){t();const l=Gt(),n=gt(),i=Fe(),r=C(()=>n.value.navbar!==!1&&i.value.navbar!==!1),o=Gi(),c=pe(!1),a=O=>{c.value=typeof O=="boolean"?O:!c.value},u={x:0,y:0},d=O=>{u.x=O.changedTouches[0].clientX,u.y=O.changedTouches[0].clientY},v=O=>{const b=O.changedTouches[0].clientX-u.x,y=O.changedTouches[0].clientY-u.y;Math.abs(b)>Math.abs(y)&&Math.abs(b)>40&&(b>0&&u.x<=80?a(!0):a(!1))},_=C(()=>[{"no-navbar":!r.value,"no-sidebar":!o.value.length,"sidebar-open":c.value},n.value.pageClass]);let g;We(()=>{g=bt().afterEach(()=>{a(!1)})}),Vn(()=>{g()});const m=Us(),x=m.resolve,A=m.pending,D={page:l,frontmatter:n,themeLocale:i,shouldShowNavbar:r,sidebarItems:o,isSidebarOpen:c,toggleSidebar:a,touchStart:u,onTouchStart:d,onTouchEnd:v,containerClass:_,get unregisterRouterHook(){return g},set unregisterRouterHook(O){g=O},scrollPromise:m,onBeforeEnter:x,onBeforeLeave:A,Home:Gv,Navbar:F_,Page:cf,Sidebar:kf};return Object.defineProperty(D,"__isScriptSetup",{enumerable:!1,value:!0}),D}});function yf(e,t,l,n,i,r){return W(),ee("div",{class:$e(["theme-container",n.containerClass]),onTouchstart:n.onTouchStart,onTouchend:n.onTouchEnd},[be(e.$slots,"navbar",{},()=>[n.shouldShowNavbar?(W(),Ae(n.Navbar,{key:0,onToggleSidebar:n.toggleSidebar},{before:Ce(()=>[be(e.$slots,"navbar-before")]),after:Ce(()=>[be(e.$slots,"navbar-after")]),_:3})):Le("",!0)]),ce("div",{class:"sidebar-mask",onClick:t[0]||(t[0]=o=>n.toggleSidebar(!1))}),be(e.$slots,"sidebar",{},()=>[ie(n.Sidebar,null,{top:Ce(()=>[be(e.$slots,"sidebar-top")]),bottom:Ce(()=>[be(e.$slots,"sidebar-bottom")]),_:3})]),be(e.$slots,"page",{},()=>[n.frontmatter.home?(W(),Ae(n.Home,{key:0})):(W(),Ae(Gl,{key:1,name:"fade-slide-y",mode:"out-in",onBeforeEnter:n.onBeforeEnter,onBeforeLeave:n.onBeforeLeave},{default:Ce(()=>[(W(),Ae(n.Page,{key:n.page.path},{top:Ce(()=>[be(e.$slots,"page-top")]),"content-top":Ce(()=>[be(e.$slots,"page-content-top")]),"content-bottom":Ce(()=>[be(e.$slots,"page-content-bottom")]),bottom:Ce(()=>[be(e.$slots,"page-bottom")]),_:3}))]),_:3},8,["onBeforeEnter","onBeforeLeave"]))])],34)}const xf=xe(Ef,[["render",yf],["__file","Layout.vue"]]),Lf=_e({__name:"NotFound",setup(e,{expose:t}){t();const l=Ql(),n=Fe(),i=n.value.notFound??["Not Found"],r=()=>i[Math.floor(Math.random()*i.length)],o=n.value.home??l.value,c=n.value.backToHome??"Back to home",a={routeLocale:l,themeLocale:n,messages:i,getMsg:r,homeLink:o,homeText:c};return Object.defineProperty(a,"__isScriptSetup",{enumerable:!1,value:!0}),a}}),Tf={class:"theme-container"},Of={class:"page"},Pf={class:"theme-default-content"},Af=ce("h1",null,"404",-1);function wf(e,t,l,n,i,r){const o=mt("RouterLink");return W(),ee("div",Tf,[ce("main",Of,[ce("div",Pf,[Af,ce("blockquote",null,Pe(n.getMsg()),1),ie(o,{to:n.homeLink},{default:Ce(()=>[Vt(Pe(n.homeText),1)]),_:1},8,["to"])])])])}const Rf=xe(Lf,[["render",wf],["__file","NotFound.vue"]]),If=Et({enhance({app:e,router:t}){e.component("Badge",Ch),e.component("CodeGroup",iv),e.component("CodeGroupItem",sv),e.component("AutoLinkExternalIcon",()=>{const n=e.component("ExternalLinkIcon");return n?he(n):null}),e.component("NavbarSearch",()=>{const n=e.component("Docsearch")||e.component("SearchBox");return n?he(n):null});const l=t.options.scrollBehavior;t.options.scrollBehavior=async(...n)=>(await Us().wait(),l(...n))},setup(){av(),pv()},layouts:{Layout:xf,NotFound:Rf}}),Df=e=>typeof e=="string",jf=(e,t)=>Df(e)&&e.startsWith(t),Sf=e=>jf(e,"/"),Cf={"/":"https://github.com/XTLS/Xray-docs-next"},Vf={"/":{lang:"zh-CN",untranslated:{title:"提示",content:(e,t)=>`此页面尚未翻译${t?`,在${e("此处",t)}了解如何帮我们翻译`:""}。`},outdated:{title:"警告",content:(e,t,l,n)=>{const i=r=>{const o=new Date(r);return`${o.getFullYear()}年${o.getMonth()}月${o.getDate()}日`};return`本页面最后修改于${i(l)},原文已在${i(t)}更新。${e("查看原文",n)}`}}},"/en/":{lang:"en-US",untranslated:{title:"Notice",content:(e,t)=>`This page has not yet been translated${t?`, see how you can help ${e("here",t)}`:""}.`},outdated:{title:"Warning",content:(e,t,l,n)=>{const i=["January","February","March","April","May","June","July","August","September","October","November","December"],r=o=>{const c=new Date(o);return`${c.getDate()} ${i[c.getMonth()]} ${c.getFullYear()}`};return`This translation was modified on ${r(l)} and an updated version (${r(t)}) is available on the source page. ${e("View the original page",n)}`}}},"/ru/":{lang:"en-US",untranslated:{title:"Notice",content:(e,t)=>`This page has not yet been translated${t?`, see how you can help ${e("here",t)}`:""}.`},outdated:{title:"Warning",content:(e,t,l,n)=>{const i=["January","February","March","April","May","June","July","August","September","October","November","December"],r=o=>{const c=new Date(o);return`${c.getDate()} ${i[c.getMonth()]} ${c.getFullYear()}`};return`This translation was modified on ${r(l)} and an updated version (${r(t)}) is available on the source page. ${e("View the original page",n)}`}}}};var Ff=["custom-container","hint-container"],Nf=["custom-container-title","hint-container-title"],Hf=Ff,Tl="/",Mf=Nf,ho=Cf,vo=Vf,$f=()=>C(()=>{const{outdated:e=!1,pathLocale:t=Tl,sourceLink:l,sourceUpdatedTime:n,untranslated:i=!1,updatedTime:r}=Gt().value.i18n??{},o=vo[t??Tl]??vo[Tl],c=ho[t]??ho[Tl];return{isOutdated:e,isUntranslated:i,locale:o,options:{baseLocalePath:Tl,containerClass:Hf,titleClass:Mf},pathLocale:t,sourceLink:l,sourceUpdatedTime:n,translationGuide:c,updatedTime:r}}),Qi=_e({__name:"I18nTip",setup(e,{expose:t}){t();const l=(m,x)=>`${m}`,n=(m,x,A)=>{switch(m){case"untranslated":return x.untranslated.content(l,A.translationGuide);case"outdated":return!A.updatedTime||!A.sourceUpdatedTime||!A.sourceLink?null:x.outdated.content(l,A.sourceUpdatedTime,A.updatedTime,A.sourceLink);default:return null}},i=$f(),{containerClass:r,titleClass:o}=i.value.options,c=C(()=>i.value.locale),a=C(()=>i.value.isUntranslated||i.value.isOutdated),u=C(()=>i.value.isUntranslated?"untranslated":"outdated"),d=C(()=>u.value==="untranslated"?"tip":"warning"),v=C(()=>c.value[u.value].title),_=C(()=>a.value?n(u.value,c.value,i.value):null),g={linkRenderer:l,getContent:n,i18nData:i,containerClass:r,titleClass:o,locale:c,showTips:a,tipType:u,containerType:d,containerTitle:v,containerContent:_};return Object.defineProperty(g,"__isScriptSetup",{enumerable:!1,value:!0}),g}}),Bf=["innerHTML"];function Wf(e,t,l,n,i,r){return n.showTips&&n.containerContent?(W(),ee("div",{key:0,class:$e([...n.containerClass,n.containerType])},[ce("p",{class:$e(n.titleClass)},Pe(n.containerTitle),3),Le("eslint-disable-next-line vue/no-v-html "),ce("p",{innerHTML:n.containerContent},null,8,Bf)],2)):Le("v-if",!0)}Qi.render=Wf;Qi.__file="src/client/components/I18nTip.vue";var Uf=Qi,zf=Et({enhance({app:e}){e.component("I18nTip",Uf)}});const Xf=e=>e instanceof Element?document.activeElement===e&&(["TEXTAREA","SELECT","INPUT"].includes(e.tagName)||e.hasAttribute("contenteditable")):!1,Kf=(e,t)=>t.some(l=>{if(it(l))return l===e.key;const{key:n,ctrl:i=!1,shift:r=!1,alt:o=!1}=l;return n===e.key&&i===e.ctrlKey&&r===e.shiftKey&&o===e.altKey}),qf=/[^\x00-\x7F]/,Gf=e=>e.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t),_o=e=>e.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),fo=(e,t)=>{const l=t.join(" "),n=Gf(e);if(qf.test(e))return n.some(o=>l.toLowerCase().indexOf(o)>-1);const i=e.endsWith(" ");return new RegExp(n.map((o,c)=>n.length===c+1&&!i?`(?=.*\\b${_o(o)})`:`(?=.*\\b${_o(o)}\\b)`).join("")+".+","gi").test(l)},Yf=({input:e,hotKeys:t})=>{if(t.value.length===0)return;const l=n=>{e.value&&Kf(n,t.value)&&!Xf(n.target)&&(n.preventDefault(),e.value.focus())};We(()=>{document.addEventListener("keydown",l)}),ql(()=>{document.removeEventListener("keydown",l)})},Qf=[{title:"",headers:[{level:2,title:"XTLS ? Xray ? V2Ray ?",slug:"xtls-xray-v2ray",link:"#xtls-xray-v2ray",children:[{level:3,title:"我们是谁?",slug:"我们是谁",link:"#我们是谁",children:[]},{level:3,title:"帮助 Xray 变得更强",slug:"帮助-xray-变得更强",link:"#帮助-xray-变得更强",children:[]},{level:3,title:"Telegram",slug:"telegram",link:"#telegram",children:[]},{level:3,title:"致谢",slug:"致谢",link:"#致谢",children:[]},{level:3,title:"更多关于 Project X",slug:"更多关于-project-x",link:"#更多关于-project-x",children:[]},{level:3,title:"License",slug:"license",link:"#license",children:[]},{level:3,title:"Stargazers over time",slug:"stargazers-over-time",link:"#stargazers-over-time",children:[]}]}],path:"/",pathLocale:"/",extraFields:[]},{title:"大史记",headers:[{level:2,title:"2021.4.6",slug:"_2021-4-6",link:"#_2021-4-6",children:[]},{level:2,title:"2021.4.4",slug:"_2021-4-4",link:"#_2021-4-4",children:[]},{level:2,title:"2021.4.1 v1.4.2",slug:"_2021-4-1-v1-4-2",link:"#_2021-4-1-v1-4-2",children:[]},{level:2,title:"2021.3.25",slug:"_2021-3-25",link:"#_2021-3-25",children:[]},{level:2,title:"2021.3.15",slug:"_2021-3-15",link:"#_2021-3-15",children:[]},{level:2,title:"2021.3.14 v1.4.0",slug:"_2021-3-14-v1-4-0",link:"#_2021-3-14-v1-4-0",children:[]},{level:2,title:"2021.3.3 1.3.1",slug:"_2021-3-3-1-3-1",link:"#_2021-3-3-1-3-1",children:[]},{level:2,title:"2021.2.14 1.3.0",slug:"_2021-2-14-1-3-0",link:"#_2021-2-14-1-3-0",children:[]},{level:2,title:"2021.01.31 1.2.4",slug:"_2021-01-31-1-2-4",link:"#_2021-01-31-1-2-4",children:[]},{level:2,title:"2021.01.25",slug:"_2021-01-25",link:"#_2021-01-25",children:[]},{level:2,title:"2021.01.22 1.2.3",slug:"_2021-01-22-1-2-3",link:"#_2021-01-22-1-2-3",children:[]},{level:2,title:"2021.01.19",slug:"_2021-01-19",link:"#_2021-01-19",children:[]},{level:2,title:"2021.01.17",slug:"_2021-01-17",link:"#_2021-01-17",children:[]},{level:2,title:"2021.01.15 1.2.2",slug:"_2021-01-15-1-2-2",link:"#_2021-01-15-1-2-2",children:[]},{level:2,title:"2021.01.12",slug:"_2021-01-12",link:"#_2021-01-12",children:[]},{level:2,title:"2021.01.10 1.2.1",slug:"_2021-01-10-1-2-1",link:"#_2021-01-10-1-2-1",children:[]},{level:2,title:"2021.01.07",slug:"_2021-01-07",link:"#_2021-01-07",children:[]},{level:2,title:"2021.01.05",slug:"_2021-01-05",link:"#_2021-01-05",children:[]},{level:2,title:"2021.01.03",slug:"_2021-01-03",link:"#_2021-01-03",children:[]},{level:2,title:"2021.01.01",slug:"_2021-01-01",link:"#_2021-01-01",children:[]},{level:2,title:"2020.12.29",slug:"_2020-12-29",link:"#_2020-12-29",children:[]},{level:2,title:"2020.12.25 1.1.5",slug:"_2020-12-25-1-1-5",link:"#_2020-12-25-1-1-5",children:[]},{level:2,title:"2020.12.24",slug:"_2020-12-24",link:"#_2020-12-24",children:[]},{level:2,title:"2020.12.23",slug:"_2020-12-23",link:"#_2020-12-23",children:[]},{level:2,title:"2020.12.21",slug:"_2020-12-21",link:"#_2020-12-21",children:[]},{level:2,title:"2020.12.18 1.1.4",slug:"_2020-12-18-1-1-4",link:"#_2020-12-18-1-1-4",children:[]},{level:2,title:"2020.12.17",slug:"_2020-12-17",link:"#_2020-12-17",children:[]},{level:2,title:"2020.12.15",slug:"_2020-12-15",link:"#_2020-12-15",children:[]},{level:2,title:"2020.12.11 1.1.3",slug:"_2020-12-11-1-1-3",link:"#_2020-12-11-1-1-3",children:[]},{level:2,title:"2020.12.06 1.1.2",slug:"_2020-12-06-1-1-2",link:"#_2020-12-06-1-1-2",children:[]},{level:2,title:"2020.12.04",slug:"_2020-12-04",link:"#_2020-12-04",children:[]},{level:2,title:"2020.11.27",slug:"_2020-11-27",link:"#_2020-11-27",children:[]},{level:2,title:"2020.11.25 1.0.0",slug:"_2020-11-25-1-0-0",link:"#_2020-11-25-1-0-0",children:[]},{level:2,title:"2020.11.23",slug:"_2020-11-23",link:"#_2020-11-23",children:[]}],path:"/about/news.html",pathLocale:"/",extraFields:[]},{title:"配置文件",headers:[{level:2,title:"概述",slug:"概述",link:"#概述",children:[]},{level:2,title:"基础配置模块",slug:"基础配置模块",link:"#基础配置模块",children:[]}],path:"/config/",pathLocale:"/",extraFields:[]},{title:"API 接口",headers:[{level:2,title:"ApiObject",slug:"apiobject",link:"#apiobject",children:[]},{level:2,title:"相关配置",slug:"相关配置",link:"#相关配置",children:[]},{level:2,title:"支持的 API 列表",slug:"支持的-api-列表",link:"#支持的-api-列表",children:[{level:3,title:"HandlerService",slug:"handlerservice",link:"#handlerservice",children:[]},{level:3,title:"RoutingService",slug:"routingservice",link:"#routingservice",children:[]},{level:3,title:"LoggerService",slug:"loggerservice",link:"#loggerservice",children:[]},{level:3,title:"StatsService",slug:"statsservice",link:"#statsservice",children:[]},{level:3,title:"ReflectionService",slug:"reflectionservice",link:"#reflectionservice",children:[]}]},{level:2,title:"API 调用示例",slug:"api-调用示例",link:"#api-调用示例",children:[]}],path:"/config/api.html",pathLocale:"/",extraFields:[]},{title:"内置 DNS 服务器",headers:[{level:2,title:"DNS 服务器",slug:"dns-服务器",link:"#dns-服务器",children:[]},{level:2,title:"DNS 处理流程",slug:"dns-处理流程",link:"#dns-处理流程",children:[]},{level:2,title:"DnsObject",slug:"dnsobject",link:"#dnsobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/dns.html",pathLocale:"/",extraFields:[]},{title:"FakeDNS",headers:[{level:2,title:"FakeDNSObject",slug:"fakednsobject",link:"#fakednsobject",children:[{level:3,title:"如何使用?",slug:"如何使用",link:"#如何使用",children:[]},{level:3,title:"与其它类型 DNS 搭配使用",slug:"与其它类型-dns-搭配使用",link:"#与其它类型-dns-搭配使用",children:[]}]}],path:"/config/fakedns.html",pathLocale:"/",extraFields:[]},{title:"入站代理",headers:[{level:2,title:"InboundObject",slug:"inboundobject",link:"#inboundobject",children:[{level:3,title:"SniffingObject",slug:"sniffingobject",link:"#sniffingobject",children:[]},{level:3,title:"AllocateObject",slug:"allocateobject",link:"#allocateobject",children:[]}]}],path:"/config/inbound.html",pathLocale:"/",extraFields:[]},{title:"日志配置",headers:[{level:2,title:"LogObject",slug:"logobject",link:"#logobject",children:[]}],path:"/config/log.html",pathLocale:"/",extraFields:[]},{title:"Metrics",headers:[{level:2,title:"相关配置",slug:"相关配置",link:"#相关配置",children:[]},{level:2,title:"使用方法",slug:"使用方法",link:"#使用方法",children:[{level:3,title:"pprof",slug:"pprof",link:"#pprof",children:[]},{level:3,title:"expvars",slug:"expvars",link:"#expvars",children:[]},{level:3,title:"Additional",slug:"additional",link:"#additional",children:[]}]}],path:"/config/metrics.html",pathLocale:"/",extraFields:[]},{title:"连接观测",headers:[{level:2,title:"ObservatoryObject",slug:"observatoryobject",link:"#observatoryobject",children:[]},{level:2,title:"BurstObservatoryObject",slug:"burstobservatoryobject",link:"#burstobservatoryobject",children:[{level:3,title:"PingConfigObject",slug:"pingconfigobject",link:"#pingconfigobject",children:[]}]}],path:"/config/observatory.html",pathLocale:"/",extraFields:[]},{title:"出站代理(Mux、XUDP)",headers:[{level:2,title:"OutboundObject",slug:"outboundobject",link:"#outboundobject",children:[{level:3,title:"ProxySettingsObject",slug:"proxysettingsobject",link:"#proxysettingsobject",children:[]},{level:3,title:"MuxObject",slug:"muxobject",link:"#muxobject",children:[]}]}],path:"/config/outbound.html",pathLocale:"/",extraFields:[]},{title:"本地策略",headers:[{level:2,title:"PolicyObject",slug:"policyobject",link:"#policyobject",children:[{level:3,title:"LevelPolicyObject",slug:"levelpolicyobject",link:"#levelpolicyobject",children:[]},{level:3,title:"SystemPolicyObject",slug:"systempolicyobject",link:"#systempolicyobject",children:[]}]}],path:"/config/policy.html",pathLocale:"/",extraFields:[]},{title:"反向代理",headers:[{level:2,title:"ReverseObject",slug:"reverseobject",link:"#reverseobject",children:[{level:3,title:"BridgeObject",slug:"bridgeobject",link:"#bridgeobject",children:[]},{level:3,title:"PortalObject",slug:"portalobject",link:"#portalobject",children:[]}]},{level:2,title:"完整配置样例",slug:"完整配置样例",link:"#完整配置样例",children:[{level:3,title:"bridge 配置",slug:"bridge-配置",link:"#bridge-配置",children:[]},{level:3,title:"portal 配置",slug:"portal-配置",link:"#portal-配置",children:[]}]}],path:"/config/reverse.html",pathLocale:"/",extraFields:[]},{title:"路由",headers:[{level:2,title:"RoutingObject",slug:"routingobject",link:"#routingobject",children:[{level:3,title:"RuleObject",slug:"ruleobject",link:"#ruleobject",children:[]},{level:3,title:"BalancerObject",slug:"balancerobject",link:"#balancerobject",children:[]},{level:3,title:"负载均衡配置示例",slug:"负载均衡配置示例",link:"#负载均衡配置示例",children:[]},{level:3,title:"预定义域名列表",slug:"预定义域名列表",link:"#预定义域名列表",children:[]}]}],path:"/config/routing.html",pathLocale:"/",extraFields:[]},{title:"统计信息",headers:[{level:2,title:"StatsObject",slug:"statsobject",link:"#statsobject",children:[]},{level:2,title:"获取统计信息",slug:"获取统计信息",link:"#获取统计信息",children:[]}],path:"/config/stats.html",pathLocale:"/",extraFields:[]},{title:"传输方式(uTLS、REALITY)",headers:[{level:2,title:"TransportObject(已弃用)",slug:"transportobject-已弃用",link:"#transportobject-已弃用",children:[]},{level:2,title:"StreamSettingsObject",slug:"streamsettingsobject",link:"#streamsettingsobject",children:[{level:3,title:"TLSObject",slug:"tlsobject",link:"#tlsobject",children:[]},{level:3,title:"RealityObject",slug:"realityobject",link:"#realityobject",children:[]},{level:3,title:"SockoptObject",slug:"sockoptobject",link:"#sockoptobject",children:[]}]}],path:"/config/transport.html",pathLocale:"/",extraFields:[]},{title:"开发指南",headers:[{level:2,title:"编译文档",slug:"编译文档",link:"#编译文档",children:[]},{level:2,title:"设计思路",slug:"设计思路",link:"#设计思路",children:[]},{level:2,title:"开发规范",slug:"开发规范",link:"#开发规范",children:[]},{level:2,title:"协议详解",slug:"协议详解",link:"#协议详解",children:[{level:3,title:"VLESS 协议",slug:"vless-协议",link:"#vless-协议",children:[]},{level:3,title:"VMess 协议",slug:"vmess-协议",link:"#vmess-协议",children:[]},{level:3,title:"Mux.Cool 协议",slug:"mux-cool-协议",link:"#mux-cool-协议",children:[]},{level:3,title:"mKCP 协议",slug:"mkcp-协议",link:"#mkcp-协议",children:[]}]}],path:"/development/",pathLocale:"/",extraFields:[]},{title:"快速入门",headers:[{level:2,title:"下载安装",slug:"下载安装",link:"#下载安装",children:[]},{level:2,title:"配置运行",slug:"配置运行",link:"#配置运行",children:[]},{level:2,title:"命令参数",slug:"命令参数",link:"#命令参数",children:[]},{level:2,title:"改进文档",slug:"改进文档",link:"#改进文档",children:[]},{level:2,title:"小小白白话文",slug:"小小白白话文",link:"#小小白白话文",children:[]},{level:2,title:"入门技巧",slug:"入门技巧",link:"#入门技巧",children:[]},{level:2,title:"进阶文档",slug:"进阶文档",link:"#进阶文档",children:[]}],path:"/document/",pathLocale:"/",extraFields:[]},{title:"命令参数",headers:[{level:2,title:"获取基本命令",slug:"获取基本命令",link:"#获取基本命令",children:[{level:3,title:"xray run",slug:"xray-run",link:"#xray-run",children:[]},{level:3,title:"xray version",slug:"xray-version",link:"#xray-version",children:[]},{level:3,title:"xray api",slug:"xray-api",link:"#xray-api",children:[]},{level:3,title:"xray convert",slug:"xray-convert",link:"#xray-convert",children:[]},{level:3,title:"xray tls",slug:"xray-tls",link:"#xray-tls",children:[]},{level:3,title:"xray uuid",slug:"xray-uuid",link:"#xray-uuid",children:[]},{level:3,title:"xray x25519",slug:"xray-x25519",link:"#xray-x25519",children:[]},{level:3,title:"xray wg",slug:"xray-wg",link:"#xray-wg",children:[]}]}],path:"/document/command.html",pathLocale:"/",extraFields:[]},{title:"配置运行",headers:[{level:2,title:"服务端配置",slug:"服务端配置",link:"#服务端配置",children:[]},{level:2,title:"客户端配置",slug:"客户端配置",link:"#客户端配置",children:[]},{level:2,title:"运行",slug:"运行",link:"#运行",children:[]}],path:"/document/config.html",pathLocale:"/",extraFields:[]},{title:"为 Project X 的文档贡献",headers:[{level:2,title:"改进文档",slug:"改进文档",link:"#改进文档",children:[]},{level:2,title:"发现问题?",slug:"发现问题",link:"#发现问题",children:[]}],path:"/document/document.html",pathLocale:"/",extraFields:[]},{title:"下载安装",headers:[{level:2,title:"平台支持",slug:"平台支持",link:"#平台支持",children:[]},{level:2,title:"下载 Xray",slug:"下载-xray",link:"#下载-xray",children:[]},{level:2,title:"验证安装包",slug:"验证安装包",link:"#验证安装包",children:[]},{level:2,title:"Windows 安装方式",slug:"windows-安装方式",link:"#windows-安装方式",children:[]},{level:2,title:"macOS 安装方式",slug:"macos-安装方式",link:"#macos-安装方式",children:[]},{level:2,title:"Linux 安装方式",slug:"linux-安装方式",link:"#linux-安装方式",children:[{level:3,title:"安装脚本",slug:"安装脚本",link:"#安装脚本",children:[]},{level:3,title:"Arch Linux",slug:"arch-linux",link:"#arch-linux",children:[]},{level:3,title:"Linuxbrew",slug:"linuxbrew",link:"#linuxbrew",children:[]},{level:3,title:"Debian",slug:"debian",link:"#debian",children:[]},{level:3,title:"Gentoo",slug:"gentoo",link:"#gentoo",children:[]}]},{level:2,title:"Docker 安装方式",slug:"docker-安装方式",link:"#docker-安装方式",children:[{level:3,title:"Docker image 的文件结构",slug:"docker-image-的文件结构",link:"#docker-image-的文件结构",children:[]}]}],path:"/document/install.html",pathLocale:"/",extraFields:[]},{title:"",headers:[{level:2,title:"XTLS? Xray? V2Ray?",slug:"xtls-xray-v2ray",link:"#xtls-xray-v2ray",children:[{level:3,title:"Who are we?",slug:"who-are-we",link:"#who-are-we",children:[]},{level:3,title:"Help Xray become stronger",slug:"help-xray-become-stronger",link:"#help-xray-become-stronger",children:[]},{level:3,title:"Telegram",slug:"telegram",link:"#telegram",children:[]},{level:3,title:"Thanks",slug:"thanks",link:"#thanks",children:[]},{level:3,title:"More about project X",slug:"more-about-project-x",link:"#more-about-project-x",children:[]},{level:3,title:"License",slug:"license",link:"#license",children:[]},{level:3,title:"Stargazers over time",slug:"stargazers-over-time",link:"#stargazers-over-time",children:[]}]}],path:"/en/",pathLocale:"/en/",extraFields:[]},{title:"",headers:[{level:2,title:"XTLS? Xray? V2Ray?",slug:"xtls-xray-v2ray",link:"#xtls-xray-v2ray",children:[{level:3,title:"Кто мы?",slug:"кто-мы",link:"#кто-мы",children:[]},{level:3,title:"Помогите Xray стать сильнее",slug:"помогите-xray-стать-сильнее",link:"#помогите-xray-стать-сильнее",children:[]},{level:3,title:"Telegram",slug:"telegram",link:"#telegram",children:[]},{level:3,title:"Благодарности",slug:"благодарности",link:"#благодарности",children:[]},{level:3,title:"Подробнее о Project X",slug:"подробнее-о-project-x",link:"#подробнее-о-project-x",children:[]},{level:3,title:"Лицензия",slug:"лицензия",link:"#лицензия",children:[]},{level:3,title:"Динамика звезд на GitHub",slug:"динамика-звезд-на-github",link:"#динамика-звезд-на-github",children:[]}]}],path:"/ru/",pathLocale:"/ru/",extraFields:[]},{title:"Browser Dialer",headers:[{level:2,title:"背景",slug:"背景",link:"#背景",children:[]},{level:2,title:"配置方法",slug:"配置方法",link:"#配置方法",children:[]},{level:2,title:"内部通信机制",slug:"内部通信机制",link:"#内部通信机制",children:[]},{level:2,title:"WebSocket",slug:"websocket",link:"#websocket",children:[]},{level:2,title:"SplitHTTP",slug:"splithttp",link:"#splithttp",children:[]}],path:"/config/features/browser_dialer.html",pathLocale:"/",extraFields:[]},{title:"环境变量",headers:[{level:2,title:"资源文件路径",slug:"资源文件路径",link:"#资源文件路径",children:[]},{level:2,title:"配置文件位置",slug:"配置文件位置",link:"#配置文件位置",children:[]},{level:2,title:"多配置目录",slug:"多配置目录",link:"#多配置目录",children:[]}],path:"/config/features/env.html",pathLocale:"/",extraFields:[]},{title:"Fallback 回落",headers:[{level:2,title:"fallbacks 配置",slug:"fallbacks-配置",link:"#fallbacks-配置",children:[{level:3,title:"FallbackObject",slug:"fallbackobject",link:"#fallbackobject",children:[]},{level:3,title:"补充说明",slug:"补充说明",link:"#补充说明",children:[]}]},{level:2,title:"Fallbacks 设计理论",slug:"fallbacks-设计理论",link:"#fallbacks-设计理论",children:[]}],path:"/config/features/fallback.html",pathLocale:"/",extraFields:[]},{title:"多文件配置",headers:[{level:2,title:"多文件启动",slug:"多文件启动",link:"#多文件启动",children:[]},{level:2,title:"规则说明",slug:"规则说明",link:"#规则说明",children:[{level:3,title:"普通对象({})",slug:"普通对象",link:"#普通对象",children:[]},{level:3,title:"数组([])",slug:"数组",link:"#数组",children:[]}]},{level:2,title:"配置例子",slug:"配置例子",link:"#配置例子",children:[]}],path:"/config/features/multiple.html",pathLocale:"/",extraFields:[]},{title:"XTLS 深度剖析",headers:[],path:"/config/features/xtls.html",pathLocale:"/",extraFields:[]},{title:"Dokodemo-Door",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"用处",slug:"用处",link:"#用处",children:[]},{level:2,title:"透明代理配置样例",slug:"透明代理配置样例",link:"#透明代理配置样例",children:[]}],path:"/config/inbounds/dokodemo.html",pathLocale:"/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/config/inbounds/http.html",pathLocale:"/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}],path:"/config/inbounds/shadowsocks.html",pathLocale:"/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/config/inbounds/socks.html",pathLocale:"/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/config/inbounds/trojan.html",pathLocale:"/",extraFields:[]},{title:"VLESS(XTLS Vision Seed)",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/config/inbounds/vless.html",pathLocale:"/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]},{level:3,title:"DetourObject",slug:"detourobject",link:"#detourobject",children:[]},{level:3,title:"DefaultObject",slug:"defaultobject",link:"#defaultobject",children:[]}]}],path:"/config/inbounds/vmess.html",pathLocale:"/",extraFields:[]},{title:"Blackhole",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ResponseObject",slug:"responseobject",link:"#responseobject",children:[]}]}],path:"/config/outbounds/blackhole.html",pathLocale:"/",extraFields:[]},{title:"DNS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]},{level:2,title:"DNS 配置实例",slug:"dns-配置实例",link:"#dns-配置实例",children:[]}],path:"/config/outbounds/dns.html",pathLocale:"/",extraFields:[]},{title:"Freedom",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]}],path:"/config/outbounds/freedom.html",pathLocale:"/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/http.html",pathLocale:"/",extraFields:[]},{title:"Loopback",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"如何使用?",slug:"如何使用",link:"#如何使用",children:[]}]}],path:"/config/outbounds/loopback.html",pathLocale:"/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/shadowsocks.html",pathLocale:"/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/socks.html",pathLocale:"/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/trojan.html",pathLocale:"/",extraFields:[]},{title:"VLESS(XTLS Vision Seed)",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]},{level:3,title:"UserObject",slug:"userobject",link:"#userobject",children:[]}]}],path:"/config/outbounds/vless.html",pathLocale:"/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/vmess.html",pathLocale:"/",extraFields:[]},{title:"Wireguard",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Peers",slug:"peers",link:"#peers",children:[]}]}],path:"/config/outbounds/wireguard.html",pathLocale:"/",extraFields:[]},{title:"Domain Socket",headers:[{level:2,title:"DomainSocketObject",slug:"domainsocketobject",link:"#domainsocketobject",children:[]}],path:"/config/transports/domainsocket.html",pathLocale:"/",extraFields:[]},{title:"gRPC",headers:[{level:2,title:"GRPCObject",slug:"grpcobject",link:"#grpcobject",children:[]}],path:"/config/transports/grpc.html",pathLocale:"/",extraFields:[]},{title:"HTTP/2",headers:[{level:2,title:"HttpObject",slug:"httpobject",link:"#httpobject",children:[]}],path:"/config/transports/h2.html",pathLocale:"/",extraFields:[]},{title:"HTTPUpgrade",headers:[{level:2,title:"HttpUpgradeObject",slug:"httpupgradeobject",link:"#httpupgradeobject",children:[]}],path:"/config/transports/httpupgrade.html",pathLocale:"/",extraFields:[]},{title:"mKCP",headers:[{level:2,title:"KcpObject",slug:"kcpobject",link:"#kcpobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]},{level:2,title:"鸣谢",slug:"鸣谢",link:"#鸣谢",children:[]},{level:2,title:"对 KCP 协议的改进",slug:"对-kcp-协议的改进",link:"#对-kcp-协议的改进",children:[{level:3,title:"更小的协议头",slug:"更小的协议头",link:"#更小的协议头",children:[]},{level:3,title:"确认包重传",slug:"确认包重传",link:"#确认包重传",children:[]},{level:3,title:"连接状态控制",slug:"连接状态控制",link:"#连接状态控制",children:[]}]}],path:"/config/transports/mkcp.html",pathLocale:"/",extraFields:[]},{title:"QUIC",headers:[{level:2,title:"QuicObject",slug:"quicobject",link:"#quicobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]}],path:"/config/transports/quic.html",pathLocale:"/",extraFields:[]},{title:"SplitHTTP(H2、QUIC H3)",headers:[{level:2,title:"SplitHttpObject",slug:"splithttpobject",link:"#splithttpobject",children:[]},{level:2,title:"HTTP 版本",slug:"http-版本",link:"#http-版本",children:[{level:3,title:"客户端行为",slug:"客户端行为",link:"#客户端行为",children:[]},{level:3,title:"服务端行为",slug:"服务端行为",link:"#服务端行为",children:[]},{level:3,title:"小提示",slug:"小提示",link:"#小提示",children:[]}]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]},{level:2,title:"协议细节",slug:"协议细节",link:"#协议细节",children:[]}],path:"/config/transports/splithttp.html",pathLocale:"/",extraFields:[]},{title:"TCP",headers:[{level:2,title:"TcpObject",slug:"tcpobject",link:"#tcpobject",children:[{level:3,title:"NoneHeaderObject",slug:"noneheaderobject",link:"#noneheaderobject",children:[]},{level:3,title:"HttpHeaderObject",slug:"httpheaderobject",link:"#httpheaderobject",children:[]}]}],path:"/config/transports/tcp.html",pathLocale:"/",extraFields:[]},{title:"WebSocket",headers:[{level:2,title:"WebSocketObject",slug:"websocketobject",link:"#websocketobject",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]}],path:"/config/transports/websocket.html",pathLocale:"/",extraFields:[]},{title:"编译文档",headers:[{level:2,title:"前序工作",slug:"前序工作",link:"#前序工作",children:[]},{level:2,title:"拉取 Xray 源代码",slug:"拉取-xray-源代码",link:"#拉取-xray-源代码",children:[]},{level:2,title:"构建二进制",slug:"构建二进制",link:"#构建二进制",children:[{level:3,title:"Windows(Powershell):",slug:"windows-powershell",link:"#windows-powershell",children:[]},{level:3,title:"macOS, Linux:",slug:"macos-linux",link:"#macos-linux",children:[]}]},{level:2,title:"交叉编译:",slug:"交叉编译",link:"#交叉编译",children:[]},{level:2,title:"可复现构建:",slug:"可复现构建",link:"#可复现构建",children:[]}],path:"/development/intro/compile.html",pathLocale:"/",extraFields:[]},{title:"设计目标",headers:[{level:2,title:"架构",slug:"架构",link:"#架构",children:[{level:3,title:"应用层",slug:"应用层",link:"#应用层",children:[]},{level:3,title:"代理层",slug:"代理层",link:"#代理层",children:[]},{level:3,title:"传输层",slug:"传输层",link:"#传输层",children:[]}]}],path:"/development/intro/design.html",pathLocale:"/",extraFields:[]},{title:"开发规范",headers:[{level:2,title:"基本",slug:"基本",link:"#基本",children:[{level:3,title:"版本控制",slug:"版本控制",link:"#版本控制",children:[]},{level:3,title:"分支(Branch)",slug:"分支-branch",link:"#分支-branch",children:[]},{level:3,title:"发布(Release)",slug:"发布-release",link:"#发布-release",children:[]},{level:3,title:"引用其它项目",slug:"引用其它项目",link:"#引用其它项目",children:[]}]},{level:2,title:"开发流程",slug:"开发流程",link:"#开发流程",children:[{level:3,title:"写代码之前",slug:"写代码之前",link:"#写代码之前",children:[]},{level:3,title:"修改代码",slug:"修改代码",link:"#修改代码",children:[]},{level:3,title:"Pull Request",slug:"pull-request",link:"#pull-request",children:[]},{level:3,title:"对代码的修改",slug:"对代码的修改",link:"#对代码的修改",children:[]}]},{level:2,title:"Xray 编码规范",slug:"xray-编码规范",link:"#xray-编码规范",children:[{level:3,title:"代码结构",slug:"代码结构",link:"#代码结构",children:[]},{level:3,title:"编码规范",slug:"编码规范",link:"#编码规范",children:[]}]}],path:"/development/intro/guide.html",pathLocale:"/",extraFields:[]},{title:"mKCP 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"数据格式",slug:"数据格式",link:"#数据格式",children:[{level:3,title:"数据包",slug:"数据包",link:"#数据包",children:[]},{level:3,title:"数据片段",slug:"数据片段",link:"#数据片段",children:[]},{level:3,title:"确认片段",slug:"确认片段",link:"#确认片段",children:[]},{level:3,title:"心跳片段",slug:"心跳片段",link:"#心跳片段",children:[]}]}],path:"/development/protocols/mkcp.html",pathLocale:"/",extraFields:[]},{title:"Mux.Cool 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[{level:3,title:"客户端行为",slug:"客户端行为",link:"#客户端行为",children:[]},{level:3,title:"服务器端行为",slug:"服务器端行为",link:"#服务器端行为",children:[]}]},{level:2,title:"传输格式",slug:"传输格式",link:"#传输格式",children:[{level:3,title:"帧格式",slug:"帧格式",link:"#帧格式",children:[]},{level:3,title:"元数据",slug:"元数据",link:"#元数据",children:[]},{level:3,title:"新建子连接 (New)",slug:"新建子连接-new",link:"#新建子连接-new",children:[]},{level:3,title:"保持子连接 (Keep)",slug:"保持子连接-keep",link:"#保持子连接-keep",children:[]},{level:3,title:"关闭子连接 (End)",slug:"关闭子连接-end",link:"#关闭子连接-end",children:[]},{level:3,title:"保持连接 (KeepAlive)",slug:"保持连接-keepalive",link:"#保持连接-keepalive",children:[]}]},{level:2,title:"应用",slug:"应用",link:"#应用",children:[]}],path:"/development/protocols/muxcool.html",pathLocale:"/",extraFields:[]},{title:"VLESS 协议",headers:[{level:2,title:"Request & Response",slug:"request-response",link:"#request-response",children:[]},{level:2,title:"ProtoBuf",slug:"protobuf",link:"#protobuf",children:[]},{level:2,title:"Schedulers Flow",slug:"schedulers-flow",link:"#schedulers-flow",children:[]},{level:2,title:"Encryption",slug:"encryption",link:"#encryption",children:[]},{level:2,title:"UDP issues",slug:"udp-issues",link:"#udp-issues",children:[]},{level:2,title:"客户端开发指引",slug:"客户端开发指引",link:"#客户端开发指引",children:[]},{level:2,title:"VLESS 分享链接标准",slug:"vless-分享链接标准",link:"#vless-分享链接标准",children:[]}],path:"/development/protocols/vless.html",pathLocale:"/",extraFields:[]},{title:"VMess 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"用户 ID",slug:"用户-id",link:"#用户-id",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"客户端请求",slug:"客户端请求",link:"#客户端请求",children:[{level:3,title:"认证信息",slug:"认证信息",link:"#认证信息",children:[]},{level:3,title:"指令部分",slug:"指令部分",link:"#指令部分",children:[]},{level:3,title:"数据部分",slug:"数据部分",link:"#数据部分",children:[]}]},{level:2,title:"服务器应答",slug:"服务器应答",link:"#服务器应答",children:[{level:3,title:"动态端口指令",slug:"动态端口指令",link:"#动态端口指令",children:[]}]},{level:2,title:"注释",slug:"注释",link:"#注释",children:[]}],path:"/development/protocols/vmess.html",pathLocale:"/",extraFields:[]},{title:"小小白白话文",headers:[],path:"/document/level-0/",pathLocale:"/",extraFields:[]},{title:"【第 1 章】 小小白白话文",headers:[{level:2,title:"1.1 这篇文档是写给谁的?",slug:"_1-1-这篇文档是写给谁的",link:"#_1-1-这篇文档是写给谁的",children:[]},{level:2,title:"1.2 这篇文档不是写给谁的?",slug:"_1-2-这篇文档不是写给谁的",link:"#_1-2-这篇文档不是写给谁的",children:[]},{level:2,title:"1.3 郑重声明及其他声明",slug:"_1-3-郑重声明及其他声明",link:"#_1-3-郑重声明及其他声明",children:[]},{level:2,title:"1.4 为什么自建是个难题?",slug:"_1-4-为什么自建是个难题",link:"#_1-4-为什么自建是个难题",children:[]},{level:2,title:"1.5 “用机场不就行了?”",slug:"_1-5-用机场不就行了",link:"#_1-5-用机场不就行了",children:[]},{level:2,title:"1.6 那么你到底要不要自建呢?",slug:"_1-6-那么你到底要不要自建呢",link:"#_1-6-那么你到底要不要自建呢",children:[]},{level:2,title:"1.7 题外啰嗦几句",slug:"_1-7-题外啰嗦几句",link:"#_1-7-题外啰嗦几句",children:[]},{level:2,title:"1.8 你的进度",slug:"_1-8-你的进度",link:"#_1-8-你的进度",children:[]}],path:"/document/level-0/ch01-preface.html",pathLocale:"/",extraFields:[]},{title:"【第 2 章】原料准备篇",headers:[{level:2,title:"2.1 获取一台 VPS",slug:"_2-1-获取一台-vps",link:"#_2-1-获取一台-vps",children:[]},{level:2,title:"2.2 获取一个心仪的域名",slug:"_2-2-获取一个心仪的域名",link:"#_2-2-获取一个心仪的域名",children:[]},{level:2,title:"2.3 你本地电脑上需要安装的软件",slug:"_2-3-你本地电脑上需要安装的软件",link:"#_2-3-你本地电脑上需要安装的软件",children:[]},{level:2,title:"2.4 你的进度",slug:"_2-4-你的进度",link:"#_2-4-你的进度",children:[]}],path:"/document/level-0/ch02-preparation.html",pathLocale:"/",extraFields:[]},{title:"【第 3 章】远程登录篇",headers:[{level:2,title:"3.1 远程登录 VPS (PuTTY)",slug:"_3-1-远程登录-vps-putty",link:"#_3-1-远程登录-vps-putty",children:[]},{level:2,title:"3.2 成功登录 SSH!初识命令行界面!",slug:"_3-2-成功登录-ssh-初识命令行界面",link:"#_3-2-成功登录-ssh-初识命令行界面",children:[]},{level:2,title:"3.3 第一次更新 Linux 的软件!",slug:"_3-3-第一次更新-linux-的软件",link:"#_3-3-第一次更新-linux-的软件",children:[]},{level:2,title:"3.4 你的进度",slug:"_3-4-你的进度",link:"#_3-4-你的进度",children:[]}],path:"/document/level-0/ch03-ssh.html",pathLocale:"/",extraFields:[]},{title:"【第 4 章】安全防护篇",headers:[{level:2,title:"4.1 为什么要做安全防护",slug:"_4-1-为什么要做安全防护",link:"#_4-1-为什么要做安全防护",children:[]},{level:2,title:"4.2 具体的风险到底是什么",slug:"_4-2-具体的风险到底是什么",link:"#_4-2-具体的风险到底是什么",children:[]},{level:2,title:"4.3 我们要做的安全防护有哪些",slug:"_4-3-我们要做的安全防护有哪些",link:"#_4-3-我们要做的安全防护有哪些",children:[]},{level:2,title:"4.4 将 SSH 远程登录端口修改为非 22 端口",slug:"_4-4-将-ssh-远程登录端口修改为非-22-端口",link:"#_4-4-将-ssh-远程登录端口修改为非-22-端口",children:[]},{level:2,title:"4.5 建立非 root 的新用户",slug:"_4-5-建立非-root-的新用户",link:"#_4-5-建立非-root-的新用户",children:[]},{level:2,title:"4.6 禁用 root 用户 SSH 远程登录",slug:"_4-6-禁用-root-用户-ssh-远程登录",link:"#_4-6-禁用-root-用户-ssh-远程登录",children:[]},{level:2,title:"4.7 使用 RSA 密钥登录并禁用密码登录",slug:"_4-7-使用-rsa-密钥登录并禁用密码登录",link:"#_4-7-使用-rsa-密钥登录并禁用密码登录",children:[]},{level:2,title:"4.8 你的进度",slug:"_4-8-你的进度",link:"#_4-8-你的进度",children:[]}],path:"/document/level-0/ch04-security.html",pathLocale:"/",extraFields:[]},{title:"【第 5 章】网站建设篇",headers:[{level:2,title:"5.1 为什么要做一个网站?",slug:"_5-1-为什么要做一个网站",link:"#_5-1-为什么要做一个网站",children:[]},{level:2,title:"5.2 登录 VPS、安装运行 Nginx",slug:"_5-2-登录-vps、安装运行-nginx",link:"#_5-2-登录-vps、安装运行-nginx",children:[]},{level:2,title:"5.3 创建一个最简单的网页",slug:"_5-3-创建一个最简单的网页",link:"#_5-3-创建一个最简单的网页",children:[]},{level:2,title:"5.4 常见错误的说明",slug:"_5-4-常见错误的说明",link:"#_5-4-常见错误的说明",children:[]},{level:2,title:"5.5 你的进度",slug:"_5-5-你的进度",link:"#_5-5-你的进度",children:[]}],path:"/document/level-0/ch05-webpage.html",pathLocale:"/",extraFields:[]},{title:"【第 6 章】证书管理篇",headers:[{level:2,title:"6.1 申请 TLS 证书",slug:"_6-1-申请-tls-证书",link:"#_6-1-申请-tls-证书",children:[]},{level:2,title:"6.2 安装 acme.sh",slug:"_6-2-安装-acme-sh",link:"#_6-2-安装-acme-sh",children:[]},{level:2,title:"6.3 测试证书申请",slug:"_6-3-测试证书申请",link:"#_6-3-测试证书申请",children:[]},{level:2,title:"6.4 正式证书申请",slug:"_6-4-正式证书申请",link:"#_6-4-正式证书申请",children:[]},{level:2,title:"6.5 证书安装",slug:"_6-5-证书安装",link:"#_6-5-证书安装",children:[]},{level:2,title:"6.6 你的进度",slug:"_6-6-你的进度",link:"#_6-6-你的进度",children:[]}],path:"/document/level-0/ch06-certificates.html",pathLocale:"/",extraFields:[]},{title:"【第 7 章】Xray 服务器篇",headers:[{level:2,title:"7.1 博观而约取,厚积而薄发",slug:"_7-1-博观而约取-厚积而薄发",link:"#_7-1-博观而约取-厚积而薄发",children:[]},{level:2,title:"7.2 安装 Xray",slug:"_7-2-安装-xray",link:"#_7-2-安装-xray",children:[]},{level:2,title:"7.3 给 Xray 配置 TLS 证书",slug:"_7-3-给-xray-配置-tls-证书",link:"#_7-3-给-xray-配置-tls-证书",children:[]},{level:2,title:"7.4 配置 Xray",slug:"_7-4-配置-xray",link:"#_7-4-配置-xray",children:[]},{level:2,title:"7.5 启动 Xray 服务!!(并查看服务状态)",slug:"_7-5-启动-xray-服务-并查看服务状态",link:"#_7-5-启动-xray-服务-并查看服务状态",children:[]},{level:2,title:"7.6 回顾 systemd 进行基本的服务管理",slug:"_7-6-回顾-systemd-进行基本的服务管理",link:"#_7-6-回顾-systemd-进行基本的服务管理",children:[]},{level:2,title:"7.7 服务器优化之一:开启 BBR",slug:"_7-7-服务器优化之一-开启-bbr",link:"#_7-7-服务器优化之一-开启-bbr",children:[]},{level:2,title:"7.8 服务器优化之二:开启 HTTP 自动跳转 HTTPS",slug:"_7-8-服务器优化之二-开启-http-自动跳转-https",link:"#_7-8-服务器优化之二-开启-http-自动跳转-https",children:[]},{level:2,title:"7.9 服务器优化之三:更丰富的回落",slug:"_7-9-服务器优化之三-更丰富的回落",link:"#_7-9-服务器优化之三-更丰富的回落",children:[]},{level:2,title:"7.10 你的进度",slug:"_7-10-你的进度",link:"#_7-10-你的进度",children:[]},{level:2,title:"7.11 重要勘误",slug:"_7-11-重要勘误",link:"#_7-11-重要勘误",children:[]}],path:"/document/level-0/ch07-xray-server.html",pathLocale:"/",extraFields:[]},{title:"【第 8 章】Xray 客户端篇",headers:[{level:2,title:"8.1 Xray 的工作原理简述",slug:"_8-1-xray-的工作原理简述",link:"#_8-1-xray-的工作原理简述",children:[]},{level:2,title:"8.2 客户端与服务器端正确连接",slug:"_8-2-客户端与服务器端正确连接",link:"#_8-2-客户端与服务器端正确连接",children:[]},{level:2,title:"8.3 附加题 1:在 PC 端手工配置 xray-core",slug:"_8-3-附加题-1-在-pc-端手工配置-xray-core",link:"#_8-3-附加题-1-在-pc-端手工配置-xray-core",children:[]},{level:2,title:"8.4 附加题 2:在 PC 端手工运行 xray-core",slug:"_8-4-附加题-2-在-pc-端手工运行-xray-core",link:"#_8-4-附加题-2-在-pc-端手工运行-xray-core",children:[]},{level:2,title:"8.5 附加题 3:在 PC 端开机自动运行 xray-core",slug:"_8-5-附加题-3-在-pc-端开机自动运行-xray-core",link:"#_8-5-附加题-3-在-pc-端开机自动运行-xray-core",children:[]},{level:2,title:"8.6 圆满完成!",slug:"_8-6-圆满完成",link:"#_8-6-圆满完成",children:[]},{level:2,title:"8.7 TO INFINITY AND BEYOND!",slug:"_8-7-to-infinity-and-beyond",link:"#_8-7-to-infinity-and-beyond",children:[]}],path:"/document/level-0/ch08-xray-clients.html",pathLocale:"/",extraFields:[]},{title:"【第 9 章】附录",headers:[{level:2,title:"1. 小小白白 Linux 基础命令索引",slug:"_1-小小白白-linux-基础命令索引",link:"#_1-小小白白-linux-基础命令索引",children:[]},{level:2,title:"2. 小小白白 Linux 重要配置文件索引",slug:"_2-小小白白-linux-重要配置文件索引",link:"#_2-小小白白-linux-重要配置文件索引",children:[]},{level:2,title:"3. 小小白白 Xray 重要文件索引",slug:"_3-小小白白-xray-重要文件索引",link:"#_3-小小白白-xray-重要文件索引",children:[]}],path:"/document/level-0/ch09-appendix.html",pathLocale:"/",extraFields:[]},{title:"入门技巧",headers:[],path:"/document/level-1/",pathLocale:"/",extraFields:[]},{title:"回落 (fallbacks) 功能简析",headers:[{level:2,title:"1. 回顾《小小白白话文》中的回落",slug:"_1-回顾《小小白白话文》中的回落",link:"#_1-回顾《小小白白话文》中的回落",children:[]},{level:2,title:"2. 重新认识回落 (WHAT, HOW v1)",slug:"_2-重新认识回落-what-how-v1",link:"#_2-重新认识回落-what-how-v1",children:[]},{level:2,title:"3. 为什么要回落 (WHY v1)",slug:"_3-为什么要回落-why-v1",link:"#_3-为什么要回落-why-v1",children:[]},{level:2,title:"4. 重新认识【回落の完全体】 (WHAT, WHY, HOW v2)",slug:"_4-重新认识【回落の完全体】-what-why-how-v2",link:"#_4-重新认识【回落の完全体】-what-why-how-v2",children:[]},{level:2,title:"5. 多层回落示例及解读",slug:"_5-多层回落示例及解读",link:"#_5-多层回落示例及解读",children:[{level:3,title:"5.1 首先,我将服务器端配置的 443 监听段摘抄如下:",slug:"_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",link:"#_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",children:[]},{level:3,title:"5.2 后续监听处理的配置段摘抄如下:",slug:"_5-2-后续监听处理的配置段摘抄如下",link:"#_5-2-后续监听处理的配置段摘抄如下",children:[]}]},{level:2,title:"6. 结语",slug:"_6-结语",link:"#_6-结语",children:[]},{level:2,title:"7. 附加题",slug:"_7-附加题",link:"#_7-附加题",children:[]}],path:"/document/level-1/fallbacks-lv1.html",pathLocale:"/",extraFields:[]},{title:"SNI 回落",headers:[{level:2,title:"应用情景",slug:"应用情景",link:"#应用情景",children:[]},{level:2,title:"SNI 简介",slug:"sni-简介",link:"#sni-简介",children:[]},{level:2,title:"思路",slug:"思路",link:"#思路",children:[]},{level:2,title:"添加 DNS 记录",slug:"添加-dns-记录",link:"#添加-dns-记录",children:[]},{level:2,title:"申请 TLS 证书",slug:"申请-tls-证书",link:"#申请-tls-证书",children:[]},{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"Nginx 配置",slug:"nginx-配置",link:"#nginx-配置",children:[]},{level:2,title:"Caddy 配置",slug:"caddy-配置",link:"#caddy-配置",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]},{level:2,title:"引用",slug:"引用",link:"#引用",children:[]}],path:"/document/level-1/fallbacks-with-sni.html",pathLocale:"/",extraFields:[]},{title:"路由 (routing) 功能简析(上)",headers:[{level:2,title:"1. 初识【路由】三兄弟",slug:"_1-初识【路由】三兄弟",link:"#_1-初识【路由】三兄弟",children:[]},{level:2,title:"2. 基本功: “兄弟一条心”",slug:"_2-基本功-兄弟一条心",link:"#_2-基本功-兄弟一条心",children:[{level:3,title:"2.1 入站",slug:"_2-1-入站",link:"#_2-1-入站",children:[]},{level:3,title:"2.3 路由",slug:"_2-3-路由",link:"#_2-3-路由",children:[]},{level:3,title:"2.4 路由配置项解析之一:流量筛选的依据",slug:"_2-4-路由配置项解析之一-流量筛选的依据",link:"#_2-4-路由配置项解析之一-流量筛选的依据",children:[]}]},{level:2,title:"3. 小试牛刀: “三分天下” 之 “域名分流”",slug:"_3-小试牛刀-三分天下-之-域名分流",link:"#_3-小试牛刀-三分天下-之-域名分流",children:[{level:3,title:"3.1 入站",slug:"_3-1-入站",link:"#_3-1-入站",children:[]},{level:3,title:"3.2 出站",slug:"_3-2-出站",link:"#_3-2-出站",children:[]},{level:3,title:"3.3 路由",slug:"_3-3-路由",link:"#_3-3-路由",children:[]},{level:3,title:"3.4 简析域名文件: geosite.dat",slug:"_3-4-简析域名文件-geosite-dat",link:"#_3-4-简析域名文件-geosite-dat",children:[]},{level:3,title:"3.5 所以 geosite.dat 到底是什么?不是有个 GFWList 吗?",slug:"_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",link:"#_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",children:[]},{level:3,title:"3.6 军师锦囊藏奇兵:一条隐藏的路由规则",slug:"_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",link:"#_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",children:[]},{level:3,title:"3.7 再看“三分天下”的大地图",slug:"_3-7-再看-三分天下-的大地图",link:"#_3-7-再看-三分天下-的大地图",children:[]}]},{level:2,title:"4. “三分天下” 之 “蜀魏争雄”",slug:"_4-三分天下-之-蜀魏争雄",link:"#_4-三分天下-之-蜀魏争雄",children:[]},{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[]}],path:"/document/level-1/routing-lv1-part1.html",pathLocale:"/",extraFields:[]},{title:"路由 (routing) 功能简析(下)",headers:[{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[{level:3,title:"5.1 基于指定域名分流:[domain], [full] 等",slug:"_5-1-基于指定域名分流-domain-full-等",link:"#_5-1-基于指定域名分流-domain-full-等",children:[]},{level:3,title:"5.2 基于 IP 文件分流:geoip.dat",slug:"_5-2-基于-ip-文件分流-geoip-dat",link:"#_5-2-基于-ip-文件分流-geoip-dat",children:[]},{level:3,title:"5.3 基于指定 IP 地址分流",slug:"_5-3-基于指定-ip-地址分流",link:"#_5-3-基于指定-ip-地址分流",children:[]},{level:3,title:"5.4 基于协议类型分流:[protocol] 等",slug:"_5-4-基于协议类型分流-protocol-等",link:"#_5-4-基于协议类型分流-protocol-等",children:[]},{level:3,title:"5.5 基于更多条件的分流",slug:"_5-5-基于更多条件的分流",link:"#_5-5-基于更多条件的分流",children:[]}]},{level:2,title:"6. “霸业初定”:路由规则整体回顾",slug:"_6-霸业初定-路由规则整体回顾",link:"#_6-霸业初定-路由规则整体回顾",children:[]},{level:2,title:"7. 路由配置常见错误",slug:"_7-路由配置常见错误",link:"#_7-路由配置常见错误",children:[{level:3,title:"7.1 错误示范",slug:"_7-1-错误示范",link:"#_7-1-错误示范",children:[]},{level:3,title:"7.2 正确示范",slug:"_7-2-正确示范",link:"#_7-2-正确示范",children:[]}]},{level:2,title:"8. 明修栈道、暗渡陈仓",slug:"_8-明修栈道、暗渡陈仓",link:"#_8-明修栈道、暗渡陈仓",children:[{level:3,title:'8.1 域名策略: "AsIs"',slug:"_8-1-域名策略-asis",link:"#_8-1-域名策略-asis",children:[]},{level:3,title:'8.2 域名策略: "IPIfNonMatch"',slug:"_8-2-域名策略-ipifnonmatch",link:"#_8-2-域名策略-ipifnonmatch",children:[]},{level:3,title:'8.3 域名策略: "IPOnDemand"',slug:"_8-3-域名策略-ipondemand",link:"#_8-3-域名策略-ipondemand",children:[]}]},{level:2,title:"9. 思考题",slug:"_9-思考题",link:"#_9-思考题",children:[]},{level:2,title:"10. 结语",slug:"_10-结语",link:"#_10-结语",children:[]},{level:2,title:"11. 尾注",slug:"_11-尾注",link:"#_11-尾注",children:[]}],path:"/document/level-1/routing-lv1-part2.html",pathLocale:"/",extraFields:[]},{title:"Xray 的工作模式",headers:[{level:2,title:"单服务器模式",slug:"单服务器模式",link:"#单服务器模式",children:[]},{level:2,title:"桥接模式",slug:"桥接模式",link:"#桥接模式",children:[]},{level:2,title:"工作原理",slug:"工作原理",link:"#工作原理",children:[]}],path:"/document/level-1/work.html",pathLocale:"/",extraFields:[]},{title:"进阶文档",headers:[],path:"/document/level-2/",pathLocale:"/",extraFields:[]},{title:"GID 透明代理",headers:[{level:2,title:"思路",slug:"思路",link:"#思路",children:[]},{level:2,title:"配置过程",slug:"配置过程",link:"#配置过程",children:[{level:3,title:"1. 前期准备",slug:"_1-前期准备",link:"#_1-前期准备",children:[]},{level:3,title:"2. 添加用户(安卓用户请忽略)",slug:"_2-添加用户-安卓用户请忽略",link:"#_2-添加用户-安卓用户请忽略",children:[]},{level:3,title:"3. 配置运行 Xray,配置 iptables 规则",slug:"_3-配置运行-xray-配置-iptables-规则",link:"#_3-配置运行-xray-配置-iptables-规则",children:[]}]},{level:2,title:"下面提供一个实现 tproxy 全局代理的完整配置过程",slug:"下面提供一个实现-tproxy-全局代理的完整配置过程",link:"#下面提供一个实现-tproxy-全局代理的完整配置过程",children:[{level:3,title:"1. 完成 前期准备 和 添加用户",slug:"_1-完成-前期准备-和-添加用户",link:"#_1-完成-前期准备-和-添加用户",children:[]},{level:3,title:"2. 准备 Xray 配置文件",slug:"_2-准备-xray-配置文件",link:"#_2-准备-xray-配置文件",children:[]},{level:3,title:"3. 配置最大文件打开数&运行 Xray 客户端",slug:"_3-配置最大文件打开数-运行-xray-客户端",link:"#_3-配置最大文件打开数-运行-xray-客户端",children:[]},{level:3,title:"4. 设置 iptables 规则",slug:"_4-设置-iptables-规则",link:"#_4-设置-iptables-规则",children:[]}]}],path:"/document/level-2/iptables_gid.html",pathLocale:"/",extraFields:[]},{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹",headers:[{level:2,title:"编译 nginx --with-stream",slug:"编译-nginx-with-stream",link:"#编译-nginx-with-stream",children:[]},{level:2,title:"配置 nginx",slug:"配置-nginx",link:"#配置-nginx",children:[]},{level:2,title:"xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"客户端及服务端启动服务",slug:"客户端及服务端启动服务",link:"#客户端及服务端启动服务",children:[]},{level:2,title:"结束",slug:"结束",link:"#结束",children:[]},{level:2,title:"HTTPS 隧道",slug:"https-隧道",link:"#https-隧道",children:[{level:3,title:"haproxy_client 配置 (运行前去掉注释)",slug:"haproxy-client-配置-运行前去掉注释",link:"#haproxy-client-配置-运行前去掉注释",children:[]},{level:3,title:"haproxy_server 配置 (运行前去掉注释)",slug:"haproxy-server-配置-运行前去掉注释",link:"#haproxy-server-配置-运行前去掉注释",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-1",link:"#xray-配置-1",children:[]}]},{level:2,title:"WebSocket over HTTP/2",slug:"websocket-over-http-2",link:"#websocket-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置",link:"#haproxy-client-配置",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置",link:"#haproxy-server-配置",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-2",link:"#xray-配置-2",children:[]}]},{level:2,title:"gRPC over HTTP/2",slug:"grpc-over-http-2",link:"#grpc-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-1",link:"#haproxy-client-配置-1",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-1",link:"#haproxy-server-配置-1",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-3",link:"#xray-配置-3",children:[]},{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-2",link:"#haproxy-client-配置-2",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-2",link:"#haproxy-server-配置-2",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-4",link:"#xray-配置-4",children:[]}]}],path:"/document/level-2/nginx_or_haproxy_tls_tunnel.html",pathLocale:"/",extraFields:[]},{title:"出站流量重定向",headers:[{level:2,title:"前言",slug:"前言",link:"#前言",children:[]},{level:2,title:"1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)",slug:"_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",link:"#_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",children:[]},{level:2,title:"2、编辑 VPN 配置文件(以 WireGuard 为例)",slug:"_2、编辑-vpn-配置文件-以-wireguard-为例",link:"#_2、编辑-vpn-配置文件-以-wireguard-为例",children:[]},{level:2,title:"3、启用 WireGuard 网络接口",slug:"_3、启用-wireguard-网络接口",link:"#_3、启用-wireguard-网络接口",children:[]},{level:2,title:"4、Xray-core 配置文件修改",slug:"_4、xray-core-配置文件修改",link:"#_4、xray-core-配置文件修改",children:[]},{level:2,title:"5、系统设置配置",slug:"_5、系统设置配置",link:"#_5、系统设置配置",children:[]},{level:2,title:"6、完成 WireGuard 相关设置",slug:"_6、完成-wireguard-相关设置",link:"#_6、完成-wireguard-相关设置",children:[]},{level:2,title:"后记",slug:"后记",link:"#后记",children:[]},{level:2,title:"感谢",slug:"感谢",link:"#感谢",children:[]}],path:"/document/level-2/redirect.html",pathLocale:"/",extraFields:[]},{title:"TProxy 透明代理",headers:[{level:2,title:"开始之前",slug:"开始之前",link:"#开始之前",children:[]},{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"策略路由配置",slug:"策略路由配置",link:"#策略路由配置",children:[]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[]},{level:2,title:"配置永久化与开机自启",slug:"配置永久化与开机自启",link:"#配置永久化与开机自启",children:[]}],path:"/document/level-2/tproxy.html",pathLocale:"/",extraFields:[]},{title:"TProxy 透明代理 (ipv4 and ipv6)",headers:[{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[{level:3,title:"客户端配置",slug:"客户端配置",link:"#客户端配置",children:[]},{level:3,title:"服务端配置",slug:"服务端配置",link:"#服务端配置",children:[]}]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[{level:3,title:"首先设置策略路由",slug:"首先设置策略路由",link:"#首先设置策略路由",children:[]},{level:3,title:"使用 iptables",slug:"使用-iptables",link:"#使用-iptables",children:[]},{level:3,title:"使用 nftables",slug:"使用-nftables",link:"#使用-nftables",children:[]},{level:3,title:"开机自动运行 Netfilter 配置",slug:"开机自动运行-netfilter-配置",link:"#开机自动运行-netfilter-配置",children:[]}]},{level:2,title:"局域网设备上网设置",slug:"局域网设备上网设置",link:"#局域网设备上网设置",children:[{level:3,title:"方法一",slug:"方法一",link:"#方法一",children:[]},{level:3,title:"方法二",slug:"方法二",link:"#方法二",children:[]}]},{level:2,title:"Finally",slug:"finally",link:"#finally",children:[]},{level:2,title:"写在最后",slug:"写在最后",link:"#写在最后",children:[]}],path:"/document/level-2/tproxy_ipv4_and_ipv6.html",pathLocale:"/",extraFields:[]},{title:"流量统计",headers:[{level:2,title:"查看流量信息",slug:"查看流量信息",link:"#查看流量信息",children:[]},{level:2,title:"流量信息的处理",slug:"流量信息的处理",link:"#流量信息的处理",children:[]}],path:"/document/level-2/traffic_stats.html",pathLocale:"/",extraFields:[]},{title:"通过 Cloudflare Warp 增强代理安全性",headers:[{level:2,title:"申请 Warp 账户",slug:"申请-warp-账户",link:"#申请-warp-账户",children:[{level:3,title:"感谢 Cloudflare 推动自由的互联网,现在你可以免费使用 Warp 服务,连接的时候会根据出口自动选择最近的服务器",slug:"感谢-cloudflare-推动自由的互联网-现在你可以免费使用-warp-服务-连接的时候会根据出口自动选择最近的服务器",link:"#感谢-cloudflare-推动自由的互联网-现在你可以免费使用-warp-服务-连接的时候会根据出口自动选择最近的服务器",children:[]}]},{level:2,title:"在服务端分流回国流量至 warp",slug:"在服务端分流回国流量至-warp",link:"#在服务端分流回国流量至-warp",children:[]},{level:2,title:"客户端使用 warp 链式代理",slug:"客户端使用-warp-链式代理",link:"#客户端使用-warp-链式代理",children:[]}],path:"/document/level-2/warp.html",pathLocale:"/",extraFields:[]},{title:"大史记",headers:[{level:2,title:"2021.4.6",slug:"_2021-4-6",link:"#_2021-4-6",children:[]},{level:2,title:"2021.4.4",slug:"_2021-4-4",link:"#_2021-4-4",children:[]},{level:2,title:"2021.4.1 v1.4.2",slug:"_2021-4-1-v1-4-2",link:"#_2021-4-1-v1-4-2",children:[]},{level:2,title:"2021.3.25",slug:"_2021-3-25",link:"#_2021-3-25",children:[]},{level:2,title:"2021.3.15",slug:"_2021-3-15",link:"#_2021-3-15",children:[]},{level:2,title:"2021.3.14 v1.4.0",slug:"_2021-3-14-v1-4-0",link:"#_2021-3-14-v1-4-0",children:[]},{level:2,title:"2021.3.3 1.3.1",slug:"_2021-3-3-1-3-1",link:"#_2021-3-3-1-3-1",children:[]},{level:2,title:"2021.2.14 1.3.0",slug:"_2021-2-14-1-3-0",link:"#_2021-2-14-1-3-0",children:[]},{level:2,title:"2021.01.31 1.2.4",slug:"_2021-01-31-1-2-4",link:"#_2021-01-31-1-2-4",children:[]},{level:2,title:"2021.01.25",slug:"_2021-01-25",link:"#_2021-01-25",children:[]},{level:2,title:"2021.01.22 1.2.3",slug:"_2021-01-22-1-2-3",link:"#_2021-01-22-1-2-3",children:[]},{level:2,title:"2021.01.19",slug:"_2021-01-19",link:"#_2021-01-19",children:[]},{level:2,title:"2021.01.17",slug:"_2021-01-17",link:"#_2021-01-17",children:[]},{level:2,title:"2021.01.15 1.2.2",slug:"_2021-01-15-1-2-2",link:"#_2021-01-15-1-2-2",children:[]},{level:2,title:"2021.01.12",slug:"_2021-01-12",link:"#_2021-01-12",children:[]},{level:2,title:"2021.01.10 1.2.1",slug:"_2021-01-10-1-2-1",link:"#_2021-01-10-1-2-1",children:[]},{level:2,title:"2021.01.07",slug:"_2021-01-07",link:"#_2021-01-07",children:[]},{level:2,title:"2021.01.05",slug:"_2021-01-05",link:"#_2021-01-05",children:[]},{level:2,title:"2021.01.03",slug:"_2021-01-03",link:"#_2021-01-03",children:[]},{level:2,title:"2021.01.01",slug:"_2021-01-01",link:"#_2021-01-01",children:[]},{level:2,title:"2020.12.29",slug:"_2020-12-29",link:"#_2020-12-29",children:[]},{level:2,title:"2020.12.25 1.1.5",slug:"_2020-12-25-1-1-5",link:"#_2020-12-25-1-1-5",children:[]},{level:2,title:"2020.12.24",slug:"_2020-12-24",link:"#_2020-12-24",children:[]},{level:2,title:"2020.12.23",slug:"_2020-12-23",link:"#_2020-12-23",children:[]},{level:2,title:"2020.12.21",slug:"_2020-12-21",link:"#_2020-12-21",children:[]},{level:2,title:"2020.12.18 1.1.4",slug:"_2020-12-18-1-1-4",link:"#_2020-12-18-1-1-4",children:[]},{level:2,title:"2020.12.17",slug:"_2020-12-17",link:"#_2020-12-17",children:[]},{level:2,title:"2020.12.15",slug:"_2020-12-15",link:"#_2020-12-15",children:[]},{level:2,title:"2020.12.11 1.1.3",slug:"_2020-12-11-1-1-3",link:"#_2020-12-11-1-1-3",children:[]},{level:2,title:"2020.12.06 1.1.2",slug:"_2020-12-06-1-1-2",link:"#_2020-12-06-1-1-2",children:[]},{level:2,title:"2020.12.04",slug:"_2020-12-04",link:"#_2020-12-04",children:[]},{level:2,title:"2020.11.27",slug:"_2020-11-27",link:"#_2020-11-27",children:[]},{level:2,title:"2020.11.25 1.0.0",slug:"_2020-11-25-1-0-0",link:"#_2020-11-25-1-0-0",children:[]},{level:2,title:"2020.11.23",slug:"_2020-11-23",link:"#_2020-11-23",children:[]}],path:"/en/about/news.html",pathLocale:"/en/",extraFields:[]},{title:"Configurations",headers:[{level:2,title:"Overview",slug:"overview",link:"#overview",children:[]},{level:2,title:"Basic Configuration Modules",slug:"basic-configuration-modules",link:"#basic-configuration-modules",children:[]}],path:"/en/config/",pathLocale:"/en/",extraFields:[]},{title:"API Interface",headers:[{level:2,title:"ApiObject",slug:"apiobject",link:"#apiobject",children:[]},{level:2,title:"Related Configuration",slug:"related-configuration",link:"#related-configuration",children:[]},{level:2,title:"Supported API List",slug:"supported-api-list",link:"#supported-api-list",children:[{level:3,title:"HandlerService",slug:"handlerservice",link:"#handlerservice",children:[]}]},{level:2,title:"RoutingService",slug:"routingservice",link:"#routingservice",children:[{level:3,title:"LoggerService",slug:"loggerservice",link:"#loggerservice",children:[]},{level:3,title:"StatsService",slug:"statsservice",link:"#statsservice",children:[]},{level:3,title:"ReflectionService",slug:"reflectionservice",link:"#reflectionservice",children:[]}]},{level:2,title:"API Calling Example",slug:"api-calling-example",link:"#api-calling-example",children:[]}],path:"/en/config/api.html",pathLocale:"/en/",extraFields:[]},{title:"Built-in DNS Server",headers:[{level:2,title:"DNS Server",slug:"dns-server",link:"#dns-server",children:[]},{level:2,title:"DNS Processing Flow",slug:"dns-processing-flow",link:"#dns-processing-flow",children:[]},{level:2,title:"DnsObject",slug:"dnsobject",link:"#dnsobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/dns.html",pathLocale:"/en/",extraFields:[]},{title:"FakeDNS",headers:[{level:2,title:"FakeDNSObject",slug:"fakednsobject",link:"#fakednsobject",children:[{level:3,title:"How to use?",slug:"how-to-use",link:"#how-to-use",children:[]},{level:3,title:"Using with other types of DNS",slug:"using-with-other-types-of-dns",link:"#using-with-other-types-of-dns",children:[]}]}],path:"/en/config/fakedns.html",pathLocale:"/en/",extraFields:[]},{title:"Inbound Proxy",headers:[{level:2,title:"InboundObject",slug:"inboundobject",link:"#inboundobject",children:[{level:3,title:"SniffingObject",slug:"sniffingobject",link:"#sniffingobject",children:[]},{level:3,title:"AllocateObject",slug:"allocateobject",link:"#allocateobject",children:[]}]}],path:"/en/config/inbound.html",pathLocale:"/en/",extraFields:[]},{title:"Log Configuration",headers:[{level:2,title:"LogObject",slug:"logobject",link:"#logobject",children:[]}],path:"/en/config/log.html",pathLocale:"/en/",extraFields:[]},{title:"Metrics",headers:[{level:2,title:"Related configurations",slug:"related-configurations",link:"#related-configurations",children:[]},{level:2,title:"Usage",slug:"usage",link:"#usage",children:[{level:3,title:"pprof",slug:"pprof",link:"#pprof",children:[]},{level:3,title:"expvars",slug:"expvars",link:"#expvars",children:[]},{level:3,title:"Additional",slug:"additional",link:"#additional",children:[]}]}],path:"/en/config/metrics.html",pathLocale:"/en/",extraFields:[]},{title:"Outbound Proxies",headers:[{level:2,title:"OutboundObject",slug:"outboundobject",link:"#outboundobject",children:[{level:3,title:"ProxySettingsObject",slug:"proxysettingsobject",link:"#proxysettingsobject",children:[]},{level:3,title:"MuxObject",slug:"muxobject",link:"#muxobject",children:[]}]}],path:"/en/config/outbound.html",pathLocale:"/en/",extraFields:[]},{title:"Local Policy",headers:[{level:2,title:"PolicyObject",slug:"policyobject",link:"#policyobject",children:[{level:3,title:"LevelPolicyObject",slug:"levelpolicyobject",link:"#levelpolicyobject",children:[]},{level:3,title:"SystemPolicyObject",slug:"systempolicyobject",link:"#systempolicyobject",children:[]}]}],path:"/en/config/policy.html",pathLocale:"/en/",extraFields:[]},{title:"Reverse Proxy",headers:[{level:2,title:"ReverseObject",slug:"reverseobject",link:"#reverseobject",children:[{level:3,title:"BridgeObject",slug:"bridgeobject",link:"#bridgeobject",children:[]},{level:3,title:"PortalObject",slug:"portalobject",link:"#portalobject",children:[]}]},{level:2,title:"Complete Configuration Example",slug:"complete-configuration-example",link:"#complete-configuration-example",children:[{level:3,title:"Bridge Configuration",slug:"bridge-configuration",link:"#bridge-configuration",children:[]},{level:3,title:"Portal Configuration",slug:"portal-configuration",link:"#portal-configuration",children:[]}]}],path:"/en/config/reverse.html",pathLocale:"/en/",extraFields:[]},{title:"Routing",headers:[{level:2,title:"RoutingObject",slug:"routingobject",link:"#routingobject",children:[{level:3,title:"RuleObject",slug:"ruleobject",link:"#ruleobject",children:[]},{level:3,title:"BalancerObject",slug:"balancerobject",link:"#balancerobject",children:[]},{level:3,title:"Predefined Domain Lists",slug:"predefined-domain-lists",link:"#predefined-domain-lists",children:[]}]}],path:"/en/config/routing.html",pathLocale:"/en/",extraFields:[]},{title:"Traffic Statistics",headers:[{level:2,title:"StatsObject",slug:"statsobject",link:"#statsobject",children:[]},{level:2,title:"Retrieving Traffic Statistics",slug:"retrieving-traffic-statistics",link:"#retrieving-traffic-statistics",children:[]}],path:"/en/config/stats.html",pathLocale:"/en/",extraFields:[]},{title:"Transport",headers:[{level:2,title:"TransportObject (deprecated)",slug:"transportobject-deprecated",link:"#transportobject-deprecated",children:[]},{level:2,title:"StreamSettingsObject",slug:"streamsettingsobject",link:"#streamsettingsobject",children:[{level:3,title:"TLSObject",slug:"tlsobject",link:"#tlsobject",children:[]},{level:3,title:"SockoptObject",slug:"sockoptobject",link:"#sockoptobject",children:[]}]}],path:"/en/config/transport.html",pathLocale:"/en/",extraFields:[]},{title:"Development Guide",headers:[{level:2,title:"Compile Documentation",slug:"compile-documentation",link:"#compile-documentation",children:[]},{level:2,title:"Design Concept",slug:"design-concept",link:"#design-concept",children:[]},{level:2,title:"Development Standards",slug:"development-standards",link:"#development-standards",children:[]},{level:2,title:"Protocol Details",slug:"protocol-details",link:"#protocol-details",children:[{level:3,title:"VLESS Protocol",slug:"vless-protocol",link:"#vless-protocol",children:[]},{level:3,title:"VMess Protocol",slug:"vmess-protocol",link:"#vmess-protocol",children:[]},{level:3,title:"Mux.Cool Protocol",slug:"mux-cool-protocol",link:"#mux-cool-protocol",children:[]},{level:3,title:"mKCP Protocol",slug:"mkcp-protocol",link:"#mkcp-protocol",children:[]}]}],path:"/en/development/",pathLocale:"/en/",extraFields:[]},{title:"Quick Start",headers:[{level:2,title:"Download and Install",slug:"download-and-install",link:"#download-and-install",children:[]},{level:2,title:"Configure and Run",slug:"configure-and-run",link:"#configure-and-run",children:[]},{level:2,title:"Command Parameters",slug:"command-parameters",link:"#command-parameters",children:[]},{level:2,title:"Improve Documents",slug:"improve-documents",link:"#improve-documents",children:[]},{level:2,title:"Beginner Tutorial",slug:"beginner-tutorial",link:"#beginner-tutorial",children:[]},{level:2,title:"Getting Started Tips",slug:"getting-started-tips",link:"#getting-started-tips",children:[]},{level:2,title:"Advanced Documentation",slug:"advanced-documentation",link:"#advanced-documentation",children:[]}],path:"/en/document/",pathLocale:"/en/",extraFields:[]},{title:"Command Parameters",headers:[{level:2,title:"Get Basic Commands",slug:"get-basic-commands",link:"#get-basic-commands",children:[{level:3,title:"xray run",slug:"xray-run",link:"#xray-run",children:[]},{level:3,title:"xray version",slug:"xray-version",link:"#xray-version",children:[]},{level:3,title:"xray api",slug:"xray-api",link:"#xray-api",children:[]},{level:3,title:"xray tls",slug:"xray-tls",link:"#xray-tls",children:[]},{level:3,title:"xray uuid",slug:"xray-uuid",link:"#xray-uuid",children:[]},{level:3,title:"xray x25519",slug:"xray-x25519",link:"#xray-x25519",children:[]},{level:3,title:"xray wg",slug:"xray-wg",link:"#xray-wg",children:[]}]}],path:"/en/document/command.html",pathLocale:"/en/",extraFields:[]},{title:"Configure and Run",headers:[{level:2,title:"Server Configuration",slug:"server-configuration",link:"#server-configuration",children:[]},{level:2,title:"Client Configuration",slug:"client-configuration",link:"#client-configuration",children:[]},{level:2,title:"Run",slug:"run",link:"#run",children:[]}],path:"/en/document/config.html",pathLocale:"/en/",extraFields:[]},{title:"Contribute to Project X's Document",headers:[{level:2,title:"Improve Document",slug:"improve-document",link:"#improve-document",children:[]},{level:2,title:"Found Problems?",slug:"found-problems",link:"#found-problems",children:[]}],path:"/en/document/document.html",pathLocale:"/en/",extraFields:[]},{title:"Download and Install",headers:[{level:2,title:"Platform Support",slug:"platform-support",link:"#platform-support",children:[]},{level:2,title:"Download Xray",slug:"download-xray",link:"#download-xray",children:[]},{level:2,title:"Verify the Installation Package",slug:"verify-the-installation-package",link:"#verify-the-installation-package",children:[]},{level:2,title:"Install on Windows",slug:"install-on-windows",link:"#install-on-windows",children:[]},{level:2,title:"Install on macOS",slug:"install-on-macos",link:"#install-on-macos",children:[]},{level:2,title:"Install on Linux",slug:"install-on-linux",link:"#install-on-linux",children:[{level:3,title:"Install Script",slug:"install-script",link:"#install-script",children:[]},{level:3,title:"Arch Linux",slug:"arch-linux",link:"#arch-linux",children:[]},{level:3,title:"Linuxbrew",slug:"linuxbrew",link:"#linuxbrew",children:[]},{level:3,title:"Debian",slug:"debian",link:"#debian",children:[]}]},{level:2,title:"Install via Docker",slug:"install-via-docker",link:"#install-via-docker",children:[{level:3,title:"The File Structure of the Docker Image",slug:"the-file-structure-of-the-docker-image",link:"#the-file-structure-of-the-docker-image",children:[]}]}],path:"/en/document/install.html",pathLocale:"/en/",extraFields:[]},{title:"大史记",headers:[{level:2,title:"2021.4.6",slug:"_2021-4-6",link:"#_2021-4-6",children:[]},{level:2,title:"2021.4.4",slug:"_2021-4-4",link:"#_2021-4-4",children:[]},{level:2,title:"2021.4.1 v1.4.2",slug:"_2021-4-1-v1-4-2",link:"#_2021-4-1-v1-4-2",children:[]},{level:2,title:"2021.3.25",slug:"_2021-3-25",link:"#_2021-3-25",children:[]},{level:2,title:"2021.3.15",slug:"_2021-3-15",link:"#_2021-3-15",children:[]},{level:2,title:"2021.3.14 v1.4.0",slug:"_2021-3-14-v1-4-0",link:"#_2021-3-14-v1-4-0",children:[]},{level:2,title:"2021.3.3 1.3.1",slug:"_2021-3-3-1-3-1",link:"#_2021-3-3-1-3-1",children:[]},{level:2,title:"2021.2.14 1.3.0",slug:"_2021-2-14-1-3-0",link:"#_2021-2-14-1-3-0",children:[]},{level:2,title:"2021.01.31 1.2.4",slug:"_2021-01-31-1-2-4",link:"#_2021-01-31-1-2-4",children:[]},{level:2,title:"2021.01.25",slug:"_2021-01-25",link:"#_2021-01-25",children:[]},{level:2,title:"2021.01.22 1.2.3",slug:"_2021-01-22-1-2-3",link:"#_2021-01-22-1-2-3",children:[]},{level:2,title:"2021.01.19",slug:"_2021-01-19",link:"#_2021-01-19",children:[]},{level:2,title:"2021.01.17",slug:"_2021-01-17",link:"#_2021-01-17",children:[]},{level:2,title:"2021.01.15 1.2.2",slug:"_2021-01-15-1-2-2",link:"#_2021-01-15-1-2-2",children:[]},{level:2,title:"2021.01.12",slug:"_2021-01-12",link:"#_2021-01-12",children:[]},{level:2,title:"2021.01.10 1.2.1",slug:"_2021-01-10-1-2-1",link:"#_2021-01-10-1-2-1",children:[]},{level:2,title:"2021.01.07",slug:"_2021-01-07",link:"#_2021-01-07",children:[]},{level:2,title:"2021.01.05",slug:"_2021-01-05",link:"#_2021-01-05",children:[]},{level:2,title:"2021.01.03",slug:"_2021-01-03",link:"#_2021-01-03",children:[]},{level:2,title:"2021.01.01",slug:"_2021-01-01",link:"#_2021-01-01",children:[]},{level:2,title:"2020.12.29",slug:"_2020-12-29",link:"#_2020-12-29",children:[]},{level:2,title:"2020.12.25 1.1.5",slug:"_2020-12-25-1-1-5",link:"#_2020-12-25-1-1-5",children:[]},{level:2,title:"2020.12.24",slug:"_2020-12-24",link:"#_2020-12-24",children:[]},{level:2,title:"2020.12.23",slug:"_2020-12-23",link:"#_2020-12-23",children:[]},{level:2,title:"2020.12.21",slug:"_2020-12-21",link:"#_2020-12-21",children:[]},{level:2,title:"2020.12.18 1.1.4",slug:"_2020-12-18-1-1-4",link:"#_2020-12-18-1-1-4",children:[]},{level:2,title:"2020.12.17",slug:"_2020-12-17",link:"#_2020-12-17",children:[]},{level:2,title:"2020.12.15",slug:"_2020-12-15",link:"#_2020-12-15",children:[]},{level:2,title:"2020.12.11 1.1.3",slug:"_2020-12-11-1-1-3",link:"#_2020-12-11-1-1-3",children:[]},{level:2,title:"2020.12.06 1.1.2",slug:"_2020-12-06-1-1-2",link:"#_2020-12-06-1-1-2",children:[]},{level:2,title:"2020.12.04",slug:"_2020-12-04",link:"#_2020-12-04",children:[]},{level:2,title:"2020.11.27",slug:"_2020-11-27",link:"#_2020-11-27",children:[]},{level:2,title:"2020.11.25 1.0.0",slug:"_2020-11-25-1-0-0",link:"#_2020-11-25-1-0-0",children:[]},{level:2,title:"2020.11.23",slug:"_2020-11-23",link:"#_2020-11-23",children:[]}],path:"/ru/about/news.html",pathLocale:"/ru/",extraFields:[]},{title:"Конфигурационный файл",headers:[{level:2,title:"Обзор",slug:"обзор",link:"#обзор",children:[]},{level:2,title:"Основные модули конфигурации",slug:"основные-модули-конфигурации",link:"#основные-модули-конфигурации",children:[]}],path:"/ru/config/",pathLocale:"/ru/",extraFields:[]},{title:"API",headers:[{level:2,title:"ApiObject",slug:"apiobject",link:"#apiobject",children:[]},{level:2,title:"Связанные настройки",slug:"связанные-настроики",link:"#связанные-настроики",children:[]},{level:2,title:"Список поддерживаемых API",slug:"список-поддерживаемых-api",link:"#список-поддерживаемых-api",children:[{level:3,title:"HandlerService",slug:"handlerservice",link:"#handlerservice",children:[]},{level:3,title:"RoutingService",slug:"routingservice",link:"#routingservice",children:[]},{level:3,title:"LoggerService",slug:"loggerservice",link:"#loggerservice",children:[]},{level:3,title:"StatsService",slug:"statsservice",link:"#statsservice",children:[]},{level:3,title:"ReflectionService",slug:"reflectionservice",link:"#reflectionservice",children:[]}]},{level:2,title:"Примеры вызова API",slug:"примеры-вызова-api",link:"#примеры-вызова-api",children:[]}],path:"/ru/config/api.html",pathLocale:"/ru/",extraFields:[]},{title:"Встроенный DNS-сервер",headers:[{level:2,title:"DNS-сервер",slug:"dns-сервер",link:"#dns-сервер",children:[]},{level:2,title:"Процесс обработки DNS-запросов",slug:"процесс-обработки-dns-запросов",link:"#процесс-обработки-dns-запросов",children:[]},{level:2,title:"DnsObject",slug:"dnsobject",link:"#dnsobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/dns.html",pathLocale:"/ru/",extraFields:[]},{title:"FakeDNS",headers:[{level:2,title:"FakeDNSObject",slug:"fakednsobject",link:"#fakednsobject",children:[{level:3,title:"Как использовать FakeDNS?",slug:"как-использовать-fakedns",link:"#как-использовать-fakedns",children:[]},{level:3,title:"Использование FakeDNS с другими типами DNS",slug:"использование-fakedns-с-другими-типами-dns",link:"#использование-fakedns-с-другими-типами-dns",children:[]}]}],path:"/ru/config/fakedns.html",pathLocale:"/ru/",extraFields:[]},{title:"Входящие подключения",headers:[{level:2,title:"InboundObject",slug:"inboundobject",link:"#inboundobject",children:[{level:3,title:"SniffingObject",slug:"sniffingobject",link:"#sniffingobject",children:[]},{level:3,title:"AllocateObject",slug:"allocateobject",link:"#allocateobject",children:[]}]}],path:"/ru/config/inbound.html",pathLocale:"/ru/",extraFields:[]},{title:"Настройка журнала",headers:[{level:2,title:"LogObject",slug:"logobject",link:"#logobject",children:[]}],path:"/ru/config/log.html",pathLocale:"/ru/",extraFields:[]},{title:"Метрики",headers:[{level:2,title:"Связанные настройки",slug:"связанные-настроики",link:"#связанные-настроики",children:[]},{level:2,title:"Использование",slug:"использование",link:"#использование",children:[{level:3,title:"pprof",slug:"pprof",link:"#pprof",children:[]},{level:3,title:"expvars",slug:"expvars",link:"#expvars",children:[]},{level:3,title:"Дополнительно",slug:"дополнительно",link:"#дополнительно",children:[]}]}],path:"/ru/config/metrics.html",pathLocale:"/ru/",extraFields:[]},{title:"Мониторинг подключений",headers:[{level:2,title:"ObservatoryObject",slug:"observatoryobject",link:"#observatoryobject",children:[]},{level:2,title:"BurstObservatoryObject",slug:"burstobservatoryobject",link:"#burstobservatoryobject",children:[{level:3,title:"PingConfigObject",slug:"pingconfigobject",link:"#pingconfigobject",children:[]}]}],path:"/ru/config/observatory.html",pathLocale:"/ru/",extraFields:[]},{title:"Исходящие подключения",headers:[{level:2,title:"OutboundObject",slug:"outboundobject",link:"#outboundobject",children:[{level:3,title:"ProxySettingsObject",slug:"proxysettingsobject",link:"#proxysettingsobject",children:[]},{level:3,title:"MuxObject",slug:"muxobject",link:"#muxobject",children:[]}]}],path:"/ru/config/outbound.html",pathLocale:"/ru/",extraFields:[]},{title:"Локальные политики",headers:[{level:2,title:"PolicyObject",slug:"policyobject",link:"#policyobject",children:[{level:3,title:"LevelPolicyObject",slug:"levelpolicyobject",link:"#levelpolicyobject",children:[]},{level:3,title:"SystemPolicyObject",slug:"systempolicyobject",link:"#systempolicyobject",children:[]}]}],path:"/ru/config/policy.html",pathLocale:"/ru/",extraFields:[]},{title:"Обратный прокси",headers:[{level:2,title:"ReverseObject",slug:"reverseobject",link:"#reverseobject",children:[{level:3,title:"BridgeObject",slug:"bridgeobject",link:"#bridgeobject",children:[]},{level:3,title:"PortalObject",slug:"portalobject",link:"#portalobject",children:[]}]},{level:2,title:"Примеры полных конфигураций",slug:"примеры-полных-конфигурации",link:"#примеры-полных-конфигурации",children:[{level:3,title:"Настройка bridge",slug:"настроика-bridge",link:"#настроика-bridge",children:[]},{level:3,title:"Настройка portal",slug:"настроика-portal",link:"#настроика-portal",children:[]}]}],path:"/ru/config/reverse.html",pathLocale:"/ru/",extraFields:[]},{title:"Маршрутизация",headers:[{level:2,title:"RoutingObject",slug:"routingobject",link:"#routingobject",children:[{level:3,title:"RuleObject",slug:"ruleobject",link:"#ruleobject",children:[]},{level:3,title:"BalancerObject",slug:"balancerobject",link:"#balancerobject",children:[]},{level:3,title:"Пример конфигурации балансировщика нагрузки",slug:"пример-конфигурации-балансировщика-нагрузки",link:"#пример-конфигурации-балансировщика-нагрузки",children:[]},{level:3,title:"Предопределенные списки доменов",slug:"предопределенные-списки-доменов",link:"#предопределенные-списки-доменов",children:[]}]}],path:"/ru/config/routing.html",pathLocale:"/ru/",extraFields:[]},{title:"Статистика",headers:[{level:2,title:"StatsObject",slug:"statsobject",link:"#statsobject",children:[]},{level:2,title:"Получение статистики",slug:"получение-статистики",link:"#получение-статистики",children:[]}],path:"/ru/config/stats.html",pathLocale:"/ru/",extraFields:[]},{title:"Транспорт",headers:[{level:2,title:"TransportObject (устарело)",slug:"transportobject-устарело",link:"#transportobject-устарело",children:[]},{level:2,title:"StreamSettingsObject",slug:"streamsettingsobject",link:"#streamsettingsobject",children:[{level:3,title:"TLSObject",slug:"tlsobject",link:"#tlsobject",children:[]},{level:3,title:"RealityObject",slug:"realityobject",link:"#realityobject",children:[]},{level:3,title:"SockoptObject",slug:"sockoptobject",link:"#sockoptobject",children:[]}]}],path:"/ru/config/transport.html",pathLocale:"/ru/",extraFields:[]},{title:"开发指南",headers:[{level:2,title:"编译文档",slug:"编译文档",link:"#编译文档",children:[]},{level:2,title:"设计思路",slug:"设计思路",link:"#设计思路",children:[]},{level:2,title:"开发规范",slug:"开发规范",link:"#开发规范",children:[]},{level:2,title:"协议详解",slug:"协议详解",link:"#协议详解",children:[{level:3,title:"VLESS 协议",slug:"vless-协议",link:"#vless-协议",children:[]},{level:3,title:"VMess 协议",slug:"vmess-协议",link:"#vmess-协议",children:[]},{level:3,title:"Mux.Cool 协议",slug:"mux-cool-协议",link:"#mux-cool-协议",children:[]},{level:3,title:"mKCP 协议",slug:"mkcp-协议",link:"#mkcp-协议",children:[]}]}],path:"/ru/development/",pathLocale:"/ru/",extraFields:[]},{title:"Быстрый старт",headers:[{level:2,title:"Загрузка и установка",slug:"загрузка-и-установка",link:"#загрузка-и-установка",children:[]},{level:2,title:"Настройка и запуск",slug:"настроика-и-запуск",link:"#настроика-и-запуск",children:[]},{level:2,title:"Команды и аргументы",slug:"команды-и-аргументы",link:"#команды-и-аргументы",children:[]},{level:2,title:"Улучшение документации",slug:"улучшение-документации",link:"#улучшение-документации",children:[]},{level:2,title:"Простыми словами",slug:"простыми-словами",link:"#простыми-словами",children:[]},{level:2,title:"Базовые навыки",slug:"базовые-навыки",link:"#базовые-навыки",children:[]},{level:2,title:"Продвинутая документация",slug:"продвинутая-документация",link:"#продвинутая-документация",children:[]}],path:"/ru/document/",pathLocale:"/ru/",extraFields:[]},{title:"Командные аргументы",headers:[{level:2,title:"Базовые команды",slug:"базовые-команды",link:"#базовые-команды",children:[{level:3,title:"xray run",slug:"xray-run",link:"#xray-run",children:[]},{level:3,title:"xray version",slug:"xray-version",link:"#xray-version",children:[]},{level:3,title:"xray api",slug:"xray-api",link:"#xray-api",children:[]},{level:3,title:"xray tls",slug:"xray-tls",link:"#xray-tls",children:[]},{level:3,title:"xray uuid",slug:"xray-uuid",link:"#xray-uuid",children:[]},{level:3,title:"xray x25519",slug:"xray-x25519",link:"#xray-x25519",children:[]},{level:3,title:"xray wg",slug:"xray-wg",link:"#xray-wg",children:[]}]}],path:"/ru/document/command.html",pathLocale:"/ru/",extraFields:[]},{title:"Настройка и запуск",headers:[{level:2,title:"Настройка сервера",slug:"настроика-сервера",link:"#настроика-сервера",children:[]},{level:2,title:"Настройка клиента",slug:"настроика-клиента",link:"#настроика-клиента",children:[]},{level:2,title:"Запуск",slug:"запуск",link:"#запуск",children:[]}],path:"/ru/document/config.html",pathLocale:"/ru/",extraFields:[]},{title:"Вклад в документацию Project X",headers:[{level:2,title:"Улучшение документации",slug:"улучшение-документации",link:"#улучшение-документации",children:[]},{level:2,title:"Нашли ошибку?",slug:"нашли-ошибку",link:"#нашли-ошибку",children:[]}],path:"/ru/document/document.html",pathLocale:"/ru/",extraFields:[]},{title:"Загрузка и установка",headers:[{level:2,title:"Поддерживаемые платформы",slug:"поддерживаемые-платформы",link:"#поддерживаемые-платформы",children:[]},{level:2,title:"Загрузка Xray",slug:"загрузка-xray",link:"#загрузка-xray",children:[]},{level:2,title:"Проверка установочного пакета",slug:"проверка-установочного-пакета",link:"#проверка-установочного-пакета",children:[]},{level:2,title:"Установка на Windows",slug:"установка-на-windows",link:"#установка-на-windows",children:[]},{level:2,title:"Установка на macOS",slug:"установка-на-macos",link:"#установка-на-macos",children:[]},{level:2,title:"Установка на Linux",slug:"установка-на-linux",link:"#установка-на-linux",children:[{level:3,title:"Установочные скрипты",slug:"установочные-скрипты",link:"#установочные-скрипты",children:[]},{level:3,title:"Arch Linux",slug:"arch-linux",link:"#arch-linux",children:[]},{level:3,title:"Linuxbrew",slug:"linuxbrew",link:"#linuxbrew",children:[]},{level:3,title:"Debian",slug:"debian",link:"#debian",children:[]},{level:3,title:"Gentoo",slug:"gentoo",link:"#gentoo",children:[]}]},{level:2,title:"Установка с помощью Docker",slug:"установка-с-помощью-docker",link:"#установка-с-помощью-docker",children:[{level:3,title:"Файловая структура образа Docker",slug:"фаиловая-структура-образа-docker",link:"#фаиловая-структура-образа-docker",children:[]}]}],path:"/ru/document/install.html",pathLocale:"/ru/",extraFields:[]},{title:"透明代理入门",headers:[{level:2,title:"什么是透明代理",slug:"什么是透明代理",link:"#什么是透明代理",children:[]},{level:2,title:"透明代理的实现",slug:"透明代理的实现",link:"#透明代理的实现",children:[{level:3,title:"tun2socks",slug:"tun2socks",link:"#tun2socks",children:[]},{level:3,title:"iptables/nftables",slug:"iptables-nftables",link:"#iptables-nftables",children:[]}]},{level:2,title:"iptables 实现透明代理原理",slug:"iptables-实现透明代理原理",link:"#iptables-实现透明代理原理",children:[]},{level:2,title:"透明代理难在哪里",slug:"透明代理难在哪里",link:"#透明代理难在哪里",children:[]},{level:2,title:"从零开始一步步实现基于 iptables-tproxy 的透明代理",slug:"从零开始一步步实现基于-iptables-tproxy-的透明代理",link:"#从零开始一步步实现基于-iptables-tproxy-的透明代理",children:[{level:3,title:"在开始之前,你需要有一定的基础知识:",slug:"在开始之前-你需要有一定的基础知识",link:"#在开始之前-你需要有一定的基础知识",children:[]},{level:3,title:"前期准备工作",slug:"前期准备工作",link:"#前期准备工作",children:[]},{level:3,title:"首先,我们先试试做到第一阶段",slug:"首先-我们先试试做到第一阶段",link:"#首先-我们先试试做到第一阶段",children:[]},{level:3,title:"第二阶段",slug:"第二阶段",link:"#第二阶段",children:[]},{level:3,title:"第三阶段",slug:"第三阶段",link:"#第三阶段",children:[]},{level:3,title:"第四阶段",slug:"第四阶段",link:"#第四阶段",children:[]},{level:3,title:"代理 ipv6",slug:"代理-ipv6",link:"#代理-ipv6",children:[]}]}],path:"/document/level-2/transparent_proxy/transparent_proxy.html",pathLocale:"/",extraFields:[]},{title:"Browser Dialer",headers:[{level:2,title:"Background",slug:"background",link:"#background",children:[]},{level:2,title:"Configuration",slug:"configuration",link:"#configuration",children:[]},{level:2,title:"Inner workings",slug:"inner-workings",link:"#inner-workings",children:[]},{level:2,title:"WebSocket",slug:"websocket",link:"#websocket",children:[]},{level:2,title:"SplitHTTP",slug:"splithttp",link:"#splithttp",children:[]}],path:"/en/config/features/browser_dialer.html",pathLocale:"/en/",extraFields:[]},{title:"Environment Variables",headers:[{level:2,title:"Xray Asset Location",slug:"xray-asset-location",link:"#xray-asset-location",children:[]},{level:2,title:"Configuration File Location",slug:"configuration-file-location",link:"#configuration-file-location",children:[]},{level:2,title:"Multiple Configuration Directories",slug:"multiple-configuration-directories",link:"#multiple-configuration-directories",children:[]}],path:"/en/config/features/env.html",pathLocale:"/en/",extraFields:[]},{title:"Fallback",headers:[{level:2,title:"fallbacks configuration",slug:"fallbacks-configuration",link:"#fallbacks-configuration",children:[{level:3,title:"FallbackObject",slug:"fallbackobject",link:"#fallbackobject",children:[]},{level:3,title:"Additional Information",slug:"additional-information",link:"#additional-information",children:[]}]},{level:2,title:"Fallbacks design theory",slug:"fallbacks-design-theory",link:"#fallbacks-design-theory",children:[]}],path:"/en/config/features/fallback.html",pathLocale:"/en/",extraFields:[]},{title:"Multi-file configuration",headers:[{level:2,title:"Multi-file startup",slug:"multi-file-startup",link:"#multi-file-startup",children:[]},{level:2,title:"Rule Explanation",slug:"rule-explanation",link:"#rule-explanation",children:[{level:3,title:"Normal Objects({})",slug:"normal-objects",link:"#normal-objects",children:[]},{level:3,title:"Arrays([])",slug:"arrays",link:"#arrays",children:[]}]},{level:2,title:"Recommended Multi-file List",slug:"recommended-multi-file-list",link:"#recommended-multi-file-list",children:[]}],path:"/en/config/features/multiple.html",pathLocale:"/en/",extraFields:[]},{title:"Deep analysis of XTLS",headers:[],path:"/en/config/features/xtls.html",pathLocale:"/en/",extraFields:[]},{title:"Dokodemo-Door",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"Transparent Proxy Configuration Example",slug:"transparent-proxy-configuration-example",link:"#transparent-proxy-configuration-example",children:[]}],path:"/en/config/inbounds/dokodemo.html",pathLocale:"/en/",extraFields:[]},{title:"HTTP",headers:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}],path:"/en/config/inbounds/http.html",pathLocale:"/en/",extraFields:[]},{title:"Shadowsocks",headers:[{level:3,title:"Supported Encryption Methods",slug:"supported-encryption-methods",link:"#supported-encryption-methods",children:[]},{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}],path:"/en/config/inbounds/shadowsocks.html",pathLocale:"/en/",extraFields:[]},{title:"SOCKS",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/en/config/inbounds/socks.html",pathLocale:"/en/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/en/config/inbounds/trojan.html",pathLocale:"/en/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/en/config/inbounds/vless.html",pathLocale:"/en/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/en/config/inbounds/vmess.html",pathLocale:"/en/",extraFields:[]},{title:"Blackhole",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ResponseObject",slug:"responseobject",link:"#responseobject",children:[]}]}],path:"/en/config/outbounds/blackhole.html",pathLocale:"/en/",extraFields:[]},{title:"DNS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]},{level:2,title:"DNS Configuration Example",slug:"dns-configuration-example",link:"#dns-configuration-example",children:[]}],path:"/en/config/outbounds/dns.html",pathLocale:"/en/",extraFields:[]},{title:"Freedom",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]}],path:"/en/config/outbounds/freedom.html",pathLocale:"/en/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/http.html",pathLocale:"/en/",extraFields:[]},{title:"Loopback",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"How to use?",slug:"how-to-use",link:"#how-to-use",children:[]}]}],path:"/en/config/outbounds/loopback.html",pathLocale:"/en/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/shadowsocks.html",pathLocale:"/en/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/socks.html",pathLocale:"/en/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/trojan.html",pathLocale:"/en/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]},{level:3,title:"UserObject",slug:"userobject",link:"#userobject",children:[]}]}],path:"/en/config/outbounds/vless.html",pathLocale:"/en/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/vmess.html",pathLocale:"/en/",extraFields:[]},{title:"Wireguard",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Peers",slug:"peers",link:"#peers",children:[]}]}],path:"/en/config/outbounds/wireguard.html",pathLocale:"/en/",extraFields:[]},{title:"Domain Socket",headers:[{level:2,title:"DomainSocketObject",slug:"domainsocketobject",link:"#domainsocketobject",children:[]}],path:"/en/config/transports/domainsocket.html",pathLocale:"/en/",extraFields:[]},{title:"gRPC",headers:[{level:2,title:"GRPCObject",slug:"grpcobject",link:"#grpcobject",children:[]}],path:"/en/config/transports/grpc.html",pathLocale:"/en/",extraFields:[]},{title:"HTTP/2",headers:[{level:2,title:"HttpObject",slug:"httpobject",link:"#httpobject",children:[]}],path:"/en/config/transports/h2.html",pathLocale:"/en/",extraFields:[]},{title:"HTTPUpgrade",headers:[{level:2,title:"HttpUpgradeObject",slug:"httpupgradeobject",link:"#httpupgradeobject",children:[]}],path:"/en/config/transports/httpupgrade.html",pathLocale:"/en/",extraFields:[]},{title:"mKCP",headers:[{level:2,title:"KcpObject",slug:"kcpobject",link:"#kcpobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]},{level:2,title:"Special Thanks",slug:"special-thanks",link:"#special-thanks",children:[]},{level:2,title:"Improvements to the KCP protocol",slug:"improvements-to-the-kcp-protocol",link:"#improvements-to-the-kcp-protocol",children:[{level:3,title:"smaller protocol header",slug:"smaller-protocol-header",link:"#smaller-protocol-header",children:[]},{level:3,title:"ACK packet retransmission",slug:"ack-packet-retransmission",link:"#ack-packet-retransmission",children:[]},{level:3,title:"Connection state control",slug:"connection-state-control",link:"#connection-state-control",children:[]}]}],path:"/en/config/transports/mkcp.html",pathLocale:"/en/",extraFields:[]},{title:"QUIC",headers:[{level:2,title:"QuicObject",slug:"quicobject",link:"#quicobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]}],path:"/en/config/transports/quic.html",pathLocale:"/en/",extraFields:[]},{title:"SplitHTTP",headers:[{level:2,title:"SplitHttpObject",slug:"splithttpobject",link:"#splithttpobject",children:[]},{level:2,title:"HTTP versions",slug:"http-versions",link:"#http-versions",children:[]},{level:2,title:"Troubleshooting",slug:"troubleshooting",link:"#troubleshooting",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]},{level:2,title:"Protocol details",slug:"protocol-details",link:"#protocol-details",children:[]}],path:"/en/config/transports/splithttp.html",pathLocale:"/en/",extraFields:[]},{title:"TCP",headers:[{level:2,title:"TcpObject",slug:"tcpobject",link:"#tcpobject",children:[{level:3,title:"NoneHeaderObject",slug:"noneheaderobject",link:"#noneheaderobject",children:[]},{level:3,title:"HttpHeaderObject",slug:"httpheaderobject",link:"#httpheaderobject",children:[]}]}],path:"/en/config/transports/tcp.html",pathLocale:"/en/",extraFields:[]},{title:"WebSocket",headers:[{level:2,title:"WebSocketObject",slug:"websocketobject",link:"#websocketobject",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]}],path:"/en/config/transports/websocket.html",pathLocale:"/en/",extraFields:[]},{title:"Compile the document",headers:[{level:2,title:"Preparatory Work",slug:"preparatory-work",link:"#preparatory-work",children:[]},{level:2,title:"Pull Xray source code",slug:"pull-xray-source-code",link:"#pull-xray-source-code",children:[]},{level:2,title:"Build Binary",slug:"build-binary",link:"#build-binary",children:[{level:3,title:"Windows(Powershell):",slug:"windows-powershell",link:"#windows-powershell",children:[]},{level:3,title:"macOS, Linux:",slug:"macos-linux",link:"#macos-linux",children:[]}]},{level:2,title:"Reproducible Build:",slug:"reproducible-build",link:"#reproducible-build",children:[]}],path:"/en/development/intro/compile.html",pathLocale:"/en/",extraFields:[]},{title:"Design Objectives",headers:[{level:2,title:"Architecture",slug:"architecture",link:"#architecture",children:[{level:3,title:"Application Layer",slug:"application-layer",link:"#application-layer",children:[]},{level:3,title:"Proxy Layer",slug:"proxy-layer",link:"#proxy-layer",children:[]},{level:3,title:"Transport Layer",slug:"transport-layer",link:"#transport-layer",children:[]}]}],path:"/en/development/intro/design.html",pathLocale:"/en/",extraFields:[]},{title:"Development Standards",headers:[{level:2,title:"Basic",slug:"basic",link:"#basic",children:[{level:3,title:"Version Control",slug:"version-control",link:"#version-control",children:[]},{level:3,title:"Branch",slug:"branch",link:"#branch",children:[]},{level:3,title:"Release",slug:"release",link:"#release",children:[]},{level:3,title:"Citing other projects",slug:"citing-other-projects",link:"#citing-other-projects",children:[]}]},{level:2,title:"Development Process",slug:"development-process",link:"#development-process",children:[{level:3,title:"Before Writing Code",slug:"before-writing-code",link:"#before-writing-code",children:[]},{level:3,title:"Modify the code",slug:"modify-the-code",link:"#modify-the-code",children:[]},{level:3,title:"Pull Request",slug:"pull-request",link:"#pull-request",children:[]},{level:3,title:"Modifying Code",slug:"modifying-code",link:"#modifying-code",children:[]}]},{level:2,title:"Xray Coding Guidelines",slug:"xray-coding-guidelines",link:"#xray-coding-guidelines",children:[{level:3,title:"Code Structure",slug:"code-structure",link:"#code-structure",children:[]},{level:3,title:"Coding Standards",slug:"coding-standards",link:"#coding-standards",children:[]}]}],path:"/en/development/intro/guide.html",pathLocale:"/en/",extraFields:[]},{title:"mKCP Protocol",headers:[{level:2,title:"Version",slug:"version",link:"#version",children:[]},{level:2,title:"Dependencies",slug:"dependencies",link:"#dependencies",children:[{level:3,title:"Underlying Protocol",slug:"underlying-protocol",link:"#underlying-protocol",children:[]},{level:3,title:"Functions",slug:"functions",link:"#functions",children:[]}]},{level:2,title:"Communication Process",slug:"communication-process",link:"#communication-process",children:[]},{level:2,title:"Data Format",slug:"data-format",link:"#data-format",children:[{level:3,title:"Data Packet",slug:"data-packet",link:"#data-packet",children:[]},{level:3,title:"Data snippet",slug:"data-snippet",link:"#data-snippet",children:[]},{level:3,title:"Confirmation snippet",slug:"confirmation-snippet",link:"#confirmation-snippet",children:[]},{level:3,title:"Heartbeat Fragments",slug:"heartbeat-fragments",link:"#heartbeat-fragments",children:[]}]}],path:"/en/development/protocols/mkcp.html",pathLocale:"/en/",extraFields:[]},{title:"Mux.Cool Protocol",headers:[{level:2,title:"Version",slug:"version",link:"#version",children:[]},{level:2,title:"Dependencies",slug:"dependencies",link:"#dependencies",children:[{level:3,title:"Underlying Protocol",slug:"underlying-protocol",link:"#underlying-protocol",children:[]}]},{level:2,title:"Communication Process",slug:"communication-process",link:"#communication-process",children:[{level:3,title:"Client behavior",slug:"client-behavior",link:"#client-behavior",children:[]},{level:3,title:"Server-side behavior",slug:"server-side-behavior",link:"#server-side-behavior",children:[]}]},{level:2,title:"Data Format",slug:"data-format",link:"#data-format",children:[{level:3,title:"Frame Format",slug:"frame-format",link:"#frame-format",children:[]},{level:3,title:"Metadata",slug:"metadata",link:"#metadata",children:[]},{level:3,title:"New Sublink (New)",slug:"new-sublink-new",link:"#new-sublink-new",children:[]},{level:3,title:"Keep sub-connections",slug:"keep-sub-connections",link:"#keep-sub-connections",children:[]},{level:3,title:"End",slug:"end",link:"#end",children:[]},{level:3,title:"KeepAlive",slug:"keepalive",link:"#keepalive",children:[]}]},{level:2,title:"Application",slug:"application",link:"#application",children:[]}],path:"/en/development/protocols/muxcool.html",pathLocale:"/en/",extraFields:[]},{title:"VLESS Protocol",headers:[{level:2,title:"Request & Response",slug:"request-response",link:"#request-response",children:[]},{level:2,title:"ProtoBuf",slug:"protobuf",link:"#protobuf",children:[]},{level:2,title:"Flow",slug:"flow",link:"#flow",children:[{level:3,title:"Flow Control (Formerly Traffic Scheduler)",slug:"flow-control-formerly-traffic-scheduler",link:"#flow-control-formerly-traffic-scheduler",children:[]}]},{level:2,title:"Encryption",slug:"encryption",link:"#encryption",children:[]},{level:2,title:"UDP issues",slug:"udp-issues",link:"#udp-issues",children:[]},{level:2,title:"Client Development Guide",slug:"client-development-guide",link:"#client-development-guide",children:[]},{level:2,title:"VLESS Sharing Link Standard",slug:"vless-sharing-link-standard",link:"#vless-sharing-link-standard",children:[]}],path:"/en/development/protocols/vless.html",pathLocale:"/en/",extraFields:[]},{title:"VMess Protocol",headers:[{level:2,title:"Version",slug:"version",link:"#version",children:[]},{level:2,title:"Dependencies",slug:"dependencies",link:"#dependencies",children:[{level:3,title:"Underlying Protocol",slug:"underlying-protocol",link:"#underlying-protocol",children:[]},{level:3,title:"User ID",slug:"user-id",link:"#user-id",children:[]},{level:3,title:"Functions",slug:"functions",link:"#functions",children:[]}]},{level:2,title:"Communication Process",slug:"communication-process",link:"#communication-process",children:[]},{level:2,title:"Client Request",slug:"client-request",link:"#client-request",children:[{level:3,title:"Authentication Information",slug:"authentication-information",link:"#authentication-information",children:[]},{level:3,title:"Command Section",slug:"command-section",link:"#command-section",children:[]},{level:3,title:"Data Section",slug:"data-section",link:"#data-section",children:[]}]},{level:2,title:"Server Response",slug:"server-response",link:"#server-response",children:[{level:3,title:"Dynamic Port Instructions",slug:"dynamic-port-instructions",link:"#dynamic-port-instructions",children:[]}]},{level:2,title:"Comment",slug:"comment",link:"#comment",children:[]}],path:"/en/development/protocols/vmess.html",pathLocale:"/en/",extraFields:[]},{title:"Plain and Simple Language",headers:[],path:"/en/document/level-0/",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 1] Simple and Plain Language",headers:[{level:2,title:"1.1 Who is this document written for?",slug:"_1-1-who-is-this-document-written-for",link:"#_1-1-who-is-this-document-written-for",children:[]},{level:2,title:"1.2 Who is this document not written for?",slug:"_1-2-who-is-this-document-not-written-for",link:"#_1-2-who-is-this-document-not-written-for",children:[]},{level:2,title:"1.3 Declaration and Other Statements",slug:"_1-3-declaration-and-other-statements",link:"#_1-3-declaration-and-other-statements",children:[]},{level:2,title:"1.4 Why is self-hosting a challenge?",slug:"_1-4-why-is-self-hosting-a-challenge",link:"#_1-4-why-is-self-hosting-a-challenge",children:[]},{level:2,title:'1.5 "Why not just use the airport?"',slug:"_1-5-why-not-just-use-the-airport",link:"#_1-5-why-not-just-use-the-airport",children:[]},{level:2,title:"1.6 So should you build your own website?",slug:"_1-6-so-should-you-build-your-own-website",link:"#_1-6-so-should-you-build-your-own-website",children:[]},{level:2,title:"1.7 Some digressions",slug:"_1-7-some-digressions",link:"#_1-7-some-digressions",children:[]},{level:2,title:"1.8 Your Progress",slug:"_1-8-your-progress",link:"#_1-8-your-progress",children:[]}],path:"/en/document/level-0/ch01-preface.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 2] Preparation of Raw Materials",headers:[{level:2,title:"2.1 Acquiring a VPS",slug:"_2-1-acquiring-a-vps",link:"#_2-1-acquiring-a-vps",children:[]},{level:2,title:"2.2 Obtaining a Desired Domain Name",slug:"_2-2-obtaining-a-desired-domain-name",link:"#_2-2-obtaining-a-desired-domain-name",children:[]},{level:2,title:"2.3 Software you need to install on your local computer",slug:"_2-3-software-you-need-to-install-on-your-local-computer",link:"#_2-3-software-you-need-to-install-on-your-local-computer",children:[]},{level:2,title:"2.4 Your Progress",slug:"_2-4-your-progress",link:"#_2-4-your-progress",children:[]}],path:"/en/document/level-0/ch02-preparation.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 3] Remote Login",headers:[{level:2,title:"3.1 Remote Login to VPS (PuTTY)",slug:"_3-1-remote-login-to-vps-putty",link:"#_3-1-remote-login-to-vps-putty",children:[]},{level:2,title:"3.2 Successfully Logging in SSH! Introduction to Command Line Interface!",slug:"_3-2-successfully-logging-in-ssh-introduction-to-command-line-interface",link:"#_3-2-successfully-logging-in-ssh-introduction-to-command-line-interface",children:[]},{level:2,title:"3.3 Updating software on Linux for the first time!",slug:"_3-3-updating-software-on-linux-for-the-first-time",link:"#_3-3-updating-software-on-linux-for-the-first-time",children:[]},{level:2,title:"3.4 Your Progress",slug:"_3-4-your-progress",link:"#_3-4-your-progress",children:[]}],path:"/en/document/level-0/ch03-ssh.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 4] Security and Protection",headers:[{level:2,title:"4.1 Why Do We Need Security Protection?",slug:"_4-1-why-do-we-need-security-protection",link:"#_4-1-why-do-we-need-security-protection",children:[]},{level:2,title:"4.2 What are the specific risks",slug:"_4-2-what-are-the-specific-risks",link:"#_4-2-what-are-the-specific-risks",children:[]},{level:2,title:"4.3 What security measures do we need to take",slug:"_4-3-what-security-measures-do-we-need-to-take",link:"#_4-3-what-security-measures-do-we-need-to-take",children:[]},{level:2,title:"4.4 Change the SSH Remote Login Port to a Non-22 Port",slug:"_4-4-change-the-ssh-remote-login-port-to-a-non-22-port",link:"#_4-4-change-the-ssh-remote-login-port-to-a-non-22-port",children:[]},{level:2,title:"4.5 Creating a New User Without Root Access",slug:"_4-5-creating-a-new-user-without-root-access",link:"#_4-5-creating-a-new-user-without-root-access",children:[]},{level:2,title:"4.8 Your Progress",slug:"_4-8-your-progress",link:"#_4-8-your-progress",children:[]}],path:"/en/document/level-0/ch04-security.html",pathLocale:"/en/",extraFields:[]},{title:"Chapter 5: Website Building",headers:[{level:2,title:"5.1 Why should you create a website?",slug:"_5-1-why-should-you-create-a-website",link:"#_5-1-why-should-you-create-a-website",children:[]},{level:2,title:"5.2 Log in to VPS, install and run Nginx",slug:"_5-2-log-in-to-vps-install-and-run-nginx",link:"#_5-2-log-in-to-vps-install-and-run-nginx",children:[]},{level:2,title:"5.3 Create the simplest web page",slug:"_5-3-create-the-simplest-web-page",link:"#_5-3-create-the-simplest-web-page",children:[]},{level:2,title:"5.4 Common error explanations",slug:"_5-4-common-error-explanations",link:"#_5-4-common-error-explanations",children:[]}],path:"/en/document/level-0/ch05-webpage.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 6] Certificate Management",headers:[{level:2,title:"6.1 Applying for a TLS Certificate",slug:"_6-1-applying-for-a-tls-certificate",link:"#_6-1-applying-for-a-tls-certificate",children:[]},{level:2,title:"6.2 Install acme.sh",slug:"_6-2-install-acme-sh",link:"#_6-2-install-acme-sh",children:[]},{level:2,title:"6.3 Testing Certificate Application",slug:"_6-3-testing-certificate-application",link:"#_6-3-testing-certificate-application",children:[]},{level:2,title:"6.5 Certificate Installation",slug:"_6-5-certificate-installation",link:"#_6-5-certificate-installation",children:[]},{level:2,title:"6.6 Your Progress",slug:"_6-6-your-progress",link:"#_6-6-your-progress",children:[]}],path:"/en/document/level-0/ch06-certificates.html",pathLocale:"/en/",extraFields:[]},{title:"【第 7 章】Xray 服务器篇",headers:[{level:2,title:"7.1 博观而约取,厚积而薄发",slug:"_7-1-博观而约取-厚积而薄发",link:"#_7-1-博观而约取-厚积而薄发",children:[]},{level:2,title:"7.2 安装 Xray",slug:"_7-2-安装-xray",link:"#_7-2-安装-xray",children:[]},{level:2,title:"7.3 给 Xray 配置 TLS 证书",slug:"_7-3-给-xray-配置-tls-证书",link:"#_7-3-给-xray-配置-tls-证书",children:[]},{level:2,title:"7.4 配置 Xray",slug:"_7-4-配置-xray",link:"#_7-4-配置-xray",children:[]},{level:2,title:"7.5 启动 Xray 服务!!(并查看服务状态)",slug:"_7-5-启动-xray-服务-并查看服务状态",link:"#_7-5-启动-xray-服务-并查看服务状态",children:[]},{level:2,title:"7.6 回顾 systemd 进行基本的服务管理",slug:"_7-6-回顾-systemd-进行基本的服务管理",link:"#_7-6-回顾-systemd-进行基本的服务管理",children:[]},{level:2,title:"7.7 服务器优化之一:开启 BBR",slug:"_7-7-服务器优化之一-开启-bbr",link:"#_7-7-服务器优化之一-开启-bbr",children:[]},{level:2,title:"7.8 服务器优化之二:开启 HTTP 自动跳转 HTTPS",slug:"_7-8-服务器优化之二-开启-http-自动跳转-https",link:"#_7-8-服务器优化之二-开启-http-自动跳转-https",children:[]},{level:2,title:"7.9 服务器优化之三:更丰富的回落",slug:"_7-9-服务器优化之三-更丰富的回落",link:"#_7-9-服务器优化之三-更丰富的回落",children:[]},{level:2,title:"7.10 你的进度",slug:"_7-10-你的进度",link:"#_7-10-你的进度",children:[]},{level:2,title:"7.11 重要勘误",slug:"_7-11-重要勘误",link:"#_7-11-重要勘误",children:[]}],path:"/en/document/level-0/ch07-xray-server.html",pathLocale:"/en/",extraFields:[]},{title:"【第 8 章】Xray 客户端篇",headers:[{level:2,title:"8.1 Xray 的工作原理简述",slug:"_8-1-xray-的工作原理简述",link:"#_8-1-xray-的工作原理简述",children:[]},{level:2,title:"8.2 客户端与服务器端正确连接",slug:"_8-2-客户端与服务器端正确连接",link:"#_8-2-客户端与服务器端正确连接",children:[]},{level:2,title:"8.3 附加题 1:在 PC 端手工配置 xray-core",slug:"_8-3-附加题-1-在-pc-端手工配置-xray-core",link:"#_8-3-附加题-1-在-pc-端手工配置-xray-core",children:[]},{level:2,title:"8.4 附加题 2:在 PC 端手工运行 xray-core",slug:"_8-4-附加题-2-在-pc-端手工运行-xray-core",link:"#_8-4-附加题-2-在-pc-端手工运行-xray-core",children:[]},{level:2,title:"8.5 附加题 3:在 PC 端开机自动运行 xray-core",slug:"_8-5-附加题-3-在-pc-端开机自动运行-xray-core",link:"#_8-5-附加题-3-在-pc-端开机自动运行-xray-core",children:[]},{level:2,title:"8.6 圆满完成!",slug:"_8-6-圆满完成",link:"#_8-6-圆满完成",children:[]},{level:2,title:"8.7 TO INFINITY AND BEYOND!",slug:"_8-7-to-infinity-and-beyond",link:"#_8-7-to-infinity-and-beyond",children:[]}],path:"/en/document/level-0/ch08-xray-clients.html",pathLocale:"/en/",extraFields:[]},{title:"【第 9 章】附录",headers:[{level:2,title:"1. 小小白白 Linux 基础命令索引",slug:"_1-小小白白-linux-基础命令索引",link:"#_1-小小白白-linux-基础命令索引",children:[]},{level:2,title:"2. 小小白白 Linux 重要配置文件索引",slug:"_2-小小白白-linux-重要配置文件索引",link:"#_2-小小白白-linux-重要配置文件索引",children:[]},{level:2,title:"3. 小小白白 Xray 重要文件索引",slug:"_3-小小白白-xray-重要文件索引",link:"#_3-小小白白-xray-重要文件索引",children:[]}],path:"/en/document/level-0/ch09-appendix.html",pathLocale:"/en/",extraFields:[]},{title:"Beginner's Tips",headers:[],path:"/en/document/level-1/",pathLocale:"/en/",extraFields:[]},{title:"回落 (fallbacks) 功能简析",headers:[{level:2,title:"1. 回顾《小小白白话文》中的回落",slug:"_1-回顾《小小白白话文》中的回落",link:"#_1-回顾《小小白白话文》中的回落",children:[]},{level:2,title:"2. 重新认识回落 (WHAT, HOW v1)",slug:"_2-重新认识回落-what-how-v1",link:"#_2-重新认识回落-what-how-v1",children:[]},{level:2,title:"3. 为什么要回落 (WHY v1)",slug:"_3-为什么要回落-why-v1",link:"#_3-为什么要回落-why-v1",children:[]},{level:2,title:"4. 重新认识【回落の完全体】 (WHAT, WHY, HOW v2)",slug:"_4-重新认识【回落の完全体】-what-why-how-v2",link:"#_4-重新认识【回落の完全体】-what-why-how-v2",children:[]},{level:2,title:"5. 多层回落示例及解读",slug:"_5-多层回落示例及解读",link:"#_5-多层回落示例及解读",children:[{level:3,title:"5.1 首先,我将服务器端配置的 443 监听段摘抄如下:",slug:"_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",link:"#_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",children:[]},{level:3,title:"5.2 后续监听处理的配置段摘抄如下:",slug:"_5-2-后续监听处理的配置段摘抄如下",link:"#_5-2-后续监听处理的配置段摘抄如下",children:[]}]},{level:2,title:"6. 结语",slug:"_6-结语",link:"#_6-结语",children:[]},{level:2,title:"7. 附加题",slug:"_7-附加题",link:"#_7-附加题",children:[]}],path:"/en/document/level-1/fallbacks-lv1.html",pathLocale:"/en/",extraFields:[]},{title:"SNI fallback",headers:[{level:2,title:"Application Scenarios",slug:"application-scenarios",link:"#application-scenarios",children:[]},{level:2,title:"Introduction to SNI",slug:"introduction-to-sni",link:"#introduction-to-sni",children:[]},{level:2,title:"Idea",slug:"idea",link:"#idea",children:[]},{level:2,title:"Adding DNS Records",slug:"adding-dns-records",link:"#adding-dns-records",children:[]},{level:2,title:"Applying for TLS Certificate",slug:"applying-for-tls-certificate",link:"#applying-for-tls-certificate",children:[]},{level:2,title:"Xray Configuration",slug:"xray-configuration",link:"#xray-configuration",children:[]},{level:2,title:"Nginx Configuration",slug:"nginx-configuration",link:"#nginx-configuration",children:[]},{level:2,title:"Caddy Configuration",slug:"caddy-configuration",link:"#caddy-configuration",children:[]},{level:2,title:"Reference",slug:"reference",link:"#reference",children:[]},{level:2,title:"Quotation",slug:"quotation",link:"#quotation",children:[]}],path:"/en/document/level-1/fallbacks-with-sni.html",pathLocale:"/en/",extraFields:[]},{title:"路由 (routing) 功能简析(上)",headers:[{level:2,title:"1. 初识【路由】三兄弟",slug:"_1-初识【路由】三兄弟",link:"#_1-初识【路由】三兄弟",children:[]},{level:2,title:"2. 基本功: “兄弟一条心”",slug:"_2-基本功-兄弟一条心",link:"#_2-基本功-兄弟一条心",children:[{level:3,title:"2.1 入站",slug:"_2-1-入站",link:"#_2-1-入站",children:[]},{level:3,title:"2.3 路由",slug:"_2-3-路由",link:"#_2-3-路由",children:[]},{level:3,title:"2.4 路由配置项解析之一:流量筛选的依据",slug:"_2-4-路由配置项解析之一-流量筛选的依据",link:"#_2-4-路由配置项解析之一-流量筛选的依据",children:[]}]},{level:2,title:"3. 小试牛刀: “三分天下” 之 “域名分流”",slug:"_3-小试牛刀-三分天下-之-域名分流",link:"#_3-小试牛刀-三分天下-之-域名分流",children:[{level:3,title:"3.1 入站",slug:"_3-1-入站",link:"#_3-1-入站",children:[]},{level:3,title:"3.2 出站",slug:"_3-2-出站",link:"#_3-2-出站",children:[]},{level:3,title:"3.3 路由",slug:"_3-3-路由",link:"#_3-3-路由",children:[]},{level:3,title:"3.4 简析域名文件: geosite.dat",slug:"_3-4-简析域名文件-geosite-dat",link:"#_3-4-简析域名文件-geosite-dat",children:[]},{level:3,title:"3.5 所以 geosite.dat 到底是什么?不是有个 GFWList 吗?",slug:"_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",link:"#_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",children:[]},{level:3,title:"3.6 军师锦囊藏奇兵:一条隐藏的路由规则",slug:"_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",link:"#_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",children:[]},{level:3,title:"3.7 再看“三分天下”的大地图",slug:"_3-7-再看-三分天下-的大地图",link:"#_3-7-再看-三分天下-的大地图",children:[]}]},{level:2,title:"4. “三分天下” 之 “蜀魏争雄”",slug:"_4-三分天下-之-蜀魏争雄",link:"#_4-三分天下-之-蜀魏争雄",children:[]},{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[]}],path:"/en/document/level-1/routing-lv1-part1.html",pathLocale:"/en/",extraFields:[]},{title:"路由 (routing) 功能简析(下)",headers:[{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[{level:3,title:"5.1 基于指定域名分流:[domain], [full] 等",slug:"_5-1-基于指定域名分流-domain-full-等",link:"#_5-1-基于指定域名分流-domain-full-等",children:[]},{level:3,title:"5.2 基于 IP 文件分流:geoip.dat",slug:"_5-2-基于-ip-文件分流-geoip-dat",link:"#_5-2-基于-ip-文件分流-geoip-dat",children:[]},{level:3,title:"5.3 基于指定 IP 地址分流",slug:"_5-3-基于指定-ip-地址分流",link:"#_5-3-基于指定-ip-地址分流",children:[]},{level:3,title:"5.4 基于协议类型分流:[protocol] 等",slug:"_5-4-基于协议类型分流-protocol-等",link:"#_5-4-基于协议类型分流-protocol-等",children:[]},{level:3,title:"5.5 基于更多条件的分流",slug:"_5-5-基于更多条件的分流",link:"#_5-5-基于更多条件的分流",children:[]}]},{level:2,title:"6. “霸业初定”:路由规则整体回顾",slug:"_6-霸业初定-路由规则整体回顾",link:"#_6-霸业初定-路由规则整体回顾",children:[]},{level:2,title:"7. 路由配置常见错误",slug:"_7-路由配置常见错误",link:"#_7-路由配置常见错误",children:[{level:3,title:"7.1 错误示范",slug:"_7-1-错误示范",link:"#_7-1-错误示范",children:[]},{level:3,title:"7.2 正确示范",slug:"_7-2-正确示范",link:"#_7-2-正确示范",children:[]}]},{level:2,title:"8. 明修栈道、暗渡陈仓",slug:"_8-明修栈道、暗渡陈仓",link:"#_8-明修栈道、暗渡陈仓",children:[{level:3,title:'8.1 域名策略: "AsIs"',slug:"_8-1-域名策略-asis",link:"#_8-1-域名策略-asis",children:[]},{level:3,title:'8.2 域名策略: "IPIfNonMatch"',slug:"_8-2-域名策略-ipifnonmatch",link:"#_8-2-域名策略-ipifnonmatch",children:[]},{level:3,title:'8.3 域名策略: "IPOnDemand"',slug:"_8-3-域名策略-ipondemand",link:"#_8-3-域名策略-ipondemand",children:[]}]},{level:2,title:"9. 思考题",slug:"_9-思考题",link:"#_9-思考题",children:[]},{level:2,title:"10. 结语",slug:"_10-结语",link:"#_10-结语",children:[]},{level:2,title:"11. 尾注",slug:"_11-尾注",link:"#_11-尾注",children:[]}],path:"/en/document/level-1/routing-lv1-part2.html",pathLocale:"/en/",extraFields:[]},{title:"Xray 的工作模式",headers:[{level:2,title:"单服务器模式",slug:"单服务器模式",link:"#单服务器模式",children:[]},{level:2,title:"桥接模式",slug:"桥接模式",link:"#桥接模式",children:[]},{level:2,title:"工作原理",slug:"工作原理",link:"#工作原理",children:[]}],path:"/en/document/level-1/work.html",pathLocale:"/en/",extraFields:[]},{title:"Advanced Documentation",headers:[],path:"/en/document/level-2/",pathLocale:"/en/",extraFields:[]},{title:"Transparent proxy via GID",headers:[{level:2,title:"Ideas",slug:"ideas",link:"#ideas",children:[]},{level:2,title:"Configuration Procedure",slug:"configuration-procedure",link:"#configuration-procedure",children:[{level:3,title:"1. Preliminary preparation",slug:"_1-preliminary-preparation",link:"#_1-preliminary-preparation",children:[]},{level:3,title:"2. Add user (Android users please ignore this section)",slug:"_2-add-user-android-users-please-ignore-this-section",link:"#_2-add-user-android-users-please-ignore-this-section",children:[]},{level:3,title:"3. Configure and run Xray, and configure iptables rules",slug:"_3-configure-and-run-xray-and-configure-iptables-rules",link:"#_3-configure-and-run-xray-and-configure-iptables-rules",children:[]}]},{level:2,title:"Steps",slug:"steps",link:"#steps",children:[{level:3,title:"1. Finish Preliminary preparation and Add user",slug:"_1-finish-preliminary-preparation-and-add-user",link:"#_1-finish-preliminary-preparation-and-add-user",children:[]},{level:3,title:"2. Preparing Xray profiles",slug:"_2-preparing-xray-profiles",link:"#_2-preparing-xray-profiles",children:[]},{level:3,title:"3. Configuring the maximum number of open files and run the Xray client",slug:"_3-configuring-the-maximum-number-of-open-files-and-run-the-xray-client",link:"#_3-configuring-the-maximum-number-of-open-files-and-run-the-xray-client",children:[]},{level:3,title:"4. Setting up iptables rules",slug:"_4-setting-up-iptables-rules",link:"#_4-setting-up-iptables-rules",children:[]}]}],path:"/en/document/level-2/iptables_gid.html",pathLocale:"/en/",extraFields:[]},{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹",headers:[{level:2,title:"编译 nginx --with-stream",slug:"编译-nginx-with-stream",link:"#编译-nginx-with-stream",children:[]},{level:2,title:"配置 nginx",slug:"配置-nginx",link:"#配置-nginx",children:[]},{level:2,title:"xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"客户端及服务端启动服务",slug:"客户端及服务端启动服务",link:"#客户端及服务端启动服务",children:[]},{level:2,title:"结束",slug:"结束",link:"#结束",children:[]},{level:2,title:"HTTPS 隧道",slug:"https-隧道",link:"#https-隧道",children:[{level:3,title:"haproxy_client 配置 (运行前去掉注释)",slug:"haproxy-client-配置-运行前去掉注释",link:"#haproxy-client-配置-运行前去掉注释",children:[]},{level:3,title:"haproxy_server 配置 (运行前去掉注释)",slug:"haproxy-server-配置-运行前去掉注释",link:"#haproxy-server-配置-运行前去掉注释",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-1",link:"#xray-配置-1",children:[]}]},{level:2,title:"WebSocket over HTTP/2",slug:"websocket-over-http-2",link:"#websocket-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置",link:"#haproxy-client-配置",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置",link:"#haproxy-server-配置",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-2",link:"#xray-配置-2",children:[]}]},{level:2,title:"gRPC over HTTP/2",slug:"grpc-over-http-2",link:"#grpc-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-1",link:"#haproxy-client-配置-1",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-1",link:"#haproxy-server-配置-1",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-3",link:"#xray-配置-3",children:[]},{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-2",link:"#haproxy-client-配置-2",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-2",link:"#haproxy-server-配置-2",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-4",link:"#xray-配置-4",children:[]}]}],path:"/en/document/level-2/nginx_or_haproxy_tls_tunnel.html",pathLocale:"/en/",extraFields:[]},{title:"出站流量重定向",headers:[{level:2,title:"前言",slug:"前言",link:"#前言",children:[]},{level:2,title:"1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)",slug:"_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",link:"#_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",children:[]},{level:2,title:"2、编辑 VPN 配置文件(以 WireGuard 为例)",slug:"_2、编辑-vpn-配置文件-以-wireguard-为例",link:"#_2、编辑-vpn-配置文件-以-wireguard-为例",children:[]},{level:2,title:"3、启用 WireGuard 网络接口",slug:"_3、启用-wireguard-网络接口",link:"#_3、启用-wireguard-网络接口",children:[]},{level:2,title:"4、Xray-core 配置文件修改",slug:"_4、xray-core-配置文件修改",link:"#_4、xray-core-配置文件修改",children:[]},{level:2,title:"5、系统设置配置",slug:"_5、系统设置配置",link:"#_5、系统设置配置",children:[]},{level:2,title:"6、完成 WireGuard 相关设置",slug:"_6、完成-wireguard-相关设置",link:"#_6、完成-wireguard-相关设置",children:[]},{level:2,title:"后记",slug:"后记",link:"#后记",children:[]},{level:2,title:"感谢",slug:"感谢",link:"#感谢",children:[]}],path:"/en/document/level-2/redirect.html",pathLocale:"/en/",extraFields:[]},{title:"TProxy 透明代理",headers:[{level:2,title:"开始之前",slug:"开始之前",link:"#开始之前",children:[]},{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"策略路由配置",slug:"策略路由配置",link:"#策略路由配置",children:[]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[]},{level:2,title:"配置永久化与开机自启",slug:"配置永久化与开机自启",link:"#配置永久化与开机自启",children:[]}],path:"/en/document/level-2/tproxy.html",pathLocale:"/en/",extraFields:[]},{title:"TProxy 透明代理 (ipv4 and ipv6)",headers:[{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[{level:3,title:"客户端配置",slug:"客户端配置",link:"#客户端配置",children:[]},{level:3,title:"服务端配置",slug:"服务端配置",link:"#服务端配置",children:[]}]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[{level:3,title:"首先设置策略路由",slug:"首先设置策略路由",link:"#首先设置策略路由",children:[]},{level:3,title:"使用 iptables",slug:"使用-iptables",link:"#使用-iptables",children:[]},{level:3,title:"使用 nftables",slug:"使用-nftables",link:"#使用-nftables",children:[]},{level:3,title:"开机自动运行 Netfilter 配置",slug:"开机自动运行-netfilter-配置",link:"#开机自动运行-netfilter-配置",children:[]}]},{level:2,title:"局域网设备上网设置",slug:"局域网设备上网设置",link:"#局域网设备上网设置",children:[{level:3,title:"方法一",slug:"方法一",link:"#方法一",children:[]},{level:3,title:"方法二",slug:"方法二",link:"#方法二",children:[]}]},{level:2,title:"Finally",slug:"finally",link:"#finally",children:[]},{level:2,title:"写在最后",slug:"写在最后",link:"#写在最后",children:[]}],path:"/en/document/level-2/tproxy_ipv4_and_ipv6.html",pathLocale:"/en/",extraFields:[]},{title:"流量统计",headers:[{level:2,title:"查看流量信息",slug:"查看流量信息",link:"#查看流量信息",children:[]},{level:2,title:"流量信息的处理",slug:"流量信息的处理",link:"#流量信息的处理",children:[]}],path:"/en/document/level-2/traffic_stats.html",pathLocale:"/en/",extraFields:[]},{title:"Enhancing Proxy Security with Cloudflare Warp",headers:[{level:2,title:"Applying for a Warp Account",slug:"applying-for-a-warp-account",link:"#applying-for-a-warp-account",children:[]},{level:2,title:"Diverting inbound traffic to warp on the server side",slug:"diverting-inbound-traffic-to-warp-on-the-server-side",link:"#diverting-inbound-traffic-to-warp-on-the-server-side",children:[]},{level:2,title:"Using Warp Chain Proxy on the Client Side",slug:"using-warp-chain-proxy-on-the-client-side",link:"#using-warp-chain-proxy-on-the-client-side",children:[]}],path:"/en/document/level-2/warp.html",pathLocale:"/en/",extraFields:[]},{title:"Browser Dialer",headers:[{level:2,title:"Предыстория",slug:"предыстория",link:"#предыстория",children:[]},{level:2,title:"Конфигурация",slug:"конфигурация",link:"#конфигурация",children:[]},{level:2,title:"Внутренняя работа",slug:"внутренняя-работа",link:"#внутренняя-работа",children:[]},{level:2,title:"WebSocket",slug:"websocket",link:"#websocket",children:[]},{level:2,title:"SplitHTTP",slug:"splithttp",link:"#splithttp",children:[]}],path:"/ru/config/features/browser_dialer.html",pathLocale:"/ru/",extraFields:[]},{title:"Переменные среды",headers:[{level:2,title:"Путь к файлам ресурсов",slug:"путь-к-фаилам-ресурсов",link:"#путь-к-фаилам-ресурсов",children:[]},{level:2,title:"Расположение файла конфигурации",slug:"расположение-фаила-конфигурации",link:"#расположение-фаила-конфигурации",children:[]},{level:2,title:"Каталог с несколькими конфигурациями",slug:"каталог-с-несколькими-конфигурациями",link:"#каталог-с-несколькими-конфигурациями",children:[]}],path:"/ru/config/features/env.html",pathLocale:"/ru/",extraFields:[]},{title:"Fallback",headers:[{level:2,title:"Настройка fallbacks",slug:"настроика-fallbacks",link:"#настроика-fallbacks",children:[{level:3,title:"FallbackObject",slug:"fallbackobject",link:"#fallbackobject",children:[]},{level:3,title:"Дополнительные замечания",slug:"дополнительные-замечания",link:"#дополнительные-замечания",children:[]}]},{level:2,title:"Теория Fallbacks",slug:"теория-fallbacks",link:"#теория-fallbacks",children:[]}],path:"/ru/config/features/fallback.html",pathLocale:"/ru/",extraFields:[]},{title:"Настройка с помощью нескольких файлов",headers:[{level:2,title:"Запуск с несколькими файлами",slug:"запуск-с-несколькими-фаилами",link:"#запуск-с-несколькими-фаилами",children:[]},{level:2,title:"Правила",slug:"правила",link:"#правила",children:[{level:3,title:"Обычные объекты ({})",slug:"обычные-объекты",link:"#обычные-объекты",children:[]},{level:3,title:"Массивы ([])",slug:"массивы",link:"#массивы",children:[]}]},{level:2,title:"Пример конфигурации",slug:"пример-конфигурации",link:"#пример-конфигурации",children:[]}],path:"/ru/config/features/multiple.html",pathLocale:"/ru/",extraFields:[]},{title:"Глубокое погружение в XTLS",headers:[],path:"/ru/config/features/xtls.html",pathLocale:"/ru/",extraFields:[]},{title:"Dokodemo-Door",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"Использование",slug:"использование",link:"#использование",children:[]},{level:2,title:"Пример настройки прозрачного прокси",slug:"пример-настроики-прозрачного-прокси",link:"#пример-настроики-прозрачного-прокси",children:[]}],path:"/ru/config/inbounds/dokodemo.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/ru/config/inbounds/http.html",pathLocale:"/ru/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}],path:"/ru/config/inbounds/shadowsocks.html",pathLocale:"/ru/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/ru/config/inbounds/socks.html",pathLocale:"/ru/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/ru/config/inbounds/trojan.html",pathLocale:"/ru/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/ru/config/inbounds/vless.html",pathLocale:"/ru/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/ru/config/inbounds/vmess.html",pathLocale:"/ru/",extraFields:[]},{title:"Blackhole",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ResponseObject",slug:"responseobject",link:"#responseobject",children:[]}]}],path:"/ru/config/outbounds/blackhole.html",pathLocale:"/ru/",extraFields:[]},{title:"DNS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]},{level:2,title:"Пример настройки DNS",slug:"пример-настроики-dns",link:"#пример-настроики-dns",children:[]}],path:"/ru/config/outbounds/dns.html",pathLocale:"/ru/",extraFields:[]},{title:"Freedom",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]}],path:"/ru/config/outbounds/freedom.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/http.html",pathLocale:"/ru/",extraFields:[]},{title:"Loopback",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Как использовать?",slug:"как-использовать",link:"#как-использовать",children:[]}]}],path:"/ru/config/outbounds/loopback.html",pathLocale:"/ru/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/shadowsocks.html",pathLocale:"/ru/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/socks.html",pathLocale:"/ru/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/trojan.html",pathLocale:"/ru/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]},{level:3,title:"UserObject",slug:"userobject",link:"#userobject",children:[]}]}],path:"/ru/config/outbounds/vless.html",pathLocale:"/ru/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/vmess.html",pathLocale:"/ru/",extraFields:[]},{title:"WireGuard",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Peers",slug:"peers",link:"#peers",children:[]}]}],path:"/ru/config/outbounds/wireguard.html",pathLocale:"/ru/",extraFields:[]},{title:"DomainSocket",headers:[{level:2,title:"DomainSocketObject",slug:"domainsocketobject",link:"#domainsocketobject",children:[]}],path:"/ru/config/transports/domainsocket.html",pathLocale:"/ru/",extraFields:[]},{title:"gRPC",headers:[{level:2,title:"GRPCObject",slug:"grpcobject",link:"#grpcobject",children:[]}],path:"/ru/config/transports/grpc.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTP/2",headers:[{level:2,title:"HttpObject",slug:"httpobject",link:"#httpobject",children:[]}],path:"/ru/config/transports/h2.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTPUpgrade",headers:[{level:2,title:"HttpUpgradeObject",slug:"httpupgradeobject",link:"#httpupgradeobject",children:[]}],path:"/ru/config/transports/httpupgrade.html",pathLocale:"/ru/",extraFields:[]},{title:"mKCP",headers:[{level:2,title:"KcpObject",slug:"kcpobject",link:"#kcpobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]},{level:2,title:"Благодарности",slug:"благодарности",link:"#благодарности",children:[]},{level:2,title:"Улучшения протокола KCP",slug:"улучшения-протокола-kcp",link:"#улучшения-протокола-kcp",children:[{level:3,title:"Более компактный заголовок протокола",slug:"более-компактныи-заголовок-протокола",link:"#более-компактныи-заголовок-протокола",children:[]},{level:3,title:"Передача пакетов подтверждения",slug:"передача-пакетов-подтверждения",link:"#передача-пакетов-подтверждения",children:[]},{level:3,title:"Управление состоянием соединения",slug:"управление-состоянием-соединения",link:"#управление-состоянием-соединения",children:[]}]}],path:"/ru/config/transports/mkcp.html",pathLocale:"/ru/",extraFields:[]},{title:"QUIC",headers:[{level:2,title:"QuicObject",slug:"quicobject",link:"#quicobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]}],path:"/ru/config/transports/quic.html",pathLocale:"/ru/",extraFields:[]},{title:"SplitHTTP",headers:[{level:2,title:"SplitHttpObject",slug:"splithttpobject",link:"#splithttpobject",children:[]},{level:2,title:"Детали протокола",slug:"детали-протокола",link:"#детали-протокола",children:[]},{level:2,title:"BrowserDialer",slug:"browserdialer",link:"#browserdialer",children:[]}],path:"/ru/config/transports/splithttp.html",pathLocale:"/ru/",extraFields:[]},{title:"TCP",headers:[{level:2,title:"TcpObject",slug:"tcpobject",link:"#tcpobject",children:[{level:3,title:"NoneHeaderObject",slug:"noneheaderobject",link:"#noneheaderobject",children:[]},{level:3,title:"HttpHeaderObject",slug:"httpheaderobject",link:"#httpheaderobject",children:[]}]}],path:"/ru/config/transports/tcp.html",pathLocale:"/ru/",extraFields:[]},{title:"WebSocket",headers:[{level:2,title:"WebSocketObject",slug:"websocketobject",link:"#websocketobject",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]}],path:"/ru/config/transports/websocket.html",pathLocale:"/ru/",extraFields:[]},{title:"编译文档",headers:[{level:2,title:"前序工作",slug:"前序工作",link:"#前序工作",children:[]},{level:2,title:"拉取 Xray 源代码",slug:"拉取-xray-源代码",link:"#拉取-xray-源代码",children:[]},{level:2,title:"构建二进制",slug:"构建二进制",link:"#构建二进制",children:[{level:3,title:"Windows(Powershell):",slug:"windows-powershell",link:"#windows-powershell",children:[]},{level:3,title:"macOS, Linux:",slug:"macos-linux",link:"#macos-linux",children:[]}]},{level:2,title:"交叉编译:",slug:"交叉编译",link:"#交叉编译",children:[]},{level:2,title:"可复现构建:",slug:"可复现构建",link:"#可复现构建",children:[]}],path:"/ru/development/intro/compile.html",pathLocale:"/ru/",extraFields:[]},{title:"设计目标",headers:[{level:2,title:"架构",slug:"架构",link:"#架构",children:[{level:3,title:"应用层",slug:"应用层",link:"#应用层",children:[]},{level:3,title:"代理层",slug:"代理层",link:"#代理层",children:[]},{level:3,title:"传输层",slug:"传输层",link:"#传输层",children:[]}]}],path:"/ru/development/intro/design.html",pathLocale:"/ru/",extraFields:[]},{title:"开发规范",headers:[{level:2,title:"基本",slug:"基本",link:"#基本",children:[{level:3,title:"版本控制",slug:"版本控制",link:"#版本控制",children:[]},{level:3,title:"分支(Branch)",slug:"分支-branch",link:"#分支-branch",children:[]},{level:3,title:"发布(Release)",slug:"发布-release",link:"#发布-release",children:[]},{level:3,title:"引用其它项目",slug:"引用其它项目",link:"#引用其它项目",children:[]}]},{level:2,title:"开发流程",slug:"开发流程",link:"#开发流程",children:[{level:3,title:"写代码之前",slug:"写代码之前",link:"#写代码之前",children:[]},{level:3,title:"修改代码",slug:"修改代码",link:"#修改代码",children:[]},{level:3,title:"Pull Request",slug:"pull-request",link:"#pull-request",children:[]},{level:3,title:"对代码的修改",slug:"对代码的修改",link:"#对代码的修改",children:[]}]},{level:2,title:"Xray 编码规范",slug:"xray-编码规范",link:"#xray-编码规范",children:[{level:3,title:"代码结构",slug:"代码结构",link:"#代码结构",children:[]},{level:3,title:"编码规范",slug:"编码规范",link:"#编码规范",children:[]}]}],path:"/ru/development/intro/guide.html",pathLocale:"/ru/",extraFields:[]},{title:"mKCP 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"数据格式",slug:"数据格式",link:"#数据格式",children:[{level:3,title:"数据包",slug:"数据包",link:"#数据包",children:[]},{level:3,title:"数据片段",slug:"数据片段",link:"#数据片段",children:[]},{level:3,title:"确认片段",slug:"确认片段",link:"#确认片段",children:[]},{level:3,title:"心跳片段",slug:"心跳片段",link:"#心跳片段",children:[]}]}],path:"/ru/development/protocols/mkcp.html",pathLocale:"/ru/",extraFields:[]},{title:"Mux.Cool 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[{level:3,title:"客户端行为",slug:"客户端行为",link:"#客户端行为",children:[]},{level:3,title:"服务器端行为",slug:"服务器端行为",link:"#服务器端行为",children:[]}]},{level:2,title:"传输格式",slug:"传输格式",link:"#传输格式",children:[{level:3,title:"帧格式",slug:"帧格式",link:"#帧格式",children:[]},{level:3,title:"元数据",slug:"元数据",link:"#元数据",children:[]},{level:3,title:"新建子连接 (New)",slug:"新建子连接-new",link:"#新建子连接-new",children:[]},{level:3,title:"保持子连接 (Keep)",slug:"保持子连接-keep",link:"#保持子连接-keep",children:[]},{level:3,title:"关闭子连接 (End)",slug:"关闭子连接-end",link:"#关闭子连接-end",children:[]},{level:3,title:"保持连接 (KeepAlive)",slug:"保持连接-keepalive",link:"#保持连接-keepalive",children:[]}]},{level:2,title:"应用",slug:"应用",link:"#应用",children:[]}],path:"/ru/development/protocols/muxcool.html",pathLocale:"/ru/",extraFields:[]},{title:"VLESS 协议",headers:[{level:2,title:"Request & Response",slug:"request-response",link:"#request-response",children:[]},{level:2,title:"ProtoBuf",slug:"protobuf",link:"#protobuf",children:[]},{level:2,title:"Schedulers Flow",slug:"schedulers-flow",link:"#schedulers-flow",children:[]},{level:2,title:"Encryption",slug:"encryption",link:"#encryption",children:[]},{level:2,title:"UDP issues",slug:"udp-issues",link:"#udp-issues",children:[]},{level:2,title:"客户端开发指引",slug:"客户端开发指引",link:"#客户端开发指引",children:[]},{level:2,title:"VLESS 分享链接标准",slug:"vless-分享链接标准",link:"#vless-分享链接标准",children:[]}],path:"/ru/development/protocols/vless.html",pathLocale:"/ru/",extraFields:[]},{title:"VMess 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"用户 ID",slug:"用户-id",link:"#用户-id",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"客户端请求",slug:"客户端请求",link:"#客户端请求",children:[{level:3,title:"认证信息",slug:"认证信息",link:"#认证信息",children:[]},{level:3,title:"指令部分",slug:"指令部分",link:"#指令部分",children:[]},{level:3,title:"数据部分",slug:"数据部分",link:"#数据部分",children:[]}]},{level:2,title:"服务器应答",slug:"服务器应答",link:"#服务器应答",children:[{level:3,title:"动态端口指令",slug:"动态端口指令",link:"#动态端口指令",children:[]}]},{level:2,title:"注释",slug:"注释",link:"#注释",children:[]}],path:"/ru/development/protocols/vmess.html",pathLocale:"/ru/",extraFields:[]},{title:"Простые разговоры о сложном",headers:[],path:"/ru/document/level-0/",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 1】 Простыми словами",headers:[{level:2,title:"1.1 Для кого эта документация?",slug:"_1-1-для-кого-эта-документация",link:"#_1-1-для-кого-эта-документация",children:[]},{level:2,title:"1.2 Для кого эта документация не предназначена?",slug:"_1-2-для-кого-эта-документация-не-предназначена",link:"#_1-2-для-кого-эта-документация-не-предназначена",children:[]},{level:2,title:"1.3 Важное замечание и другие примечания",slug:"_1-3-важное-замечание-и-другие-примечания",link:"#_1-3-важное-замечание-и-другие-примечания",children:[]},{level:2,title:"1.4 Почему самостоятельная настройка — это сложно?",slug:"_1-4-почему-самостоятельная-настроика-—-это-сложно",link:"#_1-4-почему-самостоятельная-настроика-—-это-сложно",children:[]},{level:2,title:"1.5 «Почему бы просто не пользоваться платным VPN?»",slug:"_1-5-«почему-бы-просто-не-пользоваться-платным-vpn-»",link:"#_1-5-«почему-бы-просто-не-пользоваться-платным-vpn-»",children:[]},{level:2,title:"1.6 Так стоит ли настраивать VPN самостоятельно?",slug:"_1-6-так-стоит-ли-настраивать-vpn-самостоятельно",link:"#_1-6-так-стоит-ли-настраивать-vpn-самостоятельно",children:[]},{level:2,title:"1.7 Немного лирики",slug:"_1-7-немного-лирики",link:"#_1-7-немного-лирики",children:[]},{level:2,title:"1.8 Ваш прогресс",slug:"_1-8-ваш-прогресс",link:"#_1-8-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch01-preface.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 2】 Подготовка",headers:[{level:2,title:"2.1 Приобретение VPS",slug:"_2-1-приобретение-vps",link:"#_2-1-приобретение-vps",children:[]},{level:2,title:"2.2 Выбор доменного имени",slug:"_2-2-выбор-доменного-имени",link:"#_2-2-выбор-доменного-имени",children:[]},{level:2,title:"2.3 Необходимое программное обеспечение",slug:"_2-3-необходимое-программное-обеспечение",link:"#_2-3-необходимое-программное-обеспечение",children:[]},{level:2,title:"2.4 Ваш прогресс",slug:"_2-4-ваш-прогресс",link:"#_2-4-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch02-preparation.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 3】 Удалённое подключение",headers:[{level:2,title:"3.1 Удалённое подключение к VPS (PuTTY)",slug:"_3-1-удаленное-подключение-к-vps-putty",link:"#_3-1-удаленное-подключение-к-vps-putty",children:[]},{level:2,title:"3.2 Успешное подключение по SSH! Знакомство с командной строкой!",slug:"_3-2-успешное-подключение-по-ssh-знакомство-с-команднои-строкои",link:"#_3-2-успешное-подключение-по-ssh-знакомство-с-команднои-строкои",children:[]},{level:2,title:"3.3 Первое обновление программного обеспечения Linux!",slug:"_3-3-первое-обновление-программного-обеспечения-linux",link:"#_3-3-первое-обновление-программного-обеспечения-linux",children:[]},{level:2,title:"3.4 Ваш прогресс",slug:"_3-4-ваш-прогресс",link:"#_3-4-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch03-ssh.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 4】 Обеспечение безопасности",headers:[{level:2,title:"4.1 Зачем нужна безопасность?",slug:"_4-1-зачем-нужна-безопасность",link:"#_4-1-зачем-нужна-безопасность",children:[]},{level:2,title:"4.2 Какие именно риски существуют?",slug:"_4-2-какие-именно-риски-существуют",link:"#_4-2-какие-именно-риски-существуют",children:[]},{level:2,title:"4.3 Какие меры безопасности нужно предпринять?",slug:"_4-3-какие-меры-безопасности-нужно-предпринять",link:"#_4-3-какие-меры-безопасности-нужно-предпринять",children:[]},{level:2,title:"4.4 Изменение порта SSH",slug:"_4-4-изменение-порта-ssh",link:"#_4-4-изменение-порта-ssh",children:[]},{level:2,title:"4.5 Создание нового пользователя",slug:"_4-5-создание-нового-пользователя",link:"#_4-5-создание-нового-пользователя",children:[]},{level:2,title:"4.6 Запрет удалённого подключения по SSH для пользователя root",slug:"_4-6-запрет-удаленного-подключения-по-ssh-для-пользователя-root",link:"#_4-6-запрет-удаленного-подключения-по-ssh-для-пользователя-root",children:[]},{level:2,title:"4.7 Настройка аутентификации по SSH-ключам и запрет аутентификации по паролю",slug:"_4-7-настроика-аутентификации-по-ssh-ключам-и-запрет-аутентификации-по-паролю",link:"#_4-7-настроика-аутентификации-по-ssh-ключам-и-запрет-аутентификации-по-паролю",children:[]},{level:2,title:"4.8 Ваш прогресс",slug:"_4-8-ваш-прогресс",link:"#_4-8-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch04-security.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 5】 Создание веб-сайта",headers:[{level:2,title:"5.1 Зачем нужен веб-сайт?",slug:"_5-1-зачем-нужен-веб-саит",link:"#_5-1-зачем-нужен-веб-саит",children:[]},{level:2,title:"5.2 Подключение к VPS и установка Nginx",slug:"_5-2-подключение-к-vps-и-установка-nginx",link:"#_5-2-подключение-к-vps-и-установка-nginx",children:[]},{level:2,title:"5.3 Создание простой веб-страницы",slug:"_5-3-создание-простои-веб-страницы",link:"#_5-3-создание-простои-веб-страницы",children:[]},{level:2,title:"5.4 Распространённые ошибки",slug:"_5-4-распространенные-ошибки",link:"#_5-4-распространенные-ошибки",children:[]},{level:2,title:"5.5 Ваш прогресс",slug:"_5-5-ваш-прогресс",link:"#_5-5-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch05-webpage.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 6】 Управление сертификатами",headers:[{level:2,title:"6.1 Получение SSL-сертификата",slug:"_6-1-получение-ssl-сертификата",link:"#_6-1-получение-ssl-сертификата",children:[]},{level:2,title:"6.2 Установка acme.sh",slug:"_6-2-установка-acme-sh",link:"#_6-2-установка-acme-sh",children:[]},{level:2,title:"6.3 Тестовый запрос сертификата",slug:"_6-3-тестовыи-запрос-сертификата",link:"#_6-3-тестовыи-запрос-сертификата",children:[]},{level:2,title:"6.4 Запрос настоящего сертификата",slug:"_6-4-запрос-настоящего-сертификата",link:"#_6-4-запрос-настоящего-сертификата",children:[]},{level:2,title:"6.5 Установка сертификата",slug:"_6-5-установка-сертификата",link:"#_6-5-установка-сертификата",children:[]},{level:2,title:"6.6 Ваш прогресс",slug:"_6-6-ваш-прогресс",link:"#_6-6-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch06-certificates.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 7】Настройка Xray на сервере",headers:[{level:2,title:"7.1 Познать многое, усвоить нужное; копить постепенно, тратить осмотрительно",slug:"_7-1-познать-многое-усвоить-нужное-копить-постепенно-тратить-осмотрительно",link:"#_7-1-познать-многое-усвоить-нужное-копить-постепенно-тратить-осмотрительно",children:[]},{level:2,title:"7.2 Установка Xray",slug:"_7-2-установка-xray",link:"#_7-2-установка-xray",children:[]},{level:2,title:"7.3 Установка TLS-сертификата для Xray",slug:"_7-3-установка-tls-сертификата-для-xray",link:"#_7-3-установка-tls-сертификата-для-xray",children:[]},{level:2,title:"7.4 Настройка Xray",slug:"_7-4-настроика-xray",link:"#_7-4-настроика-xray",children:[]},{level:2,title:"7.5 Запуск Xray! (и проверка состояния сервиса)",slug:"_7-5-запуск-xray-и-проверка-состояния-сервиса",link:"#_7-5-запуск-xray-и-проверка-состояния-сервиса",children:[]},{level:2,title:"7.6 Базовое управление сервисами с помощью systemd",slug:"_7-6-базовое-управление-сервисами-с-помощью-systemd",link:"#_7-6-базовое-управление-сервисами-с-помощью-systemd",children:[]},{level:2,title:"7.7 Оптимизация сервера: включение BBR",slug:"_7-7-оптимизация-сервера-включение-bbr",link:"#_7-7-оптимизация-сервера-включение-bbr",children:[]},{level:2,title:"7.8 Оптимизация сервера: автоматическое перенаправление HTTP на HTTPS",slug:"_7-8-оптимизация-сервера-автоматическое-перенаправление-http-на-https",link:"#_7-8-оптимизация-сервера-автоматическое-перенаправление-http-на-https",children:[]},{level:2,title:"7.9 Оптимизация сервера: более гибкая настройка перенаправления",slug:"_7-9-оптимизация-сервера-более-гибкая-настроика-перенаправления",link:"#_7-9-оптимизация-сервера-более-гибкая-настроика-перенаправления",children:[]},{level:2,title:"7.10 Ваши успехи",slug:"_7-10-ваши-успехи",link:"#_7-10-ваши-успехи",children:[]},{level:2,title:"7.11 Важные исправления",slug:"_7-11-важные-исправления",link:"#_7-11-важные-исправления",children:[]}],path:"/ru/document/level-0/ch07-xray-server.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 8】Настройка Xray на клиенте",headers:[{level:2,title:"8.1 Как работает Xray: краткое описание",slug:"_8-1-как-работает-xray-краткое-описание",link:"#_8-1-как-работает-xray-краткое-описание",children:[]},{level:2,title:"8.2 Подключение клиента к серверу",slug:"_8-2-подключение-клиента-к-серверу",link:"#_8-2-подключение-клиента-к-серверу",children:[]},{level:2,title:"8.3 Дополнительное задание 1: настройка xray-core на ПК вручную",slug:"_8-3-дополнительное-задание-1-настроика-xray-core-на-пк-вручную",link:"#_8-3-дополнительное-задание-1-настроика-xray-core-на-пк-вручную",children:[]},{level:2,title:"8.4 Дополнительное задание 2: запуск xray-core на ПК",slug:"_8-4-дополнительное-задание-2-запуск-xray-core-на-пк",link:"#_8-4-дополнительное-задание-2-запуск-xray-core-на-пк",children:[]},{level:2,title:"8.5 Дополнительное задание 3: автозапуск xray-core на ПК",slug:"_8-5-дополнительное-задание-3-автозапуск-xray-core-на-пк",link:"#_8-5-дополнительное-задание-3-автозапуск-xray-core-на-пк",children:[]},{level:2,title:"8.6 Финишная прямая!",slug:"_8-6-финишная-прямая",link:"#_8-6-финишная-прямая",children:[]},{level:2,title:"8.7 В бесконечность и далее!",slug:"_8-7-в-бесконечность-и-далее",link:"#_8-7-в-бесконечность-и-далее",children:[]}],path:"/ru/document/level-0/ch08-xray-clients.html",pathLocale:"/ru/",extraFields:[]},{title:"[Глава 9] Приложение",headers:[{level:2,title:"1. Индекс основных команд Linux для начинающих",slug:"_1-индекс-основных-команд-linux-для-начинающих",link:"#_1-индекс-основных-команд-linux-для-начинающих",children:[]},{level:2,title:"2. Индекс важных конфигурационных файлов Linux",slug:"_2-индекс-важных-конфигурационных-фаилов-linux",link:"#_2-индекс-важных-конфигурационных-фаилов-linux",children:[]},{level:2,title:"3. Индекс важных файлов Xray",slug:"_3-индекс-важных-фаилов-xray",link:"#_3-индекс-важных-фаилов-xray",children:[]}],path:"/ru/document/level-0/ch09-appendix.html",pathLocale:"/ru/",extraFields:[]},{title:"Советы для начинающих",headers:[],path:"/ru/document/level-1/",pathLocale:"/ru/",extraFields:[]},{title:"Обзор функции Fallback",headers:[{level:2,title:"1. Что такое Fallback в простых словах",slug:"_1-что-такое-fallback-в-простых-словах",link:"#_1-что-такое-fallback-в-простых-словах",children:[]},{level:2,title:"2. Что такое Fallback (ЧТО, КАК v1)",slug:"_2-что-такое-fallback-что-как-v1",link:"#_2-что-такое-fallback-что-как-v1",children:[]},{level:2,title:"3. Зачем нужен Fallback (ЗАЧЕМ v1)",slug:"_3-зачем-нужен-fallback-зачем-v1",link:"#_3-зачем-нужен-fallback-зачем-v1",children:[]},{level:2,title:"4. Полное понимание Fallback (ЧТО, ЗАЧЕМ, КАК v2)",slug:"_4-полное-понимание-fallback-что-зачем-как-v2",link:"#_4-полное-понимание-fallback-что-зачем-как-v2",children:[]},{level:2,title:"5. Пример и описание многоуровневого fallback",slug:"_5-пример-и-описание-многоуровневого-fallback",link:"#_5-пример-и-описание-многоуровневого-fallback",children:[{level:3,title:"5.1 Сначала скопируем фрагмент конфигурации прослушивания порта 443 на стороне сервера:",slug:"_5-1-сначала-скопируем-фрагмент-конфигурации-прослушивания-порта-443-на-стороне-сервера",link:"#_5-1-сначала-скопируем-фрагмент-конфигурации-прослушивания-порта-443-на-стороне-сервера",children:[]},{level:3,title:"5.2 Фрагмент конфигурации, отвечающий за обработку fallback:",slug:"_5-2-фрагмент-конфигурации-отвечающии-за-обработку-fallback",link:"#_5-2-фрагмент-конфигурации-отвечающии-за-обработку-fallback",children:[]}]},{level:2,title:"6. Заключение",slug:"_6-заключение",link:"#_6-заключение",children:[]},{level:2,title:"7. Дополнительное задание",slug:"_7-дополнительное-задание",link:"#_7-дополнительное-задание",children:[]}],path:"/ru/document/level-1/fallbacks-lv1.html",pathLocale:"/ru/",extraFields:[]},{title:"SNI Fallback",headers:[{level:2,title:"Сценарии использования",slug:"сценарии-использования",link:"#сценарии-использования",children:[]},{level:2,title:"Что такое SNI",slug:"что-такое-sni",link:"#что-такое-sni",children:[]},{level:2,title:"Идея",slug:"идея",link:"#идея",children:[]},{level:2,title:"Добавление DNS-записей",slug:"добавление-dns-записеи",link:"#добавление-dns-записеи",children:[]},{level:2,title:"Запрос TLS-сертификата",slug:"запрос-tls-сертификата",link:"#запрос-tls-сертификата",children:[]},{level:2,title:"Конфигурация Xray",slug:"конфигурация-xray",link:"#конфигурация-xray",children:[]},{level:2,title:"Конфигурация Nginx",slug:"конфигурация-nginx",link:"#конфигурация-nginx",children:[]},{level:2,title:"Конфигурация Caddy",slug:"конфигурация-caddy",link:"#конфигурация-caddy",children:[]},{level:2,title:"Ссылки",slug:"ссылки",link:"#ссылки",children:[]},{level:2,title:"Примечания",slug:"примечания",link:"#примечания",children:[]}],path:"/ru/document/level-1/fallbacks-with-sni.html",pathLocale:"/ru/",extraFields:[]},{title:"Краткий обзор функции маршрутизации (routing) (часть 1)",headers:[{level:2,title:"1. Знакомство с тремя братьями-маршрутизаторами",slug:"_1-знакомство-с-тремя-братьями-маршрутизаторами",link:"#_1-знакомство-с-тремя-братьями-маршрутизаторами",children:[]},{level:2,title:'2. Основы: "Братья едины"',slug:"_2-основы-братья-едины",link:"#_2-основы-братья-едины",children:[{level:3,title:"2.1 Входящий трафик",slug:"_2-1-входящии-трафик",link:"#_2-1-входящии-трафик",children:[]},{level:3,title:"2.2 Исходящий трафик",slug:"_2-2-исходящии-трафик",link:"#_2-2-исходящии-трафик",children:[]},{level:3,title:"2.3 Маршрутизация",slug:"_2-3-маршрутизация",link:"#_2-3-маршрутизация",children:[]},{level:3,title:"2.4 Анализ параметров конфигурации маршрутизации: критерии фильтрации трафика",slug:"_2-4-анализ-параметров-конфигурации-маршрутизации-критерии-фильтрации-трафика",link:"#_2-4-анализ-параметров-конфигурации-маршрутизации-критерии-фильтрации-трафика",children:[]}]},{level:2,title:'3. Первые шаги: "Разделение мира на три части" - "Разделение по домену"',slug:"_3-первые-шаги-разделение-мира-на-три-части-разделение-по-домену",link:"#_3-первые-шаги-разделение-мира-на-три-части-разделение-по-домену",children:[{level:3,title:"3.1 Входящий трафик",slug:"_3-1-входящии-трафик",link:"#_3-1-входящии-трафик",children:[]},{level:3,title:"3.2 Исходящий трафик",slug:"_3-2-исходящии-трафик",link:"#_3-2-исходящии-трафик",children:[]},{level:3,title:"3.3 Маршрутизация",slug:"_3-3-маршрутизация",link:"#_3-3-маршрутизация",children:[]},{level:3,title:"3.4 Краткий обзор файла доменов: geosite.dat",slug:"_3-4-краткии-обзор-фаила-доменов-geosite-dat",link:"#_3-4-краткии-обзор-фаила-доменов-geosite-dat",children:[]},{level:3,title:"3.5 Так что же такое geosite.dat? Разве у нас нет GFWList?",slug:"_3-5-так-что-же-такое-geosite-dat-разве-у-нас-нет-gfwlist",link:"#_3-5-так-что-же-такое-geosite-dat-разве-у-нас-нет-gfwlist",children:[]},{level:3,title:"3.6 Секретное оружие: скрытое правило маршрутизации",slug:"_3-6-секретное-оружие-скрытое-правило-маршрутизации",link:"#_3-6-секретное-оружие-скрытое-правило-маршрутизации",children:[]},{level:3,title:'3.7 Снова смотрим на карту "трех царств"',slug:"_3-7-снова-смотрим-на-карту-трех-царств",link:"#_3-7-снова-смотрим-на-карту-трех-царств",children:[]}]},{level:2,title:'4. "Разделение мира на три части" - "Битва Вэй и Шу"',slug:"_4-разделение-мира-на-три-части-битва-вэи-и-шу",link:"#_4-разделение-мира-на-три-части-битва-вэи-и-шу",children:[]},{level:2,title:"5. Покорение новых высот - Различные условия сопоставления маршрутов",slug:"_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",link:"#_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",children:[]}],path:"/ru/document/level-1/routing-lv1-part1.html",pathLocale:"/ru/",extraFields:[]},{title:"Краткий обзор функции маршрутизации (routing) (часть 2)",headers:[{level:2,title:"5. Покорение новых высот - Различные условия сопоставления маршрутов",slug:"_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",link:"#_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",children:[{level:3,title:"5.1 Разделение по определенному домену: [domain], [full] и т. д.",slug:"_5-1-разделение-по-определенному-домену-domain-full-и-т-д",link:"#_5-1-разделение-по-определенному-домену-domain-full-и-т-д",children:[]},{level:3,title:"5.2 Разделение по IP-адресам из файла: geoip.dat",slug:"_5-2-разделение-по-ip-адресам-из-фаила-geoip-dat",link:"#_5-2-разделение-по-ip-адресам-из-фаила-geoip-dat",children:[]},{level:3,title:"5.3 Разделение по определенному IP-адресу",slug:"_5-3-разделение-по-определенному-ip-адресу",link:"#_5-3-разделение-по-определенному-ip-адресу",children:[]},{level:3,title:"5.4 Разделение по типу протокола: [protocol] и т. д.",slug:"_5-4-разделение-по-типу-протокола-protocol-и-т-д",link:"#_5-4-разделение-по-типу-протокола-protocol-и-т-д",children:[]},{level:3,title:"5.5 Разделение по другим критериям",slug:"_5-5-разделение-по-другим-критериям",link:"#_5-5-разделение-по-другим-критериям",children:[]}]},{level:2,title:'6. "Начало новой эры": обзор правил маршрутизации',slug:"_6-начало-новои-эры-обзор-правил-маршрутизации",link:"#_6-начало-новои-эры-обзор-правил-маршрутизации",children:[]},{level:2,title:"7. Распространенные ошибки в конфигурации маршрутизации",slug:"_7-распространенные-ошибки-в-конфигурации-маршрутизации",link:"#_7-распространенные-ошибки-в-конфигурации-маршрутизации",children:[{level:3,title:"7.1 Неправильный пример",slug:"_7-1-неправильныи-пример",link:"#_7-1-неправильныи-пример",children:[]},{level:3,title:"7.2 Правильный пример",slug:"_7-2-правильныи-пример",link:"#_7-2-правильныи-пример",children:[]}]},{level:2,title:"8. Скрытые пути",slug:"_8-скрытые-пути",link:"#_8-скрытые-пути",children:[{level:3,title:'8.1 Стратегия домена: "AsIs"',slug:"_8-1-стратегия-домена-asis",link:"#_8-1-стратегия-домена-asis",children:[]},{level:3,title:'8.2 Стратегия домена: "IPIfNonMatch"',slug:"_8-2-стратегия-домена-ipifnonmatch",link:"#_8-2-стратегия-домена-ipifnonmatch",children:[]},{level:3,title:'8.3 Стратегия домена: "IPOnDemand"',slug:"_8-3-стратегия-домена-ipondemand",link:"#_8-3-стратегия-домена-ipondemand",children:[]}]},{level:2,title:"9. Задание для размышления",slug:"_9-задание-для-размышления",link:"#_9-задание-для-размышления",children:[]},{level:2,title:"10. Заключение",slug:"_10-заключение",link:"#_10-заключение",children:[]},{level:2,title:"11. Примечания",slug:"_11-примечания",link:"#_11-примечания",children:[]}],path:"/ru/document/level-1/routing-lv1-part2.html",pathLocale:"/ru/",extraFields:[]},{title:"Режимы работы Xray",headers:[{level:2,title:"Режим одного сервера",slug:"режим-одного-сервера",link:"#режим-одного-сервера",children:[]},{level:2,title:"Режим моста",slug:"режим-моста",link:"#режим-моста",children:[]},{level:2,title:"Принцип работы",slug:"принцип-работы",link:"#принцип-работы",children:[]}],path:"/ru/document/level-1/work.html",pathLocale:"/ru/",extraFields:[]},{title:"Продвинутая документация",headers:[],path:"/ru/document/level-2/",pathLocale:"/ru/",extraFields:[]},{title:"GID Прозрачное проксирование",headers:[{level:2,title:"Идея",slug:"идея",link:"#идея",children:[]},{level:2,title:"Настройка",slug:"настроика",link:"#настроика",children:[{level:3,title:"1. Предварительная подготовка",slug:"_1-предварительная-подготовка",link:"#_1-предварительная-подготовка",children:[]},{level:3,title:"2. Добавление пользователя (пропустите для Android)",slug:"_2-добавление-пользователя-пропустите-для-android",link:"#_2-добавление-пользователя-пропустите-для-android",children:[]},{level:3,title:"3. Настройка запуска Xray и правил iptables",slug:"_3-настроика-запуска-xray-и-правил-iptables",link:"#_3-настроика-запуска-xray-и-правил-iptables",children:[]}]},{level:2,title:"Ниже приведен пример полной настройки глобального проксирования с использованием TPROXY",slug:"ниже-приведен-пример-полнои-настроики-глобального-проксирования-с-использованием-tproxy",link:"#ниже-приведен-пример-полнои-настроики-глобального-проксирования-с-использованием-tproxy",children:[{level:3,title:"1. Выполните предварительную подготовку и добавление пользователя.",slug:"_1-выполните-предварительную-подготовку-и-добавление-пользователя",link:"#_1-выполните-предварительную-подготовку-и-добавление-пользователя",children:[]},{level:3,title:"2. Подготовьте конфигурационный файл Xray.",slug:"_2-подготовьте-конфигурационныи-фаил-xray",link:"#_2-подготовьте-конфигурационныи-фаил-xray",children:[]},{level:3,title:"3. Настройка максимального количества открытых файлов и запуск клиента Xray",slug:"_3-настроика-максимального-количества-открытых-фаилов-и-запуск-клиента-xray",link:"#_3-настроика-максимального-количества-открытых-фаилов-и-запуск-клиента-xray",children:[]},{level:3,title:"4. Настройка правил iptables",slug:"_4-настроика-правил-iptables",link:"#_4-настроика-правил-iptables",children:[]}]}],path:"/ru/document/level-2/iptables_gid.html",pathLocale:"/ru/",extraFields:[]},{title:"Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков",headers:[{level:2,title:"Компиляция nginx с поддержкой --with-stream",slug:"компиляция-nginx-с-поддержкои-with-stream",link:"#компиляция-nginx-с-поддержкои-with-stream",children:[]},{level:2,title:"Настройка nginx",slug:"настроика-nginx",link:"#настроика-nginx",children:[]},{level:2,title:"Настройка Xray",slug:"настроика-xray",link:"#настроика-xray",children:[]},{level:2,title:"Запуск сервисов на клиенте и сервере",slug:"запуск-сервисов-на-клиенте-и-сервере",link:"#запуск-сервисов-на-клиенте-и-сервере",children:[]},{level:2,title:"Завершение",slug:"завершение",link:"#завершение",children:[]},{level:2,title:"HTTPS-туннель",slug:"https-туннель",link:"#https-туннель",children:[{level:3,title:"Конфигурация haproxy_client (удалите комментарии перед запуском):",slug:"конфигурация-haproxy-client-удалите-комментарии-перед-запуском",link:"#конфигурация-haproxy-client-удалите-комментарии-перед-запуском",children:[]},{level:3,title:"Конфигурация haproxy_server (удалите комментарии перед запуском):",slug:"конфигурация-haproxy-server-удалите-комментарии-перед-запуском",link:"#конфигурация-haproxy-server-удалите-комментарии-перед-запуском",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-1",link:"#настроика-xray-1",children:[]}]},{level:2,title:"WebSocket over HTTP/2",slug:"websocket-over-http-2",link:"#websocket-over-http-2",children:[{level:3,title:"Конфигурация haproxy_client:",slug:"конфигурация-haproxy-client",link:"#конфигурация-haproxy-client",children:[]},{level:3,title:"Конфигурация haproxy_server:",slug:"конфигурация-haproxy-server",link:"#конфигурация-haproxy-server",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-2",link:"#настроика-xray-2",children:[]}]},{level:2,title:"gRPC over HTTP/2",slug:"grpc-over-http-2",link:"#grpc-over-http-2",children:[{level:3,title:"Конфигурация haproxy_client:",slug:"конфигурация-haproxy-client-1",link:"#конфигурация-haproxy-client-1",children:[]},{level:3,title:"Конфигурация haproxy_server:",slug:"конфигурация-haproxy-server-1",link:"#конфигурация-haproxy-server-1",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-3",link:"#настроика-xray-3",children:[]},{level:3,title:"Конфигурация haproxy_client:",slug:"конфигурация-haproxy-client-2",link:"#конфигурация-haproxy-client-2",children:[]},{level:3,title:"Конфигурация haproxy_server:",slug:"конфигурация-haproxy-server-2",link:"#конфигурация-haproxy-server-2",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-4",link:"#настроика-xray-4",children:[]}]}],path:"/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html",pathLocale:"/ru/",extraFields:[]},{title:"Перенаправление исходящего трафика",headers:[{level:2,title:"Введение",slug:"введение",link:"#введение",children:[]},{level:2,title:"1. Установите прокси-сервер или VPN-клиент (например, Wireguard, IPsec и т.д.)",slug:"_1-установите-прокси-сервер-или-vpn-клиент-например-wireguard-ipsec-и-т-д",link:"#_1-установите-прокси-сервер-или-vpn-клиент-например-wireguard-ipsec-и-т-д",children:[]},{level:2,title:"2. Отредактируйте конфигурационный файл VPN (на примере WireGuard)",slug:"_2-отредактируите-конфигурационныи-фаил-vpn-на-примере-wireguard",link:"#_2-отредактируите-конфигурационныи-фаил-vpn-на-примере-wireguard",children:[]},{level:2,title:"3. Активируйте сетевой интерфейс WireGuard.",slug:"_3-активируите-сетевои-интерфеис-wireguard",link:"#_3-активируите-сетевои-интерфеис-wireguard",children:[]},{level:2,title:"4. Измените конфигурационный файл Xray-core.",slug:"_4-измените-конфигурационныи-фаил-xray-core",link:"#_4-измените-конфигурационныи-фаил-xray-core",children:[]},{level:2,title:"5. Настройка системы",slug:"_5-настроика-системы",link:"#_5-настроика-системы",children:[]},{level:2,title:"6. Завершение настройки WireGuard",slug:"_6-завершение-настроики-wireguard",link:"#_6-завершение-настроики-wireguard",children:[]},{level:2,title:"Послесловие",slug:"послесловие",link:"#послесловие",children:[]},{level:2,title:"Благодарности",slug:"благодарности",link:"#благодарности",children:[]}],path:"/ru/document/level-2/redirect.html",pathLocale:"/ru/",extraFields:[]},{title:"Прозрачное проксирование TProxy",headers:[{level:2,title:"Перед началом работы",slug:"перед-началом-работы",link:"#перед-началом-работы",children:[]},{level:2,title:"Настройка Xray",slug:"настроика-xray",link:"#настроика-xray",children:[]},{level:2,title:"Настройка маршрутизации по политике",slug:"настроика-маршрутизации-по-политике",link:"#настроика-маршрутизации-по-политике",children:[]},{level:2,title:"Настройка Netfilter",slug:"настроика-netfilter",link:"#настроика-netfilter",children:[]},{level:2,title:"Настройка автозагрузки и сохранения конфигурации",slug:"настроика-автозагрузки-и-сохранения-конфигурации",link:"#настроика-автозагрузки-и-сохранения-конфигурации",children:[]}],path:"/ru/document/level-2/tproxy.html",pathLocale:"/ru/",extraFields:[]},{title:"Прозрачное проксирование TProxy (ipv4 и ipv6)",headers:[{level:2,title:"Настройка Xray",slug:"настроика-xray",link:"#настроика-xray",children:[{level:3,title:"Конфигурация клиента",slug:"конфигурация-клиента",link:"#конфигурация-клиента",children:[]},{level:3,title:"Конфигурация сервера",slug:"конфигурация-сервера",link:"#конфигурация-сервера",children:[]}]},{level:2,title:"Настройка Netfilter",slug:"настроика-netfilter",link:"#настроика-netfilter",children:[{level:3,title:"Настройка маршрутизации по политике",slug:"настроика-маршрутизации-по-политике",link:"#настроика-маршрутизации-по-политике",children:[]},{level:3,title:"Использование iptables",slug:"использование-iptables",link:"#использование-iptables",children:[]},{level:3,title:"Использование nftables",slug:"использование-nftables",link:"#использование-nftables",children:[]},{level:3,title:"Автоматический запуск конфигурации Netfilter при загрузке",slug:"автоматическии-запуск-конфигурации-netfilter-при-загрузке",link:"#автоматическии-запуск-конфигурации-netfilter-при-загрузке",children:[]}]},{level:2,title:"Настройка доступа к интернету на устройствах локальной сети",slug:"настроика-доступа-к-интернету-на-устроиствах-локальнои-сети",link:"#настроика-доступа-к-интернету-на-устроиствах-локальнои-сети",children:[{level:3,title:"Метод 1",slug:"метод-1",link:"#метод-1",children:[]},{level:3,title:"Метод 2",slug:"метод-2",link:"#метод-2",children:[]}]},{level:2,title:"Результаты",slug:"результаты",link:"#результаты",children:[]},{level:2,title:"Заключение",slug:"заключение",link:"#заключение",children:[]}],path:"/ru/document/level-2/tproxy_ipv4_and_ipv6.html",pathLocale:"/ru/",extraFields:[]},{title:"Статистика трафика",headers:[{level:2,title:"Просмотр статистики трафика",slug:"просмотр-статистики-трафика",link:"#просмотр-статистики-трафика",children:[]},{level:2,title:"Обработка статистики трафика",slug:"обработка-статистики-трафика",link:"#обработка-статистики-трафика",children:[]}],path:"/ru/document/level-2/traffic_stats.html",pathLocale:"/ru/",extraFields:[]},{title:"Повышение безопасности проксирования с помощью Cloudflare Warp",headers:[{level:2,title:"Создание аккаунта Warp",slug:"создание-аккаунта-warp",link:"#создание-аккаунта-warp",children:[{level:3,title:"Спасибо Cloudflare за содействие свободному интернету! Теперь вы можете бесплатно пользоваться услугами Warp. При подключении автоматически выбирается ближайший сервер.",slug:"спасибо-cloudflare-за-содеиствие-свободному-интернету-теперь-вы-можете-бесплатно-пользоваться-услугами-warp-при-подключении-автоматически-выбирается-ближаишии-сервер",link:"#спасибо-cloudflare-за-содеиствие-свободному-интернету-теперь-вы-можете-бесплатно-пользоваться-услугами-warp-при-подключении-автоматически-выбирается-ближаишии-сервер",children:[]}]},{level:2,title:"Перенаправление трафика в Китай через Warp на сервере",slug:"перенаправление-трафика-в-китаи-через-warp-на-сервере",link:"#перенаправление-трафика-в-китаи-через-warp-на-сервере",children:[]},{level:2,title:"Использование Warp в качестве прокси-сервера в цепочке на клиенте",slug:"использование-warp-в-качестве-прокси-сервера-в-цепочке-на-клиенте",link:"#использование-warp-в-качестве-прокси-сервера-в-цепочке-на-клиенте",children:[]}],path:"/ru/document/level-2/warp.html",pathLocale:"/ru/",extraFields:[]},{title:"透明代理入门",headers:[{level:2,title:"什么是透明代理",slug:"什么是透明代理",link:"#什么是透明代理",children:[]},{level:2,title:"透明代理的实现",slug:"透明代理的实现",link:"#透明代理的实现",children:[{level:3,title:"tun2socks",slug:"tun2socks",link:"#tun2socks",children:[]},{level:3,title:"iptables/nftables",slug:"iptables-nftables",link:"#iptables-nftables",children:[]}]},{level:2,title:"iptables 实现透明代理原理",slug:"iptables-实现透明代理原理",link:"#iptables-实现透明代理原理",children:[]},{level:2,title:"透明代理难在哪里",slug:"透明代理难在哪里",link:"#透明代理难在哪里",children:[]},{level:2,title:"从零开始一步步实现基于 iptables-tproxy 的透明代理",slug:"从零开始一步步实现基于-iptables-tproxy-的透明代理",link:"#从零开始一步步实现基于-iptables-tproxy-的透明代理",children:[{level:3,title:"在开始之前,你需要有一定的基础知识:",slug:"在开始之前-你需要有一定的基础知识",link:"#在开始之前-你需要有一定的基础知识",children:[]},{level:3,title:"前期准备工作",slug:"前期准备工作",link:"#前期准备工作",children:[]},{level:3,title:"首先,我们先试试做到第一阶段",slug:"首先-我们先试试做到第一阶段",link:"#首先-我们先试试做到第一阶段",children:[]},{level:3,title:"第二阶段",slug:"第二阶段",link:"#第二阶段",children:[]},{level:3,title:"第三阶段",slug:"第三阶段",link:"#第三阶段",children:[]},{level:3,title:"第四阶段",slug:"第四阶段",link:"#第四阶段",children:[]},{level:3,title:"代理 ipv6",slug:"代理-ipv6",link:"#代理-ipv6",children:[]}]}],path:"/en/document/level-2/transparent_proxy/transparent_proxy.html",pathLocale:"/en/",extraFields:[]},{title:"Другие замечания по прозрачному проксированию с помощью iptables",headers:[{level:2,title:"Погружение в прозрачное проксирование",slug:"погружение-в-прозрачное-проксирование",link:"#погружение-в-прозрачное-проксирование",children:[{level:3,title:"Что такое прозрачное проксирование?",slug:"что-такое-прозрачное-проксирование",link:"#что-такое-прозрачное-проксирование",children:[]},{level:3,title:"Реализация прозрачного проксирования",slug:"реализация-прозрачного-проксирования",link:"#реализация-прозрачного-проксирования",children:[]},{level:3,title:"tun2socks",slug:"tun2socks",link:"#tun2socks",children:[]},{level:3,title:"iptables/nftables",slug:"iptables-nftables",link:"#iptables-nftables",children:[]}]},{level:2,title:"Принцип реализации прозрачного проксирования с помощью iptables",slug:"принцип-реализации-прозрачного-проксирования-с-помощью-iptables",link:"#принцип-реализации-прозрачного-проксирования-с-помощью-iptables",children:[]},{level:2,title:"В чем сложность прозрачного проксирования?",slug:"в-чем-сложность-прозрачного-проксирования",link:"#в-чем-сложность-прозрачного-проксирования",children:[]},{level:2,title:"Пошаговая реализация прозрачного проксирования на основе iptables-tproxy с нуля",slug:"пошаговая-реализация-прозрачного-проксирования-на-основе-iptables-tproxy-с-нуля",link:"#пошаговая-реализация-прозрачного-проксирования-на-основе-iptables-tproxy-с-нуля",children:[{level:3,title:"Прежде чем начать, вам необходимо иметь базовые знания:",slug:"прежде-чем-начать-вам-необходимо-иметь-базовые-знания",link:"#прежде-чем-начать-вам-необходимо-иметь-базовые-знания",children:[]},{level:3,title:"Предварительная подготовка",slug:"предварительная-подготовка",link:"#предварительная-подготовка",children:[]},{level:3,title:"Сначала давайте попробуем достичь первого этапа",slug:"сначала-даваите-попробуем-достичь-первого-этапа",link:"#сначала-даваите-попробуем-достичь-первого-этапа",children:[]},{level:3,title:"Второй этап",slug:"второи-этап",link:"#второи-этап",children:[]},{level:3,title:"Третий этап",slug:"третии-этап",link:"#третии-этап",children:[]},{level:3,title:"Четвертый этап",slug:"четвертыи-этап",link:"#четвертыи-этап",children:[]},{level:3,title:"Проксирование IPv6",slug:"проксирование-ipv6",link:"#проксирование-ipv6",children:[]}]}],path:"/ru/document/level-2/transparent_proxy/transparent_proxy.html",pathLocale:"/ru/",extraFields:[]},{title:"",headers:[],path:"/404.html",pathLocale:"/",extraFields:[]},{title:"连接观测",headers:[{level:2,title:"ObservatoryObject",slug:"observatoryobject",link:"#observatoryobject",children:[]},{level:2,title:"BurstObservatoryObject",slug:"burstobservatoryobject",link:"#burstobservatoryobject",children:[{level:3,title:"PingConfigObject",slug:"pingconfigobject",link:"#pingconfigobject",children:[]}]}],path:"/en/config/observatory.html",pathLocale:"/en/",extraFields:[]}],Jf=pe(Qf),Zf=()=>Jf,ep=({searchIndex:e,routeLocale:t,query:l,maxSuggestions:n})=>{const i=C(()=>e.value.filter(r=>r.pathLocale===t.value));return C(()=>{const r=l.value.trim().toLowerCase();if(!r)return[];const o=[],c=(a,u)=>{fo(r,[u.title])&&o.push({link:`${a.path}#${u.slug}`,title:a.title,header:u.title});for(const d of u.children){if(o.length>=n.value)return;c(a,d)}};for(const a of i.value){if(o.length>=n.value)break;if(fo(r,[a.title,...a.extraFields])){o.push({link:a.path,title:a.title});continue}for(const u of a.headers){if(o.length>=n.value)break;c(a,u)}}return o})},tp=e=>{const t=pe(0);return{focusIndex:t,focusNext:()=>{t.value{t.value>0?t.value-=1:t.value=e.value.length-1}}},lp=_e({name:"SearchBox",props:{locales:{type:Object,required:!1,default:()=>({})},hotKeys:{type:Array,required:!1,default:()=>[]},maxSuggestions:{type:Number,required:!1,default:5}},setup(e){const{locales:t,hotKeys:l,maxSuggestions:n}=Dn(e),i=bt(),r=Ql(),o=Zf(),c=pe(null),a=pe(!1),u=pe(""),d=C(()=>t.value[r.value]??{}),v=ep({searchIndex:o,routeLocale:r,query:u,maxSuggestions:n}),{focusIndex:_,focusNext:g,focusPrev:m}=tp(v);Yf({input:c,hotKeys:l});const x=C(()=>a.value&&!!v.value.length),A=()=>{x.value&&m()},D=()=>{x.value&&g()},O=b=>{if(!x.value)return;const y=v.value[b];y&&i.push(y.link).then(()=>{u.value="",_.value=0})};return()=>he("form",{class:"search-box",role:"search"},[he("input",{ref:c,type:"search",placeholder:d.value.placeholder,autocomplete:"off",spellcheck:!1,value:u.value,onFocus:()=>a.value=!0,onBlur:()=>a.value=!1,onInput:b=>u.value=b.target.value,onKeydown:b=>{switch(b.key){case"ArrowUp":{A();break}case"ArrowDown":{D();break}case"Enter":{b.preventDefault(),O(_.value);break}}}}),x.value&&he("ul",{class:"suggestions",onMouseleave:()=>_.value=-1},v.value.map(({link:b,title:y,header:H},G)=>he("li",{class:["suggestion",{focus:_.value===G}],onMouseenter:()=>_.value=G,onMousedown:()=>O(G)},he("a",{href:b,onClick:N=>N.preventDefault()},[he("span",{class:"page-title"},y),H&&he("span",{class:"page-header"},`> ${H}`)]))))])}});var np=["s","/"],ip={"/":{placeholder:"搜索"}};const rp=ip,op=np,sp=5,cp=Et({enhance({app:e}){e.component("SearchBox",t=>he(lp,{locales:rp,hotKeys:op,maxSuggestions:sp,...t}))}}),ap={enhance:({app:e})=>{e.component("Mermaid",h(()=>s(()=>import("./Mermaid-OQLZrVC0.js"),__vite__mapDeps([])))),e.component("Tab",h(()=>s(()=>import("./Tab-Qnm7JOWy.js"),__vite__mapDeps([])))),e.component("Tabs",h(()=>s(()=>import("./Tabs-BWBTQACZ.js"),__vite__mapDeps([]))))}},hn=[nh,oh,dh,xh,Ph,Dh,If,zf,cp,ap],up=[["v-8daa1a0e","/",{title:""},["/README.md"]],["v-aad48c6a","/about/news.html",{title:"大史记"},[":md"]],["v-ba934fd8","/config/",{title:"配置文件"},["/config/README.md"]],["v-41ade9da","/config/api.html",{title:"API 接口"},[":md"]],["v-83dedd38","/config/dns.html",{title:"内置 DNS 服务器"},[":md"]],["v-192a19b9","/config/fakedns.html",{title:"FakeDNS"},[":md"]],["v-7f6279d8","/config/inbound.html",{title:"入站代理"},[":md"]],["v-1d860c29","/config/log.html",{title:"日志配置"},[":md"]],["v-fbaf47ec","/config/metrics.html",{title:"Metrics"},[":md"]],["v-24956213","/config/observatory.html",{title:"连接观测"},[":md"]],["v-2367d756","/config/outbound.html",{title:"出站代理(Mux、XUDP)"},[":md"]],["v-4ebec35a","/config/policy.html",{title:"本地策略"},[":md"]],["v-31b7756a","/config/reverse.html",{title:"反向代理"},[":md"]],["v-70677432","/config/routing.html",{title:"路由"},[":md"]],["v-7e21d6ae","/config/stats.html",{title:"统计信息"},[":md"]],["v-e3dfff38","/config/transport.html",{title:"传输方式(uTLS、REALITY)"},[":md"]],["v-f7496066","/development/",{title:"开发指南"},["/development/README.md"]],["v-36b1a79b","/document/",{title:"快速入门"},["/document/README.md"]],["v-09a64f89","/document/command.html",{title:"命令参数"},[":md"]],["v-2b1adf48","/document/config.html",{title:"配置运行"},[":md"]],["v-86ee963a","/document/document.html",{title:"为 Project X 的文档贡献"},[":md"]],["v-0e5d7b39","/document/install.html",{title:"下载安装"},[":md"]],["v-2d0a870d","/en/",{title:""},["/en/README.md"]],["v-2d0ab8b3","/ru/",{title:""},["/ru/README.md"]],["v-0d714d87","/config/features/browser_dialer.html",{title:"Browser Dialer"},[":md"]],["v-0da7880a","/config/features/env.html",{title:"环境变量"},[":md"]],["v-2aeb21f9","/config/features/fallback.html",{title:"Fallback 回落"},[":md"]],["v-3acf20ea","/config/features/multiple.html",{title:"多文件配置"},[":md"]],["v-792e28f8","/config/features/xtls.html",{title:"XTLS 深度剖析"},[":md"]],["v-b50d2334","/config/inbounds/dokodemo.html",{title:"Dokodemo-Door"},[":md"]],["v-593408b0","/config/inbounds/http.html",{title:"HTTP"},[":md"]],["v-802a842a","/config/inbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-29995cea","/config/inbounds/socks.html",{title:"Socks"},[":md"]],["v-2a1b3d72","/config/inbounds/trojan.html",{title:"Trojan"},[":md"]],["v-fb92e8aa","/config/inbounds/vless.html",{title:"VLESS(XTLS Vision Seed)"},[":md"]],["v-167afaac","/config/inbounds/vmess.html",{title:"VMess"},[":md"]],["v-749ad71a","/config/outbounds/blackhole.html",{title:"Blackhole"},[":md"]],["v-6d39b970","/config/outbounds/dns.html",{title:"DNS"},[":md"]],["v-d76e893a","/config/outbounds/freedom.html",{title:"Freedom"},[":md"]],["v-c6b4b59e","/config/outbounds/http.html",{title:"HTTP"},[":md"]],["v-41ec0e0e","/config/outbounds/loopback.html",{title:"Loopback"},[":md"]],["v-7b293e4a","/config/outbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-15f5452a","/config/outbounds/socks.html",{title:"Socks"},[":md"]],["v-5797bdb3","/config/outbounds/trojan.html",{title:"Trojan"},[":md"]],["v-a60f016c","/config/outbounds/vless.html",{title:"VLESS(XTLS Vision Seed)"},[":md"]],["v-413cee4b","/config/outbounds/vmess.html",{title:"VMess"},[":md"]],["v-208ca3b9","/config/outbounds/wireguard.html",{title:"Wireguard"},[":md"]],["v-775db7b1","/config/transports/domainsocket.html",{title:"Domain Socket"},[":md"]],["v-2877542a","/config/transports/grpc.html",{title:"gRPC"},[":md"]],["v-03a28284","/config/transports/h2.html",{title:"HTTP/2"},[":md"]],["v-04158536","/config/transports/httpupgrade.html",{title:"HTTPUpgrade"},[":md"]],["v-3167b1dd","/config/transports/mkcp.html",{title:"mKCP"},[":md"]],["v-8f08dbec","/config/transports/quic.html",{title:"QUIC"},[":md"]],["v-eeea2fb0","/config/transports/splithttp.html",{title:"SplitHTTP(H2、QUIC H3)"},[":md"]],["v-33b1b709","/config/transports/tcp.html",{title:"TCP"},[":md"]],["v-1ff57bba","/config/transports/websocket.html",{title:"WebSocket"},[":md"]],["v-6a9e8054","/development/intro/compile.html",{title:"编译文档"},[":md"]],["v-95e3eaea","/development/intro/design.html",{title:"设计目标"},[":md"]],["v-61e7eea6","/development/intro/guide.html",{title:"开发规范"},[":md"]],["v-6e6c37e6","/development/protocols/mkcp.html",{title:"mKCP 协议"},[":md"]],["v-13168a21","/development/protocols/muxcool.html",{title:"Mux.Cool 协议"},[":md"]],["v-5c48c82b","/development/protocols/vless.html",{title:"VLESS 协议"},[":md"]],["v-1ee591a8","/development/protocols/vmess.html",{title:"VMess 协议"},[":md"]],["v-3f09dcfa","/document/level-0/",{title:"小小白白话文"},["/document/level-0/README.md"]],["v-fb444906","/document/level-0/ch01-preface.html",{title:"【第 1 章】 小小白白话文"},[":md"]],["v-075f3ae5","/document/level-0/ch02-preparation.html",{title:"【第 2 章】原料准备篇"},[":md"]],["v-726d0633","/document/level-0/ch03-ssh.html",{title:"【第 3 章】远程登录篇"},[":md"]],["v-430c6ab8","/document/level-0/ch04-security.html",{title:"【第 4 章】安全防护篇"},[":md"]],["v-717c6376","/document/level-0/ch05-webpage.html",{title:"【第 5 章】网站建设篇"},[":md"]],["v-278039be","/document/level-0/ch06-certificates.html",{title:"【第 6 章】证书管理篇"},[":md"]],["v-a0c7f88e","/document/level-0/ch07-xray-server.html",{title:"【第 7 章】Xray 服务器篇"},[":md"]],["v-86586ca2","/document/level-0/ch08-xray-clients.html",{title:"【第 8 章】Xray 客户端篇"},[":md"]],["v-3eb62514","/document/level-0/ch09-appendix.html",{title:"【第 9 章】附录"},[":md"]],["v-3f09dcbc","/document/level-1/",{title:"入门技巧"},["/document/level-1/README.md"]],["v-b21a2a20","/document/level-1/fallbacks-lv1.html",{title:"回落 (fallbacks) 功能简析"},[":md"]],["v-da623318","/document/level-1/fallbacks-with-sni.html",{title:"SNI 回落"},[":md"]],["v-fdd722ac","/document/level-1/routing-lv1-part1.html",{title:"路由 (routing) 功能简析(上)"},[":md"]],["v-fa6d716e","/document/level-1/routing-lv1-part2.html",{title:"路由 (routing) 功能简析(下)"},[":md"]],["v-2f29e106","/document/level-1/work.html",{title:"Xray 的工作模式"},[":md"]],["v-3f09dc7e","/document/level-2/",{title:"进阶文档"},["/document/level-2/README.md"]],["v-1c17916e","/document/level-2/iptables_gid.html",{title:"GID 透明代理"},[":md"]],["v-a001cfa6","/document/level-2/nginx_or_haproxy_tls_tunnel.html",{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹"},[":md"]],["v-46333b48","/document/level-2/redirect.html",{title:"出站流量重定向"},[":md"]],["v-338bc63e","/document/level-2/tproxy.html",{title:"TProxy 透明代理"},[":md"]],["v-d68f7d58","/document/level-2/tproxy_ipv4_and_ipv6.html",{title:"TProxy 透明代理 (ipv4 and ipv6)"},[":md"]],["v-e533e2c6","/document/level-2/traffic_stats.html",{title:"流量统计"},[":md"]],["v-1e465ab0","/document/level-2/warp.html",{title:"通过 Cloudflare Warp 增强代理安全性"},[":md"]],["v-1080fb37","/en/about/news.html",{title:"大史记"},[":md"]],["v-317fc580","/en/config/",{title:"Configurations"},["/en/config/README.md"]],["v-45144c7f","/en/config/api.html",{title:"API Interface"},[":md"]],["v-23fbd2d0","/en/config/dns.html",{title:"Built-in DNS Server"},[":md"]],["v-2b7ec525","/en/config/fakedns.html",{title:"FakeDNS"},[":md"]],["v-5ab92300","/en/config/inbound.html",{title:"Inbound Proxy"},[":md"]],["v-f91d64d6","/en/config/log.html",{title:"Log Configuration"},[":md"]],["v-d705f114","/en/config/metrics.html",{title:"Metrics"},[":md"]],["v-268cd669","/en/config/outbound.html",{title:"Outbound Proxies"},[":md"]],["v-4492d567","/en/config/policy.html",{title:"Local Policy"},[":md"]],["v-0d0e1e92","/en/config/reverse.html",{title:"Reverse Proxy"},[":md"]],["v-4bbe1d5a","/en/config/routing.html",{title:"Routing"},[":md"]],["v-16426d1a","/en/config/stats.html",{title:"Traffic Statistics"},[":md"]],["v-5de780d0","/en/config/transport.html",{title:"Transport"},[":md"]],["v-f88d343e","/en/development/",{title:"Development Guide"},["/en/development/README.md"]],["v-38d56a07","/en/document/",{title:"Quick Start"},["/en/document/README.md"]],["v-4d046016","/en/document/command.html",{title:"Command Parameters"},[":md"]],["v-22b35270","/en/document/config.html",{title:"Configure and Run"},[":md"]],["v-30bd7c12","/en/document/document.html",{title:"Contribute to Project X's Document"},[":md"]],["v-439608b6","/en/document/install.html",{title:"Download and Install"},[":md"]],["v-408e88d1","/ru/about/news.html",{title:"大史记"},[":md"]],["v-b1cce5cc","/ru/config/",{title:"Конфигурационный файл"},["/ru/config/README.md"]],["v-7521da19","/ru/config/api.html",{title:"API"},[":md"]],["v-5409606a","/ru/config/dns.html",{title:"Встроенный DNS-сервер"},[":md"]],["v-5877f5bf","/ru/config/fakedns.html",{title:"FakeDNS"},[":md"]],["v-00c6c1cc","/ru/config/inbound.html",{title:"Входящие подключения"},[":md"]],["v-990249a2","/ru/config/log.html",{title:"Настройка журнала"},[":md"]],["v-7d138fe0","/ru/config/metrics.html",{title:"Метрики"},[":md"]],["v-11e9cb19","/ru/config/observatory.html",{title:"Мониторинг подключений"},[":md"]],["v-ce8c8de2","/ru/config/outbound.html",{title:"Исходящие подключения"},[":md"]],["v-3dc4298d","/ru/config/policy.html",{title:"Локальные политики"},[":md"]],["v-26722151","/ru/config/reverse.html",{title:"Обратный прокси"},[":md"]],["v-071a21ed","/ru/config/routing.html",{title:"Маршрутизация"},[":md"]],["v-7922fc34","/ru/config/stats.html",{title:"Статистика"},[":md"]],["v-3156f2ea","/ru/config/transport.html",{title:"Транспорт"},[":md"]],["v-40ee4e87","/ru/development/",{title:"开发指南"},["/ru/development/README.md"]],["v-a1c899be","/ru/document/",{title:"Быстрый старт"},["/ru/document/README.md"]],["v-a6257be2","/ru/document/command.html",{title:"Командные аргументы"},[":md"]],["v-d63f95d4","/ru/document/config.html",{title:"Настройка и запуск"},[":md"]],["v-fbbfd9c6","/ru/document/document.html",{title:"Вклад в документацию Project X"},[":md"]],["v-9cb72482","/ru/document/install.html",{title:"Загрузка и установка"},[":md"]],["v-51a51d87","/document/level-2/transparent_proxy/transparent_proxy.html",{title:"透明代理入门"},[":md"]],["v-76b9a0f3","/en/config/features/browser_dialer.html",{title:"Browser Dialer"},[":md"]],["v-565dbfc4","/en/config/features/env.html",{title:"Environment Variables"},[":md"]],["v-0fbd1336","/en/config/features/fallback.html",{title:"Fallback"},[":md"]],["v-a0627812","/en/config/features/multiple.html",{title:"Multi-file configuration"},[":md"]],["v-d190d938","/en/config/features/xtls.html",{title:"Deep analysis of XTLS"},[":md"]],["v-72afc2d2","/en/config/inbounds/dokodemo.html",{title:"Dokodemo-Door"},[":md"]],["v-773d731c","/en/config/inbounds/http.html",{title:"HTTP"},[":md"]],["v-f555fc02","/en/config/inbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-e35196c2","/en/config/inbounds/socks.html",{title:"SOCKS"},[":md"]],["v-29188644","/en/config/inbounds/trojan.html",{title:"Trojan"},[":md"]],["v-255a6ebf","/en/config/inbounds/vless.html",{title:"VLESS"},[":md"]],["v-8cc24480","/en/config/inbounds/vmess.html",{title:"VMess"},[":md"]],["v-64e47ef4","/en/config/outbounds/blackhole.html",{title:"Blackhole"},[":md"]],["v-e979b848","/en/config/outbounds/dns.html",{title:"DNS"},[":md"]],["v-617f0fcf","/en/config/outbounds/freedom.html",{title:"Freedom"},[":md"]],["v-3fc98845","/en/config/outbounds/http.html",{title:"HTTP"},[":md"]],["v-1b804722","/en/config/outbounds/loopback.html",{title:"Loopback"},[":md"]],["v-63077cb6","/en/config/outbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-516476d4","/en/config/outbounds/socks.html",{title:"Socks"},[":md"]],["v-7d61a872","/en/config/outbounds/trojan.html",{title:"Trojan"},[":md"]],["v-6e50feb6","/en/config/outbounds/vless.html",{title:"VLESS"},[":md"]],["v-02956db7","/en/config/outbounds/vmess.html",{title:"VMess"},[":md"]],["v-797f8d25","/en/config/outbounds/wireguard.html",{title:"Wireguard"},[":md"]],["v-3eb3e9c6","/en/config/transports/domainsocket.html",{title:"Domain Socket"},[":md"]],["v-2c6058d4","/en/config/transports/grpc.html",{title:"gRPC"},[":md"]],["v-1c38292a","/en/config/transports/h2.html",{title:"HTTP/2"},[":md"]],["v-17ff144a","/en/config/transports/httpupgrade.html",{title:"HTTPUpgrade"},[":md"]],["v-1a7f9d6e","/en/config/transports/mkcp.html",{title:"mKCP"},[":md"]],["v-79d41176","/en/config/transports/quic.html",{title:"QUIC"},[":md"]],["v-4df52c3c","/en/config/transports/splithttp.html",{title:"SplitHTTP"},[":md"]],["v-5254cbc6","/en/config/transports/tcp.html",{title:"TCP"},[":md"]],["v-9520f392","/en/config/transports/websocket.html",{title:"WebSocket"},[":md"]],["v-b7760e2c","/en/development/intro/compile.html",{title:"Compile the document"},[":md"]],["v-fb774212","/en/development/intro/design.html",{title:"Design Objectives"},[":md"]],["v-38c376c1","/en/development/intro/guide.html",{title:"Development Standards"},[":md"]],["v-21bccd79","/en/development/protocols/mkcp.html",{title:"mKCP Protocol"},[":md"]],["v-27001935","/en/development/protocols/muxcool.html",{title:"Mux.Cool Protocol"},[":md"]],["v-21b30c3f","/en/development/protocols/vless.html",{title:"VLESS Protocol"},[":md"]],["v-94110980","/en/development/protocols/vmess.html",{title:"VMess Protocol"},[":md"]],["v-789ba7ef","/en/document/level-0/",{title:"Plain and Simple Language"},["/en/document/level-0/README.md"]],["v-d3712ade","/en/document/level-0/ch01-preface.html",{title:"[Chapter 1] Simple and Plain Language"},[":md"]],["v-41f9c00e","/en/document/level-0/ch02-preparation.html",{title:"[Chapter 2] Preparation of Raw Materials"},[":md"]],["v-4c013f47","/en/document/level-0/ch03-ssh.html",{title:"[Chapter 3] Remote Login"},[":md"]],["v-a75683b8","/en/document/level-0/ch04-security.html",{title:"[Chapter 4] Security and Protection"},[":md"]],["v-f5341aec","/en/document/level-0/ch05-webpage.html",{title:"Chapter 5: Website Building"},[":md"]],["v-4458f72a","/en/document/level-0/ch06-certificates.html",{title:"[Chapter 6] Certificate Management"},[":md"]],["v-f1802e66","/en/document/level-0/ch07-xray-server.html",{title:"【第 7 章】Xray 服务器篇"},[":md"]],["v-4ca6f1ca","/en/document/level-0/ch08-xray-clients.html",{title:"【第 8 章】Xray 客户端篇"},[":md"]],["v-b0030f00","/en/document/level-0/ch09-appendix.html",{title:"【第 9 章】附录"},[":md"]],["v-789ba80e","/en/document/level-1/",{title:"Beginner's Tips"},["/en/document/level-1/README.md"]],["v-103b3e5c","/en/document/level-1/fallbacks-lv1.html",{title:"回落 (fallbacks) 功能简析"},[":md"]],["v-110dd688","/en/document/level-1/fallbacks-with-sni.html",{title:"SNI fallback"},[":md"]],["v-c425a7d4","/en/document/level-1/routing-lv1-part1.html",{title:"路由 (routing) 功能简析(上)"},[":md"]],["v-c0bbf696","/en/document/level-1/routing-lv1-part2.html",{title:"路由 (routing) 功能简析(下)"},[":md"]],["v-5b6477cc","/en/document/level-1/work.html",{title:"Xray 的工作模式"},[":md"]],["v-789ba82d","/en/document/level-2/",{title:"Advanced Documentation"},["/en/document/level-2/README.md"]],["v-05ddc65d","/en/document/level-2/iptables_gid.html",{title:"Transparent proxy via GID"},[":md"]],["v-474afe99","/en/document/level-2/nginx_or_haproxy_tls_tunnel.html",{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹"},[":md"]],["v-930ac920","/en/document/level-2/redirect.html",{title:"出站流量重定向"},[":md"]],["v-c579975c","/en/document/level-2/tproxy.html",{title:"TProxy 透明代理"},[":md"]],["v-7efb7c68","/en/document/level-2/tproxy_ipv4_and_ipv6.html",{title:"TProxy 透明代理 (ipv4 and ipv6)"},[":md"]],["v-12a33bee","/en/document/level-2/traffic_stats.html",{title:"流量统计"},[":md"]],["v-7d2b8478","/en/document/level-2/warp.html",{title:"Enhancing Proxy Security with Cloudflare Warp"},[":md"]],["v-1cfb44e6","/ru/config/features/browser_dialer.html",{title:"Browser Dialer"},[":md"]],["v-6a3f8078","/ru/config/features/env.html",{title:"Переменные среды"},[":md"]],["v-74f22e7f","/ru/config/features/fallback.html",{title:"Fallback"},[":md"]],["v-2c9f7c11","/ru/config/features/multiple.html",{title:"Настройка с помощью нескольких файлов"},[":md"]],["v-630c687e","/ru/config/features/xtls.html",{title:"Глубокое погружение в XTLS"},[":md"]],["v-20ff0a28","/ru/config/inbounds/dokodemo.html",{title:"Dokodemo-Door"},[":md"]],["v-43124836","/ru/config/inbounds/http.html",{title:"HTTP"},[":md"]],["v-6a351ba5","/ru/config/inbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-3d1d02c5","/ru/config/inbounds/socks.html",{title:"Socks"},[":md"]],["v-1567b378","/ru/config/inbounds/trojan.html",{title:"Trojan"},[":md"]],["v-57bf8636","/ru/config/inbounds/vless.html",{title:"VLESS"},[":md"]],["v-6864abe6","/ru/config/inbounds/vmess.html",{title:"VMess"},[":md"]],["v-5910da20","/ru/config/outbounds/blackhole.html",{title:"Blackhole"},[":md"]],["v-5717f8f6","/ru/config/outbounds/dns.html",{title:"DNS"},[":md"]],["v-4360702e","/ru/config/outbounds/freedom.html",{title:"Freedom"},[":md"]],["v-22e1532a","/ru/config/outbounds/http.html",{title:"HTTP"},[":md"]],["v-38c69248","/ru/config/outbounds/loopback.html",{title:"Loopback"},[":md"]],["v-1a2a97d0","/ru/config/outbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-0141bb30","/ru/config/outbounds/socks.html",{title:"Socks"},[":md"]],["v-544bef26","/ru/config/outbounds/trojan.html",{title:"Trojan"},[":md"]],["v-cf761560","/ru/config/outbounds/vless.html",{title:"VLESS"},[":md"]],["v-2c896451","/ru/config/outbounds/vmess.html",{title:"VMess"},[":md"]],["v-0502a6bf","/ru/config/outbounds/wireguard.html",{title:"WireGuard"},[":md"]],["v-5b6ec7b7","/ru/config/transports/domainsocket.html",{title:"DomainSocket"},[":md"]],["v-13c3ca30","/ru/config/transports/grpc.html",{title:"gRPC"},[":md"]],["v-2fe60378","/ru/config/transports/h2.html",{title:"HTTP/2"},[":md"]],["v-453f5c70","/ru/config/transports/httpupgrade.html",{title:"HTTPUpgrade"},[":md"]],["v-1cb427e3","/ru/config/transports/mkcp.html",{title:"mKCP"},[":md"]],["v-b86fefe0","/ru/config/transports/quic.html",{title:"QUIC"},[":md"]],["v-32d545e2","/ru/config/transports/splithttp.html",{title:"SplitHTTP"},[":md"]],["v-f4c92f7a","/ru/config/transports/tcp.html",{title:"TCP"},[":md"]],["v-cb60c046","/ru/config/transports/websocket.html",{title:"WebSocket"},[":md"]],["v-7ce977e0","/ru/development/intro/compile.html",{title:"编译文档"},[":md"]],["v-01d5d1de","/ru/development/intro/design.html",{title:"设计目标"},[":md"]],["v-4d4e5367","/ru/development/intro/guide.html",{title:"开发规范"},[":md"]],["v-a58031da","/ru/development/protocols/mkcp.html",{title:"mKCP 协议"},[":md"]],["v-5440615b","/ru/development/protocols/muxcool.html",{title:"Mux.Cool 协议"},[":md"]],["v-069325e5","/ru/development/protocols/vless.html",{title:"VLESS 协议"},[":md"]],["v-ca50d634","/ru/development/protocols/vmess.html",{title:"VMess 协议"},[":md"]],["v-490791ee","/ru/document/level-0/",{title:"Простые разговоры о сложном"},["/ru/document/level-0/README.md"]],["v-78f09a92","/ru/document/level-0/ch01-preface.html",{title:"【Глава 1】 Простыми словами"},[":md"]],["v-64f6e51f","/ru/document/level-0/ch02-preparation.html",{title:"【Глава 2】 Подготовка"},[":md"]],["v-69478a6d","/ru/document/level-0/ch03-ssh.html",{title:"【Глава 3】 Удалённое подключение"},[":md"]],["v-271d7abe","/ru/document/level-0/ch04-security.html",{title:"【Глава 4】 Обеспечение безопасности"},[":md"]],["v-9ab38aa0","/ru/document/level-0/ch05-webpage.html",{title:"【Глава 5】 Создание веб-сайта"},[":md"]],["v-7cddd6c4","/ru/document/level-0/ch06-certificates.html",{title:"【Глава 6】 Управление сертификатами"},[":md"]],["v-0d33adf3","/ru/document/level-0/ch07-xray-server.html",{title:"【Глава 7】Настройка Xray на сервере"},[":md"]],["v-123166b5","/ru/document/level-0/ch08-xray-clients.html",{title:"【Глава 8】Настройка Xray на клиенте"},[":md"]],["v-22c7351a","/ru/document/level-0/ch09-appendix.html",{title:"[Глава 9] Приложение"},[":md"]],["v-490791b0","/ru/document/level-1/",{title:"Советы для начинающих"},["/ru/document/level-1/README.md"]],["v-e9f80a14","/ru/document/level-1/fallbacks-lv1.html",{title:"Обзор функции Fallback"},[":md"]],["v-2db62ba4","/ru/document/level-1/fallbacks-with-sni.html",{title:"SNI Fallback"},[":md"]],["v-531be8a0","/ru/document/level-1/routing-lv1-part1.html",{title:"Краткий обзор функции маршрутизации (routing) (часть 1)"},[":md"]],["v-4fb23762","/ru/document/level-1/routing-lv1-part2.html",{title:"Краткий обзор функции маршрутизации (routing) (часть 2)"},[":md"]],["v-fdd8db80","/ru/document/level-1/work.html",{title:"Режимы работы Xray"},[":md"]],["v-49079172","/ru/document/level-2/",{title:"Продвинутая документация"},["/ru/document/level-2/README.md"]],["v-331e0e83","/ru/document/level-2/iptables_gid.html",{title:"GID Прозрачное проксирование"},[":md"]],["v-7418a5b3","/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html",{title:"Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков"},[":md"]],["v-587e32d4","/ru/document/level-2/redirect.html",{title:"Перенаправление исходящего трафика"},[":md"]],["v-9c63de10","/ru/document/level-2/tproxy.html",{title:"Прозрачное проксирование TProxy"},[":md"]],["v-a4c782e4","/ru/document/level-2/tproxy_ipv4_and_ipv6.html",{title:"Прозрачное проксирование TProxy (ipv4 и ipv6)"},[":md"]],["v-71771ea3","/ru/document/level-2/traffic_stats.html",{title:"Статистика трафика"},[":md"]],["v-70300bea","/ru/document/level-2/warp.html",{title:"Повышение безопасности проксирования с помощью Cloudflare Warp"},[":md"]],["v-7689d7f3","/en/document/level-2/transparent_proxy/transparent_proxy.html",{title:"透明代理入门"},[":md"]],["v-39b3c50d","/ru/document/level-2/transparent_proxy/transparent_proxy.html",{title:"Другие замечания по прозрачному проксированию с помощью iptables"},[":md"]],["v-3706649a","/404.html",{title:""},[]],["v-5c8e777f","/en/config/observatory.html",{title:"连接观测"},[":md"]]];var po=_e({name:"Vuepress",setup(){const e=Uu();return()=>he(e.value)}}),dp=()=>up.reduce((e,[t,l,n,i])=>(e.push({name:t,path:l,component:po,meta:n},{path:l.endsWith("/")?l+"index.html":l.substring(0,l.length-5),redirect:l},...i.map(r=>({path:r===":md"?l.substring(0,l.length-5)+".md":r,redirect:l}))),e),[{name:"404",path:"/:catchAll(.*)",component:po}]),hp=Od,vp=()=>{const e=Yd({history:hp(_s("/")),routes:dp(),scrollBehavior:(t,l,n)=>n||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,l)=>{var n;(t.path!==l.path||l===_t)&&([t.meta._data]=await Promise.all([vt.resolvePageData(t.name),(n=gs[t.name])==null?void 0:n.__asyncLoader()]))}),e},_p=e=>{e.component("ClientOnly",Bi),e.component("Content",Gu)},fp=(e,t,l)=>{const n=C(()=>t.currentRoute.value.path),i=Vh(n,()=>t.currentRoute.value.meta._data),r=C(()=>vt.resolveLayouts(l)),o=C(()=>vt.resolveRouteLocale(ll.value.locales,n.value)),c=C(()=>vt.resolveSiteLocaleData(ll.value,o.value)),a=C(()=>vt.resolvePageFrontmatter(i.value)),u=C(()=>vt.resolvePageHeadTitle(i.value,c.value)),d=C(()=>vt.resolvePageHead(u.value,a.value,c.value)),v=C(()=>vt.resolvePageLang(i.value,c.value)),_=C(()=>vt.resolvePageLayout(i.value,r.value));return e.provide(Hu,r),e.provide(ms,i),e.provide(bs,a),e.provide(Bu,u),e.provide(ks,d),e.provide(Es,v),e.provide(ys,_),e.provide(Mi,o),e.provide(Ls,c),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>a.value},$head:{get:()=>d.value},$headTitle:{get:()=>u.value},$lang:{get:()=>v.value},$page:{get:()=>i.value},$routeLocale:{get:()=>o.value},$site:{get:()=>ll.value},$siteLocale:{get:()=>c.value},$withBase:{get:()=>Wi}}),{layouts:r,pageData:i,pageFrontmatter:a,pageHead:d,pageHeadTitle:u,pageLang:v,pageLayout:_,routeLocale:o,siteData:ll,siteLocaleData:c}},pp=()=>{const e=$u(),t=Wu();let l=[];const n=()=>{e.value.forEach(o=>{const c=gp(o);c&&l.push(c)})},i=()=>{const o=[];return e.value.forEach(c=>{const a=mp(c);a&&o.push(a)}),o},r=()=>{document.documentElement.lang=t.value;const o=i();l.forEach((c,a)=>{const u=o.findIndex(d=>c.isEqualNode(d));u===-1?(c.remove(),delete l[a]):o.splice(u,1)}),o.forEach(c=>document.head.appendChild(c)),l=[...l.filter(c=>!!c),...o]};Kt(Xu,r),We(()=>{n(),Ge(e,r,{immediate:!1})})},gp=([e,t,l=""])=>{const n=Object.entries(t).map(([c,a])=>it(a)?`[${c}=${JSON.stringify(a)}]`:a===!0?`[${c}]`:"").join(""),i=`head > ${e}${n}`;return Array.from(document.querySelectorAll(i)).find(c=>c.innerText===l)||null},mp=([e,t,l])=>{if(!it(e))return null;const n=document.createElement(e);return Hi(t)&&Object.entries(t).forEach(([i,r])=>{it(r)?n.setAttribute(i,r):r===!0&&n.setAttribute(i,"")}),it(l)&&n.appendChild(document.createTextNode(l)),n},bp=Pu,kp=async()=>{var l;const e=bp({name:"VuepressApp",setup(){var n;pp();for(const i of hn)(n=i.setup)==null||n.call(i);return()=>[he(Vs),...hn.flatMap(({rootComponents:i=[]})=>i.map(r=>he(r)))]}}),t=vp();_p(e),fp(e,t,hn);for(const n of hn)await((l=n.enhance)==null?void 0:l.call(n,{app:e,router:t,siteData:ll}));return e.use(t),{app:e,router:t}};kp().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{ke as F,xe as _,ie as a,ce as b,ee as c,kp as createVueApp,Vt as d,$a as e,fc as f,Lo as g,C as h,Ge as i,pe as j,We as k,Vi as l,_e as m,Ul as n,W as o,Xl as p,s as q,mt as r,be as s,Ep as t,Xt as u,St as v,Ce as w,Pe as x}; + */const ue={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
'},status:null,set:e=>{const t=ue.isStarted();e=ti(e,ue.settings.minimum,1),ue.status=e===1?null:e;const l=ue.render(!t),n=l.querySelector(ue.settings.barSelector),i=ue.settings.speed,r=ue.settings.easing;return l.offsetWidth,Lh(o=>{an(n,{transform:"translate3d("+ro(e)+"%,0,0)",transition:"all "+i+"ms "+r}),e===1?(an(l,{transition:"none",opacity:"1"}),l.offsetWidth,setTimeout(function(){an(l,{transition:"all "+i+"ms linear",opacity:"0"}),setTimeout(function(){ue.remove(),o()},i)},i)):setTimeout(()=>o(),i)}),ue},isStarted:()=>typeof ue.status=="number",start:()=>{ue.status||ue.set(0);const e=()=>{setTimeout(()=>{ue.status&&(ue.trickle(),e())},ue.settings.trickleSpeed)};return ue.settings.trickle&&e(),ue},done:e=>!e&&!ue.status?ue:ue.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=ue.status;return t?(typeof e!="number"&&(e=(1-t)*ti(Math.random()*t,.1,.95)),t=ti(t+e,0,.994),ue.set(t)):ue.start()},trickle:()=>ue.inc(Math.random()*ue.settings.trickleRate),render:e=>{if(ue.isRendered())return document.getElementById("nprogress");oo(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=ue.settings.template;const l=t.querySelector(ue.settings.barSelector),n=e?"-100":ro(ue.status||0),i=document.querySelector(ue.settings.parent);return an(l,{transition:"all 0 linear",transform:"translate3d("+n+"%,0,0)"}),i!==document.body&&oo(i,"nprogress-custom-parent"),i==null||i.appendChild(t),t},remove:()=>{so(document.documentElement,"nprogress-busy"),so(document.querySelector(ue.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&Th(e)},isRendered:()=>!!document.getElementById("nprogress")},ti=(e,t,l)=>el?l:e,ro=e=>(-1+e)*100,Lh=function(){const e=[];function t(){const l=e.shift();l&&l(t)}return function(l){e.push(l),e.length===1&&t()}}(),an=function(){const e=["Webkit","O","Moz","ms"],t={};function l(o){return o.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(c,a){return a.toUpperCase()})}function n(o){const c=document.body.style;if(o in c)return o;let a=e.length;const u=o.charAt(0).toUpperCase()+o.slice(1);let d;for(;a--;)if(d=e[a]+u,d in c)return d;return o}function i(o){return o=l(o),t[o]??(t[o]=n(o))}function r(o,c,a){c=i(c),o.style[c]=a}return function(o,c){for(const a in c){const u=c[a];u!==void 0&&Object.prototype.hasOwnProperty.call(c,a)&&r(o,a,u)}}}(),Fs=(e,t)=>(typeof e=="string"?e:Xi(e)).indexOf(" "+t+" ")>=0,oo=(e,t)=>{const l=Xi(e),n=l+t;Fs(l,t)||(e.className=n.substring(1))},so=(e,t)=>{const l=Xi(e);if(!Fs(e,t))return;const n=l.replace(" "+t+" "," ");e.className=n.substring(1,n.length-1)},Xi=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),Th=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)},Oh=()=>{We(()=>{const e=bt(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(l=>{t.has(l.path)||ue.start()}),e.afterEach(l=>{t.add(l.path),ue.done()})})},Ph=Et({setup(){Oh()}}),Ah=JSON.parse(`{"name":"vuepress-theme-xray","smoothScroll":true,"repo":"xtls/xray-core","docsDir":"docs","docsRepo":"xtls/Xray-docs-next","docsBranch":"main","editLinks":true,"enableToggle":true,"locales":{"/":{"navbar":[{"text":"首页","link":"/"},{"text":"大史记","link":"/about/news.md"},{"text":"配置指南","link":"/config/"},{"text":"开发指南","link":"/development/"},{"text":"使用指南","link":"/document/"}],"sidebar":{"/config/":[{"text":"特性详解","children":["/config/features/xtls.md","/config/features/fallback.md","/config/features/browser_dialer.md","/config/features/env.md","/config/features/multiple.md"]},{"text":"基础配置","children":["/config/README.md","/config/log.md","/config/api.md","/config/dns.md","/config/fakedns.md","/config/inbound.md","/config/outbound.md","/config/policy.md","/config/reverse.md","/config/routing.md","/config/stats.md","/config/transport.md","/config/metrics.md","/config/observatory.md"]},{"text":"入站代理","children":["/config/inbounds/dokodemo.md","/config/inbounds/http.md","/config/inbounds/shadowsocks.md","/config/inbounds/socks.md","/config/inbounds/trojan.md","/config/inbounds/vless.md","/config/inbounds/vmess.md"]},{"text":"出站代理","children":["/config/outbounds/blackhole.md","/config/outbounds/dns.md","/config/outbounds/freedom.md","/config/outbounds/http.md","/config/outbounds/loopback.md","/config/outbounds/shadowsocks.md","/config/outbounds/socks.md","/config/outbounds/trojan.md","/config/outbounds/vless.md","/config/outbounds/vmess.md","/config/outbounds/wireguard.md"]},{"text":"底层传输","children":["/config/transports/domainsocket.md","/config/transports/grpc.md","/config/transports/h2.md","/config/transports/mkcp.md","/config/transports/quic.md","/config/transports/tcp.md","/config/transports/websocket.md","/config/transports/httpupgrade.md","/config/transports/splithttp.md"]}],"/document/":[{"text":"快速入门文档","children":["/document/README.md","/document/install.md","/document/config.md","/document/command.md","/document/document.md"]},{"text":"小小白白话文","children":["/document/level-0/README.md","/document/level-0/ch01-preface.md","/document/level-0/ch02-preparation.md","/document/level-0/ch03-ssh.md","/document/level-0/ch04-security.md","/document/level-0/ch05-webpage.md","/document/level-0/ch06-certificates.md","/document/level-0/ch07-xray-server.md","/document/level-0/ch08-xray-clients.md","/document/level-0/ch09-appendix.md"]},{"text":"入门技巧","children":["/document/level-1/README.md","/document/level-1/fallbacks-lv1.md","/document/level-1/routing-lv1-part1.md","/document/level-1/routing-lv1-part2.md","/document/level-1/work.md","/document/level-1/fallbacks-with-sni.md"]},{"text":"进阶技巧","children":["/document/level-2/README.md","/document/level-2/transparent_proxy/transparent_proxy.md","/document/level-2/tproxy.md","/document/level-2/tproxy_ipv4_and_ipv6.md","/document/level-2/nginx_or_haproxy_tls_tunnel.md","/document/level-2/iptables_gid.md","/document/level-2/redirect.md","/document/level-2/warp.md","/document/level-2/traffic_stats.md"]}],"/development/":[{"text":"开发指南","children":["/development/README.md","/development/intro/compile.md","/development/intro/design.md","/development/intro/guide.md"]},{"text":"协议详解","children":["/development/protocols/vless.md","/development/protocols/vmess.md","/development/protocols/muxcool.md","/development/protocols/mkcp.md"]}]},"repoLabel":"查看源码","editLinkText":"帮助我们改善此页面!","tip":"提示","warning":"注意","danger":"警告","lastUpdatedText":"最近更改","selectLanguageName":"简体中文","selectLanguageText":"🌏 简体中文 / Change language","selectLanguageAriaLabel":"简体中文 / Change language","docsDir":"docs","backToHome":"back to home","openInNewWindow":"open in new tag","toggleColorMode":"toggle color mode","toggleSidebar":"toggle side bar"},"/en/":{"sidebar":{"/en/config/":[{"text":"feature","children":["/en/config/features/xtls.md","/en/config/features/fallback.md","/en/config/features/browser_dialer.md","/en/config/features/env.md","/en/config/features/multiple.md"]},{"text":"config","children":["/en/config/README.md","/en/config/log.md","/en/config/api.md","/en/config/dns.md","/en/config/fakedns.md","/en/config/inbound.md","/en/config/outbound.md","/en/config/policy.md","/en/config/reverse.md","/en/config/routing.md","/en/config/stats.md","/en/config/transport.md","/en/config/metrics.md","/en/config/observatory.md"]},{"text":"inbound","children":["/en/config/inbounds/dokodemo.md","/en/config/inbounds/http.md","/en/config/inbounds/shadowsocks.md","/en/config/inbounds/socks.md","/en/config/inbounds/trojan.md","/en/config/inbounds/vless.md","/en/config/inbounds/vmess.md"]},{"text":"outbound","children":["/en/config/outbounds/blackhole.md","/en/config/outbounds/dns.md","/en/config/outbounds/freedom.md","/en/config/outbounds/http.md","/en/config/outbounds/loopback.md","/en/config/outbounds/shadowsocks.md","/en/config/outbounds/socks.md","/en/config/outbounds/trojan.md","/en/config/outbounds/vless.md","/en/config/outbounds/vmess.md","/en/config/outbounds/wireguard.md"]},{"text":"transport","children":["/en/config/transports/domainsocket.md","/en/config/transports/grpc.md","/en/config/transports/h2.md","/en/config/transports/mkcp.md","/en/config/transports/quic.md","/en/config/transports/tcp.md","/en/config/transports/websocket.md","/en/config/transports/httpupgrade.md","/en/config/transports/splithttp.md"]}],"/en/document/":[{"text":"Quick Start","children":["/en/document/README.md","/en/document/install.md","/en/document/config.md","/en/document/command.md","/en/document/document.md"]},{"text":"Beginner Tutorial","children":["/en/document/level-0/README.md","/en/document/level-0/ch01-preface.md","/en/document/level-0/ch02-preparation.md","/en/document/level-0/ch03-ssh.md","/en/document/level-0/ch04-security.md","/en/document/level-0/ch05-webpage.md","/en/document/level-0/ch06-certificates.md","/en/document/level-0/ch07-xray-server.md","/en/document/level-0/ch08-xray-clients.md","/en/document/level-0/ch09-appendix.md"]},{"text":"Getting Started Tips","children":["/en/document/level-1/README.md","/en/document/level-1/fallbacks-lv1.md","/en/document/level-1/routing-lv1-part1.md","/en/document/level-1/routing-lv1-part2.md","/en/document/level-1/work.md","/en/document/level-1/fallbacks-with-sni.md"]},{"text":"Advanced Documentation","children":["/en/document/level-2/README.md","/en/document/level-2/transparent_proxy/transparent_proxy.md","/en/document/level-2/tproxy.md","/en/document/level-2/tproxy_ipv4_and_ipv6.md","/en/document/level-2/nginx_or_haproxy_tls_tunnel.md","/en/document/level-2/iptables_gid.md","/en/document/level-2/redirect.md","/en/document/level-2/warp.md","/en/document/level-2/traffic_stats.md"]}],"/en/development/":[{"text":"Developer Guide","children":["/en/development/README.md","/en/development/intro/compile.md","/en/development/intro/design.md","/en/development/intro/guide.md"]},{"text":"Protocol Details","children":["/en/development/protocols/vless.md","/en/development/protocols/vmess.md","/en/development/protocols/muxcool.md","/en/development/protocols/mkcp.md"]}]},"navbar":[{"text":"Homepage","link":"/en"},{"text":"Website History","link":"/en/about/news.md"},{"text":"Config Reference","link":"/en/config/"},{"text":"Developer Guide","link":"/en/development/"},{"text":"Quick Start","link":"/en/document/"}],"selectLanguageName":"English (WIP)","selectLanguageText":"🌎 English / Change language","selectLanguageAriaLabel":"English / Change language","editLinkText":"Help us improve this page on GitHub!","lastUpdatedText":"Last Updated","contributorsText":"contributors","tip":"Tip","warning":"Warning","danger":"Danger","notFound":["这里什么都没有","我们怎么到这来了?","这是一个 404 页面","看起来我们进入了错误的链接"],"backToHome":"back to home","openInNewWindow":"open in new tag","toggleColorMode":"toggle color mode","toggleSidebar":"toggle side bar"},"/ru/":{"navbar":[{"text":"Главная","link":"/ru"},{"text":"История сайта","link":"/ru/about/news.md"},{"text":"Справочник по конфигурации","link":"/ru/config/"},{"text":"Руководство разработчика","link":"/ru/development/"},{"text":"Быстрый старт","link":"/ru/document/"}],"sidebar":{"/ru/config/":[{"text":"Описание функций","children":["/ru/config/features/xtls.md","/ru/config/features/fallback.md","/ru/config/features/browser_dialer.md","/ru/config/features/env.md","/ru/config/features/multiple.md"]},{"text":"Базовая конфигурация","children":["/ru/config/README.md","/ru/config/log.md","/ru/config/api.md","/ru/config/dns.md","/ru/config/fakedns.md","/ru/config/inbound.md","/ru/config/outbound.md","/ru/config/policy.md","/ru/config/reverse.md","/ru/config/routing.md","/ru/config/stats.md","/ru/config/transport.md","/ru/config/metrics.md","/ru/config/observatory.md"]},{"text":"Входящие подключения","children":["/ru/config/inbounds/dokodemo.md","/ru/config/inbounds/http.md","/ru/config/inbounds/shadowsocks.md","/ru/config/inbounds/socks.md","/ru/config/inbounds/trojan.md","/ru/config/inbounds/vless.md","/ru/config/inbounds/vmess.md"]},{"text":"Исходящие подключения","children":["/ru/config/outbounds/blackhole.md","/ru/config/outbounds/dns.md","/ru/config/outbounds/freedom.md","/ru/config/outbounds/http.md","/ru/config/outbounds/loopback.md","/ru/config/outbounds/shadowsocks.md","/ru/config/outbounds/socks.md","/ru/config/outbounds/trojan.md","/ru/config/outbounds/vless.md","/ru/config/outbounds/vmess.md","/ru/config/outbounds/wireguard.md"]},{"text":"Транспортный уровень","children":["/ru/config/transports/domainsocket.md","/ru/config/transports/grpc.md","/ru/config/transports/h2.md","/ru/config/transports/mkcp.md","/ru/config/transports/quic.md","/ru/config/transports/tcp.md","/ru/config/transports/websocket.md","/ru/config/transports/httpupgrade.md","/ru/config/transports/splithttp.md"]}],"/ru/document/":[{"text":"Быстрый старт","children":["/ru/document/README.md","/ru/document/install.md","/ru/document/config.md","/ru/document/command.md","/ru/document/document.md"]},{"text":"Простыми словами","children":["/ru/document/level-0/README.md","/ru/document/level-0/ch01-preface.md","/ru/document/level-0/ch02-preparation.md","/ru/document/level-0/ch03-ssh.md","/ru/document/level-0/ch04-security.md","/ru/document/level-0/ch05-webpage.md","/ru/document/level-0/ch06-certificates.md","/ru/document/level-0/ch07-xray-server.md","/ru/document/level-0/ch08-xray-clients.md","/ru/document/level-0/ch09-appendix.md"]},{"text":"Базовые навыки","children":["/ru/document/level-1/README.md","/ru/document/level-1/fallbacks-lv1.md","/ru/document/level-1/routing-lv1-part1.md","/ru/document/level-1/routing-lv1-part2.md","/ru/document/level-1/work.md","/ru/document/level-1/fallbacks-with-sni.md"]},{"text":"Продвинутые навыки","children":["/ru/document/level-2/README.md","/ru/document/level-2/transparent_proxy/transparent_proxy.md","/ru/document/level-2/tproxy.md","/ru/document/level-2/tproxy_ipv4_and_ipv6.md","/ru/document/level-2/nginx_or_haproxy_tls_tunnel.md","/ru/document/level-2/iptables_gid.md","/ru/document/level-2/redirect.md","/ru/document/level-2/warp.md","/ru/document/level-2/traffic_stats.md"]}],"/ru/development/":[{"text":"Руководство разработчика","children":["/ru/development/README.md","/ru/development/intro/compile.md","/ru/development/intro/design.md","/ru/development/intro/guide.md"]},{"text":"Описание протоколов","children":["/ru/development/protocols/vless.md","/ru/development/protocols/vmess.md","/ru/development/protocols/muxcool.md","/ru/development/protocols/mkcp.md"]}]},"repoLabel":"Посмотреть исходный код","editLinkText":"Помогите нам улучшить эту страницу!","tip":"Подсказка","warning":"Внимание","danger":"Предупреждение","lastUpdatedText":"Последние изменения","selectLanguageName":"Русский (WIP)","selectLanguageText":"🌍 Русский / Change language","selectLanguageAriaLabel":"Русский / Change language","docsDir":"docs","backToHome":"На главную","openInNewWindow":"Открыть в новой вкладке","toggleColorMode":"Переключить цветовую схему","toggleSidebar":"Переключить боковую панель"},"themePlugins":{"git":true}},"colorMode":"auto","colorModeSwitch":true,"navbar":[],"logo":null,"selectLanguageText":"Languages","selectLanguageAriaLabel":"Select language","sidebar":"auto","sidebarDepth":2,"editLink":true,"editLinkText":"Edit this page","lastUpdated":true,"lastUpdatedText":"Last Updated","contributors":true,"contributorsText":"Contributors","notFound":["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],"backToHome":"Take me home","openInNewWindow":"open in new window","toggleColorMode":"toggle color mode","toggleSidebar":"toggle sidebar"}`),wh=pe(Ah),Ns=()=>wh,Hs=Symbol(""),Rh=()=>{const e=Te(Hs);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},Ih=(e,t)=>{const{locales:l,...n}=e;return{...n,...l==null?void 0:l[t]}},Dh=Et({enhance({app:e}){const t=Ns(),l=e._context.provides[Mi],n=C(()=>Ih(t.value,l.value));e.provide(Hs,n),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return n.value}}})}}),jh=_e({__name:"Badge",props:{type:{type:String,required:!1,default:"tip"},text:{type:String,required:!1,default:""},vertical:{type:String,required:!1,default:void 0}},setup(e,{expose:t}){t();const l={};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),xe=(e,t)=>{const l=e.__vccOpts||e;for(const[n,i]of t)l[n]=i;return l};function Sh(e,t,l,n,i,r){return W(),ee("span",{class:$e(["badge",l.type]),style:Wl({verticalAlign:l.vertical})},[be(e.$slots,"default",{},()=>[Vt(Pe(l.text),1)])],6)}const Ch=xe(jh,[["render",Sh],["__file","Badge.vue"]]);function Vh(e,t){let l,n,i;const r=pe(!0),o=()=>{r.value=!0,i()};Ge(e,o,{flush:"sync"});const c=typeof t=="function"?t:t.get,a=typeof t=="function"?void 0:t.set,u=Mc((d,v)=>(n=d,i=v,{get(){return r.value&&(l=c(),r.value=!1),n(),l},set(_){a==null||a(_)}}));return Object.isExtensible(u)&&(u.trigger=o),u}function Ms(e){return Lo()?(fc(e),!0):!1}function _l(e){return typeof e=="function"?e():Xt(e)}const Fh=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Nh=Object.prototype.toString,Hh=e=>Nh.call(e)==="[object Object]",Mh=()=>{};function $h(e,t){function l(...n){return new Promise((i,r)=>{Promise.resolve(e(()=>t.apply(this,n),{fn:t,thisArg:this,args:n})).then(i).catch(r)})}return l}const $s=e=>e();function Bh(e=$s){const t=pe(!0);function l(){t.value=!1}function n(){t.value=!0}const i=(...r)=>{t.value&&e(...r)};return{isActive:In(t),pause:l,resume:n,eventFilter:i}}function Wh(e){return Vi()}function Uh(e,t,l={}){const{eventFilter:n=$s,...i}=l;return Ge(e,$h(n,t),i)}function zh(e,t,l={}){const{eventFilter:n,...i}=l,{eventFilter:r,pause:o,resume:c,isActive:a}=Bh(n);return{stop:Uh(e,t,{...i,eventFilter:r}),pause:o,resume:c,isActive:a}}function Xh(e,t=!0,l){Wh()?We(e,l):t?e():Xl(e)}function Kh(e=!1,t={}){const{truthyValue:l=!0,falsyValue:n=!1}=t,i=Ne(e),r=pe(e);function o(c){if(arguments.length)return r.value=c,r.value;{const a=_l(l);return r.value=r.value===a?_l(n):a,r.value}}return i?o:[r,o]}function qh(e){var t;const l=_l(e);return(t=l==null?void 0:l.$el)!=null?t:l}const On=Fh?window:void 0;function co(...e){let t,l,n,i;if(typeof e[0]=="string"||Array.isArray(e[0])?([l,n,i]=e,t=On):[t,l,n,i]=e,!t)return Mh;Array.isArray(l)||(l=[l]),Array.isArray(n)||(n=[n]);const r=[],o=()=>{r.forEach(d=>d()),r.length=0},c=(d,v,_,g)=>(d.addEventListener(v,_,g),()=>d.removeEventListener(v,_,g)),a=Ge(()=>[qh(t),_l(i)],([d,v])=>{if(o(),!d)return;const _=Hh(v)?{...v}:v;r.push(...l.flatMap(g=>n.map(m=>c(d,g,m,_))))},{immediate:!0,flush:"post"}),u=()=>{a(),o()};return Ms(u),u}function Gh(){const e=pe(!1),t=Vi();return t&&We(()=>{e.value=!0},t),e}function Yh(e){const t=Gh();return C(()=>(t.value,!!e()))}function Qh(e,t={}){const{window:l=On}=t,n=Yh(()=>l&&"matchMedia"in l&&typeof l.matchMedia=="function");let i;const r=pe(!1),o=u=>{r.value=u.matches},c=()=>{i&&("removeEventListener"in i?i.removeEventListener("change",o):i.removeListener(o))},a=ra(()=>{n.value&&(c(),i=l.matchMedia(_l(e)),"addEventListener"in i?i.addEventListener("change",o):i.addListener(o),r.value=i.matches)});return Ms(()=>{a(),c(),i=void 0}),r}const un=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},dn="__vueuse_ssr_handlers__",Jh=Zh();function Zh(){return dn in un||(un[dn]=un[dn]||{}),un[dn]}function ev(e,t){return Jh[e]||t}function tv(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"?"object":Number.isNaN(e)?"any":"number"}const lv={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}},ao="vueuse-storage";function Bs(e,t,l,n={}){var i;const{flush:r="pre",deep:o=!0,listenToStorageChanges:c=!0,writeDefaults:a=!0,mergeDefaults:u=!1,shallow:d,window:v=On,eventFilter:_,onError:g=w=>{console.error(w)},initOnMounted:m}=n,x=(d?No:pe)(typeof t=="function"?t():t);if(!l)try{l=ev("getDefaultStorage",()=>{var w;return(w=On)==null?void 0:w.localStorage})()}catch(w){g(w)}if(!l)return x;const A=_l(t),D=tv(A),O=(i=n.serializer)!=null?i:lv[D],{pause:b,resume:y}=zh(x,()=>G(x.value),{flush:r,deep:o,eventFilter:_});v&&c&&Xh(()=>{co(v,"storage",E),co(v,ao,K),m&&E()}),m||E();function H(w,z){v&&v.dispatchEvent(new CustomEvent(ao,{detail:{key:e,oldValue:w,newValue:z,storageArea:l}}))}function G(w){try{const z=l.getItem(e);if(w==null)H(z,null),l.removeItem(e);else{const L=O.write(w);z!==L&&(l.setItem(e,L),H(z,L))}}catch(z){g(z)}}function N(w){const z=w?w.newValue:l.getItem(e);if(z==null)return a&&A!=null&&l.setItem(e,O.write(A)),A;if(!w&&u){const L=O.read(z);return typeof u=="function"?u(L,A):D==="object"&&!Array.isArray(L)?{...A,...L}:L}else return typeof z!="string"?z:O.read(z)}function E(w){if(!(w&&w.storageArea!==l)){if(w&&w.key==null){x.value=A;return}if(!(w&&w.key!==e)){b();try{(w==null?void 0:w.newValue)!==O.write(x.value)&&(x.value=N(w))}catch(z){g(z)}finally{w?Xl(y):y()}}}}function K(w){E(w.detail)}return x}function nv(e){return Qh("(prefers-color-scheme: dark)",e)}const iv=_e({name:"CodeGroup",slots:Object,setup(e,{slots:t}){const l=pe([]),n=pe(-1),i=Bs("vuepress-code-group",{}),r=C(()=>l.value.map(u=>u.innerText).join(","));We(()=>{Ge(()=>i.value[r.value],(u=-1)=>{n.value!==u&&(n.value=u)},{immediate:!0}),Ge(n,u=>{i.value[r.value]!==u&&(i.value[r.value]=u)})});const o=(u=n.value)=>{u{u>0?n.value=u-1:n.value=l.value.length-1,l.value[n.value].focus()},a=(u,d)=>{u.key===" "||u.key==="Enter"?(u.preventDefault(),n.value=d):u.key==="ArrowRight"?(u.preventDefault(),o(d)):u.key==="ArrowLeft"&&(u.preventDefault(),c(d))};return()=>{var d;const u=(((d=t.default)==null?void 0:d.call(t))||[]).filter(v=>v.type.name==="CodeGroupItem").map(v=>(v.props===null&&(v.props={}),v));return u.length===0?null:(n.value<0||n.value>u.length-1?(n.value=u.findIndex(v=>v.props.active===""||v.props.active===!0),n.value===-1&&(n.value=0)):u.forEach((v,_)=>{v.props.active=_===n.value}),he("div",{class:"code-group"},[he("div",{class:"code-group__nav",role:"tablist"},u.map((v,_)=>{const g=_===n.value;return he("button",{ref:m=>{m&&(l.value[_]=m)},class:{"code-group__nav-tab":!0,"code-group__nav-tab-active":g},role:"tab",ariaSelected:g,onClick:()=>n.value=_,onKeydown:m=>a(m,_)},v.props.title)})),u]))}}}),rv=_e({name:"CodeGroupItem",__name:"CodeGroupItem",props:{title:{type:String,required:!0},active:{type:Boolean,required:!1,default:!1}},setup(e,{expose:t}){t();const l={};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}});function ov(e,t,l,n,i,r){return W(),ee("div",{class:$e(["code-group-item",{"code-group-item__active":l.active}]),role:"tabpanel"},[be(e.$slots,"default")],2)}const sv=xe(rv,[["render",ov],["__file","CodeGroupItem.vue"]]),cv=()=>Ns(),Fe=()=>Rh(),Ws=Symbol(""),Ki=()=>{const e=Te(Ws);if(!e)throw new Error("useDarkMode() is called without provider.");return e},av=()=>{const e=Fe(),t=nv(),l=Bs("vuepress-color-scheme",e.value.colorMode),n=C({get(){return e.value.colorModeSwitch?l.value==="auto"?t.value:l.value==="dark":e.value.colorMode==="dark"},set(i){i===t.value?l.value="auto":l.value=i?"dark":"light"}});Kt(Ws,n),uv(n)},uv=e=>{const t=(l=e.value)=>{const n=window==null?void 0:window.document.querySelector("html");n==null||n.classList.toggle("dark",l)};We(()=>{Ge(e,t,{immediate:!0})}),Vn(()=>t())};let li=null,Ll=null;const dv={wait:()=>li,pending:()=>{li=new Promise(e=>Ll=e)},resolve:()=>{Ll==null||Ll(),li=null,Ll=null}},Us=()=>dv,zs=(e,...t)=>{const l=e.resolve(...t),n=l.matched[l.matched.length-1];if(!(n!=null&&n.redirect))return l;const{redirect:i}=n,r=Nu(i)?i(l):i,o=it(r)?{path:r}:r;return zs(e,{hash:l.hash,query:l.query,params:l.params,...o})},qi=(e,t)=>{const l=zs(e,encodeURI(t));return{text:l.meta.title||t,link:l.name==="404"?t:l.fullPath}},uo=e=>decodeURI(e).replace(/#.*$/,"").replace(/(index)?\.(md|html)$/,""),hv=(e,t)=>{if(t.hash===e)return!0;const l=uo(t.path),n=uo(e);return l===n},Xs=(e,t)=>e.link&&hv(e.link,t)?!0:e.children?e.children.some(l=>Xs(l,t)):!1,Ks=e=>!Yl(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,vv={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},_v=({docsRepo:e,editLinkPattern:t})=>{if(t)return t;const l=Ks(e);return l!==null?vv[l]:null},fv=({docsRepo:e,docsBranch:t,docsDir:l,filePathRelative:n,editLinkPattern:i})=>{if(!n)return null;const r=_v({docsRepo:e,editLinkPattern:i});return r?r.replace(/:repo/,Yl(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,fs(`${_s(l)}/${n}`)):null},qs=Symbol("sidebarItems"),Gi=()=>{const e=Te(qs);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},pv=()=>{const e=Fe(),t=gt(),l=Gt(),n=ml(),i=bt(),r=C(()=>gv(t.value,e.value,l.value,i,n.path));Kt(qs,r)},gv=(e,t,l,n,i)=>{const r=e.sidebar??t.sidebar??"auto",o=e.sidebarDepth??t.sidebarDepth??2;return e.home||r===!1?[]:r==="auto"?Gs(l,o):Array.isArray(r)?Ys(l,n,i,r,o):Hi(r)?bv(l,n,i,r,o):[]},mv=(e,t)=>({text:e.title,link:e.link,children:Yi(e.children,t)}),Yi=(e,t)=>t>0?e.map(l=>mv(l,t-1)):[],Gs=(e,t)=>[{text:e.title,children:Yi(e.headers,t)}],Ys=(e,t,l,n,i)=>{const r=o=>{var a;let c;if(it(o)?c=qi(t,o):c=o,c.children)return{...c,children:c.children.map(u=>r(u))};if(c.link===l){const u=((a=e.headers[0])==null?void 0:a.level)===1?e.headers[0].children:e.headers;return{...c,children:Yi(u,i)}}return c};return n.map(o=>r(o))},bv=(e,t,l,n,i)=>{const r=ps(n,l),o=n[r]??[];return o==="heading"?Gs(e,i):Ys(e,t,l,o,i)},kv="719px",Ev={mobile:kv};var $l;(function(e){e.MOBILE="mobile"})($l||($l={}));var go;const yv={[$l.MOBILE]:Number.parseInt((go=Ev.mobile)==null?void 0:go.replace("px",""),10)},Qs=(e,t)=>{const l=yv[e];Number.isInteger(l)&&We(()=>{t(l),window.addEventListener("resize",()=>t(l),!1),window.addEventListener("orientationchange",()=>t(l),!1)})},xv={},Lv={class:"theme-default-content"};function Tv(e,t){const l=mt("Content");return W(),ee("div",Lv,[ie(l)])}const Ov=xe(xv,[["render",Tv],["__file","HomeContent.vue"]]),Pv=_e({__name:"HomeFeatures",setup(e,{expose:t}){t();const l=gt(),n=C(()=>Array.isArray(l.value.features)?l.value.features:[]),i={frontmatter:l,features:n};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}}),Av={key:0,class:"features"};function wv(e,t,l,n,i,r){return n.features.length?(W(),ee("div",Av,[(W(!0),ee(ke,null,St(n.features,o=>(W(),ee("div",{key:o.title,class:"feature"},[ce("h2",null,Pe(o.title),1),ce("p",null,Pe(o.details),1)]))),128))])):Le("",!0)}const Rv=xe(Pv,[["render",wv],["__file","HomeFeatures.vue"]]),Iv=_e({__name:"HomeFooter",setup(e,{expose:t}){t();const l=gt(),n=C(()=>l.value.footer),i=C(()=>l.value.footerHtml),r={frontmatter:l,footer:n,footerHtml:i};return Object.defineProperty(r,"__isScriptSetup",{enumerable:!1,value:!0}),r}}),Dv=["innerHTML"],jv=["textContent"];function Sv(e,t,l,n,i,r){return n.footer?(W(),ee(ke,{key:0},[n.footerHtml?(W(),ee("div",{key:0,class:"footer",innerHTML:n.footer},null,8,Dv)):(W(),ee("div",{key:1,class:"footer",textContent:Pe(n.footer)},null,8,jv))],64)):Le("",!0)}const Cv=xe(Iv,[["render",Sv],["__file","HomeFooter.vue"]]),Vv=_e({inheritAttrs:!1,__name:"AutoLink",props:{item:{type:Object,required:!0}},setup(e,{expose:t}){t();const l=e,n=ml(),i=xs(),{item:r}=Dn(l),o=C(()=>Yl(r.value.link)),c=C(()=>!o.value&&Fu(r.value.link)),a=C(()=>{if(!c.value){if(r.value.target)return r.value.target;if(o.value)return"_blank"}}),u=C(()=>a.value==="_blank"),d=C(()=>!o.value&&!c.value&&!u.value),v=C(()=>{if(!c.value){if(r.value.rel)return r.value.rel;if(u.value)return"noopener noreferrer"}}),_=C(()=>r.value.ariaLabel||r.value.text),g=C(()=>{const D=Object.keys(i.value.locales);return D.length?!D.some(O=>O===r.value.link):r.value.link!=="/"}),m=C(()=>g.value?n.path.startsWith(r.value.link):!1),x=C(()=>d.value?r.value.activeMatch?new RegExp(r.value.activeMatch).test(n.path):m.value:!1),A={props:l,route:n,site:i,item:r,hasHttpProtocol:o,hasNonHttpProtocol:c,linkTarget:a,isBlankTarget:u,isRouterLink:d,linkRel:v,linkAriaLabel:_,shouldBeActiveInSubpath:g,isActiveInSubpath:m,isActive:x};return Object.defineProperty(A,"__isScriptSetup",{enumerable:!1,value:!0}),A}}),Fv=["href","rel","target","aria-label"];function Nv(e,t,l,n,i,r){const o=mt("RouterLink"),c=mt("AutoLinkExternalIcon");return n.isRouterLink?(W(),Ae(o,_i({key:0,class:{"router-link-active":n.isActive},to:n.item.link,"aria-label":n.linkAriaLabel},e.$attrs),{default:Ce(()=>[be(e.$slots,"before"),Vt(" "+Pe(n.item.text)+" ",1),be(e.$slots,"after")]),_:3},16,["class","to","aria-label"])):(W(),ee("a",_i({key:1,class:"external-link",href:n.item.link,rel:n.linkRel,target:n.linkTarget,"aria-label":n.linkAriaLabel},e.$attrs),[be(e.$slots,"before"),Vt(" "+Pe(n.item.text)+" ",1),n.isBlankTarget?(W(),Ae(c,{key:0})):Le("",!0),be(e.$slots,"after")],16,Fv))}const bl=xe(Vv,[["render",Nv],["__file","AutoLink.vue"]]),Hv=_e({__name:"HomeHero",setup(e,{expose:t}){t();const l=gt(),n=$i(),i=Ki(),r=C(()=>i.value&&l.value.heroImageDark!==void 0?l.value.heroImageDark:l.value.heroImage),o=C(()=>l.value.heroAlt||a.value||"hero"),c=C(()=>l.value.heroHeight||280),a=C(()=>l.value.heroText===null?null:l.value.heroText||n.value.title||"Hello"),u=C(()=>l.value.tagline===null?null:l.value.tagline||n.value.description||"Welcome to your VuePress site"),d=C(()=>Array.isArray(l.value.actions)?l.value.actions.map(({text:g,link:m,type:x="primary"})=>({text:g,link:m,type:x})):[]),_={frontmatter:l,siteLocale:n,isDarkMode:i,heroImage:r,heroAlt:o,heroHeight:c,heroText:a,tagline:u,actions:d,HomeHeroImage:()=>{if(!r.value)return null;const g=he("img",{src:Wi(r.value),alt:o.value,height:c.value});return l.value.heroImageDark===void 0?g:he(Bi,()=>g)},AutoLink:bl};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),Mv={class:"hero"},$v={key:0,id:"main-title"},Bv={key:1,class:"description"},Wv={key:2,class:"actions"};function Uv(e,t,l,n,i,r){return W(),ee("header",Mv,[ie(n.HomeHeroImage),n.heroText?(W(),ee("h1",$v,Pe(n.heroText),1)):Le("",!0),n.tagline?(W(),ee("p",Bv,Pe(n.tagline),1)):Le("",!0),n.actions.length?(W(),ee("p",Wv,[(W(!0),ee(ke,null,St(n.actions,o=>(W(),Ae(n.AutoLink,{key:o.text,class:$e(["action-button",[o.type]]),item:o},null,8,["class","item"]))),128))])):Le("",!0)])}const zv=xe(Hv,[["render",Uv],["__file","HomeHero.vue"]]),Xv=_e({__name:"Home",setup(e,{expose:t}){t();const l={HomeContent:Ov,HomeFeatures:Rv,HomeFooter:Cv,HomeHero:zv};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),Kv={class:"home"};function qv(e,t,l,n,i,r){return W(),ee("main",Kv,[ie(n.HomeHero),ie(n.HomeFeatures),ie(n.HomeContent),ie(n.HomeFooter)])}const Gv=xe(Xv,[["render",qv],["__file","Home.vue"]]),Yv=_e({__name:"NavbarBrand",setup(e,{expose:t}){t();const l=Ql(),n=$i(),i=Fe(),r=Ki(),o=C(()=>i.value.home||l.value),c=C(()=>n.value.title),a=C(()=>r.value&&i.value.logoDark!==void 0?i.value.logoDark:i.value.logo),u=C(()=>i.value.logoAlt??c.value),d=C(()=>c.value.toLocaleUpperCase().trim()===u.value.toLocaleUpperCase().trim()),_={routeLocale:l,siteLocale:n,themeLocale:i,isDarkMode:r,navbarBrandLink:o,navbarBrandTitle:c,navbarBrandLogo:a,navbarBrandLogoAlt:u,navBarLogoAltMatchesTitle:d,NavbarBrandLogo:()=>{if(!a.value)return null;const g=he("img",{class:"logo",src:Wi(a.value),alt:u.value});return i.value.logoDark===void 0?g:he(Bi,()=>g)}};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),Qv=["aria-hidden"];function Jv(e,t,l,n,i,r){const o=mt("RouterLink");return W(),Ae(o,{to:n.navbarBrandLink},{default:Ce(()=>[ie(n.NavbarBrandLogo),n.navbarBrandTitle?(W(),ee("span",{key:0,class:$e(["site-name",{"can-hide":n.navbarBrandLogo}]),"aria-hidden":n.navBarLogoAltMatchesTitle},Pe(n.navbarBrandTitle),11,Qv)):Le("",!0)]),_:1},8,["to"])}const Zv=xe(Yv,[["render",Jv],["__file","NavbarBrand.vue"]]),e_=_e({__name:"DropdownTransition",setup(e,{expose:t}){t();const i={setHeight:r=>{r.style.height=r.scrollHeight+"px"},unsetHeight:r=>{r.style.height=""}};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}});function t_(e,t,l,n,i,r){return W(),Ae(Gl,{name:"dropdown",onEnter:n.setHeight,onAfterEnter:n.unsetHeight,onBeforeLeave:n.setHeight},{default:Ce(()=>[be(e.$slots,"default")]),_:3})}const Js=xe(e_,[["render",t_],["__file","DropdownTransition.vue"]]),l_=_e({__name:"NavbarDropdown",props:{item:{type:Object,required:!0}},setup(e,{expose:t}){t();const l=e,{item:n}=Dn(l),i=C(()=>n.value.ariaLabel||n.value.text),r=pe(!1),o=ml();Ge(()=>o.path,()=>{r.value=!1});const u={props:l,item:n,dropdownAriaLabel:i,open:r,route:o,handleDropdown:d=>{d.detail===0?r.value=!r.value:r.value=!1},isLastItemOfArray:(d,v)=>v[v.length-1]===d,AutoLink:bl,DropdownTransition:Js};return Object.defineProperty(u,"__isScriptSetup",{enumerable:!1,value:!0}),u}}),n_=["aria-label"],i_={class:"title"},r_=ce("span",{class:"arrow down"},null,-1),o_=["aria-label"],s_={class:"title"},c_={class:"navbar-dropdown"},a_={class:"navbar-dropdown-subtitle"},u_={key:1},d_={class:"navbar-dropdown-subitem-wrapper"};function h_(e,t,l,n,i,r){return W(),ee("div",{class:$e(["navbar-dropdown-wrapper",{open:n.open}])},[ce("button",{class:"navbar-dropdown-title",type:"button","aria-label":n.dropdownAriaLabel,onClick:n.handleDropdown},[ce("span",i_,Pe(n.item.text),1),r_],8,n_),ce("button",{class:"navbar-dropdown-title-mobile",type:"button","aria-label":n.dropdownAriaLabel,onClick:t[0]||(t[0]=o=>n.open=!n.open)},[ce("span",s_,Pe(n.item.text),1),ce("span",{class:$e(["arrow",n.open?"down":"right"])},null,2)],8,o_),ie(n.DropdownTransition,null,{default:Ce(()=>[kn(ce("ul",c_,[(W(!0),ee(ke,null,St(n.item.children,o=>(W(),ee("li",{key:o.text,class:"navbar-dropdown-item"},[o.children?(W(),ee(ke,{key:0},[ce("h4",a_,[o.link?(W(),Ae(n.AutoLink,{key:0,item:o,onFocusout:c=>n.isLastItemOfArray(o,n.item.children)&&o.children.length===0&&(n.open=!1)},null,8,["item","onFocusout"])):(W(),ee("span",u_,Pe(o.text),1))]),ce("ul",d_,[(W(!0),ee(ke,null,St(o.children,c=>(W(),ee("li",{key:c.link,class:"navbar-dropdown-subitem"},[ie(n.AutoLink,{item:c,onFocusout:a=>n.isLastItemOfArray(c,o.children)&&n.isLastItemOfArray(o,n.item.children)&&(n.open=!1)},null,8,["item","onFocusout"])]))),128))])],64)):(W(),Ae(n.AutoLink,{key:1,item:o,onFocusout:c=>n.isLastItemOfArray(o,n.item.children)&&(n.open=!1)},null,8,["item","onFocusout"]))]))),128))],512),[[Tn,n.open]])]),_:1})],2)}const v_=xe(l_,[["render",h_],["__file","NavbarDropdown.vue"]]),__=_e({__name:"NavbarItems",setup(e,{expose:t}){t();const l=()=>{const g=bt(),m=Ql(),x=xs(),A=$i(),D=cv(),O=Fe();return C(()=>{const b=Object.keys(x.value.locales);if(b.length<2)return[];const y=g.currentRoute.value.path,H=g.currentRoute.value.fullPath;return[{text:`${O.value.selectLanguageText}`,ariaLabel:`${O.value.selectLanguageAriaLabel??O.value.selectLanguageText}`,children:b.map(N=>{var V,le;const E=((V=x.value.locales)==null?void 0:V[N])??{},K=((le=D.value.locales)==null?void 0:le[N])??{},w=`${E.lang}`,z=K.selectLanguageName??w;let L;if(w===A.value.lang)L=H;else{const ne=y.replace(m.value,N);g.getRoutes().some(S=>S.path===ne)?L=H.replace(y,ne):L=K.home??N}return{text:z,link:L}})}]})},n=()=>{const g=Fe(),m=C(()=>g.value.repo),x=C(()=>m.value?Ks(m.value):null),A=C(()=>m.value&&!Yl(m.value)?`https://github.com/${m.value}`:m.value),D=C(()=>A.value?g.value.repoLabel?g.value.repoLabel:x.value===null?"Source":x.value:null);return C(()=>!A.value||!D.value?[]:[{text:D.value,link:A.value}])},i=(g,m)=>it(m)?qi(g,m):m.children?{...m,children:m.children.map(x=>i(g,x))}:m,r=()=>{const g=bt(),m=Fe();return C(()=>(m.value.navbar||[]).map(x=>i(g,x)))},o=pe(!1),c=r(),a=l(),u=n(),d=C(()=>[...c.value,...a.value,...u.value]);Qs($l.MOBILE,g=>{window.innerWidthFe().value.navbarLabel??"site navigation"),_={useNavbarSelectLanguage:l,useNavbarRepo:n,resolveNavbarItem:i,useNavbarConfig:r,isMobile:o,navbarConfig:c,navbarSelectLanguage:a,navbarRepo:u,navbarLinks:d,navbarLabel:v,AutoLink:bl,NavbarDropdown:v_};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),f_=["aria-label"];function p_(e,t,l,n,i,r){return n.navbarLinks.length?(W(),ee("nav",{key:0,class:"navbar-items","aria-label":n.navbarLabel},[(W(!0),ee(ke,null,St(n.navbarLinks,o=>(W(),ee("div",{key:o.text,class:"navbar-item"},[o.children?(W(),Ae(n.NavbarDropdown,{key:0,item:o,class:$e(n.isMobile?"mobile":"")},null,8,["item","class"])):(W(),Ae(n.AutoLink,{key:1,item:o},null,8,["item"]))]))),128))],8,f_)):Le("",!0)}const Zs=xe(__,[["render",p_],["__file","NavbarItems.vue"]]),g_=_e({__name:"ToggleColorModeButton",setup(e,{expose:t}){t();const l=Fe(),n=Ki(),r={themeLocale:l,isDarkMode:n,toggleColorMode:()=>{n.value=!n.value}};return Object.defineProperty(r,"__isScriptSetup",{enumerable:!1,value:!0}),r}}),m_=["title"],b_={class:"icon",focusable:"false",viewBox:"0 0 32 32"},k_=$a('',9),E_=[k_],y_={class:"icon",focusable:"false",viewBox:"0 0 32 32"},x_=ce("path",{d:"M13.502 5.414a15.075 15.075 0 0 0 11.594 18.194a11.113 11.113 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1.002 1.002 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.072 13.072 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3z",fill:"currentColor"},null,-1),L_=[x_];function T_(e,t,l,n,i,r){return W(),ee("button",{class:"toggle-color-mode-button",title:n.themeLocale.toggleColorMode,onClick:n.toggleColorMode},[kn((W(),ee("svg",b_,E_,512)),[[Tn,!n.isDarkMode]]),kn((W(),ee("svg",y_,L_,512)),[[Tn,n.isDarkMode]])],8,m_)}const O_=xe(g_,[["render",T_],["__file","ToggleColorModeButton.vue"]]),P_=_e({__name:"ToggleSidebarButton",emits:["toggle"],setup(e,{expose:t}){t();const n={themeLocale:Fe()};return Object.defineProperty(n,"__isScriptSetup",{enumerable:!1,value:!0}),n}}),A_=["title"],w_=ce("div",{class:"icon","aria-hidden":"true"},[ce("span"),ce("span"),ce("span")],-1),R_=[w_];function I_(e,t,l,n,i,r){return W(),ee("div",{class:"toggle-sidebar-button",title:n.themeLocale.toggleSidebar,"aria-expanded":"false",role:"button",tabindex:"0",onClick:t[0]||(t[0]=o=>e.$emit("toggle"))},R_,8,A_)}const D_=xe(P_,[["render",I_],["__file","ToggleSidebarButton.vue"]]),j_=_e({__name:"Navbar",emits:["toggle-sidebar"],setup(e,{expose:t}){t();const l=Fe(),n=pe(null),i=pe(null),r=pe(0),o=C(()=>r.value?{maxWidth:r.value+"px"}:{});Qs($l.MOBILE,u=>{var v;const d=c(n.value,"paddingLeft")+c(n.value,"paddingRight");window.innerWidthe.$emit("toggle-sidebar"))}),ce("span",C_,[ie(n.NavbarBrand)],512),ce("div",{class:"navbar-items-wrapper",style:Wl(n.linksWrapperStyle)},[be(e.$slots,"before"),ie(n.NavbarItems,{class:"can-hide"}),be(e.$slots,"after"),n.themeLocale.colorModeSwitch?(W(),Ae(n.ToggleColorModeButton,{key:0})):Le("",!0),ie(o)],4)],512)}const F_=xe(j_,[["render",V_],["__file","Navbar.vue"]]),N_=_e({__name:"PageMeta",setup(e,{expose:t}){t();const l=()=>{const d=Fe(),v=Gt(),_=gt();return C(()=>{if(!(_.value.editLink??d.value.editLink??!0))return null;const{repo:m,docsRepo:x=m,docsBranch:A="main",docsDir:D="",editLinkText:O}=d.value;if(!x)return null;const b=fv({docsRepo:x,docsBranch:A,docsDir:D,filePathRelative:v.value.filePathRelative,editLinkPattern:_.value.editLinkPattern??d.value.editLinkPattern});return b?{text:O??"Edit this page",link:b}:null})},n=()=>{const d=Fe(),v=Gt(),_=gt();return C(()=>{var x,A;return!(_.value.lastUpdated??d.value.lastUpdated??!0)||!((x=v.value.git)!=null&&x.updatedTime)?null:new Date((A=v.value.git)==null?void 0:A.updatedTime).toLocaleString()})},i=()=>{const d=Fe(),v=Gt(),_=gt();return C(()=>{var m;return _.value.contributors??d.value.contributors??!0?((m=v.value.git)==null?void 0:m.contributors)??null:null})},r=Fe(),o=l(),c=n(),a=i(),u={useEditNavLink:l,useLastUpdated:n,useContributors:i,themeLocale:r,editNavLink:o,lastUpdated:c,contributors:a,AutoLink:bl};return Object.defineProperty(u,"__isScriptSetup",{enumerable:!1,value:!0}),u}}),H_={class:"page-meta"},M_={key:0,class:"meta-item edit-link"},$_={key:1,class:"meta-item last-updated"},B_={class:"meta-item-label"},W_={class:"meta-item-info"},U_={key:2,class:"meta-item contributors"},z_={class:"meta-item-label"},X_={class:"meta-item-info"},K_=["title"];function q_(e,t,l,n,i,r){const o=mt("ClientOnly");return W(),ee("footer",H_,[n.editNavLink?(W(),ee("div",M_,[ie(n.AutoLink,{class:"meta-item-label",item:n.editNavLink},null,8,["item"])])):Le("",!0),n.lastUpdated?(W(),ee("div",$_,[ce("span",B_,Pe(n.themeLocale.lastUpdatedText)+": ",1),ie(o,null,{default:Ce(()=>[ce("span",W_,Pe(n.lastUpdated),1)]),_:1})])):Le("",!0),n.contributors&&n.contributors.length?(W(),ee("div",U_,[ce("span",z_,Pe(n.themeLocale.contributorsText)+": ",1),ce("span",X_,[(W(!0),ee(ke,null,St(n.contributors,(c,a)=>(W(),ee(ke,{key:a},[ce("span",{class:"contributor",title:`email: ${c.email}`},Pe(c.name),9,K_),a!==n.contributors.length-1?(W(),ee(ke,{key:0},[Vt(", ")],64)):Le("",!0)],64))),128))])])):Le("",!0)])}const G_=xe(N_,[["render",q_],["__file","PageMeta.vue"]]),Y_=_e({__name:"PageNav",setup(e,{expose:t}){t();const l=(_,g)=>g===!1?null:it(g)?qi(_,g):Hi(g)?g:!1,n=(_,g,m)=>{const x=_.findIndex(A=>A.link===g);if(x!==-1){const A=_[x+m];return A!=null&&A.link?A:null}for(const A of _)if(A.children){const D=n(A.children,g,m);if(D)return D}return null},i=gt(),r=Gi(),o=ml(),c=bt(),a=C(()=>{const _=l(c,i.value.prev);return _!==!1?_:n(r.value,o.path,-1)}),u=C(()=>{const _=l(c,i.value.next);return _!==!1?_:n(r.value,o.path,1)}),d=C(()=>Fe().value.pageNavbarLabel??"page navigation"),v={resolveFromFrontmatterConfig:l,resolveFromSidebarItems:n,frontmatter:i,sidebarItems:r,route:o,router:c,prevNavLink:a,nextNavLink:u,navbarLabel:d,AutoLink:bl};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}}),Q_=["aria-label"],J_={class:"inner"},Z_={key:0,class:"prev"},ef={key:1,class:"next"};function tf(e,t,l,n,i,r){return n.prevNavLink||n.nextNavLink?(W(),ee("nav",{key:0,class:"page-nav","aria-label":n.navbarLabel},[ce("p",J_,[n.prevNavLink?(W(),ee("span",Z_,[ie(n.AutoLink,{item:n.prevNavLink},null,8,["item"])])):Le("",!0),n.nextNavLink?(W(),ee("span",ef,[ie(n.AutoLink,{item:n.nextNavLink},null,8,["item"])])):Le("",!0)])],8,Q_)):Le("",!0)}const lf=xe(Y_,[["render",tf],["__file","PageNav.vue"]]),nf=_e({__name:"Page",setup(e,{expose:t}){t();const l={PageMeta:G_,PageNav:lf};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),rf={class:"page"},of={class:"theme-default-content"};function sf(e,t,l,n,i,r){const o=mt("Content");return W(),ee("main",rf,[be(e.$slots,"top"),ce("div",of,[be(e.$slots,"content-top"),ie(o),be(e.$slots,"content-bottom")]),ie(n.PageMeta),ie(n.PageNav),be(e.$slots,"bottom")])}const cf=xe(nf,[["render",sf],["__file","Page.vue"]]),af=_e({__name:"SidebarItem",props:{item:{type:Object,required:!0},depth:{type:Number,required:!1,default:0}},setup(e,{expose:t}){t();const l=e,{item:n,depth:i}=Dn(l),r=ml(),o=bt(),c=C(()=>Xs(n.value,r)),a=C(()=>({"sidebar-item":!0,"sidebar-heading":i.value===0,active:c.value,collapsible:n.value.collapsible})),u=C(()=>n.value.collapsible?c.value:!0),[d,v]=Kh(u.value),_=x=>{n.value.collapsible&&(x.preventDefault(),v())},g=o.afterEach(x=>{Xl(()=>{d.value=u.value})});ql(()=>{g()});const m={props:l,item:n,depth:i,route:r,router:o,isActive:c,itemClass:a,isOpenDefault:u,isOpen:d,toggleIsOpen:v,onClick:_,unregisterRouterHook:g,AutoLink:bl,DropdownTransition:Js};return Object.defineProperty(m,"__isScriptSetup",{enumerable:!1,value:!0}),m}}),uf={class:"sidebar-item-children"};function df(e,t,l,n,i,r){var c;const o=mt("SidebarItem",!0);return W(),ee("li",null,[n.item.link?(W(),Ae(n.AutoLink,{key:0,class:$e(n.itemClass),item:n.item},null,8,["class","item"])):(W(),ee("p",{key:1,tabindex:"0",class:$e(n.itemClass),onClick:n.onClick,onKeydown:Lu(n.onClick,["enter"])},[Vt(Pe(n.item.text)+" ",1),n.item.collapsible?(W(),ee("span",{key:0,class:$e(["arrow",n.isOpen?"down":"right"])},null,2)):Le("",!0)],34)),(c=n.item.children)!=null&&c.length?(W(),Ae(n.DropdownTransition,{key:2},{default:Ce(()=>[kn(ce("ul",uf,[(W(!0),ee(ke,null,St(n.item.children,a=>(W(),Ae(o,{key:`${n.depth}${a.text}${a.link}`,item:a,depth:n.depth+1},null,8,["item","depth"]))),128))],512),[[Tn,n.isOpen]])]),_:1})):Le("",!0)])}const hf=xe(af,[["render",df],["__file","SidebarItem.vue"]]),vf=_e({__name:"SidebarItems",setup(e,{expose:t}){t();const l=ml(),n=Gi();We(()=>{Ge(()=>l.hash,r=>{const o=document.querySelector(".sidebar");if(!o)return;const c=document.querySelector(`.sidebar a.sidebar-item[href="${l.path}${r}"]`);if(!c)return;const{top:a,height:u}=o.getBoundingClientRect(),{top:d,height:v}=c.getBoundingClientRect();da+u&&c.scrollIntoView(!1)})});const i={route:l,sidebarItems:n,SidebarItem:hf};return Object.defineProperty(i,"__isScriptSetup",{enumerable:!1,value:!0}),i}}),_f={key:0,class:"sidebar-items"};function ff(e,t,l,n,i,r){return n.sidebarItems.length?(W(),ee("ul",_f,[(W(!0),ee(ke,null,St(n.sidebarItems,o=>(W(),Ae(n.SidebarItem,{key:`${o.text}${o.link}`,item:o},null,8,["item"]))),128))])):Le("",!0)}const pf=xe(vf,[["render",ff],["__file","SidebarItems.vue"]]),gf=_e({__name:"Sidebar",setup(e,{expose:t}){t();const l={NavbarItems:Zs,SidebarItems:pf};return Object.defineProperty(l,"__isScriptSetup",{enumerable:!1,value:!0}),l}}),mf={class:"sidebar"};function bf(e,t,l,n,i,r){return W(),ee("aside",mf,[ie(n.NavbarItems),be(e.$slots,"top"),ie(n.SidebarItems),be(e.$slots,"bottom")])}const kf=xe(gf,[["render",bf],["__file","Sidebar.vue"]]),Ef=_e({__name:"Layout",setup(e,{expose:t}){t();const l=Gt(),n=gt(),i=Fe(),r=C(()=>n.value.navbar!==!1&&i.value.navbar!==!1),o=Gi(),c=pe(!1),a=O=>{c.value=typeof O=="boolean"?O:!c.value},u={x:0,y:0},d=O=>{u.x=O.changedTouches[0].clientX,u.y=O.changedTouches[0].clientY},v=O=>{const b=O.changedTouches[0].clientX-u.x,y=O.changedTouches[0].clientY-u.y;Math.abs(b)>Math.abs(y)&&Math.abs(b)>40&&(b>0&&u.x<=80?a(!0):a(!1))},_=C(()=>[{"no-navbar":!r.value,"no-sidebar":!o.value.length,"sidebar-open":c.value},n.value.pageClass]);let g;We(()=>{g=bt().afterEach(()=>{a(!1)})}),Vn(()=>{g()});const m=Us(),x=m.resolve,A=m.pending,D={page:l,frontmatter:n,themeLocale:i,shouldShowNavbar:r,sidebarItems:o,isSidebarOpen:c,toggleSidebar:a,touchStart:u,onTouchStart:d,onTouchEnd:v,containerClass:_,get unregisterRouterHook(){return g},set unregisterRouterHook(O){g=O},scrollPromise:m,onBeforeEnter:x,onBeforeLeave:A,Home:Gv,Navbar:F_,Page:cf,Sidebar:kf};return Object.defineProperty(D,"__isScriptSetup",{enumerable:!1,value:!0}),D}});function yf(e,t,l,n,i,r){return W(),ee("div",{class:$e(["theme-container",n.containerClass]),onTouchstart:n.onTouchStart,onTouchend:n.onTouchEnd},[be(e.$slots,"navbar",{},()=>[n.shouldShowNavbar?(W(),Ae(n.Navbar,{key:0,onToggleSidebar:n.toggleSidebar},{before:Ce(()=>[be(e.$slots,"navbar-before")]),after:Ce(()=>[be(e.$slots,"navbar-after")]),_:3})):Le("",!0)]),ce("div",{class:"sidebar-mask",onClick:t[0]||(t[0]=o=>n.toggleSidebar(!1))}),be(e.$slots,"sidebar",{},()=>[ie(n.Sidebar,null,{top:Ce(()=>[be(e.$slots,"sidebar-top")]),bottom:Ce(()=>[be(e.$slots,"sidebar-bottom")]),_:3})]),be(e.$slots,"page",{},()=>[n.frontmatter.home?(W(),Ae(n.Home,{key:0})):(W(),Ae(Gl,{key:1,name:"fade-slide-y",mode:"out-in",onBeforeEnter:n.onBeforeEnter,onBeforeLeave:n.onBeforeLeave},{default:Ce(()=>[(W(),Ae(n.Page,{key:n.page.path},{top:Ce(()=>[be(e.$slots,"page-top")]),"content-top":Ce(()=>[be(e.$slots,"page-content-top")]),"content-bottom":Ce(()=>[be(e.$slots,"page-content-bottom")]),bottom:Ce(()=>[be(e.$slots,"page-bottom")]),_:3}))]),_:3},8,["onBeforeEnter","onBeforeLeave"]))])],34)}const xf=xe(Ef,[["render",yf],["__file","Layout.vue"]]),Lf=_e({__name:"NotFound",setup(e,{expose:t}){t();const l=Ql(),n=Fe(),i=n.value.notFound??["Not Found"],r=()=>i[Math.floor(Math.random()*i.length)],o=n.value.home??l.value,c=n.value.backToHome??"Back to home",a={routeLocale:l,themeLocale:n,messages:i,getMsg:r,homeLink:o,homeText:c};return Object.defineProperty(a,"__isScriptSetup",{enumerable:!1,value:!0}),a}}),Tf={class:"theme-container"},Of={class:"page"},Pf={class:"theme-default-content"},Af=ce("h1",null,"404",-1);function wf(e,t,l,n,i,r){const o=mt("RouterLink");return W(),ee("div",Tf,[ce("main",Of,[ce("div",Pf,[Af,ce("blockquote",null,Pe(n.getMsg()),1),ie(o,{to:n.homeLink},{default:Ce(()=>[Vt(Pe(n.homeText),1)]),_:1},8,["to"])])])])}const Rf=xe(Lf,[["render",wf],["__file","NotFound.vue"]]),If=Et({enhance({app:e,router:t}){e.component("Badge",Ch),e.component("CodeGroup",iv),e.component("CodeGroupItem",sv),e.component("AutoLinkExternalIcon",()=>{const n=e.component("ExternalLinkIcon");return n?he(n):null}),e.component("NavbarSearch",()=>{const n=e.component("Docsearch")||e.component("SearchBox");return n?he(n):null});const l=t.options.scrollBehavior;t.options.scrollBehavior=async(...n)=>(await Us().wait(),l(...n))},setup(){av(),pv()},layouts:{Layout:xf,NotFound:Rf}}),Df=e=>typeof e=="string",jf=(e,t)=>Df(e)&&e.startsWith(t),Sf=e=>jf(e,"/"),Cf={"/":"https://github.com/XTLS/Xray-docs-next"},Vf={"/":{lang:"zh-CN",untranslated:{title:"提示",content:(e,t)=>`此页面尚未翻译${t?`,在${e("此处",t)}了解如何帮我们翻译`:""}。`},outdated:{title:"警告",content:(e,t,l,n)=>{const i=r=>{const o=new Date(r);return`${o.getFullYear()}年${o.getMonth()}月${o.getDate()}日`};return`本页面最后修改于${i(l)},原文已在${i(t)}更新。${e("查看原文",n)}`}}},"/en/":{lang:"en-US",untranslated:{title:"Notice",content:(e,t)=>`This page has not yet been translated${t?`, see how you can help ${e("here",t)}`:""}.`},outdated:{title:"Warning",content:(e,t,l,n)=>{const i=["January","February","March","April","May","June","July","August","September","October","November","December"],r=o=>{const c=new Date(o);return`${c.getDate()} ${i[c.getMonth()]} ${c.getFullYear()}`};return`This translation was modified on ${r(l)} and an updated version (${r(t)}) is available on the source page. ${e("View the original page",n)}`}}},"/ru/":{lang:"en-US",untranslated:{title:"Notice",content:(e,t)=>`This page has not yet been translated${t?`, see how you can help ${e("here",t)}`:""}.`},outdated:{title:"Warning",content:(e,t,l,n)=>{const i=["January","February","March","April","May","June","July","August","September","October","November","December"],r=o=>{const c=new Date(o);return`${c.getDate()} ${i[c.getMonth()]} ${c.getFullYear()}`};return`This translation was modified on ${r(l)} and an updated version (${r(t)}) is available on the source page. ${e("View the original page",n)}`}}}};var Ff=["custom-container","hint-container"],Nf=["custom-container-title","hint-container-title"],Hf=Ff,Tl="/",Mf=Nf,ho=Cf,vo=Vf,$f=()=>C(()=>{const{outdated:e=!1,pathLocale:t=Tl,sourceLink:l,sourceUpdatedTime:n,untranslated:i=!1,updatedTime:r}=Gt().value.i18n??{},o=vo[t??Tl]??vo[Tl],c=ho[t]??ho[Tl];return{isOutdated:e,isUntranslated:i,locale:o,options:{baseLocalePath:Tl,containerClass:Hf,titleClass:Mf},pathLocale:t,sourceLink:l,sourceUpdatedTime:n,translationGuide:c,updatedTime:r}}),Qi=_e({__name:"I18nTip",setup(e,{expose:t}){t();const l=(m,x)=>`${m}`,n=(m,x,A)=>{switch(m){case"untranslated":return x.untranslated.content(l,A.translationGuide);case"outdated":return!A.updatedTime||!A.sourceUpdatedTime||!A.sourceLink?null:x.outdated.content(l,A.sourceUpdatedTime,A.updatedTime,A.sourceLink);default:return null}},i=$f(),{containerClass:r,titleClass:o}=i.value.options,c=C(()=>i.value.locale),a=C(()=>i.value.isUntranslated||i.value.isOutdated),u=C(()=>i.value.isUntranslated?"untranslated":"outdated"),d=C(()=>u.value==="untranslated"?"tip":"warning"),v=C(()=>c.value[u.value].title),_=C(()=>a.value?n(u.value,c.value,i.value):null),g={linkRenderer:l,getContent:n,i18nData:i,containerClass:r,titleClass:o,locale:c,showTips:a,tipType:u,containerType:d,containerTitle:v,containerContent:_};return Object.defineProperty(g,"__isScriptSetup",{enumerable:!1,value:!0}),g}}),Bf=["innerHTML"];function Wf(e,t,l,n,i,r){return n.showTips&&n.containerContent?(W(),ee("div",{key:0,class:$e([...n.containerClass,n.containerType])},[ce("p",{class:$e(n.titleClass)},Pe(n.containerTitle),3),Le("eslint-disable-next-line vue/no-v-html "),ce("p",{innerHTML:n.containerContent},null,8,Bf)],2)):Le("v-if",!0)}Qi.render=Wf;Qi.__file="src/client/components/I18nTip.vue";var Uf=Qi,zf=Et({enhance({app:e}){e.component("I18nTip",Uf)}});const Xf=e=>e instanceof Element?document.activeElement===e&&(["TEXTAREA","SELECT","INPUT"].includes(e.tagName)||e.hasAttribute("contenteditable")):!1,Kf=(e,t)=>t.some(l=>{if(it(l))return l===e.key;const{key:n,ctrl:i=!1,shift:r=!1,alt:o=!1}=l;return n===e.key&&i===e.ctrlKey&&r===e.shiftKey&&o===e.altKey}),qf=/[^\x00-\x7F]/,Gf=e=>e.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t),_o=e=>e.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),fo=(e,t)=>{const l=t.join(" "),n=Gf(e);if(qf.test(e))return n.some(o=>l.toLowerCase().indexOf(o)>-1);const i=e.endsWith(" ");return new RegExp(n.map((o,c)=>n.length===c+1&&!i?`(?=.*\\b${_o(o)})`:`(?=.*\\b${_o(o)}\\b)`).join("")+".+","gi").test(l)},Yf=({input:e,hotKeys:t})=>{if(t.value.length===0)return;const l=n=>{e.value&&Kf(n,t.value)&&!Xf(n.target)&&(n.preventDefault(),e.value.focus())};We(()=>{document.addEventListener("keydown",l)}),ql(()=>{document.removeEventListener("keydown",l)})},Qf=[{title:"",headers:[{level:2,title:"XTLS ? Xray ? V2Ray ?",slug:"xtls-xray-v2ray",link:"#xtls-xray-v2ray",children:[{level:3,title:"我们是谁?",slug:"我们是谁",link:"#我们是谁",children:[]},{level:3,title:"帮助 Xray 变得更强",slug:"帮助-xray-变得更强",link:"#帮助-xray-变得更强",children:[]},{level:3,title:"Telegram",slug:"telegram",link:"#telegram",children:[]},{level:3,title:"致谢",slug:"致谢",link:"#致谢",children:[]},{level:3,title:"更多关于 Project X",slug:"更多关于-project-x",link:"#更多关于-project-x",children:[]},{level:3,title:"License",slug:"license",link:"#license",children:[]},{level:3,title:"Stargazers over time",slug:"stargazers-over-time",link:"#stargazers-over-time",children:[]}]}],path:"/",pathLocale:"/",extraFields:[]},{title:"大史记",headers:[{level:2,title:"2021.4.6",slug:"_2021-4-6",link:"#_2021-4-6",children:[]},{level:2,title:"2021.4.4",slug:"_2021-4-4",link:"#_2021-4-4",children:[]},{level:2,title:"2021.4.1 v1.4.2",slug:"_2021-4-1-v1-4-2",link:"#_2021-4-1-v1-4-2",children:[]},{level:2,title:"2021.3.25",slug:"_2021-3-25",link:"#_2021-3-25",children:[]},{level:2,title:"2021.3.15",slug:"_2021-3-15",link:"#_2021-3-15",children:[]},{level:2,title:"2021.3.14 v1.4.0",slug:"_2021-3-14-v1-4-0",link:"#_2021-3-14-v1-4-0",children:[]},{level:2,title:"2021.3.3 1.3.1",slug:"_2021-3-3-1-3-1",link:"#_2021-3-3-1-3-1",children:[]},{level:2,title:"2021.2.14 1.3.0",slug:"_2021-2-14-1-3-0",link:"#_2021-2-14-1-3-0",children:[]},{level:2,title:"2021.01.31 1.2.4",slug:"_2021-01-31-1-2-4",link:"#_2021-01-31-1-2-4",children:[]},{level:2,title:"2021.01.25",slug:"_2021-01-25",link:"#_2021-01-25",children:[]},{level:2,title:"2021.01.22 1.2.3",slug:"_2021-01-22-1-2-3",link:"#_2021-01-22-1-2-3",children:[]},{level:2,title:"2021.01.19",slug:"_2021-01-19",link:"#_2021-01-19",children:[]},{level:2,title:"2021.01.17",slug:"_2021-01-17",link:"#_2021-01-17",children:[]},{level:2,title:"2021.01.15 1.2.2",slug:"_2021-01-15-1-2-2",link:"#_2021-01-15-1-2-2",children:[]},{level:2,title:"2021.01.12",slug:"_2021-01-12",link:"#_2021-01-12",children:[]},{level:2,title:"2021.01.10 1.2.1",slug:"_2021-01-10-1-2-1",link:"#_2021-01-10-1-2-1",children:[]},{level:2,title:"2021.01.07",slug:"_2021-01-07",link:"#_2021-01-07",children:[]},{level:2,title:"2021.01.05",slug:"_2021-01-05",link:"#_2021-01-05",children:[]},{level:2,title:"2021.01.03",slug:"_2021-01-03",link:"#_2021-01-03",children:[]},{level:2,title:"2021.01.01",slug:"_2021-01-01",link:"#_2021-01-01",children:[]},{level:2,title:"2020.12.29",slug:"_2020-12-29",link:"#_2020-12-29",children:[]},{level:2,title:"2020.12.25 1.1.5",slug:"_2020-12-25-1-1-5",link:"#_2020-12-25-1-1-5",children:[]},{level:2,title:"2020.12.24",slug:"_2020-12-24",link:"#_2020-12-24",children:[]},{level:2,title:"2020.12.23",slug:"_2020-12-23",link:"#_2020-12-23",children:[]},{level:2,title:"2020.12.21",slug:"_2020-12-21",link:"#_2020-12-21",children:[]},{level:2,title:"2020.12.18 1.1.4",slug:"_2020-12-18-1-1-4",link:"#_2020-12-18-1-1-4",children:[]},{level:2,title:"2020.12.17",slug:"_2020-12-17",link:"#_2020-12-17",children:[]},{level:2,title:"2020.12.15",slug:"_2020-12-15",link:"#_2020-12-15",children:[]},{level:2,title:"2020.12.11 1.1.3",slug:"_2020-12-11-1-1-3",link:"#_2020-12-11-1-1-3",children:[]},{level:2,title:"2020.12.06 1.1.2",slug:"_2020-12-06-1-1-2",link:"#_2020-12-06-1-1-2",children:[]},{level:2,title:"2020.12.04",slug:"_2020-12-04",link:"#_2020-12-04",children:[]},{level:2,title:"2020.11.27",slug:"_2020-11-27",link:"#_2020-11-27",children:[]},{level:2,title:"2020.11.25 1.0.0",slug:"_2020-11-25-1-0-0",link:"#_2020-11-25-1-0-0",children:[]},{level:2,title:"2020.11.23",slug:"_2020-11-23",link:"#_2020-11-23",children:[]}],path:"/about/news.html",pathLocale:"/",extraFields:[]},{title:"配置文件",headers:[{level:2,title:"概述",slug:"概述",link:"#概述",children:[]},{level:2,title:"基础配置模块",slug:"基础配置模块",link:"#基础配置模块",children:[]}],path:"/config/",pathLocale:"/",extraFields:[]},{title:"API 接口",headers:[{level:2,title:"ApiObject",slug:"apiobject",link:"#apiobject",children:[]},{level:2,title:"相关配置",slug:"相关配置",link:"#相关配置",children:[]},{level:2,title:"支持的 API 列表",slug:"支持的-api-列表",link:"#支持的-api-列表",children:[{level:3,title:"HandlerService",slug:"handlerservice",link:"#handlerservice",children:[]},{level:3,title:"RoutingService",slug:"routingservice",link:"#routingservice",children:[]},{level:3,title:"LoggerService",slug:"loggerservice",link:"#loggerservice",children:[]},{level:3,title:"StatsService",slug:"statsservice",link:"#statsservice",children:[]},{level:3,title:"ReflectionService",slug:"reflectionservice",link:"#reflectionservice",children:[]}]},{level:2,title:"API 调用示例",slug:"api-调用示例",link:"#api-调用示例",children:[]}],path:"/config/api.html",pathLocale:"/",extraFields:[]},{title:"内置 DNS 服务器",headers:[{level:2,title:"DNS 服务器",slug:"dns-服务器",link:"#dns-服务器",children:[]},{level:2,title:"DNS 处理流程",slug:"dns-处理流程",link:"#dns-处理流程",children:[]},{level:2,title:"DnsObject",slug:"dnsobject",link:"#dnsobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/dns.html",pathLocale:"/",extraFields:[]},{title:"FakeDNS",headers:[{level:2,title:"FakeDNSObject",slug:"fakednsobject",link:"#fakednsobject",children:[{level:3,title:"如何使用?",slug:"如何使用",link:"#如何使用",children:[]},{level:3,title:"与其它类型 DNS 搭配使用",slug:"与其它类型-dns-搭配使用",link:"#与其它类型-dns-搭配使用",children:[]}]}],path:"/config/fakedns.html",pathLocale:"/",extraFields:[]},{title:"入站代理",headers:[{level:2,title:"InboundObject",slug:"inboundobject",link:"#inboundobject",children:[{level:3,title:"SniffingObject",slug:"sniffingobject",link:"#sniffingobject",children:[]},{level:3,title:"AllocateObject",slug:"allocateobject",link:"#allocateobject",children:[]}]}],path:"/config/inbound.html",pathLocale:"/",extraFields:[]},{title:"日志配置",headers:[{level:2,title:"LogObject",slug:"logobject",link:"#logobject",children:[]}],path:"/config/log.html",pathLocale:"/",extraFields:[]},{title:"Metrics",headers:[{level:2,title:"相关配置",slug:"相关配置",link:"#相关配置",children:[]},{level:2,title:"使用方法",slug:"使用方法",link:"#使用方法",children:[{level:3,title:"pprof",slug:"pprof",link:"#pprof",children:[]},{level:3,title:"expvars",slug:"expvars",link:"#expvars",children:[]},{level:3,title:"Additional",slug:"additional",link:"#additional",children:[]}]}],path:"/config/metrics.html",pathLocale:"/",extraFields:[]},{title:"连接观测",headers:[{level:2,title:"ObservatoryObject",slug:"observatoryobject",link:"#observatoryobject",children:[]},{level:2,title:"BurstObservatoryObject",slug:"burstobservatoryobject",link:"#burstobservatoryobject",children:[{level:3,title:"PingConfigObject",slug:"pingconfigobject",link:"#pingconfigobject",children:[]}]}],path:"/config/observatory.html",pathLocale:"/",extraFields:[]},{title:"出站代理(Mux、XUDP)",headers:[{level:2,title:"OutboundObject",slug:"outboundobject",link:"#outboundobject",children:[{level:3,title:"ProxySettingsObject",slug:"proxysettingsobject",link:"#proxysettingsobject",children:[]},{level:3,title:"MuxObject",slug:"muxobject",link:"#muxobject",children:[]}]}],path:"/config/outbound.html",pathLocale:"/",extraFields:[]},{title:"本地策略",headers:[{level:2,title:"PolicyObject",slug:"policyobject",link:"#policyobject",children:[{level:3,title:"LevelPolicyObject",slug:"levelpolicyobject",link:"#levelpolicyobject",children:[]},{level:3,title:"SystemPolicyObject",slug:"systempolicyobject",link:"#systempolicyobject",children:[]}]}],path:"/config/policy.html",pathLocale:"/",extraFields:[]},{title:"反向代理",headers:[{level:2,title:"ReverseObject",slug:"reverseobject",link:"#reverseobject",children:[{level:3,title:"BridgeObject",slug:"bridgeobject",link:"#bridgeobject",children:[]},{level:3,title:"PortalObject",slug:"portalobject",link:"#portalobject",children:[]}]},{level:2,title:"完整配置样例",slug:"完整配置样例",link:"#完整配置样例",children:[{level:3,title:"bridge 配置",slug:"bridge-配置",link:"#bridge-配置",children:[]},{level:3,title:"portal 配置",slug:"portal-配置",link:"#portal-配置",children:[]}]}],path:"/config/reverse.html",pathLocale:"/",extraFields:[]},{title:"路由",headers:[{level:2,title:"RoutingObject",slug:"routingobject",link:"#routingobject",children:[{level:3,title:"RuleObject",slug:"ruleobject",link:"#ruleobject",children:[]},{level:3,title:"BalancerObject",slug:"balancerobject",link:"#balancerobject",children:[]},{level:3,title:"负载均衡配置示例",slug:"负载均衡配置示例",link:"#负载均衡配置示例",children:[]},{level:3,title:"预定义域名列表",slug:"预定义域名列表",link:"#预定义域名列表",children:[]}]}],path:"/config/routing.html",pathLocale:"/",extraFields:[]},{title:"统计信息",headers:[{level:2,title:"StatsObject",slug:"statsobject",link:"#statsobject",children:[]},{level:2,title:"获取统计信息",slug:"获取统计信息",link:"#获取统计信息",children:[]}],path:"/config/stats.html",pathLocale:"/",extraFields:[]},{title:"传输方式(uTLS、REALITY)",headers:[{level:2,title:"TransportObject(已弃用)",slug:"transportobject-已弃用",link:"#transportobject-已弃用",children:[]},{level:2,title:"StreamSettingsObject",slug:"streamsettingsobject",link:"#streamsettingsobject",children:[{level:3,title:"TLSObject",slug:"tlsobject",link:"#tlsobject",children:[]},{level:3,title:"RealityObject",slug:"realityobject",link:"#realityobject",children:[]},{level:3,title:"SockoptObject",slug:"sockoptobject",link:"#sockoptobject",children:[]}]}],path:"/config/transport.html",pathLocale:"/",extraFields:[]},{title:"开发指南",headers:[{level:2,title:"编译文档",slug:"编译文档",link:"#编译文档",children:[]},{level:2,title:"设计思路",slug:"设计思路",link:"#设计思路",children:[]},{level:2,title:"开发规范",slug:"开发规范",link:"#开发规范",children:[]},{level:2,title:"协议详解",slug:"协议详解",link:"#协议详解",children:[{level:3,title:"VLESS 协议",slug:"vless-协议",link:"#vless-协议",children:[]},{level:3,title:"VMess 协议",slug:"vmess-协议",link:"#vmess-协议",children:[]},{level:3,title:"Mux.Cool 协议",slug:"mux-cool-协议",link:"#mux-cool-协议",children:[]},{level:3,title:"mKCP 协议",slug:"mkcp-协议",link:"#mkcp-协议",children:[]}]}],path:"/development/",pathLocale:"/",extraFields:[]},{title:"快速入门",headers:[{level:2,title:"下载安装",slug:"下载安装",link:"#下载安装",children:[]},{level:2,title:"配置运行",slug:"配置运行",link:"#配置运行",children:[]},{level:2,title:"命令参数",slug:"命令参数",link:"#命令参数",children:[]},{level:2,title:"改进文档",slug:"改进文档",link:"#改进文档",children:[]},{level:2,title:"小小白白话文",slug:"小小白白话文",link:"#小小白白话文",children:[]},{level:2,title:"入门技巧",slug:"入门技巧",link:"#入门技巧",children:[]},{level:2,title:"进阶文档",slug:"进阶文档",link:"#进阶文档",children:[]}],path:"/document/",pathLocale:"/",extraFields:[]},{title:"命令参数",headers:[{level:2,title:"获取基本命令",slug:"获取基本命令",link:"#获取基本命令",children:[{level:3,title:"xray run",slug:"xray-run",link:"#xray-run",children:[]},{level:3,title:"xray version",slug:"xray-version",link:"#xray-version",children:[]},{level:3,title:"xray api",slug:"xray-api",link:"#xray-api",children:[]},{level:3,title:"xray convert",slug:"xray-convert",link:"#xray-convert",children:[]},{level:3,title:"xray tls",slug:"xray-tls",link:"#xray-tls",children:[]},{level:3,title:"xray uuid",slug:"xray-uuid",link:"#xray-uuid",children:[]},{level:3,title:"xray x25519",slug:"xray-x25519",link:"#xray-x25519",children:[]},{level:3,title:"xray wg",slug:"xray-wg",link:"#xray-wg",children:[]}]}],path:"/document/command.html",pathLocale:"/",extraFields:[]},{title:"配置运行",headers:[{level:2,title:"服务端配置",slug:"服务端配置",link:"#服务端配置",children:[]},{level:2,title:"客户端配置",slug:"客户端配置",link:"#客户端配置",children:[]},{level:2,title:"运行",slug:"运行",link:"#运行",children:[]}],path:"/document/config.html",pathLocale:"/",extraFields:[]},{title:"为 Project X 的文档贡献",headers:[{level:2,title:"改进文档",slug:"改进文档",link:"#改进文档",children:[]},{level:2,title:"发现问题?",slug:"发现问题",link:"#发现问题",children:[]}],path:"/document/document.html",pathLocale:"/",extraFields:[]},{title:"下载安装",headers:[{level:2,title:"平台支持",slug:"平台支持",link:"#平台支持",children:[]},{level:2,title:"下载 Xray",slug:"下载-xray",link:"#下载-xray",children:[]},{level:2,title:"验证安装包",slug:"验证安装包",link:"#验证安装包",children:[]},{level:2,title:"Windows 安装方式",slug:"windows-安装方式",link:"#windows-安装方式",children:[]},{level:2,title:"macOS 安装方式",slug:"macos-安装方式",link:"#macos-安装方式",children:[]},{level:2,title:"Linux 安装方式",slug:"linux-安装方式",link:"#linux-安装方式",children:[{level:3,title:"安装脚本",slug:"安装脚本",link:"#安装脚本",children:[]},{level:3,title:"Arch Linux",slug:"arch-linux",link:"#arch-linux",children:[]},{level:3,title:"Linuxbrew",slug:"linuxbrew",link:"#linuxbrew",children:[]},{level:3,title:"Debian",slug:"debian",link:"#debian",children:[]},{level:3,title:"Gentoo",slug:"gentoo",link:"#gentoo",children:[]}]},{level:2,title:"Docker 安装方式",slug:"docker-安装方式",link:"#docker-安装方式",children:[{level:3,title:"Docker image 的文件结构",slug:"docker-image-的文件结构",link:"#docker-image-的文件结构",children:[]}]}],path:"/document/install.html",pathLocale:"/",extraFields:[]},{title:"",headers:[{level:2,title:"XTLS? Xray? V2Ray?",slug:"xtls-xray-v2ray",link:"#xtls-xray-v2ray",children:[{level:3,title:"Who are we?",slug:"who-are-we",link:"#who-are-we",children:[]},{level:3,title:"Help Xray become stronger",slug:"help-xray-become-stronger",link:"#help-xray-become-stronger",children:[]},{level:3,title:"Telegram",slug:"telegram",link:"#telegram",children:[]},{level:3,title:"Thanks",slug:"thanks",link:"#thanks",children:[]},{level:3,title:"More about project X",slug:"more-about-project-x",link:"#more-about-project-x",children:[]},{level:3,title:"License",slug:"license",link:"#license",children:[]},{level:3,title:"Stargazers over time",slug:"stargazers-over-time",link:"#stargazers-over-time",children:[]}]}],path:"/en/",pathLocale:"/en/",extraFields:[]},{title:"",headers:[{level:2,title:"XTLS? Xray? V2Ray?",slug:"xtls-xray-v2ray",link:"#xtls-xray-v2ray",children:[{level:3,title:"Кто мы?",slug:"кто-мы",link:"#кто-мы",children:[]},{level:3,title:"Помогите Xray стать сильнее",slug:"помогите-xray-стать-сильнее",link:"#помогите-xray-стать-сильнее",children:[]},{level:3,title:"Telegram",slug:"telegram",link:"#telegram",children:[]},{level:3,title:"Благодарности",slug:"благодарности",link:"#благодарности",children:[]},{level:3,title:"Подробнее о Project X",slug:"подробнее-о-project-x",link:"#подробнее-о-project-x",children:[]},{level:3,title:"Лицензия",slug:"лицензия",link:"#лицензия",children:[]},{level:3,title:"Динамика звезд на GitHub",slug:"динамика-звезд-на-github",link:"#динамика-звезд-на-github",children:[]}]}],path:"/ru/",pathLocale:"/ru/",extraFields:[]},{title:"Browser Dialer",headers:[{level:2,title:"背景",slug:"背景",link:"#背景",children:[]},{level:2,title:"配置方法",slug:"配置方法",link:"#配置方法",children:[]},{level:2,title:"内部通信机制",slug:"内部通信机制",link:"#内部通信机制",children:[]},{level:2,title:"WebSocket",slug:"websocket",link:"#websocket",children:[]},{level:2,title:"SplitHTTP",slug:"splithttp",link:"#splithttp",children:[]}],path:"/config/features/browser_dialer.html",pathLocale:"/",extraFields:[]},{title:"环境变量",headers:[{level:2,title:"资源文件路径",slug:"资源文件路径",link:"#资源文件路径",children:[]},{level:2,title:"配置文件位置",slug:"配置文件位置",link:"#配置文件位置",children:[]},{level:2,title:"多配置目录",slug:"多配置目录",link:"#多配置目录",children:[]}],path:"/config/features/env.html",pathLocale:"/",extraFields:[]},{title:"Fallback 回落",headers:[{level:2,title:"fallbacks 配置",slug:"fallbacks-配置",link:"#fallbacks-配置",children:[{level:3,title:"FallbackObject",slug:"fallbackobject",link:"#fallbackobject",children:[]},{level:3,title:"补充说明",slug:"补充说明",link:"#补充说明",children:[]}]},{level:2,title:"Fallbacks 设计理论",slug:"fallbacks-设计理论",link:"#fallbacks-设计理论",children:[]}],path:"/config/features/fallback.html",pathLocale:"/",extraFields:[]},{title:"多文件配置",headers:[{level:2,title:"多文件启动",slug:"多文件启动",link:"#多文件启动",children:[]},{level:2,title:"规则说明",slug:"规则说明",link:"#规则说明",children:[{level:3,title:"普通对象({})",slug:"普通对象",link:"#普通对象",children:[]},{level:3,title:"数组([])",slug:"数组",link:"#数组",children:[]}]},{level:2,title:"配置例子",slug:"配置例子",link:"#配置例子",children:[]}],path:"/config/features/multiple.html",pathLocale:"/",extraFields:[]},{title:"XTLS 深度剖析",headers:[],path:"/config/features/xtls.html",pathLocale:"/",extraFields:[]},{title:"Dokodemo-Door",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"用处",slug:"用处",link:"#用处",children:[]},{level:2,title:"透明代理配置样例",slug:"透明代理配置样例",link:"#透明代理配置样例",children:[]}],path:"/config/inbounds/dokodemo.html",pathLocale:"/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/config/inbounds/http.html",pathLocale:"/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}],path:"/config/inbounds/shadowsocks.html",pathLocale:"/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/config/inbounds/socks.html",pathLocale:"/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/config/inbounds/trojan.html",pathLocale:"/",extraFields:[]},{title:"VLESS(XTLS Vision Seed)",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/config/inbounds/vless.html",pathLocale:"/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]},{level:3,title:"DetourObject",slug:"detourobject",link:"#detourobject",children:[]},{level:3,title:"DefaultObject",slug:"defaultobject",link:"#defaultobject",children:[]}]}],path:"/config/inbounds/vmess.html",pathLocale:"/",extraFields:[]},{title:"Blackhole",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ResponseObject",slug:"responseobject",link:"#responseobject",children:[]}]}],path:"/config/outbounds/blackhole.html",pathLocale:"/",extraFields:[]},{title:"DNS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]},{level:2,title:"DNS 配置实例",slug:"dns-配置实例",link:"#dns-配置实例",children:[]}],path:"/config/outbounds/dns.html",pathLocale:"/",extraFields:[]},{title:"Freedom",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]}],path:"/config/outbounds/freedom.html",pathLocale:"/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/http.html",pathLocale:"/",extraFields:[]},{title:"Loopback",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"如何使用?",slug:"如何使用",link:"#如何使用",children:[]}]}],path:"/config/outbounds/loopback.html",pathLocale:"/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/shadowsocks.html",pathLocale:"/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/socks.html",pathLocale:"/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/trojan.html",pathLocale:"/",extraFields:[]},{title:"VLESS(XTLS Vision Seed)",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]},{level:3,title:"UserObject",slug:"userobject",link:"#userobject",children:[]}]}],path:"/config/outbounds/vless.html",pathLocale:"/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/config/outbounds/vmess.html",pathLocale:"/",extraFields:[]},{title:"Wireguard",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Peers",slug:"peers",link:"#peers",children:[]}]}],path:"/config/outbounds/wireguard.html",pathLocale:"/",extraFields:[]},{title:"Domain Socket",headers:[{level:2,title:"DomainSocketObject",slug:"domainsocketobject",link:"#domainsocketobject",children:[]}],path:"/config/transports/domainsocket.html",pathLocale:"/",extraFields:[]},{title:"gRPC",headers:[{level:2,title:"GRPCObject",slug:"grpcobject",link:"#grpcobject",children:[]}],path:"/config/transports/grpc.html",pathLocale:"/",extraFields:[]},{title:"HTTP/2",headers:[{level:2,title:"HttpObject",slug:"httpobject",link:"#httpobject",children:[]}],path:"/config/transports/h2.html",pathLocale:"/",extraFields:[]},{title:"HTTPUpgrade",headers:[{level:2,title:"HttpUpgradeObject",slug:"httpupgradeobject",link:"#httpupgradeobject",children:[]}],path:"/config/transports/httpupgrade.html",pathLocale:"/",extraFields:[]},{title:"mKCP",headers:[{level:2,title:"KcpObject",slug:"kcpobject",link:"#kcpobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]},{level:2,title:"鸣谢",slug:"鸣谢",link:"#鸣谢",children:[]},{level:2,title:"对 KCP 协议的改进",slug:"对-kcp-协议的改进",link:"#对-kcp-协议的改进",children:[{level:3,title:"更小的协议头",slug:"更小的协议头",link:"#更小的协议头",children:[]},{level:3,title:"确认包重传",slug:"确认包重传",link:"#确认包重传",children:[]},{level:3,title:"连接状态控制",slug:"连接状态控制",link:"#连接状态控制",children:[]}]}],path:"/config/transports/mkcp.html",pathLocale:"/",extraFields:[]},{title:"QUIC",headers:[{level:2,title:"QuicObject",slug:"quicobject",link:"#quicobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]}],path:"/config/transports/quic.html",pathLocale:"/",extraFields:[]},{title:"SplitHTTP(H2、QUIC H3)",headers:[{level:2,title:"SplitHttpObject",slug:"splithttpobject",link:"#splithttpobject",children:[]},{level:2,title:"HTTP 版本",slug:"http-版本",link:"#http-版本",children:[{level:3,title:"客户端行为",slug:"客户端行为",link:"#客户端行为",children:[]},{level:3,title:"服务端行为",slug:"服务端行为",link:"#服务端行为",children:[]},{level:3,title:"小提示",slug:"小提示",link:"#小提示",children:[]}]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]},{level:2,title:"协议细节",slug:"协议细节",link:"#协议细节",children:[]}],path:"/config/transports/splithttp.html",pathLocale:"/",extraFields:[]},{title:"TCP",headers:[{level:2,title:"TcpObject",slug:"tcpobject",link:"#tcpobject",children:[{level:3,title:"NoneHeaderObject",slug:"noneheaderobject",link:"#noneheaderobject",children:[]},{level:3,title:"HttpHeaderObject",slug:"httpheaderobject",link:"#httpheaderobject",children:[]}]}],path:"/config/transports/tcp.html",pathLocale:"/",extraFields:[]},{title:"WebSocket",headers:[{level:2,title:"WebSocketObject",slug:"websocketobject",link:"#websocketobject",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]}],path:"/config/transports/websocket.html",pathLocale:"/",extraFields:[]},{title:"编译文档",headers:[{level:2,title:"前序工作",slug:"前序工作",link:"#前序工作",children:[]},{level:2,title:"拉取 Xray 源代码",slug:"拉取-xray-源代码",link:"#拉取-xray-源代码",children:[]},{level:2,title:"构建二进制",slug:"构建二进制",link:"#构建二进制",children:[{level:3,title:"Windows(Powershell):",slug:"windows-powershell",link:"#windows-powershell",children:[]},{level:3,title:"macOS, Linux:",slug:"macos-linux",link:"#macos-linux",children:[]}]},{level:2,title:"交叉编译:",slug:"交叉编译",link:"#交叉编译",children:[]},{level:2,title:"可复现构建:",slug:"可复现构建",link:"#可复现构建",children:[]}],path:"/development/intro/compile.html",pathLocale:"/",extraFields:[]},{title:"设计目标",headers:[{level:2,title:"架构",slug:"架构",link:"#架构",children:[{level:3,title:"应用层",slug:"应用层",link:"#应用层",children:[]},{level:3,title:"代理层",slug:"代理层",link:"#代理层",children:[]},{level:3,title:"传输层",slug:"传输层",link:"#传输层",children:[]}]}],path:"/development/intro/design.html",pathLocale:"/",extraFields:[]},{title:"开发规范",headers:[{level:2,title:"基本",slug:"基本",link:"#基本",children:[{level:3,title:"版本控制",slug:"版本控制",link:"#版本控制",children:[]},{level:3,title:"分支(Branch)",slug:"分支-branch",link:"#分支-branch",children:[]},{level:3,title:"发布(Release)",slug:"发布-release",link:"#发布-release",children:[]},{level:3,title:"引用其它项目",slug:"引用其它项目",link:"#引用其它项目",children:[]}]},{level:2,title:"开发流程",slug:"开发流程",link:"#开发流程",children:[{level:3,title:"写代码之前",slug:"写代码之前",link:"#写代码之前",children:[]},{level:3,title:"修改代码",slug:"修改代码",link:"#修改代码",children:[]},{level:3,title:"Pull Request",slug:"pull-request",link:"#pull-request",children:[]},{level:3,title:"对代码的修改",slug:"对代码的修改",link:"#对代码的修改",children:[]}]},{level:2,title:"Xray 编码规范",slug:"xray-编码规范",link:"#xray-编码规范",children:[{level:3,title:"代码结构",slug:"代码结构",link:"#代码结构",children:[]},{level:3,title:"编码规范",slug:"编码规范",link:"#编码规范",children:[]}]}],path:"/development/intro/guide.html",pathLocale:"/",extraFields:[]},{title:"mKCP 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"数据格式",slug:"数据格式",link:"#数据格式",children:[{level:3,title:"数据包",slug:"数据包",link:"#数据包",children:[]},{level:3,title:"数据片段",slug:"数据片段",link:"#数据片段",children:[]},{level:3,title:"确认片段",slug:"确认片段",link:"#确认片段",children:[]},{level:3,title:"心跳片段",slug:"心跳片段",link:"#心跳片段",children:[]}]}],path:"/development/protocols/mkcp.html",pathLocale:"/",extraFields:[]},{title:"Mux.Cool 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[{level:3,title:"客户端行为",slug:"客户端行为",link:"#客户端行为",children:[]},{level:3,title:"服务器端行为",slug:"服务器端行为",link:"#服务器端行为",children:[]}]},{level:2,title:"传输格式",slug:"传输格式",link:"#传输格式",children:[{level:3,title:"帧格式",slug:"帧格式",link:"#帧格式",children:[]},{level:3,title:"元数据",slug:"元数据",link:"#元数据",children:[]},{level:3,title:"新建子连接 (New)",slug:"新建子连接-new",link:"#新建子连接-new",children:[]},{level:3,title:"保持子连接 (Keep)",slug:"保持子连接-keep",link:"#保持子连接-keep",children:[]},{level:3,title:"关闭子连接 (End)",slug:"关闭子连接-end",link:"#关闭子连接-end",children:[]},{level:3,title:"保持连接 (KeepAlive)",slug:"保持连接-keepalive",link:"#保持连接-keepalive",children:[]}]},{level:2,title:"应用",slug:"应用",link:"#应用",children:[]}],path:"/development/protocols/muxcool.html",pathLocale:"/",extraFields:[]},{title:"VLESS 协议",headers:[{level:2,title:"Request & Response",slug:"request-response",link:"#request-response",children:[]},{level:2,title:"ProtoBuf",slug:"protobuf",link:"#protobuf",children:[]},{level:2,title:"Schedulers Flow",slug:"schedulers-flow",link:"#schedulers-flow",children:[]},{level:2,title:"Encryption",slug:"encryption",link:"#encryption",children:[]},{level:2,title:"UDP issues",slug:"udp-issues",link:"#udp-issues",children:[]},{level:2,title:"客户端开发指引",slug:"客户端开发指引",link:"#客户端开发指引",children:[]},{level:2,title:"VLESS 分享链接标准",slug:"vless-分享链接标准",link:"#vless-分享链接标准",children:[]}],path:"/development/protocols/vless.html",pathLocale:"/",extraFields:[]},{title:"VMess 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"用户 ID",slug:"用户-id",link:"#用户-id",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"客户端请求",slug:"客户端请求",link:"#客户端请求",children:[{level:3,title:"认证信息",slug:"认证信息",link:"#认证信息",children:[]},{level:3,title:"指令部分",slug:"指令部分",link:"#指令部分",children:[]},{level:3,title:"数据部分",slug:"数据部分",link:"#数据部分",children:[]}]},{level:2,title:"服务器应答",slug:"服务器应答",link:"#服务器应答",children:[{level:3,title:"动态端口指令",slug:"动态端口指令",link:"#动态端口指令",children:[]}]},{level:2,title:"注释",slug:"注释",link:"#注释",children:[]}],path:"/development/protocols/vmess.html",pathLocale:"/",extraFields:[]},{title:"小小白白话文",headers:[],path:"/document/level-0/",pathLocale:"/",extraFields:[]},{title:"【第 1 章】 小小白白话文",headers:[{level:2,title:"1.1 这篇文档是写给谁的?",slug:"_1-1-这篇文档是写给谁的",link:"#_1-1-这篇文档是写给谁的",children:[]},{level:2,title:"1.2 这篇文档不是写给谁的?",slug:"_1-2-这篇文档不是写给谁的",link:"#_1-2-这篇文档不是写给谁的",children:[]},{level:2,title:"1.3 郑重声明及其他声明",slug:"_1-3-郑重声明及其他声明",link:"#_1-3-郑重声明及其他声明",children:[]},{level:2,title:"1.4 为什么自建是个难题?",slug:"_1-4-为什么自建是个难题",link:"#_1-4-为什么自建是个难题",children:[]},{level:2,title:"1.5 “用机场不就行了?”",slug:"_1-5-用机场不就行了",link:"#_1-5-用机场不就行了",children:[]},{level:2,title:"1.6 那么你到底要不要自建呢?",slug:"_1-6-那么你到底要不要自建呢",link:"#_1-6-那么你到底要不要自建呢",children:[]},{level:2,title:"1.7 题外啰嗦几句",slug:"_1-7-题外啰嗦几句",link:"#_1-7-题外啰嗦几句",children:[]},{level:2,title:"1.8 你的进度",slug:"_1-8-你的进度",link:"#_1-8-你的进度",children:[]}],path:"/document/level-0/ch01-preface.html",pathLocale:"/",extraFields:[]},{title:"【第 2 章】原料准备篇",headers:[{level:2,title:"2.1 获取一台 VPS",slug:"_2-1-获取一台-vps",link:"#_2-1-获取一台-vps",children:[]},{level:2,title:"2.2 获取一个心仪的域名",slug:"_2-2-获取一个心仪的域名",link:"#_2-2-获取一个心仪的域名",children:[]},{level:2,title:"2.3 你本地电脑上需要安装的软件",slug:"_2-3-你本地电脑上需要安装的软件",link:"#_2-3-你本地电脑上需要安装的软件",children:[]},{level:2,title:"2.4 你的进度",slug:"_2-4-你的进度",link:"#_2-4-你的进度",children:[]}],path:"/document/level-0/ch02-preparation.html",pathLocale:"/",extraFields:[]},{title:"【第 3 章】远程登录篇",headers:[{level:2,title:"3.1 远程登录 VPS (PuTTY)",slug:"_3-1-远程登录-vps-putty",link:"#_3-1-远程登录-vps-putty",children:[]},{level:2,title:"3.2 成功登录 SSH!初识命令行界面!",slug:"_3-2-成功登录-ssh-初识命令行界面",link:"#_3-2-成功登录-ssh-初识命令行界面",children:[]},{level:2,title:"3.3 第一次更新 Linux 的软件!",slug:"_3-3-第一次更新-linux-的软件",link:"#_3-3-第一次更新-linux-的软件",children:[]},{level:2,title:"3.4 你的进度",slug:"_3-4-你的进度",link:"#_3-4-你的进度",children:[]}],path:"/document/level-0/ch03-ssh.html",pathLocale:"/",extraFields:[]},{title:"【第 4 章】安全防护篇",headers:[{level:2,title:"4.1 为什么要做安全防护",slug:"_4-1-为什么要做安全防护",link:"#_4-1-为什么要做安全防护",children:[]},{level:2,title:"4.2 具体的风险到底是什么",slug:"_4-2-具体的风险到底是什么",link:"#_4-2-具体的风险到底是什么",children:[]},{level:2,title:"4.3 我们要做的安全防护有哪些",slug:"_4-3-我们要做的安全防护有哪些",link:"#_4-3-我们要做的安全防护有哪些",children:[]},{level:2,title:"4.4 将 SSH 远程登录端口修改为非 22 端口",slug:"_4-4-将-ssh-远程登录端口修改为非-22-端口",link:"#_4-4-将-ssh-远程登录端口修改为非-22-端口",children:[]},{level:2,title:"4.5 建立非 root 的新用户",slug:"_4-5-建立非-root-的新用户",link:"#_4-5-建立非-root-的新用户",children:[]},{level:2,title:"4.6 禁用 root 用户 SSH 远程登录",slug:"_4-6-禁用-root-用户-ssh-远程登录",link:"#_4-6-禁用-root-用户-ssh-远程登录",children:[]},{level:2,title:"4.7 使用 RSA 密钥登录并禁用密码登录",slug:"_4-7-使用-rsa-密钥登录并禁用密码登录",link:"#_4-7-使用-rsa-密钥登录并禁用密码登录",children:[]},{level:2,title:"4.8 你的进度",slug:"_4-8-你的进度",link:"#_4-8-你的进度",children:[]}],path:"/document/level-0/ch04-security.html",pathLocale:"/",extraFields:[]},{title:"【第 5 章】网站建设篇",headers:[{level:2,title:"5.1 为什么要做一个网站?",slug:"_5-1-为什么要做一个网站",link:"#_5-1-为什么要做一个网站",children:[]},{level:2,title:"5.2 登录 VPS、安装运行 Nginx",slug:"_5-2-登录-vps、安装运行-nginx",link:"#_5-2-登录-vps、安装运行-nginx",children:[]},{level:2,title:"5.3 创建一个最简单的网页",slug:"_5-3-创建一个最简单的网页",link:"#_5-3-创建一个最简单的网页",children:[]},{level:2,title:"5.4 常见错误的说明",slug:"_5-4-常见错误的说明",link:"#_5-4-常见错误的说明",children:[]},{level:2,title:"5.5 你的进度",slug:"_5-5-你的进度",link:"#_5-5-你的进度",children:[]}],path:"/document/level-0/ch05-webpage.html",pathLocale:"/",extraFields:[]},{title:"【第 6 章】证书管理篇",headers:[{level:2,title:"6.1 申请 TLS 证书",slug:"_6-1-申请-tls-证书",link:"#_6-1-申请-tls-证书",children:[]},{level:2,title:"6.2 安装 acme.sh",slug:"_6-2-安装-acme-sh",link:"#_6-2-安装-acme-sh",children:[]},{level:2,title:"6.3 测试证书申请",slug:"_6-3-测试证书申请",link:"#_6-3-测试证书申请",children:[]},{level:2,title:"6.4 正式证书申请",slug:"_6-4-正式证书申请",link:"#_6-4-正式证书申请",children:[]},{level:2,title:"6.5 证书安装",slug:"_6-5-证书安装",link:"#_6-5-证书安装",children:[]},{level:2,title:"6.6 你的进度",slug:"_6-6-你的进度",link:"#_6-6-你的进度",children:[]}],path:"/document/level-0/ch06-certificates.html",pathLocale:"/",extraFields:[]},{title:"【第 7 章】Xray 服务器篇",headers:[{level:2,title:"7.1 博观而约取,厚积而薄发",slug:"_7-1-博观而约取-厚积而薄发",link:"#_7-1-博观而约取-厚积而薄发",children:[]},{level:2,title:"7.2 安装 Xray",slug:"_7-2-安装-xray",link:"#_7-2-安装-xray",children:[]},{level:2,title:"7.3 给 Xray 配置 TLS 证书",slug:"_7-3-给-xray-配置-tls-证书",link:"#_7-3-给-xray-配置-tls-证书",children:[]},{level:2,title:"7.4 配置 Xray",slug:"_7-4-配置-xray",link:"#_7-4-配置-xray",children:[]},{level:2,title:"7.5 启动 Xray 服务!!(并查看服务状态)",slug:"_7-5-启动-xray-服务-并查看服务状态",link:"#_7-5-启动-xray-服务-并查看服务状态",children:[]},{level:2,title:"7.6 回顾 systemd 进行基本的服务管理",slug:"_7-6-回顾-systemd-进行基本的服务管理",link:"#_7-6-回顾-systemd-进行基本的服务管理",children:[]},{level:2,title:"7.7 服务器优化之一:开启 BBR",slug:"_7-7-服务器优化之一-开启-bbr",link:"#_7-7-服务器优化之一-开启-bbr",children:[]},{level:2,title:"7.8 服务器优化之二:开启 HTTP 自动跳转 HTTPS",slug:"_7-8-服务器优化之二-开启-http-自动跳转-https",link:"#_7-8-服务器优化之二-开启-http-自动跳转-https",children:[]},{level:2,title:"7.9 服务器优化之三:更丰富的回落",slug:"_7-9-服务器优化之三-更丰富的回落",link:"#_7-9-服务器优化之三-更丰富的回落",children:[]},{level:2,title:"7.10 你的进度",slug:"_7-10-你的进度",link:"#_7-10-你的进度",children:[]},{level:2,title:"7.11 重要勘误",slug:"_7-11-重要勘误",link:"#_7-11-重要勘误",children:[]}],path:"/document/level-0/ch07-xray-server.html",pathLocale:"/",extraFields:[]},{title:"【第 8 章】Xray 客户端篇",headers:[{level:2,title:"8.1 Xray 的工作原理简述",slug:"_8-1-xray-的工作原理简述",link:"#_8-1-xray-的工作原理简述",children:[]},{level:2,title:"8.2 客户端与服务器端正确连接",slug:"_8-2-客户端与服务器端正确连接",link:"#_8-2-客户端与服务器端正确连接",children:[]},{level:2,title:"8.3 附加题 1:在 PC 端手工配置 xray-core",slug:"_8-3-附加题-1-在-pc-端手工配置-xray-core",link:"#_8-3-附加题-1-在-pc-端手工配置-xray-core",children:[]},{level:2,title:"8.4 附加题 2:在 PC 端手工运行 xray-core",slug:"_8-4-附加题-2-在-pc-端手工运行-xray-core",link:"#_8-4-附加题-2-在-pc-端手工运行-xray-core",children:[]},{level:2,title:"8.5 附加题 3:在 PC 端开机自动运行 xray-core",slug:"_8-5-附加题-3-在-pc-端开机自动运行-xray-core",link:"#_8-5-附加题-3-在-pc-端开机自动运行-xray-core",children:[]},{level:2,title:"8.6 圆满完成!",slug:"_8-6-圆满完成",link:"#_8-6-圆满完成",children:[]},{level:2,title:"8.7 TO INFINITY AND BEYOND!",slug:"_8-7-to-infinity-and-beyond",link:"#_8-7-to-infinity-and-beyond",children:[]}],path:"/document/level-0/ch08-xray-clients.html",pathLocale:"/",extraFields:[]},{title:"【第 9 章】附录",headers:[{level:2,title:"1. 小小白白 Linux 基础命令索引",slug:"_1-小小白白-linux-基础命令索引",link:"#_1-小小白白-linux-基础命令索引",children:[]},{level:2,title:"2. 小小白白 Linux 重要配置文件索引",slug:"_2-小小白白-linux-重要配置文件索引",link:"#_2-小小白白-linux-重要配置文件索引",children:[]},{level:2,title:"3. 小小白白 Xray 重要文件索引",slug:"_3-小小白白-xray-重要文件索引",link:"#_3-小小白白-xray-重要文件索引",children:[]}],path:"/document/level-0/ch09-appendix.html",pathLocale:"/",extraFields:[]},{title:"入门技巧",headers:[],path:"/document/level-1/",pathLocale:"/",extraFields:[]},{title:"回落 (fallbacks) 功能简析",headers:[{level:2,title:"1. 回顾《小小白白话文》中的回落",slug:"_1-回顾《小小白白话文》中的回落",link:"#_1-回顾《小小白白话文》中的回落",children:[]},{level:2,title:"2. 重新认识回落 (WHAT, HOW v1)",slug:"_2-重新认识回落-what-how-v1",link:"#_2-重新认识回落-what-how-v1",children:[]},{level:2,title:"3. 为什么要回落 (WHY v1)",slug:"_3-为什么要回落-why-v1",link:"#_3-为什么要回落-why-v1",children:[]},{level:2,title:"4. 重新认识【回落の完全体】 (WHAT, WHY, HOW v2)",slug:"_4-重新认识【回落の完全体】-what-why-how-v2",link:"#_4-重新认识【回落の完全体】-what-why-how-v2",children:[]},{level:2,title:"5. 多层回落示例及解读",slug:"_5-多层回落示例及解读",link:"#_5-多层回落示例及解读",children:[{level:3,title:"5.1 首先,我将服务器端配置的 443 监听段摘抄如下:",slug:"_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",link:"#_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",children:[]},{level:3,title:"5.2 后续监听处理的配置段摘抄如下:",slug:"_5-2-后续监听处理的配置段摘抄如下",link:"#_5-2-后续监听处理的配置段摘抄如下",children:[]}]},{level:2,title:"6. 结语",slug:"_6-结语",link:"#_6-结语",children:[]},{level:2,title:"7. 附加题",slug:"_7-附加题",link:"#_7-附加题",children:[]}],path:"/document/level-1/fallbacks-lv1.html",pathLocale:"/",extraFields:[]},{title:"SNI 回落",headers:[{level:2,title:"应用情景",slug:"应用情景",link:"#应用情景",children:[]},{level:2,title:"SNI 简介",slug:"sni-简介",link:"#sni-简介",children:[]},{level:2,title:"思路",slug:"思路",link:"#思路",children:[]},{level:2,title:"添加 DNS 记录",slug:"添加-dns-记录",link:"#添加-dns-记录",children:[]},{level:2,title:"申请 TLS 证书",slug:"申请-tls-证书",link:"#申请-tls-证书",children:[]},{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"Nginx 配置",slug:"nginx-配置",link:"#nginx-配置",children:[]},{level:2,title:"Caddy 配置",slug:"caddy-配置",link:"#caddy-配置",children:[]},{level:2,title:"参考",slug:"参考",link:"#参考",children:[]},{level:2,title:"引用",slug:"引用",link:"#引用",children:[]}],path:"/document/level-1/fallbacks-with-sni.html",pathLocale:"/",extraFields:[]},{title:"路由 (routing) 功能简析(上)",headers:[{level:2,title:"1. 初识【路由】三兄弟",slug:"_1-初识【路由】三兄弟",link:"#_1-初识【路由】三兄弟",children:[]},{level:2,title:"2. 基本功: “兄弟一条心”",slug:"_2-基本功-兄弟一条心",link:"#_2-基本功-兄弟一条心",children:[{level:3,title:"2.1 入站",slug:"_2-1-入站",link:"#_2-1-入站",children:[]},{level:3,title:"2.3 路由",slug:"_2-3-路由",link:"#_2-3-路由",children:[]},{level:3,title:"2.4 路由配置项解析之一:流量筛选的依据",slug:"_2-4-路由配置项解析之一-流量筛选的依据",link:"#_2-4-路由配置项解析之一-流量筛选的依据",children:[]}]},{level:2,title:"3. 小试牛刀: “三分天下” 之 “域名分流”",slug:"_3-小试牛刀-三分天下-之-域名分流",link:"#_3-小试牛刀-三分天下-之-域名分流",children:[{level:3,title:"3.1 入站",slug:"_3-1-入站",link:"#_3-1-入站",children:[]},{level:3,title:"3.2 出站",slug:"_3-2-出站",link:"#_3-2-出站",children:[]},{level:3,title:"3.3 路由",slug:"_3-3-路由",link:"#_3-3-路由",children:[]},{level:3,title:"3.4 简析域名文件: geosite.dat",slug:"_3-4-简析域名文件-geosite-dat",link:"#_3-4-简析域名文件-geosite-dat",children:[]},{level:3,title:"3.5 所以 geosite.dat 到底是什么?不是有个 GFWList 吗?",slug:"_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",link:"#_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",children:[]},{level:3,title:"3.6 军师锦囊藏奇兵:一条隐藏的路由规则",slug:"_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",link:"#_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",children:[]},{level:3,title:"3.7 再看“三分天下”的大地图",slug:"_3-7-再看-三分天下-的大地图",link:"#_3-7-再看-三分天下-的大地图",children:[]}]},{level:2,title:"4. “三分天下” 之 “蜀魏争雄”",slug:"_4-三分天下-之-蜀魏争雄",link:"#_4-三分天下-之-蜀魏争雄",children:[]},{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[]}],path:"/document/level-1/routing-lv1-part1.html",pathLocale:"/",extraFields:[]},{title:"路由 (routing) 功能简析(下)",headers:[{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[{level:3,title:"5.1 基于指定域名分流:[domain], [full] 等",slug:"_5-1-基于指定域名分流-domain-full-等",link:"#_5-1-基于指定域名分流-domain-full-等",children:[]},{level:3,title:"5.2 基于 IP 文件分流:geoip.dat",slug:"_5-2-基于-ip-文件分流-geoip-dat",link:"#_5-2-基于-ip-文件分流-geoip-dat",children:[]},{level:3,title:"5.3 基于指定 IP 地址分流",slug:"_5-3-基于指定-ip-地址分流",link:"#_5-3-基于指定-ip-地址分流",children:[]},{level:3,title:"5.4 基于协议类型分流:[protocol] 等",slug:"_5-4-基于协议类型分流-protocol-等",link:"#_5-4-基于协议类型分流-protocol-等",children:[]},{level:3,title:"5.5 基于更多条件的分流",slug:"_5-5-基于更多条件的分流",link:"#_5-5-基于更多条件的分流",children:[]}]},{level:2,title:"6. “霸业初定”:路由规则整体回顾",slug:"_6-霸业初定-路由规则整体回顾",link:"#_6-霸业初定-路由规则整体回顾",children:[]},{level:2,title:"7. 路由配置常见错误",slug:"_7-路由配置常见错误",link:"#_7-路由配置常见错误",children:[{level:3,title:"7.1 错误示范",slug:"_7-1-错误示范",link:"#_7-1-错误示范",children:[]},{level:3,title:"7.2 正确示范",slug:"_7-2-正确示范",link:"#_7-2-正确示范",children:[]}]},{level:2,title:"8. 明修栈道、暗渡陈仓",slug:"_8-明修栈道、暗渡陈仓",link:"#_8-明修栈道、暗渡陈仓",children:[{level:3,title:'8.1 域名策略: "AsIs"',slug:"_8-1-域名策略-asis",link:"#_8-1-域名策略-asis",children:[]},{level:3,title:'8.2 域名策略: "IPIfNonMatch"',slug:"_8-2-域名策略-ipifnonmatch",link:"#_8-2-域名策略-ipifnonmatch",children:[]},{level:3,title:'8.3 域名策略: "IPOnDemand"',slug:"_8-3-域名策略-ipondemand",link:"#_8-3-域名策略-ipondemand",children:[]}]},{level:2,title:"9. 思考题",slug:"_9-思考题",link:"#_9-思考题",children:[]},{level:2,title:"10. 结语",slug:"_10-结语",link:"#_10-结语",children:[]},{level:2,title:"11. 尾注",slug:"_11-尾注",link:"#_11-尾注",children:[]}],path:"/document/level-1/routing-lv1-part2.html",pathLocale:"/",extraFields:[]},{title:"Xray 的工作模式",headers:[{level:2,title:"单服务器模式",slug:"单服务器模式",link:"#单服务器模式",children:[]},{level:2,title:"桥接模式",slug:"桥接模式",link:"#桥接模式",children:[]},{level:2,title:"工作原理",slug:"工作原理",link:"#工作原理",children:[]}],path:"/document/level-1/work.html",pathLocale:"/",extraFields:[]},{title:"进阶文档",headers:[],path:"/document/level-2/",pathLocale:"/",extraFields:[]},{title:"GID 透明代理",headers:[{level:2,title:"思路",slug:"思路",link:"#思路",children:[]},{level:2,title:"配置过程",slug:"配置过程",link:"#配置过程",children:[{level:3,title:"1. 前期准备",slug:"_1-前期准备",link:"#_1-前期准备",children:[]},{level:3,title:"2. 添加用户(安卓用户请忽略)",slug:"_2-添加用户-安卓用户请忽略",link:"#_2-添加用户-安卓用户请忽略",children:[]},{level:3,title:"3. 配置运行 Xray,配置 iptables 规则",slug:"_3-配置运行-xray-配置-iptables-规则",link:"#_3-配置运行-xray-配置-iptables-规则",children:[]}]},{level:2,title:"下面提供一个实现 tproxy 全局代理的完整配置过程",slug:"下面提供一个实现-tproxy-全局代理的完整配置过程",link:"#下面提供一个实现-tproxy-全局代理的完整配置过程",children:[{level:3,title:"1. 完成 前期准备 和 添加用户",slug:"_1-完成-前期准备-和-添加用户",link:"#_1-完成-前期准备-和-添加用户",children:[]},{level:3,title:"2. 准备 Xray 配置文件",slug:"_2-准备-xray-配置文件",link:"#_2-准备-xray-配置文件",children:[]},{level:3,title:"3. 配置最大文件打开数&运行 Xray 客户端",slug:"_3-配置最大文件打开数-运行-xray-客户端",link:"#_3-配置最大文件打开数-运行-xray-客户端",children:[]},{level:3,title:"4. 设置 iptables 规则",slug:"_4-设置-iptables-规则",link:"#_4-设置-iptables-规则",children:[]}]}],path:"/document/level-2/iptables_gid.html",pathLocale:"/",extraFields:[]},{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹",headers:[{level:2,title:"编译 nginx --with-stream",slug:"编译-nginx-with-stream",link:"#编译-nginx-with-stream",children:[]},{level:2,title:"配置 nginx",slug:"配置-nginx",link:"#配置-nginx",children:[]},{level:2,title:"xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"客户端及服务端启动服务",slug:"客户端及服务端启动服务",link:"#客户端及服务端启动服务",children:[]},{level:2,title:"结束",slug:"结束",link:"#结束",children:[]},{level:2,title:"HTTPS 隧道",slug:"https-隧道",link:"#https-隧道",children:[{level:3,title:"haproxy_client 配置 (运行前去掉注释)",slug:"haproxy-client-配置-运行前去掉注释",link:"#haproxy-client-配置-运行前去掉注释",children:[]},{level:3,title:"haproxy_server 配置 (运行前去掉注释)",slug:"haproxy-server-配置-运行前去掉注释",link:"#haproxy-server-配置-运行前去掉注释",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-1",link:"#xray-配置-1",children:[]}]},{level:2,title:"WebSocket over HTTP/2",slug:"websocket-over-http-2",link:"#websocket-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置",link:"#haproxy-client-配置",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置",link:"#haproxy-server-配置",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-2",link:"#xray-配置-2",children:[]}]},{level:2,title:"gRPC over HTTP/2",slug:"grpc-over-http-2",link:"#grpc-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-1",link:"#haproxy-client-配置-1",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-1",link:"#haproxy-server-配置-1",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-3",link:"#xray-配置-3",children:[]},{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-2",link:"#haproxy-client-配置-2",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-2",link:"#haproxy-server-配置-2",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-4",link:"#xray-配置-4",children:[]}]}],path:"/document/level-2/nginx_or_haproxy_tls_tunnel.html",pathLocale:"/",extraFields:[]},{title:"出站流量重定向",headers:[{level:2,title:"前言",slug:"前言",link:"#前言",children:[]},{level:2,title:"1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)",slug:"_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",link:"#_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",children:[]},{level:2,title:"2、编辑 VPN 配置文件(以 WireGuard 为例)",slug:"_2、编辑-vpn-配置文件-以-wireguard-为例",link:"#_2、编辑-vpn-配置文件-以-wireguard-为例",children:[]},{level:2,title:"3、启用 WireGuard 网络接口",slug:"_3、启用-wireguard-网络接口",link:"#_3、启用-wireguard-网络接口",children:[]},{level:2,title:"4、Xray-core 配置文件修改",slug:"_4、xray-core-配置文件修改",link:"#_4、xray-core-配置文件修改",children:[]},{level:2,title:"5、系统设置配置",slug:"_5、系统设置配置",link:"#_5、系统设置配置",children:[]},{level:2,title:"6、完成 WireGuard 相关设置",slug:"_6、完成-wireguard-相关设置",link:"#_6、完成-wireguard-相关设置",children:[]},{level:2,title:"后记",slug:"后记",link:"#后记",children:[]},{level:2,title:"感谢",slug:"感谢",link:"#感谢",children:[]}],path:"/document/level-2/redirect.html",pathLocale:"/",extraFields:[]},{title:"TProxy 透明代理",headers:[{level:2,title:"开始之前",slug:"开始之前",link:"#开始之前",children:[]},{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"策略路由配置",slug:"策略路由配置",link:"#策略路由配置",children:[]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[]},{level:2,title:"配置永久化与开机自启",slug:"配置永久化与开机自启",link:"#配置永久化与开机自启",children:[]}],path:"/document/level-2/tproxy.html",pathLocale:"/",extraFields:[]},{title:"TProxy 透明代理 (ipv4 and ipv6)",headers:[{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[{level:3,title:"客户端配置",slug:"客户端配置",link:"#客户端配置",children:[]},{level:3,title:"服务端配置",slug:"服务端配置",link:"#服务端配置",children:[]}]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[{level:3,title:"首先设置策略路由",slug:"首先设置策略路由",link:"#首先设置策略路由",children:[]},{level:3,title:"使用 iptables",slug:"使用-iptables",link:"#使用-iptables",children:[]},{level:3,title:"使用 nftables",slug:"使用-nftables",link:"#使用-nftables",children:[]},{level:3,title:"开机自动运行 Netfilter 配置",slug:"开机自动运行-netfilter-配置",link:"#开机自动运行-netfilter-配置",children:[]}]},{level:2,title:"局域网设备上网设置",slug:"局域网设备上网设置",link:"#局域网设备上网设置",children:[{level:3,title:"方法一",slug:"方法一",link:"#方法一",children:[]},{level:3,title:"方法二",slug:"方法二",link:"#方法二",children:[]}]},{level:2,title:"Finally",slug:"finally",link:"#finally",children:[]},{level:2,title:"写在最后",slug:"写在最后",link:"#写在最后",children:[]}],path:"/document/level-2/tproxy_ipv4_and_ipv6.html",pathLocale:"/",extraFields:[]},{title:"流量统计",headers:[{level:2,title:"查看流量信息",slug:"查看流量信息",link:"#查看流量信息",children:[]},{level:2,title:"流量信息的处理",slug:"流量信息的处理",link:"#流量信息的处理",children:[]}],path:"/document/level-2/traffic_stats.html",pathLocale:"/",extraFields:[]},{title:"通过 Cloudflare Warp 增强代理安全性",headers:[{level:2,title:"申请 Warp 账户",slug:"申请-warp-账户",link:"#申请-warp-账户",children:[{level:3,title:"感谢 Cloudflare 推动自由的互联网,现在你可以免费使用 Warp 服务,连接的时候会根据出口自动选择最近的服务器",slug:"感谢-cloudflare-推动自由的互联网-现在你可以免费使用-warp-服务-连接的时候会根据出口自动选择最近的服务器",link:"#感谢-cloudflare-推动自由的互联网-现在你可以免费使用-warp-服务-连接的时候会根据出口自动选择最近的服务器",children:[]}]},{level:2,title:"在服务端分流回国流量至 warp",slug:"在服务端分流回国流量至-warp",link:"#在服务端分流回国流量至-warp",children:[]},{level:2,title:"客户端使用 warp 链式代理",slug:"客户端使用-warp-链式代理",link:"#客户端使用-warp-链式代理",children:[]}],path:"/document/level-2/warp.html",pathLocale:"/",extraFields:[]},{title:"大史记",headers:[{level:2,title:"2021.4.6",slug:"_2021-4-6",link:"#_2021-4-6",children:[]},{level:2,title:"2021.4.4",slug:"_2021-4-4",link:"#_2021-4-4",children:[]},{level:2,title:"2021.4.1 v1.4.2",slug:"_2021-4-1-v1-4-2",link:"#_2021-4-1-v1-4-2",children:[]},{level:2,title:"2021.3.25",slug:"_2021-3-25",link:"#_2021-3-25",children:[]},{level:2,title:"2021.3.15",slug:"_2021-3-15",link:"#_2021-3-15",children:[]},{level:2,title:"2021.3.14 v1.4.0",slug:"_2021-3-14-v1-4-0",link:"#_2021-3-14-v1-4-0",children:[]},{level:2,title:"2021.3.3 1.3.1",slug:"_2021-3-3-1-3-1",link:"#_2021-3-3-1-3-1",children:[]},{level:2,title:"2021.2.14 1.3.0",slug:"_2021-2-14-1-3-0",link:"#_2021-2-14-1-3-0",children:[]},{level:2,title:"2021.01.31 1.2.4",slug:"_2021-01-31-1-2-4",link:"#_2021-01-31-1-2-4",children:[]},{level:2,title:"2021.01.25",slug:"_2021-01-25",link:"#_2021-01-25",children:[]},{level:2,title:"2021.01.22 1.2.3",slug:"_2021-01-22-1-2-3",link:"#_2021-01-22-1-2-3",children:[]},{level:2,title:"2021.01.19",slug:"_2021-01-19",link:"#_2021-01-19",children:[]},{level:2,title:"2021.01.17",slug:"_2021-01-17",link:"#_2021-01-17",children:[]},{level:2,title:"2021.01.15 1.2.2",slug:"_2021-01-15-1-2-2",link:"#_2021-01-15-1-2-2",children:[]},{level:2,title:"2021.01.12",slug:"_2021-01-12",link:"#_2021-01-12",children:[]},{level:2,title:"2021.01.10 1.2.1",slug:"_2021-01-10-1-2-1",link:"#_2021-01-10-1-2-1",children:[]},{level:2,title:"2021.01.07",slug:"_2021-01-07",link:"#_2021-01-07",children:[]},{level:2,title:"2021.01.05",slug:"_2021-01-05",link:"#_2021-01-05",children:[]},{level:2,title:"2021.01.03",slug:"_2021-01-03",link:"#_2021-01-03",children:[]},{level:2,title:"2021.01.01",slug:"_2021-01-01",link:"#_2021-01-01",children:[]},{level:2,title:"2020.12.29",slug:"_2020-12-29",link:"#_2020-12-29",children:[]},{level:2,title:"2020.12.25 1.1.5",slug:"_2020-12-25-1-1-5",link:"#_2020-12-25-1-1-5",children:[]},{level:2,title:"2020.12.24",slug:"_2020-12-24",link:"#_2020-12-24",children:[]},{level:2,title:"2020.12.23",slug:"_2020-12-23",link:"#_2020-12-23",children:[]},{level:2,title:"2020.12.21",slug:"_2020-12-21",link:"#_2020-12-21",children:[]},{level:2,title:"2020.12.18 1.1.4",slug:"_2020-12-18-1-1-4",link:"#_2020-12-18-1-1-4",children:[]},{level:2,title:"2020.12.17",slug:"_2020-12-17",link:"#_2020-12-17",children:[]},{level:2,title:"2020.12.15",slug:"_2020-12-15",link:"#_2020-12-15",children:[]},{level:2,title:"2020.12.11 1.1.3",slug:"_2020-12-11-1-1-3",link:"#_2020-12-11-1-1-3",children:[]},{level:2,title:"2020.12.06 1.1.2",slug:"_2020-12-06-1-1-2",link:"#_2020-12-06-1-1-2",children:[]},{level:2,title:"2020.12.04",slug:"_2020-12-04",link:"#_2020-12-04",children:[]},{level:2,title:"2020.11.27",slug:"_2020-11-27",link:"#_2020-11-27",children:[]},{level:2,title:"2020.11.25 1.0.0",slug:"_2020-11-25-1-0-0",link:"#_2020-11-25-1-0-0",children:[]},{level:2,title:"2020.11.23",slug:"_2020-11-23",link:"#_2020-11-23",children:[]}],path:"/en/about/news.html",pathLocale:"/en/",extraFields:[]},{title:"Configurations",headers:[{level:2,title:"Overview",slug:"overview",link:"#overview",children:[]},{level:2,title:"Basic Configuration Modules",slug:"basic-configuration-modules",link:"#basic-configuration-modules",children:[]}],path:"/en/config/",pathLocale:"/en/",extraFields:[]},{title:"API Interface",headers:[{level:2,title:"ApiObject",slug:"apiobject",link:"#apiobject",children:[]},{level:2,title:"Related Configuration",slug:"related-configuration",link:"#related-configuration",children:[]},{level:2,title:"Supported API List",slug:"supported-api-list",link:"#supported-api-list",children:[{level:3,title:"HandlerService",slug:"handlerservice",link:"#handlerservice",children:[]}]},{level:2,title:"RoutingService",slug:"routingservice",link:"#routingservice",children:[{level:3,title:"LoggerService",slug:"loggerservice",link:"#loggerservice",children:[]},{level:3,title:"StatsService",slug:"statsservice",link:"#statsservice",children:[]},{level:3,title:"ReflectionService",slug:"reflectionservice",link:"#reflectionservice",children:[]}]},{level:2,title:"API Calling Example",slug:"api-calling-example",link:"#api-calling-example",children:[]}],path:"/en/config/api.html",pathLocale:"/en/",extraFields:[]},{title:"Built-in DNS Server",headers:[{level:2,title:"DNS Server",slug:"dns-server",link:"#dns-server",children:[]},{level:2,title:"DNS Processing Flow",slug:"dns-processing-flow",link:"#dns-processing-flow",children:[]},{level:2,title:"DnsObject",slug:"dnsobject",link:"#dnsobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/dns.html",pathLocale:"/en/",extraFields:[]},{title:"FakeDNS",headers:[{level:2,title:"FakeDNSObject",slug:"fakednsobject",link:"#fakednsobject",children:[{level:3,title:"How to use?",slug:"how-to-use",link:"#how-to-use",children:[]},{level:3,title:"Using with other types of DNS",slug:"using-with-other-types-of-dns",link:"#using-with-other-types-of-dns",children:[]}]}],path:"/en/config/fakedns.html",pathLocale:"/en/",extraFields:[]},{title:"Inbound Proxy",headers:[{level:2,title:"InboundObject",slug:"inboundobject",link:"#inboundobject",children:[{level:3,title:"SniffingObject",slug:"sniffingobject",link:"#sniffingobject",children:[]},{level:3,title:"AllocateObject",slug:"allocateobject",link:"#allocateobject",children:[]}]}],path:"/en/config/inbound.html",pathLocale:"/en/",extraFields:[]},{title:"Log Configuration",headers:[{level:2,title:"LogObject",slug:"logobject",link:"#logobject",children:[]}],path:"/en/config/log.html",pathLocale:"/en/",extraFields:[]},{title:"Metrics",headers:[{level:2,title:"Related configurations",slug:"related-configurations",link:"#related-configurations",children:[]},{level:2,title:"Usage",slug:"usage",link:"#usage",children:[{level:3,title:"pprof",slug:"pprof",link:"#pprof",children:[]},{level:3,title:"expvars",slug:"expvars",link:"#expvars",children:[]},{level:3,title:"Additional",slug:"additional",link:"#additional",children:[]}]}],path:"/en/config/metrics.html",pathLocale:"/en/",extraFields:[]},{title:"Outbound Proxies",headers:[{level:2,title:"OutboundObject",slug:"outboundobject",link:"#outboundobject",children:[{level:3,title:"ProxySettingsObject",slug:"proxysettingsobject",link:"#proxysettingsobject",children:[]},{level:3,title:"MuxObject",slug:"muxobject",link:"#muxobject",children:[]}]}],path:"/en/config/outbound.html",pathLocale:"/en/",extraFields:[]},{title:"Local Policy",headers:[{level:2,title:"PolicyObject",slug:"policyobject",link:"#policyobject",children:[{level:3,title:"LevelPolicyObject",slug:"levelpolicyobject",link:"#levelpolicyobject",children:[]},{level:3,title:"SystemPolicyObject",slug:"systempolicyobject",link:"#systempolicyobject",children:[]}]}],path:"/en/config/policy.html",pathLocale:"/en/",extraFields:[]},{title:"Reverse Proxy",headers:[{level:2,title:"ReverseObject",slug:"reverseobject",link:"#reverseobject",children:[{level:3,title:"BridgeObject",slug:"bridgeobject",link:"#bridgeobject",children:[]},{level:3,title:"PortalObject",slug:"portalobject",link:"#portalobject",children:[]}]},{level:2,title:"Complete Configuration Example",slug:"complete-configuration-example",link:"#complete-configuration-example",children:[{level:3,title:"Bridge Configuration",slug:"bridge-configuration",link:"#bridge-configuration",children:[]},{level:3,title:"Portal Configuration",slug:"portal-configuration",link:"#portal-configuration",children:[]}]}],path:"/en/config/reverse.html",pathLocale:"/en/",extraFields:[]},{title:"Routing",headers:[{level:2,title:"RoutingObject",slug:"routingobject",link:"#routingobject",children:[{level:3,title:"RuleObject",slug:"ruleobject",link:"#ruleobject",children:[]},{level:3,title:"BalancerObject",slug:"balancerobject",link:"#balancerobject",children:[]},{level:3,title:"Predefined Domain Lists",slug:"predefined-domain-lists",link:"#predefined-domain-lists",children:[]}]}],path:"/en/config/routing.html",pathLocale:"/en/",extraFields:[]},{title:"Traffic Statistics",headers:[{level:2,title:"StatsObject",slug:"statsobject",link:"#statsobject",children:[]},{level:2,title:"Retrieving Traffic Statistics",slug:"retrieving-traffic-statistics",link:"#retrieving-traffic-statistics",children:[]}],path:"/en/config/stats.html",pathLocale:"/en/",extraFields:[]},{title:"Transport",headers:[{level:2,title:"TransportObject (deprecated)",slug:"transportobject-deprecated",link:"#transportobject-deprecated",children:[]},{level:2,title:"StreamSettingsObject",slug:"streamsettingsobject",link:"#streamsettingsobject",children:[{level:3,title:"TLSObject",slug:"tlsobject",link:"#tlsobject",children:[]},{level:3,title:"SockoptObject",slug:"sockoptobject",link:"#sockoptobject",children:[]}]}],path:"/en/config/transport.html",pathLocale:"/en/",extraFields:[]},{title:"Development Guide",headers:[{level:2,title:"Compile Documentation",slug:"compile-documentation",link:"#compile-documentation",children:[]},{level:2,title:"Design Concept",slug:"design-concept",link:"#design-concept",children:[]},{level:2,title:"Development Standards",slug:"development-standards",link:"#development-standards",children:[]},{level:2,title:"Protocol Details",slug:"protocol-details",link:"#protocol-details",children:[{level:3,title:"VLESS Protocol",slug:"vless-protocol",link:"#vless-protocol",children:[]},{level:3,title:"VMess Protocol",slug:"vmess-protocol",link:"#vmess-protocol",children:[]},{level:3,title:"Mux.Cool Protocol",slug:"mux-cool-protocol",link:"#mux-cool-protocol",children:[]},{level:3,title:"mKCP Protocol",slug:"mkcp-protocol",link:"#mkcp-protocol",children:[]}]}],path:"/en/development/",pathLocale:"/en/",extraFields:[]},{title:"Quick Start",headers:[{level:2,title:"Download and Install",slug:"download-and-install",link:"#download-and-install",children:[]},{level:2,title:"Configure and Run",slug:"configure-and-run",link:"#configure-and-run",children:[]},{level:2,title:"Command Parameters",slug:"command-parameters",link:"#command-parameters",children:[]},{level:2,title:"Improve Documents",slug:"improve-documents",link:"#improve-documents",children:[]},{level:2,title:"Beginner Tutorial",slug:"beginner-tutorial",link:"#beginner-tutorial",children:[]},{level:2,title:"Getting Started Tips",slug:"getting-started-tips",link:"#getting-started-tips",children:[]},{level:2,title:"Advanced Documentation",slug:"advanced-documentation",link:"#advanced-documentation",children:[]}],path:"/en/document/",pathLocale:"/en/",extraFields:[]},{title:"Command Parameters",headers:[{level:2,title:"Get Basic Commands",slug:"get-basic-commands",link:"#get-basic-commands",children:[{level:3,title:"xray run",slug:"xray-run",link:"#xray-run",children:[]},{level:3,title:"xray version",slug:"xray-version",link:"#xray-version",children:[]},{level:3,title:"xray api",slug:"xray-api",link:"#xray-api",children:[]},{level:3,title:"xray tls",slug:"xray-tls",link:"#xray-tls",children:[]},{level:3,title:"xray uuid",slug:"xray-uuid",link:"#xray-uuid",children:[]},{level:3,title:"xray x25519",slug:"xray-x25519",link:"#xray-x25519",children:[]},{level:3,title:"xray wg",slug:"xray-wg",link:"#xray-wg",children:[]}]}],path:"/en/document/command.html",pathLocale:"/en/",extraFields:[]},{title:"Configure and Run",headers:[{level:2,title:"Server Configuration",slug:"server-configuration",link:"#server-configuration",children:[]},{level:2,title:"Client Configuration",slug:"client-configuration",link:"#client-configuration",children:[]},{level:2,title:"Run",slug:"run",link:"#run",children:[]}],path:"/en/document/config.html",pathLocale:"/en/",extraFields:[]},{title:"Contribute to Project X's Document",headers:[{level:2,title:"Improve Document",slug:"improve-document",link:"#improve-document",children:[]},{level:2,title:"Found Problems?",slug:"found-problems",link:"#found-problems",children:[]}],path:"/en/document/document.html",pathLocale:"/en/",extraFields:[]},{title:"Download and Install",headers:[{level:2,title:"Platform Support",slug:"platform-support",link:"#platform-support",children:[]},{level:2,title:"Download Xray",slug:"download-xray",link:"#download-xray",children:[]},{level:2,title:"Verify the Installation Package",slug:"verify-the-installation-package",link:"#verify-the-installation-package",children:[]},{level:2,title:"Install on Windows",slug:"install-on-windows",link:"#install-on-windows",children:[]},{level:2,title:"Install on macOS",slug:"install-on-macos",link:"#install-on-macos",children:[]},{level:2,title:"Install on Linux",slug:"install-on-linux",link:"#install-on-linux",children:[{level:3,title:"Install Script",slug:"install-script",link:"#install-script",children:[]},{level:3,title:"Arch Linux",slug:"arch-linux",link:"#arch-linux",children:[]},{level:3,title:"Linuxbrew",slug:"linuxbrew",link:"#linuxbrew",children:[]},{level:3,title:"Debian",slug:"debian",link:"#debian",children:[]}]},{level:2,title:"Install via Docker",slug:"install-via-docker",link:"#install-via-docker",children:[{level:3,title:"The File Structure of the Docker Image",slug:"the-file-structure-of-the-docker-image",link:"#the-file-structure-of-the-docker-image",children:[]}]}],path:"/en/document/install.html",pathLocale:"/en/",extraFields:[]},{title:"大史记",headers:[{level:2,title:"2021.4.6",slug:"_2021-4-6",link:"#_2021-4-6",children:[]},{level:2,title:"2021.4.4",slug:"_2021-4-4",link:"#_2021-4-4",children:[]},{level:2,title:"2021.4.1 v1.4.2",slug:"_2021-4-1-v1-4-2",link:"#_2021-4-1-v1-4-2",children:[]},{level:2,title:"2021.3.25",slug:"_2021-3-25",link:"#_2021-3-25",children:[]},{level:2,title:"2021.3.15",slug:"_2021-3-15",link:"#_2021-3-15",children:[]},{level:2,title:"2021.3.14 v1.4.0",slug:"_2021-3-14-v1-4-0",link:"#_2021-3-14-v1-4-0",children:[]},{level:2,title:"2021.3.3 1.3.1",slug:"_2021-3-3-1-3-1",link:"#_2021-3-3-1-3-1",children:[]},{level:2,title:"2021.2.14 1.3.0",slug:"_2021-2-14-1-3-0",link:"#_2021-2-14-1-3-0",children:[]},{level:2,title:"2021.01.31 1.2.4",slug:"_2021-01-31-1-2-4",link:"#_2021-01-31-1-2-4",children:[]},{level:2,title:"2021.01.25",slug:"_2021-01-25",link:"#_2021-01-25",children:[]},{level:2,title:"2021.01.22 1.2.3",slug:"_2021-01-22-1-2-3",link:"#_2021-01-22-1-2-3",children:[]},{level:2,title:"2021.01.19",slug:"_2021-01-19",link:"#_2021-01-19",children:[]},{level:2,title:"2021.01.17",slug:"_2021-01-17",link:"#_2021-01-17",children:[]},{level:2,title:"2021.01.15 1.2.2",slug:"_2021-01-15-1-2-2",link:"#_2021-01-15-1-2-2",children:[]},{level:2,title:"2021.01.12",slug:"_2021-01-12",link:"#_2021-01-12",children:[]},{level:2,title:"2021.01.10 1.2.1",slug:"_2021-01-10-1-2-1",link:"#_2021-01-10-1-2-1",children:[]},{level:2,title:"2021.01.07",slug:"_2021-01-07",link:"#_2021-01-07",children:[]},{level:2,title:"2021.01.05",slug:"_2021-01-05",link:"#_2021-01-05",children:[]},{level:2,title:"2021.01.03",slug:"_2021-01-03",link:"#_2021-01-03",children:[]},{level:2,title:"2021.01.01",slug:"_2021-01-01",link:"#_2021-01-01",children:[]},{level:2,title:"2020.12.29",slug:"_2020-12-29",link:"#_2020-12-29",children:[]},{level:2,title:"2020.12.25 1.1.5",slug:"_2020-12-25-1-1-5",link:"#_2020-12-25-1-1-5",children:[]},{level:2,title:"2020.12.24",slug:"_2020-12-24",link:"#_2020-12-24",children:[]},{level:2,title:"2020.12.23",slug:"_2020-12-23",link:"#_2020-12-23",children:[]},{level:2,title:"2020.12.21",slug:"_2020-12-21",link:"#_2020-12-21",children:[]},{level:2,title:"2020.12.18 1.1.4",slug:"_2020-12-18-1-1-4",link:"#_2020-12-18-1-1-4",children:[]},{level:2,title:"2020.12.17",slug:"_2020-12-17",link:"#_2020-12-17",children:[]},{level:2,title:"2020.12.15",slug:"_2020-12-15",link:"#_2020-12-15",children:[]},{level:2,title:"2020.12.11 1.1.3",slug:"_2020-12-11-1-1-3",link:"#_2020-12-11-1-1-3",children:[]},{level:2,title:"2020.12.06 1.1.2",slug:"_2020-12-06-1-1-2",link:"#_2020-12-06-1-1-2",children:[]},{level:2,title:"2020.12.04",slug:"_2020-12-04",link:"#_2020-12-04",children:[]},{level:2,title:"2020.11.27",slug:"_2020-11-27",link:"#_2020-11-27",children:[]},{level:2,title:"2020.11.25 1.0.0",slug:"_2020-11-25-1-0-0",link:"#_2020-11-25-1-0-0",children:[]},{level:2,title:"2020.11.23",slug:"_2020-11-23",link:"#_2020-11-23",children:[]}],path:"/ru/about/news.html",pathLocale:"/ru/",extraFields:[]},{title:"Конфигурационный файл",headers:[{level:2,title:"Обзор",slug:"обзор",link:"#обзор",children:[]},{level:2,title:"Основные модули конфигурации",slug:"основные-модули-конфигурации",link:"#основные-модули-конфигурации",children:[]}],path:"/ru/config/",pathLocale:"/ru/",extraFields:[]},{title:"API",headers:[{level:2,title:"ApiObject",slug:"apiobject",link:"#apiobject",children:[]},{level:2,title:"Связанные настройки",slug:"связанные-настроики",link:"#связанные-настроики",children:[]},{level:2,title:"Список поддерживаемых API",slug:"список-поддерживаемых-api",link:"#список-поддерживаемых-api",children:[{level:3,title:"HandlerService",slug:"handlerservice",link:"#handlerservice",children:[]},{level:3,title:"RoutingService",slug:"routingservice",link:"#routingservice",children:[]},{level:3,title:"LoggerService",slug:"loggerservice",link:"#loggerservice",children:[]},{level:3,title:"StatsService",slug:"statsservice",link:"#statsservice",children:[]},{level:3,title:"ReflectionService",slug:"reflectionservice",link:"#reflectionservice",children:[]}]},{level:2,title:"Примеры вызова API",slug:"примеры-вызова-api",link:"#примеры-вызова-api",children:[]}],path:"/ru/config/api.html",pathLocale:"/ru/",extraFields:[]},{title:"Встроенный DNS-сервер",headers:[{level:2,title:"DNS-сервер",slug:"dns-сервер",link:"#dns-сервер",children:[]},{level:2,title:"Процесс обработки DNS-запросов",slug:"процесс-обработки-dns-запросов",link:"#процесс-обработки-dns-запросов",children:[]},{level:2,title:"DnsObject",slug:"dnsobject",link:"#dnsobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/dns.html",pathLocale:"/ru/",extraFields:[]},{title:"FakeDNS",headers:[{level:2,title:"FakeDNSObject",slug:"fakednsobject",link:"#fakednsobject",children:[{level:3,title:"Как использовать FakeDNS?",slug:"как-использовать-fakedns",link:"#как-использовать-fakedns",children:[]},{level:3,title:"Использование FakeDNS с другими типами DNS",slug:"использование-fakedns-с-другими-типами-dns",link:"#использование-fakedns-с-другими-типами-dns",children:[]}]}],path:"/ru/config/fakedns.html",pathLocale:"/ru/",extraFields:[]},{title:"Входящие подключения",headers:[{level:2,title:"InboundObject",slug:"inboundobject",link:"#inboundobject",children:[{level:3,title:"SniffingObject",slug:"sniffingobject",link:"#sniffingobject",children:[]},{level:3,title:"AllocateObject",slug:"allocateobject",link:"#allocateobject",children:[]}]}],path:"/ru/config/inbound.html",pathLocale:"/ru/",extraFields:[]},{title:"Настройка журнала",headers:[{level:2,title:"LogObject",slug:"logobject",link:"#logobject",children:[]}],path:"/ru/config/log.html",pathLocale:"/ru/",extraFields:[]},{title:"Метрики",headers:[{level:2,title:"Связанные настройки",slug:"связанные-настроики",link:"#связанные-настроики",children:[]},{level:2,title:"Использование",slug:"использование",link:"#использование",children:[{level:3,title:"pprof",slug:"pprof",link:"#pprof",children:[]},{level:3,title:"expvars",slug:"expvars",link:"#expvars",children:[]},{level:3,title:"Дополнительно",slug:"дополнительно",link:"#дополнительно",children:[]}]}],path:"/ru/config/metrics.html",pathLocale:"/ru/",extraFields:[]},{title:"Мониторинг подключений",headers:[{level:2,title:"ObservatoryObject",slug:"observatoryobject",link:"#observatoryobject",children:[]},{level:2,title:"BurstObservatoryObject",slug:"burstobservatoryobject",link:"#burstobservatoryobject",children:[{level:3,title:"PingConfigObject",slug:"pingconfigobject",link:"#pingconfigobject",children:[]}]}],path:"/ru/config/observatory.html",pathLocale:"/ru/",extraFields:[]},{title:"Исходящие подключения",headers:[{level:2,title:"OutboundObject",slug:"outboundobject",link:"#outboundobject",children:[{level:3,title:"ProxySettingsObject",slug:"proxysettingsobject",link:"#proxysettingsobject",children:[]},{level:3,title:"MuxObject",slug:"muxobject",link:"#muxobject",children:[]}]}],path:"/ru/config/outbound.html",pathLocale:"/ru/",extraFields:[]},{title:"Локальные политики",headers:[{level:2,title:"PolicyObject",slug:"policyobject",link:"#policyobject",children:[{level:3,title:"LevelPolicyObject",slug:"levelpolicyobject",link:"#levelpolicyobject",children:[]},{level:3,title:"SystemPolicyObject",slug:"systempolicyobject",link:"#systempolicyobject",children:[]}]}],path:"/ru/config/policy.html",pathLocale:"/ru/",extraFields:[]},{title:"Обратный прокси",headers:[{level:2,title:"ReverseObject",slug:"reverseobject",link:"#reverseobject",children:[{level:3,title:"BridgeObject",slug:"bridgeobject",link:"#bridgeobject",children:[]},{level:3,title:"PortalObject",slug:"portalobject",link:"#portalobject",children:[]}]},{level:2,title:"Примеры полных конфигураций",slug:"примеры-полных-конфигурации",link:"#примеры-полных-конфигурации",children:[{level:3,title:"Настройка bridge",slug:"настроика-bridge",link:"#настроика-bridge",children:[]},{level:3,title:"Настройка portal",slug:"настроика-portal",link:"#настроика-portal",children:[]}]}],path:"/ru/config/reverse.html",pathLocale:"/ru/",extraFields:[]},{title:"Маршрутизация",headers:[{level:2,title:"RoutingObject",slug:"routingobject",link:"#routingobject",children:[{level:3,title:"RuleObject",slug:"ruleobject",link:"#ruleobject",children:[]},{level:3,title:"BalancerObject",slug:"balancerobject",link:"#balancerobject",children:[]},{level:3,title:"Пример конфигурации балансировщика нагрузки",slug:"пример-конфигурации-балансировщика-нагрузки",link:"#пример-конфигурации-балансировщика-нагрузки",children:[]},{level:3,title:"Предопределенные списки доменов",slug:"предопределенные-списки-доменов",link:"#предопределенные-списки-доменов",children:[]}]}],path:"/ru/config/routing.html",pathLocale:"/ru/",extraFields:[]},{title:"Статистика",headers:[{level:2,title:"StatsObject",slug:"statsobject",link:"#statsobject",children:[]},{level:2,title:"Получение статистики",slug:"получение-статистики",link:"#получение-статистики",children:[]}],path:"/ru/config/stats.html",pathLocale:"/ru/",extraFields:[]},{title:"Транспорт",headers:[{level:2,title:"TransportObject (устарело)",slug:"transportobject-устарело",link:"#transportobject-устарело",children:[]},{level:2,title:"StreamSettingsObject",slug:"streamsettingsobject",link:"#streamsettingsobject",children:[{level:3,title:"TLSObject",slug:"tlsobject",link:"#tlsobject",children:[]},{level:3,title:"RealityObject",slug:"realityobject",link:"#realityobject",children:[]},{level:3,title:"SockoptObject",slug:"sockoptobject",link:"#sockoptobject",children:[]}]}],path:"/ru/config/transport.html",pathLocale:"/ru/",extraFields:[]},{title:"开发指南",headers:[{level:2,title:"编译文档",slug:"编译文档",link:"#编译文档",children:[]},{level:2,title:"设计思路",slug:"设计思路",link:"#设计思路",children:[]},{level:2,title:"开发规范",slug:"开发规范",link:"#开发规范",children:[]},{level:2,title:"协议详解",slug:"协议详解",link:"#协议详解",children:[{level:3,title:"VLESS 协议",slug:"vless-协议",link:"#vless-协议",children:[]},{level:3,title:"VMess 协议",slug:"vmess-协议",link:"#vmess-协议",children:[]},{level:3,title:"Mux.Cool 协议",slug:"mux-cool-协议",link:"#mux-cool-协议",children:[]},{level:3,title:"mKCP 协议",slug:"mkcp-协议",link:"#mkcp-协议",children:[]}]}],path:"/ru/development/",pathLocale:"/ru/",extraFields:[]},{title:"Быстрый старт",headers:[{level:2,title:"Загрузка и установка",slug:"загрузка-и-установка",link:"#загрузка-и-установка",children:[]},{level:2,title:"Настройка и запуск",slug:"настроика-и-запуск",link:"#настроика-и-запуск",children:[]},{level:2,title:"Команды и аргументы",slug:"команды-и-аргументы",link:"#команды-и-аргументы",children:[]},{level:2,title:"Улучшение документации",slug:"улучшение-документации",link:"#улучшение-документации",children:[]},{level:2,title:"Простыми словами",slug:"простыми-словами",link:"#простыми-словами",children:[]},{level:2,title:"Базовые навыки",slug:"базовые-навыки",link:"#базовые-навыки",children:[]},{level:2,title:"Продвинутая документация",slug:"продвинутая-документация",link:"#продвинутая-документация",children:[]}],path:"/ru/document/",pathLocale:"/ru/",extraFields:[]},{title:"Командные аргументы",headers:[{level:2,title:"Базовые команды",slug:"базовые-команды",link:"#базовые-команды",children:[{level:3,title:"xray run",slug:"xray-run",link:"#xray-run",children:[]},{level:3,title:"xray version",slug:"xray-version",link:"#xray-version",children:[]},{level:3,title:"xray api",slug:"xray-api",link:"#xray-api",children:[]},{level:3,title:"xray tls",slug:"xray-tls",link:"#xray-tls",children:[]},{level:3,title:"xray uuid",slug:"xray-uuid",link:"#xray-uuid",children:[]},{level:3,title:"xray x25519",slug:"xray-x25519",link:"#xray-x25519",children:[]},{level:3,title:"xray wg",slug:"xray-wg",link:"#xray-wg",children:[]}]}],path:"/ru/document/command.html",pathLocale:"/ru/",extraFields:[]},{title:"Настройка и запуск",headers:[{level:2,title:"Настройка сервера",slug:"настроика-сервера",link:"#настроика-сервера",children:[]},{level:2,title:"Настройка клиента",slug:"настроика-клиента",link:"#настроика-клиента",children:[]},{level:2,title:"Запуск",slug:"запуск",link:"#запуск",children:[]}],path:"/ru/document/config.html",pathLocale:"/ru/",extraFields:[]},{title:"Вклад в документацию Project X",headers:[{level:2,title:"Улучшение документации",slug:"улучшение-документации",link:"#улучшение-документации",children:[]},{level:2,title:"Нашли ошибку?",slug:"нашли-ошибку",link:"#нашли-ошибку",children:[]}],path:"/ru/document/document.html",pathLocale:"/ru/",extraFields:[]},{title:"Загрузка и установка",headers:[{level:2,title:"Поддерживаемые платформы",slug:"поддерживаемые-платформы",link:"#поддерживаемые-платформы",children:[]},{level:2,title:"Загрузка Xray",slug:"загрузка-xray",link:"#загрузка-xray",children:[]},{level:2,title:"Проверка установочного пакета",slug:"проверка-установочного-пакета",link:"#проверка-установочного-пакета",children:[]},{level:2,title:"Установка на Windows",slug:"установка-на-windows",link:"#установка-на-windows",children:[]},{level:2,title:"Установка на macOS",slug:"установка-на-macos",link:"#установка-на-macos",children:[]},{level:2,title:"Установка на Linux",slug:"установка-на-linux",link:"#установка-на-linux",children:[{level:3,title:"Установочные скрипты",slug:"установочные-скрипты",link:"#установочные-скрипты",children:[]},{level:3,title:"Arch Linux",slug:"arch-linux",link:"#arch-linux",children:[]},{level:3,title:"Linuxbrew",slug:"linuxbrew",link:"#linuxbrew",children:[]},{level:3,title:"Debian",slug:"debian",link:"#debian",children:[]},{level:3,title:"Gentoo",slug:"gentoo",link:"#gentoo",children:[]}]},{level:2,title:"Установка с помощью Docker",slug:"установка-с-помощью-docker",link:"#установка-с-помощью-docker",children:[{level:3,title:"Файловая структура образа Docker",slug:"фаиловая-структура-образа-docker",link:"#фаиловая-структура-образа-docker",children:[]}]}],path:"/ru/document/install.html",pathLocale:"/ru/",extraFields:[]},{title:"透明代理入门",headers:[{level:2,title:"什么是透明代理",slug:"什么是透明代理",link:"#什么是透明代理",children:[]},{level:2,title:"透明代理的实现",slug:"透明代理的实现",link:"#透明代理的实现",children:[{level:3,title:"tun2socks",slug:"tun2socks",link:"#tun2socks",children:[]},{level:3,title:"iptables/nftables",slug:"iptables-nftables",link:"#iptables-nftables",children:[]}]},{level:2,title:"iptables 实现透明代理原理",slug:"iptables-实现透明代理原理",link:"#iptables-实现透明代理原理",children:[]},{level:2,title:"透明代理难在哪里",slug:"透明代理难在哪里",link:"#透明代理难在哪里",children:[]},{level:2,title:"从零开始一步步实现基于 iptables-tproxy 的透明代理",slug:"从零开始一步步实现基于-iptables-tproxy-的透明代理",link:"#从零开始一步步实现基于-iptables-tproxy-的透明代理",children:[{level:3,title:"在开始之前,你需要有一定的基础知识:",slug:"在开始之前-你需要有一定的基础知识",link:"#在开始之前-你需要有一定的基础知识",children:[]},{level:3,title:"前期准备工作",slug:"前期准备工作",link:"#前期准备工作",children:[]},{level:3,title:"首先,我们先试试做到第一阶段",slug:"首先-我们先试试做到第一阶段",link:"#首先-我们先试试做到第一阶段",children:[]},{level:3,title:"第二阶段",slug:"第二阶段",link:"#第二阶段",children:[]},{level:3,title:"第三阶段",slug:"第三阶段",link:"#第三阶段",children:[]},{level:3,title:"第四阶段",slug:"第四阶段",link:"#第四阶段",children:[]},{level:3,title:"代理 ipv6",slug:"代理-ipv6",link:"#代理-ipv6",children:[]}]}],path:"/document/level-2/transparent_proxy/transparent_proxy.html",pathLocale:"/",extraFields:[]},{title:"Browser Dialer",headers:[{level:2,title:"Background",slug:"background",link:"#background",children:[]},{level:2,title:"Configuration",slug:"configuration",link:"#configuration",children:[]},{level:2,title:"Inner workings",slug:"inner-workings",link:"#inner-workings",children:[]},{level:2,title:"WebSocket",slug:"websocket",link:"#websocket",children:[]},{level:2,title:"SplitHTTP",slug:"splithttp",link:"#splithttp",children:[]}],path:"/en/config/features/browser_dialer.html",pathLocale:"/en/",extraFields:[]},{title:"Environment Variables",headers:[{level:2,title:"Xray Asset Location",slug:"xray-asset-location",link:"#xray-asset-location",children:[]},{level:2,title:"Configuration File Location",slug:"configuration-file-location",link:"#configuration-file-location",children:[]},{level:2,title:"Multiple Configuration Directories",slug:"multiple-configuration-directories",link:"#multiple-configuration-directories",children:[]}],path:"/en/config/features/env.html",pathLocale:"/en/",extraFields:[]},{title:"Fallback",headers:[{level:2,title:"fallbacks configuration",slug:"fallbacks-configuration",link:"#fallbacks-configuration",children:[{level:3,title:"FallbackObject",slug:"fallbackobject",link:"#fallbackobject",children:[]},{level:3,title:"Additional Information",slug:"additional-information",link:"#additional-information",children:[]}]},{level:2,title:"Fallbacks design theory",slug:"fallbacks-design-theory",link:"#fallbacks-design-theory",children:[]}],path:"/en/config/features/fallback.html",pathLocale:"/en/",extraFields:[]},{title:"Multi-file configuration",headers:[{level:2,title:"Multi-file startup",slug:"multi-file-startup",link:"#multi-file-startup",children:[]},{level:2,title:"Rule Explanation",slug:"rule-explanation",link:"#rule-explanation",children:[{level:3,title:"Normal Objects({})",slug:"normal-objects",link:"#normal-objects",children:[]},{level:3,title:"Arrays([])",slug:"arrays",link:"#arrays",children:[]}]},{level:2,title:"Recommended Multi-file List",slug:"recommended-multi-file-list",link:"#recommended-multi-file-list",children:[]}],path:"/en/config/features/multiple.html",pathLocale:"/en/",extraFields:[]},{title:"Deep analysis of XTLS",headers:[],path:"/en/config/features/xtls.html",pathLocale:"/en/",extraFields:[]},{title:"Dokodemo-Door",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"Transparent Proxy Configuration Example",slug:"transparent-proxy-configuration-example",link:"#transparent-proxy-configuration-example",children:[]}],path:"/en/config/inbounds/dokodemo.html",pathLocale:"/en/",extraFields:[]},{title:"HTTP",headers:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}],path:"/en/config/inbounds/http.html",pathLocale:"/en/",extraFields:[]},{title:"Shadowsocks",headers:[{level:3,title:"Supported Encryption Methods",slug:"supported-encryption-methods",link:"#supported-encryption-methods",children:[]},{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}],path:"/en/config/inbounds/shadowsocks.html",pathLocale:"/en/",extraFields:[]},{title:"SOCKS",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/en/config/inbounds/socks.html",pathLocale:"/en/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/en/config/inbounds/trojan.html",pathLocale:"/en/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/en/config/inbounds/vless.html",pathLocale:"/en/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/en/config/inbounds/vmess.html",pathLocale:"/en/",extraFields:[]},{title:"Blackhole",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ResponseObject",slug:"responseobject",link:"#responseobject",children:[]}]}],path:"/en/config/outbounds/blackhole.html",pathLocale:"/en/",extraFields:[]},{title:"DNS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]},{level:2,title:"DNS Configuration Example",slug:"dns-configuration-example",link:"#dns-configuration-example",children:[]}],path:"/en/config/outbounds/dns.html",pathLocale:"/en/",extraFields:[]},{title:"Freedom",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]}],path:"/en/config/outbounds/freedom.html",pathLocale:"/en/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/http.html",pathLocale:"/en/",extraFields:[]},{title:"Loopback",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"How to use?",slug:"how-to-use",link:"#how-to-use",children:[]}]}],path:"/en/config/outbounds/loopback.html",pathLocale:"/en/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/shadowsocks.html",pathLocale:"/en/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/socks.html",pathLocale:"/en/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/trojan.html",pathLocale:"/en/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]},{level:3,title:"UserObject",slug:"userobject",link:"#userobject",children:[]}]}],path:"/en/config/outbounds/vless.html",pathLocale:"/en/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/en/config/outbounds/vmess.html",pathLocale:"/en/",extraFields:[]},{title:"Wireguard",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Peers",slug:"peers",link:"#peers",children:[]}]}],path:"/en/config/outbounds/wireguard.html",pathLocale:"/en/",extraFields:[]},{title:"Domain Socket",headers:[{level:2,title:"DomainSocketObject",slug:"domainsocketobject",link:"#domainsocketobject",children:[]}],path:"/en/config/transports/domainsocket.html",pathLocale:"/en/",extraFields:[]},{title:"gRPC",headers:[{level:2,title:"GRPCObject",slug:"grpcobject",link:"#grpcobject",children:[]}],path:"/en/config/transports/grpc.html",pathLocale:"/en/",extraFields:[]},{title:"HTTP/2",headers:[{level:2,title:"HttpObject",slug:"httpobject",link:"#httpobject",children:[]}],path:"/en/config/transports/h2.html",pathLocale:"/en/",extraFields:[]},{title:"HTTPUpgrade",headers:[{level:2,title:"HttpUpgradeObject",slug:"httpupgradeobject",link:"#httpupgradeobject",children:[]}],path:"/en/config/transports/httpupgrade.html",pathLocale:"/en/",extraFields:[]},{title:"mKCP",headers:[{level:2,title:"KcpObject",slug:"kcpobject",link:"#kcpobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]},{level:2,title:"Special Thanks",slug:"special-thanks",link:"#special-thanks",children:[]},{level:2,title:"Improvements to the KCP protocol",slug:"improvements-to-the-kcp-protocol",link:"#improvements-to-the-kcp-protocol",children:[{level:3,title:"smaller protocol header",slug:"smaller-protocol-header",link:"#smaller-protocol-header",children:[]},{level:3,title:"ACK packet retransmission",slug:"ack-packet-retransmission",link:"#ack-packet-retransmission",children:[]},{level:3,title:"Connection state control",slug:"connection-state-control",link:"#connection-state-control",children:[]}]}],path:"/en/config/transports/mkcp.html",pathLocale:"/en/",extraFields:[]},{title:"QUIC",headers:[{level:2,title:"QuicObject",slug:"quicobject",link:"#quicobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]}],path:"/en/config/transports/quic.html",pathLocale:"/en/",extraFields:[]},{title:"SplitHTTP",headers:[{level:2,title:"SplitHttpObject",slug:"splithttpobject",link:"#splithttpobject",children:[]},{level:2,title:"HTTP versions",slug:"http-versions",link:"#http-versions",children:[]},{level:2,title:"Troubleshooting",slug:"troubleshooting",link:"#troubleshooting",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]},{level:2,title:"Protocol details",slug:"protocol-details",link:"#protocol-details",children:[]}],path:"/en/config/transports/splithttp.html",pathLocale:"/en/",extraFields:[]},{title:"TCP",headers:[{level:2,title:"TcpObject",slug:"tcpobject",link:"#tcpobject",children:[{level:3,title:"NoneHeaderObject",slug:"noneheaderobject",link:"#noneheaderobject",children:[]},{level:3,title:"HttpHeaderObject",slug:"httpheaderobject",link:"#httpheaderobject",children:[]}]}],path:"/en/config/transports/tcp.html",pathLocale:"/en/",extraFields:[]},{title:"WebSocket",headers:[{level:2,title:"WebSocketObject",slug:"websocketobject",link:"#websocketobject",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]}],path:"/en/config/transports/websocket.html",pathLocale:"/en/",extraFields:[]},{title:"Compile the document",headers:[{level:2,title:"Preparatory Work",slug:"preparatory-work",link:"#preparatory-work",children:[]},{level:2,title:"Pull Xray source code",slug:"pull-xray-source-code",link:"#pull-xray-source-code",children:[]},{level:2,title:"Build Binary",slug:"build-binary",link:"#build-binary",children:[{level:3,title:"Windows(Powershell):",slug:"windows-powershell",link:"#windows-powershell",children:[]},{level:3,title:"macOS, Linux:",slug:"macos-linux",link:"#macos-linux",children:[]}]},{level:2,title:"Reproducible Build:",slug:"reproducible-build",link:"#reproducible-build",children:[]}],path:"/en/development/intro/compile.html",pathLocale:"/en/",extraFields:[]},{title:"Design Objectives",headers:[{level:2,title:"Architecture",slug:"architecture",link:"#architecture",children:[{level:3,title:"Application Layer",slug:"application-layer",link:"#application-layer",children:[]},{level:3,title:"Proxy Layer",slug:"proxy-layer",link:"#proxy-layer",children:[]},{level:3,title:"Transport Layer",slug:"transport-layer",link:"#transport-layer",children:[]}]}],path:"/en/development/intro/design.html",pathLocale:"/en/",extraFields:[]},{title:"Development Standards",headers:[{level:2,title:"Basic",slug:"basic",link:"#basic",children:[{level:3,title:"Version Control",slug:"version-control",link:"#version-control",children:[]},{level:3,title:"Branch",slug:"branch",link:"#branch",children:[]},{level:3,title:"Release",slug:"release",link:"#release",children:[]},{level:3,title:"Citing other projects",slug:"citing-other-projects",link:"#citing-other-projects",children:[]}]},{level:2,title:"Development Process",slug:"development-process",link:"#development-process",children:[{level:3,title:"Before Writing Code",slug:"before-writing-code",link:"#before-writing-code",children:[]},{level:3,title:"Modify the code",slug:"modify-the-code",link:"#modify-the-code",children:[]},{level:3,title:"Pull Request",slug:"pull-request",link:"#pull-request",children:[]},{level:3,title:"Modifying Code",slug:"modifying-code",link:"#modifying-code",children:[]}]},{level:2,title:"Xray Coding Guidelines",slug:"xray-coding-guidelines",link:"#xray-coding-guidelines",children:[{level:3,title:"Code Structure",slug:"code-structure",link:"#code-structure",children:[]},{level:3,title:"Coding Standards",slug:"coding-standards",link:"#coding-standards",children:[]}]}],path:"/en/development/intro/guide.html",pathLocale:"/en/",extraFields:[]},{title:"mKCP Protocol",headers:[{level:2,title:"Version",slug:"version",link:"#version",children:[]},{level:2,title:"Dependencies",slug:"dependencies",link:"#dependencies",children:[{level:3,title:"Underlying Protocol",slug:"underlying-protocol",link:"#underlying-protocol",children:[]},{level:3,title:"Functions",slug:"functions",link:"#functions",children:[]}]},{level:2,title:"Communication Process",slug:"communication-process",link:"#communication-process",children:[]},{level:2,title:"Data Format",slug:"data-format",link:"#data-format",children:[{level:3,title:"Data Packet",slug:"data-packet",link:"#data-packet",children:[]},{level:3,title:"Data snippet",slug:"data-snippet",link:"#data-snippet",children:[]},{level:3,title:"Confirmation snippet",slug:"confirmation-snippet",link:"#confirmation-snippet",children:[]},{level:3,title:"Heartbeat Fragments",slug:"heartbeat-fragments",link:"#heartbeat-fragments",children:[]}]}],path:"/en/development/protocols/mkcp.html",pathLocale:"/en/",extraFields:[]},{title:"Mux.Cool Protocol",headers:[{level:2,title:"Version",slug:"version",link:"#version",children:[]},{level:2,title:"Dependencies",slug:"dependencies",link:"#dependencies",children:[{level:3,title:"Underlying Protocol",slug:"underlying-protocol",link:"#underlying-protocol",children:[]}]},{level:2,title:"Communication Process",slug:"communication-process",link:"#communication-process",children:[{level:3,title:"Client behavior",slug:"client-behavior",link:"#client-behavior",children:[]},{level:3,title:"Server-side behavior",slug:"server-side-behavior",link:"#server-side-behavior",children:[]}]},{level:2,title:"Data Format",slug:"data-format",link:"#data-format",children:[{level:3,title:"Frame Format",slug:"frame-format",link:"#frame-format",children:[]},{level:3,title:"Metadata",slug:"metadata",link:"#metadata",children:[]},{level:3,title:"New Sublink (New)",slug:"new-sublink-new",link:"#new-sublink-new",children:[]},{level:3,title:"Keep sub-connections",slug:"keep-sub-connections",link:"#keep-sub-connections",children:[]},{level:3,title:"End",slug:"end",link:"#end",children:[]},{level:3,title:"KeepAlive",slug:"keepalive",link:"#keepalive",children:[]}]},{level:2,title:"Application",slug:"application",link:"#application",children:[]}],path:"/en/development/protocols/muxcool.html",pathLocale:"/en/",extraFields:[]},{title:"VLESS Protocol",headers:[{level:2,title:"Request & Response",slug:"request-response",link:"#request-response",children:[]},{level:2,title:"ProtoBuf",slug:"protobuf",link:"#protobuf",children:[]},{level:2,title:"Flow",slug:"flow",link:"#flow",children:[{level:3,title:"Flow Control (Formerly Traffic Scheduler)",slug:"flow-control-formerly-traffic-scheduler",link:"#flow-control-formerly-traffic-scheduler",children:[]}]},{level:2,title:"Encryption",slug:"encryption",link:"#encryption",children:[]},{level:2,title:"UDP issues",slug:"udp-issues",link:"#udp-issues",children:[]},{level:2,title:"Client Development Guide",slug:"client-development-guide",link:"#client-development-guide",children:[]},{level:2,title:"VLESS Sharing Link Standard",slug:"vless-sharing-link-standard",link:"#vless-sharing-link-standard",children:[]}],path:"/en/development/protocols/vless.html",pathLocale:"/en/",extraFields:[]},{title:"VMess Protocol",headers:[{level:2,title:"Version",slug:"version",link:"#version",children:[]},{level:2,title:"Dependencies",slug:"dependencies",link:"#dependencies",children:[{level:3,title:"Underlying Protocol",slug:"underlying-protocol",link:"#underlying-protocol",children:[]},{level:3,title:"User ID",slug:"user-id",link:"#user-id",children:[]},{level:3,title:"Functions",slug:"functions",link:"#functions",children:[]}]},{level:2,title:"Communication Process",slug:"communication-process",link:"#communication-process",children:[]},{level:2,title:"Client Request",slug:"client-request",link:"#client-request",children:[{level:3,title:"Authentication Information",slug:"authentication-information",link:"#authentication-information",children:[]},{level:3,title:"Command Section",slug:"command-section",link:"#command-section",children:[]},{level:3,title:"Data Section",slug:"data-section",link:"#data-section",children:[]}]},{level:2,title:"Server Response",slug:"server-response",link:"#server-response",children:[{level:3,title:"Dynamic Port Instructions",slug:"dynamic-port-instructions",link:"#dynamic-port-instructions",children:[]}]},{level:2,title:"Comment",slug:"comment",link:"#comment",children:[]}],path:"/en/development/protocols/vmess.html",pathLocale:"/en/",extraFields:[]},{title:"Plain and Simple Language",headers:[],path:"/en/document/level-0/",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 1] Simple and Plain Language",headers:[{level:2,title:"1.1 Who is this document written for?",slug:"_1-1-who-is-this-document-written-for",link:"#_1-1-who-is-this-document-written-for",children:[]},{level:2,title:"1.2 Who is this document not written for?",slug:"_1-2-who-is-this-document-not-written-for",link:"#_1-2-who-is-this-document-not-written-for",children:[]},{level:2,title:"1.3 Declaration and Other Statements",slug:"_1-3-declaration-and-other-statements",link:"#_1-3-declaration-and-other-statements",children:[]},{level:2,title:"1.4 Why is self-hosting a challenge?",slug:"_1-4-why-is-self-hosting-a-challenge",link:"#_1-4-why-is-self-hosting-a-challenge",children:[]},{level:2,title:'1.5 "Why not just use the airport?"',slug:"_1-5-why-not-just-use-the-airport",link:"#_1-5-why-not-just-use-the-airport",children:[]},{level:2,title:"1.6 So should you build your own website?",slug:"_1-6-so-should-you-build-your-own-website",link:"#_1-6-so-should-you-build-your-own-website",children:[]},{level:2,title:"1.7 Some digressions",slug:"_1-7-some-digressions",link:"#_1-7-some-digressions",children:[]},{level:2,title:"1.8 Your Progress",slug:"_1-8-your-progress",link:"#_1-8-your-progress",children:[]}],path:"/en/document/level-0/ch01-preface.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 2] Preparation of Raw Materials",headers:[{level:2,title:"2.1 Acquiring a VPS",slug:"_2-1-acquiring-a-vps",link:"#_2-1-acquiring-a-vps",children:[]},{level:2,title:"2.2 Obtaining a Desired Domain Name",slug:"_2-2-obtaining-a-desired-domain-name",link:"#_2-2-obtaining-a-desired-domain-name",children:[]},{level:2,title:"2.3 Software you need to install on your local computer",slug:"_2-3-software-you-need-to-install-on-your-local-computer",link:"#_2-3-software-you-need-to-install-on-your-local-computer",children:[]},{level:2,title:"2.4 Your Progress",slug:"_2-4-your-progress",link:"#_2-4-your-progress",children:[]}],path:"/en/document/level-0/ch02-preparation.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 3] Remote Login",headers:[{level:2,title:"3.1 Remote Login to VPS (PuTTY)",slug:"_3-1-remote-login-to-vps-putty",link:"#_3-1-remote-login-to-vps-putty",children:[]},{level:2,title:"3.2 Successfully Logging in SSH! Introduction to Command Line Interface!",slug:"_3-2-successfully-logging-in-ssh-introduction-to-command-line-interface",link:"#_3-2-successfully-logging-in-ssh-introduction-to-command-line-interface",children:[]},{level:2,title:"3.3 Updating software on Linux for the first time!",slug:"_3-3-updating-software-on-linux-for-the-first-time",link:"#_3-3-updating-software-on-linux-for-the-first-time",children:[]},{level:2,title:"3.4 Your Progress",slug:"_3-4-your-progress",link:"#_3-4-your-progress",children:[]}],path:"/en/document/level-0/ch03-ssh.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 4] Security and Protection",headers:[{level:2,title:"4.1 Why Do We Need Security Protection?",slug:"_4-1-why-do-we-need-security-protection",link:"#_4-1-why-do-we-need-security-protection",children:[]},{level:2,title:"4.2 What are the specific risks",slug:"_4-2-what-are-the-specific-risks",link:"#_4-2-what-are-the-specific-risks",children:[]},{level:2,title:"4.3 What security measures do we need to take",slug:"_4-3-what-security-measures-do-we-need-to-take",link:"#_4-3-what-security-measures-do-we-need-to-take",children:[]},{level:2,title:"4.4 Change the SSH Remote Login Port to a Non-22 Port",slug:"_4-4-change-the-ssh-remote-login-port-to-a-non-22-port",link:"#_4-4-change-the-ssh-remote-login-port-to-a-non-22-port",children:[]},{level:2,title:"4.5 Creating a New User Without Root Access",slug:"_4-5-creating-a-new-user-without-root-access",link:"#_4-5-creating-a-new-user-without-root-access",children:[]},{level:2,title:"4.8 Your Progress",slug:"_4-8-your-progress",link:"#_4-8-your-progress",children:[]}],path:"/en/document/level-0/ch04-security.html",pathLocale:"/en/",extraFields:[]},{title:"Chapter 5: Website Building",headers:[{level:2,title:"5.1 Why should you create a website?",slug:"_5-1-why-should-you-create-a-website",link:"#_5-1-why-should-you-create-a-website",children:[]},{level:2,title:"5.2 Log in to VPS, install and run Nginx",slug:"_5-2-log-in-to-vps-install-and-run-nginx",link:"#_5-2-log-in-to-vps-install-and-run-nginx",children:[]},{level:2,title:"5.3 Create the simplest web page",slug:"_5-3-create-the-simplest-web-page",link:"#_5-3-create-the-simplest-web-page",children:[]},{level:2,title:"5.4 Common error explanations",slug:"_5-4-common-error-explanations",link:"#_5-4-common-error-explanations",children:[]}],path:"/en/document/level-0/ch05-webpage.html",pathLocale:"/en/",extraFields:[]},{title:"[Chapter 6] Certificate Management",headers:[{level:2,title:"6.1 Applying for a TLS Certificate",slug:"_6-1-applying-for-a-tls-certificate",link:"#_6-1-applying-for-a-tls-certificate",children:[]},{level:2,title:"6.2 Install acme.sh",slug:"_6-2-install-acme-sh",link:"#_6-2-install-acme-sh",children:[]},{level:2,title:"6.3 Testing Certificate Application",slug:"_6-3-testing-certificate-application",link:"#_6-3-testing-certificate-application",children:[]},{level:2,title:"6.5 Certificate Installation",slug:"_6-5-certificate-installation",link:"#_6-5-certificate-installation",children:[]},{level:2,title:"6.6 Your Progress",slug:"_6-6-your-progress",link:"#_6-6-your-progress",children:[]}],path:"/en/document/level-0/ch06-certificates.html",pathLocale:"/en/",extraFields:[]},{title:"【第 7 章】Xray 服务器篇",headers:[{level:2,title:"7.1 博观而约取,厚积而薄发",slug:"_7-1-博观而约取-厚积而薄发",link:"#_7-1-博观而约取-厚积而薄发",children:[]},{level:2,title:"7.2 安装 Xray",slug:"_7-2-安装-xray",link:"#_7-2-安装-xray",children:[]},{level:2,title:"7.3 给 Xray 配置 TLS 证书",slug:"_7-3-给-xray-配置-tls-证书",link:"#_7-3-给-xray-配置-tls-证书",children:[]},{level:2,title:"7.4 配置 Xray",slug:"_7-4-配置-xray",link:"#_7-4-配置-xray",children:[]},{level:2,title:"7.5 启动 Xray 服务!!(并查看服务状态)",slug:"_7-5-启动-xray-服务-并查看服务状态",link:"#_7-5-启动-xray-服务-并查看服务状态",children:[]},{level:2,title:"7.6 回顾 systemd 进行基本的服务管理",slug:"_7-6-回顾-systemd-进行基本的服务管理",link:"#_7-6-回顾-systemd-进行基本的服务管理",children:[]},{level:2,title:"7.7 服务器优化之一:开启 BBR",slug:"_7-7-服务器优化之一-开启-bbr",link:"#_7-7-服务器优化之一-开启-bbr",children:[]},{level:2,title:"7.8 服务器优化之二:开启 HTTP 自动跳转 HTTPS",slug:"_7-8-服务器优化之二-开启-http-自动跳转-https",link:"#_7-8-服务器优化之二-开启-http-自动跳转-https",children:[]},{level:2,title:"7.9 服务器优化之三:更丰富的回落",slug:"_7-9-服务器优化之三-更丰富的回落",link:"#_7-9-服务器优化之三-更丰富的回落",children:[]},{level:2,title:"7.10 你的进度",slug:"_7-10-你的进度",link:"#_7-10-你的进度",children:[]},{level:2,title:"7.11 重要勘误",slug:"_7-11-重要勘误",link:"#_7-11-重要勘误",children:[]}],path:"/en/document/level-0/ch07-xray-server.html",pathLocale:"/en/",extraFields:[]},{title:"【第 8 章】Xray 客户端篇",headers:[{level:2,title:"8.1 Xray 的工作原理简述",slug:"_8-1-xray-的工作原理简述",link:"#_8-1-xray-的工作原理简述",children:[]},{level:2,title:"8.2 客户端与服务器端正确连接",slug:"_8-2-客户端与服务器端正确连接",link:"#_8-2-客户端与服务器端正确连接",children:[]},{level:2,title:"8.3 附加题 1:在 PC 端手工配置 xray-core",slug:"_8-3-附加题-1-在-pc-端手工配置-xray-core",link:"#_8-3-附加题-1-在-pc-端手工配置-xray-core",children:[]},{level:2,title:"8.4 附加题 2:在 PC 端手工运行 xray-core",slug:"_8-4-附加题-2-在-pc-端手工运行-xray-core",link:"#_8-4-附加题-2-在-pc-端手工运行-xray-core",children:[]},{level:2,title:"8.5 附加题 3:在 PC 端开机自动运行 xray-core",slug:"_8-5-附加题-3-在-pc-端开机自动运行-xray-core",link:"#_8-5-附加题-3-在-pc-端开机自动运行-xray-core",children:[]},{level:2,title:"8.6 圆满完成!",slug:"_8-6-圆满完成",link:"#_8-6-圆满完成",children:[]},{level:2,title:"8.7 TO INFINITY AND BEYOND!",slug:"_8-7-to-infinity-and-beyond",link:"#_8-7-to-infinity-and-beyond",children:[]}],path:"/en/document/level-0/ch08-xray-clients.html",pathLocale:"/en/",extraFields:[]},{title:"【第 9 章】附录",headers:[{level:2,title:"1. 小小白白 Linux 基础命令索引",slug:"_1-小小白白-linux-基础命令索引",link:"#_1-小小白白-linux-基础命令索引",children:[]},{level:2,title:"2. 小小白白 Linux 重要配置文件索引",slug:"_2-小小白白-linux-重要配置文件索引",link:"#_2-小小白白-linux-重要配置文件索引",children:[]},{level:2,title:"3. 小小白白 Xray 重要文件索引",slug:"_3-小小白白-xray-重要文件索引",link:"#_3-小小白白-xray-重要文件索引",children:[]}],path:"/en/document/level-0/ch09-appendix.html",pathLocale:"/en/",extraFields:[]},{title:"Beginner's Tips",headers:[],path:"/en/document/level-1/",pathLocale:"/en/",extraFields:[]},{title:"回落 (fallbacks) 功能简析",headers:[{level:2,title:"1. 回顾《小小白白话文》中的回落",slug:"_1-回顾《小小白白话文》中的回落",link:"#_1-回顾《小小白白话文》中的回落",children:[]},{level:2,title:"2. 重新认识回落 (WHAT, HOW v1)",slug:"_2-重新认识回落-what-how-v1",link:"#_2-重新认识回落-what-how-v1",children:[]},{level:2,title:"3. 为什么要回落 (WHY v1)",slug:"_3-为什么要回落-why-v1",link:"#_3-为什么要回落-why-v1",children:[]},{level:2,title:"4. 重新认识【回落の完全体】 (WHAT, WHY, HOW v2)",slug:"_4-重新认识【回落の完全体】-what-why-how-v2",link:"#_4-重新认识【回落の完全体】-what-why-how-v2",children:[]},{level:2,title:"5. 多层回落示例及解读",slug:"_5-多层回落示例及解读",link:"#_5-多层回落示例及解读",children:[{level:3,title:"5.1 首先,我将服务器端配置的 443 监听段摘抄如下:",slug:"_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",link:"#_5-1-首先-我将服务器端配置的-443-监听段摘抄如下",children:[]},{level:3,title:"5.2 后续监听处理的配置段摘抄如下:",slug:"_5-2-后续监听处理的配置段摘抄如下",link:"#_5-2-后续监听处理的配置段摘抄如下",children:[]}]},{level:2,title:"6. 结语",slug:"_6-结语",link:"#_6-结语",children:[]},{level:2,title:"7. 附加题",slug:"_7-附加题",link:"#_7-附加题",children:[]}],path:"/en/document/level-1/fallbacks-lv1.html",pathLocale:"/en/",extraFields:[]},{title:"SNI fallback",headers:[{level:2,title:"Application Scenarios",slug:"application-scenarios",link:"#application-scenarios",children:[]},{level:2,title:"Introduction to SNI",slug:"introduction-to-sni",link:"#introduction-to-sni",children:[]},{level:2,title:"Idea",slug:"idea",link:"#idea",children:[]},{level:2,title:"Adding DNS Records",slug:"adding-dns-records",link:"#adding-dns-records",children:[]},{level:2,title:"Applying for TLS Certificate",slug:"applying-for-tls-certificate",link:"#applying-for-tls-certificate",children:[]},{level:2,title:"Xray Configuration",slug:"xray-configuration",link:"#xray-configuration",children:[]},{level:2,title:"Nginx Configuration",slug:"nginx-configuration",link:"#nginx-configuration",children:[]},{level:2,title:"Caddy Configuration",slug:"caddy-configuration",link:"#caddy-configuration",children:[]},{level:2,title:"Reference",slug:"reference",link:"#reference",children:[]},{level:2,title:"Quotation",slug:"quotation",link:"#quotation",children:[]}],path:"/en/document/level-1/fallbacks-with-sni.html",pathLocale:"/en/",extraFields:[]},{title:"路由 (routing) 功能简析(上)",headers:[{level:2,title:"1. 初识【路由】三兄弟",slug:"_1-初识【路由】三兄弟",link:"#_1-初识【路由】三兄弟",children:[]},{level:2,title:"2. 基本功: “兄弟一条心”",slug:"_2-基本功-兄弟一条心",link:"#_2-基本功-兄弟一条心",children:[{level:3,title:"2.1 入站",slug:"_2-1-入站",link:"#_2-1-入站",children:[]},{level:3,title:"2.3 路由",slug:"_2-3-路由",link:"#_2-3-路由",children:[]},{level:3,title:"2.4 路由配置项解析之一:流量筛选的依据",slug:"_2-4-路由配置项解析之一-流量筛选的依据",link:"#_2-4-路由配置项解析之一-流量筛选的依据",children:[]}]},{level:2,title:"3. 小试牛刀: “三分天下” 之 “域名分流”",slug:"_3-小试牛刀-三分天下-之-域名分流",link:"#_3-小试牛刀-三分天下-之-域名分流",children:[{level:3,title:"3.1 入站",slug:"_3-1-入站",link:"#_3-1-入站",children:[]},{level:3,title:"3.2 出站",slug:"_3-2-出站",link:"#_3-2-出站",children:[]},{level:3,title:"3.3 路由",slug:"_3-3-路由",link:"#_3-3-路由",children:[]},{level:3,title:"3.4 简析域名文件: geosite.dat",slug:"_3-4-简析域名文件-geosite-dat",link:"#_3-4-简析域名文件-geosite-dat",children:[]},{level:3,title:"3.5 所以 geosite.dat 到底是什么?不是有个 GFWList 吗?",slug:"_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",link:"#_3-5-所以-geosite-dat-到底是什么-不是有个-gfwlist-吗",children:[]},{level:3,title:"3.6 军师锦囊藏奇兵:一条隐藏的路由规则",slug:"_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",link:"#_3-6-军师锦囊藏奇兵-一条隐藏的路由规则",children:[]},{level:3,title:"3.7 再看“三分天下”的大地图",slug:"_3-7-再看-三分天下-的大地图",link:"#_3-7-再看-三分天下-的大地图",children:[]}]},{level:2,title:"4. “三分天下” 之 “蜀魏争雄”",slug:"_4-三分天下-之-蜀魏争雄",link:"#_4-三分天下-之-蜀魏争雄",children:[]},{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[]}],path:"/en/document/level-1/routing-lv1-part1.html",pathLocale:"/en/",extraFields:[]},{title:"路由 (routing) 功能简析(下)",headers:[{level:2,title:"5. 攻城略池 - 多种路由匹配条件",slug:"_5-攻城略池-多种路由匹配条件",link:"#_5-攻城略池-多种路由匹配条件",children:[{level:3,title:"5.1 基于指定域名分流:[domain], [full] 等",slug:"_5-1-基于指定域名分流-domain-full-等",link:"#_5-1-基于指定域名分流-domain-full-等",children:[]},{level:3,title:"5.2 基于 IP 文件分流:geoip.dat",slug:"_5-2-基于-ip-文件分流-geoip-dat",link:"#_5-2-基于-ip-文件分流-geoip-dat",children:[]},{level:3,title:"5.3 基于指定 IP 地址分流",slug:"_5-3-基于指定-ip-地址分流",link:"#_5-3-基于指定-ip-地址分流",children:[]},{level:3,title:"5.4 基于协议类型分流:[protocol] 等",slug:"_5-4-基于协议类型分流-protocol-等",link:"#_5-4-基于协议类型分流-protocol-等",children:[]},{level:3,title:"5.5 基于更多条件的分流",slug:"_5-5-基于更多条件的分流",link:"#_5-5-基于更多条件的分流",children:[]}]},{level:2,title:"6. “霸业初定”:路由规则整体回顾",slug:"_6-霸业初定-路由规则整体回顾",link:"#_6-霸业初定-路由规则整体回顾",children:[]},{level:2,title:"7. 路由配置常见错误",slug:"_7-路由配置常见错误",link:"#_7-路由配置常见错误",children:[{level:3,title:"7.1 错误示范",slug:"_7-1-错误示范",link:"#_7-1-错误示范",children:[]},{level:3,title:"7.2 正确示范",slug:"_7-2-正确示范",link:"#_7-2-正确示范",children:[]}]},{level:2,title:"8. 明修栈道、暗渡陈仓",slug:"_8-明修栈道、暗渡陈仓",link:"#_8-明修栈道、暗渡陈仓",children:[{level:3,title:'8.1 域名策略: "AsIs"',slug:"_8-1-域名策略-asis",link:"#_8-1-域名策略-asis",children:[]},{level:3,title:'8.2 域名策略: "IPIfNonMatch"',slug:"_8-2-域名策略-ipifnonmatch",link:"#_8-2-域名策略-ipifnonmatch",children:[]},{level:3,title:'8.3 域名策略: "IPOnDemand"',slug:"_8-3-域名策略-ipondemand",link:"#_8-3-域名策略-ipondemand",children:[]}]},{level:2,title:"9. 思考题",slug:"_9-思考题",link:"#_9-思考题",children:[]},{level:2,title:"10. 结语",slug:"_10-结语",link:"#_10-结语",children:[]},{level:2,title:"11. 尾注",slug:"_11-尾注",link:"#_11-尾注",children:[]}],path:"/en/document/level-1/routing-lv1-part2.html",pathLocale:"/en/",extraFields:[]},{title:"Xray 的工作模式",headers:[{level:2,title:"单服务器模式",slug:"单服务器模式",link:"#单服务器模式",children:[]},{level:2,title:"桥接模式",slug:"桥接模式",link:"#桥接模式",children:[]},{level:2,title:"工作原理",slug:"工作原理",link:"#工作原理",children:[]}],path:"/en/document/level-1/work.html",pathLocale:"/en/",extraFields:[]},{title:"Advanced Documentation",headers:[],path:"/en/document/level-2/",pathLocale:"/en/",extraFields:[]},{title:"Transparent proxy via GID",headers:[{level:2,title:"Ideas",slug:"ideas",link:"#ideas",children:[]},{level:2,title:"Configuration Procedure",slug:"configuration-procedure",link:"#configuration-procedure",children:[{level:3,title:"1. Preliminary preparation",slug:"_1-preliminary-preparation",link:"#_1-preliminary-preparation",children:[]},{level:3,title:"2. Add user (Android users please ignore this section)",slug:"_2-add-user-android-users-please-ignore-this-section",link:"#_2-add-user-android-users-please-ignore-this-section",children:[]},{level:3,title:"3. Configure and run Xray, and configure iptables rules",slug:"_3-configure-and-run-xray-and-configure-iptables-rules",link:"#_3-configure-and-run-xray-and-configure-iptables-rules",children:[]}]},{level:2,title:"Steps",slug:"steps",link:"#steps",children:[{level:3,title:"1. Finish Preliminary preparation and Add user",slug:"_1-finish-preliminary-preparation-and-add-user",link:"#_1-finish-preliminary-preparation-and-add-user",children:[]},{level:3,title:"2. Preparing Xray profiles",slug:"_2-preparing-xray-profiles",link:"#_2-preparing-xray-profiles",children:[]},{level:3,title:"3. Configuring the maximum number of open files and run the Xray client",slug:"_3-configuring-the-maximum-number-of-open-files-and-run-the-xray-client",link:"#_3-configuring-the-maximum-number-of-open-files-and-run-the-xray-client",children:[]},{level:3,title:"4. Setting up iptables rules",slug:"_4-setting-up-iptables-rules",link:"#_4-setting-up-iptables-rules",children:[]}]}],path:"/en/document/level-2/iptables_gid.html",pathLocale:"/en/",extraFields:[]},{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹",headers:[{level:2,title:"编译 nginx --with-stream",slug:"编译-nginx-with-stream",link:"#编译-nginx-with-stream",children:[]},{level:2,title:"配置 nginx",slug:"配置-nginx",link:"#配置-nginx",children:[]},{level:2,title:"xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"客户端及服务端启动服务",slug:"客户端及服务端启动服务",link:"#客户端及服务端启动服务",children:[]},{level:2,title:"结束",slug:"结束",link:"#结束",children:[]},{level:2,title:"HTTPS 隧道",slug:"https-隧道",link:"#https-隧道",children:[{level:3,title:"haproxy_client 配置 (运行前去掉注释)",slug:"haproxy-client-配置-运行前去掉注释",link:"#haproxy-client-配置-运行前去掉注释",children:[]},{level:3,title:"haproxy_server 配置 (运行前去掉注释)",slug:"haproxy-server-配置-运行前去掉注释",link:"#haproxy-server-配置-运行前去掉注释",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-1",link:"#xray-配置-1",children:[]}]},{level:2,title:"WebSocket over HTTP/2",slug:"websocket-over-http-2",link:"#websocket-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置",link:"#haproxy-client-配置",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置",link:"#haproxy-server-配置",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-2",link:"#xray-配置-2",children:[]}]},{level:2,title:"gRPC over HTTP/2",slug:"grpc-over-http-2",link:"#grpc-over-http-2",children:[{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-1",link:"#haproxy-client-配置-1",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-1",link:"#haproxy-server-配置-1",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-3",link:"#xray-配置-3",children:[]},{level:3,title:"haproxy_client 配置",slug:"haproxy-client-配置-2",link:"#haproxy-client-配置-2",children:[]},{level:3,title:"haproxy_server 配置",slug:"haproxy-server-配置-2",link:"#haproxy-server-配置-2",children:[]},{level:3,title:"xray 配置",slug:"xray-配置-4",link:"#xray-配置-4",children:[]}]}],path:"/en/document/level-2/nginx_or_haproxy_tls_tunnel.html",pathLocale:"/en/",extraFields:[]},{title:"出站流量重定向",headers:[{level:2,title:"前言",slug:"前言",link:"#前言",children:[]},{level:2,title:"1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)",slug:"_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",link:"#_1、安装代理或者-vpn-软件-例如-wireguard、ipsec-等",children:[]},{level:2,title:"2、编辑 VPN 配置文件(以 WireGuard 为例)",slug:"_2、编辑-vpn-配置文件-以-wireguard-为例",link:"#_2、编辑-vpn-配置文件-以-wireguard-为例",children:[]},{level:2,title:"3、启用 WireGuard 网络接口",slug:"_3、启用-wireguard-网络接口",link:"#_3、启用-wireguard-网络接口",children:[]},{level:2,title:"4、Xray-core 配置文件修改",slug:"_4、xray-core-配置文件修改",link:"#_4、xray-core-配置文件修改",children:[]},{level:2,title:"5、系统设置配置",slug:"_5、系统设置配置",link:"#_5、系统设置配置",children:[]},{level:2,title:"6、完成 WireGuard 相关设置",slug:"_6、完成-wireguard-相关设置",link:"#_6、完成-wireguard-相关设置",children:[]},{level:2,title:"后记",slug:"后记",link:"#后记",children:[]},{level:2,title:"感谢",slug:"感谢",link:"#感谢",children:[]}],path:"/en/document/level-2/redirect.html",pathLocale:"/en/",extraFields:[]},{title:"TProxy 透明代理",headers:[{level:2,title:"开始之前",slug:"开始之前",link:"#开始之前",children:[]},{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[]},{level:2,title:"策略路由配置",slug:"策略路由配置",link:"#策略路由配置",children:[]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[]},{level:2,title:"配置永久化与开机自启",slug:"配置永久化与开机自启",link:"#配置永久化与开机自启",children:[]}],path:"/en/document/level-2/tproxy.html",pathLocale:"/en/",extraFields:[]},{title:"TProxy 透明代理 (ipv4 and ipv6)",headers:[{level:2,title:"Xray 配置",slug:"xray-配置",link:"#xray-配置",children:[{level:3,title:"客户端配置",slug:"客户端配置",link:"#客户端配置",children:[]},{level:3,title:"服务端配置",slug:"服务端配置",link:"#服务端配置",children:[]}]},{level:2,title:"Netfilter 配置",slug:"netfilter-配置",link:"#netfilter-配置",children:[{level:3,title:"首先设置策略路由",slug:"首先设置策略路由",link:"#首先设置策略路由",children:[]},{level:3,title:"使用 iptables",slug:"使用-iptables",link:"#使用-iptables",children:[]},{level:3,title:"使用 nftables",slug:"使用-nftables",link:"#使用-nftables",children:[]},{level:3,title:"开机自动运行 Netfilter 配置",slug:"开机自动运行-netfilter-配置",link:"#开机自动运行-netfilter-配置",children:[]}]},{level:2,title:"局域网设备上网设置",slug:"局域网设备上网设置",link:"#局域网设备上网设置",children:[{level:3,title:"方法一",slug:"方法一",link:"#方法一",children:[]},{level:3,title:"方法二",slug:"方法二",link:"#方法二",children:[]}]},{level:2,title:"Finally",slug:"finally",link:"#finally",children:[]},{level:2,title:"写在最后",slug:"写在最后",link:"#写在最后",children:[]}],path:"/en/document/level-2/tproxy_ipv4_and_ipv6.html",pathLocale:"/en/",extraFields:[]},{title:"流量统计",headers:[{level:2,title:"查看流量信息",slug:"查看流量信息",link:"#查看流量信息",children:[]},{level:2,title:"流量信息的处理",slug:"流量信息的处理",link:"#流量信息的处理",children:[]}],path:"/en/document/level-2/traffic_stats.html",pathLocale:"/en/",extraFields:[]},{title:"Enhancing Proxy Security with Cloudflare Warp",headers:[{level:2,title:"Applying for a Warp Account",slug:"applying-for-a-warp-account",link:"#applying-for-a-warp-account",children:[]},{level:2,title:"Diverting inbound traffic to warp on the server side",slug:"diverting-inbound-traffic-to-warp-on-the-server-side",link:"#diverting-inbound-traffic-to-warp-on-the-server-side",children:[]},{level:2,title:"Using Warp Chain Proxy on the Client Side",slug:"using-warp-chain-proxy-on-the-client-side",link:"#using-warp-chain-proxy-on-the-client-side",children:[]}],path:"/en/document/level-2/warp.html",pathLocale:"/en/",extraFields:[]},{title:"Browser Dialer",headers:[{level:2,title:"Предыстория",slug:"предыстория",link:"#предыстория",children:[]},{level:2,title:"Конфигурация",slug:"конфигурация",link:"#конфигурация",children:[]},{level:2,title:"Внутренняя работа",slug:"внутренняя-работа",link:"#внутренняя-работа",children:[]},{level:2,title:"WebSocket",slug:"websocket",link:"#websocket",children:[]},{level:2,title:"SplitHTTP",slug:"splithttp",link:"#splithttp",children:[]}],path:"/ru/config/features/browser_dialer.html",pathLocale:"/ru/",extraFields:[]},{title:"Переменные среды",headers:[{level:2,title:"Путь к файлам ресурсов",slug:"путь-к-фаилам-ресурсов",link:"#путь-к-фаилам-ресурсов",children:[]},{level:2,title:"Расположение файла конфигурации",slug:"расположение-фаила-конфигурации",link:"#расположение-фаила-конфигурации",children:[]},{level:2,title:"Каталог с несколькими конфигурациями",slug:"каталог-с-несколькими-конфигурациями",link:"#каталог-с-несколькими-конфигурациями",children:[]}],path:"/ru/config/features/env.html",pathLocale:"/ru/",extraFields:[]},{title:"Fallback",headers:[{level:2,title:"Настройка fallbacks",slug:"настроика-fallbacks",link:"#настроика-fallbacks",children:[{level:3,title:"FallbackObject",slug:"fallbackobject",link:"#fallbackobject",children:[]},{level:3,title:"Дополнительные замечания",slug:"дополнительные-замечания",link:"#дополнительные-замечания",children:[]}]},{level:2,title:"Теория Fallbacks",slug:"теория-fallbacks",link:"#теория-fallbacks",children:[]}],path:"/ru/config/features/fallback.html",pathLocale:"/ru/",extraFields:[]},{title:"Настройка с помощью нескольких файлов",headers:[{level:2,title:"Запуск с несколькими файлами",slug:"запуск-с-несколькими-фаилами",link:"#запуск-с-несколькими-фаилами",children:[]},{level:2,title:"Правила",slug:"правила",link:"#правила",children:[{level:3,title:"Обычные объекты ({})",slug:"обычные-объекты",link:"#обычные-объекты",children:[]},{level:3,title:"Массивы ([])",slug:"массивы",link:"#массивы",children:[]}]},{level:2,title:"Пример конфигурации",slug:"пример-конфигурации",link:"#пример-конфигурации",children:[]}],path:"/ru/config/features/multiple.html",pathLocale:"/ru/",extraFields:[]},{title:"Глубокое погружение в XTLS",headers:[],path:"/ru/config/features/xtls.html",pathLocale:"/ru/",extraFields:[]},{title:"Dokodemo-Door",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"Использование",slug:"использование",link:"#использование",children:[]},{level:2,title:"Пример настройки прозрачного прокси",slug:"пример-настроики-прозрачного-прокси",link:"#пример-настроики-прозрачного-прокси",children:[]}],path:"/ru/config/inbounds/dokodemo.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/ru/config/inbounds/http.html",pathLocale:"/ru/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[]},{level:2,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}],path:"/ru/config/inbounds/shadowsocks.html",pathLocale:"/ru/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"AccountObject",slug:"accountobject",link:"#accountobject",children:[]}]}],path:"/ru/config/inbounds/socks.html",pathLocale:"/ru/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/ru/config/inbounds/trojan.html",pathLocale:"/ru/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/ru/config/inbounds/vless.html",pathLocale:"/ru/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"InboundConfigurationObject",slug:"inboundconfigurationobject",link:"#inboundconfigurationobject",children:[{level:3,title:"ClientObject",slug:"clientobject",link:"#clientobject",children:[]}]}],path:"/ru/config/inbounds/vmess.html",pathLocale:"/ru/",extraFields:[]},{title:"Blackhole",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ResponseObject",slug:"responseobject",link:"#responseobject",children:[]}]}],path:"/ru/config/outbounds/blackhole.html",pathLocale:"/ru/",extraFields:[]},{title:"DNS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]},{level:2,title:"Пример настройки DNS",slug:"пример-настроики-dns",link:"#пример-настроики-dns",children:[]}],path:"/ru/config/outbounds/dns.html",pathLocale:"/ru/",extraFields:[]},{title:"Freedom",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[]}],path:"/ru/config/outbounds/freedom.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTP",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/http.html",pathLocale:"/ru/",extraFields:[]},{title:"Loopback",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Как использовать?",slug:"как-использовать",link:"#как-использовать",children:[]}]}],path:"/ru/config/outbounds/loopback.html",pathLocale:"/ru/",extraFields:[]},{title:"Shadowsocks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/shadowsocks.html",pathLocale:"/ru/",extraFields:[]},{title:"Socks",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/socks.html",pathLocale:"/ru/",extraFields:[]},{title:"Trojan",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/trojan.html",pathLocale:"/ru/",extraFields:[]},{title:"VLESS",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]},{level:3,title:"UserObject",slug:"userobject",link:"#userobject",children:[]}]}],path:"/ru/config/outbounds/vless.html",pathLocale:"/ru/",extraFields:[]},{title:"VMess",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"ServerObject",slug:"serverobject",link:"#serverobject",children:[]}]}],path:"/ru/config/outbounds/vmess.html",pathLocale:"/ru/",extraFields:[]},{title:"WireGuard",headers:[{level:2,title:"OutboundConfigurationObject",slug:"outboundconfigurationobject",link:"#outboundconfigurationobject",children:[{level:3,title:"Peers",slug:"peers",link:"#peers",children:[]}]}],path:"/ru/config/outbounds/wireguard.html",pathLocale:"/ru/",extraFields:[]},{title:"DomainSocket",headers:[{level:2,title:"DomainSocketObject",slug:"domainsocketobject",link:"#domainsocketobject",children:[]}],path:"/ru/config/transports/domainsocket.html",pathLocale:"/ru/",extraFields:[]},{title:"gRPC",headers:[{level:2,title:"GRPCObject",slug:"grpcobject",link:"#grpcobject",children:[]}],path:"/ru/config/transports/grpc.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTP/2",headers:[{level:2,title:"HttpObject",slug:"httpobject",link:"#httpobject",children:[]}],path:"/ru/config/transports/h2.html",pathLocale:"/ru/",extraFields:[]},{title:"HTTPUpgrade",headers:[{level:2,title:"HttpUpgradeObject",slug:"httpupgradeobject",link:"#httpupgradeobject",children:[]}],path:"/ru/config/transports/httpupgrade.html",pathLocale:"/ru/",extraFields:[]},{title:"mKCP",headers:[{level:2,title:"KcpObject",slug:"kcpobject",link:"#kcpobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]},{level:2,title:"Благодарности",slug:"благодарности",link:"#благодарности",children:[]},{level:2,title:"Улучшения протокола KCP",slug:"улучшения-протокола-kcp",link:"#улучшения-протокола-kcp",children:[{level:3,title:"Более компактный заголовок протокола",slug:"более-компактныи-заголовок-протокола",link:"#более-компактныи-заголовок-протокола",children:[]},{level:3,title:"Передача пакетов подтверждения",slug:"передача-пакетов-подтверждения",link:"#передача-пакетов-подтверждения",children:[]},{level:3,title:"Управление состоянием соединения",slug:"управление-состоянием-соединения",link:"#управление-состоянием-соединения",children:[]}]}],path:"/ru/config/transports/mkcp.html",pathLocale:"/ru/",extraFields:[]},{title:"QUIC",headers:[{level:2,title:"QuicObject",slug:"quicobject",link:"#quicobject",children:[{level:3,title:"HeaderObject",slug:"headerobject",link:"#headerobject",children:[]}]}],path:"/ru/config/transports/quic.html",pathLocale:"/ru/",extraFields:[]},{title:"SplitHTTP",headers:[{level:2,title:"SplitHttpObject",slug:"splithttpobject",link:"#splithttpobject",children:[]},{level:2,title:"Детали протокола",slug:"детали-протокола",link:"#детали-протокола",children:[]},{level:2,title:"BrowserDialer",slug:"browserdialer",link:"#browserdialer",children:[]}],path:"/ru/config/transports/splithttp.html",pathLocale:"/ru/",extraFields:[]},{title:"TCP",headers:[{level:2,title:"TcpObject",slug:"tcpobject",link:"#tcpobject",children:[{level:3,title:"NoneHeaderObject",slug:"noneheaderobject",link:"#noneheaderobject",children:[]},{level:3,title:"HttpHeaderObject",slug:"httpheaderobject",link:"#httpheaderobject",children:[]}]}],path:"/ru/config/transports/tcp.html",pathLocale:"/ru/",extraFields:[]},{title:"WebSocket",headers:[{level:2,title:"WebSocketObject",slug:"websocketobject",link:"#websocketobject",children:[]},{level:2,title:"Browser Dialer",slug:"browser-dialer",link:"#browser-dialer",children:[]}],path:"/ru/config/transports/websocket.html",pathLocale:"/ru/",extraFields:[]},{title:"编译文档",headers:[{level:2,title:"前序工作",slug:"前序工作",link:"#前序工作",children:[]},{level:2,title:"拉取 Xray 源代码",slug:"拉取-xray-源代码",link:"#拉取-xray-源代码",children:[]},{level:2,title:"构建二进制",slug:"构建二进制",link:"#构建二进制",children:[{level:3,title:"Windows(Powershell):",slug:"windows-powershell",link:"#windows-powershell",children:[]},{level:3,title:"macOS, Linux:",slug:"macos-linux",link:"#macos-linux",children:[]}]},{level:2,title:"交叉编译:",slug:"交叉编译",link:"#交叉编译",children:[]},{level:2,title:"可复现构建:",slug:"可复现构建",link:"#可复现构建",children:[]}],path:"/ru/development/intro/compile.html",pathLocale:"/ru/",extraFields:[]},{title:"设计目标",headers:[{level:2,title:"架构",slug:"架构",link:"#架构",children:[{level:3,title:"应用层",slug:"应用层",link:"#应用层",children:[]},{level:3,title:"代理层",slug:"代理层",link:"#代理层",children:[]},{level:3,title:"传输层",slug:"传输层",link:"#传输层",children:[]}]}],path:"/ru/development/intro/design.html",pathLocale:"/ru/",extraFields:[]},{title:"开发规范",headers:[{level:2,title:"基本",slug:"基本",link:"#基本",children:[{level:3,title:"版本控制",slug:"版本控制",link:"#版本控制",children:[]},{level:3,title:"分支(Branch)",slug:"分支-branch",link:"#分支-branch",children:[]},{level:3,title:"发布(Release)",slug:"发布-release",link:"#发布-release",children:[]},{level:3,title:"引用其它项目",slug:"引用其它项目",link:"#引用其它项目",children:[]}]},{level:2,title:"开发流程",slug:"开发流程",link:"#开发流程",children:[{level:3,title:"写代码之前",slug:"写代码之前",link:"#写代码之前",children:[]},{level:3,title:"修改代码",slug:"修改代码",link:"#修改代码",children:[]},{level:3,title:"Pull Request",slug:"pull-request",link:"#pull-request",children:[]},{level:3,title:"对代码的修改",slug:"对代码的修改",link:"#对代码的修改",children:[]}]},{level:2,title:"Xray 编码规范",slug:"xray-编码规范",link:"#xray-编码规范",children:[{level:3,title:"代码结构",slug:"代码结构",link:"#代码结构",children:[]},{level:3,title:"编码规范",slug:"编码规范",link:"#编码规范",children:[]}]}],path:"/ru/development/intro/guide.html",pathLocale:"/ru/",extraFields:[]},{title:"mKCP 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"数据格式",slug:"数据格式",link:"#数据格式",children:[{level:3,title:"数据包",slug:"数据包",link:"#数据包",children:[]},{level:3,title:"数据片段",slug:"数据片段",link:"#数据片段",children:[]},{level:3,title:"确认片段",slug:"确认片段",link:"#确认片段",children:[]},{level:3,title:"心跳片段",slug:"心跳片段",link:"#心跳片段",children:[]}]}],path:"/ru/development/protocols/mkcp.html",pathLocale:"/ru/",extraFields:[]},{title:"Mux.Cool 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[{level:3,title:"客户端行为",slug:"客户端行为",link:"#客户端行为",children:[]},{level:3,title:"服务器端行为",slug:"服务器端行为",link:"#服务器端行为",children:[]}]},{level:2,title:"传输格式",slug:"传输格式",link:"#传输格式",children:[{level:3,title:"帧格式",slug:"帧格式",link:"#帧格式",children:[]},{level:3,title:"元数据",slug:"元数据",link:"#元数据",children:[]},{level:3,title:"新建子连接 (New)",slug:"新建子连接-new",link:"#新建子连接-new",children:[]},{level:3,title:"保持子连接 (Keep)",slug:"保持子连接-keep",link:"#保持子连接-keep",children:[]},{level:3,title:"关闭子连接 (End)",slug:"关闭子连接-end",link:"#关闭子连接-end",children:[]},{level:3,title:"保持连接 (KeepAlive)",slug:"保持连接-keepalive",link:"#保持连接-keepalive",children:[]}]},{level:2,title:"应用",slug:"应用",link:"#应用",children:[]}],path:"/ru/development/protocols/muxcool.html",pathLocale:"/ru/",extraFields:[]},{title:"VLESS 协议",headers:[{level:2,title:"Request & Response",slug:"request-response",link:"#request-response",children:[]},{level:2,title:"ProtoBuf",slug:"protobuf",link:"#protobuf",children:[]},{level:2,title:"Schedulers Flow",slug:"schedulers-flow",link:"#schedulers-flow",children:[]},{level:2,title:"Encryption",slug:"encryption",link:"#encryption",children:[]},{level:2,title:"UDP issues",slug:"udp-issues",link:"#udp-issues",children:[]},{level:2,title:"客户端开发指引",slug:"客户端开发指引",link:"#客户端开发指引",children:[]},{level:2,title:"VLESS 分享链接标准",slug:"vless-分享链接标准",link:"#vless-分享链接标准",children:[]}],path:"/ru/development/protocols/vless.html",pathLocale:"/ru/",extraFields:[]},{title:"VMess 协议",headers:[{level:2,title:"版本",slug:"版本",link:"#版本",children:[]},{level:2,title:"依赖",slug:"依赖",link:"#依赖",children:[{level:3,title:"底层协议",slug:"底层协议",link:"#底层协议",children:[]},{level:3,title:"用户 ID",slug:"用户-id",link:"#用户-id",children:[]},{level:3,title:"函数",slug:"函数",link:"#函数",children:[]}]},{level:2,title:"通讯过程",slug:"通讯过程",link:"#通讯过程",children:[]},{level:2,title:"客户端请求",slug:"客户端请求",link:"#客户端请求",children:[{level:3,title:"认证信息",slug:"认证信息",link:"#认证信息",children:[]},{level:3,title:"指令部分",slug:"指令部分",link:"#指令部分",children:[]},{level:3,title:"数据部分",slug:"数据部分",link:"#数据部分",children:[]}]},{level:2,title:"服务器应答",slug:"服务器应答",link:"#服务器应答",children:[{level:3,title:"动态端口指令",slug:"动态端口指令",link:"#动态端口指令",children:[]}]},{level:2,title:"注释",slug:"注释",link:"#注释",children:[]}],path:"/ru/development/protocols/vmess.html",pathLocale:"/ru/",extraFields:[]},{title:"Простые разговоры о сложном",headers:[],path:"/ru/document/level-0/",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 1】 Простыми словами",headers:[{level:2,title:"1.1 Для кого эта документация?",slug:"_1-1-для-кого-эта-документация",link:"#_1-1-для-кого-эта-документация",children:[]},{level:2,title:"1.2 Для кого эта документация не предназначена?",slug:"_1-2-для-кого-эта-документация-не-предназначена",link:"#_1-2-для-кого-эта-документация-не-предназначена",children:[]},{level:2,title:"1.3 Важное замечание и другие примечания",slug:"_1-3-важное-замечание-и-другие-примечания",link:"#_1-3-важное-замечание-и-другие-примечания",children:[]},{level:2,title:"1.4 Почему самостоятельная настройка — это сложно?",slug:"_1-4-почему-самостоятельная-настроика-—-это-сложно",link:"#_1-4-почему-самостоятельная-настроика-—-это-сложно",children:[]},{level:2,title:"1.5 «Почему бы просто не пользоваться платным VPN?»",slug:"_1-5-«почему-бы-просто-не-пользоваться-платным-vpn-»",link:"#_1-5-«почему-бы-просто-не-пользоваться-платным-vpn-»",children:[]},{level:2,title:"1.6 Так стоит ли настраивать VPN самостоятельно?",slug:"_1-6-так-стоит-ли-настраивать-vpn-самостоятельно",link:"#_1-6-так-стоит-ли-настраивать-vpn-самостоятельно",children:[]},{level:2,title:"1.7 Немного лирики",slug:"_1-7-немного-лирики",link:"#_1-7-немного-лирики",children:[]},{level:2,title:"1.8 Ваш прогресс",slug:"_1-8-ваш-прогресс",link:"#_1-8-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch01-preface.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 2】 Подготовка",headers:[{level:2,title:"2.1 Приобретение VPS",slug:"_2-1-приобретение-vps",link:"#_2-1-приобретение-vps",children:[]},{level:2,title:"2.2 Выбор доменного имени",slug:"_2-2-выбор-доменного-имени",link:"#_2-2-выбор-доменного-имени",children:[]},{level:2,title:"2.3 Необходимое программное обеспечение",slug:"_2-3-необходимое-программное-обеспечение",link:"#_2-3-необходимое-программное-обеспечение",children:[]},{level:2,title:"2.4 Ваш прогресс",slug:"_2-4-ваш-прогресс",link:"#_2-4-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch02-preparation.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 3】 Удалённое подключение",headers:[{level:2,title:"3.1 Удалённое подключение к VPS (PuTTY)",slug:"_3-1-удаленное-подключение-к-vps-putty",link:"#_3-1-удаленное-подключение-к-vps-putty",children:[]},{level:2,title:"3.2 Успешное подключение по SSH! Знакомство с командной строкой!",slug:"_3-2-успешное-подключение-по-ssh-знакомство-с-команднои-строкои",link:"#_3-2-успешное-подключение-по-ssh-знакомство-с-команднои-строкои",children:[]},{level:2,title:"3.3 Первое обновление программного обеспечения Linux!",slug:"_3-3-первое-обновление-программного-обеспечения-linux",link:"#_3-3-первое-обновление-программного-обеспечения-linux",children:[]},{level:2,title:"3.4 Ваш прогресс",slug:"_3-4-ваш-прогресс",link:"#_3-4-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch03-ssh.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 4】 Обеспечение безопасности",headers:[{level:2,title:"4.1 Зачем нужна безопасность?",slug:"_4-1-зачем-нужна-безопасность",link:"#_4-1-зачем-нужна-безопасность",children:[]},{level:2,title:"4.2 Какие именно риски существуют?",slug:"_4-2-какие-именно-риски-существуют",link:"#_4-2-какие-именно-риски-существуют",children:[]},{level:2,title:"4.3 Какие меры безопасности нужно предпринять?",slug:"_4-3-какие-меры-безопасности-нужно-предпринять",link:"#_4-3-какие-меры-безопасности-нужно-предпринять",children:[]},{level:2,title:"4.4 Изменение порта SSH",slug:"_4-4-изменение-порта-ssh",link:"#_4-4-изменение-порта-ssh",children:[]},{level:2,title:"4.5 Создание нового пользователя",slug:"_4-5-создание-нового-пользователя",link:"#_4-5-создание-нового-пользователя",children:[]},{level:2,title:"4.6 Запрет удалённого подключения по SSH для пользователя root",slug:"_4-6-запрет-удаленного-подключения-по-ssh-для-пользователя-root",link:"#_4-6-запрет-удаленного-подключения-по-ssh-для-пользователя-root",children:[]},{level:2,title:"4.7 Настройка аутентификации по SSH-ключам и запрет аутентификации по паролю",slug:"_4-7-настроика-аутентификации-по-ssh-ключам-и-запрет-аутентификации-по-паролю",link:"#_4-7-настроика-аутентификации-по-ssh-ключам-и-запрет-аутентификации-по-паролю",children:[]},{level:2,title:"4.8 Ваш прогресс",slug:"_4-8-ваш-прогресс",link:"#_4-8-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch04-security.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 5】 Создание веб-сайта",headers:[{level:2,title:"5.1 Зачем нужен веб-сайт?",slug:"_5-1-зачем-нужен-веб-саит",link:"#_5-1-зачем-нужен-веб-саит",children:[]},{level:2,title:"5.2 Подключение к VPS и установка Nginx",slug:"_5-2-подключение-к-vps-и-установка-nginx",link:"#_5-2-подключение-к-vps-и-установка-nginx",children:[]},{level:2,title:"5.3 Создание простой веб-страницы",slug:"_5-3-создание-простои-веб-страницы",link:"#_5-3-создание-простои-веб-страницы",children:[]},{level:2,title:"5.4 Распространённые ошибки",slug:"_5-4-распространенные-ошибки",link:"#_5-4-распространенные-ошибки",children:[]},{level:2,title:"5.5 Ваш прогресс",slug:"_5-5-ваш-прогресс",link:"#_5-5-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch05-webpage.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 6】 Управление сертификатами",headers:[{level:2,title:"6.1 Получение SSL-сертификата",slug:"_6-1-получение-ssl-сертификата",link:"#_6-1-получение-ssl-сертификата",children:[]},{level:2,title:"6.2 Установка acme.sh",slug:"_6-2-установка-acme-sh",link:"#_6-2-установка-acme-sh",children:[]},{level:2,title:"6.3 Тестовый запрос сертификата",slug:"_6-3-тестовыи-запрос-сертификата",link:"#_6-3-тестовыи-запрос-сертификата",children:[]},{level:2,title:"6.4 Запрос настоящего сертификата",slug:"_6-4-запрос-настоящего-сертификата",link:"#_6-4-запрос-настоящего-сертификата",children:[]},{level:2,title:"6.5 Установка сертификата",slug:"_6-5-установка-сертификата",link:"#_6-5-установка-сертификата",children:[]},{level:2,title:"6.6 Ваш прогресс",slug:"_6-6-ваш-прогресс",link:"#_6-6-ваш-прогресс",children:[]}],path:"/ru/document/level-0/ch06-certificates.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 7】Настройка Xray на сервере",headers:[{level:2,title:"7.1 Познать многое, усвоить нужное; копить постепенно, тратить осмотрительно",slug:"_7-1-познать-многое-усвоить-нужное-копить-постепенно-тратить-осмотрительно",link:"#_7-1-познать-многое-усвоить-нужное-копить-постепенно-тратить-осмотрительно",children:[]},{level:2,title:"7.2 Установка Xray",slug:"_7-2-установка-xray",link:"#_7-2-установка-xray",children:[]},{level:2,title:"7.3 Установка TLS-сертификата для Xray",slug:"_7-3-установка-tls-сертификата-для-xray",link:"#_7-3-установка-tls-сертификата-для-xray",children:[]},{level:2,title:"7.4 Настройка Xray",slug:"_7-4-настроика-xray",link:"#_7-4-настроика-xray",children:[]},{level:2,title:"7.5 Запуск Xray! (и проверка состояния сервиса)",slug:"_7-5-запуск-xray-и-проверка-состояния-сервиса",link:"#_7-5-запуск-xray-и-проверка-состояния-сервиса",children:[]},{level:2,title:"7.6 Базовое управление сервисами с помощью systemd",slug:"_7-6-базовое-управление-сервисами-с-помощью-systemd",link:"#_7-6-базовое-управление-сервисами-с-помощью-systemd",children:[]},{level:2,title:"7.7 Оптимизация сервера: включение BBR",slug:"_7-7-оптимизация-сервера-включение-bbr",link:"#_7-7-оптимизация-сервера-включение-bbr",children:[]},{level:2,title:"7.8 Оптимизация сервера: автоматическое перенаправление HTTP на HTTPS",slug:"_7-8-оптимизация-сервера-автоматическое-перенаправление-http-на-https",link:"#_7-8-оптимизация-сервера-автоматическое-перенаправление-http-на-https",children:[]},{level:2,title:"7.9 Оптимизация сервера: более гибкая настройка перенаправления",slug:"_7-9-оптимизация-сервера-более-гибкая-настроика-перенаправления",link:"#_7-9-оптимизация-сервера-более-гибкая-настроика-перенаправления",children:[]},{level:2,title:"7.10 Ваши успехи",slug:"_7-10-ваши-успехи",link:"#_7-10-ваши-успехи",children:[]},{level:2,title:"7.11 Важные исправления",slug:"_7-11-важные-исправления",link:"#_7-11-важные-исправления",children:[]}],path:"/ru/document/level-0/ch07-xray-server.html",pathLocale:"/ru/",extraFields:[]},{title:"【Глава 8】Настройка Xray на клиенте",headers:[{level:2,title:"8.1 Как работает Xray: краткое описание",slug:"_8-1-как-работает-xray-краткое-описание",link:"#_8-1-как-работает-xray-краткое-описание",children:[]},{level:2,title:"8.2 Подключение клиента к серверу",slug:"_8-2-подключение-клиента-к-серверу",link:"#_8-2-подключение-клиента-к-серверу",children:[]},{level:2,title:"8.3 Дополнительное задание 1: настройка xray-core на ПК вручную",slug:"_8-3-дополнительное-задание-1-настроика-xray-core-на-пк-вручную",link:"#_8-3-дополнительное-задание-1-настроика-xray-core-на-пк-вручную",children:[]},{level:2,title:"8.4 Дополнительное задание 2: запуск xray-core на ПК",slug:"_8-4-дополнительное-задание-2-запуск-xray-core-на-пк",link:"#_8-4-дополнительное-задание-2-запуск-xray-core-на-пк",children:[]},{level:2,title:"8.5 Дополнительное задание 3: автозапуск xray-core на ПК",slug:"_8-5-дополнительное-задание-3-автозапуск-xray-core-на-пк",link:"#_8-5-дополнительное-задание-3-автозапуск-xray-core-на-пк",children:[]},{level:2,title:"8.6 Финишная прямая!",slug:"_8-6-финишная-прямая",link:"#_8-6-финишная-прямая",children:[]},{level:2,title:"8.7 В бесконечность и далее!",slug:"_8-7-в-бесконечность-и-далее",link:"#_8-7-в-бесконечность-и-далее",children:[]}],path:"/ru/document/level-0/ch08-xray-clients.html",pathLocale:"/ru/",extraFields:[]},{title:"[Глава 9] Приложение",headers:[{level:2,title:"1. Индекс основных команд Linux для начинающих",slug:"_1-индекс-основных-команд-linux-для-начинающих",link:"#_1-индекс-основных-команд-linux-для-начинающих",children:[]},{level:2,title:"2. Индекс важных конфигурационных файлов Linux",slug:"_2-индекс-важных-конфигурационных-фаилов-linux",link:"#_2-индекс-важных-конфигурационных-фаилов-linux",children:[]},{level:2,title:"3. Индекс важных файлов Xray",slug:"_3-индекс-важных-фаилов-xray",link:"#_3-индекс-важных-фаилов-xray",children:[]}],path:"/ru/document/level-0/ch09-appendix.html",pathLocale:"/ru/",extraFields:[]},{title:"Советы для начинающих",headers:[],path:"/ru/document/level-1/",pathLocale:"/ru/",extraFields:[]},{title:"Обзор функции Fallback",headers:[{level:2,title:"1. Что такое Fallback в простых словах",slug:"_1-что-такое-fallback-в-простых-словах",link:"#_1-что-такое-fallback-в-простых-словах",children:[]},{level:2,title:"2. Что такое Fallback (ЧТО, КАК v1)",slug:"_2-что-такое-fallback-что-как-v1",link:"#_2-что-такое-fallback-что-как-v1",children:[]},{level:2,title:"3. Зачем нужен Fallback (ЗАЧЕМ v1)",slug:"_3-зачем-нужен-fallback-зачем-v1",link:"#_3-зачем-нужен-fallback-зачем-v1",children:[]},{level:2,title:"4. Полное понимание Fallback (ЧТО, ЗАЧЕМ, КАК v2)",slug:"_4-полное-понимание-fallback-что-зачем-как-v2",link:"#_4-полное-понимание-fallback-что-зачем-как-v2",children:[]},{level:2,title:"5. Пример и описание многоуровневого fallback",slug:"_5-пример-и-описание-многоуровневого-fallback",link:"#_5-пример-и-описание-многоуровневого-fallback",children:[{level:3,title:"5.1 Сначала скопируем фрагмент конфигурации прослушивания порта 443 на стороне сервера:",slug:"_5-1-сначала-скопируем-фрагмент-конфигурации-прослушивания-порта-443-на-стороне-сервера",link:"#_5-1-сначала-скопируем-фрагмент-конфигурации-прослушивания-порта-443-на-стороне-сервера",children:[]},{level:3,title:"5.2 Фрагмент конфигурации, отвечающий за обработку fallback:",slug:"_5-2-фрагмент-конфигурации-отвечающии-за-обработку-fallback",link:"#_5-2-фрагмент-конфигурации-отвечающии-за-обработку-fallback",children:[]}]},{level:2,title:"6. Заключение",slug:"_6-заключение",link:"#_6-заключение",children:[]},{level:2,title:"7. Дополнительное задание",slug:"_7-дополнительное-задание",link:"#_7-дополнительное-задание",children:[]}],path:"/ru/document/level-1/fallbacks-lv1.html",pathLocale:"/ru/",extraFields:[]},{title:"SNI Fallback",headers:[{level:2,title:"Сценарии использования",slug:"сценарии-использования",link:"#сценарии-использования",children:[]},{level:2,title:"Что такое SNI",slug:"что-такое-sni",link:"#что-такое-sni",children:[]},{level:2,title:"Идея",slug:"идея",link:"#идея",children:[]},{level:2,title:"Добавление DNS-записей",slug:"добавление-dns-записеи",link:"#добавление-dns-записеи",children:[]},{level:2,title:"Запрос TLS-сертификата",slug:"запрос-tls-сертификата",link:"#запрос-tls-сертификата",children:[]},{level:2,title:"Конфигурация Xray",slug:"конфигурация-xray",link:"#конфигурация-xray",children:[]},{level:2,title:"Конфигурация Nginx",slug:"конфигурация-nginx",link:"#конфигурация-nginx",children:[]},{level:2,title:"Конфигурация Caddy",slug:"конфигурация-caddy",link:"#конфигурация-caddy",children:[]},{level:2,title:"Ссылки",slug:"ссылки",link:"#ссылки",children:[]},{level:2,title:"Примечания",slug:"примечания",link:"#примечания",children:[]}],path:"/ru/document/level-1/fallbacks-with-sni.html",pathLocale:"/ru/",extraFields:[]},{title:"Краткий обзор функции маршрутизации (routing) (часть 1)",headers:[{level:2,title:"1. Знакомство с тремя братьями-маршрутизаторами",slug:"_1-знакомство-с-тремя-братьями-маршрутизаторами",link:"#_1-знакомство-с-тремя-братьями-маршрутизаторами",children:[]},{level:2,title:'2. Основы: "Братья едины"',slug:"_2-основы-братья-едины",link:"#_2-основы-братья-едины",children:[{level:3,title:"2.1 Входящий трафик",slug:"_2-1-входящии-трафик",link:"#_2-1-входящии-трафик",children:[]},{level:3,title:"2.2 Исходящий трафик",slug:"_2-2-исходящии-трафик",link:"#_2-2-исходящии-трафик",children:[]},{level:3,title:"2.3 Маршрутизация",slug:"_2-3-маршрутизация",link:"#_2-3-маршрутизация",children:[]},{level:3,title:"2.4 Анализ параметров конфигурации маршрутизации: критерии фильтрации трафика",slug:"_2-4-анализ-параметров-конфигурации-маршрутизации-критерии-фильтрации-трафика",link:"#_2-4-анализ-параметров-конфигурации-маршрутизации-критерии-фильтрации-трафика",children:[]}]},{level:2,title:'3. Первые шаги: "Разделение мира на три части" - "Разделение по домену"',slug:"_3-первые-шаги-разделение-мира-на-три-части-разделение-по-домену",link:"#_3-первые-шаги-разделение-мира-на-три-части-разделение-по-домену",children:[{level:3,title:"3.1 Входящий трафик",slug:"_3-1-входящии-трафик",link:"#_3-1-входящии-трафик",children:[]},{level:3,title:"3.2 Исходящий трафик",slug:"_3-2-исходящии-трафик",link:"#_3-2-исходящии-трафик",children:[]},{level:3,title:"3.3 Маршрутизация",slug:"_3-3-маршрутизация",link:"#_3-3-маршрутизация",children:[]},{level:3,title:"3.4 Краткий обзор файла доменов: geosite.dat",slug:"_3-4-краткии-обзор-фаила-доменов-geosite-dat",link:"#_3-4-краткии-обзор-фаила-доменов-geosite-dat",children:[]},{level:3,title:"3.5 Так что же такое geosite.dat? Разве у нас нет GFWList?",slug:"_3-5-так-что-же-такое-geosite-dat-разве-у-нас-нет-gfwlist",link:"#_3-5-так-что-же-такое-geosite-dat-разве-у-нас-нет-gfwlist",children:[]},{level:3,title:"3.6 Секретное оружие: скрытое правило маршрутизации",slug:"_3-6-секретное-оружие-скрытое-правило-маршрутизации",link:"#_3-6-секретное-оружие-скрытое-правило-маршрутизации",children:[]},{level:3,title:'3.7 Снова смотрим на карту "трех царств"',slug:"_3-7-снова-смотрим-на-карту-трех-царств",link:"#_3-7-снова-смотрим-на-карту-трех-царств",children:[]}]},{level:2,title:'4. "Разделение мира на три части" - "Битва Вэй и Шу"',slug:"_4-разделение-мира-на-три-части-битва-вэи-и-шу",link:"#_4-разделение-мира-на-три-части-битва-вэи-и-шу",children:[]},{level:2,title:"5. Покорение новых высот - Различные условия сопоставления маршрутов",slug:"_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",link:"#_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",children:[]}],path:"/ru/document/level-1/routing-lv1-part1.html",pathLocale:"/ru/",extraFields:[]},{title:"Краткий обзор функции маршрутизации (routing) (часть 2)",headers:[{level:2,title:"5. Покорение новых высот - Различные условия сопоставления маршрутов",slug:"_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",link:"#_5-покорение-новых-высот-различные-условия-сопоставления-маршрутов",children:[{level:3,title:"5.1 Разделение по определенному домену: [domain], [full] и т. д.",slug:"_5-1-разделение-по-определенному-домену-domain-full-и-т-д",link:"#_5-1-разделение-по-определенному-домену-domain-full-и-т-д",children:[]},{level:3,title:"5.2 Разделение по IP-адресам из файла: geoip.dat",slug:"_5-2-разделение-по-ip-адресам-из-фаила-geoip-dat",link:"#_5-2-разделение-по-ip-адресам-из-фаила-geoip-dat",children:[]},{level:3,title:"5.3 Разделение по определенному IP-адресу",slug:"_5-3-разделение-по-определенному-ip-адресу",link:"#_5-3-разделение-по-определенному-ip-адресу",children:[]},{level:3,title:"5.4 Разделение по типу протокола: [protocol] и т. д.",slug:"_5-4-разделение-по-типу-протокола-protocol-и-т-д",link:"#_5-4-разделение-по-типу-протокола-protocol-и-т-д",children:[]},{level:3,title:"5.5 Разделение по другим критериям",slug:"_5-5-разделение-по-другим-критериям",link:"#_5-5-разделение-по-другим-критериям",children:[]}]},{level:2,title:'6. "Начало новой эры": обзор правил маршрутизации',slug:"_6-начало-новои-эры-обзор-правил-маршрутизации",link:"#_6-начало-новои-эры-обзор-правил-маршрутизации",children:[]},{level:2,title:"7. Распространенные ошибки в конфигурации маршрутизации",slug:"_7-распространенные-ошибки-в-конфигурации-маршрутизации",link:"#_7-распространенные-ошибки-в-конфигурации-маршрутизации",children:[{level:3,title:"7.1 Неправильный пример",slug:"_7-1-неправильныи-пример",link:"#_7-1-неправильныи-пример",children:[]},{level:3,title:"7.2 Правильный пример",slug:"_7-2-правильныи-пример",link:"#_7-2-правильныи-пример",children:[]}]},{level:2,title:"8. Скрытые пути",slug:"_8-скрытые-пути",link:"#_8-скрытые-пути",children:[{level:3,title:'8.1 Стратегия домена: "AsIs"',slug:"_8-1-стратегия-домена-asis",link:"#_8-1-стратегия-домена-asis",children:[]},{level:3,title:'8.2 Стратегия домена: "IPIfNonMatch"',slug:"_8-2-стратегия-домена-ipifnonmatch",link:"#_8-2-стратегия-домена-ipifnonmatch",children:[]},{level:3,title:'8.3 Стратегия домена: "IPOnDemand"',slug:"_8-3-стратегия-домена-ipondemand",link:"#_8-3-стратегия-домена-ipondemand",children:[]}]},{level:2,title:"9. Задание для размышления",slug:"_9-задание-для-размышления",link:"#_9-задание-для-размышления",children:[]},{level:2,title:"10. Заключение",slug:"_10-заключение",link:"#_10-заключение",children:[]},{level:2,title:"11. Примечания",slug:"_11-примечания",link:"#_11-примечания",children:[]}],path:"/ru/document/level-1/routing-lv1-part2.html",pathLocale:"/ru/",extraFields:[]},{title:"Режимы работы Xray",headers:[{level:2,title:"Режим одного сервера",slug:"режим-одного-сервера",link:"#режим-одного-сервера",children:[]},{level:2,title:"Режим моста",slug:"режим-моста",link:"#режим-моста",children:[]},{level:2,title:"Принцип работы",slug:"принцип-работы",link:"#принцип-работы",children:[]}],path:"/ru/document/level-1/work.html",pathLocale:"/ru/",extraFields:[]},{title:"Продвинутая документация",headers:[],path:"/ru/document/level-2/",pathLocale:"/ru/",extraFields:[]},{title:"GID Прозрачное проксирование",headers:[{level:2,title:"Идея",slug:"идея",link:"#идея",children:[]},{level:2,title:"Настройка",slug:"настроика",link:"#настроика",children:[{level:3,title:"1. Предварительная подготовка",slug:"_1-предварительная-подготовка",link:"#_1-предварительная-подготовка",children:[]},{level:3,title:"2. Добавление пользователя (пропустите для Android)",slug:"_2-добавление-пользователя-пропустите-для-android",link:"#_2-добавление-пользователя-пропустите-для-android",children:[]},{level:3,title:"3. Настройка запуска Xray и правил iptables",slug:"_3-настроика-запуска-xray-и-правил-iptables",link:"#_3-настроика-запуска-xray-и-правил-iptables",children:[]}]},{level:2,title:"Ниже приведен пример полной настройки глобального проксирования с использованием TPROXY",slug:"ниже-приведен-пример-полнои-настроики-глобального-проксирования-с-использованием-tproxy",link:"#ниже-приведен-пример-полнои-настроики-глобального-проксирования-с-использованием-tproxy",children:[{level:3,title:"1. Выполните предварительную подготовку и добавление пользователя.",slug:"_1-выполните-предварительную-подготовку-и-добавление-пользователя",link:"#_1-выполните-предварительную-подготовку-и-добавление-пользователя",children:[]},{level:3,title:"2. Подготовьте конфигурационный файл Xray.",slug:"_2-подготовьте-конфигурационныи-фаил-xray",link:"#_2-подготовьте-конфигурационныи-фаил-xray",children:[]},{level:3,title:"3. Настройка максимального количества открытых файлов и запуск клиента Xray",slug:"_3-настроика-максимального-количества-открытых-фаилов-и-запуск-клиента-xray",link:"#_3-настроика-максимального-количества-открытых-фаилов-и-запуск-клиента-xray",children:[]},{level:3,title:"4. Настройка правил iptables",slug:"_4-настроика-правил-iptables",link:"#_4-настроика-правил-iptables",children:[]}]}],path:"/ru/document/level-2/iptables_gid.html",pathLocale:"/ru/",extraFields:[]},{title:"Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков",headers:[{level:2,title:"Компиляция nginx с поддержкой --with-stream",slug:"компиляция-nginx-с-поддержкои-with-stream",link:"#компиляция-nginx-с-поддержкои-with-stream",children:[]},{level:2,title:"Настройка nginx",slug:"настроика-nginx",link:"#настроика-nginx",children:[]},{level:2,title:"Настройка Xray",slug:"настроика-xray",link:"#настроика-xray",children:[]},{level:2,title:"Запуск сервисов на клиенте и сервере",slug:"запуск-сервисов-на-клиенте-и-сервере",link:"#запуск-сервисов-на-клиенте-и-сервере",children:[]},{level:2,title:"Завершение",slug:"завершение",link:"#завершение",children:[]},{level:2,title:"HTTPS-туннель",slug:"https-туннель",link:"#https-туннель",children:[{level:3,title:"Конфигурация haproxy_client (удалите комментарии перед запуском):",slug:"конфигурация-haproxy-client-удалите-комментарии-перед-запуском",link:"#конфигурация-haproxy-client-удалите-комментарии-перед-запуском",children:[]},{level:3,title:"Конфигурация haproxy_server (удалите комментарии перед запуском):",slug:"конфигурация-haproxy-server-удалите-комментарии-перед-запуском",link:"#конфигурация-haproxy-server-удалите-комментарии-перед-запуском",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-1",link:"#настроика-xray-1",children:[]}]},{level:2,title:"WebSocket over HTTP/2",slug:"websocket-over-http-2",link:"#websocket-over-http-2",children:[{level:3,title:"Конфигурация haproxy_client:",slug:"конфигурация-haproxy-client",link:"#конфигурация-haproxy-client",children:[]},{level:3,title:"Конфигурация haproxy_server:",slug:"конфигурация-haproxy-server",link:"#конфигурация-haproxy-server",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-2",link:"#настроика-xray-2",children:[]}]},{level:2,title:"gRPC over HTTP/2",slug:"grpc-over-http-2",link:"#grpc-over-http-2",children:[{level:3,title:"Конфигурация haproxy_client:",slug:"конфигурация-haproxy-client-1",link:"#конфигурация-haproxy-client-1",children:[]},{level:3,title:"Конфигурация haproxy_server:",slug:"конфигурация-haproxy-server-1",link:"#конфигурация-haproxy-server-1",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-3",link:"#настроика-xray-3",children:[]},{level:3,title:"Конфигурация haproxy_client:",slug:"конфигурация-haproxy-client-2",link:"#конфигурация-haproxy-client-2",children:[]},{level:3,title:"Конфигурация haproxy_server:",slug:"конфигурация-haproxy-server-2",link:"#конфигурация-haproxy-server-2",children:[]},{level:3,title:"Настройка Xray",slug:"настроика-xray-4",link:"#настроика-xray-4",children:[]}]}],path:"/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html",pathLocale:"/ru/",extraFields:[]},{title:"Перенаправление исходящего трафика",headers:[{level:2,title:"Введение",slug:"введение",link:"#введение",children:[]},{level:2,title:"1. Установите прокси-сервер или VPN-клиент (например, Wireguard, IPsec и т.д.)",slug:"_1-установите-прокси-сервер-или-vpn-клиент-например-wireguard-ipsec-и-т-д",link:"#_1-установите-прокси-сервер-или-vpn-клиент-например-wireguard-ipsec-и-т-д",children:[]},{level:2,title:"2. Отредактируйте конфигурационный файл VPN (на примере WireGuard)",slug:"_2-отредактируите-конфигурационныи-фаил-vpn-на-примере-wireguard",link:"#_2-отредактируите-конфигурационныи-фаил-vpn-на-примере-wireguard",children:[]},{level:2,title:"3. Активируйте сетевой интерфейс WireGuard.",slug:"_3-активируите-сетевои-интерфеис-wireguard",link:"#_3-активируите-сетевои-интерфеис-wireguard",children:[]},{level:2,title:"4. Измените конфигурационный файл Xray-core.",slug:"_4-измените-конфигурационныи-фаил-xray-core",link:"#_4-измените-конфигурационныи-фаил-xray-core",children:[]},{level:2,title:"5. Настройка системы",slug:"_5-настроика-системы",link:"#_5-настроика-системы",children:[]},{level:2,title:"6. Завершение настройки WireGuard",slug:"_6-завершение-настроики-wireguard",link:"#_6-завершение-настроики-wireguard",children:[]},{level:2,title:"Послесловие",slug:"послесловие",link:"#послесловие",children:[]},{level:2,title:"Благодарности",slug:"благодарности",link:"#благодарности",children:[]}],path:"/ru/document/level-2/redirect.html",pathLocale:"/ru/",extraFields:[]},{title:"Прозрачное проксирование TProxy",headers:[{level:2,title:"Перед началом работы",slug:"перед-началом-работы",link:"#перед-началом-работы",children:[]},{level:2,title:"Настройка Xray",slug:"настроика-xray",link:"#настроика-xray",children:[]},{level:2,title:"Настройка маршрутизации по политике",slug:"настроика-маршрутизации-по-политике",link:"#настроика-маршрутизации-по-политике",children:[]},{level:2,title:"Настройка Netfilter",slug:"настроика-netfilter",link:"#настроика-netfilter",children:[]},{level:2,title:"Настройка автозагрузки и сохранения конфигурации",slug:"настроика-автозагрузки-и-сохранения-конфигурации",link:"#настроика-автозагрузки-и-сохранения-конфигурации",children:[]}],path:"/ru/document/level-2/tproxy.html",pathLocale:"/ru/",extraFields:[]},{title:"Прозрачное проксирование TProxy (ipv4 и ipv6)",headers:[{level:2,title:"Настройка Xray",slug:"настроика-xray",link:"#настроика-xray",children:[{level:3,title:"Конфигурация клиента",slug:"конфигурация-клиента",link:"#конфигурация-клиента",children:[]},{level:3,title:"Конфигурация сервера",slug:"конфигурация-сервера",link:"#конфигурация-сервера",children:[]}]},{level:2,title:"Настройка Netfilter",slug:"настроика-netfilter",link:"#настроика-netfilter",children:[{level:3,title:"Настройка маршрутизации по политике",slug:"настроика-маршрутизации-по-политике",link:"#настроика-маршрутизации-по-политике",children:[]},{level:3,title:"Использование iptables",slug:"использование-iptables",link:"#использование-iptables",children:[]},{level:3,title:"Использование nftables",slug:"использование-nftables",link:"#использование-nftables",children:[]},{level:3,title:"Автоматический запуск конфигурации Netfilter при загрузке",slug:"автоматическии-запуск-конфигурации-netfilter-при-загрузке",link:"#автоматическии-запуск-конфигурации-netfilter-при-загрузке",children:[]}]},{level:2,title:"Настройка доступа к интернету на устройствах локальной сети",slug:"настроика-доступа-к-интернету-на-устроиствах-локальнои-сети",link:"#настроика-доступа-к-интернету-на-устроиствах-локальнои-сети",children:[{level:3,title:"Метод 1",slug:"метод-1",link:"#метод-1",children:[]},{level:3,title:"Метод 2",slug:"метод-2",link:"#метод-2",children:[]}]},{level:2,title:"Результаты",slug:"результаты",link:"#результаты",children:[]},{level:2,title:"Заключение",slug:"заключение",link:"#заключение",children:[]}],path:"/ru/document/level-2/tproxy_ipv4_and_ipv6.html",pathLocale:"/ru/",extraFields:[]},{title:"Статистика трафика",headers:[{level:2,title:"Просмотр статистики трафика",slug:"просмотр-статистики-трафика",link:"#просмотр-статистики-трафика",children:[]},{level:2,title:"Обработка статистики трафика",slug:"обработка-статистики-трафика",link:"#обработка-статистики-трафика",children:[]}],path:"/ru/document/level-2/traffic_stats.html",pathLocale:"/ru/",extraFields:[]},{title:"Повышение безопасности проксирования с помощью Cloudflare Warp",headers:[{level:2,title:"Создание аккаунта Warp",slug:"создание-аккаунта-warp",link:"#создание-аккаунта-warp",children:[{level:3,title:"Спасибо Cloudflare за содействие свободному интернету! Теперь вы можете бесплатно пользоваться услугами Warp. При подключении автоматически выбирается ближайший сервер.",slug:"спасибо-cloudflare-за-содеиствие-свободному-интернету-теперь-вы-можете-бесплатно-пользоваться-услугами-warp-при-подключении-автоматически-выбирается-ближаишии-сервер",link:"#спасибо-cloudflare-за-содеиствие-свободному-интернету-теперь-вы-можете-бесплатно-пользоваться-услугами-warp-при-подключении-автоматически-выбирается-ближаишии-сервер",children:[]}]},{level:2,title:"Перенаправление трафика в Китай через Warp на сервере",slug:"перенаправление-трафика-в-китаи-через-warp-на-сервере",link:"#перенаправление-трафика-в-китаи-через-warp-на-сервере",children:[]},{level:2,title:"Использование Warp в качестве прокси-сервера в цепочке на клиенте",slug:"использование-warp-в-качестве-прокси-сервера-в-цепочке-на-клиенте",link:"#использование-warp-в-качестве-прокси-сервера-в-цепочке-на-клиенте",children:[]}],path:"/ru/document/level-2/warp.html",pathLocale:"/ru/",extraFields:[]},{title:"透明代理入门",headers:[{level:2,title:"什么是透明代理",slug:"什么是透明代理",link:"#什么是透明代理",children:[]},{level:2,title:"透明代理的实现",slug:"透明代理的实现",link:"#透明代理的实现",children:[{level:3,title:"tun2socks",slug:"tun2socks",link:"#tun2socks",children:[]},{level:3,title:"iptables/nftables",slug:"iptables-nftables",link:"#iptables-nftables",children:[]}]},{level:2,title:"iptables 实现透明代理原理",slug:"iptables-实现透明代理原理",link:"#iptables-实现透明代理原理",children:[]},{level:2,title:"透明代理难在哪里",slug:"透明代理难在哪里",link:"#透明代理难在哪里",children:[]},{level:2,title:"从零开始一步步实现基于 iptables-tproxy 的透明代理",slug:"从零开始一步步实现基于-iptables-tproxy-的透明代理",link:"#从零开始一步步实现基于-iptables-tproxy-的透明代理",children:[{level:3,title:"在开始之前,你需要有一定的基础知识:",slug:"在开始之前-你需要有一定的基础知识",link:"#在开始之前-你需要有一定的基础知识",children:[]},{level:3,title:"前期准备工作",slug:"前期准备工作",link:"#前期准备工作",children:[]},{level:3,title:"首先,我们先试试做到第一阶段",slug:"首先-我们先试试做到第一阶段",link:"#首先-我们先试试做到第一阶段",children:[]},{level:3,title:"第二阶段",slug:"第二阶段",link:"#第二阶段",children:[]},{level:3,title:"第三阶段",slug:"第三阶段",link:"#第三阶段",children:[]},{level:3,title:"第四阶段",slug:"第四阶段",link:"#第四阶段",children:[]},{level:3,title:"代理 ipv6",slug:"代理-ipv6",link:"#代理-ipv6",children:[]}]}],path:"/en/document/level-2/transparent_proxy/transparent_proxy.html",pathLocale:"/en/",extraFields:[]},{title:"Другие замечания по прозрачному проксированию с помощью iptables",headers:[{level:2,title:"Погружение в прозрачное проксирование",slug:"погружение-в-прозрачное-проксирование",link:"#погружение-в-прозрачное-проксирование",children:[{level:3,title:"Что такое прозрачное проксирование?",slug:"что-такое-прозрачное-проксирование",link:"#что-такое-прозрачное-проксирование",children:[]},{level:3,title:"Реализация прозрачного проксирования",slug:"реализация-прозрачного-проксирования",link:"#реализация-прозрачного-проксирования",children:[]},{level:3,title:"tun2socks",slug:"tun2socks",link:"#tun2socks",children:[]},{level:3,title:"iptables/nftables",slug:"iptables-nftables",link:"#iptables-nftables",children:[]}]},{level:2,title:"Принцип реализации прозрачного проксирования с помощью iptables",slug:"принцип-реализации-прозрачного-проксирования-с-помощью-iptables",link:"#принцип-реализации-прозрачного-проксирования-с-помощью-iptables",children:[]},{level:2,title:"В чем сложность прозрачного проксирования?",slug:"в-чем-сложность-прозрачного-проксирования",link:"#в-чем-сложность-прозрачного-проксирования",children:[]},{level:2,title:"Пошаговая реализация прозрачного проксирования на основе iptables-tproxy с нуля",slug:"пошаговая-реализация-прозрачного-проксирования-на-основе-iptables-tproxy-с-нуля",link:"#пошаговая-реализация-прозрачного-проксирования-на-основе-iptables-tproxy-с-нуля",children:[{level:3,title:"Прежде чем начать, вам необходимо иметь базовые знания:",slug:"прежде-чем-начать-вам-необходимо-иметь-базовые-знания",link:"#прежде-чем-начать-вам-необходимо-иметь-базовые-знания",children:[]},{level:3,title:"Предварительная подготовка",slug:"предварительная-подготовка",link:"#предварительная-подготовка",children:[]},{level:3,title:"Сначала давайте попробуем достичь первого этапа",slug:"сначала-даваите-попробуем-достичь-первого-этапа",link:"#сначала-даваите-попробуем-достичь-первого-этапа",children:[]},{level:3,title:"Второй этап",slug:"второи-этап",link:"#второи-этап",children:[]},{level:3,title:"Третий этап",slug:"третии-этап",link:"#третии-этап",children:[]},{level:3,title:"Четвертый этап",slug:"четвертыи-этап",link:"#четвертыи-этап",children:[]},{level:3,title:"Проксирование IPv6",slug:"проксирование-ipv6",link:"#проксирование-ipv6",children:[]}]}],path:"/ru/document/level-2/transparent_proxy/transparent_proxy.html",pathLocale:"/ru/",extraFields:[]},{title:"",headers:[],path:"/404.html",pathLocale:"/",extraFields:[]},{title:"连接观测",headers:[{level:2,title:"ObservatoryObject",slug:"observatoryobject",link:"#observatoryobject",children:[]},{level:2,title:"BurstObservatoryObject",slug:"burstobservatoryobject",link:"#burstobservatoryobject",children:[{level:3,title:"PingConfigObject",slug:"pingconfigobject",link:"#pingconfigobject",children:[]}]}],path:"/en/config/observatory.html",pathLocale:"/en/",extraFields:[]}],Jf=pe(Qf),Zf=()=>Jf,ep=({searchIndex:e,routeLocale:t,query:l,maxSuggestions:n})=>{const i=C(()=>e.value.filter(r=>r.pathLocale===t.value));return C(()=>{const r=l.value.trim().toLowerCase();if(!r)return[];const o=[],c=(a,u)=>{fo(r,[u.title])&&o.push({link:`${a.path}#${u.slug}`,title:a.title,header:u.title});for(const d of u.children){if(o.length>=n.value)return;c(a,d)}};for(const a of i.value){if(o.length>=n.value)break;if(fo(r,[a.title,...a.extraFields])){o.push({link:a.path,title:a.title});continue}for(const u of a.headers){if(o.length>=n.value)break;c(a,u)}}return o})},tp=e=>{const t=pe(0);return{focusIndex:t,focusNext:()=>{t.value{t.value>0?t.value-=1:t.value=e.value.length-1}}},lp=_e({name:"SearchBox",props:{locales:{type:Object,required:!1,default:()=>({})},hotKeys:{type:Array,required:!1,default:()=>[]},maxSuggestions:{type:Number,required:!1,default:5}},setup(e){const{locales:t,hotKeys:l,maxSuggestions:n}=Dn(e),i=bt(),r=Ql(),o=Zf(),c=pe(null),a=pe(!1),u=pe(""),d=C(()=>t.value[r.value]??{}),v=ep({searchIndex:o,routeLocale:r,query:u,maxSuggestions:n}),{focusIndex:_,focusNext:g,focusPrev:m}=tp(v);Yf({input:c,hotKeys:l});const x=C(()=>a.value&&!!v.value.length),A=()=>{x.value&&m()},D=()=>{x.value&&g()},O=b=>{if(!x.value)return;const y=v.value[b];y&&i.push(y.link).then(()=>{u.value="",_.value=0})};return()=>he("form",{class:"search-box",role:"search"},[he("input",{ref:c,type:"search",placeholder:d.value.placeholder,autocomplete:"off",spellcheck:!1,value:u.value,onFocus:()=>a.value=!0,onBlur:()=>a.value=!1,onInput:b=>u.value=b.target.value,onKeydown:b=>{switch(b.key){case"ArrowUp":{A();break}case"ArrowDown":{D();break}case"Enter":{b.preventDefault(),O(_.value);break}}}}),x.value&&he("ul",{class:"suggestions",onMouseleave:()=>_.value=-1},v.value.map(({link:b,title:y,header:H},G)=>he("li",{class:["suggestion",{focus:_.value===G}],onMouseenter:()=>_.value=G,onMousedown:()=>O(G)},he("a",{href:b,onClick:N=>N.preventDefault()},[he("span",{class:"page-title"},y),H&&he("span",{class:"page-header"},`> ${H}`)]))))])}});var np=["s","/"],ip={"/":{placeholder:"搜索"}};const rp=ip,op=np,sp=5,cp=Et({enhance({app:e}){e.component("SearchBox",t=>he(lp,{locales:rp,hotKeys:op,maxSuggestions:sp,...t}))}}),ap={enhance:({app:e})=>{e.component("Mermaid",h(()=>s(()=>import("./Mermaid-DaLi44oU.js"),__vite__mapDeps([])))),e.component("Tab",h(()=>s(()=>import("./Tab-Ci2eJWYz.js"),__vite__mapDeps([])))),e.component("Tabs",h(()=>s(()=>import("./Tabs-CXHA-R7W.js"),__vite__mapDeps([]))))}},hn=[nh,oh,dh,xh,Ph,Dh,If,zf,cp,ap],up=[["v-8daa1a0e","/",{title:""},["/README.md"]],["v-aad48c6a","/about/news.html",{title:"大史记"},[":md"]],["v-ba934fd8","/config/",{title:"配置文件"},["/config/README.md"]],["v-41ade9da","/config/api.html",{title:"API 接口"},[":md"]],["v-83dedd38","/config/dns.html",{title:"内置 DNS 服务器"},[":md"]],["v-192a19b9","/config/fakedns.html",{title:"FakeDNS"},[":md"]],["v-7f6279d8","/config/inbound.html",{title:"入站代理"},[":md"]],["v-1d860c29","/config/log.html",{title:"日志配置"},[":md"]],["v-fbaf47ec","/config/metrics.html",{title:"Metrics"},[":md"]],["v-24956213","/config/observatory.html",{title:"连接观测"},[":md"]],["v-2367d756","/config/outbound.html",{title:"出站代理(Mux、XUDP)"},[":md"]],["v-4ebec35a","/config/policy.html",{title:"本地策略"},[":md"]],["v-31b7756a","/config/reverse.html",{title:"反向代理"},[":md"]],["v-70677432","/config/routing.html",{title:"路由"},[":md"]],["v-7e21d6ae","/config/stats.html",{title:"统计信息"},[":md"]],["v-e3dfff38","/config/transport.html",{title:"传输方式(uTLS、REALITY)"},[":md"]],["v-f7496066","/development/",{title:"开发指南"},["/development/README.md"]],["v-36b1a79b","/document/",{title:"快速入门"},["/document/README.md"]],["v-09a64f89","/document/command.html",{title:"命令参数"},[":md"]],["v-2b1adf48","/document/config.html",{title:"配置运行"},[":md"]],["v-86ee963a","/document/document.html",{title:"为 Project X 的文档贡献"},[":md"]],["v-0e5d7b39","/document/install.html",{title:"下载安装"},[":md"]],["v-2d0a870d","/en/",{title:""},["/en/README.md"]],["v-2d0ab8b3","/ru/",{title:""},["/ru/README.md"]],["v-0d714d87","/config/features/browser_dialer.html",{title:"Browser Dialer"},[":md"]],["v-0da7880a","/config/features/env.html",{title:"环境变量"},[":md"]],["v-2aeb21f9","/config/features/fallback.html",{title:"Fallback 回落"},[":md"]],["v-3acf20ea","/config/features/multiple.html",{title:"多文件配置"},[":md"]],["v-792e28f8","/config/features/xtls.html",{title:"XTLS 深度剖析"},[":md"]],["v-b50d2334","/config/inbounds/dokodemo.html",{title:"Dokodemo-Door"},[":md"]],["v-593408b0","/config/inbounds/http.html",{title:"HTTP"},[":md"]],["v-802a842a","/config/inbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-29995cea","/config/inbounds/socks.html",{title:"Socks"},[":md"]],["v-2a1b3d72","/config/inbounds/trojan.html",{title:"Trojan"},[":md"]],["v-fb92e8aa","/config/inbounds/vless.html",{title:"VLESS(XTLS Vision Seed)"},[":md"]],["v-167afaac","/config/inbounds/vmess.html",{title:"VMess"},[":md"]],["v-749ad71a","/config/outbounds/blackhole.html",{title:"Blackhole"},[":md"]],["v-6d39b970","/config/outbounds/dns.html",{title:"DNS"},[":md"]],["v-d76e893a","/config/outbounds/freedom.html",{title:"Freedom"},[":md"]],["v-c6b4b59e","/config/outbounds/http.html",{title:"HTTP"},[":md"]],["v-41ec0e0e","/config/outbounds/loopback.html",{title:"Loopback"},[":md"]],["v-7b293e4a","/config/outbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-15f5452a","/config/outbounds/socks.html",{title:"Socks"},[":md"]],["v-5797bdb3","/config/outbounds/trojan.html",{title:"Trojan"},[":md"]],["v-a60f016c","/config/outbounds/vless.html",{title:"VLESS(XTLS Vision Seed)"},[":md"]],["v-413cee4b","/config/outbounds/vmess.html",{title:"VMess"},[":md"]],["v-208ca3b9","/config/outbounds/wireguard.html",{title:"Wireguard"},[":md"]],["v-775db7b1","/config/transports/domainsocket.html",{title:"Domain Socket"},[":md"]],["v-2877542a","/config/transports/grpc.html",{title:"gRPC"},[":md"]],["v-03a28284","/config/transports/h2.html",{title:"HTTP/2"},[":md"]],["v-04158536","/config/transports/httpupgrade.html",{title:"HTTPUpgrade"},[":md"]],["v-3167b1dd","/config/transports/mkcp.html",{title:"mKCP"},[":md"]],["v-8f08dbec","/config/transports/quic.html",{title:"QUIC"},[":md"]],["v-eeea2fb0","/config/transports/splithttp.html",{title:"SplitHTTP(H2、QUIC H3)"},[":md"]],["v-33b1b709","/config/transports/tcp.html",{title:"TCP"},[":md"]],["v-1ff57bba","/config/transports/websocket.html",{title:"WebSocket"},[":md"]],["v-6a9e8054","/development/intro/compile.html",{title:"编译文档"},[":md"]],["v-95e3eaea","/development/intro/design.html",{title:"设计目标"},[":md"]],["v-61e7eea6","/development/intro/guide.html",{title:"开发规范"},[":md"]],["v-6e6c37e6","/development/protocols/mkcp.html",{title:"mKCP 协议"},[":md"]],["v-13168a21","/development/protocols/muxcool.html",{title:"Mux.Cool 协议"},[":md"]],["v-5c48c82b","/development/protocols/vless.html",{title:"VLESS 协议"},[":md"]],["v-1ee591a8","/development/protocols/vmess.html",{title:"VMess 协议"},[":md"]],["v-3f09dcfa","/document/level-0/",{title:"小小白白话文"},["/document/level-0/README.md"]],["v-fb444906","/document/level-0/ch01-preface.html",{title:"【第 1 章】 小小白白话文"},[":md"]],["v-075f3ae5","/document/level-0/ch02-preparation.html",{title:"【第 2 章】原料准备篇"},[":md"]],["v-726d0633","/document/level-0/ch03-ssh.html",{title:"【第 3 章】远程登录篇"},[":md"]],["v-430c6ab8","/document/level-0/ch04-security.html",{title:"【第 4 章】安全防护篇"},[":md"]],["v-717c6376","/document/level-0/ch05-webpage.html",{title:"【第 5 章】网站建设篇"},[":md"]],["v-278039be","/document/level-0/ch06-certificates.html",{title:"【第 6 章】证书管理篇"},[":md"]],["v-a0c7f88e","/document/level-0/ch07-xray-server.html",{title:"【第 7 章】Xray 服务器篇"},[":md"]],["v-86586ca2","/document/level-0/ch08-xray-clients.html",{title:"【第 8 章】Xray 客户端篇"},[":md"]],["v-3eb62514","/document/level-0/ch09-appendix.html",{title:"【第 9 章】附录"},[":md"]],["v-3f09dcbc","/document/level-1/",{title:"入门技巧"},["/document/level-1/README.md"]],["v-b21a2a20","/document/level-1/fallbacks-lv1.html",{title:"回落 (fallbacks) 功能简析"},[":md"]],["v-da623318","/document/level-1/fallbacks-with-sni.html",{title:"SNI 回落"},[":md"]],["v-fdd722ac","/document/level-1/routing-lv1-part1.html",{title:"路由 (routing) 功能简析(上)"},[":md"]],["v-fa6d716e","/document/level-1/routing-lv1-part2.html",{title:"路由 (routing) 功能简析(下)"},[":md"]],["v-2f29e106","/document/level-1/work.html",{title:"Xray 的工作模式"},[":md"]],["v-3f09dc7e","/document/level-2/",{title:"进阶文档"},["/document/level-2/README.md"]],["v-1c17916e","/document/level-2/iptables_gid.html",{title:"GID 透明代理"},[":md"]],["v-a001cfa6","/document/level-2/nginx_or_haproxy_tls_tunnel.html",{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹"},[":md"]],["v-46333b48","/document/level-2/redirect.html",{title:"出站流量重定向"},[":md"]],["v-338bc63e","/document/level-2/tproxy.html",{title:"TProxy 透明代理"},[":md"]],["v-d68f7d58","/document/level-2/tproxy_ipv4_and_ipv6.html",{title:"TProxy 透明代理 (ipv4 and ipv6)"},[":md"]],["v-e533e2c6","/document/level-2/traffic_stats.html",{title:"流量统计"},[":md"]],["v-1e465ab0","/document/level-2/warp.html",{title:"通过 Cloudflare Warp 增强代理安全性"},[":md"]],["v-1080fb37","/en/about/news.html",{title:"大史记"},[":md"]],["v-317fc580","/en/config/",{title:"Configurations"},["/en/config/README.md"]],["v-45144c7f","/en/config/api.html",{title:"API Interface"},[":md"]],["v-23fbd2d0","/en/config/dns.html",{title:"Built-in DNS Server"},[":md"]],["v-2b7ec525","/en/config/fakedns.html",{title:"FakeDNS"},[":md"]],["v-5ab92300","/en/config/inbound.html",{title:"Inbound Proxy"},[":md"]],["v-f91d64d6","/en/config/log.html",{title:"Log Configuration"},[":md"]],["v-d705f114","/en/config/metrics.html",{title:"Metrics"},[":md"]],["v-268cd669","/en/config/outbound.html",{title:"Outbound Proxies"},[":md"]],["v-4492d567","/en/config/policy.html",{title:"Local Policy"},[":md"]],["v-0d0e1e92","/en/config/reverse.html",{title:"Reverse Proxy"},[":md"]],["v-4bbe1d5a","/en/config/routing.html",{title:"Routing"},[":md"]],["v-16426d1a","/en/config/stats.html",{title:"Traffic Statistics"},[":md"]],["v-5de780d0","/en/config/transport.html",{title:"Transport"},[":md"]],["v-f88d343e","/en/development/",{title:"Development Guide"},["/en/development/README.md"]],["v-38d56a07","/en/document/",{title:"Quick Start"},["/en/document/README.md"]],["v-4d046016","/en/document/command.html",{title:"Command Parameters"},[":md"]],["v-22b35270","/en/document/config.html",{title:"Configure and Run"},[":md"]],["v-30bd7c12","/en/document/document.html",{title:"Contribute to Project X's Document"},[":md"]],["v-439608b6","/en/document/install.html",{title:"Download and Install"},[":md"]],["v-408e88d1","/ru/about/news.html",{title:"大史记"},[":md"]],["v-b1cce5cc","/ru/config/",{title:"Конфигурационный файл"},["/ru/config/README.md"]],["v-7521da19","/ru/config/api.html",{title:"API"},[":md"]],["v-5409606a","/ru/config/dns.html",{title:"Встроенный DNS-сервер"},[":md"]],["v-5877f5bf","/ru/config/fakedns.html",{title:"FakeDNS"},[":md"]],["v-00c6c1cc","/ru/config/inbound.html",{title:"Входящие подключения"},[":md"]],["v-990249a2","/ru/config/log.html",{title:"Настройка журнала"},[":md"]],["v-7d138fe0","/ru/config/metrics.html",{title:"Метрики"},[":md"]],["v-11e9cb19","/ru/config/observatory.html",{title:"Мониторинг подключений"},[":md"]],["v-ce8c8de2","/ru/config/outbound.html",{title:"Исходящие подключения"},[":md"]],["v-3dc4298d","/ru/config/policy.html",{title:"Локальные политики"},[":md"]],["v-26722151","/ru/config/reverse.html",{title:"Обратный прокси"},[":md"]],["v-071a21ed","/ru/config/routing.html",{title:"Маршрутизация"},[":md"]],["v-7922fc34","/ru/config/stats.html",{title:"Статистика"},[":md"]],["v-3156f2ea","/ru/config/transport.html",{title:"Транспорт"},[":md"]],["v-40ee4e87","/ru/development/",{title:"开发指南"},["/ru/development/README.md"]],["v-a1c899be","/ru/document/",{title:"Быстрый старт"},["/ru/document/README.md"]],["v-a6257be2","/ru/document/command.html",{title:"Командные аргументы"},[":md"]],["v-d63f95d4","/ru/document/config.html",{title:"Настройка и запуск"},[":md"]],["v-fbbfd9c6","/ru/document/document.html",{title:"Вклад в документацию Project X"},[":md"]],["v-9cb72482","/ru/document/install.html",{title:"Загрузка и установка"},[":md"]],["v-51a51d87","/document/level-2/transparent_proxy/transparent_proxy.html",{title:"透明代理入门"},[":md"]],["v-76b9a0f3","/en/config/features/browser_dialer.html",{title:"Browser Dialer"},[":md"]],["v-565dbfc4","/en/config/features/env.html",{title:"Environment Variables"},[":md"]],["v-0fbd1336","/en/config/features/fallback.html",{title:"Fallback"},[":md"]],["v-a0627812","/en/config/features/multiple.html",{title:"Multi-file configuration"},[":md"]],["v-d190d938","/en/config/features/xtls.html",{title:"Deep analysis of XTLS"},[":md"]],["v-72afc2d2","/en/config/inbounds/dokodemo.html",{title:"Dokodemo-Door"},[":md"]],["v-773d731c","/en/config/inbounds/http.html",{title:"HTTP"},[":md"]],["v-f555fc02","/en/config/inbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-e35196c2","/en/config/inbounds/socks.html",{title:"SOCKS"},[":md"]],["v-29188644","/en/config/inbounds/trojan.html",{title:"Trojan"},[":md"]],["v-255a6ebf","/en/config/inbounds/vless.html",{title:"VLESS"},[":md"]],["v-8cc24480","/en/config/inbounds/vmess.html",{title:"VMess"},[":md"]],["v-64e47ef4","/en/config/outbounds/blackhole.html",{title:"Blackhole"},[":md"]],["v-e979b848","/en/config/outbounds/dns.html",{title:"DNS"},[":md"]],["v-617f0fcf","/en/config/outbounds/freedom.html",{title:"Freedom"},[":md"]],["v-3fc98845","/en/config/outbounds/http.html",{title:"HTTP"},[":md"]],["v-1b804722","/en/config/outbounds/loopback.html",{title:"Loopback"},[":md"]],["v-63077cb6","/en/config/outbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-516476d4","/en/config/outbounds/socks.html",{title:"Socks"},[":md"]],["v-7d61a872","/en/config/outbounds/trojan.html",{title:"Trojan"},[":md"]],["v-6e50feb6","/en/config/outbounds/vless.html",{title:"VLESS"},[":md"]],["v-02956db7","/en/config/outbounds/vmess.html",{title:"VMess"},[":md"]],["v-797f8d25","/en/config/outbounds/wireguard.html",{title:"Wireguard"},[":md"]],["v-3eb3e9c6","/en/config/transports/domainsocket.html",{title:"Domain Socket"},[":md"]],["v-2c6058d4","/en/config/transports/grpc.html",{title:"gRPC"},[":md"]],["v-1c38292a","/en/config/transports/h2.html",{title:"HTTP/2"},[":md"]],["v-17ff144a","/en/config/transports/httpupgrade.html",{title:"HTTPUpgrade"},[":md"]],["v-1a7f9d6e","/en/config/transports/mkcp.html",{title:"mKCP"},[":md"]],["v-79d41176","/en/config/transports/quic.html",{title:"QUIC"},[":md"]],["v-4df52c3c","/en/config/transports/splithttp.html",{title:"SplitHTTP"},[":md"]],["v-5254cbc6","/en/config/transports/tcp.html",{title:"TCP"},[":md"]],["v-9520f392","/en/config/transports/websocket.html",{title:"WebSocket"},[":md"]],["v-b7760e2c","/en/development/intro/compile.html",{title:"Compile the document"},[":md"]],["v-fb774212","/en/development/intro/design.html",{title:"Design Objectives"},[":md"]],["v-38c376c1","/en/development/intro/guide.html",{title:"Development Standards"},[":md"]],["v-21bccd79","/en/development/protocols/mkcp.html",{title:"mKCP Protocol"},[":md"]],["v-27001935","/en/development/protocols/muxcool.html",{title:"Mux.Cool Protocol"},[":md"]],["v-21b30c3f","/en/development/protocols/vless.html",{title:"VLESS Protocol"},[":md"]],["v-94110980","/en/development/protocols/vmess.html",{title:"VMess Protocol"},[":md"]],["v-789ba7ef","/en/document/level-0/",{title:"Plain and Simple Language"},["/en/document/level-0/README.md"]],["v-d3712ade","/en/document/level-0/ch01-preface.html",{title:"[Chapter 1] Simple and Plain Language"},[":md"]],["v-41f9c00e","/en/document/level-0/ch02-preparation.html",{title:"[Chapter 2] Preparation of Raw Materials"},[":md"]],["v-4c013f47","/en/document/level-0/ch03-ssh.html",{title:"[Chapter 3] Remote Login"},[":md"]],["v-a75683b8","/en/document/level-0/ch04-security.html",{title:"[Chapter 4] Security and Protection"},[":md"]],["v-f5341aec","/en/document/level-0/ch05-webpage.html",{title:"Chapter 5: Website Building"},[":md"]],["v-4458f72a","/en/document/level-0/ch06-certificates.html",{title:"[Chapter 6] Certificate Management"},[":md"]],["v-f1802e66","/en/document/level-0/ch07-xray-server.html",{title:"【第 7 章】Xray 服务器篇"},[":md"]],["v-4ca6f1ca","/en/document/level-0/ch08-xray-clients.html",{title:"【第 8 章】Xray 客户端篇"},[":md"]],["v-b0030f00","/en/document/level-0/ch09-appendix.html",{title:"【第 9 章】附录"},[":md"]],["v-789ba80e","/en/document/level-1/",{title:"Beginner's Tips"},["/en/document/level-1/README.md"]],["v-103b3e5c","/en/document/level-1/fallbacks-lv1.html",{title:"回落 (fallbacks) 功能简析"},[":md"]],["v-110dd688","/en/document/level-1/fallbacks-with-sni.html",{title:"SNI fallback"},[":md"]],["v-c425a7d4","/en/document/level-1/routing-lv1-part1.html",{title:"路由 (routing) 功能简析(上)"},[":md"]],["v-c0bbf696","/en/document/level-1/routing-lv1-part2.html",{title:"路由 (routing) 功能简析(下)"},[":md"]],["v-5b6477cc","/en/document/level-1/work.html",{title:"Xray 的工作模式"},[":md"]],["v-789ba82d","/en/document/level-2/",{title:"Advanced Documentation"},["/en/document/level-2/README.md"]],["v-05ddc65d","/en/document/level-2/iptables_gid.html",{title:"Transparent proxy via GID"},[":md"]],["v-474afe99","/en/document/level-2/nginx_or_haproxy_tls_tunnel.html",{title:"Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹"},[":md"]],["v-930ac920","/en/document/level-2/redirect.html",{title:"出站流量重定向"},[":md"]],["v-c579975c","/en/document/level-2/tproxy.html",{title:"TProxy 透明代理"},[":md"]],["v-7efb7c68","/en/document/level-2/tproxy_ipv4_and_ipv6.html",{title:"TProxy 透明代理 (ipv4 and ipv6)"},[":md"]],["v-12a33bee","/en/document/level-2/traffic_stats.html",{title:"流量统计"},[":md"]],["v-7d2b8478","/en/document/level-2/warp.html",{title:"Enhancing Proxy Security with Cloudflare Warp"},[":md"]],["v-1cfb44e6","/ru/config/features/browser_dialer.html",{title:"Browser Dialer"},[":md"]],["v-6a3f8078","/ru/config/features/env.html",{title:"Переменные среды"},[":md"]],["v-74f22e7f","/ru/config/features/fallback.html",{title:"Fallback"},[":md"]],["v-2c9f7c11","/ru/config/features/multiple.html",{title:"Настройка с помощью нескольких файлов"},[":md"]],["v-630c687e","/ru/config/features/xtls.html",{title:"Глубокое погружение в XTLS"},[":md"]],["v-20ff0a28","/ru/config/inbounds/dokodemo.html",{title:"Dokodemo-Door"},[":md"]],["v-43124836","/ru/config/inbounds/http.html",{title:"HTTP"},[":md"]],["v-6a351ba5","/ru/config/inbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-3d1d02c5","/ru/config/inbounds/socks.html",{title:"Socks"},[":md"]],["v-1567b378","/ru/config/inbounds/trojan.html",{title:"Trojan"},[":md"]],["v-57bf8636","/ru/config/inbounds/vless.html",{title:"VLESS"},[":md"]],["v-6864abe6","/ru/config/inbounds/vmess.html",{title:"VMess"},[":md"]],["v-5910da20","/ru/config/outbounds/blackhole.html",{title:"Blackhole"},[":md"]],["v-5717f8f6","/ru/config/outbounds/dns.html",{title:"DNS"},[":md"]],["v-4360702e","/ru/config/outbounds/freedom.html",{title:"Freedom"},[":md"]],["v-22e1532a","/ru/config/outbounds/http.html",{title:"HTTP"},[":md"]],["v-38c69248","/ru/config/outbounds/loopback.html",{title:"Loopback"},[":md"]],["v-1a2a97d0","/ru/config/outbounds/shadowsocks.html",{title:"Shadowsocks"},[":md"]],["v-0141bb30","/ru/config/outbounds/socks.html",{title:"Socks"},[":md"]],["v-544bef26","/ru/config/outbounds/trojan.html",{title:"Trojan"},[":md"]],["v-cf761560","/ru/config/outbounds/vless.html",{title:"VLESS"},[":md"]],["v-2c896451","/ru/config/outbounds/vmess.html",{title:"VMess"},[":md"]],["v-0502a6bf","/ru/config/outbounds/wireguard.html",{title:"WireGuard"},[":md"]],["v-5b6ec7b7","/ru/config/transports/domainsocket.html",{title:"DomainSocket"},[":md"]],["v-13c3ca30","/ru/config/transports/grpc.html",{title:"gRPC"},[":md"]],["v-2fe60378","/ru/config/transports/h2.html",{title:"HTTP/2"},[":md"]],["v-453f5c70","/ru/config/transports/httpupgrade.html",{title:"HTTPUpgrade"},[":md"]],["v-1cb427e3","/ru/config/transports/mkcp.html",{title:"mKCP"},[":md"]],["v-b86fefe0","/ru/config/transports/quic.html",{title:"QUIC"},[":md"]],["v-32d545e2","/ru/config/transports/splithttp.html",{title:"SplitHTTP"},[":md"]],["v-f4c92f7a","/ru/config/transports/tcp.html",{title:"TCP"},[":md"]],["v-cb60c046","/ru/config/transports/websocket.html",{title:"WebSocket"},[":md"]],["v-7ce977e0","/ru/development/intro/compile.html",{title:"编译文档"},[":md"]],["v-01d5d1de","/ru/development/intro/design.html",{title:"设计目标"},[":md"]],["v-4d4e5367","/ru/development/intro/guide.html",{title:"开发规范"},[":md"]],["v-a58031da","/ru/development/protocols/mkcp.html",{title:"mKCP 协议"},[":md"]],["v-5440615b","/ru/development/protocols/muxcool.html",{title:"Mux.Cool 协议"},[":md"]],["v-069325e5","/ru/development/protocols/vless.html",{title:"VLESS 协议"},[":md"]],["v-ca50d634","/ru/development/protocols/vmess.html",{title:"VMess 协议"},[":md"]],["v-490791ee","/ru/document/level-0/",{title:"Простые разговоры о сложном"},["/ru/document/level-0/README.md"]],["v-78f09a92","/ru/document/level-0/ch01-preface.html",{title:"【Глава 1】 Простыми словами"},[":md"]],["v-64f6e51f","/ru/document/level-0/ch02-preparation.html",{title:"【Глава 2】 Подготовка"},[":md"]],["v-69478a6d","/ru/document/level-0/ch03-ssh.html",{title:"【Глава 3】 Удалённое подключение"},[":md"]],["v-271d7abe","/ru/document/level-0/ch04-security.html",{title:"【Глава 4】 Обеспечение безопасности"},[":md"]],["v-9ab38aa0","/ru/document/level-0/ch05-webpage.html",{title:"【Глава 5】 Создание веб-сайта"},[":md"]],["v-7cddd6c4","/ru/document/level-0/ch06-certificates.html",{title:"【Глава 6】 Управление сертификатами"},[":md"]],["v-0d33adf3","/ru/document/level-0/ch07-xray-server.html",{title:"【Глава 7】Настройка Xray на сервере"},[":md"]],["v-123166b5","/ru/document/level-0/ch08-xray-clients.html",{title:"【Глава 8】Настройка Xray на клиенте"},[":md"]],["v-22c7351a","/ru/document/level-0/ch09-appendix.html",{title:"[Глава 9] Приложение"},[":md"]],["v-490791b0","/ru/document/level-1/",{title:"Советы для начинающих"},["/ru/document/level-1/README.md"]],["v-e9f80a14","/ru/document/level-1/fallbacks-lv1.html",{title:"Обзор функции Fallback"},[":md"]],["v-2db62ba4","/ru/document/level-1/fallbacks-with-sni.html",{title:"SNI Fallback"},[":md"]],["v-531be8a0","/ru/document/level-1/routing-lv1-part1.html",{title:"Краткий обзор функции маршрутизации (routing) (часть 1)"},[":md"]],["v-4fb23762","/ru/document/level-1/routing-lv1-part2.html",{title:"Краткий обзор функции маршрутизации (routing) (часть 2)"},[":md"]],["v-fdd8db80","/ru/document/level-1/work.html",{title:"Режимы работы Xray"},[":md"]],["v-49079172","/ru/document/level-2/",{title:"Продвинутая документация"},["/ru/document/level-2/README.md"]],["v-331e0e83","/ru/document/level-2/iptables_gid.html",{title:"GID Прозрачное проксирование"},[":md"]],["v-7418a5b3","/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html",{title:"Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков"},[":md"]],["v-587e32d4","/ru/document/level-2/redirect.html",{title:"Перенаправление исходящего трафика"},[":md"]],["v-9c63de10","/ru/document/level-2/tproxy.html",{title:"Прозрачное проксирование TProxy"},[":md"]],["v-a4c782e4","/ru/document/level-2/tproxy_ipv4_and_ipv6.html",{title:"Прозрачное проксирование TProxy (ipv4 и ipv6)"},[":md"]],["v-71771ea3","/ru/document/level-2/traffic_stats.html",{title:"Статистика трафика"},[":md"]],["v-70300bea","/ru/document/level-2/warp.html",{title:"Повышение безопасности проксирования с помощью Cloudflare Warp"},[":md"]],["v-7689d7f3","/en/document/level-2/transparent_proxy/transparent_proxy.html",{title:"透明代理入门"},[":md"]],["v-39b3c50d","/ru/document/level-2/transparent_proxy/transparent_proxy.html",{title:"Другие замечания по прозрачному проксированию с помощью iptables"},[":md"]],["v-3706649a","/404.html",{title:""},[]],["v-5c8e777f","/en/config/observatory.html",{title:"连接观测"},[":md"]]];var po=_e({name:"Vuepress",setup(){const e=Uu();return()=>he(e.value)}}),dp=()=>up.reduce((e,[t,l,n,i])=>(e.push({name:t,path:l,component:po,meta:n},{path:l.endsWith("/")?l+"index.html":l.substring(0,l.length-5),redirect:l},...i.map(r=>({path:r===":md"?l.substring(0,l.length-5)+".md":r,redirect:l}))),e),[{name:"404",path:"/:catchAll(.*)",component:po}]),hp=Od,vp=()=>{const e=Yd({history:hp(_s("/")),routes:dp(),scrollBehavior:(t,l,n)=>n||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,l)=>{var n;(t.path!==l.path||l===_t)&&([t.meta._data]=await Promise.all([vt.resolvePageData(t.name),(n=gs[t.name])==null?void 0:n.__asyncLoader()]))}),e},_p=e=>{e.component("ClientOnly",Bi),e.component("Content",Gu)},fp=(e,t,l)=>{const n=C(()=>t.currentRoute.value.path),i=Vh(n,()=>t.currentRoute.value.meta._data),r=C(()=>vt.resolveLayouts(l)),o=C(()=>vt.resolveRouteLocale(ll.value.locales,n.value)),c=C(()=>vt.resolveSiteLocaleData(ll.value,o.value)),a=C(()=>vt.resolvePageFrontmatter(i.value)),u=C(()=>vt.resolvePageHeadTitle(i.value,c.value)),d=C(()=>vt.resolvePageHead(u.value,a.value,c.value)),v=C(()=>vt.resolvePageLang(i.value,c.value)),_=C(()=>vt.resolvePageLayout(i.value,r.value));return e.provide(Hu,r),e.provide(ms,i),e.provide(bs,a),e.provide(Bu,u),e.provide(ks,d),e.provide(Es,v),e.provide(ys,_),e.provide(Mi,o),e.provide(Ls,c),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>a.value},$head:{get:()=>d.value},$headTitle:{get:()=>u.value},$lang:{get:()=>v.value},$page:{get:()=>i.value},$routeLocale:{get:()=>o.value},$site:{get:()=>ll.value},$siteLocale:{get:()=>c.value},$withBase:{get:()=>Wi}}),{layouts:r,pageData:i,pageFrontmatter:a,pageHead:d,pageHeadTitle:u,pageLang:v,pageLayout:_,routeLocale:o,siteData:ll,siteLocaleData:c}},pp=()=>{const e=$u(),t=Wu();let l=[];const n=()=>{e.value.forEach(o=>{const c=gp(o);c&&l.push(c)})},i=()=>{const o=[];return e.value.forEach(c=>{const a=mp(c);a&&o.push(a)}),o},r=()=>{document.documentElement.lang=t.value;const o=i();l.forEach((c,a)=>{const u=o.findIndex(d=>c.isEqualNode(d));u===-1?(c.remove(),delete l[a]):o.splice(u,1)}),o.forEach(c=>document.head.appendChild(c)),l=[...l.filter(c=>!!c),...o]};Kt(Xu,r),We(()=>{n(),Ge(e,r,{immediate:!1})})},gp=([e,t,l=""])=>{const n=Object.entries(t).map(([c,a])=>it(a)?`[${c}=${JSON.stringify(a)}]`:a===!0?`[${c}]`:"").join(""),i=`head > ${e}${n}`;return Array.from(document.querySelectorAll(i)).find(c=>c.innerText===l)||null},mp=([e,t,l])=>{if(!it(e))return null;const n=document.createElement(e);return Hi(t)&&Object.entries(t).forEach(([i,r])=>{it(r)?n.setAttribute(i,r):r===!0&&n.setAttribute(i,"")}),it(l)&&n.appendChild(document.createTextNode(l)),n},bp=Pu,kp=async()=>{var l;const e=bp({name:"VuepressApp",setup(){var n;pp();for(const i of hn)(n=i.setup)==null||n.call(i);return()=>[he(Vs),...hn.flatMap(({rootComponents:i=[]})=>i.map(r=>he(r)))]}}),t=vp();_p(e),fp(e,t,hn);for(const n of hn)await((l=n.enhance)==null?void 0:l.call(n,{app:e,router:t,siteData:ll}));return e.use(t),{app:e,router:t}};kp().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{ke as F,xe as _,ie as a,ce as b,ee as c,kp as createVueApp,Vt as d,$a as e,fc as f,Lo as g,C as h,Ge as i,pe as j,We as k,Vi as l,_e as m,Ul as n,W as o,Xl as p,s as q,mt as r,be as s,Ep as t,Xt as u,St as v,Ce as w,Pe as x}; function __vite__mapDeps(indexes) { if (!__vite__mapDeps.viteFileDeps) { __vite__mapDeps.viteFileDeps = [] diff --git a/assets/arc-xLaeEKkr.js b/assets/arc-C5d-KvsZ.js similarity index 96% rename from assets/arc-xLaeEKkr.js rename to assets/arc-C5d-KvsZ.js index 0b278c1451..8897b54320 100644 --- a/assets/arc-xLaeEKkr.js +++ b/assets/arc-C5d-KvsZ.js @@ -1 +1 @@ -import{w as ln,c as U}from"./path-CbwjOpE9.js";import{aO as an,aP as Y,aQ as O,aR as rn,aS as y,aK as on,aT as z,aU as _,aV as un,aW as t,aX as sn,aY as tn,aZ as fn}from"./mermaid.core-CArNAncI.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function mn(l){return l.endAngle}function pn(l){return l&&l.padAngle}function dn(l,h,D,S,v,R,V,a){var E=D-l,i=S-h,n=V-v,m=a-R,r=m*E-n*i;if(!(r*ru*u+X*X&&(K=w,Q=d),{cx:K,cy:Q,x01:-n,y01:-m,x11:K*(v/T-1),y11:Q*(v/T-1)}}function vn(){var l=cn,h=yn,D=U(0),S=null,v=gn,R=mn,V=pn,a=null,E=ln(i);function i(){var n,m,r=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-rn,c=R.apply(this,arguments)-rn,W=un(c-f),o=c>f;if(a||(a=n=E()),sy))a.moveTo(0,0);else if(W>on-y)a.moveTo(s*Y(f),s*O(f)),a.arc(0,0,s,f,c,!o),r>y&&(a.moveTo(r*Y(c),r*O(c)),a.arc(0,0,r,c,f,o));else{var p=f,g=c,A=f,T=c,P=W,I=W,K=V.apply(this,arguments)/2,Q=K>y&&(S?+S.apply(this,arguments):z(r*r+s*s)),w=_(un(s-r)/2,+D.apply(this,arguments)),d=w,x=w,e,u;if(Q>y){var X=sn(Q/r*O(K)),B=sn(Q/s*O(K));(P-=X*2)>y?(X*=o?1:-1,A+=X,T-=X):(P=0,A=T=(f+c)/2),(I-=B*2)>y?(B*=o?1:-1,p+=B,g-=B):(I=0,p=g=(f+c)/2)}var Z=s*Y(p),j=s*O(p),C=r*Y(T),F=r*O(T);if(w>y){var G=s*Y(g),H=s*O(g),L=r*Y(A),M=r*O(A),q;if(Wy?x>y?(e=J(L,M,Z,j,s,x,o),u=J(G,H,C,F,s,x,o),a.moveTo(e.cx+e.x01,e.cy+e.y01),xy)||!(P>y)?a.lineTo(C,F):d>y?(e=J(C,F,G,H,r,-d,o),u=J(Z,j,L,M,r,-d,o),a.lineTo(e.cx+e.x01,e.cy+e.y01),du*u+X*X&&(K=w,Q=d),{cx:K,cy:Q,x01:-n,y01:-m,x11:K*(v/T-1),y11:Q*(v/T-1)}}function vn(){var l=cn,h=yn,D=U(0),S=null,v=gn,R=mn,V=pn,a=null,E=ln(i);function i(){var n,m,r=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-rn,c=R.apply(this,arguments)-rn,W=un(c-f),o=c>f;if(a||(a=n=E()),sy))a.moveTo(0,0);else if(W>on-y)a.moveTo(s*Y(f),s*O(f)),a.arc(0,0,s,f,c,!o),r>y&&(a.moveTo(r*Y(c),r*O(c)),a.arc(0,0,r,c,f,o));else{var p=f,g=c,A=f,T=c,P=W,I=W,K=V.apply(this,arguments)/2,Q=K>y&&(S?+S.apply(this,arguments):z(r*r+s*s)),w=_(un(s-r)/2,+D.apply(this,arguments)),d=w,x=w,e,u;if(Q>y){var X=sn(Q/r*O(K)),B=sn(Q/s*O(K));(P-=X*2)>y?(X*=o?1:-1,A+=X,T-=X):(P=0,A=T=(f+c)/2),(I-=B*2)>y?(B*=o?1:-1,p+=B,g-=B):(I=0,p=g=(f+c)/2)}var Z=s*Y(p),j=s*O(p),C=r*Y(T),F=r*O(T);if(w>y){var G=s*Y(g),H=s*O(g),L=r*Y(A),M=r*O(A),q;if(Wy?x>y?(e=J(L,M,Z,j,s,x,o),u=J(G,H,C,F,s,x,o),a.moveTo(e.cx+e.x01,e.cy+e.y01),xy)||!(P>y)?a.lineTo(C,F):d>y?(e=J(C,F,G,H,r,-d,o),u=J(Z,j,L,M,r,-d,o),a.lineTo(e.cx+e.x01,e.cy+e.y01),dOutboundConfigurationObject
{
+import{_ as c,r as o,o as l,c as p,a as s,b as e,d as n,w as i,e as d}from"./app-Bw2NG-QJ.js";const r={},u=e("h1",{id:"blackhole",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#blackhole"},[e("span",null,"Blackhole")])],-1),h=d(`

OutboundConfigurationObject

{
   "response": {
     "type": "none"
   }
diff --git a/assets/blackhole.html-CobmF86r.js b/assets/blackhole.html-BqrDbtFw.js
similarity index 97%
rename from assets/blackhole.html-CobmF86r.js
rename to assets/blackhole.html-BqrDbtFw.js
index 539b07c23f..3d91705cf7 100644
--- a/assets/blackhole.html-CobmF86r.js
+++ b/assets/blackhole.html-BqrDbtFw.js
@@ -1,4 +1,4 @@
-import{_ as c,r as o,o as l,c as i,a as s,b as e,d as n,w as d,e as p}from"./app-5SoadDYS.js";const r={},u=e("h1",{id:"blackhole",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#blackhole"},[e("span",null,"Blackhole")])],-1),h=p(`

OutboundConfigurationObject

{
+import{_ as c,r as o,o as l,c as i,a as s,b as e,d as n,w as d,e as p}from"./app-Bw2NG-QJ.js";const r={},u=e("h1",{id:"blackhole",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#blackhole"},[e("span",null,"Blackhole")])],-1),h=p(`

OutboundConfigurationObject

{
   "response": {
     "type": "none"
   }
diff --git a/assets/blackhole.html-EGsblD7s.js b/assets/blackhole.html-CBPzXtbg.js
similarity index 98%
rename from assets/blackhole.html-EGsblD7s.js
rename to assets/blackhole.html-CBPzXtbg.js
index bf9e4287e2..7621a244d4 100644
--- a/assets/blackhole.html-EGsblD7s.js
+++ b/assets/blackhole.html-CBPzXtbg.js
@@ -1,4 +1,4 @@
-import{_ as c,r as o,o as l,c as p,a as s,b as e,d as n,w as i,e as d}from"./app-5SoadDYS.js";const r={},u=e("h1",{id:"blackhole",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#blackhole"},[e("span",null,"Blackhole")])],-1),h=d(`

OutboundConfigurationObject

{
+import{_ as c,r as o,o as l,c as p,a as s,b as e,d as n,w as i,e as d}from"./app-Bw2NG-QJ.js";const r={},u=e("h1",{id:"blackhole",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#blackhole"},[e("span",null,"Blackhole")])],-1),h=d(`

OutboundConfigurationObject

{
   "response": {
     "type": "none"
   }
diff --git a/assets/blockDiagram-9f4a6865-QPsisUYk.js b/assets/blockDiagram-9f4a6865-BqKpDrqb.js
similarity index 98%
rename from assets/blockDiagram-9f4a6865-QPsisUYk.js
rename to assets/blockDiagram-9f4a6865-BqKpDrqb.js
index 643dec3d17..337701c8cd 100644
--- a/assets/blockDiagram-9f4a6865-QPsisUYk.js
+++ b/assets/blockDiagram-9f4a6865-BqKpDrqb.js
@@ -1,4 +1,4 @@
-import{c as he,a$ as se,h as H,i as ye,l as S,A as Ee,af as we,j as De,p as ve}from"./mermaid.core-CArNAncI.js";import{c as Ne}from"./clone-D0wOyyCk.js";import{i as ke,c as Ie,b as Oe,d as Te,a as ge,p as ze}from"./edges-066a5561-BnmFWp88.js";import{G as Ce}from"./graph-D2qW7eTj.js";import{o as Ae}from"./ordinal-Cboi1Yqb.js";import{c as Re}from"./channel-C_7gBDjR.js";import{s as Be}from"./Tableau10-B-NsZVaP.js";import"./app-5SoadDYS.js";import"./createText-ca0c5216-X7RVUogw.js";import"./line-BIqtvXUi.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";import"./init-Gi6I4Gst.js";var le,oe,ee=function(){var e=function(D,o,s,i){for(s=s||{},i=D.length;i--;s[D[i]]=o);return s},a=[1,7],d=[1,13],c=[1,14],n=[1,15],g=[1,19],l=[1,16],f=[1,17],b=[1,18],p=[8,30],x=[8,21,28,29,30,31,32,40,44,47],y=[1,23],T=[1,24],v=[8,15,16,21,28,29,30,31,32,40,44,47],N=[8,15,16,21,27,28,29,30,31,32,40,44,47],E=[1,49],L={trace:function(){},yy:{},symbols_:{error:2,spaceLines:3,SPACELINE:4,NL:5,separator:6,SPACE:7,EOF:8,start:9,BLOCK_DIAGRAM_KEY:10,document:11,stop:12,statement:13,link:14,LINK:15,START_LINK:16,LINK_LABEL:17,STR:18,nodeStatement:19,columnsStatement:20,SPACE_BLOCK:21,blockStatement:22,classDefStatement:23,cssClassStatement:24,styleStatement:25,node:26,SIZE:27,COLUMNS:28,"id-block":29,end:30,block:31,NODE_ID:32,nodeShapeNLabel:33,dirList:34,DIR:35,NODE_DSTART:36,NODE_DEND:37,BLOCK_ARROW_START:38,BLOCK_ARROW_END:39,classDef:40,CLASSDEF_ID:41,CLASSDEF_STYLEOPTS:42,DEFAULT:43,class:44,CLASSENTITY_IDS:45,STYLECLASS:46,style:47,STYLE_ENTITY_IDS:48,STYLE_DEFINITION_DATA:49,$accept:0,$end:1},terminals_:{2:"error",4:"SPACELINE",5:"NL",7:"SPACE",8:"EOF",10:"BLOCK_DIAGRAM_KEY",15:"LINK",16:"START_LINK",17:"LINK_LABEL",18:"STR",21:"SPACE_BLOCK",27:"SIZE",28:"COLUMNS",29:"id-block",30:"end",31:"block",32:"NODE_ID",35:"DIR",36:"NODE_DSTART",37:"NODE_DEND",38:"BLOCK_ARROW_START",39:"BLOCK_ARROW_END",40:"classDef",41:"CLASSDEF_ID",42:"CLASSDEF_STYLEOPTS",43:"DEFAULT",44:"class",45:"CLASSENTITY_IDS",46:"STYLECLASS",47:"style",48:"STYLE_ENTITY_IDS",49:"STYLE_DEFINITION_DATA"},productions_:[0,[3,1],[3,2],[3,2],[6,1],[6,1],[6,1],[9,3],[12,1],[12,1],[12,2],[12,2],[11,1],[11,2],[14,1],[14,4],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[19,3],[19,2],[19,1],[20,1],[22,4],[22,3],[26,1],[26,2],[34,1],[34,2],[33,3],[33,4],[23,3],[23,3],[24,3],[25,3]],performAction:function(o,s,i,u,h,t,m){var r=t.length-1;switch(h){case 4:u.getLogger().debug("Rule: separator (NL) ");break;case 5:u.getLogger().debug("Rule: separator (Space) ");break;case 6:u.getLogger().debug("Rule: separator (EOF) ");break;case 7:u.getLogger().debug("Rule: hierarchy: ",t[r-1]),u.setHierarchy(t[r-1]);break;case 8:u.getLogger().debug("Stop NL ");break;case 9:u.getLogger().debug("Stop EOF ");break;case 10:u.getLogger().debug("Stop NL2 ");break;case 11:u.getLogger().debug("Stop EOF2 ");break;case 12:u.getLogger().debug("Rule: statement: ",t[r]),typeof t[r].length=="number"?this.$=t[r]:this.$=[t[r]];break;case 13:u.getLogger().debug("Rule: statement #2: ",t[r-1]),this.$=[t[r-1]].concat(t[r]);break;case 14:u.getLogger().debug("Rule: link: ",t[r],o),this.$={edgeTypeStr:t[r],label:""};break;case 15:u.getLogger().debug("Rule: LABEL link: ",t[r-3],t[r-1],t[r]),this.$={edgeTypeStr:t[r],label:t[r-1]};break;case 18:const R=parseInt(t[r]),Y=u.generateId();this.$={id:Y,type:"space",label:"",width:R,children:[]};break;case 23:u.getLogger().debug("Rule: (nodeStatement link node) ",t[r-2],t[r-1],t[r]," typestr: ",t[r-1].edgeTypeStr);const F=u.edgeStrToEdgeData(t[r-1].edgeTypeStr);this.$=[{id:t[r-2].id,label:t[r-2].label,type:t[r-2].type,directions:t[r-2].directions},{id:t[r-2].id+"-"+t[r].id,start:t[r-2].id,end:t[r].id,label:t[r-1].label,type:"edge",directions:t[r].directions,arrowTypeEnd:F,arrowTypeStart:"arrow_open"},{id:t[r].id,label:t[r].label,type:u.typeStr2Type(t[r].typeStr),directions:t[r].directions}];break;case 24:u.getLogger().debug("Rule: nodeStatement (abc88 node size) ",t[r-1],t[r]),this.$={id:t[r-1].id,label:t[r-1].label,type:u.typeStr2Type(t[r-1].typeStr),directions:t[r-1].directions,widthInColumns:parseInt(t[r],10)};break;case 25:u.getLogger().debug("Rule: nodeStatement (node) ",t[r]),this.$={id:t[r].id,label:t[r].label,type:u.typeStr2Type(t[r].typeStr),directions:t[r].directions,widthInColumns:1};break;case 26:u.getLogger().debug("APA123",this?this:"na"),u.getLogger().debug("COLUMNS: ",t[r]),this.$={type:"column-setting",columns:t[r]==="auto"?-1:parseInt(t[r])};break;case 27:u.getLogger().debug("Rule: id-block statement : ",t[r-2],t[r-1]),u.generateId(),this.$={...t[r-2],type:"composite",children:t[r-1]};break;case 28:u.getLogger().debug("Rule: blockStatement : ",t[r-2],t[r-1],t[r]);const C=u.generateId();this.$={id:C,type:"composite",label:"",children:t[r-1]};break;case 29:u.getLogger().debug("Rule: node (NODE_ID separator): ",t[r]),this.$={id:t[r]};break;case 30:u.getLogger().debug("Rule: node (NODE_ID nodeShapeNLabel separator): ",t[r-1],t[r]),this.$={id:t[r-1],label:t[r].label,typeStr:t[r].typeStr,directions:t[r].directions};break;case 31:u.getLogger().debug("Rule: dirList: ",t[r]),this.$=[t[r]];break;case 32:u.getLogger().debug("Rule: dirList: ",t[r-1],t[r]),this.$=[t[r-1]].concat(t[r]);break;case 33:u.getLogger().debug("Rule: nodeShapeNLabel: ",t[r-2],t[r-1],t[r]),this.$={typeStr:t[r-2]+t[r],label:t[r-1]};break;case 34:u.getLogger().debug("Rule: BLOCK_ARROW nodeShapeNLabel: ",t[r-3],t[r-2]," #3:",t[r-1],t[r]),this.$={typeStr:t[r-3]+t[r],label:t[r-2],directions:t[r-1]};break;case 35:case 36:this.$={type:"classDef",id:t[r-1].trim(),css:t[r].trim()};break;case 37:this.$={type:"applyClass",id:t[r-1].trim(),styleClass:t[r].trim()};break;case 38:this.$={type:"applyStyles",id:t[r-1].trim(),stylesStr:t[r].trim()};break}},table:[{9:1,10:[1,2]},{1:[3]},{11:3,13:4,19:5,20:6,21:a,22:8,23:9,24:10,25:11,26:12,28:d,29:c,31:n,32:g,40:l,44:f,47:b},{8:[1,20]},e(p,[2,12],{13:4,19:5,20:6,22:8,23:9,24:10,25:11,26:12,11:21,21:a,28:d,29:c,31:n,32:g,40:l,44:f,47:b}),e(x,[2,16],{14:22,15:y,16:T}),e(x,[2,17]),e(x,[2,18]),e(x,[2,19]),e(x,[2,20]),e(x,[2,21]),e(x,[2,22]),e(v,[2,25],{27:[1,25]}),e(x,[2,26]),{19:26,26:12,32:g},{11:27,13:4,19:5,20:6,21:a,22:8,23:9,24:10,25:11,26:12,28:d,29:c,31:n,32:g,40:l,44:f,47:b},{41:[1,28],43:[1,29]},{45:[1,30]},{48:[1,31]},e(N,[2,29],{33:32,36:[1,33],38:[1,34]}),{1:[2,7]},e(p,[2,13]),{26:35,32:g},{32:[2,14]},{17:[1,36]},e(v,[2,24]),{11:37,13:4,14:22,15:y,16:T,19:5,20:6,21:a,22:8,23:9,24:10,25:11,26:12,28:d,29:c,31:n,32:g,40:l,44:f,47:b},{30:[1,38]},{42:[1,39]},{42:[1,40]},{46:[1,41]},{49:[1,42]},e(N,[2,30]),{18:[1,43]},{18:[1,44]},e(v,[2,23]),{18:[1,45]},{30:[1,46]},e(x,[2,28]),e(x,[2,35]),e(x,[2,36]),e(x,[2,37]),e(x,[2,38]),{37:[1,47]},{34:48,35:E},{15:[1,50]},e(x,[2,27]),e(N,[2,33]),{39:[1,51]},{34:52,35:E,39:[2,31]},{32:[2,15]},e(N,[2,34]),{39:[2,32]}],defaultActions:{20:[2,7],23:[2,14],50:[2,15],52:[2,32]},parseError:function(o,s){if(s.recoverable)this.trace(o);else{var i=new Error(o);throw i.hash=s,i}},parse:function(o){var s=this,i=[0],u=[],h=[null],t=[],m=this.table,r="",R=0,Y=0,F=2,C=1,Le=t.slice.call(arguments,1),w=Object.create(this.lexer),K={yy:{}};for(var Z in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Z)&&(K.yy[Z]=this.yy[Z]);w.setInput(o,K.yy),K.yy.lexer=w,K.yy.parser=this,typeof w.yylloc>"u"&&(w.yylloc={});var J=w.yylloc;t.push(J);var me=w.options&&w.options.ranges;typeof K.yy.parseError=="function"?this.parseError=K.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function _e(){var P;return P=u.pop()||w.lex()||C,typeof P!="number"&&(P instanceof Array&&(u=P,P=u.pop()),P=s.symbols_[P]||P),P}for(var I,M,z,Q,W={},X,B,ae,G;;){if(M=i[i.length-1],this.defaultActions[M]?z=this.defaultActions[M]:((I===null||typeof I>"u")&&(I=_e()),z=m[M]&&m[M][I]),typeof z>"u"||!z.length||!z[0]){var $="";G=[];for(X in m[M])this.terminals_[X]&&X>F&&G.push("'"+this.terminals_[X]+"'");w.showPosition?$="Parse error on line "+(R+1)+`:
+import{c as he,a$ as se,h as H,i as ye,l as S,A as Ee,af as we,j as De,p as ve}from"./mermaid.core-Bq0kX0MS.js";import{c as Ne}from"./clone-BjoOJyl6.js";import{i as ke,c as Ie,b as Oe,d as Te,a as ge,p as ze}from"./edges-066a5561-CIBMFaLO.js";import{G as Ce}from"./graph-C-EgwjAv.js";import{o as Ae}from"./ordinal-Cboi1Yqb.js";import{c as Re}from"./channel-DIeeoF-2.js";import{s as Be}from"./Tableau10-B-NsZVaP.js";import"./app-Bw2NG-QJ.js";import"./createText-ca0c5216-xyt9uAlz.js";import"./line-DY_oMjHu.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";import"./init-Gi6I4Gst.js";var le,oe,ee=function(){var e=function(D,o,s,i){for(s=s||{},i=D.length;i--;s[D[i]]=o);return s},a=[1,7],d=[1,13],c=[1,14],n=[1,15],g=[1,19],l=[1,16],f=[1,17],b=[1,18],p=[8,30],x=[8,21,28,29,30,31,32,40,44,47],y=[1,23],T=[1,24],v=[8,15,16,21,28,29,30,31,32,40,44,47],N=[8,15,16,21,27,28,29,30,31,32,40,44,47],E=[1,49],L={trace:function(){},yy:{},symbols_:{error:2,spaceLines:3,SPACELINE:4,NL:5,separator:6,SPACE:7,EOF:8,start:9,BLOCK_DIAGRAM_KEY:10,document:11,stop:12,statement:13,link:14,LINK:15,START_LINK:16,LINK_LABEL:17,STR:18,nodeStatement:19,columnsStatement:20,SPACE_BLOCK:21,blockStatement:22,classDefStatement:23,cssClassStatement:24,styleStatement:25,node:26,SIZE:27,COLUMNS:28,"id-block":29,end:30,block:31,NODE_ID:32,nodeShapeNLabel:33,dirList:34,DIR:35,NODE_DSTART:36,NODE_DEND:37,BLOCK_ARROW_START:38,BLOCK_ARROW_END:39,classDef:40,CLASSDEF_ID:41,CLASSDEF_STYLEOPTS:42,DEFAULT:43,class:44,CLASSENTITY_IDS:45,STYLECLASS:46,style:47,STYLE_ENTITY_IDS:48,STYLE_DEFINITION_DATA:49,$accept:0,$end:1},terminals_:{2:"error",4:"SPACELINE",5:"NL",7:"SPACE",8:"EOF",10:"BLOCK_DIAGRAM_KEY",15:"LINK",16:"START_LINK",17:"LINK_LABEL",18:"STR",21:"SPACE_BLOCK",27:"SIZE",28:"COLUMNS",29:"id-block",30:"end",31:"block",32:"NODE_ID",35:"DIR",36:"NODE_DSTART",37:"NODE_DEND",38:"BLOCK_ARROW_START",39:"BLOCK_ARROW_END",40:"classDef",41:"CLASSDEF_ID",42:"CLASSDEF_STYLEOPTS",43:"DEFAULT",44:"class",45:"CLASSENTITY_IDS",46:"STYLECLASS",47:"style",48:"STYLE_ENTITY_IDS",49:"STYLE_DEFINITION_DATA"},productions_:[0,[3,1],[3,2],[3,2],[6,1],[6,1],[6,1],[9,3],[12,1],[12,1],[12,2],[12,2],[11,1],[11,2],[14,1],[14,4],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[19,3],[19,2],[19,1],[20,1],[22,4],[22,3],[26,1],[26,2],[34,1],[34,2],[33,3],[33,4],[23,3],[23,3],[24,3],[25,3]],performAction:function(o,s,i,u,h,t,m){var r=t.length-1;switch(h){case 4:u.getLogger().debug("Rule: separator (NL) ");break;case 5:u.getLogger().debug("Rule: separator (Space) ");break;case 6:u.getLogger().debug("Rule: separator (EOF) ");break;case 7:u.getLogger().debug("Rule: hierarchy: ",t[r-1]),u.setHierarchy(t[r-1]);break;case 8:u.getLogger().debug("Stop NL ");break;case 9:u.getLogger().debug("Stop EOF ");break;case 10:u.getLogger().debug("Stop NL2 ");break;case 11:u.getLogger().debug("Stop EOF2 ");break;case 12:u.getLogger().debug("Rule: statement: ",t[r]),typeof t[r].length=="number"?this.$=t[r]:this.$=[t[r]];break;case 13:u.getLogger().debug("Rule: statement #2: ",t[r-1]),this.$=[t[r-1]].concat(t[r]);break;case 14:u.getLogger().debug("Rule: link: ",t[r],o),this.$={edgeTypeStr:t[r],label:""};break;case 15:u.getLogger().debug("Rule: LABEL link: ",t[r-3],t[r-1],t[r]),this.$={edgeTypeStr:t[r],label:t[r-1]};break;case 18:const R=parseInt(t[r]),Y=u.generateId();this.$={id:Y,type:"space",label:"",width:R,children:[]};break;case 23:u.getLogger().debug("Rule: (nodeStatement link node) ",t[r-2],t[r-1],t[r]," typestr: ",t[r-1].edgeTypeStr);const F=u.edgeStrToEdgeData(t[r-1].edgeTypeStr);this.$=[{id:t[r-2].id,label:t[r-2].label,type:t[r-2].type,directions:t[r-2].directions},{id:t[r-2].id+"-"+t[r].id,start:t[r-2].id,end:t[r].id,label:t[r-1].label,type:"edge",directions:t[r].directions,arrowTypeEnd:F,arrowTypeStart:"arrow_open"},{id:t[r].id,label:t[r].label,type:u.typeStr2Type(t[r].typeStr),directions:t[r].directions}];break;case 24:u.getLogger().debug("Rule: nodeStatement (abc88 node size) ",t[r-1],t[r]),this.$={id:t[r-1].id,label:t[r-1].label,type:u.typeStr2Type(t[r-1].typeStr),directions:t[r-1].directions,widthInColumns:parseInt(t[r],10)};break;case 25:u.getLogger().debug("Rule: nodeStatement (node) ",t[r]),this.$={id:t[r].id,label:t[r].label,type:u.typeStr2Type(t[r].typeStr),directions:t[r].directions,widthInColumns:1};break;case 26:u.getLogger().debug("APA123",this?this:"na"),u.getLogger().debug("COLUMNS: ",t[r]),this.$={type:"column-setting",columns:t[r]==="auto"?-1:parseInt(t[r])};break;case 27:u.getLogger().debug("Rule: id-block statement : ",t[r-2],t[r-1]),u.generateId(),this.$={...t[r-2],type:"composite",children:t[r-1]};break;case 28:u.getLogger().debug("Rule: blockStatement : ",t[r-2],t[r-1],t[r]);const C=u.generateId();this.$={id:C,type:"composite",label:"",children:t[r-1]};break;case 29:u.getLogger().debug("Rule: node (NODE_ID separator): ",t[r]),this.$={id:t[r]};break;case 30:u.getLogger().debug("Rule: node (NODE_ID nodeShapeNLabel separator): ",t[r-1],t[r]),this.$={id:t[r-1],label:t[r].label,typeStr:t[r].typeStr,directions:t[r].directions};break;case 31:u.getLogger().debug("Rule: dirList: ",t[r]),this.$=[t[r]];break;case 32:u.getLogger().debug("Rule: dirList: ",t[r-1],t[r]),this.$=[t[r-1]].concat(t[r]);break;case 33:u.getLogger().debug("Rule: nodeShapeNLabel: ",t[r-2],t[r-1],t[r]),this.$={typeStr:t[r-2]+t[r],label:t[r-1]};break;case 34:u.getLogger().debug("Rule: BLOCK_ARROW nodeShapeNLabel: ",t[r-3],t[r-2]," #3:",t[r-1],t[r]),this.$={typeStr:t[r-3]+t[r],label:t[r-2],directions:t[r-1]};break;case 35:case 36:this.$={type:"classDef",id:t[r-1].trim(),css:t[r].trim()};break;case 37:this.$={type:"applyClass",id:t[r-1].trim(),styleClass:t[r].trim()};break;case 38:this.$={type:"applyStyles",id:t[r-1].trim(),stylesStr:t[r].trim()};break}},table:[{9:1,10:[1,2]},{1:[3]},{11:3,13:4,19:5,20:6,21:a,22:8,23:9,24:10,25:11,26:12,28:d,29:c,31:n,32:g,40:l,44:f,47:b},{8:[1,20]},e(p,[2,12],{13:4,19:5,20:6,22:8,23:9,24:10,25:11,26:12,11:21,21:a,28:d,29:c,31:n,32:g,40:l,44:f,47:b}),e(x,[2,16],{14:22,15:y,16:T}),e(x,[2,17]),e(x,[2,18]),e(x,[2,19]),e(x,[2,20]),e(x,[2,21]),e(x,[2,22]),e(v,[2,25],{27:[1,25]}),e(x,[2,26]),{19:26,26:12,32:g},{11:27,13:4,19:5,20:6,21:a,22:8,23:9,24:10,25:11,26:12,28:d,29:c,31:n,32:g,40:l,44:f,47:b},{41:[1,28],43:[1,29]},{45:[1,30]},{48:[1,31]},e(N,[2,29],{33:32,36:[1,33],38:[1,34]}),{1:[2,7]},e(p,[2,13]),{26:35,32:g},{32:[2,14]},{17:[1,36]},e(v,[2,24]),{11:37,13:4,14:22,15:y,16:T,19:5,20:6,21:a,22:8,23:9,24:10,25:11,26:12,28:d,29:c,31:n,32:g,40:l,44:f,47:b},{30:[1,38]},{42:[1,39]},{42:[1,40]},{46:[1,41]},{49:[1,42]},e(N,[2,30]),{18:[1,43]},{18:[1,44]},e(v,[2,23]),{18:[1,45]},{30:[1,46]},e(x,[2,28]),e(x,[2,35]),e(x,[2,36]),e(x,[2,37]),e(x,[2,38]),{37:[1,47]},{34:48,35:E},{15:[1,50]},e(x,[2,27]),e(N,[2,33]),{39:[1,51]},{34:52,35:E,39:[2,31]},{32:[2,15]},e(N,[2,34]),{39:[2,32]}],defaultActions:{20:[2,7],23:[2,14],50:[2,15],52:[2,32]},parseError:function(o,s){if(s.recoverable)this.trace(o);else{var i=new Error(o);throw i.hash=s,i}},parse:function(o){var s=this,i=[0],u=[],h=[null],t=[],m=this.table,r="",R=0,Y=0,F=2,C=1,Le=t.slice.call(arguments,1),w=Object.create(this.lexer),K={yy:{}};for(var Z in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Z)&&(K.yy[Z]=this.yy[Z]);w.setInput(o,K.yy),K.yy.lexer=w,K.yy.parser=this,typeof w.yylloc>"u"&&(w.yylloc={});var J=w.yylloc;t.push(J);var me=w.options&&w.options.ranges;typeof K.yy.parseError=="function"?this.parseError=K.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function _e(){var P;return P=u.pop()||w.lex()||C,typeof P!="number"&&(P instanceof Array&&(u=P,P=u.pop()),P=s.symbols_[P]||P),P}for(var I,M,z,Q,W={},X,B,ae,G;;){if(M=i[i.length-1],this.defaultActions[M]?z=this.defaultActions[M]:((I===null||typeof I>"u")&&(I=_e()),z=m[M]&&m[M][I]),typeof z>"u"||!z.length||!z[0]){var $="";G=[];for(X in m[M])this.terminals_[X]&&X>F&&G.push("'"+this.terminals_[X]+"'");w.showPosition?$="Parse error on line "+(R+1)+`:
 `+w.showPosition()+`
 Expecting `+G.join(", ")+", got '"+(this.terminals_[I]||I)+"'":$="Parse error on line "+(R+1)+": Unexpected "+(I==C?"end of input":"'"+(this.terminals_[I]||I)+"'"),this.parseError($,{text:w.match,token:this.terminals_[I]||I,line:w.yylineno,loc:J,expected:G})}if(z[0]instanceof Array&&z.length>1)throw new Error("Parse Error: multiple actions possible at state: "+M+", token: "+I);switch(z[0]){case 1:i.push(I),h.push(w.yytext),t.push(w.yylloc),i.push(z[1]),I=null,Y=w.yyleng,r=w.yytext,R=w.yylineno,J=w.yylloc;break;case 2:if(B=this.productions_[z[1]][1],W.$=h[h.length-B],W._$={first_line:t[t.length-(B||1)].first_line,last_line:t[t.length-1].last_line,first_column:t[t.length-(B||1)].first_column,last_column:t[t.length-1].last_column},me&&(W._$.range=[t[t.length-(B||1)].range[0],t[t.length-1].range[1]]),Q=this.performAction.apply(W,[r,Y,R,K.yy,z[1],h,t].concat(Le)),typeof Q<"u")return Q;B&&(i=i.slice(0,-1*B*2),h=h.slice(0,-1*B),t=t.slice(0,-1*B)),i.push(this.productions_[z[1]][0]),h.push(W.$),t.push(W._$),ae=m[i[i.length-2]][i[i.length-1]],i.push(ae);break;case 3:return!0}}return!0}},A=function(){var D={EOF:1,parseError:function(s,i){if(this.yy.parser)this.yy.parser.parseError(s,i);else throw new Error(s)},setInput:function(o,s){return this.yy=s||this.yy||{},this._input=o,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var o=this._input[0];this.yytext+=o,this.yyleng++,this.offset++,this.match+=o,this.matched+=o;var s=o.match(/(?:\r\n?|\n).*/g);return s?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),o},unput:function(o){var s=o.length,i=o.split(/(?:\r\n?|\n)/g);this._input=o+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-s),this.offset-=s;var u=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),i.length-1&&(this.yylineno-=i.length-1);var h=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:i?(i.length===u.length?this.yylloc.first_column:0)+u[u.length-i.length].length-i[0].length:this.yylloc.first_column-s},this.options.ranges&&(this.yylloc.range=[h[0],h[0]+this.yyleng-s]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
 `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(o){this.unput(this.match.slice(o))},pastInput:function(){var o=this.matched.substr(0,this.matched.length-this.match.length);return(o.length>20?"...":"")+o.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var o=this.match;return o.length<20&&(o+=this._input.substr(0,20-o.length)),(o.substr(0,20)+(o.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var o=this.pastInput(),s=new Array(o.length+1).join("-");return o+this.upcomingInput()+`
diff --git a/assets/browser_dialer.html-C3dkn1hN.js b/assets/browser_dialer.html-B00Yg-45.js
similarity index 99%
rename from assets/browser_dialer.html-C3dkn1hN.js
rename to assets/browser_dialer.html-B00Yg-45.js
index 81e9431e38..70bd3d16b8 100644
--- a/assets/browser_dialer.html-C3dkn1hN.js
+++ b/assets/browser_dialer.html-B00Yg-45.js
@@ -1 +1 @@
-import{_ as i,r as n,o as d,c as h,a as t,d as o,b as e,w as r,e as _}from"./app-5SoadDYS.js";const u={},p=e("h1",{id:"browser-dialer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#browser-dialer"},[e("span",null,"Browser Dialer")])],-1),S=e("h2",{id:"предыстория",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#предыстория"},[e("span",null,"Предыстория")])],-1),T=e("p",null,[o("Xray обычно использует uTLS для имитации поведения популярных браузеров, и им можно управлять с помощью настройки "),e("code",null,"fingerprint"),o(". Однако отпечатки, создаваемые uTLS, являются несовершенной копией реальных, и поскольку uTLS является популярной библиотекой, они сами могут стать целью.")],-1),b={href:"https://github.com/v2ray/discussion/issues/754#issuecomment-647934994",target:"_blank",rel:"noopener noreferrer"},f=e("code",null,"localhost:8080",-1),m=e("p",null,"Таким образом, поведение снятия отпечатков TLS является идеальным, и поэтому может быть возможно оживить серверы, которые отлично открываются как веб-сайты в браузере, но не подключаются с использованием какого-либо программного обеспечения для проксирования.",-1),x=e("p",null,"Однако есть много недостатков:",-1),y=e("li",null,"Пользователь должен запускать браузер рядом с клиентом Xray только для открытия прокси-соединения.",-1),g=e("li",null,"Browser Dialer не должен быть туннелирован через сам прокси, иначе возникнет петля. Пользователи TUN должны быть осторожны.",-1),w={href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS",target:"_blank",rel:"noopener noreferrer"},R=e("code",null,"localhost:8080",-1),k=e("code",null,"proxy.example.com:443",-1),X=e("li",null,"Браузер туннелирует ваш трафик с помощью JavaScript, поэтому наблюдается значительное снижение производительности (или разрядка аккумулятора).",-1),L=e("li",null,[o("Конфигурация, используемая с Browser Dialer, не может использовать собственные заголовки SNI или хоста. "),e("code",null,"SNI == host == address"),o(". Пользовательские заголовки HTTP и "),e("code",null,"tlsSettings"),o(" игнорируются полностью.")],-1),B=_('

Конфигурация

  1. Подготовьте рабочую конфигурацию WebSocket или SplitHTTP. Помните о вышеуказанных ограничениях.
  2. Запустите Xray с помощью XRAY_BROWSER_DIALER=127.0.0.1:8080. В Windows это можно сделать как set XRAY_BROWSER_DIALER=..., а затем запустить ядро из консоли, в Linux ядро можно запустить как XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json.
  3. Откройте браузер, который не туннелирован через прокси, или измените маршрутизацию конфигурации таким образом, чтобы домен сервера Xray переходил к freedom непосредственно с клиента. Перейдите по адресу localhost:8080 и откройте консоль разработчика с помощью F12, чтобы отслеживать ошибки.
  4. Для повышения производительности и обхода произвольных ограничений на подключение, применяемых браузером, рекомендуется включить Mux.Cool.

Внутренняя работа

  • Xray прослушивает http://127.0.0.1:8080, а браузер обращается к http://127.0.0.1:8080, чтобы загрузить JS на веб-страницу.
  • JS активно устанавливает соединение WebSocket с http://127.0.0.1:8080. Xray будет использовать это соединение для отправки инструкций, но пока оно попадает в пул соединений (реализованный как канал Go).
  • Когда необходимо установить соединение, Xray получает доступное соединение из пула и отправляет имя протокола, целевой URL-адрес и необязательные ранние данные.
  • Как только JS успешно подключается к цели, он сообщает об этом Xray и продолжает использовать это соединение для двунаправленной пересылки данных.
  • После закрытия соединения с сервером соединение с localhost также закрывается, но JS гарантирует, что всегда доступно как минимум одно незанятое соединение.

WebSocket

',5),E=e("p",null,"В соответствии с потребностями браузера механизм ранних данных был скорректирован следующим образом:",-1),I=e("li",null,[o("Заголовок ответа сервера будет содержать запрошенный "),e("code",null,"Sec-WebSocket-Protocol"),o(", который также изначально obfuscates the length characteristic of the WSS handshake response.")],-1),P=e("li",null,[o("Кодировка, используемая для ранних данных для браузеров, - это "),e("code",null,"base64.RawURLEncoding"),o(" вместо "),e("code",null,"StdEncoding"),o(", и сервер сделал ее совместимой.")],-1),W={href:"https://github.com/XTLS/Xray-core/pull/375",target:"_blank",rel:"noopener noreferrer"},v=e("code",null,"?ed=2048",-1),H=e("code",null,"MaxHeaderBytes",-1),C=e("s",null,"(Хотя, похоже, это будет работать и без модификации.)",-1),D=e("h2",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),N=e("p",null,[o("SplitHTTP поддерживает QUIC, но также может использоваться собственный стек QUIC браузера. В Chrome это можно сделать через "),e("code",null,"chrome://flags"),o(", в других браузерах он может быть уже включен или для него может потребоваться другой флаг.")],-1),A=e("p",null,[o("В общем, "),e("code",null,"tlsSettings"),o(" полностью игнорируются при использовании Browser Dialer. Xray никак не контролирует, какую версию HTTP выбирает браузер.")],-1);function J(U,O){const a=n("I18nTip"),l=n("Badge"),s=n("ExternalLinkIcon"),c=n("RouterLink");return d(),h("div",null,[t(a),p,t(l,{text:"БЕТА",type:"warning"}),o(),t(l,{text:"v1.4.1+",type:"warning"}),S,T,e("p",null,[o("Итак, "),e("a",b,[o("идея Browser Dialer"),t(s)]),o(" заключается в том, что Xray использует настоящий браузер для установления TLS-соединений. Это работает так: Xray запускает небольшой веб-сайт на "),f,o(", пользователь открывает этот веб-сайт в выбранном им браузере, а JavaScript на этой странице будет действовать как сетевой стек Xray (HTTP-клиент, TLS-клиент).")]),m,x,e("ul",null,[y,g,e("li",null,[o("Браузер может работать только со стандартным HTTP, что означает, что поддерживаются только "),t(c,{to:"/ru/transports/websocket.html"},{default:r(()=>[o("WebSocket")]),_:1}),o(" и "),t(c,{to:"/ru/transports/splithttp.html"},{default:r(()=>[o("SplitHTTP")]),_:1}),o(".")]),e("li",null,[e("a",w,[o("CORS"),t(s)]),o(" необходимо учитывать при выполнении запросов с одного веб-сайта ("),R,o(") на другой ("),k,o(").")]),X,L]),B,t(l,{text:"v1.4.1+",type:"warning"}),E,e("ul",null,[I,P,e("li",null,[o("Кроме того, в связи с "),e("a",W,[o("Xray-core#375"),t(s)]),o(" рекомендациями по "),v,o(" этот PR также увеличил сервер "),H,o(" на 4096. "),C])]),D,t(l,{text:"v1.8.19+",type:"warning"}),N,A])}const Y=i(u,[["render",J],["__file","browser_dialer.html.vue"]]);export{Y as default}; +import{_ as i,r as n,o as d,c as h,a as t,d as o,b as e,w as r,e as _}from"./app-Bw2NG-QJ.js";const u={},p=e("h1",{id:"browser-dialer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#browser-dialer"},[e("span",null,"Browser Dialer")])],-1),S=e("h2",{id:"предыстория",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#предыстория"},[e("span",null,"Предыстория")])],-1),T=e("p",null,[o("Xray обычно использует uTLS для имитации поведения популярных браузеров, и им можно управлять с помощью настройки "),e("code",null,"fingerprint"),o(". Однако отпечатки, создаваемые uTLS, являются несовершенной копией реальных, и поскольку uTLS является популярной библиотекой, они сами могут стать целью.")],-1),b={href:"https://github.com/v2ray/discussion/issues/754#issuecomment-647934994",target:"_blank",rel:"noopener noreferrer"},f=e("code",null,"localhost:8080",-1),m=e("p",null,"Таким образом, поведение снятия отпечатков TLS является идеальным, и поэтому может быть возможно оживить серверы, которые отлично открываются как веб-сайты в браузере, но не подключаются с использованием какого-либо программного обеспечения для проксирования.",-1),x=e("p",null,"Однако есть много недостатков:",-1),y=e("li",null,"Пользователь должен запускать браузер рядом с клиентом Xray только для открытия прокси-соединения.",-1),g=e("li",null,"Browser Dialer не должен быть туннелирован через сам прокси, иначе возникнет петля. Пользователи TUN должны быть осторожны.",-1),w={href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS",target:"_blank",rel:"noopener noreferrer"},R=e("code",null,"localhost:8080",-1),k=e("code",null,"proxy.example.com:443",-1),X=e("li",null,"Браузер туннелирует ваш трафик с помощью JavaScript, поэтому наблюдается значительное снижение производительности (или разрядка аккумулятора).",-1),L=e("li",null,[o("Конфигурация, используемая с Browser Dialer, не может использовать собственные заголовки SNI или хоста. "),e("code",null,"SNI == host == address"),o(". Пользовательские заголовки HTTP и "),e("code",null,"tlsSettings"),o(" игнорируются полностью.")],-1),B=_('

Конфигурация

  1. Подготовьте рабочую конфигурацию WebSocket или SplitHTTP. Помните о вышеуказанных ограничениях.
  2. Запустите Xray с помощью XRAY_BROWSER_DIALER=127.0.0.1:8080. В Windows это можно сделать как set XRAY_BROWSER_DIALER=..., а затем запустить ядро из консоли, в Linux ядро можно запустить как XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json.
  3. Откройте браузер, который не туннелирован через прокси, или измените маршрутизацию конфигурации таким образом, чтобы домен сервера Xray переходил к freedom непосредственно с клиента. Перейдите по адресу localhost:8080 и откройте консоль разработчика с помощью F12, чтобы отслеживать ошибки.
  4. Для повышения производительности и обхода произвольных ограничений на подключение, применяемых браузером, рекомендуется включить Mux.Cool.

Внутренняя работа

  • Xray прослушивает http://127.0.0.1:8080, а браузер обращается к http://127.0.0.1:8080, чтобы загрузить JS на веб-страницу.
  • JS активно устанавливает соединение WebSocket с http://127.0.0.1:8080. Xray будет использовать это соединение для отправки инструкций, но пока оно попадает в пул соединений (реализованный как канал Go).
  • Когда необходимо установить соединение, Xray получает доступное соединение из пула и отправляет имя протокола, целевой URL-адрес и необязательные ранние данные.
  • Как только JS успешно подключается к цели, он сообщает об этом Xray и продолжает использовать это соединение для двунаправленной пересылки данных.
  • После закрытия соединения с сервером соединение с localhost также закрывается, но JS гарантирует, что всегда доступно как минимум одно незанятое соединение.

WebSocket

',5),E=e("p",null,"В соответствии с потребностями браузера механизм ранних данных был скорректирован следующим образом:",-1),I=e("li",null,[o("Заголовок ответа сервера будет содержать запрошенный "),e("code",null,"Sec-WebSocket-Protocol"),o(", который также изначально obfuscates the length characteristic of the WSS handshake response.")],-1),P=e("li",null,[o("Кодировка, используемая для ранних данных для браузеров, - это "),e("code",null,"base64.RawURLEncoding"),o(" вместо "),e("code",null,"StdEncoding"),o(", и сервер сделал ее совместимой.")],-1),W={href:"https://github.com/XTLS/Xray-core/pull/375",target:"_blank",rel:"noopener noreferrer"},v=e("code",null,"?ed=2048",-1),H=e("code",null,"MaxHeaderBytes",-1),C=e("s",null,"(Хотя, похоже, это будет работать и без модификации.)",-1),D=e("h2",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),N=e("p",null,[o("SplitHTTP поддерживает QUIC, но также может использоваться собственный стек QUIC браузера. В Chrome это можно сделать через "),e("code",null,"chrome://flags"),o(", в других браузерах он может быть уже включен или для него может потребоваться другой флаг.")],-1),A=e("p",null,[o("В общем, "),e("code",null,"tlsSettings"),o(" полностью игнорируются при использовании Browser Dialer. Xray никак не контролирует, какую версию HTTP выбирает браузер.")],-1);function J(U,O){const a=n("I18nTip"),l=n("Badge"),s=n("ExternalLinkIcon"),c=n("RouterLink");return d(),h("div",null,[t(a),p,t(l,{text:"БЕТА",type:"warning"}),o(),t(l,{text:"v1.4.1+",type:"warning"}),S,T,e("p",null,[o("Итак, "),e("a",b,[o("идея Browser Dialer"),t(s)]),o(" заключается в том, что Xray использует настоящий браузер для установления TLS-соединений. Это работает так: Xray запускает небольшой веб-сайт на "),f,o(", пользователь открывает этот веб-сайт в выбранном им браузере, а JavaScript на этой странице будет действовать как сетевой стек Xray (HTTP-клиент, TLS-клиент).")]),m,x,e("ul",null,[y,g,e("li",null,[o("Браузер может работать только со стандартным HTTP, что означает, что поддерживаются только "),t(c,{to:"/ru/transports/websocket.html"},{default:r(()=>[o("WebSocket")]),_:1}),o(" и "),t(c,{to:"/ru/transports/splithttp.html"},{default:r(()=>[o("SplitHTTP")]),_:1}),o(".")]),e("li",null,[e("a",w,[o("CORS"),t(s)]),o(" необходимо учитывать при выполнении запросов с одного веб-сайта ("),R,o(") на другой ("),k,o(").")]),X,L]),B,t(l,{text:"v1.4.1+",type:"warning"}),E,e("ul",null,[I,P,e("li",null,[o("Кроме того, в связи с "),e("a",W,[o("Xray-core#375"),t(s)]),o(" рекомендациями по "),v,o(" этот PR также увеличил сервер "),H,o(" на 4096. "),C])]),D,t(l,{text:"v1.8.19+",type:"warning"}),N,A])}const Y=i(u,[["render",J],["__file","browser_dialer.html.vue"]]);export{Y as default}; diff --git a/assets/browser_dialer.html-BIzbQgRR.js b/assets/browser_dialer.html-C_TsP8h-.js similarity index 98% rename from assets/browser_dialer.html-BIzbQgRR.js rename to assets/browser_dialer.html-C_TsP8h-.js index 715537c0e8..7e200791e6 100644 --- a/assets/browser_dialer.html-BIzbQgRR.js +++ b/assets/browser_dialer.html-C_TsP8h-.js @@ -1 +1 @@ -import{_ as d,r as l,o as i,c as _,a as t,b as e,d as o,w as a,e as h}from"./app-5SoadDYS.js";const u={},p=e("h1",{id:"browser-dialer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#browser-dialer"},[e("span",null,"Browser Dialer")])],-1),S=e("h2",{id:"背景",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#背景"},[e("span",null,"背景")])],-1),T=e("p",null,[o("通过 uTLS,Xray 可以模拟主流浏览器的 TLS 握手指纹(具体参见 TLS 中 "),e("code",null,"fingerprint"),o(" 选项)。但是仍然不能保证在任意时刻 uTLS 模拟浏览器行为完全一致。")],-1),b={href:"https://github.com/v2ray/discussion/issues/754#issuecomment-647934994",target:"_blank",rel:"noopener noreferrer"},f=e("code",null,"localhost:8080",-1),m=e("p",null,"这个方法简洁的实现了真实的浏览器的 TLS 指纹、行为特征。最大程度抗检测与抗封锁。",-1),R=e("p",null,"不过目前的浏览器转发有以下缺点:",-1),x=e("li",null,"用户需要手动开浏览器",-1),k=e("li",null,"浏览器发出的连接必须直连 使用 tun 的用户需要特别注意容易形成死循环",-1),g=e("code",null,"localhost:8080",-1),y={href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS",target:"_blank",rel:"noopener noreferrer"},L=e("li",null,"因为中间经过 JS 处理数据,会有一些性能损耗",-1),w=e("li",null,[o("不能使用自定义 SNI 或者 Host,也就是说 "),e("code",null,"SNI == host == address"),o("。自定义 HTTP 头以及其它 "),e("code",null,"tlsSettings"),o(" 项会被忽略")],-1),P=h('

配置方法

  1. 准备一份 WebSocket 或 SplitHTTP 配置,注意 address 必须填域名,若需要指定 IP,请配置 DNS 或系统 hosts
  2. 使用环境变量启动 Xray XRAY_BROWSER_DIALER=127.0.0.1:8080。Windows 上命令为 set XRAY_BROWSER_DIALER=127.0.0.1:8080 Linux 上命令为 XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json
  3. 确保浏览器直连(或者在路由中将服务端地址直接由 freedom 发出),打开页面 localhost:8080,还可以 F12ConsoleNetwork
  4. 浏览器会限制发出的连接数,所以建议开启 Mux.Cool

内部通信机制

  • Xray 监听地址端口 http://127.0.0.1:8080,作为 HTTP 服务,浏览器访问地址,加载网页中的 JS。
  • JS 主动向 http://127.0.0.1:8080 建立 WebSocket 连接,成功后,Xray 将连接发给 channel。
  • 需要建立连接时,Xray 从 channel 接收一个可用的连接,并发送目标 URL 和可选的 early data。
  • JS 成功连接到目标后告知 Xray,并继续用这个 conn 全双工双向转发数据,连接关闭行为同步。
  • 连接使用后就会被关闭,但 JS 会确保始终有新空闲连接可用。

WebSocket

',5),X=e("p",null,"根据浏览器的需求,对 early data 机制进行了如下调整:",-1),H=e("li",null,[o("服务端响应头会带有请求的 "),e("code",null,"Sec-WebSocket-Protocol"),o(",这也初步混淆了 WSS 握手响应的长度特征。")],-1),I=e("li",null,[o("用于浏览器的 early data 编码是 "),e("code",null,"base64.RawURLEncoding"),o(" 而不是 "),e("code",null,"StdEncoding"),o(",服务端做了兼容。")],-1),E={href:"https://github.com/XTLS/Xray-core/pull/375",target:"_blank",rel:"noopener noreferrer"},W=e("code",null,"?ed=2048",-1),B=e("code",null,"MaxHeaderBytes",-1),C=e("s",null,"(虽然好像不改也没问题)",-1),N=e("h2",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),v=e("p",null,[o("SplitHTTP 本身支持 QUIC,如果想使用浏览器自己的 QUIC 网络栈,Chrome 可以在 "),e("code",null,"chrome://flags"),o(" 中设定。其它浏览器也有相关选项。")],-1),A=e("p",null,[o("原理上说 "),e("code",null,"tlsSettings"),o(" 项会被忽略,使用哪个 HTTP 版本将完全由浏览器决定。")],-1);function J(D,O){const r=l("I18nTip"),n=l("ExternalLinkIcon"),s=l("RouterLink"),c=l("Badge");return i(),_("div",null,[t(r),p,S,T,e("p",null,[o("对此 "),e("a",b,[o("浏览器转发(browser dialer)"),t(n)]),o("应运而生。用户在自己的浏览器中打开一个页面至 "),f,o(",这个页面利用原生 JS 充当 Xray 的网络栈,与代理服务端建立 TLS,HTTP 连接。")]),m,R,e("ul",null,[x,k,e("li",null,[o("浏览器只能发出 HTTP 连接 所以目前仅支持 "),t(s,{to:"/transports/websocket.html"},{default:a(()=>[o("WebSocket")]),_:1}),o(" 与 "),t(s,{to:"/transports/splithttp.html"},{default:a(()=>[o("SplitHTTP")]),_:1}),o(" 传输方式")]),e("li",null,[o("当浏览器从 "),g,o(" 页面连接至代理服务端,需要考虑 "),e("a",y,[o("CORS"),t(n)])]),L,w]),P,t(c,{text:"v1.4.1+",type:"warning"}),X,e("ul",null,[H,I,e("li",null,[o("此外,由于 "),e("a",E,[o("Xray-core#375"),t(n)]),o(" 推荐 "),W,o(",这个 PR 顺便将服务端一处 "),B,o(" 扩至了 4096。 "),C])]),N,t(c,{text:"v1.8.19+",type:"warning"}),v,A])}const V=d(u,[["render",J],["__file","browser_dialer.html.vue"]]);export{V as default}; +import{_ as d,r as l,o as i,c as _,a as t,b as e,d as o,w as a,e as h}from"./app-Bw2NG-QJ.js";const u={},p=e("h1",{id:"browser-dialer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#browser-dialer"},[e("span",null,"Browser Dialer")])],-1),S=e("h2",{id:"背景",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#背景"},[e("span",null,"背景")])],-1),T=e("p",null,[o("通过 uTLS,Xray 可以模拟主流浏览器的 TLS 握手指纹(具体参见 TLS 中 "),e("code",null,"fingerprint"),o(" 选项)。但是仍然不能保证在任意时刻 uTLS 模拟浏览器行为完全一致。")],-1),b={href:"https://github.com/v2ray/discussion/issues/754#issuecomment-647934994",target:"_blank",rel:"noopener noreferrer"},f=e("code",null,"localhost:8080",-1),m=e("p",null,"这个方法简洁的实现了真实的浏览器的 TLS 指纹、行为特征。最大程度抗检测与抗封锁。",-1),R=e("p",null,"不过目前的浏览器转发有以下缺点:",-1),x=e("li",null,"用户需要手动开浏览器",-1),k=e("li",null,"浏览器发出的连接必须直连 使用 tun 的用户需要特别注意容易形成死循环",-1),g=e("code",null,"localhost:8080",-1),y={href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS",target:"_blank",rel:"noopener noreferrer"},L=e("li",null,"因为中间经过 JS 处理数据,会有一些性能损耗",-1),w=e("li",null,[o("不能使用自定义 SNI 或者 Host,也就是说 "),e("code",null,"SNI == host == address"),o("。自定义 HTTP 头以及其它 "),e("code",null,"tlsSettings"),o(" 项会被忽略")],-1),P=h('

配置方法

  1. 准备一份 WebSocket 或 SplitHTTP 配置,注意 address 必须填域名,若需要指定 IP,请配置 DNS 或系统 hosts
  2. 使用环境变量启动 Xray XRAY_BROWSER_DIALER=127.0.0.1:8080。Windows 上命令为 set XRAY_BROWSER_DIALER=127.0.0.1:8080 Linux 上命令为 XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json
  3. 确保浏览器直连(或者在路由中将服务端地址直接由 freedom 发出),打开页面 localhost:8080,还可以 F12ConsoleNetwork
  4. 浏览器会限制发出的连接数,所以建议开启 Mux.Cool

内部通信机制

  • Xray 监听地址端口 http://127.0.0.1:8080,作为 HTTP 服务,浏览器访问地址,加载网页中的 JS。
  • JS 主动向 http://127.0.0.1:8080 建立 WebSocket 连接,成功后,Xray 将连接发给 channel。
  • 需要建立连接时,Xray 从 channel 接收一个可用的连接,并发送目标 URL 和可选的 early data。
  • JS 成功连接到目标后告知 Xray,并继续用这个 conn 全双工双向转发数据,连接关闭行为同步。
  • 连接使用后就会被关闭,但 JS 会确保始终有新空闲连接可用。

WebSocket

',5),X=e("p",null,"根据浏览器的需求,对 early data 机制进行了如下调整:",-1),H=e("li",null,[o("服务端响应头会带有请求的 "),e("code",null,"Sec-WebSocket-Protocol"),o(",这也初步混淆了 WSS 握手响应的长度特征。")],-1),I=e("li",null,[o("用于浏览器的 early data 编码是 "),e("code",null,"base64.RawURLEncoding"),o(" 而不是 "),e("code",null,"StdEncoding"),o(",服务端做了兼容。")],-1),E={href:"https://github.com/XTLS/Xray-core/pull/375",target:"_blank",rel:"noopener noreferrer"},W=e("code",null,"?ed=2048",-1),B=e("code",null,"MaxHeaderBytes",-1),C=e("s",null,"(虽然好像不改也没问题)",-1),N=e("h2",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),v=e("p",null,[o("SplitHTTP 本身支持 QUIC,如果想使用浏览器自己的 QUIC 网络栈,Chrome 可以在 "),e("code",null,"chrome://flags"),o(" 中设定。其它浏览器也有相关选项。")],-1),A=e("p",null,[o("原理上说 "),e("code",null,"tlsSettings"),o(" 项会被忽略,使用哪个 HTTP 版本将完全由浏览器决定。")],-1);function J(D,O){const r=l("I18nTip"),n=l("ExternalLinkIcon"),s=l("RouterLink"),c=l("Badge");return i(),_("div",null,[t(r),p,S,T,e("p",null,[o("对此 "),e("a",b,[o("浏览器转发(browser dialer)"),t(n)]),o("应运而生。用户在自己的浏览器中打开一个页面至 "),f,o(",这个页面利用原生 JS 充当 Xray 的网络栈,与代理服务端建立 TLS,HTTP 连接。")]),m,R,e("ul",null,[x,k,e("li",null,[o("浏览器只能发出 HTTP 连接 所以目前仅支持 "),t(s,{to:"/transports/websocket.html"},{default:a(()=>[o("WebSocket")]),_:1}),o(" 与 "),t(s,{to:"/transports/splithttp.html"},{default:a(()=>[o("SplitHTTP")]),_:1}),o(" 传输方式")]),e("li",null,[o("当浏览器从 "),g,o(" 页面连接至代理服务端,需要考虑 "),e("a",y,[o("CORS"),t(n)])]),L,w]),P,t(c,{text:"v1.4.1+",type:"warning"}),X,e("ul",null,[H,I,e("li",null,[o("此外,由于 "),e("a",E,[o("Xray-core#375"),t(n)]),o(" 推荐 "),W,o(",这个 PR 顺便将服务端一处 "),B,o(" 扩至了 4096。 "),C])]),N,t(c,{text:"v1.8.19+",type:"warning"}),v,A])}const V=d(u,[["render",J],["__file","browser_dialer.html.vue"]]);export{V as default}; diff --git a/assets/browser_dialer.html-D_VAS8oa.js b/assets/browser_dialer.html-DTufXirY.js similarity index 99% rename from assets/browser_dialer.html-D_VAS8oa.js rename to assets/browser_dialer.html-DTufXirY.js index b57075d350..c2a60253a3 100644 --- a/assets/browser_dialer.html-D_VAS8oa.js +++ b/assets/browser_dialer.html-DTufXirY.js @@ -1 +1 @@ -import{_ as c,r as s,o as h,c as d,a as t,d as o,b as e,w as i,e as u}from"./app-5SoadDYS.js";const p={},b=e("h1",{id:"browser-dialer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#browser-dialer"},[e("span",null,"Browser Dialer")])],-1),_=e("h2",{id:"background",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#background"},[e("span",null,"Background")])],-1),w=e("p",null,[o("Xray generally uses uTLS to mimic the behavior of popular browsers, and it can be controlled through the "),e("code",null,"fingerprint"),o(" setting. However, the fingerprints produced by uTLS are an imperfect replica of the real thing, and because uTLS is a popular library, they may be targeted themselves.")],-1),f={href:"https://github.com/v2ray/discussion/issues/754#issuecomment-647934994",target:"_blank",rel:"noopener noreferrer"},g=e("code",null,"localhost:8080",-1),m=e("p",null,"The TLS fingerprinting behavior is perfect this way, and so it may be possible to revive servers that open fine as websites in the browser, but do not connect using any proxying software.",-1),y=e("p",null,"However, there are many drawbacks:",-1),T=e("li",null,"The user has to launch a browser next to the Xray client just for opening the proxy connection.",-1),S=e("li",null,"The browser dialer must not be tunneled through the proxy itself, otherwise there is a loop. TUN users should be cautious.",-1),k={href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS",target:"_blank",rel:"noopener noreferrer"},v=e("code",null,"localhost:8080",-1),x=e("code",null,"proxy.example.com:443",-1),R=e("li",null,"The browser tunnels your traffic using JavaScript, so there is a significant performance penalty (or, battery drain)",-1),L=e("li",null,[o("The configuration to be used with browser dialer cannot use custom SNI or host headers. "),e("code",null,"SNI == host == address"),o(". Custom HTTP headers and "),e("code",null,"tlsSettings"),o(" are ignored entirely.")],-1),X=u('

Configuration

  1. Prepare a usable WebSocket or SplitHTTP configuration. Be aware of the above restrictions.
  2. Launch Xray with XRAY_BROWSER_DIALER=127.0.0.1:8080. On Windows, this can be done as set XRAY_BROWSER_DIALER=... and then launching the core from the console, on Linux the core can be launched as XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json.
  3. Open a browser that is not tunneled through the proxy, or modify the config's routing such that the Xray server's domain goes to freedom directly from the client. Browse to localhost:8080, and open the developer console with F12 to monitor for errors.
  4. For better performance and to bypass arbitrary connection limits enforced by the browser, it is recommended to enable Mux.Cool.

Inner workings

  • Xray listens on http://127.0.0.1:8080, and the browser accesses http://127.0.0.1:8080 to load the JS in the webpage.
  • The JS actively establishes a WebSocket connection to http://127.0.0.1:8080. Xray will use this connection to send instructions, but for now it goes into a connection pool (implemented as Go channel).
  • When a connection needs to be established, Xray receives an available connection from the pool and sends the protocol name, target URL and optional early data.
  • Once the JS successfully connects to the target, it informs Xray and continues to use this conn to bi-directionally forward data.
  • After the connection to the server is closed, the connection to localhost is also closed, but the JS ensures that there is always at least one idle connection available.

WebSocket

',5),B=e("p",null,"According to the browser's needs, the early data mechanism has been adjusted as follows:",-1),I=e("li",null,[o("The server response header will contain the requested "),e("code",null,"Sec-WebSocket-Protocol"),o(", which also initially obfuscates the length characteristic of the WSS handshake response.")],-1),E=e("li",null,[o("The encoding used for early data for browsers is "),e("code",null,"base64.RawURLEncoding"),o(" instead of "),e("code",null,"StdEncoding"),o(", and the server has made it compatible.")],-1),H={href:"https://github.com/XTLS/Xray-core/pull/375",target:"_blank",rel:"noopener noreferrer"},P=e("code",null,"?ed=2048",-1),W=e("code",null,"MaxHeaderBytes",-1),A=e("s",null,"(Although it seems like it would work without modification.)",-1),C=e("h2",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),O=e("p",null,[o("SplitHTTP supports QUIC, but the browser's own QUIC stack may be used as well. In Chrome this can be done through "),e("code",null,"chrome://flags"),o(", in other browsers it may already be enabled or need a different flag.")],-1),N=e("p",null,[o("In general, "),e("code",null,"tlsSettings"),o(" are completely ignored when Browser Dialer is used. Xray does not have any control over which HTTP version the browser selects.")],-1);function J(U,D){const l=s("I18nTip"),n=s("Badge"),r=s("ExternalLinkIcon"),a=s("RouterLink");return h(),d("div",null,[t(l),b,t(n,{text:"BETA",type:"warning"}),o(),t(n,{text:"v1.4.1+",type:"warning"}),_,w,e("p",null,[o("So "),e("a",f,[o("the idea of browser dialer"),t(r)]),o(" is that Xray uses a real browser to establish TLS connections. The way this works is that Xray hosts a small website on "),g,o(", the user opens this website in a browser of their choice, and JavaScript on that page will act as Xray's networking stack (HTTP client, TLS client).")]),m,y,e("ul",null,[T,S,e("li",null,[o("The browser can only speak standard HTTP, which means that only "),t(a,{to:"/en/transports/websocket.html"},{default:i(()=>[o("WebSocket")]),_:1}),o(" and "),t(a,{to:"/en/transports/splithttp.html"},{default:i(()=>[o("SplitHTTP")]),_:1}),o(" are supported")]),e("li",null,[e("a",k,[o("CORS"),t(r)]),o(" needs to be considered when making requests from one website ("),v,o(") to another ("),x,o(")")]),R,L]),X,t(n,{text:"v1.4.1+",type:"warning"}),B,e("ul",null,[I,E,e("li",null,[o("In addition, due to "),e("a",H,[o("Xray-core#375"),t(r)]),o(" recommendations for "),P,o(", this PR also increased server "),W,o(" by 4096. "),A])]),C,t(n,{text:"v1.8.19+",type:"warning"}),O,N])}const j=c(p,[["render",J],["__file","browser_dialer.html.vue"]]);export{j as default}; +import{_ as c,r as s,o as h,c as d,a as t,d as o,b as e,w as i,e as u}from"./app-Bw2NG-QJ.js";const p={},b=e("h1",{id:"browser-dialer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#browser-dialer"},[e("span",null,"Browser Dialer")])],-1),_=e("h2",{id:"background",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#background"},[e("span",null,"Background")])],-1),w=e("p",null,[o("Xray generally uses uTLS to mimic the behavior of popular browsers, and it can be controlled through the "),e("code",null,"fingerprint"),o(" setting. However, the fingerprints produced by uTLS are an imperfect replica of the real thing, and because uTLS is a popular library, they may be targeted themselves.")],-1),f={href:"https://github.com/v2ray/discussion/issues/754#issuecomment-647934994",target:"_blank",rel:"noopener noreferrer"},g=e("code",null,"localhost:8080",-1),m=e("p",null,"The TLS fingerprinting behavior is perfect this way, and so it may be possible to revive servers that open fine as websites in the browser, but do not connect using any proxying software.",-1),y=e("p",null,"However, there are many drawbacks:",-1),T=e("li",null,"The user has to launch a browser next to the Xray client just for opening the proxy connection.",-1),S=e("li",null,"The browser dialer must not be tunneled through the proxy itself, otherwise there is a loop. TUN users should be cautious.",-1),k={href:"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS",target:"_blank",rel:"noopener noreferrer"},v=e("code",null,"localhost:8080",-1),x=e("code",null,"proxy.example.com:443",-1),R=e("li",null,"The browser tunnels your traffic using JavaScript, so there is a significant performance penalty (or, battery drain)",-1),L=e("li",null,[o("The configuration to be used with browser dialer cannot use custom SNI or host headers. "),e("code",null,"SNI == host == address"),o(". Custom HTTP headers and "),e("code",null,"tlsSettings"),o(" are ignored entirely.")],-1),X=u('

Configuration

  1. Prepare a usable WebSocket or SplitHTTP configuration. Be aware of the above restrictions.
  2. Launch Xray with XRAY_BROWSER_DIALER=127.0.0.1:8080. On Windows, this can be done as set XRAY_BROWSER_DIALER=... and then launching the core from the console, on Linux the core can be launched as XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json.
  3. Open a browser that is not tunneled through the proxy, or modify the config's routing such that the Xray server's domain goes to freedom directly from the client. Browse to localhost:8080, and open the developer console with F12 to monitor for errors.
  4. For better performance and to bypass arbitrary connection limits enforced by the browser, it is recommended to enable Mux.Cool.

Inner workings

  • Xray listens on http://127.0.0.1:8080, and the browser accesses http://127.0.0.1:8080 to load the JS in the webpage.
  • The JS actively establishes a WebSocket connection to http://127.0.0.1:8080. Xray will use this connection to send instructions, but for now it goes into a connection pool (implemented as Go channel).
  • When a connection needs to be established, Xray receives an available connection from the pool and sends the protocol name, target URL and optional early data.
  • Once the JS successfully connects to the target, it informs Xray and continues to use this conn to bi-directionally forward data.
  • After the connection to the server is closed, the connection to localhost is also closed, but the JS ensures that there is always at least one idle connection available.

WebSocket

',5),B=e("p",null,"According to the browser's needs, the early data mechanism has been adjusted as follows:",-1),I=e("li",null,[o("The server response header will contain the requested "),e("code",null,"Sec-WebSocket-Protocol"),o(", which also initially obfuscates the length characteristic of the WSS handshake response.")],-1),E=e("li",null,[o("The encoding used for early data for browsers is "),e("code",null,"base64.RawURLEncoding"),o(" instead of "),e("code",null,"StdEncoding"),o(", and the server has made it compatible.")],-1),H={href:"https://github.com/XTLS/Xray-core/pull/375",target:"_blank",rel:"noopener noreferrer"},P=e("code",null,"?ed=2048",-1),W=e("code",null,"MaxHeaderBytes",-1),A=e("s",null,"(Although it seems like it would work without modification.)",-1),C=e("h2",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),O=e("p",null,[o("SplitHTTP supports QUIC, but the browser's own QUIC stack may be used as well. In Chrome this can be done through "),e("code",null,"chrome://flags"),o(", in other browsers it may already be enabled or need a different flag.")],-1),N=e("p",null,[o("In general, "),e("code",null,"tlsSettings"),o(" are completely ignored when Browser Dialer is used. Xray does not have any control over which HTTP version the browser selects.")],-1);function J(U,D){const l=s("I18nTip"),n=s("Badge"),r=s("ExternalLinkIcon"),a=s("RouterLink");return h(),d("div",null,[t(l),b,t(n,{text:"BETA",type:"warning"}),o(),t(n,{text:"v1.4.1+",type:"warning"}),_,w,e("p",null,[o("So "),e("a",f,[o("the idea of browser dialer"),t(r)]),o(" is that Xray uses a real browser to establish TLS connections. The way this works is that Xray hosts a small website on "),g,o(", the user opens this website in a browser of their choice, and JavaScript on that page will act as Xray's networking stack (HTTP client, TLS client).")]),m,y,e("ul",null,[T,S,e("li",null,[o("The browser can only speak standard HTTP, which means that only "),t(a,{to:"/en/transports/websocket.html"},{default:i(()=>[o("WebSocket")]),_:1}),o(" and "),t(a,{to:"/en/transports/splithttp.html"},{default:i(()=>[o("SplitHTTP")]),_:1}),o(" are supported")]),e("li",null,[e("a",k,[o("CORS"),t(r)]),o(" needs to be considered when making requests from one website ("),v,o(") to another ("),x,o(")")]),R,L]),X,t(n,{text:"v1.4.1+",type:"warning"}),B,e("ul",null,[I,E,e("li",null,[o("In addition, due to "),e("a",H,[o("Xray-core#375"),t(r)]),o(" recommendations for "),P,o(", this PR also increased server "),W,o(" by 4096. "),A])]),C,t(n,{text:"v1.8.19+",type:"warning"}),O,N])}const j=c(p,[["render",J],["__file","browser_dialer.html.vue"]]);export{j as default}; diff --git a/assets/c4Diagram-ae766693-TOZe-7Pl.js b/assets/c4Diagram-ae766693-DVn8Dofm.js similarity index 99% rename from assets/c4Diagram-ae766693-TOZe-7Pl.js rename to assets/c4Diagram-ae766693-DVn8Dofm.js index 8d2723b2f1..57c1e47613 100644 --- a/assets/c4Diagram-ae766693-TOZe-7Pl.js +++ b/assets/c4Diagram-ae766693-DVn8Dofm.js @@ -1,4 +1,4 @@ -import{s as we,g as Oe,a as Te,b as Re,c as Dt,d as ue,e as De,f as wt,h as Nt,l as le,i as Se,w as Pe,j as Kt,k as oe,m as Me}from"./mermaid.core-CArNAncI.js";import{d as Le,g as Ne}from"./svgDrawCommon-5e1cfd1d-BWP2bQZS.js";import"./app-5SoadDYS.js";var Yt=function(){var e=function(bt,_,x,m){for(x=x||{},m=bt.length;m--;x[bt[m]]=_);return x},t=[1,24],a=[1,25],o=[1,26],l=[1,27],i=[1,28],s=[1,63],r=[1,64],n=[1,65],h=[1,66],f=[1,67],d=[1,68],p=[1,69],E=[1,29],O=[1,30],R=[1,31],S=[1,32],L=[1,33],Y=[1,34],Q=[1,35],H=[1,36],q=[1,37],G=[1,38],K=[1,39],J=[1,40],Z=[1,41],$=[1,42],tt=[1,43],et=[1,44],it=[1,45],nt=[1,46],st=[1,47],at=[1,48],rt=[1,50],lt=[1,51],ot=[1,52],ct=[1,53],ht=[1,54],ut=[1,55],dt=[1,56],ft=[1,57],pt=[1,58],yt=[1,59],gt=[1,60],At=[14,42],Vt=[14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],Ot=[12,14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],v=[1,82],k=[1,83],A=[1,84],C=[1,85],w=[12,14,42],ne=[12,14,33,42],Pt=[12,14,33,42,76,77,79,80],mt=[12,33],zt=[34,36,37,38,39,40,41,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],Xt={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,direction_tb:6,direction_bt:7,direction_rl:8,direction_lr:9,graphConfig:10,C4_CONTEXT:11,NEWLINE:12,statements:13,EOF:14,C4_CONTAINER:15,C4_COMPONENT:16,C4_DYNAMIC:17,C4_DEPLOYMENT:18,otherStatements:19,diagramStatements:20,otherStatement:21,title:22,accDescription:23,acc_title:24,acc_title_value:25,acc_descr:26,acc_descr_value:27,acc_descr_multiline_value:28,boundaryStatement:29,boundaryStartStatement:30,boundaryStopStatement:31,boundaryStart:32,LBRACE:33,ENTERPRISE_BOUNDARY:34,attributes:35,SYSTEM_BOUNDARY:36,BOUNDARY:37,CONTAINER_BOUNDARY:38,NODE:39,NODE_L:40,NODE_R:41,RBRACE:42,diagramStatement:43,PERSON:44,PERSON_EXT:45,SYSTEM:46,SYSTEM_DB:47,SYSTEM_QUEUE:48,SYSTEM_EXT:49,SYSTEM_EXT_DB:50,SYSTEM_EXT_QUEUE:51,CONTAINER:52,CONTAINER_DB:53,CONTAINER_QUEUE:54,CONTAINER_EXT:55,CONTAINER_EXT_DB:56,CONTAINER_EXT_QUEUE:57,COMPONENT:58,COMPONENT_DB:59,COMPONENT_QUEUE:60,COMPONENT_EXT:61,COMPONENT_EXT_DB:62,COMPONENT_EXT_QUEUE:63,REL:64,BIREL:65,REL_U:66,REL_D:67,REL_L:68,REL_R:69,REL_B:70,REL_INDEX:71,UPDATE_EL_STYLE:72,UPDATE_REL_STYLE:73,UPDATE_LAYOUT_CONFIG:74,attribute:75,STR:76,STR_KEY:77,STR_VALUE:78,ATTRIBUTE:79,ATTRIBUTE_EMPTY:80,$accept:0,$end:1},terminals_:{2:"error",6:"direction_tb",7:"direction_bt",8:"direction_rl",9:"direction_lr",11:"C4_CONTEXT",12:"NEWLINE",14:"EOF",15:"C4_CONTAINER",16:"C4_COMPONENT",17:"C4_DYNAMIC",18:"C4_DEPLOYMENT",22:"title",23:"accDescription",24:"acc_title",25:"acc_title_value",26:"acc_descr",27:"acc_descr_value",28:"acc_descr_multiline_value",33:"LBRACE",34:"ENTERPRISE_BOUNDARY",36:"SYSTEM_BOUNDARY",37:"BOUNDARY",38:"CONTAINER_BOUNDARY",39:"NODE",40:"NODE_L",41:"NODE_R",42:"RBRACE",44:"PERSON",45:"PERSON_EXT",46:"SYSTEM",47:"SYSTEM_DB",48:"SYSTEM_QUEUE",49:"SYSTEM_EXT",50:"SYSTEM_EXT_DB",51:"SYSTEM_EXT_QUEUE",52:"CONTAINER",53:"CONTAINER_DB",54:"CONTAINER_QUEUE",55:"CONTAINER_EXT",56:"CONTAINER_EXT_DB",57:"CONTAINER_EXT_QUEUE",58:"COMPONENT",59:"COMPONENT_DB",60:"COMPONENT_QUEUE",61:"COMPONENT_EXT",62:"COMPONENT_EXT_DB",63:"COMPONENT_EXT_QUEUE",64:"REL",65:"BIREL",66:"REL_U",67:"REL_D",68:"REL_L",69:"REL_R",70:"REL_B",71:"REL_INDEX",72:"UPDATE_EL_STYLE",73:"UPDATE_REL_STYLE",74:"UPDATE_LAYOUT_CONFIG",76:"STR",77:"STR_KEY",78:"STR_VALUE",79:"ATTRIBUTE",80:"ATTRIBUTE_EMPTY"},productions_:[0,[3,1],[3,1],[5,1],[5,1],[5,1],[5,1],[4,1],[10,4],[10,4],[10,4],[10,4],[10,4],[13,1],[13,1],[13,2],[19,1],[19,2],[19,3],[21,1],[21,1],[21,2],[21,2],[21,1],[29,3],[30,3],[30,3],[30,4],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[31,1],[20,1],[20,2],[20,3],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,1],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[35,1],[35,2],[75,1],[75,2],[75,1],[75,1]],performAction:function(_,x,m,g,T,u,Tt){var y=u.length-1;switch(T){case 3:g.setDirection("TB");break;case 4:g.setDirection("BT");break;case 5:g.setDirection("RL");break;case 6:g.setDirection("LR");break;case 8:case 9:case 10:case 11:case 12:g.setC4Type(u[y-3]);break;case 19:g.setTitle(u[y].substring(6)),this.$=u[y].substring(6);break;case 20:g.setAccDescription(u[y].substring(15)),this.$=u[y].substring(15);break;case 21:this.$=u[y].trim(),g.setTitle(this.$);break;case 22:case 23:this.$=u[y].trim(),g.setAccDescription(this.$);break;case 28:case 29:u[y].splice(2,0,"ENTERPRISE"),g.addPersonOrSystemBoundary(...u[y]),this.$=u[y];break;case 30:g.addPersonOrSystemBoundary(...u[y]),this.$=u[y];break;case 31:u[y].splice(2,0,"CONTAINER"),g.addContainerBoundary(...u[y]),this.$=u[y];break;case 32:g.addDeploymentNode("node",...u[y]),this.$=u[y];break;case 33:g.addDeploymentNode("nodeL",...u[y]),this.$=u[y];break;case 34:g.addDeploymentNode("nodeR",...u[y]),this.$=u[y];break;case 35:g.popBoundaryParseStack();break;case 39:g.addPersonOrSystem("person",...u[y]),this.$=u[y];break;case 40:g.addPersonOrSystem("external_person",...u[y]),this.$=u[y];break;case 41:g.addPersonOrSystem("system",...u[y]),this.$=u[y];break;case 42:g.addPersonOrSystem("system_db",...u[y]),this.$=u[y];break;case 43:g.addPersonOrSystem("system_queue",...u[y]),this.$=u[y];break;case 44:g.addPersonOrSystem("external_system",...u[y]),this.$=u[y];break;case 45:g.addPersonOrSystem("external_system_db",...u[y]),this.$=u[y];break;case 46:g.addPersonOrSystem("external_system_queue",...u[y]),this.$=u[y];break;case 47:g.addContainer("container",...u[y]),this.$=u[y];break;case 48:g.addContainer("container_db",...u[y]),this.$=u[y];break;case 49:g.addContainer("container_queue",...u[y]),this.$=u[y];break;case 50:g.addContainer("external_container",...u[y]),this.$=u[y];break;case 51:g.addContainer("external_container_db",...u[y]),this.$=u[y];break;case 52:g.addContainer("external_container_queue",...u[y]),this.$=u[y];break;case 53:g.addComponent("component",...u[y]),this.$=u[y];break;case 54:g.addComponent("component_db",...u[y]),this.$=u[y];break;case 55:g.addComponent("component_queue",...u[y]),this.$=u[y];break;case 56:g.addComponent("external_component",...u[y]),this.$=u[y];break;case 57:g.addComponent("external_component_db",...u[y]),this.$=u[y];break;case 58:g.addComponent("external_component_queue",...u[y]),this.$=u[y];break;case 60:g.addRel("rel",...u[y]),this.$=u[y];break;case 61:g.addRel("birel",...u[y]),this.$=u[y];break;case 62:g.addRel("rel_u",...u[y]),this.$=u[y];break;case 63:g.addRel("rel_d",...u[y]),this.$=u[y];break;case 64:g.addRel("rel_l",...u[y]),this.$=u[y];break;case 65:g.addRel("rel_r",...u[y]),this.$=u[y];break;case 66:g.addRel("rel_b",...u[y]),this.$=u[y];break;case 67:u[y].splice(0,1),g.addRel("rel",...u[y]),this.$=u[y];break;case 68:g.updateElStyle("update_el_style",...u[y]),this.$=u[y];break;case 69:g.updateRelStyle("update_rel_style",...u[y]),this.$=u[y];break;case 70:g.updateLayoutConfig("update_layout_config",...u[y]),this.$=u[y];break;case 71:this.$=[u[y]];break;case 72:u[y].unshift(u[y-1]),this.$=u[y];break;case 73:case 75:this.$=u[y].trim();break;case 74:let Et={};Et[u[y-1].trim()]=u[y].trim(),this.$=Et;break;case 76:this.$="";break}},table:[{3:1,4:2,5:3,6:[1,5],7:[1,6],8:[1,7],9:[1,8],10:4,11:[1,9],15:[1,10],16:[1,11],17:[1,12],18:[1,13]},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,7]},{1:[2,3]},{1:[2,4]},{1:[2,5]},{1:[2,6]},{12:[1,14]},{12:[1,15]},{12:[1,16]},{12:[1,17]},{12:[1,18]},{13:19,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:70,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:71,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:72,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:73,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{14:[1,74]},e(At,[2,13],{43:23,29:49,30:61,32:62,20:75,34:s,36:r,37:n,38:h,39:f,40:d,41:p,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt}),e(At,[2,14]),e(Vt,[2,16],{12:[1,76]}),e(At,[2,36],{12:[1,77]}),e(Ot,[2,19]),e(Ot,[2,20]),{25:[1,78]},{27:[1,79]},e(Ot,[2,23]),{35:80,75:81,76:v,77:k,79:A,80:C},{35:86,75:81,76:v,77:k,79:A,80:C},{35:87,75:81,76:v,77:k,79:A,80:C},{35:88,75:81,76:v,77:k,79:A,80:C},{35:89,75:81,76:v,77:k,79:A,80:C},{35:90,75:81,76:v,77:k,79:A,80:C},{35:91,75:81,76:v,77:k,79:A,80:C},{35:92,75:81,76:v,77:k,79:A,80:C},{35:93,75:81,76:v,77:k,79:A,80:C},{35:94,75:81,76:v,77:k,79:A,80:C},{35:95,75:81,76:v,77:k,79:A,80:C},{35:96,75:81,76:v,77:k,79:A,80:C},{35:97,75:81,76:v,77:k,79:A,80:C},{35:98,75:81,76:v,77:k,79:A,80:C},{35:99,75:81,76:v,77:k,79:A,80:C},{35:100,75:81,76:v,77:k,79:A,80:C},{35:101,75:81,76:v,77:k,79:A,80:C},{35:102,75:81,76:v,77:k,79:A,80:C},{35:103,75:81,76:v,77:k,79:A,80:C},{35:104,75:81,76:v,77:k,79:A,80:C},e(w,[2,59]),{35:105,75:81,76:v,77:k,79:A,80:C},{35:106,75:81,76:v,77:k,79:A,80:C},{35:107,75:81,76:v,77:k,79:A,80:C},{35:108,75:81,76:v,77:k,79:A,80:C},{35:109,75:81,76:v,77:k,79:A,80:C},{35:110,75:81,76:v,77:k,79:A,80:C},{35:111,75:81,76:v,77:k,79:A,80:C},{35:112,75:81,76:v,77:k,79:A,80:C},{35:113,75:81,76:v,77:k,79:A,80:C},{35:114,75:81,76:v,77:k,79:A,80:C},{35:115,75:81,76:v,77:k,79:A,80:C},{20:116,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{12:[1,118],33:[1,117]},{35:119,75:81,76:v,77:k,79:A,80:C},{35:120,75:81,76:v,77:k,79:A,80:C},{35:121,75:81,76:v,77:k,79:A,80:C},{35:122,75:81,76:v,77:k,79:A,80:C},{35:123,75:81,76:v,77:k,79:A,80:C},{35:124,75:81,76:v,77:k,79:A,80:C},{35:125,75:81,76:v,77:k,79:A,80:C},{14:[1,126]},{14:[1,127]},{14:[1,128]},{14:[1,129]},{1:[2,8]},e(At,[2,15]),e(Vt,[2,17],{21:22,19:130,22:t,23:a,24:o,26:l,28:i}),e(At,[2,37],{19:20,20:21,21:22,43:23,29:49,30:61,32:62,13:131,22:t,23:a,24:o,26:l,28:i,34:s,36:r,37:n,38:h,39:f,40:d,41:p,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt}),e(Ot,[2,21]),e(Ot,[2,22]),e(w,[2,39]),e(ne,[2,71],{75:81,35:132,76:v,77:k,79:A,80:C}),e(Pt,[2,73]),{78:[1,133]},e(Pt,[2,75]),e(Pt,[2,76]),e(w,[2,40]),e(w,[2,41]),e(w,[2,42]),e(w,[2,43]),e(w,[2,44]),e(w,[2,45]),e(w,[2,46]),e(w,[2,47]),e(w,[2,48]),e(w,[2,49]),e(w,[2,50]),e(w,[2,51]),e(w,[2,52]),e(w,[2,53]),e(w,[2,54]),e(w,[2,55]),e(w,[2,56]),e(w,[2,57]),e(w,[2,58]),e(w,[2,60]),e(w,[2,61]),e(w,[2,62]),e(w,[2,63]),e(w,[2,64]),e(w,[2,65]),e(w,[2,66]),e(w,[2,67]),e(w,[2,68]),e(w,[2,69]),e(w,[2,70]),{31:134,42:[1,135]},{12:[1,136]},{33:[1,137]},e(mt,[2,28]),e(mt,[2,29]),e(mt,[2,30]),e(mt,[2,31]),e(mt,[2,32]),e(mt,[2,33]),e(mt,[2,34]),{1:[2,9]},{1:[2,10]},{1:[2,11]},{1:[2,12]},e(Vt,[2,18]),e(At,[2,38]),e(ne,[2,72]),e(Pt,[2,74]),e(w,[2,24]),e(w,[2,35]),e(zt,[2,25]),e(zt,[2,26],{12:[1,138]}),e(zt,[2,27])],defaultActions:{2:[2,1],3:[2,2],4:[2,7],5:[2,3],6:[2,4],7:[2,5],8:[2,6],74:[2,8],126:[2,9],127:[2,10],128:[2,11],129:[2,12]},parseError:function(_,x){if(x.recoverable)this.trace(_);else{var m=new Error(_);throw m.hash=x,m}},parse:function(_){var x=this,m=[0],g=[],T=[null],u=[],Tt=this.table,y="",Et=0,se=0,ve=2,ae=1,ke=u.slice.call(arguments,1),D=Object.create(this.lexer),vt={yy:{}};for(var Qt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Qt)&&(vt.yy[Qt]=this.yy[Qt]);D.setInput(_,vt.yy),vt.yy.lexer=D,vt.yy.parser=this,typeof D.yylloc>"u"&&(D.yylloc={});var Ht=D.yylloc;u.push(Ht);var Ae=D.options&&D.options.ranges;typeof vt.yy.parseError=="function"?this.parseError=vt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ce(){var X;return X=g.pop()||D.lex()||ae,typeof X!="number"&&(X instanceof Array&&(g=X,X=g.pop()),X=x.symbols_[X]||X),X}for(var M,kt,N,qt,Ct={},Mt,z,re,Lt;;){if(kt=m[m.length-1],this.defaultActions[kt]?N=this.defaultActions[kt]:((M===null||typeof M>"u")&&(M=Ce()),N=Tt[kt]&&Tt[kt][M]),typeof N>"u"||!N.length||!N[0]){var Gt="";Lt=[];for(Mt in Tt[kt])this.terminals_[Mt]&&Mt>ve&&Lt.push("'"+this.terminals_[Mt]+"'");D.showPosition?Gt="Parse error on line "+(Et+1)+`: +import{s as we,g as Oe,a as Te,b as Re,c as Dt,d as ue,e as De,f as wt,h as Nt,l as le,i as Se,w as Pe,j as Kt,k as oe,m as Me}from"./mermaid.core-Bq0kX0MS.js";import{d as Le,g as Ne}from"./svgDrawCommon-5e1cfd1d-CX_gVtbt.js";import"./app-Bw2NG-QJ.js";var Yt=function(){var e=function(bt,_,x,m){for(x=x||{},m=bt.length;m--;x[bt[m]]=_);return x},t=[1,24],a=[1,25],o=[1,26],l=[1,27],i=[1,28],s=[1,63],r=[1,64],n=[1,65],h=[1,66],f=[1,67],d=[1,68],p=[1,69],E=[1,29],O=[1,30],R=[1,31],S=[1,32],L=[1,33],Y=[1,34],Q=[1,35],H=[1,36],q=[1,37],G=[1,38],K=[1,39],J=[1,40],Z=[1,41],$=[1,42],tt=[1,43],et=[1,44],it=[1,45],nt=[1,46],st=[1,47],at=[1,48],rt=[1,50],lt=[1,51],ot=[1,52],ct=[1,53],ht=[1,54],ut=[1,55],dt=[1,56],ft=[1,57],pt=[1,58],yt=[1,59],gt=[1,60],At=[14,42],Vt=[14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],Ot=[12,14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],v=[1,82],k=[1,83],A=[1,84],C=[1,85],w=[12,14,42],ne=[12,14,33,42],Pt=[12,14,33,42,76,77,79,80],mt=[12,33],zt=[34,36,37,38,39,40,41,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],Xt={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,direction_tb:6,direction_bt:7,direction_rl:8,direction_lr:9,graphConfig:10,C4_CONTEXT:11,NEWLINE:12,statements:13,EOF:14,C4_CONTAINER:15,C4_COMPONENT:16,C4_DYNAMIC:17,C4_DEPLOYMENT:18,otherStatements:19,diagramStatements:20,otherStatement:21,title:22,accDescription:23,acc_title:24,acc_title_value:25,acc_descr:26,acc_descr_value:27,acc_descr_multiline_value:28,boundaryStatement:29,boundaryStartStatement:30,boundaryStopStatement:31,boundaryStart:32,LBRACE:33,ENTERPRISE_BOUNDARY:34,attributes:35,SYSTEM_BOUNDARY:36,BOUNDARY:37,CONTAINER_BOUNDARY:38,NODE:39,NODE_L:40,NODE_R:41,RBRACE:42,diagramStatement:43,PERSON:44,PERSON_EXT:45,SYSTEM:46,SYSTEM_DB:47,SYSTEM_QUEUE:48,SYSTEM_EXT:49,SYSTEM_EXT_DB:50,SYSTEM_EXT_QUEUE:51,CONTAINER:52,CONTAINER_DB:53,CONTAINER_QUEUE:54,CONTAINER_EXT:55,CONTAINER_EXT_DB:56,CONTAINER_EXT_QUEUE:57,COMPONENT:58,COMPONENT_DB:59,COMPONENT_QUEUE:60,COMPONENT_EXT:61,COMPONENT_EXT_DB:62,COMPONENT_EXT_QUEUE:63,REL:64,BIREL:65,REL_U:66,REL_D:67,REL_L:68,REL_R:69,REL_B:70,REL_INDEX:71,UPDATE_EL_STYLE:72,UPDATE_REL_STYLE:73,UPDATE_LAYOUT_CONFIG:74,attribute:75,STR:76,STR_KEY:77,STR_VALUE:78,ATTRIBUTE:79,ATTRIBUTE_EMPTY:80,$accept:0,$end:1},terminals_:{2:"error",6:"direction_tb",7:"direction_bt",8:"direction_rl",9:"direction_lr",11:"C4_CONTEXT",12:"NEWLINE",14:"EOF",15:"C4_CONTAINER",16:"C4_COMPONENT",17:"C4_DYNAMIC",18:"C4_DEPLOYMENT",22:"title",23:"accDescription",24:"acc_title",25:"acc_title_value",26:"acc_descr",27:"acc_descr_value",28:"acc_descr_multiline_value",33:"LBRACE",34:"ENTERPRISE_BOUNDARY",36:"SYSTEM_BOUNDARY",37:"BOUNDARY",38:"CONTAINER_BOUNDARY",39:"NODE",40:"NODE_L",41:"NODE_R",42:"RBRACE",44:"PERSON",45:"PERSON_EXT",46:"SYSTEM",47:"SYSTEM_DB",48:"SYSTEM_QUEUE",49:"SYSTEM_EXT",50:"SYSTEM_EXT_DB",51:"SYSTEM_EXT_QUEUE",52:"CONTAINER",53:"CONTAINER_DB",54:"CONTAINER_QUEUE",55:"CONTAINER_EXT",56:"CONTAINER_EXT_DB",57:"CONTAINER_EXT_QUEUE",58:"COMPONENT",59:"COMPONENT_DB",60:"COMPONENT_QUEUE",61:"COMPONENT_EXT",62:"COMPONENT_EXT_DB",63:"COMPONENT_EXT_QUEUE",64:"REL",65:"BIREL",66:"REL_U",67:"REL_D",68:"REL_L",69:"REL_R",70:"REL_B",71:"REL_INDEX",72:"UPDATE_EL_STYLE",73:"UPDATE_REL_STYLE",74:"UPDATE_LAYOUT_CONFIG",76:"STR",77:"STR_KEY",78:"STR_VALUE",79:"ATTRIBUTE",80:"ATTRIBUTE_EMPTY"},productions_:[0,[3,1],[3,1],[5,1],[5,1],[5,1],[5,1],[4,1],[10,4],[10,4],[10,4],[10,4],[10,4],[13,1],[13,1],[13,2],[19,1],[19,2],[19,3],[21,1],[21,1],[21,2],[21,2],[21,1],[29,3],[30,3],[30,3],[30,4],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[31,1],[20,1],[20,2],[20,3],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,1],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[35,1],[35,2],[75,1],[75,2],[75,1],[75,1]],performAction:function(_,x,m,g,T,u,Tt){var y=u.length-1;switch(T){case 3:g.setDirection("TB");break;case 4:g.setDirection("BT");break;case 5:g.setDirection("RL");break;case 6:g.setDirection("LR");break;case 8:case 9:case 10:case 11:case 12:g.setC4Type(u[y-3]);break;case 19:g.setTitle(u[y].substring(6)),this.$=u[y].substring(6);break;case 20:g.setAccDescription(u[y].substring(15)),this.$=u[y].substring(15);break;case 21:this.$=u[y].trim(),g.setTitle(this.$);break;case 22:case 23:this.$=u[y].trim(),g.setAccDescription(this.$);break;case 28:case 29:u[y].splice(2,0,"ENTERPRISE"),g.addPersonOrSystemBoundary(...u[y]),this.$=u[y];break;case 30:g.addPersonOrSystemBoundary(...u[y]),this.$=u[y];break;case 31:u[y].splice(2,0,"CONTAINER"),g.addContainerBoundary(...u[y]),this.$=u[y];break;case 32:g.addDeploymentNode("node",...u[y]),this.$=u[y];break;case 33:g.addDeploymentNode("nodeL",...u[y]),this.$=u[y];break;case 34:g.addDeploymentNode("nodeR",...u[y]),this.$=u[y];break;case 35:g.popBoundaryParseStack();break;case 39:g.addPersonOrSystem("person",...u[y]),this.$=u[y];break;case 40:g.addPersonOrSystem("external_person",...u[y]),this.$=u[y];break;case 41:g.addPersonOrSystem("system",...u[y]),this.$=u[y];break;case 42:g.addPersonOrSystem("system_db",...u[y]),this.$=u[y];break;case 43:g.addPersonOrSystem("system_queue",...u[y]),this.$=u[y];break;case 44:g.addPersonOrSystem("external_system",...u[y]),this.$=u[y];break;case 45:g.addPersonOrSystem("external_system_db",...u[y]),this.$=u[y];break;case 46:g.addPersonOrSystem("external_system_queue",...u[y]),this.$=u[y];break;case 47:g.addContainer("container",...u[y]),this.$=u[y];break;case 48:g.addContainer("container_db",...u[y]),this.$=u[y];break;case 49:g.addContainer("container_queue",...u[y]),this.$=u[y];break;case 50:g.addContainer("external_container",...u[y]),this.$=u[y];break;case 51:g.addContainer("external_container_db",...u[y]),this.$=u[y];break;case 52:g.addContainer("external_container_queue",...u[y]),this.$=u[y];break;case 53:g.addComponent("component",...u[y]),this.$=u[y];break;case 54:g.addComponent("component_db",...u[y]),this.$=u[y];break;case 55:g.addComponent("component_queue",...u[y]),this.$=u[y];break;case 56:g.addComponent("external_component",...u[y]),this.$=u[y];break;case 57:g.addComponent("external_component_db",...u[y]),this.$=u[y];break;case 58:g.addComponent("external_component_queue",...u[y]),this.$=u[y];break;case 60:g.addRel("rel",...u[y]),this.$=u[y];break;case 61:g.addRel("birel",...u[y]),this.$=u[y];break;case 62:g.addRel("rel_u",...u[y]),this.$=u[y];break;case 63:g.addRel("rel_d",...u[y]),this.$=u[y];break;case 64:g.addRel("rel_l",...u[y]),this.$=u[y];break;case 65:g.addRel("rel_r",...u[y]),this.$=u[y];break;case 66:g.addRel("rel_b",...u[y]),this.$=u[y];break;case 67:u[y].splice(0,1),g.addRel("rel",...u[y]),this.$=u[y];break;case 68:g.updateElStyle("update_el_style",...u[y]),this.$=u[y];break;case 69:g.updateRelStyle("update_rel_style",...u[y]),this.$=u[y];break;case 70:g.updateLayoutConfig("update_layout_config",...u[y]),this.$=u[y];break;case 71:this.$=[u[y]];break;case 72:u[y].unshift(u[y-1]),this.$=u[y];break;case 73:case 75:this.$=u[y].trim();break;case 74:let Et={};Et[u[y-1].trim()]=u[y].trim(),this.$=Et;break;case 76:this.$="";break}},table:[{3:1,4:2,5:3,6:[1,5],7:[1,6],8:[1,7],9:[1,8],10:4,11:[1,9],15:[1,10],16:[1,11],17:[1,12],18:[1,13]},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,7]},{1:[2,3]},{1:[2,4]},{1:[2,5]},{1:[2,6]},{12:[1,14]},{12:[1,15]},{12:[1,16]},{12:[1,17]},{12:[1,18]},{13:19,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:70,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:71,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:72,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{13:73,19:20,20:21,21:22,22:t,23:a,24:o,26:l,28:i,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{14:[1,74]},e(At,[2,13],{43:23,29:49,30:61,32:62,20:75,34:s,36:r,37:n,38:h,39:f,40:d,41:p,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt}),e(At,[2,14]),e(Vt,[2,16],{12:[1,76]}),e(At,[2,36],{12:[1,77]}),e(Ot,[2,19]),e(Ot,[2,20]),{25:[1,78]},{27:[1,79]},e(Ot,[2,23]),{35:80,75:81,76:v,77:k,79:A,80:C},{35:86,75:81,76:v,77:k,79:A,80:C},{35:87,75:81,76:v,77:k,79:A,80:C},{35:88,75:81,76:v,77:k,79:A,80:C},{35:89,75:81,76:v,77:k,79:A,80:C},{35:90,75:81,76:v,77:k,79:A,80:C},{35:91,75:81,76:v,77:k,79:A,80:C},{35:92,75:81,76:v,77:k,79:A,80:C},{35:93,75:81,76:v,77:k,79:A,80:C},{35:94,75:81,76:v,77:k,79:A,80:C},{35:95,75:81,76:v,77:k,79:A,80:C},{35:96,75:81,76:v,77:k,79:A,80:C},{35:97,75:81,76:v,77:k,79:A,80:C},{35:98,75:81,76:v,77:k,79:A,80:C},{35:99,75:81,76:v,77:k,79:A,80:C},{35:100,75:81,76:v,77:k,79:A,80:C},{35:101,75:81,76:v,77:k,79:A,80:C},{35:102,75:81,76:v,77:k,79:A,80:C},{35:103,75:81,76:v,77:k,79:A,80:C},{35:104,75:81,76:v,77:k,79:A,80:C},e(w,[2,59]),{35:105,75:81,76:v,77:k,79:A,80:C},{35:106,75:81,76:v,77:k,79:A,80:C},{35:107,75:81,76:v,77:k,79:A,80:C},{35:108,75:81,76:v,77:k,79:A,80:C},{35:109,75:81,76:v,77:k,79:A,80:C},{35:110,75:81,76:v,77:k,79:A,80:C},{35:111,75:81,76:v,77:k,79:A,80:C},{35:112,75:81,76:v,77:k,79:A,80:C},{35:113,75:81,76:v,77:k,79:A,80:C},{35:114,75:81,76:v,77:k,79:A,80:C},{35:115,75:81,76:v,77:k,79:A,80:C},{20:116,29:49,30:61,32:62,34:s,36:r,37:n,38:h,39:f,40:d,41:p,43:23,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt},{12:[1,118],33:[1,117]},{35:119,75:81,76:v,77:k,79:A,80:C},{35:120,75:81,76:v,77:k,79:A,80:C},{35:121,75:81,76:v,77:k,79:A,80:C},{35:122,75:81,76:v,77:k,79:A,80:C},{35:123,75:81,76:v,77:k,79:A,80:C},{35:124,75:81,76:v,77:k,79:A,80:C},{35:125,75:81,76:v,77:k,79:A,80:C},{14:[1,126]},{14:[1,127]},{14:[1,128]},{14:[1,129]},{1:[2,8]},e(At,[2,15]),e(Vt,[2,17],{21:22,19:130,22:t,23:a,24:o,26:l,28:i}),e(At,[2,37],{19:20,20:21,21:22,43:23,29:49,30:61,32:62,13:131,22:t,23:a,24:o,26:l,28:i,34:s,36:r,37:n,38:h,39:f,40:d,41:p,44:E,45:O,46:R,47:S,48:L,49:Y,50:Q,51:H,52:q,53:G,54:K,55:J,56:Z,57:$,58:tt,59:et,60:it,61:nt,62:st,63:at,64:rt,65:lt,66:ot,67:ct,68:ht,69:ut,70:dt,71:ft,72:pt,73:yt,74:gt}),e(Ot,[2,21]),e(Ot,[2,22]),e(w,[2,39]),e(ne,[2,71],{75:81,35:132,76:v,77:k,79:A,80:C}),e(Pt,[2,73]),{78:[1,133]},e(Pt,[2,75]),e(Pt,[2,76]),e(w,[2,40]),e(w,[2,41]),e(w,[2,42]),e(w,[2,43]),e(w,[2,44]),e(w,[2,45]),e(w,[2,46]),e(w,[2,47]),e(w,[2,48]),e(w,[2,49]),e(w,[2,50]),e(w,[2,51]),e(w,[2,52]),e(w,[2,53]),e(w,[2,54]),e(w,[2,55]),e(w,[2,56]),e(w,[2,57]),e(w,[2,58]),e(w,[2,60]),e(w,[2,61]),e(w,[2,62]),e(w,[2,63]),e(w,[2,64]),e(w,[2,65]),e(w,[2,66]),e(w,[2,67]),e(w,[2,68]),e(w,[2,69]),e(w,[2,70]),{31:134,42:[1,135]},{12:[1,136]},{33:[1,137]},e(mt,[2,28]),e(mt,[2,29]),e(mt,[2,30]),e(mt,[2,31]),e(mt,[2,32]),e(mt,[2,33]),e(mt,[2,34]),{1:[2,9]},{1:[2,10]},{1:[2,11]},{1:[2,12]},e(Vt,[2,18]),e(At,[2,38]),e(ne,[2,72]),e(Pt,[2,74]),e(w,[2,24]),e(w,[2,35]),e(zt,[2,25]),e(zt,[2,26],{12:[1,138]}),e(zt,[2,27])],defaultActions:{2:[2,1],3:[2,2],4:[2,7],5:[2,3],6:[2,4],7:[2,5],8:[2,6],74:[2,8],126:[2,9],127:[2,10],128:[2,11],129:[2,12]},parseError:function(_,x){if(x.recoverable)this.trace(_);else{var m=new Error(_);throw m.hash=x,m}},parse:function(_){var x=this,m=[0],g=[],T=[null],u=[],Tt=this.table,y="",Et=0,se=0,ve=2,ae=1,ke=u.slice.call(arguments,1),D=Object.create(this.lexer),vt={yy:{}};for(var Qt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Qt)&&(vt.yy[Qt]=this.yy[Qt]);D.setInput(_,vt.yy),vt.yy.lexer=D,vt.yy.parser=this,typeof D.yylloc>"u"&&(D.yylloc={});var Ht=D.yylloc;u.push(Ht);var Ae=D.options&&D.options.ranges;typeof vt.yy.parseError=="function"?this.parseError=vt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ce(){var X;return X=g.pop()||D.lex()||ae,typeof X!="number"&&(X instanceof Array&&(g=X,X=g.pop()),X=x.symbols_[X]||X),X}for(var M,kt,N,qt,Ct={},Mt,z,re,Lt;;){if(kt=m[m.length-1],this.defaultActions[kt]?N=this.defaultActions[kt]:((M===null||typeof M>"u")&&(M=Ce()),N=Tt[kt]&&Tt[kt][M]),typeof N>"u"||!N.length||!N[0]){var Gt="";Lt=[];for(Mt in Tt[kt])this.terminals_[Mt]&&Mt>ve&&Lt.push("'"+this.terminals_[Mt]+"'");D.showPosition?Gt="Parse error on line "+(Et+1)+`: `+D.showPosition()+` Expecting `+Lt.join(", ")+", got '"+(this.terminals_[M]||M)+"'":Gt="Parse error on line "+(Et+1)+": Unexpected "+(M==ae?"end of input":"'"+(this.terminals_[M]||M)+"'"),this.parseError(Gt,{text:D.match,token:this.terminals_[M]||M,line:D.yylineno,loc:Ht,expected:Lt})}if(N[0]instanceof Array&&N.length>1)throw new Error("Parse Error: multiple actions possible at state: "+kt+", token: "+M);switch(N[0]){case 1:m.push(M),T.push(D.yytext),u.push(D.yylloc),m.push(N[1]),M=null,se=D.yyleng,y=D.yytext,Et=D.yylineno,Ht=D.yylloc;break;case 2:if(z=this.productions_[N[1]][1],Ct.$=T[T.length-z],Ct._$={first_line:u[u.length-(z||1)].first_line,last_line:u[u.length-1].last_line,first_column:u[u.length-(z||1)].first_column,last_column:u[u.length-1].last_column},Ae&&(Ct._$.range=[u[u.length-(z||1)].range[0],u[u.length-1].range[1]]),qt=this.performAction.apply(Ct,[y,se,Et,vt.yy,N[1],T,u].concat(ke)),typeof qt<"u")return qt;z&&(m=m.slice(0,-1*z*2),T=T.slice(0,-1*z),u=u.slice(0,-1*z)),m.push(this.productions_[N[1]][0]),T.push(Ct.$),u.push(Ct._$),re=Tt[m[m.length-2]][m[m.length-1]],m.push(re);break;case 3:return!0}}return!0}},Ee=function(){var bt={EOF:1,parseError:function(x,m){if(this.yy.parser)this.yy.parser.parseError(x,m);else throw new Error(x)},setInput:function(_,x){return this.yy=x||this.yy||{},this._input=_,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var _=this._input[0];this.yytext+=_,this.yyleng++,this.offset++,this.match+=_,this.matched+=_;var x=_.match(/(?:\r\n?|\n).*/g);return x?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),_},unput:function(_){var x=_.length,m=_.split(/(?:\r\n?|\n)/g);this._input=_+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-x),this.offset-=x;var g=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),m.length-1&&(this.yylineno-=m.length-1);var T=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:m?(m.length===g.length?this.yylloc.first_column:0)+g[g.length-m.length].length-m[0].length:this.yylloc.first_column-x},this.options.ranges&&(this.yylloc.range=[T[0],T[0]+this.yyleng-x]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(_){this.unput(this.match.slice(_))},pastInput:function(){var _=this.matched.substr(0,this.matched.length-this.match.length);return(_.length>20?"...":"")+_.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var _=this.match;return _.length<20&&(_+=this._input.substr(0,20-_.length)),(_.substr(0,20)+(_.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var _=this.pastInput(),x=new Array(_.length+1).join("-");return _+this.upcomingInput()+` diff --git a/assets/ch01-preface.html-D5988Uh0.js b/assets/ch01-preface.html-Bts5JwT1.js similarity index 99% rename from assets/ch01-preface.html-D5988Uh0.js rename to assets/ch01-preface.html-Bts5JwT1.js index 318ad0358d..d8bbba5dc0 100644 --- a/assets/ch01-preface.html-D5988Uh0.js +++ b/assets/ch01-preface.html-Bts5JwT1.js @@ -1 +1 @@ -import{_ as t,r as o,o as i,c as n,a,e as s}from"./app-5SoadDYS.js";const r="/assets/ch01-img01-choice-DrFC1LCY.png",l={},h=s('

[Chapter 1] Simple and Plain Language

1.1 Who is this document written for?

One sentence: Written for newbies who are (1) absolute beginners and (2) interested in learning how to build their own VPS.

1.2 Who is this document not written for?

Including but not limited to: experts and professionals, beginners who are too lazy to tinker on their own, advanced users who already know how to tinker, wealthy users who insist on using airport services, and those who prefer using one-click scripts. In short, if you have a technical background or don't want to build it yourself, you can close this article directly, because this article may not be suitable for you and may even make you upset.

1.3 Declaration and Other Statements

Declaration:

My technical skills are extremely limited, so this article is inevitably full of errors and flaws. If you find any problems, please kindly point them out and don't be too harsh on me.

Disclaimer:

Please judge the reliability and usability of the content of this article by yourself. If you encounter any problems or negative results when establishing and using a VPS server based on the content of this article, I am not responsible for it.

Verbose statement:

Considering the target audience of this article, which is "users with zero experience", many details will be explained in great detail, so the language may be verbose. Please be mentally prepared for this.

1.4 Why is self-hosting a challenge?

To answer this question, we need to provide a little more background information.

  1. On the matter of accessing the internet through scientific means

The act of accessing the internet using scientific methods has been around for almost 20 years (shocking!!!.jpg). Initially, one could do it with a little effort (changing the host file, using SSH), then one had to find a web proxy, and later, one had to develop a private protocol (such as Shadowsocks) and so on.

With the continuous iteration and upgrade of GFW technology over the past decade, to achieve the goal of [building your own scientific Internet access], the things that need to be done include but are not limited to:

  • Understand basic Linux commands
  • Understand network transmission protocols
  • Have the technical and financial ability to purchase and manage a VPS
  • Have the technical and financial ability to purchase and manage a domain name
  • Have the technical ability to apply for a TLS certificate, and so on.

This has turned the once simple act of [setting up a self-built VPS for accessing the internet in a secure and unrestricted manner] into a daunting challenge that intimidates newcomers.

  1. Helplessness of Zero-based Users

For non-technical users with zero foundation, if they complete the above series of operations, they will inevitably need to learn a lot of knowledge. However, after a little searching, newbies are likely to become even more confused: a large amount of information is scattered in various corners of the Internet: blogs, Q&A sites, groups, forums, GitHub, Telegram, YouTube, and so on. These pieces of information are chaotic and complex, with varying levels of quality, and may even contradict each other. Basically, they won't stop until they completely confuse the newcomer.

Faced with such chaotic information, newcomers suddenly shift from [information scarcity] to [information overload]. If they fail after several attempts of groping and guessing (which is highly probable), their enthusiasm is bound to be greatly frustrated. In this process, if they happen to seek help in some unfriendly places, they may be ridiculed even more: "You're so inexperienced, just use the airport, why bother messing around!" "Go learn Linux first before coming back to ask."

At this moment, probably only an "hehe" can express the mood.

1.5 "Why not just use the airport?"

First of all, I would like to respond to those who ridicule and criticize by asking a question: Is using the airport really a panacea?

Secondly, I believe that there is a fundamental difference between "not understanding" and "not wanting to understand". The bad attitude of some people who just want handouts is naturally annoying, but those who sincerely want to learn but don't know how should not be subject to unjustified contempt and discrimination. It is precisely this kind of bad community atmosphere that does not distinguish between newcomers that prompted me to write this article. So without further ado, let's take a look at the advantages and disadvantages of the airport:

  1. 稳定性高:机场节点数量多,分布广泛,避免了单点故障的风险,保证了整个网络的稳定性。
  2. 速度快:机场的节点通常采用高速服务器和优化的网络架构,网络速度较快,能够满足用户的高速上网需求。
  3. 安全性高:机场通常会采用严格的安全措施,如流量加密、防火墙等,保护用户数据的安全性。
  4. 稳定性高:机场通常采用专业的运维团队进行管理和维护,保证了服务的稳定性和可靠性。
  5. 服务质量高:机场通常会提供完善的客户服务,及时解决用户的问题和反馈,提升用户的满意度。

The so-called "airport" refers to the "line provider". They are responsible for completing the technical operations and management mentioned in section 1.4, while users pay for the right to use the service. Therefore, its advantages include at least:

  1. Simple User Operation: Scan code operation, one-click rule addition, etc.
  2. Multiple Line Options: Can unlock network services in different countries and regions, such as iplc dedicated line services, game acceleration services, etc.
  3. Multiple Access Nodes: Therefore, it has a stronger ability to resist node blocking, if one is blocked, just switch to another one.
  • Risks of "Airport"

"The other side of the coin of 'convenience' is 'risk'. Based on the technical characteristics and market conditions of the 'airport', its risks include at least:"

  1. "Airport" can fully obtain user information: All the traces left by users online will inevitably and very likely be stored on their servers for a long time. These records cannot be restricted by any legally binding user privacy agreement. ("Snooping and recording your every move")
  2. "Airport" lacks market management: There are inevitably malicious merchants who target fraud. ("Actively run away")
  3. "Airport" faces regulatory pressure: While large airports are relatively secure, they cannot avoid attracting attention. In 2020, several large airports experienced shutdowns and runaways, seriously disrupting users' normal usage. ("Passively run away")
  4. "Airport" technical level is difficult to determine: The quality of the line varies greatly, and the phenomenon of falsely advertising quality services is common. ("Slow speed, frequent disconnections, unable to connect")

1.6 So should you build your own website?

Now that you have seen the advantages and risks of the airport, please think carefully and make your own decision on what to use. After all, the best plan is the one that suits you best.

It's Your Choice!

  1. If you decide to use the airport, you can close this article now.

  2. If you decide to build it yourself, please continue reading the following chapters!

In short, the goal of this article is to serve as a starting point for users with zero experience, providing thorough explanations and demonstrations for each step, even if it may seem overly detailed or repetitive. The aim is to assist beginners in completing the entire process of deploying a VPS server from the first command input to successfully accessing the internet via the client, and gradually introducing them to basic Linux operations, laying a foundation for further self-learning.

1.7 Some digressions

  1. There is a wealth of information outside of the wall, so please learn to think rationally and independently. Don't take sides easily and don't believe in sensational information.

  2. We sincerely hope that with a smoother internet, everyone can access fresher knowledge, richer entertainment, experience a better world, and make more like-minded friends, but do not become a scapegoat for anyone with ulterior motives.

  3. Your internet identity is still your identity, and achieving absolute anonymity is extremely difficult. Therefore, please be sure to comply with the relevant laws and regulations in your personal location and the location of your IP address. Self-protection is always the most basic bottom line.

1.8 Your Progress

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

',41);function c(d,u){const e=o("I18nTip");return i(),n("div",null,[a(e),h])}const f=t(l,[["render",c],["__file","ch01-preface.html.vue"]]);export{f as default}; +import{_ as t,r as o,o as i,c as n,a,e as s}from"./app-Bw2NG-QJ.js";const r="/assets/ch01-img01-choice-DrFC1LCY.png",l={},h=s('

[Chapter 1] Simple and Plain Language

1.1 Who is this document written for?

One sentence: Written for newbies who are (1) absolute beginners and (2) interested in learning how to build their own VPS.

1.2 Who is this document not written for?

Including but not limited to: experts and professionals, beginners who are too lazy to tinker on their own, advanced users who already know how to tinker, wealthy users who insist on using airport services, and those who prefer using one-click scripts. In short, if you have a technical background or don't want to build it yourself, you can close this article directly, because this article may not be suitable for you and may even make you upset.

1.3 Declaration and Other Statements

Declaration:

My technical skills are extremely limited, so this article is inevitably full of errors and flaws. If you find any problems, please kindly point them out and don't be too harsh on me.

Disclaimer:

Please judge the reliability and usability of the content of this article by yourself. If you encounter any problems or negative results when establishing and using a VPS server based on the content of this article, I am not responsible for it.

Verbose statement:

Considering the target audience of this article, which is "users with zero experience", many details will be explained in great detail, so the language may be verbose. Please be mentally prepared for this.

1.4 Why is self-hosting a challenge?

To answer this question, we need to provide a little more background information.

  1. On the matter of accessing the internet through scientific means

The act of accessing the internet using scientific methods has been around for almost 20 years (shocking!!!.jpg). Initially, one could do it with a little effort (changing the host file, using SSH), then one had to find a web proxy, and later, one had to develop a private protocol (such as Shadowsocks) and so on.

With the continuous iteration and upgrade of GFW technology over the past decade, to achieve the goal of [building your own scientific Internet access], the things that need to be done include but are not limited to:

  • Understand basic Linux commands
  • Understand network transmission protocols
  • Have the technical and financial ability to purchase and manage a VPS
  • Have the technical and financial ability to purchase and manage a domain name
  • Have the technical ability to apply for a TLS certificate, and so on.

This has turned the once simple act of [setting up a self-built VPS for accessing the internet in a secure and unrestricted manner] into a daunting challenge that intimidates newcomers.

  1. Helplessness of Zero-based Users

For non-technical users with zero foundation, if they complete the above series of operations, they will inevitably need to learn a lot of knowledge. However, after a little searching, newbies are likely to become even more confused: a large amount of information is scattered in various corners of the Internet: blogs, Q&A sites, groups, forums, GitHub, Telegram, YouTube, and so on. These pieces of information are chaotic and complex, with varying levels of quality, and may even contradict each other. Basically, they won't stop until they completely confuse the newcomer.

Faced with such chaotic information, newcomers suddenly shift from [information scarcity] to [information overload]. If they fail after several attempts of groping and guessing (which is highly probable), their enthusiasm is bound to be greatly frustrated. In this process, if they happen to seek help in some unfriendly places, they may be ridiculed even more: "You're so inexperienced, just use the airport, why bother messing around!" "Go learn Linux first before coming back to ask."

At this moment, probably only an "hehe" can express the mood.

1.5 "Why not just use the airport?"

First of all, I would like to respond to those who ridicule and criticize by asking a question: Is using the airport really a panacea?

Secondly, I believe that there is a fundamental difference between "not understanding" and "not wanting to understand". The bad attitude of some people who just want handouts is naturally annoying, but those who sincerely want to learn but don't know how should not be subject to unjustified contempt and discrimination. It is precisely this kind of bad community atmosphere that does not distinguish between newcomers that prompted me to write this article. So without further ado, let's take a look at the advantages and disadvantages of the airport:

  1. 稳定性高:机场节点数量多,分布广泛,避免了单点故障的风险,保证了整个网络的稳定性。
  2. 速度快:机场的节点通常采用高速服务器和优化的网络架构,网络速度较快,能够满足用户的高速上网需求。
  3. 安全性高:机场通常会采用严格的安全措施,如流量加密、防火墙等,保护用户数据的安全性。
  4. 稳定性高:机场通常采用专业的运维团队进行管理和维护,保证了服务的稳定性和可靠性。
  5. 服务质量高:机场通常会提供完善的客户服务,及时解决用户的问题和反馈,提升用户的满意度。

The so-called "airport" refers to the "line provider". They are responsible for completing the technical operations and management mentioned in section 1.4, while users pay for the right to use the service. Therefore, its advantages include at least:

  1. Simple User Operation: Scan code operation, one-click rule addition, etc.
  2. Multiple Line Options: Can unlock network services in different countries and regions, such as iplc dedicated line services, game acceleration services, etc.
  3. Multiple Access Nodes: Therefore, it has a stronger ability to resist node blocking, if one is blocked, just switch to another one.
  • Risks of "Airport"

"The other side of the coin of 'convenience' is 'risk'. Based on the technical characteristics and market conditions of the 'airport', its risks include at least:"

  1. "Airport" can fully obtain user information: All the traces left by users online will inevitably and very likely be stored on their servers for a long time. These records cannot be restricted by any legally binding user privacy agreement. ("Snooping and recording your every move")
  2. "Airport" lacks market management: There are inevitably malicious merchants who target fraud. ("Actively run away")
  3. "Airport" faces regulatory pressure: While large airports are relatively secure, they cannot avoid attracting attention. In 2020, several large airports experienced shutdowns and runaways, seriously disrupting users' normal usage. ("Passively run away")
  4. "Airport" technical level is difficult to determine: The quality of the line varies greatly, and the phenomenon of falsely advertising quality services is common. ("Slow speed, frequent disconnections, unable to connect")

1.6 So should you build your own website?

Now that you have seen the advantages and risks of the airport, please think carefully and make your own decision on what to use. After all, the best plan is the one that suits you best.

It's Your Choice!

  1. If you decide to use the airport, you can close this article now.

  2. If you decide to build it yourself, please continue reading the following chapters!

In short, the goal of this article is to serve as a starting point for users with zero experience, providing thorough explanations and demonstrations for each step, even if it may seem overly detailed or repetitive. The aim is to assist beginners in completing the entire process of deploying a VPS server from the first command input to successfully accessing the internet via the client, and gradually introducing them to basic Linux operations, laying a foundation for further self-learning.

1.7 Some digressions

  1. There is a wealth of information outside of the wall, so please learn to think rationally and independently. Don't take sides easily and don't believe in sensational information.

  2. We sincerely hope that with a smoother internet, everyone can access fresher knowledge, richer entertainment, experience a better world, and make more like-minded friends, but do not become a scapegoat for anyone with ulterior motives.

  3. Your internet identity is still your identity, and achieving absolute anonymity is extremely difficult. Therefore, please be sure to comply with the relevant laws and regulations in your personal location and the location of your IP address. Self-protection is always the most basic bottom line.

1.8 Your Progress

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

',41);function c(d,u){const e=o("I18nTip");return i(),n("div",null,[a(e),h])}const f=t(l,[["render",c],["__file","ch01-preface.html.vue"]]);export{f as default}; diff --git a/assets/ch01-preface.html-D5NO_n3E.js b/assets/ch01-preface.html-C6vuCTiJ.js similarity index 99% rename from assets/ch01-preface.html-D5NO_n3E.js rename to assets/ch01-preface.html-C6vuCTiJ.js index c04087e94b..497ed779dd 100644 --- a/assets/ch01-preface.html-D5NO_n3E.js +++ b/assets/ch01-preface.html-C6vuCTiJ.js @@ -1 +1 @@ -import{_ as s,r as a,o as n,c as o,a as r,e}from"./app-5SoadDYS.js";const i="/assets/ch01-img01-choice-DrFC1LCY.png",t={},l=e('

【第 1 章】 小小白白话文

1.1 这篇文档是写给谁的?

一句话:写给 ① 零基础 ② 希望学习自建 VPS 的新人。

1.2 这篇文档不是写给谁的?

包括但不限于:各路大神大能、懒得自己折腾的小白、已经会折腾的高手、确定要用机场的土豪、确定要用一键脚本的逍遥派...... 总之只要有技术基础、或不愿不想自建的同学,您直接关闭本文即可,因为这篇文章大概是入不了您的法眼的,更可能会让您生一肚子闲气,那多划不来。

1.3 郑重声明及其他声明

郑重声明:

鄙人技术奇菜无比,故本文必然挂一漏万破绽百出。您若发现问题还请温柔提醒,莫要人参公鸡。

免责声明:

本文内容请您自行判断是否可信可靠可用,若您根据本文内容建立和使用 VPS 服务器时出了任何问题和不良结果,鄙人概不负责。

啰嗦声明:

基于本文【零基础用户】的目标受众,许多内容会尽力详尽说明,所以语言偏啰嗦,请做好心理准备。

1.4 为什么自建是个难题?

要回答这个问题,就需要稍微多说一点背景信息了。

一、科学上网这件事

科学上网这件事情,说来已经发展了近二十年(震惊!!!.jpg)。最初,自己稍微动动手即可(改改 host、连一下 ssh)、后来需要找一个网页代理,再后来需要写一个私有协议(比如 Shadowsocks)等等。

随着 GFW 技术这十几年来不断的迭代升级,若要完成【自己动手科学上网】这个目标,需要做的事情已经包括但不限于:

  • 了解 Linux 系统基本命令
  • 了解网络传输协议
  • 有技术和经济能力完成 VPS 购买及管理
  • 有技术和经济能力完成域名购买及管理
  • 有技术能力完成 TLS 证书申请 等等。

这就让【自建 VPS 科学上网】这个曾经简单的行为逐渐变成了令新人望而生畏的挑战。

二、零基础用户的无奈

零基础的非技术用户,如果完成上面这一连串的操作,势必要学习大量的知识,但稍微搜索之后,新人只怕会更加迷茫:大量的信息散布在互联网的各个角落:博客、问答网站、群组、论坛、GitHub、Telegram、YouTube 等等等等)。这些信息纷乱复杂、水平良莠不齐、甚至可能互相矛盾。基本上就是不把新人彻底弄晕誓不罢休。

面对这些杂乱无章的信息,新人突然就从【信息匮乏】变成了【信息过剩】。若是几番连蒙带猜的折腾以失败告终(大概率如此)的话,他的积极性势必大受挫折。在这个过程中,若他又恰好去了一些不太友好的地方去求助,恐怕还要雪上加霜的被嘲讽一番:“这么菜,用机场不就行了,瞎折腾什么啊!”、“先去学会 Linux 再回来问吧”。

这时候,大概也只有一声“呵呵”可以表达心情了。

1.5 “用机场不就行了?”

首先,我想反问一下那些冷嘲热讽的人:“用机场”真的就是万灵药吗?

其次,我认为“不懂”和“不想懂”是有本质区别的。态度恶劣的巨婴伸手党自然惹人厌烦,但真心自学却不得要领的人不该受到无端的白眼和歧视,也正是这种对新人不加区分的恶劣社区氛围促使我写下本文。那么闲话少说,我们来看看机场的优势与劣势究竟如何:

一、“机场“的优势

所谓“机场”,就是“线路提供商”。他负责完成 1.4 提到的那一串技术操作和管理,用户则付费获得使用权。所以,它的优点至少有:

  1. 用户操作简单:扫码操作、一键添加规则等
  2. 线路选择多:可解锁不同国家、地区的网络服务;比如 iplc 等专线服务、游戏加速服务等
  3. 接入节点多:所以抵抗节点封锁的能力强一些,封了一个就换下一个

二、“机场”的风险

“方便”这枚硬币的另一面就是“风险”,基于“机场”的技术特点和市场情况,它的风险至少有:

  1. “机场”可完全获得用户信息:用户在网上的所有痕迹,都【必然】经过且【非常可能】长期存储在其服务器上,这些记录无法受到任何具备法律效力的用户隐私协议的约束(窥视、记录你的一举一动
  2. “机场”缺乏市场管理:不可避免存在着以欺诈为目标的恶意商家(主动跑路
  3. “机场”面临监管压力:大机场相对有保障的同时,也无法避免树大招风。2020 年间,已经有几个大机场停运、跑路的事件发生,用户的正常使用受到严重干扰(被动跑路
  4. “机场”技术水平难以确定:线路质量良莠不齐,挂羊头卖狗肉的现象屡见不鲜(速度慢、掉线多、连不上

1.6 那么你到底要不要自建呢?

现在,你已经看到了机场的优势和风险,要用什么,就请各位充分思考并自行决定。毕竟,最适合你的方案才是最好的方案。

It's Your Choice!

  1. 如果决定使用机场的话,现在,你可以关闭本文了。

  2. 如果你决定自建,那就请继续阅读后面的章节吧!!

总之,本文的目标就是成为零基础用户的知识起点,提供对每一步充分的讲解和演示,清清楚楚(甚至婆婆妈妈、絮絮叨叨、啰啰嗦嗦)的协助新人完成【从输入第一条命令开始,完成 VPS 服务器部署,并成功在客户端完成科学上网】的全程。并在这个过程中帮助新人逐步接触和熟悉 Linux 的基础操作,为之后的进一步自学打下基础。

1.7 题外啰嗦几句

  1. 墙外的信息泥沙俱下,请务必学会理性、独立的思辨,不要随意站队,不要轻信猎奇的信息。

  2. 衷心希望大家获得更顺畅的网络后,可以获取更新鲜的知识、更丰富的娱乐、接触更美好的世界、结交更多志同道合的朋友,但不要成为任何有不可告人目的之人的替罪羊。

  3. 你的互联网身份依然是你的身份,绝对的匿名化是极为困难的,所以请务必遵守你个人所在地区和 IP 所在地区的相关法律法规。无论何时,自我保护都是最基本的底线。

1.8 你的进度

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

',41);function h(c,d){const p=a("I18nTip");return n(),o("div",null,[r(p),l])}const _=s(t,[["render",h],["__file","ch01-preface.html.vue"]]);export{_ as default}; +import{_ as s,r as a,o as n,c as o,a as r,e}from"./app-Bw2NG-QJ.js";const i="/assets/ch01-img01-choice-DrFC1LCY.png",t={},l=e('

【第 1 章】 小小白白话文

1.1 这篇文档是写给谁的?

一句话:写给 ① 零基础 ② 希望学习自建 VPS 的新人。

1.2 这篇文档不是写给谁的?

包括但不限于:各路大神大能、懒得自己折腾的小白、已经会折腾的高手、确定要用机场的土豪、确定要用一键脚本的逍遥派...... 总之只要有技术基础、或不愿不想自建的同学,您直接关闭本文即可,因为这篇文章大概是入不了您的法眼的,更可能会让您生一肚子闲气,那多划不来。

1.3 郑重声明及其他声明

郑重声明:

鄙人技术奇菜无比,故本文必然挂一漏万破绽百出。您若发现问题还请温柔提醒,莫要人参公鸡。

免责声明:

本文内容请您自行判断是否可信可靠可用,若您根据本文内容建立和使用 VPS 服务器时出了任何问题和不良结果,鄙人概不负责。

啰嗦声明:

基于本文【零基础用户】的目标受众,许多内容会尽力详尽说明,所以语言偏啰嗦,请做好心理准备。

1.4 为什么自建是个难题?

要回答这个问题,就需要稍微多说一点背景信息了。

一、科学上网这件事

科学上网这件事情,说来已经发展了近二十年(震惊!!!.jpg)。最初,自己稍微动动手即可(改改 host、连一下 ssh)、后来需要找一个网页代理,再后来需要写一个私有协议(比如 Shadowsocks)等等。

随着 GFW 技术这十几年来不断的迭代升级,若要完成【自己动手科学上网】这个目标,需要做的事情已经包括但不限于:

  • 了解 Linux 系统基本命令
  • 了解网络传输协议
  • 有技术和经济能力完成 VPS 购买及管理
  • 有技术和经济能力完成域名购买及管理
  • 有技术能力完成 TLS 证书申请 等等。

这就让【自建 VPS 科学上网】这个曾经简单的行为逐渐变成了令新人望而生畏的挑战。

二、零基础用户的无奈

零基础的非技术用户,如果完成上面这一连串的操作,势必要学习大量的知识,但稍微搜索之后,新人只怕会更加迷茫:大量的信息散布在互联网的各个角落:博客、问答网站、群组、论坛、GitHub、Telegram、YouTube 等等等等)。这些信息纷乱复杂、水平良莠不齐、甚至可能互相矛盾。基本上就是不把新人彻底弄晕誓不罢休。

面对这些杂乱无章的信息,新人突然就从【信息匮乏】变成了【信息过剩】。若是几番连蒙带猜的折腾以失败告终(大概率如此)的话,他的积极性势必大受挫折。在这个过程中,若他又恰好去了一些不太友好的地方去求助,恐怕还要雪上加霜的被嘲讽一番:“这么菜,用机场不就行了,瞎折腾什么啊!”、“先去学会 Linux 再回来问吧”。

这时候,大概也只有一声“呵呵”可以表达心情了。

1.5 “用机场不就行了?”

首先,我想反问一下那些冷嘲热讽的人:“用机场”真的就是万灵药吗?

其次,我认为“不懂”和“不想懂”是有本质区别的。态度恶劣的巨婴伸手党自然惹人厌烦,但真心自学却不得要领的人不该受到无端的白眼和歧视,也正是这种对新人不加区分的恶劣社区氛围促使我写下本文。那么闲话少说,我们来看看机场的优势与劣势究竟如何:

一、“机场“的优势

所谓“机场”,就是“线路提供商”。他负责完成 1.4 提到的那一串技术操作和管理,用户则付费获得使用权。所以,它的优点至少有:

  1. 用户操作简单:扫码操作、一键添加规则等
  2. 线路选择多:可解锁不同国家、地区的网络服务;比如 iplc 等专线服务、游戏加速服务等
  3. 接入节点多:所以抵抗节点封锁的能力强一些,封了一个就换下一个

二、“机场”的风险

“方便”这枚硬币的另一面就是“风险”,基于“机场”的技术特点和市场情况,它的风险至少有:

  1. “机场”可完全获得用户信息:用户在网上的所有痕迹,都【必然】经过且【非常可能】长期存储在其服务器上,这些记录无法受到任何具备法律效力的用户隐私协议的约束(窥视、记录你的一举一动
  2. “机场”缺乏市场管理:不可避免存在着以欺诈为目标的恶意商家(主动跑路
  3. “机场”面临监管压力:大机场相对有保障的同时,也无法避免树大招风。2020 年间,已经有几个大机场停运、跑路的事件发生,用户的正常使用受到严重干扰(被动跑路
  4. “机场”技术水平难以确定:线路质量良莠不齐,挂羊头卖狗肉的现象屡见不鲜(速度慢、掉线多、连不上

1.6 那么你到底要不要自建呢?

现在,你已经看到了机场的优势和风险,要用什么,就请各位充分思考并自行决定。毕竟,最适合你的方案才是最好的方案。

It's Your Choice!

  1. 如果决定使用机场的话,现在,你可以关闭本文了。

  2. 如果你决定自建,那就请继续阅读后面的章节吧!!

总之,本文的目标就是成为零基础用户的知识起点,提供对每一步充分的讲解和演示,清清楚楚(甚至婆婆妈妈、絮絮叨叨、啰啰嗦嗦)的协助新人完成【从输入第一条命令开始,完成 VPS 服务器部署,并成功在客户端完成科学上网】的全程。并在这个过程中帮助新人逐步接触和熟悉 Linux 的基础操作,为之后的进一步自学打下基础。

1.7 题外啰嗦几句

  1. 墙外的信息泥沙俱下,请务必学会理性、独立的思辨,不要随意站队,不要轻信猎奇的信息。

  2. 衷心希望大家获得更顺畅的网络后,可以获取更新鲜的知识、更丰富的娱乐、接触更美好的世界、结交更多志同道合的朋友,但不要成为任何有不可告人目的之人的替罪羊。

  3. 你的互联网身份依然是你的身份,绝对的匿名化是极为困难的,所以请务必遵守你个人所在地区和 IP 所在地区的相关法律法规。无论何时,自我保护都是最基本的底线。

1.8 你的进度

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

',41);function h(c,d){const p=a("I18nTip");return n(),o("div",null,[r(p),l])}const _=s(t,[["render",h],["__file","ch01-preface.html.vue"]]);export{_ as default}; diff --git a/assets/ch01-preface.html-CtiGatzy.js b/assets/ch01-preface.html-CVJyR7B9.js similarity index 99% rename from assets/ch01-preface.html-CtiGatzy.js rename to assets/ch01-preface.html-CVJyR7B9.js index a9cbed561f..5280821138 100644 --- a/assets/ch01-preface.html-CtiGatzy.js +++ b/assets/ch01-preface.html-CVJyR7B9.js @@ -1 +1 @@ -import{_ as s,r as o,o as p,c as r,a,e as t}from"./app-5SoadDYS.js";const e="/assets/ch01-img01-choice-DrFC1LCY.png",i={},l=t('

【Глава 1】 Простыми словами

1.1 Для кого эта документация?

В двух словах: для ① новичков без опыта ② желающих научиться настраивать свой собственный VPS.

1.2 Для кого эта документация не предназначена?

В том числе, но не ограничиваясь: для всевозможных гуру и экспертов, для тех, кто слишком ленив, чтобы во всём разбираться самостоятельно, для тех, кто уже умеет настраивать VPS, для тех, кто точно решил пользоваться платными VPN-сервисами, для тех, кто предпочитает использовать готовые скрипты... Короче говоря, если у вас есть технические знания или вы не хотите настраивать всё сами, можете смело закрывать эту статью. Скорее всего, она покажется вам бесполезной и даже может вызвать раздражение, а оно вам надо?

1.3 Важное замечание и другие примечания

Важное замечание:

Я не являюсь техническим экспертом, поэтому в этой статье неизбежны пробелы и неточности. Если вы обнаружите какие-либо ошибки, пожалуйста, дайте мне знать об этом деликатно, без лишних эмоций.

Отказ от ответственности:

Пожалуйста, относитесь к информации, представленной в этой статье, критически и проверяйте её самостоятельно. Я не несу никакой ответственности за любые проблемы или негативные последствия, возникшие в результате использования информации из этой статьи.

Предупреждение о многословности:

Поскольку эта статья предназначена для новичков без опыта, многие вещи будут объяснены максимально подробно. Поэтому будьте готовы к тому, что текст будет довольно многословным.

1.4 Почему самостоятельная настройка — это сложно?

Чтобы ответить на этот вопрос, нужно немного углубиться в историю вопроса.

Во-первых, обход блокировок существует уже почти двадцать лет (Шок! Ужас!). Сначала для этого достаточно было пары манипуляций (поправить файл hosts, подключиться по SSH), потом понадобились веб-прокси, затем — собственные протоколы (например, Shadowsocks) и так далее.

По мере того, как технологии блокировок совершенствовались на протяжении последних десятилетий, для самостоятельного обхода блокировок теперь нужно уметь:

  • Разбираться в основных командах Linux.
  • Понимать принципы работы сетевых протоколов.
  • Иметь технические навыки и средства для покупки и управления VPS.
  • Иметь технические навыки и средства для покупки и управления доменными именами.
  • Уметь получать TLS-сертификаты.
  • И многое другое.

Всё это превратило некогда простую задачу в пугающее испытание для новичков.

Во-вторых, о проблемах новичков.

Начинающим пользователям без технического бэкграунда, чтобы разобраться во всех этих премудростях, приходится изучать огромные массивы информации, разбросанной по всему интернету: блогам, форумам, группам в мессенджерах, репозиториям на GitHub, видео на YouTube и так далее.

Вся эта информация часто оказывается противоречивой, неполной или попросту неверной. Новичкам остаётся только гадать, кому верить и как всё это работает на самом деле.

В итоге вместо нехватки информации новички сталкиваются с её избытком. После нескольких (скорее всего, неудачных) попыток разобраться во всём этом, их энтузиазм угасает. А если по пути им ещё и «посчастливится» обратиться за помощью не в то место, их могут ещё и высмеять: «Ну ты и нуб, проще уж платным VPN пользоваться, зачем изобретать велосипед?» или «Сначала Linux изучи, потом приходи».

В такие моменты остаётся только горько усмехнуться.

1.5 «Почему бы просто не пользоваться платным VPN?»

Во-первых, я хотел бы спросить у любителей подобных советов: разве платные VPN — это панацея?

Во-вторых, я считаю, что «не знать» и «не хотеть знать» — это две большие разницы. Конечно, инфантилы, которые хотят всё и сразу, не прилагая никаких усилий, вызывают только раздражение. Но люди, которые искренне хотят разобраться во всём сами, не заслуживают презрения и издёвок. Именно эта нетерпимость к новичкам и побудила меня написать эту статью.

Давайте разберёмся, в чём плюсы и минусы платных VPN-сервисов.

Плюсы:

  1. Простота использования: сканирование QR-кода, добавление правил в один клик и т.д.
  2. Большой выбор серверов: доступ к ресурсам разных стран и регионов; например, выделенные серверы с низкой задержкой (iplc), серверы для онлайн-игр и т.д.
  3. Множество точек подключения: выше устойчивость к блокировкам, если один сервер заблокируют, можно подключиться к другому.

Риски:

За удобство приходится платить, и в случае с платными VPN-сервисами риски следующие:

  1. VPN-провайдер имеет полный доступ к вашим данным: всё, что вы делаете в интернете, обязательно проходит и с большой вероятностью хранится на серверах провайдера. Эти данные никак не защищены пользовательским соглашением или законом о защите персональных данных (вас могут отслеживать и записывать всё, что вы делаете).
  2. Отсутствие регулирования рынка: высока вероятность нарваться на мошенников (провайдер может в любой момент исчезнуть с вашими деньгами).
  3. Давление со стороны регулирующих органов: крупные VPN-провайдеры, с одной стороны, кажутся более надёжными, но, с другой стороны, чаще привлекают к себе внимание властей. В 2020 году было несколько случаев закрытия и прекращения работы крупных VPN-провайдеров, что привело к серьёзным неудобствам для пользователей (провайдер может быть вынужден прекратить работу).
  4. Непрозрачность технических решений: качество предоставляемых услуг может сильно варьироваться, не редки случаи обмана (низкая скорость, частые обрывы связи, невозможность подключения).

1.6 Так стоит ли настраивать VPN самостоятельно?

Теперь, когда вы знаете о плюсах и минусах платных VPN, решать вам. В конце концов, лучший вариант — тот, который подходит именно вам.

Выбор за вами!

  1. Если вы решили воспользоваться платным VPN, можете закрыть эту статью.

  2. Если же вы решили настроить всё самостоятельно, продолжайте чтение!

Цель этой статьи — стать отправной точкой для новичков, предоставить подробное пошаговое руководство по настройке VPN-сервера на VPS, начиная с ввода первой команды и заканчивая успешным подключением к заблокированным ресурсам.

В процессе настройки вы познакомитесь с основными командами Linux, что станет хорошей базой для дальнейшего изучения этой операционной системы.

1.7 Немного лирики

  1. В интернете много дезинформации, поэтому важно научиться критически мыслить, не поддаваться на провокации и не верить всему, что пишут.
  2. Искренне надеюсь, что, получив доступ к свободному интернету, вы сможете узнавать больше нового, наслаждаться разнообразным контентом, знакомиться с интересными людьми и находить единомышленников.
  3. Ваша личность в интернете — это всё ещё вы. Добиться полной анонимности крайне сложно, поэтому не забывайте о законах вашей страны и стран, IP-адреса которых вы используете. Всегда помните о собственной безопасности.

1.8 Ваш прогресс

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

',42);function h(c,g){const n=o("I18nTip");return p(),r("div",null,[a(n),l])}const _=s(i,[["render",h],["__file","ch01-preface.html.vue"]]);export{_ as default}; +import{_ as s,r as o,o as p,c as r,a,e as t}from"./app-Bw2NG-QJ.js";const e="/assets/ch01-img01-choice-DrFC1LCY.png",i={},l=t('

【Глава 1】 Простыми словами

1.1 Для кого эта документация?

В двух словах: для ① новичков без опыта ② желающих научиться настраивать свой собственный VPS.

1.2 Для кого эта документация не предназначена?

В том числе, но не ограничиваясь: для всевозможных гуру и экспертов, для тех, кто слишком ленив, чтобы во всём разбираться самостоятельно, для тех, кто уже умеет настраивать VPS, для тех, кто точно решил пользоваться платными VPN-сервисами, для тех, кто предпочитает использовать готовые скрипты... Короче говоря, если у вас есть технические знания или вы не хотите настраивать всё сами, можете смело закрывать эту статью. Скорее всего, она покажется вам бесполезной и даже может вызвать раздражение, а оно вам надо?

1.3 Важное замечание и другие примечания

Важное замечание:

Я не являюсь техническим экспертом, поэтому в этой статье неизбежны пробелы и неточности. Если вы обнаружите какие-либо ошибки, пожалуйста, дайте мне знать об этом деликатно, без лишних эмоций.

Отказ от ответственности:

Пожалуйста, относитесь к информации, представленной в этой статье, критически и проверяйте её самостоятельно. Я не несу никакой ответственности за любые проблемы или негативные последствия, возникшие в результате использования информации из этой статьи.

Предупреждение о многословности:

Поскольку эта статья предназначена для новичков без опыта, многие вещи будут объяснены максимально подробно. Поэтому будьте готовы к тому, что текст будет довольно многословным.

1.4 Почему самостоятельная настройка — это сложно?

Чтобы ответить на этот вопрос, нужно немного углубиться в историю вопроса.

Во-первых, обход блокировок существует уже почти двадцать лет (Шок! Ужас!). Сначала для этого достаточно было пары манипуляций (поправить файл hosts, подключиться по SSH), потом понадобились веб-прокси, затем — собственные протоколы (например, Shadowsocks) и так далее.

По мере того, как технологии блокировок совершенствовались на протяжении последних десятилетий, для самостоятельного обхода блокировок теперь нужно уметь:

  • Разбираться в основных командах Linux.
  • Понимать принципы работы сетевых протоколов.
  • Иметь технические навыки и средства для покупки и управления VPS.
  • Иметь технические навыки и средства для покупки и управления доменными именами.
  • Уметь получать TLS-сертификаты.
  • И многое другое.

Всё это превратило некогда простую задачу в пугающее испытание для новичков.

Во-вторых, о проблемах новичков.

Начинающим пользователям без технического бэкграунда, чтобы разобраться во всех этих премудростях, приходится изучать огромные массивы информации, разбросанной по всему интернету: блогам, форумам, группам в мессенджерах, репозиториям на GitHub, видео на YouTube и так далее.

Вся эта информация часто оказывается противоречивой, неполной или попросту неверной. Новичкам остаётся только гадать, кому верить и как всё это работает на самом деле.

В итоге вместо нехватки информации новички сталкиваются с её избытком. После нескольких (скорее всего, неудачных) попыток разобраться во всём этом, их энтузиазм угасает. А если по пути им ещё и «посчастливится» обратиться за помощью не в то место, их могут ещё и высмеять: «Ну ты и нуб, проще уж платным VPN пользоваться, зачем изобретать велосипед?» или «Сначала Linux изучи, потом приходи».

В такие моменты остаётся только горько усмехнуться.

1.5 «Почему бы просто не пользоваться платным VPN?»

Во-первых, я хотел бы спросить у любителей подобных советов: разве платные VPN — это панацея?

Во-вторых, я считаю, что «не знать» и «не хотеть знать» — это две большие разницы. Конечно, инфантилы, которые хотят всё и сразу, не прилагая никаких усилий, вызывают только раздражение. Но люди, которые искренне хотят разобраться во всём сами, не заслуживают презрения и издёвок. Именно эта нетерпимость к новичкам и побудила меня написать эту статью.

Давайте разберёмся, в чём плюсы и минусы платных VPN-сервисов.

Плюсы:

  1. Простота использования: сканирование QR-кода, добавление правил в один клик и т.д.
  2. Большой выбор серверов: доступ к ресурсам разных стран и регионов; например, выделенные серверы с низкой задержкой (iplc), серверы для онлайн-игр и т.д.
  3. Множество точек подключения: выше устойчивость к блокировкам, если один сервер заблокируют, можно подключиться к другому.

Риски:

За удобство приходится платить, и в случае с платными VPN-сервисами риски следующие:

  1. VPN-провайдер имеет полный доступ к вашим данным: всё, что вы делаете в интернете, обязательно проходит и с большой вероятностью хранится на серверах провайдера. Эти данные никак не защищены пользовательским соглашением или законом о защите персональных данных (вас могут отслеживать и записывать всё, что вы делаете).
  2. Отсутствие регулирования рынка: высока вероятность нарваться на мошенников (провайдер может в любой момент исчезнуть с вашими деньгами).
  3. Давление со стороны регулирующих органов: крупные VPN-провайдеры, с одной стороны, кажутся более надёжными, но, с другой стороны, чаще привлекают к себе внимание властей. В 2020 году было несколько случаев закрытия и прекращения работы крупных VPN-провайдеров, что привело к серьёзным неудобствам для пользователей (провайдер может быть вынужден прекратить работу).
  4. Непрозрачность технических решений: качество предоставляемых услуг может сильно варьироваться, не редки случаи обмана (низкая скорость, частые обрывы связи, невозможность подключения).

1.6 Так стоит ли настраивать VPN самостоятельно?

Теперь, когда вы знаете о плюсах и минусах платных VPN, решать вам. В конце концов, лучший вариант — тот, который подходит именно вам.

Выбор за вами!

  1. Если вы решили воспользоваться платным VPN, можете закрыть эту статью.

  2. Если же вы решили настроить всё самостоятельно, продолжайте чтение!

Цель этой статьи — стать отправной точкой для новичков, предоставить подробное пошаговое руководство по настройке VPN-сервера на VPS, начиная с ввода первой команды и заканчивая успешным подключением к заблокированным ресурсам.

В процессе настройки вы познакомитесь с основными командами Linux, что станет хорошей базой для дальнейшего изучения этой операционной системы.

1.7 Немного лирики

  1. В интернете много дезинформации, поэтому важно научиться критически мыслить, не поддаваться на провокации и не верить всему, что пишут.
  2. Искренне надеюсь, что, получив доступ к свободному интернету, вы сможете узнавать больше нового, наслаждаться разнообразным контентом, знакомиться с интересными людьми и находить единомышленников.
  3. Ваша личность в интернете — это всё ещё вы. Добиться полной анонимности крайне сложно, поэтому не забывайте о законах вашей страны и стран, IP-адреса которых вы используете. Всегда помните о собственной безопасности.

1.8 Ваш прогресс

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

',42);function h(c,g){const n=o("I18nTip");return p(),r("div",null,[a(n),l])}const _=s(i,[["render",h],["__file","ch01-preface.html.vue"]]);export{_ as default}; diff --git a/assets/ch02-preparation.html-zWJTI2fh.js b/assets/ch02-preparation.html-3rYGUPF0.js similarity index 98% rename from assets/ch02-preparation.html-zWJTI2fh.js rename to assets/ch02-preparation.html-3rYGUPF0.js index 04d9b7094d..1a66e5a0e2 100644 --- a/assets/ch02-preparation.html-zWJTI2fh.js +++ b/assets/ch02-preparation.html-3rYGUPF0.js @@ -1 +1 @@ -import{_ as s,r as a,o as i,c,a as o,b as n,d as e,e as r}from"./app-5SoadDYS.js";const p="/assets/ch02-img01-a-name-Bhw9qwKG.png",d={},u=r('

【第 2 章】原料准备篇

这一章比较特殊,因为涉及到金钱交易行为,本文基于项目的中立立场,不做具体的推荐。我能做的,是告诉你需要准备哪些东西。

2.1 获取一台 VPS

你需要获取一台健康的、IP 没有被墙的 VPS,并在管理后台做下面这些基础准备:

  1. 在 VPS 的后台安装 Debian 10 64bit 系统
  2. 小本本记下 VPS 的 IP 地址(本文会用 "100.200.300.400" 来表示)

    提示

    这是一个故意写错的非法 IP,请替换成你的真实 IP)

  3. 小本本记下 VPS 的 SSH 远程登陆端口(Port)
  4. 小本本记下 SSH 远程登录的用户名和密码

购买 VPS 是一个比较复杂的事情,建议先去学习一下相关知识,选择适合自己的经济能力和线路需求的即可。另外可以选择薅一些国际大厂的羊毛(比如甲骨文和谷歌提供的永久免费或限时免费的套餐)。总之,务必量力而行。

说明

关于选择 Debian 10 作为操作系统,这里稍微多说一句:不管你在网上听说了什么,不管哪个大神告诉你 XXX 版的 Linux 更好、XXX 版的 Linux 更牛,这些 Linux 的派系之争跟现在的你半毛钱关系也没有!使用 Debian 10 足以让你的 VPS 服务器在安全、稳健运行的同时得到足够的优化(如 cloud 专用内核、及时的 bbr 支持等)。等你对 Linux 熟悉之后,再回头去尝试其他的 Linux 发行版也不迟。

2.2 获取一个心仪的域名

你需要获取一个域名、并在 DNS 设置中添加一条 A 记录,指向你 VPS 的 IP 地址

  1. 请选择靠谱的国际域名服务商。选择一些常见的域名后缀就行,注意不要用 .cn 后缀。
  2. 在 DNS 设置中,添加一条指向你 VPS 的 IP 地址的 A 记录(A 记录的名字可以随便起,本文会用 "a-name" 来表示。完整的域名则会用 "二级域名.你的域名.com" 或者 "a-name.yourdomain.com" 来表示)。效果如下图:

添加A记录

提示

不是一个真实可用的网址,请替换成你的真实网址

2.3 你本地电脑上需要安装的软件

',13),h=n("p",null,"SSH 远程登录工具",-1),_={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},m=n("li",null,"macOS/Linux: Terminal",-1),S=n("p",null,"远程文件拷贝工具",-1),x={href:"https://winscp.net/eng/index.php",target:"_blank",rel:"noopener noreferrer"},P=n("li",null,"macOS/Linux: Terminal",-1),f=n("p",null,"靠谱的文本编辑器",-1),b={href:"https://code.visualstudio.com",target:"_blank",rel:"noopener noreferrer"},g=n("h2",{id:"_2-4-你的进度",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-4-你的进度"},[n("span",null,"2.4 你的进度")])],-1),V=n("p",null,"如果上面的原材料你都准备好了的话,你已经拿到了开启新世界大门的钥匙。那还等什么,让我们快点进入下一章,走进这扇门吧!",-1),v=n("blockquote",null,[n("p",null,"⬛⬛⬜⬜⬜⬜⬜⬜ 25%")],-1);function k(q,I){const l=a("I18nTip"),t=a("ExternalLinkIcon");return i(),c("div",null,[o(l),u,n("ol",null,[n("li",null,[h,n("ul",null,[n("li",null,[e("Windows: "),n("a",_,[e("PuTTY"),o(t)])]),m])]),n("li",null,[S,n("ul",null,[n("li",null,[e("Windows: "),n("a",x,[e("WinSCP"),o(t)])]),P])]),n("li",null,[f,n("ul",null,[n("li",null,[e("Windows/macOS/Linux: "),n("a",b,[e("VSCode"),o(t)])])])])]),g,V,v])}const w=s(d,[["render",k],["__file","ch02-preparation.html.vue"]]);export{w as default}; +import{_ as s,r as a,o as i,c,a as o,b as n,d as e,e as r}from"./app-Bw2NG-QJ.js";const p="/assets/ch02-img01-a-name-Bhw9qwKG.png",d={},u=r('

【第 2 章】原料准备篇

这一章比较特殊,因为涉及到金钱交易行为,本文基于项目的中立立场,不做具体的推荐。我能做的,是告诉你需要准备哪些东西。

2.1 获取一台 VPS

你需要获取一台健康的、IP 没有被墙的 VPS,并在管理后台做下面这些基础准备:

  1. 在 VPS 的后台安装 Debian 10 64bit 系统
  2. 小本本记下 VPS 的 IP 地址(本文会用 "100.200.300.400" 来表示)

    提示

    这是一个故意写错的非法 IP,请替换成你的真实 IP)

  3. 小本本记下 VPS 的 SSH 远程登陆端口(Port)
  4. 小本本记下 SSH 远程登录的用户名和密码

购买 VPS 是一个比较复杂的事情,建议先去学习一下相关知识,选择适合自己的经济能力和线路需求的即可。另外可以选择薅一些国际大厂的羊毛(比如甲骨文和谷歌提供的永久免费或限时免费的套餐)。总之,务必量力而行。

说明

关于选择 Debian 10 作为操作系统,这里稍微多说一句:不管你在网上听说了什么,不管哪个大神告诉你 XXX 版的 Linux 更好、XXX 版的 Linux 更牛,这些 Linux 的派系之争跟现在的你半毛钱关系也没有!使用 Debian 10 足以让你的 VPS 服务器在安全、稳健运行的同时得到足够的优化(如 cloud 专用内核、及时的 bbr 支持等)。等你对 Linux 熟悉之后,再回头去尝试其他的 Linux 发行版也不迟。

2.2 获取一个心仪的域名

你需要获取一个域名、并在 DNS 设置中添加一条 A 记录,指向你 VPS 的 IP 地址

  1. 请选择靠谱的国际域名服务商。选择一些常见的域名后缀就行,注意不要用 .cn 后缀。
  2. 在 DNS 设置中,添加一条指向你 VPS 的 IP 地址的 A 记录(A 记录的名字可以随便起,本文会用 "a-name" 来表示。完整的域名则会用 "二级域名.你的域名.com" 或者 "a-name.yourdomain.com" 来表示)。效果如下图:

添加A记录

提示

不是一个真实可用的网址,请替换成你的真实网址

2.3 你本地电脑上需要安装的软件

',13),h=n("p",null,"SSH 远程登录工具",-1),_={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},m=n("li",null,"macOS/Linux: Terminal",-1),S=n("p",null,"远程文件拷贝工具",-1),x={href:"https://winscp.net/eng/index.php",target:"_blank",rel:"noopener noreferrer"},P=n("li",null,"macOS/Linux: Terminal",-1),f=n("p",null,"靠谱的文本编辑器",-1),b={href:"https://code.visualstudio.com",target:"_blank",rel:"noopener noreferrer"},g=n("h2",{id:"_2-4-你的进度",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-4-你的进度"},[n("span",null,"2.4 你的进度")])],-1),V=n("p",null,"如果上面的原材料你都准备好了的话,你已经拿到了开启新世界大门的钥匙。那还等什么,让我们快点进入下一章,走进这扇门吧!",-1),v=n("blockquote",null,[n("p",null,"⬛⬛⬜⬜⬜⬜⬜⬜ 25%")],-1);function k(q,I){const l=a("I18nTip"),t=a("ExternalLinkIcon");return i(),c("div",null,[o(l),u,n("ol",null,[n("li",null,[h,n("ul",null,[n("li",null,[e("Windows: "),n("a",_,[e("PuTTY"),o(t)])]),m])]),n("li",null,[S,n("ul",null,[n("li",null,[e("Windows: "),n("a",x,[e("WinSCP"),o(t)])]),P])]),n("li",null,[f,n("ul",null,[n("li",null,[e("Windows/macOS/Linux: "),n("a",b,[e("VSCode"),o(t)])])])])]),g,V,v])}const w=s(d,[["render",k],["__file","ch02-preparation.html.vue"]]);export{w as default}; diff --git a/assets/ch02-preparation.html-DOc8B9wn.js b/assets/ch02-preparation.html-Bux35H5q.js similarity index 99% rename from assets/ch02-preparation.html-DOc8B9wn.js rename to assets/ch02-preparation.html-Bux35H5q.js index 5395e95cc0..1b91416a0f 100644 --- a/assets/ch02-preparation.html-DOc8B9wn.js +++ b/assets/ch02-preparation.html-Bux35H5q.js @@ -1 +1 @@ -import{_ as s,r as l,o as i,c,a as o,b as n,d as e,e as r}from"./app-5SoadDYS.js";const p="/assets/ch02-img01-a-name-Bhw9qwKG.png",d={},u=r('

【Глава 2】 Подготовка

Эта глава особенная, поскольку затрагивает финансовые операции. В соответствии с нейтральной позицией проекта, здесь не будет конкретных рекомендаций. Всё, что я могу сделать, — это рассказать, что вам понадобится.

2.1 Приобретение VPS

Вам нужно получить работающий VPS с не заблокированным IP-адресом и выполнить следующие базовые действия в панели управления:

  1. Установить на VPS операционную систему Debian 10 64-bit.
  2. Записать IP-адрес VPS (в этой статье он будет обозначаться как "100.200.300.400").

    Подсказка

    Это неверный IP-адрес, используемый только в качестве примера. Не забудьте заменить его на свой реальный IP-адрес.

  3. Записать порт (Port) SSH для удалённого подключения к VPS.
  4. Записать имя пользователя и пароль для удалённого подключения по SSH.

Выбор и покупка VPS — дело непростое. Рекомендуем сначала изучить этот вопрос и выбрать тариф, который соответствует вашим финансовым возможностям и требованиям к скорости и качеству связи. Также можно воспользоваться бесплатными (постоянными или временными) предложениями от крупных облачных провайдеров, таких как Oracle Cloud и Google Cloud. Главное — не влезайте в долги.

Пояснение

Несколько слов о выборе Debian 10 в качестве операционной системы. Что бы вы ни слышали в интернете, какой бы дистрибутив Linux ни советовали вам гуру, все эти споры о том, какой Linux лучше, не имеют к вам никакого отношения! Debian 10 — это надёжная и стабильная операционная система, которая отлично подходит для работы VPN-сервера и достаточно оптимизирована (например, имеет специальное ядро для облачных сред и своевременную поддержку BBR). Когда вы освоитесь с Linux, можете попробовать и другие дистрибутивы.

2.2 Выбор доменного имени

Вам нужно получить доменное имя и добавить A-запись, указывающую на IP-адрес вашего VPS, в настройках DNS.

  1. Выберите надёжного международного регистратора доменных имён. Доменная зона (расширение домена) может быть любой, главное — не используйте .cn.
  2. В настройках DNS добавьте A-запись, указывающую на IP-адрес вашего VPS (имя A-записи может быть любым, в этой статье оно будет обозначаться как "a-name". Полное доменное имя будет выглядеть как "a-name.yourdomain.com"). Должно получиться примерно так:

Добавление A-записи

Подсказка

Это не настоящий URL-адрес. Не забудьте заменить его на свой реальный адрес.

2.3 Необходимое программное обеспечение

',13),h=n("p",null,"SSH-клиент для удалённого подключения:",-1),_={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},m=n("li",null,"macOS/Linux: Terminal",-1),S=n("p",null,"Программа для передачи файлов:",-1),P={href:"https://winscp.net/eng/index.php",target:"_blank",rel:"noopener noreferrer"},f=n("li",null,"macOS/Linux: Terminal",-1),x=n("p",null,"Хороший текстовый редактор:",-1),g={href:"https://code.visualstudio.com",target:"_blank",rel:"noopener noreferrer"},b=n("h2",{id:"_2-4-ваш-прогресс",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-4-ваш-прогресс"},[n("span",null,"2.4 Ваш прогресс")])],-1),V=n("p",null,"Если вы выполнили все пункты из этого раздела, у вас уже есть всё необходимое, чтобы открыть для себя новый мир. Так чего же мы ждём? Давайте перейдём к следующей главе и сделаем это!",-1),v=n("blockquote",null,[n("p",null,"⬛⬛⬜⬜⬜⬜⬜⬜ 25%")],-1);function k(I,w){const a=l("I18nTip"),t=l("ExternalLinkIcon");return i(),c("div",null,[o(a),u,n("ol",null,[n("li",null,[h,n("ul",null,[n("li",null,[e("Windows: "),n("a",_,[e("PuTTY"),o(t)])]),m])]),n("li",null,[S,n("ul",null,[n("li",null,[e("Windows: "),n("a",P,[e("WinSCP"),o(t)])]),f])]),n("li",null,[x,n("ul",null,[n("li",null,[e("Windows/macOS/Linux: "),n("a",g,[e("VSCode"),o(t)])])])])]),b,V,v])}const q=s(d,[["render",k],["__file","ch02-preparation.html.vue"]]);export{q as default}; +import{_ as s,r as l,o as i,c,a as o,b as n,d as e,e as r}from"./app-Bw2NG-QJ.js";const p="/assets/ch02-img01-a-name-Bhw9qwKG.png",d={},u=r('

【Глава 2】 Подготовка

Эта глава особенная, поскольку затрагивает финансовые операции. В соответствии с нейтральной позицией проекта, здесь не будет конкретных рекомендаций. Всё, что я могу сделать, — это рассказать, что вам понадобится.

2.1 Приобретение VPS

Вам нужно получить работающий VPS с не заблокированным IP-адресом и выполнить следующие базовые действия в панели управления:

  1. Установить на VPS операционную систему Debian 10 64-bit.
  2. Записать IP-адрес VPS (в этой статье он будет обозначаться как "100.200.300.400").

    Подсказка

    Это неверный IP-адрес, используемый только в качестве примера. Не забудьте заменить его на свой реальный IP-адрес.

  3. Записать порт (Port) SSH для удалённого подключения к VPS.
  4. Записать имя пользователя и пароль для удалённого подключения по SSH.

Выбор и покупка VPS — дело непростое. Рекомендуем сначала изучить этот вопрос и выбрать тариф, который соответствует вашим финансовым возможностям и требованиям к скорости и качеству связи. Также можно воспользоваться бесплатными (постоянными или временными) предложениями от крупных облачных провайдеров, таких как Oracle Cloud и Google Cloud. Главное — не влезайте в долги.

Пояснение

Несколько слов о выборе Debian 10 в качестве операционной системы. Что бы вы ни слышали в интернете, какой бы дистрибутив Linux ни советовали вам гуру, все эти споры о том, какой Linux лучше, не имеют к вам никакого отношения! Debian 10 — это надёжная и стабильная операционная система, которая отлично подходит для работы VPN-сервера и достаточно оптимизирована (например, имеет специальное ядро для облачных сред и своевременную поддержку BBR). Когда вы освоитесь с Linux, можете попробовать и другие дистрибутивы.

2.2 Выбор доменного имени

Вам нужно получить доменное имя и добавить A-запись, указывающую на IP-адрес вашего VPS, в настройках DNS.

  1. Выберите надёжного международного регистратора доменных имён. Доменная зона (расширение домена) может быть любой, главное — не используйте .cn.
  2. В настройках DNS добавьте A-запись, указывающую на IP-адрес вашего VPS (имя A-записи может быть любым, в этой статье оно будет обозначаться как "a-name". Полное доменное имя будет выглядеть как "a-name.yourdomain.com"). Должно получиться примерно так:

Добавление A-записи

Подсказка

Это не настоящий URL-адрес. Не забудьте заменить его на свой реальный адрес.

2.3 Необходимое программное обеспечение

',13),h=n("p",null,"SSH-клиент для удалённого подключения:",-1),_={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},m=n("li",null,"macOS/Linux: Terminal",-1),S=n("p",null,"Программа для передачи файлов:",-1),P={href:"https://winscp.net/eng/index.php",target:"_blank",rel:"noopener noreferrer"},f=n("li",null,"macOS/Linux: Terminal",-1),x=n("p",null,"Хороший текстовый редактор:",-1),g={href:"https://code.visualstudio.com",target:"_blank",rel:"noopener noreferrer"},b=n("h2",{id:"_2-4-ваш-прогресс",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_2-4-ваш-прогресс"},[n("span",null,"2.4 Ваш прогресс")])],-1),V=n("p",null,"Если вы выполнили все пункты из этого раздела, у вас уже есть всё необходимое, чтобы открыть для себя новый мир. Так чего же мы ждём? Давайте перейдём к следующей главе и сделаем это!",-1),v=n("blockquote",null,[n("p",null,"⬛⬛⬜⬜⬜⬜⬜⬜ 25%")],-1);function k(I,w){const a=l("I18nTip"),t=l("ExternalLinkIcon");return i(),c("div",null,[o(a),u,n("ol",null,[n("li",null,[h,n("ul",null,[n("li",null,[e("Windows: "),n("a",_,[e("PuTTY"),o(t)])]),m])]),n("li",null,[S,n("ul",null,[n("li",null,[e("Windows: "),n("a",P,[e("WinSCP"),o(t)])]),f])]),n("li",null,[x,n("ul",null,[n("li",null,[e("Windows/macOS/Linux: "),n("a",g,[e("VSCode"),o(t)])])])])]),b,V,v])}const q=s(d,[["render",k],["__file","ch02-preparation.html.vue"]]);export{q as default}; diff --git a/assets/ch02-preparation.html-CBryXq1M.js b/assets/ch02-preparation.html-BuxrUsmj.js similarity index 98% rename from assets/ch02-preparation.html-CBryXq1M.js rename to assets/ch02-preparation.html-BuxrUsmj.js index c5e3cecd99..1fe2dacb95 100644 --- a/assets/ch02-preparation.html-CBryXq1M.js +++ b/assets/ch02-preparation.html-BuxrUsmj.js @@ -1 +1 @@ -import{_ as r,r as n,o as s,c as l,a as t,b as e,d as o,e as c}from"./app-5SoadDYS.js";const d="/assets/ch02-img01-a-name-Bhw9qwKG.png",h={},u=c('

[Chapter 2] Preparation of Raw Materials

This chapter is rather special because it involves monetary transactions. This article takes a neutral stance on the project and does not make specific recommendations. What I can do is to tell you what you need to prepare.

2.1 Acquiring a VPS

You need to obtain a healthy VPS with an unblocked IP, and perform the following basic preparations in the management console:

  1. Install Debian 10 64-bit system in the backend of VPS.
  2. Write down the IP address of VPS in a notebook (this article will use "100.200.300.400" as an example, which is an intentionally incorrect and illegal IP address. Please replace it with your real IP address).
  3. Write down the SSH remote login port of VPS in a notebook.
  4. Write down the username and password for SSH remote login in a notebook.

Buying a VPS is a relatively complex matter. It is recommended to first learn the relevant knowledge and choose one that suits your own economic ability and line requirements. In addition, you can choose to take advantage of some benefits offered by international giants (such as permanent free or limited-time free packages offered by Oracle and Google). In any case, you must act within your means.

Explanation

Regarding the choice of Debian 10 as the operating system, let me elaborate a bit: No matter what you have heard online, no matter which guru has told you that XXX version of Linux is better or XXX version of Linux is more powerful, these sectarian disputes have nothing to do with you right now! Using Debian 10 is enough to optimize your VPS server for security, stability, and performance (such as using cloud-optimized kernel, timely support of BBR, etc.). After you become familiar with Linux, you can try other Linux distributions.

2.2 Obtaining a Desired Domain Name

You need to obtain a domain name and add an A record in the DNS settings, pointing to the IP address of your VPS.

  1. Please choose a reliable international domain name service provider. Choose some common domain name suffixes, and make sure not to use the .cn suffix.
  2. In the DNS settings, add an A record pointing to the IP address of your VPS (the name of the A record can be anything, and in this article, it will be represented by "a-name"). The complete domain name will be represented by "subdomain.yourdomain.com" or "a-name.yourdomain.com". The effect is as shown in the picture below:

Add A Record

Tip

This is not a real usable website. Please replace it with your real website URL.

2.3 Software you need to install on your local computer

  1. SSH remote login tool
',14),p={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},m=e("ul",null,[e("li",null,"macOS/Linux: Terminal")],-1),f=e("ol",{start:"2"},[e("li",null,"Remote file copying tool")],-1),g={href:"https://winscp.net/eng/index.php",target:"_blank",rel:"noopener noreferrer"},y=e("ul",null,[e("li",null,"macOS/Linux: Terminal")],-1),_={start:"3"},b={href:"https://code.visualstudio.com",target:"_blank",rel:"noopener noreferrer"},w=e("h2",{id:"_2-4-your-progress",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2-4-your-progress"},[e("span",null,"2.4 Your Progress")])],-1),v=e("p",null,"If you have all the raw materials ready as mentioned above, you have already obtained the key to unlocking the door to a new world. So, what are you waiting for? Let's quickly move on to the next chapter and step through this door!",-1),x=e("blockquote",null,[e("p",null,"⬛⬛⬜⬜⬜⬜⬜⬜ 25%")],-1);function k(S,P){const i=n("I18nTip"),a=n("ExternalLinkIcon");return s(),l("div",null,[t(i),u,e("ul",null,[e("li",null,[o("Windows: "),e("a",p,[o("PuTTY"),t(a)]),m])]),f,e("ul",null,[e("li",null,[o("Windows: "),e("a",g,[o("WinSCP"),t(a)]),y])]),e("ol",_,[e("li",null,[o("Reliable text editor "),e("ul",null,[e("li",null,[o("Windows/macOS/Linux: "),e("a",b,[o("VSCode"),t(a)])])])])]),w,v,x])}const q=r(h,[["render",k],["__file","ch02-preparation.html.vue"]]);export{q as default}; +import{_ as r,r as n,o as s,c as l,a as t,b as e,d as o,e as c}from"./app-Bw2NG-QJ.js";const d="/assets/ch02-img01-a-name-Bhw9qwKG.png",h={},u=c('

[Chapter 2] Preparation of Raw Materials

This chapter is rather special because it involves monetary transactions. This article takes a neutral stance on the project and does not make specific recommendations. What I can do is to tell you what you need to prepare.

2.1 Acquiring a VPS

You need to obtain a healthy VPS with an unblocked IP, and perform the following basic preparations in the management console:

  1. Install Debian 10 64-bit system in the backend of VPS.
  2. Write down the IP address of VPS in a notebook (this article will use "100.200.300.400" as an example, which is an intentionally incorrect and illegal IP address. Please replace it with your real IP address).
  3. Write down the SSH remote login port of VPS in a notebook.
  4. Write down the username and password for SSH remote login in a notebook.

Buying a VPS is a relatively complex matter. It is recommended to first learn the relevant knowledge and choose one that suits your own economic ability and line requirements. In addition, you can choose to take advantage of some benefits offered by international giants (such as permanent free or limited-time free packages offered by Oracle and Google). In any case, you must act within your means.

Explanation

Regarding the choice of Debian 10 as the operating system, let me elaborate a bit: No matter what you have heard online, no matter which guru has told you that XXX version of Linux is better or XXX version of Linux is more powerful, these sectarian disputes have nothing to do with you right now! Using Debian 10 is enough to optimize your VPS server for security, stability, and performance (such as using cloud-optimized kernel, timely support of BBR, etc.). After you become familiar with Linux, you can try other Linux distributions.

2.2 Obtaining a Desired Domain Name

You need to obtain a domain name and add an A record in the DNS settings, pointing to the IP address of your VPS.

  1. Please choose a reliable international domain name service provider. Choose some common domain name suffixes, and make sure not to use the .cn suffix.
  2. In the DNS settings, add an A record pointing to the IP address of your VPS (the name of the A record can be anything, and in this article, it will be represented by "a-name"). The complete domain name will be represented by "subdomain.yourdomain.com" or "a-name.yourdomain.com". The effect is as shown in the picture below:

Add A Record

Tip

This is not a real usable website. Please replace it with your real website URL.

2.3 Software you need to install on your local computer

  1. SSH remote login tool
',14),p={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},m=e("ul",null,[e("li",null,"macOS/Linux: Terminal")],-1),f=e("ol",{start:"2"},[e("li",null,"Remote file copying tool")],-1),g={href:"https://winscp.net/eng/index.php",target:"_blank",rel:"noopener noreferrer"},y=e("ul",null,[e("li",null,"macOS/Linux: Terminal")],-1),_={start:"3"},b={href:"https://code.visualstudio.com",target:"_blank",rel:"noopener noreferrer"},w=e("h2",{id:"_2-4-your-progress",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2-4-your-progress"},[e("span",null,"2.4 Your Progress")])],-1),v=e("p",null,"If you have all the raw materials ready as mentioned above, you have already obtained the key to unlocking the door to a new world. So, what are you waiting for? Let's quickly move on to the next chapter and step through this door!",-1),x=e("blockquote",null,[e("p",null,"⬛⬛⬜⬜⬜⬜⬜⬜ 25%")],-1);function k(S,P){const i=n("I18nTip"),a=n("ExternalLinkIcon");return s(),l("div",null,[t(i),u,e("ul",null,[e("li",null,[o("Windows: "),e("a",p,[o("PuTTY"),t(a)]),m])]),f,e("ul",null,[e("li",null,[o("Windows: "),e("a",g,[o("WinSCP"),t(a)]),y])]),e("ol",_,[e("li",null,[o("Reliable text editor "),e("ul",null,[e("li",null,[o("Windows/macOS/Linux: "),e("a",b,[o("VSCode"),t(a)])])])])]),w,v,x])}const q=r(h,[["render",k],["__file","ch02-preparation.html.vue"]]);export{q as default}; diff --git a/assets/ch03-ssh.html-B-PYaYYd.js b/assets/ch03-ssh.html-10pGoOUk.js similarity index 99% rename from assets/ch03-ssh.html-B-PYaYYd.js rename to assets/ch03-ssh.html-10pGoOUk.js index 78a59cd97a..a4da6471b2 100644 --- a/assets/ch03-ssh.html-B-PYaYYd.js +++ b/assets/ch03-ssh.html-10pGoOUk.js @@ -1,3 +1,3 @@ -import{_ as c,r as o,o as i,c as d,a as n,b as e,d as t,w as r,e as p}from"./app-5SoadDYS.js";const u="/assets/ch03-img01-putty-download-CBXDLA1o.png",h="/assets/ch03-img02-putty-settings-D0Xbl0Z8.png",_="/assets/ch03-img03-putty-keepalive-B2CBMeC6.png",g="/assets/ch03-img04-ssh-login-DwyvE7DL.png",m="/assets/ch03-img05-ssh-login-success-BulNCpdO.png",x="/assets/ch03-img06-apt-upgrade-full--w3BBGrx.gif",P={},S=e("h1",{id:"【第-3-章】远程登录篇",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#【第-3-章】远程登录篇"},[e("span",null,"【第 3 章】远程登录篇")])],-1),v=e("h2",{id:"_3-1-远程登录-vps-putty",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-1-远程登录-vps-putty"},[e("span",null,"3.1 远程登录 VPS (PuTTY)")])],-1),b=e("p",null,"首先,鉴于零基础人群中 Windows 的用户基数最大,所以本文以 Windows 为例进行展示。",-1),f=e("p",null,"其次,虽然 Windows 10 之后的 PowerShell 和 WSL 也可以达到很好的 SSH 操作体验。但是因为并非所有版本的 Windows 都有最新的组件,故本文还是以老牌的 PuTTY 为例,进行 SSH 远程登录的操作详解。(使用其他工具的话、在 SSH 登陆之后的操作都是一样的)",-1),y=e("p",null,"下面就跟我一步步操作吧。",-1),L={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},T=e("p",null,[e("img",{src:u,alt:"下载PuTTY"})],-1),k=e("strong",null,[t("IP 地址(VPS IP)"),e("strong",null,"和"),t("端口(VPS PORT)")],-1),w=e("p",null,[e("img",{src:h,alt:"设置PuTTY"})],-1),B=e("li",null,[e("p",null,[t("我建议将 "),e("code",null,"Connection"),t(" 中的 "),e("code",null,"keepalive"),t(" 设置为 "),e("code",null,"60"),t(" 秒,防止你一段时间没有操作之后 SSH 自动断线。另外务必再次保存设置。")]),e("p",null,[e("img",{src:_,alt:"防止频繁断线"})])],-1),V=p('

注意

对 PuTTY 的任何设置更新都要再次手动保存 Session,不然关闭后就会丢失

  1. 点击 Open 就会进入 SSH 连接窗口,对应下图输入用户名与密码,与你的 VPS 远程主机建立连接。(本文假设默认用户名是 root,另外,在 Linux 系统输入密码的时候,是不会出现 ****** 这种提示符的,这样可以避免密码长度泄漏,不是你的键盘坏掉了哦!)

    SSH远程登录

3.2 成功登录 SSH!初识命令行界面!

  1. 如果你的信息都填写正确,你将会看到类似下图的界面,说明已登录成功:

    初次登录VPS

    这个界面,就等于远程服务器的【桌面】,但它没有你熟悉的图标和鼠标,没有绚丽的色彩,有的只是简单文字,这就是【命令行界面】- Command Line Interface,或者缩写为 CLI

    接下来的所有操作,都需要你像电影里的黑客一样,在这个命令行界面中完成。也许你会觉得陌生,但请相信我,使用命令行既不可怕,也不神秘。说到底,它只不过是把你习惯的鼠标操作变成了文字指令而已,你说一句,它做一句

  2. 现在,你可以稍微观察并熟悉一下命令行环境,这个界面其实已经告诉了你一些有用的信息了,比如系统内核版本(比如图内是 4.19.37-5)、上次登录时间及 IP 等。当然根据 VPS 的不同,你看到的界面可能会略有不同。

  3. 请注意命令行最下面一行,闪动的光标左边,有一串字符。图中显示的是root@vps-server:~#,这一串要怎么理解呢?很简单:

    • 现在的用户是 root
    • root 所在的服务器是 vps-server
    • root 现在所在的文件夹是 ~
    • # 之后是你可以输入命令的地方

    前两个很直观,无需多说。第三个是关于 Linux 的文件夹系统,现在也不需要过于深入,你只需要知道,"~"就是【当前用户的大本营】。第四个,提示符#,你也不用管,只需要知道,未来文章中会写一些需要你输入的命令,都会以 "#" 或者 "$" 开头,提示你后面是你输入命令的地方。(所以你复制命令的时候,只需要复制后面的内容,不要复制提示符)

3.3 第一次更新 Linux 的软件!

  1. 正如你的手机,无论安卓还是 iPhone,为了 APP 及时更新(获取安全补丁和新功能),都会时不时从应用商店获得更新信息,并且提示你有多少个 APP 可更新。Linux 系统也有逻辑十分类似的更新机制。所以只要你会更新手机 APP,就能学会更新 Linux 软件!

  2. Linux 下,每个 APP 都叫做一个“包” (package)。管理 APP 的程序自然就叫做“包管理器”(Package Manager)。你可以通过它安装、更新、卸载各种软件、甚至更新 Linux 系统本身。Linux 下的包管理器非常强大,此处按下不表,现在你只需要知道 Debian 系统的包管理器叫做 apt 即可。接下来,我们就先使用 apt 做一次软件的全面更新,让你熟悉它的基本操作。

  3. 小小白白 Linux 基础命令:

    编号命令名称命令说明
    cmd-01apt update查询软件更新
    cmd-02apt upgrade执行软件更新
  4. 现在请输入第一条命令,获取更新信息

    apt update
    +import{_ as c,r as o,o as i,c as d,a as n,b as e,d as t,w as r,e as p}from"./app-Bw2NG-QJ.js";const u="/assets/ch03-img01-putty-download-CBXDLA1o.png",h="/assets/ch03-img02-putty-settings-D0Xbl0Z8.png",_="/assets/ch03-img03-putty-keepalive-B2CBMeC6.png",g="/assets/ch03-img04-ssh-login-DwyvE7DL.png",m="/assets/ch03-img05-ssh-login-success-BulNCpdO.png",x="/assets/ch03-img06-apt-upgrade-full--w3BBGrx.gif",P={},S=e("h1",{id:"【第-3-章】远程登录篇",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#【第-3-章】远程登录篇"},[e("span",null,"【第 3 章】远程登录篇")])],-1),v=e("h2",{id:"_3-1-远程登录-vps-putty",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-1-远程登录-vps-putty"},[e("span",null,"3.1 远程登录 VPS (PuTTY)")])],-1),b=e("p",null,"首先,鉴于零基础人群中 Windows 的用户基数最大,所以本文以 Windows 为例进行展示。",-1),f=e("p",null,"其次,虽然 Windows 10 之后的 PowerShell 和 WSL 也可以达到很好的 SSH 操作体验。但是因为并非所有版本的 Windows 都有最新的组件,故本文还是以老牌的 PuTTY 为例,进行 SSH 远程登录的操作详解。(使用其他工具的话、在 SSH 登陆之后的操作都是一样的)",-1),y=e("p",null,"下面就跟我一步步操作吧。",-1),L={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},T=e("p",null,[e("img",{src:u,alt:"下载PuTTY"})],-1),k=e("strong",null,[t("IP 地址(VPS IP)"),e("strong",null,"和"),t("端口(VPS PORT)")],-1),w=e("p",null,[e("img",{src:h,alt:"设置PuTTY"})],-1),B=e("li",null,[e("p",null,[t("我建议将 "),e("code",null,"Connection"),t(" 中的 "),e("code",null,"keepalive"),t(" 设置为 "),e("code",null,"60"),t(" 秒,防止你一段时间没有操作之后 SSH 自动断线。另外务必再次保存设置。")]),e("p",null,[e("img",{src:_,alt:"防止频繁断线"})])],-1),V=p('

    注意

    对 PuTTY 的任何设置更新都要再次手动保存 Session,不然关闭后就会丢失

    1. 点击 Open 就会进入 SSH 连接窗口,对应下图输入用户名与密码,与你的 VPS 远程主机建立连接。(本文假设默认用户名是 root,另外,在 Linux 系统输入密码的时候,是不会出现 ****** 这种提示符的,这样可以避免密码长度泄漏,不是你的键盘坏掉了哦!)

      SSH远程登录

    3.2 成功登录 SSH!初识命令行界面!

    1. 如果你的信息都填写正确,你将会看到类似下图的界面,说明已登录成功:

      初次登录VPS

      这个界面,就等于远程服务器的【桌面】,但它没有你熟悉的图标和鼠标,没有绚丽的色彩,有的只是简单文字,这就是【命令行界面】- Command Line Interface,或者缩写为 CLI

      接下来的所有操作,都需要你像电影里的黑客一样,在这个命令行界面中完成。也许你会觉得陌生,但请相信我,使用命令行既不可怕,也不神秘。说到底,它只不过是把你习惯的鼠标操作变成了文字指令而已,你说一句,它做一句

    2. 现在,你可以稍微观察并熟悉一下命令行环境,这个界面其实已经告诉了你一些有用的信息了,比如系统内核版本(比如图内是 4.19.37-5)、上次登录时间及 IP 等。当然根据 VPS 的不同,你看到的界面可能会略有不同。

    3. 请注意命令行最下面一行,闪动的光标左边,有一串字符。图中显示的是root@vps-server:~#,这一串要怎么理解呢?很简单:

      • 现在的用户是 root
      • root 所在的服务器是 vps-server
      • root 现在所在的文件夹是 ~
      • # 之后是你可以输入命令的地方

      前两个很直观,无需多说。第三个是关于 Linux 的文件夹系统,现在也不需要过于深入,你只需要知道,"~"就是【当前用户的大本营】。第四个,提示符#,你也不用管,只需要知道,未来文章中会写一些需要你输入的命令,都会以 "#" 或者 "$" 开头,提示你后面是你输入命令的地方。(所以你复制命令的时候,只需要复制后面的内容,不要复制提示符)

    3.3 第一次更新 Linux 的软件!

    1. 正如你的手机,无论安卓还是 iPhone,为了 APP 及时更新(获取安全补丁和新功能),都会时不时从应用商店获得更新信息,并且提示你有多少个 APP 可更新。Linux 系统也有逻辑十分类似的更新机制。所以只要你会更新手机 APP,就能学会更新 Linux 软件!

    2. Linux 下,每个 APP 都叫做一个“包” (package)。管理 APP 的程序自然就叫做“包管理器”(Package Manager)。你可以通过它安装、更新、卸载各种软件、甚至更新 Linux 系统本身。Linux 下的包管理器非常强大,此处按下不表,现在你只需要知道 Debian 系统的包管理器叫做 apt 即可。接下来,我们就先使用 apt 做一次软件的全面更新,让你熟悉它的基本操作。

    3. 小小白白 Linux 基础命令:

      编号命令名称命令说明
      cmd-01apt update查询软件更新
      cmd-02apt upgrade执行软件更新
    4. 现在请输入第一条命令,获取更新信息

      apt update
       
    5. 然后请输入第二条命令,并在询问是否继续安装 (Y/n) 时输入 y 并回车确认,开始安装

      apt upgrade
       
    6. 完整流程演示如下:

      初次软件更新流程演示

    3.4 你的进度

    恭喜你又迈出了坚实的一步! 现在,你已经可以通过 SSH 来登录你的远程服务器了!那登录进去之后,除了升级软件之外,应该再做点什么呢?敬请进入下一章一探究竟吧!

    ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%

    ',9);function C(E,I){const s=o("I18nTip"),l=o("ExternalLinkIcon"),a=o("RouterLink");return i(),d("div",null,[n(s),S,v,b,f,y,e("ol",null,[e("li",null,[e("p",null,[t("进入 PuTTY 的"),e("a",L,[t("官网"),n(l)]),t(",选择适合你操作系统的版本下载。(本文以 64 位版本为例)")]),T]),e("li",null,[e("p",null,[t("安装运行后,将会看到 PuTTY 的主界面。现在请拿出你上一章记东西的"),n(a,{to:"/document/level-0/ch02-preparation.html#21-%E8%8E%B7%E5%8F%96%E4%B8%80%E5%8F%B0vps"},{default:r(()=>[t("小本本")]),_:1}),t(",在下图的对应位置填入你 VPS 的"),k,t("。为了方便以后使用时不用重复输入,我们可以保存会话 (Saved Sessions),未来使用时只要按 Load 即可一键载入设置。")]),w]),B]),V])}const H=c(P,[["render",C],["__file","ch03-ssh.html.vue"]]);export{H as default}; diff --git a/assets/ch03-ssh.html-xo_x6se1.js b/assets/ch03-ssh.html-9CSgBxsO.js similarity index 99% rename from assets/ch03-ssh.html-xo_x6se1.js rename to assets/ch03-ssh.html-9CSgBxsO.js index 6dadc4ba7f..918c435e18 100644 --- a/assets/ch03-ssh.html-xo_x6se1.js +++ b/assets/ch03-ssh.html-9CSgBxsO.js @@ -1,3 +1,3 @@ -import{_ as c,r as o,o as d,c as i,a as n,b as e,d as t,w as r,e as p}from"./app-5SoadDYS.js";const u="/assets/ch03-img01-putty-download-CBXDLA1o.png",h="/assets/ch03-img02-putty-settings-D0Xbl0Z8.png",_="/assets/ch03-img03-putty-keepalive-B2CBMeC6.png",g="/assets/ch03-img04-ssh-login-DwyvE7DL.png",m="/assets/ch03-img05-ssh-login-success-BulNCpdO.png",x="/assets/ch03-img06-apt-upgrade-full--w3BBGrx.gif",v={},S=e("h1",{id:"【глава-3】-удаленное-подключение",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#【глава-3】-удаленное-подключение"},[e("span",null,"【Глава 3】 Удалённое подключение")])],-1),b=e("h2",{id:"_3-1-удаленное-подключение-к-vps-putty",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-1-удаленное-подключение-к-vps-putty"},[e("span",null,"3.1 Удалённое подключение к VPS (PuTTY)")])],-1),f=e("p",null,"Во-первых, поскольку Windows является самой распространённой операционной системой среди новичков, в этой статье мы будем использовать её в качестве примера.",-1),y=e("p",null,"Во-вторых, хотя PowerShell и WSL в Windows 10 и выше также предоставляют удобные инструменты для работы по SSH, не все версии Windows имеют эти компоненты. Поэтому в этой статье мы рассмотрим подключение по SSH с помощью старого доброго PuTTY. (После подключения по SSH действия во всех программах будут одинаковыми.)",-1),k=e("p",null,"Итак, давайте начнём.",-1),B={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},L=e("p",null,[e("img",{src:u,alt:"Скачать PuTTY"})],-1),P=e("strong",null,"IP-адрес",-1),T=e("strong",null,"порт",-1),D=e("p",null,[e("img",{src:h,alt:"Настройка PuTTY"})],-1),w=e("li",null,[e("p",null,[t("Рекомендуем установить значение "),e("code",null,"keepalive"),t(" в разделе "),e("code",null,"Connection"),t(" равным "),e("code",null,"60"),t(" секундам, чтобы предотвратить разрыв SSH-соединения, если вы долгое время не будете выполнять никаких действий. Не забудьте снова сохранить настройки.")]),e("p",null,[e("img",{src:_,alt:"Предотвращение разрывов соединения"})])],-1),C=p('

    Внимание

    После любых изменений настроек PuTTY необходимо сохранить сеанс, иначе они будут потеряны при закрытии программы.

    1. Нажмите кнопку "Open", чтобы открыть окно SSH-подключения. Введите имя пользователя и пароль для подключения к вашему VPS (в этой статье предполагается, что имя пользователя по умолчанию — root. Обратите внимание, что при вводе пароля в Linux не отображаются символы ******. Это сделано для того, чтобы скрыть длину пароля. Не пугайтесь, ваша клавиатура в порядке!).

      Подключение по SSH

    3.2 Успешное подключение по SSH! Знакомство с командной строкой!

    1. Если вы всё сделали правильно, вы увидите примерно такой экран, как на рисунке ниже. Это означает, что вы успешно подключились к серверу:

      Первое подключение к VPS

      Этот экран — аналог «рабочего стола» на удалённом сервере, но здесь нет привычных значков, курсора мыши и ярких цветов. Только текст. Это и есть командная строкаCommand Line Interface или сокращённо CLI.

      Все дальнейшие действия вам придётся выполнять в командной строке, как хакер в кино. Возможно, поначалу это покажется вам непривычным, но поверьте, в использовании командной строки нет ничего страшного или сложного. По сути, это всего лишь способ взаимодействия с компьютером с помощью текстовых команд вместо графического интерфейса. Вы пишете команду, а компьютер её выполняет.

    2. Теперь можете немного осмотреться и познакомиться с командной строкой. На этом экране уже есть полезная информация, например, версия ядра системы (в данном случае 4.19.37-5), время последнего входа в систему, IP-адрес и т.д. Конечно, в зависимости от VPS, ваш экран может выглядеть немного иначе.

    3. Обратите внимание на последнюю строку командной строки. Слева от мигающего курсора находится набор символов. В данном случае это root@vps-server:~#. Что это значит? Всё просто:

      • Текущий пользователь: root.
      • Имя сервера, на котором работает пользователь root: vps-server.
      • Текущий каталог, в котором находится пользователь root: ~.
      • Символ # указывает на то, что после него можно вводить команды.

      Первые два пункта интуитивно понятны и не требуют пояснений. Третий пункт относится к файловой системе Linux. Сейчас вам не нужно вдаваться в подробности, достаточно знать, что ~ — это «домашний каталог» текущего пользователя. Четвёртый пункт, символ #, также не требует особого внимания. Просто знайте, что в дальнейшем все команды, которые вам нужно будет вводить, будут начинаться с # или $. Это будет означать, что после этого символа нужно ввести команду (поэтому при копировании команд копируйте только текст после, без символа # или $).

    3.3 Первое обновление программного обеспечения Linux!

    1. Так же, как и ваш телефон, будь то Android или iPhone, Linux нуждается в регулярном обновлении программного обеспечения для получения исправлений безопасности и новых функций. В Linux каждое приложение называется «пакетом» (package). А программа, которая управляет пакетами, называется «менеджером пакетов» (Package Manager). С помощью менеджера пакетов можно устанавливать, обновлять и удалять программы, а также обновлять саму систему Linux. Менеджеры пакетов Linux очень мощные, но сейчас вам достаточно знать, что в Debian используется менеджер пакетов apt. Давайте обновим систему с помощью apt, чтобы вы познакомились с его основными функциями.

    2. Базовые команды Linux:

      НомерКомандаОписание
      cmd-01apt updateПроверить обновления
      cmd-02apt upgradeУстановить обновления
    3. Введите первую команду, чтобы получить информацию об обновлениях:

      apt update
      +import{_ as c,r as o,o as d,c as i,a as n,b as e,d as t,w as r,e as p}from"./app-Bw2NG-QJ.js";const u="/assets/ch03-img01-putty-download-CBXDLA1o.png",h="/assets/ch03-img02-putty-settings-D0Xbl0Z8.png",_="/assets/ch03-img03-putty-keepalive-B2CBMeC6.png",g="/assets/ch03-img04-ssh-login-DwyvE7DL.png",m="/assets/ch03-img05-ssh-login-success-BulNCpdO.png",x="/assets/ch03-img06-apt-upgrade-full--w3BBGrx.gif",v={},S=e("h1",{id:"【глава-3】-удаленное-подключение",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#【глава-3】-удаленное-подключение"},[e("span",null,"【Глава 3】 Удалённое подключение")])],-1),b=e("h2",{id:"_3-1-удаленное-подключение-к-vps-putty",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-1-удаленное-подключение-к-vps-putty"},[e("span",null,"3.1 Удалённое подключение к VPS (PuTTY)")])],-1),f=e("p",null,"Во-первых, поскольку Windows является самой распространённой операционной системой среди новичков, в этой статье мы будем использовать её в качестве примера.",-1),y=e("p",null,"Во-вторых, хотя PowerShell и WSL в Windows 10 и выше также предоставляют удобные инструменты для работы по SSH, не все версии Windows имеют эти компоненты. Поэтому в этой статье мы рассмотрим подключение по SSH с помощью старого доброго PuTTY. (После подключения по SSH действия во всех программах будут одинаковыми.)",-1),k=e("p",null,"Итак, давайте начнём.",-1),B={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},L=e("p",null,[e("img",{src:u,alt:"Скачать PuTTY"})],-1),P=e("strong",null,"IP-адрес",-1),T=e("strong",null,"порт",-1),D=e("p",null,[e("img",{src:h,alt:"Настройка PuTTY"})],-1),w=e("li",null,[e("p",null,[t("Рекомендуем установить значение "),e("code",null,"keepalive"),t(" в разделе "),e("code",null,"Connection"),t(" равным "),e("code",null,"60"),t(" секундам, чтобы предотвратить разрыв SSH-соединения, если вы долгое время не будете выполнять никаких действий. Не забудьте снова сохранить настройки.")]),e("p",null,[e("img",{src:_,alt:"Предотвращение разрывов соединения"})])],-1),C=p('

      Внимание

      После любых изменений настроек PuTTY необходимо сохранить сеанс, иначе они будут потеряны при закрытии программы.

      1. Нажмите кнопку "Open", чтобы открыть окно SSH-подключения. Введите имя пользователя и пароль для подключения к вашему VPS (в этой статье предполагается, что имя пользователя по умолчанию — root. Обратите внимание, что при вводе пароля в Linux не отображаются символы ******. Это сделано для того, чтобы скрыть длину пароля. Не пугайтесь, ваша клавиатура в порядке!).

        Подключение по SSH

      3.2 Успешное подключение по SSH! Знакомство с командной строкой!

      1. Если вы всё сделали правильно, вы увидите примерно такой экран, как на рисунке ниже. Это означает, что вы успешно подключились к серверу:

        Первое подключение к VPS

        Этот экран — аналог «рабочего стола» на удалённом сервере, но здесь нет привычных значков, курсора мыши и ярких цветов. Только текст. Это и есть командная строкаCommand Line Interface или сокращённо CLI.

        Все дальнейшие действия вам придётся выполнять в командной строке, как хакер в кино. Возможно, поначалу это покажется вам непривычным, но поверьте, в использовании командной строки нет ничего страшного или сложного. По сути, это всего лишь способ взаимодействия с компьютером с помощью текстовых команд вместо графического интерфейса. Вы пишете команду, а компьютер её выполняет.

      2. Теперь можете немного осмотреться и познакомиться с командной строкой. На этом экране уже есть полезная информация, например, версия ядра системы (в данном случае 4.19.37-5), время последнего входа в систему, IP-адрес и т.д. Конечно, в зависимости от VPS, ваш экран может выглядеть немного иначе.

      3. Обратите внимание на последнюю строку командной строки. Слева от мигающего курсора находится набор символов. В данном случае это root@vps-server:~#. Что это значит? Всё просто:

        • Текущий пользователь: root.
        • Имя сервера, на котором работает пользователь root: vps-server.
        • Текущий каталог, в котором находится пользователь root: ~.
        • Символ # указывает на то, что после него можно вводить команды.

        Первые два пункта интуитивно понятны и не требуют пояснений. Третий пункт относится к файловой системе Linux. Сейчас вам не нужно вдаваться в подробности, достаточно знать, что ~ — это «домашний каталог» текущего пользователя. Четвёртый пункт, символ #, также не требует особого внимания. Просто знайте, что в дальнейшем все команды, которые вам нужно будет вводить, будут начинаться с # или $. Это будет означать, что после этого символа нужно ввести команду (поэтому при копировании команд копируйте только текст после, без символа # или $).

      3.3 Первое обновление программного обеспечения Linux!

      1. Так же, как и ваш телефон, будь то Android или iPhone, Linux нуждается в регулярном обновлении программного обеспечения для получения исправлений безопасности и новых функций. В Linux каждое приложение называется «пакетом» (package). А программа, которая управляет пакетами, называется «менеджером пакетов» (Package Manager). С помощью менеджера пакетов можно устанавливать, обновлять и удалять программы, а также обновлять саму систему Linux. Менеджеры пакетов Linux очень мощные, но сейчас вам достаточно знать, что в Debian используется менеджер пакетов apt. Давайте обновим систему с помощью apt, чтобы вы познакомились с его основными функциями.

      2. Базовые команды Linux:

        НомерКомандаОписание
        cmd-01apt updateПроверить обновления
        cmd-02apt upgradeУстановить обновления
      3. Введите первую команду, чтобы получить информацию об обновлениях:

        apt update
         
      4. Затем введите вторую команду. При появлении запроса на подтверждение установки (Y/n) введите y и нажмите Enter, чтобы начать установку.

        apt upgrade
         
      5. Весь процесс показан на гифке ниже:

        Демонстрация процесса обновления

      3.4 Ваш прогресс

      Поздравляем, вы сделали ещё один важный шаг! Теперь вы умеете подключаться к своему серверу по SSH! Но что делать после подключения, кроме обновления системы? Узнаем в следующей главе!

      ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%

      ',9);function V(H,I){const s=o("I18nTip"),l=o("ExternalLinkIcon"),a=o("RouterLink");return d(),i("div",null,[n(s),S,b,f,y,k,e("ol",null,[e("li",null,[e("p",null,[t("Перейдите на "),e("a",B,[t("официальный сайт"),n(l)]),t(" PuTTY и скачайте версию, подходящую для вашей операционной системы (в этой статье мы будем использовать 64-битную версию).")]),L]),e("li",null,[e("p",null,[t("Запустите PuTTY. Откроется главное окно программы. Теперь возьмите "),n(a,{to:"/ru/document/level-0/ch02-preparation.html#21-%D0%BF%D0%BE%D0%BB%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-vps"},{default:r(()=>[t("блокнот")]),_:1}),t(", в который вы записывали информацию в предыдущей главе, и введите "),P,t(" и "),T,t(" вашего VPS в соответствующие поля (на скриншоте ниже). Чтобы не вводить эти данные каждый раз, можно сохранить сеанс (Saved Sessions). В дальнейшем вы сможете загрузить сохранённые настройки одним кликом.")]),D]),w]),C])}const E=c(v,[["render",V],["__file","ch03-ssh.html.vue"]]);export{E as default}; diff --git a/assets/ch03-ssh.html-CKpEhhik.js b/assets/ch03-ssh.html-Bbgd91VB.js similarity index 99% rename from assets/ch03-ssh.html-CKpEhhik.js rename to assets/ch03-ssh.html-Bbgd91VB.js index c2dc813d7d..cc4f256a21 100644 --- a/assets/ch03-ssh.html-CKpEhhik.js +++ b/assets/ch03-ssh.html-Bbgd91VB.js @@ -1,3 +1,3 @@ -import{_ as i,r as o,o as r,c as l,a as n,b as e,d as t,e as d}from"./app-5SoadDYS.js";const c="/assets/ch03-img01-putty-download-CBXDLA1o.png",h="/assets/ch03-img02-putty-settings-D0Xbl0Z8.png",u="/assets/ch03-img03-putty-keepalive-B2CBMeC6.png",p="/assets/ch03-img04-ssh-login-DwyvE7DL.png",m="/assets/ch03-img05-ssh-login-success-BulNCpdO.png",g="/assets/ch03-img06-apt-upgrade-full--w3BBGrx.gif",f={},y=e("h1",{id:"chapter-3-remote-login",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#chapter-3-remote-login"},[e("span",null,"[Chapter 3] Remote Login")])],-1),w=e("h2",{id:"_3-1-remote-login-to-vps-putty",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-1-remote-login-to-vps-putty"},[e("span",null,"3.1 Remote Login to VPS (PuTTY)")])],-1),v=e("p",null,"First of all, considering that the user base of Windows is the largest among the zero-based population, this article uses Windows as an example for demonstration.",-1),b=e("p",null,"Secondly, although PowerShell and WSL after Windows 10 can also achieve a good SSH operation experience, not all versions of Windows have the latest components. Therefore, this article uses the classic PuTTY as an example to provide a detailed explanation of SSH remote login operation. (If you use other tools, the operations after the SSH login are the same.)",-1),_=e("p",null,"Follow me step by step and let's start the operation.",-1),x={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},k=d('

      Download PuTTY

      1. After installation and running, you will see the main interface of PuTTY. Now please take out your notebook from the previous chapter where you wrote down the IP address (VPS IP) and port (VPS PORT) of your VPS in the corresponding positions of the following figure. In order to save time and avoid repeatedly entering these details in the future, we can save the session (Saved Sessions), and simply load it in the future with one click.

      PuTTY Settings

      1. I suggest setting keepalive to 60 seconds in the Connection to prevent SSH from automatically disconnecting after a period of inactivity. Be sure to save the settings again.

      Prevent frequent disconnection

      Attention

      Any update to the PuTTY configuration needs to be manually saved to the session again. Otherwise, it will be lost after closing.

      1. Click on Open to enter the SSH connection window, then enter the username and password corresponding to the following figure to establish a connection with your VPS remote host. (This article assumes that the default username is root. Also, when entering a password in the Linux system, there will be no prompt like ******, which can avoid password length leakage. It's not that your keyboard is broken!)

      SSH Remote Login

      3.2 Successfully Logging in SSH! Introduction to Command Line Interface!

      1. If you have filled in your information correctly, you will see a similar interface as the picture below, indicating that you have successfully logged in:

      Logging in to VPS for the first time

      This interface is equivalent to the "desktop" of a remote server, but it does not have familiar icons and a mouse, nor does it have colorful graphics. Instead, all you see is simple text. This is the "Command Line Interface" - shortened as CLI.

      All the following operations require you to act like a hacker in a movie and complete them in this command-line interface. Maybe you will feel unfamiliar, but please believe me, using the command-line interface is neither scary nor mysterious. In the end, it just turns your familiar mouse operations into textual commands, you say it, it does it.

      1. Now, you can observe and familiarize yourself with the command line environment a little bit. This interface has actually provided you with some useful information, such as the system kernel version (e.g. 4.19.37-5 in the picture), last login time and IP address. Of course, depending on the VPS, the interface you see may be slightly different.

      2. Please pay attention to the line at the bottom of the command line, to the left of the flashing cursor, there is a string of characters. The one shown in the figure is root@vps-server:~#. How to understand this string? It's very simple:

      • The current user is root
      • The server where root is located is vps-server
      • The current directory where root is located is ~
      • After # is the place where you can input commands.

      The first two are pretty straightforward, no need to explain further. The third one is about the folder system in Linux. You don't need to go too deep into it for now. Just know that "~" represents the home directory of the current user. As for the fourth one, the prompt symbol "#", you don't need to worry about it either. Just know that in future articles, there will be some commands that you need to input, and they will be preceded by "#" or "$" to indicate where you should input the command. (So when you copy the command, just copy the content after the prompt symbol and don't copy the prompt symbol itself.)

      3.3 Updating software on Linux for the first time!

      1. Just like your phone, whether it's Android or iPhone, in order to keep your apps up-to-date (to get security patches and new features), you will occasionally receive update notifications from the app store, telling you how many apps need to be updated. Linux systems also have a similar update mechanism that works logically. So as long as you know how to update phone apps, you can learn how to update Linux software!

      2. In Linux, each application is called a "package". The program that manages the applications is naturally called a "package manager". You can use it to install, update, and uninstall various software, and even update the Linux system itself. Package managers in Linux are very powerful, but we won't go into details here. For now, you only need to know that the package manager for the Debian system is called apt. Next, we will first use apt to do a comprehensive update of the software to familiarize you with its basic operations.

      3. Tiny White Linux Basic Commands:

      NumberCommand NameCommand Description
      cmd-01apt updateQuery software updates
      cmd-02apt upgradePerform software updates
      1. Now, please enter the first command to get update information.
      apt update
      +import{_ as i,r as o,o as r,c as l,a as n,b as e,d as t,e as d}from"./app-Bw2NG-QJ.js";const c="/assets/ch03-img01-putty-download-CBXDLA1o.png",h="/assets/ch03-img02-putty-settings-D0Xbl0Z8.png",u="/assets/ch03-img03-putty-keepalive-B2CBMeC6.png",p="/assets/ch03-img04-ssh-login-DwyvE7DL.png",m="/assets/ch03-img05-ssh-login-success-BulNCpdO.png",g="/assets/ch03-img06-apt-upgrade-full--w3BBGrx.gif",f={},y=e("h1",{id:"chapter-3-remote-login",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#chapter-3-remote-login"},[e("span",null,"[Chapter 3] Remote Login")])],-1),w=e("h2",{id:"_3-1-remote-login-to-vps-putty",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_3-1-remote-login-to-vps-putty"},[e("span",null,"3.1 Remote Login to VPS (PuTTY)")])],-1),v=e("p",null,"First of all, considering that the user base of Windows is the largest among the zero-based population, this article uses Windows as an example for demonstration.",-1),b=e("p",null,"Secondly, although PowerShell and WSL after Windows 10 can also achieve a good SSH operation experience, not all versions of Windows have the latest components. Therefore, this article uses the classic PuTTY as an example to provide a detailed explanation of SSH remote login operation. (If you use other tools, the operations after the SSH login are the same.)",-1),_=e("p",null,"Follow me step by step and let's start the operation.",-1),x={href:"https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html",target:"_blank",rel:"noopener noreferrer"},k=d('

      Download PuTTY

      1. After installation and running, you will see the main interface of PuTTY. Now please take out your notebook from the previous chapter where you wrote down the IP address (VPS IP) and port (VPS PORT) of your VPS in the corresponding positions of the following figure. In order to save time and avoid repeatedly entering these details in the future, we can save the session (Saved Sessions), and simply load it in the future with one click.

      PuTTY Settings

      1. I suggest setting keepalive to 60 seconds in the Connection to prevent SSH from automatically disconnecting after a period of inactivity. Be sure to save the settings again.

      Prevent frequent disconnection

      Attention

      Any update to the PuTTY configuration needs to be manually saved to the session again. Otherwise, it will be lost after closing.

      1. Click on Open to enter the SSH connection window, then enter the username and password corresponding to the following figure to establish a connection with your VPS remote host. (This article assumes that the default username is root. Also, when entering a password in the Linux system, there will be no prompt like ******, which can avoid password length leakage. It's not that your keyboard is broken!)

      SSH Remote Login

      3.2 Successfully Logging in SSH! Introduction to Command Line Interface!

      1. If you have filled in your information correctly, you will see a similar interface as the picture below, indicating that you have successfully logged in:

      Logging in to VPS for the first time

      This interface is equivalent to the "desktop" of a remote server, but it does not have familiar icons and a mouse, nor does it have colorful graphics. Instead, all you see is simple text. This is the "Command Line Interface" - shortened as CLI.

      All the following operations require you to act like a hacker in a movie and complete them in this command-line interface. Maybe you will feel unfamiliar, but please believe me, using the command-line interface is neither scary nor mysterious. In the end, it just turns your familiar mouse operations into textual commands, you say it, it does it.

      1. Now, you can observe and familiarize yourself with the command line environment a little bit. This interface has actually provided you with some useful information, such as the system kernel version (e.g. 4.19.37-5 in the picture), last login time and IP address. Of course, depending on the VPS, the interface you see may be slightly different.

      2. Please pay attention to the line at the bottom of the command line, to the left of the flashing cursor, there is a string of characters. The one shown in the figure is root@vps-server:~#. How to understand this string? It's very simple:

      • The current user is root
      • The server where root is located is vps-server
      • The current directory where root is located is ~
      • After # is the place where you can input commands.

      The first two are pretty straightforward, no need to explain further. The third one is about the folder system in Linux. You don't need to go too deep into it for now. Just know that "~" represents the home directory of the current user. As for the fourth one, the prompt symbol "#", you don't need to worry about it either. Just know that in future articles, there will be some commands that you need to input, and they will be preceded by "#" or "$" to indicate where you should input the command. (So when you copy the command, just copy the content after the prompt symbol and don't copy the prompt symbol itself.)

      3.3 Updating software on Linux for the first time!

      1. Just like your phone, whether it's Android or iPhone, in order to keep your apps up-to-date (to get security patches and new features), you will occasionally receive update notifications from the app store, telling you how many apps need to be updated. Linux systems also have a similar update mechanism that works logically. So as long as you know how to update phone apps, you can learn how to update Linux software!

      2. In Linux, each application is called a "package". The program that manages the applications is naturally called a "package manager". You can use it to install, update, and uninstall various software, and even update the Linux system itself. Package managers in Linux are very powerful, but we won't go into details here. For now, you only need to know that the package manager for the Debian system is called apt. Next, we will first use apt to do a comprehensive update of the software to familiarize you with its basic operations.

      3. Tiny White Linux Basic Commands:

      NumberCommand NameCommand Description
      cmd-01apt updateQuery software updates
      cmd-02apt upgradePerform software updates
      1. Now, please enter the first command to get update information.
      apt update
       

      This is a command used in a Linux terminal to update the package list from the repositories configured on the system.

      1. Then enter the second command, and when asked if you want to continue installing (Y/n), type y and press enter to confirm and start the installation.
      apt upgrade
       

      This is a command in the shell terminal to upgrade the installed packages on a Debian or Ubuntu Linux system.

      1. The complete demonstration of the process is as follows:

      Demonstration of the software update process for the first time

      3.4 Your Progress

      Congratulations on taking another solid step! Now, you can log in to your remote server via SSH! After logging in, besides upgrading the software, what else should you do? Please enter the next chapter to find out!

      ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%

      ',30);function T(S,P){const s=o("I18nTip"),a=o("ExternalLinkIcon");return r(),l("div",null,[n(s),y,w,v,b,_,e("ol",null,[e("li",null,[t("Go to the "),e("a",x,[t("official website"),n(a)]),t(" of PuTTY and download the version that suits your operating system (this article uses the 64-bit version as an example).")])]),k])}const q=i(f,[["render",T],["__file","ch03-ssh.html.vue"]]);export{q as default}; diff --git a/assets/ch04-security.html-CDDodZLn.js b/assets/ch04-security.html-CR6Uh8v_.js similarity index 99% rename from assets/ch04-security.html-CDDodZLn.js rename to assets/ch04-security.html-CR6Uh8v_.js index acf8e4e9c9..87ba4a0479 100644 --- a/assets/ch04-security.html-CDDodZLn.js +++ b/assets/ch04-security.html-CR6Uh8v_.js @@ -1,4 +1,4 @@ -import{_ as l,r as o,o as c,c as a,a as d,b as e,d as t,e as s}from"./app-5SoadDYS.js";const p="/assets/ch04-img01-nano-ui-6jgdTYpm.png",r="/assets/ch04-img02-sshd-conf-full-Dv8kUzC-.gif",g="/assets/ch04-img03-adduser-Cikb_tfM.png",u="/assets/ch04-img04-adduser-full-DgDkjVtm.gif",h="/assets/ch04-img05-sudo-full-DeKisL39.gif",m="/assets/ch04-img06-ssh-no-root-full-DZeR7uks.gif",S="/assets/ch04-img07-putty-default-user-BTPoHJe1.png",_="/assets/ch04-img08-puttygen-save-C2ur0GMu.png",v="/assets/ch04-img09-puttygen-save-keys-C8sxEVZz.png",b="/assets/ch04-img10-winscp-import-session-Bdx5sqJC.png",f="/assets/ch04-img11-winscp-ui-Cql7rWCm.png",x="/assets/ch04-img12-winscp-locations-tVIXHQa-.png",y="/assets/ch04-img13-winscp-newfolder-key-sIaUkXvO.png",P="/assets/ch04-img14-winscp-upload-key-BxgNsqKA.png",k="/assets/ch04-img15-winscp-rename-key-DQdsowRR.png",T="/assets/ch04-img16-winscp-full-B_z2QlO-.gif",H="/assets/ch04-img17-rsa-login-full-CZytVZwr.gif",C="/assets/ch04-img18-putty-privatekey-location-gVqxTouh.png",L="/assets/ch04-img19-putty-privatekey-passphrase-CDI2p4Ie.png",w="/assets/ch04-img20-winscp-privatekey-location-Cw1xSMYh.png",V={},Y=s(`

      【Глава 4】 Обеспечение безопасности

      4.1 Зачем нужна безопасность?

      Безопасность Linux-серверов — это обширная и сложная тема. Бесчисленные веб-сайты, приложения, сервисы и даже критически важная инфраструктура построены на базе Linux. За всем этим стоят огромные деньги и коммерческие интересы, что, естественно, привлекает злоумышленников. В то же время надёжная работа этих сервисов крайне важна, поэтому любые серьёзные уязвимости недопустимы. Именно поэтому множество специалистов по безопасности изо дня в день ведут борьбу на передовой, обеспечивая стабильную работу цифрового мира, к которому мы все привыкли.

      Теперь, когда у вас есть собственный VPS-сервер, и вы собираетесь открыть на нём порты для перенаправления трафика, вы фактически оказываетесь на передовой этой борьбы и подвергаетесь тем же рискам. В то же время, новички, не обладающие достаточными знаниями и информацией, склонны впадать в крайности: либо они считают, что им ничего не угрожает, либо же, наоборот, впадают в паранойю.

      • Первым я бы посоветовал не относиться к безопасности легкомысленно и изучить этот вопрос более подробно, чтобы потом не пришлось кусать локти.

      • Вторым я бы посоветовал не паниковать. Ваш сервер вряд ли представляет собой лакомую цель для серьёзных злоумышленников, поэтому вам достаточно базовых мер защиты от автоматических сканеров и ботов, о которых мы и поговорим в этой главе.

      4.2 Какие именно риски существуют?

      Как мы уже говорили в главе про удалённое подключение, для доступа к вашему VPS достаточно знать четыре вещи: IP-адрес, порт, имя пользователя и пароль. Очевидно, что эти четыре элемента нужно защищать в первую очередь. Давайте разберём каждый из них:

      1. IP-адрес: злоумышленники могут сканировать целые диапазоны IP-адресов в поисках уязвимых серверов. Ваш IP-адрес — это публичная информация, которую невозможно скрыть.

      2. Порт: если вы используете настройки по умолчанию, то порт SSH равен 22.

      3. Имя пользователя: если вы используете настройки по умолчанию, то имя пользователя — root.

      4. Пароль: пароль не имеет значения по умолчанию. Он либо генерируется автоматически при создании VPS, либо задаётся вами. Таким образом, если вы не меняли настройки сервера, то три из четырёх элементов уже известны злоумышленникам, и вся безопасность вашего сервера держится на одном только пароле. Возможны следующие варианты:

        • Вы используете автоматически сгенерированный пароль из панели управления VPS. Такие пароли обычно состоят из случайного набора символов (букв в разных регистрах, цифр и спецсимволов) и достаточно надёжны.

        • Вы установили простой пароль, например, 123456. Взломать такой сервер не составит труда.

        • Вы установили сложный пароль, который используете где-то ещё. Это тоже небезопасно. Злоумышленники используют специальные программы, которые перебирают миллионы ранее скомпрометированных паролей из утечек данных.

      5. Важно понимать, что никакой хакер не будет лично подбирать ваш пароль. Все атаки выполняются автоматически с помощью специальных скриптов, которые работают круглосуточно. Пока вы спите, ваш сервер может подвергаться атакам.

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

      6. Не забывайте, что при покупке VPS вы, скорее всего, указывали свои реальные платёжные данные. А при посещении сайтов и использовании социальных сетей ваш IP-адрес также сохраняется. Всё это может быть использовано против вас. Поэтому, если на вашем сервере произойдёт что-то противозаконное, отвечать за это придётся вам.

      4.3 Какие меры безопасности нужно предпринять?

      Исходя из всего вышесказанного, нам нужно защитить порт, имя пользователя и пароль, чтобы снизить риск взлома. Для этого необходимо:

      1. Изменить порт SSH на нестандартный (отличный от 22) (см. раздел 4.4).
      2. Создать нового пользователя (не root) и запретить удалённое подключение по SSH для пользователя root (см. разделы 4.5 и 4.6).
      3. Настроить аутентификацию по SSH-ключам и запретить аутентификацию по паролю (см. раздел 4.7).

      Выполняйте эти действия по порядку, чтобы не оказаться случайно заблокированным на своём же сервере.

      4.4 Изменение порта SSH

      Давайте решим проблему с портом SSH, который по умолчанию равен 22 (обратите внимание: у некоторых хостинг-провайдеров порт SSH по умолчанию уже отличается от 22. В этом случае вы можете пропустить этот шаг, но можете и изменить порт ещё раз, следуя инструкциям ниже).

      1. Базовые команды Linux:

        НомерКомандаОписание
        cmd-03nanoТекстовый редактор
        cmd-04systemctl restartПерезапуск службы
      2. Важные файлы конфигурации Linux:

        НомерПуть к файлуОписание
        conf-01/etc/ssh/sshd_configНастройки SSH-сервера
      3. Первое, что нужно сделать, — это открыть файл настроек SSH-сервера (/etc/ssh/sshd_config) в текстовом редакторе nano. В Windows вы бы просто нашли этот файл и дважды кликнули по нему. А как это сделать в Linux? Если вы внимательно читали предыдущие разделы, то наверняка уже догадались! Правильно, нужно выполнить команду:

        nano /etc/ssh/sshd_config
        +import{_ as l,r as o,o as c,c as a,a as d,b as e,d as t,e as s}from"./app-Bw2NG-QJ.js";const p="/assets/ch04-img01-nano-ui-6jgdTYpm.png",r="/assets/ch04-img02-sshd-conf-full-Dv8kUzC-.gif",g="/assets/ch04-img03-adduser-Cikb_tfM.png",u="/assets/ch04-img04-adduser-full-DgDkjVtm.gif",h="/assets/ch04-img05-sudo-full-DeKisL39.gif",m="/assets/ch04-img06-ssh-no-root-full-DZeR7uks.gif",S="/assets/ch04-img07-putty-default-user-BTPoHJe1.png",_="/assets/ch04-img08-puttygen-save-C2ur0GMu.png",v="/assets/ch04-img09-puttygen-save-keys-C8sxEVZz.png",b="/assets/ch04-img10-winscp-import-session-Bdx5sqJC.png",f="/assets/ch04-img11-winscp-ui-Cql7rWCm.png",x="/assets/ch04-img12-winscp-locations-tVIXHQa-.png",y="/assets/ch04-img13-winscp-newfolder-key-sIaUkXvO.png",P="/assets/ch04-img14-winscp-upload-key-BxgNsqKA.png",k="/assets/ch04-img15-winscp-rename-key-DQdsowRR.png",T="/assets/ch04-img16-winscp-full-B_z2QlO-.gif",H="/assets/ch04-img17-rsa-login-full-CZytVZwr.gif",C="/assets/ch04-img18-putty-privatekey-location-gVqxTouh.png",L="/assets/ch04-img19-putty-privatekey-passphrase-CDI2p4Ie.png",w="/assets/ch04-img20-winscp-privatekey-location-Cw1xSMYh.png",V={},Y=s(`

        【Глава 4】 Обеспечение безопасности

        4.1 Зачем нужна безопасность?

        Безопасность Linux-серверов — это обширная и сложная тема. Бесчисленные веб-сайты, приложения, сервисы и даже критически важная инфраструктура построены на базе Linux. За всем этим стоят огромные деньги и коммерческие интересы, что, естественно, привлекает злоумышленников. В то же время надёжная работа этих сервисов крайне важна, поэтому любые серьёзные уязвимости недопустимы. Именно поэтому множество специалистов по безопасности изо дня в день ведут борьбу на передовой, обеспечивая стабильную работу цифрового мира, к которому мы все привыкли.

        Теперь, когда у вас есть собственный VPS-сервер, и вы собираетесь открыть на нём порты для перенаправления трафика, вы фактически оказываетесь на передовой этой борьбы и подвергаетесь тем же рискам. В то же время, новички, не обладающие достаточными знаниями и информацией, склонны впадать в крайности: либо они считают, что им ничего не угрожает, либо же, наоборот, впадают в паранойю.

        • Первым я бы посоветовал не относиться к безопасности легкомысленно и изучить этот вопрос более подробно, чтобы потом не пришлось кусать локти.

        • Вторым я бы посоветовал не паниковать. Ваш сервер вряд ли представляет собой лакомую цель для серьёзных злоумышленников, поэтому вам достаточно базовых мер защиты от автоматических сканеров и ботов, о которых мы и поговорим в этой главе.

        4.2 Какие именно риски существуют?

        Как мы уже говорили в главе про удалённое подключение, для доступа к вашему VPS достаточно знать четыре вещи: IP-адрес, порт, имя пользователя и пароль. Очевидно, что эти четыре элемента нужно защищать в первую очередь. Давайте разберём каждый из них:

        1. IP-адрес: злоумышленники могут сканировать целые диапазоны IP-адресов в поисках уязвимых серверов. Ваш IP-адрес — это публичная информация, которую невозможно скрыть.

        2. Порт: если вы используете настройки по умолчанию, то порт SSH равен 22.

        3. Имя пользователя: если вы используете настройки по умолчанию, то имя пользователя — root.

        4. Пароль: пароль не имеет значения по умолчанию. Он либо генерируется автоматически при создании VPS, либо задаётся вами. Таким образом, если вы не меняли настройки сервера, то три из четырёх элементов уже известны злоумышленникам, и вся безопасность вашего сервера держится на одном только пароле. Возможны следующие варианты:

          • Вы используете автоматически сгенерированный пароль из панели управления VPS. Такие пароли обычно состоят из случайного набора символов (букв в разных регистрах, цифр и спецсимволов) и достаточно надёжны.

          • Вы установили простой пароль, например, 123456. Взломать такой сервер не составит труда.

          • Вы установили сложный пароль, который используете где-то ещё. Это тоже небезопасно. Злоумышленники используют специальные программы, которые перебирают миллионы ранее скомпрометированных паролей из утечек данных.

        5. Важно понимать, что никакой хакер не будет лично подбирать ваш пароль. Все атаки выполняются автоматически с помощью специальных скриптов, которые работают круглосуточно. Пока вы спите, ваш сервер может подвергаться атакам.

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

        6. Не забывайте, что при покупке VPS вы, скорее всего, указывали свои реальные платёжные данные. А при посещении сайтов и использовании социальных сетей ваш IP-адрес также сохраняется. Всё это может быть использовано против вас. Поэтому, если на вашем сервере произойдёт что-то противозаконное, отвечать за это придётся вам.

        4.3 Какие меры безопасности нужно предпринять?

        Исходя из всего вышесказанного, нам нужно защитить порт, имя пользователя и пароль, чтобы снизить риск взлома. Для этого необходимо:

        1. Изменить порт SSH на нестандартный (отличный от 22) (см. раздел 4.4).
        2. Создать нового пользователя (не root) и запретить удалённое подключение по SSH для пользователя root (см. разделы 4.5 и 4.6).
        3. Настроить аутентификацию по SSH-ключам и запретить аутентификацию по паролю (см. раздел 4.7).

        Выполняйте эти действия по порядку, чтобы не оказаться случайно заблокированным на своём же сервере.

        4.4 Изменение порта SSH

        Давайте решим проблему с портом SSH, который по умолчанию равен 22 (обратите внимание: у некоторых хостинг-провайдеров порт SSH по умолчанию уже отличается от 22. В этом случае вы можете пропустить этот шаг, но можете и изменить порт ещё раз, следуя инструкциям ниже).

        1. Базовые команды Linux:

          НомерКомандаОписание
          cmd-03nanoТекстовый редактор
          cmd-04systemctl restartПерезапуск службы
        2. Важные файлы конфигурации Linux:

          НомерПуть к файлуОписание
          conf-01/etc/ssh/sshd_configНастройки SSH-сервера
        3. Первое, что нужно сделать, — это открыть файл настроек SSH-сервера (/etc/ssh/sshd_config) в текстовом редакторе nano. В Windows вы бы просто нашли этот файл и дважды кликнули по нему. А как это сделать в Linux? Если вы внимательно читали предыдущие разделы, то наверняка уже догадались! Правильно, нужно выполнить команду:

          nano /etc/ssh/sshd_config
           
        4. После открытия файла вы увидите интерфейс редактора nano. Обратите внимание на нижнюю часть экрана, где перечислены основные горячие клавиши (на скриншоте ниже выделены красной рамкой). Не нужно ничего заучивать, всё необходимое всегда перед глазами!

          Интерфейс nano

        1. Второе, что нужно сделать, — это найти строку, начинающуюся с Port, и изменить номер порта. Число после Port — это номер порта SSH. Рекомендуется использовать число в диапазоне от 1024 до 65535 (в этой статье мы будем использовать порт 9753). Как это сделать, используя горячие клавиши nano? Вы уже наверняка догадались!

          • Нажмите Ctrl+W, чтобы открыть поиск, введите Port 22 и нажмите Enter.
          • Замените 22 на 9753.
          • Примечание: если в начале строки стоит символ #, значит, эта строка закомментирована и не будет применяться. Вы можете либо раскомментировать её (удалив #), либо добавить новую строку без # в конце файла, как показано на скриншоте.

          Внимание

          Использование порта 9753 в этой статье делает его менее безопасным, поскольку злоумышленники могут начать сканировать этот порт в первую очередь. Кроме того, этот порт может быть заблокирован некоторыми провайдерами. Поэтому настоятельно рекомендуем использовать другой порт. У вас в распоряжении более 60 тысяч портов, так что выбрать есть из чего.

        1. Третье, что нужно сделать, — это сохранить изменения и выйти из редактора.

          • Как вы уже могли заметить, для сохранения файла используется не Ctrl+S, как в большинстве программ.
          • Горячие клавиши: Ctrl+O — сохранить, Ctrl+X — выйти.
        • Добавьте новое правило в брандмауэр, чтобы открыть новый порт SSH. В противном случае, после перезагрузки инстанса, подключение по SSH будет недоступно.

        • Пример для Ubuntu с использованием ufw:

          sudo ufw allow 9753/tcp
           
        1. И последнее, что нужно сделать, — это перезапустить SSH-сервер, чтобы изменения вступили в силу.

          systemctl restart ssh
           

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

        1. Весь процесс показан на гифке ниже:

          Изменение порта SSH

        2. Изменение настроек PuTTY

          Теперь, когда вы изменили порт SSH, вам нужно указать новый порт (9753) в настройках PuTTY. Вы ведь помните, где это делается? (Если нет, вернитесь и перечитайте предыдущие разделы!)

        4.5 Создание нового пользователя

        Перейдём ко второму шагу — избавлению от пользователя root.

        Прежде всего, нужно понимать, что пользователь root в Linux — это не просто администратор. Это корень системы, её основа, верховный правитель. Если безопасность учётной записи root будет нарушена, под угрозой окажется вся система.

        1. Базовые команды Linux:

          НомерКомандаОписание
          cmd-05adduserДобавление нового пользователя
          cmd-06apt installУстановка программного обеспечения
          cmd-07visudoРедактор файла sudoers
        2. Первое, что нужно сделать, — это создать нового пользователя и установить для него пароль. Имя пользователя может быть любым, в этой статье мы будем использовать имя vpsadmin.

          adduser vpsadmin
          diff --git a/assets/ch04-security.html-BzzIgsFs.js b/assets/ch04-security.html-CRFoFiSw.js
          similarity index 99%
          rename from assets/ch04-security.html-BzzIgsFs.js
          rename to assets/ch04-security.html-CRFoFiSw.js
          index 142c8d5b53..8a615a4424 100644
          --- a/assets/ch04-security.html-BzzIgsFs.js
          +++ b/assets/ch04-security.html-CRFoFiSw.js
          @@ -1,4 +1,4 @@
          -import{_ as r,r as t,o as l,c as d,a as o,b as s,d as e,e as a}from"./app-5SoadDYS.js";const c="/assets/ch04-img01-nano-ui-6jgdTYpm.png",h="/assets/ch04-img02-sshd-conf-full-Dv8kUzC-.gif",u="/assets/ch04-img03-adduser-Cikb_tfM.png",p="/assets/ch04-img04-adduser-full-DgDkjVtm.gif",m="/assets/ch04-img05-sudo-full-DeKisL39.gif",g="/assets/ch04-img06-ssh-no-root-full-DZeR7uks.gif",y="/assets/ch04-img07-putty-default-user-BTPoHJe1.png",f="/assets/ch04-img08-puttygen-save-C2ur0GMu.png",w="/assets/ch04-img09-puttygen-save-keys-C8sxEVZz.png",v="/assets/ch04-img10-winscp-import-session-Bdx5sqJC.png",b="/assets/ch04-img11-winscp-ui-Cql7rWCm.png",k="/assets/ch04-img12-winscp-locations-tVIXHQa-.png",S="/assets/ch04-img13-winscp-newfolder-key-sIaUkXvO.png",x="/assets/ch04-img14-winscp-upload-key-BxgNsqKA.png",T="/assets/ch04-img15-winscp-rename-key-DQdsowRR.png",_="/assets/ch04-img16-winscp-full-B_z2QlO-.gif",P="/assets/ch04-img17-rsa-login-full-CZytVZwr.gif",I="/assets/ch04-img18-putty-privatekey-location-gVqxTouh.png",C="/assets/ch04-img19-putty-privatekey-passphrase-CDI2p4Ie.png",A="/assets/ch04-img20-winscp-privatekey-location-Cw1xSMYh.png",q={},L=a(`

          [Chapter 4] Security and Protection

          4.1 Why Do We Need Security Protection?

          Security protection for Linux servers is a complex and huge subject. Countless websites, apps, services, and even offline infrastructure are built on the foundation of Linux, which involves huge economic benefits and commercial value. This also means that there is a huge motivation for black and gray industries to launch attacks. However, these services are so important that major security vulnerabilities are not allowed. Therefore, countless operation and maintenance professionals are working hard on the battlefield of security attacks and defense, which enables us to enjoy a basic stable modern digital life.

          Now, you have a VPS and will open its data access channel to achieve the goal of traffic forwarding, which means you are now on the front line of the security battle and face all risks. However, at the same time, newcomers tend to have a polarized view of security issues due to lack of knowledge and information: either they feel it is as light as a feather and has nothing to do with them, or they feel it is as heavy as Mount Tai and feel anxious all day long.

          • For the former, my suggestion is: safety is of utmost importance. Try to gather more information on safety issues to avoid regretting after experiencing losses.

          • For the latter, my suggestion is: don't worry too much, our servers still don't have too much value and generally won't attract high-level attacks. The basic threats we need to face are mostly malicious scans and login attempts from some automated scripts. Just follow this article to do some basic protection.

          4.2 What are the specific risks

          Just like the configuration we did in the "Remote Login" section, anyone who knows the four elements of [IP address] + [port] + [username] + [password] can log in to your VPS server. So obviously, the security of these four elements is the bottom line that we need to protect. Let's analyze them one by one:

          1. [IP Address]: Malicious scripts randomly attempt to scan IP ranges, which can be regarded as public information and cannot be hidden.

          2. [Port]: If you are using the default port, then [Port = 22].

          3. [Username]: If using the default user, then [Username = root]

          4. [Password]: There is no default value for the password. It must be randomly generated by the VPS backend or set by you. In other words, if all the settings of your server are default, then three of the four elements are already known. Therefore, the security of your entire server relies on a small password. In this case, there are several situations:

          • If you use a VPS management background to generate passwords randomly, it usually contains random uppercase and lowercase letters, symbols, and is relatively secure.

          • If you changed your password to something super weak like 123456 just for the sake of easy memorization, hacking into your VPS server would be a piece of cake.

          • If you change your password to a more complex one that you have used elsewhere just for the sake of easy memory, it is not really safe. You should understand that hackers have cheats in their hands, such as password tables, which contain tens of thousands, hundreds of thousands, millions, or even more real leaked passwords.

          1. But you should understand that no hacker really sits in front of a computer and tries your password repeatedly. All attack attempts are carried out automatically by malicious scripts, which work tirelessly for 24 hours. Perhaps while you are sleeping soundly every night, your server is enduring round after round of attacks.

          Once the password is successfully cracked, it means that all four of your elements have been mastered by the attacker. The malicious script will quickly log in to the server, obtain the highest root control of the server, install and deploy its malicious services, and then use your server to do all kinds of bad things 24 hours a day (such as mining, spreading viruses, sending spam emails, fraudulent emails, acting as a BT relay, and even dark web public nodes, and so on). If the malicious script is relatively restrained, it can actually achieve considerable concealment. Generally, newcomers will not observe and pay attention to indicators such as login records, process changes, CPU usage changes, and traffic changes of the VPS, so it is difficult for you to discover that you have been hacked. Until your VPS service provider blocks your account or you receive a lawyer's letter.

          1. Don't forget that when you obtain a VPS, you probably need to use your real payment information, and when you log in to various websites and social platforms, your IP address will also be recorded, which has a direct or indirect relationship with your identity. Therefore, once these bad things happen, they will inevitably be associated with you.

          4.3 What security measures do we need to take

          Based on the above analysis, what we need to do is to strengthen the three elements of [port], [username], and [password] to reduce the risk of being hacked.

          1. [Port]: Modify the SSH remote login port to a [non-22 port] (4.4).
          2. [Username]: Create a [non-root] new user and disable root user SSH remote login (4.5, 4.6).
          3. [Password]: Enable RSA key verification for SSH login and disable password verification login (4.7).

          Remember to follow the order and don't lock yourself out.

          4.4 Change the SSH Remote Login Port to a Non-22 Port

          Now, let's solve the problem of "port = 22". (Note: some VPS service providers have non-22 ports set as default, so you can ignore this step if that's the case. Of course, you can also follow this article to change it to another port.)

          1. Basic commands of Little White Linux:
          IDCommand NameDescription
          cmd-03nanoText editor
          cmd-04systemctl restartRestart a service
          1. Basic Configuration Files of Little White Linux
          NumberConfiguration File LocationFile Description
          conf-01/etc/ssh/sshd_configSSH Remote Login Program Settings
          1. The first thing we need to do, of course, is to [open the SSH remote login program settings with the text editor nano]. In Windows, you will [find the file and double-click] it. What should you do in Linux? Take a close look at the command instructions above, isn't it simple? Yes, it is:
          nano /etc/ssh/sshd_config
          +import{_ as r,r as t,o as l,c as d,a as o,b as s,d as e,e as a}from"./app-Bw2NG-QJ.js";const c="/assets/ch04-img01-nano-ui-6jgdTYpm.png",h="/assets/ch04-img02-sshd-conf-full-Dv8kUzC-.gif",u="/assets/ch04-img03-adduser-Cikb_tfM.png",p="/assets/ch04-img04-adduser-full-DgDkjVtm.gif",m="/assets/ch04-img05-sudo-full-DeKisL39.gif",g="/assets/ch04-img06-ssh-no-root-full-DZeR7uks.gif",y="/assets/ch04-img07-putty-default-user-BTPoHJe1.png",f="/assets/ch04-img08-puttygen-save-C2ur0GMu.png",w="/assets/ch04-img09-puttygen-save-keys-C8sxEVZz.png",v="/assets/ch04-img10-winscp-import-session-Bdx5sqJC.png",b="/assets/ch04-img11-winscp-ui-Cql7rWCm.png",k="/assets/ch04-img12-winscp-locations-tVIXHQa-.png",S="/assets/ch04-img13-winscp-newfolder-key-sIaUkXvO.png",x="/assets/ch04-img14-winscp-upload-key-BxgNsqKA.png",T="/assets/ch04-img15-winscp-rename-key-DQdsowRR.png",_="/assets/ch04-img16-winscp-full-B_z2QlO-.gif",P="/assets/ch04-img17-rsa-login-full-CZytVZwr.gif",I="/assets/ch04-img18-putty-privatekey-location-gVqxTouh.png",C="/assets/ch04-img19-putty-privatekey-passphrase-CDI2p4Ie.png",A="/assets/ch04-img20-winscp-privatekey-location-Cw1xSMYh.png",q={},L=a(`

          [Chapter 4] Security and Protection

          4.1 Why Do We Need Security Protection?

          Security protection for Linux servers is a complex and huge subject. Countless websites, apps, services, and even offline infrastructure are built on the foundation of Linux, which involves huge economic benefits and commercial value. This also means that there is a huge motivation for black and gray industries to launch attacks. However, these services are so important that major security vulnerabilities are not allowed. Therefore, countless operation and maintenance professionals are working hard on the battlefield of security attacks and defense, which enables us to enjoy a basic stable modern digital life.

          Now, you have a VPS and will open its data access channel to achieve the goal of traffic forwarding, which means you are now on the front line of the security battle and face all risks. However, at the same time, newcomers tend to have a polarized view of security issues due to lack of knowledge and information: either they feel it is as light as a feather and has nothing to do with them, or they feel it is as heavy as Mount Tai and feel anxious all day long.

          • For the former, my suggestion is: safety is of utmost importance. Try to gather more information on safety issues to avoid regretting after experiencing losses.

          • For the latter, my suggestion is: don't worry too much, our servers still don't have too much value and generally won't attract high-level attacks. The basic threats we need to face are mostly malicious scans and login attempts from some automated scripts. Just follow this article to do some basic protection.

          4.2 What are the specific risks

          Just like the configuration we did in the "Remote Login" section, anyone who knows the four elements of [IP address] + [port] + [username] + [password] can log in to your VPS server. So obviously, the security of these four elements is the bottom line that we need to protect. Let's analyze them one by one:

          1. [IP Address]: Malicious scripts randomly attempt to scan IP ranges, which can be regarded as public information and cannot be hidden.

          2. [Port]: If you are using the default port, then [Port = 22].

          3. [Username]: If using the default user, then [Username = root]

          4. [Password]: There is no default value for the password. It must be randomly generated by the VPS backend or set by you. In other words, if all the settings of your server are default, then three of the four elements are already known. Therefore, the security of your entire server relies on a small password. In this case, there are several situations:

          • If you use a VPS management background to generate passwords randomly, it usually contains random uppercase and lowercase letters, symbols, and is relatively secure.

          • If you changed your password to something super weak like 123456 just for the sake of easy memorization, hacking into your VPS server would be a piece of cake.

          • If you change your password to a more complex one that you have used elsewhere just for the sake of easy memory, it is not really safe. You should understand that hackers have cheats in their hands, such as password tables, which contain tens of thousands, hundreds of thousands, millions, or even more real leaked passwords.

          1. But you should understand that no hacker really sits in front of a computer and tries your password repeatedly. All attack attempts are carried out automatically by malicious scripts, which work tirelessly for 24 hours. Perhaps while you are sleeping soundly every night, your server is enduring round after round of attacks.

          Once the password is successfully cracked, it means that all four of your elements have been mastered by the attacker. The malicious script will quickly log in to the server, obtain the highest root control of the server, install and deploy its malicious services, and then use your server to do all kinds of bad things 24 hours a day (such as mining, spreading viruses, sending spam emails, fraudulent emails, acting as a BT relay, and even dark web public nodes, and so on). If the malicious script is relatively restrained, it can actually achieve considerable concealment. Generally, newcomers will not observe and pay attention to indicators such as login records, process changes, CPU usage changes, and traffic changes of the VPS, so it is difficult for you to discover that you have been hacked. Until your VPS service provider blocks your account or you receive a lawyer's letter.

          1. Don't forget that when you obtain a VPS, you probably need to use your real payment information, and when you log in to various websites and social platforms, your IP address will also be recorded, which has a direct or indirect relationship with your identity. Therefore, once these bad things happen, they will inevitably be associated with you.

          4.3 What security measures do we need to take

          Based on the above analysis, what we need to do is to strengthen the three elements of [port], [username], and [password] to reduce the risk of being hacked.

          1. [Port]: Modify the SSH remote login port to a [non-22 port] (4.4).
          2. [Username]: Create a [non-root] new user and disable root user SSH remote login (4.5, 4.6).
          3. [Password]: Enable RSA key verification for SSH login and disable password verification login (4.7).

          Remember to follow the order and don't lock yourself out.

          4.4 Change the SSH Remote Login Port to a Non-22 Port

          Now, let's solve the problem of "port = 22". (Note: some VPS service providers have non-22 ports set as default, so you can ignore this step if that's the case. Of course, you can also follow this article to change it to another port.)

          1. Basic commands of Little White Linux:
          IDCommand NameDescription
          cmd-03nanoText editor
          cmd-04systemctl restartRestart a service
          1. Basic Configuration Files of Little White Linux
          NumberConfiguration File LocationFile Description
          conf-01/etc/ssh/sshd_configSSH Remote Login Program Settings
          1. The first thing we need to do, of course, is to [open the SSH remote login program settings with the text editor nano]. In Windows, you will [find the file and double-click] it. What should you do in Linux? Take a close look at the command instructions above, isn't it simple? Yes, it is:
          nano /etc/ssh/sshd_config
           

          This is a command in the shell terminal to open the sshd_config file located in the /etc/ssh/ directory using the nano text editor.

          1. Once the file is opened, you will enter the interface of nano. After observing for a while, you will find that it displays important shortcut keys at the bottom of the screen (enclosed in a red box in the figure below). You can take the exam directly without memorizing them, which is very user-friendly, isn't it?

          Interface of nano

          1. The second thing we need to do is to find the Port item in the opened file and modify its port. The number after Port is the SSH port. It is generally recommended to change it to an integer greater than 1024 and less than 65535 (this article takes 9753 as an example). Please think about how to operate it with the shortcut keys of nano. You are right again! It is:
          • Use ctrl+w to enter search mode, then type Port 22 and press Enter
          • Delete 22 and replace it with 9753
          • Note: If this line starts with #, it means that this line is [commented out] and [does not take effect]. You can write a new line at the end of the file without #, or delete the # to enable this line.

          Warning

          This article uses 9753 as an example, which means that with the release of this article, this port will become a feature that may be prioritized or blocked by attackers or the Great Firewall of China. Therefore, I strongly recommend that you use another port that you come up with yourself, after all, you have over 60,000 ports to choose from freely.

          1. The third thing we need to do is to [save the file and exit].
          • If you observed carefully in step 3, you would have noticed that saving is not done by the common ctrl+s.
          • The correct shortcut keys: save is ctrl+o + enter, and exit is ctrl+x.
          • (For some operating systems) Add a firewall rule to set the new SSH port, otherwise, you won't be able to log in via SSH after the instance restarts.
          • For example, on Ubuntu using ufw.
          sudo ufw allow 9753/tcp
           
          1. The last thing we need to do is to [restart the SSH service to make the changes take effect].
          systemctl restart ssh
           

          Then you can try opening a new session in your SSH software to check if you can connect. If there are any issues, you can modify the configuration through the old SSH session (SSH connections that are already open will not be closed when restarting sshd).

          1. The complete process demonstration is as follows:

          Demonstration of modifying non-22 port

          1. Modify PuTTY Configuration

          "Now that the new port is in effect, you will need to use 9753 the next time you log in with PuTTY. So please go to the PuTTY settings to change the port number and save the session. Well, you should know where to change it, right? (If you don't know, you need to reread the previous content!)"

          4.5 Creating a New User Without Root Access

          In the second step, let's solve the issue of the username being root.

          Firstly, you need to understand that root in Linux system is not just a simple administrator account. It is the foundation of the entire system, the ruler and the supreme god of the system. Once the root account has security issues, the entire system will be vulnerable and there will be nowhere to hide. So, let's follow me to carry out the operations:

          1. Little White Linux Basic Commands:
          NumberCommand NameCommand Description
          cmd-05adduserAdd new user to the system
          cmd-06apt installInstall a software package
          cmd-07visudoSpecial editor to modify sudo permission settings
          1. The first thing we need to do is to [add a new user and set a login password]. You can choose any name you want, here I will use vpsadmin as an example:
          adduser vpsadmin
          diff --git a/assets/ch04-security.html-DDDnSxfv.js b/assets/ch04-security.html-DyDK2hA6.js
          similarity index 99%
          rename from assets/ch04-security.html-DDDnSxfv.js
          rename to assets/ch04-security.html-DyDK2hA6.js
          index 7016313ca9..f1c18a23c3 100644
          --- a/assets/ch04-security.html-DDDnSxfv.js
          +++ b/assets/ch04-security.html-DyDK2hA6.js
          @@ -1,4 +1,4 @@
          -import{_ as l,r as o,o as n,c as a,a as d,b as e,d as t,e as s}from"./app-5SoadDYS.js";const p="/assets/ch04-img01-nano-ui-6jgdTYpm.png",r="/assets/ch04-img02-sshd-conf-full-Dv8kUzC-.gif",u="/assets/ch04-img03-adduser-Cikb_tfM.png",h="/assets/ch04-img04-adduser-full-DgDkjVtm.gif",g="/assets/ch04-img05-sudo-full-DeKisL39.gif",m="/assets/ch04-img06-ssh-no-root-full-DZeR7uks.gif",_="/assets/ch04-img07-putty-default-user-BTPoHJe1.png",v="/assets/ch04-img08-puttygen-save-C2ur0GMu.png",S="/assets/ch04-img09-puttygen-save-keys-C8sxEVZz.png",b="/assets/ch04-img10-winscp-import-session-Bdx5sqJC.png",x="/assets/ch04-img11-winscp-ui-Cql7rWCm.png",y="/assets/ch04-img12-winscp-locations-tVIXHQa-.png",P="/assets/ch04-img13-winscp-newfolder-key-sIaUkXvO.png",f="/assets/ch04-img14-winscp-upload-key-BxgNsqKA.png",k="/assets/ch04-img15-winscp-rename-key-DQdsowRR.png",T="/assets/ch04-img16-winscp-full-B_z2QlO-.gif",V="/assets/ch04-img17-rsa-login-full-CZytVZwr.gif",w="/assets/ch04-img18-putty-privatekey-location-gVqxTouh.png",L="/assets/ch04-img19-putty-privatekey-passphrase-CDI2p4Ie.png",A="/assets/ch04-img20-winscp-privatekey-location-Cw1xSMYh.png",H={},C=s(`

          【第 4 章】安全防护篇

          4.1 为什么要做安全防护

          Linux 服务器的安全防护是一个纷繁复杂的巨大课题。无数的网站、APP、服务、甚至线下基础设施都建立在 Linux 的基石之上,这背后牵涉到巨大的经济利益和商业价值,当然也就就意味着黑灰产有巨大的攻击动力。但是这些服务是如此重要、根本不允许出现重大的安全漏洞。于是无数的运维专业人员都在安全攻防的战场上拼搏努力,这才让大家能享受到基本稳定的现代化数字生活。

          现在,你拥有了一台 VPS,并且将会敞开他的数据访问渠道来达到流量转发的目标,那就相当于你已经置身于安全攻防战场的第一线、直面所有风险。但与此同时,新人由于知识和信息的不足,看待安全问题是总是难免两极分化:要么觉得轻如鸿毛和自己没有半点关系,要么觉得重于泰山甚至惶惶不可终日。

          • 对于前者,我的建议是:安全无小事,尽量多查一些安全方面的信息,免得自己真的受了损失才后悔莫及

          • 对于后者,我的建议是:不用紧张,我们的服务器仍不具有太高的价值、一般不会吸引到高水平的攻击,需要面对的基本都是一些自动化脚本的恶意扫描和登录尝试,跟着本文做一些基础的防护即可

          4.2 具体的风险到底是什么

          就像我们在《远程登录篇》配置的一样,任何人只需要知道【IP 地址】+【端口】+【用户名】+【密码】这四个要素,就能登录你的 VPS 服务器。那很显然,这四要素的安全就是我们要防护的底线。我们来逐一分析:

          1. 【IP 地址】:恶意脚本会随机尝试和扫描 IP 段,可以简单认为是公开信息、无法隐藏

          2. 【端口】:如果使用默认端口,那么【端口 = 22

          3. 【用户名】:如果使用默认用户,那么【用户名 = root

          4. 【密码】:密码不存在默认值,一定是由 VPS 后台随机生成或由你自行设置的。也就是说,如果你的服务器都是默认设置,则四要素中的三个已经是已知的,那么你整个服务器的安全,就全部寄托在一串小小的密码上了。这时有几种情况:

            • 如果你用了 VPS 管理后台随机生成密码,它一般包含随机的十几个大小写混杂的字母和符号,相对比较安全

            • 如果你为了好记、把密码改成了类似123456这种超弱的密码,破解你的 VPS 服务器可谓不费吹灰之力

            • 如果你为了好记、把密码改成了比较复杂、但在别的地方用过的密码,其实也并不安全。你要明白黑客手里有作弊器,比如说密码表,包含数万、数十万、数百万甚至更多曾经泄漏的真实密码)

          5. 但你要明白,没有哪个黑客真的要坐在电脑前一次一次的尝试你的密码,全部的攻击尝试都是恶意脚本自动进行的,它会 24 小时不眠不休的工作。也许每天你酣睡之时,你的服务器都在经受着一轮又一轮的冲击。

            一旦密码被成功撞破,意味着你的四要素全部被攻击者掌握,恶意脚本就会快速登录服务器、获取服务器的最高 root 控制权、安装部署它的恶意服务,然后就可以用你的服务器来 24 小时做各种坏事(比如挖矿、传播病毒、发送垃圾邮件、欺诈邮件、做 BT 中继、甚至暗网公众节点等等等等)。如果恶意脚本比较克制,其实可以做到相当的隐蔽性。而新人一般也不会去观察留意 VPS 的登录记录、进程变化、CPU 占用变化、流量变化等指标,你其实就很难发现自己被黑了。直到你的 VPS 服务商封禁你的账号、或者收到律师函为止。

          6. 别忘了,你获得 VPS 时大概率需要使用真实的支付信息,你登录各种网站、社交平台时也会留下你的 IP 地址,这些都与你的身份有直接或者间接的关系。于是,一旦这些坏事发生,它们就不可避免的与你产生了关联。

          4.3 我们要做的安全防护有哪些

          基于上述分析,我们要做的,自然就是对【端口】、【用户名】、【密码】这三要素进行加强,来降低被攻破的风险:

          1. 【端口】:将 SSH 远程登录端口修改为【非 22 端口】 (4.4)
          2. 【用户名】:建立【非 root】的新用户、并禁用 root 用户 SSH 远程登录 (4.5、4.6)
          3. 【密码】:SSH 启用 RSA 密钥验证登录、同时禁用密码验证登录 (4.7)

          记得按顺序来,别把自己锁在门外了。

          4.4 将 SSH 远程登录端口修改为非 22 端口

          现在,我们来解决【端口 = 22】的问题。(注意:有些 VPS 服务商,默认的端口已经是非 22 端口,那么你可以忽略这一步,当然也可以跟着本文改成别的端口)

          1. 小小白白 Linux 基础命令:

            编号命令名称命令说明
            cmd-03nano文本编辑器
            cmd-04systemctl restart重启某个服务
          2. 小小白白 Linux 基础配置文件

            编号配置文件位置文件说明
            conf-01/etc/ssh/sshd_configSSH 远程登录程序设置
          3. 我们要做的第一件事,当然就是【用nano这个文本编辑器打开SSH远程登录程序设置】,在 Windows 下,你会【找到文件并双击】,在 Linux 下该怎么办呢?仔细看看上面的命令说明,是不是就很简单了?没错,就是:

            nano /etc/ssh/sshd_config
            +import{_ as l,r as o,o as n,c as a,a as d,b as e,d as t,e as s}from"./app-Bw2NG-QJ.js";const p="/assets/ch04-img01-nano-ui-6jgdTYpm.png",r="/assets/ch04-img02-sshd-conf-full-Dv8kUzC-.gif",u="/assets/ch04-img03-adduser-Cikb_tfM.png",h="/assets/ch04-img04-adduser-full-DgDkjVtm.gif",g="/assets/ch04-img05-sudo-full-DeKisL39.gif",m="/assets/ch04-img06-ssh-no-root-full-DZeR7uks.gif",_="/assets/ch04-img07-putty-default-user-BTPoHJe1.png",v="/assets/ch04-img08-puttygen-save-C2ur0GMu.png",S="/assets/ch04-img09-puttygen-save-keys-C8sxEVZz.png",b="/assets/ch04-img10-winscp-import-session-Bdx5sqJC.png",x="/assets/ch04-img11-winscp-ui-Cql7rWCm.png",y="/assets/ch04-img12-winscp-locations-tVIXHQa-.png",P="/assets/ch04-img13-winscp-newfolder-key-sIaUkXvO.png",f="/assets/ch04-img14-winscp-upload-key-BxgNsqKA.png",k="/assets/ch04-img15-winscp-rename-key-DQdsowRR.png",T="/assets/ch04-img16-winscp-full-B_z2QlO-.gif",V="/assets/ch04-img17-rsa-login-full-CZytVZwr.gif",w="/assets/ch04-img18-putty-privatekey-location-gVqxTouh.png",L="/assets/ch04-img19-putty-privatekey-passphrase-CDI2p4Ie.png",A="/assets/ch04-img20-winscp-privatekey-location-Cw1xSMYh.png",H={},C=s(`

            【第 4 章】安全防护篇

            4.1 为什么要做安全防护

            Linux 服务器的安全防护是一个纷繁复杂的巨大课题。无数的网站、APP、服务、甚至线下基础设施都建立在 Linux 的基石之上,这背后牵涉到巨大的经济利益和商业价值,当然也就就意味着黑灰产有巨大的攻击动力。但是这些服务是如此重要、根本不允许出现重大的安全漏洞。于是无数的运维专业人员都在安全攻防的战场上拼搏努力,这才让大家能享受到基本稳定的现代化数字生活。

            现在,你拥有了一台 VPS,并且将会敞开他的数据访问渠道来达到流量转发的目标,那就相当于你已经置身于安全攻防战场的第一线、直面所有风险。但与此同时,新人由于知识和信息的不足,看待安全问题是总是难免两极分化:要么觉得轻如鸿毛和自己没有半点关系,要么觉得重于泰山甚至惶惶不可终日。

            • 对于前者,我的建议是:安全无小事,尽量多查一些安全方面的信息,免得自己真的受了损失才后悔莫及

            • 对于后者,我的建议是:不用紧张,我们的服务器仍不具有太高的价值、一般不会吸引到高水平的攻击,需要面对的基本都是一些自动化脚本的恶意扫描和登录尝试,跟着本文做一些基础的防护即可

            4.2 具体的风险到底是什么

            就像我们在《远程登录篇》配置的一样,任何人只需要知道【IP 地址】+【端口】+【用户名】+【密码】这四个要素,就能登录你的 VPS 服务器。那很显然,这四要素的安全就是我们要防护的底线。我们来逐一分析:

            1. 【IP 地址】:恶意脚本会随机尝试和扫描 IP 段,可以简单认为是公开信息、无法隐藏

            2. 【端口】:如果使用默认端口,那么【端口 = 22

            3. 【用户名】:如果使用默认用户,那么【用户名 = root

            4. 【密码】:密码不存在默认值,一定是由 VPS 后台随机生成或由你自行设置的。也就是说,如果你的服务器都是默认设置,则四要素中的三个已经是已知的,那么你整个服务器的安全,就全部寄托在一串小小的密码上了。这时有几种情况:

              • 如果你用了 VPS 管理后台随机生成密码,它一般包含随机的十几个大小写混杂的字母和符号,相对比较安全

              • 如果你为了好记、把密码改成了类似123456这种超弱的密码,破解你的 VPS 服务器可谓不费吹灰之力

              • 如果你为了好记、把密码改成了比较复杂、但在别的地方用过的密码,其实也并不安全。你要明白黑客手里有作弊器,比如说密码表,包含数万、数十万、数百万甚至更多曾经泄漏的真实密码)

            5. 但你要明白,没有哪个黑客真的要坐在电脑前一次一次的尝试你的密码,全部的攻击尝试都是恶意脚本自动进行的,它会 24 小时不眠不休的工作。也许每天你酣睡之时,你的服务器都在经受着一轮又一轮的冲击。

              一旦密码被成功撞破,意味着你的四要素全部被攻击者掌握,恶意脚本就会快速登录服务器、获取服务器的最高 root 控制权、安装部署它的恶意服务,然后就可以用你的服务器来 24 小时做各种坏事(比如挖矿、传播病毒、发送垃圾邮件、欺诈邮件、做 BT 中继、甚至暗网公众节点等等等等)。如果恶意脚本比较克制,其实可以做到相当的隐蔽性。而新人一般也不会去观察留意 VPS 的登录记录、进程变化、CPU 占用变化、流量变化等指标,你其实就很难发现自己被黑了。直到你的 VPS 服务商封禁你的账号、或者收到律师函为止。

            6. 别忘了,你获得 VPS 时大概率需要使用真实的支付信息,你登录各种网站、社交平台时也会留下你的 IP 地址,这些都与你的身份有直接或者间接的关系。于是,一旦这些坏事发生,它们就不可避免的与你产生了关联。

            4.3 我们要做的安全防护有哪些

            基于上述分析,我们要做的,自然就是对【端口】、【用户名】、【密码】这三要素进行加强,来降低被攻破的风险:

            1. 【端口】:将 SSH 远程登录端口修改为【非 22 端口】 (4.4)
            2. 【用户名】:建立【非 root】的新用户、并禁用 root 用户 SSH 远程登录 (4.5、4.6)
            3. 【密码】:SSH 启用 RSA 密钥验证登录、同时禁用密码验证登录 (4.7)

            记得按顺序来,别把自己锁在门外了。

            4.4 将 SSH 远程登录端口修改为非 22 端口

            现在,我们来解决【端口 = 22】的问题。(注意:有些 VPS 服务商,默认的端口已经是非 22 端口,那么你可以忽略这一步,当然也可以跟着本文改成别的端口)

            1. 小小白白 Linux 基础命令:

              编号命令名称命令说明
              cmd-03nano文本编辑器
              cmd-04systemctl restart重启某个服务
            2. 小小白白 Linux 基础配置文件

              编号配置文件位置文件说明
              conf-01/etc/ssh/sshd_configSSH 远程登录程序设置
            3. 我们要做的第一件事,当然就是【用nano这个文本编辑器打开SSH远程登录程序设置】,在 Windows 下,你会【找到文件并双击】,在 Linux 下该怎么办呢?仔细看看上面的命令说明,是不是就很简单了?没错,就是:

              nano /etc/ssh/sshd_config
               
            4. 文件打开后,你就进入了nano的界面,稍微观察一下,你会发现,它把重要的快捷键都显示在屏幕下方了(下图红框内),直接开卷考试、不用死记硬背,是不是很贴心呢?

              nano的界面

            1. 我们要做的第二件事,是【在打开的文件中找到Port这一项,并修改它的端口】。Port 后面的数字就是 SSH 的端口,一般建议把它改成一个大于1024小于65535的整数(本文以9753为例)。请结合nano的快捷键,想一下该怎么操作呢?果然,你又说对了!就是:

              • 使用 ctrl+w 进入搜索模式,然后输入 Port 22 并回车
              • 删除 22 并改成 9753
              • 说明:如果这一行开头有个#,证明这一行【不生效】(被注释掉了),你可像我一样在文件最后写一个不带#的,或者把#删掉就好。

              注意

              本文以9753为例,就意味着随着本文的发布,这个端口会变成一个不大不小的特征,也许会被攻击者优先尝试、也许被 GFW 干扰、阻断。所以我强烈建议你用一个自己想到的其他端口,毕竟,你有 6 万多个端口可以自由选择。

            1. 我们要做的第三件事,是【保存文件并退出】

              • 如果第 3 步你有仔细观察,就会发现保存并不是常见的 ctrl+s

              • 正确的快捷键:保存是 ctrl+o + 回车,退出是 ctrl+x

              • (部分操作系统) 新增一个防火墙规则,设置为新增的SSH端口, 否则实例重启后无法SSH登陆。

              • 如 Ubuntu 的 ufw

              sudo ufw allow 9753/tcp
               
            2. 我们最后要做的事,是【重启 ssh 服务,使变更生效】

              systemctl restart ssh
               

              然后可以尝试在ssh软件上打开新的会话尝试是否可以连上,如果出现问题可以通过旧的ssh会话修改配置(重启sshd时已经打开的ssh不会被关闭)

            3. 完整流程演示如下:

              修改非22端口演示

            4. 修改 PuTTY 配置

              现在新的端口已经生效,下次使用 PuTTY 登录时就要用9753了。所以现在请到 PuTTY 的设置中修改端口号码,然后保存 Session。嗯,你应该知道去哪里改了吧?(如果不知道的话,要重读前面的内容了哦!)

            4.5 建立非 root 的新用户

            第二步,我们来解决【用户名 = root】的问题。

            首先你要理解, Linux 系统中的root,不仅仅是一个管理员账号那么简单。它是整个系统的【根基】、是系统的主宰、至高无上的神。一旦root账号出现安全问题,整个系统都只能任人鱼肉、无处可逃。那么就跟随我进行操作吧:

            1. 小小白白 Linux 基础命令:

              编号命令名称命令说明
              cmd-05adduser给系统新增用户
              cmd-06apt install安装某个软件
              cmd-07visudo修改 sudo 权限设置专用编辑器
            2. 我们要做的第一件事,是【新增一个用户并设定登录密码】,名字你可以随便起,我这里以vpsadmin为例:

              adduser vpsadmin
              diff --git a/assets/ch05-webpage.html-BHBAeKP6.js b/assets/ch05-webpage.html-3v0I9fWw.js
              similarity index 99%
              rename from assets/ch05-webpage.html-BHBAeKP6.js
              rename to assets/ch05-webpage.html-3v0I9fWw.js
              index e1e18ed6a9..1504eacf20 100644
              --- a/assets/ch05-webpage.html-BHBAeKP6.js
              +++ b/assets/ch05-webpage.html-3v0I9fWw.js
              @@ -1,4 +1,4 @@
              -import{_ as a,r as s,o as t,c as e,a as p,e as l}from"./app-5SoadDYS.js";const c="/assets/ch05-img01-nginx-default-running-CBlB4Sf4.png",i="/assets/ch05-img02-nginx-conf-full-C_TeO_k2.gif",o="/assets/ch05-img03-nginx-http-running-CkyqMkQN.png",d={},u=l(`

              【第 5 章】网站建设篇

              5.1 为什么要做一个网站?

              新人也许会迷惑,为什么科学上网还要建一个网站?我不会编程啊,是不是特别麻烦?

              先回答第一个问题,建网站的原因有:

              1. 申请合法的 TLS 证书(非常重要)
              2. 提供合理的回落,防止主动探测攻击,提高安全性
              3. 建设一个伪装站(如博客、私人网盘、多媒体网站、游戏网站等),直接访问时有合理的前台,使流量使用看上去更合理。

              再回答第二个问题:

              1. 本文作为演示,仅仅使用了一个最简单的【单文件 html 页面 + Nginx】来搭建,以此完成上面的目标,所以【非常简单】
              2. 这个网站完全可以不仅仅是伪装,而是真的做大做强,这个复杂性就完全取决于你了
              3. 对于“伪装”和“网站运营”这个目标,需要的就是各不相同、秀出真我,需要的同学可以自行搜索学习。这个内容已经完全偏离了科学上网,本文就不深入解析了。

              5.2 登录 VPS、安装运行 Nginx

              1. 这里用到的,都是之前已经详解过的命令,所以就不重复讲解了。看不懂的同学可以看看前面的章节哦。

                sudo apt update && sudo apt install nginx
                +import{_ as a,r as s,o as t,c as e,a as p,e as l}from"./app-Bw2NG-QJ.js";const c="/assets/ch05-img01-nginx-default-running-CBlB4Sf4.png",i="/assets/ch05-img02-nginx-conf-full-C_TeO_k2.gif",o="/assets/ch05-img03-nginx-http-running-CkyqMkQN.png",d={},u=l(`

                【第 5 章】网站建设篇

                5.1 为什么要做一个网站?

                新人也许会迷惑,为什么科学上网还要建一个网站?我不会编程啊,是不是特别麻烦?

                先回答第一个问题,建网站的原因有:

                1. 申请合法的 TLS 证书(非常重要)
                2. 提供合理的回落,防止主动探测攻击,提高安全性
                3. 建设一个伪装站(如博客、私人网盘、多媒体网站、游戏网站等),直接访问时有合理的前台,使流量使用看上去更合理。

                再回答第二个问题:

                1. 本文作为演示,仅仅使用了一个最简单的【单文件 html 页面 + Nginx】来搭建,以此完成上面的目标,所以【非常简单】
                2. 这个网站完全可以不仅仅是伪装,而是真的做大做强,这个复杂性就完全取决于你了
                3. 对于“伪装”和“网站运营”这个目标,需要的就是各不相同、秀出真我,需要的同学可以自行搜索学习。这个内容已经完全偏离了科学上网,本文就不深入解析了。

                5.2 登录 VPS、安装运行 Nginx

                1. 这里用到的,都是之前已经详解过的命令,所以就不重复讲解了。看不懂的同学可以看看前面的章节哦。

                  sudo apt update && sudo apt install nginx
                   
                2. 完成后,Nginx 已经自动运行。此时打开 Windows 上的浏览器并输入 http://100.200.300.400:80,若看到下图的界面就说明 Nginx 已经正常在运行了。

                  Nginx默认界面

                3. 如果无法看到上述Nginx默认页面,可能是需要配置Debian系统上默认的防火墙组件Uncomplicated Firewall (UFW),以便启用 HTTP (80) 和 HTTPS (443) 端口流量。

                  a. 验证方法,输入:

                  sudo ufw status
                   

                  b. 如果输出如下,表明80和433端口未开启,需要执行c步骤

                  Status: active
                   To                         Action      From
                  diff --git a/assets/ch05-webpage.html-DR79qyrD.js b/assets/ch05-webpage.html-D09gDc8i.js
                  similarity index 99%
                  rename from assets/ch05-webpage.html-DR79qyrD.js
                  rename to assets/ch05-webpage.html-D09gDc8i.js
                  index 8adc3a54e0..3d0a4a58aa 100644
                  --- a/assets/ch05-webpage.html-DR79qyrD.js
                  +++ b/assets/ch05-webpage.html-D09gDc8i.js
                  @@ -1,4 +1,4 @@
                  -import{_ as a,r as s,o as t,c as e,a as p,e as l}from"./app-5SoadDYS.js";const i="/assets/ch05-img01-nginx-default-running-CBlB4Sf4.png",o="/assets/ch05-img02-nginx-conf-full-C_TeO_k2.gif",c="/assets/ch05-img03-nginx-http-running-CkyqMkQN.png",d={},u=l(`

                  【Глава 5】 Создание веб-сайта

                  5.1 Зачем нужен веб-сайт?

                  Начинающие пользователи могут задаться вопросом: зачем создавать веб-сайт для обхода блокировок? Я не программист, это же сложно?

                  Начнём с первого вопроса. Веб-сайт нужен для того, чтобы:

                  1. Получить действующий SSL-сертификат (это очень важно).
                  2. Обеспечить маскировку трафика (fallback) и защититься от атак, направленных на выявление VPN-серверов.
                  3. Создать сайт-прикрытие (например, блог, облачное хранилище, медиа-портал, игровой сайт), который будет отображаться при прямом доступе к серверу, делая использование VPN менее заметным.

                  Теперь ответим на второй вопрос:

                  1. В этой статье мы создадим максимально простой веб-сайт, состоящий из одного HTML-файла и работающий на веб-сервере Nginx, чтобы решить поставленные выше задачи. Это очень просто.
                  2. Этот веб-сайт не обязательно должен быть просто прикрытием. Вы можете развивать его и превратить в полноценный проект. Всё зависит от ваших желаний и возможностей.
                  3. Создание сайта-прикрытия и его продвижение — это отдельная большая тема, которая выходит за рамки этой статьи. Если вам интересно, вы можете найти информацию об этом в интернете.

                  5.2 Подключение к VPS и установка Nginx

                  1. В этом разделе мы будем использовать команды, которые уже были подробно рассмотрены ранее. Если вы что-то не понимаете, вернитесь и перечитайте предыдущие главы.

                    sudo apt update && sudo apt install nginx
                    +import{_ as a,r as s,o as t,c as e,a as p,e as l}from"./app-Bw2NG-QJ.js";const i="/assets/ch05-img01-nginx-default-running-CBlB4Sf4.png",o="/assets/ch05-img02-nginx-conf-full-C_TeO_k2.gif",c="/assets/ch05-img03-nginx-http-running-CkyqMkQN.png",d={},u=l(`

                    【Глава 5】 Создание веб-сайта

                    5.1 Зачем нужен веб-сайт?

                    Начинающие пользователи могут задаться вопросом: зачем создавать веб-сайт для обхода блокировок? Я не программист, это же сложно?

                    Начнём с первого вопроса. Веб-сайт нужен для того, чтобы:

                    1. Получить действующий SSL-сертификат (это очень важно).
                    2. Обеспечить маскировку трафика (fallback) и защититься от атак, направленных на выявление VPN-серверов.
                    3. Создать сайт-прикрытие (например, блог, облачное хранилище, медиа-портал, игровой сайт), который будет отображаться при прямом доступе к серверу, делая использование VPN менее заметным.

                    Теперь ответим на второй вопрос:

                    1. В этой статье мы создадим максимально простой веб-сайт, состоящий из одного HTML-файла и работающий на веб-сервере Nginx, чтобы решить поставленные выше задачи. Это очень просто.
                    2. Этот веб-сайт не обязательно должен быть просто прикрытием. Вы можете развивать его и превратить в полноценный проект. Всё зависит от ваших желаний и возможностей.
                    3. Создание сайта-прикрытия и его продвижение — это отдельная большая тема, которая выходит за рамки этой статьи. Если вам интересно, вы можете найти информацию об этом в интернете.

                    5.2 Подключение к VPS и установка Nginx

                    1. В этом разделе мы будем использовать команды, которые уже были подробно рассмотрены ранее. Если вы что-то не понимаете, вернитесь и перечитайте предыдущие главы.

                      sudo apt update && sudo apt install nginx
                       
                    2. После завершения установки Nginx запустится автоматически. Откройте браузер на своём компьютере и введите адрес http://100.200.300.400:80. Если вы увидите страницу, как на скриншоте ниже, значит, Nginx работает.

                      Стандартная страница Nginx

                    3. Если вы не видите страницу Nginx, возможно, вам нужно настроить Uncomplicated Firewall (UFW), стандартный брандмауэр в Debian, чтобы разрешить трафик на портах HTTP (80) и HTTPS (443).

                      a. Чтобы проверить, введите:

                      sudo ufw status
                       

                      b. Если вывод команды такой, как показано ниже, это означает, что порты 80 и 443 закрыты. Выполните действия, описанные в пункте c.

                      Status: active
                       To                         Action      From
                      diff --git a/assets/ch05-webpage.html-CWPEvHEd.js b/assets/ch05-webpage.html-XNRjbxse.js
                      similarity index 99%
                      rename from assets/ch05-webpage.html-CWPEvHEd.js
                      rename to assets/ch05-webpage.html-XNRjbxse.js
                      index 4dc4b4b65f..f0324ab24f 100644
                      --- a/assets/ch05-webpage.html-CWPEvHEd.js
                      +++ b/assets/ch05-webpage.html-XNRjbxse.js
                      @@ -1,4 +1,4 @@
                      -import{_ as a,r as s,o as t,c as e,a as o,e as i}from"./app-5SoadDYS.js";const p="/assets/ch05-img01-nginx-default-running-CBlB4Sf4.png",l="/assets/ch05-img02-nginx-conf-full-C_TeO_k2.gif",c="/assets/ch05-img03-nginx-http-running-CkyqMkQN.png",u={},r=i(`

                      Chapter 5: Website Building

                      5.1 Why should you create a website?

                      Some newcomers may be confused: why do I need to build a website for securing an open digital environment? I don't know how to code! Isn't it very complicated?

                      First, let's answer the first question. The reasons for building a website are:

                      1. Apply for a legitimate TLS certificate (very important)
                      2. Provide reasonable fallback to prevent active probing attacks and improve security
                      3. Set up a camouflage site (such as a blog, private cloud storage, multimedia site, game site, etc.) with a reasonable frontend when directly accessed, making traffic usage look more legitimate.

                      Now let's answer the second question:

                      1. As a demonstration, this article uses only the simplest "single-file HTML page + Nginx" setup to achieve the above objectives, so it is very easy.
                      2. This website can not only be used for camouflage but also for real development and growth. The complexity depends entirely on you.
                      3. For the goals of "camouflage" and "website operation", uniqueness and personalization are needed. Students who need this can search and learn by themselves. This content has completely deviated from scientific online access, so this article will not go into depth.

                      5.2 Log in to VPS, install and run Nginx

                      1. Here we use commands that have been explained in detail before, so they won't be repeated. If you don't understand, please refer to the previous chapters.

                        sudo apt update && sudo apt install nginx
                        +import{_ as a,r as s,o as t,c as e,a as o,e as i}from"./app-Bw2NG-QJ.js";const p="/assets/ch05-img01-nginx-default-running-CBlB4Sf4.png",l="/assets/ch05-img02-nginx-conf-full-C_TeO_k2.gif",c="/assets/ch05-img03-nginx-http-running-CkyqMkQN.png",u={},r=i(`

                        Chapter 5: Website Building

                        5.1 Why should you create a website?

                        Some newcomers may be confused: why do I need to build a website for securing an open digital environment? I don't know how to code! Isn't it very complicated?

                        First, let's answer the first question. The reasons for building a website are:

                        1. Apply for a legitimate TLS certificate (very important)
                        2. Provide reasonable fallback to prevent active probing attacks and improve security
                        3. Set up a camouflage site (such as a blog, private cloud storage, multimedia site, game site, etc.) with a reasonable frontend when directly accessed, making traffic usage look more legitimate.

                        Now let's answer the second question:

                        1. As a demonstration, this article uses only the simplest "single-file HTML page + Nginx" setup to achieve the above objectives, so it is very easy.
                        2. This website can not only be used for camouflage but also for real development and growth. The complexity depends entirely on you.
                        3. For the goals of "camouflage" and "website operation", uniqueness and personalization are needed. Students who need this can search and learn by themselves. This content has completely deviated from scientific online access, so this article will not go into depth.

                        5.2 Log in to VPS, install and run Nginx

                        1. Here we use commands that have been explained in detail before, so they won't be repeated. If you don't understand, please refer to the previous chapters.

                          sudo apt update && sudo apt install nginx
                           
                        2. After completion, Nginx will automatically run. Open the browser on Windows and enter http://100.200.300.400:80. If you see the interface shown below, it means Nginx is running normally.

                          Nginx default interface

                        5.3 Create the simplest web page

                        1. Basic Linux commands for beginners:

                          No.Command NameCommand Description
                          cmd-10mkdirCreate a new folder
                          cmd-11systemctl reloadReload a specific service
                        2. Basic Linux configuration files for beginners:

                          No.Configuration File LocationFile Description
                          conf-02/etc/nginx/nginx.confNginx program settings
                        3. Create a dedicated folder /home/vpsadmin/www/webpage/ for the website and create the web page file index.html

                          mkdir -p ~/www/webpage/ && nano ~/www/webpage/index.html
                           

                        Warning

                        If you are not using the username vpsadmin, please be sure to understand the meaning of the "~" symbol in this command (this is related to Step 5 content):

                        • If it is a non-root user, "~" is equivalent to /home/username
                        • If it is a root user, "~" is equivalent to /root
                        1. Copy the entire content below, save (ctrl+o) and exit (ctrl+x).

                          <html lang="">
                             <!-- Text between angle brackets is an HTML tag and is not displayed.
                          diff --git a/assets/ch06-certificates.html-D3AQTy0p.js b/assets/ch06-certificates.html-BCM-NNIg.js
                          similarity index 99%
                          rename from assets/ch06-certificates.html-D3AQTy0p.js
                          rename to assets/ch06-certificates.html-BCM-NNIg.js
                          index ccdbc3a752..48b19f55cc 100644
                          --- a/assets/ch06-certificates.html-D3AQTy0p.js
                          +++ b/assets/ch06-certificates.html-BCM-NNIg.js
                          @@ -1,4 +1,4 @@
                          -import{_ as i,r as s,o as l,c as o,a,b as n,d as e,e as t}from"./app-5SoadDYS.js";const r="/assets/ch06-img01-acme-install-Dowds3tU.gif",d={},u=t('

                          【第 6 章】证书管理篇

                          6.1 申请 TLS 证书

                          接下来我们要做的,是为我们的域名申请一个真实的 TLS 证书,使网站具备标准 TLS 加密的能力及 HTTPS 访问的能力。这就是 Xray 等现阶段安全代理工具确保流量充分加密最重要的工具。

                          注意

                          请不要轻易使用自签证书。它并没有让操作简单太多,但增加了无谓的风险(如中间人攻击)。

                          ',4),m={href:"https://github.com/acmesh-official/acme.sh",target:"_blank",rel:"noopener noreferrer"},k=n("code",null,"acme.sh",-1),b=t(`

                          另外,我相信,现在你已经逐渐熟悉了 Linux 的基础操作,所以已经多次出现的命令从本章开始不再重复截图、只做简单的描述。如果实在想不起来怎么用的话,就稍微复习一下前面的章节吧。

                          6.2 安装 acme.sh

                          1. 小小白白 Linux 基础命令:

                            编号命令名称命令说明
                            cmd-12wget访问(或下载)某个网页文件
                            cmd-13acme.shacme.sh 证书管理相关的命令
                          2. 运行安装脚本

                            wget -O -  https://get.acme.sh | sh
                            +import{_ as i,r as s,o as l,c as o,a,b as n,d as e,e as t}from"./app-Bw2NG-QJ.js";const r="/assets/ch06-img01-acme-install-Dowds3tU.gif",d={},u=t('

                            【第 6 章】证书管理篇

                            6.1 申请 TLS 证书

                            接下来我们要做的,是为我们的域名申请一个真实的 TLS 证书,使网站具备标准 TLS 加密的能力及 HTTPS 访问的能力。这就是 Xray 等现阶段安全代理工具确保流量充分加密最重要的工具。

                            注意

                            请不要轻易使用自签证书。它并没有让操作简单太多,但增加了无谓的风险(如中间人攻击)。

                            ',4),m={href:"https://github.com/acmesh-official/acme.sh",target:"_blank",rel:"noopener noreferrer"},k=n("code",null,"acme.sh",-1),b=t(`

                            另外,我相信,现在你已经逐渐熟悉了 Linux 的基础操作,所以已经多次出现的命令从本章开始不再重复截图、只做简单的描述。如果实在想不起来怎么用的话,就稍微复习一下前面的章节吧。

                            6.2 安装 acme.sh

                            1. 小小白白 Linux 基础命令:

                              编号命令名称命令说明
                              cmd-12wget访问(或下载)某个网页文件
                              cmd-13acme.shacme.sh 证书管理相关的命令
                            2. 运行安装脚本

                              wget -O -  https://get.acme.sh | sh
                               
                            3. acme.sh 命令生效

                              . .bashrc
                               
                            4. 开启 acme.sh 的自动升级

                              acme.sh --upgrade --auto-upgrade
                               
                            5. 到这一步的完整流程如下图:

                              acme.sh安装演示

                            6.3 测试证书申请

                            在正式申请证书之前,我们先用测试命令(--issue --test)来验证是否可以成功申请,这样可以避免在本地配置有误时,反复申请证书失败,超过 Let's Encrypt 的频率上限(比如,每小时、每个域名、每个用户失败最多 5 次),导致后面的步骤无法进行。

                            1. 测试证书申请的命令如下(本文均以 ECC 证书为例,因为时至今日,实在没什么理由不用它):

                              acme.sh --issue --server letsencrypt --test -d 二级域名.你的域名.com -w /home/vpsadmin/www/webpage --keylength ec-256
                              diff --git a/assets/ch06-certificates.html-DUHSveME.js b/assets/ch06-certificates.html-Cjl3-nTJ.js
                              similarity index 99%
                              rename from assets/ch06-certificates.html-DUHSveME.js
                              rename to assets/ch06-certificates.html-Cjl3-nTJ.js
                              index af07211b60..fbb9f460fb 100644
                              --- a/assets/ch06-certificates.html-DUHSveME.js
                              +++ b/assets/ch06-certificates.html-Cjl3-nTJ.js
                              @@ -1,4 +1,4 @@
                              -import{_ as c,r as s,o as p,c as l,a,b as n,d as e,e as t}from"./app-5SoadDYS.js";const r="/assets/ch06-img01-acme-install-Dowds3tU.gif",d={},u=t('

                              [Chapter 6] Certificate Management

                              6.1 Applying for a TLS Certificate

                              Next, we need to apply for a real TLS certificate for our domain name, so that the website has the ability to encrypt with standard TLS and the ability to access via HTTPS. This is the most important tool for Xray and other current security proxy tools to ensure fully encrypted traffic.

                              Warning

                              Please do not use self-signed certificates lightly. It does not make the operation much simpler, but adds unnecessary risks (such as man-in-the-middle attacks).

                              ',4),m={href:"https://github.com/acmesh-official/acme.sh",target:"_blank",rel:"noopener noreferrer"},b=n("code",null,"acme.sh",-1),k=t(`

                              In addition, I believe that you have gradually become familiar with the basic operations of Linux. Therefore, from this chapter on, commands that have appeared multiple times will no longer have screenshots and will only be briefly described. If you really can't remember how to use them, just review the previous chapters.

                              6.2 Install acme.sh

                              1. Basic Linux commands for beginners:

                                NumberCommandDescription
                                cmd-12wgetRetrieve (or download) a webpage file
                                cmd-13acme.shCommands related to acme.sh certificate management
                              2. Run the installation script.

                              wget -O - https://get.acme.sh | sh
                              +import{_ as c,r as s,o as p,c as l,a,b as n,d as e,e as t}from"./app-Bw2NG-QJ.js";const r="/assets/ch06-img01-acme-install-Dowds3tU.gif",d={},u=t('

                              [Chapter 6] Certificate Management

                              6.1 Applying for a TLS Certificate

                              Next, we need to apply for a real TLS certificate for our domain name, so that the website has the ability to encrypt with standard TLS and the ability to access via HTTPS. This is the most important tool for Xray and other current security proxy tools to ensure fully encrypted traffic.

                              Warning

                              Please do not use self-signed certificates lightly. It does not make the operation much simpler, but adds unnecessary risks (such as man-in-the-middle attacks).

                              ',4),m={href:"https://github.com/acmesh-official/acme.sh",target:"_blank",rel:"noopener noreferrer"},b=n("code",null,"acme.sh",-1),k=t(`

                              In addition, I believe that you have gradually become familiar with the basic operations of Linux. Therefore, from this chapter on, commands that have appeared multiple times will no longer have screenshots and will only be briefly described. If you really can't remember how to use them, just review the previous chapters.

                              6.2 Install acme.sh

                              1. Basic Linux commands for beginners:

                                NumberCommandDescription
                                cmd-12wgetRetrieve (or download) a webpage file
                                cmd-13acme.shCommands related to acme.sh certificate management
                              2. Run the installation script.

                              wget -O - https://get.acme.sh | sh
                               
                              1. Make the acme.sh command effective.
                              . .bashrc
                               

                              (Note: This command is used to source (load) the .bashrc file in the shell environment.)

                              1. Enable acme.sh automatic upgrade.
                              acme.sh --upgrade --auto-upgrade
                               
                              1. The complete process up to this point is shown in the following diagram:

                              acme.sh installation demo

                              6.3 Testing Certificate Application

                              Before officially applying for the certificate, we use the testing command (--issue --test) to verify if the application can be successfully submitted. This can avoid repeated failures in applying for a certificate due to incorrect local configuration, exceeding the frequency limit of Let's Encrypt (such as a maximum of 5 failures per hour, per domain, or per user), which may prevent the subsequent steps from being carried out.

                              1. The command to apply for a test certificate is as follows (this article uses ECC certificate as an example, because there is really no reason not to use it nowadays):
                              acme.sh --issue --server letsencrypt --test -d subdomain.yourdomain.com -w /home/vpsadmin/www/webpage --keylength ec-256
                              diff --git a/assets/ch06-certificates.html-K5oNRMFq.js b/assets/ch06-certificates.html-DQoStl8T.js
                              similarity index 99%
                              rename from assets/ch06-certificates.html-K5oNRMFq.js
                              rename to assets/ch06-certificates.html-DQoStl8T.js
                              index 10b6736f8c..fdc8b299cd 100644
                              --- a/assets/ch06-certificates.html-K5oNRMFq.js
                              +++ b/assets/ch06-certificates.html-DQoStl8T.js
                              @@ -1,4 +1,4 @@
                              -import{_ as i,r as s,o as l,c as o,a,b as n,d as e,e as t}from"./app-5SoadDYS.js";const r="/assets/ch06-img01-acme-install-Dowds3tU.gif",d={},u=t('

                              【Глава 6】 Управление сертификатами

                              6.1 Получение SSL-сертификата

                              Теперь нам нужно получить действующий SSL-сертификат для нашего доменного имени, чтобы веб-сайт работал по протоколу HTTPS. Это важнейший инструмент для обеспечения безопасности трафика при использовании современных VPN-сервисов, таких как Xray.

                              Внимание

                              Не используйте самоподписанные сертификаты. Это ненамного упростит задачу, но создаст дополнительные риски (например, возможность атак типа «человек посередине»).

                              ',4),m={href:"https://github.com/acmesh-official/acme.sh",target:"_blank",rel:"noopener noreferrer"},k=n("code",null,"acme.sh",-1),b=t(`

                              Я уверен, что вы уже освоились с базовыми командами Linux, поэтому скриншоты с выводом команд, которые мы уже использовали ранее, будут опущены. Если вы забыли, как выполнять ту или иную команду, вернитесь и перечитайте предыдущие главы.

                              6.2 Установка acme.sh

                              1. Базовые команды Linux:

                                НомерКомандаОписание
                                cmd-12wgetЗагрузка файла из интернета
                                cmd-13acme.shУправление сертификатами
                              2. Запустите скрипт установки:

                                wget -O -  https://get.acme.sh | sh
                                +import{_ as i,r as s,o as l,c as o,a,b as n,d as e,e as t}from"./app-Bw2NG-QJ.js";const r="/assets/ch06-img01-acme-install-Dowds3tU.gif",d={},u=t('

                                【Глава 6】 Управление сертификатами

                                6.1 Получение SSL-сертификата

                                Теперь нам нужно получить действующий SSL-сертификат для нашего доменного имени, чтобы веб-сайт работал по протоколу HTTPS. Это важнейший инструмент для обеспечения безопасности трафика при использовании современных VPN-сервисов, таких как Xray.

                                Внимание

                                Не используйте самоподписанные сертификаты. Это ненамного упростит задачу, но создаст дополнительные риски (например, возможность атак типа «человек посередине»).

                                ',4),m={href:"https://github.com/acmesh-official/acme.sh",target:"_blank",rel:"noopener noreferrer"},k=n("code",null,"acme.sh",-1),b=t(`

                                Я уверен, что вы уже освоились с базовыми командами Linux, поэтому скриншоты с выводом команд, которые мы уже использовали ранее, будут опущены. Если вы забыли, как выполнять ту или иную команду, вернитесь и перечитайте предыдущие главы.

                                6.2 Установка acme.sh

                                1. Базовые команды Linux:

                                  НомерКомандаОписание
                                  cmd-12wgetЗагрузка файла из интернета
                                  cmd-13acme.shУправление сертификатами
                                2. Запустите скрипт установки:

                                  wget -O -  https://get.acme.sh | sh
                                   
                                3. Сделайте команду acme.sh доступной:

                                  . .bashrc
                                   
                                4. Включите автоматическое обновление acme.sh:

                                  acme.sh --upgrade --auto-upgrade
                                   
                                5. Весь процесс установки показан на гифке ниже:

                                  Установка acme.sh

                                6.3 Тестовый запрос сертификата

                                Перед тем, как запросить настоящий сертификат, давайте сделаем тестовый запрос (--issue --test), чтобы убедиться, что всё настроено правильно. Это позволит избежать превышения лимита на количество запросов Let's Encrypt (например, не более 5 неудачных запросов в час для одного домена и одного аккаунта).

                                1. Команда для тестового запроса сертификата (в этой статье мы будем использовать сертификаты ECC, поскольку на сегодняшний день нет причин не использовать их):

                                  acme.sh --issue --server letsencrypt --test -d поддомен.ваш_домен.com -w /home/vpsadmin/www/webpage --keylength ec-256
                                  diff --git a/assets/ch07-xray-server.html-C-3gFLNQ.js b/assets/ch07-xray-server.html-BqO-iTQU.js
                                  similarity index 99%
                                  rename from assets/ch07-xray-server.html-C-3gFLNQ.js
                                  rename to assets/ch07-xray-server.html-BqO-iTQU.js
                                  index 465510937c..ead2bab348 100644
                                  --- a/assets/ch07-xray-server.html-C-3gFLNQ.js
                                  +++ b/assets/ch07-xray-server.html-BqO-iTQU.js
                                  @@ -1,4 +1,4 @@
                                  -import{_ as c,r as o,o as d,c as p,a as e,b as s,d as n,w as r,e as a}from"./app-5SoadDYS.js";const u="/assets/ch07-img01-xray-install-6RUithnp.gif",v="/assets/ch07-img02-xray-cert-install-ByKnHBd1.png",m="/assets/ch07-img03-crontab-cert-renew-B_dwSLtg.gif",b="/assets/ch07-img04-xray-log-and-config-BP5ccZ8k.gif",h="/assets/ch07-img05-xray-start-and-status-Cl6yKbrT.gif",g="/assets/ch07-img06-bbr-proper-BpzfpFMr.gif",k="/assets/ch07-img07-http-to-https-QYIcd_gO.gif",y="/assets/ch07-img08-http-to-https-check-Dl2uIAjv.png",q={},x=a('

                                  【Глава 7】Настройка Xray на сервере

                                  7.1 Познать многое, усвоить нужное; копить постепенно, тратить осмотрительно

                                  Во время написания этого руководства один знакомый в шутку заметил: "Твое руководство уже 6 глав публикуется, а до Xray всё никак не дойдёт. Кто не знает, подумает, что это руководство "Создание сайта с нуля". (И ведь не поспоришь! 😂)

                                  На самом деле такая структура — результат моего осознанного решения. Ведь только заложив прочный фундамент, можно в дальнейшем двигаться вперёд семимильными шагами. Я видел в чатах много новичков, которые не могут правильно использовать даже nano, не говоря уже о WinSCP. Из-за этого их config.json, написанные вручную на удалённом сервере, пестрят ошибками, а поиск и исправление этих ошибок превращается в мучение.

                                  Внимание

                                  Пройдя первые 6 глав, мы вместе с вами преодолели несколько важных этапов: освоили базовые операции Linux, научились удалённо управлять VPS, разобрались с установкой веб-сервера, управлением доменными именами, получением SSL-сертификатов. Оглядываясь назад, разве всё это кажется таким уж сложным? Теперь, имея такой солидный багаж знаний, мы подойдём к установке и настройке Xray с чувством лёгкости и уверенности, ведь всё уже готово!

                                  Дальнейшие шаги предельно просты:

                                  1. Установка
                                  2. Настройка (например, установка TLS-сертификата, настройка config.json)
                                  3. Запуск
                                  4. Оптимизация (например, обновление ядра, включение bbr, автоматическое перенаправление http-запросов на https и т. д.)

                                  7.2 Установка Xray

                                  ',8),_={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"MPL 2.0",-1),X=s("strong",null,"конфигурации",-1),B={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},T=s("strong",null,"В данном руководстве мы будем использовать установку от имени непривилегированного пользователя",-1),S=a(`

                                  На момент написания руководства в скрипте есть небольшая ошибка при установке от имени непривилегированного пользователя, поэтому мы выполним эти шаги вручную. Заодно рассмотрим команду удаления файлов в Linux.

                                  1. Базовые команды Linux:

                                    НомерКомандаОписание
                                    cmd-14rmУдаление файлов
                                  2. Скачиваем установочный скрипт:

                                    wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                    +import{_ as c,r as o,o as d,c as p,a as e,b as s,d as n,w as r,e as a}from"./app-Bw2NG-QJ.js";const u="/assets/ch07-img01-xray-install-6RUithnp.gif",v="/assets/ch07-img02-xray-cert-install-ByKnHBd1.png",m="/assets/ch07-img03-crontab-cert-renew-B_dwSLtg.gif",b="/assets/ch07-img04-xray-log-and-config-BP5ccZ8k.gif",h="/assets/ch07-img05-xray-start-and-status-Cl6yKbrT.gif",g="/assets/ch07-img06-bbr-proper-BpzfpFMr.gif",k="/assets/ch07-img07-http-to-https-QYIcd_gO.gif",y="/assets/ch07-img08-http-to-https-check-Dl2uIAjv.png",q={},x=a('

                                    【Глава 7】Настройка Xray на сервере

                                    7.1 Познать многое, усвоить нужное; копить постепенно, тратить осмотрительно

                                    Во время написания этого руководства один знакомый в шутку заметил: "Твое руководство уже 6 глав публикуется, а до Xray всё никак не дойдёт. Кто не знает, подумает, что это руководство "Создание сайта с нуля". (И ведь не поспоришь! 😂)

                                    На самом деле такая структура — результат моего осознанного решения. Ведь только заложив прочный фундамент, можно в дальнейшем двигаться вперёд семимильными шагами. Я видел в чатах много новичков, которые не могут правильно использовать даже nano, не говоря уже о WinSCP. Из-за этого их config.json, написанные вручную на удалённом сервере, пестрят ошибками, а поиск и исправление этих ошибок превращается в мучение.

                                    Внимание

                                    Пройдя первые 6 глав, мы вместе с вами преодолели несколько важных этапов: освоили базовые операции Linux, научились удалённо управлять VPS, разобрались с установкой веб-сервера, управлением доменными именами, получением SSL-сертификатов. Оглядываясь назад, разве всё это кажется таким уж сложным? Теперь, имея такой солидный багаж знаний, мы подойдём к установке и настройке Xray с чувством лёгкости и уверенности, ведь всё уже готово!

                                    Дальнейшие шаги предельно просты:

                                    1. Установка
                                    2. Настройка (например, установка TLS-сертификата, настройка config.json)
                                    3. Запуск
                                    4. Оптимизация (например, обновление ядра, включение bbr, автоматическое перенаправление http-запросов на https и т. д.)

                                    7.2 Установка Xray

                                    ',8),_={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"MPL 2.0",-1),X=s("strong",null,"конфигурации",-1),B={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},T=s("strong",null,"В данном руководстве мы будем использовать установку от имени непривилегированного пользователя",-1),S=a(`

                                    На момент написания руководства в скрипте есть небольшая ошибка при установке от имени непривилегированного пользователя, поэтому мы выполним эти шаги вручную. Заодно рассмотрим команду удаления файлов в Linux.

                                    1. Базовые команды Linux:

                                      НомерКомандаОписание
                                      cmd-14rmУдаление файлов
                                    2. Скачиваем установочный скрипт:

                                      wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                       
                                    3. Запускаем установку:

                                      sudo bash install-release.sh
                                       
                                    4. После завершения установки удаляем скрипт:

                                      rm ~/install-release.sh
                                       

                                      Внимание

                                      При использовании команды rm для удаления файлов по умолчанию подразумевается удаление файлов в текущей директории. Однако я всё же указал полный путь: ~/install-release.sh. Это моя привычка, которая повышает безопасность при использовании rm. Думаю, вы слышали истории про "программиста, который удалил базу данных и сбежал". 😉

                                    5. Весь процесс показан на гифке:

                                      Процесс установки Xray на сервер

                                    7.3 Установка TLS-сертификата для Xray

                                    ',3),w={href:"https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E#3-copy%E5%AE%89%E8%A3%85-%E8%AF%81%E4%B9%A6",target:"_blank",rel:"noopener noreferrer"},L=s("code",null,"acme.sh",-1),P=s("code",null,"--install-cert",-1),R=s("code",null,"xray-core",-1),D=a(`
                                  3. Чтобы избежать проблем с правами доступа при работе от имени непривилегированного пользователя, создадим папку для сертификатов в домашней директории пользователя vpsadmin:

                                    mkdir ~/xray_cert
                                    diff --git a/assets/ch07-xray-server.html-D_AT7DH0.js b/assets/ch07-xray-server.html-DWmdh7MW.js
                                    similarity index 99%
                                    rename from assets/ch07-xray-server.html-D_AT7DH0.js
                                    rename to assets/ch07-xray-server.html-DWmdh7MW.js
                                    index e914520370..0aa4d6063f 100644
                                    --- a/assets/ch07-xray-server.html-D_AT7DH0.js
                                    +++ b/assets/ch07-xray-server.html-DWmdh7MW.js
                                    @@ -1,4 +1,4 @@
                                    -import{_ as c,r as o,o as d,c as p,a as e,b as s,d as n,w as r,e as a}from"./app-5SoadDYS.js";const u="/assets/ch07-img01-xray-install-6RUithnp.gif",v="/assets/ch07-img02-xray-cert-install-ByKnHBd1.png",m="/assets/ch07-img03-crontab-cert-renew-B_dwSLtg.gif",b="/assets/ch07-img04-xray-log-and-config-BP5ccZ8k.gif",h="/assets/ch07-img05-xray-start-and-status-Cl6yKbrT.gif",g="/assets/ch07-img06-bbr-proper-BpzfpFMr.gif",k="/assets/ch07-img07-http-to-https-QYIcd_gO.gif",y="/assets/ch07-img08-http-to-https-check-Dl2uIAjv.png",x={},q=a('

                                    【第 7 章】Xray 服务器篇

                                    7.1 博观而约取,厚积而薄发

                                    本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!)

                                    其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连nano都无法正确使用,也不会用WinSCP,远程手写编辑出来的config.json自然错误百出,连查错也变得举步维艰。

                                    Warning

                                    经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray 时会有一种【水到渠成】的轻快感觉。

                                    后面要做的事情非常简单:

                                    1. 安装
                                    2. 配置(如安装 TLS 证书、config.json
                                    3. 运行
                                    4. 优化(如更新内核、开启bbr、网站http访问自动跳转https等)

                                    7.2 安装 Xray

                                    ',8),_={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"MPL 2.0",-1),X={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=s("strong",null,"本文使用的是【非 root 用户】安装模式",-1),w=a(`

                                    写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。

                                    1. 小小白白 Linux 基础命令:

                                      编号命令名称命令说明
                                      cmd-14rm删除命令
                                    2. 将安装脚本下载至本地:

                                      wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                      +import{_ as c,r as o,o as d,c as p,a as e,b as s,d as n,w as r,e as a}from"./app-Bw2NG-QJ.js";const u="/assets/ch07-img01-xray-install-6RUithnp.gif",v="/assets/ch07-img02-xray-cert-install-ByKnHBd1.png",m="/assets/ch07-img03-crontab-cert-renew-B_dwSLtg.gif",b="/assets/ch07-img04-xray-log-and-config-BP5ccZ8k.gif",h="/assets/ch07-img05-xray-start-and-status-Cl6yKbrT.gif",g="/assets/ch07-img06-bbr-proper-BpzfpFMr.gif",k="/assets/ch07-img07-http-to-https-QYIcd_gO.gif",y="/assets/ch07-img08-http-to-https-check-Dl2uIAjv.png",x={},q=a('

                                      【第 7 章】Xray 服务器篇

                                      7.1 博观而约取,厚积而薄发

                                      本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!)

                                      其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连nano都无法正确使用,也不会用WinSCP,远程手写编辑出来的config.json自然错误百出,连查错也变得举步维艰。

                                      Warning

                                      经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray 时会有一种【水到渠成】的轻快感觉。

                                      后面要做的事情非常简单:

                                      1. 安装
                                      2. 配置(如安装 TLS 证书、config.json
                                      3. 运行
                                      4. 优化(如更新内核、开启bbr、网站http访问自动跳转https等)

                                      7.2 安装 Xray

                                      ',8),_={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"MPL 2.0",-1),X={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=s("strong",null,"本文使用的是【非 root 用户】安装模式",-1),w=a(`

                                      写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。

                                      1. 小小白白 Linux 基础命令:

                                        编号命令名称命令说明
                                        cmd-14rm删除命令
                                      2. 将安装脚本下载至本地:

                                        wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                         
                                      3. 执行安装命令

                                        sudo bash install-release.sh
                                         
                                      4. 使用完成之后可以删除该脚本

                                        rm ~/install-release.sh
                                         

                                        Warning

                                        使用 rm 命令删除文件的时候,默认其实就是删除现在所在的文件夹下的文件。但是,我依然写了完整的路径~/install-release.sh,这是我使用 rm 时的一个安全习惯、也是我把安装分成几步之后想强调一下的内容。如果你听过一些“程序员从删库到跑路”之类的段子,大概就知道为什么了。

                                      5. 完整流程演示如下:

                                        Xray服务器端安装流程演示

                                      7.3 给 Xray 配置 TLS 证书

                                      ',3),S={href:"https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E#3-copy%E5%AE%89%E8%A3%85-%E8%AF%81%E4%B9%A6",target:"_blank",rel:"noopener noreferrer"},L=s("code",null,"acme.sh",-1),R=s("code",null,"--install-cert",-1),T=s("code",null,"xray-core",-1),D=a(`
                                    3. 为了规避非 root 账户的各种潜在的权限困扰,我们在 vpsadmin 账户下建立一个证书文件夹

                                      mkdir ~/xray_cert
                                      diff --git a/assets/ch07-xray-server.html-BCFis-sE.js b/assets/ch07-xray-server.html-xXsQBQ03.js
                                      similarity index 99%
                                      rename from assets/ch07-xray-server.html-BCFis-sE.js
                                      rename to assets/ch07-xray-server.html-xXsQBQ03.js
                                      index 57a6cebf0e..eac1723314 100644
                                      --- a/assets/ch07-xray-server.html-BCFis-sE.js
                                      +++ b/assets/ch07-xray-server.html-xXsQBQ03.js
                                      @@ -1,4 +1,4 @@
                                      -import{_ as c,r as o,o as d,c as p,a as e,b as s,d as n,w as r,e as a}from"./app-5SoadDYS.js";const u="/assets/ch07-img01-xray-install-6RUithnp.gif",v="/assets/ch07-img02-xray-cert-install-ByKnHBd1.png",m="/assets/ch07-img03-crontab-cert-renew-B_dwSLtg.gif",b="/assets/ch07-img04-xray-log-and-config-BP5ccZ8k.gif",h="/assets/ch07-img05-xray-start-and-status-Cl6yKbrT.gif",g="/assets/ch07-img06-bbr-proper-BpzfpFMr.gif",k="/assets/ch07-img07-http-to-https-QYIcd_gO.gif",y="/assets/ch07-img08-http-to-https-check-Dl2uIAjv.png",x={},q=a('

                                      【第 7 章】Xray 服务器篇

                                      7.1 博观而约取,厚积而薄发

                                      本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!)

                                      其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连nano都无法正确使用,也不会用WinSCP,远程手写编辑出来的config.json自然错误百出,连查错也变得举步维艰。

                                      注意

                                      经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray 时会有一种【水到渠成】的轻快感觉。

                                      后面要做的事情非常简单:

                                      1. 安装
                                      2. 配置(如安装 TLS 证书、config.json
                                      3. 运行
                                      4. 优化(如更新内核、开启bbr、网站http访问自动跳转https等)

                                      7.2 安装 Xray

                                      ',8),_={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"MPL 2.0",-1),X={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=s("strong",null,"本文使用的是【非 root 用户】安装模式",-1),w=a(`

                                      写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。

                                      1. 小小白白 Linux 基础命令:

                                        编号命令名称命令说明
                                        cmd-14rm删除命令
                                      2. 将安装脚本下载至本地:

                                        wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                        +import{_ as c,r as o,o as d,c as p,a as e,b as s,d as n,w as r,e as a}from"./app-Bw2NG-QJ.js";const u="/assets/ch07-img01-xray-install-6RUithnp.gif",v="/assets/ch07-img02-xray-cert-install-ByKnHBd1.png",m="/assets/ch07-img03-crontab-cert-renew-B_dwSLtg.gif",b="/assets/ch07-img04-xray-log-and-config-BP5ccZ8k.gif",h="/assets/ch07-img05-xray-start-and-status-Cl6yKbrT.gif",g="/assets/ch07-img06-bbr-proper-BpzfpFMr.gif",k="/assets/ch07-img07-http-to-https-QYIcd_gO.gif",y="/assets/ch07-img08-http-to-https-check-Dl2uIAjv.png",x={},q=a('

                                        【第 7 章】Xray 服务器篇

                                        7.1 博观而约取,厚积而薄发

                                        本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!)

                                        其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连nano都无法正确使用,也不会用WinSCP,远程手写编辑出来的config.json自然错误百出,连查错也变得举步维艰。

                                        注意

                                        经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray 时会有一种【水到渠成】的轻快感觉。

                                        后面要做的事情非常简单:

                                        1. 安装
                                        2. 配置(如安装 TLS 证书、config.json
                                        3. 运行
                                        4. 优化(如更新内核、开启bbr、网站http访问自动跳转https等)

                                        7.2 安装 Xray

                                        ',8),_={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"MPL 2.0",-1),X={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=s("strong",null,"本文使用的是【非 root 用户】安装模式",-1),w=a(`

                                        写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。

                                        1. 小小白白 Linux 基础命令:

                                          编号命令名称命令说明
                                          cmd-14rm删除命令
                                        2. 将安装脚本下载至本地:

                                          wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                           
                                        3. 执行安装命令

                                          sudo bash install-release.sh
                                           
                                        4. 使用完成之后可以删除该脚本

                                          rm ~/install-release.sh
                                           

                                          注意

                                          使用 rm 命令删除文件的时候,默认其实就是删除现在所在的文件夹下的文件。但是,我依然写了完整的路径~/install-release.sh,这是我使用 rm 时的一个安全习惯、也是我把安装分成几步之后想强调一下的内容。如果你听过一些“程序员从删库到跑路”之类的段子,大概就知道为什么了。

                                        5. 完整流程演示如下:

                                          Xray服务器端安装流程演示

                                        7.3 给 Xray 配置 TLS 证书

                                        ',3),S={href:"https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E#3-copy%E5%AE%89%E8%A3%85-%E8%AF%81%E4%B9%A6",target:"_blank",rel:"noopener noreferrer"},L=s("code",null,"acme.sh",-1),R=s("code",null,"--install-cert",-1),T=s("code",null,"xray-core",-1),D=a(`
                                      3. 为了规避非 root 账户的各种潜在的权限困扰,我们在 vpsadmin 账户下建立一个证书文件夹

                                        mkdir ~/xray_cert
                                        diff --git a/assets/ch08-xray-clients.html-DueTm8m2.js b/assets/ch08-xray-clients.html-BNAUVuV_.js
                                        similarity index 99%
                                        rename from assets/ch08-xray-clients.html-DueTm8m2.js
                                        rename to assets/ch08-xray-clients.html-BNAUVuV_.js
                                        index 05d62f5dbb..46903f58ac 100644
                                        --- a/assets/ch08-xray-clients.html-DueTm8m2.js
                                        +++ b/assets/ch08-xray-clients.html-BNAUVuV_.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as e,o as u,c as r,a,b as n,d as s,w as l,e as t}from"./app-5SoadDYS.js";const d="/assets/ch08-img01-flow-26zmbxeD.png",k="/assets/ch08-img02-buzz-EySltltm.png",v={},m=t('

                                        【第 8 章】Xray 客户端篇

                                        8.1 Xray 的工作原理简述

                                        要正确的配置和使用Xray,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置):

                                        Xray数据流向

                                        这其中的关键点是:

                                        1. APP 要主动或借助转发工具,将数据【流入(inbounds)】Xray 客户端

                                        2. 流量进入客户端后,会被【客户端路由(routing)】按规则处理后,向不同方向【流出(outbounds)Xray 客户端。比如:

                                          1. 国内流量直连(direct
                                          2. 国外流量转发 VPS(proxy
                                          3. 广告流量屏蔽(block
                                        3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(inbounds)】 Xray 服务器端

                                        4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(routing)】按规则处理后,向不同方向【流出(outbounds)】:

                                          1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(direct
                                          2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(proxy
                                          3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(block
                                        ',6),q={class:"custom-container warning"},b=n("p",{class:"custom-container-title"},"注意",-1),g=n("p",null,[s("请务必记得,"),n("code",null,"Xray"),s(" 的路由配置非常灵活,上面的说明只是无限可能性中的一种。")],-1),y=n("p",null,[s("借助 "),n("code",null,"geosite.dat"),s(" 和 "),n("code",null,"geoip.dat"),s(" 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 "),n("code",null,"GFWList"),s(" 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。)")],-1),h=n("h2",{id:"_8-2-客户端与服务器端正确连接",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_8-2-客户端与服务器端正确连接"},[n("span",null,"8.2 客户端与服务器端正确连接")])],-1),_=n("p",null,[s("现在你已经理解了 "),n("code",null,"Xray"),s(" 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉"),n("code",null,"PuTTY"),s("如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。")],-1),x=n("code",null,"Xray",-1),f=n("code",null,"config.json",-1),S=n("code",null,"Xray",-1),X=n("code",null,"VLESS",-1),N=n("code",null,"XTLS",-1),P=t('
                                        • 服务器【地址】: a-name.yourdomain.com
                                        • 服务器【端口】: 443
                                        • 连接的【协议】: vless
                                        • 连接的【流控】: xtls-rprx-vision (vision 模式适合全平台)
                                        • 连接的【验证】: uuiduuid-uuid-uuid-uuiduuiduuid
                                        • 连接的【安全】: "allowInsecure": false

                                        鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。

                                        注意

                                        许多工具其实是同时支持 xray-corev2fly-core 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦!

                                        ',3),w=n("p",null,[n("strong",null,"v2rayN - 适用于 Windows 平台")],-1),I={href:"https://github.com/2dust/v2rayN/releases",target:"_blank",rel:"noopener noreferrer"},T=n("li",null,"请根据该客户端的说明进行设置",-1),L=n("p",null,[n("strong",null,"v2rayNG - 适用于 Android 平台")],-1),V={href:"https://github.com/2dust/v2rayNG/releases",target:"_blank",rel:"noopener noreferrer"},C=n("li",null,"请根据该客户端的说明进行设置",-1),D=n("li",null,[n("p",null,[n("strong",null,"Shadowrocket - 适用于 iOS, 基于苹果 M 芯片的 macOS")]),n("ul",null,[n("li",null,"你需要注册一个【非中国区】的 iCloud 账户"),n("li",null,"你需要通过 App Store 搜索并购买"),n("li",null,"请根据该客户端的说明进行设置")])],-1),E=n("p",null,[n("strong",null,"Qv2ray - 跨平台图形界面,适用于 Linux, Windows, macOS")],-1),j={href:"https://github.com/Qv2ray/Qv2ray/releases",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/Qv2ray/Qv2ray/actions",target:"_blank",rel:"noopener noreferrer"},A={href:"https://qv2ray.net/",target:"_blank",rel:"noopener noreferrer"},O=n("li",null,"请根据该客户端的说明进行设置",-1),R=n("p",null,[n("strong",null,"V2RayXS - 基于 V2RayX 开发的一款使用 xray-core 的 macOS 客户端")],-1),B={href:"https://github.com/tzmax/v2rayXS/releases",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"},Q=n("li",null,"请根据该客户端的说明进行设置",-1),W=t('

                                        到这一步,你的全套配置就已经可以正常使用啦!

                                        8.3 附加题 1:在 PC 端手工配置 xray-core

                                        虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把xray-core 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 xray-core 做客户端呢?

                                        为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势:

                                        • 第一时间获得最新版而无需等待 APP 升级适配

                                        • 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能)

                                        • 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现)

                                        它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤:

                                        ',6),F={href:"https://github.com/XTLS/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},Y=t(`
                                      4. 在合适的文件夹建立空白配置文件:config.json (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了)

                                      5. 至于什么是“合适的文件夹”?这就取决于具体的平台了~

                                      6. 填写客户端配置

                                        • 我就以 8.1 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 8.2 的连接要素,写成一个配置文件
                                        • 请将 uuid 替换成与你服务器一致的 uuid
                                        • 请将 address 替换成你的真实域名
                                        • 请将 serverName 替换成你的真实域名
                                        • 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了
                                        // REFERENCE:
                                        +import{_ as i,r as e,o as u,c as r,a,b as n,d as s,w as l,e as t}from"./app-Bw2NG-QJ.js";const d="/assets/ch08-img01-flow-26zmbxeD.png",k="/assets/ch08-img02-buzz-EySltltm.png",v={},m=t('

                                        【第 8 章】Xray 客户端篇

                                        8.1 Xray 的工作原理简述

                                        要正确的配置和使用Xray,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置):

                                        Xray数据流向

                                        这其中的关键点是:

                                        1. APP 要主动或借助转发工具,将数据【流入(inbounds)】Xray 客户端

                                        2. 流量进入客户端后,会被【客户端路由(routing)】按规则处理后,向不同方向【流出(outbounds)Xray 客户端。比如:

                                          1. 国内流量直连(direct
                                          2. 国外流量转发 VPS(proxy
                                          3. 广告流量屏蔽(block
                                        3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(inbounds)】 Xray 服务器端

                                        4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(routing)】按规则处理后,向不同方向【流出(outbounds)】:

                                          1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(direct
                                          2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(proxy
                                          3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(block
                                        ',6),q={class:"custom-container warning"},b=n("p",{class:"custom-container-title"},"注意",-1),g=n("p",null,[s("请务必记得,"),n("code",null,"Xray"),s(" 的路由配置非常灵活,上面的说明只是无限可能性中的一种。")],-1),y=n("p",null,[s("借助 "),n("code",null,"geosite.dat"),s(" 和 "),n("code",null,"geoip.dat"),s(" 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 "),n("code",null,"GFWList"),s(" 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。)")],-1),h=n("h2",{id:"_8-2-客户端与服务器端正确连接",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_8-2-客户端与服务器端正确连接"},[n("span",null,"8.2 客户端与服务器端正确连接")])],-1),_=n("p",null,[s("现在你已经理解了 "),n("code",null,"Xray"),s(" 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉"),n("code",null,"PuTTY"),s("如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。")],-1),x=n("code",null,"Xray",-1),f=n("code",null,"config.json",-1),S=n("code",null,"Xray",-1),X=n("code",null,"VLESS",-1),N=n("code",null,"XTLS",-1),P=t('
                                        • 服务器【地址】: a-name.yourdomain.com
                                        • 服务器【端口】: 443
                                        • 连接的【协议】: vless
                                        • 连接的【流控】: xtls-rprx-vision (vision 模式适合全平台)
                                        • 连接的【验证】: uuiduuid-uuid-uuid-uuiduuiduuid
                                        • 连接的【安全】: "allowInsecure": false

                                        鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。

                                        注意

                                        许多工具其实是同时支持 xray-corev2fly-core 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦!

                                        ',3),w=n("p",null,[n("strong",null,"v2rayN - 适用于 Windows 平台")],-1),I={href:"https://github.com/2dust/v2rayN/releases",target:"_blank",rel:"noopener noreferrer"},T=n("li",null,"请根据该客户端的说明进行设置",-1),L=n("p",null,[n("strong",null,"v2rayNG - 适用于 Android 平台")],-1),V={href:"https://github.com/2dust/v2rayNG/releases",target:"_blank",rel:"noopener noreferrer"},C=n("li",null,"请根据该客户端的说明进行设置",-1),D=n("li",null,[n("p",null,[n("strong",null,"Shadowrocket - 适用于 iOS, 基于苹果 M 芯片的 macOS")]),n("ul",null,[n("li",null,"你需要注册一个【非中国区】的 iCloud 账户"),n("li",null,"你需要通过 App Store 搜索并购买"),n("li",null,"请根据该客户端的说明进行设置")])],-1),E=n("p",null,[n("strong",null,"Qv2ray - 跨平台图形界面,适用于 Linux, Windows, macOS")],-1),j={href:"https://github.com/Qv2ray/Qv2ray/releases",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/Qv2ray/Qv2ray/actions",target:"_blank",rel:"noopener noreferrer"},A={href:"https://qv2ray.net/",target:"_blank",rel:"noopener noreferrer"},O=n("li",null,"请根据该客户端的说明进行设置",-1),R=n("p",null,[n("strong",null,"V2RayXS - 基于 V2RayX 开发的一款使用 xray-core 的 macOS 客户端")],-1),B={href:"https://github.com/tzmax/v2rayXS/releases",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"},Q=n("li",null,"请根据该客户端的说明进行设置",-1),W=t('

                                        到这一步,你的全套配置就已经可以正常使用啦!

                                        8.3 附加题 1:在 PC 端手工配置 xray-core

                                        虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把xray-core 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 xray-core 做客户端呢?

                                        为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势:

                                        • 第一时间获得最新版而无需等待 APP 升级适配

                                        • 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能)

                                        • 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现)

                                        它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤:

                                        ',6),F={href:"https://github.com/XTLS/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},Y=t(`
                                      7. 在合适的文件夹建立空白配置文件:config.json (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了)

                                      8. 至于什么是“合适的文件夹”?这就取决于具体的平台了~

                                      9. 填写客户端配置

                                        • 我就以 8.1 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 8.2 的连接要素,写成一个配置文件
                                        • 请将 uuid 替换成与你服务器一致的 uuid
                                        • 请将 address 替换成你的真实域名
                                        • 请将 serverName 替换成你的真实域名
                                        • 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了
                                        // REFERENCE:
                                         // https://github.com/XTLS/Xray-examples
                                         // https://xtls.github.io/config/
                                         
                                        diff --git a/assets/ch08-xray-clients.html-CJXEK9-Y.js b/assets/ch08-xray-clients.html-Bcxw8xnI.js
                                        similarity index 99%
                                        rename from assets/ch08-xray-clients.html-CJXEK9-Y.js
                                        rename to assets/ch08-xray-clients.html-Bcxw8xnI.js
                                        index e673f2e722..a6f99cba26 100644
                                        --- a/assets/ch08-xray-clients.html-CJXEK9-Y.js
                                        +++ b/assets/ch08-xray-clients.html-Bcxw8xnI.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as e,o as u,c as r,a,b as n,d as s,w as l,e as t}from"./app-5SoadDYS.js";const d="/assets/ch08-img01-flow-26zmbxeD.png",k="/assets/ch08-img02-buzz-EySltltm.png",v={},m=t('

                                        【Глава 8】Настройка Xray на клиенте

                                        8.1 Как работает Xray: краткое описание

                                        Чтобы правильно настраивать и использовать Xray, важно понимать принципы его работы. Новичкам поможет упрощённая схема, на которой не показаны некоторые сложные моменты:

                                        Поток данных в Xray

                                        Ключевые моменты:

                                        1. Приложение должно самостоятельно или с помощью стороннего инструмента перенаправить трафик на входящее подключение (inbounds) клиента Xray.

                                        2. Поступивший на клиент трафик обрабатывается модулем маршрутизации (routing) в соответствии с заданными правилами и перенаправляется на разные исходящие подключения (outbounds) клиента Xray, например:

                                          • Трафик на китайские ресурсы — напрямую (direct)
                                          • Трафик на зарубежные ресурсы — через VPS (proxy)
                                          • Рекламный трафик — блокируется (block)
                                        3. Трафик на зарубежные ресурсы, перенаправленный на VPS, проходит через Великий Китайский Файрвол и попадает на входящее подключение (inbounds) сервера Xray.

                                        4. Как и на клиенте, трафик, поступивший на сервер, обрабатывается модулем маршрутизации (routing) в соответствии с заданными правилами и перенаправляется на разные исходящие подключения (outbounds):

                                          • Поскольку сервер находится за пределами Китая, трафик по умолчанию идёт напрямую, что позволяет получить доступ к заблокированным ресурсам (direct).
                                          • При необходимости можно настроить перенаправление трафика на другие VPS (proxy).
                                          • На сервере также можно блокировать нежелательный трафик, например, рекламу или торренты (block).
                                        ',6),q={class:"custom-container warning"},b=n("p",{class:"custom-container-title"},"Внимание!",-1),g=n("p",null,[s("Важно помнить, что маршрутизация в "),n("code",null,"Xray"),s(" очень гибкая, и описанный выше сценарий — лишь один из множества возможных.")],-1),y=n("p",null,[s("Используя файлы "),n("code",null,"geosite.dat"),s(" и "),n("code",null,"geoip.dat"),s(", можно очень гибко управлять маршрутизацией трафика по доменным именам и IP-адресам. Это гораздо удобнее, чем устаревший "),n("code",null,"GFWList"),s(", поскольку позволяет очень точно настроить правила: например, можно разрешить прямое подключение к доменам Apple, перенаправить трафик на домены Amazon через прокси-сервер, блокировать доступ к доменам Baidu и т. д.")],-1),h=n("h2",{id:"_8-2-подключение-клиента-к-серверу",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_8-2-подключение-клиента-к-серверу"},[n("span",null,"8.2 Подключение клиента к серверу")])],-1),_=n("p",null,[s("Теперь, когда вы понимаете принципы работы "),n("code",null,"Xray"),s(", настройка клиента сводится к тому, чтобы "),n("strong",null,"сообщить ему, как подключиться к вашему VPS"),s(". Это как настроить "),n("code",null,"PuTTY"),s(" для подключения к серверу, только в случае с Xray параметров подключения больше, чем IP-адрес, порт, имя пользователя и пароль.")],-1),x=n("code",null,"Xray",-1),f=n("code",null,"VLESS",-1),S=n("code",null,"XTLS",-1),X=t('
                                        • Адрес сервера: sub.yourdomain.com
                                        • Порт сервера: 443
                                        • Протокол: vless
                                        • Поток: xtls-rprx-vision (режим vision подходит для всех платформ)
                                        • Идентификатор: uuiduuid-uuid-uuid-uuid-uuiduuiduuid
                                        • Безопасность: "allowInsecure": false

                                        Ниже приведен список популярных клиентов Xray для мобильных и настольных устройств. Каждый клиент имеет свой собственный интерфейс, поэтому я не буду делать скриншоты для каждого из них. Внимательно изучите документацию к выбранному клиенту и укажите нужные параметры подключения.

                                        Внимание!

                                        Многие клиенты поддерживают как xray-core, так и v2fly-core. Но по умолчанию может использоваться не тот, который вам нужен. Убедитесь, что вы выбрали нужный инструмент!

                                        ',3),w=n("p",null,[n("strong",null,"v2rayN - для Windows")],-1),N={href:"https://github.com/2dust/v2rayN/releases",target:"_blank",rel:"noopener noreferrer"},T=n("li",null,"Настройте клиент в соответствии с документацией",-1),L=n("p",null,[n("strong",null,"v2rayNG - для Android")],-1),P={href:"https://github.com/2dust/v2rayNG/releases",target:"_blank",rel:"noopener noreferrer"},V=n("li",null,"Настройте клиент в соответствии с документацией",-1),D=n("li",null,[n("p",null,[n("strong",null,"Shadowrocket - для iOS, macOS на базе Apple M1")]),n("ul",null,[n("li",null,[s("Создайте учётную запись iCloud "),n("strong",null,"не"),s(" в китайском регионе")]),n("li",null,"Купите приложение в App Store"),n("li",null,"Настройте клиент в соответствии с документацией")])],-1),I=n("p",null,[n("strong",null,"Qv2ray - кроссплатформенный графический интерфейс для Linux, Windows, macOS")],-1),C={href:"https://github.com/Qv2ray/Qv2ray/releases",target:"_blank",rel:"noopener noreferrer"},j={href:"https://github.com/Qv2ray/Qv2ray/actions",target:"_blank",rel:"noopener noreferrer"},O={href:"https://qv2ray.net/",target:"_blank",rel:"noopener noreferrer"},G=n("li",null,"Настройте клиент в соответствии с документацией",-1),H=n("p",null,[n("strong",null,"V2RayXS - клиент для macOS, основанный на V2RayX и использующий xray-core")],-1),A={href:"https://github.com/tzmax/v2rayXS/releases",target:"_blank",rel:"noopener noreferrer"},E={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"},Q=n("li",null,"Настройте клиент в соответствии с документацией",-1),W=t('

                                        На этом этапе ваша система готова к работе!

                                        8.3 Дополнительное задание 1: настройка xray-core на ПК вручную

                                        Хотя на предыдущем шаге мы уже всё настроили, любознательным и обладающим хорошей памятью читателям наверняка вспомнятся мои слова из предыдущей главы о том, что xray-core можно запускать как на сервере, так и на клиенте. Так как же использовать xray-core в качестве клиента?

                                        Чтобы ответить на этот вопрос, я добавил этот раздел с дополнительным заданием. Оно немного выходит за рамки основного материала и может показаться сложным, но у него есть свои преимущества:

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

                                        Недостаток этого способа заключается в том, что вам придётся настраивать клиент вручную, редактируя файл конфигурации. Но ведь на сервере вы уже делали это, так что ничего сложного здесь нет. Давайте разберёмся по шагам:

                                        ',6),z=n("code",null,"xray-core",-1),B={href:"https://github.com/XTLS/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},K=t(`
                                      10. Создайте пустой файл конфигурации config.json в той же папке (думаю, с этим проблем не возникнет).

                                      11. Что значит "удобное место"? Это зависит от платформы.

                                      12. Заполните файл конфигурации.

                                        • Я написал пример конфигурации, основанный на схеме из раздела 8.1 (прямое подключение к китайским ресурсам, проксирование трафика на зарубежные ресурсы через VPS, блокировка рекламы) и параметрах подключения из раздела 8.2.
                                        • Замените uuid на идентификатор из вашей конфигурации сервера.
                                        • Замените address на доменное имя вашего сервера.
                                        • Замените serverName на доменное имя вашего сервера.
                                        • Я добавил подробные комментарии к каждому разделу конфигурации.
                                        // ССЫЛКИ:
                                        +import{_ as i,r as e,o as u,c as r,a,b as n,d as s,w as l,e as t}from"./app-Bw2NG-QJ.js";const d="/assets/ch08-img01-flow-26zmbxeD.png",k="/assets/ch08-img02-buzz-EySltltm.png",v={},m=t('

                                        【Глава 8】Настройка Xray на клиенте

                                        8.1 Как работает Xray: краткое описание

                                        Чтобы правильно настраивать и использовать Xray, важно понимать принципы его работы. Новичкам поможет упрощённая схема, на которой не показаны некоторые сложные моменты:

                                        Поток данных в Xray

                                        Ключевые моменты:

                                        1. Приложение должно самостоятельно или с помощью стороннего инструмента перенаправить трафик на входящее подключение (inbounds) клиента Xray.

                                        2. Поступивший на клиент трафик обрабатывается модулем маршрутизации (routing) в соответствии с заданными правилами и перенаправляется на разные исходящие подключения (outbounds) клиента Xray, например:

                                          • Трафик на китайские ресурсы — напрямую (direct)
                                          • Трафик на зарубежные ресурсы — через VPS (proxy)
                                          • Рекламный трафик — блокируется (block)
                                        3. Трафик на зарубежные ресурсы, перенаправленный на VPS, проходит через Великий Китайский Файрвол и попадает на входящее подключение (inbounds) сервера Xray.

                                        4. Как и на клиенте, трафик, поступивший на сервер, обрабатывается модулем маршрутизации (routing) в соответствии с заданными правилами и перенаправляется на разные исходящие подключения (outbounds):

                                          • Поскольку сервер находится за пределами Китая, трафик по умолчанию идёт напрямую, что позволяет получить доступ к заблокированным ресурсам (direct).
                                          • При необходимости можно настроить перенаправление трафика на другие VPS (proxy).
                                          • На сервере также можно блокировать нежелательный трафик, например, рекламу или торренты (block).
                                        ',6),q={class:"custom-container warning"},b=n("p",{class:"custom-container-title"},"Внимание!",-1),g=n("p",null,[s("Важно помнить, что маршрутизация в "),n("code",null,"Xray"),s(" очень гибкая, и описанный выше сценарий — лишь один из множества возможных.")],-1),y=n("p",null,[s("Используя файлы "),n("code",null,"geosite.dat"),s(" и "),n("code",null,"geoip.dat"),s(", можно очень гибко управлять маршрутизацией трафика по доменным именам и IP-адресам. Это гораздо удобнее, чем устаревший "),n("code",null,"GFWList"),s(", поскольку позволяет очень точно настроить правила: например, можно разрешить прямое подключение к доменам Apple, перенаправить трафик на домены Amazon через прокси-сервер, блокировать доступ к доменам Baidu и т. д.")],-1),h=n("h2",{id:"_8-2-подключение-клиента-к-серверу",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_8-2-подключение-клиента-к-серверу"},[n("span",null,"8.2 Подключение клиента к серверу")])],-1),_=n("p",null,[s("Теперь, когда вы понимаете принципы работы "),n("code",null,"Xray"),s(", настройка клиента сводится к тому, чтобы "),n("strong",null,"сообщить ему, как подключиться к вашему VPS"),s(". Это как настроить "),n("code",null,"PuTTY"),s(" для подключения к серверу, только в случае с Xray параметров подключения больше, чем IP-адрес, порт, имя пользователя и пароль.")],-1),x=n("code",null,"Xray",-1),f=n("code",null,"VLESS",-1),S=n("code",null,"XTLS",-1),X=t('
                                        • Адрес сервера: sub.yourdomain.com
                                        • Порт сервера: 443
                                        • Протокол: vless
                                        • Поток: xtls-rprx-vision (режим vision подходит для всех платформ)
                                        • Идентификатор: uuiduuid-uuid-uuid-uuid-uuiduuiduuid
                                        • Безопасность: "allowInsecure": false

                                        Ниже приведен список популярных клиентов Xray для мобильных и настольных устройств. Каждый клиент имеет свой собственный интерфейс, поэтому я не буду делать скриншоты для каждого из них. Внимательно изучите документацию к выбранному клиенту и укажите нужные параметры подключения.

                                        Внимание!

                                        Многие клиенты поддерживают как xray-core, так и v2fly-core. Но по умолчанию может использоваться не тот, который вам нужен. Убедитесь, что вы выбрали нужный инструмент!

                                        ',3),w=n("p",null,[n("strong",null,"v2rayN - для Windows")],-1),N={href:"https://github.com/2dust/v2rayN/releases",target:"_blank",rel:"noopener noreferrer"},T=n("li",null,"Настройте клиент в соответствии с документацией",-1),L=n("p",null,[n("strong",null,"v2rayNG - для Android")],-1),P={href:"https://github.com/2dust/v2rayNG/releases",target:"_blank",rel:"noopener noreferrer"},V=n("li",null,"Настройте клиент в соответствии с документацией",-1),D=n("li",null,[n("p",null,[n("strong",null,"Shadowrocket - для iOS, macOS на базе Apple M1")]),n("ul",null,[n("li",null,[s("Создайте учётную запись iCloud "),n("strong",null,"не"),s(" в китайском регионе")]),n("li",null,"Купите приложение в App Store"),n("li",null,"Настройте клиент в соответствии с документацией")])],-1),I=n("p",null,[n("strong",null,"Qv2ray - кроссплатформенный графический интерфейс для Linux, Windows, macOS")],-1),C={href:"https://github.com/Qv2ray/Qv2ray/releases",target:"_blank",rel:"noopener noreferrer"},j={href:"https://github.com/Qv2ray/Qv2ray/actions",target:"_blank",rel:"noopener noreferrer"},O={href:"https://qv2ray.net/",target:"_blank",rel:"noopener noreferrer"},G=n("li",null,"Настройте клиент в соответствии с документацией",-1),H=n("p",null,[n("strong",null,"V2RayXS - клиент для macOS, основанный на V2RayX и использующий xray-core")],-1),A={href:"https://github.com/tzmax/v2rayXS/releases",target:"_blank",rel:"noopener noreferrer"},E={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"},Q=n("li",null,"Настройте клиент в соответствии с документацией",-1),W=t('

                                        На этом этапе ваша система готова к работе!

                                        8.3 Дополнительное задание 1: настройка xray-core на ПК вручную

                                        Хотя на предыдущем шаге мы уже всё настроили, любознательным и обладающим хорошей памятью читателям наверняка вспомнятся мои слова из предыдущей главы о том, что xray-core можно запускать как на сервере, так и на клиенте. Так как же использовать xray-core в качестве клиента?

                                        Чтобы ответить на этот вопрос, я добавил этот раздел с дополнительным заданием. Оно немного выходит за рамки основного материала и может показаться сложным, но у него есть свои преимущества:

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

                                        Недостаток этого способа заключается в том, что вам придётся настраивать клиент вручную, редактируя файл конфигурации. Но ведь на сервере вы уже делали это, так что ничего сложного здесь нет. Давайте разберёмся по шагам:

                                        ',6),z=n("code",null,"xray-core",-1),B={href:"https://github.com/XTLS/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},K=t(`
                                      13. Создайте пустой файл конфигурации config.json в той же папке (думаю, с этим проблем не возникнет).

                                      14. Что значит "удобное место"? Это зависит от платформы.

                                      15. Заполните файл конфигурации.

                                        • Я написал пример конфигурации, основанный на схеме из раздела 8.1 (прямое подключение к китайским ресурсам, проксирование трафика на зарубежные ресурсы через VPS, блокировка рекламы) и параметрах подключения из раздела 8.2.
                                        • Замените uuid на идентификатор из вашей конфигурации сервера.
                                        • Замените address на доменное имя вашего сервера.
                                        • Замените serverName на доменное имя вашего сервера.
                                        • Я добавил подробные комментарии к каждому разделу конфигурации.
                                        // ССЫЛКИ:
                                         // https://github.com/XTLS/Xray-examples
                                         // https://xtls.github.io/config/
                                         
                                        diff --git a/assets/ch08-xray-clients.html-CxcURVTg.js b/assets/ch08-xray-clients.html-Bqf0blkP.js
                                        similarity index 99%
                                        rename from assets/ch08-xray-clients.html-CxcURVTg.js
                                        rename to assets/ch08-xray-clients.html-Bqf0blkP.js
                                        index fab0c5279c..cfd14fe4e2 100644
                                        --- a/assets/ch08-xray-clients.html-CxcURVTg.js
                                        +++ b/assets/ch08-xray-clients.html-Bqf0blkP.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as e,o as u,c as r,a,b as n,d as s,w as l,e as t}from"./app-5SoadDYS.js";const d="/assets/ch08-img01-flow-26zmbxeD.png",k="/assets/ch08-img02-buzz-EySltltm.png",v={},m=t('

                                        【第 8 章】Xray 客户端篇

                                        8.1 Xray 的工作原理简述

                                        要正确的配置和使用Xray,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置):

                                        Xray数据流向

                                        这其中的关键点是:

                                        1. APP 要主动或借助转发工具,将数据【流入(inbounds)】Xray 客户端

                                        2. 流量进入客户端后,会被【客户端路由(routing)】按规则处理后,向不同方向【流出(outbounds)Xray 客户端。比如:

                                          1. 国内流量直连(direct
                                          2. 国外流量转发 VPS(proxy
                                          3. 广告流量屏蔽(block
                                        3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(inbounds)】 Xray 服务器端

                                        4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(routing)】按规则处理后,向不同方向【流出(outbounds)】:

                                          1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(direct
                                          2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(proxy
                                          3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(block
                                        ',6),q={class:"custom-container warning"},b=n("p",{class:"custom-container-title"},"注意",-1),g=n("p",null,[s("请务必记得,"),n("code",null,"Xray"),s(" 的路由配置非常灵活,上面的说明只是无限可能性中的一种。")],-1),y=n("p",null,[s("借助 "),n("code",null,"geosite.dat"),s(" 和 "),n("code",null,"geoip.dat"),s(" 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 "),n("code",null,"GFWList"),s(" 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。)")],-1),h=n("h2",{id:"_8-2-客户端与服务器端正确连接",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_8-2-客户端与服务器端正确连接"},[n("span",null,"8.2 客户端与服务器端正确连接")])],-1),_=n("p",null,[s("现在你已经理解了 "),n("code",null,"Xray"),s(" 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉"),n("code",null,"PuTTY"),s("如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。")],-1),x=n("code",null,"Xray",-1),f=n("code",null,"config.json",-1),S=n("code",null,"Xray",-1),X=n("code",null,"VLESS",-1),N=n("code",null,"XTLS",-1),P=t('
                                        • 服务器【地址】: a-name.yourdomain.com
                                        • 服务器【端口】: 443
                                        • 连接的【协议】: vless
                                        • 连接的【流控】: xtls-rprx-vision (vision 模式适合全平台)
                                        • 连接的【验证】: uuiduuid-uuid-uuid-uuiduuiduuid
                                        • 连接的【安全】: "allowInsecure": false

                                        鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。

                                        注意

                                        许多工具其实是同时支持 xray-corev2fly-core 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦!

                                        ',3),w=n("p",null,[n("strong",null,"v2rayN - 适用于 Windows 平台")],-1),I={href:"https://github.com/2dust/v2rayN/releases",target:"_blank",rel:"noopener noreferrer"},T=n("li",null,"请根据该客户端的说明进行设置",-1),L=n("p",null,[n("strong",null,"v2rayNG - 适用于 Android 平台")],-1),V={href:"https://github.com/2dust/v2rayNG/releases",target:"_blank",rel:"noopener noreferrer"},C=n("li",null,"请根据该客户端的说明进行设置",-1),D=n("li",null,[n("p",null,[n("strong",null,"Shadowrocket - 适用于 iOS, 基于苹果 M 芯片的 macOS")]),n("ul",null,[n("li",null,"你需要注册一个【非中国区】的 iCloud 账户"),n("li",null,"你需要通过 App Store 搜索并购买"),n("li",null,"请根据该客户端的说明进行设置")])],-1),E=n("p",null,[n("strong",null,"Qv2ray - 跨平台图形界面,适用于 Linux, Windows, macOS")],-1),j={href:"https://github.com/Qv2ray/Qv2ray/releases",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/Qv2ray/Qv2ray/actions",target:"_blank",rel:"noopener noreferrer"},A={href:"https://qv2ray.net/",target:"_blank",rel:"noopener noreferrer"},O=n("li",null,"请根据该客户端的说明进行设置",-1),R=n("p",null,[n("strong",null,"V2RayXS - 基于 V2RayX 开发的一款使用 xray-core 的 macOS 客户端")],-1),B={href:"https://github.com/tzmax/v2rayXS/releases",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"},Q=n("li",null,"请根据该客户端的说明进行设置",-1),W=t('

                                        到这一步,你的全套配置就已经可以正常使用啦!

                                        8.3 附加题 1:在 PC 端手工配置 xray-core

                                        虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把xray-core 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 xray-core 做客户端呢?

                                        为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势:

                                        • 第一时间获得最新版而无需等待 APP 升级适配

                                        • 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能)

                                        • 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现)

                                        它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤:

                                        ',6),F={href:"https://github.com/XTLS/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},Y=t(`
                                      16. 在合适的文件夹建立空白配置文件:config.json (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了)

                                      17. 至于什么是“合适的文件夹”?这就取决于具体的平台了~

                                      18. 填写客户端配置

                                        • 我就以 8.1 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 8.2 的连接要素,写成一个配置文件
                                        • 请将 uuid 替换成与你服务器一致的 uuid
                                        • 请将 address 替换成你的真实域名
                                        • 请将 serverName 替换成你的真实域名
                                        • 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了
                                        // REFERENCE:
                                        +import{_ as i,r as e,o as u,c as r,a,b as n,d as s,w as l,e as t}from"./app-Bw2NG-QJ.js";const d="/assets/ch08-img01-flow-26zmbxeD.png",k="/assets/ch08-img02-buzz-EySltltm.png",v={},m=t('

                                        【第 8 章】Xray 客户端篇

                                        8.1 Xray 的工作原理简述

                                        要正确的配置和使用Xray,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置):

                                        Xray数据流向

                                        这其中的关键点是:

                                        1. APP 要主动或借助转发工具,将数据【流入(inbounds)】Xray 客户端

                                        2. 流量进入客户端后,会被【客户端路由(routing)】按规则处理后,向不同方向【流出(outbounds)Xray 客户端。比如:

                                          1. 国内流量直连(direct
                                          2. 国外流量转发 VPS(proxy
                                          3. 广告流量屏蔽(block
                                        3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(inbounds)】 Xray 服务器端

                                        4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(routing)】按规则处理后,向不同方向【流出(outbounds)】:

                                          1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(direct
                                          2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(proxy
                                          3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(block
                                        ',6),q={class:"custom-container warning"},b=n("p",{class:"custom-container-title"},"注意",-1),g=n("p",null,[s("请务必记得,"),n("code",null,"Xray"),s(" 的路由配置非常灵活,上面的说明只是无限可能性中的一种。")],-1),y=n("p",null,[s("借助 "),n("code",null,"geosite.dat"),s(" 和 "),n("code",null,"geoip.dat"),s(" 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 "),n("code",null,"GFWList"),s(" 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。)")],-1),h=n("h2",{id:"_8-2-客户端与服务器端正确连接",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_8-2-客户端与服务器端正确连接"},[n("span",null,"8.2 客户端与服务器端正确连接")])],-1),_=n("p",null,[s("现在你已经理解了 "),n("code",null,"Xray"),s(" 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉"),n("code",null,"PuTTY"),s("如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。")],-1),x=n("code",null,"Xray",-1),f=n("code",null,"config.json",-1),S=n("code",null,"Xray",-1),X=n("code",null,"VLESS",-1),N=n("code",null,"XTLS",-1),P=t('
                                        • 服务器【地址】: a-name.yourdomain.com
                                        • 服务器【端口】: 443
                                        • 连接的【协议】: vless
                                        • 连接的【流控】: xtls-rprx-vision (vision 模式适合全平台)
                                        • 连接的【验证】: uuiduuid-uuid-uuid-uuiduuiduuid
                                        • 连接的【安全】: "allowInsecure": false

                                        鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。

                                        注意

                                        许多工具其实是同时支持 xray-corev2fly-core 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦!

                                        ',3),w=n("p",null,[n("strong",null,"v2rayN - 适用于 Windows 平台")],-1),I={href:"https://github.com/2dust/v2rayN/releases",target:"_blank",rel:"noopener noreferrer"},T=n("li",null,"请根据该客户端的说明进行设置",-1),L=n("p",null,[n("strong",null,"v2rayNG - 适用于 Android 平台")],-1),V={href:"https://github.com/2dust/v2rayNG/releases",target:"_blank",rel:"noopener noreferrer"},C=n("li",null,"请根据该客户端的说明进行设置",-1),D=n("li",null,[n("p",null,[n("strong",null,"Shadowrocket - 适用于 iOS, 基于苹果 M 芯片的 macOS")]),n("ul",null,[n("li",null,"你需要注册一个【非中国区】的 iCloud 账户"),n("li",null,"你需要通过 App Store 搜索并购买"),n("li",null,"请根据该客户端的说明进行设置")])],-1),E=n("p",null,[n("strong",null,"Qv2ray - 跨平台图形界面,适用于 Linux, Windows, macOS")],-1),j={href:"https://github.com/Qv2ray/Qv2ray/releases",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/Qv2ray/Qv2ray/actions",target:"_blank",rel:"noopener noreferrer"},A={href:"https://qv2ray.net/",target:"_blank",rel:"noopener noreferrer"},O=n("li",null,"请根据该客户端的说明进行设置",-1),R=n("p",null,[n("strong",null,"V2RayXS - 基于 V2RayX 开发的一款使用 xray-core 的 macOS 客户端")],-1),B={href:"https://github.com/tzmax/v2rayXS/releases",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"},Q=n("li",null,"请根据该客户端的说明进行设置",-1),W=t('

                                        到这一步,你的全套配置就已经可以正常使用啦!

                                        8.3 附加题 1:在 PC 端手工配置 xray-core

                                        虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把xray-core 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 xray-core 做客户端呢?

                                        为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势:

                                        • 第一时间获得最新版而无需等待 APP 升级适配

                                        • 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能)

                                        • 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现)

                                        它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤:

                                        ',6),F={href:"https://github.com/XTLS/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},Y=t(`
                                      19. 在合适的文件夹建立空白配置文件:config.json (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了)

                                      20. 至于什么是“合适的文件夹”?这就取决于具体的平台了~

                                      21. 填写客户端配置

                                        • 我就以 8.1 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 8.2 的连接要素,写成一个配置文件
                                        • 请将 uuid 替换成与你服务器一致的 uuid
                                        • 请将 address 替换成你的真实域名
                                        • 请将 serverName 替换成你的真实域名
                                        • 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了
                                        // REFERENCE:
                                         // https://github.com/XTLS/Xray-examples
                                         // https://xtls.github.io/config/
                                         
                                        diff --git a/assets/ch09-appendix.html-DsxMf9Eu.js b/assets/ch09-appendix.html-BP917XpD.js
                                        similarity index 99%
                                        rename from assets/ch09-appendix.html-DsxMf9Eu.js
                                        rename to assets/ch09-appendix.html-BP917XpD.js
                                        index d2af7fe7da..9f7d1240b2 100644
                                        --- a/assets/ch09-appendix.html-DsxMf9Eu.js
                                        +++ b/assets/ch09-appendix.html-BP917XpD.js
                                        @@ -1 +1 @@
                                        -import{_ as c,r as o,o as i,c as _,a as l,b as t,w as s,d as e}from"./app-5SoadDYS.js";const a={},r=t("h1",{id:"【第-9-章】附录",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#【第-9-章】附录"},[t("span",null,"【第 9 章】附录")])],-1),h=t("h2",{id:"_1-小小白白-linux-基础命令索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-小小白白-linux-基础命令索引"},[t("span",null,"1. 小小白白 Linux 基础命令索引")])],-1),u=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"命令名称"),t("th",{style:{"text-align":"left"}},"命令说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),y=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-01")],-1),x=t("td",{style:{"text-align":"left"}},[t("code",null,"apt update")],-1),g=t("td",{style:{"text-align":"left"}},"查询软件更新",-1),f={style:{"text-align":"center"}},m=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-02")],-1),v=t("td",{style:{"text-align":"left"}},[t("code",null,"apt upgrade")],-1),p=t("td",{style:{"text-align":"left"}},"执行软件更新",-1),X={style:{"text-align":"center"}},b=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-03")],-1),k=t("td",{style:{"text-align":"left"}},[t("code",null,"nano")],-1),L=t("td",{style:{"text-align":"left"}},"文本编辑器",-1),w={style:{"text-align":"center"}},T=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-04")],-1),N=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl restart")],-1),S=t("td",{style:{"text-align":"left"}},"重启某个服务",-1),B={style:{"text-align":"center"}},V=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-05")],-1),C=t("td",{style:{"text-align":"left"}},[t("code",null,"adduser")],-1),I=t("td",{style:{"text-align":"left"}},"给系统新增用户",-1),R={style:{"text-align":"center"}},j=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-06")],-1),A=t("td",{style:{"text-align":"left"}},[t("code",null,"apt install")],-1),E=t("td",{style:{"text-align":"left"}},"安装某个软件",-1),H={style:{"text-align":"center"}},q=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-07")],-1),z=t("td",{style:{"text-align":"left"}},[t("code",null,"visudo")],-1),D=t("td",{style:{"text-align":"left"}},"修改 sudo 权限设置专用编辑器",-1),F={style:{"text-align":"center"}},G=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-08")],-1),J=t("td",{style:{"text-align":"left"}},[t("code",null,"sudo")],-1),K=t("td",{style:{"text-align":"left"}},[e("用"),t("code",null,"root"),e("权限运行某个命令")],-1),M={style:{"text-align":"center"}},O=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-09")],-1),P=t("td",{style:{"text-align":"left"}},[t("code",null,"chmod")],-1),Q=t("td",{style:{"text-align":"left"}},"修改目标文件/文件夹的权限",-1),U={style:{"text-align":"center"}},W=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-10")],-1),Y=t("td",{style:{"text-align":"left"}},[t("code",null,"mkdir")],-1),Z=t("td",{style:{"text-align":"left"}},"新建文件夹",-1),$={style:{"text-align":"center"}},tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-11")],-1),et=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl reload")],-1),lt=t("td",{style:{"text-align":"left"}},"重新加载某个服务",-1),nt={style:{"text-align":"center"}},st=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-12")],-1),ot=t("td",{style:{"text-align":"left"}},[t("code",null,"wget")],-1),dt=t("td",{style:{"text-align":"left"}},"访问(或下载)某个网页文件",-1),ct={style:{"text-align":"center"}},it=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-13")],-1),_t=t("td",{style:{"text-align":"left"}},[t("code",null,"acme.sh")],-1),at=t("td",{style:{"text-align":"left"}},"acme.sh 证书管理相关的命令",-1),rt={style:{"text-align":"center"}},ht=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-14")],-1),ut=t("td",{style:{"text-align":"left"}},[t("code",null,"rm")],-1),yt=t("td",{style:{"text-align":"left"}},"删除命令",-1),xt={style:{"text-align":"center"}},gt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-15")],-1),ft=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),mt=t("td",{style:{"text-align":"left"}},"编辑当前用户的定时任务",-1),vt={style:{"text-align":"center"}},pt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-16")],-1),Xt=t("td",{style:{"text-align":"left"}},[t("code",null,"touch")],-1),bt=t("td",{style:{"text-align":"left"}},"建立空白文件",-1),kt={style:{"text-align":"center"}},Lt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-17")],-1),wt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl")],-1),Tt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemd"),e("基本服务管理命令")],-1),Nt={style:{"text-align":"center"}},St=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-18")],-1),Bt=t("td",{style:{"text-align":"left"}},[t("code",null,"reboot")],-1),Vt=t("td",{style:{"text-align":"left"}},"重启 Linux 系统",-1),Ct={style:{"text-align":"center"}},It=t("h2",{id:"_2-小小白白-linux-重要配置文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-小小白白-linux-重要配置文件索引"},[t("span",null,"2. 小小白白 Linux 重要配置文件索引")])],-1),Rt=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),jt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-01")],-1),At=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/ssh/sshd_config")],-1),Et=t("td",{style:{"text-align":"left"}},"SSH 远程登录程序设置",-1),Ht={style:{"text-align":"center"}},qt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-02")],-1),zt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/nginx/nginx.conf")],-1),Dt=t("td",{style:{"text-align":"left"}},"Nginx 程序设置",-1),Ft={style:{"text-align":"center"}},Gt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-03")],-1),Jt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list")],-1),Kt=t("td",{style:{"text-align":"left"}},"apt 软件源列表",-1),Mt={style:{"text-align":"center"}},Ot=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-04")],-1),Pt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list.d/vpsadmin.list")],-1),Qt=t("td",{style:{"text-align":"left"}},"用户自定义软件源列表列表",-1),Ut={style:{"text-align":"center"}},Wt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-05")],-1),Yt=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),Zt=t("td",{style:{"text-align":"left"}},"当前用户的定时任务",-1),$t={style:{"text-align":"center"}},te=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-06")],-1),ee=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.conf")],-1),le=t("td",{style:{"text-align":"left"}},"手动设置 kernel 参数",-1),ne={style:{"text-align":"center"}},se=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-07")],-1),oe=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.d/vpsadmin.conf")],-1),de=t("td",{style:{"text-align":"left"}},"用户自定义 kernel 参数配置文件",-1),ce={style:{"text-align":"center"}},ie=t("h2",{id:"_3-小小白白-xray-重要文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-小小白白-xray-重要文件索引"},[t("span",null,"3. 小小白白 Xray 重要文件索引")])],-1),_e=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),ae=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-01")],-1),re=t("td",{style:{"text-align":"left"}},[t("code",null,"/usr/local/etc/xray/config.json")],-1),he=t("td",{style:{"text-align":"left"}},"Xray 程序设置",-1),ue={style:{"text-align":"center"}},ye=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-02")],-1),xe=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.cert")],-1),ge=t("td",{style:{"text-align":"left"}},"TLS 证书",-1),fe={style:{"text-align":"center"}},me=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-03")],-1),ve=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.key")],-1),pe=t("td",{style:{"text-align":"left"}},"TLS 私钥",-1),Xe={style:{"text-align":"center"}},be=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-04")],-1),ke=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/access.log")],-1),Le=t("td",{style:{"text-align":"left"}},"Xray 访问日志",-1),we={style:{"text-align":"center"}},Te=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-05")],-1),Ne=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/error.log")],-1),Se=t("td",{style:{"text-align":"left"}},"Xray 错误日志",-1),Be={style:{"text-align":"center"}};function Ve(Ce,Ie){const d=o("I18nTip"),n=o("RouterLink");return i(),_("div",null,[l(d),r,h,t("table",null,[u,t("tbody",null,[t("tr",null,[y,x,g,t("td",f,[l(n,{to:"/en/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[m,v,p,t("td",X,[l(n,{to:"/en/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[b,k,L,t("td",w,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[T,N,S,t("td",B,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[V,C,I,t("td",R,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[j,A,E,t("td",H,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[q,z,D,t("td",F,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[G,J,K,t("td",M,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[O,P,Q,t("td",U,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[W,Y,Z,t("td",$,[l(n,{to:"/en/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[tt,et,lt,t("td",nt,[l(n,{to:"/en/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[st,ot,dt,t("td",ct,[l(n,{to:"/en/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[it,_t,at,t("td",rt,[l(n,{to:"/en/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[ht,ut,yt,t("td",xt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[gt,ft,mt,t("td",vt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[pt,Xt,bt,t("td",kt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Lt,wt,Tt,t("td",Nt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[St,Bt,Vt,t("td",Ct,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),It,t("table",null,[Rt,t("tbody",null,[t("tr",null,[jt,At,Et,t("td",Ht,[l(n,{to:"/en/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[qt,zt,Dt,t("td",Ft,[l(n,{to:"/en/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[Gt,Jt,Kt,t("td",Mt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Ot,Pt,Qt,t("td",Ut,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Wt,Yt,Zt,t("td",$t,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[te,ee,le,t("td",ne,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[se,oe,de,t("td",ce,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),ie,t("table",null,[_e,t("tbody",null,[t("tr",null,[ae,re,he,t("td",ue,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[ye,xe,ge,t("td",fe,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[me,ve,pe,t("td",Xe,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[be,ke,Le,t("td",we,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Te,Ne,Se,t("td",Be,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])])])}const je=c(a,[["render",Ve],["__file","ch09-appendix.html.vue"]]);export{je as default};
                                        +import{_ as c,r as o,o as i,c as _,a as l,b as t,w as s,d as e}from"./app-Bw2NG-QJ.js";const a={},r=t("h1",{id:"【第-9-章】附录",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#【第-9-章】附录"},[t("span",null,"【第 9 章】附录")])],-1),h=t("h2",{id:"_1-小小白白-linux-基础命令索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-小小白白-linux-基础命令索引"},[t("span",null,"1. 小小白白 Linux 基础命令索引")])],-1),u=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"命令名称"),t("th",{style:{"text-align":"left"}},"命令说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),y=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-01")],-1),x=t("td",{style:{"text-align":"left"}},[t("code",null,"apt update")],-1),g=t("td",{style:{"text-align":"left"}},"查询软件更新",-1),f={style:{"text-align":"center"}},m=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-02")],-1),v=t("td",{style:{"text-align":"left"}},[t("code",null,"apt upgrade")],-1),p=t("td",{style:{"text-align":"left"}},"执行软件更新",-1),X={style:{"text-align":"center"}},b=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-03")],-1),k=t("td",{style:{"text-align":"left"}},[t("code",null,"nano")],-1),L=t("td",{style:{"text-align":"left"}},"文本编辑器",-1),w={style:{"text-align":"center"}},T=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-04")],-1),N=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl restart")],-1),S=t("td",{style:{"text-align":"left"}},"重启某个服务",-1),B={style:{"text-align":"center"}},V=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-05")],-1),C=t("td",{style:{"text-align":"left"}},[t("code",null,"adduser")],-1),I=t("td",{style:{"text-align":"left"}},"给系统新增用户",-1),R={style:{"text-align":"center"}},j=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-06")],-1),A=t("td",{style:{"text-align":"left"}},[t("code",null,"apt install")],-1),E=t("td",{style:{"text-align":"left"}},"安装某个软件",-1),H={style:{"text-align":"center"}},q=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-07")],-1),z=t("td",{style:{"text-align":"left"}},[t("code",null,"visudo")],-1),D=t("td",{style:{"text-align":"left"}},"修改 sudo 权限设置专用编辑器",-1),F={style:{"text-align":"center"}},G=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-08")],-1),J=t("td",{style:{"text-align":"left"}},[t("code",null,"sudo")],-1),K=t("td",{style:{"text-align":"left"}},[e("用"),t("code",null,"root"),e("权限运行某个命令")],-1),M={style:{"text-align":"center"}},O=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-09")],-1),P=t("td",{style:{"text-align":"left"}},[t("code",null,"chmod")],-1),Q=t("td",{style:{"text-align":"left"}},"修改目标文件/文件夹的权限",-1),U={style:{"text-align":"center"}},W=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-10")],-1),Y=t("td",{style:{"text-align":"left"}},[t("code",null,"mkdir")],-1),Z=t("td",{style:{"text-align":"left"}},"新建文件夹",-1),$={style:{"text-align":"center"}},tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-11")],-1),et=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl reload")],-1),lt=t("td",{style:{"text-align":"left"}},"重新加载某个服务",-1),nt={style:{"text-align":"center"}},st=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-12")],-1),ot=t("td",{style:{"text-align":"left"}},[t("code",null,"wget")],-1),dt=t("td",{style:{"text-align":"left"}},"访问(或下载)某个网页文件",-1),ct={style:{"text-align":"center"}},it=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-13")],-1),_t=t("td",{style:{"text-align":"left"}},[t("code",null,"acme.sh")],-1),at=t("td",{style:{"text-align":"left"}},"acme.sh 证书管理相关的命令",-1),rt={style:{"text-align":"center"}},ht=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-14")],-1),ut=t("td",{style:{"text-align":"left"}},[t("code",null,"rm")],-1),yt=t("td",{style:{"text-align":"left"}},"删除命令",-1),xt={style:{"text-align":"center"}},gt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-15")],-1),ft=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),mt=t("td",{style:{"text-align":"left"}},"编辑当前用户的定时任务",-1),vt={style:{"text-align":"center"}},pt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-16")],-1),Xt=t("td",{style:{"text-align":"left"}},[t("code",null,"touch")],-1),bt=t("td",{style:{"text-align":"left"}},"建立空白文件",-1),kt={style:{"text-align":"center"}},Lt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-17")],-1),wt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl")],-1),Tt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemd"),e("基本服务管理命令")],-1),Nt={style:{"text-align":"center"}},St=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-18")],-1),Bt=t("td",{style:{"text-align":"left"}},[t("code",null,"reboot")],-1),Vt=t("td",{style:{"text-align":"left"}},"重启 Linux 系统",-1),Ct={style:{"text-align":"center"}},It=t("h2",{id:"_2-小小白白-linux-重要配置文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-小小白白-linux-重要配置文件索引"},[t("span",null,"2. 小小白白 Linux 重要配置文件索引")])],-1),Rt=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),jt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-01")],-1),At=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/ssh/sshd_config")],-1),Et=t("td",{style:{"text-align":"left"}},"SSH 远程登录程序设置",-1),Ht={style:{"text-align":"center"}},qt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-02")],-1),zt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/nginx/nginx.conf")],-1),Dt=t("td",{style:{"text-align":"left"}},"Nginx 程序设置",-1),Ft={style:{"text-align":"center"}},Gt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-03")],-1),Jt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list")],-1),Kt=t("td",{style:{"text-align":"left"}},"apt 软件源列表",-1),Mt={style:{"text-align":"center"}},Ot=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-04")],-1),Pt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list.d/vpsadmin.list")],-1),Qt=t("td",{style:{"text-align":"left"}},"用户自定义软件源列表列表",-1),Ut={style:{"text-align":"center"}},Wt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-05")],-1),Yt=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),Zt=t("td",{style:{"text-align":"left"}},"当前用户的定时任务",-1),$t={style:{"text-align":"center"}},te=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-06")],-1),ee=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.conf")],-1),le=t("td",{style:{"text-align":"left"}},"手动设置 kernel 参数",-1),ne={style:{"text-align":"center"}},se=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-07")],-1),oe=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.d/vpsadmin.conf")],-1),de=t("td",{style:{"text-align":"left"}},"用户自定义 kernel 参数配置文件",-1),ce={style:{"text-align":"center"}},ie=t("h2",{id:"_3-小小白白-xray-重要文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-小小白白-xray-重要文件索引"},[t("span",null,"3. 小小白白 Xray 重要文件索引")])],-1),_e=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),ae=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-01")],-1),re=t("td",{style:{"text-align":"left"}},[t("code",null,"/usr/local/etc/xray/config.json")],-1),he=t("td",{style:{"text-align":"left"}},"Xray 程序设置",-1),ue={style:{"text-align":"center"}},ye=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-02")],-1),xe=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.cert")],-1),ge=t("td",{style:{"text-align":"left"}},"TLS 证书",-1),fe={style:{"text-align":"center"}},me=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-03")],-1),ve=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.key")],-1),pe=t("td",{style:{"text-align":"left"}},"TLS 私钥",-1),Xe={style:{"text-align":"center"}},be=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-04")],-1),ke=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/access.log")],-1),Le=t("td",{style:{"text-align":"left"}},"Xray 访问日志",-1),we={style:{"text-align":"center"}},Te=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-05")],-1),Ne=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/error.log")],-1),Se=t("td",{style:{"text-align":"left"}},"Xray 错误日志",-1),Be={style:{"text-align":"center"}};function Ve(Ce,Ie){const d=o("I18nTip"),n=o("RouterLink");return i(),_("div",null,[l(d),r,h,t("table",null,[u,t("tbody",null,[t("tr",null,[y,x,g,t("td",f,[l(n,{to:"/en/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[m,v,p,t("td",X,[l(n,{to:"/en/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[b,k,L,t("td",w,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[T,N,S,t("td",B,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[V,C,I,t("td",R,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[j,A,E,t("td",H,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[q,z,D,t("td",F,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[G,J,K,t("td",M,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[O,P,Q,t("td",U,[l(n,{to:"/en/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[W,Y,Z,t("td",$,[l(n,{to:"/en/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[tt,et,lt,t("td",nt,[l(n,{to:"/en/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[st,ot,dt,t("td",ct,[l(n,{to:"/en/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[it,_t,at,t("td",rt,[l(n,{to:"/en/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[ht,ut,yt,t("td",xt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[gt,ft,mt,t("td",vt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[pt,Xt,bt,t("td",kt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Lt,wt,Tt,t("td",Nt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[St,Bt,Vt,t("td",Ct,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),It,t("table",null,[Rt,t("tbody",null,[t("tr",null,[jt,At,Et,t("td",Ht,[l(n,{to:"/en/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[qt,zt,Dt,t("td",Ft,[l(n,{to:"/en/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[Gt,Jt,Kt,t("td",Mt,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Ot,Pt,Qt,t("td",Ut,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Wt,Yt,Zt,t("td",$t,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[te,ee,le,t("td",ne,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[se,oe,de,t("td",ce,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),ie,t("table",null,[_e,t("tbody",null,[t("tr",null,[ae,re,he,t("td",ue,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[ye,xe,ge,t("td",fe,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[me,ve,pe,t("td",Xe,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[be,ke,Le,t("td",we,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Te,Ne,Se,t("td",Be,[l(n,{to:"/en/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])])])}const je=c(a,[["render",Ve],["__file","ch09-appendix.html.vue"]]);export{je as default};
                                        diff --git a/assets/ch09-appendix.html-DQIQbM0Q.js b/assets/ch09-appendix.html-DHpTAQmp.js
                                        similarity index 99%
                                        rename from assets/ch09-appendix.html-DQIQbM0Q.js
                                        rename to assets/ch09-appendix.html-DHpTAQmp.js
                                        index 5a23d0a2a2..1dd3cbca1b 100644
                                        --- a/assets/ch09-appendix.html-DQIQbM0Q.js
                                        +++ b/assets/ch09-appendix.html-DHpTAQmp.js
                                        @@ -1 +1 @@
                                        -import{_ as c,r as o,o as i,c as _,a as l,b as t,w as s,d as e}from"./app-5SoadDYS.js";const a={},r=t("h1",{id:"【第-9-章】附录",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#【第-9-章】附录"},[t("span",null,"【第 9 章】附录")])],-1),h=t("h2",{id:"_1-小小白白-linux-基础命令索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-小小白白-linux-基础命令索引"},[t("span",null,"1. 小小白白 Linux 基础命令索引")])],-1),u=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"命令名称"),t("th",{style:{"text-align":"left"}},"命令说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),y=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-01")],-1),x=t("td",{style:{"text-align":"left"}},[t("code",null,"apt update")],-1),g=t("td",{style:{"text-align":"left"}},"查询软件更新",-1),f={style:{"text-align":"center"}},m=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-02")],-1),v=t("td",{style:{"text-align":"left"}},[t("code",null,"apt upgrade")],-1),p=t("td",{style:{"text-align":"left"}},"执行软件更新",-1),X={style:{"text-align":"center"}},b=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-03")],-1),k=t("td",{style:{"text-align":"left"}},[t("code",null,"nano")],-1),L=t("td",{style:{"text-align":"left"}},"文本编辑器",-1),w={style:{"text-align":"center"}},T=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-04")],-1),N=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl restart")],-1),S=t("td",{style:{"text-align":"left"}},"重启某个服务",-1),B={style:{"text-align":"center"}},V=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-05")],-1),C=t("td",{style:{"text-align":"left"}},[t("code",null,"adduser")],-1),I=t("td",{style:{"text-align":"left"}},"给系统新增用户",-1),R={style:{"text-align":"center"}},j=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-06")],-1),A=t("td",{style:{"text-align":"left"}},[t("code",null,"apt install")],-1),E=t("td",{style:{"text-align":"left"}},"安装某个软件",-1),H={style:{"text-align":"center"}},q=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-07")],-1),z=t("td",{style:{"text-align":"left"}},[t("code",null,"visudo")],-1),D=t("td",{style:{"text-align":"left"}},"修改 sudo 权限设置专用编辑器",-1),F={style:{"text-align":"center"}},G=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-08")],-1),J=t("td",{style:{"text-align":"left"}},[t("code",null,"sudo")],-1),K=t("td",{style:{"text-align":"left"}},[e("用"),t("code",null,"root"),e("权限运行某个命令")],-1),M={style:{"text-align":"center"}},O=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-09")],-1),P=t("td",{style:{"text-align":"left"}},[t("code",null,"chmod")],-1),Q=t("td",{style:{"text-align":"left"}},"修改目标文件/文件夹的权限",-1),U={style:{"text-align":"center"}},W=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-10")],-1),Y=t("td",{style:{"text-align":"left"}},[t("code",null,"mkdir")],-1),Z=t("td",{style:{"text-align":"left"}},"新建文件夹",-1),$={style:{"text-align":"center"}},tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-11")],-1),et=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl reload")],-1),lt=t("td",{style:{"text-align":"left"}},"重新加载某个服务",-1),nt={style:{"text-align":"center"}},st=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-12")],-1),ot=t("td",{style:{"text-align":"left"}},[t("code",null,"wget")],-1),dt=t("td",{style:{"text-align":"left"}},"访问(或下载)某个网页文件",-1),ct={style:{"text-align":"center"}},it=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-13")],-1),_t=t("td",{style:{"text-align":"left"}},[t("code",null,"acme.sh")],-1),at=t("td",{style:{"text-align":"left"}},"acme.sh 证书管理相关的命令",-1),rt={style:{"text-align":"center"}},ht=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-14")],-1),ut=t("td",{style:{"text-align":"left"}},[t("code",null,"rm")],-1),yt=t("td",{style:{"text-align":"left"}},"删除命令",-1),xt={style:{"text-align":"center"}},gt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-15")],-1),ft=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),mt=t("td",{style:{"text-align":"left"}},"编辑当前用户的定时任务",-1),vt={style:{"text-align":"center"}},pt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-16")],-1),Xt=t("td",{style:{"text-align":"left"}},[t("code",null,"touch")],-1),bt=t("td",{style:{"text-align":"left"}},"建立空白文件",-1),kt={style:{"text-align":"center"}},Lt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-17")],-1),wt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl")],-1),Tt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemd"),e("基本服务管理命令")],-1),Nt={style:{"text-align":"center"}},St=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-18")],-1),Bt=t("td",{style:{"text-align":"left"}},[t("code",null,"reboot")],-1),Vt=t("td",{style:{"text-align":"left"}},"重启 Linux 系统",-1),Ct={style:{"text-align":"center"}},It=t("h2",{id:"_2-小小白白-linux-重要配置文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-小小白白-linux-重要配置文件索引"},[t("span",null,"2. 小小白白 Linux 重要配置文件索引")])],-1),Rt=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),jt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-01")],-1),At=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/ssh/sshd_config")],-1),Et=t("td",{style:{"text-align":"left"}},"SSH 远程登录程序设置",-1),Ht={style:{"text-align":"center"}},qt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-02")],-1),zt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/nginx/nginx.conf")],-1),Dt=t("td",{style:{"text-align":"left"}},"Nginx 程序设置",-1),Ft={style:{"text-align":"center"}},Gt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-03")],-1),Jt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list")],-1),Kt=t("td",{style:{"text-align":"left"}},"apt 软件源列表",-1),Mt={style:{"text-align":"center"}},Ot=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-04")],-1),Pt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list.d/vpsadmin.list")],-1),Qt=t("td",{style:{"text-align":"left"}},"用户自定义软件源列表列表",-1),Ut={style:{"text-align":"center"}},Wt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-05")],-1),Yt=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),Zt=t("td",{style:{"text-align":"left"}},"当前用户的定时任务",-1),$t={style:{"text-align":"center"}},te=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-06")],-1),ee=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.conf")],-1),le=t("td",{style:{"text-align":"left"}},"手动设置 kernel 参数",-1),ne={style:{"text-align":"center"}},se=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-07")],-1),oe=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.d/vpsadmin.conf")],-1),de=t("td",{style:{"text-align":"left"}},"用户自定义 kernel 参数配置文件",-1),ce={style:{"text-align":"center"}},ie=t("h2",{id:"_3-小小白白-xray-重要文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-小小白白-xray-重要文件索引"},[t("span",null,"3. 小小白白 Xray 重要文件索引")])],-1),_e=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),ae=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-01")],-1),re=t("td",{style:{"text-align":"left"}},[t("code",null,"/usr/local/etc/xray/config.json")],-1),he=t("td",{style:{"text-align":"left"}},"Xray 程序设置",-1),ue={style:{"text-align":"center"}},ye=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-02")],-1),xe=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.cert")],-1),ge=t("td",{style:{"text-align":"left"}},"TLS 证书",-1),fe={style:{"text-align":"center"}},me=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-03")],-1),ve=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.key")],-1),pe=t("td",{style:{"text-align":"left"}},"TLS 私钥",-1),Xe={style:{"text-align":"center"}},be=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-04")],-1),ke=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/access.log")],-1),Le=t("td",{style:{"text-align":"left"}},"Xray 访问日志",-1),we={style:{"text-align":"center"}},Te=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-05")],-1),Ne=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/error.log")],-1),Se=t("td",{style:{"text-align":"left"}},"Xray 错误日志",-1),Be={style:{"text-align":"center"}};function Ve(Ce,Ie){const d=o("I18nTip"),n=o("RouterLink");return i(),_("div",null,[l(d),r,h,t("table",null,[u,t("tbody",null,[t("tr",null,[y,x,g,t("td",f,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[m,v,p,t("td",X,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[b,k,L,t("td",w,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[T,N,S,t("td",B,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[V,C,I,t("td",R,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[j,A,E,t("td",H,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[q,z,D,t("td",F,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[G,J,K,t("td",M,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[O,P,Q,t("td",U,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[W,Y,Z,t("td",$,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[tt,et,lt,t("td",nt,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[st,ot,dt,t("td",ct,[l(n,{to:"/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[it,_t,at,t("td",rt,[l(n,{to:"/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[ht,ut,yt,t("td",xt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[gt,ft,mt,t("td",vt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[pt,Xt,bt,t("td",kt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Lt,wt,Tt,t("td",Nt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[St,Bt,Vt,t("td",Ct,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),It,t("table",null,[Rt,t("tbody",null,[t("tr",null,[jt,At,Et,t("td",Ht,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[qt,zt,Dt,t("td",Ft,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[Gt,Jt,Kt,t("td",Mt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Ot,Pt,Qt,t("td",Ut,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Wt,Yt,Zt,t("td",$t,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[te,ee,le,t("td",ne,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[se,oe,de,t("td",ce,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),ie,t("table",null,[_e,t("tbody",null,[t("tr",null,[ae,re,he,t("td",ue,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[ye,xe,ge,t("td",fe,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[me,ve,pe,t("td",Xe,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[be,ke,Le,t("td",we,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Te,Ne,Se,t("td",Be,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])])])}const je=c(a,[["render",Ve],["__file","ch09-appendix.html.vue"]]);export{je as default};
                                        +import{_ as c,r as o,o as i,c as _,a as l,b as t,w as s,d as e}from"./app-Bw2NG-QJ.js";const a={},r=t("h1",{id:"【第-9-章】附录",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#【第-9-章】附录"},[t("span",null,"【第 9 章】附录")])],-1),h=t("h2",{id:"_1-小小白白-linux-基础命令索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-小小白白-linux-基础命令索引"},[t("span",null,"1. 小小白白 Linux 基础命令索引")])],-1),u=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"命令名称"),t("th",{style:{"text-align":"left"}},"命令说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),y=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-01")],-1),x=t("td",{style:{"text-align":"left"}},[t("code",null,"apt update")],-1),g=t("td",{style:{"text-align":"left"}},"查询软件更新",-1),f={style:{"text-align":"center"}},m=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-02")],-1),v=t("td",{style:{"text-align":"left"}},[t("code",null,"apt upgrade")],-1),p=t("td",{style:{"text-align":"left"}},"执行软件更新",-1),X={style:{"text-align":"center"}},b=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-03")],-1),k=t("td",{style:{"text-align":"left"}},[t("code",null,"nano")],-1),L=t("td",{style:{"text-align":"left"}},"文本编辑器",-1),w={style:{"text-align":"center"}},T=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-04")],-1),N=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl restart")],-1),S=t("td",{style:{"text-align":"left"}},"重启某个服务",-1),B={style:{"text-align":"center"}},V=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-05")],-1),C=t("td",{style:{"text-align":"left"}},[t("code",null,"adduser")],-1),I=t("td",{style:{"text-align":"left"}},"给系统新增用户",-1),R={style:{"text-align":"center"}},j=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-06")],-1),A=t("td",{style:{"text-align":"left"}},[t("code",null,"apt install")],-1),E=t("td",{style:{"text-align":"left"}},"安装某个软件",-1),H={style:{"text-align":"center"}},q=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-07")],-1),z=t("td",{style:{"text-align":"left"}},[t("code",null,"visudo")],-1),D=t("td",{style:{"text-align":"left"}},"修改 sudo 权限设置专用编辑器",-1),F={style:{"text-align":"center"}},G=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-08")],-1),J=t("td",{style:{"text-align":"left"}},[t("code",null,"sudo")],-1),K=t("td",{style:{"text-align":"left"}},[e("用"),t("code",null,"root"),e("权限运行某个命令")],-1),M={style:{"text-align":"center"}},O=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-09")],-1),P=t("td",{style:{"text-align":"left"}},[t("code",null,"chmod")],-1),Q=t("td",{style:{"text-align":"left"}},"修改目标文件/文件夹的权限",-1),U={style:{"text-align":"center"}},W=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-10")],-1),Y=t("td",{style:{"text-align":"left"}},[t("code",null,"mkdir")],-1),Z=t("td",{style:{"text-align":"left"}},"新建文件夹",-1),$={style:{"text-align":"center"}},tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-11")],-1),et=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl reload")],-1),lt=t("td",{style:{"text-align":"left"}},"重新加载某个服务",-1),nt={style:{"text-align":"center"}},st=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-12")],-1),ot=t("td",{style:{"text-align":"left"}},[t("code",null,"wget")],-1),dt=t("td",{style:{"text-align":"left"}},"访问(或下载)某个网页文件",-1),ct={style:{"text-align":"center"}},it=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-13")],-1),_t=t("td",{style:{"text-align":"left"}},[t("code",null,"acme.sh")],-1),at=t("td",{style:{"text-align":"left"}},"acme.sh 证书管理相关的命令",-1),rt={style:{"text-align":"center"}},ht=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-14")],-1),ut=t("td",{style:{"text-align":"left"}},[t("code",null,"rm")],-1),yt=t("td",{style:{"text-align":"left"}},"删除命令",-1),xt={style:{"text-align":"center"}},gt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-15")],-1),ft=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),mt=t("td",{style:{"text-align":"left"}},"编辑当前用户的定时任务",-1),vt={style:{"text-align":"center"}},pt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-16")],-1),Xt=t("td",{style:{"text-align":"left"}},[t("code",null,"touch")],-1),bt=t("td",{style:{"text-align":"left"}},"建立空白文件",-1),kt={style:{"text-align":"center"}},Lt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-17")],-1),wt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl")],-1),Tt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemd"),e("基本服务管理命令")],-1),Nt={style:{"text-align":"center"}},St=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-18")],-1),Bt=t("td",{style:{"text-align":"left"}},[t("code",null,"reboot")],-1),Vt=t("td",{style:{"text-align":"left"}},"重启 Linux 系统",-1),Ct={style:{"text-align":"center"}},It=t("h2",{id:"_2-小小白白-linux-重要配置文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-小小白白-linux-重要配置文件索引"},[t("span",null,"2. 小小白白 Linux 重要配置文件索引")])],-1),Rt=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),jt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-01")],-1),At=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/ssh/sshd_config")],-1),Et=t("td",{style:{"text-align":"left"}},"SSH 远程登录程序设置",-1),Ht={style:{"text-align":"center"}},qt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-02")],-1),zt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/nginx/nginx.conf")],-1),Dt=t("td",{style:{"text-align":"left"}},"Nginx 程序设置",-1),Ft={style:{"text-align":"center"}},Gt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-03")],-1),Jt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list")],-1),Kt=t("td",{style:{"text-align":"left"}},"apt 软件源列表",-1),Mt={style:{"text-align":"center"}},Ot=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-04")],-1),Pt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list.d/vpsadmin.list")],-1),Qt=t("td",{style:{"text-align":"left"}},"用户自定义软件源列表列表",-1),Ut={style:{"text-align":"center"}},Wt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-05")],-1),Yt=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),Zt=t("td",{style:{"text-align":"left"}},"当前用户的定时任务",-1),$t={style:{"text-align":"center"}},te=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-06")],-1),ee=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.conf")],-1),le=t("td",{style:{"text-align":"left"}},"手动设置 kernel 参数",-1),ne={style:{"text-align":"center"}},se=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-07")],-1),oe=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.d/vpsadmin.conf")],-1),de=t("td",{style:{"text-align":"left"}},"用户自定义 kernel 参数配置文件",-1),ce={style:{"text-align":"center"}},ie=t("h2",{id:"_3-小小白白-xray-重要文件索引",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-小小白白-xray-重要文件索引"},[t("span",null,"3. 小小白白 Xray 重要文件索引")])],-1),_e=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"编号"),t("th",{style:{"text-align":"left"}},"配置文件位置"),t("th",{style:{"text-align":"left"}},"文件说明"),t("th",{style:{"text-align":"center"}},"出现篇章")])],-1),ae=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-01")],-1),re=t("td",{style:{"text-align":"left"}},[t("code",null,"/usr/local/etc/xray/config.json")],-1),he=t("td",{style:{"text-align":"left"}},"Xray 程序设置",-1),ue={style:{"text-align":"center"}},ye=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-02")],-1),xe=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.cert")],-1),ge=t("td",{style:{"text-align":"left"}},"TLS 证书",-1),fe={style:{"text-align":"center"}},me=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-03")],-1),ve=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.key")],-1),pe=t("td",{style:{"text-align":"left"}},"TLS 私钥",-1),Xe={style:{"text-align":"center"}},be=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-04")],-1),ke=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/access.log")],-1),Le=t("td",{style:{"text-align":"left"}},"Xray 访问日志",-1),we={style:{"text-align":"center"}},Te=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-05")],-1),Ne=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/error.log")],-1),Se=t("td",{style:{"text-align":"left"}},"Xray 错误日志",-1),Be={style:{"text-align":"center"}};function Ve(Ce,Ie){const d=o("I18nTip"),n=o("RouterLink");return i(),_("div",null,[l(d),r,h,t("table",null,[u,t("tbody",null,[t("tr",null,[y,x,g,t("td",f,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[m,v,p,t("td",X,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[b,k,L,t("td",w,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[T,N,S,t("td",B,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[V,C,I,t("td",R,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[j,A,E,t("td",H,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[q,z,D,t("td",F,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[G,J,K,t("td",M,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[O,P,Q,t("td",U,[l(n,{to:"/document/level-0/ch04-security.html"},{default:s(()=>[e("《安全防护篇》")]),_:1})])]),t("tr",null,[W,Y,Z,t("td",$,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[tt,et,lt,t("td",nt,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[st,ot,dt,t("td",ct,[l(n,{to:"/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[it,_t,at,t("td",rt,[l(n,{to:"/document/level-0/ch06-certificates.html"},{default:s(()=>[e("《证书管理篇》")]),_:1})])]),t("tr",null,[ht,ut,yt,t("td",xt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[gt,ft,mt,t("td",vt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[pt,Xt,bt,t("td",kt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Lt,wt,Tt,t("td",Nt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[St,Bt,Vt,t("td",Ct,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),It,t("table",null,[Rt,t("tbody",null,[t("tr",null,[jt,At,Et,t("td",Ht,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:s(()=>[e("《远程登录篇》")]),_:1})])]),t("tr",null,[qt,zt,Dt,t("td",Ft,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:s(()=>[e("《网站建设篇》")]),_:1})])]),t("tr",null,[Gt,Jt,Kt,t("td",Mt,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Ot,Pt,Qt,t("td",Ut,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Wt,Yt,Zt,t("td",$t,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[te,ee,le,t("td",ne,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[se,oe,de,t("td",ce,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])]),ie,t("table",null,[_e,t("tbody",null,[t("tr",null,[ae,re,he,t("td",ue,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[ye,xe,ge,t("td",fe,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[me,ve,pe,t("td",Xe,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[be,ke,Le,t("td",we,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])]),t("tr",null,[Te,Ne,Se,t("td",Be,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:s(()=>[e("《Xray 服务器篇》")]),_:1})])])])])])}const je=c(a,[["render",Ve],["__file","ch09-appendix.html.vue"]]);export{je as default};
                                        diff --git a/assets/ch09-appendix.html-CCG5ZhR3.js b/assets/ch09-appendix.html-cJZrrwi6.js
                                        similarity index 99%
                                        rename from assets/ch09-appendix.html-CCG5ZhR3.js
                                        rename to assets/ch09-appendix.html-cJZrrwi6.js
                                        index d5d5338d51..8e6b57404a 100644
                                        --- a/assets/ch09-appendix.html-CCG5ZhR3.js
                                        +++ b/assets/ch09-appendix.html-cJZrrwi6.js
                                        @@ -1 +1 @@
                                        -import{_ as c,r as o,o as i,c as _,a as e,b as t,w as n,d as s}from"./app-5SoadDYS.js";const a={},r=t("h1",{id:"глава-9-приложение",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#глава-9-приложение"},[t("span",null,"[Глава 9] Приложение")])],-1),h=t("h2",{id:"_1-индекс-основных-команд-linux-для-начинающих",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-индекс-основных-команд-linux-для-начинающих"},[t("span",null,"1. Индекс основных команд Linux для начинающих")])],-1),u=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"Номер"),t("th",{style:{"text-align":"left"}},"Название команды"),t("th",{style:{"text-align":"left"}},"Описание команды"),t("th",{style:{"text-align":"center"}},"Глава")])],-1),y=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-01")],-1),x=t("td",{style:{"text-align":"left"}},[t("code",null,"apt update")],-1),g=t("td",{style:{"text-align":"left"}},"Обновление списка пакетов",-1),f={style:{"text-align":"center"}},m=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-02")],-1),v=t("td",{style:{"text-align":"left"}},[t("code",null,"apt upgrade")],-1),p=t("td",{style:{"text-align":"left"}},"Обновление пакетов системы",-1),b={style:{"text-align":"center"}},X=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-03")],-1),L=t("td",{style:{"text-align":"left"}},[t("code",null,"nano")],-1),T=t("td",{style:{"text-align":"left"}},"Текстовый редактор",-1),k={style:{"text-align":"center"}},w=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-04")],-1),N=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl restart")],-1),S=t("td",{style:{"text-align":"left"}},"Перезапуск сервиса",-1),A={style:{"text-align":"center"}},B=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-05")],-1),C=t("td",{style:{"text-align":"left"}},[t("code",null,"adduser")],-1),V=t("td",{style:{"text-align":"left"}},"Добавление пользователя",-1),I={style:{"text-align":"center"}},P=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-06")],-1),R=t("td",{style:{"text-align":"left"}},[t("code",null,"apt install")],-1),j=t("td",{style:{"text-align":"left"}},"Установка пакета",-1),E={style:{"text-align":"center"}},H=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-07")],-1),q=t("td",{style:{"text-align":"left"}},[t("code",null,"visudo")],-1),z=t("td",{style:{"text-align":"left"}},"Редактор для настройки sudo",-1),D={style:{"text-align":"center"}},F=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-08")],-1),G=t("td",{style:{"text-align":"left"}},[t("code",null,"sudo")],-1),J=t("td",{style:{"text-align":"left"}},"Выполнение команды от имени root",-1),K={style:{"text-align":"center"}},M=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-09")],-1),O=t("td",{style:{"text-align":"left"}},[t("code",null,"chmod")],-1),Q=t("td",{style:{"text-align":"left"}},"Изменение прав доступа к файлу/папке",-1),U={style:{"text-align":"center"}},W=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-10")],-1),Y=t("td",{style:{"text-align":"left"}},[t("code",null,"mkdir")],-1),Z=t("td",{style:{"text-align":"left"}},"Создание папки",-1),$={style:{"text-align":"center"}},tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-11")],-1),et=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl reload")],-1),lt=t("td",{style:{"text-align":"left"}},"Перезагрузка конфигурации сервиса",-1),nt={style:{"text-align":"center"}},st=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-12")],-1),ot=t("td",{style:{"text-align":"left"}},[t("code",null,"wget")],-1),dt=t("td",{style:{"text-align":"left"}},"Загрузка файла/страницы из сети",-1),ct={style:{"text-align":"center"}},it=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-13")],-1),_t=t("td",{style:{"text-align":"left"}},[t("code",null,"acme.sh")],-1),at=t("td",{style:{"text-align":"left"}},"Управление сертификатами с помощью acme.sh",-1),rt={style:{"text-align":"center"}},ht=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-14")],-1),ut=t("td",{style:{"text-align":"left"}},[t("code",null,"rm")],-1),yt=t("td",{style:{"text-align":"left"}},"Удаление файлов/папок",-1),xt={style:{"text-align":"center"}},gt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-15")],-1),ft=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),mt=t("td",{style:{"text-align":"left"}},"Редактирование crontab текущего пользователя",-1),vt={style:{"text-align":"center"}},pt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-16")],-1),bt=t("td",{style:{"text-align":"left"}},[t("code",null,"touch")],-1),Xt=t("td",{style:{"text-align":"left"}},"Создание пустого файла",-1),Lt={style:{"text-align":"center"}},Tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-17")],-1),kt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl")],-1),wt=t("td",{style:{"text-align":"left"}},"Базовые команды управления сервисами systemd",-1),Nt={style:{"text-align":"center"}},St=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-18")],-1),At=t("td",{style:{"text-align":"left"}},[t("code",null,"reboot")],-1),Bt=t("td",{style:{"text-align":"left"}},"Перезагрузка Linux",-1),Ct={style:{"text-align":"center"}},Vt=t("h2",{id:"_2-индекс-важных-конфигурационных-фаилов-linux",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-индекс-важных-конфигурационных-фаилов-linux"},[t("span",null,"2. Индекс важных конфигурационных файлов Linux")])],-1),It=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"Номер"),t("th",{style:{"text-align":"left"}},"Расположение файла"),t("th",{style:{"text-align":"left"}},"Описание файла"),t("th",{style:{"text-align":"center"}},"Глава")])],-1),Pt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-01")],-1),Rt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/ssh/sshd_config")],-1),jt=t("td",{style:{"text-align":"left"}},"Конфигурация SSH сервера",-1),Et={style:{"text-align":"center"}},Ht=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-02")],-1),qt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/nginx/nginx.conf")],-1),zt=t("td",{style:{"text-align":"left"}},"Конфигурация Nginx",-1),Dt={style:{"text-align":"center"}},Ft=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-03")],-1),Gt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list")],-1),Jt=t("td",{style:{"text-align":"left"}},"Список репозиториев APT",-1),Kt={style:{"text-align":"center"}},Mt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-04")],-1),Ot=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list.d/vpsadmin.list")],-1),Qt=t("td",{style:{"text-align":"left"}},"Список пользовательских репозиториев APT",-1),Ut={style:{"text-align":"center"}},Wt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-05")],-1),Yt=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),Zt=t("td",{style:{"text-align":"left"}},"Crontab текущего пользователя",-1),$t={style:{"text-align":"center"}},te=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-06")],-1),ee=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.conf")],-1),le=t("td",{style:{"text-align":"left"}},"Настройки ядра Linux",-1),ne={style:{"text-align":"center"}},se=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-07")],-1),oe=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.d/vpsadmin.conf")],-1),de=t("td",{style:{"text-align":"left"}},"Пользовательские настройки ядра Linux",-1),ce={style:{"text-align":"center"}},ie=t("h2",{id:"_3-индекс-важных-фаилов-xray",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-индекс-важных-фаилов-xray"},[t("span",null,"3. Индекс важных файлов Xray")])],-1),_e=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"Номер"),t("th",{style:{"text-align":"left"}},"Расположение файла"),t("th",{style:{"text-align":"left"}},"Описание файла"),t("th",{style:{"text-align":"center"}},"Глава")])],-1),ae=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-01")],-1),re=t("td",{style:{"text-align":"left"}},[t("code",null,"/usr/local/etc/xray/config.json")],-1),he=t("td",{style:{"text-align":"left"}},"Конфигурация Xray",-1),ue={style:{"text-align":"center"}},ye=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-02")],-1),xe=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.cert")],-1),ge=t("td",{style:{"text-align":"left"}},"TLS сертификат",-1),fe={style:{"text-align":"center"}},me=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-03")],-1),ve=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.key")],-1),pe=t("td",{style:{"text-align":"left"}},"TLS ключ",-1),be={style:{"text-align":"center"}},Xe=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-04")],-1),Le=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/access.log")],-1),Te=t("td",{style:{"text-align":"left"}},"Лог доступа Xray",-1),ke={style:{"text-align":"center"}},we=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-05")],-1),Ne=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/error.log")],-1),Se=t("td",{style:{"text-align":"left"}},"Лог ошибок Xray",-1),Ae={style:{"text-align":"center"}};function Be(Ce,Ve){const d=o("I18nTip"),l=o("RouterLink");return i(),_("div",null,[e(d),r,h,t("table",null,[u,t("tbody",null,[t("tr",null,[y,x,g,t("td",f,[e(l,{to:"/ru/document/level-0/ch03-ssh.html"},{default:n(()=>[s("Глава о удаленном подключении")]),_:1})])]),t("tr",null,[m,v,p,t("td",b,[e(l,{to:"/ru/document/level-0/ch03-ssh.html"},{default:n(()=>[s("Глава о удаленном подключении")]),_:1})])]),t("tr",null,[X,L,T,t("td",k,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[w,N,S,t("td",A,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[B,C,V,t("td",I,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[P,R,j,t("td",E,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[H,q,z,t("td",D,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[F,G,J,t("td",K,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[M,O,Q,t("td",U,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[W,Y,Z,t("td",$,[e(l,{to:"/ru/document/level-0/ch05-webpage.html"},{default:n(()=>[s("Глава о создании сайта")]),_:1})])]),t("tr",null,[tt,et,lt,t("td",nt,[e(l,{to:"/ru/document/level-0/ch05-webpage.html"},{default:n(()=>[s("Глава о создании сайта")]),_:1})])]),t("tr",null,[st,ot,dt,t("td",ct,[e(l,{to:"/ru/document/level-0/ch06-certificates.html"},{default:n(()=>[s("Глава об управлении сертификатами")]),_:1})])]),t("tr",null,[it,_t,at,t("td",rt,[e(l,{to:"/ru/document/level-0/ch06-certificates.html"},{default:n(()=>[s("Глава об управлении сертификатами")]),_:1})])]),t("tr",null,[ht,ut,yt,t("td",xt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[gt,ft,mt,t("td",vt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[pt,bt,Xt,t("td",Lt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Tt,kt,wt,t("td",Nt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[St,At,Bt,t("td",Ct,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])])])]),Vt,t("table",null,[It,t("tbody",null,[t("tr",null,[Pt,Rt,jt,t("td",Et,[e(l,{to:"/ru/document/level-0/ch03-ssh.html"},{default:n(()=>[s("Глава о удаленном подключении")]),_:1})])]),t("tr",null,[Ht,qt,zt,t("td",Dt,[e(l,{to:"/ru/document/level-0/ch05-webpage.html"},{default:n(()=>[s("Глава о создании сайта")]),_:1})])]),t("tr",null,[Ft,Gt,Jt,t("td",Kt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Mt,Ot,Qt,t("td",Ut,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Wt,Yt,Zt,t("td",$t,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[te,ee,le,t("td",ne,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[se,oe,de,t("td",ce,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])])])]),ie,t("table",null,[_e,t("tbody",null,[t("tr",null,[ae,re,he,t("td",ue,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[ye,xe,ge,t("td",fe,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[me,ve,pe,t("td",be,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Xe,Le,Te,t("td",ke,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[we,Ne,Se,t("td",Ae,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])])])])])}const Pe=c(a,[["render",Be],["__file","ch09-appendix.html.vue"]]);export{Pe as default};
                                        +import{_ as c,r as o,o as i,c as _,a as e,b as t,w as n,d as s}from"./app-Bw2NG-QJ.js";const a={},r=t("h1",{id:"глава-9-приложение",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#глава-9-приложение"},[t("span",null,"[Глава 9] Приложение")])],-1),h=t("h2",{id:"_1-индекс-основных-команд-linux-для-начинающих",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_1-индекс-основных-команд-linux-для-начинающих"},[t("span",null,"1. Индекс основных команд Linux для начинающих")])],-1),u=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"Номер"),t("th",{style:{"text-align":"left"}},"Название команды"),t("th",{style:{"text-align":"left"}},"Описание команды"),t("th",{style:{"text-align":"center"}},"Глава")])],-1),y=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-01")],-1),x=t("td",{style:{"text-align":"left"}},[t("code",null,"apt update")],-1),g=t("td",{style:{"text-align":"left"}},"Обновление списка пакетов",-1),f={style:{"text-align":"center"}},m=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-02")],-1),v=t("td",{style:{"text-align":"left"}},[t("code",null,"apt upgrade")],-1),p=t("td",{style:{"text-align":"left"}},"Обновление пакетов системы",-1),b={style:{"text-align":"center"}},X=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-03")],-1),L=t("td",{style:{"text-align":"left"}},[t("code",null,"nano")],-1),T=t("td",{style:{"text-align":"left"}},"Текстовый редактор",-1),k={style:{"text-align":"center"}},w=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-04")],-1),N=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl restart")],-1),S=t("td",{style:{"text-align":"left"}},"Перезапуск сервиса",-1),A={style:{"text-align":"center"}},B=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-05")],-1),C=t("td",{style:{"text-align":"left"}},[t("code",null,"adduser")],-1),V=t("td",{style:{"text-align":"left"}},"Добавление пользователя",-1),I={style:{"text-align":"center"}},P=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-06")],-1),R=t("td",{style:{"text-align":"left"}},[t("code",null,"apt install")],-1),j=t("td",{style:{"text-align":"left"}},"Установка пакета",-1),E={style:{"text-align":"center"}},H=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-07")],-1),q=t("td",{style:{"text-align":"left"}},[t("code",null,"visudo")],-1),z=t("td",{style:{"text-align":"left"}},"Редактор для настройки sudo",-1),D={style:{"text-align":"center"}},F=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-08")],-1),G=t("td",{style:{"text-align":"left"}},[t("code",null,"sudo")],-1),J=t("td",{style:{"text-align":"left"}},"Выполнение команды от имени root",-1),K={style:{"text-align":"center"}},M=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-09")],-1),O=t("td",{style:{"text-align":"left"}},[t("code",null,"chmod")],-1),Q=t("td",{style:{"text-align":"left"}},"Изменение прав доступа к файлу/папке",-1),U={style:{"text-align":"center"}},W=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-10")],-1),Y=t("td",{style:{"text-align":"left"}},[t("code",null,"mkdir")],-1),Z=t("td",{style:{"text-align":"left"}},"Создание папки",-1),$={style:{"text-align":"center"}},tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-11")],-1),et=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl reload")],-1),lt=t("td",{style:{"text-align":"left"}},"Перезагрузка конфигурации сервиса",-1),nt={style:{"text-align":"center"}},st=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-12")],-1),ot=t("td",{style:{"text-align":"left"}},[t("code",null,"wget")],-1),dt=t("td",{style:{"text-align":"left"}},"Загрузка файла/страницы из сети",-1),ct={style:{"text-align":"center"}},it=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-13")],-1),_t=t("td",{style:{"text-align":"left"}},[t("code",null,"acme.sh")],-1),at=t("td",{style:{"text-align":"left"}},"Управление сертификатами с помощью acme.sh",-1),rt={style:{"text-align":"center"}},ht=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-14")],-1),ut=t("td",{style:{"text-align":"left"}},[t("code",null,"rm")],-1),yt=t("td",{style:{"text-align":"left"}},"Удаление файлов/папок",-1),xt={style:{"text-align":"center"}},gt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-15")],-1),ft=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),mt=t("td",{style:{"text-align":"left"}},"Редактирование crontab текущего пользователя",-1),vt={style:{"text-align":"center"}},pt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-16")],-1),bt=t("td",{style:{"text-align":"left"}},[t("code",null,"touch")],-1),Xt=t("td",{style:{"text-align":"left"}},"Создание пустого файла",-1),Lt={style:{"text-align":"center"}},Tt=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-17")],-1),kt=t("td",{style:{"text-align":"left"}},[t("code",null,"systemctl")],-1),wt=t("td",{style:{"text-align":"left"}},"Базовые команды управления сервисами systemd",-1),Nt={style:{"text-align":"center"}},St=t("td",{style:{"text-align":"center"}},[t("code",null,"cmd-18")],-1),At=t("td",{style:{"text-align":"left"}},[t("code",null,"reboot")],-1),Bt=t("td",{style:{"text-align":"left"}},"Перезагрузка Linux",-1),Ct={style:{"text-align":"center"}},Vt=t("h2",{id:"_2-индекс-важных-конфигурационных-фаилов-linux",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_2-индекс-важных-конфигурационных-фаилов-linux"},[t("span",null,"2. Индекс важных конфигурационных файлов Linux")])],-1),It=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"Номер"),t("th",{style:{"text-align":"left"}},"Расположение файла"),t("th",{style:{"text-align":"left"}},"Описание файла"),t("th",{style:{"text-align":"center"}},"Глава")])],-1),Pt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-01")],-1),Rt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/ssh/sshd_config")],-1),jt=t("td",{style:{"text-align":"left"}},"Конфигурация SSH сервера",-1),Et={style:{"text-align":"center"}},Ht=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-02")],-1),qt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/nginx/nginx.conf")],-1),zt=t("td",{style:{"text-align":"left"}},"Конфигурация Nginx",-1),Dt={style:{"text-align":"center"}},Ft=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-03")],-1),Gt=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list")],-1),Jt=t("td",{style:{"text-align":"left"}},"Список репозиториев APT",-1),Kt={style:{"text-align":"center"}},Mt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-04")],-1),Ot=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/apt/sources.list.d/vpsadmin.list")],-1),Qt=t("td",{style:{"text-align":"left"}},"Список пользовательских репозиториев APT",-1),Ut={style:{"text-align":"center"}},Wt=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-05")],-1),Yt=t("td",{style:{"text-align":"left"}},[t("code",null,"crontab -e")],-1),Zt=t("td",{style:{"text-align":"left"}},"Crontab текущего пользователя",-1),$t={style:{"text-align":"center"}},te=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-06")],-1),ee=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.conf")],-1),le=t("td",{style:{"text-align":"left"}},"Настройки ядра Linux",-1),ne={style:{"text-align":"center"}},se=t("td",{style:{"text-align":"center"}},[t("code",null,"conf-07")],-1),oe=t("td",{style:{"text-align":"left"}},[t("code",null,"/etc/sysctl.d/vpsadmin.conf")],-1),de=t("td",{style:{"text-align":"left"}},"Пользовательские настройки ядра Linux",-1),ce={style:{"text-align":"center"}},ie=t("h2",{id:"_3-индекс-важных-фаилов-xray",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#_3-индекс-важных-фаилов-xray"},[t("span",null,"3. Индекс важных файлов Xray")])],-1),_e=t("thead",null,[t("tr",null,[t("th",{style:{"text-align":"center"}},"Номер"),t("th",{style:{"text-align":"left"}},"Расположение файла"),t("th",{style:{"text-align":"left"}},"Описание файла"),t("th",{style:{"text-align":"center"}},"Глава")])],-1),ae=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-01")],-1),re=t("td",{style:{"text-align":"left"}},[t("code",null,"/usr/local/etc/xray/config.json")],-1),he=t("td",{style:{"text-align":"left"}},"Конфигурация Xray",-1),ue={style:{"text-align":"center"}},ye=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-02")],-1),xe=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.cert")],-1),ge=t("td",{style:{"text-align":"left"}},"TLS сертификат",-1),fe={style:{"text-align":"center"}},me=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-03")],-1),ve=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_cert/xray.key")],-1),pe=t("td",{style:{"text-align":"left"}},"TLS ключ",-1),be={style:{"text-align":"center"}},Xe=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-04")],-1),Le=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/access.log")],-1),Te=t("td",{style:{"text-align":"left"}},"Лог доступа Xray",-1),ke={style:{"text-align":"center"}},we=t("td",{style:{"text-align":"center"}},[t("code",null,"xray-05")],-1),Ne=t("td",{style:{"text-align":"left"}},[t("code",null,"/home/vpsadmin/xray_log/error.log")],-1),Se=t("td",{style:{"text-align":"left"}},"Лог ошибок Xray",-1),Ae={style:{"text-align":"center"}};function Be(Ce,Ve){const d=o("I18nTip"),l=o("RouterLink");return i(),_("div",null,[e(d),r,h,t("table",null,[u,t("tbody",null,[t("tr",null,[y,x,g,t("td",f,[e(l,{to:"/ru/document/level-0/ch03-ssh.html"},{default:n(()=>[s("Глава о удаленном подключении")]),_:1})])]),t("tr",null,[m,v,p,t("td",b,[e(l,{to:"/ru/document/level-0/ch03-ssh.html"},{default:n(()=>[s("Глава о удаленном подключении")]),_:1})])]),t("tr",null,[X,L,T,t("td",k,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[w,N,S,t("td",A,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[B,C,V,t("td",I,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[P,R,j,t("td",E,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[H,q,z,t("td",D,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[F,G,J,t("td",K,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[M,O,Q,t("td",U,[e(l,{to:"/ru/document/level-0/ch04-security.html"},{default:n(()=>[s("Глава о безопасности")]),_:1})])]),t("tr",null,[W,Y,Z,t("td",$,[e(l,{to:"/ru/document/level-0/ch05-webpage.html"},{default:n(()=>[s("Глава о создании сайта")]),_:1})])]),t("tr",null,[tt,et,lt,t("td",nt,[e(l,{to:"/ru/document/level-0/ch05-webpage.html"},{default:n(()=>[s("Глава о создании сайта")]),_:1})])]),t("tr",null,[st,ot,dt,t("td",ct,[e(l,{to:"/ru/document/level-0/ch06-certificates.html"},{default:n(()=>[s("Глава об управлении сертификатами")]),_:1})])]),t("tr",null,[it,_t,at,t("td",rt,[e(l,{to:"/ru/document/level-0/ch06-certificates.html"},{default:n(()=>[s("Глава об управлении сертификатами")]),_:1})])]),t("tr",null,[ht,ut,yt,t("td",xt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[gt,ft,mt,t("td",vt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[pt,bt,Xt,t("td",Lt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Tt,kt,wt,t("td",Nt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[St,At,Bt,t("td",Ct,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])])])]),Vt,t("table",null,[It,t("tbody",null,[t("tr",null,[Pt,Rt,jt,t("td",Et,[e(l,{to:"/ru/document/level-0/ch03-ssh.html"},{default:n(()=>[s("Глава о удаленном подключении")]),_:1})])]),t("tr",null,[Ht,qt,zt,t("td",Dt,[e(l,{to:"/ru/document/level-0/ch05-webpage.html"},{default:n(()=>[s("Глава о создании сайта")]),_:1})])]),t("tr",null,[Ft,Gt,Jt,t("td",Kt,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Mt,Ot,Qt,t("td",Ut,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Wt,Yt,Zt,t("td",$t,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[te,ee,le,t("td",ne,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[se,oe,de,t("td",ce,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])])])]),ie,t("table",null,[_e,t("tbody",null,[t("tr",null,[ae,re,he,t("td",ue,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[ye,xe,ge,t("td",fe,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[me,ve,pe,t("td",be,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[Xe,Le,Te,t("td",ke,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])]),t("tr",null,[we,Ne,Se,t("td",Ae,[e(l,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:n(()=>[s("Глава о Xray сервере")]),_:1})])])])])])}const Pe=c(a,[["render",Be],["__file","ch09-appendix.html.vue"]]);export{Pe as default};
                                        diff --git a/assets/channel-C_7gBDjR.js b/assets/channel-C_7gBDjR.js
                                        deleted file mode 100644
                                        index 19934a35aa..0000000000
                                        --- a/assets/channel-C_7gBDjR.js
                                        +++ /dev/null
                                        @@ -1 +0,0 @@
                                        -import{al as o,am as n}from"./mermaid.core-CArNAncI.js";const l=(a,r)=>o.lang.round(n.parse(a)[r]);export{l as c};
                                        diff --git a/assets/channel-DIeeoF-2.js b/assets/channel-DIeeoF-2.js
                                        new file mode 100644
                                        index 0000000000..3d797d04b5
                                        --- /dev/null
                                        +++ b/assets/channel-DIeeoF-2.js
                                        @@ -0,0 +1 @@
                                        +import{al as o,am as n}from"./mermaid.core-Bq0kX0MS.js";const l=(a,r)=>o.lang.round(n.parse(a)[r]);export{l as c};
                                        diff --git a/assets/classDiagram-fb54d2a0-C9zXAHzr.js b/assets/classDiagram-fb54d2a0-CnVcQW-t.js
                                        similarity index 97%
                                        rename from assets/classDiagram-fb54d2a0-C9zXAHzr.js
                                        rename to assets/classDiagram-fb54d2a0-CnVcQW-t.js
                                        index 025ec8699e..3b40a4714c 100644
                                        --- a/assets/classDiagram-fb54d2a0-C9zXAHzr.js
                                        +++ b/assets/classDiagram-fb54d2a0-CnVcQW-t.js
                                        @@ -1,2 +1,2 @@
                                        -import{p as A,d as S,s as G}from"./styles-b83b31c9-BypRRRwZ.js";import{c as v,l as y,h as B,i as W,ao as $,z as M,ar as I}from"./mermaid.core-CArNAncI.js";import{G as O}from"./graph-D2qW7eTj.js";import{l as P}from"./layout-BlaWeSu5.js";import{l as X}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";let H=0;const Y=function(i,a,t,o,p){const g=function(e){switch(e){case p.db.relationType.AGGREGATION:return"aggregation";case p.db.relationType.EXTENSION:return"extension";case p.db.relationType.COMPOSITION:return"composition";case p.db.relationType.DEPENDENCY:return"dependency";case p.db.relationType.LOLLIPOP:return"lollipop"}};a.points=a.points.filter(e=>!Number.isNaN(e.y));const s=a.points,c=X().x(function(e){return e.x}).y(function(e){return e.y}).curve($),n=i.append("path").attr("d",c(s)).attr("id","edge"+H).attr("class","relation");let r="";o.arrowMarkerAbsolute&&(r=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,r=r.replace(/\(/g,"\\("),r=r.replace(/\)/g,"\\)")),t.relation.lineType==1&&n.attr("class","relation dashed-line"),t.relation.lineType==10&&n.attr("class","relation dotted-line"),t.relation.type1!=="none"&&n.attr("marker-start","url("+r+"#"+g(t.relation.type1)+"Start)"),t.relation.type2!=="none"&&n.attr("marker-end","url("+r+"#"+g(t.relation.type2)+"End)");let f,h;const x=a.points.length;let b=M.calcLabelPosition(a.points);f=b.x,h=b.y;let u,m,w,k;if(x%2!==0&&x>1){let e=M.calcCardinalityPosition(t.relation.type1!=="none",a.points,a.points[0]),d=M.calcCardinalityPosition(t.relation.type2!=="none",a.points,a.points[x-1]);y.debug("cardinality_1_point "+JSON.stringify(e)),y.debug("cardinality_2_point "+JSON.stringify(d)),u=e.x,m=e.y,w=d.x,k=d.y}if(t.title!==void 0){const e=i.append("g").attr("class","classLabel"),d=e.append("text").attr("class","label").attr("x",f).attr("y",h).attr("fill","red").attr("text-anchor","middle").text(t.title);window.label=d;const l=d.node().getBBox();e.insert("rect",":first-child").attr("class","box").attr("x",l.x-o.padding/2).attr("y",l.y-o.padding/2).attr("width",l.width+o.padding).attr("height",l.height+o.padding)}y.info("Rendering relation "+JSON.stringify(t)),t.relationTitle1!==void 0&&t.relationTitle1!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type1").attr("x",u).attr("y",m).attr("fill","black").attr("font-size","6").text(t.relationTitle1),t.relationTitle2!==void 0&&t.relationTitle2!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type2").attr("x",w).attr("y",k).attr("fill","black").attr("font-size","6").text(t.relationTitle2),H++},J=function(i,a,t,o){y.debug("Rendering class ",a,t);const p=a.id,g={id:p,label:a.id,width:0,height:0},s=i.append("g").attr("id",o.db.lookUpDomId(p)).attr("class","classGroup");let c;a.link?c=s.append("svg:a").attr("xlink:href",a.link).attr("target",a.linkTarget).append("text").attr("y",t.textHeight+t.padding).attr("x",0):c=s.append("text").attr("y",t.textHeight+t.padding).attr("x",0);let n=!0;a.annotations.forEach(function(d){const l=c.append("tspan").text("«"+d+"»");n||l.attr("dy",t.textHeight),n=!1});let r=C(a);const f=c.append("tspan").text(r).attr("class","title");n||f.attr("dy",t.textHeight);const h=c.node().getBBox().height;let x,b,u;if(a.members.length>0){x=s.append("line").attr("x1",0).attr("y1",t.padding+h+t.dividerMargin/2).attr("y2",t.padding+h+t.dividerMargin/2);const d=s.append("text").attr("x",t.padding).attr("y",h+t.dividerMargin+t.textHeight).attr("fill","white").attr("class","classText");n=!0,a.members.forEach(function(l){_(d,l,n,t),n=!1}),b=d.node().getBBox()}if(a.methods.length>0){u=s.append("line").attr("x1",0).attr("y1",t.padding+h+t.dividerMargin+b.height).attr("y2",t.padding+h+t.dividerMargin+b.height);const d=s.append("text").attr("x",t.padding).attr("y",h+2*t.dividerMargin+b.height+t.textHeight).attr("fill","white").attr("class","classText");n=!0,a.methods.forEach(function(l){_(d,l,n,t),n=!1})}const m=s.node().getBBox();var w=" ";a.cssClasses.length>0&&(w=w+a.cssClasses.join(" "));const e=s.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",m.width+2*t.padding).attr("height",m.height+t.padding+.5*t.dividerMargin).attr("class",w).node().getBBox().width;return c.node().childNodes.forEach(function(d){d.setAttribute("x",(e-d.getBBox().width)/2)}),a.tooltip&&c.insert("title").text(a.tooltip),x&&x.attr("x2",e),u&&u.attr("x2",e),g.width=e,g.height=m.height+t.padding+.5*t.dividerMargin,g},C=function(i){let a=i.id;return i.type&&(a+="<"+I(i.type)+">"),a},Z=function(i,a,t,o){y.debug("Rendering note ",a,t);const p=a.id,g={id:p,text:a.text,width:0,height:0},s=i.append("g").attr("id",p).attr("class","classGroup");let c=s.append("text").attr("y",t.textHeight+t.padding).attr("x",0);const n=JSON.parse(`"${a.text}"`).split(`
                                        +import{p as A,d as S,s as G}from"./styles-b83b31c9-BItTogIC.js";import{c as v,l as y,h as B,i as W,ao as $,z as M,ar as I}from"./mermaid.core-Bq0kX0MS.js";import{G as O}from"./graph-C-EgwjAv.js";import{l as P}from"./layout-DSxgfneE.js";import{l as X}from"./line-DY_oMjHu.js";import"./app-Bw2NG-QJ.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";let H=0;const Y=function(i,a,t,o,p){const g=function(e){switch(e){case p.db.relationType.AGGREGATION:return"aggregation";case p.db.relationType.EXTENSION:return"extension";case p.db.relationType.COMPOSITION:return"composition";case p.db.relationType.DEPENDENCY:return"dependency";case p.db.relationType.LOLLIPOP:return"lollipop"}};a.points=a.points.filter(e=>!Number.isNaN(e.y));const s=a.points,c=X().x(function(e){return e.x}).y(function(e){return e.y}).curve($),n=i.append("path").attr("d",c(s)).attr("id","edge"+H).attr("class","relation");let r="";o.arrowMarkerAbsolute&&(r=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,r=r.replace(/\(/g,"\\("),r=r.replace(/\)/g,"\\)")),t.relation.lineType==1&&n.attr("class","relation dashed-line"),t.relation.lineType==10&&n.attr("class","relation dotted-line"),t.relation.type1!=="none"&&n.attr("marker-start","url("+r+"#"+g(t.relation.type1)+"Start)"),t.relation.type2!=="none"&&n.attr("marker-end","url("+r+"#"+g(t.relation.type2)+"End)");let f,h;const x=a.points.length;let b=M.calcLabelPosition(a.points);f=b.x,h=b.y;let u,m,w,k;if(x%2!==0&&x>1){let e=M.calcCardinalityPosition(t.relation.type1!=="none",a.points,a.points[0]),d=M.calcCardinalityPosition(t.relation.type2!=="none",a.points,a.points[x-1]);y.debug("cardinality_1_point "+JSON.stringify(e)),y.debug("cardinality_2_point "+JSON.stringify(d)),u=e.x,m=e.y,w=d.x,k=d.y}if(t.title!==void 0){const e=i.append("g").attr("class","classLabel"),d=e.append("text").attr("class","label").attr("x",f).attr("y",h).attr("fill","red").attr("text-anchor","middle").text(t.title);window.label=d;const l=d.node().getBBox();e.insert("rect",":first-child").attr("class","box").attr("x",l.x-o.padding/2).attr("y",l.y-o.padding/2).attr("width",l.width+o.padding).attr("height",l.height+o.padding)}y.info("Rendering relation "+JSON.stringify(t)),t.relationTitle1!==void 0&&t.relationTitle1!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type1").attr("x",u).attr("y",m).attr("fill","black").attr("font-size","6").text(t.relationTitle1),t.relationTitle2!==void 0&&t.relationTitle2!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type2").attr("x",w).attr("y",k).attr("fill","black").attr("font-size","6").text(t.relationTitle2),H++},J=function(i,a,t,o){y.debug("Rendering class ",a,t);const p=a.id,g={id:p,label:a.id,width:0,height:0},s=i.append("g").attr("id",o.db.lookUpDomId(p)).attr("class","classGroup");let c;a.link?c=s.append("svg:a").attr("xlink:href",a.link).attr("target",a.linkTarget).append("text").attr("y",t.textHeight+t.padding).attr("x",0):c=s.append("text").attr("y",t.textHeight+t.padding).attr("x",0);let n=!0;a.annotations.forEach(function(d){const l=c.append("tspan").text("«"+d+"»");n||l.attr("dy",t.textHeight),n=!1});let r=C(a);const f=c.append("tspan").text(r).attr("class","title");n||f.attr("dy",t.textHeight);const h=c.node().getBBox().height;let x,b,u;if(a.members.length>0){x=s.append("line").attr("x1",0).attr("y1",t.padding+h+t.dividerMargin/2).attr("y2",t.padding+h+t.dividerMargin/2);const d=s.append("text").attr("x",t.padding).attr("y",h+t.dividerMargin+t.textHeight).attr("fill","white").attr("class","classText");n=!0,a.members.forEach(function(l){_(d,l,n,t),n=!1}),b=d.node().getBBox()}if(a.methods.length>0){u=s.append("line").attr("x1",0).attr("y1",t.padding+h+t.dividerMargin+b.height).attr("y2",t.padding+h+t.dividerMargin+b.height);const d=s.append("text").attr("x",t.padding).attr("y",h+2*t.dividerMargin+b.height+t.textHeight).attr("fill","white").attr("class","classText");n=!0,a.methods.forEach(function(l){_(d,l,n,t),n=!1})}const m=s.node().getBBox();var w=" ";a.cssClasses.length>0&&(w=w+a.cssClasses.join(" "));const e=s.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",m.width+2*t.padding).attr("height",m.height+t.padding+.5*t.dividerMargin).attr("class",w).node().getBBox().width;return c.node().childNodes.forEach(function(d){d.setAttribute("x",(e-d.getBBox().width)/2)}),a.tooltip&&c.insert("title").text(a.tooltip),x&&x.attr("x2",e),u&&u.attr("x2",e),g.width=e,g.height=m.height+t.padding+.5*t.dividerMargin,g},C=function(i){let a=i.id;return i.type&&(a+="<"+I(i.type)+">"),a},Z=function(i,a,t,o){y.debug("Rendering note ",a,t);const p=a.id,g={id:p,text:a.text,width:0,height:0},s=i.append("g").attr("id",p).attr("class","classGroup");let c=s.append("text").attr("y",t.textHeight+t.padding).attr("x",0);const n=JSON.parse(`"${a.text}"`).split(`
                                         `);n.forEach(function(x){y.debug(`Adding line: ${x}`),c.append("tspan").text(x).attr("class","title").attr("dy",t.textHeight)});const r=s.node().getBBox(),h=s.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",r.width+2*t.padding).attr("height",r.height+n.length*t.textHeight+t.padding+.5*t.dividerMargin).node().getBBox().width;return c.node().childNodes.forEach(function(x){x.setAttribute("x",(h-x.getBBox().width)/2)}),g.width=h,g.height=r.height+n.length*t.textHeight+t.padding+.5*t.dividerMargin,g},_=function(i,a,t,o){const{displayText:p,cssStyle:g}=a.getDisplayDetails(),s=i.append("tspan").attr("x",o.padding).text(p);g!==""&&s.attr("style",a.cssStyle),t||s.attr("dy",o.textHeight)},N={getClassTitleString:C,drawClass:J,drawEdge:Y,drawNote:Z};let T={};const E=20,L=function(i){const a=Object.entries(T).find(t=>t[1].label===i);if(a)return a[0]},R=function(i){i.append("defs").append("marker").attr("id","extensionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),i.append("defs").append("marker").attr("id","extensionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z"),i.append("defs").append("marker").attr("id","compositionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","compositionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","aggregationStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","aggregationEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","dependencyStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},z=function(i,a,t,o){const p=v().class;T={},y.info("Rendering diagram "+i);const g=v().securityLevel;let s;g==="sandbox"&&(s=B("#i"+a));const c=g==="sandbox"?B(s.nodes()[0].contentDocument.body):B("body"),n=c.select(`[id='${a}']`);R(n);const r=new O({multigraph:!0});r.setGraph({isMultiGraph:!0}),r.setDefaultEdgeLabel(function(){return{}});const f=o.db.getClasses(),h=Object.keys(f);for(const e of h){const d=f[e],l=N.drawClass(n,d,p,o);T[l.id]=l,r.setNode(l.id,l),y.info("Org height: "+l.height)}o.db.getRelations().forEach(function(e){y.info("tjoho"+L(e.id1)+L(e.id2)+JSON.stringify(e)),r.setEdge(L(e.id1),L(e.id2),{relation:e},e.title||"DEFAULT")}),o.db.getNotes().forEach(function(e){y.debug(`Adding note: ${JSON.stringify(e)}`);const d=N.drawNote(n,e,p,o);T[d.id]=d,r.setNode(d.id,d),e.class&&e.class in f&&r.setEdge(e.id,L(e.class),{relation:{id1:e.id,id2:e.class,relation:{type1:"none",type2:"none",lineType:10}}},"DEFAULT")}),P(r),r.nodes().forEach(function(e){e!==void 0&&r.node(e)!==void 0&&(y.debug("Node "+e+": "+JSON.stringify(r.node(e))),c.select("#"+(o.db.lookUpDomId(e)||e)).attr("transform","translate("+(r.node(e).x-r.node(e).width/2)+","+(r.node(e).y-r.node(e).height/2)+" )"))}),r.edges().forEach(function(e){e!==void 0&&r.edge(e)!==void 0&&(y.debug("Edge "+e.v+" -> "+e.w+": "+JSON.stringify(r.edge(e))),N.drawEdge(n,r.edge(e),r.edge(e).relation,p,o))});const u=n.node().getBBox(),m=u.width+E*2,w=u.height+E*2;W(n,w,m,p.useMaxWidth);const k=`${u.x-E} ${u.y-E} ${m} ${w}`;y.debug(`viewBox ${k}`),n.attr("viewBox",k)},F={draw:z},et={parser:A,db:S,renderer:F,styles:G,init:i=>{i.class||(i.class={}),i.class.arrowMarkerAbsolute=i.arrowMarkerAbsolute,S.clear()}};export{et as diagram};
                                        diff --git a/assets/classDiagram-v2-a2b738ad-ChHu4we1.js b/assets/classDiagram-v2-a2b738ad-D4iAgbOW.js
                                        similarity index 92%
                                        rename from assets/classDiagram-v2-a2b738ad-ChHu4we1.js
                                        rename to assets/classDiagram-v2-a2b738ad-D4iAgbOW.js
                                        index 2f942cb560..9a3ebc7c9a 100644
                                        --- a/assets/classDiagram-v2-a2b738ad-ChHu4we1.js
                                        +++ b/assets/classDiagram-v2-a2b738ad-D4iAgbOW.js
                                        @@ -1,2 +1,2 @@
                                        -import{p as M,d as _,s as R}from"./styles-b83b31c9-BypRRRwZ.js";import{l as d,c,h as w,z as B,u as G,p as D,t as E,o as C,j as A}from"./mermaid.core-CArNAncI.js";import{G as z}from"./graph-D2qW7eTj.js";import{r as P}from"./index-01f381cb-fgk8rzsW.js";import"./layout-BlaWeSu5.js";import"./app-5SoadDYS.js";import"./clone-D0wOyyCk.js";import"./edges-066a5561-BnmFWp88.js";import"./createText-ca0c5216-X7RVUogw.js";import"./line-BIqtvXUi.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const S=s=>A.sanitizeText(s,c());let k={dividerMargin:10,padding:5,textHeight:10,curve:void 0};const q=function(s,t,y,a){const e=Object.keys(s);d.info("keys:",e),d.info(s),e.forEach(function(i){var o,r;const l=s[i],p={shape:"rect",id:l.id,domId:l.domId,labelText:S(l.id),labelStyle:"",style:"fill: none; stroke: black",padding:((o=c().flowchart)==null?void 0:o.padding)??((r=c().class)==null?void 0:r.padding)};t.setNode(l.id,p),$(l.classes,t,y,a,l.id),d.info("setNode",p)})},$=function(s,t,y,a,e){const i=Object.keys(s);d.info("keys:",i),d.info(s),i.filter(o=>s[o].parent==e).forEach(function(o){var r,l;const n=s[o],p=n.cssClasses.join(" "),f=D(n.styles),h=n.label??n.id,u=0,b={labelStyle:f.labelStyle,shape:"class_box",labelText:S(h),classData:n,rx:u,ry:u,class:p,style:f.style,id:n.id,domId:n.domId,tooltip:a.db.getTooltip(n.id,e)||"",haveCallback:n.haveCallback,link:n.link,width:n.type==="group"?500:void 0,type:n.type,padding:((r=c().flowchart)==null?void 0:r.padding)??((l=c().class)==null?void 0:l.padding)};t.setNode(n.id,b),e&&t.setParent(n.id,e),d.info("setNode",b)})},F=function(s,t,y,a){d.info(s),s.forEach(function(e,i){var o,r;const l=e,n="",p={labelStyle:"",style:""},f=l.text,h=0,m={labelStyle:p.labelStyle,shape:"note",labelText:S(f),noteData:l,rx:h,ry:h,class:n,style:p.style,id:l.id,domId:l.id,tooltip:"",type:"note",padding:((o=c().flowchart)==null?void 0:o.padding)??((r=c().class)==null?void 0:r.padding)};if(t.setNode(l.id,m),d.info("setNode",m),!l.class||!(l.class in a))return;const b=y+i,x={id:`edgeNote${b}`,classes:"relation",pattern:"dotted",arrowhead:"none",startLabelRight:"",endLabelLeft:"",arrowTypeStart:"none",arrowTypeEnd:"none",style:"fill:none",labelStyle:"",curve:E(k.curve,C)};t.setEdge(l.id,l.class,x,b)})},H=function(s,t){const y=c().flowchart;let a=0;s.forEach(function(e){var i;a++;const o={classes:"relation",pattern:e.relation.lineType==1?"dashed":"solid",id:`id_${e.id1}_${e.id2}_${a}`,arrowhead:e.type==="arrow_open"?"none":"normal",startLabelRight:e.relationTitle1==="none"?"":e.relationTitle1,endLabelLeft:e.relationTitle2==="none"?"":e.relationTitle2,arrowTypeStart:N(e.relation.type1),arrowTypeEnd:N(e.relation.type2),style:"fill:none",labelStyle:"",curve:E(y==null?void 0:y.curve,C)};if(d.info(o,e),e.style!==void 0){const r=D(e.style);o.style=r.style,o.labelStyle=r.labelStyle}e.text=e.title,e.text===void 0?e.style!==void 0&&(o.arrowheadStyle="fill: #333"):(o.arrowheadStyle="fill: #333",o.labelpos="c",((i=c().flowchart)==null?void 0:i.htmlLabels)??c().htmlLabels?(o.labelType="html",o.label=''+e.text+""):(o.labelType="text",o.label=e.text.replace(A.lineBreakRegex,`
                                        +import{p as M,d as _,s as R}from"./styles-b83b31c9-BItTogIC.js";import{l as d,c,h as w,z as B,u as G,p as D,t as E,o as C,j as A}from"./mermaid.core-Bq0kX0MS.js";import{G as z}from"./graph-C-EgwjAv.js";import{r as P}from"./index-01f381cb-DWGV-_zg.js";import"./layout-DSxgfneE.js";import"./app-Bw2NG-QJ.js";import"./clone-BjoOJyl6.js";import"./edges-066a5561-CIBMFaLO.js";import"./createText-ca0c5216-xyt9uAlz.js";import"./line-DY_oMjHu.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const S=s=>A.sanitizeText(s,c());let k={dividerMargin:10,padding:5,textHeight:10,curve:void 0};const q=function(s,t,y,a){const e=Object.keys(s);d.info("keys:",e),d.info(s),e.forEach(function(i){var o,r;const l=s[i],p={shape:"rect",id:l.id,domId:l.domId,labelText:S(l.id),labelStyle:"",style:"fill: none; stroke: black",padding:((o=c().flowchart)==null?void 0:o.padding)??((r=c().class)==null?void 0:r.padding)};t.setNode(l.id,p),$(l.classes,t,y,a,l.id),d.info("setNode",p)})},$=function(s,t,y,a,e){const i=Object.keys(s);d.info("keys:",i),d.info(s),i.filter(o=>s[o].parent==e).forEach(function(o){var r,l;const n=s[o],p=n.cssClasses.join(" "),f=D(n.styles),h=n.label??n.id,u=0,b={labelStyle:f.labelStyle,shape:"class_box",labelText:S(h),classData:n,rx:u,ry:u,class:p,style:f.style,id:n.id,domId:n.domId,tooltip:a.db.getTooltip(n.id,e)||"",haveCallback:n.haveCallback,link:n.link,width:n.type==="group"?500:void 0,type:n.type,padding:((r=c().flowchart)==null?void 0:r.padding)??((l=c().class)==null?void 0:l.padding)};t.setNode(n.id,b),e&&t.setParent(n.id,e),d.info("setNode",b)})},F=function(s,t,y,a){d.info(s),s.forEach(function(e,i){var o,r;const l=e,n="",p={labelStyle:"",style:""},f=l.text,h=0,m={labelStyle:p.labelStyle,shape:"note",labelText:S(f),noteData:l,rx:h,ry:h,class:n,style:p.style,id:l.id,domId:l.id,tooltip:"",type:"note",padding:((o=c().flowchart)==null?void 0:o.padding)??((r=c().class)==null?void 0:r.padding)};if(t.setNode(l.id,m),d.info("setNode",m),!l.class||!(l.class in a))return;const b=y+i,x={id:`edgeNote${b}`,classes:"relation",pattern:"dotted",arrowhead:"none",startLabelRight:"",endLabelLeft:"",arrowTypeStart:"none",arrowTypeEnd:"none",style:"fill:none",labelStyle:"",curve:E(k.curve,C)};t.setEdge(l.id,l.class,x,b)})},H=function(s,t){const y=c().flowchart;let a=0;s.forEach(function(e){var i;a++;const o={classes:"relation",pattern:e.relation.lineType==1?"dashed":"solid",id:`id_${e.id1}_${e.id2}_${a}`,arrowhead:e.type==="arrow_open"?"none":"normal",startLabelRight:e.relationTitle1==="none"?"":e.relationTitle1,endLabelLeft:e.relationTitle2==="none"?"":e.relationTitle2,arrowTypeStart:N(e.relation.type1),arrowTypeEnd:N(e.relation.type2),style:"fill:none",labelStyle:"",curve:E(y==null?void 0:y.curve,C)};if(d.info(o,e),e.style!==void 0){const r=D(e.style);o.style=r.style,o.labelStyle=r.labelStyle}e.text=e.title,e.text===void 0?e.style!==void 0&&(o.arrowheadStyle="fill: #333"):(o.arrowheadStyle="fill: #333",o.labelpos="c",((i=c().flowchart)==null?void 0:i.htmlLabels)??c().htmlLabels?(o.labelType="html",o.label=''+e.text+""):(o.labelType="text",o.label=e.text.replace(A.lineBreakRegex,`
                                         `),e.style===void 0&&(o.style=o.style||"stroke: #333; stroke-width: 1.5px;fill:none"),o.labelStyle=o.labelStyle.replace("color:","fill:"))),t.setEdge(e.id1,e.id2,o,a)})},V=function(s){k={...k,...s}},W=async function(s,t,y,a){d.info("Drawing class - ",t);const e=c().flowchart??c().class,i=c().securityLevel;d.info("config:",e);const o=(e==null?void 0:e.nodeSpacing)??50,r=(e==null?void 0:e.rankSpacing)??50,l=new z({multigraph:!0,compound:!0}).setGraph({rankdir:a.db.getDirection(),nodesep:o,ranksep:r,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}}),n=a.db.getNamespaces(),p=a.db.getClasses(),f=a.db.getRelations(),h=a.db.getNotes();d.info(f),q(n,l,t,a),$(p,l,t,a),H(f,l),F(h,l,f.length+1,p);let u;i==="sandbox"&&(u=w("#i"+t));const m=i==="sandbox"?w(u.nodes()[0].contentDocument.body):w("body"),b=m.select(`[id="${t}"]`),x=m.select("#"+t+" g");if(await P(x,l,["aggregation","extension","composition","dependency","lollipop"],"classDiagram",t),B.insertTitle(b,"classTitleText",(e==null?void 0:e.titleTopMargin)??5,a.db.getDiagramTitle()),G(l,b,e==null?void 0:e.diagramPadding,e==null?void 0:e.useMaxWidth),!(e!=null&&e.htmlLabels)){const T=i==="sandbox"?u.nodes()[0].contentDocument:document,I=T.querySelectorAll('[id="'+t+'"] .edgeLabel .label');for(const g of I){const L=g.getBBox(),v=T.createElementNS("http://www.w3.org/2000/svg","rect");v.setAttribute("rx",0),v.setAttribute("ry",0),v.setAttribute("width",L.width),v.setAttribute("height",L.height),g.insertBefore(v,g.firstChild)}}};function N(s){let t;switch(s){case 0:t="aggregation";break;case 1:t="extension";break;case 2:t="composition";break;case 3:t="dependency";break;case 4:t="lollipop";break;default:t="none"}return t}const J={setConf:V,draw:W},se={parser:M,db:_,renderer:J,styles:R,init:s=>{s.class||(s.class={}),s.class.arrowMarkerAbsolute=s.arrowMarkerAbsolute,_.clear()}};export{se as diagram};
                                        diff --git a/assets/clone-BjoOJyl6.js b/assets/clone-BjoOJyl6.js
                                        new file mode 100644
                                        index 0000000000..22253ecb36
                                        --- /dev/null
                                        +++ b/assets/clone-BjoOJyl6.js
                                        @@ -0,0 +1 @@
                                        +import{a as r}from"./graph-C-EgwjAv.js";var a=4;function n(o){return r(o,a)}export{n as c};
                                        diff --git a/assets/clone-D0wOyyCk.js b/assets/clone-D0wOyyCk.js
                                        deleted file mode 100644
                                        index f8fa04dbc4..0000000000
                                        --- a/assets/clone-D0wOyyCk.js
                                        +++ /dev/null
                                        @@ -1 +0,0 @@
                                        -import{a as r}from"./graph-D2qW7eTj.js";var a=4;function n(o){return r(o,a)}export{n as c};
                                        diff --git a/assets/command.html-Bto6ikLY.js b/assets/command.html-C5O9QrFP.js
                                        similarity index 99%
                                        rename from assets/command.html-Bto6ikLY.js
                                        rename to assets/command.html-C5O9QrFP.js
                                        index 232d174246..831d04ead2 100644
                                        --- a/assets/command.html-Bto6ikLY.js
                                        +++ b/assets/command.html-C5O9QrFP.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as d,r as n,o as r,c as l,a as i,b as e,d as a,w as c,e as o}from"./app-5SoadDYS.js";const u={},v=o(`

                                        Командные аргументы

                                        Подсказка

                                        Xray использует команды и аргументы в стиле Go.

                                        Базовые команды

                                        Вы можете запустить xray help, чтобы получить список всех базовых команд Xray, а также их описание и примеры использования.

                                        Xray is a platform for building proxies.
                                        +import{_ as d,r as n,o as r,c as l,a as i,b as e,d as a,w as c,e as o}from"./app-Bw2NG-QJ.js";const u={},v=o(`

                                        Командные аргументы

                                        Подсказка

                                        Xray использует команды и аргументы в стиле Go.

                                        Базовые команды

                                        Вы можете запустить xray help, чтобы получить список всех базовых команд Xray, а также их описание и примеры использования.

                                        Xray is a platform for building proxies.
                                         
                                         Usage:
                                         
                                        diff --git a/assets/command.html-D8s_eq69.js b/assets/command.html-DiZIQO57.js
                                        similarity index 99%
                                        rename from assets/command.html-D8s_eq69.js
                                        rename to assets/command.html-DiZIQO57.js
                                        index 65202df052..e1f1556d48 100644
                                        --- a/assets/command.html-D8s_eq69.js
                                        +++ b/assets/command.html-DiZIQO57.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as d,r as n,o as r,c as l,a as i,b as e,d as a,w as c,e as o}from"./app-5SoadDYS.js";const u={},v=o(`

                                        Command Parameters

                                        Tip

                                        Xray uses Go-style commands and parameters

                                        Get Basic Commands

                                        You can run xray helpto get the most basic usage of all xray, as well as available commands and instructions.

                                        Xray is a platform for building proxies.
                                        +import{_ as d,r as n,o as r,c as l,a as i,b as e,d as a,w as c,e as o}from"./app-Bw2NG-QJ.js";const u={},v=o(`

                                        Command Parameters

                                        Tip

                                        Xray uses Go-style commands and parameters

                                        Get Basic Commands

                                        You can run xray helpto get the most basic usage of all xray, as well as available commands and instructions.

                                        Xray is a platform for building proxies.
                                         
                                         Usage:
                                         
                                        diff --git a/assets/command.html-BIuE6LDM.js b/assets/command.html-wqNPUGxk.js
                                        similarity index 99%
                                        rename from assets/command.html-BIuE6LDM.js
                                        rename to assets/command.html-wqNPUGxk.js
                                        index 7127bfe6d8..52a53a5260 100644
                                        --- a/assets/command.html-BIuE6LDM.js
                                        +++ b/assets/command.html-wqNPUGxk.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as d,r as a,o as l,c as r,a as s,b as e,w as c,d as n,e as o}from"./app-5SoadDYS.js";const v={},u=o(`

                                        命令参数

                                        提示

                                        Xray 使用 Go 风格的命令及参数

                                        获取基本命令

                                        您可以运行 xray help 来获得所有 xray 最基础的用法, 以及可用的命令及说明。

                                        Xray is a platform for building proxies.
                                        +import{_ as d,r as a,o as l,c as r,a as s,b as e,w as c,d as n,e as o}from"./app-Bw2NG-QJ.js";const v={},u=o(`

                                        命令参数

                                        提示

                                        Xray 使用 Go 风格的命令及参数

                                        获取基本命令

                                        您可以运行 xray help 来获得所有 xray 最基础的用法, 以及可用的命令及说明。

                                        Xray is a platform for building proxies.
                                         
                                         Usage:
                                         
                                        diff --git a/assets/compile.html-BcVx6NTs.js b/assets/compile.html-Bm6vm5gG.js
                                        similarity index 99%
                                        rename from assets/compile.html-BcVx6NTs.js
                                        rename to assets/compile.html-Bm6vm5gG.js
                                        index bffe7ebb98..9d53f2cca4 100644
                                        --- a/assets/compile.html-BcVx6NTs.js
                                        +++ b/assets/compile.html-Bm6vm5gG.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as t,r as o,o as i,c as r,a as e,b as a,d as s,e as c}from"./app-5SoadDYS.js";const p={},d=a("h1",{id:"编译文档",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#编译文档"},[a("span",null,"编译文档")])],-1),u=a("h2",{id:"前序工作",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#前序工作"},[a("span",null,"前序工作")])],-1),h={href:"https://golang.org/",target:"_blank",rel:"noopener noreferrer"},v={class:"custom-container tip"},m=a("p",{class:"custom-container-title"},"TIP",-1),b={href:"https://golang.org/doc/install",target:"_blank",rel:"noopener noreferrer"},g=c(`

                                        如果你不幸使用 Windows, 请 务必 使用 Powershell

                                        拉取 Xray 源代码

                                        git clone https://github.com/XTLS/Xray-core.git
                                        +import{_ as t,r as o,o as i,c as r,a as e,b as a,d as s,e as c}from"./app-Bw2NG-QJ.js";const p={},d=a("h1",{id:"编译文档",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#编译文档"},[a("span",null,"编译文档")])],-1),u=a("h2",{id:"前序工作",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#前序工作"},[a("span",null,"前序工作")])],-1),h={href:"https://golang.org/",target:"_blank",rel:"noopener noreferrer"},v={class:"custom-container tip"},m=a("p",{class:"custom-container-title"},"TIP",-1),b={href:"https://golang.org/doc/install",target:"_blank",rel:"noopener noreferrer"},g=c(`

                                        如果你不幸使用 Windows, 请 务必 使用 Powershell

                                        拉取 Xray 源代码

                                        git clone https://github.com/XTLS/Xray-core.git
                                         cd Xray-core && go mod download
                                         

                                        如果你闲的没事干,可以试试 GitHub 官方工具: gh repo clone XTLS/Xray-core

                                        注意:在无法正常访问 Google 的网络环境,依赖无法被正常拉取,需要先设置 GOPROXY

                                        go env -w GOPROXY=https://goproxy.io,direct
                                         

                                        构建二进制

                                        注意

                                        本小节的命令需要在 Xray 根目录内运行。

                                        Windows(Powershell):

                                        $env:CGO_ENABLED=0
                                        diff --git a/assets/compile.html-BmYWzF7l.js b/assets/compile.html-Csfc2z7k.js
                                        similarity index 99%
                                        rename from assets/compile.html-BmYWzF7l.js
                                        rename to assets/compile.html-Csfc2z7k.js
                                        index 537f706103..c1987a155a 100644
                                        --- a/assets/compile.html-BmYWzF7l.js
                                        +++ b/assets/compile.html-Csfc2z7k.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as o,o as l,c as r,a as s,b as e,d as a,e as c}from"./app-5SoadDYS.js";const d={},p=e("h1",{id:"compile-the-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#compile-the-document"},[e("span",null,"Compile the document")])],-1),u=e("h2",{id:"preparatory-work",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#preparatory-work"},[e("span",null,"Preparatory Work")])],-1),h={href:"https://golang.org/",target:"_blank",rel:"noopener noreferrer"},m={class:"custom-container tip"},g=e("p",{class:"custom-container-title"},"TIP",-1),b={href:"https://golang.org/doc/install",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        If you happen to use Windows, please make sure to use Powershell.

                                        Pull Xray source code

                                        git clone https://github.com/XTLS/Xray-core.git
                                        +import{_ as i,r as o,o as l,c as r,a as s,b as e,d as a,e as c}from"./app-Bw2NG-QJ.js";const d={},p=e("h1",{id:"compile-the-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#compile-the-document"},[e("span",null,"Compile the document")])],-1),u=e("h2",{id:"preparatory-work",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#preparatory-work"},[e("span",null,"Preparatory Work")])],-1),h={href:"https://golang.org/",target:"_blank",rel:"noopener noreferrer"},m={class:"custom-container tip"},g=e("p",{class:"custom-container-title"},"TIP",-1),b={href:"https://golang.org/doc/install",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        If you happen to use Windows, please make sure to use Powershell.

                                        Pull Xray source code

                                        git clone https://github.com/XTLS/Xray-core.git
                                         cd Xray-core && go mod download
                                         

                                        If you have free time, you can try GitHub's official tool: gh repo clone XTLS/Xray-core

                                        Note: In a network environment where Google cannot be accessed normally, dependencies cannot be pulled normally, and GOPROXY needs to be set first:

                                        go env -w GOPROXY=https://goproxy.io,direct
                                         

                                        Build Binary

                                        Warning

                                        This command needs to be executed within Xray root directory.

                                        Windows(Powershell):

                                        $env:CGO_ENABLED=0
                                        diff --git a/assets/compile.html-C3Y8utqQ.js b/assets/compile.html-D0_Ut9wS.js
                                        similarity index 99%
                                        rename from assets/compile.html-C3Y8utqQ.js
                                        rename to assets/compile.html-D0_Ut9wS.js
                                        index 65a4da443d..c6f8f56a27 100644
                                        --- a/assets/compile.html-C3Y8utqQ.js
                                        +++ b/assets/compile.html-D0_Ut9wS.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as t,r as o,o as i,c as r,a as e,b as a,d as s,e as c}from"./app-5SoadDYS.js";const p={},d=a("h1",{id:"编译文档",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#编译文档"},[a("span",null,"编译文档")])],-1),u=a("h2",{id:"前序工作",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#前序工作"},[a("span",null,"前序工作")])],-1),h={href:"https://golang.org/",target:"_blank",rel:"noopener noreferrer"},v={class:"custom-container tip"},m=a("p",{class:"custom-container-title"},"TIP",-1),b={href:"https://golang.org/doc/install",target:"_blank",rel:"noopener noreferrer"},g=c(`

                                        如果你不幸使用 Windows, 请 务必 使用 Powershell

                                        拉取 Xray 源代码

                                        git clone https://github.com/XTLS/Xray-core.git
                                        +import{_ as t,r as o,o as i,c as r,a as e,b as a,d as s,e as c}from"./app-Bw2NG-QJ.js";const p={},d=a("h1",{id:"编译文档",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#编译文档"},[a("span",null,"编译文档")])],-1),u=a("h2",{id:"前序工作",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#前序工作"},[a("span",null,"前序工作")])],-1),h={href:"https://golang.org/",target:"_blank",rel:"noopener noreferrer"},v={class:"custom-container tip"},m=a("p",{class:"custom-container-title"},"TIP",-1),b={href:"https://golang.org/doc/install",target:"_blank",rel:"noopener noreferrer"},g=c(`

                                        如果你不幸使用 Windows, 请 务必 使用 Powershell

                                        拉取 Xray 源代码

                                        git clone https://github.com/XTLS/Xray-core.git
                                         cd Xray-core && go mod download
                                         

                                        如果你闲的没事干,可以试试 GitHub 官方工具: gh repo clone XTLS/Xray-core

                                        注意:在无法正常访问 Google 的网络环境,依赖无法被正常拉取,需要先设置 GOPROXY

                                        go env -w GOPROXY=https://goproxy.io,direct
                                         

                                        构建二进制

                                        Внимание

                                        本小节的命令需要在 Xray 根目录内运行。

                                        Windows(Powershell):

                                        $env:CGO_ENABLED=0
                                        diff --git a/assets/config.html-BRKvbU_c.js b/assets/config.html-B_bOsf-2.js
                                        similarity index 99%
                                        rename from assets/config.html-BRKvbU_c.js
                                        rename to assets/config.html-B_bOsf-2.js
                                        index e43ff84f2f..5dc9e82760 100644
                                        --- a/assets/config.html-BRKvbU_c.js
                                        +++ b/assets/config.html-B_bOsf-2.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as o,o as l,c as u,a,b as s,d as n,w as e,e as r}from"./app-5SoadDYS.js";const d={},k=s("h1",{id:"配置运行",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#配置运行"},[s("span",null,"配置运行")])],-1),v=s("p",null,[s("a",{href:"./install"},"下载并安装"),n(" 了 Xray 之后,您需要对它进行一下配置。")],-1),m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b=r(`

                                        警告

                                        为了避免你的流量被解密,
                                        你应该使用 xray uuiduuidgen 生成一个独一无二的uuid
                                        在服务端上,放入 inbounds[0].settings.clients[0].id
                                        在客户端内,放入 outbounds[0].settings.vnext[0].users[0].id

                                        服务端配置

                                        你需要一台防火墙外的服务器,来运行服务器端的 Xray。配置如下:

                                        {
                                        +import{_ as i,r as o,o as l,c as u,a,b as s,d as n,w as e,e as r}from"./app-Bw2NG-QJ.js";const d={},k=s("h1",{id:"配置运行",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#配置运行"},[s("span",null,"配置运行")])],-1),v=s("p",null,[s("a",{href:"./install"},"下载并安装"),n(" 了 Xray 之后,您需要对它进行一下配置。")],-1),m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b=r(`

                                        警告

                                        为了避免你的流量被解密,
                                        你应该使用 xray uuiduuidgen 生成一个独一无二的uuid
                                        在服务端上,放入 inbounds[0].settings.clients[0].id
                                        在客户端内,放入 outbounds[0].settings.vnext[0].users[0].id

                                        服务端配置

                                        你需要一台防火墙外的服务器,来运行服务器端的 Xray。配置如下:

                                        {
                                           "inbounds": [
                                             {
                                               "port": 10086, // 服务器监听端口
                                        diff --git a/assets/config.html-B1P46wfI.js b/assets/config.html-D5Tr_5W7.js
                                        similarity index 99%
                                        rename from assets/config.html-B1P46wfI.js
                                        rename to assets/config.html-D5Tr_5W7.js
                                        index 0ed907519c..c8f888e951 100644
                                        --- a/assets/config.html-B1P46wfI.js
                                        +++ b/assets/config.html-D5Tr_5W7.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as o,o as l,c as r,a,b as s,d as n,w as e,e as u}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"configure-and-run",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#configure-and-run"},[s("span",null,"Configure and Run")])],-1),k={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},m=u(`

                                        Server Configuration

                                        You need a server outside the firewall to run server-side Xray. The configuration is as follows:

                                        {
                                        +import{_ as c,r as o,o as l,c as r,a,b as s,d as n,w as e,e as u}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"configure-and-run",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#configure-and-run"},[s("span",null,"Configure and Run")])],-1),k={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},m=u(`

                                        Server Configuration

                                        You need a server outside the firewall to run server-side Xray. The configuration is as follows:

                                        {
                                           "inbounds": [
                                             {
                                               "port": 10086, // The port on which the server is listening
                                        diff --git a/assets/config.html-BeNJtLqo.js b/assets/config.html-DXicnlDr.js
                                        similarity index 99%
                                        rename from assets/config.html-BeNJtLqo.js
                                        rename to assets/config.html-DXicnlDr.js
                                        index d493e5a2a8..30c16280c8 100644
                                        --- a/assets/config.html-BeNJtLqo.js
                                        +++ b/assets/config.html-DXicnlDr.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as o,o as l,c as u,a,b as s,d as n,w as e,e as r}from"./app-5SoadDYS.js";const d={},k=s("h1",{id:"настроика-и-запуск",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#настроика-и-запуск"},[s("span",null,"Настройка и запуск")])],-1),v=s("p",null,[n("После того, как вы "),s("a",{href:"./install"},"скачали и установили"),n(" Xray, вам потребуется его настроить.")],-1),m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b=r(`

                                        Предупреждение

                                        Во избежание расшифровки вашего трафика
                                        следует сгенерировать уникальный UUID с помощью команды xray uuid или uuidgen,
                                        который затем нужно вставить на стороне сервера в поле inbounds[0].settings.clients[0].id,
                                        а на стороне клиента - в поле outbounds[0].settings.vnext[0].users[0].id.

                                        Настройка сервера

                                        Вам понадобится сервер с публичным IP-адресом (не за NAT), на котором будет запущен Xray. Конфигурация сервера:

                                        {
                                        +import{_ as i,r as o,o as l,c as u,a,b as s,d as n,w as e,e as r}from"./app-Bw2NG-QJ.js";const d={},k=s("h1",{id:"настроика-и-запуск",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#настроика-и-запуск"},[s("span",null,"Настройка и запуск")])],-1),v=s("p",null,[n("После того, как вы "),s("a",{href:"./install"},"скачали и установили"),n(" Xray, вам потребуется его настроить.")],-1),m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b=r(`

                                        Предупреждение

                                        Во избежание расшифровки вашего трафика
                                        следует сгенерировать уникальный UUID с помощью команды xray uuid или uuidgen,
                                        который затем нужно вставить на стороне сервера в поле inbounds[0].settings.clients[0].id,
                                        а на стороне клиента - в поле outbounds[0].settings.vnext[0].users[0].id.

                                        Настройка сервера

                                        Вам понадобится сервер с публичным IP-адресом (не за NAT), на котором будет запущен Xray. Конфигурация сервера:

                                        {
                                           "inbounds": [
                                             {
                                               "port": 10086, // Порт, который слушает сервер
                                        diff --git a/assets/createText-ca0c5216-X7RVUogw.js b/assets/createText-ca0c5216-xyt9uAlz.js
                                        similarity index 99%
                                        rename from assets/createText-ca0c5216-X7RVUogw.js
                                        rename to assets/createText-ca0c5216-xyt9uAlz.js
                                        index d6743cf535..9d6149c938 100644
                                        --- a/assets/createText-ca0c5216-X7RVUogw.js
                                        +++ b/assets/createText-ca0c5216-xyt9uAlz.js
                                        @@ -1,4 +1,4 @@
                                        -import{l as At,an as zt,ap as It}from"./mermaid.core-CArNAncI.js";const Tt={};function Bt(n,r){const t=Tt,e=typeof t.includeImageAlt=="boolean"?t.includeImageAlt:!0,u=typeof t.includeHtml=="boolean"?t.includeHtml:!0;return et(n,e,u)}function et(n,r,t){if(Lt(n)){if("value"in n)return n.type==="html"&&!t?"":n.value;if(r&&"alt"in n&&n.alt)return n.alt;if("children"in n)return Vn(n.children,r,t)}return Array.isArray(n)?Vn(n,r,t):""}function Vn(n,r,t){const e=[];let u=-1;for(;++uu?0:u+r:r=r>u?u:r,t=t>0?t:0,e.length<1e4)l=Array.from(e),l.unshift(r,t),n.splice(...l);else for(t&&n.splice(r,t);i0?(tn(n,n.length,0,r),n):r}const Wn={}.hasOwnProperty;function Ot(n){const r={};let t=-1;for(;++tl))return;const T=r.events.length;let H=T,N,V;for(;H--;)if(r.events[H][0]==="exit"&&r.events[H][1].type==="chunkFlow"){if(N){V=r.events[H][1].end;break}N=!0}for(b(e),k=T;kF;){const _=t[D];r.containerState=_[1],_[0].exit.call(r,n)}t.length=F}function j(){u.write([null]),i=void 0,u=void 0,r.containerState._closeFlow=void 0}}function Ut(n,r,t){return O(n,n.attempt(this.parser.constructs.document,r,t),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function Un(n){if(n===null||Z(n)||Ht(n))return 1;if(qt(n))return 2}function Ln(n,r,t){const e=[];let u=-1;for(;++u1&&n[t][1].end.offset-n[t][1].start.offset>1?2:1;const f=Object.assign({},n[e][1].end),x=Object.assign({},n[t][1].start);$n(f,-m),$n(x,m),l={type:m>1?"strongSequence":"emphasisSequence",start:f,end:Object.assign({},n[e][1].end)},a={type:m>1?"strongSequence":"emphasisSequence",start:Object.assign({},n[t][1].start),end:x},i={type:m>1?"strongText":"emphasisText",start:Object.assign({},n[e][1].end),end:Object.assign({},n[t][1].start)},u={type:m>1?"strong":"emphasis",start:Object.assign({},l.start),end:Object.assign({},a.end)},n[e][1].end=Object.assign({},l.start),n[t][1].start=Object.assign({},a.end),c=[],n[e][1].end.offset-n[e][1].start.offset&&(c=Y(c,[["enter",n[e][1],r],["exit",n[e][1],r]])),c=Y(c,[["enter",u,r],["enter",l,r],["exit",l,r],["enter",i,r]]),c=Y(c,Ln(r.parser.constructs.insideSpan.null,n.slice(e+1,t),r)),c=Y(c,[["exit",i,r],["enter",a,r],["exit",a,r],["exit",u,r]]),n[t][1].end.offset-n[t][1].start.offset?(p=2,c=Y(c,[["enter",n[t][1],r],["exit",n[t][1],r]])):p=0,tn(n,e-1,t-e+3,c),t=e+c.length-p-2;break}}for(t=-1;++t0&&z(k)?O(n,j,"linePrefix",i+1)(k):j(k)}function j(k){return k===null||C(k)?n.check(Yn,I,D)(k):(n.enter("codeFlowValue"),F(k))}function F(k){return k===null||C(k)?(n.exit("codeFlowValue"),j(k)):(n.consume(k),F)}function D(k){return n.exit("codeFenced"),r(k)}function _(k,T,H){let N=0;return V;function V(w){return k.enter("lineEnding"),k.consume(w),k.exit("lineEnding"),y}function y(w){return k.enter("codeFencedFence"),z(w)?O(k,S,"linePrefix",e.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(w):S(w)}function S(w){return w===a?(k.enter("codeFencedFenceSequence"),P(w)):H(w)}function P(w){return w===a?(N++,k.consume(w),P):N>=l?(k.exit("codeFencedFenceSequence"),z(w)?O(k,R,"whitespace")(w):R(w)):H(w)}function R(w){return w===null||C(w)?(k.exit("codeFencedFence"),T(w)):H(w)}}}function re(n,r,t){const e=this;return u;function u(l){return l===null?t(l):(n.enter("lineEnding"),n.consume(l),n.exit("lineEnding"),i)}function i(l){return e.parser.lazy[e.now().line]?t(l):r(l)}}const Cn={name:"codeIndented",tokenize:ue},ie={tokenize:le,partial:!0};function ue(n,r,t){const e=this;return u;function u(c){return n.enter("codeIndented"),O(n,i,"linePrefix",5)(c)}function i(c){const p=e.events[e.events.length-1];return p&&p[1].type==="linePrefix"&&p[2].sliceSerialize(p[1],!0).length>=4?l(c):t(c)}function l(c){return c===null?m(c):C(c)?n.attempt(ie,l,m)(c):(n.enter("codeFlowValue"),a(c))}function a(c){return c===null||C(c)?(n.exit("codeFlowValue"),l(c)):(n.consume(c),a)}function m(c){return n.exit("codeIndented"),r(c)}}function le(n,r,t){const e=this;return u;function u(l){return e.parser.lazy[e.now().line]?t(l):C(l)?(n.enter("lineEnding"),n.consume(l),n.exit("lineEnding"),u):O(n,i,"linePrefix",5)(l)}function i(l){const a=e.events[e.events.length-1];return a&&a[1].type==="linePrefix"&&a[2].sliceSerialize(a[1],!0).length>=4?r(l):C(l)?u(l):t(l)}}const ae={name:"codeText",tokenize:ce,resolve:oe,previous:se};function oe(n){let r=n.length-4,t=3,e,u;if((n[t][1].type==="lineEnding"||n[t][1].type==="space")&&(n[r][1].type==="lineEnding"||n[r][1].type==="space")){for(e=t;++e=4?r(l):n.interrupt(e.parser.constructs.flow,t,r)(l)}}function at(n,r,t,e,u,i,l,a,m){const c=m||Number.POSITIVE_INFINITY;let p=0;return f;function f(b){return b===60?(n.enter(e),n.enter(u),n.enter(i),n.consume(b),n.exit(i),x):b===null||b===32||b===41||An(b)?t(b):(n.enter(e),n.enter(l),n.enter(a),n.enter("chunkString",{contentType:"string"}),I(b))}function x(b){return b===62?(n.enter(i),n.consume(b),n.exit(i),n.exit(u),n.exit(e),r):(n.enter(a),n.enter("chunkString",{contentType:"string"}),h(b))}function h(b){return b===62?(n.exit("chunkString"),n.exit(a),x(b)):b===null||b===60||C(b)?t(b):(n.consume(b),b===92?A:h)}function A(b){return b===60||b===62||b===92?(n.consume(b),h):h(b)}function I(b){return!p&&(b===null||b===41||Z(b))?(n.exit("chunkString"),n.exit(a),n.exit(l),n.exit(e),r(b)):p999||h===null||h===91||h===93&&!m||h===94&&!a&&"_hiddenFootnoteSupport"in l.parser.constructs?t(h):h===93?(n.exit(i),n.enter(u),n.consume(h),n.exit(u),n.exit(e),r):C(h)?(n.enter("lineEnding"),n.consume(h),n.exit("lineEnding"),p):(n.enter("chunkString",{contentType:"string"}),f(h))}function f(h){return h===null||h===91||h===93||C(h)||a++>999?(n.exit("chunkString"),p(h)):(n.consume(h),m||(m=!z(h)),h===92?x:f)}function x(h){return h===91||h===92||h===93?(n.consume(h),a++,f):f(h)}}function st(n,r,t,e,u,i){let l;return a;function a(x){return x===34||x===39||x===40?(n.enter(e),n.enter(u),n.consume(x),n.exit(u),l=x===40?41:x,m):t(x)}function m(x){return x===l?(n.enter(u),n.consume(x),n.exit(u),n.exit(e),r):(n.enter(i),c(x))}function c(x){return x===l?(n.exit(i),m(l)):x===null?t(x):C(x)?(n.enter("lineEnding"),n.consume(x),n.exit("lineEnding"),O(n,c,"linePrefix")):(n.enter("chunkString",{contentType:"string"}),p(x))}function p(x){return x===l||x===null||C(x)?(n.exit("chunkString"),c(x)):(n.consume(x),x===92?f:p)}function f(x){return x===l||x===92?(n.consume(x),p):p(x)}}function dn(n,r){let t;return e;function e(u){return C(u)?(n.enter("lineEnding"),n.consume(u),n.exit("lineEnding"),t=!0,e):z(u)?O(n,e,t?"linePrefix":"lineSuffix")(u):r(u)}}function xn(n){return n.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const ke={name:"definition",tokenize:be},de={tokenize:ye,partial:!0};function be(n,r,t){const e=this;let u;return i;function i(h){return n.enter("definition"),l(h)}function l(h){return ot.call(e,n,a,t,"definitionLabel","definitionLabelMarker","definitionLabelString")(h)}function a(h){return u=xn(e.sliceSerialize(e.events[e.events.length-1][1]).slice(1,-1)),h===58?(n.enter("definitionMarker"),n.consume(h),n.exit("definitionMarker"),m):t(h)}function m(h){return Z(h)?dn(n,c)(h):c(h)}function c(h){return at(n,p,t,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(h)}function p(h){return n.attempt(de,f,f)(h)}function f(h){return z(h)?O(n,x,"whitespace")(h):x(h)}function x(h){return h===null||C(h)?(n.exit("definition"),e.parser.defined.push(u),r(h)):t(h)}}function ye(n,r,t){return e;function e(a){return Z(a)?dn(n,u)(a):t(a)}function u(a){return st(n,i,t,"definitionTitle","definitionTitleMarker","definitionTitleString")(a)}function i(a){return z(a)?O(n,l,"whitespace")(a):l(a)}function l(a){return a===null||C(a)?r(a):t(a)}}const Se={name:"hardBreakEscape",tokenize:Fe};function Fe(n,r,t){return e;function e(i){return n.enter("hardBreakEscape"),n.consume(i),u}function u(i){return C(i)?(n.exit("hardBreakEscape"),r(i)):t(i)}}const Ee={name:"headingAtx",tokenize:we,resolve:Ce};function Ce(n,r){let t=n.length-2,e=3,u,i;return n[e][1].type==="whitespace"&&(e+=2),t-2>e&&n[t][1].type==="whitespace"&&(t-=2),n[t][1].type==="atxHeadingSequence"&&(e===t-1||t-4>e&&n[t-2][1].type==="whitespace")&&(t-=e+1===t?2:4),t>e&&(u={type:"atxHeadingText",start:n[e][1].start,end:n[t][1].end},i={type:"chunkText",start:n[e][1].start,end:n[t][1].end,contentType:"text"},tn(n,e,t-e+1,[["enter",u,r],["enter",i,r],["exit",i,r],["exit",u,r]])),n}function we(n,r,t){let e=0;return u;function u(p){return n.enter("atxHeading"),i(p)}function i(p){return n.enter("atxHeadingSequence"),l(p)}function l(p){return p===35&&e++<6?(n.consume(p),l):p===null||Z(p)?(n.exit("atxHeadingSequence"),a(p)):t(p)}function a(p){return p===35?(n.enter("atxHeadingSequence"),m(p)):p===null||C(p)?(n.exit("atxHeading"),r(p)):z(p)?O(n,a,"whitespace")(p):(n.enter("atxHeadingText"),c(p))}function m(p){return p===35?(n.consume(p),m):(n.exit("atxHeadingSequence"),a(p))}function c(p){return p===null||p===35||Z(p)?(n.exit("atxHeadingText"),a(p)):(n.consume(p),c)}}const Ae=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],Jn=["pre","script","style","textarea"],ze={name:"htmlFlow",tokenize:Le,resolveTo:Be,concrete:!0},Ie={tokenize:De,partial:!0},Te={tokenize:Oe,partial:!0};function Be(n){let r=n.length;for(;r--&&!(n[r][0]==="enter"&&n[r][1].type==="htmlFlow"););return r>1&&n[r-2][1].type==="linePrefix"&&(n[r][1].start=n[r-2][1].start,n[r+1][1].start=n[r-2][1].start,n.splice(r-2,2)),n}function Le(n,r,t){const e=this;let u,i,l,a,m;return c;function c(s){return p(s)}function p(s){return n.enter("htmlFlow"),n.enter("htmlFlowData"),n.consume(s),f}function f(s){return s===33?(n.consume(s),x):s===47?(n.consume(s),i=!0,I):s===63?(n.consume(s),u=3,e.interrupt?r:o):nn(s)?(n.consume(s),l=String.fromCharCode(s),M):t(s)}function x(s){return s===45?(n.consume(s),u=2,h):s===91?(n.consume(s),u=5,a=0,A):nn(s)?(n.consume(s),u=4,e.interrupt?r:o):t(s)}function h(s){return s===45?(n.consume(s),e.interrupt?r:o):t(s)}function A(s){const K="CDATA[";return s===K.charCodeAt(a++)?(n.consume(s),a===K.length?e.interrupt?r:S:A):t(s)}function I(s){return nn(s)?(n.consume(s),l=String.fromCharCode(s),M):t(s)}function M(s){if(s===null||s===47||s===62||Z(s)){const K=s===47,hn=l.toLowerCase();return!K&&!i&&Jn.includes(hn)?(u=1,e.interrupt?r(s):S(s)):Ae.includes(l.toLowerCase())?(u=6,K?(n.consume(s),b):e.interrupt?r(s):S(s)):(u=7,e.interrupt&&!e.parser.lazy[e.now().line]?t(s):i?j(s):F(s))}return s===45||v(s)?(n.consume(s),l+=String.fromCharCode(s),M):t(s)}function b(s){return s===62?(n.consume(s),e.interrupt?r:S):t(s)}function j(s){return z(s)?(n.consume(s),j):V(s)}function F(s){return s===47?(n.consume(s),V):s===58||s===95||nn(s)?(n.consume(s),D):z(s)?(n.consume(s),F):V(s)}function D(s){return s===45||s===46||s===58||s===95||v(s)?(n.consume(s),D):_(s)}function _(s){return s===61?(n.consume(s),k):z(s)?(n.consume(s),_):F(s)}function k(s){return s===null||s===60||s===61||s===62||s===96?t(s):s===34||s===39?(n.consume(s),m=s,T):z(s)?(n.consume(s),k):H(s)}function T(s){return s===m?(n.consume(s),m=null,N):s===null||C(s)?t(s):(n.consume(s),T)}function H(s){return s===null||s===34||s===39||s===47||s===60||s===61||s===62||s===96||Z(s)?_(s):(n.consume(s),H)}function N(s){return s===47||s===62||z(s)?F(s):t(s)}function V(s){return s===62?(n.consume(s),y):t(s)}function y(s){return s===null||C(s)?S(s):z(s)?(n.consume(s),y):t(s)}function S(s){return s===45&&u===2?(n.consume(s),U):s===60&&u===1?(n.consume(s),W):s===62&&u===4?(n.consume(s),J):s===63&&u===3?(n.consume(s),o):s===93&&u===5?(n.consume(s),en):C(s)&&(u===6||u===7)?(n.exit("htmlFlowData"),n.check(Ie,rn,P)(s)):s===null||C(s)?(n.exit("htmlFlowData"),P(s)):(n.consume(s),S)}function P(s){return n.check(Te,R,rn)(s)}function R(s){return n.enter("lineEnding"),n.consume(s),n.exit("lineEnding"),w}function w(s){return s===null||C(s)?P(s):(n.enter("htmlFlowData"),S(s))}function U(s){return s===45?(n.consume(s),o):S(s)}function W(s){return s===47?(n.consume(s),l="",G):S(s)}function G(s){if(s===62){const K=l.toLowerCase();return Jn.includes(K)?(n.consume(s),J):S(s)}return nn(s)&&l.length<8?(n.consume(s),l+=String.fromCharCode(s),G):S(s)}function en(s){return s===93?(n.consume(s),o):S(s)}function o(s){return s===62?(n.consume(s),J):s===45&&u===2?(n.consume(s),o):S(s)}function J(s){return s===null||C(s)?(n.exit("htmlFlowData"),rn(s)):(n.consume(s),J)}function rn(s){return n.exit("htmlFlow"),r(s)}}function Oe(n,r,t){const e=this;return u;function u(l){return C(l)?(n.enter("lineEnding"),n.consume(l),n.exit("lineEnding"),i):t(l)}function i(l){return e.parser.lazy[e.now().line]?t(l):r(l)}}function De(n,r,t){return e;function e(u){return n.enter("lineEnding"),n.consume(u),n.exit("lineEnding"),n.attempt(Sn,r,t)}}const Pe={name:"htmlText",tokenize:_e};function _e(n,r,t){const e=this;let u,i,l;return a;function a(o){return n.enter("htmlText"),n.enter("htmlTextData"),n.consume(o),m}function m(o){return o===33?(n.consume(o),c):o===47?(n.consume(o),_):o===63?(n.consume(o),F):nn(o)?(n.consume(o),H):t(o)}function c(o){return o===45?(n.consume(o),p):o===91?(n.consume(o),i=0,A):nn(o)?(n.consume(o),j):t(o)}function p(o){return o===45?(n.consume(o),h):t(o)}function f(o){return o===null?t(o):o===45?(n.consume(o),x):C(o)?(l=f,W(o)):(n.consume(o),f)}function x(o){return o===45?(n.consume(o),h):f(o)}function h(o){return o===62?U(o):o===45?x(o):f(o)}function A(o){const J="CDATA[";return o===J.charCodeAt(i++)?(n.consume(o),i===J.length?I:A):t(o)}function I(o){return o===null?t(o):o===93?(n.consume(o),M):C(o)?(l=I,W(o)):(n.consume(o),I)}function M(o){return o===93?(n.consume(o),b):I(o)}function b(o){return o===62?U(o):o===93?(n.consume(o),b):I(o)}function j(o){return o===null||o===62?U(o):C(o)?(l=j,W(o)):(n.consume(o),j)}function F(o){return o===null?t(o):o===63?(n.consume(o),D):C(o)?(l=F,W(o)):(n.consume(o),F)}function D(o){return o===62?U(o):F(o)}function _(o){return nn(o)?(n.consume(o),k):t(o)}function k(o){return o===45||v(o)?(n.consume(o),k):T(o)}function T(o){return C(o)?(l=T,W(o)):z(o)?(n.consume(o),T):U(o)}function H(o){return o===45||v(o)?(n.consume(o),H):o===47||o===62||Z(o)?N(o):t(o)}function N(o){return o===47?(n.consume(o),U):o===58||o===95||nn(o)?(n.consume(o),V):C(o)?(l=N,W(o)):z(o)?(n.consume(o),N):U(o)}function V(o){return o===45||o===46||o===58||o===95||v(o)?(n.consume(o),V):y(o)}function y(o){return o===61?(n.consume(o),S):C(o)?(l=y,W(o)):z(o)?(n.consume(o),y):N(o)}function S(o){return o===null||o===60||o===61||o===62||o===96?t(o):o===34||o===39?(n.consume(o),u=o,P):C(o)?(l=S,W(o)):z(o)?(n.consume(o),S):(n.consume(o),R)}function P(o){return o===u?(n.consume(o),u=void 0,w):o===null?t(o):C(o)?(l=P,W(o)):(n.consume(o),P)}function R(o){return o===null||o===34||o===39||o===60||o===61||o===96?t(o):o===47||o===62||Z(o)?N(o):(n.consume(o),R)}function w(o){return o===47||o===62||Z(o)?N(o):t(o)}function U(o){return o===62?(n.consume(o),n.exit("htmlTextData"),n.exit("htmlText"),r):t(o)}function W(o){return n.exit("htmlTextData"),n.enter("lineEnding"),n.consume(o),n.exit("lineEnding"),G}function G(o){return z(o)?O(n,en,"linePrefix",e.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(o):en(o)}function en(o){return n.enter("htmlTextData"),l(o)}}const Dn={name:"labelEnd",tokenize:Ne,resolveTo:He,resolveAll:qe},Me={tokenize:Ve},je={tokenize:We},Re={tokenize:Qe};function qe(n){let r=-1;for(;++r=3&&(c===null||C(c))?(n.exit("thematicBreak"),r(c)):t(c)}function m(c){return c===u?(n.consume(c),e++,m):(n.exit("thematicBreakSequence"),z(c)?O(n,a,"whitespace")(c):a(c))}}const $={name:"list",tokenize:ve,continuation:{tokenize:nr},exit:er},Ke={tokenize:rr,partial:!0},Xe={tokenize:tr,partial:!0};function ve(n,r,t){const e=this,u=e.events[e.events.length-1];let i=u&&u[1].type==="linePrefix"?u[2].sliceSerialize(u[1],!0).length:0,l=0;return a;function a(h){const A=e.containerState.type||(h===42||h===43||h===45?"listUnordered":"listOrdered");if(A==="listUnordered"?!e.containerState.marker||h===e.containerState.marker:zn(h)){if(e.containerState.type||(e.containerState.type=A,n.enter(A,{_container:!0})),A==="listUnordered")return n.enter("listItemPrefix"),h===42||h===45?n.check(bn,t,c)(h):c(h);if(!e.interrupt||h===49)return n.enter("listItemPrefix"),n.enter("listItemValue"),m(h)}return t(h)}function m(h){return zn(h)&&++l<10?(n.consume(h),m):(!e.interrupt||l<2)&&(e.containerState.marker?h===e.containerState.marker:h===41||h===46)?(n.exit("listItemValue"),c(h)):t(h)}function c(h){return n.enter("listItemMarker"),n.consume(h),n.exit("listItemMarker"),e.containerState.marker=e.containerState.marker||h,n.check(Sn,e.interrupt?t:p,n.attempt(Ke,x,f))}function p(h){return e.containerState.initialBlankLine=!0,i++,x(h)}function f(h){return z(h)?(n.enter("listItemPrefixWhitespace"),n.consume(h),n.exit("listItemPrefixWhitespace"),x):t(h)}function x(h){return e.containerState.size=i+e.sliceSerialize(n.exit("listItemPrefix"),!0).length,r(h)}}function nr(n,r,t){const e=this;return e.containerState._closeFlow=void 0,n.check(Sn,u,i);function u(a){return e.containerState.furtherBlankLines=e.containerState.furtherBlankLines||e.containerState.initialBlankLine,O(n,r,"listItemIndent",e.containerState.size+1)(a)}function i(a){return e.containerState.furtherBlankLines||!z(a)?(e.containerState.furtherBlankLines=void 0,e.containerState.initialBlankLine=void 0,l(a)):(e.containerState.furtherBlankLines=void 0,e.containerState.initialBlankLine=void 0,n.attempt(Xe,r,l)(a))}function l(a){return e.containerState._closeFlow=!0,e.interrupt=void 0,O(n,n.attempt($,r,t),"linePrefix",e.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(a)}}function tr(n,r,t){const e=this;return O(n,u,"listItemIndent",e.containerState.size+1);function u(i){const l=e.events[e.events.length-1];return l&&l[1].type==="listItemIndent"&&l[2].sliceSerialize(l[1],!0).length===e.containerState.size?r(i):t(i)}}function er(n){n.exit(this.containerState.type)}function rr(n,r,t){const e=this;return O(n,u,"listItemPrefixWhitespace",e.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function u(i){const l=e.events[e.events.length-1];return!z(i)&&l&&l[1].type==="listItemPrefixWhitespace"?r(i):t(i)}}const Kn={name:"setextUnderline",tokenize:ur,resolveTo:ir};function ir(n,r){let t=n.length,e,u,i;for(;t--;)if(n[t][0]==="enter"){if(n[t][1].type==="content"){e=t;break}n[t][1].type==="paragraph"&&(u=t)}else n[t][1].type==="content"&&n.splice(t,1),!i&&n[t][1].type==="definition"&&(i=t);const l={type:"setextHeading",start:Object.assign({},n[u][1].start),end:Object.assign({},n[n.length-1][1].end)};return n[u][1].type="setextHeadingText",i?(n.splice(u,0,["enter",l,r]),n.splice(i+1,0,["exit",n[e][1],r]),n[e][1].end=Object.assign({},n[i][1].end)):n[e][1]=l,n.push(["exit",l,r]),n}function ur(n,r,t){const e=this;let u;return i;function i(c){let p=e.events.length,f;for(;p--;)if(e.events[p][1].type!=="lineEnding"&&e.events[p][1].type!=="linePrefix"&&e.events[p][1].type!=="content"){f=e.events[p][1].type==="paragraph";break}return!e.parser.lazy[e.now().line]&&(e.interrupt||f)?(n.enter("setextHeadingLine"),u=c,l(c)):t(c)}function l(c){return n.enter("setextHeadingLineSequence"),a(c)}function a(c){return c===u?(n.consume(c),a):(n.exit("setextHeadingLineSequence"),z(c)?O(n,m,"lineSuffix")(c):m(c))}function m(c){return c===null||C(c)?(n.exit("setextHeadingLine"),r(c)):t(c)}}const lr={tokenize:ar};function ar(n){const r=this,t=n.attempt(Sn,e,n.attempt(this.parser.constructs.flowInitial,u,O(n,n.attempt(this.parser.constructs.flow,u,n.attempt(pe,u)),"linePrefix")));return t;function e(i){if(i===null){n.consume(i);return}return n.enter("lineEndingBlank"),n.consume(i),n.exit("lineEndingBlank"),r.currentConstruct=void 0,t}function u(i){if(i===null){n.consume(i);return}return n.enter("lineEnding"),n.consume(i),n.exit("lineEnding"),r.currentConstruct=void 0,t}}const or={resolveAll:ht()},sr=ct("string"),cr=ct("text");function ct(n){return{tokenize:r,resolveAll:ht(n==="text"?hr:void 0)};function r(t){const e=this,u=this.parser.constructs[n],i=t.attempt(u,l,a);return l;function l(p){return c(p)?i(p):a(p)}function a(p){if(p===null){t.consume(p);return}return t.enter("data"),t.consume(p),m}function m(p){return c(p)?(t.exit("data"),i(p)):(t.consume(p),m)}function c(p){if(p===null)return!0;const f=u[p];let x=-1;if(f)for(;++x-1){const a=l[0];typeof a=="string"?l[0]=a.slice(e):l.shift()}i>0&&l.push(n[u].slice(0,i))}return l}function mr(n,r){let t=-1;const e=[];let u;for(;++tu?0:u+r:r=r>u?u:r,t=t>0?t:0,e.length<1e4)l=Array.from(e),l.unshift(r,t),n.splice(...l);else for(t&&n.splice(r,t);i0?(tn(n,n.length,0,r),n):r}const Wn={}.hasOwnProperty;function Ot(n){const r={};let t=-1;for(;++tl))return;const T=r.events.length;let H=T,N,V;for(;H--;)if(r.events[H][0]==="exit"&&r.events[H][1].type==="chunkFlow"){if(N){V=r.events[H][1].end;break}N=!0}for(b(e),k=T;kF;){const _=t[D];r.containerState=_[1],_[0].exit.call(r,n)}t.length=F}function j(){u.write([null]),i=void 0,u=void 0,r.containerState._closeFlow=void 0}}function Ut(n,r,t){return O(n,n.attempt(this.parser.constructs.document,r,t),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function Un(n){if(n===null||Z(n)||Ht(n))return 1;if(qt(n))return 2}function Ln(n,r,t){const e=[];let u=-1;for(;++u1&&n[t][1].end.offset-n[t][1].start.offset>1?2:1;const f=Object.assign({},n[e][1].end),x=Object.assign({},n[t][1].start);$n(f,-m),$n(x,m),l={type:m>1?"strongSequence":"emphasisSequence",start:f,end:Object.assign({},n[e][1].end)},a={type:m>1?"strongSequence":"emphasisSequence",start:Object.assign({},n[t][1].start),end:x},i={type:m>1?"strongText":"emphasisText",start:Object.assign({},n[e][1].end),end:Object.assign({},n[t][1].start)},u={type:m>1?"strong":"emphasis",start:Object.assign({},l.start),end:Object.assign({},a.end)},n[e][1].end=Object.assign({},l.start),n[t][1].start=Object.assign({},a.end),c=[],n[e][1].end.offset-n[e][1].start.offset&&(c=Y(c,[["enter",n[e][1],r],["exit",n[e][1],r]])),c=Y(c,[["enter",u,r],["enter",l,r],["exit",l,r],["enter",i,r]]),c=Y(c,Ln(r.parser.constructs.insideSpan.null,n.slice(e+1,t),r)),c=Y(c,[["exit",i,r],["enter",a,r],["exit",a,r],["exit",u,r]]),n[t][1].end.offset-n[t][1].start.offset?(p=2,c=Y(c,[["enter",n[t][1],r],["exit",n[t][1],r]])):p=0,tn(n,e-1,t-e+3,c),t=e+c.length-p-2;break}}for(t=-1;++t0&&z(k)?O(n,j,"linePrefix",i+1)(k):j(k)}function j(k){return k===null||C(k)?n.check(Yn,I,D)(k):(n.enter("codeFlowValue"),F(k))}function F(k){return k===null||C(k)?(n.exit("codeFlowValue"),j(k)):(n.consume(k),F)}function D(k){return n.exit("codeFenced"),r(k)}function _(k,T,H){let N=0;return V;function V(w){return k.enter("lineEnding"),k.consume(w),k.exit("lineEnding"),y}function y(w){return k.enter("codeFencedFence"),z(w)?O(k,S,"linePrefix",e.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(w):S(w)}function S(w){return w===a?(k.enter("codeFencedFenceSequence"),P(w)):H(w)}function P(w){return w===a?(N++,k.consume(w),P):N>=l?(k.exit("codeFencedFenceSequence"),z(w)?O(k,R,"whitespace")(w):R(w)):H(w)}function R(w){return w===null||C(w)?(k.exit("codeFencedFence"),T(w)):H(w)}}}function re(n,r,t){const e=this;return u;function u(l){return l===null?t(l):(n.enter("lineEnding"),n.consume(l),n.exit("lineEnding"),i)}function i(l){return e.parser.lazy[e.now().line]?t(l):r(l)}}const Cn={name:"codeIndented",tokenize:ue},ie={tokenize:le,partial:!0};function ue(n,r,t){const e=this;return u;function u(c){return n.enter("codeIndented"),O(n,i,"linePrefix",5)(c)}function i(c){const p=e.events[e.events.length-1];return p&&p[1].type==="linePrefix"&&p[2].sliceSerialize(p[1],!0).length>=4?l(c):t(c)}function l(c){return c===null?m(c):C(c)?n.attempt(ie,l,m)(c):(n.enter("codeFlowValue"),a(c))}function a(c){return c===null||C(c)?(n.exit("codeFlowValue"),l(c)):(n.consume(c),a)}function m(c){return n.exit("codeIndented"),r(c)}}function le(n,r,t){const e=this;return u;function u(l){return e.parser.lazy[e.now().line]?t(l):C(l)?(n.enter("lineEnding"),n.consume(l),n.exit("lineEnding"),u):O(n,i,"linePrefix",5)(l)}function i(l){const a=e.events[e.events.length-1];return a&&a[1].type==="linePrefix"&&a[2].sliceSerialize(a[1],!0).length>=4?r(l):C(l)?u(l):t(l)}}const ae={name:"codeText",tokenize:ce,resolve:oe,previous:se};function oe(n){let r=n.length-4,t=3,e,u;if((n[t][1].type==="lineEnding"||n[t][1].type==="space")&&(n[r][1].type==="lineEnding"||n[r][1].type==="space")){for(e=t;++e=4?r(l):n.interrupt(e.parser.constructs.flow,t,r)(l)}}function at(n,r,t,e,u,i,l,a,m){const c=m||Number.POSITIVE_INFINITY;let p=0;return f;function f(b){return b===60?(n.enter(e),n.enter(u),n.enter(i),n.consume(b),n.exit(i),x):b===null||b===32||b===41||An(b)?t(b):(n.enter(e),n.enter(l),n.enter(a),n.enter("chunkString",{contentType:"string"}),I(b))}function x(b){return b===62?(n.enter(i),n.consume(b),n.exit(i),n.exit(u),n.exit(e),r):(n.enter(a),n.enter("chunkString",{contentType:"string"}),h(b))}function h(b){return b===62?(n.exit("chunkString"),n.exit(a),x(b)):b===null||b===60||C(b)?t(b):(n.consume(b),b===92?A:h)}function A(b){return b===60||b===62||b===92?(n.consume(b),h):h(b)}function I(b){return!p&&(b===null||b===41||Z(b))?(n.exit("chunkString"),n.exit(a),n.exit(l),n.exit(e),r(b)):p999||h===null||h===91||h===93&&!m||h===94&&!a&&"_hiddenFootnoteSupport"in l.parser.constructs?t(h):h===93?(n.exit(i),n.enter(u),n.consume(h),n.exit(u),n.exit(e),r):C(h)?(n.enter("lineEnding"),n.consume(h),n.exit("lineEnding"),p):(n.enter("chunkString",{contentType:"string"}),f(h))}function f(h){return h===null||h===91||h===93||C(h)||a++>999?(n.exit("chunkString"),p(h)):(n.consume(h),m||(m=!z(h)),h===92?x:f)}function x(h){return h===91||h===92||h===93?(n.consume(h),a++,f):f(h)}}function st(n,r,t,e,u,i){let l;return a;function a(x){return x===34||x===39||x===40?(n.enter(e),n.enter(u),n.consume(x),n.exit(u),l=x===40?41:x,m):t(x)}function m(x){return x===l?(n.enter(u),n.consume(x),n.exit(u),n.exit(e),r):(n.enter(i),c(x))}function c(x){return x===l?(n.exit(i),m(l)):x===null?t(x):C(x)?(n.enter("lineEnding"),n.consume(x),n.exit("lineEnding"),O(n,c,"linePrefix")):(n.enter("chunkString",{contentType:"string"}),p(x))}function p(x){return x===l||x===null||C(x)?(n.exit("chunkString"),c(x)):(n.consume(x),x===92?f:p)}function f(x){return x===l||x===92?(n.consume(x),p):p(x)}}function dn(n,r){let t;return e;function e(u){return C(u)?(n.enter("lineEnding"),n.consume(u),n.exit("lineEnding"),t=!0,e):z(u)?O(n,e,t?"linePrefix":"lineSuffix")(u):r(u)}}function xn(n){return n.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const ke={name:"definition",tokenize:be},de={tokenize:ye,partial:!0};function be(n,r,t){const e=this;let u;return i;function i(h){return n.enter("definition"),l(h)}function l(h){return ot.call(e,n,a,t,"definitionLabel","definitionLabelMarker","definitionLabelString")(h)}function a(h){return u=xn(e.sliceSerialize(e.events[e.events.length-1][1]).slice(1,-1)),h===58?(n.enter("definitionMarker"),n.consume(h),n.exit("definitionMarker"),m):t(h)}function m(h){return Z(h)?dn(n,c)(h):c(h)}function c(h){return at(n,p,t,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(h)}function p(h){return n.attempt(de,f,f)(h)}function f(h){return z(h)?O(n,x,"whitespace")(h):x(h)}function x(h){return h===null||C(h)?(n.exit("definition"),e.parser.defined.push(u),r(h)):t(h)}}function ye(n,r,t){return e;function e(a){return Z(a)?dn(n,u)(a):t(a)}function u(a){return st(n,i,t,"definitionTitle","definitionTitleMarker","definitionTitleString")(a)}function i(a){return z(a)?O(n,l,"whitespace")(a):l(a)}function l(a){return a===null||C(a)?r(a):t(a)}}const Se={name:"hardBreakEscape",tokenize:Fe};function Fe(n,r,t){return e;function e(i){return n.enter("hardBreakEscape"),n.consume(i),u}function u(i){return C(i)?(n.exit("hardBreakEscape"),r(i)):t(i)}}const Ee={name:"headingAtx",tokenize:we,resolve:Ce};function Ce(n,r){let t=n.length-2,e=3,u,i;return n[e][1].type==="whitespace"&&(e+=2),t-2>e&&n[t][1].type==="whitespace"&&(t-=2),n[t][1].type==="atxHeadingSequence"&&(e===t-1||t-4>e&&n[t-2][1].type==="whitespace")&&(t-=e+1===t?2:4),t>e&&(u={type:"atxHeadingText",start:n[e][1].start,end:n[t][1].end},i={type:"chunkText",start:n[e][1].start,end:n[t][1].end,contentType:"text"},tn(n,e,t-e+1,[["enter",u,r],["enter",i,r],["exit",i,r],["exit",u,r]])),n}function we(n,r,t){let e=0;return u;function u(p){return n.enter("atxHeading"),i(p)}function i(p){return n.enter("atxHeadingSequence"),l(p)}function l(p){return p===35&&e++<6?(n.consume(p),l):p===null||Z(p)?(n.exit("atxHeadingSequence"),a(p)):t(p)}function a(p){return p===35?(n.enter("atxHeadingSequence"),m(p)):p===null||C(p)?(n.exit("atxHeading"),r(p)):z(p)?O(n,a,"whitespace")(p):(n.enter("atxHeadingText"),c(p))}function m(p){return p===35?(n.consume(p),m):(n.exit("atxHeadingSequence"),a(p))}function c(p){return p===null||p===35||Z(p)?(n.exit("atxHeadingText"),a(p)):(n.consume(p),c)}}const Ae=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],Jn=["pre","script","style","textarea"],ze={name:"htmlFlow",tokenize:Le,resolveTo:Be,concrete:!0},Ie={tokenize:De,partial:!0},Te={tokenize:Oe,partial:!0};function Be(n){let r=n.length;for(;r--&&!(n[r][0]==="enter"&&n[r][1].type==="htmlFlow"););return r>1&&n[r-2][1].type==="linePrefix"&&(n[r][1].start=n[r-2][1].start,n[r+1][1].start=n[r-2][1].start,n.splice(r-2,2)),n}function Le(n,r,t){const e=this;let u,i,l,a,m;return c;function c(s){return p(s)}function p(s){return n.enter("htmlFlow"),n.enter("htmlFlowData"),n.consume(s),f}function f(s){return s===33?(n.consume(s),x):s===47?(n.consume(s),i=!0,I):s===63?(n.consume(s),u=3,e.interrupt?r:o):nn(s)?(n.consume(s),l=String.fromCharCode(s),M):t(s)}function x(s){return s===45?(n.consume(s),u=2,h):s===91?(n.consume(s),u=5,a=0,A):nn(s)?(n.consume(s),u=4,e.interrupt?r:o):t(s)}function h(s){return s===45?(n.consume(s),e.interrupt?r:o):t(s)}function A(s){const K="CDATA[";return s===K.charCodeAt(a++)?(n.consume(s),a===K.length?e.interrupt?r:S:A):t(s)}function I(s){return nn(s)?(n.consume(s),l=String.fromCharCode(s),M):t(s)}function M(s){if(s===null||s===47||s===62||Z(s)){const K=s===47,hn=l.toLowerCase();return!K&&!i&&Jn.includes(hn)?(u=1,e.interrupt?r(s):S(s)):Ae.includes(l.toLowerCase())?(u=6,K?(n.consume(s),b):e.interrupt?r(s):S(s)):(u=7,e.interrupt&&!e.parser.lazy[e.now().line]?t(s):i?j(s):F(s))}return s===45||v(s)?(n.consume(s),l+=String.fromCharCode(s),M):t(s)}function b(s){return s===62?(n.consume(s),e.interrupt?r:S):t(s)}function j(s){return z(s)?(n.consume(s),j):V(s)}function F(s){return s===47?(n.consume(s),V):s===58||s===95||nn(s)?(n.consume(s),D):z(s)?(n.consume(s),F):V(s)}function D(s){return s===45||s===46||s===58||s===95||v(s)?(n.consume(s),D):_(s)}function _(s){return s===61?(n.consume(s),k):z(s)?(n.consume(s),_):F(s)}function k(s){return s===null||s===60||s===61||s===62||s===96?t(s):s===34||s===39?(n.consume(s),m=s,T):z(s)?(n.consume(s),k):H(s)}function T(s){return s===m?(n.consume(s),m=null,N):s===null||C(s)?t(s):(n.consume(s),T)}function H(s){return s===null||s===34||s===39||s===47||s===60||s===61||s===62||s===96||Z(s)?_(s):(n.consume(s),H)}function N(s){return s===47||s===62||z(s)?F(s):t(s)}function V(s){return s===62?(n.consume(s),y):t(s)}function y(s){return s===null||C(s)?S(s):z(s)?(n.consume(s),y):t(s)}function S(s){return s===45&&u===2?(n.consume(s),U):s===60&&u===1?(n.consume(s),W):s===62&&u===4?(n.consume(s),J):s===63&&u===3?(n.consume(s),o):s===93&&u===5?(n.consume(s),en):C(s)&&(u===6||u===7)?(n.exit("htmlFlowData"),n.check(Ie,rn,P)(s)):s===null||C(s)?(n.exit("htmlFlowData"),P(s)):(n.consume(s),S)}function P(s){return n.check(Te,R,rn)(s)}function R(s){return n.enter("lineEnding"),n.consume(s),n.exit("lineEnding"),w}function w(s){return s===null||C(s)?P(s):(n.enter("htmlFlowData"),S(s))}function U(s){return s===45?(n.consume(s),o):S(s)}function W(s){return s===47?(n.consume(s),l="",G):S(s)}function G(s){if(s===62){const K=l.toLowerCase();return Jn.includes(K)?(n.consume(s),J):S(s)}return nn(s)&&l.length<8?(n.consume(s),l+=String.fromCharCode(s),G):S(s)}function en(s){return s===93?(n.consume(s),o):S(s)}function o(s){return s===62?(n.consume(s),J):s===45&&u===2?(n.consume(s),o):S(s)}function J(s){return s===null||C(s)?(n.exit("htmlFlowData"),rn(s)):(n.consume(s),J)}function rn(s){return n.exit("htmlFlow"),r(s)}}function Oe(n,r,t){const e=this;return u;function u(l){return C(l)?(n.enter("lineEnding"),n.consume(l),n.exit("lineEnding"),i):t(l)}function i(l){return e.parser.lazy[e.now().line]?t(l):r(l)}}function De(n,r,t){return e;function e(u){return n.enter("lineEnding"),n.consume(u),n.exit("lineEnding"),n.attempt(Sn,r,t)}}const Pe={name:"htmlText",tokenize:_e};function _e(n,r,t){const e=this;let u,i,l;return a;function a(o){return n.enter("htmlText"),n.enter("htmlTextData"),n.consume(o),m}function m(o){return o===33?(n.consume(o),c):o===47?(n.consume(o),_):o===63?(n.consume(o),F):nn(o)?(n.consume(o),H):t(o)}function c(o){return o===45?(n.consume(o),p):o===91?(n.consume(o),i=0,A):nn(o)?(n.consume(o),j):t(o)}function p(o){return o===45?(n.consume(o),h):t(o)}function f(o){return o===null?t(o):o===45?(n.consume(o),x):C(o)?(l=f,W(o)):(n.consume(o),f)}function x(o){return o===45?(n.consume(o),h):f(o)}function h(o){return o===62?U(o):o===45?x(o):f(o)}function A(o){const J="CDATA[";return o===J.charCodeAt(i++)?(n.consume(o),i===J.length?I:A):t(o)}function I(o){return o===null?t(o):o===93?(n.consume(o),M):C(o)?(l=I,W(o)):(n.consume(o),I)}function M(o){return o===93?(n.consume(o),b):I(o)}function b(o){return o===62?U(o):o===93?(n.consume(o),b):I(o)}function j(o){return o===null||o===62?U(o):C(o)?(l=j,W(o)):(n.consume(o),j)}function F(o){return o===null?t(o):o===63?(n.consume(o),D):C(o)?(l=F,W(o)):(n.consume(o),F)}function D(o){return o===62?U(o):F(o)}function _(o){return nn(o)?(n.consume(o),k):t(o)}function k(o){return o===45||v(o)?(n.consume(o),k):T(o)}function T(o){return C(o)?(l=T,W(o)):z(o)?(n.consume(o),T):U(o)}function H(o){return o===45||v(o)?(n.consume(o),H):o===47||o===62||Z(o)?N(o):t(o)}function N(o){return o===47?(n.consume(o),U):o===58||o===95||nn(o)?(n.consume(o),V):C(o)?(l=N,W(o)):z(o)?(n.consume(o),N):U(o)}function V(o){return o===45||o===46||o===58||o===95||v(o)?(n.consume(o),V):y(o)}function y(o){return o===61?(n.consume(o),S):C(o)?(l=y,W(o)):z(o)?(n.consume(o),y):N(o)}function S(o){return o===null||o===60||o===61||o===62||o===96?t(o):o===34||o===39?(n.consume(o),u=o,P):C(o)?(l=S,W(o)):z(o)?(n.consume(o),S):(n.consume(o),R)}function P(o){return o===u?(n.consume(o),u=void 0,w):o===null?t(o):C(o)?(l=P,W(o)):(n.consume(o),P)}function R(o){return o===null||o===34||o===39||o===60||o===61||o===96?t(o):o===47||o===62||Z(o)?N(o):(n.consume(o),R)}function w(o){return o===47||o===62||Z(o)?N(o):t(o)}function U(o){return o===62?(n.consume(o),n.exit("htmlTextData"),n.exit("htmlText"),r):t(o)}function W(o){return n.exit("htmlTextData"),n.enter("lineEnding"),n.consume(o),n.exit("lineEnding"),G}function G(o){return z(o)?O(n,en,"linePrefix",e.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(o):en(o)}function en(o){return n.enter("htmlTextData"),l(o)}}const Dn={name:"labelEnd",tokenize:Ne,resolveTo:He,resolveAll:qe},Me={tokenize:Ve},je={tokenize:We},Re={tokenize:Qe};function qe(n){let r=-1;for(;++r=3&&(c===null||C(c))?(n.exit("thematicBreak"),r(c)):t(c)}function m(c){return c===u?(n.consume(c),e++,m):(n.exit("thematicBreakSequence"),z(c)?O(n,a,"whitespace")(c):a(c))}}const $={name:"list",tokenize:ve,continuation:{tokenize:nr},exit:er},Ke={tokenize:rr,partial:!0},Xe={tokenize:tr,partial:!0};function ve(n,r,t){const e=this,u=e.events[e.events.length-1];let i=u&&u[1].type==="linePrefix"?u[2].sliceSerialize(u[1],!0).length:0,l=0;return a;function a(h){const A=e.containerState.type||(h===42||h===43||h===45?"listUnordered":"listOrdered");if(A==="listUnordered"?!e.containerState.marker||h===e.containerState.marker:zn(h)){if(e.containerState.type||(e.containerState.type=A,n.enter(A,{_container:!0})),A==="listUnordered")return n.enter("listItemPrefix"),h===42||h===45?n.check(bn,t,c)(h):c(h);if(!e.interrupt||h===49)return n.enter("listItemPrefix"),n.enter("listItemValue"),m(h)}return t(h)}function m(h){return zn(h)&&++l<10?(n.consume(h),m):(!e.interrupt||l<2)&&(e.containerState.marker?h===e.containerState.marker:h===41||h===46)?(n.exit("listItemValue"),c(h)):t(h)}function c(h){return n.enter("listItemMarker"),n.consume(h),n.exit("listItemMarker"),e.containerState.marker=e.containerState.marker||h,n.check(Sn,e.interrupt?t:p,n.attempt(Ke,x,f))}function p(h){return e.containerState.initialBlankLine=!0,i++,x(h)}function f(h){return z(h)?(n.enter("listItemPrefixWhitespace"),n.consume(h),n.exit("listItemPrefixWhitespace"),x):t(h)}function x(h){return e.containerState.size=i+e.sliceSerialize(n.exit("listItemPrefix"),!0).length,r(h)}}function nr(n,r,t){const e=this;return e.containerState._closeFlow=void 0,n.check(Sn,u,i);function u(a){return e.containerState.furtherBlankLines=e.containerState.furtherBlankLines||e.containerState.initialBlankLine,O(n,r,"listItemIndent",e.containerState.size+1)(a)}function i(a){return e.containerState.furtherBlankLines||!z(a)?(e.containerState.furtherBlankLines=void 0,e.containerState.initialBlankLine=void 0,l(a)):(e.containerState.furtherBlankLines=void 0,e.containerState.initialBlankLine=void 0,n.attempt(Xe,r,l)(a))}function l(a){return e.containerState._closeFlow=!0,e.interrupt=void 0,O(n,n.attempt($,r,t),"linePrefix",e.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(a)}}function tr(n,r,t){const e=this;return O(n,u,"listItemIndent",e.containerState.size+1);function u(i){const l=e.events[e.events.length-1];return l&&l[1].type==="listItemIndent"&&l[2].sliceSerialize(l[1],!0).length===e.containerState.size?r(i):t(i)}}function er(n){n.exit(this.containerState.type)}function rr(n,r,t){const e=this;return O(n,u,"listItemPrefixWhitespace",e.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function u(i){const l=e.events[e.events.length-1];return!z(i)&&l&&l[1].type==="listItemPrefixWhitespace"?r(i):t(i)}}const Kn={name:"setextUnderline",tokenize:ur,resolveTo:ir};function ir(n,r){let t=n.length,e,u,i;for(;t--;)if(n[t][0]==="enter"){if(n[t][1].type==="content"){e=t;break}n[t][1].type==="paragraph"&&(u=t)}else n[t][1].type==="content"&&n.splice(t,1),!i&&n[t][1].type==="definition"&&(i=t);const l={type:"setextHeading",start:Object.assign({},n[u][1].start),end:Object.assign({},n[n.length-1][1].end)};return n[u][1].type="setextHeadingText",i?(n.splice(u,0,["enter",l,r]),n.splice(i+1,0,["exit",n[e][1],r]),n[e][1].end=Object.assign({},n[i][1].end)):n[e][1]=l,n.push(["exit",l,r]),n}function ur(n,r,t){const e=this;let u;return i;function i(c){let p=e.events.length,f;for(;p--;)if(e.events[p][1].type!=="lineEnding"&&e.events[p][1].type!=="linePrefix"&&e.events[p][1].type!=="content"){f=e.events[p][1].type==="paragraph";break}return!e.parser.lazy[e.now().line]&&(e.interrupt||f)?(n.enter("setextHeadingLine"),u=c,l(c)):t(c)}function l(c){return n.enter("setextHeadingLineSequence"),a(c)}function a(c){return c===u?(n.consume(c),a):(n.exit("setextHeadingLineSequence"),z(c)?O(n,m,"lineSuffix")(c):m(c))}function m(c){return c===null||C(c)?(n.exit("setextHeadingLine"),r(c)):t(c)}}const lr={tokenize:ar};function ar(n){const r=this,t=n.attempt(Sn,e,n.attempt(this.parser.constructs.flowInitial,u,O(n,n.attempt(this.parser.constructs.flow,u,n.attempt(pe,u)),"linePrefix")));return t;function e(i){if(i===null){n.consume(i);return}return n.enter("lineEndingBlank"),n.consume(i),n.exit("lineEndingBlank"),r.currentConstruct=void 0,t}function u(i){if(i===null){n.consume(i);return}return n.enter("lineEnding"),n.consume(i),n.exit("lineEnding"),r.currentConstruct=void 0,t}}const or={resolveAll:ht()},sr=ct("string"),cr=ct("text");function ct(n){return{tokenize:r,resolveAll:ht(n==="text"?hr:void 0)};function r(t){const e=this,u=this.parser.constructs[n],i=t.attempt(u,l,a);return l;function l(p){return c(p)?i(p):a(p)}function a(p){if(p===null){t.consume(p);return}return t.enter("data"),t.consume(p),m}function m(p){return c(p)?(t.exit("data"),i(p)):(t.consume(p),m)}function c(p){if(p===null)return!0;const f=u[p];let x=-1;if(f)for(;++x-1){const a=l[0];typeof a=="string"?l[0]=a.slice(e):l.shift()}i>0&&l.push(n[u].slice(0,i))}return l}function mr(n,r){let t=-1;const e=[];let u;for(;++t13&&t<32||t>126&&t<160||t>55295&&t<57344||t>64975&&t<65008||(t&65535)===65535||(t&65535)===65534||t>1114111?"�":String.fromCharCode(t)}const Ir=/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi;function Tr(n){return n.replace(Ir,Br)}function Br(n,r,t){if(r)return r;if(t.charCodeAt(0)===35){const u=t.charCodeAt(1),i=u===120||u===88;return pt(t.slice(i?2:1),i?16:10)}return On(t)||n}function yn(n){return!n||typeof n!="object"?"":"position"in n||"type"in n?vn(n.position):"start"in n||"end"in n?vn(n):"line"in n||"column"in n?Tn(n):""}function Tn(n){return nt(n&&n.line)+":"+nt(n&&n.column)}function vn(n){return Tn(n&&n.start)+"-"+Tn(n&&n.end)}function nt(n){return n&&typeof n=="number"?n:1}const ft={}.hasOwnProperty,mt=function(n,r,t){return typeof r!="string"&&(t=r,r=void 0),Lr(t)(zr(wr(t).document().write(Ar()(n,r,!0))))};function Lr(n){const r={transforms:[],canContainEols:["emphasis","fragment","heading","paragraph","strong"],enter:{autolink:a(Hn),autolinkProtocol:y,autolinkEmail:y,atxHeading:a(jn),blockQuote:a(Fn),characterEscape:y,characterReference:y,codeFenced:a(Mn),codeFencedFenceInfo:m,codeFencedFenceMeta:m,codeIndented:a(Mn,m),codeText:a(kt,m),codeTextData:y,data:y,codeFlowValue:y,definition:a(dt),definitionDestinationString:m,definitionLabelString:m,definitionTitleString:m,emphasis:a(bt),hardBreakEscape:a(Rn),hardBreakTrailing:a(Rn),htmlFlow:a(qn,m),htmlFlowData:y,htmlText:a(qn,m),htmlTextData:y,image:a(yt),label:m,link:a(Hn),listItem:a(St),listItemValue:A,listOrdered:a(Nn,h),listUnordered:a(Nn),paragraph:a(Ft),reference:hn,referenceString:m,resourceDestinationString:m,resourceTitleString:m,setextHeading:a(jn),strong:a(Et),thematicBreak:a(wt)},exit:{atxHeading:p(),atxHeadingSequence:T,autolink:p(),autolinkEmail:mn,autolinkProtocol:fn,blockQuote:p(),characterEscapeValue:S,characterReferenceMarkerHexadecimal:pn,characterReferenceMarkerNumeric:pn,characterReferenceValue:an,codeFenced:p(j),codeFencedFence:b,codeFencedFenceInfo:I,codeFencedFenceMeta:M,codeFlowValue:S,codeIndented:p(F),codeText:p(W),codeTextData:S,data:S,definition:p(),definitionDestinationString:k,definitionLabelString:D,definitionTitleString:_,emphasis:p(),hardBreakEscape:p(R),hardBreakTrailing:p(R),htmlFlow:p(w),htmlFlowData:S,htmlText:p(U),htmlTextData:S,image:p(en),label:J,labelText:o,lineEnding:P,link:p(G),listItem:p(),listOrdered:p(),listUnordered:p(),paragraph:p(),referenceString:Q,resourceDestinationString:rn,resourceTitleString:s,resource:K,setextHeading:p(V),setextHeadingLineSequence:N,setextHeadingText:H,strong:p(),thematicBreak:p()}};xt(r,(n||{}).mdastExtensions||[]);const t={};return e;function e(g){let d={type:"root",children:[]};const E={stack:[d],tokenStack:[],config:r,enter:c,exit:f,buffer:m,resume:x,setData:i,getData:l},B=[];let L=-1;for(;++L0){const X=E.tokenStack[E.tokenStack.length-1];(X[1]||tt).call(E,void 0,X[0])}for(d.position={start:sn(g.length>0?g[0][1].start:{line:1,column:1,offset:0}),end:sn(g.length>0?g[g.length-2][1].end:{line:1,column:1,offset:0})},L=-1;++L设计目标
                                        • Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验;
                                        • 以跨平台为首要原则,以减少二次开发的成本;

                                        架构

                                        Architecture

                                        内核分为三层:应用层、代理层和传输层。

                                        每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。

                                        应用层

                                        应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。

                                        应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。

                                        重要模块列表:

                                        ',10),x=e("li",null,"Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理;",-1),f=e("li",null,"DNS: 内置的 DNS 服务器模块;",-1),b=e("li",null,"Proxy Manager: 代理管理器;",-1),m=e("h3",{id:"代理层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#代理层"},[e("span",null,"代理层")])],-1),g=e("p",null,"代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。",-1),y=e("p",null,"两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。",-1),k=e("h4",{id:"入站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入站代理"},[e("span",null,"入站代理")])],-1),I={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},N=e("h4",{id:"出站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#出站代理"},[e("span",null,"出站代理")])],-1),B={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},L=e("h3",{id:"传输层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#传输层"},[e("span",null,"传输层")])],-1),V=e("p",null,"传输层提供一些网络数据传输相关的工具模块。",-1);function v(w,D){const s=t("I18nTip"),r=t("RouterLink"),a=t("ExternalLinkIcon");return c(),i("div",null,[o(s),u,e("ul",null,[x,e("li",null,[n("Router: 路由模块,详见 "),o(r,{to:"/config/routing.html"},{default:h(()=>[n("路由配置")]),_:1}),n(";")]),f,b]),m,g,y,k,e("ul",null,[e("li",null,[n("实现 "),e("a",I,[n("proxy.Inbound"),o(a)]),n(" 接口;")])]),N,e("ul",null,[e("li",null,[n("实现 "),e("a",B,[n("proxy.Outbound"),o(a)]),n(" 接口;")])]),L,V])}const O=l(p,[["render",v],["__file","design.html.vue"]]);export{O as default}; +import{_ as l,r as t,o as c,c as i,a as o,b as e,d as n,w as h,e as d}from"./app-Bw2NG-QJ.js";const _="/assets/framework-B9ZtOYdZ.png",p={},u=d('

                                        设计目标

                                        • Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验;
                                        • 以跨平台为首要原则,以减少二次开发的成本;

                                        架构

                                        Architecture

                                        内核分为三层:应用层、代理层和传输层。

                                        每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。

                                        应用层

                                        应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。

                                        应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。

                                        重要模块列表:

                                        ',10),x=e("li",null,"Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理;",-1),f=e("li",null,"DNS: 内置的 DNS 服务器模块;",-1),b=e("li",null,"Proxy Manager: 代理管理器;",-1),m=e("h3",{id:"代理层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#代理层"},[e("span",null,"代理层")])],-1),g=e("p",null,"代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。",-1),y=e("p",null,"两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。",-1),k=e("h4",{id:"入站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入站代理"},[e("span",null,"入站代理")])],-1),I={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},N=e("h4",{id:"出站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#出站代理"},[e("span",null,"出站代理")])],-1),B={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},L=e("h3",{id:"传输层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#传输层"},[e("span",null,"传输层")])],-1),V=e("p",null,"传输层提供一些网络数据传输相关的工具模块。",-1);function v(w,D){const s=t("I18nTip"),r=t("RouterLink"),a=t("ExternalLinkIcon");return c(),i("div",null,[o(s),u,e("ul",null,[x,e("li",null,[n("Router: 路由模块,详见 "),o(r,{to:"/config/routing.html"},{default:h(()=>[n("路由配置")]),_:1}),n(";")]),f,b]),m,g,y,k,e("ul",null,[e("li",null,[n("实现 "),e("a",I,[n("proxy.Inbound"),o(a)]),n(" 接口;")])]),N,e("ul",null,[e("li",null,[n("实现 "),e("a",B,[n("proxy.Outbound"),o(a)]),n(" 接口;")])]),L,V])}const O=l(p,[["render",v],["__file","design.html.vue"]]);export{O as default}; diff --git a/assets/design.html-nD32aykc.js b/assets/design.html-Buz8frIk.js similarity index 98% rename from assets/design.html-nD32aykc.js rename to assets/design.html-Buz8frIk.js index da65837a9d..217f7d2011 100644 --- a/assets/design.html-nD32aykc.js +++ b/assets/design.html-Buz8frIk.js @@ -1 +1 @@ -import{_ as i,r as t,o as l,c as d,a as n,b as e,d as o,w as p,e as c}from"./app-5SoadDYS.js";const h="/assets/framework-B9ZtOYdZ.png",u={},y=c('

                                        Design Objectives

                                        • Xray Kernel provides a platform that supports essential network proxy functions and can be developed upon to provide a better user experience.
                                        • Cross-platform is the primary principle to reduce the cost of secondary development.

                                        Architecture

                                        Architecture

                                        The kernel is divided into three layers: the application layer, the proxy layer, and the transport layer.

                                        Each layer contains several modules, which are independent of each other. Modules of the same type can be seamlessly replaced.

                                        Application Layer

                                        The application layer contains some commonly used functions in proxy layers, which are abstracted for reuse in different proxy modules.

                                        The modules at the application layer should be implemented purely in software and should not be dependent on hardware or platform-related technologies.

                                        List of Important Modules:

                                        ',10),_=e("li",null,"Dispatcher: Used to transfer data received by the inbound agent to the outbound agent;",-1),m=e("li",null,"DNS: Built-in DNS server module;",-1),x=e("li",null,"Proxy Manager: Proxy manager;",-1),f=e("h3",{id:"proxy-layer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#proxy-layer"},[e("span",null,"Proxy Layer")])],-1),b=e("p",null,"The proxy layer is divided into two parts: Inbound Proxy and Outbound Proxy.",-1),g=e("p",null,"The two parts are independent of each other, where the inbound proxy does not rely on a specific outbound proxy, and vice versa.",-1),v=e("h4",{id:"inbound-proxy",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#inbound-proxy"},[e("span",null,"Inbound Proxy")])],-1),k={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},w=e("h4",{id:"outbound-proxy",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#outbound-proxy"},[e("span",null,"Outbound Proxy")])],-1),I={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},T=e("h3",{id:"transport-layer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#transport-layer"},[e("span",null,"Transport Layer")])],-1),L=e("p",null,"The transport layer provides a set of tools and modules related to network data transmission.",-1);function P(N,B){const a=t("I18nTip"),s=t("RouterLink"),r=t("ExternalLinkIcon");return l(),d("div",null,[n(a),y,e("ul",null,[_,e("li",null,[o("Router: Routing module, see "),n(s,{to:"/en/config/routing.html"},{default:p(()=>[o("Routing Configuration")]),_:1}),o(" for details;")]),m,x]),f,b,g,v,e("ul",null,[e("li",null,[o("Implement the "),e("a",k,[o("proxy.Inbound"),n(r)]),o(" interface;")])]),w,e("ul",null,[e("li",null,[o("Implement the "),e("a",I,[o("proxy.Outbound"),n(r)]),o(" interface;")])]),T,L])}const R=i(u,[["render",P],["__file","design.html.vue"]]);export{R as default}; +import{_ as i,r as t,o as l,c as d,a as n,b as e,d as o,w as p,e as c}from"./app-Bw2NG-QJ.js";const h="/assets/framework-B9ZtOYdZ.png",u={},y=c('

                                        Design Objectives

                                        • Xray Kernel provides a platform that supports essential network proxy functions and can be developed upon to provide a better user experience.
                                        • Cross-platform is the primary principle to reduce the cost of secondary development.

                                        Architecture

                                        Architecture

                                        The kernel is divided into three layers: the application layer, the proxy layer, and the transport layer.

                                        Each layer contains several modules, which are independent of each other. Modules of the same type can be seamlessly replaced.

                                        Application Layer

                                        The application layer contains some commonly used functions in proxy layers, which are abstracted for reuse in different proxy modules.

                                        The modules at the application layer should be implemented purely in software and should not be dependent on hardware or platform-related technologies.

                                        List of Important Modules:

                                        ',10),_=e("li",null,"Dispatcher: Used to transfer data received by the inbound agent to the outbound agent;",-1),m=e("li",null,"DNS: Built-in DNS server module;",-1),x=e("li",null,"Proxy Manager: Proxy manager;",-1),f=e("h3",{id:"proxy-layer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#proxy-layer"},[e("span",null,"Proxy Layer")])],-1),b=e("p",null,"The proxy layer is divided into two parts: Inbound Proxy and Outbound Proxy.",-1),g=e("p",null,"The two parts are independent of each other, where the inbound proxy does not rely on a specific outbound proxy, and vice versa.",-1),v=e("h4",{id:"inbound-proxy",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#inbound-proxy"},[e("span",null,"Inbound Proxy")])],-1),k={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},w=e("h4",{id:"outbound-proxy",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#outbound-proxy"},[e("span",null,"Outbound Proxy")])],-1),I={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},T=e("h3",{id:"transport-layer",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#transport-layer"},[e("span",null,"Transport Layer")])],-1),L=e("p",null,"The transport layer provides a set of tools and modules related to network data transmission.",-1);function P(N,B){const a=t("I18nTip"),s=t("RouterLink"),r=t("ExternalLinkIcon");return l(),d("div",null,[n(a),y,e("ul",null,[_,e("li",null,[o("Router: Routing module, see "),n(s,{to:"/en/config/routing.html"},{default:p(()=>[o("Routing Configuration")]),_:1}),o(" for details;")]),m,x]),f,b,g,v,e("ul",null,[e("li",null,[o("Implement the "),e("a",k,[o("proxy.Inbound"),n(r)]),o(" interface;")])]),w,e("ul",null,[e("li",null,[o("Implement the "),e("a",I,[o("proxy.Outbound"),n(r)]),o(" interface;")])]),T,L])}const R=i(u,[["render",P],["__file","design.html.vue"]]);export{R as default}; diff --git a/assets/design.html-B4pWfzca.js b/assets/design.html-DhXmb5CJ.js similarity index 97% rename from assets/design.html-B4pWfzca.js rename to assets/design.html-DhXmb5CJ.js index 624db5a0a3..7b63631aaa 100644 --- a/assets/design.html-B4pWfzca.js +++ b/assets/design.html-DhXmb5CJ.js @@ -1 +1 @@ -import{_ as l,r as t,o as c,c as i,a as o,b as e,d as n,w as h,e as d}from"./app-5SoadDYS.js";const _="/assets/framework-B9ZtOYdZ.png",p={},u=d('

                                        设计目标

                                        • Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验;
                                        • 以跨平台为首要原则,以减少二次开发的成本;

                                        架构

                                        Architecture

                                        内核分为三层:应用层、代理层和传输层。

                                        每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。

                                        应用层

                                        应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。

                                        应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。

                                        重要模块列表:

                                        ',10),x=e("li",null,"Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理;",-1),f=e("li",null,"DNS: 内置的 DNS 服务器模块;",-1),b=e("li",null,"Proxy Manager: 代理管理器;",-1),m=e("h3",{id:"代理层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#代理层"},[e("span",null,"代理层")])],-1),g=e("p",null,"代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。",-1),y=e("p",null,"两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。",-1),k=e("h4",{id:"入站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入站代理"},[e("span",null,"入站代理")])],-1),I={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},N=e("h4",{id:"出站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#出站代理"},[e("span",null,"出站代理")])],-1),B={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},L=e("h3",{id:"传输层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#传输层"},[e("span",null,"传输层")])],-1),V=e("p",null,"传输层提供一些网络数据传输相关的工具模块。",-1);function v(w,D){const r=t("I18nTip"),s=t("RouterLink"),a=t("ExternalLinkIcon");return c(),i("div",null,[o(r),u,e("ul",null,[x,e("li",null,[n("Router: 路由模块,详见 "),o(s,{to:"/ru/config/routing.html"},{default:h(()=>[n("路由配置")]),_:1}),n(";")]),f,b]),m,g,y,k,e("ul",null,[e("li",null,[n("实现 "),e("a",I,[n("proxy.Inbound"),o(a)]),n(" 接口;")])]),N,e("ul",null,[e("li",null,[n("实现 "),e("a",B,[n("proxy.Outbound"),o(a)]),n(" 接口;")])]),L,V])}const O=l(p,[["render",v],["__file","design.html.vue"]]);export{O as default}; +import{_ as l,r as t,o as c,c as i,a as o,b as e,d as n,w as h,e as d}from"./app-Bw2NG-QJ.js";const _="/assets/framework-B9ZtOYdZ.png",p={},u=d('

                                        设计目标

                                        • Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验;
                                        • 以跨平台为首要原则,以减少二次开发的成本;

                                        架构

                                        Architecture

                                        内核分为三层:应用层、代理层和传输层。

                                        每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。

                                        应用层

                                        应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。

                                        应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。

                                        重要模块列表:

                                        ',10),x=e("li",null,"Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理;",-1),f=e("li",null,"DNS: 内置的 DNS 服务器模块;",-1),b=e("li",null,"Proxy Manager: 代理管理器;",-1),m=e("h3",{id:"代理层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#代理层"},[e("span",null,"代理层")])],-1),g=e("p",null,"代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。",-1),y=e("p",null,"两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。",-1),k=e("h4",{id:"入站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入站代理"},[e("span",null,"入站代理")])],-1),I={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},N=e("h4",{id:"出站代理",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#出站代理"},[e("span",null,"出站代理")])],-1),B={href:"https://github.com/xtls/Xray-core/blob/main/proxy/proxy.go",target:"_blank",rel:"noopener noreferrer"},L=e("h3",{id:"传输层",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#传输层"},[e("span",null,"传输层")])],-1),V=e("p",null,"传输层提供一些网络数据传输相关的工具模块。",-1);function v(w,D){const r=t("I18nTip"),s=t("RouterLink"),a=t("ExternalLinkIcon");return c(),i("div",null,[o(r),u,e("ul",null,[x,e("li",null,[n("Router: 路由模块,详见 "),o(s,{to:"/ru/config/routing.html"},{default:h(()=>[n("路由配置")]),_:1}),n(";")]),f,b]),m,g,y,k,e("ul",null,[e("li",null,[n("实现 "),e("a",I,[n("proxy.Inbound"),o(a)]),n(" 接口;")])]),N,e("ul",null,[e("li",null,[n("实现 "),e("a",B,[n("proxy.Outbound"),o(a)]),n(" 接口;")])]),L,V])}const O=l(p,[["render",v],["__file","design.html.vue"]]);export{O as default}; diff --git a/assets/dns.html-DVJjxkIY.js b/assets/dns.html-CfUMjcx_.js similarity index 99% rename from assets/dns.html-DVJjxkIY.js rename to assets/dns.html-CfUMjcx_.js index 1d7c571872..c59facc236 100644 --- a/assets/dns.html-DVJjxkIY.js +++ b/assets/dns.html-CfUMjcx_.js @@ -1,4 +1,4 @@ -import{_ as u,r as p,o as l,c as r,a as o,b as s,d as n,w as t,e}from"./app-5SoadDYS.js";const d={},i=e(`

                                        Встроенный DNS-сервер

                                        DNS-сервер

                                        Встроенный DNS-модуль Xray имеет два основных назначения:

                                        • Разрешение доменных имен в IP-адреса на этапе маршрутизации и сопоставление правил с полученными IP-адресами для разделения трафика.
                                          Разрешение доменных имен и разделение трафика зависят от значения параметра domainStrategy в модуле конфигурации маршрутизации.
                                          Встроенный DNS-сервер будет использоваться для DNS-запросов только при следующих значениях:

                                          • "IPIfNonMatch": при запросе доменного имени Xray сопоставляет его с доменами, указанными в правилах маршрутизации.
                                            Если совпадение не найдено, встроенный DNS-сервер используется для разрешения доменного имени, а затем полученный IP-адрес снова сопоставляется с правилами маршрутизации на основе IP-адресов.
                                          • "IPOnDemand": при сопоставлении правил, основанных на IP-адресах, доменное имя немедленно разрешается в IP-адрес для сопоставления.
                                        • Разрешение целевого адреса для подключения.

                                          • Например, в исходящем подключении freedom, если параметр domainStrategy установлен в UseIP, исходящие запросы будут сначала разрешать доменное имя в IP-адрес с помощью встроенного DNS-сервера, а затем устанавливать соединение.
                                          • Например, в sockopt, если параметр domainStrategy установлен в UseIP, системные соединения, инициированные этим исходящим подключением, будут сначала разрешать доменное имя в IP-адрес с помощью встроенного DNS-сервера, а затем устанавливать соединение.

                                        Совет 1

                                        DNS-запросы, отправляемые встроенным DNS-сервером, автоматически перенаправляются в соответствии с конфигурацией маршрутизации.

                                        Совет 2

                                        Поддерживаются только базовые запросы IP-адресов (записи A и AAAA). Записи CNAME будут запрашиваться повторно до тех пор, пока не будет возвращена запись A/AAAA. Другие запросы не обрабатываются встроенным DNS-сервером.

                                        Процесс обработки DNS-запросов

                                        Если запрашиваемое доменное имя:

                                        • Соответствует сопоставлению "домен - IP" или "домен - массив IP" в hosts, то этот IP-адрес или массив IP-адресов возвращается в качестве результата DNS-разрешения.
                                        • Соответствует сопоставлению "домен - домен" в hosts, то значение этого сопоставления (другой домен) используется в качестве текущего запрашиваемого доменного имени, и процесс обработки DNS-запросов продолжается до тех пор, пока не будет разрешен IP-адрес или не будет возвращен пустой результат.
                                        • Не соответствует hosts, но соответствует списку доменов domains одного (или нескольких) DNS-серверов, то запросы отправляются на соответствующие DNS-серверы в порядке приоритета.
                                          Если запрос к DNS-серверу завершается неудачей или expectIPs не совпадает, используется следующий подходящий DNS-сервер.
                                          В противном случае возвращается полученный IP-адрес.
                                          Если запросы ко всем подходящим DNS-серверам завершаются неудачей или expectIPs не совпадает, компонент DNS:
                                          • По умолчанию выполняет "резервный (fallback) запрос DNS": запросы отправляются на "DNS-серверы, которые не использовались в предыдущем раунде неудачных запросов и для которых skipFallback имеет значение по умолчанию false".
                                            Если запрос завершается неудачей или expectIPs не совпадает, возвращается пустой результат.
                                            В противном случае возвращается полученный IP-адрес.
                                          • Если disableFallback установлен в true, "резервный (fallback) запрос DNS" не выполняется.
                                        • Не соответствует hosts и не соответствует списку доменов domains ни одного DNS-сервера, то:
                                          • По умолчанию запросы отправляются на "DNS-серверы, для которых skipFallback имеет значение по умолчанию false".
                                            Если запрос к первому выбранному DNS-серверу завершается неудачей или expectIPs не совпадает, используется следующий выбранный DNS-сервер.
                                            В противном случае возвращается полученный IP-адрес.
                                            Если запросы ко всем выбранным DNS-серверам завершаются неудачей или expectIPs не совпадает, возвращается пустой результат.
                                          • Если количество "DNS-серверов, для которых skipFallback имеет значение по умолчанию false", равно 0 или disableFallback установлен в true, используется первый DNS-сервер в конфигурации DNS.
                                            Если запрос завершается неудачей или expectIPs не совпадает, возвращается пустой результат.
                                            В противном случае возвращается полученный IP-адрес.

                                        DnsObject

                                        DnsObject соответствует полю dns в конфигурационном файле.

                                        {
                                        +import{_ as u,r as p,o as l,c as r,a as o,b as s,d as n,w as t,e}from"./app-Bw2NG-QJ.js";const d={},i=e(`

                                        Встроенный DNS-сервер

                                        DNS-сервер

                                        Встроенный DNS-модуль Xray имеет два основных назначения:

                                        • Разрешение доменных имен в IP-адреса на этапе маршрутизации и сопоставление правил с полученными IP-адресами для разделения трафика.
                                          Разрешение доменных имен и разделение трафика зависят от значения параметра domainStrategy в модуле конфигурации маршрутизации.
                                          Встроенный DNS-сервер будет использоваться для DNS-запросов только при следующих значениях:

                                          • "IPIfNonMatch": при запросе доменного имени Xray сопоставляет его с доменами, указанными в правилах маршрутизации.
                                            Если совпадение не найдено, встроенный DNS-сервер используется для разрешения доменного имени, а затем полученный IP-адрес снова сопоставляется с правилами маршрутизации на основе IP-адресов.
                                          • "IPOnDemand": при сопоставлении правил, основанных на IP-адресах, доменное имя немедленно разрешается в IP-адрес для сопоставления.
                                        • Разрешение целевого адреса для подключения.

                                          • Например, в исходящем подключении freedom, если параметр domainStrategy установлен в UseIP, исходящие запросы будут сначала разрешать доменное имя в IP-адрес с помощью встроенного DNS-сервера, а затем устанавливать соединение.
                                          • Например, в sockopt, если параметр domainStrategy установлен в UseIP, системные соединения, инициированные этим исходящим подключением, будут сначала разрешать доменное имя в IP-адрес с помощью встроенного DNS-сервера, а затем устанавливать соединение.

                                        Совет 1

                                        DNS-запросы, отправляемые встроенным DNS-сервером, автоматически перенаправляются в соответствии с конфигурацией маршрутизации.

                                        Совет 2

                                        Поддерживаются только базовые запросы IP-адресов (записи A и AAAA). Записи CNAME будут запрашиваться повторно до тех пор, пока не будет возвращена запись A/AAAA. Другие запросы не обрабатываются встроенным DNS-сервером.

                                        Процесс обработки DNS-запросов

                                        Если запрашиваемое доменное имя:

                                        • Соответствует сопоставлению "домен - IP" или "домен - массив IP" в hosts, то этот IP-адрес или массив IP-адресов возвращается в качестве результата DNS-разрешения.
                                        • Соответствует сопоставлению "домен - домен" в hosts, то значение этого сопоставления (другой домен) используется в качестве текущего запрашиваемого доменного имени, и процесс обработки DNS-запросов продолжается до тех пор, пока не будет разрешен IP-адрес или не будет возвращен пустой результат.
                                        • Не соответствует hosts, но соответствует списку доменов domains одного (или нескольких) DNS-серверов, то запросы отправляются на соответствующие DNS-серверы в порядке приоритета.
                                          Если запрос к DNS-серверу завершается неудачей или expectIPs не совпадает, используется следующий подходящий DNS-сервер.
                                          В противном случае возвращается полученный IP-адрес.
                                          Если запросы ко всем подходящим DNS-серверам завершаются неудачей или expectIPs не совпадает, компонент DNS:
                                          • По умолчанию выполняет "резервный (fallback) запрос DNS": запросы отправляются на "DNS-серверы, которые не использовались в предыдущем раунде неудачных запросов и для которых skipFallback имеет значение по умолчанию false".
                                            Если запрос завершается неудачей или expectIPs не совпадает, возвращается пустой результат.
                                            В противном случае возвращается полученный IP-адрес.
                                          • Если disableFallback установлен в true, "резервный (fallback) запрос DNS" не выполняется.
                                        • Не соответствует hosts и не соответствует списку доменов domains ни одного DNS-сервера, то:
                                          • По умолчанию запросы отправляются на "DNS-серверы, для которых skipFallback имеет значение по умолчанию false".
                                            Если запрос к первому выбранному DNS-серверу завершается неудачей или expectIPs не совпадает, используется следующий выбранный DNS-сервер.
                                            В противном случае возвращается полученный IP-адрес.
                                            Если запросы ко всем выбранным DNS-серверам завершаются неудачей или expectIPs не совпадает, возвращается пустой результат.
                                          • Если количество "DNS-серверов, для которых skipFallback имеет значение по умолчанию false", равно 0 или disableFallback установлен в true, используется первый DNS-сервер в конфигурации DNS.
                                            Если запрос завершается неудачей или expectIPs не совпадает, возвращается пустой результат.
                                            В противном случае возвращается полученный IP-адрес.

                                        DnsObject

                                        DnsObject соответствует полю dns в конфигурационном файле.

                                        {
                                           "dns": {
                                             "hosts": {
                                               "baidu.com": "127.0.0.1",
                                        diff --git a/assets/dns.html-5Ofmmx3O.js b/assets/dns.html-D-rYzT__.js
                                        similarity index 98%
                                        rename from assets/dns.html-5Ofmmx3O.js
                                        rename to assets/dns.html-D-rYzT__.js
                                        index a900d6d5e0..582e0f465a 100644
                                        --- a/assets/dns.html-5Ofmmx3O.js
                                        +++ b/assets/dns.html-D-rYzT__.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as e,o as d,c as u,a as s,b as o,d as n,w as r,e as l}from"./app-5SoadDYS.js";const i={},q=o("h1",{id:"dns",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#dns"},[o("span",null,"DNS")])],-1),k=o("p",null,"DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。",-1),_=o("p",null,"此出站协议只能接收 DNS 流量(包含基于 UDP 和 TCP 协议的查询),其它类型的流量会导致错误。",-1),b=l(`

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as p,r as e,o as d,c as u,a as s,b as o,d as n,w as r,e as l}from"./app-Bw2NG-QJ.js";const i={},q=o("h1",{id:"dns",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#dns"},[o("span",null,"DNS")])],-1),k=o("p",null,"DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。",-1),_=o("p",null,"此出站协议只能接收 DNS 流量(包含基于 UDP 和 TCP 协议的查询),其它类型的流量会导致错误。",-1),b=l(`

                                        OutboundConfigurationObject

                                        {
                                           "network": "tcp",
                                           "address": "1.1.1.1",
                                           "port": 53,
                                        diff --git a/assets/dns.html-DdV6b7iZ.js b/assets/dns.html-Db5UBVvD.js
                                        similarity index 99%
                                        rename from assets/dns.html-DdV6b7iZ.js
                                        rename to assets/dns.html-Db5UBVvD.js
                                        index f930ad7fe7..c6d14a6f62 100644
                                        --- a/assets/dns.html-DdV6b7iZ.js
                                        +++ b/assets/dns.html-Db5UBVvD.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as a,o as c,c as l,a as t,b as e,d as s,w as n,e as i}from"./app-5SoadDYS.js";const d={},p=i(`

                                        Built-in DNS Server

                                        DNS Server

                                        The DNS module built into Xray has two main purposes:

                                        • During the routing phase, it resolves domain names to IP addresses and performs traffic splitting based on the results of domain name resolution and the value of domainStrategy in the routing configuration module. The built-in DNS server is only used for DNS queries when either of the following values is set:
                                          • "IPIfNonMatch": When a domain name is requested, it first tries to match it against the domain entries in the routing configuration. If no match is found, the built-in DNS server is used to perform a DNS query for the domain name, and the returned IP address is used to perform IP routing matching again.
                                          • "IPOnDemand": When a domain name is matched against any IP-based rule, it is immediately resolved to an IP address for matching.
                                        • It resolves the target address for connection.
                                          • In the freedom outbound setting, if domainStrategy is set to UseIP, requests made through the outbound proxy will first resolve the domain name to an IP address using the built-in server before making the connection.
                                          • In the sockopt setting, if domainStrategy is set to UseIP, system connections initiated through the outbound proxy will first be resolved to an IP address using the built-in server before making the connection.

                                        TIP 1

                                        DNS queries sent by the built-in DNS server are automatically forwarded based on the routing configuration.

                                        TIP 2

                                        Only basic IP queries (A and AAAA records) are supported. CNAME records will be queried repeatedly until an A/AAAA record is returned. Other queries will not enter the built-in DNS server.

                                        DNS Processing Flow

                                        If the domain name to be queried:

                                        • Matches the mapping of "domain name - IP" or "domain name - IP array" in the hosts, then the IP or IP array will be returned as the DNS resolution result.

                                        • Matches the mapping of "domain name - domain name" in the hosts, then the value of this mapping (another domain name) will be used as the domain name to be queried, and enter the DNS processing flow until an IP is resolved and returned, or an empty resolution is returned.

                                        • Does not match hosts, but matches the domains list in one or more DNS servers, then according to the priority of the matching rule, use the DNS server corresponding to the rule to perform the query in sequence. If the DNS server that is hit fails to query or expectIPs does not match, then use the next hit DNS server to perform the query. Otherwise, return the resolved IP. If all hit DNS servers fail to query or expectIPs does not match, then the DNS component:

                                          • By default, it will perform "DNS fallback query": use the "DNS server that has not been used in the last failed query and has a default value of false for skipFallback" to perform the query in sequence. If the query fails or expectIPs does not match, return an empty resolution; otherwise, return the resolved IP.
                                          • If disableFallback is set to true, "DNS fallback query" will not be performed.
                                        • If neither hosts nor the domains list in DNS servers matches, then:

                                          • By default, use the "DNS server that has a default value of false for skipFallback" to perform the query in sequence. If the first selected DNS server fails to query or expectIPs does not match, then use the next selected DNS server to perform the query. Otherwise, return the resolved IP. If all selected DNS servers fail to query or expectIPs does not match, return an empty resolution.
                                          • If the number of "DNS servers that have a default value of false for skipFallback" is 0 or disableFallback is set to true, use the first DNS server in the DNS configuration to perform the query. If the query fails or expectIPs does not match, return an empty resolution; otherwise, return the resolved IP.

                                        DnsObject

                                        DnsObject corresponds to the dns section in the configuration file.

                                        {
                                        +import{_ as u,r as a,o as c,c as l,a as t,b as e,d as s,w as n,e as i}from"./app-Bw2NG-QJ.js";const d={},p=i(`

                                        Built-in DNS Server

                                        DNS Server

                                        The DNS module built into Xray has two main purposes:

                                        • During the routing phase, it resolves domain names to IP addresses and performs traffic splitting based on the results of domain name resolution and the value of domainStrategy in the routing configuration module. The built-in DNS server is only used for DNS queries when either of the following values is set:
                                          • "IPIfNonMatch": When a domain name is requested, it first tries to match it against the domain entries in the routing configuration. If no match is found, the built-in DNS server is used to perform a DNS query for the domain name, and the returned IP address is used to perform IP routing matching again.
                                          • "IPOnDemand": When a domain name is matched against any IP-based rule, it is immediately resolved to an IP address for matching.
                                        • It resolves the target address for connection.
                                          • In the freedom outbound setting, if domainStrategy is set to UseIP, requests made through the outbound proxy will first resolve the domain name to an IP address using the built-in server before making the connection.
                                          • In the sockopt setting, if domainStrategy is set to UseIP, system connections initiated through the outbound proxy will first be resolved to an IP address using the built-in server before making the connection.

                                        TIP 1

                                        DNS queries sent by the built-in DNS server are automatically forwarded based on the routing configuration.

                                        TIP 2

                                        Only basic IP queries (A and AAAA records) are supported. CNAME records will be queried repeatedly until an A/AAAA record is returned. Other queries will not enter the built-in DNS server.

                                        DNS Processing Flow

                                        If the domain name to be queried:

                                        • Matches the mapping of "domain name - IP" or "domain name - IP array" in the hosts, then the IP or IP array will be returned as the DNS resolution result.

                                        • Matches the mapping of "domain name - domain name" in the hosts, then the value of this mapping (another domain name) will be used as the domain name to be queried, and enter the DNS processing flow until an IP is resolved and returned, or an empty resolution is returned.

                                        • Does not match hosts, but matches the domains list in one or more DNS servers, then according to the priority of the matching rule, use the DNS server corresponding to the rule to perform the query in sequence. If the DNS server that is hit fails to query or expectIPs does not match, then use the next hit DNS server to perform the query. Otherwise, return the resolved IP. If all hit DNS servers fail to query or expectIPs does not match, then the DNS component:

                                          • By default, it will perform "DNS fallback query": use the "DNS server that has not been used in the last failed query and has a default value of false for skipFallback" to perform the query in sequence. If the query fails or expectIPs does not match, return an empty resolution; otherwise, return the resolved IP.
                                          • If disableFallback is set to true, "DNS fallback query" will not be performed.
                                        • If neither hosts nor the domains list in DNS servers matches, then:

                                          • By default, use the "DNS server that has a default value of false for skipFallback" to perform the query in sequence. If the first selected DNS server fails to query or expectIPs does not match, then use the next selected DNS server to perform the query. Otherwise, return the resolved IP. If all selected DNS servers fail to query or expectIPs does not match, return an empty resolution.
                                          • If the number of "DNS servers that have a default value of false for skipFallback" is 0 or disableFallback is set to true, use the first DNS server in the DNS configuration to perform the query. If the query fails or expectIPs does not match, return an empty resolution; otherwise, return the resolved IP.

                                        DnsObject

                                        DnsObject corresponds to the dns section in the configuration file.

                                        {
                                           "dns": {
                                             "hosts": {
                                               "baidu.com": "127.0.0.1",
                                        diff --git a/assets/dns.html-Rm3Jy1-p.js b/assets/dns.html-Dc7rS11a.js
                                        similarity index 98%
                                        rename from assets/dns.html-Rm3Jy1-p.js
                                        rename to assets/dns.html-Dc7rS11a.js
                                        index 4af036d366..fea3877bf6 100644
                                        --- a/assets/dns.html-Rm3Jy1-p.js
                                        +++ b/assets/dns.html-Dc7rS11a.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as n,o as d,c,a as t,b as e,d as o,w as p,e as u}from"./app-5SoadDYS.js";const l={},h=e("h1",{id:"dns",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#dns"},[e("span",null,"DNS")])],-1),q=e("p",null,"DNS is an outbound protocol used for intercepting and forwarding DNS queries.",-1),f=e("p",null,"This outbound protocol can only handle DNS traffic, including queries based on UDP and TCP protocols. Other types of traffic will result in an error.",-1),b=u(`

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as i,r as n,o as d,c,a as t,b as e,d as o,w as p,e as u}from"./app-Bw2NG-QJ.js";const l={},h=e("h1",{id:"dns",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#dns"},[e("span",null,"DNS")])],-1),q=e("p",null,"DNS is an outbound protocol used for intercepting and forwarding DNS queries.",-1),f=e("p",null,"This outbound protocol can only handle DNS traffic, including queries based on UDP and TCP protocols. Other types of traffic will result in an error.",-1),b=u(`

                                        OutboundConfigurationObject

                                        {
                                           "network": "tcp",
                                           "address": "1.1.1.1",
                                           "port": 53,
                                        diff --git a/assets/dns.html-YTRgF6GX.js b/assets/dns.html-Dh-LYENQ.js
                                        similarity index 99%
                                        rename from assets/dns.html-YTRgF6GX.js
                                        rename to assets/dns.html-Dh-LYENQ.js
                                        index 68e705e60d..fcc7d8dc1e 100644
                                        --- a/assets/dns.html-YTRgF6GX.js
                                        +++ b/assets/dns.html-Dh-LYENQ.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as p,o as l,c as d,a as o,b as s,d as n,w as e,e as t}from"./app-5SoadDYS.js";const i={},r=t(`

                                        内置 DNS 服务器

                                        DNS 服务器

                                        Xray 内置的 DNS 模块,主要有两大用途:

                                        • 在路由阶段, 解析域名为 IP, 并且根据域名解析得到的 IP 进行规则匹配以分流. 是否解析域名及分流和路由配置模块中 domainStrategy 的值有关, 只有在设置以下两种值时,才会使用内置 DNS 服务器进行 DNS 查询:

                                          • "IPIfNonMatch", 请求一个域名时,进行路由里面的 domain 进行匹配,若无法匹配到结果,则对这个域名使用内置 DNS 服务器进行 DNS 查询,并且使用查询返回的 IP 地址再重新进行 IP 路由匹配。
                                          • "IPOnDemand", 当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配。
                                        • 解析目标地址进行连接。

                                          • 如 在 freedom 出站中,将 domainStrategy 设置为 UseIP, 由此出站发出的请求, 会先将域名通过内置服务器解析成 IP, 然后进行连接。
                                          • 如 在 sockopt 中,将 domainStrategy 设置为 UseIP, 此出站发起的系统连接,将先由内置服务器解析为 IP, 然后进行连接。

                                        TIP 1

                                        内置 DNS 服务器所发出的 DNS 查询请求,会自动根据路由配置进行转发。

                                        TIP 2

                                        只支持最基本的 IP 查询(A 和 AAAA 记录),CNAME 记录将会重复查询直至返回 A/AAAA 记录为止。其他查询不会进入内置 DNS 服务器。

                                        DNS 处理流程

                                        若当前要查询的域名:

                                        • 命中了 hosts 中的「域名 - IP」、「域名 - IP 数组」映射,则将该 IP 或 IP 数组作为 DNS 解析结果返回。
                                        • 命中了 hosts 中的「域名 - 域名」映射,则该映射的值(另一个域名)将作为当前要查询的域名,进入 DNS 处理流程,直到解析出 IP 后返回,或返回空解析。
                                        • 没有命中 hosts,但命中了某(几)个 DNS 服务器中的 domains 域名列表,则按照命中的规则的优先级,依次使用该规则对应的 DNS 服务器进行查询。若命中的 DNS 服务器查询失败或 expectIPs 不匹配,则使用下一个命中的 DNS 服务器进行查询;否则返回解析得到的 IP。若所有命中的 DNS 服务器均查询失败或 expectIPs 不匹配,此时 DNS 组件:
                                          • 默认会进行 「DNS 回退(fallback)查询」:使用「上一轮失败查询中未被使用的、且 skipFallback 为默认值 false 的 DNS 服务器」依次查询。若查询失败或 expectIPs 不匹配,返回空解析;否则返回解析得到的 IP。
                                          • disableFallback 设置为 true,则不会进行「DNS 回退(fallback)查询」。
                                        • 既没有命中 hosts,又没有命中 DNS 服务器中的 domains 域名列表,则:
                                          • 默认使用「skipFallback 为默认值 false 的 DNS 服务器」依次查询。若第一个被选中的 DNS 服务器查询失败或 expectIPs 不匹配,则使用下一个被选中的 DNS 服务器进行查询;否则返回解析得到的 IP。若所有被选中的 DNS 服务器均查询失败或 expectIPs 不匹配,返回空解析。
                                          • 若「skipFallback 为默认值 false 的 DNS 服务器」数量为 0 或 disableFallback 设置为 true,则使用 DNS 配置中的第一个 DNS 服务器进行查询。查询失败或 expectIPs 不匹配,返回空解析;否则返回解析得到的 IP。

                                        DnsObject

                                        DnsObject 对应配置文件的 dns 项。

                                        {
                                        +import{_ as u,r as p,o as l,c as d,a as o,b as s,d as n,w as e,e as t}from"./app-Bw2NG-QJ.js";const i={},r=t(`

                                        内置 DNS 服务器

                                        DNS 服务器

                                        Xray 内置的 DNS 模块,主要有两大用途:

                                        • 在路由阶段, 解析域名为 IP, 并且根据域名解析得到的 IP 进行规则匹配以分流. 是否解析域名及分流和路由配置模块中 domainStrategy 的值有关, 只有在设置以下两种值时,才会使用内置 DNS 服务器进行 DNS 查询:

                                          • "IPIfNonMatch", 请求一个域名时,进行路由里面的 domain 进行匹配,若无法匹配到结果,则对这个域名使用内置 DNS 服务器进行 DNS 查询,并且使用查询返回的 IP 地址再重新进行 IP 路由匹配。
                                          • "IPOnDemand", 当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配。
                                        • 解析目标地址进行连接。

                                          • 如 在 freedom 出站中,将 domainStrategy 设置为 UseIP, 由此出站发出的请求, 会先将域名通过内置服务器解析成 IP, 然后进行连接。
                                          • 如 在 sockopt 中,将 domainStrategy 设置为 UseIP, 此出站发起的系统连接,将先由内置服务器解析为 IP, 然后进行连接。

                                        TIP 1

                                        内置 DNS 服务器所发出的 DNS 查询请求,会自动根据路由配置进行转发。

                                        TIP 2

                                        只支持最基本的 IP 查询(A 和 AAAA 记录),CNAME 记录将会重复查询直至返回 A/AAAA 记录为止。其他查询不会进入内置 DNS 服务器。

                                        DNS 处理流程

                                        若当前要查询的域名:

                                        • 命中了 hosts 中的「域名 - IP」、「域名 - IP 数组」映射,则将该 IP 或 IP 数组作为 DNS 解析结果返回。
                                        • 命中了 hosts 中的「域名 - 域名」映射,则该映射的值(另一个域名)将作为当前要查询的域名,进入 DNS 处理流程,直到解析出 IP 后返回,或返回空解析。
                                        • 没有命中 hosts,但命中了某(几)个 DNS 服务器中的 domains 域名列表,则按照命中的规则的优先级,依次使用该规则对应的 DNS 服务器进行查询。若命中的 DNS 服务器查询失败或 expectIPs 不匹配,则使用下一个命中的 DNS 服务器进行查询;否则返回解析得到的 IP。若所有命中的 DNS 服务器均查询失败或 expectIPs 不匹配,此时 DNS 组件:
                                          • 默认会进行 「DNS 回退(fallback)查询」:使用「上一轮失败查询中未被使用的、且 skipFallback 为默认值 false 的 DNS 服务器」依次查询。若查询失败或 expectIPs 不匹配,返回空解析;否则返回解析得到的 IP。
                                          • disableFallback 设置为 true,则不会进行「DNS 回退(fallback)查询」。
                                        • 既没有命中 hosts,又没有命中 DNS 服务器中的 domains 域名列表,则:
                                          • 默认使用「skipFallback 为默认值 false 的 DNS 服务器」依次查询。若第一个被选中的 DNS 服务器查询失败或 expectIPs 不匹配,则使用下一个被选中的 DNS 服务器进行查询;否则返回解析得到的 IP。若所有被选中的 DNS 服务器均查询失败或 expectIPs 不匹配,返回空解析。
                                          • 若「skipFallback 为默认值 false 的 DNS 服务器」数量为 0 或 disableFallback 设置为 true,则使用 DNS 配置中的第一个 DNS 服务器进行查询。查询失败或 expectIPs 不匹配,返回空解析;否则返回解析得到的 IP。

                                        DnsObject

                                        DnsObject 对应配置文件的 dns 项。

                                        {
                                           "dns": {
                                             "hosts": {
                                               "baidu.com": "127.0.0.1",
                                        diff --git a/assets/dns.html-Bv4y0xp3.js b/assets/dns.html-fTI6Udl3.js
                                        similarity index 98%
                                        rename from assets/dns.html-Bv4y0xp3.js
                                        rename to assets/dns.html-fTI6Udl3.js
                                        index a2a9b6d7f9..90c34ab779 100644
                                        --- a/assets/dns.html-Bv4y0xp3.js
                                        +++ b/assets/dns.html-fTI6Udl3.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as e,o as d,c as u,a as s,b as o,d as n,w as r,e as l}from"./app-5SoadDYS.js";const i={},q=o("h1",{id:"dns",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#dns"},[o("span",null,"DNS")])],-1),k=o("p",null,"DNS — это исходящий протокол, который в основном используется для перехвата и пересылки DNS-запросов.",-1),_=o("p",null,"Этот исходящий протокол может принимать только DNS-трафик (включая запросы по протоколам UDP и TCP), другие типы трафика будут вызывать ошибки.",-1),b=l(`

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as p,r as e,o as d,c as u,a as s,b as o,d as n,w as r,e as l}from"./app-Bw2NG-QJ.js";const i={},q=o("h1",{id:"dns",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#dns"},[o("span",null,"DNS")])],-1),k=o("p",null,"DNS — это исходящий протокол, который в основном используется для перехвата и пересылки DNS-запросов.",-1),_=o("p",null,"Этот исходящий протокол может принимать только DNS-трафик (включая запросы по протоколам UDP и TCP), другие типы трафика будут вызывать ошибки.",-1),b=l(`

                                        OutboundConfigurationObject

                                        {
                                           "network": "tcp",
                                           "address": "1.1.1.1",
                                           "port": 53,
                                        diff --git a/assets/document.html-DzcEysYS.js b/assets/document.html-BgS7tOmx.js
                                        similarity index 98%
                                        rename from assets/document.html-DzcEysYS.js
                                        rename to assets/document.html-BgS7tOmx.js
                                        index bb1d505493..f89375bdb0 100644
                                        --- a/assets/document.html-DzcEysYS.js
                                        +++ b/assets/document.html-BgS7tOmx.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as o,o as a,c as i,a as n,b as e,d as t,e as c}from"./app-5SoadDYS.js";const d={},u=e("h1",{id:"вклад-в-документацию-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#вклад-в-документацию-project-x"},[e("span",null,"Вклад в документацию Project X")])],-1),h=e("p",null,"Мы приветствуем ваш вклад в документацию Project X и благодарим каждого контрибьютора за помощь! Вы делаете Xray лучше!",-1),_=e("h2",{id:"улучшение-документации",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#улучшение-документации"},[e("span",null,"Улучшение документации")])],-1),p={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},b=e("p",null,"Вы можете внести изменения в документацию, выполнив следующие действия:",-1),g={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},x=e("li",null,[e("p",null,"Используйте любой удобный инструмент для клонирования документации из вашего репозитория, например:")],-1),m=c(`
                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                        +import{_ as s,r as o,o as a,c as i,a as n,b as e,d as t,e as c}from"./app-Bw2NG-QJ.js";const d={},u=e("h1",{id:"вклад-в-документацию-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#вклад-в-документацию-project-x"},[e("span",null,"Вклад в документацию Project X")])],-1),h=e("p",null,"Мы приветствуем ваш вклад в документацию Project X и благодарим каждого контрибьютора за помощь! Вы делаете Xray лучше!",-1),_=e("h2",{id:"улучшение-документации",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#улучшение-документации"},[e("span",null,"Улучшение документации")])],-1),p={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},b=e("p",null,"Вы можете внести изменения в документацию, выполнив следующие действия:",-1),g={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},x=e("li",null,[e("p",null,"Используйте любой удобный инструмент для клонирования документации из вашего репозитория, например:")],-1),m=c(`
                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                         
                                        1. Создайте новую ветку на основе ветки main, например:
                                        git checkout -b your-branch
                                         
                                        `,3),f={start:"4"},v=e("p",null,"Внесите изменения в новую ветку.",-1),X={href:"https://github.com/sparanoid/chinese-copywriting-guidelines",target:"_blank",rel:"noopener noreferrer"},k={href:"https://prettier.io/docs/en/install.html",target:"_blank",rel:"noopener noreferrer"},P=e("p",null,"Примечание: запросы на включение (PR) с ошибками форматирования могут быть отклонены.",-1),j=e("li",null,[e("p",null,"Зафиксируйте изменения и отправьте их в ваш репозиторий:")],-1),y=e("div",{class:"language-text line-numbers-mode","data-ext":"text","data-title":"text"},[e("pre",{class:"language-text"},[e("code",null,`git push -u origin your-branch `)]),e("div",{class:"line-numbers","aria-hidden":"true"},[e("div",{class:"line-number"})])],-1),T={start:"7"},L={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},I=e("li",null,[e("p",null,"В заголовке и описании PR кратко опишите внесенные изменения.")],-1),S={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},N=e("h2",{id:"нашли-ошибку",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#нашли-ошибку"},[e("span",null,"Нашли ошибку?")])],-1),R=e("p",null,"Если вы обнаружили ошибку в документации, вы можете внести исправления или создать задачу (Issue).",-1);function V(B,E){const r=o("I18nTip"),l=o("ExternalLinkIcon");return a(),i("div",null,[n(r),u,h,_,e("p",null,[t("Документация Project X размещена на "),e("a",p,[t("GitHub"),n(l)]),t(".")]),b,e("ol",null,[e("li",null,[e("p",null,[t("Откройте "),e("a",g,[t("репозиторий документации Project X"),n(l)]),t(', нажмите кнопку "Fork" в правом верхнем углу, чтобы создать копию репозитория документации в вашей учетной записи GitHub.')])]),x]),m,e("ol",f,[e("li",null,[v,e("p",null,[t("Примечание: рекомендуем придерживаться "),e("a",X,[t("Руководства по оформлению текстов на китайском языке"),n(l)]),t(" (на китайском).")])]),e("li",null,[e("p",null,[t("После внесения изменений отформатируйте их с помощью "),e("a",k,[t("Prettier"),n(l)]),t(".")]),P]),j]),y,e("ol",T,[e("li",null,[e("p",null,[t('Откройте GitHub, перейдите в раздел "Pull requests" и создайте новый запрос на включение (PR) в '),e("a",L,[t("репозиторий документации Project X"),n(l)]),t(".")])]),I,e("li",null,[e("p",null,[t("Дождитесь ответа. Если ваш PR будет принят, изменения появятся на "),e("a",S,[t("сайте документации Project X"),n(l)]),t(".")])])]),N,R])}const H=s(d,[["render",V],["__file","document.html.vue"]]);export{H as default}; diff --git a/assets/document.html-BoquODLh.js b/assets/document.html-DhUVedrJ.js similarity index 98% rename from assets/document.html-BoquODLh.js rename to assets/document.html-DhUVedrJ.js index 3450c49491..cb39d993db 100644 --- a/assets/document.html-BoquODLh.js +++ b/assets/document.html-DhUVedrJ.js @@ -1,4 +1,4 @@ -import{_ as s,r as l,o as a,c as i,a as n,b as e,d as t,e as c}from"./app-5SoadDYS.js";const d={},u=e("h1",{id:"为-project-x-的文档贡献",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#为-project-x-的文档贡献"},[e("span",null,"为 Project X 的文档贡献")])],-1),h=e("p",null,"欢迎您为 Project X 的文档做出贡献,我们感谢每一位 Contributor 的贡献!是你们让 Xray 更加强大!",-1),_=e("h2",{id:"改进文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#改进文档"},[e("span",null,"改进文档")])],-1),p={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"您可以通过以下步骤, 提交您对文档的改动:",-1),b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},m=e("li",null,[e("p",null,"使用任何您喜欢的工具, 从您克隆的仓库获得文档的克隆, 如:")],-1),x=c(`
                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                        +import{_ as s,r as l,o as a,c as i,a as n,b as e,d as t,e as c}from"./app-Bw2NG-QJ.js";const d={},u=e("h1",{id:"为-project-x-的文档贡献",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#为-project-x-的文档贡献"},[e("span",null,"为 Project X 的文档贡献")])],-1),h=e("p",null,"欢迎您为 Project X 的文档做出贡献,我们感谢每一位 Contributor 的贡献!是你们让 Xray 更加强大!",-1),_=e("h2",{id:"改进文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#改进文档"},[e("span",null,"改进文档")])],-1),p={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"您可以通过以下步骤, 提交您对文档的改动:",-1),b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},m=e("li",null,[e("p",null,"使用任何您喜欢的工具, 从您克隆的仓库获得文档的克隆, 如:")],-1),x=c(`
                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                         
                                        1. 基于 main 分支创建新的分支, 如:
                                        git checkout -b your-branch
                                         
                                        `,3),f={start:"4"},v=e("p",null,"在新分支上做修改。",-1),X={href:"https://github.com/sparanoid/chinese-copywriting-guidelines",target:"_blank",rel:"noopener noreferrer"},k={href:"https://prettier.io/docs/en/install.html",target:"_blank",rel:"noopener noreferrer"},P=e("p",null,"注:存在格式问题的 PR,将有可能被拒绝。",-1),j=e("li",null,[e("p",null,"提交修改,并推送到您的仓库中")],-1),y=e("div",{class:"language-text line-numbers-mode","data-ext":"text","data-title":"text"},[e("pre",{class:"language-text"},[e("code",null,`git push -u origin your-branch `)]),e("div",{class:"line-numbers","aria-hidden":"true"},[e("div",{class:"line-number"})])],-1),T={start:"6"},L={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},I=e("li",null,[e("p",null,"请在 PR 的标题和正文中,概述此次 PR 新增/修改的内容等;")],-1),R={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},S=e("h2",{id:"发现问题",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#发现问题"},[e("span",null,"发现问题?")])],-1),N=e("p",null,"如果您发现文档出错,可以改进文档或提交一个 Issue。",-1);function V(B,E){const r=l("I18nTip"),o=l("ExternalLinkIcon");return a(),i("div",null,[n(r),u,h,_,e("p",null,[t("Project X 的文档托管在 "),e("a",p,[t("GitHub"),n(o)]),t(" 上.")]),g,e("ol",null,[e("li",null,[e("p",null,[t("从 "),e("a",b,[t("Project X 文档仓库"),n(o)]),t(" 打开仓库, 点击右上角的 fork, fork 一份文档仓库的镜像到您自己的 github 仓库.")])]),m]),x,e("ol",f,[e("li",null,[v,e("p",null,[t("注:推荐 "),e("a",X,[t("中文文案排版指北"),n(o)])])]),e("li",null,[e("p",null,[t("修改完成后,请使用 "),e("a",k,[t("Prettier"),n(o)]),t(" 格式化您的更改。")]),P]),j]),y,e("ol",T,[e("li",null,[e("p",null,[t("打开 GitHub, 点击 'Pull request' 向 "),e("a",L,[t("Project X 文档仓库"),n(o)]),t(" 提交 PR。")])]),I,e("li",null,[e("p",null,[t("等待回应, 如果 PR 被 merge, 您做的修改将直接呈现在 "),e("a",R,[t("Project X 文档网站"),n(o)]),t("。")])])]),S,N])}const G=s(d,[["render",V],["__file","document.html.vue"]]);export{G as default}; diff --git a/assets/document.html-Bi2pgjPr.js b/assets/document.html-uNBJD12O.js similarity index 98% rename from assets/document.html-Bi2pgjPr.js rename to assets/document.html-uNBJD12O.js index 2f583a9a6a..4a7eae8346 100644 --- a/assets/document.html-Bi2pgjPr.js +++ b/assets/document.html-uNBJD12O.js @@ -1,4 +1,4 @@ -import{_ as l,r,o as i,c as a,a as o,b as e,d as t,e as c}from"./app-5SoadDYS.js";const u={},d=e("h1",{id:"contribute-to-project-x-s-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contribute-to-project-x-s-document"},[e("span",null,"Contribute to Project X's Document")])],-1),h=e("p",null,"Contributions to Project X's Document are welcome, and we appreciate every Contributor's contribution! You guys make Xray stronger!",-1),p=e("h2",{id:"improve-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#improve-document"},[e("span",null,"Improve Document")])],-1),m={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},_=e("p",null,"You can submit your changes to the Document by following these steps:",-1),b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,[e("p",null,"Get a clone of the docs from the repository you cloned using whatever tool you like, like:")],-1),f=c(`
                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                        +import{_ as l,r,o as i,c as a,a as o,b as e,d as t,e as c}from"./app-Bw2NG-QJ.js";const u={},d=e("h1",{id:"contribute-to-project-x-s-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contribute-to-project-x-s-document"},[e("span",null,"Contribute to Project X's Document")])],-1),h=e("p",null,"Contributions to Project X's Document are welcome, and we appreciate every Contributor's contribution! You guys make Xray stronger!",-1),p=e("h2",{id:"improve-document",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#improve-document"},[e("span",null,"Improve Document")])],-1),m={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},_=e("p",null,"You can submit your changes to the Document by following these steps:",-1),b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,[e("p",null,"Get a clone of the docs from the repository you cloned using whatever tool you like, like:")],-1),f=c(`
                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                         
                                        1. Create a new branch based on the main branch, such as:
                                        git checkout -b your-branch
                                         
                                        `,3),x={start:"4"},y=e("li",null,[e("p",null,"Make changes on the new branch.")],-1),v={href:"https://prettier.io/docs/en/install.html",target:"_blank",rel:"noopener noreferrer"},k=e("p",null,"Note: Pull requests with formatting issues may be rejected.",-1),X=e("li",null,[e("p",null,"Submit the changes and push them to your repository")],-1),P=e("div",{class:"language-text line-numbers-mode","data-ext":"text","data-title":"text"},[e("pre",{class:"language-text"},[e("code",null,`git push -u origin your-branch `)]),e("div",{class:"line-numbers","aria-hidden":"true"},[e("div",{class:"line-number"})])],-1),w={start:"6"},j={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},D=e("li",null,[e("p",null,"Please outline the new/modified content of this pull request in the title and body of the pull request;")],-1),T={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},q=e("h2",{id:"found-problems",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#found-problems"},[e("span",null,"Found Problems?")])],-1),I=e("p",null,"If you find an error in the document, you can improve the documentation or submit an issue.",-1);function L(S,C){const s=r("I18nTip"),n=r("ExternalLinkIcon");return i(),a("div",null,[o(s),d,h,p,e("p",null,[t("Document for Project X is hosted on "),e("a",m,[t("GitHub"),o(n)]),t(".")]),_,e("ol",null,[e("li",null,[e("p",null,[t("Open the repository from "),e("a",b,[t("Project X Document"),o(n)]),t(", click fork in the upper right corner, fork a mirror image of the document repository to your own GitHub repository.")])]),g]),f,e("ol",x,[y,e("li",null,[e("p",null,[t("After modification, please use "),e("a",v,[t("Prettier"),o(n)]),t("Format your changes.")]),k]),X]),P,e("ol",w,[e("li",null,[e("p",null,[t("Open GitHub, click 'Pull request' to submit a pull request to "),e("a",j,[t("Project X Document"),o(n)]),t(".")])]),D,e("li",null,[e("p",null,[t("Waiting for a response, if the pull request is merged, your changes will be directly displayed on "),e("a",T,[t("Project X Document Website"),o(n)]),t(".")])])]),q,I])}const G=l(u,[["render",L],["__file","document.html.vue"]]);export{G as default}; diff --git a/assets/dokodemo.html-Bt8oAJZq.js b/assets/dokodemo.html-BdfcwHNb.js similarity index 99% rename from assets/dokodemo.html-Bt8oAJZq.js rename to assets/dokodemo.html-BdfcwHNb.js index f88b778bb3..a703473a28 100644 --- a/assets/dokodemo.html-Bt8oAJZq.js +++ b/assets/dokodemo.html-BdfcwHNb.js @@ -1,4 +1,4 @@ -import{_ as l,r as t,o as r,c as u,a as o,b as s,d as n,w as e,e as p}from"./app-5SoadDYS.js";const d={},i=p(`

                                        Dokodemo-Door

                                        Dokodemo door может прослушивать локальный порт и отправлять все данные, поступающие на этот порт, на порт указанного сервера, тем самым реализуя перенаправление портов.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as l,r as t,o as r,c as u,a as o,b as s,d as n,w as e,e as p}from"./app-Bw2NG-QJ.js";const d={},i=p(`

                                        Dokodemo-Door

                                        Dokodemo door может прослушивать локальный порт и отправлять все данные, поступающие на этот порт, на порт указанного сервера, тем самым реализуя перенаправление портов.

                                        InboundConfigurationObject

                                        {
                                           "address": "8.8.8.8",
                                           "port": 53,
                                           "network": "tcp",
                                        diff --git a/assets/dokodemo.html-DgSj7rLG.js b/assets/dokodemo.html-BeyAN9oF.js
                                        similarity index 98%
                                        rename from assets/dokodemo.html-DgSj7rLG.js
                                        rename to assets/dokodemo.html-BeyAN9oF.js
                                        index 0b68dbe2c8..4d0d652180 100644
                                        --- a/assets/dokodemo.html-DgSj7rLG.js
                                        +++ b/assets/dokodemo.html-BeyAN9oF.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as s,o as p,c as i,a as t,b as o,d as e,w as a,e as l}from"./app-5SoadDYS.js";const d={},u=l(`

                                        Dokodemo-Door

                                        Dokodemo door (Anywhere Door) can listen to a local port and forward all incoming data on this port to a specified server's port, achieving the effect of port mapping.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as c,r as s,o as p,c as i,a as t,b as o,d as e,w as a,e as l}from"./app-Bw2NG-QJ.js";const d={},u=l(`

                                        Dokodemo-Door

                                        Dokodemo door (Anywhere Door) can listen to a local port and forward all incoming data on this port to a specified server's port, achieving the effect of port mapping.

                                        InboundConfigurationObject

                                        {
                                           "address": "8.8.8.8",
                                           "port": 53,
                                           "network": "tcp",
                                        diff --git a/assets/dokodemo.html-D2iCUcXO.js b/assets/dokodemo.html-C06CbLuo.js
                                        similarity index 99%
                                        rename from assets/dokodemo.html-D2iCUcXO.js
                                        rename to assets/dokodemo.html-C06CbLuo.js
                                        index 738704ff69..9020bd1871 100644
                                        --- a/assets/dokodemo.html-D2iCUcXO.js
                                        +++ b/assets/dokodemo.html-C06CbLuo.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as t,o as r,c as u,a as o,b as s,d as n,w as e,e as p}from"./app-5SoadDYS.js";const i={},d=p(`

                                        Dokodemo-Door

                                        Dokodemo door(任意门)可以监听一个本地端口,并把所有进入此端口的数据发送至指定服务器的一个端口,从而达到端口映射的效果。

                                        InboundConfigurationObject

                                        {
                                        +import{_ as l,r as t,o as r,c as u,a as o,b as s,d as n,w as e,e as p}from"./app-Bw2NG-QJ.js";const i={},d=p(`

                                        Dokodemo-Door

                                        Dokodemo door(任意门)可以监听一个本地端口,并把所有进入此端口的数据发送至指定服务器的一个端口,从而达到端口映射的效果。

                                        InboundConfigurationObject

                                        {
                                           "address": "8.8.8.8",
                                           "port": 53,
                                           "network": "tcp",
                                        diff --git a/assets/domainsocket.html-DOaqP0Hi.js b/assets/domainsocket.html-BAuPukib.js
                                        similarity index 98%
                                        rename from assets/domainsocket.html-DOaqP0Hi.js
                                        rename to assets/domainsocket.html-BAuPukib.js
                                        index e81a41cc79..4471d846f8 100644
                                        --- a/assets/domainsocket.html-DOaqP0Hi.js
                                        +++ b/assets/domainsocket.html-BAuPukib.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as n,o as p,c as i,a,b as e,d as o,w as d,e as l}from"./app-5SoadDYS.js";const r={},u=e("h1",{id:"domainsocket",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#domainsocket"},[e("span",null,"DomainSocket")])],-1),k={class:"custom-container danger"},m=e("p",{class:"custom-container-title"},"Предупреждение",-1),b=e("code",null,"listen",-1),_=l(`

                                        DomainSocket использует стандартные доменные сокеты Unix для передачи данных.

                                        Его преимущество заключается в использовании встроенного в операционную систему канала передачи, не занимающего сетевой буфер. Теоретически, по сравнению с локальной петлей (local loopback), доменный сокет работает немного быстрее.

                                        В настоящее время он доступен только на платформах, поддерживающих доменные сокеты Unix, таких как Linux и macOS. Недоступно в Windows 10 до сборки 17036.

                                        Если в качестве способа передачи указан DomainSocket, то порт и IP-адрес, настроенные во входящем и исходящем прокси, будут недействительны, и вся передача будет осуществляться через DomainSocket.

                                        DomainSocketObject

                                        DomainSocketObject соответствует элементу dsSettings конфигурации передачи.

                                        {
                                        +import{_ as c,r as n,o as p,c as i,a,b as e,d as o,w as d,e as l}from"./app-Bw2NG-QJ.js";const r={},u=e("h1",{id:"domainsocket",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#domainsocket"},[e("span",null,"DomainSocket")])],-1),k={class:"custom-container danger"},m=e("p",{class:"custom-container-title"},"Предупреждение",-1),b=e("code",null,"listen",-1),_=l(`

                                        DomainSocket использует стандартные доменные сокеты Unix для передачи данных.

                                        Его преимущество заключается в использовании встроенного в операционную систему канала передачи, не занимающего сетевой буфер. Теоретически, по сравнению с локальной петлей (local loopback), доменный сокет работает немного быстрее.

                                        В настоящее время он доступен только на платформах, поддерживающих доменные сокеты Unix, таких как Linux и macOS. Недоступно в Windows 10 до сборки 17036.

                                        Если в качестве способа передачи указан DomainSocket, то порт и IP-адрес, настроенные во входящем и исходящем прокси, будут недействительны, и вся передача будет осуществляться через DomainSocket.

                                        DomainSocketObject

                                        DomainSocketObject соответствует элементу dsSettings конфигурации передачи.

                                        {
                                           "path": "/path/to/ds/file",
                                           "abstract": false,
                                           "padding": false
                                        diff --git a/assets/domainsocket.html-D3nBLz-F.js b/assets/domainsocket.html-CudQIOhr.js
                                        similarity index 98%
                                        rename from assets/domainsocket.html-D3nBLz-F.js
                                        rename to assets/domainsocket.html-CudQIOhr.js
                                        index b99ad37dba..44dfadac83 100644
                                        --- a/assets/domainsocket.html-D3nBLz-F.js
                                        +++ b/assets/domainsocket.html-CudQIOhr.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as a,o as i,c as d,a as n,b as e,d as t,w as l,e as p}from"./app-5SoadDYS.js";const r={},u=e("h1",{id:"domain-socket",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#domain-socket"},[e("span",null,"Domain Socket")])],-1),h={class:"custom-container danger"},m=e("p",{class:"custom-container-title"},"Danger",-1),k=e("code",null,"listen",-1),b=e("p",null,"Note that the DomainSocket option here may be deprecated in the future.",-1),f=p(`

                                        Domain Socket uses standard Unix domain sockets to transmit data.

                                        The advantage of using DomainSocket is that it uses the built-in transport channel of the operating system and does not occupy the network cache. Theoretically, it is slightly faster than local loopback networks.

                                        Currently, it can only be used on platforms that support Unix domain sockets, such as Linux and macOS. It is not available until Windows 10 Build 17036.

                                        If DomainSocket is specified as the transport mode, the ports and IP addresses configured in the inbound and outbound proxies will be invalidated, and all transports will be replaced by DomainSocket.

                                        DomainSocketObject

                                        DomainSocketObject corresponds to the dsSettings item.

                                        {
                                        +import{_ as c,r as a,o as i,c as d,a as n,b as e,d as t,w as l,e as p}from"./app-Bw2NG-QJ.js";const r={},u=e("h1",{id:"domain-socket",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#domain-socket"},[e("span",null,"Domain Socket")])],-1),h={class:"custom-container danger"},m=e("p",{class:"custom-container-title"},"Danger",-1),k=e("code",null,"listen",-1),b=e("p",null,"Note that the DomainSocket option here may be deprecated in the future.",-1),f=p(`

                                        Domain Socket uses standard Unix domain sockets to transmit data.

                                        The advantage of using DomainSocket is that it uses the built-in transport channel of the operating system and does not occupy the network cache. Theoretically, it is slightly faster than local loopback networks.

                                        Currently, it can only be used on platforms that support Unix domain sockets, such as Linux and macOS. It is not available until Windows 10 Build 17036.

                                        If DomainSocket is specified as the transport mode, the ports and IP addresses configured in the inbound and outbound proxies will be invalidated, and all transports will be replaced by DomainSocket.

                                        DomainSocketObject

                                        DomainSocketObject corresponds to the dsSettings item.

                                        {
                                           "path": "/path/to/ds/file",
                                           "abstract": false,
                                           "padding": false
                                        diff --git a/assets/domainsocket.html-CaKSedJK.js b/assets/domainsocket.html-Dl3H8vlJ.js
                                        similarity index 97%
                                        rename from assets/domainsocket.html-CaKSedJK.js
                                        rename to assets/domainsocket.html-Dl3H8vlJ.js
                                        index 51094e147e..7f4f53a57f 100644
                                        --- a/assets/domainsocket.html-CaKSedJK.js
                                        +++ b/assets/domainsocket.html-Dl3H8vlJ.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as n,o as i,c as p,a,b as o,d as e,w as d,e as l}from"./app-5SoadDYS.js";const r={},u=o("h1",{id:"domain-socket",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#domain-socket"},[o("span",null,"Domain Socket")])],-1),k={class:"custom-container danger"},m=o("p",{class:"custom-container-title"},"警告",-1),b=o("code",null,"listen",-1),_=l(`

                                        Domain Socket 使用标准的 Unix domain socket 来传输数据。

                                        它的优势是使用了操作系统内建的传输通道,而不会占用网络缓存。 理论上相比起本地环回网络(local loopback)来说,Domain socket 速度略快一些。

                                        目前仅可用于支持 Unix domain socket 的平台,如 Linux 和 macOS。在 Windows 10 Build 17036 前不可用。

                                        如果指定了 domain socket 作为传输方式,在入站出站代理中配置的端口和 IP 地址将会失效,所有的传输由 domain socket 取代。

                                        DomainSocketObject

                                        DomainSocketObject 对应传输配置的 dsSettings 项。

                                        {
                                        +import{_ as c,r as n,o as i,c as p,a,b as o,d as e,w as d,e as l}from"./app-Bw2NG-QJ.js";const r={},u=o("h1",{id:"domain-socket",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#domain-socket"},[o("span",null,"Domain Socket")])],-1),k={class:"custom-container danger"},m=o("p",{class:"custom-container-title"},"警告",-1),b=o("code",null,"listen",-1),_=l(`

                                        Domain Socket 使用标准的 Unix domain socket 来传输数据。

                                        它的优势是使用了操作系统内建的传输通道,而不会占用网络缓存。 理论上相比起本地环回网络(local loopback)来说,Domain socket 速度略快一些。

                                        目前仅可用于支持 Unix domain socket 的平台,如 Linux 和 macOS。在 Windows 10 Build 17036 前不可用。

                                        如果指定了 domain socket 作为传输方式,在入站出站代理中配置的端口和 IP 地址将会失效,所有的传输由 domain socket 取代。

                                        DomainSocketObject

                                        DomainSocketObject 对应传输配置的 dsSettings 项。

                                        {
                                           "path": "/path/to/ds/file",
                                           "abstract": false,
                                           "padding": false
                                        diff --git a/assets/edges-066a5561-BnmFWp88.js b/assets/edges-066a5561-CIBMFaLO.js
                                        similarity index 99%
                                        rename from assets/edges-066a5561-BnmFWp88.js
                                        rename to assets/edges-066a5561-CIBMFaLO.js
                                        index dc21bc0932..194837731f 100644
                                        --- a/assets/edges-066a5561-BnmFWp88.js
                                        +++ b/assets/edges-066a5561-CIBMFaLO.js
                                        @@ -1,4 +1,4 @@
                                        -import{q as H,c as b,d as V,an as q,h as E,l as g,z as j,ao as lt}from"./mermaid.core-CArNAncI.js";import{c as st}from"./createText-ca0c5216-X7RVUogw.js";import{l as ct}from"./line-BIqtvXUi.js";const ht=(e,t,a,i)=>{t.forEach(l=>{wt[l](e,a,i)})},ot=(e,t,a)=>{g.trace("Making markers for ",a),e.append("defs").append("marker").attr("id",a+"_"+t+"-extensionStart").attr("class","marker extension "+t).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-extensionEnd").attr("class","marker extension "+t).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z")},yt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-compositionStart").attr("class","marker composition "+t).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-compositionEnd").attr("class","marker composition "+t).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},pt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-aggregationStart").attr("class","marker aggregation "+t).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-aggregationEnd").attr("class","marker aggregation "+t).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},ft=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-dependencyStart").attr("class","marker dependency "+t).attr("refX",6).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-dependencyEnd").attr("class","marker dependency "+t).attr("refX",13).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},xt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-lollipopStart").attr("class","marker lollipop "+t).attr("refX",13).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","transparent").attr("cx",7).attr("cy",7).attr("r",6),e.append("defs").append("marker").attr("id",a+"_"+t+"-lollipopEnd").attr("class","marker lollipop "+t).attr("refX",1).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","transparent").attr("cx",7).attr("cy",7).attr("r",6)},dt=(e,t,a)=>{e.append("marker").attr("id",a+"_"+t+"-pointEnd").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",6).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),e.append("marker").attr("id",a+"_"+t+"-pointStart").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",4.5).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 5 L 10 10 L 10 0 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},gt=(e,t,a)=>{e.append("marker").attr("id",a+"_"+t+"-circleEnd").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",11).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),e.append("marker").attr("id",a+"_"+t+"-circleStart").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",-1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},ut=(e,t,a)=>{e.append("marker").attr("id",a+"_"+t+"-crossEnd").attr("class","marker cross "+t).attr("viewBox","0 0 11 11").attr("refX",12).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0"),e.append("marker").attr("id",a+"_"+t+"-crossStart").attr("class","marker cross "+t).attr("viewBox","0 0 11 11").attr("refX",-1).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0")},bt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-barbEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",14).attr("markerUnits","strokeWidth").attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")},wt={extension:ot,composition:yt,aggregation:pt,dependency:ft,lollipop:xt,point:dt,circle:gt,cross:ut,barb:bt},hr=ht;function mt(e,t){t&&e.attr("style",t)}function kt(e){const t=E(document.createElementNS("http://www.w3.org/2000/svg","foreignObject")),a=t.append("xhtml:div"),i=e.label,l=e.isNode?"nodeLabel":"edgeLabel";return a.html('"+i+""),mt(a,e.labelStyle),a.style("display","inline-block"),a.style("white-space","nowrap"),a.attr("xmlns","http://www.w3.org/1999/xhtml"),t.node()}const vt=(e,t,a,i)=>{let l=e||"";if(typeof l=="object"&&(l=l[0]),H(b().flowchart.htmlLabels)){l=l.replace(/\\n|\n/g,"
                                        "),g.debug("vertexText"+l);const r={isNode:i,label:q(l).replace(/fa[blrs]?:fa-[\w-]+/g,n=>``),labelStyle:t.replace("fill:","color:")};return kt(r)}else{const r=document.createElementNS("http://www.w3.org/2000/svg","text");r.setAttribute("style",t.replace("color:","fill:"));let s=[];typeof l=="string"?s=l.split(/\\n|\n|/gi):Array.isArray(l)?s=l:s=[];for(const n of s){const c=document.createElementNS("http://www.w3.org/2000/svg","tspan");c.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),c.setAttribute("dy","1em"),c.setAttribute("x","0"),a?c.setAttribute("class","title-row"):c.setAttribute("class","row"),c.textContent=n.trim(),r.appendChild(c)}return r}},R=vt,M=async(e,t,a,i)=>{let l;const r=t.useHtmlLabels||H(b().flowchart.htmlLabels);a?l=a:l="node default";const s=e.insert("g").attr("class",l).attr("id",t.domId||t.id),n=s.insert("g").attr("class","label").attr("style",t.labelStyle);let c;t.labelText===void 0?c="":c=typeof t.labelText=="string"?t.labelText:t.labelText[0];const o=n.node();let h;t.labelType==="markdown"?h=st(n,V(q(c),b()),{useHtmlLabels:r,width:t.width||b().flowchart.wrappingWidth,classes:"markdown-node-label"}):h=o.appendChild(R(V(q(c),b()),t.labelStyle,!1,i));let y=h.getBBox();const f=t.padding/2;if(H(b().flowchart.htmlLabels)){const p=h.children[0],d=E(h),k=p.getElementsByTagName("img");if(k){const x=c.replace(/]*>/g,"").trim()==="";await Promise.all([...k].map(u=>new Promise(S=>{function B(){if(u.style.display="flex",u.style.flexDirection="column",x){const C=b().fontSize?b().fontSize:window.getComputedStyle(document.body).fontSize,D=parseInt(C,10)*5+"px";u.style.minWidth=D,u.style.maxWidth=D}else u.style.width="100%";S(u)}setTimeout(()=>{u.complete&&B()}),u.addEventListener("error",B),u.addEventListener("load",B)})))}y=p.getBoundingClientRect(),d.attr("width",y.width),d.attr("height",y.height)}return r?n.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"):n.attr("transform","translate(0, "+-y.height/2+")"),t.centerLabel&&n.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),n.insert("rect",":first-child"),{shapeSvg:s,bbox:y,halfPadding:f,label:n}},m=(e,t)=>{const a=t.node().getBBox();e.width=a.width,e.height=a.height};function I(e,t,a,i){return e.insert("polygon",":first-child").attr("points",i.map(function(l){return l.x+","+l.y}).join(" ")).attr("class","label-container").attr("transform","translate("+-t/2+","+a/2+")")}function Lt(e,t){return e.intersect(t)}function it(e,t,a,i){var l=e.x,r=e.y,s=l-i.x,n=r-i.y,c=Math.sqrt(t*t*n*n+a*a*s*s),o=Math.abs(t*a*s/c);i.x0}function Tt(e,t,a){var i=e.x,l=e.y,r=[],s=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY;typeof t.forEach=="function"?t.forEach(function(d){s=Math.min(s,d.x),n=Math.min(n,d.y)}):(s=Math.min(s,t.x),n=Math.min(n,t.y));for(var c=i-e.width/2-s,o=l-e.height/2-n,h=0;h1&&r.sort(function(d,k){var x=d.x-a.x,u=d.y-a.y,S=Math.sqrt(x*x+u*u),B=k.x-a.x,C=k.y-a.y,X=Math.sqrt(B*B+C*C);return S{var a=e.x,i=e.y,l=t.x-a,r=t.y-i,s=e.width/2,n=e.height/2,c,o;return Math.abs(r)*s>Math.abs(l)*n?(r<0&&(n=-n),c=r===0?0:n*l/r,o=n):(l<0&&(s=-s),c=s,o=l===0?0:s*r/l),{x:a+c,y:i+o}},Et=Bt,w={node:Lt,circle:St,ellipse:it,polygon:Tt,rect:Et},Ct=async(e,t)=>{t.useHtmlLabels||b().flowchart.htmlLabels||(t.centerLabel=!0);const{shapeSvg:i,bbox:l,halfPadding:r}=await M(e,t,"node "+t.classes,!0);g.info("Classes = ",t.classes);const s=i.insert("rect",":first-child");return s.attr("rx",t.rx).attr("ry",t.ry).attr("x",-l.width/2-r).attr("y",-l.height/2-r).attr("width",l.width+t.padding).attr("height",l.height+t.padding),m(t,s),t.intersect=function(n){return w.rect(t,n)},i},$t=Ct,_t=e=>{const t=new Set;for(const a of e)switch(a){case"x":t.add("right"),t.add("left");break;case"y":t.add("up"),t.add("down");break;default:t.add(a);break}return t},Rt=(e,t,a)=>{const i=_t(e),l=2,r=t.height+2*a.padding,s=r/l,n=t.width+2*s+a.padding,c=a.padding/2;return i.has("right")&&i.has("left")&&i.has("up")&&i.has("down")?[{x:0,y:0},{x:s,y:0},{x:n/2,y:2*c},{x:n-s,y:0},{x:n,y:0},{x:n,y:-r/3},{x:n+2*c,y:-r/2},{x:n,y:-2*r/3},{x:n,y:-r},{x:n-s,y:-r},{x:n/2,y:-r-2*c},{x:s,y:-r},{x:0,y:-r},{x:0,y:-2*r/3},{x:-2*c,y:-r/2},{x:0,y:-r/3}]:i.has("right")&&i.has("left")&&i.has("up")?[{x:s,y:0},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:s,y:-r},{x:0,y:-r/2}]:i.has("right")&&i.has("left")&&i.has("down")?[{x:0,y:0},{x:s,y:-r},{x:n-s,y:-r},{x:n,y:0}]:i.has("right")&&i.has("up")&&i.has("down")?[{x:0,y:0},{x:n,y:-s},{x:n,y:-r+s},{x:0,y:-r}]:i.has("left")&&i.has("up")&&i.has("down")?[{x:n,y:0},{x:0,y:-s},{x:0,y:-r+s},{x:n,y:-r}]:i.has("right")&&i.has("left")?[{x:s,y:0},{x:s,y:-c},{x:n-s,y:-c},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:n-s,y:-r+c},{x:s,y:-r+c},{x:s,y:-r},{x:0,y:-r/2}]:i.has("up")&&i.has("down")?[{x:n/2,y:0},{x:0,y:-c},{x:s,y:-c},{x:s,y:-r+c},{x:0,y:-r+c},{x:n/2,y:-r},{x:n,y:-r+c},{x:n-s,y:-r+c},{x:n-s,y:-c},{x:n,y:-c}]:i.has("right")&&i.has("up")?[{x:0,y:0},{x:n,y:-s},{x:0,y:-r}]:i.has("right")&&i.has("down")?[{x:0,y:0},{x:n,y:0},{x:0,y:-r}]:i.has("left")&&i.has("up")?[{x:n,y:0},{x:0,y:-s},{x:n,y:-r}]:i.has("left")&&i.has("down")?[{x:n,y:0},{x:0,y:0},{x:n,y:-r}]:i.has("right")?[{x:s,y:-c},{x:s,y:-c},{x:n-s,y:-c},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:n-s,y:-r+c},{x:s,y:-r+c},{x:s,y:-r+c}]:i.has("left")?[{x:s,y:0},{x:s,y:-c},{x:n-s,y:-c},{x:n-s,y:-r+c},{x:s,y:-r+c},{x:s,y:-r},{x:0,y:-r/2}]:i.has("up")?[{x:s,y:-c},{x:s,y:-r+c},{x:0,y:-r+c},{x:n/2,y:-r},{x:n,y:-r+c},{x:n-s,y:-r+c},{x:n-s,y:-c}]:i.has("down")?[{x:n/2,y:0},{x:0,y:-c},{x:s,y:-c},{x:s,y:-r+c},{x:n-s,y:-r+c},{x:n-s,y:-c},{x:n,y:-c}]:[{x:0,y:0}]},K=e=>e?" "+e:"",_=(e,t)=>`node default${K(e.classes)} ${K(e.class)}`,P=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=l+r,n=[{x:s/2,y:0},{x:s,y:-s/2},{x:s/2,y:-s},{x:0,y:-s/2}];g.info("Question main (Circle)");const c=I(a,s,s,n);return c.attr("style",t.style),m(t,c),t.intersect=function(o){return g.warn("Intersect called"),w.polygon(t,n,o)},a},Ht=(e,t)=>{const a=e.insert("g").attr("class","node default").attr("id",t.domId||t.id),i=28,l=[{x:0,y:i/2},{x:i/2,y:0},{x:0,y:-i/2},{x:-i/2,y:0}];return a.insert("polygon",":first-child").attr("points",l.map(function(s){return s.x+","+s.y}).join(" ")).attr("class","state-start").attr("r",7).attr("width",28).attr("height",28),t.width=28,t.height=28,t.intersect=function(s){return w.circle(t,14,s)},a},It=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=4,r=i.height+t.padding,s=r/l,n=i.width+2*s+t.padding,c=[{x:s,y:0},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:s,y:-r},{x:0,y:-r/2}],o=I(a,n,r,c);return o.attr("style",t.style),m(t,o),t.intersect=function(h){return w.polygon(t,c,h)},a},Nt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,void 0,!0),l=2,r=i.height+2*t.padding,s=r/l,n=i.width+2*s+t.padding,c=Rt(t.directions,i,t),o=I(a,n,r,c);return o.attr("style",t.style),m(t,o),t.intersect=function(h){return w.polygon(t,c,h)},a},Ot=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:-r/2,y:0},{x:l,y:0},{x:l,y:-r},{x:-r/2,y:-r},{x:0,y:-r/2}];return I(a,l,r,s).attr("style",t.style),t.width=l+r,t.height=r,t.intersect=function(c){return w.polygon(t,s,c)},a},Wt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:-2*r/6,y:0},{x:l-r/6,y:0},{x:l+2*r/6,y:-r},{x:r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Xt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:2*r/6,y:0},{x:l+r/6,y:0},{x:l-2*r/6,y:-r},{x:-r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Yt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:-2*r/6,y:0},{x:l+2*r/6,y:0},{x:l-r/6,y:-r},{x:r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Dt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:r/6,y:0},{x:l-r/6,y:0},{x:l+2*r/6,y:-r},{x:-2*r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},At=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:0,y:0},{x:l+r/2,y:0},{x:l,y:-r/2},{x:l+r/2,y:-r},{x:0,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},jt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=l/2,s=r/(2.5+l/50),n=i.height+s+t.padding,c="M 0,"+s+" a "+r+","+s+" 0,0,0 "+l+" 0 a "+r+","+s+" 0,0,0 "+-l+" 0 l 0,"+n+" a "+r+","+s+" 0,0,0 "+l+" 0 l 0,"+-n,o=a.attr("label-offset-y",s).insert("path",":first-child").attr("style",t.style).attr("d",c).attr("transform","translate("+-l/2+","+-(n/2+s)+")");return m(t,o),t.intersect=function(h){const y=w.rect(t,h),f=y.x-t.x;if(r!=0&&(Math.abs(f)t.height/2-s)){let p=s*s*(1-f*f/(r*r));p!=0&&(p=Math.sqrt(p)),p=s-p,h.y-t.y>0&&(p=-p),y.y+=p}return y},a},Ut=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,"node "+t.classes+" "+t.class,!0),r=a.insert("rect",":first-child"),s=t.positioned?t.width:i.width+t.padding,n=t.positioned?t.height:i.height+t.padding,c=t.positioned?-s/2:-i.width/2-l,o=t.positioned?-n/2:-i.height/2-l;if(r.attr("class","basic label-container").attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("x",c).attr("y",o).attr("width",s).attr("height",n),t.props){const h=new Set(Object.keys(t.props));t.props.borders&&(Q(r,t.props.borders,s,n),h.delete("borders")),h.forEach(y=>{g.warn(`Unknown node property ${y}`)})}return m(t,r),t.intersect=function(h){return w.rect(t,h)},a},zt=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,"node "+t.classes,!0),r=a.insert("rect",":first-child"),s=t.positioned?t.width:i.width+t.padding,n=t.positioned?t.height:i.height+t.padding,c=t.positioned?-s/2:-i.width/2-l,o=t.positioned?-n/2:-i.height/2-l;if(r.attr("class","basic cluster composite label-container").attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("x",c).attr("y",o).attr("width",s).attr("height",n),t.props){const h=new Set(Object.keys(t.props));t.props.borders&&(Q(r,t.props.borders,s,n),h.delete("borders")),h.forEach(y=>{g.warn(`Unknown node property ${y}`)})}return m(t,r),t.intersect=function(h){return w.rect(t,h)},a},Zt=async(e,t)=>{const{shapeSvg:a}=await M(e,t,"label",!0);g.trace("Classes = ",t.class);const i=a.insert("rect",":first-child"),l=0,r=0;if(i.attr("width",l).attr("height",r),a.attr("class","label edgeLabel"),t.props){const s=new Set(Object.keys(t.props));t.props.borders&&(Q(i,t.props.borders,l,r),s.delete("borders")),s.forEach(n=>{g.warn(`Unknown node property ${n}`)})}return m(t,i),t.intersect=function(s){return w.rect(t,s)},a};function Q(e,t,a,i){const l=[],r=n=>{l.push(n,0)},s=n=>{l.push(0,n)};t.includes("t")?(g.debug("add top border"),r(a)):s(a),t.includes("r")?(g.debug("add right border"),r(i)):s(i),t.includes("b")?(g.debug("add bottom border"),r(a)):s(a),t.includes("l")?(g.debug("add left border"),r(i)):s(i),e.attr("stroke-dasharray",l.join(" "))}const Gt=(e,t)=>{let a;t.classes?a="node "+t.classes:a="node default";const i=e.insert("g").attr("class",a).attr("id",t.domId||t.id),l=i.insert("rect",":first-child"),r=i.insert("line"),s=i.insert("g").attr("class","label"),n=t.labelText.flat?t.labelText.flat():t.labelText;let c="";typeof n=="object"?c=n[0]:c=n,g.info("Label text abc79",c,n,typeof n=="object");const o=s.node().appendChild(R(c,t.labelStyle,!0,!0));let h={width:0,height:0};if(H(b().flowchart.htmlLabels)){const k=o.children[0],x=E(o);h=k.getBoundingClientRect(),x.attr("width",h.width),x.attr("height",h.height)}g.info("Text 2",n);const y=n.slice(1,n.length);let f=o.getBBox();const p=s.node().appendChild(R(y.join?y.join("
                                        "):y,t.labelStyle,!0,!0));if(H(b().flowchart.htmlLabels)){const k=p.children[0],x=E(p);h=k.getBoundingClientRect(),x.attr("width",h.width),x.attr("height",h.height)}const d=t.padding/2;return E(p).attr("transform","translate( "+(h.width>f.width?0:(f.width-h.width)/2)+", "+(f.height+d+5)+")"),E(o).attr("transform","translate( "+(h.width{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.height+t.padding,r=i.width+l/4+t.padding,s=a.insert("rect",":first-child").attr("style",t.style).attr("rx",l/2).attr("ry",l/2).attr("x",-r/2).attr("y",-l/2).attr("width",r).attr("height",l);return m(t,s),t.intersect=function(n){return w.rect(t,n)},a},qt=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,_(t),!0),r=a.insert("circle",":first-child");return r.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("r",i.width/2+l).attr("width",i.width+t.padding).attr("height",i.height+t.padding),g.info("Circle main"),m(t,r),t.intersect=function(s){return g.info("Circle intersect",t,i.width/2+l,s),w.circle(t,i.width/2+l,s)},a},Qt=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,_(t),!0),r=5,s=a.insert("g",":first-child"),n=s.insert("circle"),c=s.insert("circle");return s.attr("class",t.class),n.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("r",i.width/2+l+r).attr("width",i.width+t.padding+r*2).attr("height",i.height+t.padding+r*2),c.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("r",i.width/2+l).attr("width",i.width+t.padding).attr("height",i.height+t.padding),g.info("DoubleCircle main"),m(t,n),t.intersect=function(o){return g.info("DoubleCircle intersect",t,i.width/2+l+r,o),w.circle(t,i.width/2+l+r,o)},a},Vt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:0,y:0},{x:l,y:0},{x:l,y:-r},{x:0,y:-r},{x:0,y:0},{x:-8,y:0},{x:l+8,y:0},{x:l+8,y:-r},{x:-8,y:-r},{x:-8,y:0}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Jt=(e,t)=>{const a=e.insert("g").attr("class","node default").attr("id",t.domId||t.id),i=a.insert("circle",":first-child");return i.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),m(t,i),t.intersect=function(l){return w.circle(t,7,l)},a},tt=(e,t,a)=>{const i=e.insert("g").attr("class","node default").attr("id",t.domId||t.id);let l=70,r=10;a==="LR"&&(l=10,r=70);const s=i.append("rect").attr("x",-1*l/2).attr("y",-1*r/2).attr("width",l).attr("height",r).attr("class","fork-join");return m(t,s),t.height=t.height+t.padding/2,t.width=t.width+t.padding/2,t.intersect=function(n){return w.rect(t,n)},i},Kt=(e,t)=>{const a=e.insert("g").attr("class","node default").attr("id",t.domId||t.id),i=a.insert("circle",":first-child"),l=a.insert("circle",":first-child");return l.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),i.attr("class","state-end").attr("r",5).attr("width",10).attr("height",10),m(t,l),t.intersect=function(r){return w.circle(t,7,r)},a},Pt=(e,t)=>{const a=t.padding/2,i=4,l=8;let r;t.classes?r="node "+t.classes:r="node default";const s=e.insert("g").attr("class",r).attr("id",t.domId||t.id),n=s.insert("rect",":first-child"),c=s.insert("line"),o=s.insert("line");let h=0,y=i;const f=s.insert("g").attr("class","label");let p=0;const d=t.classData.annotations&&t.classData.annotations[0],k=t.classData.annotations[0]?"«"+t.classData.annotations[0]+"»":"",x=f.node().appendChild(R(k,t.labelStyle,!0,!0));let u=x.getBBox();if(H(b().flowchart.htmlLabels)){const v=x.children[0],L=E(x);u=v.getBoundingClientRect(),L.attr("width",u.width),L.attr("height",u.height)}t.classData.annotations[0]&&(y+=u.height+i,h+=u.width);let S=t.classData.label;t.classData.type!==void 0&&t.classData.type!==""&&(b().flowchart.htmlLabels?S+="<"+t.classData.type+">":S+="<"+t.classData.type+">");const B=f.node().appendChild(R(S,t.labelStyle,!0,!0));E(B).attr("class","classTitle");let C=B.getBBox();if(H(b().flowchart.htmlLabels)){const v=B.children[0],L=E(B);C=v.getBoundingClientRect(),L.attr("width",C.width),L.attr("height",C.height)}y+=C.height+i,C.width>h&&(h=C.width);const X=[];t.classData.members.forEach(v=>{const L=v.getDisplayDetails();let W=L.displayText;b().flowchart.htmlLabels&&(W=W.replace(//g,">"));const N=f.node().appendChild(R(W,L.cssStyle?L.cssStyle:t.labelStyle,!0,!0));let $=N.getBBox();if(H(b().flowchart.htmlLabels)){const F=N.children[0],A=E(N);$=F.getBoundingClientRect(),A.attr("width",$.width),A.attr("height",$.height)}$.width>h&&(h=$.width),y+=$.height+i,X.push(N)}),y+=l;const D=[];if(t.classData.methods.forEach(v=>{const L=v.getDisplayDetails();let W=L.displayText;b().flowchart.htmlLabels&&(W=W.replace(//g,">"));const N=f.node().appendChild(R(W,L.cssStyle?L.cssStyle:t.labelStyle,!0,!0));let $=N.getBBox();if(H(b().flowchart.htmlLabels)){const F=N.children[0],A=E(N);$=F.getBoundingClientRect(),A.attr("width",$.width),A.attr("height",$.height)}$.width>h&&(h=$.width),y+=$.height+i,D.push(N)}),y+=l,d){let v=(h-u.width)/2;E(x).attr("transform","translate( "+(-1*h/2+v)+", "+-1*y/2+")"),p=u.height+i}let nt=(h-C.width)/2;return E(B).attr("transform","translate( "+(-1*h/2+nt)+", "+(-1*y/2+p)+")"),p+=C.height+i,c.attr("class","divider").attr("x1",-h/2-a).attr("x2",h/2+a).attr("y1",-y/2-a+l+p).attr("y2",-y/2-a+l+p),p+=l,X.forEach(v=>{E(v).attr("transform","translate( "+-h/2+", "+(-1*y/2+p+l/2)+")");const L=v==null?void 0:v.getBBox();p+=((L==null?void 0:L.height)??0)+i}),p+=l,o.attr("class","divider").attr("x1",-h/2-a).attr("x2",h/2+a).attr("y1",-y/2-a+l+p).attr("y2",-y/2-a+l+p),p+=l,D.forEach(v=>{E(v).attr("transform","translate( "+-h/2+", "+(-1*y/2+p)+")");const L=v==null?void 0:v.getBBox();p+=((L==null?void 0:L.height)??0)+i}),n.attr("style",t.style).attr("class","outer title-state").attr("x",-h/2-a).attr("y",-(y/2)-a).attr("width",h+t.padding).attr("height",y+t.padding),m(t,n),t.intersect=function(v){return w.rect(t,v)},s},rt={rhombus:P,composite:zt,question:P,rect:Ut,labelRect:Zt,rectWithTitle:Gt,choice:Ht,circle:qt,doublecircle:Qt,stadium:Ft,hexagon:It,block_arrow:Nt,rect_left_inv_arrow:Ot,lean_right:Wt,lean_left:Xt,trapezoid:Yt,inv_trapezoid:Dt,rect_right_inv_arrow:At,cylinder:jt,start:Jt,end:Kt,note:$t,subroutine:Vt,fork:tt,join:tt,class_box:Pt};let Y={};const or=async(e,t,a)=>{let i,l;if(t.link){let r;b().securityLevel==="sandbox"?r="_top":t.linkTarget&&(r=t.linkTarget||"_blank"),i=e.insert("svg:a").attr("xlink:href",t.link).attr("target",r),l=await rt[t.shape](i,t,a)}else l=await rt[t.shape](e,t,a),i=l;return t.tooltip&&l.attr("title",t.tooltip),t.class&&l.attr("class","node default "+t.class),i.attr("data-node","true"),i.attr("data-id",t.id),Y[t.id]=i,t.haveCallback&&Y[t.id].attr("class",Y[t.id].attr("class")+" clickable"),i},yr=(e,t)=>{Y[t.id]=e},pr=()=>{Y={}},fr=e=>{const t=Y[e.id];g.trace("Transforming node",e.diff,e,"translate("+(e.x-e.width/2-5)+", "+e.width/2+")");const a=8,i=e.diff||0;return e.clusterNode?t.attr("transform","translate("+(e.x+i-e.width/2)+", "+(e.y-e.height/2-a)+")"):t.attr("transform","translate("+e.x+", "+e.y+")"),i},tr=({flowchart:e})=>{var t,a;const i=((t=e==null?void 0:e.subGraphTitleMargin)==null?void 0:t.top)??0,l=((a=e==null?void 0:e.subGraphTitleMargin)==null?void 0:a.bottom)??0,r=i+l;return{subGraphTitleTopMargin:i,subGraphTitleBottomMargin:l,subGraphTitleTotalMargin:r}},O={aggregation:18,extension:18,composition:18,dependency:6,lollipop:13.5,arrow_point:5.3};function U(e,t){if(e===void 0||t===void 0)return{angle:0,deltaX:0,deltaY:0};e=Z(e),t=Z(t);const[a,i]=[e.x,e.y],[l,r]=[t.x,t.y],s=l-a,n=r-i;return{angle:Math.atan(n/s),deltaX:s,deltaY:n}}const Z=e=>Array.isArray(e)?{x:e[0],y:e[1]}:e,rr=e=>({x:function(t,a,i){let l=0;if(a===0&&Object.hasOwn(O,e.arrowTypeStart)){const{angle:r,deltaX:s}=U(i[0],i[1]);l=O[e.arrowTypeStart]*Math.cos(r)*(s>=0?1:-1)}else if(a===i.length-1&&Object.hasOwn(O,e.arrowTypeEnd)){const{angle:r,deltaX:s}=U(i[i.length-1],i[i.length-2]);l=O[e.arrowTypeEnd]*Math.cos(r)*(s>=0?1:-1)}return Z(t).x+l},y:function(t,a,i){let l=0;if(a===0&&Object.hasOwn(O,e.arrowTypeStart)){const{angle:r,deltaY:s}=U(i[0],i[1]);l=O[e.arrowTypeStart]*Math.abs(Math.sin(r))*(s>=0?1:-1)}else if(a===i.length-1&&Object.hasOwn(O,e.arrowTypeEnd)){const{angle:r,deltaY:s}=U(i[i.length-1],i[i.length-2]);l=O[e.arrowTypeEnd]*Math.abs(Math.sin(r))*(s>=0?1:-1)}return Z(t).y+l}}),ar=(e,t,a,i,l)=>{t.arrowTypeStart&&at(e,"start",t.arrowTypeStart,a,i,l),t.arrowTypeEnd&&at(e,"end",t.arrowTypeEnd,a,i,l)},er={arrow_cross:"cross",arrow_point:"point",arrow_barb:"barb",arrow_circle:"circle",aggregation:"aggregation",extension:"extension",composition:"composition",dependency:"dependency",lollipop:"lollipop"},at=(e,t,a,i,l,r)=>{const s=er[a];if(!s){g.warn(`Unknown arrow type: ${a}`);return}const n=t==="start"?"Start":"End";e.attr(`marker-${t}`,`url(${i}#${l}_${r}-${s}${n})`)};let G={},T={};const xr=()=>{G={},T={}},dr=(e,t)=>{const a=H(b().flowchart.htmlLabels),i=t.labelType==="markdown"?st(e,t.label,{style:t.labelStyle,useHtmlLabels:a,addSvgBackground:!0}):R(t.label,t.labelStyle),l=e.insert("g").attr("class","edgeLabel"),r=l.insert("g").attr("class","label");r.node().appendChild(i);let s=i.getBBox();if(a){const c=i.children[0],o=E(i);s=c.getBoundingClientRect(),o.attr("width",s.width),o.attr("height",s.height)}r.attr("transform","translate("+-s.width/2+", "+-s.height/2+")"),G[t.id]=l,t.width=s.width,t.height=s.height;let n;if(t.startLabelLeft){const c=R(t.startLabelLeft,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),T[t.id]||(T[t.id]={}),T[t.id].startLeft=o,z(n,t.startLabelLeft)}if(t.startLabelRight){const c=R(t.startLabelRight,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=o.node().appendChild(c),h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),T[t.id]||(T[t.id]={}),T[t.id].startRight=o,z(n,t.startLabelRight)}if(t.endLabelLeft){const c=R(t.endLabelLeft,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),o.node().appendChild(c),T[t.id]||(T[t.id]={}),T[t.id].endLeft=o,z(n,t.endLabelLeft)}if(t.endLabelRight){const c=R(t.endLabelRight,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),o.node().appendChild(c),T[t.id]||(T[t.id]={}),T[t.id].endRight=o,z(n,t.endLabelRight)}return i};function z(e,t){b().flowchart.htmlLabels&&e&&(e.style.width=t.length*9+"px",e.style.height="12px")}const gr=(e,t)=>{g.debug("Moving label abc88 ",e.id,e.label,G[e.id],t);let a=t.updatedPath?t.updatedPath:t.originalPath;const i=b(),{subGraphTitleTotalMargin:l}=tr(i);if(e.label){const r=G[e.id];let s=e.x,n=e.y;if(a){const c=j.calcLabelPosition(a);g.debug("Moving label "+e.label+" from (",s,",",n,") to (",c.x,",",c.y,") abc88"),t.updatedPath&&(s=c.x,n=c.y)}r.attr("transform",`translate(${s}, ${n+l/2})`)}if(e.startLabelLeft){const r=T[e.id].startLeft;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeStart?10:0,"start_left",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}if(e.startLabelRight){const r=T[e.id].startRight;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeStart?10:0,"start_right",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}if(e.endLabelLeft){const r=T[e.id].endLeft;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeEnd?10:0,"end_left",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}if(e.endLabelRight){const r=T[e.id].endRight;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeEnd?10:0,"end_right",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}},sr=(e,t)=>{const a=e.x,i=e.y,l=Math.abs(t.x-a),r=Math.abs(t.y-i),s=e.width/2,n=e.height/2;return l>=s||r>=n},ir=(e,t,a)=>{g.debug(`intersection calc abc89: +import{q as H,c as b,d as V,an as q,h as E,l as g,z as j,ao as lt}from"./mermaid.core-Bq0kX0MS.js";import{c as st}from"./createText-ca0c5216-xyt9uAlz.js";import{l as ct}from"./line-DY_oMjHu.js";const ht=(e,t,a,i)=>{t.forEach(l=>{wt[l](e,a,i)})},ot=(e,t,a)=>{g.trace("Making markers for ",a),e.append("defs").append("marker").attr("id",a+"_"+t+"-extensionStart").attr("class","marker extension "+t).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-extensionEnd").attr("class","marker extension "+t).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z")},yt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-compositionStart").attr("class","marker composition "+t).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-compositionEnd").attr("class","marker composition "+t).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},pt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-aggregationStart").attr("class","marker aggregation "+t).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-aggregationEnd").attr("class","marker aggregation "+t).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},ft=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-dependencyStart").attr("class","marker dependency "+t).attr("refX",6).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),e.append("defs").append("marker").attr("id",a+"_"+t+"-dependencyEnd").attr("class","marker dependency "+t).attr("refX",13).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},xt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-lollipopStart").attr("class","marker lollipop "+t).attr("refX",13).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","transparent").attr("cx",7).attr("cy",7).attr("r",6),e.append("defs").append("marker").attr("id",a+"_"+t+"-lollipopEnd").attr("class","marker lollipop "+t).attr("refX",1).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","transparent").attr("cx",7).attr("cy",7).attr("r",6)},dt=(e,t,a)=>{e.append("marker").attr("id",a+"_"+t+"-pointEnd").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",6).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),e.append("marker").attr("id",a+"_"+t+"-pointStart").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",4.5).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 5 L 10 10 L 10 0 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},gt=(e,t,a)=>{e.append("marker").attr("id",a+"_"+t+"-circleEnd").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",11).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),e.append("marker").attr("id",a+"_"+t+"-circleStart").attr("class","marker "+t).attr("viewBox","0 0 10 10").attr("refX",-1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},ut=(e,t,a)=>{e.append("marker").attr("id",a+"_"+t+"-crossEnd").attr("class","marker cross "+t).attr("viewBox","0 0 11 11").attr("refX",12).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0"),e.append("marker").attr("id",a+"_"+t+"-crossStart").attr("class","marker cross "+t).attr("viewBox","0 0 11 11").attr("refX",-1).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0")},bt=(e,t,a)=>{e.append("defs").append("marker").attr("id",a+"_"+t+"-barbEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",14).attr("markerUnits","strokeWidth").attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")},wt={extension:ot,composition:yt,aggregation:pt,dependency:ft,lollipop:xt,point:dt,circle:gt,cross:ut,barb:bt},hr=ht;function mt(e,t){t&&e.attr("style",t)}function kt(e){const t=E(document.createElementNS("http://www.w3.org/2000/svg","foreignObject")),a=t.append("xhtml:div"),i=e.label,l=e.isNode?"nodeLabel":"edgeLabel";return a.html('"+i+""),mt(a,e.labelStyle),a.style("display","inline-block"),a.style("white-space","nowrap"),a.attr("xmlns","http://www.w3.org/1999/xhtml"),t.node()}const vt=(e,t,a,i)=>{let l=e||"";if(typeof l=="object"&&(l=l[0]),H(b().flowchart.htmlLabels)){l=l.replace(/\\n|\n/g,"
                                        "),g.debug("vertexText"+l);const r={isNode:i,label:q(l).replace(/fa[blrs]?:fa-[\w-]+/g,n=>``),labelStyle:t.replace("fill:","color:")};return kt(r)}else{const r=document.createElementNS("http://www.w3.org/2000/svg","text");r.setAttribute("style",t.replace("color:","fill:"));let s=[];typeof l=="string"?s=l.split(/\\n|\n|/gi):Array.isArray(l)?s=l:s=[];for(const n of s){const c=document.createElementNS("http://www.w3.org/2000/svg","tspan");c.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),c.setAttribute("dy","1em"),c.setAttribute("x","0"),a?c.setAttribute("class","title-row"):c.setAttribute("class","row"),c.textContent=n.trim(),r.appendChild(c)}return r}},R=vt,M=async(e,t,a,i)=>{let l;const r=t.useHtmlLabels||H(b().flowchart.htmlLabels);a?l=a:l="node default";const s=e.insert("g").attr("class",l).attr("id",t.domId||t.id),n=s.insert("g").attr("class","label").attr("style",t.labelStyle);let c;t.labelText===void 0?c="":c=typeof t.labelText=="string"?t.labelText:t.labelText[0];const o=n.node();let h;t.labelType==="markdown"?h=st(n,V(q(c),b()),{useHtmlLabels:r,width:t.width||b().flowchart.wrappingWidth,classes:"markdown-node-label"}):h=o.appendChild(R(V(q(c),b()),t.labelStyle,!1,i));let y=h.getBBox();const f=t.padding/2;if(H(b().flowchart.htmlLabels)){const p=h.children[0],d=E(h),k=p.getElementsByTagName("img");if(k){const x=c.replace(/]*>/g,"").trim()==="";await Promise.all([...k].map(u=>new Promise(S=>{function B(){if(u.style.display="flex",u.style.flexDirection="column",x){const C=b().fontSize?b().fontSize:window.getComputedStyle(document.body).fontSize,D=parseInt(C,10)*5+"px";u.style.minWidth=D,u.style.maxWidth=D}else u.style.width="100%";S(u)}setTimeout(()=>{u.complete&&B()}),u.addEventListener("error",B),u.addEventListener("load",B)})))}y=p.getBoundingClientRect(),d.attr("width",y.width),d.attr("height",y.height)}return r?n.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"):n.attr("transform","translate(0, "+-y.height/2+")"),t.centerLabel&&n.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),n.insert("rect",":first-child"),{shapeSvg:s,bbox:y,halfPadding:f,label:n}},m=(e,t)=>{const a=t.node().getBBox();e.width=a.width,e.height=a.height};function I(e,t,a,i){return e.insert("polygon",":first-child").attr("points",i.map(function(l){return l.x+","+l.y}).join(" ")).attr("class","label-container").attr("transform","translate("+-t/2+","+a/2+")")}function Lt(e,t){return e.intersect(t)}function it(e,t,a,i){var l=e.x,r=e.y,s=l-i.x,n=r-i.y,c=Math.sqrt(t*t*n*n+a*a*s*s),o=Math.abs(t*a*s/c);i.x0}function Tt(e,t,a){var i=e.x,l=e.y,r=[],s=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY;typeof t.forEach=="function"?t.forEach(function(d){s=Math.min(s,d.x),n=Math.min(n,d.y)}):(s=Math.min(s,t.x),n=Math.min(n,t.y));for(var c=i-e.width/2-s,o=l-e.height/2-n,h=0;h1&&r.sort(function(d,k){var x=d.x-a.x,u=d.y-a.y,S=Math.sqrt(x*x+u*u),B=k.x-a.x,C=k.y-a.y,X=Math.sqrt(B*B+C*C);return S{var a=e.x,i=e.y,l=t.x-a,r=t.y-i,s=e.width/2,n=e.height/2,c,o;return Math.abs(r)*s>Math.abs(l)*n?(r<0&&(n=-n),c=r===0?0:n*l/r,o=n):(l<0&&(s=-s),c=s,o=l===0?0:s*r/l),{x:a+c,y:i+o}},Et=Bt,w={node:Lt,circle:St,ellipse:it,polygon:Tt,rect:Et},Ct=async(e,t)=>{t.useHtmlLabels||b().flowchart.htmlLabels||(t.centerLabel=!0);const{shapeSvg:i,bbox:l,halfPadding:r}=await M(e,t,"node "+t.classes,!0);g.info("Classes = ",t.classes);const s=i.insert("rect",":first-child");return s.attr("rx",t.rx).attr("ry",t.ry).attr("x",-l.width/2-r).attr("y",-l.height/2-r).attr("width",l.width+t.padding).attr("height",l.height+t.padding),m(t,s),t.intersect=function(n){return w.rect(t,n)},i},$t=Ct,_t=e=>{const t=new Set;for(const a of e)switch(a){case"x":t.add("right"),t.add("left");break;case"y":t.add("up"),t.add("down");break;default:t.add(a);break}return t},Rt=(e,t,a)=>{const i=_t(e),l=2,r=t.height+2*a.padding,s=r/l,n=t.width+2*s+a.padding,c=a.padding/2;return i.has("right")&&i.has("left")&&i.has("up")&&i.has("down")?[{x:0,y:0},{x:s,y:0},{x:n/2,y:2*c},{x:n-s,y:0},{x:n,y:0},{x:n,y:-r/3},{x:n+2*c,y:-r/2},{x:n,y:-2*r/3},{x:n,y:-r},{x:n-s,y:-r},{x:n/2,y:-r-2*c},{x:s,y:-r},{x:0,y:-r},{x:0,y:-2*r/3},{x:-2*c,y:-r/2},{x:0,y:-r/3}]:i.has("right")&&i.has("left")&&i.has("up")?[{x:s,y:0},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:s,y:-r},{x:0,y:-r/2}]:i.has("right")&&i.has("left")&&i.has("down")?[{x:0,y:0},{x:s,y:-r},{x:n-s,y:-r},{x:n,y:0}]:i.has("right")&&i.has("up")&&i.has("down")?[{x:0,y:0},{x:n,y:-s},{x:n,y:-r+s},{x:0,y:-r}]:i.has("left")&&i.has("up")&&i.has("down")?[{x:n,y:0},{x:0,y:-s},{x:0,y:-r+s},{x:n,y:-r}]:i.has("right")&&i.has("left")?[{x:s,y:0},{x:s,y:-c},{x:n-s,y:-c},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:n-s,y:-r+c},{x:s,y:-r+c},{x:s,y:-r},{x:0,y:-r/2}]:i.has("up")&&i.has("down")?[{x:n/2,y:0},{x:0,y:-c},{x:s,y:-c},{x:s,y:-r+c},{x:0,y:-r+c},{x:n/2,y:-r},{x:n,y:-r+c},{x:n-s,y:-r+c},{x:n-s,y:-c},{x:n,y:-c}]:i.has("right")&&i.has("up")?[{x:0,y:0},{x:n,y:-s},{x:0,y:-r}]:i.has("right")&&i.has("down")?[{x:0,y:0},{x:n,y:0},{x:0,y:-r}]:i.has("left")&&i.has("up")?[{x:n,y:0},{x:0,y:-s},{x:n,y:-r}]:i.has("left")&&i.has("down")?[{x:n,y:0},{x:0,y:0},{x:n,y:-r}]:i.has("right")?[{x:s,y:-c},{x:s,y:-c},{x:n-s,y:-c},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:n-s,y:-r+c},{x:s,y:-r+c},{x:s,y:-r+c}]:i.has("left")?[{x:s,y:0},{x:s,y:-c},{x:n-s,y:-c},{x:n-s,y:-r+c},{x:s,y:-r+c},{x:s,y:-r},{x:0,y:-r/2}]:i.has("up")?[{x:s,y:-c},{x:s,y:-r+c},{x:0,y:-r+c},{x:n/2,y:-r},{x:n,y:-r+c},{x:n-s,y:-r+c},{x:n-s,y:-c}]:i.has("down")?[{x:n/2,y:0},{x:0,y:-c},{x:s,y:-c},{x:s,y:-r+c},{x:n-s,y:-r+c},{x:n-s,y:-c},{x:n,y:-c}]:[{x:0,y:0}]},K=e=>e?" "+e:"",_=(e,t)=>`node default${K(e.classes)} ${K(e.class)}`,P=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=l+r,n=[{x:s/2,y:0},{x:s,y:-s/2},{x:s/2,y:-s},{x:0,y:-s/2}];g.info("Question main (Circle)");const c=I(a,s,s,n);return c.attr("style",t.style),m(t,c),t.intersect=function(o){return g.warn("Intersect called"),w.polygon(t,n,o)},a},Ht=(e,t)=>{const a=e.insert("g").attr("class","node default").attr("id",t.domId||t.id),i=28,l=[{x:0,y:i/2},{x:i/2,y:0},{x:0,y:-i/2},{x:-i/2,y:0}];return a.insert("polygon",":first-child").attr("points",l.map(function(s){return s.x+","+s.y}).join(" ")).attr("class","state-start").attr("r",7).attr("width",28).attr("height",28),t.width=28,t.height=28,t.intersect=function(s){return w.circle(t,14,s)},a},It=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=4,r=i.height+t.padding,s=r/l,n=i.width+2*s+t.padding,c=[{x:s,y:0},{x:n-s,y:0},{x:n,y:-r/2},{x:n-s,y:-r},{x:s,y:-r},{x:0,y:-r/2}],o=I(a,n,r,c);return o.attr("style",t.style),m(t,o),t.intersect=function(h){return w.polygon(t,c,h)},a},Nt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,void 0,!0),l=2,r=i.height+2*t.padding,s=r/l,n=i.width+2*s+t.padding,c=Rt(t.directions,i,t),o=I(a,n,r,c);return o.attr("style",t.style),m(t,o),t.intersect=function(h){return w.polygon(t,c,h)},a},Ot=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:-r/2,y:0},{x:l,y:0},{x:l,y:-r},{x:-r/2,y:-r},{x:0,y:-r/2}];return I(a,l,r,s).attr("style",t.style),t.width=l+r,t.height=r,t.intersect=function(c){return w.polygon(t,s,c)},a},Wt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:-2*r/6,y:0},{x:l-r/6,y:0},{x:l+2*r/6,y:-r},{x:r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Xt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:2*r/6,y:0},{x:l+r/6,y:0},{x:l-2*r/6,y:-r},{x:-r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Yt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:-2*r/6,y:0},{x:l+2*r/6,y:0},{x:l-r/6,y:-r},{x:r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Dt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:r/6,y:0},{x:l-r/6,y:0},{x:l+2*r/6,y:-r},{x:-2*r/6,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},At=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:0,y:0},{x:l+r/2,y:0},{x:l,y:-r/2},{x:l+r/2,y:-r},{x:0,y:-r}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},jt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=l/2,s=r/(2.5+l/50),n=i.height+s+t.padding,c="M 0,"+s+" a "+r+","+s+" 0,0,0 "+l+" 0 a "+r+","+s+" 0,0,0 "+-l+" 0 l 0,"+n+" a "+r+","+s+" 0,0,0 "+l+" 0 l 0,"+-n,o=a.attr("label-offset-y",s).insert("path",":first-child").attr("style",t.style).attr("d",c).attr("transform","translate("+-l/2+","+-(n/2+s)+")");return m(t,o),t.intersect=function(h){const y=w.rect(t,h),f=y.x-t.x;if(r!=0&&(Math.abs(f)t.height/2-s)){let p=s*s*(1-f*f/(r*r));p!=0&&(p=Math.sqrt(p)),p=s-p,h.y-t.y>0&&(p=-p),y.y+=p}return y},a},Ut=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,"node "+t.classes+" "+t.class,!0),r=a.insert("rect",":first-child"),s=t.positioned?t.width:i.width+t.padding,n=t.positioned?t.height:i.height+t.padding,c=t.positioned?-s/2:-i.width/2-l,o=t.positioned?-n/2:-i.height/2-l;if(r.attr("class","basic label-container").attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("x",c).attr("y",o).attr("width",s).attr("height",n),t.props){const h=new Set(Object.keys(t.props));t.props.borders&&(Q(r,t.props.borders,s,n),h.delete("borders")),h.forEach(y=>{g.warn(`Unknown node property ${y}`)})}return m(t,r),t.intersect=function(h){return w.rect(t,h)},a},zt=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,"node "+t.classes,!0),r=a.insert("rect",":first-child"),s=t.positioned?t.width:i.width+t.padding,n=t.positioned?t.height:i.height+t.padding,c=t.positioned?-s/2:-i.width/2-l,o=t.positioned?-n/2:-i.height/2-l;if(r.attr("class","basic cluster composite label-container").attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("x",c).attr("y",o).attr("width",s).attr("height",n),t.props){const h=new Set(Object.keys(t.props));t.props.borders&&(Q(r,t.props.borders,s,n),h.delete("borders")),h.forEach(y=>{g.warn(`Unknown node property ${y}`)})}return m(t,r),t.intersect=function(h){return w.rect(t,h)},a},Zt=async(e,t)=>{const{shapeSvg:a}=await M(e,t,"label",!0);g.trace("Classes = ",t.class);const i=a.insert("rect",":first-child"),l=0,r=0;if(i.attr("width",l).attr("height",r),a.attr("class","label edgeLabel"),t.props){const s=new Set(Object.keys(t.props));t.props.borders&&(Q(i,t.props.borders,l,r),s.delete("borders")),s.forEach(n=>{g.warn(`Unknown node property ${n}`)})}return m(t,i),t.intersect=function(s){return w.rect(t,s)},a};function Q(e,t,a,i){const l=[],r=n=>{l.push(n,0)},s=n=>{l.push(0,n)};t.includes("t")?(g.debug("add top border"),r(a)):s(a),t.includes("r")?(g.debug("add right border"),r(i)):s(i),t.includes("b")?(g.debug("add bottom border"),r(a)):s(a),t.includes("l")?(g.debug("add left border"),r(i)):s(i),e.attr("stroke-dasharray",l.join(" "))}const Gt=(e,t)=>{let a;t.classes?a="node "+t.classes:a="node default";const i=e.insert("g").attr("class",a).attr("id",t.domId||t.id),l=i.insert("rect",":first-child"),r=i.insert("line"),s=i.insert("g").attr("class","label"),n=t.labelText.flat?t.labelText.flat():t.labelText;let c="";typeof n=="object"?c=n[0]:c=n,g.info("Label text abc79",c,n,typeof n=="object");const o=s.node().appendChild(R(c,t.labelStyle,!0,!0));let h={width:0,height:0};if(H(b().flowchart.htmlLabels)){const k=o.children[0],x=E(o);h=k.getBoundingClientRect(),x.attr("width",h.width),x.attr("height",h.height)}g.info("Text 2",n);const y=n.slice(1,n.length);let f=o.getBBox();const p=s.node().appendChild(R(y.join?y.join("
                                        "):y,t.labelStyle,!0,!0));if(H(b().flowchart.htmlLabels)){const k=p.children[0],x=E(p);h=k.getBoundingClientRect(),x.attr("width",h.width),x.attr("height",h.height)}const d=t.padding/2;return E(p).attr("transform","translate( "+(h.width>f.width?0:(f.width-h.width)/2)+", "+(f.height+d+5)+")"),E(o).attr("transform","translate( "+(h.width{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.height+t.padding,r=i.width+l/4+t.padding,s=a.insert("rect",":first-child").attr("style",t.style).attr("rx",l/2).attr("ry",l/2).attr("x",-r/2).attr("y",-l/2).attr("width",r).attr("height",l);return m(t,s),t.intersect=function(n){return w.rect(t,n)},a},qt=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,_(t),!0),r=a.insert("circle",":first-child");return r.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("r",i.width/2+l).attr("width",i.width+t.padding).attr("height",i.height+t.padding),g.info("Circle main"),m(t,r),t.intersect=function(s){return g.info("Circle intersect",t,i.width/2+l,s),w.circle(t,i.width/2+l,s)},a},Qt=async(e,t)=>{const{shapeSvg:a,bbox:i,halfPadding:l}=await M(e,t,_(t),!0),r=5,s=a.insert("g",":first-child"),n=s.insert("circle"),c=s.insert("circle");return s.attr("class",t.class),n.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("r",i.width/2+l+r).attr("width",i.width+t.padding+r*2).attr("height",i.height+t.padding+r*2),c.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("r",i.width/2+l).attr("width",i.width+t.padding).attr("height",i.height+t.padding),g.info("DoubleCircle main"),m(t,n),t.intersect=function(o){return g.info("DoubleCircle intersect",t,i.width/2+l+r,o),w.circle(t,i.width/2+l+r,o)},a},Vt=async(e,t)=>{const{shapeSvg:a,bbox:i}=await M(e,t,_(t),!0),l=i.width+t.padding,r=i.height+t.padding,s=[{x:0,y:0},{x:l,y:0},{x:l,y:-r},{x:0,y:-r},{x:0,y:0},{x:-8,y:0},{x:l+8,y:0},{x:l+8,y:-r},{x:-8,y:-r},{x:-8,y:0}],n=I(a,l,r,s);return n.attr("style",t.style),m(t,n),t.intersect=function(c){return w.polygon(t,s,c)},a},Jt=(e,t)=>{const a=e.insert("g").attr("class","node default").attr("id",t.domId||t.id),i=a.insert("circle",":first-child");return i.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),m(t,i),t.intersect=function(l){return w.circle(t,7,l)},a},tt=(e,t,a)=>{const i=e.insert("g").attr("class","node default").attr("id",t.domId||t.id);let l=70,r=10;a==="LR"&&(l=10,r=70);const s=i.append("rect").attr("x",-1*l/2).attr("y",-1*r/2).attr("width",l).attr("height",r).attr("class","fork-join");return m(t,s),t.height=t.height+t.padding/2,t.width=t.width+t.padding/2,t.intersect=function(n){return w.rect(t,n)},i},Kt=(e,t)=>{const a=e.insert("g").attr("class","node default").attr("id",t.domId||t.id),i=a.insert("circle",":first-child"),l=a.insert("circle",":first-child");return l.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),i.attr("class","state-end").attr("r",5).attr("width",10).attr("height",10),m(t,l),t.intersect=function(r){return w.circle(t,7,r)},a},Pt=(e,t)=>{const a=t.padding/2,i=4,l=8;let r;t.classes?r="node "+t.classes:r="node default";const s=e.insert("g").attr("class",r).attr("id",t.domId||t.id),n=s.insert("rect",":first-child"),c=s.insert("line"),o=s.insert("line");let h=0,y=i;const f=s.insert("g").attr("class","label");let p=0;const d=t.classData.annotations&&t.classData.annotations[0],k=t.classData.annotations[0]?"«"+t.classData.annotations[0]+"»":"",x=f.node().appendChild(R(k,t.labelStyle,!0,!0));let u=x.getBBox();if(H(b().flowchart.htmlLabels)){const v=x.children[0],L=E(x);u=v.getBoundingClientRect(),L.attr("width",u.width),L.attr("height",u.height)}t.classData.annotations[0]&&(y+=u.height+i,h+=u.width);let S=t.classData.label;t.classData.type!==void 0&&t.classData.type!==""&&(b().flowchart.htmlLabels?S+="<"+t.classData.type+">":S+="<"+t.classData.type+">");const B=f.node().appendChild(R(S,t.labelStyle,!0,!0));E(B).attr("class","classTitle");let C=B.getBBox();if(H(b().flowchart.htmlLabels)){const v=B.children[0],L=E(B);C=v.getBoundingClientRect(),L.attr("width",C.width),L.attr("height",C.height)}y+=C.height+i,C.width>h&&(h=C.width);const X=[];t.classData.members.forEach(v=>{const L=v.getDisplayDetails();let W=L.displayText;b().flowchart.htmlLabels&&(W=W.replace(//g,">"));const N=f.node().appendChild(R(W,L.cssStyle?L.cssStyle:t.labelStyle,!0,!0));let $=N.getBBox();if(H(b().flowchart.htmlLabels)){const F=N.children[0],A=E(N);$=F.getBoundingClientRect(),A.attr("width",$.width),A.attr("height",$.height)}$.width>h&&(h=$.width),y+=$.height+i,X.push(N)}),y+=l;const D=[];if(t.classData.methods.forEach(v=>{const L=v.getDisplayDetails();let W=L.displayText;b().flowchart.htmlLabels&&(W=W.replace(//g,">"));const N=f.node().appendChild(R(W,L.cssStyle?L.cssStyle:t.labelStyle,!0,!0));let $=N.getBBox();if(H(b().flowchart.htmlLabels)){const F=N.children[0],A=E(N);$=F.getBoundingClientRect(),A.attr("width",$.width),A.attr("height",$.height)}$.width>h&&(h=$.width),y+=$.height+i,D.push(N)}),y+=l,d){let v=(h-u.width)/2;E(x).attr("transform","translate( "+(-1*h/2+v)+", "+-1*y/2+")"),p=u.height+i}let nt=(h-C.width)/2;return E(B).attr("transform","translate( "+(-1*h/2+nt)+", "+(-1*y/2+p)+")"),p+=C.height+i,c.attr("class","divider").attr("x1",-h/2-a).attr("x2",h/2+a).attr("y1",-y/2-a+l+p).attr("y2",-y/2-a+l+p),p+=l,X.forEach(v=>{E(v).attr("transform","translate( "+-h/2+", "+(-1*y/2+p+l/2)+")");const L=v==null?void 0:v.getBBox();p+=((L==null?void 0:L.height)??0)+i}),p+=l,o.attr("class","divider").attr("x1",-h/2-a).attr("x2",h/2+a).attr("y1",-y/2-a+l+p).attr("y2",-y/2-a+l+p),p+=l,D.forEach(v=>{E(v).attr("transform","translate( "+-h/2+", "+(-1*y/2+p)+")");const L=v==null?void 0:v.getBBox();p+=((L==null?void 0:L.height)??0)+i}),n.attr("style",t.style).attr("class","outer title-state").attr("x",-h/2-a).attr("y",-(y/2)-a).attr("width",h+t.padding).attr("height",y+t.padding),m(t,n),t.intersect=function(v){return w.rect(t,v)},s},rt={rhombus:P,composite:zt,question:P,rect:Ut,labelRect:Zt,rectWithTitle:Gt,choice:Ht,circle:qt,doublecircle:Qt,stadium:Ft,hexagon:It,block_arrow:Nt,rect_left_inv_arrow:Ot,lean_right:Wt,lean_left:Xt,trapezoid:Yt,inv_trapezoid:Dt,rect_right_inv_arrow:At,cylinder:jt,start:Jt,end:Kt,note:$t,subroutine:Vt,fork:tt,join:tt,class_box:Pt};let Y={};const or=async(e,t,a)=>{let i,l;if(t.link){let r;b().securityLevel==="sandbox"?r="_top":t.linkTarget&&(r=t.linkTarget||"_blank"),i=e.insert("svg:a").attr("xlink:href",t.link).attr("target",r),l=await rt[t.shape](i,t,a)}else l=await rt[t.shape](e,t,a),i=l;return t.tooltip&&l.attr("title",t.tooltip),t.class&&l.attr("class","node default "+t.class),i.attr("data-node","true"),i.attr("data-id",t.id),Y[t.id]=i,t.haveCallback&&Y[t.id].attr("class",Y[t.id].attr("class")+" clickable"),i},yr=(e,t)=>{Y[t.id]=e},pr=()=>{Y={}},fr=e=>{const t=Y[e.id];g.trace("Transforming node",e.diff,e,"translate("+(e.x-e.width/2-5)+", "+e.width/2+")");const a=8,i=e.diff||0;return e.clusterNode?t.attr("transform","translate("+(e.x+i-e.width/2)+", "+(e.y-e.height/2-a)+")"):t.attr("transform","translate("+e.x+", "+e.y+")"),i},tr=({flowchart:e})=>{var t,a;const i=((t=e==null?void 0:e.subGraphTitleMargin)==null?void 0:t.top)??0,l=((a=e==null?void 0:e.subGraphTitleMargin)==null?void 0:a.bottom)??0,r=i+l;return{subGraphTitleTopMargin:i,subGraphTitleBottomMargin:l,subGraphTitleTotalMargin:r}},O={aggregation:18,extension:18,composition:18,dependency:6,lollipop:13.5,arrow_point:5.3};function U(e,t){if(e===void 0||t===void 0)return{angle:0,deltaX:0,deltaY:0};e=Z(e),t=Z(t);const[a,i]=[e.x,e.y],[l,r]=[t.x,t.y],s=l-a,n=r-i;return{angle:Math.atan(n/s),deltaX:s,deltaY:n}}const Z=e=>Array.isArray(e)?{x:e[0],y:e[1]}:e,rr=e=>({x:function(t,a,i){let l=0;if(a===0&&Object.hasOwn(O,e.arrowTypeStart)){const{angle:r,deltaX:s}=U(i[0],i[1]);l=O[e.arrowTypeStart]*Math.cos(r)*(s>=0?1:-1)}else if(a===i.length-1&&Object.hasOwn(O,e.arrowTypeEnd)){const{angle:r,deltaX:s}=U(i[i.length-1],i[i.length-2]);l=O[e.arrowTypeEnd]*Math.cos(r)*(s>=0?1:-1)}return Z(t).x+l},y:function(t,a,i){let l=0;if(a===0&&Object.hasOwn(O,e.arrowTypeStart)){const{angle:r,deltaY:s}=U(i[0],i[1]);l=O[e.arrowTypeStart]*Math.abs(Math.sin(r))*(s>=0?1:-1)}else if(a===i.length-1&&Object.hasOwn(O,e.arrowTypeEnd)){const{angle:r,deltaY:s}=U(i[i.length-1],i[i.length-2]);l=O[e.arrowTypeEnd]*Math.abs(Math.sin(r))*(s>=0?1:-1)}return Z(t).y+l}}),ar=(e,t,a,i,l)=>{t.arrowTypeStart&&at(e,"start",t.arrowTypeStart,a,i,l),t.arrowTypeEnd&&at(e,"end",t.arrowTypeEnd,a,i,l)},er={arrow_cross:"cross",arrow_point:"point",arrow_barb:"barb",arrow_circle:"circle",aggregation:"aggregation",extension:"extension",composition:"composition",dependency:"dependency",lollipop:"lollipop"},at=(e,t,a,i,l,r)=>{const s=er[a];if(!s){g.warn(`Unknown arrow type: ${a}`);return}const n=t==="start"?"Start":"End";e.attr(`marker-${t}`,`url(${i}#${l}_${r}-${s}${n})`)};let G={},T={};const xr=()=>{G={},T={}},dr=(e,t)=>{const a=H(b().flowchart.htmlLabels),i=t.labelType==="markdown"?st(e,t.label,{style:t.labelStyle,useHtmlLabels:a,addSvgBackground:!0}):R(t.label,t.labelStyle),l=e.insert("g").attr("class","edgeLabel"),r=l.insert("g").attr("class","label");r.node().appendChild(i);let s=i.getBBox();if(a){const c=i.children[0],o=E(i);s=c.getBoundingClientRect(),o.attr("width",s.width),o.attr("height",s.height)}r.attr("transform","translate("+-s.width/2+", "+-s.height/2+")"),G[t.id]=l,t.width=s.width,t.height=s.height;let n;if(t.startLabelLeft){const c=R(t.startLabelLeft,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),T[t.id]||(T[t.id]={}),T[t.id].startLeft=o,z(n,t.startLabelLeft)}if(t.startLabelRight){const c=R(t.startLabelRight,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=o.node().appendChild(c),h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),T[t.id]||(T[t.id]={}),T[t.id].startRight=o,z(n,t.startLabelRight)}if(t.endLabelLeft){const c=R(t.endLabelLeft,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),o.node().appendChild(c),T[t.id]||(T[t.id]={}),T[t.id].endLeft=o,z(n,t.endLabelLeft)}if(t.endLabelRight){const c=R(t.endLabelRight,t.labelStyle),o=e.insert("g").attr("class","edgeTerminals"),h=o.insert("g").attr("class","inner");n=h.node().appendChild(c);const y=c.getBBox();h.attr("transform","translate("+-y.width/2+", "+-y.height/2+")"),o.node().appendChild(c),T[t.id]||(T[t.id]={}),T[t.id].endRight=o,z(n,t.endLabelRight)}return i};function z(e,t){b().flowchart.htmlLabels&&e&&(e.style.width=t.length*9+"px",e.style.height="12px")}const gr=(e,t)=>{g.debug("Moving label abc88 ",e.id,e.label,G[e.id],t);let a=t.updatedPath?t.updatedPath:t.originalPath;const i=b(),{subGraphTitleTotalMargin:l}=tr(i);if(e.label){const r=G[e.id];let s=e.x,n=e.y;if(a){const c=j.calcLabelPosition(a);g.debug("Moving label "+e.label+" from (",s,",",n,") to (",c.x,",",c.y,") abc88"),t.updatedPath&&(s=c.x,n=c.y)}r.attr("transform",`translate(${s}, ${n+l/2})`)}if(e.startLabelLeft){const r=T[e.id].startLeft;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeStart?10:0,"start_left",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}if(e.startLabelRight){const r=T[e.id].startRight;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeStart?10:0,"start_right",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}if(e.endLabelLeft){const r=T[e.id].endLeft;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeEnd?10:0,"end_left",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}if(e.endLabelRight){const r=T[e.id].endRight;let s=e.x,n=e.y;if(a){const c=j.calcTerminalLabelPosition(e.arrowTypeEnd?10:0,"end_right",a);s=c.x,n=c.y}r.attr("transform",`translate(${s}, ${n})`)}},sr=(e,t)=>{const a=e.x,i=e.y,l=Math.abs(t.x-a),r=Math.abs(t.y-i),s=e.width/2,n=e.height/2;return l>=s||r>=n},ir=(e,t,a)=>{g.debug(`intersection calc abc89: outsidePoint: ${JSON.stringify(t)} insidePoint : ${JSON.stringify(a)} node : x:${e.x} y:${e.y} w:${e.width} h:${e.height}`);const i=e.x,l=e.y,r=Math.abs(i-a.x),s=e.width/2;let n=a.xMath.abs(i-t.x)*c){let y=a.y{g.debug("abc88 cutPathAtIntersect",e,t);let a=[],i=e[0],l=!1;return e.forEach(r=>{if(!sr(t,r)&&!l){const s=ir(t,i,r);let n=!1;a.forEach(c=>{n=n||c.x===s.x&&c.y===s.y}),a.some(c=>c.x===s.x&&c.y===s.y)||a.push(s),l=!0}else i=r,l||a.push(r)}),a},ur=function(e,t,a,i,l,r,s){let n=a.points;g.debug("abc88 InsertEdge: edge=",a,"e=",t);let c=!1;const o=r.node(t.v);var h=r.node(t.w);h!=null&&h.intersect&&(o!=null&&o.intersect)&&(n=n.slice(1,a.points.length-1),n.unshift(o.intersect(n[0])),n.push(h.intersect(n[n.length-1]))),a.toCluster&&(g.debug("to cluster abc88",i[a.toCluster]),n=et(a.points,i[a.toCluster].node),c=!0),a.fromCluster&&(g.debug("from cluster abc88",i[a.fromCluster]),n=et(n.reverse(),i[a.fromCluster].node).reverse(),c=!0);const y=n.filter(C=>!Number.isNaN(C.y));let f=lt;a.curve&&(l==="graph"||l==="flowchart")&&(f=a.curve);const{x:p,y:d}=rr(a),k=ct().x(p).y(d).curve(f);let x;switch(a.thickness){case"normal":x="edge-thickness-normal";break;case"thick":x="edge-thickness-thick";break;case"invisible":x="edge-thickness-thick";break;default:x=""}switch(a.pattern){case"solid":x+=" edge-pattern-solid";break;case"dotted":x+=" edge-pattern-dotted";break;case"dashed":x+=" edge-pattern-dashed";break}const u=e.append("path").attr("d",k(y)).attr("id",a.id).attr("class"," "+x+(a.classes?" "+a.classes:"")).attr("style",a.style);let S="";(b().flowchart.arrowMarkerAbsolute||b().state.arrowMarkerAbsolute)&&(S=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,S=S.replace(/\(/g,"\\("),S=S.replace(/\)/g,"\\)")),ar(u,a,S,s,l);let B={};return c&&(B.updatedPath=n),B.originalPath=a.points,B};export{or as a,dr as b,ur as c,gr as d,pr as e,xr as f,tr as g,R as h,hr as i,Et as j,rr as k,M as l,ar as m,fr as p,yr as s,m as u}; diff --git a/assets/env.html-CjyJA0Yb.js b/assets/env.html-5Sl2lv4f.js similarity index 97% rename from assets/env.html-CjyJA0Yb.js rename to assets/env.html-5Sl2lv4f.js index 9d45ee2ffc..3f5bb20b45 100644 --- a/assets/env.html-CjyJA0Yb.js +++ b/assets/env.html-5Sl2lv4f.js @@ -1,4 +1,4 @@ -import{_ as l,r as o,o as r,c as s,a as i,b as e,d as a,e as c}from"./app-5SoadDYS.js";const d={},u=e("h1",{id:"environment-variables",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#environment-variables"},[e("span",null,"Environment Variables")])],-1),h=e("p",null,"Xray provides the following environment variables for modifying some of its underlying configurations.",-1),f=e("h2",{id:"xray-asset-location",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#xray-asset-location"},[e("span",null,"Xray Asset Location")])],-1),p=e("li",null,[a("Name:"),e("code",null,"xray.location.asset"),a(" or "),e("code",null,"XRAY_LOCATION_ASSET"),a("。")],-1),_={href:"https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard",target:"_blank",rel:"noopener noreferrer"},m=c(`

                                        This environment variable specifies a folder location that should contain the geoip.dat and geosite.dat files. If no variable value is specified, the program will search for resource files in the following order:

                                        ./
                                        +import{_ as l,r as o,o as r,c as s,a as i,b as e,d as a,e as c}from"./app-Bw2NG-QJ.js";const d={},u=e("h1",{id:"environment-variables",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#environment-variables"},[e("span",null,"Environment Variables")])],-1),h=e("p",null,"Xray provides the following environment variables for modifying some of its underlying configurations.",-1),f=e("h2",{id:"xray-asset-location",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#xray-asset-location"},[e("span",null,"Xray Asset Location")])],-1),p=e("li",null,[a("Name:"),e("code",null,"xray.location.asset"),a(" or "),e("code",null,"XRAY_LOCATION_ASSET"),a("。")],-1),_={href:"https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard",target:"_blank",rel:"noopener noreferrer"},m=c(`

                                        This environment variable specifies a folder location that should contain the geoip.dat and geosite.dat files. If no variable value is specified, the program will search for resource files in the following order:

                                        ./
                                         /usr/local/share/xray
                                         /usr/share/xray
                                         

                                        Configuration File Location

                                        • Name:xray.location.config or XRAY_LOCATION_CONFIG
                                        • Default value: Same path as the Xray file.

                                        This environment variable specifies a folder location that should contain the config.json file.

                                        Multiple Configuration Directories

                                        • Name:xray.location.confdir or XRAY_LOCATION_CONFDIR
                                        • Default value:""

                                        The .json files in this directory will be read in alphabetical order by filename and used as options for multiple configurations.

                                        `,8);function v(g,x){const n=o("I18nTip"),t=o("ExternalLinkIcon");return r(),s("div",null,[i(n),u,h,f,e("ul",null,[p,e("li",null,[a("Default value:specified "),e("a",_,[a("FHS"),i(t)]),a(" directory or the same path as the Xray file.")])]),m])}const y=l(d,[["render",v],["__file","env.html.vue"]]);export{y as default}; diff --git a/assets/env.html-X4QtRUwr.js b/assets/env.html-BaUecgO2.js similarity index 98% rename from assets/env.html-X4QtRUwr.js rename to assets/env.html-BaUecgO2.js index 1c896eff7c..59d97ee81d 100644 --- a/assets/env.html-X4QtRUwr.js +++ b/assets/env.html-BaUecgO2.js @@ -1,4 +1,4 @@ -import{_ as d,r as n,o as s,c as l,a as o,b as e,d as a,e as i}from"./app-5SoadDYS.js";const r={},_=e("h1",{id:"переменные-среды",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#переменные-среды"},[e("span",null,"Переменные среды")])],-1),h=e("p",null,"Xray предоставляет следующие переменные среды для изменения некоторых базовых настроек Xray.",-1),u=e("h2",{id:"путь-к-фаилам-ресурсов",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#путь-к-фаилам-ресурсов"},[e("span",null,"Путь к файлам ресурсов")])],-1),p=e("li",null,[a("Название: "),e("code",null,"xray.location.asset"),a(" или "),e("code",null,"XRAY_LOCATION_ASSET"),a(".")],-1),x={href:"https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard",target:"_blank",rel:"noopener noreferrer"},f=i(`

                                        Эта переменная среды указывает расположение папки, которая должна содержать файлы geoip.dat и geosite.dat. Если значение переменной не указано, программа будет искать файлы ресурсов в следующем порядке:

                                        ./
                                        +import{_ as d,r as n,o as s,c as l,a as o,b as e,d as a,e as i}from"./app-Bw2NG-QJ.js";const r={},_=e("h1",{id:"переменные-среды",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#переменные-среды"},[e("span",null,"Переменные среды")])],-1),h=e("p",null,"Xray предоставляет следующие переменные среды для изменения некоторых базовых настроек Xray.",-1),u=e("h2",{id:"путь-к-фаилам-ресурсов",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#путь-к-фаилам-ресурсов"},[e("span",null,"Путь к файлам ресурсов")])],-1),p=e("li",null,[a("Название: "),e("code",null,"xray.location.asset"),a(" или "),e("code",null,"XRAY_LOCATION_ASSET"),a(".")],-1),x={href:"https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard",target:"_blank",rel:"noopener noreferrer"},f=i(`

                                        Эта переменная среды указывает расположение папки, которая должна содержать файлы geoip.dat и geosite.dat. Если значение переменной не указано, программа будет искать файлы ресурсов в следующем порядке:

                                        ./
                                         /usr/local/share/xray
                                         /usr/share/xray
                                         

                                        Расположение файла конфигурации

                                        • Название: xray.location.config или XRAY_LOCATION_CONFIG.
                                        • Значение по умолчанию: Тот же каталог, что и файл Xray.

                                        Эта переменная среды указывает расположение папки, которая должна содержать файл config.json.

                                        Каталог с несколькими конфигурациями

                                        • Название: xray.location.confdir или XRAY_LOCATION_CONFDIR.
                                        • Значение по умолчанию: "".

                                        Файлы .json в этом каталоге будут читаться в порядке имен файлов как параметры конфигурации.

                                        `,8);function m(v,b){const c=n("I18nTip"),t=n("ExternalLinkIcon");return s(),l("div",null,[o(c),_,h,u,e("ul",null,[p,e("li",null,[a("Значение по умолчанию: Определенный каталог "),e("a",x,[a("FHS"),o(t)]),a(" или тот же каталог, что и файл Xray.")])]),f])}const g=d(r,[["render",m],["__file","env.html.vue"]]);export{g as default}; diff --git a/assets/env.html-DzAnx11j.js b/assets/env.html-aOvx_pi1.js similarity index 97% rename from assets/env.html-DzAnx11j.js rename to assets/env.html-aOvx_pi1.js index 32e0825eb0..3246cf7e37 100644 --- a/assets/env.html-DzAnx11j.js +++ b/assets/env.html-aOvx_pi1.js @@ -1,4 +1,4 @@ -import{_ as l,r as n,o as c,c as i,a as o,b as e,d as a,e as r}from"./app-5SoadDYS.js";const d={},_=e("h1",{id:"环境变量",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#环境变量"},[e("span",null,"环境变量")])],-1),h=e("p",null,"Xray 提供以下环境变量以供修改 Xray 的一些底层配置。",-1),u=e("h2",{id:"资源文件路径",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#资源文件路径"},[e("span",null,"资源文件路径")])],-1),p=e("li",null,[a("名称:"),e("code",null,"xray.location.asset"),a(" 或 "),e("code",null,"XRAY_LOCATION_ASSET"),a("。")],-1),x={href:"https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard",target:"_blank",rel:"noopener noreferrer"},f=r(`

                                        这个环境变量指定了一个文件夹位置,这个文件夹应当包含 geoip.dat 和 geosite.dat 文件。 若无指定变量值,程序将会按以下顺序寻找资源文件:

                                        ./
                                        +import{_ as l,r as n,o as c,c as i,a as o,b as e,d as a,e as r}from"./app-Bw2NG-QJ.js";const d={},_=e("h1",{id:"环境变量",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#环境变量"},[e("span",null,"环境变量")])],-1),h=e("p",null,"Xray 提供以下环境变量以供修改 Xray 的一些底层配置。",-1),u=e("h2",{id:"资源文件路径",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#资源文件路径"},[e("span",null,"资源文件路径")])],-1),p=e("li",null,[a("名称:"),e("code",null,"xray.location.asset"),a(" 或 "),e("code",null,"XRAY_LOCATION_ASSET"),a("。")],-1),x={href:"https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard",target:"_blank",rel:"noopener noreferrer"},f=r(`

                                        这个环境变量指定了一个文件夹位置,这个文件夹应当包含 geoip.dat 和 geosite.dat 文件。 若无指定变量值,程序将会按以下顺序寻找资源文件:

                                        ./
                                         /usr/local/share/xray
                                         /usr/share/xray
                                         

                                        配置文件位置

                                        • 名称:xray.location.configXRAY_LOCATION_CONFIG
                                        • 默认值:和 Xray 文件同路径。

                                        这个环境变量指定了一个文件夹位置,这个文件夹应当包含 config.json 文件。

                                        多配置目录

                                        • 名称:xray.location.confdirXRAY_LOCATION_CONFDIR
                                        • 默认值:""

                                        这个目录内的 .json 文件会按文件名顺序读取,作为多配置选项。

                                        `,8);function m(v,b){const t=n("I18nTip"),s=n("ExternalLinkIcon");return c(),i("div",null,[o(t),_,h,u,e("ul",null,[p,e("li",null,[a("默认值:特定 "),e("a",x,[a("FHS"),o(s)]),a(" 目录或 Xray 文件同路径。")])]),f])}const g=l(d,[["render",m],["__file","env.html.vue"]]);export{g as default}; diff --git a/assets/erDiagram-09d1c15f-DTI3Ywn0.js b/assets/erDiagram-09d1c15f-CxugSXM3.js similarity index 99% rename from assets/erDiagram-09d1c15f-DTI3Ywn0.js rename to assets/erDiagram-09d1c15f-CxugSXM3.js index 7221296b30..31f23bb867 100644 --- a/assets/erDiagram-09d1c15f-DTI3Ywn0.js +++ b/assets/erDiagram-09d1c15f-CxugSXM3.js @@ -1,4 +1,4 @@ -import{c as Z,s as Et,g as mt,b as gt,a as kt,x as xt,y as Rt,l as V,A as Ot,h as rt,z as bt,i as Nt,ao as Tt,ar as At}from"./mermaid.core-CArNAncI.js";import{G as Mt}from"./graph-D2qW7eTj.js";import{l as St}from"./layout-BlaWeSu5.js";import{l as wt}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const It=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function Dt(t){return typeof t=="string"&&It.test(t)}const A=[];for(let t=0;t<256;++t)A.push((t+256).toString(16).slice(1));function vt(t,e=0){return A[t[e+0]]+A[t[e+1]]+A[t[e+2]]+A[t[e+3]]+"-"+A[t[e+4]]+A[t[e+5]]+"-"+A[t[e+6]]+A[t[e+7]]+"-"+A[t[e+8]]+A[t[e+9]]+"-"+A[t[e+10]]+A[t[e+11]]+A[t[e+12]]+A[t[e+13]]+A[t[e+14]]+A[t[e+15]]}function Lt(t){if(!Dt(t))throw TypeError("Invalid UUID");let e;const r=new Uint8Array(16);return r[0]=(e=parseInt(t.slice(0,8),16))>>>24,r[1]=e>>>16&255,r[2]=e>>>8&255,r[3]=e&255,r[4]=(e=parseInt(t.slice(9,13),16))>>>8,r[5]=e&255,r[6]=(e=parseInt(t.slice(14,18),16))>>>8,r[7]=e&255,r[8]=(e=parseInt(t.slice(19,23),16))>>>8,r[9]=e&255,r[10]=(e=parseInt(t.slice(24,36),16))/1099511627776&255,r[11]=e/4294967296&255,r[12]=e>>>24&255,r[13]=e>>>16&255,r[14]=e>>>8&255,r[15]=e&255,r}function Bt(t){t=unescape(encodeURIComponent(t));const e=[];for(let r=0;r>>32-e}function Ft(t){const e=[1518500249,1859775393,2400959708,3395469782],r=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof t=="string"){const f=unescape(encodeURIComponent(t));t=[];for(let o=0;o>>0;x=g,g=m,m=it(_,30)>>>0,_=h,h=I}r[0]=r[0]+h>>>0,r[1]=r[1]+_>>>0,r[2]=r[2]+m>>>0,r[3]=r[3]+g>>>0,r[4]=r[4]+x>>>0}return[r[0]>>24&255,r[0]>>16&255,r[0]>>8&255,r[0]&255,r[1]>>24&255,r[1]>>16&255,r[1]>>8&255,r[1]&255,r[2]>>24&255,r[2]>>16&255,r[2]>>8&255,r[2]&255,r[3]>>24&255,r[3]>>16&255,r[3]>>8&255,r[3]&255,r[4]>>24&255,r[4]>>16&255,r[4]>>8&255,r[4]&255]}const Wt=Yt("v5",80,Ft);var at=function(){var t=function(S,a,n,c){for(n=n||{},c=S.length;c--;n[S[c]]=a);return n},e=[6,8,10,20,22,24,26,27,28],r=[1,10],u=[1,11],l=[1,12],p=[1,13],f=[1,14],o=[1,15],h=[1,21],_=[1,22],m=[1,23],g=[1,24],x=[1,25],y=[6,8,10,13,15,18,19,20,22,24,26,27,28,41,42,43,44,45],N=[1,34],I=[27,28,46,47],F=[41,42,43,44,45],W=[17,34],C=[1,54],T=[1,53],M=[17,34,36,38],R={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,entityName:11,relSpec:12,":":13,role:14,BLOCK_START:15,attributes:16,BLOCK_STOP:17,SQS:18,SQE:19,title:20,title_value:21,acc_title:22,acc_title_value:23,acc_descr:24,acc_descr_value:25,acc_descr_multiline_value:26,ALPHANUM:27,ENTITY_NAME:28,attribute:29,attributeType:30,attributeName:31,attributeKeyTypeList:32,attributeComment:33,ATTRIBUTE_WORD:34,attributeKeyType:35,COMMA:36,ATTRIBUTE_KEY:37,COMMENT:38,cardinality:39,relType:40,ZERO_OR_ONE:41,ZERO_OR_MORE:42,ONE_OR_MORE:43,ONLY_ONE:44,MD_PARENT:45,NON_IDENTIFYING:46,IDENTIFYING:47,WORD:48,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",8:"SPACE",10:"NEWLINE",13:":",15:"BLOCK_START",17:"BLOCK_STOP",18:"SQS",19:"SQE",20:"title",21:"title_value",22:"acc_title",23:"acc_title_value",24:"acc_descr",25:"acc_descr_value",26:"acc_descr_multiline_value",27:"ALPHANUM",28:"ENTITY_NAME",34:"ATTRIBUTE_WORD",36:"COMMA",37:"ATTRIBUTE_KEY",38:"COMMENT",41:"ZERO_OR_ONE",42:"ZERO_OR_MORE",43:"ONE_OR_MORE",44:"ONLY_ONE",45:"MD_PARENT",46:"NON_IDENTIFYING",47:"IDENTIFYING",48:"WORD"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,5],[9,4],[9,3],[9,1],[9,7],[9,6],[9,4],[9,2],[9,2],[9,2],[9,1],[11,1],[11,1],[16,1],[16,2],[29,2],[29,3],[29,3],[29,4],[30,1],[31,1],[32,1],[32,3],[35,1],[33,1],[12,3],[39,1],[39,1],[39,1],[39,1],[39,1],[40,1],[40,1],[14,1],[14,1],[14,1]],performAction:function(a,n,c,d,E,i,K){var s=i.length-1;switch(E){case 1:break;case 2:this.$=[];break;case 3:i[s-1].push(i[s]),this.$=i[s-1];break;case 4:case 5:this.$=i[s];break;case 6:case 7:this.$=[];break;case 8:d.addEntity(i[s-4]),d.addEntity(i[s-2]),d.addRelationship(i[s-4],i[s],i[s-2],i[s-3]);break;case 9:d.addEntity(i[s-3]),d.addAttributes(i[s-3],i[s-1]);break;case 10:d.addEntity(i[s-2]);break;case 11:d.addEntity(i[s]);break;case 12:d.addEntity(i[s-6],i[s-4]),d.addAttributes(i[s-6],i[s-1]);break;case 13:d.addEntity(i[s-5],i[s-3]);break;case 14:d.addEntity(i[s-3],i[s-1]);break;case 15:case 16:this.$=i[s].trim(),d.setAccTitle(this.$);break;case 17:case 18:this.$=i[s].trim(),d.setAccDescription(this.$);break;case 19:case 43:this.$=i[s];break;case 20:case 41:case 42:this.$=i[s].replace(/"/g,"");break;case 21:case 29:this.$=[i[s]];break;case 22:i[s].push(i[s-1]),this.$=i[s];break;case 23:this.$={attributeType:i[s-1],attributeName:i[s]};break;case 24:this.$={attributeType:i[s-2],attributeName:i[s-1],attributeKeyTypeList:i[s]};break;case 25:this.$={attributeType:i[s-2],attributeName:i[s-1],attributeComment:i[s]};break;case 26:this.$={attributeType:i[s-3],attributeName:i[s-2],attributeKeyTypeList:i[s-1],attributeComment:i[s]};break;case 27:case 28:case 31:this.$=i[s];break;case 30:i[s-2].push(i[s]),this.$=i[s-2];break;case 32:this.$=i[s].replace(/"/g,"");break;case 33:this.$={cardA:i[s],relType:i[s-1],cardB:i[s-2]};break;case 34:this.$=d.Cardinality.ZERO_OR_ONE;break;case 35:this.$=d.Cardinality.ZERO_OR_MORE;break;case 36:this.$=d.Cardinality.ONE_OR_MORE;break;case 37:this.$=d.Cardinality.ONLY_ONE;break;case 38:this.$=d.Cardinality.MD_PARENT;break;case 39:this.$=d.Identification.NON_IDENTIFYING;break;case 40:this.$=d.Identification.IDENTIFYING;break}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:9,20:r,22:u,24:l,26:p,27:f,28:o},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:16,11:9,20:r,22:u,24:l,26:p,27:f,28:o},t(e,[2,5]),t(e,[2,6]),t(e,[2,11],{12:17,39:20,15:[1,18],18:[1,19],41:h,42:_,43:m,44:g,45:x}),{21:[1,26]},{23:[1,27]},{25:[1,28]},t(e,[2,18]),t(y,[2,19]),t(y,[2,20]),t(e,[2,4]),{11:29,27:f,28:o},{16:30,17:[1,31],29:32,30:33,34:N},{11:35,27:f,28:o},{40:36,46:[1,37],47:[1,38]},t(I,[2,34]),t(I,[2,35]),t(I,[2,36]),t(I,[2,37]),t(I,[2,38]),t(e,[2,15]),t(e,[2,16]),t(e,[2,17]),{13:[1,39]},{17:[1,40]},t(e,[2,10]),{16:41,17:[2,21],29:32,30:33,34:N},{31:42,34:[1,43]},{34:[2,27]},{19:[1,44]},{39:45,41:h,42:_,43:m,44:g,45:x},t(F,[2,39]),t(F,[2,40]),{14:46,27:[1,49],28:[1,48],48:[1,47]},t(e,[2,9]),{17:[2,22]},t(W,[2,23],{32:50,33:51,35:52,37:C,38:T}),t([17,34,37,38],[2,28]),t(e,[2,14],{15:[1,55]}),t([27,28],[2,33]),t(e,[2,8]),t(e,[2,41]),t(e,[2,42]),t(e,[2,43]),t(W,[2,24],{33:56,36:[1,57],38:T}),t(W,[2,25]),t(M,[2,29]),t(W,[2,32]),t(M,[2,31]),{16:58,17:[1,59],29:32,30:33,34:N},t(W,[2,26]),{35:60,37:C},{17:[1,61]},t(e,[2,13]),t(M,[2,30]),t(e,[2,12])],defaultActions:{34:[2,27],41:[2,22]},parseError:function(a,n){if(n.recoverable)this.trace(a);else{var c=new Error(a);throw c.hash=n,c}},parse:function(a){var n=this,c=[0],d=[],E=[null],i=[],K=this.table,s="",Q=0,st=0,ft=2,ot=1,yt=i.slice.call(arguments,1),b=Object.create(this.lexer),z={yy:{}};for(var J in this.yy)Object.prototype.hasOwnProperty.call(this.yy,J)&&(z.yy[J]=this.yy[J]);b.setInput(a,z.yy),z.yy.lexer=b,z.yy.parser=this,typeof b.yylloc>"u"&&(b.yylloc={});var $=b.yylloc;i.push($);var pt=b.options&&b.options.ranges;typeof z.yy.parseError=="function"?this.parseError=z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function _t(){var Y;return Y=d.pop()||b.lex()||ot,typeof Y!="number"&&(Y instanceof Array&&(d=Y,Y=d.pop()),Y=n.symbols_[Y]||Y),Y}for(var w,H,D,tt,G={},j,P,lt,q;;){if(H=c[c.length-1],this.defaultActions[H]?D=this.defaultActions[H]:((w===null||typeof w>"u")&&(w=_t()),D=K[H]&&K[H][w]),typeof D>"u"||!D.length||!D[0]){var et="";q=[];for(j in K[H])this.terminals_[j]&&j>ft&&q.push("'"+this.terminals_[j]+"'");b.showPosition?et="Parse error on line "+(Q+1)+`: +import{c as Z,s as Et,g as mt,b as gt,a as kt,x as xt,y as Rt,l as V,A as Ot,h as rt,z as bt,i as Nt,ao as Tt,ar as At}from"./mermaid.core-Bq0kX0MS.js";import{G as Mt}from"./graph-C-EgwjAv.js";import{l as St}from"./layout-DSxgfneE.js";import{l as wt}from"./line-DY_oMjHu.js";import"./app-Bw2NG-QJ.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const It=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function Dt(t){return typeof t=="string"&&It.test(t)}const A=[];for(let t=0;t<256;++t)A.push((t+256).toString(16).slice(1));function vt(t,e=0){return A[t[e+0]]+A[t[e+1]]+A[t[e+2]]+A[t[e+3]]+"-"+A[t[e+4]]+A[t[e+5]]+"-"+A[t[e+6]]+A[t[e+7]]+"-"+A[t[e+8]]+A[t[e+9]]+"-"+A[t[e+10]]+A[t[e+11]]+A[t[e+12]]+A[t[e+13]]+A[t[e+14]]+A[t[e+15]]}function Lt(t){if(!Dt(t))throw TypeError("Invalid UUID");let e;const r=new Uint8Array(16);return r[0]=(e=parseInt(t.slice(0,8),16))>>>24,r[1]=e>>>16&255,r[2]=e>>>8&255,r[3]=e&255,r[4]=(e=parseInt(t.slice(9,13),16))>>>8,r[5]=e&255,r[6]=(e=parseInt(t.slice(14,18),16))>>>8,r[7]=e&255,r[8]=(e=parseInt(t.slice(19,23),16))>>>8,r[9]=e&255,r[10]=(e=parseInt(t.slice(24,36),16))/1099511627776&255,r[11]=e/4294967296&255,r[12]=e>>>24&255,r[13]=e>>>16&255,r[14]=e>>>8&255,r[15]=e&255,r}function Bt(t){t=unescape(encodeURIComponent(t));const e=[];for(let r=0;r>>32-e}function Ft(t){const e=[1518500249,1859775393,2400959708,3395469782],r=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof t=="string"){const f=unescape(encodeURIComponent(t));t=[];for(let o=0;o>>0;x=g,g=m,m=it(_,30)>>>0,_=h,h=I}r[0]=r[0]+h>>>0,r[1]=r[1]+_>>>0,r[2]=r[2]+m>>>0,r[3]=r[3]+g>>>0,r[4]=r[4]+x>>>0}return[r[0]>>24&255,r[0]>>16&255,r[0]>>8&255,r[0]&255,r[1]>>24&255,r[1]>>16&255,r[1]>>8&255,r[1]&255,r[2]>>24&255,r[2]>>16&255,r[2]>>8&255,r[2]&255,r[3]>>24&255,r[3]>>16&255,r[3]>>8&255,r[3]&255,r[4]>>24&255,r[4]>>16&255,r[4]>>8&255,r[4]&255]}const Wt=Yt("v5",80,Ft);var at=function(){var t=function(S,a,n,c){for(n=n||{},c=S.length;c--;n[S[c]]=a);return n},e=[6,8,10,20,22,24,26,27,28],r=[1,10],u=[1,11],l=[1,12],p=[1,13],f=[1,14],o=[1,15],h=[1,21],_=[1,22],m=[1,23],g=[1,24],x=[1,25],y=[6,8,10,13,15,18,19,20,22,24,26,27,28,41,42,43,44,45],N=[1,34],I=[27,28,46,47],F=[41,42,43,44,45],W=[17,34],C=[1,54],T=[1,53],M=[17,34,36,38],R={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,entityName:11,relSpec:12,":":13,role:14,BLOCK_START:15,attributes:16,BLOCK_STOP:17,SQS:18,SQE:19,title:20,title_value:21,acc_title:22,acc_title_value:23,acc_descr:24,acc_descr_value:25,acc_descr_multiline_value:26,ALPHANUM:27,ENTITY_NAME:28,attribute:29,attributeType:30,attributeName:31,attributeKeyTypeList:32,attributeComment:33,ATTRIBUTE_WORD:34,attributeKeyType:35,COMMA:36,ATTRIBUTE_KEY:37,COMMENT:38,cardinality:39,relType:40,ZERO_OR_ONE:41,ZERO_OR_MORE:42,ONE_OR_MORE:43,ONLY_ONE:44,MD_PARENT:45,NON_IDENTIFYING:46,IDENTIFYING:47,WORD:48,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",8:"SPACE",10:"NEWLINE",13:":",15:"BLOCK_START",17:"BLOCK_STOP",18:"SQS",19:"SQE",20:"title",21:"title_value",22:"acc_title",23:"acc_title_value",24:"acc_descr",25:"acc_descr_value",26:"acc_descr_multiline_value",27:"ALPHANUM",28:"ENTITY_NAME",34:"ATTRIBUTE_WORD",36:"COMMA",37:"ATTRIBUTE_KEY",38:"COMMENT",41:"ZERO_OR_ONE",42:"ZERO_OR_MORE",43:"ONE_OR_MORE",44:"ONLY_ONE",45:"MD_PARENT",46:"NON_IDENTIFYING",47:"IDENTIFYING",48:"WORD"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,5],[9,4],[9,3],[9,1],[9,7],[9,6],[9,4],[9,2],[9,2],[9,2],[9,1],[11,1],[11,1],[16,1],[16,2],[29,2],[29,3],[29,3],[29,4],[30,1],[31,1],[32,1],[32,3],[35,1],[33,1],[12,3],[39,1],[39,1],[39,1],[39,1],[39,1],[40,1],[40,1],[14,1],[14,1],[14,1]],performAction:function(a,n,c,d,E,i,K){var s=i.length-1;switch(E){case 1:break;case 2:this.$=[];break;case 3:i[s-1].push(i[s]),this.$=i[s-1];break;case 4:case 5:this.$=i[s];break;case 6:case 7:this.$=[];break;case 8:d.addEntity(i[s-4]),d.addEntity(i[s-2]),d.addRelationship(i[s-4],i[s],i[s-2],i[s-3]);break;case 9:d.addEntity(i[s-3]),d.addAttributes(i[s-3],i[s-1]);break;case 10:d.addEntity(i[s-2]);break;case 11:d.addEntity(i[s]);break;case 12:d.addEntity(i[s-6],i[s-4]),d.addAttributes(i[s-6],i[s-1]);break;case 13:d.addEntity(i[s-5],i[s-3]);break;case 14:d.addEntity(i[s-3],i[s-1]);break;case 15:case 16:this.$=i[s].trim(),d.setAccTitle(this.$);break;case 17:case 18:this.$=i[s].trim(),d.setAccDescription(this.$);break;case 19:case 43:this.$=i[s];break;case 20:case 41:case 42:this.$=i[s].replace(/"/g,"");break;case 21:case 29:this.$=[i[s]];break;case 22:i[s].push(i[s-1]),this.$=i[s];break;case 23:this.$={attributeType:i[s-1],attributeName:i[s]};break;case 24:this.$={attributeType:i[s-2],attributeName:i[s-1],attributeKeyTypeList:i[s]};break;case 25:this.$={attributeType:i[s-2],attributeName:i[s-1],attributeComment:i[s]};break;case 26:this.$={attributeType:i[s-3],attributeName:i[s-2],attributeKeyTypeList:i[s-1],attributeComment:i[s]};break;case 27:case 28:case 31:this.$=i[s];break;case 30:i[s-2].push(i[s]),this.$=i[s-2];break;case 32:this.$=i[s].replace(/"/g,"");break;case 33:this.$={cardA:i[s],relType:i[s-1],cardB:i[s-2]};break;case 34:this.$=d.Cardinality.ZERO_OR_ONE;break;case 35:this.$=d.Cardinality.ZERO_OR_MORE;break;case 36:this.$=d.Cardinality.ONE_OR_MORE;break;case 37:this.$=d.Cardinality.ONLY_ONE;break;case 38:this.$=d.Cardinality.MD_PARENT;break;case 39:this.$=d.Identification.NON_IDENTIFYING;break;case 40:this.$=d.Identification.IDENTIFYING;break}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:9,20:r,22:u,24:l,26:p,27:f,28:o},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:16,11:9,20:r,22:u,24:l,26:p,27:f,28:o},t(e,[2,5]),t(e,[2,6]),t(e,[2,11],{12:17,39:20,15:[1,18],18:[1,19],41:h,42:_,43:m,44:g,45:x}),{21:[1,26]},{23:[1,27]},{25:[1,28]},t(e,[2,18]),t(y,[2,19]),t(y,[2,20]),t(e,[2,4]),{11:29,27:f,28:o},{16:30,17:[1,31],29:32,30:33,34:N},{11:35,27:f,28:o},{40:36,46:[1,37],47:[1,38]},t(I,[2,34]),t(I,[2,35]),t(I,[2,36]),t(I,[2,37]),t(I,[2,38]),t(e,[2,15]),t(e,[2,16]),t(e,[2,17]),{13:[1,39]},{17:[1,40]},t(e,[2,10]),{16:41,17:[2,21],29:32,30:33,34:N},{31:42,34:[1,43]},{34:[2,27]},{19:[1,44]},{39:45,41:h,42:_,43:m,44:g,45:x},t(F,[2,39]),t(F,[2,40]),{14:46,27:[1,49],28:[1,48],48:[1,47]},t(e,[2,9]),{17:[2,22]},t(W,[2,23],{32:50,33:51,35:52,37:C,38:T}),t([17,34,37,38],[2,28]),t(e,[2,14],{15:[1,55]}),t([27,28],[2,33]),t(e,[2,8]),t(e,[2,41]),t(e,[2,42]),t(e,[2,43]),t(W,[2,24],{33:56,36:[1,57],38:T}),t(W,[2,25]),t(M,[2,29]),t(W,[2,32]),t(M,[2,31]),{16:58,17:[1,59],29:32,30:33,34:N},t(W,[2,26]),{35:60,37:C},{17:[1,61]},t(e,[2,13]),t(M,[2,30]),t(e,[2,12])],defaultActions:{34:[2,27],41:[2,22]},parseError:function(a,n){if(n.recoverable)this.trace(a);else{var c=new Error(a);throw c.hash=n,c}},parse:function(a){var n=this,c=[0],d=[],E=[null],i=[],K=this.table,s="",Q=0,st=0,ft=2,ot=1,yt=i.slice.call(arguments,1),b=Object.create(this.lexer),z={yy:{}};for(var J in this.yy)Object.prototype.hasOwnProperty.call(this.yy,J)&&(z.yy[J]=this.yy[J]);b.setInput(a,z.yy),z.yy.lexer=b,z.yy.parser=this,typeof b.yylloc>"u"&&(b.yylloc={});var $=b.yylloc;i.push($);var pt=b.options&&b.options.ranges;typeof z.yy.parseError=="function"?this.parseError=z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function _t(){var Y;return Y=d.pop()||b.lex()||ot,typeof Y!="number"&&(Y instanceof Array&&(d=Y,Y=d.pop()),Y=n.symbols_[Y]||Y),Y}for(var w,H,D,tt,G={},j,P,lt,q;;){if(H=c[c.length-1],this.defaultActions[H]?D=this.defaultActions[H]:((w===null||typeof w>"u")&&(w=_t()),D=K[H]&&K[H][w]),typeof D>"u"||!D.length||!D[0]){var et="";q=[];for(j in K[H])this.terminals_[j]&&j>ft&&q.push("'"+this.terminals_[j]+"'");b.showPosition?et="Parse error on line "+(Q+1)+`: `+b.showPosition()+` Expecting `+q.join(", ")+", got '"+(this.terminals_[w]||w)+"'":et="Parse error on line "+(Q+1)+": Unexpected "+(w==ot?"end of input":"'"+(this.terminals_[w]||w)+"'"),this.parseError(et,{text:b.match,token:this.terminals_[w]||w,line:b.yylineno,loc:$,expected:q})}if(D[0]instanceof Array&&D.length>1)throw new Error("Parse Error: multiple actions possible at state: "+H+", token: "+w);switch(D[0]){case 1:c.push(w),E.push(b.yytext),i.push(b.yylloc),c.push(D[1]),w=null,st=b.yyleng,s=b.yytext,Q=b.yylineno,$=b.yylloc;break;case 2:if(P=this.productions_[D[1]][1],G.$=E[E.length-P],G._$={first_line:i[i.length-(P||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(P||1)].first_column,last_column:i[i.length-1].last_column},pt&&(G._$.range=[i[i.length-(P||1)].range[0],i[i.length-1].range[1]]),tt=this.performAction.apply(G,[s,st,Q,z.yy,D[1],E,i].concat(yt)),typeof tt<"u")return tt;P&&(c=c.slice(0,-1*P*2),E=E.slice(0,-1*P),i=i.slice(0,-1*P)),c.push(this.productions_[D[1]][0]),E.push(G.$),i.push(G._$),lt=K[c[c.length-2]][c[c.length-1]],c.push(lt);break;case 3:return!0}}return!0}},O=function(){var S={EOF:1,parseError:function(n,c){if(this.yy.parser)this.yy.parser.parseError(n,c);else throw new Error(n)},setInput:function(a,n){return this.yy=n||this.yy||{},this._input=a,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var n=a.match(/(?:\r\n?|\n).*/g);return n?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var n=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-n),this.offset-=n;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var E=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-n},this.options.ranges&&(this.yylloc.range=[E[0],E[0]+this.yyleng-n]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),n=new Array(a.length+1).join("-");return a+this.upcomingInput()+` diff --git a/assets/fakedns.html-BInfP9sg.js b/assets/fakedns.html-C-g4Cxj-.js similarity index 99% rename from assets/fakedns.html-BInfP9sg.js rename to assets/fakedns.html-C-g4Cxj-.js index 7bb3524e68..4fec1a56a8 100644 --- a/assets/fakedns.html-BInfP9sg.js +++ b/assets/fakedns.html-C-g4Cxj-.js @@ -1,4 +1,4 @@ -import{_ as p,r as s,o as c,c as i,a,b as l,d as n,w as u,e}from"./app-5SoadDYS.js";const d={},r=e(`

                                        FakeDNS

                                        FakeDNS 通过伪造 DNS 以获取目标域名,能够降低 DNS 查询时的延迟、配合透明代理获取目标域名。

                                        注意

                                        FakeDNS 有可能会污染本地 DNS,导致 Xray 关闭后“无法访问网络”。

                                        FakeDNSObject

                                        FakeDNSObject 对应配置文件的 fakedns 项。

                                        {
                                        +import{_ as p,r as s,o as c,c as i,a,b as l,d as n,w as u,e}from"./app-Bw2NG-QJ.js";const d={},r=e(`

                                        FakeDNS

                                        FakeDNS 通过伪造 DNS 以获取目标域名,能够降低 DNS 查询时的延迟、配合透明代理获取目标域名。

                                        注意

                                        FakeDNS 有可能会污染本地 DNS,导致 Xray 关闭后“无法访问网络”。

                                        FakeDNSObject

                                        FakeDNSObject 对应配置文件的 fakedns 项。

                                        {
                                           "ipPool": "198.18.0.0/16",
                                           "poolSize": 65535
                                         }
                                        diff --git a/assets/fakedns.html-CAdn95B6.js b/assets/fakedns.html-CZTe-tiD.js
                                        similarity index 99%
                                        rename from assets/fakedns.html-CAdn95B6.js
                                        rename to assets/fakedns.html-CZTe-tiD.js
                                        index 09f071e4c5..a6ba526b0e 100644
                                        --- a/assets/fakedns.html-CAdn95B6.js
                                        +++ b/assets/fakedns.html-CZTe-tiD.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as s,o as c,c as i,a,b as l,d as n,w as u,e}from"./app-5SoadDYS.js";const d={},r=e(`

                                        FakeDNS

                                        FakeDNS подменяет DNS-записи, чтобы получить целевое доменное имя, что позволяет сократить время DNS-запросов и получить целевое доменное имя при использовании прозрачного проксирования.

                                        Внимание

                                        FakeDNS может загрязнить локальный DNS-кэш, что может привести к "недоступности сети" после отключения Xray.

                                        FakeDNSObject

                                        FakeDNSObject соответствует полю fakedns в конфигурационном файле.

                                        {
                                        +import{_ as p,r as s,o as c,c as i,a,b as l,d as n,w as u,e}from"./app-Bw2NG-QJ.js";const d={},r=e(`

                                        FakeDNS

                                        FakeDNS подменяет DNS-записи, чтобы получить целевое доменное имя, что позволяет сократить время DNS-запросов и получить целевое доменное имя при использовании прозрачного проксирования.

                                        Внимание

                                        FakeDNS может загрязнить локальный DNS-кэш, что может привести к "недоступности сети" после отключения Xray.

                                        FakeDNSObject

                                        FakeDNSObject соответствует полю fakedns в конфигурационном файле.

                                        {
                                           "ipPool": "198.18.0.0/16",
                                           "poolSize": 65535
                                         }
                                        diff --git a/assets/fakedns.html-C_E8DnIz.js b/assets/fakedns.html-Dh-VkFFO.js
                                        similarity index 99%
                                        rename from assets/fakedns.html-C_E8DnIz.js
                                        rename to assets/fakedns.html-Dh-VkFFO.js
                                        index ab9eac2d22..ab8d223d59 100644
                                        --- a/assets/fakedns.html-C_E8DnIz.js
                                        +++ b/assets/fakedns.html-Dh-VkFFO.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as s,o as i,c,a,b as l,d as n,w as u,e}from"./app-5SoadDYS.js";const r={},d=e(`

                                        FakeDNS

                                        FakeDNS is used to obtain target domain names by forging DNS, which can reduce the delay in DNS queries and work with transparent proxies to obtain target domain names.

                                        Warning

                                        FakeDNS may contaminate the local DNS and cause "network unreachable" after Xray is closed.

                                        FakeDNSObject

                                        FakeDNSObject corresponds to the fakedns item in the configuration file.

                                        {
                                        +import{_ as p,r as s,o as i,c,a,b as l,d as n,w as u,e}from"./app-Bw2NG-QJ.js";const r={},d=e(`

                                        FakeDNS

                                        FakeDNS is used to obtain target domain names by forging DNS, which can reduce the delay in DNS queries and work with transparent proxies to obtain target domain names.

                                        Warning

                                        FakeDNS may contaminate the local DNS and cause "network unreachable" after Xray is closed.

                                        FakeDNSObject

                                        FakeDNSObject corresponds to the fakedns item in the configuration file.

                                        {
                                           "ipPool": "198.18.0.0/16",
                                           "poolSize": 65535
                                         }
                                        diff --git a/assets/fallback.html-P3OM7a42.js b/assets/fallback.html-BuLRpbj4.js
                                        similarity index 99%
                                        rename from assets/fallback.html-P3OM7a42.js
                                        rename to assets/fallback.html-BuLRpbj4.js
                                        index 37a4cdc88f..f60f99d9c0 100644
                                        --- a/assets/fallback.html-P3OM7a42.js
                                        +++ b/assets/fallback.html-BuLRpbj4.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as e,o as i,c as u,a,b as n,d as o,w as c,e as s}from"./app-5SoadDYS.js";const b={},k=s(`

                                        Fallback

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

                                        Fallback обеспечивает Xray высокой степенью защиты от активного зондирования и имеет уникальный механизм резервирования первого пакета.

                                        Fallback также может разделять трафик различных типов по пути, что позволяет совместно использовать один порт для нескольких служб.

                                        В настоящее время вы можете использовать функцию fallback при использовании протоколов VLESS или Trojan, настроив fallbacks, и создавать очень разнообразные комбинации.

                                        Настройка fallbacks

                                          "fallbacks": [
                                        +import{_ as r,r as e,o as i,c as u,a,b as n,d as o,w as c,e as s}from"./app-Bw2NG-QJ.js";const b={},k=s(`

                                        Fallback

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

                                        Fallback обеспечивает Xray высокой степенью защиты от активного зондирования и имеет уникальный механизм резервирования первого пакета.

                                        Fallback также может разделять трафик различных типов по пути, что позволяет совместно использовать один порт для нескольких служб.

                                        В настоящее время вы можете использовать функцию fallback при использовании протоколов VLESS или Trojan, настроив fallbacks, и создавать очень разнообразные комбинации.

                                        Настройка fallbacks

                                          "fallbacks": [
                                             {
                                               "dest": 80
                                             }
                                        diff --git a/assets/fallback.html-DxkOyMwP.js b/assets/fallback.html-DKu1U9AN.js
                                        similarity index 99%
                                        rename from assets/fallback.html-DxkOyMwP.js
                                        rename to assets/fallback.html-DKu1U9AN.js
                                        index d2d9e3a40b..6fbbd3f1b5 100644
                                        --- a/assets/fallback.html-DxkOyMwP.js
                                        +++ b/assets/fallback.html-DKu1U9AN.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as d,r as e,o as i,c as u,a as o,b as n,d as a,w as c,e as t}from"./app-5SoadDYS.js";const b={},k=t(`

                                        Fallback 回落

                                        Fallback 是 Xray 的最强大功能之一, 可有效防止主动探测, 自由配置常用端口多服务共享

                                        fallback 为 Xray 提供了高强度的防主动探测性, 并且具有独创的首包回落机制.

                                        fallback 也可以将不同类型的流量根据 path 进行分流, 从而实现一个端口, 多种服务共享.

                                        目前您可以在使用 VLESS 或者 trojan 协议时, 通过配置 fallbacks 来使用回落这一特性, 并且创造出非常丰富的组合玩法.

                                        fallbacks 配置

                                          "fallbacks": [
                                        +import{_ as d,r as e,o as i,c as u,a as o,b as n,d as a,w as c,e as t}from"./app-Bw2NG-QJ.js";const b={},k=t(`

                                        Fallback 回落

                                        Fallback 是 Xray 的最强大功能之一, 可有效防止主动探测, 自由配置常用端口多服务共享

                                        fallback 为 Xray 提供了高强度的防主动探测性, 并且具有独创的首包回落机制.

                                        fallback 也可以将不同类型的流量根据 path 进行分流, 从而实现一个端口, 多种服务共享.

                                        目前您可以在使用 VLESS 或者 trojan 协议时, 通过配置 fallbacks 来使用回落这一特性, 并且创造出非常丰富的组合玩法.

                                        fallbacks 配置

                                          "fallbacks": [
                                             {
                                               "dest": 80
                                             }
                                        diff --git a/assets/fallback.html-BUzHu26K.js b/assets/fallback.html-O3X9XOSg.js
                                        similarity index 99%
                                        rename from assets/fallback.html-BUzHu26K.js
                                        rename to assets/fallback.html-O3X9XOSg.js
                                        index 86c719ede2..9665ddb3ef 100644
                                        --- a/assets/fallback.html-BUzHu26K.js
                                        +++ b/assets/fallback.html-O3X9XOSg.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as n,o as d,c as p,a as o,b as e,d as t,w as u,e as a}from"./app-5SoadDYS.js";const h={},f=a(`

                                        Fallback

                                        Fallback is one of the most powerful features of Xray, which can effectively prevent active probing and allows you to use one port for multiple services

                                        Fallback provides Xray with high-strength anti-active probing capabilities and has a unique first-packet fallback mechanism.

                                        Fallback can also divide traffic of different types based on path for multi-service sharing on a single port.

                                        Currently, you can use the fallback feature by configuring fallbacks when using VLESS or Trojan protocols, thus creating an unimaginable combo of services becomes REALITY.

                                        fallbacks configuration

                                          "fallbacks": [
                                        +import{_ as r,r as n,o as d,c as p,a as o,b as e,d as t,w as u,e as a}from"./app-Bw2NG-QJ.js";const h={},f=a(`

                                        Fallback

                                        Fallback is one of the most powerful features of Xray, which can effectively prevent active probing and allows you to use one port for multiple services

                                        Fallback provides Xray with high-strength anti-active probing capabilities and has a unique first-packet fallback mechanism.

                                        Fallback can also divide traffic of different types based on path for multi-service sharing on a single port.

                                        Currently, you can use the fallback feature by configuring fallbacks when using VLESS or Trojan protocols, thus creating an unimaginable combo of services becomes REALITY.

                                        fallbacks configuration

                                          "fallbacks": [
                                             {
                                               "dest": 80
                                             }
                                        diff --git a/assets/fallbacks-lv1.html-CogqnjdA.js b/assets/fallbacks-lv1.html-BCtwtJCw.js
                                        similarity index 99%
                                        rename from assets/fallbacks-lv1.html-CogqnjdA.js
                                        rename to assets/fallbacks-lv1.html-BCtwtJCw.js
                                        index d4d6ddedb5..f735d8b417 100644
                                        --- a/assets/fallbacks-lv1.html-CogqnjdA.js
                                        +++ b/assets/fallbacks-lv1.html-BCtwtJCw.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as t,o as r,c as d,a,b as n,d as s,w as l,e as o}from"./app-5SoadDYS.js";const k={},v=n("h1",{id:"回落-fallbacks-功能简析",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#回落-fallbacks-功能简析"},[n("span",null,"回落 (fallbacks) 功能简析")])],-1),m=n("p",null,"在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。",-1),q=n("h2",{id:"_1-回顾《小小白白话文》中的回落",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_1-回顾《小小白白话文》中的回落"},[n("span",null,"1. 回顾《小小白白话文》中的回落")])],-1),b=n("code",null,"VLESS",-1),E=o(`
                                        {
                                        +import{_ as u,r as t,o as r,c as d,a,b as n,d as s,w as l,e as o}from"./app-Bw2NG-QJ.js";const k={},v=n("h1",{id:"回落-fallbacks-功能简析",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#回落-fallbacks-功能简析"},[n("span",null,"回落 (fallbacks) 功能简析")])],-1),m=n("p",null,"在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。",-1),q=n("h2",{id:"_1-回顾《小小白白话文》中的回落",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_1-回顾《小小白白话文》中的回落"},[n("span",null,"1. 回顾《小小白白话文》中的回落")])],-1),b=n("code",null,"VLESS",-1),E=o(`
                                        {
                                           "inbounds": [
                                             {
                                               "port": 443,
                                        diff --git a/assets/fallbacks-lv1.html-R7zbt45s.js b/assets/fallbacks-lv1.html-CI6CRNYF.js
                                        similarity index 99%
                                        rename from assets/fallbacks-lv1.html-R7zbt45s.js
                                        rename to assets/fallbacks-lv1.html-CI6CRNYF.js
                                        index e240800c0e..19e6f8fda2 100644
                                        --- a/assets/fallbacks-lv1.html-R7zbt45s.js
                                        +++ b/assets/fallbacks-lv1.html-CI6CRNYF.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as t,o as r,c as d,a,b as n,d as s,w as l,e as o}from"./app-5SoadDYS.js";const k={},v=n("h1",{id:"回落-fallbacks-功能简析",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#回落-fallbacks-功能简析"},[n("span",null,"回落 (fallbacks) 功能简析")])],-1),m=n("p",null,"在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。",-1),q=n("h2",{id:"_1-回顾《小小白白话文》中的回落",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_1-回顾《小小白白话文》中的回落"},[n("span",null,"1. 回顾《小小白白话文》中的回落")])],-1),b=n("code",null,"VLESS",-1),E=o(`
                                        {
                                        +import{_ as u,r as t,o as r,c as d,a,b as n,d as s,w as l,e as o}from"./app-Bw2NG-QJ.js";const k={},v=n("h1",{id:"回落-fallbacks-功能简析",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#回落-fallbacks-功能简析"},[n("span",null,"回落 (fallbacks) 功能简析")])],-1),m=n("p",null,"在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。",-1),q=n("h2",{id:"_1-回顾《小小白白话文》中的回落",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_1-回顾《小小白白话文》中的回落"},[n("span",null,"1. 回顾《小小白白话文》中的回落")])],-1),b=n("code",null,"VLESS",-1),E=o(`
                                        {
                                           "inbounds": [
                                             {
                                               "port": 443,
                                        diff --git a/assets/fallbacks-lv1.html-3a74qZ1k.js b/assets/fallbacks-lv1.html-DYToMiS6.js
                                        similarity index 99%
                                        rename from assets/fallbacks-lv1.html-3a74qZ1k.js
                                        rename to assets/fallbacks-lv1.html-DYToMiS6.js
                                        index ef8c304f57..2b9965a8a6 100644
                                        --- a/assets/fallbacks-lv1.html-3a74qZ1k.js
                                        +++ b/assets/fallbacks-lv1.html-DYToMiS6.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as t,o as u,c as d,a,b as n,d as s,w as l,e as o}from"./app-5SoadDYS.js";const k={},v=n("h1",{id:"обзор-функции-fallback",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#обзор-функции-fallback"},[n("span",null,"Обзор функции Fallback")])],-1),D=n("p",null,[s("При использовании Xray вы наверняка много раз слышали о функции "),n("strong",null,'"fallback"'),s(". В этой статье мы кратко рассмотрим логику этой функции и способы ее применения.")],-1),m=n("h2",{id:"_1-что-такое-fallback-в-простых-словах",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_1-что-такое-fallback-в-простых-словах"},[n("span",null,"1. Что такое Fallback в простых словах")])],-1),b=n("code",null,"VLESS",-1),q=o(`
                                        {
                                        +import{_ as r,r as t,o as u,c as d,a,b as n,d as s,w as l,e as o}from"./app-Bw2NG-QJ.js";const k={},v=n("h1",{id:"обзор-функции-fallback",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#обзор-функции-fallback"},[n("span",null,"Обзор функции Fallback")])],-1),D=n("p",null,[s("При использовании Xray вы наверняка много раз слышали о функции "),n("strong",null,'"fallback"'),s(". В этой статье мы кратко рассмотрим логику этой функции и способы ее применения.")],-1),m=n("h2",{id:"_1-что-такое-fallback-в-простых-словах",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#_1-что-такое-fallback-в-простых-словах"},[n("span",null,"1. Что такое Fallback в простых словах")])],-1),b=n("code",null,"VLESS",-1),q=o(`
                                        {
                                           "inbounds": [
                                             {
                                               "port": 443,
                                        diff --git a/assets/fallbacks-with-sni.html-BAchho5z.js b/assets/fallbacks-with-sni.html-B0wSUJmq.js
                                        similarity index 99%
                                        rename from assets/fallbacks-with-sni.html-BAchho5z.js
                                        rename to assets/fallbacks-with-sni.html-B0wSUJmq.js
                                        index f348b6fb05..3947e58585 100644
                                        --- a/assets/fallbacks-with-sni.html-BAchho5z.js
                                        +++ b/assets/fallbacks-with-sni.html-B0wSUJmq.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as o,o as l,c as r,a,b as n,d as s,e as t}from"./app-5SoadDYS.js";const c="/assets/xray-fallbacks-gLm6MqAx.svg",d="/assets/xray-dns-records-lpau4JTO.webp",u="/assets/cf-api-token-permissions-for-acme-BmGfLU86.webp",v={},h=n("h1",{id:"implementing-camouflage-and-domain-based-routing-through-sni-fallback-function",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#implementing-camouflage-and-domain-based-routing-through-sni-fallback-function"},[n("span",null,"Implementing camouflage and domain-based routing through SNI fallback function")])],-1),m=t(`

                                        VLESS is a lightweight protocol that, like Trojan, does not perform complex encryption and obfuscation on traffic. Instead, it is encrypted through the TLS protocol and mixed in with other HTTPS traffic, making it difficult to detect. In order to better disguise itself and respond to active probing, the fallback function appeared with VLESS at the same time. This tutorial will demonstrate how to use the fallback function of VLESS inbound protocol in Xray, combined with Nginx or Caddy, to achieve domain name-based traffic routing while ensuring complete disguise.

                                        Application Scenarios

                                        Due to XTLS, Xray needs to listen on port 443, which means that if there is a website running on the server, it cannot run or needs to run on another port, which is obviously unreasonable. There are three solutions to this problem:

                                        • Xray monitors other commonly used ports (such as 22, 3389, 8443).

                                        This plan is the simplest, but not perfect enough.

                                        • Nginx or HAProxy listens on port 443, uses SNI for L4 load balancing, and achieves port multiplexing through reverse proxy.

                                        This plan is relatively complicated and requires some understanding of using Nginx or HAProxy. We will not explain it in too much detail here.

                                        • Xray listens on port 443, and uses Fallbacks feature to split website traffic based on SNI and fallbacks it to Nginx or Caddy.

                                        This plan has a moderate level of difficulty and is the scheme that this tutorial will demonstrate next.

                                        Introduction to SNI

                                        Server Name Indication (SNI) is an extension protocol of TLS. Friends who are familiar with reverse proxies know that the following configuration is required if you want to proxy traffic to the correct content through a domain name:

                                        proxy_set_header Host hostname;
                                        +import{_ as p,r as o,o as l,c as r,a,b as n,d as s,e as t}from"./app-Bw2NG-QJ.js";const c="/assets/xray-fallbacks-gLm6MqAx.svg",d="/assets/xray-dns-records-lpau4JTO.webp",u="/assets/cf-api-token-permissions-for-acme-BmGfLU86.webp",v={},h=n("h1",{id:"implementing-camouflage-and-domain-based-routing-through-sni-fallback-function",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#implementing-camouflage-and-domain-based-routing-through-sni-fallback-function"},[n("span",null,"Implementing camouflage and domain-based routing through SNI fallback function")])],-1),m=t(`

                                        VLESS is a lightweight protocol that, like Trojan, does not perform complex encryption and obfuscation on traffic. Instead, it is encrypted through the TLS protocol and mixed in with other HTTPS traffic, making it difficult to detect. In order to better disguise itself and respond to active probing, the fallback function appeared with VLESS at the same time. This tutorial will demonstrate how to use the fallback function of VLESS inbound protocol in Xray, combined with Nginx or Caddy, to achieve domain name-based traffic routing while ensuring complete disguise.

                                        Application Scenarios

                                        Due to XTLS, Xray needs to listen on port 443, which means that if there is a website running on the server, it cannot run or needs to run on another port, which is obviously unreasonable. There are three solutions to this problem:

                                        • Xray monitors other commonly used ports (such as 22, 3389, 8443).

                                        This plan is the simplest, but not perfect enough.

                                        • Nginx or HAProxy listens on port 443, uses SNI for L4 load balancing, and achieves port multiplexing through reverse proxy.

                                        This plan is relatively complicated and requires some understanding of using Nginx or HAProxy. We will not explain it in too much detail here.

                                        • Xray listens on port 443, and uses Fallbacks feature to split website traffic based on SNI and fallbacks it to Nginx or Caddy.

                                        This plan has a moderate level of difficulty and is the scheme that this tutorial will demonstrate next.

                                        Introduction to SNI

                                        Server Name Indication (SNI) is an extension protocol of TLS. Friends who are familiar with reverse proxies know that the following configuration is required if you want to proxy traffic to the correct content through a domain name:

                                        proxy_set_header Host hostname;
                                         

                                        (Note: "hostname" should be replaced with the actual hostname.)

                                        This sentence sets the HTTP Header named "Host" to a certain hostname. Why do we need to do this? Generally, one server corresponds to one IP address, but it runs multiple websites. Visitors access the server by querying the IP address via domain name to visit the website. Then the question arises, how to determine which website the visitor wants to access? This requires "name-based virtual hosting".

                                        When a Web server receives a request, it looks at the host header to direct the visitor to the correct website. However, this simple method cannot be used when HTTP protocol is encrypted by TLS protocol. This is because the TLS handshake occurs before the server sees any HTTP headers, so the server cannot use the information in the HTTP host header to determine which certificate to present or which destination the visitor wants to access.

                                        The principle of SNI is also very simple. It solves the problem by allowing the client to send the hostname as part of the TLS negotiation. Therefore, when using Nginx to reverse proxy the HTTPS protocol, you need to add proxy_ssl_server_name on; to the configuration. At this time, Nginx will send SNI information to the proxied server, solving the problem of virtual host failure under the HTTPS protocol. In addition, when using SNI, even if the host header is not specified, the website can be accessed correctly.

                                        Idea

                                        Xray Fallback Process

                                        After receiving traffic from port 443, Xray will decrypt the TLS and forward the traffic that has a first packet length < 18, invalid protocol version, or failed authentication through matching name, path, and alpn to the address specified by dest.

                                        Adding DNS Records

                                        DNS Records

                                        Please modify the domain name and IP according to the actual situation.

                                        Applying for TLS Certificate

                                        ',23),k=n("code",null,"*.example.com",-1),b=n("code",null,"example.com",-1),f=n("code",null,"*.*.example.com",-1),g={href:"https://en.wikipedia.org/wiki/Subject_Alternative_Name",target:"_blank",rel:"noopener noreferrer"},y={href:"https://acme.sh",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/acmesh-official/acme.sh/wiki/dnsapi",target:"_blank",rel:"noopener noreferrer"},x={href:"https://dash.cloudflare.com/profile/api-tokens",target:"_blank",rel:"noopener noreferrer"},w=t('

                                        API Token permission settings

                                        The permission part is crucial, while other parts are optional.

                                        After creating, you will receive a mysterious string of characters. Please keep it safe in a secure and non-losing place, as it will not be displayed again. This string of characters is the CF_Token that will be used soon.

                                        Note

                                        The following operations need to be performed under the root user. Using sudo will result in errors.

                                        curl https://get.acme.sh | sh # Install acme.sh
                                         export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" # Set API Token variable
                                         acme.sh --issue -d example.com -d *.example.com --dns dns_cf # Apply for a certificate using DNS-01 validation method
                                        diff --git a/assets/fallbacks-with-sni.html-B2NZf_xW.js b/assets/fallbacks-with-sni.html-B3snUr7L.js
                                        similarity index 99%
                                        rename from assets/fallbacks-with-sni.html-B2NZf_xW.js
                                        rename to assets/fallbacks-with-sni.html-B3snUr7L.js
                                        index dd16d93b89..12e1f8cca0 100644
                                        --- a/assets/fallbacks-with-sni.html-B2NZf_xW.js
                                        +++ b/assets/fallbacks-with-sni.html-B3snUr7L.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as o,o as i,c,a,b as n,d as s,e as t}from"./app-5SoadDYS.js";const r="/assets/xray-fallbacks-gLm6MqAx.svg",u="/assets/xray-dns-records-lpau4JTO.webp",d="/assets/cf-api-token-permissions-for-acme-BmGfLU86.webp",v={},k=n("h1",{id:"маскировка-и-разделение-трафика-по-доменам-с-помощью-функции-sni-fallback",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#маскировка-и-разделение-трафика-по-доменам-с-помощью-функции-sni-fallback"},[n("span",null,"Маскировка и разделение трафика по доменам с помощью функции SNI Fallback")])],-1),m=t(`

                                        VLESS - это очень легкий протокол, который, как и Trojan, не использует сложного шифрования и обфускации трафика. Вместо этого он, подобно тому, как искусный мастер кунг-фу скрывает свою силу, шифрует трафик с помощью протокола TLS, маскируя его под обычный HTTPS-трафик и позволяя ему беспрепятственно проходить через Великий китайский файрвол. Для лучшей маскировки от активного зондирования вместе с VLESS была представлена функция Fallbacks (резервирование). В этой статье мы рассмотрим, как использовать функцию Fallbacks входящего протокола VLESS в Xray совместно с Nginx или Caddy для реализации разделения трафика по доменам при обеспечении полной маскировки.

                                        Сценарии использования

                                        Из-за XTLS Xray необходимо прослушивать порт 443, что создает проблему, если на сервере уже запущен веб-сайт - сайт либо не сможет работать, либо его придется запускать на другом порту, что нежелательно. Есть три способа решить эту проблему:

                                        • Xray прослушивает другие часто используемые порты (например, 22, 3389, 8443).

                                          Это самое простое решение, но оно не идеально.

                                        • Nginx или HAProxy прослушивает порт 443 и выполняет обратное проксирование на уровне L4 с разделением трафика по SNI, что позволяет использовать один порт для нескольких сервисов.

                                          Этот вариант более сложный и требует определенных знаний Nginx или HAProxy, поэтому мы не будем его здесь подробно рассматривать.

                                        • Xray прослушивает порт 443 и использует функцию Fallbacks для перенаправления трафика веб-сайта на Nginx или Caddy на основе SNI.

                                          Этот вариант имеет среднюю сложность и является тем, который мы рассмотрим в этом руководстве.

                                        Что такое SNI

                                        SNI (Server Name Indication) - это расширение протокола TLS. Те, кто знаком с обратным проксированием, знают, что для правильной маршрутизации трафика по доменному имени необходимо следующее правило:

                                        proxy_set_header Host имя_хоста;
                                        +import{_ as l,r as o,o as i,c,a,b as n,d as s,e as t}from"./app-Bw2NG-QJ.js";const r="/assets/xray-fallbacks-gLm6MqAx.svg",u="/assets/xray-dns-records-lpau4JTO.webp",d="/assets/cf-api-token-permissions-for-acme-BmGfLU86.webp",v={},k=n("h1",{id:"маскировка-и-разделение-трафика-по-доменам-с-помощью-функции-sni-fallback",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#маскировка-и-разделение-трафика-по-доменам-с-помощью-функции-sni-fallback"},[n("span",null,"Маскировка и разделение трафика по доменам с помощью функции SNI Fallback")])],-1),m=t(`

                                        VLESS - это очень легкий протокол, который, как и Trojan, не использует сложного шифрования и обфускации трафика. Вместо этого он, подобно тому, как искусный мастер кунг-фу скрывает свою силу, шифрует трафик с помощью протокола TLS, маскируя его под обычный HTTPS-трафик и позволяя ему беспрепятственно проходить через Великий китайский файрвол. Для лучшей маскировки от активного зондирования вместе с VLESS была представлена функция Fallbacks (резервирование). В этой статье мы рассмотрим, как использовать функцию Fallbacks входящего протокола VLESS в Xray совместно с Nginx или Caddy для реализации разделения трафика по доменам при обеспечении полной маскировки.

                                        Сценарии использования

                                        Из-за XTLS Xray необходимо прослушивать порт 443, что создает проблему, если на сервере уже запущен веб-сайт - сайт либо не сможет работать, либо его придется запускать на другом порту, что нежелательно. Есть три способа решить эту проблему:

                                        • Xray прослушивает другие часто используемые порты (например, 22, 3389, 8443).

                                          Это самое простое решение, но оно не идеально.

                                        • Nginx или HAProxy прослушивает порт 443 и выполняет обратное проксирование на уровне L4 с разделением трафика по SNI, что позволяет использовать один порт для нескольких сервисов.

                                          Этот вариант более сложный и требует определенных знаний Nginx или HAProxy, поэтому мы не будем его здесь подробно рассматривать.

                                        • Xray прослушивает порт 443 и использует функцию Fallbacks для перенаправления трафика веб-сайта на Nginx или Caddy на основе SNI.

                                          Этот вариант имеет среднюю сложность и является тем, который мы рассмотрим в этом руководстве.

                                        Что такое SNI

                                        SNI (Server Name Indication) - это расширение протокола TLS. Те, кто знаком с обратным проксированием, знают, что для правильной маршрутизации трафика по доменному имени необходимо следующее правило:

                                        proxy_set_header Host имя_хоста;
                                         

                                        Эта строка устанавливает HTTP-заголовок "Host" на определенное имя хоста. Зачем это нужно? Обычно у одного сервера один IP-адрес, но на нем может быть запущено несколько сайтов. Пользователи получают IP-адрес по доменному имени и обращаются к серверу, но как сервер определяет, какой именно сайт запрашивает пользователь? Для этого используются виртуальные хосты, основанные на имени.

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

                                        SNI решает эту проблему, позволяя клиенту отправлять имя хоста как часть TLS-рукопожатия. Поэтому при использовании Nginx для обратного проксирования HTTPS-трафика необходимо добавить в конфигурацию proxy_ssl_server_name on;. В этом случае Nginx будет отправлять информацию SNI на проксируемый сервер, решая проблему неработающих виртуальных хостов по HTTPS. Кроме того, при использовании SNI можно получить доступ к нужному сайту, даже не указывая заголовок "Host".

                                        Идея

                                        Схема работы Xray Fallbacks

                                        После получения трафика на порт 443 Xray расшифровывает TLS и перенаправляет трафик с длиной первого пакета менее 18 байт, неверной версией протокола или ошибкой аутентификации на адрес, указанный в dest, на основе совпадения name, path или alpn.

                                        Добавление DNS-записей

                                        DNS-записи

                                        Измените домен и IP-адрес в соответствии с вашей ситуацией.

                                        Запрос TLS-сертификата

                                        ',17),b=n("code",null,"*.example.com",-1),h=n("code",null,"example.com",-1),q=n("code",null,"*.*.example.com",-1),f={href:"https://ru.wikipedia.org/wiki/Subject_Alternative_Name",target:"_blank",rel:"noopener noreferrer"},y=n("sup",{class:"footnote-ref"},[n("a",{href:"#fn1",id:"fnref1"},"[1]")],-1),g={href:"https://acme.sh",target:"_blank",rel:"noopener noreferrer"},_={href:"https://github.com/acmesh-official/acme.sh/wiki/dnsapi",target:"_blank",rel:"noopener noreferrer"},x={href:"https://dash.cloudflare.com/profile/api-tokens",target:"_blank",rel:"noopener noreferrer"},w=t('

                                        Настройка прав доступа API-токена

                                        Настройка прав доступа очень важна, остальные параметры можно оставить по умолчанию.

                                        После создания вы получите строку символов - это и есть ваш API-токен (CF_Token). Сохраните его в надежном месте, так как он больше не будет отображаться.

                                        Внимание

                                        Следующие действия необходимо выполнять от имени пользователя root. Использование sudo может привести к ошибкам.

                                        curl https://get.acme.sh | sh # Установка acme.sh
                                         export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" # Установка переменной окружения с API-токеном
                                         acme.sh --issue -d example.com -d *.example.com --dns dns_cf # Запрос сертификата с проверкой DNS-01
                                        diff --git a/assets/fallbacks-with-sni.html-BO2m1L8j.js b/assets/fallbacks-with-sni.html-iAcmmVov.js
                                        similarity index 99%
                                        rename from assets/fallbacks-with-sni.html-BO2m1L8j.js
                                        rename to assets/fallbacks-with-sni.html-iAcmmVov.js
                                        index b492abdbea..5ea81f56a3 100644
                                        --- a/assets/fallbacks-with-sni.html-BO2m1L8j.js
                                        +++ b/assets/fallbacks-with-sni.html-iAcmmVov.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as o,o as i,c,a,b as n,d as s,e as t}from"./app-5SoadDYS.js";const r="/assets/xray-fallbacks-gLm6MqAx.svg",u="/assets/xray-dns-records-lpau4JTO.webp",d="/assets/cf-api-token-permissions-for-acme-BmGfLU86.webp",v={},k=n("h1",{id:"通过-sni-回落功能实现伪装与按域名分流",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#通过-sni-回落功能实现伪装与按域名分流"},[n("span",null,"通过 SNI 回落功能实现伪装与按域名分流")])],-1),m=t(`

                                        VLESS 是一种很轻的协议,和 Trojan 一样,不对流量进行复杂的加密和混淆,而是大隐隐于市,通过 TLS 协议加密,混杂在其他 HTTPS 流量中,在墙内外穿进穿出。为了更好的伪装以应对主动探测,Fallbacks 回落功能随 VLESS 同时出现。这篇教程将演示如何使用 Xray 中 VLESS 入站协议的回落功能配合 Nginx 或 Caddy 在保证伪装完全的前提下实现按域名分流。

                                        应用情景

                                        由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题:

                                        • Xray 监听其他常用端口(如 22、3389、8443)

                                          这个方案是最简单的,但不够完美。

                                        • Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用

                                          这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。

                                        • Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy

                                          这个方案难度适中,也是此教程接下来想要演示的方案。

                                        SNI 简介

                                        服务器名称指示(英语:Server Name Indication,缩写:SNI)是 TLS 的一个扩展协议。熟悉反向代理的朋友都知道,如果想要通过域名将流量代理到正确的内容上,需要以下配置:

                                        proxy_set_header Host 主机名;
                                        +import{_ as l,r as o,o as i,c,a,b as n,d as s,e as t}from"./app-Bw2NG-QJ.js";const r="/assets/xray-fallbacks-gLm6MqAx.svg",u="/assets/xray-dns-records-lpau4JTO.webp",d="/assets/cf-api-token-permissions-for-acme-BmGfLU86.webp",v={},k=n("h1",{id:"通过-sni-回落功能实现伪装与按域名分流",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#通过-sni-回落功能实现伪装与按域名分流"},[n("span",null,"通过 SNI 回落功能实现伪装与按域名分流")])],-1),m=t(`

                                        VLESS 是一种很轻的协议,和 Trojan 一样,不对流量进行复杂的加密和混淆,而是大隐隐于市,通过 TLS 协议加密,混杂在其他 HTTPS 流量中,在墙内外穿进穿出。为了更好的伪装以应对主动探测,Fallbacks 回落功能随 VLESS 同时出现。这篇教程将演示如何使用 Xray 中 VLESS 入站协议的回落功能配合 Nginx 或 Caddy 在保证伪装完全的前提下实现按域名分流。

                                        应用情景

                                        由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题:

                                        • Xray 监听其他常用端口(如 22、3389、8443)

                                          这个方案是最简单的,但不够完美。

                                        • Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用

                                          这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。

                                        • Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy

                                          这个方案难度适中,也是此教程接下来想要演示的方案。

                                        SNI 简介

                                        服务器名称指示(英语:Server Name Indication,缩写:SNI)是 TLS 的一个扩展协议。熟悉反向代理的朋友都知道,如果想要通过域名将流量代理到正确的内容上,需要以下配置:

                                        proxy_set_header Host 主机名;
                                         

                                        这句的作用是将名为 “Host” 的 HTTP Header 设定为某个主机名。为什么要这样做?一般而言,一台服务器对应一个 IP,但却运行多个网站,访问者通过域名查询到 IP 以访问服务器,那么问题来了,如何确定访问者想要访问的是哪一个网站?这需要“基于名称的虚拟主机”。

                                        当 Web 服务器收到访问请求后,它会查看请求的主机头,使访问者访问正确的网站。然而当 HTTP 协议被 TLS 协议加密后,这种简单的方法就无法实现了。因为 TLS 握手发生在服务器看到任何 HTTP 头之前,因此,服务器不可能使用 HTTP 主机头中的信息来决定呈现哪个证书,更无法决定访问者的访问目标。

                                        SNI 的原理也很简单,它通过让客户端发送主机名作为 TLS 协商的一部分来解决此问题。所以在使用 Nginx 对 HTTPS 协议进行反向代理时,需要在配置中加入 proxy_ssl_server_name on;,此时 Nginx 会向被代理的服务器发送 SNI 信息,解决了 HTTPS 协议下虚拟主机失效的问题。另外,使用 SNI 时,即使不指定主机头,也可以正确访问网站。

                                        思路

                                        Xray 回落流程

                                        从 443 端口接收到流量后,Xray 会把 TLS 解密后首包长度 < 18、协议版本无效或身份认证失败的流量通过对 name、path、alpn 的匹配转发到 dest 指定的地址。

                                        添加 DNS 记录

                                        DNS 记录

                                        请按实际情况修改域名和 IP。

                                        申请 TLS 证书

                                        ',17),b=n("code",null,"*.example.com",-1),h=n("code",null,"example.com",-1),q=n("code",null,"*.*.example.com",-1),f={href:"https://zh.wikipedia.org/wiki/%E4%B8%BB%E9%A2%98%E5%A4%87%E7%94%A8%E5%90%8D%E7%A7%B0",target:"_blank",rel:"noopener noreferrer"},y=n("sup",{class:"footnote-ref"},[n("a",{href:"#fn1",id:"fnref1"},"[1]")],-1),g={href:"https://acme.sh",target:"_blank",rel:"noopener noreferrer"},_={href:"https://github.com/acmesh-official/acme.sh/wiki/dnsapi",target:"_blank",rel:"noopener noreferrer"},x={href:"https://dash.cloudflare.com/profile/api-tokens",target:"_blank",rel:"noopener noreferrer"},T=t('

                                        API Token 的权限设置

                                        权限部分至关重要,其他部分任意。

                                        创建完毕后,你会得到一串神秘字符,请将其妥善保管到安全且不会丢失的地方,因为它不再会显示。这串字符就是即将用到的 CF_Token

                                        注意

                                        以下操作需要在 root 用户下进行,使用 sudo 会出现错误。

                                        curl https://get.acme.sh | sh # 安装 acme.sh
                                         export CF_Token="sdfsdfsdfljlbjkljlkjsdfoiwje" # 设定 API Token 变量
                                         acme.sh --issue -d example.com -d *.example.com --dns dns_cf # 使用 DNS-01 验证方式申请证书
                                        diff --git a/assets/flowDb-c1833063-8FVnhkY0.js b/assets/flowDb-c1833063-Csuwz1ip.js
                                        similarity index 99%
                                        rename from assets/flowDb-c1833063-8FVnhkY0.js
                                        rename to assets/flowDb-c1833063-Csuwz1ip.js
                                        index f677ec3db6..e31ef0189c 100644
                                        --- a/assets/flowDb-c1833063-8FVnhkY0.js
                                        +++ b/assets/flowDb-c1833063-Csuwz1ip.js
                                        @@ -1,4 +1,4 @@
                                        -import{c as et,v as me,s as ye,g as ve,a as Ve,b as Le,x as Ie,y as Re,l as J1,z as dt,A as Ne,j as we,h as w1}from"./mermaid.core-CArNAncI.js";var pt=function(){var e=function(f1,a,o,f){for(o=o||{},f=f1.length;f--;o[f1[f]]=a);return o},u=[1,4],i=[1,3],n=[1,5],c=[1,8,9,10,11,27,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],l=[2,2],h=[1,13],U=[1,14],F=[1,15],w=[1,16],X=[1,23],o1=[1,25],p1=[1,26],A1=[1,27],C=[1,49],k=[1,48],l1=[1,29],U1=[1,30],G1=[1,31],M1=[1,32],K1=[1,33],x=[1,44],B=[1,46],m=[1,42],y=[1,47],v=[1,43],V=[1,50],L=[1,45],I=[1,51],R=[1,52],Y1=[1,34],j1=[1,35],z1=[1,36],X1=[1,37],I1=[1,57],b=[1,8,9,10,11,27,32,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],q=[1,61],Q=[1,60],Z=[1,62],H1=[8,9,11,73,75],k1=[1,88],b1=[1,93],g1=[1,92],D1=[1,89],F1=[1,85],T1=[1,91],S1=[1,87],C1=[1,94],_1=[1,90],x1=[1,95],B1=[1,86],W1=[8,9,10,11,73,75],N=[8,9,10,11,44,73,75],M=[8,9,10,11,29,42,44,46,48,50,52,54,56,58,61,63,65,66,68,73,75,86,99,102,103,106,108,111,112,113],Et=[8,9,11,42,58,73,75,86,99,102,103,106,108,111,112,113],R1=[42,58,86,99,102,103,106,108,111,112,113],kt=[1,121],bt=[1,120],gt=[1,128],Dt=[1,142],Ft=[1,143],Tt=[1,144],St=[1,145],Ct=[1,130],_t=[1,132],xt=[1,136],Bt=[1,137],mt=[1,138],yt=[1,139],vt=[1,140],Vt=[1,141],Lt=[1,146],It=[1,147],Rt=[1,126],Nt=[1,127],wt=[1,134],Ot=[1,129],Pt=[1,133],Ut=[1,131],nt=[8,9,10,11,27,32,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],Gt=[1,149],T=[8,9,11],K=[8,9,10,11,14,42,58,86,102,103,106,108,111,112,113],p=[1,169],O=[1,165],P=[1,166],A=[1,170],d=[1,167],E=[1,168],m1=[75,113,116],g=[8,9,10,11,12,14,27,29,32,42,58,73,81,82,83,84,85,86,87,102,106,108,111,112,113],Mt=[10,103],h1=[31,47,49,51,53,55,60,62,64,65,67,69,113,114,115],J=[1,235],$=[1,233],t1=[1,237],e1=[1,231],s1=[1,232],u1=[1,234],i1=[1,236],r1=[1,238],y1=[1,255],Kt=[8,9,11,103],W=[8,9,10,11,58,81,102,103,106,107,108,109],at={trace:function(){},yy:{},symbols_:{error:2,start:3,graphConfig:4,document:5,line:6,statement:7,SEMI:8,NEWLINE:9,SPACE:10,EOF:11,GRAPH:12,NODIR:13,DIR:14,FirstStmtSeparator:15,ending:16,endToken:17,spaceList:18,spaceListNewline:19,vertexStatement:20,separator:21,styleStatement:22,linkStyleStatement:23,classDefStatement:24,classStatement:25,clickStatement:26,subgraph:27,textNoTags:28,SQS:29,text:30,SQE:31,end:32,direction:33,acc_title:34,acc_title_value:35,acc_descr:36,acc_descr_value:37,acc_descr_multiline_value:38,link:39,node:40,styledVertex:41,AMP:42,vertex:43,STYLE_SEPARATOR:44,idString:45,DOUBLECIRCLESTART:46,DOUBLECIRCLEEND:47,PS:48,PE:49,"(-":50,"-)":51,STADIUMSTART:52,STADIUMEND:53,SUBROUTINESTART:54,SUBROUTINEEND:55,VERTEX_WITH_PROPS_START:56,"NODE_STRING[field]":57,COLON:58,"NODE_STRING[value]":59,PIPE:60,CYLINDERSTART:61,CYLINDEREND:62,DIAMOND_START:63,DIAMOND_STOP:64,TAGEND:65,TRAPSTART:66,TRAPEND:67,INVTRAPSTART:68,INVTRAPEND:69,linkStatement:70,arrowText:71,TESTSTR:72,START_LINK:73,edgeText:74,LINK:75,edgeTextToken:76,STR:77,MD_STR:78,textToken:79,keywords:80,STYLE:81,LINKSTYLE:82,CLASSDEF:83,CLASS:84,CLICK:85,DOWN:86,UP:87,textNoTagsToken:88,stylesOpt:89,"idString[vertex]":90,"idString[class]":91,CALLBACKNAME:92,CALLBACKARGS:93,HREF:94,LINK_TARGET:95,"STR[link]":96,"STR[tooltip]":97,alphaNum:98,DEFAULT:99,numList:100,INTERPOLATE:101,NUM:102,COMMA:103,style:104,styleComponent:105,NODE_STRING:106,UNIT:107,BRKT:108,PCT:109,idStringToken:110,MINUS:111,MULT:112,UNICODE_TEXT:113,TEXT:114,TAGSTART:115,EDGE_TEXT:116,alphaNumToken:117,direction_tb:118,direction_bt:119,direction_rl:120,direction_lr:121,$accept:0,$end:1},terminals_:{2:"error",8:"SEMI",9:"NEWLINE",10:"SPACE",11:"EOF",12:"GRAPH",13:"NODIR",14:"DIR",27:"subgraph",29:"SQS",31:"SQE",32:"end",34:"acc_title",35:"acc_title_value",36:"acc_descr",37:"acc_descr_value",38:"acc_descr_multiline_value",42:"AMP",44:"STYLE_SEPARATOR",46:"DOUBLECIRCLESTART",47:"DOUBLECIRCLEEND",48:"PS",49:"PE",50:"(-",51:"-)",52:"STADIUMSTART",53:"STADIUMEND",54:"SUBROUTINESTART",55:"SUBROUTINEEND",56:"VERTEX_WITH_PROPS_START",57:"NODE_STRING[field]",58:"COLON",59:"NODE_STRING[value]",60:"PIPE",61:"CYLINDERSTART",62:"CYLINDEREND",63:"DIAMOND_START",64:"DIAMOND_STOP",65:"TAGEND",66:"TRAPSTART",67:"TRAPEND",68:"INVTRAPSTART",69:"INVTRAPEND",72:"TESTSTR",73:"START_LINK",75:"LINK",77:"STR",78:"MD_STR",81:"STYLE",82:"LINKSTYLE",83:"CLASSDEF",84:"CLASS",85:"CLICK",86:"DOWN",87:"UP",90:"idString[vertex]",91:"idString[class]",92:"CALLBACKNAME",93:"CALLBACKARGS",94:"HREF",95:"LINK_TARGET",96:"STR[link]",97:"STR[tooltip]",99:"DEFAULT",101:"INTERPOLATE",102:"NUM",103:"COMMA",106:"NODE_STRING",107:"UNIT",108:"BRKT",109:"PCT",111:"MINUS",112:"MULT",113:"UNICODE_TEXT",114:"TEXT",115:"TAGSTART",116:"EDGE_TEXT",118:"direction_tb",119:"direction_bt",120:"direction_rl",121:"direction_lr"},productions_:[0,[3,2],[5,0],[5,2],[6,1],[6,1],[6,1],[6,1],[6,1],[4,2],[4,2],[4,2],[4,3],[16,2],[16,1],[17,1],[17,1],[17,1],[15,1],[15,1],[15,2],[19,2],[19,2],[19,1],[19,1],[18,2],[18,1],[7,2],[7,2],[7,2],[7,2],[7,2],[7,2],[7,9],[7,6],[7,4],[7,1],[7,2],[7,2],[7,1],[21,1],[21,1],[21,1],[20,3],[20,4],[20,2],[20,1],[40,1],[40,5],[41,1],[41,3],[43,4],[43,4],[43,6],[43,4],[43,4],[43,4],[43,8],[43,4],[43,4],[43,4],[43,6],[43,4],[43,4],[43,4],[43,4],[43,4],[43,1],[39,2],[39,3],[39,3],[39,1],[39,3],[74,1],[74,2],[74,1],[74,1],[70,1],[71,3],[30,1],[30,2],[30,1],[30,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[28,1],[28,2],[28,1],[28,1],[24,5],[25,5],[26,2],[26,4],[26,3],[26,5],[26,3],[26,5],[26,5],[26,7],[26,2],[26,4],[26,2],[26,4],[26,4],[26,6],[22,5],[23,5],[23,5],[23,9],[23,9],[23,7],[23,7],[100,1],[100,3],[89,1],[89,3],[104,1],[104,2],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[79,1],[79,1],[79,1],[79,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[76,1],[76,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[45,1],[45,2],[98,1],[98,2],[33,1],[33,1],[33,1],[33,1]],performAction:function(a,o,f,r,S,t,N1){var s=t.length-1;switch(S){case 2:this.$=[];break;case 3:(!Array.isArray(t[s])||t[s].length>0)&&t[s-1].push(t[s]),this.$=t[s-1];break;case 4:case 176:this.$=t[s];break;case 11:r.setDirection("TB"),this.$="TB";break;case 12:r.setDirection(t[s-1]),this.$=t[s-1];break;case 27:this.$=t[s-1].nodes;break;case 28:case 29:case 30:case 31:case 32:this.$=[];break;case 33:this.$=r.addSubGraph(t[s-6],t[s-1],t[s-4]);break;case 34:this.$=r.addSubGraph(t[s-3],t[s-1],t[s-3]);break;case 35:this.$=r.addSubGraph(void 0,t[s-1],void 0);break;case 37:this.$=t[s].trim(),r.setAccTitle(this.$);break;case 38:case 39:this.$=t[s].trim(),r.setAccDescription(this.$);break;case 43:r.addLink(t[s-2].stmt,t[s],t[s-1]),this.$={stmt:t[s],nodes:t[s].concat(t[s-2].nodes)};break;case 44:r.addLink(t[s-3].stmt,t[s-1],t[s-2]),this.$={stmt:t[s-1],nodes:t[s-1].concat(t[s-3].nodes)};break;case 45:this.$={stmt:t[s-1],nodes:t[s-1]};break;case 46:this.$={stmt:t[s],nodes:t[s]};break;case 47:this.$=[t[s]];break;case 48:this.$=t[s-4].concat(t[s]);break;case 49:this.$=t[s];break;case 50:this.$=t[s-2],r.setClass(t[s-2],t[s]);break;case 51:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"square");break;case 52:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"doublecircle");break;case 53:this.$=t[s-5],r.addVertex(t[s-5],t[s-2],"circle");break;case 54:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"ellipse");break;case 55:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"stadium");break;case 56:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"subroutine");break;case 57:this.$=t[s-7],r.addVertex(t[s-7],t[s-1],"rect",void 0,void 0,void 0,Object.fromEntries([[t[s-5],t[s-3]]]));break;case 58:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"cylinder");break;case 59:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"round");break;case 60:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"diamond");break;case 61:this.$=t[s-5],r.addVertex(t[s-5],t[s-2],"hexagon");break;case 62:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"odd");break;case 63:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"trapezoid");break;case 64:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"inv_trapezoid");break;case 65:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"lean_right");break;case 66:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"lean_left");break;case 67:this.$=t[s],r.addVertex(t[s]);break;case 68:t[s-1].text=t[s],this.$=t[s-1];break;case 69:case 70:t[s-2].text=t[s-1],this.$=t[s-2];break;case 71:this.$=t[s];break;case 72:var Y=r.destructLink(t[s],t[s-2]);this.$={type:Y.type,stroke:Y.stroke,length:Y.length,text:t[s-1]};break;case 73:this.$={text:t[s],type:"text"};break;case 74:this.$={text:t[s-1].text+""+t[s],type:t[s-1].type};break;case 75:this.$={text:t[s],type:"string"};break;case 76:this.$={text:t[s],type:"markdown"};break;case 77:var Y=r.destructLink(t[s]);this.$={type:Y.type,stroke:Y.stroke,length:Y.length};break;case 78:this.$=t[s-1];break;case 79:this.$={text:t[s],type:"text"};break;case 80:this.$={text:t[s-1].text+""+t[s],type:t[s-1].type};break;case 81:this.$={text:t[s],type:"string"};break;case 82:case 97:this.$={text:t[s],type:"markdown"};break;case 94:this.$={text:t[s],type:"text"};break;case 95:this.$={text:t[s-1].text+""+t[s],type:t[s-1].type};break;case 96:this.$={text:t[s],type:"text"};break;case 98:this.$=t[s-4],r.addClass(t[s-2],t[s]);break;case 99:this.$=t[s-4],r.setClass(t[s-2],t[s]);break;case 100:case 108:this.$=t[s-1],r.setClickEvent(t[s-1],t[s]);break;case 101:case 109:this.$=t[s-3],r.setClickEvent(t[s-3],t[s-2]),r.setTooltip(t[s-3],t[s]);break;case 102:this.$=t[s-2],r.setClickEvent(t[s-2],t[s-1],t[s]);break;case 103:this.$=t[s-4],r.setClickEvent(t[s-4],t[s-3],t[s-2]),r.setTooltip(t[s-4],t[s]);break;case 104:this.$=t[s-2],r.setLink(t[s-2],t[s]);break;case 105:this.$=t[s-4],r.setLink(t[s-4],t[s-2]),r.setTooltip(t[s-4],t[s]);break;case 106:this.$=t[s-4],r.setLink(t[s-4],t[s-2],t[s]);break;case 107:this.$=t[s-6],r.setLink(t[s-6],t[s-4],t[s]),r.setTooltip(t[s-6],t[s-2]);break;case 110:this.$=t[s-1],r.setLink(t[s-1],t[s]);break;case 111:this.$=t[s-3],r.setLink(t[s-3],t[s-2]),r.setTooltip(t[s-3],t[s]);break;case 112:this.$=t[s-3],r.setLink(t[s-3],t[s-2],t[s]);break;case 113:this.$=t[s-5],r.setLink(t[s-5],t[s-4],t[s]),r.setTooltip(t[s-5],t[s-2]);break;case 114:this.$=t[s-4],r.addVertex(t[s-2],void 0,void 0,t[s]);break;case 115:this.$=t[s-4],r.updateLink([t[s-2]],t[s]);break;case 116:this.$=t[s-4],r.updateLink(t[s-2],t[s]);break;case 117:this.$=t[s-8],r.updateLinkInterpolate([t[s-6]],t[s-2]),r.updateLink([t[s-6]],t[s]);break;case 118:this.$=t[s-8],r.updateLinkInterpolate(t[s-6],t[s-2]),r.updateLink(t[s-6],t[s]);break;case 119:this.$=t[s-6],r.updateLinkInterpolate([t[s-4]],t[s]);break;case 120:this.$=t[s-6],r.updateLinkInterpolate(t[s-4],t[s]);break;case 121:case 123:this.$=[t[s]];break;case 122:case 124:t[s-2].push(t[s]),this.$=t[s-2];break;case 126:this.$=t[s-1]+t[s];break;case 174:this.$=t[s];break;case 175:this.$=t[s-1]+""+t[s];break;case 177:this.$=t[s-1]+""+t[s];break;case 178:this.$={stmt:"dir",value:"TB"};break;case 179:this.$={stmt:"dir",value:"BT"};break;case 180:this.$={stmt:"dir",value:"RL"};break;case 181:this.$={stmt:"dir",value:"LR"};break}},table:[{3:1,4:2,9:u,10:i,12:n},{1:[3]},e(c,l,{5:6}),{4:7,9:u,10:i,12:n},{4:8,9:u,10:i,12:n},{13:[1,9],14:[1,10]},{1:[2,1],6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},e(c,[2,9]),e(c,[2,10]),e(c,[2,11]),{8:[1,54],9:[1,55],10:I1,15:53,18:56},e(b,[2,3]),e(b,[2,4]),e(b,[2,5]),e(b,[2,6]),e(b,[2,7]),e(b,[2,8]),{8:q,9:Q,11:Z,21:58,39:59,70:63,73:[1,64],75:[1,65]},{8:q,9:Q,11:Z,21:66},{8:q,9:Q,11:Z,21:67},{8:q,9:Q,11:Z,21:68},{8:q,9:Q,11:Z,21:69},{8:q,9:Q,11:Z,21:70},{8:q,9:Q,10:[1,71],11:Z,21:72},e(b,[2,36]),{35:[1,73]},{37:[1,74]},e(b,[2,39]),e(H1,[2,46],{18:75,10:I1}),{10:[1,76]},{10:[1,77]},{10:[1,78]},{10:[1,79]},{14:k1,42:b1,58:g1,77:[1,83],86:D1,92:[1,80],94:[1,81],98:82,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1,117:84},e(b,[2,178]),e(b,[2,179]),e(b,[2,180]),e(b,[2,181]),e(W1,[2,47]),e(W1,[2,49],{44:[1,96]}),e(N,[2,67],{110:109,29:[1,97],42:C,46:[1,98],48:[1,99],50:[1,100],52:[1,101],54:[1,102],56:[1,103],58:k,61:[1,104],63:[1,105],65:[1,106],66:[1,107],68:[1,108],86:x,99:B,102:m,103:y,106:v,108:V,111:L,112:I,113:R}),e(M,[2,174]),e(M,[2,135]),e(M,[2,136]),e(M,[2,137]),e(M,[2,138]),e(M,[2,139]),e(M,[2,140]),e(M,[2,141]),e(M,[2,142]),e(M,[2,143]),e(M,[2,144]),e(M,[2,145]),e(c,[2,12]),e(c,[2,18]),e(c,[2,19]),{9:[1,110]},e(Et,[2,26],{18:111,10:I1}),e(b,[2,27]),{40:112,41:38,42:C,43:39,45:40,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},e(b,[2,40]),e(b,[2,41]),e(b,[2,42]),e(R1,[2,71],{71:113,60:[1,115],72:[1,114]}),{74:116,76:117,77:[1,118],78:[1,119],113:kt,116:bt},e([42,58,60,72,86,99,102,103,106,108,111,112,113],[2,77]),e(b,[2,28]),e(b,[2,29]),e(b,[2,30]),e(b,[2,31]),e(b,[2,32]),{10:gt,12:Dt,14:Ft,27:Tt,28:122,32:St,42:Ct,58:_t,73:xt,77:[1,124],78:[1,125],80:135,81:Bt,82:mt,83:yt,84:vt,85:Vt,86:Lt,87:It,88:123,102:Rt,106:Nt,108:wt,111:Ot,112:Pt,113:Ut},e(nt,l,{5:148}),e(b,[2,37]),e(b,[2,38]),e(H1,[2,45],{42:Gt}),{42:C,45:150,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{99:[1,151],100:152,102:[1,153]},{42:C,45:154,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{42:C,45:155,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},e(T,[2,100],{10:[1,156],93:[1,157]}),{77:[1,158]},e(T,[2,108],{117:160,10:[1,159],14:k1,42:b1,58:g1,86:D1,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1}),e(T,[2,110],{10:[1,161]}),e(K,[2,176]),e(K,[2,163]),e(K,[2,164]),e(K,[2,165]),e(K,[2,166]),e(K,[2,167]),e(K,[2,168]),e(K,[2,169]),e(K,[2,170]),e(K,[2,171]),e(K,[2,172]),e(K,[2,173]),{42:C,45:162,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{30:163,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:171,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:173,48:[1,172],65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:174,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:175,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:176,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{106:[1,177]},{30:178,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:179,63:[1,180],65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:181,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:182,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:183,65:p,77:O,78:P,79:164,113:A,114:d,115:E},e(M,[2,175]),e(c,[2,20]),e(Et,[2,25]),e(H1,[2,43],{18:184,10:I1}),e(R1,[2,68],{10:[1,185]}),{10:[1,186]},{30:187,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{75:[1,188],76:189,113:kt,116:bt},e(m1,[2,73]),e(m1,[2,75]),e(m1,[2,76]),e(m1,[2,161]),e(m1,[2,162]),{8:q,9:Q,10:gt,11:Z,12:Dt,14:Ft,21:191,27:Tt,29:[1,190],32:St,42:Ct,58:_t,73:xt,80:135,81:Bt,82:mt,83:yt,84:vt,85:Vt,86:Lt,87:It,88:192,102:Rt,106:Nt,108:wt,111:Ot,112:Pt,113:Ut},e(g,[2,94]),e(g,[2,96]),e(g,[2,97]),e(g,[2,150]),e(g,[2,151]),e(g,[2,152]),e(g,[2,153]),e(g,[2,154]),e(g,[2,155]),e(g,[2,156]),e(g,[2,157]),e(g,[2,158]),e(g,[2,159]),e(g,[2,160]),e(g,[2,83]),e(g,[2,84]),e(g,[2,85]),e(g,[2,86]),e(g,[2,87]),e(g,[2,88]),e(g,[2,89]),e(g,[2,90]),e(g,[2,91]),e(g,[2,92]),e(g,[2,93]),{6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,32:[1,193],33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},{10:I1,18:194},{10:[1,195],42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:109,111:L,112:I,113:R},{10:[1,196]},{10:[1,197],103:[1,198]},e(Mt,[2,121]),{10:[1,199],42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:109,111:L,112:I,113:R},{10:[1,200],42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:109,111:L,112:I,113:R},{77:[1,201]},e(T,[2,102],{10:[1,202]}),e(T,[2,104],{10:[1,203]}),{77:[1,204]},e(K,[2,177]),{77:[1,205],95:[1,206]},e(W1,[2,50],{110:109,42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,111:L,112:I,113:R}),{31:[1,207],65:p,79:208,113:A,114:d,115:E},e(h1,[2,79]),e(h1,[2,81]),e(h1,[2,82]),e(h1,[2,146]),e(h1,[2,147]),e(h1,[2,148]),e(h1,[2,149]),{47:[1,209],65:p,79:208,113:A,114:d,115:E},{30:210,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{49:[1,211],65:p,79:208,113:A,114:d,115:E},{51:[1,212],65:p,79:208,113:A,114:d,115:E},{53:[1,213],65:p,79:208,113:A,114:d,115:E},{55:[1,214],65:p,79:208,113:A,114:d,115:E},{58:[1,215]},{62:[1,216],65:p,79:208,113:A,114:d,115:E},{64:[1,217],65:p,79:208,113:A,114:d,115:E},{30:218,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{31:[1,219],65:p,79:208,113:A,114:d,115:E},{65:p,67:[1,220],69:[1,221],79:208,113:A,114:d,115:E},{65:p,67:[1,223],69:[1,222],79:208,113:A,114:d,115:E},e(H1,[2,44],{42:Gt}),e(R1,[2,70]),e(R1,[2,69]),{60:[1,224],65:p,79:208,113:A,114:d,115:E},e(R1,[2,72]),e(m1,[2,74]),{30:225,65:p,77:O,78:P,79:164,113:A,114:d,115:E},e(nt,l,{5:226}),e(g,[2,95]),e(b,[2,35]),{41:227,42:C,43:39,45:40,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{10:J,58:$,81:t1,89:228,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{10:J,58:$,81:t1,89:239,101:[1,240],102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{10:J,58:$,81:t1,89:241,101:[1,242],102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{102:[1,243]},{10:J,58:$,81:t1,89:244,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{42:C,45:245,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},e(T,[2,101]),{77:[1,246]},{77:[1,247],95:[1,248]},e(T,[2,109]),e(T,[2,111],{10:[1,249]}),e(T,[2,112]),e(N,[2,51]),e(h1,[2,80]),e(N,[2,52]),{49:[1,250],65:p,79:208,113:A,114:d,115:E},e(N,[2,59]),e(N,[2,54]),e(N,[2,55]),e(N,[2,56]),{106:[1,251]},e(N,[2,58]),e(N,[2,60]),{64:[1,252],65:p,79:208,113:A,114:d,115:E},e(N,[2,62]),e(N,[2,63]),e(N,[2,65]),e(N,[2,64]),e(N,[2,66]),e([10,42,58,86,99,102,103,106,108,111,112,113],[2,78]),{31:[1,253],65:p,79:208,113:A,114:d,115:E},{6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,32:[1,254],33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},e(W1,[2,48]),e(T,[2,114],{103:y1}),e(Kt,[2,123],{105:256,10:J,58:$,81:t1,102:e1,106:s1,107:u1,108:i1,109:r1}),e(W,[2,125]),e(W,[2,127]),e(W,[2,128]),e(W,[2,129]),e(W,[2,130]),e(W,[2,131]),e(W,[2,132]),e(W,[2,133]),e(W,[2,134]),e(T,[2,115],{103:y1}),{10:[1,257]},e(T,[2,116],{103:y1}),{10:[1,258]},e(Mt,[2,122]),e(T,[2,98],{103:y1}),e(T,[2,99],{110:109,42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,111:L,112:I,113:R}),e(T,[2,103]),e(T,[2,105],{10:[1,259]}),e(T,[2,106]),{95:[1,260]},{49:[1,261]},{60:[1,262]},{64:[1,263]},{8:q,9:Q,11:Z,21:264},e(b,[2,34]),{10:J,58:$,81:t1,102:e1,104:265,105:230,106:s1,107:u1,108:i1,109:r1},e(W,[2,126]),{14:k1,42:b1,58:g1,86:D1,98:266,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1,117:84},{14:k1,42:b1,58:g1,86:D1,98:267,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1,117:84},{95:[1,268]},e(T,[2,113]),e(N,[2,53]),{30:269,65:p,77:O,78:P,79:164,113:A,114:d,115:E},e(N,[2,61]),e(nt,l,{5:270}),e(Kt,[2,124],{105:256,10:J,58:$,81:t1,102:e1,106:s1,107:u1,108:i1,109:r1}),e(T,[2,119],{117:160,10:[1,271],14:k1,42:b1,58:g1,86:D1,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1}),e(T,[2,120],{117:160,10:[1,272],14:k1,42:b1,58:g1,86:D1,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1}),e(T,[2,107]),{31:[1,273],65:p,79:208,113:A,114:d,115:E},{6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,32:[1,274],33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},{10:J,58:$,81:t1,89:275,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{10:J,58:$,81:t1,89:276,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},e(N,[2,57]),e(b,[2,33]),e(T,[2,117],{103:y1}),e(T,[2,118],{103:y1})],defaultActions:{},parseError:function(a,o){if(o.recoverable)this.trace(a);else{var f=new Error(a);throw f.hash=o,f}},parse:function(a){var o=this,f=[0],r=[],S=[null],t=[],N1=this.table,s="",Y=0,Yt=0,Ce=2,jt=1,_e=t.slice.call(arguments,1),_=Object.create(this.lexer),d1={yy:{}};for(var ot in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ot)&&(d1.yy[ot]=this.yy[ot]);_.setInput(a,d1.yy),d1.yy.lexer=_,d1.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var lt=_.yylloc;t.push(lt);var xe=_.options&&_.options.ranges;typeof d1.yy.parseError=="function"?this.parseError=d1.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Be(){var a1;return a1=r.pop()||_.lex()||jt,typeof a1!="number"&&(a1 instanceof Array&&(r=a1,a1=r.pop()),a1=o.symbols_[a1]||a1),a1}for(var G,E1,j,ht,v1={},q1,n1,zt,Q1;;){if(E1=f[f.length-1],this.defaultActions[E1]?j=this.defaultActions[E1]:((G===null||typeof G>"u")&&(G=Be()),j=N1[E1]&&N1[E1][G]),typeof j>"u"||!j.length||!j[0]){var ft="";Q1=[];for(q1 in N1[E1])this.terminals_[q1]&&q1>Ce&&Q1.push("'"+this.terminals_[q1]+"'");_.showPosition?ft="Parse error on line "+(Y+1)+`:
                                        +import{c as et,v as me,s as ye,g as ve,a as Ve,b as Le,x as Ie,y as Re,l as J1,z as dt,A as Ne,j as we,h as w1}from"./mermaid.core-Bq0kX0MS.js";var pt=function(){var e=function(f1,a,o,f){for(o=o||{},f=f1.length;f--;o[f1[f]]=a);return o},u=[1,4],i=[1,3],n=[1,5],c=[1,8,9,10,11,27,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],l=[2,2],h=[1,13],U=[1,14],F=[1,15],w=[1,16],X=[1,23],o1=[1,25],p1=[1,26],A1=[1,27],C=[1,49],k=[1,48],l1=[1,29],U1=[1,30],G1=[1,31],M1=[1,32],K1=[1,33],x=[1,44],B=[1,46],m=[1,42],y=[1,47],v=[1,43],V=[1,50],L=[1,45],I=[1,51],R=[1,52],Y1=[1,34],j1=[1,35],z1=[1,36],X1=[1,37],I1=[1,57],b=[1,8,9,10,11,27,32,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],q=[1,61],Q=[1,60],Z=[1,62],H1=[8,9,11,73,75],k1=[1,88],b1=[1,93],g1=[1,92],D1=[1,89],F1=[1,85],T1=[1,91],S1=[1,87],C1=[1,94],_1=[1,90],x1=[1,95],B1=[1,86],W1=[8,9,10,11,73,75],N=[8,9,10,11,44,73,75],M=[8,9,10,11,29,42,44,46,48,50,52,54,56,58,61,63,65,66,68,73,75,86,99,102,103,106,108,111,112,113],Et=[8,9,11,42,58,73,75,86,99,102,103,106,108,111,112,113],R1=[42,58,86,99,102,103,106,108,111,112,113],kt=[1,121],bt=[1,120],gt=[1,128],Dt=[1,142],Ft=[1,143],Tt=[1,144],St=[1,145],Ct=[1,130],_t=[1,132],xt=[1,136],Bt=[1,137],mt=[1,138],yt=[1,139],vt=[1,140],Vt=[1,141],Lt=[1,146],It=[1,147],Rt=[1,126],Nt=[1,127],wt=[1,134],Ot=[1,129],Pt=[1,133],Ut=[1,131],nt=[8,9,10,11,27,32,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],Gt=[1,149],T=[8,9,11],K=[8,9,10,11,14,42,58,86,102,103,106,108,111,112,113],p=[1,169],O=[1,165],P=[1,166],A=[1,170],d=[1,167],E=[1,168],m1=[75,113,116],g=[8,9,10,11,12,14,27,29,32,42,58,73,81,82,83,84,85,86,87,102,106,108,111,112,113],Mt=[10,103],h1=[31,47,49,51,53,55,60,62,64,65,67,69,113,114,115],J=[1,235],$=[1,233],t1=[1,237],e1=[1,231],s1=[1,232],u1=[1,234],i1=[1,236],r1=[1,238],y1=[1,255],Kt=[8,9,11,103],W=[8,9,10,11,58,81,102,103,106,107,108,109],at={trace:function(){},yy:{},symbols_:{error:2,start:3,graphConfig:4,document:5,line:6,statement:7,SEMI:8,NEWLINE:9,SPACE:10,EOF:11,GRAPH:12,NODIR:13,DIR:14,FirstStmtSeparator:15,ending:16,endToken:17,spaceList:18,spaceListNewline:19,vertexStatement:20,separator:21,styleStatement:22,linkStyleStatement:23,classDefStatement:24,classStatement:25,clickStatement:26,subgraph:27,textNoTags:28,SQS:29,text:30,SQE:31,end:32,direction:33,acc_title:34,acc_title_value:35,acc_descr:36,acc_descr_value:37,acc_descr_multiline_value:38,link:39,node:40,styledVertex:41,AMP:42,vertex:43,STYLE_SEPARATOR:44,idString:45,DOUBLECIRCLESTART:46,DOUBLECIRCLEEND:47,PS:48,PE:49,"(-":50,"-)":51,STADIUMSTART:52,STADIUMEND:53,SUBROUTINESTART:54,SUBROUTINEEND:55,VERTEX_WITH_PROPS_START:56,"NODE_STRING[field]":57,COLON:58,"NODE_STRING[value]":59,PIPE:60,CYLINDERSTART:61,CYLINDEREND:62,DIAMOND_START:63,DIAMOND_STOP:64,TAGEND:65,TRAPSTART:66,TRAPEND:67,INVTRAPSTART:68,INVTRAPEND:69,linkStatement:70,arrowText:71,TESTSTR:72,START_LINK:73,edgeText:74,LINK:75,edgeTextToken:76,STR:77,MD_STR:78,textToken:79,keywords:80,STYLE:81,LINKSTYLE:82,CLASSDEF:83,CLASS:84,CLICK:85,DOWN:86,UP:87,textNoTagsToken:88,stylesOpt:89,"idString[vertex]":90,"idString[class]":91,CALLBACKNAME:92,CALLBACKARGS:93,HREF:94,LINK_TARGET:95,"STR[link]":96,"STR[tooltip]":97,alphaNum:98,DEFAULT:99,numList:100,INTERPOLATE:101,NUM:102,COMMA:103,style:104,styleComponent:105,NODE_STRING:106,UNIT:107,BRKT:108,PCT:109,idStringToken:110,MINUS:111,MULT:112,UNICODE_TEXT:113,TEXT:114,TAGSTART:115,EDGE_TEXT:116,alphaNumToken:117,direction_tb:118,direction_bt:119,direction_rl:120,direction_lr:121,$accept:0,$end:1},terminals_:{2:"error",8:"SEMI",9:"NEWLINE",10:"SPACE",11:"EOF",12:"GRAPH",13:"NODIR",14:"DIR",27:"subgraph",29:"SQS",31:"SQE",32:"end",34:"acc_title",35:"acc_title_value",36:"acc_descr",37:"acc_descr_value",38:"acc_descr_multiline_value",42:"AMP",44:"STYLE_SEPARATOR",46:"DOUBLECIRCLESTART",47:"DOUBLECIRCLEEND",48:"PS",49:"PE",50:"(-",51:"-)",52:"STADIUMSTART",53:"STADIUMEND",54:"SUBROUTINESTART",55:"SUBROUTINEEND",56:"VERTEX_WITH_PROPS_START",57:"NODE_STRING[field]",58:"COLON",59:"NODE_STRING[value]",60:"PIPE",61:"CYLINDERSTART",62:"CYLINDEREND",63:"DIAMOND_START",64:"DIAMOND_STOP",65:"TAGEND",66:"TRAPSTART",67:"TRAPEND",68:"INVTRAPSTART",69:"INVTRAPEND",72:"TESTSTR",73:"START_LINK",75:"LINK",77:"STR",78:"MD_STR",81:"STYLE",82:"LINKSTYLE",83:"CLASSDEF",84:"CLASS",85:"CLICK",86:"DOWN",87:"UP",90:"idString[vertex]",91:"idString[class]",92:"CALLBACKNAME",93:"CALLBACKARGS",94:"HREF",95:"LINK_TARGET",96:"STR[link]",97:"STR[tooltip]",99:"DEFAULT",101:"INTERPOLATE",102:"NUM",103:"COMMA",106:"NODE_STRING",107:"UNIT",108:"BRKT",109:"PCT",111:"MINUS",112:"MULT",113:"UNICODE_TEXT",114:"TEXT",115:"TAGSTART",116:"EDGE_TEXT",118:"direction_tb",119:"direction_bt",120:"direction_rl",121:"direction_lr"},productions_:[0,[3,2],[5,0],[5,2],[6,1],[6,1],[6,1],[6,1],[6,1],[4,2],[4,2],[4,2],[4,3],[16,2],[16,1],[17,1],[17,1],[17,1],[15,1],[15,1],[15,2],[19,2],[19,2],[19,1],[19,1],[18,2],[18,1],[7,2],[7,2],[7,2],[7,2],[7,2],[7,2],[7,9],[7,6],[7,4],[7,1],[7,2],[7,2],[7,1],[21,1],[21,1],[21,1],[20,3],[20,4],[20,2],[20,1],[40,1],[40,5],[41,1],[41,3],[43,4],[43,4],[43,6],[43,4],[43,4],[43,4],[43,8],[43,4],[43,4],[43,4],[43,6],[43,4],[43,4],[43,4],[43,4],[43,4],[43,1],[39,2],[39,3],[39,3],[39,1],[39,3],[74,1],[74,2],[74,1],[74,1],[70,1],[71,3],[30,1],[30,2],[30,1],[30,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[28,1],[28,2],[28,1],[28,1],[24,5],[25,5],[26,2],[26,4],[26,3],[26,5],[26,3],[26,5],[26,5],[26,7],[26,2],[26,4],[26,2],[26,4],[26,4],[26,6],[22,5],[23,5],[23,5],[23,9],[23,9],[23,7],[23,7],[100,1],[100,3],[89,1],[89,3],[104,1],[104,2],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[79,1],[79,1],[79,1],[79,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[76,1],[76,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[45,1],[45,2],[98,1],[98,2],[33,1],[33,1],[33,1],[33,1]],performAction:function(a,o,f,r,S,t,N1){var s=t.length-1;switch(S){case 2:this.$=[];break;case 3:(!Array.isArray(t[s])||t[s].length>0)&&t[s-1].push(t[s]),this.$=t[s-1];break;case 4:case 176:this.$=t[s];break;case 11:r.setDirection("TB"),this.$="TB";break;case 12:r.setDirection(t[s-1]),this.$=t[s-1];break;case 27:this.$=t[s-1].nodes;break;case 28:case 29:case 30:case 31:case 32:this.$=[];break;case 33:this.$=r.addSubGraph(t[s-6],t[s-1],t[s-4]);break;case 34:this.$=r.addSubGraph(t[s-3],t[s-1],t[s-3]);break;case 35:this.$=r.addSubGraph(void 0,t[s-1],void 0);break;case 37:this.$=t[s].trim(),r.setAccTitle(this.$);break;case 38:case 39:this.$=t[s].trim(),r.setAccDescription(this.$);break;case 43:r.addLink(t[s-2].stmt,t[s],t[s-1]),this.$={stmt:t[s],nodes:t[s].concat(t[s-2].nodes)};break;case 44:r.addLink(t[s-3].stmt,t[s-1],t[s-2]),this.$={stmt:t[s-1],nodes:t[s-1].concat(t[s-3].nodes)};break;case 45:this.$={stmt:t[s-1],nodes:t[s-1]};break;case 46:this.$={stmt:t[s],nodes:t[s]};break;case 47:this.$=[t[s]];break;case 48:this.$=t[s-4].concat(t[s]);break;case 49:this.$=t[s];break;case 50:this.$=t[s-2],r.setClass(t[s-2],t[s]);break;case 51:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"square");break;case 52:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"doublecircle");break;case 53:this.$=t[s-5],r.addVertex(t[s-5],t[s-2],"circle");break;case 54:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"ellipse");break;case 55:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"stadium");break;case 56:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"subroutine");break;case 57:this.$=t[s-7],r.addVertex(t[s-7],t[s-1],"rect",void 0,void 0,void 0,Object.fromEntries([[t[s-5],t[s-3]]]));break;case 58:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"cylinder");break;case 59:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"round");break;case 60:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"diamond");break;case 61:this.$=t[s-5],r.addVertex(t[s-5],t[s-2],"hexagon");break;case 62:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"odd");break;case 63:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"trapezoid");break;case 64:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"inv_trapezoid");break;case 65:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"lean_right");break;case 66:this.$=t[s-3],r.addVertex(t[s-3],t[s-1],"lean_left");break;case 67:this.$=t[s],r.addVertex(t[s]);break;case 68:t[s-1].text=t[s],this.$=t[s-1];break;case 69:case 70:t[s-2].text=t[s-1],this.$=t[s-2];break;case 71:this.$=t[s];break;case 72:var Y=r.destructLink(t[s],t[s-2]);this.$={type:Y.type,stroke:Y.stroke,length:Y.length,text:t[s-1]};break;case 73:this.$={text:t[s],type:"text"};break;case 74:this.$={text:t[s-1].text+""+t[s],type:t[s-1].type};break;case 75:this.$={text:t[s],type:"string"};break;case 76:this.$={text:t[s],type:"markdown"};break;case 77:var Y=r.destructLink(t[s]);this.$={type:Y.type,stroke:Y.stroke,length:Y.length};break;case 78:this.$=t[s-1];break;case 79:this.$={text:t[s],type:"text"};break;case 80:this.$={text:t[s-1].text+""+t[s],type:t[s-1].type};break;case 81:this.$={text:t[s],type:"string"};break;case 82:case 97:this.$={text:t[s],type:"markdown"};break;case 94:this.$={text:t[s],type:"text"};break;case 95:this.$={text:t[s-1].text+""+t[s],type:t[s-1].type};break;case 96:this.$={text:t[s],type:"text"};break;case 98:this.$=t[s-4],r.addClass(t[s-2],t[s]);break;case 99:this.$=t[s-4],r.setClass(t[s-2],t[s]);break;case 100:case 108:this.$=t[s-1],r.setClickEvent(t[s-1],t[s]);break;case 101:case 109:this.$=t[s-3],r.setClickEvent(t[s-3],t[s-2]),r.setTooltip(t[s-3],t[s]);break;case 102:this.$=t[s-2],r.setClickEvent(t[s-2],t[s-1],t[s]);break;case 103:this.$=t[s-4],r.setClickEvent(t[s-4],t[s-3],t[s-2]),r.setTooltip(t[s-4],t[s]);break;case 104:this.$=t[s-2],r.setLink(t[s-2],t[s]);break;case 105:this.$=t[s-4],r.setLink(t[s-4],t[s-2]),r.setTooltip(t[s-4],t[s]);break;case 106:this.$=t[s-4],r.setLink(t[s-4],t[s-2],t[s]);break;case 107:this.$=t[s-6],r.setLink(t[s-6],t[s-4],t[s]),r.setTooltip(t[s-6],t[s-2]);break;case 110:this.$=t[s-1],r.setLink(t[s-1],t[s]);break;case 111:this.$=t[s-3],r.setLink(t[s-3],t[s-2]),r.setTooltip(t[s-3],t[s]);break;case 112:this.$=t[s-3],r.setLink(t[s-3],t[s-2],t[s]);break;case 113:this.$=t[s-5],r.setLink(t[s-5],t[s-4],t[s]),r.setTooltip(t[s-5],t[s-2]);break;case 114:this.$=t[s-4],r.addVertex(t[s-2],void 0,void 0,t[s]);break;case 115:this.$=t[s-4],r.updateLink([t[s-2]],t[s]);break;case 116:this.$=t[s-4],r.updateLink(t[s-2],t[s]);break;case 117:this.$=t[s-8],r.updateLinkInterpolate([t[s-6]],t[s-2]),r.updateLink([t[s-6]],t[s]);break;case 118:this.$=t[s-8],r.updateLinkInterpolate(t[s-6],t[s-2]),r.updateLink(t[s-6],t[s]);break;case 119:this.$=t[s-6],r.updateLinkInterpolate([t[s-4]],t[s]);break;case 120:this.$=t[s-6],r.updateLinkInterpolate(t[s-4],t[s]);break;case 121:case 123:this.$=[t[s]];break;case 122:case 124:t[s-2].push(t[s]),this.$=t[s-2];break;case 126:this.$=t[s-1]+t[s];break;case 174:this.$=t[s];break;case 175:this.$=t[s-1]+""+t[s];break;case 177:this.$=t[s-1]+""+t[s];break;case 178:this.$={stmt:"dir",value:"TB"};break;case 179:this.$={stmt:"dir",value:"BT"};break;case 180:this.$={stmt:"dir",value:"RL"};break;case 181:this.$={stmt:"dir",value:"LR"};break}},table:[{3:1,4:2,9:u,10:i,12:n},{1:[3]},e(c,l,{5:6}),{4:7,9:u,10:i,12:n},{4:8,9:u,10:i,12:n},{13:[1,9],14:[1,10]},{1:[2,1],6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},e(c,[2,9]),e(c,[2,10]),e(c,[2,11]),{8:[1,54],9:[1,55],10:I1,15:53,18:56},e(b,[2,3]),e(b,[2,4]),e(b,[2,5]),e(b,[2,6]),e(b,[2,7]),e(b,[2,8]),{8:q,9:Q,11:Z,21:58,39:59,70:63,73:[1,64],75:[1,65]},{8:q,9:Q,11:Z,21:66},{8:q,9:Q,11:Z,21:67},{8:q,9:Q,11:Z,21:68},{8:q,9:Q,11:Z,21:69},{8:q,9:Q,11:Z,21:70},{8:q,9:Q,10:[1,71],11:Z,21:72},e(b,[2,36]),{35:[1,73]},{37:[1,74]},e(b,[2,39]),e(H1,[2,46],{18:75,10:I1}),{10:[1,76]},{10:[1,77]},{10:[1,78]},{10:[1,79]},{14:k1,42:b1,58:g1,77:[1,83],86:D1,92:[1,80],94:[1,81],98:82,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1,117:84},e(b,[2,178]),e(b,[2,179]),e(b,[2,180]),e(b,[2,181]),e(W1,[2,47]),e(W1,[2,49],{44:[1,96]}),e(N,[2,67],{110:109,29:[1,97],42:C,46:[1,98],48:[1,99],50:[1,100],52:[1,101],54:[1,102],56:[1,103],58:k,61:[1,104],63:[1,105],65:[1,106],66:[1,107],68:[1,108],86:x,99:B,102:m,103:y,106:v,108:V,111:L,112:I,113:R}),e(M,[2,174]),e(M,[2,135]),e(M,[2,136]),e(M,[2,137]),e(M,[2,138]),e(M,[2,139]),e(M,[2,140]),e(M,[2,141]),e(M,[2,142]),e(M,[2,143]),e(M,[2,144]),e(M,[2,145]),e(c,[2,12]),e(c,[2,18]),e(c,[2,19]),{9:[1,110]},e(Et,[2,26],{18:111,10:I1}),e(b,[2,27]),{40:112,41:38,42:C,43:39,45:40,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},e(b,[2,40]),e(b,[2,41]),e(b,[2,42]),e(R1,[2,71],{71:113,60:[1,115],72:[1,114]}),{74:116,76:117,77:[1,118],78:[1,119],113:kt,116:bt},e([42,58,60,72,86,99,102,103,106,108,111,112,113],[2,77]),e(b,[2,28]),e(b,[2,29]),e(b,[2,30]),e(b,[2,31]),e(b,[2,32]),{10:gt,12:Dt,14:Ft,27:Tt,28:122,32:St,42:Ct,58:_t,73:xt,77:[1,124],78:[1,125],80:135,81:Bt,82:mt,83:yt,84:vt,85:Vt,86:Lt,87:It,88:123,102:Rt,106:Nt,108:wt,111:Ot,112:Pt,113:Ut},e(nt,l,{5:148}),e(b,[2,37]),e(b,[2,38]),e(H1,[2,45],{42:Gt}),{42:C,45:150,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{99:[1,151],100:152,102:[1,153]},{42:C,45:154,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{42:C,45:155,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},e(T,[2,100],{10:[1,156],93:[1,157]}),{77:[1,158]},e(T,[2,108],{117:160,10:[1,159],14:k1,42:b1,58:g1,86:D1,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1}),e(T,[2,110],{10:[1,161]}),e(K,[2,176]),e(K,[2,163]),e(K,[2,164]),e(K,[2,165]),e(K,[2,166]),e(K,[2,167]),e(K,[2,168]),e(K,[2,169]),e(K,[2,170]),e(K,[2,171]),e(K,[2,172]),e(K,[2,173]),{42:C,45:162,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{30:163,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:171,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:173,48:[1,172],65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:174,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:175,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:176,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{106:[1,177]},{30:178,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:179,63:[1,180],65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:181,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:182,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{30:183,65:p,77:O,78:P,79:164,113:A,114:d,115:E},e(M,[2,175]),e(c,[2,20]),e(Et,[2,25]),e(H1,[2,43],{18:184,10:I1}),e(R1,[2,68],{10:[1,185]}),{10:[1,186]},{30:187,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{75:[1,188],76:189,113:kt,116:bt},e(m1,[2,73]),e(m1,[2,75]),e(m1,[2,76]),e(m1,[2,161]),e(m1,[2,162]),{8:q,9:Q,10:gt,11:Z,12:Dt,14:Ft,21:191,27:Tt,29:[1,190],32:St,42:Ct,58:_t,73:xt,80:135,81:Bt,82:mt,83:yt,84:vt,85:Vt,86:Lt,87:It,88:192,102:Rt,106:Nt,108:wt,111:Ot,112:Pt,113:Ut},e(g,[2,94]),e(g,[2,96]),e(g,[2,97]),e(g,[2,150]),e(g,[2,151]),e(g,[2,152]),e(g,[2,153]),e(g,[2,154]),e(g,[2,155]),e(g,[2,156]),e(g,[2,157]),e(g,[2,158]),e(g,[2,159]),e(g,[2,160]),e(g,[2,83]),e(g,[2,84]),e(g,[2,85]),e(g,[2,86]),e(g,[2,87]),e(g,[2,88]),e(g,[2,89]),e(g,[2,90]),e(g,[2,91]),e(g,[2,92]),e(g,[2,93]),{6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,32:[1,193],33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},{10:I1,18:194},{10:[1,195],42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:109,111:L,112:I,113:R},{10:[1,196]},{10:[1,197],103:[1,198]},e(Mt,[2,121]),{10:[1,199],42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:109,111:L,112:I,113:R},{10:[1,200],42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:109,111:L,112:I,113:R},{77:[1,201]},e(T,[2,102],{10:[1,202]}),e(T,[2,104],{10:[1,203]}),{77:[1,204]},e(K,[2,177]),{77:[1,205],95:[1,206]},e(W1,[2,50],{110:109,42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,111:L,112:I,113:R}),{31:[1,207],65:p,79:208,113:A,114:d,115:E},e(h1,[2,79]),e(h1,[2,81]),e(h1,[2,82]),e(h1,[2,146]),e(h1,[2,147]),e(h1,[2,148]),e(h1,[2,149]),{47:[1,209],65:p,79:208,113:A,114:d,115:E},{30:210,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{49:[1,211],65:p,79:208,113:A,114:d,115:E},{51:[1,212],65:p,79:208,113:A,114:d,115:E},{53:[1,213],65:p,79:208,113:A,114:d,115:E},{55:[1,214],65:p,79:208,113:A,114:d,115:E},{58:[1,215]},{62:[1,216],65:p,79:208,113:A,114:d,115:E},{64:[1,217],65:p,79:208,113:A,114:d,115:E},{30:218,65:p,77:O,78:P,79:164,113:A,114:d,115:E},{31:[1,219],65:p,79:208,113:A,114:d,115:E},{65:p,67:[1,220],69:[1,221],79:208,113:A,114:d,115:E},{65:p,67:[1,223],69:[1,222],79:208,113:A,114:d,115:E},e(H1,[2,44],{42:Gt}),e(R1,[2,70]),e(R1,[2,69]),{60:[1,224],65:p,79:208,113:A,114:d,115:E},e(R1,[2,72]),e(m1,[2,74]),{30:225,65:p,77:O,78:P,79:164,113:A,114:d,115:E},e(nt,l,{5:226}),e(g,[2,95]),e(b,[2,35]),{41:227,42:C,43:39,45:40,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},{10:J,58:$,81:t1,89:228,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{10:J,58:$,81:t1,89:239,101:[1,240],102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{10:J,58:$,81:t1,89:241,101:[1,242],102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{102:[1,243]},{10:J,58:$,81:t1,89:244,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{42:C,45:245,58:k,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R},e(T,[2,101]),{77:[1,246]},{77:[1,247],95:[1,248]},e(T,[2,109]),e(T,[2,111],{10:[1,249]}),e(T,[2,112]),e(N,[2,51]),e(h1,[2,80]),e(N,[2,52]),{49:[1,250],65:p,79:208,113:A,114:d,115:E},e(N,[2,59]),e(N,[2,54]),e(N,[2,55]),e(N,[2,56]),{106:[1,251]},e(N,[2,58]),e(N,[2,60]),{64:[1,252],65:p,79:208,113:A,114:d,115:E},e(N,[2,62]),e(N,[2,63]),e(N,[2,65]),e(N,[2,64]),e(N,[2,66]),e([10,42,58,86,99,102,103,106,108,111,112,113],[2,78]),{31:[1,253],65:p,79:208,113:A,114:d,115:E},{6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,32:[1,254],33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},e(W1,[2,48]),e(T,[2,114],{103:y1}),e(Kt,[2,123],{105:256,10:J,58:$,81:t1,102:e1,106:s1,107:u1,108:i1,109:r1}),e(W,[2,125]),e(W,[2,127]),e(W,[2,128]),e(W,[2,129]),e(W,[2,130]),e(W,[2,131]),e(W,[2,132]),e(W,[2,133]),e(W,[2,134]),e(T,[2,115],{103:y1}),{10:[1,257]},e(T,[2,116],{103:y1}),{10:[1,258]},e(Mt,[2,122]),e(T,[2,98],{103:y1}),e(T,[2,99],{110:109,42:C,58:k,86:x,99:B,102:m,103:y,106:v,108:V,111:L,112:I,113:R}),e(T,[2,103]),e(T,[2,105],{10:[1,259]}),e(T,[2,106]),{95:[1,260]},{49:[1,261]},{60:[1,262]},{64:[1,263]},{8:q,9:Q,11:Z,21:264},e(b,[2,34]),{10:J,58:$,81:t1,102:e1,104:265,105:230,106:s1,107:u1,108:i1,109:r1},e(W,[2,126]),{14:k1,42:b1,58:g1,86:D1,98:266,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1,117:84},{14:k1,42:b1,58:g1,86:D1,98:267,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1,117:84},{95:[1,268]},e(T,[2,113]),e(N,[2,53]),{30:269,65:p,77:O,78:P,79:164,113:A,114:d,115:E},e(N,[2,61]),e(nt,l,{5:270}),e(Kt,[2,124],{105:256,10:J,58:$,81:t1,102:e1,106:s1,107:u1,108:i1,109:r1}),e(T,[2,119],{117:160,10:[1,271],14:k1,42:b1,58:g1,86:D1,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1}),e(T,[2,120],{117:160,10:[1,272],14:k1,42:b1,58:g1,86:D1,102:F1,103:T1,106:S1,108:C1,111:_1,112:x1,113:B1}),e(T,[2,107]),{31:[1,273],65:p,79:208,113:A,114:d,115:E},{6:11,7:12,8:h,9:U,10:F,11:w,20:17,22:18,23:19,24:20,25:21,26:22,27:X,32:[1,274],33:24,34:o1,36:p1,38:A1,40:28,41:38,42:C,43:39,45:40,58:k,81:l1,82:U1,83:G1,84:M1,85:K1,86:x,99:B,102:m,103:y,106:v,108:V,110:41,111:L,112:I,113:R,118:Y1,119:j1,120:z1,121:X1},{10:J,58:$,81:t1,89:275,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},{10:J,58:$,81:t1,89:276,102:e1,104:229,105:230,106:s1,107:u1,108:i1,109:r1},e(N,[2,57]),e(b,[2,33]),e(T,[2,117],{103:y1}),e(T,[2,118],{103:y1})],defaultActions:{},parseError:function(a,o){if(o.recoverable)this.trace(a);else{var f=new Error(a);throw f.hash=o,f}},parse:function(a){var o=this,f=[0],r=[],S=[null],t=[],N1=this.table,s="",Y=0,Yt=0,Ce=2,jt=1,_e=t.slice.call(arguments,1),_=Object.create(this.lexer),d1={yy:{}};for(var ot in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ot)&&(d1.yy[ot]=this.yy[ot]);_.setInput(a,d1.yy),d1.yy.lexer=_,d1.yy.parser=this,typeof _.yylloc>"u"&&(_.yylloc={});var lt=_.yylloc;t.push(lt);var xe=_.options&&_.options.ranges;typeof d1.yy.parseError=="function"?this.parseError=d1.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Be(){var a1;return a1=r.pop()||_.lex()||jt,typeof a1!="number"&&(a1 instanceof Array&&(r=a1,a1=r.pop()),a1=o.symbols_[a1]||a1),a1}for(var G,E1,j,ht,v1={},q1,n1,zt,Q1;;){if(E1=f[f.length-1],this.defaultActions[E1]?j=this.defaultActions[E1]:((G===null||typeof G>"u")&&(G=Be()),j=N1[E1]&&N1[E1][G]),typeof j>"u"||!j.length||!j[0]){var ft="";Q1=[];for(q1 in N1[E1])this.terminals_[q1]&&q1>Ce&&Q1.push("'"+this.terminals_[q1]+"'");_.showPosition?ft="Parse error on line "+(Y+1)+`:
                                         `+_.showPosition()+`
                                         Expecting `+Q1.join(", ")+", got '"+(this.terminals_[G]||G)+"'":ft="Parse error on line "+(Y+1)+": Unexpected "+(G==jt?"end of input":"'"+(this.terminals_[G]||G)+"'"),this.parseError(ft,{text:_.match,token:this.terminals_[G]||G,line:_.yylineno,loc:lt,expected:Q1})}if(j[0]instanceof Array&&j.length>1)throw new Error("Parse Error: multiple actions possible at state: "+E1+", token: "+G);switch(j[0]){case 1:f.push(G),S.push(_.yytext),t.push(_.yylloc),f.push(j[1]),G=null,Yt=_.yyleng,s=_.yytext,Y=_.yylineno,lt=_.yylloc;break;case 2:if(n1=this.productions_[j[1]][1],v1.$=S[S.length-n1],v1._$={first_line:t[t.length-(n1||1)].first_line,last_line:t[t.length-1].last_line,first_column:t[t.length-(n1||1)].first_column,last_column:t[t.length-1].last_column},xe&&(v1._$.range=[t[t.length-(n1||1)].range[0],t[t.length-1].range[1]]),ht=this.performAction.apply(v1,[s,Yt,Y,d1.yy,j[1],S,t].concat(_e)),typeof ht<"u")return ht;n1&&(f=f.slice(0,-1*n1*2),S=S.slice(0,-1*n1),t=t.slice(0,-1*n1)),f.push(this.productions_[j[1]][0]),S.push(v1.$),t.push(v1._$),zt=N1[f[f.length-2]][f[f.length-1]],f.push(zt);break;case 3:return!0}}return!0}},Se=function(){var f1={EOF:1,parseError:function(o,f){if(this.yy.parser)this.yy.parser.parseError(o,f);else throw new Error(o)},setInput:function(a,o){return this.yy=o||this.yy||{},this._input=a,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var o=a.match(/(?:\r\n?|\n).*/g);return o?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var o=a.length,f=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-o),this.offset-=o;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),f.length-1&&(this.yylineno-=f.length-1);var S=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:f?(f.length===r.length?this.yylloc.first_column:0)+r[r.length-f.length].length-f[0].length:this.yylloc.first_column-o},this.options.ranges&&(this.yylloc.range=[S[0],S[0]+this.yyleng-o]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),o=new Array(a.length+1).join("-");return a+this.upcomingInput()+`
                                        diff --git a/assets/flowDiagram-b222e15a-ClSO8xjE.js b/assets/flowDiagram-b222e15a-CRKbP293.js
                                        similarity index 97%
                                        rename from assets/flowDiagram-b222e15a-ClSO8xjE.js
                                        rename to assets/flowDiagram-b222e15a-CRKbP293.js
                                        index 180c718051..22a3b3efe7 100644
                                        --- a/assets/flowDiagram-b222e15a-ClSO8xjE.js
                                        +++ b/assets/flowDiagram-b222e15a-CRKbP293.js
                                        @@ -1,4 +1,4 @@
                                        -import{p as Lt,f as V}from"./flowDb-c1833063-8FVnhkY0.js";import{h as S,f as tt,G as _t}from"./graph-D2qW7eTj.js";import{h as x,o as U,p as Y,q as et,c as G,r as rt,j as at,l as R,t as z,u as Et}from"./mermaid.core-CArNAncI.js";import{u as Tt,r as Nt,p as At,l as Ct,d as M}from"./layout-BlaWeSu5.js";import{a as N,b as nt,i as st,c as E,e as it,d as ot,f as It,g as Bt,s as Mt}from"./styles-483fbfea-B2onFAKT.js";import{l as Dt}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./index-01f381cb-fgk8rzsW.js";import"./clone-D0wOyyCk.js";import"./edges-066a5561-BnmFWp88.js";import"./createText-ca0c5216-X7RVUogw.js";import"./channel-C_7gBDjR.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";function Rt(r){if(!r.ok)throw new Error(r.status+" "+r.statusText);return r.text()}function Gt(r,e){return fetch(r,e).then(Rt)}function Pt(r){return(e,t)=>Gt(e,t).then(n=>new DOMParser().parseFromString(n,r))}var Ut=Pt("image/svg+xml"),H={normal:Wt,vee:Vt,undirected:zt};function $t(r){H=r}function Wt(r,e,t,n){var a=r.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto"),s=a.append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("stroke-width",1).style("stroke-dasharray","1,0");N(s,t[n+"Style"]),t[n+"Class"]&&s.attr("class",t[n+"Class"])}function Vt(r,e,t,n){var a=r.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto"),s=a.append("path").attr("d","M 0 0 L 10 5 L 0 10 L 4 5 z").style("stroke-width",1).style("stroke-dasharray","1,0");N(s,t[n+"Style"]),t[n+"Class"]&&s.attr("class",t[n+"Class"])}function zt(r,e,t,n){var a=r.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto"),s=a.append("path").attr("d","M 0 5 L 10 5").style("stroke-width",1).style("stroke-dasharray","1,0");N(s,t[n+"Style"]),t[n+"Class"]&&s.attr("class",t[n+"Class"])}function Yt(r,e){var t=r;return t.node().appendChild(e.label),N(t,e.labelStyle),t}function Ht(r,e){for(var t=r.append("text"),n=Xt(e.label).split(`
                                        +import{p as Lt,f as V}from"./flowDb-c1833063-Csuwz1ip.js";import{h as S,f as tt,G as _t}from"./graph-C-EgwjAv.js";import{h as x,o as U,p as Y,q as et,c as G,r as rt,j as at,l as R,t as z,u as Et}from"./mermaid.core-Bq0kX0MS.js";import{u as Tt,r as Nt,p as At,l as Ct,d as M}from"./layout-DSxgfneE.js";import{a as N,b as nt,i as st,c as E,e as it,d as ot,f as It,g as Bt,s as Mt}from"./styles-483fbfea-BRNgjsWa.js";import{l as Dt}from"./line-DY_oMjHu.js";import"./app-Bw2NG-QJ.js";import"./index-01f381cb-DWGV-_zg.js";import"./clone-BjoOJyl6.js";import"./edges-066a5561-CIBMFaLO.js";import"./createText-ca0c5216-xyt9uAlz.js";import"./channel-DIeeoF-2.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";function Rt(r){if(!r.ok)throw new Error(r.status+" "+r.statusText);return r.text()}function Gt(r,e){return fetch(r,e).then(Rt)}function Pt(r){return(e,t)=>Gt(e,t).then(n=>new DOMParser().parseFromString(n,r))}var Ut=Pt("image/svg+xml"),H={normal:Wt,vee:Vt,undirected:zt};function $t(r){H=r}function Wt(r,e,t,n){var a=r.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto"),s=a.append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("stroke-width",1).style("stroke-dasharray","1,0");N(s,t[n+"Style"]),t[n+"Class"]&&s.attr("class",t[n+"Class"])}function Vt(r,e,t,n){var a=r.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto"),s=a.append("path").attr("d","M 0 0 L 10 5 L 0 10 L 4 5 z").style("stroke-width",1).style("stroke-dasharray","1,0");N(s,t[n+"Style"]),t[n+"Class"]&&s.attr("class",t[n+"Class"])}function zt(r,e,t,n){var a=r.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",9).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",6).attr("orient","auto"),s=a.append("path").attr("d","M 0 5 L 10 5").style("stroke-width",1).style("stroke-dasharray","1,0");N(s,t[n+"Style"]),t[n+"Class"]&&s.attr("class",t[n+"Class"])}function Yt(r,e){var t=r;return t.node().appendChild(e.label),N(t,e.labelStyle),t}function Ht(r,e){for(var t=r.append("text"),n=Xt(e.label).split(`
                                         `),a=0;a0}function T(r,e,t){var n=r.x,a=r.y,s=[],i=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY;e.forEach(function(p){i=Math.min(i,p.x),o=Math.min(o,p.y)});for(var c=n-r.width/2-i,d=a-r.height/2-o,l=0;l1&&s.sort(function(p,y){var f=p.x-t.x,g=p.y-t.y,k=Math.sqrt(f*f+g*g),I=y.x-t.x,_=y.y-t.y,$=Math.sqrt(I*I+_*_);return k<$?-1:k===$?0:1}),s[0]):(console.log("NO INTERSECTION FOUND, RETURN NODE CENTER",r),r)}function Z(r,e){var t=r.x,n=r.y,a=e.x-t,s=e.y-n,i=r.width/2,o=r.height/2,c,d;return Math.abs(s)*i>Math.abs(a)*o?(s<0&&(o=-o),c=s===0?0:o*a/s,d=o):(a<0&&(i=-i),c=i,d=a===0?0:i*s/a),{x:t+c,y:n+d}}var K={rect:oe,ellipse:le,circle:ce,diamond:de};function ie(r){K=r}function oe(r,e,t){var n=r.insert("rect",":first-child").attr("rx",t.rx).attr("ry",t.ry).attr("x",-e.width/2).attr("y",-e.height/2).attr("width",e.width).attr("height",e.height);return t.intersect=function(a){return Z(t,a)},n}function le(r,e,t){var n=e.width/2,a=e.height/2,s=r.insert("ellipse",":first-child").attr("x",-e.width/2).attr("y",-e.height/2).attr("rx",n).attr("ry",a);return t.intersect=function(i){return ct(t,n,a,i)},s}function ce(r,e,t){var n=Math.max(e.width,e.height)/2,a=r.insert("circle",":first-child").attr("x",-e.width/2).attr("y",-e.height/2).attr("r",n);return t.intersect=function(s){return ne(t,n,s)},a}function de(r,e,t){var n=e.width*Math.SQRT2/2,a=e.height*Math.SQRT2/2,s=[{x:0,y:-a},{x:-n,y:0},{x:0,y:a},{x:n,y:0}],i=r.insert("polygon",":first-child").attr("points",s.map(function(o){return o.x+","+o.y}).join(" "));return t.intersect=function(o){return T(t,s,o)},i}function he(){var r=function(e,t){pe(t);var n=D(e,"output"),a=D(n,"clusters"),s=D(n,"edgePaths"),i=F(D(n,"edgeLabels"),t),o=Q(D(n,"nodes"),t,K);Ct(t),ae(o,t),re(i,t),q(s,t,H);var c=X(a,t);ee(c,t),ve(t)};return r.createNodes=function(e){return arguments.length?(te(e),r):Q},r.createClusters=function(e){return arguments.length?(Ft(e),r):X},r.createEdgeLabels=function(e){return arguments.length?(qt(e),r):F},r.createEdgePaths=function(e){return arguments.length?(Qt(e),r):q},r.shapes=function(e){return arguments.length?(ie(e),r):K},r.arrows=function(e){return arguments.length?($t(e),r):H},r}var ue={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"},fe={arrowhead:"normal",curve:U};function pe(r){r.nodes().forEach(function(e){var t=r.node(e);!S(t,"label")&&!r.children(e).length&&(t.label=e),S(t,"paddingX")&&M(t,{paddingLeft:t.paddingX,paddingRight:t.paddingX}),S(t,"paddingY")&&M(t,{paddingTop:t.paddingY,paddingBottom:t.paddingY}),S(t,"padding")&&M(t,{paddingLeft:t.padding,paddingRight:t.padding,paddingTop:t.padding,paddingBottom:t.padding}),M(t,ue),tt(["paddingLeft","paddingRight","paddingTop","paddingBottom"],function(n){t[n]=Number(t[n])}),S(t,"width")&&(t._prevWidth=t.width),S(t,"height")&&(t._prevHeight=t.height)}),r.edges().forEach(function(e){var t=r.edge(e);S(t,"label")||(t.label=""),M(t,fe)})}function ve(r){tt(r.nodes(),function(e){var t=r.node(e);S(t,"_prevWidth")?t.width=t._prevWidth:delete t.width,S(t,"_prevHeight")?t.height=t._prevHeight:delete t.height,delete t._prevWidth,delete t._prevHeight})}function D(r,e){var t=r.select("g."+e);return t.empty()&&(t=r.append("g").attr("class",e)),t}function dt(r,e,t){const n=e.width,a=e.height,s=(n+a)*.9,i=[{x:s/2,y:0},{x:s,y:-s/2},{x:s/2,y:-s},{x:0,y:-s/2}],o=A(r,s,s,i);return t.intersect=function(c){return T(t,i,c)},o}function ht(r,e,t){const a=e.height,s=a/4,i=e.width+2*s,o=[{x:s,y:0},{x:i-s,y:0},{x:i,y:-a/2},{x:i-s,y:-a},{x:s,y:-a},{x:0,y:-a/2}],c=A(r,i,a,o);return t.intersect=function(d){return T(t,o,d)},c}function ut(r,e,t){const n=e.width,a=e.height,s=[{x:-a/2,y:0},{x:n,y:0},{x:n,y:-a},{x:-a/2,y:-a},{x:0,y:-a/2}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function ft(r,e,t){const n=e.width,a=e.height,s=[{x:-2*a/6,y:0},{x:n-a/6,y:0},{x:n+2*a/6,y:-a},{x:a/6,y:-a}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function pt(r,e,t){const n=e.width,a=e.height,s=[{x:2*a/6,y:0},{x:n+a/6,y:0},{x:n-2*a/6,y:-a},{x:-a/6,y:-a}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function vt(r,e,t){const n=e.width,a=e.height,s=[{x:-2*a/6,y:0},{x:n+2*a/6,y:0},{x:n-a/6,y:-a},{x:a/6,y:-a}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function gt(r,e,t){const n=e.width,a=e.height,s=[{x:a/6,y:0},{x:n-a/6,y:0},{x:n+2*a/6,y:-a},{x:-2*a/6,y:-a}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function yt(r,e,t){const n=e.width,a=e.height,s=[{x:0,y:0},{x:n+a/2,y:0},{x:n,y:-a/2},{x:n+a/2,y:-a},{x:0,y:-a}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function wt(r,e,t){const n=e.height,a=e.width+n/4,s=r.insert("rect",":first-child").attr("rx",n/2).attr("ry",n/2).attr("x",-a/2).attr("y",-n/2).attr("width",a).attr("height",n);return t.intersect=function(i){return Z(t,i)},s}function mt(r,e,t){const n=e.width,a=e.height,s=[{x:0,y:0},{x:n,y:0},{x:n,y:-a},{x:0,y:-a},{x:0,y:0},{x:-8,y:0},{x:n+8,y:0},{x:n+8,y:-a},{x:-8,y:-a},{x:-8,y:0}],i=A(r,n,a,s);return t.intersect=function(o){return T(t,s,o)},i}function xt(r,e,t){const n=e.width,a=n/2,s=a/(2.5+n/50),i=e.height+s,o="M 0,"+s+" a "+a+","+s+" 0,0,0 "+n+" 0 a "+a+","+s+" 0,0,0 "+-n+" 0 l 0,"+i+" a "+a+","+s+" 0,0,0 "+n+" 0 l 0,"+-i,c=r.attr("label-offset-y",s).insert("path",":first-child").attr("d",o).attr("transform","translate("+-n/2+","+-(i/2+s)+")");return t.intersect=function(d){const l=Z(t,d),v=l.x-t.x;if(a!=0&&(Math.abs(v)t.height/2-s)){let h=s*s*(1-v*v/(a*a));h!=0&&(h=Math.sqrt(h)),h=s-h,d.y-t.y>0&&(h=-h),l.y+=h}return l},c}function ge(r){r.shapes().question=dt,r.shapes().hexagon=ht,r.shapes().stadium=wt,r.shapes().subroutine=mt,r.shapes().cylinder=xt,r.shapes().rect_left_inv_arrow=ut,r.shapes().lean_right=ft,r.shapes().lean_left=pt,r.shapes().trapezoid=vt,r.shapes().inv_trapezoid=gt,r.shapes().rect_right_inv_arrow=yt}function ye(r){r({question:dt}),r({hexagon:ht}),r({stadium:wt}),r({subroutine:mt}),r({cylinder:xt}),r({rect_left_inv_arrow:ut}),r({lean_right:ft}),r({lean_left:pt}),r({trapezoid:vt}),r({inv_trapezoid:gt}),r({rect_right_inv_arrow:yt})}function A(r,e,t,n){return r.insert("polygon",":first-child").attr("points",n.map(function(a){return a.x+","+a.y}).join(" ")).attr("transform","translate("+-e/2+","+t/2+")")}const we={addToRender:ge,addToRenderV2:ye},bt={},me=function(r){const e=Object.keys(r);for(const t of e)bt[t]=r[t]},kt=async function(r,e,t,n,a,s){const i=n?n.select(`[id="${t}"]`):x(`[id="${t}"]`),o=a||document,c=Object.keys(r);for(const d of c){const l=r[d];let v="default";l.classes.length>0&&(v=l.classes.join(" "));const h=Y(l.styles);let u=l.text!==void 0?l.text:l.id,p;if(et(G().flowchart.htmlLabels)){const g={label:await rt(u.replace(/fa[blrs]?:fa-[\w-]+/g,k=>``),G())};p=nt(i,g).node(),p.parentNode.removeChild(p)}else{const g=o.createElementNS("http://www.w3.org/2000/svg","text");g.setAttribute("style",h.labelStyle.replace("color:","fill:"));const k=u.split(at.lineBreakRegex);for(const I of k){const _=o.createElementNS("http://www.w3.org/2000/svg","tspan");_.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),_.setAttribute("dy","1em"),_.setAttribute("x","1"),_.textContent=I,g.appendChild(_)}p=g}let y=0,f="";switch(l.type){case"round":y=5,f="rect";break;case"square":f="rect";break;case"diamond":f="question";break;case"hexagon":f="hexagon";break;case"odd":f="rect_left_inv_arrow";break;case"lean_right":f="lean_right";break;case"lean_left":f="lean_left";break;case"trapezoid":f="trapezoid";break;case"inv_trapezoid":f="inv_trapezoid";break;case"odd_right":f="rect_left_inv_arrow";break;case"circle":f="circle";break;case"ellipse":f="ellipse";break;case"stadium":f="stadium";break;case"subroutine":f="subroutine";break;case"cylinder":f="cylinder";break;case"group":f="rect";break;default:f="rect"}R.warn("Adding node",l.id,l.domId),e.setNode(s.db.lookUpDomId(l.id),{labelType:"svg",labelStyle:h.labelStyle,shape:f,label:p,rx:y,ry:y,class:v,style:h.style,id:s.db.lookUpDomId(l.id)})}},St=async function(r,e,t){let n=0,a,s;if(r.defaultStyle!==void 0){const i=Y(r.defaultStyle);a=i.style,s=i.labelStyle}for(const i of r){n++;const o="L-"+i.start+"-"+i.end,c="LS-"+i.start,d="LE-"+i.end,l={};i.type==="arrow_open"?l.arrowhead="none":l.arrowhead="normal";let v="",h="";if(i.style!==void 0){const u=Y(i.style);v=u.style,h=u.labelStyle}else switch(i.stroke){case"normal":v="fill:none",a!==void 0&&(v=a),s!==void 0&&(h=s);break;case"dotted":v="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":v=" stroke-width: 3.5px;fill:none";break}l.style=v,l.labelStyle=h,i.interpolate!==void 0?l.curve=z(i.interpolate,U):r.defaultInterpolate!==void 0?l.curve=z(r.defaultInterpolate,U):l.curve=z(bt.curve,U),i.text===void 0?i.style!==void 0&&(l.arrowheadStyle="fill: #333"):(l.arrowheadStyle="fill: #333",l.labelpos="c",et(G().flowchart.htmlLabels)?(l.labelType="html",l.label=`${await rt(i.text.replace(/fa[blrs]?:fa-[\w-]+/g,u=>``),G())}`):(l.labelType="text",l.label=i.text.replace(at.lineBreakRegex,`
                                         `),i.style===void 0&&(l.style=l.style||"stroke: #333; stroke-width: 1.5px;fill:none"),l.labelStyle=l.labelStyle.replace("color:","fill:"))),l.id=o,l.class=c+" "+d,l.minlen=i.length||1,e.setEdge(t.db.lookUpDomId(i.start),t.db.lookUpDomId(i.end),l,n)}},xe=function(r,e){return R.info("Extracting classes"),e.db.getClasses()},be=async function(r,e,t,n){R.info("Drawing flowchart");const{securityLevel:a,flowchart:s}=G();let i;a==="sandbox"&&(i=x("#i"+e));const o=a==="sandbox"?x(i.nodes()[0].contentDocument.body):x("body"),c=a==="sandbox"?i.nodes()[0].contentDocument:document;let d=n.db.getDirection();d===void 0&&(d="TD");const l=s.nodeSpacing||50,v=s.rankSpacing||50,h=new _t({multigraph:!0,compound:!0}).setGraph({rankdir:d,nodesep:l,ranksep:v,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});let u;const p=n.db.getSubGraphs();for(let w=p.length-1;w>=0;w--)u=p[w],n.db.addVertex(u.id,u.title,"group",void 0,u.classes);const y=n.db.getVertices();R.warn("Get vertices",y);const f=n.db.getEdges();let g=0;for(g=p.length-1;g>=0;g--){u=p[g],Mt("cluster").append("text");for(let w=0;w{r.flowchart||(r.flowchart={}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,ke.setConf(r.flowchart),V.clear(),V.setGen("gen-1")}};export{Pe as diagram};
                                        diff --git a/assets/flowDiagram-v2-13329dc7-CD3itvv-.js b/assets/flowDiagram-v2-13329dc7-CD3itvv-.js
                                        deleted file mode 100644
                                        index da48af29b1..0000000000
                                        --- a/assets/flowDiagram-v2-13329dc7-CD3itvv-.js
                                        +++ /dev/null
                                        @@ -1 +0,0 @@
                                        -import{p as e,f as o}from"./flowDb-c1833063-8FVnhkY0.js";import{f as t,g as a}from"./styles-483fbfea-B2onFAKT.js";import{aq as i}from"./mermaid.core-CArNAncI.js";import"./graph-D2qW7eTj.js";import"./layout-BlaWeSu5.js";import"./index-01f381cb-fgk8rzsW.js";import"./clone-D0wOyyCk.js";import"./edges-066a5561-BnmFWp88.js";import"./createText-ca0c5216-X7RVUogw.js";import"./line-BIqtvXUi.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";import"./channel-C_7gBDjR.js";import"./app-5SoadDYS.js";const n={parser:e,db:o,renderer:t,styles:a,init:r=>{r.flowchart||(r.flowchart={}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,i({flowchart:{arrowMarkerAbsolute:r.arrowMarkerAbsolute}}),t.setConf(r.flowchart),o.clear(),o.setGen("gen-2")}};export{n as diagram};
                                        diff --git a/assets/flowDiagram-v2-13329dc7-CUX8GDMK.js b/assets/flowDiagram-v2-13329dc7-CUX8GDMK.js
                                        new file mode 100644
                                        index 0000000000..07392637cd
                                        --- /dev/null
                                        +++ b/assets/flowDiagram-v2-13329dc7-CUX8GDMK.js
                                        @@ -0,0 +1 @@
                                        +import{p as e,f as o}from"./flowDb-c1833063-Csuwz1ip.js";import{f as t,g as a}from"./styles-483fbfea-BRNgjsWa.js";import{aq as i}from"./mermaid.core-Bq0kX0MS.js";import"./graph-C-EgwjAv.js";import"./layout-DSxgfneE.js";import"./index-01f381cb-DWGV-_zg.js";import"./clone-BjoOJyl6.js";import"./edges-066a5561-CIBMFaLO.js";import"./createText-ca0c5216-xyt9uAlz.js";import"./line-DY_oMjHu.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";import"./channel-DIeeoF-2.js";import"./app-Bw2NG-QJ.js";const n={parser:e,db:o,renderer:t,styles:a,init:r=>{r.flowchart||(r.flowchart={}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,i({flowchart:{arrowMarkerAbsolute:r.arrowMarkerAbsolute}}),t.setConf(r.flowchart),o.clear(),o.setGen("gen-2")}};export{n as diagram};
                                        diff --git a/assets/flowchart-elk-definition-ae0efee6-Df6_ziIo.js b/assets/flowchart-elk-definition-ae0efee6-H9NB2Lq2.js
                                        similarity index 99%
                                        rename from assets/flowchart-elk-definition-ae0efee6-Df6_ziIo.js
                                        rename to assets/flowchart-elk-definition-ae0efee6-H9NB2Lq2.js
                                        index d0754fe3a5..58cd730087 100644
                                        --- a/assets/flowchart-elk-definition-ae0efee6-Df6_ziIo.js
                                        +++ b/assets/flowchart-elk-definition-ae0efee6-H9NB2Lq2.js
                                        @@ -1,4 +1,4 @@
                                        -import{d as xNe,p as FNe}from"./flowDb-c1833063-8FVnhkY0.js";import{aB as Nse,aC as BNe,l as Ba,h as IO,a$ as xU,u as RNe,p as E0n,t as j0n,o as $U,j as KNe}from"./mermaid.core-CArNAncI.js";import{i as _Ne,a as HNe,l as qNe,b as UNe,k as GNe,m as zNe}from"./edges-066a5561-BnmFWp88.js";import{l as XNe}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./createText-ca0c5216-X7RVUogw.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";function NU(ct){throw new Error('Could not dynamically require "'+ct+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Bse={exports:{}};(function(ct,_t){(function(Xt){ct.exports=Xt()})(function(){return function(){function Xt(gt,Sr,Di){function y(Ht,Jt){if(!Sr[Ht]){if(!gt[Ht]){var ze=typeof NU=="function"&&NU;if(!Jt&&ze)return ze(Ht,!0);if(Wt)return Wt(Ht,!0);var Yi=new Error("Cannot find module '"+Ht+"'");throw Yi.code="MODULE_NOT_FOUND",Yi}var Ri=Sr[Ht]={exports:{}};gt[Ht][0].call(Ri.exports,function(En){var hu=gt[Ht][1][En];return y(hu||En)},Ri,Ri.exports,Xt,gt,Sr,Di)}return Sr[Ht].exports}for(var Wt=typeof NU=="function"&&NU,Bu=0;Bu0&&arguments[0]!==void 0?arguments[0]:{},Yi=ze.defaultLayoutOptions,Ri=Yi===void 0?{}:Yi,En=ze.algorithms,hu=En===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:En,Qc=ze.workerFactory,Ru=ze.workerUrl;if(y(this,Ht),this.defaultLayoutOptions=Ri,this.initialized=!1,typeof Ru>"u"&&typeof Qc>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var Pr=Qc;typeof Ru<"u"&&typeof Qc>"u"&&(Pr=function(N1){return new Worker(N1)});var Cf=Pr(Ru);if(typeof Cf.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new Bu(Cf),this.worker.postMessage({cmd:"register",algorithms:hu}).then(function(L1){return Jt.initialized=!0}).catch(console.err)}return Di(Ht,[{key:"layout",value:function(ze){var Yi=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Ri=Yi.layoutOptions,En=Ri===void 0?this.defaultLayoutOptions:Ri,hu=Yi.logging,Qc=hu===void 0?!1:hu,Ru=Yi.measureExecutionTime,Pr=Ru===void 0?!1:Ru;return ze?this.worker.postMessage({cmd:"layout",graph:ze,layoutOptions:En,options:{logging:Qc,measureExecutionTime:Pr}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker&&this.worker.terminate()}}]),Ht}();Sr.default=Wt;var Bu=function(){function Ht(Jt){var ze=this;if(y(this,Ht),Jt===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=Jt,this.worker.onmessage=function(Yi){setTimeout(function(){ze.receive(ze,Yi)},0)}}return Di(Ht,[{key:"postMessage",value:function(ze){var Yi=this.id||0;this.id=Yi+1,ze.id=Yi;var Ri=this;return new Promise(function(En,hu){Ri.resolvers[Yi]=function(Qc,Ru){Qc?(Ri.convertGwtStyleError(Qc),hu(Qc)):En(Ru)},Ri.worker.postMessage(ze)})}},{key:"receive",value:function(ze,Yi){var Ri=Yi.data,En=ze.resolvers[Ri.id];En&&(delete ze.resolvers[Ri.id],Ri.error?En(Ri.error):En(null,Ri.data))}},{key:"terminate",value:function(){this.worker&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(ze){if(ze){var Yi=ze.__java$exception;Yi&&(Yi.cause&&Yi.cause.backingJsObject&&(ze.cause=Yi.cause.backingJsObject,this.convertGwtStyleError(ze.cause)),delete ze.__java$exception)}}}]),Ht}()},{}],2:[function(Xt,gt,Sr){(function(Di){(function(){var y;typeof window<"u"?y=window:typeof Di<"u"?y=Di:typeof self<"u"&&(y=self);var Wt;function Bu(){}function Ht(){}function Jt(){}function ze(){}function Yi(){}function Ri(){}function En(){}function hu(){}function Qc(){}function Ru(){}function Pr(){}function Cf(){}function L1(){}function N1(){}function og(){}function V3(){}function $1(){}function ul(){}function C0n(){}function M0n(){}function J2(){}function F(){}function T0n(){}function mE(){}function A0n(){}function S0n(){}function P0n(){}function I0n(){}function O0n(){}function FU(){}function D0n(){}function L0n(){}function N0n(){}function OO(){}function $0n(){}function x0n(){}function F0n(){}function DO(){}function B0n(){}function R0n(){}function BU(){}function K0n(){}function _0n(){}function yu(){}function ju(){}function Q2(){}function Y2(){}function H0n(){}function q0n(){}function U0n(){}function G0n(){}function RU(){}function Eu(){}function Z2(){}function np(){}function z0n(){}function X0n(){}function LO(){}function V0n(){}function W0n(){}function J0n(){}function Q0n(){}function Y0n(){}function Z0n(){}function nbn(){}function ebn(){}function tbn(){}function ibn(){}function rbn(){}function cbn(){}function ubn(){}function obn(){}function sbn(){}function fbn(){}function hbn(){}function lbn(){}function abn(){}function dbn(){}function bbn(){}function wbn(){}function gbn(){}function pbn(){}function mbn(){}function vbn(){}function kbn(){}function ybn(){}function jbn(){}function Ebn(){}function Cbn(){}function Mbn(){}function Tbn(){}function KU(){}function Abn(){}function Sbn(){}function Pbn(){}function Ibn(){}function NO(){}function $O(){}function vE(){}function Obn(){}function Dbn(){}function xO(){}function Lbn(){}function Nbn(){}function $bn(){}function kE(){}function xbn(){}function Fbn(){}function Bbn(){}function Rbn(){}function Kbn(){}function _bn(){}function Hbn(){}function qbn(){}function Ubn(){}function _U(){}function Gbn(){}function zbn(){}function HU(){}function Xbn(){}function Vbn(){}function Wbn(){}function Jbn(){}function Qbn(){}function Ybn(){}function Zbn(){}function nwn(){}function ewn(){}function twn(){}function iwn(){}function rwn(){}function cwn(){}function FO(){}function uwn(){}function own(){}function swn(){}function fwn(){}function hwn(){}function lwn(){}function awn(){}function dwn(){}function bwn(){}function qU(){}function UU(){}function wwn(){}function gwn(){}function pwn(){}function mwn(){}function vwn(){}function kwn(){}function ywn(){}function jwn(){}function Ewn(){}function Cwn(){}function Mwn(){}function Twn(){}function Awn(){}function Swn(){}function Pwn(){}function Iwn(){}function Own(){}function Dwn(){}function Lwn(){}function Nwn(){}function $wn(){}function xwn(){}function Fwn(){}function Bwn(){}function Rwn(){}function Kwn(){}function _wn(){}function Hwn(){}function qwn(){}function Uwn(){}function Gwn(){}function zwn(){}function Xwn(){}function Vwn(){}function Wwn(){}function Jwn(){}function Qwn(){}function Ywn(){}function Zwn(){}function ngn(){}function egn(){}function tgn(){}function ign(){}function rgn(){}function cgn(){}function ugn(){}function ogn(){}function sgn(){}function fgn(){}function hgn(){}function lgn(){}function agn(){}function dgn(){}function bgn(){}function wgn(){}function ggn(){}function pgn(){}function mgn(){}function vgn(){}function kgn(){}function ygn(){}function jgn(){}function Egn(){}function Cgn(){}function Mgn(){}function Tgn(){}function Agn(){}function Sgn(){}function Pgn(){}function Ign(){}function Ogn(){}function Dgn(){}function Lgn(){}function Ngn(){}function $gn(){}function xgn(){}function Fgn(){}function Bgn(){}function Rgn(){}function Kgn(){}function _gn(){}function Hgn(){}function qgn(){}function Ugn(){}function Ggn(){}function zgn(){}function Xgn(){}function Vgn(){}function Wgn(){}function Jgn(){}function Qgn(){}function Ygn(){}function Zgn(){}function n2n(){}function e2n(){}function t2n(){}function i2n(){}function r2n(){}function c2n(){}function u2n(){}function GU(){}function o2n(){}function s2n(){}function f2n(){}function h2n(){}function l2n(){}function a2n(){}function d2n(){}function b2n(){}function w2n(){}function g2n(){}function p2n(){}function m2n(){}function v2n(){}function k2n(){}function y2n(){}function j2n(){}function E2n(){}function C2n(){}function M2n(){}function T2n(){}function A2n(){}function S2n(){}function P2n(){}function I2n(){}function O2n(){}function D2n(){}function L2n(){}function N2n(){}function $2n(){}function x2n(){}function F2n(){}function B2n(){}function R2n(){}function K2n(){}function _2n(){}function H2n(){}function q2n(){}function U2n(){}function G2n(){}function z2n(){}function X2n(){}function V2n(){}function W2n(){}function J2n(){}function Q2n(){}function Y2n(){}function Z2n(){}function npn(){}function epn(){}function tpn(){}function ipn(){}function rpn(){}function cpn(){}function upn(){}function opn(){}function spn(){}function fpn(){}function hpn(){}function lpn(){}function apn(){}function dpn(){}function bpn(){}function wpn(){}function gpn(){}function ppn(){}function mpn(){}function vpn(){}function kpn(){}function ypn(){}function jpn(){}function Epn(){}function Cpn(){}function Mpn(){}function zU(){}function Tpn(){}function Apn(){}function Spn(){}function Ppn(){}function Ipn(){}function Opn(){}function Dpn(){}function Lpn(){}function Npn(){}function $pn(){}function XU(){}function xpn(){}function Fpn(){}function Bpn(){}function Rpn(){}function Kpn(){}function _pn(){}function VU(){}function WU(){}function Hpn(){}function JU(){}function QU(){}function qpn(){}function Upn(){}function Gpn(){}function zpn(){}function Xpn(){}function Vpn(){}function Wpn(){}function Jpn(){}function Qpn(){}function Ypn(){}function Zpn(){}function YU(){}function n3n(){}function e3n(){}function t3n(){}function i3n(){}function r3n(){}function c3n(){}function u3n(){}function o3n(){}function s3n(){}function f3n(){}function h3n(){}function l3n(){}function a3n(){}function d3n(){}function b3n(){}function w3n(){}function g3n(){}function p3n(){}function m3n(){}function v3n(){}function k3n(){}function y3n(){}function j3n(){}function E3n(){}function C3n(){}function M3n(){}function T3n(){}function A3n(){}function S3n(){}function P3n(){}function I3n(){}function O3n(){}function D3n(){}function L3n(){}function N3n(){}function $3n(){}function x3n(){}function F3n(){}function B3n(){}function R3n(){}function K3n(){}function _3n(){}function H3n(){}function q3n(){}function U3n(){}function G3n(){}function z3n(){}function X3n(){}function V3n(){}function W3n(){}function J3n(){}function Q3n(){}function Y3n(){}function Z3n(){}function n4n(){}function e4n(){}function t4n(){}function i4n(){}function r4n(){}function c4n(){}function u4n(){}function o4n(){}function s4n(){}function f4n(){}function h4n(){}function l4n(){}function a4n(){}function d4n(){}function b4n(){}function w4n(){}function g4n(){}function p4n(){}function m4n(){}function v4n(){}function k4n(){}function y4n(){}function j4n(){}function E4n(){}function C4n(){}function M4n(){}function T4n(){}function A4n(){}function S4n(){}function P4n(){}function I4n(){}function O4n(){}function _se(){}function D4n(){}function L4n(){}function N4n(){}function $4n(){}function x4n(){}function F4n(){}function B4n(){}function R4n(){}function K4n(){}function _4n(){}function H4n(){}function q4n(){}function U4n(){}function G4n(){}function z4n(){}function X4n(){}function V4n(){}function W4n(){}function J4n(){}function Q4n(){}function Y4n(){}function Z4n(){}function nmn(){}function emn(){}function tmn(){}function imn(){}function rmn(){}function BO(){}function RO(){}function cmn(){}function KO(){}function umn(){}function omn(){}function smn(){}function fmn(){}function hmn(){}function lmn(){}function amn(){}function dmn(){}function bmn(){}function wmn(){}function ZU(){}function gmn(){}function pmn(){}function mmn(){}function Hse(){}function vmn(){}function kmn(){}function ymn(){}function jmn(){}function Emn(){}function Cmn(){}function Mmn(){}function Ra(){}function Tmn(){}function ep(){}function nG(){}function Amn(){}function Smn(){}function Pmn(){}function Imn(){}function Omn(){}function Dmn(){}function Lmn(){}function Nmn(){}function $mn(){}function xmn(){}function Fmn(){}function Bmn(){}function Rmn(){}function Kmn(){}function _mn(){}function Hmn(){}function qmn(){}function Umn(){}function Gmn(){}function hn(){}function zmn(){}function Xmn(){}function Vmn(){}function Wmn(){}function Jmn(){}function Qmn(){}function Ymn(){}function Zmn(){}function nvn(){}function evn(){}function tvn(){}function ivn(){}function rvn(){}function _O(){}function cvn(){}function uvn(){}function ovn(){}function yE(){}function svn(){}function HO(){}function jE(){}function fvn(){}function eG(){}function hvn(){}function lvn(){}function avn(){}function dvn(){}function bvn(){}function wvn(){}function EE(){}function gvn(){}function pvn(){}function CE(){}function mvn(){}function ME(){}function vvn(){}function tG(){}function kvn(){}function qO(){}function iG(){}function yvn(){}function jvn(){}function Evn(){}function Cvn(){}function qse(){}function Mvn(){}function Tvn(){}function Avn(){}function Svn(){}function Pvn(){}function Ivn(){}function Ovn(){}function Dvn(){}function Lvn(){}function Nvn(){}function W3(){}function UO(){}function $vn(){}function xvn(){}function Fvn(){}function Bvn(){}function Rvn(){}function Kvn(){}function _vn(){}function Hvn(){}function qvn(){}function Uvn(){}function Gvn(){}function zvn(){}function Xvn(){}function Vvn(){}function Wvn(){}function Jvn(){}function Qvn(){}function Yvn(){}function Zvn(){}function n6n(){}function e6n(){}function t6n(){}function i6n(){}function r6n(){}function c6n(){}function u6n(){}function o6n(){}function s6n(){}function f6n(){}function h6n(){}function l6n(){}function a6n(){}function d6n(){}function b6n(){}function w6n(){}function g6n(){}function p6n(){}function m6n(){}function v6n(){}function k6n(){}function y6n(){}function j6n(){}function E6n(){}function C6n(){}function M6n(){}function T6n(){}function A6n(){}function S6n(){}function P6n(){}function I6n(){}function O6n(){}function D6n(){}function L6n(){}function N6n(){}function $6n(){}function x6n(){}function F6n(){}function B6n(){}function R6n(){}function K6n(){}function _6n(){}function H6n(){}function q6n(){}function U6n(){}function G6n(){}function z6n(){}function X6n(){}function V6n(){}function W6n(){}function J6n(){}function Q6n(){}function Y6n(){}function Z6n(){}function n5n(){}function e5n(){}function t5n(){}function i5n(){}function r5n(){}function c5n(){}function u5n(){}function o5n(){}function s5n(){}function f5n(){}function h5n(){}function l5n(){}function a5n(){}function d5n(){}function b5n(){}function w5n(){}function g5n(){}function p5n(){}function m5n(){}function v5n(){}function k5n(){}function y5n(){}function j5n(){}function E5n(){}function C5n(){}function M5n(){}function T5n(){}function A5n(){}function rG(){}function S5n(){}function P5n(){}function GO(){n6()}function I5n(){u7()}function O5n(){aA()}function D5n(){Q$()}function L5n(){M5()}function N5n(){ann()}function $5n(){qs()}function x5n(){jZ()}function F5n(){zk()}function B5n(){o7()}function R5n(){$7()}function K5n(){aCn()}function _5n(){Hp()}function H5n(){KLn()}function q5n(){yQ()}function U5n(){SOn()}function G5n(){jQ()}function z5n(){pNn()}function X5n(){AOn()}function V5n(){cm()}function W5n(){nxn()}function J5n(){Z$n()}function Q5n(){EDn()}function Y5n(){exn()}function Z5n(){ca()}function n8n(){ZE()}function e8n(){ltn()}function t8n(){cn()}function i8n(){txn()}function r8n(){Pxn()}function c8n(){POn()}function u8n(){nKn()}function o8n(){IOn()}function s8n(){bUn()}function f8n(){qnn()}function h8n(){kl()}function l8n(){wBn()}function a8n(){lc()}function d8n(){ROn()}function b8n(){_p()}function w8n(){Men()}function g8n(){ua()}function p8n(){Ten()}function m8n(){Bf()}function v8n(){Qk()}function k8n(){EF()}function y8n(){Dx()}function cf(){wSn()}function j8n(){YM()}function E8n(){mA()}function cG(){qe()}function C8n(){NT()}function M8n(){YY()}function uG(){D$()}function oG(){KA()}function T8n(){Fen()}function sG(n){Jn(n)}function A8n(n){this.a=n}function TE(n){this.a=n}function S8n(n){this.a=n}function P8n(n){this.a=n}function I8n(n){this.a=n}function O8n(n){this.a=n}function D8n(n){this.a=n}function L8n(n){this.a=n}function fG(n){this.a=n}function hG(n){this.a=n}function N8n(n){this.a=n}function $8n(n){this.a=n}function zO(n){this.a=n}function x8n(n){this.a=n}function F8n(n){this.a=n}function XO(n){this.a=n}function VO(n){this.a=n}function B8n(n){this.a=n}function WO(n){this.a=n}function R8n(n){this.a=n}function K8n(n){this.a=n}function _8n(n){this.a=n}function lG(n){this.b=n}function H8n(n){this.c=n}function q8n(n){this.a=n}function U8n(n){this.a=n}function G8n(n){this.a=n}function z8n(n){this.a=n}function X8n(n){this.a=n}function V8n(n){this.a=n}function W8n(n){this.a=n}function J8n(n){this.a=n}function Q8n(n){this.a=n}function Y8n(n){this.a=n}function Z8n(n){this.a=n}function n9n(n){this.a=n}function e9n(n){this.a=n}function aG(n){this.a=n}function dG(n){this.a=n}function AE(n){this.a=n}function z9(n){this.a=n}function Ka(){this.a=[]}function t9n(n,e){n.a=e}function Use(n,e){n.a=e}function Gse(n,e){n.b=e}function zse(n,e){n.b=e}function Xse(n,e){n.b=e}function bG(n,e){n.j=e}function Vse(n,e){n.g=e}function Wse(n,e){n.i=e}function Jse(n,e){n.c=e}function Qse(n,e){n.c=e}function Yse(n,e){n.d=e}function Zse(n,e){n.d=e}function _a(n,e){n.k=e}function nfe(n,e){n.c=e}function wG(n,e){n.c=e}function gG(n,e){n.a=e}function efe(n,e){n.a=e}function tfe(n,e){n.f=e}function ife(n,e){n.a=e}function rfe(n,e){n.b=e}function JO(n,e){n.d=e}function SE(n,e){n.i=e}function pG(n,e){n.o=e}function cfe(n,e){n.r=e}function ufe(n,e){n.a=e}function ofe(n,e){n.b=e}function i9n(n,e){n.e=e}function sfe(n,e){n.f=e}function mG(n,e){n.g=e}function ffe(n,e){n.e=e}function hfe(n,e){n.f=e}function lfe(n,e){n.f=e}function QO(n,e){n.a=e}function YO(n,e){n.b=e}function afe(n,e){n.n=e}function dfe(n,e){n.a=e}function bfe(n,e){n.c=e}function wfe(n,e){n.c=e}function gfe(n,e){n.c=e}function pfe(n,e){n.a=e}function mfe(n,e){n.a=e}function vfe(n,e){n.d=e}function kfe(n,e){n.d=e}function yfe(n,e){n.e=e}function jfe(n,e){n.e=e}function Efe(n,e){n.g=e}function Cfe(n,e){n.f=e}function Mfe(n,e){n.j=e}function Tfe(n,e){n.a=e}function Afe(n,e){n.a=e}function Sfe(n,e){n.b=e}function r9n(n){n.b=n.a}function c9n(n){n.c=n.d.d}function vG(n){this.a=n}function kG(n){this.a=n}function yG(n){this.a=n}function Ha(n){this.a=n}function qa(n){this.a=n}function X9(n){this.a=n}function u9n(n){this.a=n}function jG(n){this.a=n}function V9(n){this.a=n}function PE(n){this.a=n}function ol(n){this.a=n}function Sb(n){this.a=n}function o9n(n){this.a=n}function s9n(n){this.a=n}function ZO(n){this.b=n}function J3(n){this.b=n}function Q3(n){this.b=n}function nD(n){this.a=n}function f9n(n){this.a=n}function eD(n){this.c=n}function C(n){this.c=n}function h9n(n){this.c=n}function Xv(n){this.d=n}function EG(n){this.a=n}function Te(n){this.a=n}function l9n(n){this.a=n}function CG(n){this.a=n}function MG(n){this.a=n}function TG(n){this.a=n}function AG(n){this.a=n}function SG(n){this.a=n}function PG(n){this.a=n}function Y3(n){this.a=n}function a9n(n){this.a=n}function d9n(n){this.a=n}function Z3(n){this.a=n}function b9n(n){this.a=n}function w9n(n){this.a=n}function g9n(n){this.a=n}function p9n(n){this.a=n}function m9n(n){this.a=n}function v9n(n){this.a=n}function k9n(n){this.a=n}function y9n(n){this.a=n}function j9n(n){this.a=n}function E9n(n){this.a=n}function C9n(n){this.a=n}function M9n(n){this.a=n}function T9n(n){this.a=n}function A9n(n){this.a=n}function S9n(n){this.a=n}function Vv(n){this.a=n}function P9n(n){this.a=n}function I9n(n){this.a=n}function O9n(n){this.a=n}function D9n(n){this.a=n}function IE(n){this.a=n}function L9n(n){this.a=n}function N9n(n){this.a=n}function n4(n){this.a=n}function IG(n){this.a=n}function $9n(n){this.a=n}function x9n(n){this.a=n}function F9n(n){this.a=n}function B9n(n){this.a=n}function R9n(n){this.a=n}function K9n(n){this.a=n}function OG(n){this.a=n}function DG(n){this.a=n}function LG(n){this.a=n}function Wv(n){this.a=n}function OE(n){this.e=n}function e4(n){this.a=n}function _9n(n){this.a=n}function tp(n){this.a=n}function NG(n){this.a=n}function H9n(n){this.a=n}function q9n(n){this.a=n}function U9n(n){this.a=n}function G9n(n){this.a=n}function z9n(n){this.a=n}function X9n(n){this.a=n}function V9n(n){this.a=n}function W9n(n){this.a=n}function J9n(n){this.a=n}function Q9n(n){this.a=n}function Y9n(n){this.a=n}function $G(n){this.a=n}function Z9n(n){this.a=n}function n7n(n){this.a=n}function e7n(n){this.a=n}function t7n(n){this.a=n}function i7n(n){this.a=n}function r7n(n){this.a=n}function c7n(n){this.a=n}function u7n(n){this.a=n}function o7n(n){this.a=n}function s7n(n){this.a=n}function f7n(n){this.a=n}function h7n(n){this.a=n}function l7n(n){this.a=n}function a7n(n){this.a=n}function d7n(n){this.a=n}function b7n(n){this.a=n}function w7n(n){this.a=n}function g7n(n){this.a=n}function p7n(n){this.a=n}function m7n(n){this.a=n}function v7n(n){this.a=n}function k7n(n){this.a=n}function y7n(n){this.a=n}function j7n(n){this.a=n}function E7n(n){this.a=n}function C7n(n){this.a=n}function M7n(n){this.a=n}function T7n(n){this.a=n}function A7n(n){this.a=n}function S7n(n){this.a=n}function P7n(n){this.a=n}function I7n(n){this.a=n}function O7n(n){this.a=n}function D7n(n){this.a=n}function L7n(n){this.a=n}function N7n(n){this.a=n}function $7n(n){this.a=n}function x7n(n){this.a=n}function F7n(n){this.c=n}function B7n(n){this.b=n}function R7n(n){this.a=n}function K7n(n){this.a=n}function _7n(n){this.a=n}function H7n(n){this.a=n}function q7n(n){this.a=n}function U7n(n){this.a=n}function G7n(n){this.a=n}function z7n(n){this.a=n}function X7n(n){this.a=n}function V7n(n){this.a=n}function W7n(n){this.a=n}function J7n(n){this.a=n}function Q7n(n){this.a=n}function Y7n(n){this.a=n}function Z7n(n){this.a=n}function nkn(n){this.a=n}function ekn(n){this.a=n}function tkn(n){this.a=n}function ikn(n){this.a=n}function rkn(n){this.a=n}function ckn(n){this.a=n}function ukn(n){this.a=n}function okn(n){this.a=n}function skn(n){this.a=n}function fkn(n){this.a=n}function hkn(n){this.a=n}function lkn(n){this.a=n}function sl(n){this.a=n}function sg(n){this.a=n}function akn(n){this.a=n}function dkn(n){this.a=n}function bkn(n){this.a=n}function wkn(n){this.a=n}function gkn(n){this.a=n}function pkn(n){this.a=n}function mkn(n){this.a=n}function vkn(n){this.a=n}function kkn(n){this.a=n}function ykn(n){this.a=n}function jkn(n){this.a=n}function Ekn(n){this.a=n}function Ckn(n){this.a=n}function Mkn(n){this.a=n}function Tkn(n){this.a=n}function Akn(n){this.a=n}function Skn(n){this.a=n}function Pkn(n){this.a=n}function Ikn(n){this.a=n}function Okn(n){this.a=n}function Dkn(n){this.a=n}function Lkn(n){this.a=n}function Nkn(n){this.a=n}function $kn(n){this.a=n}function xkn(n){this.a=n}function Fkn(n){this.a=n}function DE(n){this.a=n}function Bkn(n){this.f=n}function Rkn(n){this.a=n}function Kkn(n){this.a=n}function _kn(n){this.a=n}function Hkn(n){this.a=n}function qkn(n){this.a=n}function Ukn(n){this.a=n}function Gkn(n){this.a=n}function zkn(n){this.a=n}function Xkn(n){this.a=n}function Vkn(n){this.a=n}function Wkn(n){this.a=n}function Jkn(n){this.a=n}function Qkn(n){this.a=n}function Ykn(n){this.a=n}function Zkn(n){this.a=n}function nyn(n){this.a=n}function eyn(n){this.a=n}function tyn(n){this.a=n}function iyn(n){this.a=n}function ryn(n){this.a=n}function cyn(n){this.a=n}function uyn(n){this.a=n}function oyn(n){this.a=n}function syn(n){this.a=n}function fyn(n){this.a=n}function hyn(n){this.a=n}function lyn(n){this.a=n}function ayn(n){this.a=n}function tD(n){this.a=n}function xG(n){this.a=n}function lt(n){this.b=n}function dyn(n){this.a=n}function byn(n){this.a=n}function wyn(n){this.a=n}function gyn(n){this.a=n}function pyn(n){this.a=n}function myn(n){this.a=n}function vyn(n){this.a=n}function kyn(n){this.b=n}function yyn(n){this.a=n}function W9(n){this.a=n}function jyn(n){this.a=n}function Eyn(n){this.a=n}function FG(n){this.c=n}function LE(n){this.e=n}function NE(n){this.a=n}function $E(n){this.a=n}function iD(n){this.a=n}function Cyn(n){this.d=n}function Myn(n){this.a=n}function BG(n){this.a=n}function RG(n){this.a=n}function Wd(n){this.e=n}function Pfe(){this.a=0}function de(){Hu(this)}function Z(){pL(this)}function rD(){sIn(this)}function Tyn(){}function Jd(){this.c=Gdn}function Ayn(n,e){n.b+=e}function Ife(n,e){e.Wb(n)}function Ofe(n){return n.a}function Dfe(n){return n.a}function Lfe(n){return n.a}function Nfe(n){return n.a}function $fe(n){return n.a}function M(n){return n.e}function xfe(){return null}function Ffe(){return null}function Bfe(){Cz(),pLe()}function Rfe(n){n.b.Of(n.e)}function Syn(n){n.b=new CD}function Jv(n,e){n.b=e-n.b}function Qv(n,e){n.a=e-n.a}function Bn(n,e){n.push(e)}function Pyn(n,e){n.sort(e)}function Iyn(n,e){e.jd(n.a)}function Kfe(n,e){gi(e,n)}function _fe(n,e,t){n.Yd(t,e)}function J9(n,e){n.e=e,e.b=n}function KG(n){uh(),this.a=n}function Oyn(n){uh(),this.a=n}function Dyn(n){uh(),this.a=n}function cD(n){m0(),this.a=n}function Lyn(n){O4(),VK.le(n)}function _G(){_G=F,new de}function Ua(){YTn.call(this)}function HG(){YTn.call(this)}function qG(){Ua.call(this)}function uD(){Ua.call(this)}function Nyn(){Ua.call(this)}function Q9(){Ua.call(this)}function Cu(){Ua.call(this)}function ip(){Ua.call(this)}function Pe(){Ua.call(this)}function Bo(){Ua.call(this)}function $yn(){Ua.call(this)}function nc(){Ua.call(this)}function xyn(){Ua.call(this)}function Fyn(){this.a=this}function xE(){this.Bb|=256}function Byn(){this.b=new GMn}function Pb(n,e){n.length=e}function FE(n,e){nn(n.a,e)}function Hfe(n,e){bnn(n.c,e)}function qfe(n,e){fi(n.b,e)}function Ufe(n,e){uA(n.a,e)}function Gfe(n,e){cx(n.a,e)}function t4(n,e){it(n.e,e)}function rp(n){jA(n.c,n.b)}function zfe(n,e){n.kc().Nb(e)}function UG(n){this.a=B5e(n)}function ni(){this.a=new de}function Ryn(){this.a=new de}function GG(){this.a=new rCn}function BE(){this.a=new Z}function oD(){this.a=new Z}function zG(){this.a=new Z}function hs(){this.a=new cbn}function Ga(){this.a=new NLn}function XG(){this.a=new _U}function VG(){this.a=new TOn}function WG(){this.a=new BAn}function Kyn(){this.a=new Z}function _yn(){this.a=new Z}function Hyn(){this.a=new Z}function JG(){this.a=new Z}function qyn(){this.d=new Z}function Uyn(){this.a=new zOn}function Gyn(){this.a=new ni}function zyn(){this.a=new de}function Xyn(){this.b=new de}function Vyn(){this.b=new Z}function QG(){this.e=new Z}function Wyn(){this.a=new Z5n}function Jyn(){this.d=new Z}function Qyn(){QIn.call(this)}function Yyn(){QIn.call(this)}function Zyn(){Z.call(this)}function YG(){qG.call(this)}function ZG(){BE.call(this)}function njn(){qC.call(this)}function ejn(){JG.call(this)}function Yv(){Tyn.call(this)}function sD(){Yv.call(this)}function cp(){Tyn.call(this)}function nz(){cp.call(this)}function tjn(){rz.call(this)}function ijn(){rz.call(this)}function rjn(){rz.call(this)}function cjn(){cz.call(this)}function Zv(){svn.call(this)}function ez(){svn.call(this)}function Mu(){Ct.call(this)}function ujn(){yjn.call(this)}function ojn(){yjn.call(this)}function sjn(){de.call(this)}function fjn(){de.call(this)}function hjn(){de.call(this)}function fD(){cxn.call(this)}function ljn(){ni.call(this)}function ajn(){xE.call(this)}function hD(){BX.call(this)}function tz(){de.call(this)}function lD(){BX.call(this)}function aD(){de.call(this)}function djn(){de.call(this)}function iz(){ME.call(this)}function bjn(){iz.call(this)}function wjn(){ME.call(this)}function gjn(){rG.call(this)}function rz(){this.a=new ni}function pjn(){this.a=new de}function mjn(){this.a=new Z}function cz(){this.a=new de}function up(){this.a=new Ct}function vjn(){this.j=new Z}function kjn(){this.a=new mEn}function yjn(){this.a=new mvn}function uz(){this.a=new Z4n}function n6(){n6=F,KK=new Ht}function dD(){dD=F,_K=new Ejn}function bD(){bD=F,HK=new jjn}function jjn(){XO.call(this,"")}function Ejn(){XO.call(this,"")}function Cjn(n){S$n.call(this,n)}function Mjn(n){S$n.call(this,n)}function oz(n){fG.call(this,n)}function sz(n){XEn.call(this,n)}function Xfe(n){XEn.call(this,n)}function Vfe(n){sz.call(this,n)}function Wfe(n){sz.call(this,n)}function Jfe(n){sz.call(this,n)}function Tjn(n){zN.call(this,n)}function Ajn(n){zN.call(this,n)}function Sjn(n){uSn.call(this,n)}function Pjn(n){Oz.call(this,n)}function e6(n){WE.call(this,n)}function fz(n){WE.call(this,n)}function Ijn(n){WE.call(this,n)}function hz(n){mje.call(this,n)}function lz(n){hz.call(this,n)}function ec(n){APn.call(this,n)}function Ojn(n){ec.call(this,n)}function op(){z9.call(this,{})}function Djn(){Djn=F,dQn=new M0n}function RE(){RE=F,GK=new STn}function Ljn(){Ljn=F,oun=new Bu}function az(){az=F,sun=new N1}function KE(){KE=F,P8=new $1}function wD(n){b4(),this.a=n}function gD(n){RQ(),this.a=n}function Qd(n){nN(),this.f=n}function pD(n){nN(),this.f=n}function Njn(n){bSn(),this.a=n}function $jn(n){n.b=null,n.c=0}function Qfe(n,e){n.e=e,bqn(n,e)}function Yfe(n,e){n.a=e,cEe(n)}function mD(n,e,t){n.a[e.g]=t}function Zfe(n,e,t){kke(t,n,e)}function nhe(n,e){Wae(e.i,n.n)}function xjn(n,e){v6e(n).Cd(e)}function ehe(n,e){n.a.ec().Mc(e)}function Fjn(n,e){return n.g-e.g}function the(n,e){return n*n/e}function on(n){return Jn(n),n}function $(n){return Jn(n),n}function Y9(n){return Jn(n),n}function ihe(n){return new AE(n)}function rhe(n){return new qb(n)}function dz(n){return Jn(n),n}function che(n){return Jn(n),n}function _E(n){ec.call(this,n)}function Ir(n){ec.call(this,n)}function Bjn(n){ec.call(this,n)}function vD(n){APn.call(this,n)}function i4(n){ec.call(this,n)}function Gn(n){ec.call(this,n)}function Or(n){ec.call(this,n)}function Rjn(n){ec.call(this,n)}function sp(n){ec.call(this,n)}function Kl(n){ec.call(this,n)}function _l(n){ec.call(this,n)}function fp(n){ec.call(this,n)}function nh(n){ec.call(this,n)}function kD(n){ec.call(this,n)}function Le(n){ec.call(this,n)}function Ku(n){Jn(n),this.a=n}function bz(n){return ld(n),n}function t6(n){TW(n,n.length)}function i6(n){return n.b==n.c}function Ib(n){return!!n&&n.b}function uhe(n){return!!n&&n.k}function ohe(n){return!!n&&n.j}function she(n,e,t){n.c.Ef(e,t)}function Kjn(n,e){n.be(e),e.ae(n)}function hp(n){uh(),this.a=Se(n)}function yD(){this.a=Oe(Se(ur))}function _jn(){throw M(new Pe)}function fhe(){throw M(new Pe)}function wz(){throw M(new Pe)}function Hjn(){throw M(new Pe)}function hhe(){throw M(new Pe)}function lhe(){throw M(new Pe)}function HE(){HE=F,O4()}function Hl(){X9.call(this,"")}function r6(){X9.call(this,"")}function x1(){X9.call(this,"")}function lp(){X9.call(this,"")}function gz(n){Ir.call(this,n)}function pz(n){Ir.call(this,n)}function eh(n){Gn.call(this,n)}function r4(n){Q3.call(this,n)}function qjn(n){r4.call(this,n)}function jD(n){BC.call(this,n)}function ED(n){JX.call(this,n,0)}function CD(){sJ.call(this,12,3)}function T(n,e){return kOn(n,e)}function qE(n,e){return o$(n,e)}function ahe(n,e){return n.a-e.a}function dhe(n,e){return n.a-e.a}function bhe(n,e){return n.a-e.a}function whe(n,e){return e in n.a}function Ujn(n){return n.a?n.b:0}function ghe(n){return n.a?n.b:0}function phe(n,e,t){e.Cd(n.a[t])}function mhe(n,e,t){e.Pe(n.a[t])}function vhe(n,e){n.b=new rr(e)}function khe(n,e){return n.b=e,n}function Gjn(n,e){return n.c=e,n}function zjn(n,e){return n.f=e,n}function yhe(n,e){return n.g=e,n}function mz(n,e){return n.a=e,n}function vz(n,e){return n.f=e,n}function jhe(n,e){return n.k=e,n}function kz(n,e){return n.a=e,n}function Ehe(n,e){return n.e=e,n}function yz(n,e){return n.e=e,n}function Che(n,e){return n.f=e,n}function Mhe(n,e){n.b=!0,n.d=e}function The(n,e){return n.b-e.b}function Ahe(n,e){return n.g-e.g}function She(n,e){return n?0:e-1}function Xjn(n,e){return n?0:e-1}function Phe(n,e){return n?e-1:0}function Ihe(n,e){return n.s-e.s}function Ohe(n,e){return e.rg(n)}function Yd(n,e){return n.b=e,n}function UE(n,e){return n.a=e,n}function Zd(n,e){return n.c=e,n}function n0(n,e){return n.d=e,n}function e0(n,e){return n.e=e,n}function jz(n,e){return n.f=e,n}function c6(n,e){return n.a=e,n}function c4(n,e){return n.b=e,n}function u4(n,e){return n.c=e,n}function an(n,e){return n.c=e,n}function Sn(n,e){return n.b=e,n}function dn(n,e){return n.d=e,n}function bn(n,e){return n.e=e,n}function Dhe(n,e){return n.f=e,n}function wn(n,e){return n.g=e,n}function gn(n,e){return n.a=e,n}function pn(n,e){return n.i=e,n}function mn(n,e){return n.j=e,n}function Lhe(n,e){ca(),ic(e,n)}function Nhe(n,e,t){Jbe(n.a,e,t)}function GE(n){$L.call(this,n)}function Vjn(n){Z5e.call(this,n)}function Wjn(n){SIn.call(this,n)}function Ez(n){SIn.call(this,n)}function F1(n){S0.call(this,n)}function Jjn(n){CN.call(this,n)}function Qjn(n){CN.call(this,n)}function Yjn(){DX.call(this,"")}function Li(){this.a=0,this.b=0}function Zjn(){this.b=0,this.a=0}function nEn(n,e){n.b=0,Zb(n,e)}function eEn(n,e){return n.k=e,n}function $he(n,e){return n.j=e,n}function xhe(n,e){n.c=e,n.b=!0}function tEn(){tEn=F,TQn=Xke()}function B1(){B1=F,voe=rke()}function iEn(){iEn=F,Ti=gye()}function Cz(){Cz=F,Oa=z4()}function o4(){o4=F,Udn=cke()}function rEn(){rEn=F,ise=uke()}function Mz(){Mz=F,yc=tEe()}function uf(n){return n.e&&n.e()}function cEn(n){return n.l|n.m<<22}function uEn(n,e){return n.c._b(e)}function oEn(n,e){return rBn(n.b,e)}function MD(n){return n?n.d:null}function Fhe(n){return n?n.g:null}function Bhe(n){return n?n.i:null}function za(n){return ll(n),n.o}function fg(n,e){return n.a+=e,n}function TD(n,e){return n.a+=e,n}function ql(n,e){return n.a+=e,n}function t0(n,e){return n.a+=e,n}function Tz(n,e){for(;n.Bd(e););}function zE(n){this.a=new ap(n)}function sEn(){throw M(new Pe)}function fEn(){throw M(new Pe)}function hEn(){throw M(new Pe)}function lEn(){throw M(new Pe)}function aEn(){throw M(new Pe)}function dEn(){throw M(new Pe)}function Ul(n){this.a=new iN(n)}function bEn(){this.a=new K5(Rln)}function wEn(){this.b=new K5(rln)}function gEn(){this.a=new K5(f1n)}function pEn(){this.b=new K5(Fq)}function mEn(){this.b=new K5(Fq)}function XE(n){this.a=0,this.b=n}function Az(n){zGn(),ILe(this,n)}function s4(n){return z1(n),n.a}function Z9(n){return n.b!=n.d.c}function Sz(n,e){return n.d[e.p]}function vEn(n,e){return XTe(n,e)}function Pz(n,e,t){n.splice(e,t)}function hg(n,e){for(;n.Re(e););}function kEn(n){n.c?Dqn(n):Lqn(n)}function yEn(){throw M(new Pe)}function jEn(){throw M(new Pe)}function EEn(){throw M(new Pe)}function CEn(){throw M(new Pe)}function MEn(){throw M(new Pe)}function TEn(){throw M(new Pe)}function AEn(){throw M(new Pe)}function SEn(){throw M(new Pe)}function PEn(){throw M(new Pe)}function IEn(){throw M(new Pe)}function Rhe(){throw M(new nc)}function Khe(){throw M(new nc)}function n7(n){this.a=new OEn(n)}function OEn(n){Ume(this,n,jje())}function e7(n){return!n||oIn(n)}function t7(n){return Zf[n]!=-1}function _he(){cP!=0&&(cP=0),uP=-1}function DEn(){RK==null&&(RK=[])}function i7(n,e){Cg.call(this,n,e)}function f4(n,e){i7.call(this,n,e)}function LEn(n,e){this.a=n,this.b=e}function NEn(n,e){this.a=n,this.b=e}function $En(n,e){this.a=n,this.b=e}function xEn(n,e){this.a=n,this.b=e}function FEn(n,e){this.a=n,this.b=e}function BEn(n,e){this.a=n,this.b=e}function REn(n,e){this.a=n,this.b=e}function h4(n,e){this.e=n,this.d=e}function Iz(n,e){this.b=n,this.c=e}function KEn(n,e){this.b=n,this.a=e}function _En(n,e){this.b=n,this.a=e}function HEn(n,e){this.b=n,this.a=e}function qEn(n,e){this.b=n,this.a=e}function UEn(n,e){this.a=n,this.b=e}function AD(n,e){this.a=n,this.b=e}function GEn(n,e){this.a=n,this.f=e}function i0(n,e){this.g=n,this.i=e}function je(n,e){this.f=n,this.g=e}function zEn(n,e){this.b=n,this.c=e}function XEn(n){KX(n.dc()),this.c=n}function Hhe(n,e){this.a=n,this.b=e}function VEn(n,e){this.a=n,this.b=e}function WEn(n){this.a=u(Se(n),15)}function Oz(n){this.a=u(Se(n),15)}function JEn(n){this.a=u(Se(n),85)}function VE(n){this.b=u(Se(n),85)}function WE(n){this.b=u(Se(n),51)}function JE(){this.q=new y.Date}function SD(n,e){this.a=n,this.b=e}function QEn(n,e){return Zc(n.b,e)}function r7(n,e){return n.b.Hc(e)}function YEn(n,e){return n.b.Ic(e)}function ZEn(n,e){return n.b.Qc(e)}function nCn(n,e){return n.b.Hc(e)}function eCn(n,e){return n.c.uc(e)}function tCn(n,e){return rt(n.c,e)}function of(n,e){return n.a._b(e)}function iCn(n,e){return n>e&&e0}function ND(n,e){return Ec(n,e)<0}function vCn(n,e){return JL(n.a,e)}function ole(n,e){yOn.call(this,n,e)}function Bz(n){wN(),uSn.call(this,n)}function Rz(n,e){bPn(n,n.length,e)}function s7(n,e){HPn(n,n.length,e)}function d6(n,e){return n.a.get(e)}function kCn(n,e){return Zc(n.e,e)}function Kz(n){return Jn(n),!1}function _z(n){this.a=u(Se(n),229)}function cC(n){In.call(this,n,21)}function uC(n,e){je.call(this,n,e)}function $D(n,e){je.call(this,n,e)}function yCn(n,e){this.b=n,this.a=e}function oC(n,e){this.d=n,this.e=e}function jCn(n,e){this.a=n,this.b=e}function ECn(n,e){this.a=n,this.b=e}function CCn(n,e){this.a=n,this.b=e}function MCn(n,e){this.a=n,this.b=e}function bp(n,e){this.a=n,this.b=e}function TCn(n,e){this.b=n,this.a=e}function Hz(n,e){this.b=n,this.a=e}function qz(n,e){je.call(this,n,e)}function Uz(n,e){je.call(this,n,e)}function lg(n,e){je.call(this,n,e)}function xD(n,e){je.call(this,n,e)}function FD(n,e){je.call(this,n,e)}function BD(n,e){je.call(this,n,e)}function sC(n,e){je.call(this,n,e)}function Gz(n,e){this.b=n,this.a=e}function fC(n,e){je.call(this,n,e)}function zz(n,e){this.b=n,this.a=e}function hC(n,e){je.call(this,n,e)}function ACn(n,e){this.b=n,this.a=e}function Xz(n,e){je.call(this,n,e)}function RD(n,e){je.call(this,n,e)}function f7(n,e){je.call(this,n,e)}function b6(n,e,t){n.splice(e,0,t)}function sle(n,e,t){n.Mb(t)&&e.Cd(t)}function fle(n,e,t){e.Pe(n.a.Ye(t))}function hle(n,e,t){e.Dd(n.a.Ze(t))}function lle(n,e,t){e.Cd(n.a.Kb(t))}function ale(n,e){return Au(n.c,e)}function dle(n,e){return Au(n.e,e)}function lC(n,e){je.call(this,n,e)}function aC(n,e){je.call(this,n,e)}function w6(n,e){je.call(this,n,e)}function Vz(n,e){je.call(this,n,e)}function ei(n,e){je.call(this,n,e)}function dC(n,e){je.call(this,n,e)}function SCn(n,e){this.a=n,this.b=e}function PCn(n,e){this.a=n,this.b=e}function ICn(n,e){this.a=n,this.b=e}function OCn(n,e){this.a=n,this.b=e}function DCn(n,e){this.a=n,this.b=e}function LCn(n,e){this.a=n,this.b=e}function NCn(n,e){this.b=n,this.a=e}function $Cn(n,e){this.b=n,this.a=e}function Wz(n,e){this.b=n,this.a=e}function d4(n,e){this.c=n,this.d=e}function xCn(n,e){this.e=n,this.d=e}function FCn(n,e){this.a=n,this.b=e}function BCn(n,e){this.a=n,this.b=e}function RCn(n,e){this.a=n,this.b=e}function KCn(n,e){this.b=n,this.a=e}function _Cn(n,e){this.b=e,this.c=n}function bC(n,e){je.call(this,n,e)}function h7(n,e){je.call(this,n,e)}function KD(n,e){je.call(this,n,e)}function Jz(n,e){je.call(this,n,e)}function g6(n,e){je.call(this,n,e)}function _D(n,e){je.call(this,n,e)}function HD(n,e){je.call(this,n,e)}function l7(n,e){je.call(this,n,e)}function Qz(n,e){je.call(this,n,e)}function qD(n,e){je.call(this,n,e)}function p6(n,e){je.call(this,n,e)}function Yz(n,e){je.call(this,n,e)}function m6(n,e){je.call(this,n,e)}function v6(n,e){je.call(this,n,e)}function Db(n,e){je.call(this,n,e)}function UD(n,e){je.call(this,n,e)}function GD(n,e){je.call(this,n,e)}function Zz(n,e){je.call(this,n,e)}function a7(n,e){je.call(this,n,e)}function ag(n,e){je.call(this,n,e)}function zD(n,e){je.call(this,n,e)}function wC(n,e){je.call(this,n,e)}function d7(n,e){je.call(this,n,e)}function Lb(n,e){je.call(this,n,e)}function gC(n,e){je.call(this,n,e)}function nX(n,e){je.call(this,n,e)}function XD(n,e){je.call(this,n,e)}function VD(n,e){je.call(this,n,e)}function WD(n,e){je.call(this,n,e)}function JD(n,e){je.call(this,n,e)}function QD(n,e){je.call(this,n,e)}function YD(n,e){je.call(this,n,e)}function ZD(n,e){je.call(this,n,e)}function HCn(n,e){this.b=n,this.a=e}function eX(n,e){je.call(this,n,e)}function qCn(n,e){this.a=n,this.b=e}function UCn(n,e){this.a=n,this.b=e}function GCn(n,e){this.a=n,this.b=e}function tX(n,e){je.call(this,n,e)}function iX(n,e){je.call(this,n,e)}function zCn(n,e){this.a=n,this.b=e}function ble(n,e){return k4(),e!=n}function b7(n){return oe(n.a),n.b}function nL(n){return yCe(n,n.c),n}function XCn(){return tEn(),new TQn}function VCn(){VC(),this.a=new kV}function WCn(){OA(),this.a=new ni}function JCn(){NN(),this.b=new ni}function QCn(n,e){this.b=n,this.d=e}function YCn(n,e){this.a=n,this.b=e}function ZCn(n,e){this.a=n,this.b=e}function nMn(n,e){this.a=n,this.b=e}function eMn(n,e){this.b=n,this.a=e}function rX(n,e){je.call(this,n,e)}function cX(n,e){je.call(this,n,e)}function pC(n,e){je.call(this,n,e)}function u0(n,e){je.call(this,n,e)}function eL(n,e){je.call(this,n,e)}function mC(n,e){je.call(this,n,e)}function uX(n,e){je.call(this,n,e)}function oX(n,e){je.call(this,n,e)}function w7(n,e){je.call(this,n,e)}function sX(n,e){je.call(this,n,e)}function tL(n,e){je.call(this,n,e)}function vC(n,e){je.call(this,n,e)}function iL(n,e){je.call(this,n,e)}function rL(n,e){je.call(this,n,e)}function cL(n,e){je.call(this,n,e)}function uL(n,e){je.call(this,n,e)}function fX(n,e){je.call(this,n,e)}function oL(n,e){je.call(this,n,e)}function hX(n,e){je.call(this,n,e)}function g7(n,e){je.call(this,n,e)}function sL(n,e){je.call(this,n,e)}function lX(n,e){je.call(this,n,e)}function p7(n,e){je.call(this,n,e)}function aX(n,e){je.call(this,n,e)}function tMn(n,e){this.b=n,this.a=e}function iMn(n,e){this.b=n,this.a=e}function rMn(n,e){this.b=n,this.a=e}function cMn(n,e){this.b=n,this.a=e}function dX(n,e){this.a=n,this.b=e}function uMn(n,e){this.a=n,this.b=e}function oMn(n,e){this.a=n,this.b=e}function V(n,e){this.a=n,this.b=e}function k6(n,e){je.call(this,n,e)}function m7(n,e){je.call(this,n,e)}function wp(n,e){je.call(this,n,e)}function y6(n,e){je.call(this,n,e)}function v7(n,e){je.call(this,n,e)}function fL(n,e){je.call(this,n,e)}function kC(n,e){je.call(this,n,e)}function j6(n,e){je.call(this,n,e)}function hL(n,e){je.call(this,n,e)}function yC(n,e){je.call(this,n,e)}function dg(n,e){je.call(this,n,e)}function k7(n,e){je.call(this,n,e)}function E6(n,e){je.call(this,n,e)}function C6(n,e){je.call(this,n,e)}function y7(n,e){je.call(this,n,e)}function jC(n,e){je.call(this,n,e)}function bg(n,e){je.call(this,n,e)}function lL(n,e){je.call(this,n,e)}function sMn(n,e){je.call(this,n,e)}function EC(n,e){je.call(this,n,e)}function fMn(n,e){this.a=n,this.b=e}function hMn(n,e){this.a=n,this.b=e}function lMn(n,e){this.a=n,this.b=e}function aMn(n,e){this.a=n,this.b=e}function dMn(n,e){this.a=n,this.b=e}function bMn(n,e){this.a=n,this.b=e}function bi(n,e){this.a=n,this.b=e}function wMn(n,e){this.a=n,this.b=e}function gMn(n,e){this.a=n,this.b=e}function pMn(n,e){this.a=n,this.b=e}function mMn(n,e){this.a=n,this.b=e}function vMn(n,e){this.a=n,this.b=e}function kMn(n,e){this.a=n,this.b=e}function yMn(n,e){this.b=n,this.a=e}function jMn(n,e){this.b=n,this.a=e}function EMn(n,e){this.b=n,this.a=e}function CMn(n,e){this.b=n,this.a=e}function MMn(n,e){this.a=n,this.b=e}function TMn(n,e){this.a=n,this.b=e}function CC(n,e){je.call(this,n,e)}function AMn(n,e){this.a=n,this.b=e}function SMn(n,e){this.a=n,this.b=e}function gp(n,e){je.call(this,n,e)}function PMn(n,e){this.f=n,this.c=e}function bX(n,e){return Au(n.g,e)}function wle(n,e){return Au(e.b,n)}function IMn(n,e){return wx(n.a,e)}function gle(n,e){return-n.b.af(e)}function ple(n,e){n&&Xe(hE,n,e)}function wX(n,e){n.i=null,kT(n,e)}function mle(n,e,t){yKn(e,oF(n,t))}function vle(n,e,t){yKn(e,oF(n,t))}function kle(n,e){VMe(n.a,u(e,58))}function OMn(n,e){U4e(n.a,u(e,12))}function MC(n,e){this.a=n,this.b=e}function DMn(n,e){this.a=n,this.b=e}function LMn(n,e){this.a=n,this.b=e}function NMn(n,e){this.a=n,this.b=e}function $Mn(n,e){this.a=n,this.b=e}function xMn(n,e){this.d=n,this.b=e}function FMn(n,e){this.e=n,this.a=e}function j7(n,e){this.b=n,this.c=e}function gX(n,e){this.i=n,this.g=e}function pX(n,e){this.d=n,this.e=e}function yle(n,e){cme(new ne(n),e)}function TC(n){return Rk(n.c,n.b)}function Kr(n){return n?n.md():null}function x(n){return n??null}function Ai(n){return typeof n===nB}function Nb(n){return typeof n===i3}function $b(n){return typeof n===dtn}function o0(n,e){return Ec(n,e)==0}function AC(n,e){return Ec(n,e)>=0}function M6(n,e){return Ec(n,e)!=0}function SC(n,e){return jve(n.Kc(),e)}function _1(n,e){return n.Rd().Xb(e)}function BMn(n){return eo(n),n.d.gc()}function PC(n){return F6(n==null),n}function T6(n,e){return n.a+=""+e,n}function Er(n,e){return n.a+=""+e,n}function A6(n,e){return n.a+=""+e,n}function Dc(n,e){return n.a+=""+e,n}function Be(n,e){return n.a+=""+e,n}function mX(n,e){return n.a+=""+e,n}function jle(n){return""+(Jn(n),n)}function RMn(n){Hu(this),f5(this,n)}function KMn(){oJ(),dW.call(this)}function _Mn(n,e){mW.call(this,n,e)}function HMn(n,e){mW.call(this,n,e)}function IC(n,e){mW.call(this,n,e)}function ir(n,e){xt(n,e,n.c.b,n.c)}function wg(n,e){xt(n,e,n.a,n.a.a)}function vX(n){return Ln(n,0),null}function qMn(){this.b=0,this.a=!1}function UMn(){this.b=0,this.a=!1}function GMn(){this.b=new ap(Qb(12))}function zMn(){zMn=F,kYn=Ce(jx())}function XMn(){XMn=F,HZn=Ce(iqn())}function VMn(){VMn=F,lre=Ce(xxn())}function kX(){kX=F,_G(),fun=new de}function sf(n){return n.a=0,n.b=0,n}function WMn(n,e){return n.a=e.g+1,n}function aL(n,e){Kb.call(this,n,e)}function Mn(n,e){Dt.call(this,n,e)}function gg(n,e){gX.call(this,n,e)}function JMn(n,e){T7.call(this,n,e)}function dL(n,e){Y4.call(this,n,e)}function Ue(n,e){iC(),Xe(yO,n,e)}function QMn(n,e){n.q.setTime(id(e))}function Ele(n){y.clearTimeout(n)}function Cle(n){return Se(n),new S6(n)}function YMn(n,e){return x(n)===x(e)}function ZMn(n,e){return n.a.a.a.cc(e)}function bL(n,e){return qo(n.a,0,e)}function yX(n){return Awe(u(n,74))}function pp(n){return wi((Jn(n),n))}function Mle(n){return wi((Jn(n),n))}function nTn(n){return Yc(n.l,n.m,n.h)}function jX(n,e){return jc(n.a,e.a)}function Tle(n,e){return KPn(n.a,e.a)}function Ale(n,e){return bt(n.a,e.a)}function th(n,e){return n.indexOf(e)}function Sle(n,e){return n.j[e.p]==2}function s0(n,e){return n==e?0:n?1:-1}function OC(n){return n<10?"0"+n:""+n}function Vr(n){return typeof n===dtn}function Ple(n){return n==rb||n==Iw}function Ile(n){return n==rb||n==Pw}function eTn(n,e){return jc(n.g,e.g)}function EX(n){return qr(n.b.b,n,0)}function tTn(){rM.call(this,0,0,0,0)}function ih(){CG.call(this,new Ql)}function CX(n,e){F4(n,0,n.length,e)}function Ole(n,e){return nn(n.a,e),e}function Dle(n,e){return xs(),e.a+=n}function Lle(n,e){return xs(),e.a+=n}function Nle(n,e){return xs(),e.c+=n}function $le(n,e){return nn(n.c,e),n}function MX(n,e){return Mo(n.a,e),n}function iTn(n){this.a=XCn(),this.b=n}function rTn(n){this.a=XCn(),this.b=n}function rr(n){this.a=n.a,this.b=n.b}function S6(n){this.a=n,GO.call(this)}function cTn(n){this.a=n,GO.call(this)}function mp(){Ho.call(this,0,0,0,0)}function DC(n){return Mo(new ii,n)}function uTn(n){return jM(u(n,123))}function fo(n){return n.vh()&&n.wh()}function pg(n){return n!=Jf&&n!=Sa}function hl(n){return n==Br||n==Xr}function mg(n){return n==us||n==Vf}function oTn(n){return n==S2||n==A2}function xle(n,e){return jc(n.g,e.g)}function sTn(n,e){return new Y4(e,n)}function Fle(n,e){return new Y4(e,n)}function TX(n){return rbe(n.b.Kc(),n.a)}function wL(n,e){um(n,e),G4(n,n.D)}function gL(n,e,t){aT(n,e),lT(n,t)}function vg(n,e,t){I0(n,e),P0(n,t)}function Ro(n,e,t){eu(n,e),tu(n,t)}function E7(n,e,t){_4(n,e),q4(n,t)}function C7(n,e,t){H4(n,e),U4(n,t)}function fTn(n,e,t){sV.call(this,n,e,t)}function AX(n){PMn.call(this,n,!0)}function hTn(){uC.call(this,"Tail",3)}function lTn(){uC.call(this,"Head",1)}function H1(n){dh(),mve.call(this,n)}function f0(n){rM.call(this,n,n,n,n)}function pL(n){n.c=K(ki,Fn,1,0,5,1)}function SX(n){return n.b&&xF(n),n.a}function PX(n){return n.b&&xF(n),n.c}function Ble(n,e){qf||(n.b=e)}function Rle(n,e){return n[n.length]=e}function Kle(n,e){return n[n.length]=e}function _le(n,e){return Yb(e,Af(n))}function Hle(n,e){return Yb(e,Af(n))}function qle(n,e){return pT(dN(n.d),e)}function Ule(n,e){return pT(dN(n.g),e)}function Gle(n,e){return pT(dN(n.j),e)}function Ni(n,e){Dt.call(this,n.b,e)}function zle(n,e){ve(Sc(n.a),DOn(e))}function Xle(n,e){ve(no(n.a),LOn(e))}function Vle(n,e,t){Ro(t,t.i+n,t.j+e)}function aTn(n,e,t){$t(n.c[e.g],e.g,t)}function Wle(n,e,t){u(n.c,71).Gi(e,t)}function mL(n,e,t){return $t(n,e,t),t}function dTn(n){nu(n.Sf(),new D9n(n))}function kg(n){return n!=null?mt(n):0}function Jle(n){return n==null?0:mt(n)}function P6(n){nt(),Wd.call(this,n)}function bTn(n){this.a=n,qV.call(this,n)}function Mf(){Mf=F,y.Math.log(2)}function Ko(){Ko=F,rl=(pCn(),Moe)}function wTn(){wTn=F,YH=new j5(aU)}function Ie(){Ie=F,new gTn,new Z}function gTn(){new de,new de,new de}function Qle(){throw M(new Kl(QJn))}function Yle(){throw M(new Kl(QJn))}function Zle(){throw M(new Kl(YJn))}function n1e(){throw M(new Kl(YJn))}function vL(n){this.a=n,VE.call(this,n)}function kL(n){this.a=n,VE.call(this,n)}function pTn(n,e){m0(),this.a=n,this.b=e}function e1e(n,e){Se(e),Tg(n).Jc(new Ru)}function Yt(n,e){QL(n.c,n.c.length,e)}function tc(n){return n.ae?1:0}function OX(n,e){return Ec(n,e)>0?n:e}function Yc(n,e,t){return{l:n,m:e,h:t}}function t1e(n,e){n.a!=null&&OMn(e,n.a)}function i1e(n){Zi(n,null),Ii(n,null)}function r1e(n,e,t){return Xe(n.g,t,e)}function yg(n,e,t){return nZ(e,t,n.c)}function c1e(n,e,t){return Xe(n.k,t,e)}function u1e(n,e,t){return GOe(n,e,t),t}function o1e(n,e){return ko(),e.n.b+=n}function vTn(n){nJ.call(this),this.b=n}function DX(n){vV.call(this),this.a=n}function kTn(){uC.call(this,"Range",2)}function LC(n){this.b=n,this.a=new Z}function yTn(n){this.b=new $bn,this.a=n}function jTn(n){n.a=new OO,n.c=new OO}function ETn(n){n.a=new de,n.d=new de}function CTn(n){$N(n,null),xN(n,null)}function MTn(n,e){return XOe(n.a,e,null)}function s1e(n,e){return Xe(n.a,e.a,e)}function Ki(n){return new V(n.a,n.b)}function LX(n){return new V(n.c,n.d)}function f1e(n){return new V(n.c,n.d)}function I6(n,e){return cOe(n.c,n.b,e)}function O(n,e){return n!=null&&Tx(n,e)}function yL(n,e){return Yve(n.Kc(),e)!=-1}function NC(n){return n.Ob()?n.Pb():null}function h1e(n){this.b=(Dn(),new eD(n))}function NX(n){this.a=n,de.call(this)}function TTn(){T7.call(this,null,null)}function ATn(){_C.call(this,null,null)}function STn(){je.call(this,"INSTANCE",0)}function PTn(){LZ(),this.a=new K5(Ion)}function ITn(n){return hh(n,0,n.length)}function l1e(n,e){return new VTn(n.Kc(),e)}function $X(n,e){return n.a.Bc(e)!=null}function OTn(n,e){me(n),n.Gc(u(e,15))}function a1e(n,e,t){n.c.bd(e,u(t,136))}function d1e(n,e,t){n.c.Ui(e,u(t,136))}function DTn(n,e){n.c&&(tW(e),rOn(e))}function b1e(n,e){n.q.setHours(e),G5(n,e)}function w1e(n,e){a0(e,n.a.a.a,n.a.a.b)}function g1e(n,e,t,i){$t(n.a[e.g],t.g,i)}function jL(n,e,t){return n.a[e.g][t.g]}function p1e(n,e){return n.e[e.c.p][e.p]}function m1e(n,e){return n.c[e.c.p][e.p]}function Tf(n,e){return n.a[e.c.p][e.p]}function v1e(n,e){return n.j[e.p]=IMe(e)}function EL(n,e){return n.a.Bc(e)!=null}function k1e(n,e){return $(R(e.a))<=n}function y1e(n,e){return $(R(e.a))>=n}function j1e(n,e){return RJ(n.f,e.Pg())}function vp(n,e){return n.a*e.a+n.b*e.b}function E1e(n,e){return n.a0?e/(n*n):e*100}function V1e(n,e){return n>0?e*e/n:e*e*100}function xb(n,e){return u(Lf(n.a,e),34)}function W1e(n,e){return ca(),Pn(n,e.e,e)}function J1e(n,e,t){return nC(),t.Mg(n,e)}function Q1e(n){return kl(),n.e.a+n.f.a/2}function Y1e(n,e,t){return kl(),t.e.a-n*e}function Z1e(n){return kl(),n.e.b+n.f.b/2}function nae(n,e,t){return kl(),t.e.b-n*e}function sAn(n){n.d=new cAn(n),n.e=new de}function fAn(){this.a=new C0,this.b=new C0}function hAn(n){this.c=n,this.a=1,this.b=1}function lAn(n){YF(),Syn(this),this.Ff(n)}function eae(n,e,t){YM(),n.pf(e)&&t.Cd(n)}function tae(n,e,t){return nn(e,jBn(n,t))}function a0(n,e,t){return n.a+=e,n.b+=t,n}function iae(n,e,t){return n.a*=e,n.b*=t,n}function ZX(n,e){return n.a=e.a,n.b=e.b,n}function HC(n){return n.a=-n.a,n.b=-n.b,n}function N6(n,e,t){return n.a-=e,n.b-=t,n}function aAn(n){Ct.call(this),c5(this,n)}function dAn(){je.call(this,"GROW_TREE",0)}function bAn(){je.call(this,"POLYOMINO",0)}function lo(n,e,t){Iu.call(this,n,e,t,2)}function rae(n,e,t){k5(Sc(n.a),e,DOn(t))}function wAn(n,e){a6(),T7.call(this,n,e)}function nV(n,e){Gl(),_C.call(this,n,e)}function gAn(n,e){Gl(),nV.call(this,n,e)}function pAn(n,e){Gl(),_C.call(this,n,e)}function cae(n,e){return n.c.Fc(u(e,136))}function uae(n,e,t){k5(no(n.a),e,LOn(t))}function mAn(n){this.c=n,eu(n,0),tu(n,0)}function PL(n,e){Ko(),oM.call(this,n,e)}function vAn(n,e){Ko(),PL.call(this,n,e)}function eV(n,e){Ko(),PL.call(this,n,e)}function tV(n,e){Ko(),oM.call(this,n,e)}function kAn(n,e){Ko(),eV.call(this,n,e)}function yAn(n,e){Ko(),tV.call(this,n,e)}function jAn(n,e){Ko(),oM.call(this,n,e)}function oae(n,e,t){return e.zl(n.e,n.c,t)}function sae(n,e,t){return e.Al(n.e,n.c,t)}function iV(n,e,t){return qA(ak(n,e),t)}function IL(n,e){return na(n.e,u(e,54))}function fae(n){return n==null?null:NDe(n)}function hae(n){return n==null?null:Aje(n)}function lae(n){return n==null?null:Jr(n)}function aae(n){return n==null?null:Jr(n)}function un(n){return F6(n==null||Nb(n)),n}function R(n){return F6(n==null||$b(n)),n}function Oe(n){return F6(n==null||Ai(n)),n}function ll(n){n.o==null&&cMe(n)}function rV(n){if(!n)throw M(new Q9)}function dae(n){if(!n)throw M(new uD)}function oe(n){if(!n)throw M(new nc)}function Fb(n){if(!n)throw M(new Cu)}function EAn(n){if(!n)throw M(new Bo)}function m4(){m4=F,aE=new ujn,new ojn}function Mg(){Mg=F,O2=new lt("root")}function cV(){cxn.call(this),this.Bb|=hr}function bae(n,e){this.d=n,c9n(this),this.b=e}function uV(n,e){i$.call(this,n),this.a=e}function oV(n,e){i$.call(this,n),this.a=e}function sV(n,e,t){VM.call(this,n,e,t,null)}function CAn(n,e,t){VM.call(this,n,e,t,null)}function P7(n,e){this.c=n,h4.call(this,n,e)}function $6(n,e){this.a=n,P7.call(this,n,e)}function fV(n){this.q=new y.Date(id(n))}function MAn(n){return n>8?0:n+1}function TAn(n,e){qf||nn(n.a,e)}function wae(n,e){return o7(),Q4(e.d.i,n)}function gae(n,e){return Hp(),new tUn(e,n)}function pae(n,e,t){return n.Ne(e,t)<=0?t:e}function mae(n,e,t){return n.Ne(e,t)<=0?e:t}function vae(n,e){return u(Lf(n.b,e),143)}function kae(n,e){return u(Lf(n.c,e),233)}function OL(n){return u(sn(n.a,n.b),294)}function AAn(n){return new V(n.c,n.d+n.a)}function SAn(n){return Jn(n),n?1231:1237}function PAn(n){return ko(),oTn(u(n,203))}function Bb(){Bb=F,ron=yn((go(),Gd))}function yae(n,e){e.a?MCe(n,e):EL(n.a,e.b)}function I7(n,e,t){++n.j,n.tj(),t$(n,e,t)}function IAn(n,e,t){++n.j,n.qj(e,n.Zi(e,t))}function OAn(n,e,t){var i;i=n.fd(e),i.Rb(t)}function hV(n,e,t){return t=So(n,e,6,t),t}function lV(n,e,t){return t=So(n,e,3,t),t}function aV(n,e,t){return t=So(n,e,9,t),t}function ch(n,e){return X7(e,xtn),n.f=e,n}function dV(n,e){return(e&et)%n.d.length}function DAn(n,e,t){return zen(n.c,n.b,e,t)}function LAn(n,e){this.c=n,S0.call(this,e)}function NAn(n,e){this.a=n,kyn.call(this,e)}function O7(n,e){this.a=n,kyn.call(this,e)}function Dt(n,e){lt.call(this,n),this.a=e}function bV(n,e){FG.call(this,n),this.a=e}function DL(n,e){FG.call(this,n),this.a=e}function jae(n){VY.call(this,0,0),this.f=n}function $An(n,e,t){return n.a+=hh(e,0,t),n}function D7(n){return!n.a&&(n.a=new C0n),n.a}function wV(n,e){var t;return t=n.e,n.e=e,t}function gV(n,e){var t;return t=e,!!n.Fe(t)}function Eae(n,e){return _n(),n==e?0:n?1:-1}function Rb(n,e){n.a.bd(n.b,e),++n.b,n.c=-1}function L7(n){n.b?L7(n.b):n.f.c.zc(n.e,n.d)}function xAn(n){Hu(n.e),n.d.b=n.d,n.d.a=n.d}function Cae(n,e,t){Xa(),t9n(n,e.Ve(n.a,t))}function pV(n,e,t){return Pp(n,u(e,22),t)}function $s(n,e){return qE(new Array(e),n)}function Mae(n){return Ae(U1(n,32))^Ae(n)}function LL(n){return String.fromCharCode(n)}function Tae(n){return n==null?null:n.message}function Aae(n,e,t){return n.apply(e,t)}function Sae(n,e){var t;t=n[DB],t.call(n,e)}function Pae(n,e){var t;t=n[DB],t.call(n,e)}function Iae(n,e){return o7(),!Q4(e.d.i,n)}function mV(n,e,t,i){rM.call(this,n,e,t,i)}function FAn(){qC.call(this),this.a=new Li}function vV(){this.n=new Li,this.o=new Li}function BAn(){this.b=new Li,this.c=new Z}function RAn(){this.a=new Z,this.b=new Z}function KAn(){this.a=new _U,this.b=new Byn}function kV(){this.b=new Ql,this.a=new Ql}function _An(){this.b=new ni,this.a=new ni}function HAn(){this.b=new de,this.a=new de}function qAn(){this.b=new wEn,this.a=new H3n}function UAn(){this.a=new n8n,this.b=new Lpn}function GAn(){this.a=new Z,this.d=new Z}function qC(){this.n=new cp,this.i=new mp}function zAn(n){this.a=(Co(n,mw),new Gc(n))}function XAn(n){this.a=(Co(n,mw),new Gc(n))}function Oae(n){return n<100?null:new F1(n)}function Dae(n,e){return n.n.a=(Jn(e),e+10)}function Lae(n,e){return n.n.a=(Jn(e),e+10)}function Nae(n,e){return e==n||km(TA(e),n)}function VAn(n,e){return Xe(n.a,e,"")==null}function $ae(n,e){var t;return t=e.qi(n.a),t}function tt(n,e){return n.a+=e.a,n.b+=e.b,n}function mi(n,e){return n.a-=e.a,n.b-=e.b,n}function xae(n){return Pb(n.j.c,0),n.a=-1,n}function yV(n,e,t){return t=So(n,e,11,t),t}function Fae(n,e,t){t!=null&&mT(e,Fx(n,t))}function Bae(n,e,t){t!=null&&vT(e,Fx(n,t))}function jp(n,e,t,i){q.call(this,n,e,t,i)}function jV(n,e,t,i){q.call(this,n,e,t,i)}function WAn(n,e,t,i){jV.call(this,n,e,t,i)}function JAn(n,e,t,i){bM.call(this,n,e,t,i)}function NL(n,e,t,i){bM.call(this,n,e,t,i)}function EV(n,e,t,i){bM.call(this,n,e,t,i)}function QAn(n,e,t,i){NL.call(this,n,e,t,i)}function CV(n,e,t,i){NL.call(this,n,e,t,i)}function Nn(n,e,t,i){EV.call(this,n,e,t,i)}function YAn(n,e,t,i){CV.call(this,n,e,t,i)}function ZAn(n,e,t,i){jW.call(this,n,e,t,i)}function Kb(n,e){Ir.call(this,k8+n+Td+e)}function MV(n,e){return n.jk().wi().ri(n,e)}function TV(n,e){return n.jk().wi().ti(n,e)}function nSn(n,e){return Jn(n),x(n)===x(e)}function An(n,e){return Jn(n),x(n)===x(e)}function Rae(n,e){return n.b.Bd(new ECn(n,e))}function Kae(n,e){return n.b.Bd(new CCn(n,e))}function eSn(n,e){return n.b.Bd(new MCn(n,e))}function _ae(n,e){return n.e=u(n.d.Kb(e),159)}function AV(n,e,t){return n.lastIndexOf(e,t)}function Hae(n,e,t){return bt(n[e.a],n[t.a])}function qae(n,e){return U(e,(cn(),Cj),n)}function Uae(n,e){return jc(e.a.d.p,n.a.d.p)}function Gae(n,e){return jc(n.a.d.p,e.a.d.p)}function zae(n,e){return bt(n.c-n.s,e.c-e.s)}function Xae(n,e){return bt(n.b.e.a,e.b.e.a)}function Vae(n,e){return bt(n.c.e.a,e.c.e.a)}function tSn(n){return n.c?qr(n.c.a,n,0):-1}function Ep(n){return n==Ud||n==tl||n==qc}function SV(n,e){this.c=n,oN.call(this,n,e)}function iSn(n,e,t){this.a=n,JX.call(this,e,t)}function rSn(n){this.c=n,IC.call(this,Ey,0)}function cSn(n,e,t){this.c=e,this.b=t,this.a=n}function N7(n){k4(),this.d=n,this.a=new Eg}function uSn(n){uh(),this.a=(Dn(),new r4(n))}function Wae(n,e){hl(n.f)?QCe(n,e):Sye(n,e)}function oSn(n,e){sbe.call(this,n,n.length,e)}function Jae(n,e){qf||e&&(n.d=e)}function sSn(n,e){return O(e,15)&&xqn(n.c,e)}function Qae(n,e,t){return u(n.c,71).Wk(e,t)}function UC(n,e,t){return u(n.c,71).Xk(e,t)}function Yae(n,e,t){return oae(n,u(e,343),t)}function PV(n,e,t){return sae(n,u(e,343),t)}function Zae(n,e,t){return PKn(n,u(e,343),t)}function fSn(n,e,t){return _ye(n,u(e,343),t)}function x6(n,e){return e==null?null:tw(n.b,e)}function IV(n){return $b(n)?(Jn(n),n):n.ue()}function GC(n){return!isNaN(n)&&!isFinite(n)}function $L(n){jTn(this),vo(this),Bi(this,n)}function _u(n){pL(this),zV(this.c,0,n.Pc())}function _o(n,e,t){this.a=n,this.b=e,this.c=t}function hSn(n,e,t){this.a=n,this.b=e,this.c=t}function lSn(n,e,t){this.d=n,this.b=t,this.a=e}function aSn(n){this.a=n,fl(),vc(Date.now())}function dSn(n){bo(n.a),GJ(n.c,n.b),n.b=null}function xL(){xL=F,Oun=new $0n,AQn=new x0n}function bSn(){bSn=F,Ioe=K(ki,Fn,1,0,5,1)}function wSn(){wSn=F,Voe=K(ki,Fn,1,0,5,1)}function OV(){OV=F,Woe=K(ki,Fn,1,0,5,1)}function uh(){uh=F,new KG((Dn(),Dn(),sr))}function nde(n){return B4(),Ee((yNn(),IQn),n)}function ede(n){return Gu(),Ee((lNn(),xQn),n)}function tde(n){return YT(),Ee((JDn(),HQn),n)}function ide(n){return cT(),Ee((QDn(),qQn),n)}function rde(n){return NA(),Ee((Jxn(),UQn),n)}function cde(n){return bf(),Ee((fNn(),XQn),n)}function ude(n){return Uu(),Ee((sNn(),WQn),n)}function ode(n){return bu(),Ee((hNn(),QQn),n)}function sde(n){return VA(),Ee((zMn(),kYn),n)}function fde(n){return N0(),Ee((ENn(),jYn),n)}function hde(n){return Vp(),Ee((MNn(),CYn),n)}function lde(n){return A5(),Ee((CNn(),AYn),n)}function ade(n){return YE(),Ee((jDn(),SYn),n)}function dde(n){return uT(),Ee((YDn(),GYn),n)}function bde(n){return i5(),Ee((aNn(),pZn),n)}function wde(n){return Vi(),Ee((u$n(),yZn),n)}function gde(n){return nm(),Ee((ANn(),TZn),n)}function pde(n){return dd(),Ee((TNn(),DZn),n)}function DV(n,e){if(!n)throw M(new Gn(e))}function v4(n){if(!n)throw M(new Or(btn))}function FL(n,e){if(n!=e)throw M(new Bo)}function gSn(n,e,t){this.a=n,this.b=e,this.c=t}function LV(n,e,t){this.a=n,this.b=e,this.c=t}function pSn(n,e,t){this.a=n,this.b=e,this.c=t}function zC(n,e,t){this.b=n,this.a=e,this.c=t}function NV(n,e,t){this.b=n,this.c=e,this.a=t}function $V(n,e,t){this.a=n,this.b=e,this.c=t}function XC(n,e,t){this.e=e,this.b=n,this.d=t}function mSn(n,e,t){this.b=n,this.a=e,this.c=t}function mde(n,e,t){return Xa(),n.a.Yd(e,t),e}function BL(n){var e;return e=new ubn,e.e=n,e}function xV(n){var e;return e=new qyn,e.b=n,e}function $7(){$7=F,CP=new sgn,MP=new fgn}function VC(){VC=F,XZn=new xgn,zZn=new Fgn}function xs(){xs=F,YZn=new G2n,ZZn=new z2n}function vde(n){return D0(),Ee((qLn(),fne),n)}function kde(n){return tr(),Ee((XMn(),HZn),n)}function yde(n){return OT(),Ee((PNn(),GZn),n)}function jde(n){return $f(),Ee((SNn(),tne),n)}function Ede(n){return ow(),Ee((o$n(),rne),n)}function Cde(n){return DA(),Ee(($xn(),hne),n)}function Mde(n){return Yp(),Ee((D$n(),lne),n)}function Tde(n){return QM(),Ee((cLn(),ane),n)}function Ade(n){return u5(),Ee((_Ln(),dne),n)}function Sde(n){return bT(),Ee((HLn(),bne),n)}function Pde(n){return o1(),Ee((s$n(),wne),n)}function Ide(n){return pk(),Ee((eLn(),gne),n)}function Ode(n){return jm(),Ee(($$n(),jne),n)}function Dde(n){return pr(),Ee((aFn(),Ene),n)}function Lde(n){return Z4(),Ee((GLn(),Cne),n)}function Nde(n){return vl(),Ee((zLn(),Tne),n)}function $de(n){return KM(),Ee((nLn(),Ane),n)}function xde(n){return Jk(),Ee((N$n(),yne),n)}function Fde(n){return hd(),Ee((ULn(),mne),n)}function Bde(n){return vA(),Ee((L$n(),vne),n)}function Rde(n){return hk(),Ee((tLn(),kne),n)}function Kde(n){return Yo(),Ee((h$n(),Sne),n)}function _de(n){return a1(),Ee((Xxn(),Yte),n)}function Hde(n){return g5(),Ee((XLn(),Zte),n)}function qde(n){return cw(),Ee((INn(),nie),n)}function Ude(n){return T5(),Ee((f$n(),eie),n)}function Gde(n){return gs(),Ee((dFn(),tie),n)}function zde(n){return lh(),Ee((ONn(),iie),n)}function Xde(n){return wk(),Ee((iLn(),rie),n)}function Vde(n){return gr(),Ee((JLn(),uie),n)}function Wde(n){return ST(),Ee((VLn(),oie),n)}function Jde(n){return d5(),Ee((WLn(),sie),n)}function Qde(n){return om(),Ee((QLn(),fie),n)}function Yde(n){return dT(),Ee((YLn(),hie),n)}function Zde(n){return DT(),Ee((ZLn(),lie),n)}function n0e(n){return O0(),Ee((oNn(),Aie),n)}function e0e(n){return n5(),Ee((rLn(),Die),n)}function t0e(n){return sh(),Ee((sLn(),Rie),n)}function i0e(n){return Sf(),Ee((fLn(),_ie),n)}function r0e(n){return lf(),Ee((hLn(),tre),n)}function c0e(n){return M0(),Ee((lLn(),fre),n)}function u0e(n){return Qp(),Ee((BNn(),hre),n)}function o0e(n){return q5(),Ee((VMn(),lre),n)}function s0e(n){return b5(),Ee((nNn(),are),n)}function f0e(n){return w5(),Ee((FNn(),$re),n)}function h0e(n){return FM(),Ee((uLn(),xre),n)}function l0e(n){return yT(),Ee((oLn(),_re),n)}function a0e(n){return wA(),Ee((l$n(),qre),n)}function d0e(n){return Ok(),Ee((eNn(),Gre),n)}function b0e(n){return ZM(),Ee((aLn(),Ure),n)}function w0e(n){return sA(),Ee((xNn(),lce),n)}function g0e(n){return AT(),Ee((tNn(),ace),n)}function p0e(n){return XT(),Ee((iNn(),dce),n)}function m0e(n){return rA(),Ee((rNn(),wce),n)}function v0e(n){return _T(),Ee((cNn(),mce),n)}function k0e(n){return GM(),Ee((dLn(),Rce),n)}function y0e(n){return V4(),Ee((ZDn(),_Zn),n)}function j0e(n){return Vn(),Ee((x$n(),xZn),n)}function E0e(n){return nT(),Ee((uNn(),Kce),n)}function C0e(n){return N$(),Ee((bLn(),_ce),n)}function M0e(n){return R5(),Ee((a$n(),qce),n)}function T0e(n){return eC(),Ee((IDn(),Gce),n)}function A0e(n){return Fk(),Ee((bNn(),Uce),n)}function S0e(n){return tC(),Ee((ODn(),Xce),n)}function P0e(n){return ck(),Ee((wLn(),Vce),n)}function I0e(n){return Yk(),Ee((d$n(),Wce),n)}function O0e(n){return f6(),Ee((DDn(),lue),n)}function D0e(n){return Ak(),Ee((gLn(),aue),n)}function L0e(n){return gf(),Ee((w$n(),mue),n)}function N0e(n){return l1(),Ee((Lxn(),kue),n)}function $0e(n){return Rh(),Ee((F$n(),yue),n)}function x0e(n){return wd(),Ee((B$n(),Aue),n)}function F0e(n){return ci(),Ee((b$n(),zue),n)}function B0e(n){return Nf(),Ee((wNn(),Xue),n)}function R0e(n){return El(),Ee((RNn(),Vue),n)}function K0e(n){return pA(),Ee((R$n(),Wue),n)}function _0e(n){return jl(),Ee((dNn(),Que),n)}function H0e(n){return To(),Ee((KNn(),Zue),n)}function q0e(n){return lw(),Ee((Wxn(),noe),n)}function U0e(n){return Fg(),Ee((g$n(),eoe),n)}function G0e(n){return Oi(),Ee((K$n(),toe),n)}function z0e(n){return zu(),Ee((_$n(),ioe),n)}function X0e(n){return tn(),Ee((p$n(),roe),n)}function V0e(n){return go(),Ee((_Nn(),foe),n)}function W0e(n){return io(),Ee((Vxn(),hoe),n)}function J0e(n){return Gp(),Ee((gNn(),loe),n)}function Q0e(n,e){return Jn(n),n+(Jn(e),e)}function Y0e(n){return RL(),Ee((pLn(),aoe),n)}function Z0e(n){return qT(),Ee((HNn(),doe),n)}function nbe(n){return LT(),Ee((qNn(),goe),n)}function k4(){k4=F,tln=(tn(),Wn),II=Zn}function RL(){RL=F,vdn=new VSn,kdn=new LPn}function ebe(n){return!n.e&&(n.e=new Z),n.e}function KL(n,e){this.c=n,this.a=e,this.b=e-n}function vSn(n,e,t){this.a=n,this.b=e,this.c=t}function _L(n,e,t){this.a=n,this.b=e,this.c=t}function FV(n,e,t){this.a=n,this.b=e,this.c=t}function BV(n,e,t){this.a=n,this.b=e,this.c=t}function kSn(n,e,t){this.a=n,this.b=e,this.c=t}function ySn(n,e,t){this.a=n,this.b=e,this.c=t}function Xl(n,e,t){this.e=n,this.a=e,this.c=t}function jSn(n,e,t){Ko(),tJ.call(this,n,e,t)}function HL(n,e,t){Ko(),RW.call(this,n,e,t)}function RV(n,e,t){Ko(),RW.call(this,n,e,t)}function KV(n,e,t){Ko(),RW.call(this,n,e,t)}function ESn(n,e,t){Ko(),HL.call(this,n,e,t)}function _V(n,e,t){Ko(),HL.call(this,n,e,t)}function CSn(n,e,t){Ko(),_V.call(this,n,e,t)}function MSn(n,e,t){Ko(),RV.call(this,n,e,t)}function TSn(n,e,t){Ko(),KV.call(this,n,e,t)}function qL(n){rM.call(this,n.d,n.c,n.a,n.b)}function HV(n){rM.call(this,n.d,n.c,n.a,n.b)}function qV(n){this.d=n,c9n(this),this.b=nwe(n.d)}function tbe(n){return Cm(),Ee((Nxn(),Poe),n)}function x7(n,e){return Se(n),Se(e),new NEn(n,e)}function Cp(n,e){return Se(n),Se(e),new RSn(n,e)}function ibe(n,e){return Se(n),Se(e),new KSn(n,e)}function rbe(n,e){return Se(n),Se(e),new qEn(n,e)}function UL(n){return oe(n.b!=0),Xo(n,n.a.a)}function cbe(n){return oe(n.b!=0),Xo(n,n.c.b)}function ube(n){return!n.c&&(n.c=new W3),n.c}function y4(n){var e;return e=new Z,b$(e,n),e}function obe(n){var e;return e=new ni,b$(e,n),e}function ASn(n){var e;return e=new GG,A$(e,n),e}function F7(n){var e;return e=new Ct,A$(e,n),e}function u(n,e){return F6(n==null||Tx(n,e)),n}function sbe(n,e,t){TPn.call(this,e,t),this.a=n}function SSn(n,e){this.c=n,this.b=e,this.a=!1}function PSn(){this.a=";,;",this.b="",this.c=""}function ISn(n,e,t){this.b=n,_Mn.call(this,e,t)}function UV(n,e,t){this.c=n,oC.call(this,e,t)}function GV(n,e,t){d4.call(this,n,e),this.b=t}function zV(n,e,t){Bnn(t,0,n,e,t.length,!1)}function Lh(n,e,t,i,r){n.b=e,n.c=t,n.d=i,n.a=r}function XV(n,e,t,i,r){n.d=e,n.c=t,n.a=i,n.b=r}function fbe(n,e){e&&(n.b=e,n.a=(z1(e),e.a))}function B7(n,e){if(!n)throw M(new Gn(e))}function Mp(n,e){if(!n)throw M(new Or(e))}function VV(n,e){if(!n)throw M(new Bjn(e))}function hbe(n,e){return ZE(),jc(n.d.p,e.d.p)}function lbe(n,e){return kl(),bt(n.e.b,e.e.b)}function abe(n,e){return kl(),bt(n.e.a,e.e.a)}function dbe(n,e){return jc(GSn(n.d),GSn(e.d))}function WC(n,e){return e&&vM(n,e.d)?e:null}function bbe(n,e){return e==(tn(),Wn)?n.c:n.d}function WV(n){return Q1(dwe(Vr(n)?ds(n):n))}function wbe(n){return new V(n.c+n.b,n.d+n.a)}function OSn(n){return n!=null&&!lx(n,N9,$9)}function gbe(n,e){return(fBn(n)<<4|fBn(e))&ui}function DSn(n,e,t,i,r){n.c=e,n.d=t,n.b=i,n.a=r}function JV(n){var e,t;e=n.b,t=n.c,n.b=t,n.c=e}function QV(n){var e,t;t=n.d,e=n.a,n.d=e,n.a=t}function pbe(n,e){var t;return t=n.c,PQ(n,e),t}function YV(n,e){return e<0?n.g=-1:n.g=e,n}function JC(n,e){return Mme(n),n.a*=e,n.b*=e,n}function LSn(n,e,t){A$n.call(this,e,t),this.d=n}function R7(n,e,t){pX.call(this,n,e),this.c=t}function QC(n,e,t){pX.call(this,n,e),this.c=t}function ZV(n){OV(),ME.call(this),this.ci(n)}function NSn(){$4(),Bwe.call(this,(R1(),Ss))}function $Sn(n){return nt(),new Nh(0,n)}function xSn(){xSn=F,AU=(Dn(),new nD(IK))}function YC(){YC=F,new hZ((bD(),HK),(dD(),_K))}function FSn(){FSn=F,pun=K(Gi,J,17,256,0,1)}function BSn(){this.b=$(R(rn((qs(),y_))))}function GL(n){this.b=n,this.a=Wa(this.b.a).Od()}function RSn(n,e){this.b=n,this.a=e,GO.call(this)}function KSn(n,e){this.a=n,this.b=e,GO.call(this)}function _Sn(n,e,t){this.a=n,gg.call(this,e,t)}function HSn(n,e,t){this.a=n,gg.call(this,e,t)}function j4(n,e,t){var i;i=new qb(t),df(n,e,i)}function nW(n,e,t){var i;return i=n[e],n[e]=t,i}function ZC(n){var e;return e=n.slice(),o$(e,n)}function nM(n){var e;return e=n.n,n.a.b+e.d+e.a}function qSn(n){var e;return e=n.n,n.e.b+e.d+e.a}function eW(n){var e;return e=n.n,n.e.a+e.b+e.c}function tW(n){n.a.b=n.b,n.b.a=n.a,n.a=n.b=null}function xe(n,e){return xt(n,e,n.c.b,n.c),!0}function mbe(n){return n.a?n.a:vN(n)}function vbe(n){return Lp(),Kh(n)==At(ia(n))}function kbe(n){return Lp(),ia(n)==At(Kh(n))}function d0(n,e){return O5(n,new d4(e.a,e.b))}function ybe(n,e){return yM(),Nx(n,e),new lIn(n,e)}function jbe(n,e){return n.c=e)throw M(new YG)}function _b(n,e){return $k(n,(Jn(e),new a9n(e)))}function Ap(n,e){return $k(n,(Jn(e),new d9n(e)))}function SPn(n,e,t){return VLe(n,u(e,12),u(t,12))}function PPn(n){return Ou(),u(n,12).g.c.length!=0}function IPn(n){return Ou(),u(n,12).e.c.length!=0}function uwe(n,e){return Hp(),bt(e.a.o.a,n.a.o.a)}function owe(n,e){e.Bb&kc&&!n.a.o&&(n.a.o=e)}function swe(n,e){e.Ug("General 'Rotator",1),jDe(n)}function fwe(n,e,t){e.qf(t,$(R(ee(n.b,t)))*n.a)}function OPn(n,e,t){return Xg(),W4(n,e)&&W4(n,t)}function _6(n){return zu(),!n.Hc(Fl)&&!n.Hc(Pa)}function hwe(n){return n.e?qJ(n.e):null}function H6(n){return Vr(n)?""+n:$qn(n)}function yW(n){var e;for(e=n;e.f;)e=e.f;return e}function lwe(n,e,t){return $t(e,0,oW(e[0],t[0])),e}function Vl(n,e,t,i){var r;r=n.i,r.i=e,r.a=t,r.b=i}function q(n,e,t,i){ti.call(this,n,e,t),this.b=i}function Ci(n,e,t,i,r){c$.call(this,n,e,t,i,r,-1)}function q6(n,e,t,i,r){ok.call(this,n,e,t,i,r,-1)}function bM(n,e,t,i){R7.call(this,n,e,t),this.b=i}function DPn(n){PMn.call(this,n,!1),this.a=!1}function LPn(){sMn.call(this,"LOOKAHEAD_LAYOUT",1)}function NPn(n){this.b=n,kp.call(this,n),RTn(this)}function $Pn(n){this.b=n,A7.call(this,n),KTn(this)}function Hb(n,e,t){this.a=n,jp.call(this,e,t,5,6)}function jW(n,e,t,i){this.b=n,ti.call(this,e,t,i)}function xPn(n,e){this.b=n,H8n.call(this,n.b),this.a=e}function FPn(n){this.a=kRn(n.a),this.b=new _u(n.b)}function EW(n,e){m0(),Hhe.call(this,n,FT(new Ku(e)))}function wM(n,e){return nt(),new BW(n,e,0)}function rN(n,e){return nt(),new BW(6,n,e)}function _i(n,e){for(Jn(e);n.Ob();)e.Cd(n.Pb())}function Zc(n,e){return Ai(e)?AN(n,e):!!wr(n.f,e)}function cN(n,e){return e.Vh()?na(n.b,u(e,54)):e}function awe(n,e){return An(n.substr(0,e.length),e)}function $h(n){return new te(new UX(n.a.length,n.a))}function gM(n){return new V(n.c+n.b/2,n.d+n.a/2)}function dwe(n){return Yc(~n.l&ro,~n.m&ro,~n.h&Il)}function uN(n){return typeof n===vy||typeof n===eB}function Hu(n){n.f=new iTn(n),n.i=new rTn(n),++n.g}function BPn(n){if(!n)throw M(new nc);return n.d}function Sp(n){var e;return e=a5(n),oe(e!=null),e}function bwe(n){var e;return e=I5e(n),oe(e!=null),e}function C4(n,e){var t;return t=n.a.gc(),BJ(e,t),t-e}function fi(n,e){var t;return t=n.a.zc(e,n),t==null}function _7(n,e){return n.a.zc(e,(_n(),wa))==null}function CW(n){return new Tn(null,vwe(n,n.length))}function MW(n,e,t){return cGn(n,u(e,42),u(t,176))}function Pp(n,e,t){return Ks(n.a,e),nW(n.b,e.g,t)}function wwe(n,e,t){E4(t,n.a.c.length),Go(n.a,t,e)}function B(n,e,t,i){xFn(e,t,n.length),gwe(n,e,t,i)}function gwe(n,e,t,i){var r;for(r=e;r0?y.Math.log(n/e):-100}function KPn(n,e){return Ec(n,e)<0?-1:Ec(n,e)>0?1:0}function H7(n,e){OTn(n,O(e,160)?e:u(e,2036).Rl())}function PW(n,e){if(n==null)throw M(new sp(e))}function vwe(n,e){return yme(e,n.length),new XSn(n,e)}function IW(n,e){return e?Bi(n,e):!1}function kwe(){return RE(),S(T(uQn,1),G,549,0,[GK])}function G6(n){return n.e==0?n:new Qa(-n.e,n.d,n.a)}function ywe(n,e){return bt(n.c.c+n.c.b,e.c.c+e.c.b)}function q7(n,e){xt(n.d,e,n.b.b,n.b),++n.a,n.c=null}function _Pn(n,e){return n.c?_Pn(n.c,e):nn(n.b,e),n}function jwe(n,e,t){var i;return i=Jb(n,e),qN(n,e,t),i}function HPn(n,e,t){var i;for(i=0;i=n.g}function $t(n,e,t){return dae(t==null||oPe(n,t)),n[e]=t}function $W(n,e){return zn(e,n.length+1),n.substr(e)}function gN(n,e){for(Jn(e);n.c=n?new Dz:Gme(n-1)}function Hi(n){return!n.a&&n.c?n.c.b:n.a}function KW(n){return O(n,616)?n:new oOn(n)}function z1(n){n.c?z1(n.c):(ea(n),n.d=!0)}function V6(n){n.c?n.c.$e():(n.d=!0,fTe(n))}function sIn(n){n.b=!1,n.c=!1,n.d=!1,n.a=!1}function fIn(n){var e,t;return e=n.c.i.c,t=n.d.i.c,e==t}function _we(n,e){var t;t=n.Ih(e),t>=0?n.ki(t):Pnn(n,e)}function hIn(n,e){n.c<0||n.b.b0;)n=n<<1|(n<0?1:0);return n}function mIn(n,e){var t;return t=new Lc(n),Bn(e.c,t),t}function vIn(n,e){n.u.Hc((zu(),Fl))&&zEe(n,e),h4e(n,e)}function mc(n,e){return x(n)===x(e)||n!=null&&rt(n,e)}function Cr(n,e){return JL(n.a,e)?n.b[u(e,22).g]:null}function nge(){return YE(),S(T(oon,1),G,489,0,[b_])}function ege(){return eC(),S(T($1n,1),G,490,0,[Bq])}function tge(){return tC(),S(T(zce,1),G,558,0,[Rq])}function ige(){return f6(),S(T(tan,1),G,539,0,[Hj])}function jM(n){return!n.n&&(n.n=new q(Ar,n,1,7)),n.n}function mN(n){return!n.c&&(n.c=new q(Qu,n,9,9)),n.c}function UW(n){return!n.c&&(n.c=new Nn(he,n,5,8)),n.c}function rge(n){return!n.b&&(n.b=new Nn(he,n,4,7)),n.b}function U7(n){return n.j.c.length=0,zW(n.c),xae(n.a),n}function P4(n){return n.e==rv&&jfe(n,Y8e(n.g,n.b)),n.e}function G7(n){return n.f==rv&&Cfe(n,q7e(n.g,n.b)),n.f}function Ve(n,e,t,i){return Hxn(n,e,t,!1),BT(n,i),n}function kIn(n,e){this.b=n,oN.call(this,n,e),RTn(this)}function yIn(n,e){this.b=n,SV.call(this,n,e),KTn(this)}function W6(n){this.d=n,this.a=this.d.b,this.b=this.d.c}function GW(n,e){this.b=n,this.c=e,this.a=new dp(this.b)}function Xi(n,e){return zn(e,n.length),n.charCodeAt(e)}function cge(n,e){DY(n,$(yl(e,"x")),$(yl(e,"y")))}function uge(n,e){DY(n,$(yl(e,"x")),$(yl(e,"y")))}function ut(n,e){return ea(n),new Tn(n,new tQ(e,n.a))}function _r(n,e){return ea(n),new Tn(n,new _J(e,n.a))}function Ub(n,e){return ea(n),new uV(n,new ILn(e,n.a))}function EM(n,e){return ea(n),new oV(n,new OLn(e,n.a))}function oge(n,e){return new GIn(u(Se(n),50),u(Se(e),50))}function sge(n,e){return bt(n.d.c+n.d.b/2,e.d.c+e.d.b/2)}function jIn(n,e,t){t.a?tu(n,e.b-n.f/2):eu(n,e.a-n.g/2)}function fge(n,e){return bt(n.g.c+n.g.b/2,e.g.c+e.g.b/2)}function hge(n,e){return $z(),bt((Jn(n),n),(Jn(e),e))}function lge(n){return n!=null&&r7(jO,n.toLowerCase())}function zW(n){var e;for(e=n.Kc();e.Ob();)e.Pb(),e.Qb()}function Tg(n){var e;return e=n.b,!e&&(n.b=e=new N8n(n)),e}function vN(n){var e;return e=Wme(n),e||null}function EIn(n,e){var t,i;return t=n/e,i=wi(t),t>i&&++i,i}function age(n,e,t){var i;i=u(n.d.Kb(t),159),i&&i.Nb(e)}function dge(n,e,t){wIe(n.a,t),zve(t),xCe(n.b,t),$Ie(e,t)}function CM(n,e,t,i){this.a=n,this.c=e,this.b=t,this.d=i}function XW(n,e,t,i){this.c=n,this.b=e,this.a=t,this.d=i}function CIn(n,e,t,i){this.c=n,this.b=e,this.d=t,this.a=i}function Ho(n,e,t,i){this.c=n,this.d=e,this.b=t,this.a=i}function MIn(n,e,t,i){this.a=n,this.d=e,this.c=t,this.b=i}function kN(n,e,t,i){this.a=n,this.e=e,this.d=t,this.c=i}function TIn(n,e,t,i){this.a=n,this.c=e,this.d=t,this.b=i}function yN(n,e,t){this.a=ktn,this.d=n,this.b=e,this.c=t}function Op(n,e,t,i){je.call(this,n,e),this.a=t,this.b=i}function AIn(n,e){this.d=(Jn(n),n),this.a=16449,this.c=e}function SIn(n){this.a=new Z,this.e=K(ye,J,53,n,0,2)}function bge(n){n.Ug("No crossing minimization",1),n.Vg()}function PIn(){ec.call(this,"There is no more element.")}function IIn(n,e,t,i){this.a=n,this.b=e,this.c=t,this.d=i}function OIn(n,e,t,i){this.a=n,this.b=e,this.c=t,this.d=i}function Za(n,e,t,i){this.e=n,this.a=e,this.c=t,this.d=i}function DIn(n,e,t,i){this.a=n,this.c=e,this.d=t,this.b=i}function LIn(n,e,t,i){Ko(),DLn.call(this,e,t,i),this.a=n}function NIn(n,e,t,i){Ko(),DLn.call(this,e,t,i),this.a=n}function jN(n,e,t){var i,r;return i=utn(n),r=e.ti(t,i),r}function al(n){var e,t;return t=(e=new Jd,e),K4(t,n),t}function EN(n){var e,t;return t=(e=new Jd,e),fnn(t,n),t}function wge(n,e){var t;return t=ee(n.f,e),HQ(e,t),null}function $In(n){return!n.b&&(n.b=new q(Vt,n,12,3)),n.b}function xIn(n){return F6(n==null||uN(n)&&n.Tm!==J2),n}function MM(n){return n.n&&(n.e!==Fzn&&n.je(),n.j=null),n}function I4(n){if(eo(n.d),n.d.d!=n.c)throw M(new Bo)}function VW(n){return oe(n.b0&&bKn(this)}function FIn(n,e){this.a=n,bae.call(this,n,u(n.d,15).fd(e))}function gge(n,e){return bt(Su(n)*ao(n),Su(e)*ao(e))}function pge(n,e){return bt(Su(n)*ao(n),Su(e)*ao(e))}function mge(n){return _0(n)&&on(un(z(n,(cn(),Nd))))}function vge(n,e){return Pn(n,u(v(e,(cn(),Cv)),17),e)}function kge(n,e){return u(v(n,(W(),T3)),15).Fc(e),e}function WW(n,e){return n.b=e.b,n.c=e.c,n.d=e.d,n.a=e.a,n}function BIn(n,e,t,i){this.b=n,this.c=i,IC.call(this,e,t)}function yge(n,e,t){n.i=0,n.e=0,e!=t&&yFn(n,e,t)}function jge(n,e,t){n.i=0,n.e=0,e!=t&&jFn(n,e,t)}function Ege(n,e,t){return s6(),J5e(u(ee(n.e,e),529),t)}function Dp(n){var e;return e=n.f,e||(n.f=new h4(n,n.c))}function RIn(n,e){return xg(n.j,e.s,e.c)+xg(e.e,n.s,n.c)}function KIn(n,e){n.e&&!n.e.a&&(Ayn(n.e,e),KIn(n.e,e))}function _In(n,e){n.d&&!n.d.a&&(Ayn(n.d,e),_In(n.d,e))}function Cge(n,e){return-bt(Su(n)*ao(n),Su(e)*ao(e))}function Mge(n){return u(n.ld(),149).Pg()+":"+Jr(n.md())}function HIn(){tF(this,new oG),this.wb=(G1(),Hn),o4()}function qIn(n){this.b=new Z,hi(this.b,this.b),this.a=n}function JW(n,e){new Ct,this.a=new Mu,this.b=n,this.c=e}function j0(){j0=F,Pun=new FU,ZK=new FU,Iun=new D0n}function Dn(){Dn=F,sr=new A0n,Wh=new P0n,hP=new I0n}function QW(){QW=F,RQn=new nbn,_Qn=new aW,KQn=new ebn}function Lp(){Lp=F,mP=new Z,m_=new de,p_=new Z}function TM(n,e){if(n==null)throw M(new sp(e));return n}function AM(n){return!n.a&&(n.a=new q(Qe,n,10,11)),n.a}function ft(n){return!n.q&&(n.q=new q(As,n,11,10)),n.q}function _(n){return!n.s&&(n.s=new q(ku,n,21,17)),n.s}function Tge(n){return Se(n),IRn(new te(re(n.a.Kc(),new En)))}function Age(n,e){return wo(n),wo(e),Fjn(u(n,22),u(e,22))}function nd(n,e,t){var i,r;i=IV(t),r=new AE(i),df(n,e,r)}function MN(n,e,t,i,r,c){ok.call(this,n,e,t,i,r,c?-2:-1)}function UIn(n,e,t,i){pX.call(this,e,t),this.b=n,this.a=i}function GIn(n,e){Vfe.call(this,new iN(n)),this.a=n,this.b=e}function YW(n){this.b=n,this.c=n,n.e=null,n.c=null,this.a=1}function Sge(n){xs();var e;e=u(n.g,10),e.n.a=n.d.c+e.d.b}function O4(){O4=F;var n,e;e=!$8e(),n=new V3,VK=e?new og:n}function TN(n){return Dn(),O(n,59)?new jD(n):new BC(n)}function SM(n){return O(n,16)?new B6(u(n,16)):obe(n.Kc())}function Pge(n){return new HTn(n,n.e.Rd().gc()*n.c.Rd().gc())}function Ige(n){return new qTn(n,n.e.Rd().gc()*n.c.Rd().gc())}function ZW(n){return n&&n.hashCode?n.hashCode():l0(n)}function AN(n,e){return e==null?!!wr(n.f,null):zbe(n.i,e)}function Oge(n,e){var t;return t=$X(n.a,e),t&&(e.d=null),t}function zIn(n,e,t){return n.f?n.f.ef(e,t):!1}function z7(n,e,t,i){$t(n.c[e.g],t.g,i),$t(n.c[t.g],e.g,i)}function SN(n,e,t,i){$t(n.c[e.g],e.g,t),$t(n.b[e.g],e.g,i)}function Dge(n,e,t){return $(R(t.a))<=n&&$(R(t.b))>=e}function XIn(n,e){this.g=n,this.d=S(T(Qh,1),b1,10,0,[e])}function VIn(n){this.c=n,this.b=new Ul(u(Se(new tbn),50))}function WIn(n){this.c=n,this.b=new Ul(u(Se(new ewn),50))}function JIn(n){this.b=n,this.a=new Ul(u(Se(new Nbn),50))}function QIn(){this.b=new ni,this.d=new Ct,this.e=new ZG}function nJ(){this.c=new Li,this.d=new Li,this.e=new Li}function E0(){this.a=new Mu,this.b=(Co(3,mw),new Gc(3))}function Wl(n,e){this.e=n,this.a=ki,this.b=Qqn(e),this.c=e}function PM(n){this.c=n.c,this.d=n.d,this.b=n.b,this.a=n.a}function YIn(n,e,t,i,r,c){this.a=n,k$.call(this,e,t,i,r,c)}function ZIn(n,e,t,i,r,c){this.a=n,k$.call(this,e,t,i,r,c)}function X1(n,e,t,i,r,c,s){return new GN(n.e,e,t,i,r,c,s)}function Lge(n,e,t){return t>=0&&An(n.substr(t,e.length),e)}function nOn(n,e){return O(e,149)&&An(n.b,u(e,149).Pg())}function Nge(n,e){return n.a?e.Gh().Kc():u(e.Gh(),71).Ii()}function eOn(n,e){var t;return t=n.b.Qc(e),WDn(t,n.b.gc()),t}function X7(n,e){if(n==null)throw M(new sp(e));return n}function Hr(n){return n.u||(Zu(n),n.u=new NAn(n,n)),n.u}function PN(n){this.a=(Dn(),O(n,59)?new jD(n):new BC(n))}function au(n){var e;return e=u(Un(n,16),29),e||n.ii()}function IM(n,e){var t;return t=za(n.Rm),e==null?t:t+": "+e}function qo(n,e,t){return Fi(e,t,n.length),n.substr(e,t-e)}function tOn(n,e){qC.call(this),lQ(this),this.a=n,this.c=e}function $ge(n){n&&IM(n,n.ie())}function xge(n){HE(),y.setTimeout(function(){throw n},0)}function Fge(){return YT(),S(T(Bun,1),G,436,0,[o_,Fun])}function Bge(){return cT(),S(T(Kun,1),G,435,0,[Run,s_])}function Rge(){return uT(),S(T(bon,1),G,432,0,[v_,vP])}function Kge(){return V4(),S(T(KZn,1),G,517,0,[dj,L_])}function _ge(){return KM(),S(T(Qsn,1),G,429,0,[fH,Jsn])}function Hge(){return pk(),S(T($sn,1),G,428,0,[WP,Nsn])}function qge(){return QM(),S(T(Asn,1),G,431,0,[Tsn,V_])}function Uge(){return wk(),S(T(qhn,1),G,430,0,[UH,GH])}function Gge(){return n5(),S(T(Oie,1),G,531,0,[r9,i9])}function zge(){return yT(),S(T(Rln,1),G,501,0,[RI,D2])}function Xge(){return sh(),S(T(Bie,1),G,523,0,[mb,y1])}function Vge(){return Sf(),S(T(Kie,1),G,522,0,[Rd,zf])}function Wge(){return lf(),S(T(ere,1),G,528,0,[zw,ja])}function Jge(){return hk(),S(T(Bsn,1),G,488,0,[Fsn,QP])}function Qge(){return GM(),S(T(S1n,1),G,491,0,[$q,A1n])}function Yge(){return N$(),S(T(N1n,1),G,492,0,[D1n,L1n])}function Zge(){return FM(),S(T(Bln,1),G,433,0,[dq,Fln])}function n2e(){return ZM(),S(T(_ln,1),G,434,0,[Kln,vq])}function e2e(){return M0(),S(T(sre,1),G,465,0,[Ea,P2])}function t2e(){return ck(),S(T(x1n,1),G,438,0,[Kq,JI])}function i2e(){return Ak(),S(T(ran,1),G,437,0,[YI,ian])}function r2e(){return RL(),S(T(dO,1),G,347,0,[vdn,kdn])}function OM(n,e,t,i){return t>=0?n.Uh(e,t,i):n.Ch(null,t,i)}function V7(n){return n.b.b==0?n.a.sf():UL(n.b)}function c2e(n){if(n.p!=5)throw M(new Cu);return Ae(n.f)}function u2e(n){if(n.p!=5)throw M(new Cu);return Ae(n.k)}function eJ(n){return x(n.a)===x((D$(),CU))&&rOe(n),n.a}function o2e(n,e){n.b=e,n.c>0&&n.b>0&&(n.g=cM(n.c,n.b,n.a))}function s2e(n,e){n.c=e,n.c>0&&n.b>0&&(n.g=cM(n.c,n.b,n.a))}function iOn(n,e){ufe(this,new V(n.a,n.b)),ofe(this,F7(e))}function C0(){Wfe.call(this,new ap(Qb(12))),KX(!0),this.a=2}function IN(n,e,t){nt(),Wd.call(this,n),this.b=e,this.a=t}function tJ(n,e,t){Ko(),LE.call(this,e),this.a=n,this.b=t}function rOn(n){var e;e=n.c.d.b,n.b=e,n.a=n.c.d,e.a=n.c.d.b=n}function f2e(n){return n.b==0?null:(oe(n.b!=0),Xo(n,n.a.a))}function Nc(n,e){return e==null?Kr(wr(n.f,null)):d6(n.i,e)}function cOn(n,e,t,i,r){return new rF(n,(B4(),i_),e,t,i,r)}function DM(n,e){return zDn(e),Lme(n,K(ye,Ke,28,e,15,1),e)}function LM(n,e){return TM(n,"set1"),TM(e,"set2"),new VEn(n,e)}function h2e(n,e){var t=XK[n.charCodeAt(0)];return t??n}function uOn(n,e){var t,i;return t=e,i=new DO,LGn(n,t,i),i.d}function ON(n,e,t,i){var r;r=new FAn,e.a[t.g]=r,Pp(n.b,i,r)}function l2e(n,e){var t;return t=Ime(n.f,e),tt(HC(t),n.f.d)}function W7(n){var e;_me(n.a),dTn(n.a),e=new IE(n.a),HY(e)}function a2e(n,e){_qn(n,!0),nu(n.e.Rf(),new NV(n,!0,e))}function d2e(n,e){return Lp(),n==At(Kh(e))||n==At(ia(e))}function b2e(n,e){return kl(),u(v(e,(lc(),Sh)),17).a==n}function wi(n){return Math.max(Math.min(n,et),-2147483648)|0}function oOn(n){this.a=u(Se(n),277),this.b=(Dn(),new XX(n))}function sOn(n,e,t){this.i=new Z,this.b=n,this.g=e,this.a=t}function iJ(n,e,t){this.a=new Z,this.e=n,this.f=e,this.c=t}function NM(n,e,t){this.c=new Z,this.e=n,this.f=e,this.b=t}function fOn(n){qC.call(this),lQ(this),this.a=n,this.c=!0}function w2e(n){function e(){}return e.prototype=n||{},new e}function g2e(n){if(n.Ae())return null;var e=n.n;return rP[e]}function J7(n){return n.Db>>16!=3?null:u(n.Cb,27)}function Af(n){return n.Db>>16!=9?null:u(n.Cb,27)}function hOn(n){return n.Db>>16!=6?null:u(n.Cb,74)}function M0(){M0=F,Ea=new cX(s3,0),P2=new cX(f3,1)}function sh(){sh=F,mb=new tX(f3,0),y1=new tX(s3,1)}function Sf(){Sf=F,Rd=new iX(_B,0),zf=new iX("UP",1)}function lOn(){lOn=F,oQn=Ce((RE(),S(T(uQn,1),G,549,0,[GK])))}function aOn(n){var e;return e=new zE(Qb(n.length)),eY(e,n),e}function dOn(n,e){return n.b+=e.b,n.c+=e.c,n.d+=e.d,n.a+=e.a,n}function p2e(n,e){return Zxn(n,e)?(W$n(n),!0):!1}function dl(n,e){if(e==null)throw M(new ip);return F8e(n,e)}function Q7(n,e){var t;t=n.q.getHours(),n.q.setDate(e),G5(n,t)}function rJ(n,e,t){var i;i=n.Ih(e),i>=0?n.bi(i,t):ten(n,e,t)}function bOn(n,e){var t;return t=n.Ih(e),t>=0?n.Wh(t):hF(n,e)}function wOn(n,e){var t;for(Se(e),t=n.a;t;t=t.c)e.Yd(t.g,t.i)}function DN(n,e,t){var i;i=vFn(n,e,t),n.b=new ET(i.c.length)}function Ag(n,e,t){$M(),n&&Xe(yU,n,e),n&&Xe(hE,n,t)}function m2e(n,e){return VC(),_n(),u(e.a,17).a0}function cJ(n){var e;return e=n.d,e=n.bj(n.f),ve(n,e),e.Ob()}function gOn(n,e){var t;return t=new fW(e),_Kn(t,n),new _u(t)}function y2e(n){if(n.p!=0)throw M(new Cu);return M6(n.f,0)}function j2e(n){if(n.p!=0)throw M(new Cu);return M6(n.k,0)}function pOn(n){return n.Db>>16!=7?null:u(n.Cb,241)}function D4(n){return n.Db>>16!=6?null:u(n.Cb,241)}function mOn(n){return n.Db>>16!=7?null:u(n.Cb,167)}function At(n){return n.Db>>16!=11?null:u(n.Cb,27)}function Gb(n){return n.Db>>16!=17?null:u(n.Cb,29)}function vOn(n){return n.Db>>16!=3?null:u(n.Cb,155)}function uJ(n){var e;return ea(n),e=new ni,ut(n,new M9n(e))}function kOn(n,e){var t=n.a=n.a||[];return t[e]||(t[e]=n.ve(e))}function E2e(n,e){var t;t=n.q.getHours(),n.q.setMonth(e),G5(n,t)}function yOn(n,e){xC(this),this.f=e,this.g=n,MM(this),this.je()}function jOn(n,e){this.a=n,this.c=Ki(this.a),this.b=new PM(e)}function EOn(n,e,t){this.a=e,this.c=n,this.b=(Se(t),new _u(t))}function COn(n,e,t){this.a=e,this.c=n,this.b=(Se(t),new _u(t))}function MOn(n){this.a=n,this.b=K(Sie,J,2043,n.e.length,0,2)}function TOn(){this.a=new ih,this.e=new ni,this.g=0,this.i=0}function $M(){$M=F,yU=new de,hE=new de,ple(MQn,new wvn)}function AOn(){AOn=F,aie=Pu(new ii,(Vi(),zr),(tr(),bj))}function oJ(){oJ=F,die=Pu(new ii,(Vi(),zr),(tr(),bj))}function SOn(){SOn=F,wie=Pu(new ii,(Vi(),zr),(tr(),bj))}function POn(){POn=F,Lie=Re(new ii,(Vi(),zr),(tr(),x8))}function ko(){ko=F,xie=Re(new ii,(Vi(),zr),(tr(),x8))}function IOn(){IOn=F,Fie=Re(new ii,(Vi(),zr),(tr(),x8))}function NN(){NN=F,Hie=Re(new ii,(Vi(),zr),(tr(),x8))}function J6(n,e,t,i,r,c){return new ml(n.e,e,n.Lj(),t,i,r,c)}function Dr(n,e,t){return e==null?Vc(n.f,null,t):$0(n.i,e,t)}function Zi(n,e){n.c&&du(n.c.g,n),n.c=e,n.c&&nn(n.c.g,n)}function $i(n,e){n.c&&du(n.c.a,n),n.c=e,n.c&&nn(n.c.a,n)}function ic(n,e){n.i&&du(n.i.j,n),n.i=e,n.i&&nn(n.i.j,n)}function Ii(n,e){n.d&&du(n.d.e,n),n.d=e,n.d&&nn(n.d.e,n)}function $N(n,e){n.a&&du(n.a.k,n),n.a=e,n.a&&nn(n.a.k,n)}function xN(n,e){n.b&&du(n.b.f,n),n.b=e,n.b&&nn(n.b.f,n)}function OOn(n,e){$we(n,n.b,n.c),u(n.b.b,68),e&&u(e.b,68).b}function C2e(n,e){return bt(u(n.c,65).c.e.b,u(e.c,65).c.e.b)}function M2e(n,e){return bt(u(n.c,65).c.e.a,u(e.c,65).c.e.a)}function T2e(n){return Y$(),_n(),u(n.a,86).d.e!=0}function xM(n,e){O(n.Cb,184)&&(u(n.Cb,184).tb=null),zc(n,e)}function FN(n,e){O(n.Cb,90)&&hw(Zu(u(n.Cb,90)),4),zc(n,e)}function A2e(n,e){LY(n,e),O(n.Cb,90)&&hw(Zu(u(n.Cb,90)),2)}function S2e(n,e){var t,i;t=e.c,i=t!=null,i&&Ip(n,new qb(e.c))}function DOn(n){var e,t;return t=(o4(),e=new Jd,e),K4(t,n),t}function LOn(n){var e,t;return t=(o4(),e=new Jd,e),K4(t,n),t}function NOn(n){for(var e;;)if(e=n.Pb(),!n.Ob())return e}function P2e(n,e,t){return nn(n.a,(yM(),Nx(e,t),new i0(e,t))),n}function $c(n,e){return dr(),a$(e)?new eM(e,n):new j7(e,n)}function Y7(n){return dh(),Ec(n,0)>=0?ta(n):G6(ta(n1(n)))}function I2e(n){var e;return e=u(ZC(n.b),9),new _o(n.a,e,n.c)}function $On(n,e){var t;return t=u(tw(Dp(n.a),e),16),t?t.gc():0}function xOn(n,e,t){var i;oBn(e,t,n.c.length),i=t-e,Pz(n.c,e,i)}function Jl(n,e,t){oBn(e,t,n.gc()),this.c=n,this.a=e,this.b=t-e}function Np(n){this.c=new Ct,this.b=n.b,this.d=n.c,this.a=n.a}function BN(n){this.a=y.Math.cos(n),this.b=y.Math.sin(n)}function ed(n,e,t,i){this.c=n,this.d=i,$N(this,e),xN(this,t)}function sJ(n,e){Xfe.call(this,new ap(Qb(n))),Co(e,Ozn),this.a=e}function FOn(n,e,t){return new rF(n,(B4(),t_),null,!1,e,t)}function BOn(n,e,t){return new rF(n,(B4(),r_),e,t,null,!1)}function O2e(){return Gu(),S(T(xr,1),G,108,0,[xun,Yr,Aw])}function D2e(){return bu(),S(T(JQn,1),G,472,0,[vf,pa,zs])}function L2e(){return Uu(),S(T(VQn,1),G,471,0,[Mh,ga,Gs])}function N2e(){return bf(),S(T(Sw,1),G,237,0,[bc,Wc,wc])}function $2e(){return i5(),S(T(Pon,1),G,391,0,[E_,j_,C_])}function x2e(){return D0(),S(T(R_,1),G,372,0,[ub,ma,cb])}function F2e(){return u5(),S(T(Psn,1),G,322,0,[B8,pj,Ssn])}function B2e(){return bT(),S(T(Osn,1),G,351,0,[Isn,VP,W_])}function R2e(){return hd(),S(T(pne,1),G,460,0,[Y_,mv,p2])}function K2e(){return Z4(),S(T(sH,1),G,299,0,[uH,oH,mj])}function _2e(){return vl(),S(T(Mne,1),G,311,0,[vj,v2,E3])}function H2e(){return g5(),S(T(Lhn,1),G,390,0,[FH,Dhn,MI])}function q2e(){return gr(),S(T(cie,1),G,463,0,[n9,Vu,Jc])}function U2e(){return ST(),S(T(zhn,1),G,387,0,[Uhn,zH,Ghn])}function G2e(){return d5(),S(T(Xhn,1),G,349,0,[VH,XH,Ij])}function z2e(){return om(),S(T(Whn,1),G,350,0,[WH,Vhn,e9])}function X2e(){return dT(),S(T(Yhn,1),G,352,0,[Qhn,JH,Jhn])}function V2e(){return DT(),S(T(Zhn,1),G,388,0,[QH,Ov,Gw])}function W2e(){return O0(),S(T(Tie,1),G,464,0,[Oj,t9,PI])}function Pf(n){return cc(S(T(Ei,1),J,8,0,[n.i.n,n.n,n.a]))}function J2e(){return b5(),S(T(gln,1),G,392,0,[wln,nq,Lj])}function ROn(){ROn=F,Fre=Pu(new ii,(Qp(),u9),(q5(),uln))}function FM(){FM=F,dq=new uX("DFS",0),Fln=new uX("BFS",1)}function KOn(n,e,t){var i;i=new E3n,i.b=e,i.a=t,++e.b,nn(n.d,i)}function Q2e(n,e,t){var i;i=new rr(t.d),tt(i,n),DY(e,i.a,i.b)}function Y2e(n,e){LTn(n,Ae(vi(w0(e,24),YA)),Ae(vi(e,YA)))}function zb(n,e){if(n<0||n>e)throw M(new Ir(Ptn+n+Itn+e))}function Ln(n,e){if(n<0||n>=e)throw M(new Ir(Ptn+n+Itn+e))}function zn(n,e){if(n<0||n>=e)throw M(new gz(Ptn+n+Itn+e))}function In(n,e){this.b=(Jn(n),n),this.a=e&vw?e:e|64|wh}function fJ(n){var e;return ea(n),e=(j0(),j0(),ZK),fT(n,e)}function Z2e(n,e,t){var i;return i=V5(n,e,!1),i.b<=e&&i.a<=t}function npe(){return nT(),S(T(O1n,1),G,439,0,[xq,I1n,P1n])}function epe(){return _T(),S(T(a1n,1),G,394,0,[l1n,Oq,h1n])}function tpe(){return XT(),S(T(f1n,1),G,445,0,[Bj,qI,Mq])}function ipe(){return rA(),S(T(bce,1),G,456,0,[Tq,Sq,Aq])}function rpe(){return Ok(),S(T(Uln,1),G,393,0,[KI,Hln,qln])}function cpe(){return AT(),S(T(s1n,1),G,300,0,[Cq,o1n,u1n])}function upe(){return jl(),S(T(ldn,1),G,346,0,[uO,M1,M9])}function ope(){return Fk(),S(T(Fq,1),G,444,0,[XI,VI,WI])}function spe(){return Nf(),S(T(Zan,1),G,278,0,[Bv,Jw,Rv])}function fpe(){return Gp(),S(T(mdn,1),G,280,0,[pdn,Yw,aO])}function T0(n){return Se(n),O(n,16)?new _u(u(n,16)):y4(n.Kc())}function hJ(n,e){return n&&n.equals?n.equals(e):x(n)===x(e)}function vi(n,e){return Q1(ewe(Vr(n)?ds(n):n,Vr(e)?ds(e):e))}function hf(n,e){return Q1(twe(Vr(n)?ds(n):n,Vr(e)?ds(e):e))}function RN(n,e){return Q1(iwe(Vr(n)?ds(n):n,Vr(e)?ds(e):e))}function hpe(n,e){var t;return t=(Jn(n),n).g,rV(!!t),Jn(e),t(e)}function _On(n,e){var t,i;return i=C4(n,e),t=n.a.fd(i),new zEn(n,t)}function lpe(n){return n.Db>>16!=6?null:u(dF(n),241)}function ape(n){if(n.p!=2)throw M(new Cu);return Ae(n.f)&ui}function dpe(n){if(n.p!=2)throw M(new Cu);return Ae(n.k)&ui}function E(n){return oe(n.ai?1:0}function GOn(n,e){var t,i;return t=s$(e),i=t,u(ee(n.c,i),17).a}function KN(n,e,t){var i;i=n.d[e.p],n.d[e.p]=n.d[t.p],n.d[t.p]=i}function Cpe(n,e,t){var i;n.n&&e&&t&&(i=new uvn,nn(n.e,i))}function _N(n,e){if(fi(n.a,e),e.d)throw M(new ec(nXn));e.d=n}function dJ(n,e){this.a=new Z,this.d=new Z,this.f=n,this.c=e}function zOn(){this.c=new PTn,this.a=new $Ln,this.b=new Xyn,lCn()}function XOn(){qp(),this.b=new de,this.a=new de,this.c=new Z}function VOn(n,e,t){this.d=n,this.j=e,this.e=t,this.o=-1,this.p=3}function WOn(n,e,t){this.d=n,this.k=e,this.f=t,this.o=-1,this.p=5}function JOn(n,e,t,i,r,c){dQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function QOn(n,e,t,i,r,c){bQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function YOn(n,e,t,i,r,c){OJ.call(this,n,e,t,i,r),c&&(this.o=-2)}function ZOn(n,e,t,i,r,c){pQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function nDn(n,e,t,i,r,c){DJ.call(this,n,e,t,i,r),c&&(this.o=-2)}function eDn(n,e,t,i,r,c){wQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function tDn(n,e,t,i,r,c){gQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function iDn(n,e,t,i,r,c){LJ.call(this,n,e,t,i,r),c&&(this.o=-2)}function rDn(n,e,t,i){LE.call(this,t),this.b=n,this.c=e,this.d=i}function cDn(n,e){this.f=n,this.a=($4(),MO),this.c=MO,this.b=e}function uDn(n,e){this.g=n,this.d=($4(),TO),this.a=TO,this.b=e}function bJ(n,e){!n.c&&(n.c=new Rt(n,0)),HA(n.c,(at(),F9),e)}function Mpe(n,e){return oMe(n,e,O(e,102)&&(u(e,19).Bb&hr)!=0)}function Tpe(n,e){return KPn(vc(n.q.getTime()),vc(e.q.getTime()))}function oDn(n){return XL(n.e.Rd().gc()*n.c.Rd().gc(),16,new O8n(n))}function Ape(n){return!!n.u&&Sc(n.u.a).i!=0&&!(n.n&&Ix(n.n))}function Spe(n){return!!n.a&&no(n.a.a).i!=0&&!(n.b&&Ox(n.b))}function wJ(n,e){return e==0?!!n.o&&n.o.f!=0:Cx(n,e)}function Ppe(n,e,t){var i;return i=u(n.Zb().xc(e),16),!!i&&i.Hc(t)}function sDn(n,e,t){var i;return i=u(n.Zb().xc(e),16),!!i&&i.Mc(t)}function fDn(n,e){var t;return t=1-e,n.a[t]=jT(n.a[t],t),jT(n,e)}function hDn(n,e){var t,i;return i=vi(n,mr),t=Fs(e,32),hf(t,i)}function lDn(n,e,t){var i;i=(Se(n),new _u(n)),O7e(new EOn(i,e,t))}function Z7(n,e,t){var i;i=(Se(n),new _u(n)),D7e(new COn(i,e,t))}function fc(n,e,t,i,r,c){return Hxn(n,e,t,c),CY(n,i),MY(n,r),n}function aDn(n,e,t,i){return n.a+=""+qo(e==null?gu:Jr(e),t,i),n}function xi(n,e){this.a=n,Xv.call(this,n),zb(e,n.gc()),this.b=e}function dDn(n){this.a=K(ki,Fn,1,QQ(y.Math.max(8,n))<<1,5,1)}function nk(n){return u(xf(n,K(Qh,b1,10,n.c.length,0,1)),199)}function fh(n){return u(xf(n,K(O_,rR,18,n.c.length,0,1)),483)}function bDn(n){return n.a?n.e.length==0?n.a.a:n.a.a+(""+n.e):n.c}function Q6(n){for(;n.d>0&&n.a[--n.d]==0;);n.a[n.d++]==0&&(n.e=0)}function wDn(n){return oe(n.b.b!=n.d.a),n.c=n.b=n.b.b,--n.a,n.c.c}function Ipe(n,e,t){n.a=e,n.c=t,n.b.a.$b(),vo(n.d),Pb(n.e.a.c,0)}function gDn(n,e){var t;n.e=new uz,t=aw(e),Yt(t,n.c),Iqn(n,t,0)}function ri(n,e,t,i){var r;r=new nG,r.a=e,r.b=t,r.c=i,xe(n.a,r)}function Q(n,e,t,i){var r;r=new nG,r.a=e,r.b=t,r.c=i,xe(n.b,r)}function pDn(n,e,t){if(n<0||et)throw M(new Ir(qje(n,e,t)))}function ek(n,e){if(n<0||n>=e)throw M(new Ir(kEe(n,e)));return n}function Ope(n){if(!("stack"in n))try{throw n}catch{}return n}function Sg(n){return s6(),O(n.g,10)?u(n.g,10):null}function Dpe(n){return Tg(n).dc()?!1:(e1e(n,new Pr),!0)}function id(n){var e;return Vr(n)?(e=n,e==-0?0:e):X4e(n)}function mDn(n,e){return O(e,44)?xx(n.a,u(e,44)):!1}function vDn(n,e){return O(e,44)?xx(n.a,u(e,44)):!1}function kDn(n,e){return O(e,44)?xx(n.a,u(e,44)):!1}function gJ(n){var e;return z1(n),e=new L0n,hg(n.a,new j9n(e)),e}function pJ(){var n,e,t;return e=(t=(n=new Jd,n),t),nn(n0n,e),e}function BM(n){var e;return z1(n),e=new N0n,hg(n.a,new E9n(e)),e}function Lpe(n,e){return n.a<=n.b?(e.Dd(n.a++),!0):!1}function yDn(n){P$.call(this,n,(B4(),e_),null,!1,null,!1)}function jDn(){jDn=F,SYn=Ce((YE(),S(T(oon,1),G,489,0,[b_])))}function EDn(){EDn=F,eln=wIn(Y(1),Y(4)),nln=wIn(Y(1),Y(2))}function Npe(n,e){return new _L(e,N6(Ki(e.e),n,n),(_n(),!0))}function RM(n){return new Gc((Co(n,cB),oT(nr(nr(5,n),n/10|0))))}function $pe(n){return XL(n.e.Rd().gc()*n.c.Rd().gc(),273,new I8n(n))}function CDn(n){return u(xf(n,K(FZn,DXn,12,n.c.length,0,1)),2042)}function xpe(n){return ko(),!fr(n)&&!(!fr(n)&&n.c.i.c==n.d.i.c)}function Fpe(n,e){return _p(),u(v(e,(lc(),I2)),17).a>=n.gc()}function Y6(n,e){vLe(e,n),JV(n.d),JV(u(v(n,(cn(),mI)),214))}function HN(n,e){kLe(e,n),QV(n.d),QV(u(v(n,(cn(),mI)),214))}function Bpe(n,e,t){n.d&&du(n.d.e,n),n.d=e,n.d&&b0(n.d.e,t,n)}function Rpe(n,e,t){return t.f.c.length>0?MW(n.a,e,t):MW(n.b,e,t)}function Kpe(n,e,t){var i;i=i9e();try{return Aae(n,e,t)}finally{D3e(i)}}function A0(n,e){var t,i;return t=dl(n,e),i=null,t&&(i=t.pe()),i}function Z6(n,e){var t,i;return t=dl(n,e),i=null,t&&(i=t.se()),i}function L4(n,e){var t,i;return t=Jb(n,e),i=null,t&&(i=t.se()),i}function bl(n,e){var t,i;return t=dl(n,e),i=null,t&&(i=gnn(t)),i}function _pe(n,e,t){var i;return i=wm(t),FA(n.g,i,e),FA(n.i,e,t),e}function mJ(n,e,t){this.d=new $7n(this),this.e=n,this.i=e,this.f=t}function MDn(n,e,t,i){this.e=null,this.c=n,this.d=e,this.a=t,this.b=i}function TDn(n,e,t,i){ETn(this),this.c=n,this.e=e,this.f=t,this.b=i}function vJ(n,e,t,i){this.d=n,this.n=e,this.g=t,this.o=i,this.p=-1}function ADn(n,e,t,i){return O(t,59)?new iAn(n,e,t,i):new vW(n,e,t,i)}function N4(n){return O(n,16)?u(n,16).dc():!n.Kc().Ob()}function SDn(n){if(n.e.g!=n.b)throw M(new Bo);return!!n.c&&n.d>0}function be(n){return oe(n.b!=n.d.c),n.c=n.b,n.b=n.b.a,++n.a,n.c.c}function kJ(n,e){Jn(e),$t(n.a,n.c,e),n.c=n.c+1&n.a.length-1,JRn(n)}function V1(n,e){Jn(e),n.b=n.b-1&n.a.length-1,$t(n.a,n.b,e),JRn(n)}function PDn(n){var e;e=n.Gh(),this.a=O(e,71)?u(e,71).Ii():e.Kc()}function Hpe(n){return new In(Ame(u(n.a.md(),16).gc(),n.a.ld()),16)}function IDn(){IDn=F,Gce=Ce((eC(),S(T($1n,1),G,490,0,[Bq])))}function ODn(){ODn=F,Xce=Ce((tC(),S(T(zce,1),G,558,0,[Rq])))}function DDn(){DDn=F,lue=Ce((f6(),S(T(tan,1),G,539,0,[Hj])))}function qpe(){return dd(),S(T(Lon,1),G,389,0,[Ow,Don,P_,I_])}function Upe(){return B4(),S(T(lP,1),G,304,0,[e_,t_,i_,r_])}function Gpe(){return Vp(),S(T(EYn,1),G,332,0,[uj,cj,oj,sj])}function zpe(){return A5(),S(T(TYn,1),G,406,0,[fj,wP,gP,hj])}function Xpe(){return N0(),S(T(yYn,1),G,417,0,[rj,ij,a_,d_])}function Vpe(){return nm(),S(T(MZn,1),G,416,0,[rb,Iw,Pw,a2])}function Wpe(){return $f(),S(T(ene,1),G,421,0,[j3,lv,av,B_])}function Jpe(){return OT(),S(T(UZn,1),G,371,0,[F_,HP,qP,wj])}function Qpe(){return cw(),S(T(RH,1),G,203,0,[TI,BH,S2,A2])}function Ype(){return lh(),S(T(Hhn,1),G,284,0,[k1,_hn,HH,qH])}function Zpe(n){var e;return n.j==(tn(),ae)&&(e=mHn(n),Au(e,Zn))}function n3e(n,e){var t;t=e.a,Zi(t,e.c.d),Ii(t,e.d.d),nw(t.a,n.n)}function yJ(n,e){var t;return t=u(Lf(n.b,e),67),!t&&(t=new Ct),t}function xp(n){return s6(),O(n.g,154)?u(n.g,154):null}function e3e(n){n.a=null,n.e=null,Pb(n.b.c,0),Pb(n.f.c,0),n.c=null}function KM(){KM=F,fH=new Zz(qm,0),Jsn=new Zz("TOP_LEFT",1)}function n5(){n5=F,r9=new eX("UPPER",0),i9=new eX("LOWER",1)}function t3e(n,e){return vp(new V(e.e.a+e.f.a/2,e.e.b+e.f.b/2),n)}function LDn(n,e){return u(ho(_b(u(ot(n.k,e),15).Oc(),b2)),113)}function NDn(n,e){return u(ho(Ap(u(ot(n.k,e),15).Oc(),b2)),113)}function i3e(){return Qp(),S(T(rln,1),G,405,0,[LI,c9,u9,o9])}function r3e(){return w5(),S(T(xln,1),G,353,0,[aq,BI,lq,hq])}function c3e(){return sA(),S(T(c1n,1),G,354,0,[Eq,i1n,r1n,t1n])}function u3e(){return go(),S(T(I9,1),G,386,0,[rE,Gd,iE,Qw])}function o3e(){return To(),S(T(Yue,1),G,291,0,[nE,nl,Ta,Zj])}function s3e(){return El(),S(T(aU,1),G,223,0,[lU,Yj,Kv,F3])}function f3e(){return qT(),S(T(Cdn,1),G,320,0,[wU,ydn,Edn,jdn])}function h3e(){return LT(),S(T(woe,1),G,415,0,[gU,Tdn,Mdn,Adn])}function l3e(n){return $M(),Zc(yU,n)?u(ee(yU,n),341).Qg():null}function Uo(n,e,t){return e<0?hF(n,t):u(t,69).wk().Bk(n,n.hi(),e)}function a3e(n,e,t){var i;return i=wm(t),FA(n.j,i,e),Xe(n.k,e,t),e}function d3e(n,e,t){var i;return i=wm(t),FA(n.d,i,e),Xe(n.e,e,t),e}function $Dn(n){var e,t;return e=(B1(),t=new HO,t),n&&AA(e,n),e}function jJ(n){var e;return e=n.aj(n.i),n.i>0&&Ic(n.g,0,e,0,n.i),e}function xDn(n,e){var t;for(t=n.j.c.length;t>24}function w3e(n){if(n.p!=1)throw M(new Cu);return Ae(n.k)<<24>>24}function g3e(n){if(n.p!=7)throw M(new Cu);return Ae(n.k)<<16>>16}function p3e(n){if(n.p!=7)throw M(new Cu);return Ae(n.f)<<16>>16}function Pg(n,e){return e.e==0||n.e==0?O8:(Am(),vF(n,e))}function RDn(n,e){return x(e)===x(n)?"(this Map)":e==null?gu:Jr(e)}function m3e(n,e,t){return tN(R(Kr(wr(n.f,e))),R(Kr(wr(n.f,t))))}function v3e(n,e,t){var i;i=u(ee(n.g,t),60),nn(n.a.c,new bi(e,i))}function KDn(n,e,t){n.i=0,n.e=0,e!=t&&(jFn(n,e,t),yFn(n,e,t))}function k3e(n,e,t,i,r){var c;c=yMe(r,t,i),nn(e,dEe(r,c)),rje(n,r,e)}function EJ(n,e,t,i,r){this.i=n,this.a=e,this.e=t,this.j=i,this.f=r}function _Dn(n,e){nJ.call(this),this.a=n,this.b=e,nn(this.a.b,this)}function HDn(n){this.b=new de,this.c=new de,this.d=new de,this.a=n}function qDn(n,e){var t;return t=new lp,n.Gd(t),t.a+="..",e.Hd(t),t.a}function UDn(n,e){var t;for(t=e;t;)a0(n,t.i,t.j),t=At(t);return n}function GDn(n,e,t){var i;return i=wm(t),Xe(n.b,i,e),Xe(n.c,e,t),e}function wl(n){var e;for(e=0;n.Ob();)n.Pb(),e=nr(e,1);return oT(e)}function Fh(n,e){dr();var t;return t=u(n,69).vk(),kje(t,e),t.xl(e)}function y3e(n,e,t){if(t){var i=t.oe();n.a[e]=i(t)}else delete n.a[e]}function CJ(n,e){var t;t=n.q.getHours(),n.q.setFullYear(e+fa),G5(n,t)}function j3e(n,e){return u(e==null?Kr(wr(n.f,null)):d6(n.i,e),288)}function MJ(n,e){return n==(Vn(),zt)&&e==zt?4:n==zt||e==zt?8:32}function _M(n,e,t){return RA(n,e,t,O(e,102)&&(u(e,19).Bb&hr)!=0)}function E3e(n,e,t){return Om(n,e,t,O(e,102)&&(u(e,19).Bb&hr)!=0)}function C3e(n,e,t){return bMe(n,e,t,O(e,102)&&(u(e,19).Bb&hr)!=0)}function TJ(n){n.b!=n.c&&(n.a=K(ki,Fn,1,8,5,1),n.b=0,n.c=0)}function e5(n){return oe(n.a=0&&n.a[t]===e[t];t--);return t<0}function HM(n){var e;return n?new fW(n):(e=new ih,A$(e,n),e)}function O3e(n,e){var t,i;i=!1;do t=lFn(n,e),i=i|t;while(t);return i}function D3e(n){n&&rme((az(),sun)),--cP,n&&uP!=-1&&(Ele(uP),uP=-1)}function qM(n){nnn(),LTn(this,Ae(vi(w0(n,24),YA)),Ae(vi(n,YA)))}function JDn(){JDn=F,HQn=Ce((YT(),S(T(Bun,1),G,436,0,[o_,Fun])))}function QDn(){QDn=F,qQn=Ce((cT(),S(T(Kun,1),G,435,0,[Run,s_])))}function YDn(){YDn=F,GYn=Ce((uT(),S(T(bon,1),G,432,0,[v_,vP])))}function ZDn(){ZDn=F,_Zn=Ce((V4(),S(T(KZn,1),G,517,0,[dj,L_])))}function nLn(){nLn=F,Ane=Ce((KM(),S(T(Qsn,1),G,429,0,[fH,Jsn])))}function eLn(){eLn=F,gne=Ce((pk(),S(T($sn,1),G,428,0,[WP,Nsn])))}function tLn(){tLn=F,kne=Ce((hk(),S(T(Bsn,1),G,488,0,[Fsn,QP])))}function iLn(){iLn=F,rie=Ce((wk(),S(T(qhn,1),G,430,0,[UH,GH])))}function rLn(){rLn=F,Die=Ce((n5(),S(T(Oie,1),G,531,0,[r9,i9])))}function cLn(){cLn=F,ane=Ce((QM(),S(T(Asn,1),G,431,0,[Tsn,V_])))}function uLn(){uLn=F,xre=Ce((FM(),S(T(Bln,1),G,433,0,[dq,Fln])))}function oLn(){oLn=F,_re=Ce((yT(),S(T(Rln,1),G,501,0,[RI,D2])))}function sLn(){sLn=F,Rie=Ce((sh(),S(T(Bie,1),G,523,0,[mb,y1])))}function fLn(){fLn=F,_ie=Ce((Sf(),S(T(Kie,1),G,522,0,[Rd,zf])))}function hLn(){hLn=F,tre=Ce((lf(),S(T(ere,1),G,528,0,[zw,ja])))}function lLn(){lLn=F,fre=Ce((M0(),S(T(sre,1),G,465,0,[Ea,P2])))}function aLn(){aLn=F,Ure=Ce((ZM(),S(T(_ln,1),G,434,0,[Kln,vq])))}function dLn(){dLn=F,Rce=Ce((GM(),S(T(S1n,1),G,491,0,[$q,A1n])))}function bLn(){bLn=F,_ce=Ce((N$(),S(T(N1n,1),G,492,0,[D1n,L1n])))}function wLn(){wLn=F,Vce=Ce((ck(),S(T(x1n,1),G,438,0,[Kq,JI])))}function gLn(){gLn=F,aue=Ce((Ak(),S(T(ran,1),G,437,0,[YI,ian])))}function pLn(){pLn=F,aoe=Ce((RL(),S(T(dO,1),G,347,0,[vdn,kdn])))}function L3e(){return ci(),S(T(E9,1),G,88,0,[Wf,Xr,Br,Vf,us])}function N3e(){return tn(),S(T(lr,1),Mc,64,0,[sc,Xn,Zn,ae,Wn])}function $3e(n,e,t){return u(e==null?Vc(n.f,null,t):$0(n.i,e,t),288)}function x3e(n){return(n.k==(Vn(),zt)||n.k==Zt)&&kt(n,(W(),H8))}function XN(n){return n.c&&n.d?aJ(n.c)+"->"+aJ(n.d):"e_"+l0(n)}function qi(n,e){var t,i;for(Jn(e),i=n.Kc();i.Ob();)t=i.Pb(),e.Cd(t)}function F3e(n,e){var t;t=new op,nd(t,"x",e.a),nd(t,"y",e.b),Ip(n,t)}function B3e(n,e){var t;t=new op,nd(t,"x",e.a),nd(t,"y",e.b),Ip(n,t)}function mLn(n,e){var t;for(t=e;t;)a0(n,-t.i,-t.j),t=At(t);return n}function SJ(n,e){var t,i;for(t=e,i=0;t>0;)i+=n.a[t],t-=t&-t;return i}function Go(n,e,t){var i;return i=(Ln(e,n.c.length),n.c[e]),n.c[e]=t,i}function PJ(n,e,t){n.a.c.length=0,fOe(n,e,t),n.a.c.length==0||xSe(n,e)}function tk(n){n.i=0,s7(n.b,null),s7(n.c,null),n.a=null,n.e=null,++n.g}function UM(){UM=F,qf=!0,DQn=!1,LQn=!1,$Qn=!1,NQn=!1}function VN(n){UM(),!qf&&(this.c=n,this.e=!0,this.a=new Z)}function vLn(n,e){this.c=0,this.b=e,HMn.call(this,n,17493),this.a=this.c}function kLn(n){jzn(),Syn(this),this.a=new Ct,sY(this,n),xe(this.a,n)}function yLn(){pL(this),this.b=new V(St,St),this.a=new V(li,li)}function GM(){GM=F,$q=new fX(cin,0),A1n=new fX("TARGET_WIDTH",1)}function Ig(n,e){return(ea(n),s4(new Tn(n,new tQ(e,n.a)))).Bd(v3)}function R3e(){return Vi(),S(T(Ion,1),G,367,0,[Xs,Jh,Oc,Kc,zr])}function K3e(){return ow(),S(T(ine,1),G,375,0,[gj,zP,XP,GP,UP])}function _3e(){return o1(),S(T(Lsn,1),G,348,0,[J_,Dsn,Q_,pv,gv])}function H3e(){return T5(),S(T($hn,1),G,323,0,[Nhn,KH,_H,Y8,Z8])}function q3e(){return Yo(),S(T(hfn,1),G,171,0,[Ej,U8,ka,G8,xw])}function U3e(){return wA(),S(T(Hre,1),G,368,0,[pq,bq,mq,wq,gq])}function G3e(){return R5(),S(T(Hce,1),G,373,0,[L2,D3,g9,w9,_j])}function z3e(){return Yk(),S(T(K1n,1),G,324,0,[F1n,_q,R1n,Hq,B1n])}function X3e(){return gf(),S(T(Zh,1),G,170,0,[xn,pi,Ph,Kd,E1])}function V3e(){return Fg(),S(T(A9,1),G,256,0,[Aa,eE,adn,T9,ddn])}function W3e(n){return HE(),function(){return Kpe(n,this,arguments)}}function fr(n){return!n.c||!n.d?!1:!!n.c.i&&n.c.i==n.d.i}function IJ(n,e){return O(e,143)?An(n.c,u(e,143).c):!1}function Zu(n){return n.t||(n.t=new myn(n),k5(new Njn(n),0,n.t)),n.t}function jLn(n){this.b=n,ne.call(this,n),this.a=u(Un(this.b.a,4),129)}function ELn(n){this.b=n,yp.call(this,n),this.a=u(Un(this.b.a,4),129)}function Bs(n,e,t,i,r){LLn.call(this,e,i,r),this.c=n,this.b=t}function OJ(n,e,t,i,r){VOn.call(this,e,i,r),this.c=n,this.a=t}function DJ(n,e,t,i,r){WOn.call(this,e,i,r),this.c=n,this.a=t}function LJ(n,e,t,i,r){LLn.call(this,e,i,r),this.c=n,this.a=t}function WN(n,e){var t;return t=u(Lf(n.d,e),23),t||u(Lf(n.e,e),23)}function CLn(n,e){var t,i;return t=e.ld(),i=n.Fe(t),!!i&&mc(i.e,e.md())}function MLn(n,e){var t;return t=e.ld(),new i0(t,n.e.pc(t,u(e.md(),16)))}function J3e(n,e){var t;return t=n.a.get(e),t??K(ki,Fn,1,0,5,1)}function TLn(n){var e;return e=n.length,An(Yn.substr(Yn.length-e,e),n)}function fe(n){if(pe(n))return n.c=n.a,n.a.Pb();throw M(new nc)}function NJ(n,e){return e==0||n.e==0?n:e>0?wqn(n,e):RBn(n,-e)}function Fp(n,e){return e==0||n.e==0?n:e>0?RBn(n,e):wqn(n,-e)}function $J(n){ole.call(this,n==null?gu:Jr(n),O(n,82)?u(n,82):null)}function ALn(n){var e;return n.c||(e=n.r,O(e,90)&&(n.c=u(e,29))),n.c}function JN(n){var e;return e=new E0,Ur(e,n),U(e,(cn(),Fr),null),e}function SLn(n){var e,t;return e=n.c.i,t=n.d.i,e.k==(Vn(),Zt)&&t.k==Zt}function QN(n){var e,t,i;return e=n&ro,t=n>>22&ro,i=n<0?Il:0,Yc(e,t,i)}function Q3e(n){var e,t,i,r;for(t=n,i=0,r=t.length;i=0?n.Lh(i,t,!0):H0(n,e,t)}function Z3e(n,e,t){return bt(vp(pm(n),Ki(e.b)),vp(pm(n),Ki(t.b)))}function n4e(n,e,t){return bt(vp(pm(n),Ki(e.e)),vp(pm(n),Ki(t.e)))}function e4e(n,e){return y.Math.min(W1(e.a,n.d.d.c),W1(e.b,n.d.d.c))}function ik(n,e){n._i(n.i+1),O6(n,n.i,n.Zi(n.i,e)),n.Mi(n.i++,e),n.Ni()}function t5(n){var e,t;++n.j,e=n.g,t=n.i,n.g=null,n.i=0,n.Oi(t,e),n.Ni()}function PLn(n,e,t){var i;i=new NX(n.a),f5(i,n.a.a),Vc(i.f,e,t),n.a.a=i}function xJ(n,e,t,i){var r;for(r=0;re)throw M(new Ir(Mnn(n,e,"index")));return n}function Yl(n,e){var t;return t=(Ln(e,n.c.length),n.c[e]),Pz(n.c,e,1),t}function RJ(n,e){var t,i;return t=(Jn(n),n),i=(Jn(e),e),t==i?0:te.p?-1:0}function FLn(n){var e;return n.a||(e=n.r,O(e,156)&&(n.a=u(e,156))),n.a}function o4e(n,e,t){var i;return++n.e,--n.f,i=u(n.d[e].gd(t),136),i.md()}function s4e(n){var e,t;return e=n.ld(),t=u(n.md(),16),x7(t.Nc(),new L8n(e))}function BLn(n,e){return Zc(n.a,e)?(Bp(n.a,e),!0):!1}function Rp(n,e,t){return ek(e,n.e.Rd().gc()),ek(t,n.c.Rd().gc()),n.a[e][t]}function XM(n,e,t){this.a=n,this.b=e,this.c=t,nn(n.t,this),nn(e.i,this)}function VM(n,e,t,i){this.f=n,this.e=e,this.d=t,this.b=i,this.c=i?i.d:null}function rk(){this.b=new Ct,this.a=new Ct,this.b=new Ct,this.a=new Ct}function $4(){$4=F;var n,e;MO=(o4(),e=new xE,e),TO=(n=new fD,n)}function f4e(n){var e;return ea(n),e=new ISn(n,n.a.e,n.a.d|4),new uV(n,e)}function RLn(n){var e;for(z1(n),e=0;n.a.Bd(new W0n);)e=nr(e,1);return e}function WM(n,e){return Jn(e),n.c=0,"Initial capacity must not be negative")}function JM(){JM=F,p9=new lt("org.eclipse.elk.labels.labelManager")}function KLn(){KLn=F,ysn=new Dt("separateLayerConnections",(OT(),F_))}function lf(){lf=F,zw=new rX("REGULAR",0),ja=new rX("CRITICAL",1)}function ck(){ck=F,Kq=new lX("FIXED",0),JI=new lX("CENTER_NODE",1)}function QM(){QM=F,Tsn=new Jz("QUADRATIC",0),V_=new Jz("SCANLINE",1)}function _Ln(){_Ln=F,dne=Ce((u5(),S(T(Psn,1),G,322,0,[B8,pj,Ssn])))}function HLn(){HLn=F,bne=Ce((bT(),S(T(Osn,1),G,351,0,[Isn,VP,W_])))}function qLn(){qLn=F,fne=Ce((D0(),S(T(R_,1),G,372,0,[ub,ma,cb])))}function ULn(){ULn=F,mne=Ce((hd(),S(T(pne,1),G,460,0,[Y_,mv,p2])))}function GLn(){GLn=F,Cne=Ce((Z4(),S(T(sH,1),G,299,0,[uH,oH,mj])))}function zLn(){zLn=F,Tne=Ce((vl(),S(T(Mne,1),G,311,0,[vj,v2,E3])))}function XLn(){XLn=F,Zte=Ce((g5(),S(T(Lhn,1),G,390,0,[FH,Dhn,MI])))}function VLn(){VLn=F,oie=Ce((ST(),S(T(zhn,1),G,387,0,[Uhn,zH,Ghn])))}function WLn(){WLn=F,sie=Ce((d5(),S(T(Xhn,1),G,349,0,[VH,XH,Ij])))}function JLn(){JLn=F,uie=Ce((gr(),S(T(cie,1),G,463,0,[n9,Vu,Jc])))}function QLn(){QLn=F,fie=Ce((om(),S(T(Whn,1),G,350,0,[WH,Vhn,e9])))}function YLn(){YLn=F,hie=Ce((dT(),S(T(Yhn,1),G,352,0,[Qhn,JH,Jhn])))}function ZLn(){ZLn=F,lie=Ce((DT(),S(T(Zhn,1),G,388,0,[QH,Ov,Gw])))}function nNn(){nNn=F,are=Ce((b5(),S(T(gln,1),G,392,0,[wln,nq,Lj])))}function eNn(){eNn=F,Gre=Ce((Ok(),S(T(Uln,1),G,393,0,[KI,Hln,qln])))}function tNn(){tNn=F,ace=Ce((AT(),S(T(s1n,1),G,300,0,[Cq,o1n,u1n])))}function iNn(){iNn=F,dce=Ce((XT(),S(T(f1n,1),G,445,0,[Bj,qI,Mq])))}function rNn(){rNn=F,wce=Ce((rA(),S(T(bce,1),G,456,0,[Tq,Sq,Aq])))}function cNn(){cNn=F,mce=Ce((_T(),S(T(a1n,1),G,394,0,[l1n,Oq,h1n])))}function uNn(){uNn=F,Kce=Ce((nT(),S(T(O1n,1),G,439,0,[xq,I1n,P1n])))}function oNn(){oNn=F,Aie=Ce((O0(),S(T(Tie,1),G,464,0,[Oj,t9,PI])))}function sNn(){sNn=F,WQn=Ce((Uu(),S(T(VQn,1),G,471,0,[Mh,ga,Gs])))}function fNn(){fNn=F,XQn=Ce((bf(),S(T(Sw,1),G,237,0,[bc,Wc,wc])))}function hNn(){hNn=F,QQn=Ce((bu(),S(T(JQn,1),G,472,0,[vf,pa,zs])))}function lNn(){lNn=F,xQn=Ce((Gu(),S(T(xr,1),G,108,0,[xun,Yr,Aw])))}function aNn(){aNn=F,pZn=Ce((i5(),S(T(Pon,1),G,391,0,[E_,j_,C_])))}function dNn(){dNn=F,Que=Ce((jl(),S(T(ldn,1),G,346,0,[uO,M1,M9])))}function bNn(){bNn=F,Uce=Ce((Fk(),S(T(Fq,1),G,444,0,[XI,VI,WI])))}function wNn(){wNn=F,Xue=Ce((Nf(),S(T(Zan,1),G,278,0,[Bv,Jw,Rv])))}function gNn(){gNn=F,loe=Ce((Gp(),S(T(mdn,1),G,280,0,[pdn,Yw,aO])))}function Df(n,e){return!n.o&&(n.o=new Iu((Cc(),il),T1,n,0)),wx(n.o,e)}function h4e(n,e){var t;n.C&&(t=u(Cr(n.b,e),127).n,t.d=n.C.d,t.a=n.C.a)}function UJ(n){var e,t,i,r;r=n.d,e=n.a,t=n.b,i=n.c,n.d=t,n.a=i,n.b=r,n.c=e}function l4e(n){return!n.g&&(n.g=new CE),!n.g.b&&(n.g.b=new byn(n)),n.g.b}function uk(n){return!n.g&&(n.g=new CE),!n.g.c&&(n.g.c=new pyn(n)),n.g.c}function a4e(n){return!n.g&&(n.g=new CE),!n.g.d&&(n.g.d=new wyn(n)),n.g.d}function d4e(n){return!n.g&&(n.g=new CE),!n.g.a&&(n.g.a=new gyn(n)),n.g.a}function b4e(n,e,t,i){return t&&(i=t.Rh(e,Ot(t.Dh(),n.c.uk()),null,i)),i}function w4e(n,e,t,i){return t&&(i=t.Th(e,Ot(t.Dh(),n.c.uk()),null,i)),i}function e$(n,e,t,i){var r;return r=K(ye,Ke,28,e+1,15,1),vPe(r,n,e,t,i),r}function K(n,e,t,i,r,c){var s;return s=_Rn(r,i),r!=10&&S(T(n,c),e,t,r,s),s}function g4e(n,e,t){var i,r;for(r=new Y4(e,n),i=0;it||e=0?n.Lh(t,!0,!0):H0(n,e,!0)}function L4e(n,e,t){var i;return i=vFn(n,e,t),n.b=new ET(i.c.length),den(n,i)}function N4e(n){if(n.b<=0)throw M(new nc);return--n.b,n.a-=n.c.c,Y(n.a)}function $4e(n){var e;if(!n.a)throw M(new PIn);return e=n.a,n.a=At(n.a),e}function x4e(n){for(;!n.a;)if(!eSn(n.c,new C9n(n)))return!1;return!0}function Kp(n){var e;return Se(n),O(n,204)?(e=u(n,204),e):new _8n(n)}function F4e(n){YM(),u(n.of((qe(),Ww)),181).Fc((zu(),tE)),n.qf(sU,null)}function YM(){YM=F,wue=new Emn,pue=new Cmn,gue=M6e((qe(),sU),wue,Ma,pue)}function ZM(){ZM=F,Kln=new sX("LEAF_NUMBER",0),vq=new sX("NODE_SIZE",1)}function u$(n){n.a=K(ye,Ke,28,n.b+1,15,1),n.c=K(ye,Ke,28,n.b,15,1),n.d=0}function B4e(n,e){n.a.Ne(e.d,n.b)>0&&(nn(n.c,new GV(e.c,e.d,n.d)),n.b=e.d)}function nQ(n,e){if(n.g==null||e>=n.i)throw M(new aL(e,n.i));return n.g[e]}function kNn(n,e,t){if(rm(n,t),t!=null&&!n.fk(t))throw M(new uD);return t}function o$(n,e){return gk(e)!=10&&S(wo(e),e.Sm,e.__elementTypeId$,gk(e),n),n}function F4(n,e,t,i){var r;i=(j0(),i||Pun),r=n.slice(e,t),Tnn(r,n,e,t,-e,i)}function zo(n,e,t,i,r){return e<0?H0(n,t,i):u(t,69).wk().yk(n,n.hi(),e,i,r)}function R4e(n,e){return bt($(R(v(n,(W(),fb)))),$(R(v(e,fb))))}function yNn(){yNn=F,IQn=Ce((B4(),S(T(lP,1),G,304,0,[e_,t_,i_,r_])))}function B4(){B4=F,e_=new uC("All",0),t_=new lTn,i_=new kTn,r_=new hTn}function Uu(){Uu=F,Mh=new FD(s3,0),ga=new FD(qm,1),Gs=new FD(f3,2)}function jNn(){jNn=F,KA(),s0n=St,mse=li,f0n=new V9(St),vse=new V9(li)}function ENn(){ENn=F,jYn=Ce((N0(),S(T(yYn,1),G,417,0,[rj,ij,a_,d_])))}function CNn(){CNn=F,AYn=Ce((A5(),S(T(TYn,1),G,406,0,[fj,wP,gP,hj])))}function MNn(){MNn=F,CYn=Ce((Vp(),S(T(EYn,1),G,332,0,[uj,cj,oj,sj])))}function TNn(){TNn=F,DZn=Ce((dd(),S(T(Lon,1),G,389,0,[Ow,Don,P_,I_])))}function ANn(){ANn=F,TZn=Ce((nm(),S(T(MZn,1),G,416,0,[rb,Iw,Pw,a2])))}function SNn(){SNn=F,tne=Ce(($f(),S(T(ene,1),G,421,0,[j3,lv,av,B_])))}function PNn(){PNn=F,GZn=Ce((OT(),S(T(UZn,1),G,371,0,[F_,HP,qP,wj])))}function INn(){INn=F,nie=Ce((cw(),S(T(RH,1),G,203,0,[TI,BH,S2,A2])))}function ONn(){ONn=F,iie=Ce((lh(),S(T(Hhn,1),G,284,0,[k1,_hn,HH,qH])))}function hk(){hk=F,Fsn=new Yz(kh,0),QP=new Yz("IMPROVE_STRAIGHTNESS",1)}function DNn(n,e){var t,i;return i=e/n.c.Rd().gc()|0,t=e%n.c.Rd().gc(),Rp(n,i,t)}function LNn(n){var e;if(n.nl())for(e=n.i-1;e>=0;--e)L(n,e);return jJ(n)}function eQ(n){var e,t;if(!n.b)return null;for(t=n.b;e=t.a[0];)t=e;return t}function NNn(n){var e,t;if(!n.b)return null;for(t=n.b;e=t.a[1];)t=e;return t}function K4e(n){return O(n,180)?""+u(n,180).a:n==null?null:Jr(n)}function _4e(n){return O(n,180)?""+u(n,180).a:n==null?null:Jr(n)}function $Nn(n,e){if(e.a)throw M(new ec(nXn));fi(n.a,e),e.a=n,!n.j&&(n.j=e)}function tQ(n,e){IC.call(this,e.zd(),e.yd()&-16449),Jn(n),this.a=n,this.c=e}function H4e(n,e){return new _L(e,a0(Ki(e.e),e.f.a+n,e.f.b+n),(_n(),!1))}function q4e(n,e){return k4(),nn(n,new bi(e,Y(e.e.c.length+e.g.c.length)))}function U4e(n,e){return k4(),nn(n,new bi(e,Y(e.e.c.length+e.g.c.length)))}function xNn(){xNn=F,lce=Ce((sA(),S(T(c1n,1),G,354,0,[Eq,i1n,r1n,t1n])))}function FNn(){FNn=F,$re=Ce((w5(),S(T(xln,1),G,353,0,[aq,BI,lq,hq])))}function BNn(){BNn=F,hre=Ce((Qp(),S(T(rln,1),G,405,0,[LI,c9,u9,o9])))}function RNn(){RNn=F,Vue=Ce((El(),S(T(aU,1),G,223,0,[lU,Yj,Kv,F3])))}function KNn(){KNn=F,Zue=Ce((To(),S(T(Yue,1),G,291,0,[nE,nl,Ta,Zj])))}function _Nn(){_Nn=F,foe=Ce((go(),S(T(I9,1),G,386,0,[rE,Gd,iE,Qw])))}function HNn(){HNn=F,doe=Ce((qT(),S(T(Cdn,1),G,320,0,[wU,ydn,Edn,jdn])))}function qNn(){qNn=F,goe=Ce((LT(),S(T(woe,1),G,415,0,[gU,Tdn,Mdn,Adn])))}function nT(){nT=F,xq=new oL(mVn,0),I1n=new oL(Crn,1),P1n=new oL(kh,2)}function Wb(n,e,t,i,r){return Jn(n),Jn(e),Jn(t),Jn(i),Jn(r),new AW(n,e,i)}function UNn(n,e){var t;return t=u(Bp(n.e,e),400),t?(tW(t),t.e):null}function du(n,e){var t;return t=qr(n,e,0),t==-1?!1:(Yl(n,t),!0)}function GNn(n,e,t){var i;return z1(n),i=new LO,i.a=e,n.a.Nb(new TCn(i,t)),i.a}function G4e(n){var e;return z1(n),e=K(Pi,Tr,28,0,15,1),hg(n.a,new y9n(e)),e}function iQ(n){var e;if(!E$(n))throw M(new nc);return n.e=1,e=n.d,n.d=null,e}function n1(n){var e;return Vr(n)&&(e=0-n,!isNaN(e))?e:Q1(tm(n))}function qr(n,e,t){for(;t=0?tA(n,t,!0,!0):H0(n,e,!0)}function cQ(n){var e;return e=cd(Un(n,32)),e==null&&(iu(n),e=cd(Un(n,32))),e}function uQ(n){var e;return n.Oh()||(e=se(n.Dh())-n.ji(),n.$h().Mk(e)),n.zh()}function QNn(n,e){con=new kE,MYn=e,L8=n,u(L8.b,68),XJ(L8,con,null),aGn(L8)}function i5(){i5=F,E_=new RD("XY",0),j_=new RD("X",1),C_=new RD("Y",2)}function bu(){bu=F,vf=new BD("TOP",0),pa=new BD(qm,1),zs=new BD(Ftn,2)}function vl(){vl=F,vj=new GD(kh,0),v2=new GD("TOP",1),E3=new GD(Ftn,2)}function wk(){wk=F,UH=new nX("INPUT_ORDER",0),GH=new nX("PORT_DEGREE",1)}function R4(){R4=F,hun=Yc(ro,ro,524287),bQn=Yc(0,0,Ty),lun=QN(1),QN(2),aun=QN(0)}function a$(n){var e;return n.d!=n.r&&(e=ws(n),n.e=!!e&&e.lk()==bJn,n.d=e),n.e}function d$(n,e,t){var i;return i=n.g[e],O6(n,e,n.Zi(e,t)),n.Ri(e,t,i),n.Ni(),i}function rT(n,e){var t;return t=n.dd(e),t>=0?(n.gd(t),!0):!1}function b$(n,e){var t;for(Se(n),Se(e),t=!1;e.Ob();)t=t|n.Fc(e.Pb());return t}function Lf(n,e){var t;return t=u(ee(n.e,e),400),t?(DTn(n,t),t.e):null}function YNn(n){var e,t;return e=n/60|0,t=n%60,t==0?""+e:""+e+":"+(""+t)}function Jb(n,e){var t=n.a[e],i=(K$(),WK)[typeof t];return i?i(t):wY(typeof t)}function rc(n,e){var t,i;return ea(n),i=new _J(e,n.a),t=new rSn(i),new Tn(n,t)}function w$(n){var e;return e=n.b.c.length==0?null:sn(n.b,0),e!=null&&M$(n,0),e}function W4e(n,e){var t,i,r;r=e.c.i,t=u(ee(n.f,r),60),i=t.d.c-t.e.c,BQ(e.a,i,0)}function oQ(n,e){var t;for(++n.d,++n.c[e],t=e+1;t0&&arguments[0]!==void 0?arguments[0]:{},Yi=ze.defaultLayoutOptions,Ri=Yi===void 0?{}:Yi,En=ze.algorithms,hu=En===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:En,Qc=ze.workerFactory,Ru=ze.workerUrl;if(y(this,Ht),this.defaultLayoutOptions=Ri,this.initialized=!1,typeof Ru>"u"&&typeof Qc>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var Pr=Qc;typeof Ru<"u"&&typeof Qc>"u"&&(Pr=function(N1){return new Worker(N1)});var Cf=Pr(Ru);if(typeof Cf.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new Bu(Cf),this.worker.postMessage({cmd:"register",algorithms:hu}).then(function(L1){return Jt.initialized=!0}).catch(console.err)}return Di(Ht,[{key:"layout",value:function(ze){var Yi=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Ri=Yi.layoutOptions,En=Ri===void 0?this.defaultLayoutOptions:Ri,hu=Yi.logging,Qc=hu===void 0?!1:hu,Ru=Yi.measureExecutionTime,Pr=Ru===void 0?!1:Ru;return ze?this.worker.postMessage({cmd:"layout",graph:ze,layoutOptions:En,options:{logging:Qc,measureExecutionTime:Pr}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker&&this.worker.terminate()}}]),Ht}();Sr.default=Wt;var Bu=function(){function Ht(Jt){var ze=this;if(y(this,Ht),Jt===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=Jt,this.worker.onmessage=function(Yi){setTimeout(function(){ze.receive(ze,Yi)},0)}}return Di(Ht,[{key:"postMessage",value:function(ze){var Yi=this.id||0;this.id=Yi+1,ze.id=Yi;var Ri=this;return new Promise(function(En,hu){Ri.resolvers[Yi]=function(Qc,Ru){Qc?(Ri.convertGwtStyleError(Qc),hu(Qc)):En(Ru)},Ri.worker.postMessage(ze)})}},{key:"receive",value:function(ze,Yi){var Ri=Yi.data,En=ze.resolvers[Ri.id];En&&(delete ze.resolvers[Ri.id],Ri.error?En(Ri.error):En(null,Ri.data))}},{key:"terminate",value:function(){this.worker&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(ze){if(ze){var Yi=ze.__java$exception;Yi&&(Yi.cause&&Yi.cause.backingJsObject&&(ze.cause=Yi.cause.backingJsObject,this.convertGwtStyleError(ze.cause)),delete ze.__java$exception)}}}]),Ht}()},{}],2:[function(Xt,gt,Sr){(function(Di){(function(){var y;typeof window<"u"?y=window:typeof Di<"u"?y=Di:typeof self<"u"&&(y=self);var Wt;function Bu(){}function Ht(){}function Jt(){}function ze(){}function Yi(){}function Ri(){}function En(){}function hu(){}function Qc(){}function Ru(){}function Pr(){}function Cf(){}function L1(){}function N1(){}function og(){}function V3(){}function $1(){}function ul(){}function C0n(){}function M0n(){}function J2(){}function F(){}function T0n(){}function mE(){}function A0n(){}function S0n(){}function P0n(){}function I0n(){}function O0n(){}function FU(){}function D0n(){}function L0n(){}function N0n(){}function OO(){}function $0n(){}function x0n(){}function F0n(){}function DO(){}function B0n(){}function R0n(){}function BU(){}function K0n(){}function _0n(){}function yu(){}function ju(){}function Q2(){}function Y2(){}function H0n(){}function q0n(){}function U0n(){}function G0n(){}function RU(){}function Eu(){}function Z2(){}function np(){}function z0n(){}function X0n(){}function LO(){}function V0n(){}function W0n(){}function J0n(){}function Q0n(){}function Y0n(){}function Z0n(){}function nbn(){}function ebn(){}function tbn(){}function ibn(){}function rbn(){}function cbn(){}function ubn(){}function obn(){}function sbn(){}function fbn(){}function hbn(){}function lbn(){}function abn(){}function dbn(){}function bbn(){}function wbn(){}function gbn(){}function pbn(){}function mbn(){}function vbn(){}function kbn(){}function ybn(){}function jbn(){}function Ebn(){}function Cbn(){}function Mbn(){}function Tbn(){}function KU(){}function Abn(){}function Sbn(){}function Pbn(){}function Ibn(){}function NO(){}function $O(){}function vE(){}function Obn(){}function Dbn(){}function xO(){}function Lbn(){}function Nbn(){}function $bn(){}function kE(){}function xbn(){}function Fbn(){}function Bbn(){}function Rbn(){}function Kbn(){}function _bn(){}function Hbn(){}function qbn(){}function Ubn(){}function _U(){}function Gbn(){}function zbn(){}function HU(){}function Xbn(){}function Vbn(){}function Wbn(){}function Jbn(){}function Qbn(){}function Ybn(){}function Zbn(){}function nwn(){}function ewn(){}function twn(){}function iwn(){}function rwn(){}function cwn(){}function FO(){}function uwn(){}function own(){}function swn(){}function fwn(){}function hwn(){}function lwn(){}function awn(){}function dwn(){}function bwn(){}function qU(){}function UU(){}function wwn(){}function gwn(){}function pwn(){}function mwn(){}function vwn(){}function kwn(){}function ywn(){}function jwn(){}function Ewn(){}function Cwn(){}function Mwn(){}function Twn(){}function Awn(){}function Swn(){}function Pwn(){}function Iwn(){}function Own(){}function Dwn(){}function Lwn(){}function Nwn(){}function $wn(){}function xwn(){}function Fwn(){}function Bwn(){}function Rwn(){}function Kwn(){}function _wn(){}function Hwn(){}function qwn(){}function Uwn(){}function Gwn(){}function zwn(){}function Xwn(){}function Vwn(){}function Wwn(){}function Jwn(){}function Qwn(){}function Ywn(){}function Zwn(){}function ngn(){}function egn(){}function tgn(){}function ign(){}function rgn(){}function cgn(){}function ugn(){}function ogn(){}function sgn(){}function fgn(){}function hgn(){}function lgn(){}function agn(){}function dgn(){}function bgn(){}function wgn(){}function ggn(){}function pgn(){}function mgn(){}function vgn(){}function kgn(){}function ygn(){}function jgn(){}function Egn(){}function Cgn(){}function Mgn(){}function Tgn(){}function Agn(){}function Sgn(){}function Pgn(){}function Ign(){}function Ogn(){}function Dgn(){}function Lgn(){}function Ngn(){}function $gn(){}function xgn(){}function Fgn(){}function Bgn(){}function Rgn(){}function Kgn(){}function _gn(){}function Hgn(){}function qgn(){}function Ugn(){}function Ggn(){}function zgn(){}function Xgn(){}function Vgn(){}function Wgn(){}function Jgn(){}function Qgn(){}function Ygn(){}function Zgn(){}function n2n(){}function e2n(){}function t2n(){}function i2n(){}function r2n(){}function c2n(){}function u2n(){}function GU(){}function o2n(){}function s2n(){}function f2n(){}function h2n(){}function l2n(){}function a2n(){}function d2n(){}function b2n(){}function w2n(){}function g2n(){}function p2n(){}function m2n(){}function v2n(){}function k2n(){}function y2n(){}function j2n(){}function E2n(){}function C2n(){}function M2n(){}function T2n(){}function A2n(){}function S2n(){}function P2n(){}function I2n(){}function O2n(){}function D2n(){}function L2n(){}function N2n(){}function $2n(){}function x2n(){}function F2n(){}function B2n(){}function R2n(){}function K2n(){}function _2n(){}function H2n(){}function q2n(){}function U2n(){}function G2n(){}function z2n(){}function X2n(){}function V2n(){}function W2n(){}function J2n(){}function Q2n(){}function Y2n(){}function Z2n(){}function npn(){}function epn(){}function tpn(){}function ipn(){}function rpn(){}function cpn(){}function upn(){}function opn(){}function spn(){}function fpn(){}function hpn(){}function lpn(){}function apn(){}function dpn(){}function bpn(){}function wpn(){}function gpn(){}function ppn(){}function mpn(){}function vpn(){}function kpn(){}function ypn(){}function jpn(){}function Epn(){}function Cpn(){}function Mpn(){}function zU(){}function Tpn(){}function Apn(){}function Spn(){}function Ppn(){}function Ipn(){}function Opn(){}function Dpn(){}function Lpn(){}function Npn(){}function $pn(){}function XU(){}function xpn(){}function Fpn(){}function Bpn(){}function Rpn(){}function Kpn(){}function _pn(){}function VU(){}function WU(){}function Hpn(){}function JU(){}function QU(){}function qpn(){}function Upn(){}function Gpn(){}function zpn(){}function Xpn(){}function Vpn(){}function Wpn(){}function Jpn(){}function Qpn(){}function Ypn(){}function Zpn(){}function YU(){}function n3n(){}function e3n(){}function t3n(){}function i3n(){}function r3n(){}function c3n(){}function u3n(){}function o3n(){}function s3n(){}function f3n(){}function h3n(){}function l3n(){}function a3n(){}function d3n(){}function b3n(){}function w3n(){}function g3n(){}function p3n(){}function m3n(){}function v3n(){}function k3n(){}function y3n(){}function j3n(){}function E3n(){}function C3n(){}function M3n(){}function T3n(){}function A3n(){}function S3n(){}function P3n(){}function I3n(){}function O3n(){}function D3n(){}function L3n(){}function N3n(){}function $3n(){}function x3n(){}function F3n(){}function B3n(){}function R3n(){}function K3n(){}function _3n(){}function H3n(){}function q3n(){}function U3n(){}function G3n(){}function z3n(){}function X3n(){}function V3n(){}function W3n(){}function J3n(){}function Q3n(){}function Y3n(){}function Z3n(){}function n4n(){}function e4n(){}function t4n(){}function i4n(){}function r4n(){}function c4n(){}function u4n(){}function o4n(){}function s4n(){}function f4n(){}function h4n(){}function l4n(){}function a4n(){}function d4n(){}function b4n(){}function w4n(){}function g4n(){}function p4n(){}function m4n(){}function v4n(){}function k4n(){}function y4n(){}function j4n(){}function E4n(){}function C4n(){}function M4n(){}function T4n(){}function A4n(){}function S4n(){}function P4n(){}function I4n(){}function O4n(){}function _se(){}function D4n(){}function L4n(){}function N4n(){}function $4n(){}function x4n(){}function F4n(){}function B4n(){}function R4n(){}function K4n(){}function _4n(){}function H4n(){}function q4n(){}function U4n(){}function G4n(){}function z4n(){}function X4n(){}function V4n(){}function W4n(){}function J4n(){}function Q4n(){}function Y4n(){}function Z4n(){}function nmn(){}function emn(){}function tmn(){}function imn(){}function rmn(){}function BO(){}function RO(){}function cmn(){}function KO(){}function umn(){}function omn(){}function smn(){}function fmn(){}function hmn(){}function lmn(){}function amn(){}function dmn(){}function bmn(){}function wmn(){}function ZU(){}function gmn(){}function pmn(){}function mmn(){}function Hse(){}function vmn(){}function kmn(){}function ymn(){}function jmn(){}function Emn(){}function Cmn(){}function Mmn(){}function Ra(){}function Tmn(){}function ep(){}function nG(){}function Amn(){}function Smn(){}function Pmn(){}function Imn(){}function Omn(){}function Dmn(){}function Lmn(){}function Nmn(){}function $mn(){}function xmn(){}function Fmn(){}function Bmn(){}function Rmn(){}function Kmn(){}function _mn(){}function Hmn(){}function qmn(){}function Umn(){}function Gmn(){}function hn(){}function zmn(){}function Xmn(){}function Vmn(){}function Wmn(){}function Jmn(){}function Qmn(){}function Ymn(){}function Zmn(){}function nvn(){}function evn(){}function tvn(){}function ivn(){}function rvn(){}function _O(){}function cvn(){}function uvn(){}function ovn(){}function yE(){}function svn(){}function HO(){}function jE(){}function fvn(){}function eG(){}function hvn(){}function lvn(){}function avn(){}function dvn(){}function bvn(){}function wvn(){}function EE(){}function gvn(){}function pvn(){}function CE(){}function mvn(){}function ME(){}function vvn(){}function tG(){}function kvn(){}function qO(){}function iG(){}function yvn(){}function jvn(){}function Evn(){}function Cvn(){}function qse(){}function Mvn(){}function Tvn(){}function Avn(){}function Svn(){}function Pvn(){}function Ivn(){}function Ovn(){}function Dvn(){}function Lvn(){}function Nvn(){}function W3(){}function UO(){}function $vn(){}function xvn(){}function Fvn(){}function Bvn(){}function Rvn(){}function Kvn(){}function _vn(){}function Hvn(){}function qvn(){}function Uvn(){}function Gvn(){}function zvn(){}function Xvn(){}function Vvn(){}function Wvn(){}function Jvn(){}function Qvn(){}function Yvn(){}function Zvn(){}function n6n(){}function e6n(){}function t6n(){}function i6n(){}function r6n(){}function c6n(){}function u6n(){}function o6n(){}function s6n(){}function f6n(){}function h6n(){}function l6n(){}function a6n(){}function d6n(){}function b6n(){}function w6n(){}function g6n(){}function p6n(){}function m6n(){}function v6n(){}function k6n(){}function y6n(){}function j6n(){}function E6n(){}function C6n(){}function M6n(){}function T6n(){}function A6n(){}function S6n(){}function P6n(){}function I6n(){}function O6n(){}function D6n(){}function L6n(){}function N6n(){}function $6n(){}function x6n(){}function F6n(){}function B6n(){}function R6n(){}function K6n(){}function _6n(){}function H6n(){}function q6n(){}function U6n(){}function G6n(){}function z6n(){}function X6n(){}function V6n(){}function W6n(){}function J6n(){}function Q6n(){}function Y6n(){}function Z6n(){}function n5n(){}function e5n(){}function t5n(){}function i5n(){}function r5n(){}function c5n(){}function u5n(){}function o5n(){}function s5n(){}function f5n(){}function h5n(){}function l5n(){}function a5n(){}function d5n(){}function b5n(){}function w5n(){}function g5n(){}function p5n(){}function m5n(){}function v5n(){}function k5n(){}function y5n(){}function j5n(){}function E5n(){}function C5n(){}function M5n(){}function T5n(){}function A5n(){}function rG(){}function S5n(){}function P5n(){}function GO(){n6()}function I5n(){u7()}function O5n(){aA()}function D5n(){Q$()}function L5n(){M5()}function N5n(){ann()}function $5n(){qs()}function x5n(){jZ()}function F5n(){zk()}function B5n(){o7()}function R5n(){$7()}function K5n(){aCn()}function _5n(){Hp()}function H5n(){KLn()}function q5n(){yQ()}function U5n(){SOn()}function G5n(){jQ()}function z5n(){pNn()}function X5n(){AOn()}function V5n(){cm()}function W5n(){nxn()}function J5n(){Z$n()}function Q5n(){EDn()}function Y5n(){exn()}function Z5n(){ca()}function n8n(){ZE()}function e8n(){ltn()}function t8n(){cn()}function i8n(){txn()}function r8n(){Pxn()}function c8n(){POn()}function u8n(){nKn()}function o8n(){IOn()}function s8n(){bUn()}function f8n(){qnn()}function h8n(){kl()}function l8n(){wBn()}function a8n(){lc()}function d8n(){ROn()}function b8n(){_p()}function w8n(){Men()}function g8n(){ua()}function p8n(){Ten()}function m8n(){Bf()}function v8n(){Qk()}function k8n(){EF()}function y8n(){Dx()}function cf(){wSn()}function j8n(){YM()}function E8n(){mA()}function cG(){qe()}function C8n(){NT()}function M8n(){YY()}function uG(){D$()}function oG(){KA()}function T8n(){Fen()}function sG(n){Jn(n)}function A8n(n){this.a=n}function TE(n){this.a=n}function S8n(n){this.a=n}function P8n(n){this.a=n}function I8n(n){this.a=n}function O8n(n){this.a=n}function D8n(n){this.a=n}function L8n(n){this.a=n}function fG(n){this.a=n}function hG(n){this.a=n}function N8n(n){this.a=n}function $8n(n){this.a=n}function zO(n){this.a=n}function x8n(n){this.a=n}function F8n(n){this.a=n}function XO(n){this.a=n}function VO(n){this.a=n}function B8n(n){this.a=n}function WO(n){this.a=n}function R8n(n){this.a=n}function K8n(n){this.a=n}function _8n(n){this.a=n}function lG(n){this.b=n}function H8n(n){this.c=n}function q8n(n){this.a=n}function U8n(n){this.a=n}function G8n(n){this.a=n}function z8n(n){this.a=n}function X8n(n){this.a=n}function V8n(n){this.a=n}function W8n(n){this.a=n}function J8n(n){this.a=n}function Q8n(n){this.a=n}function Y8n(n){this.a=n}function Z8n(n){this.a=n}function n9n(n){this.a=n}function e9n(n){this.a=n}function aG(n){this.a=n}function dG(n){this.a=n}function AE(n){this.a=n}function z9(n){this.a=n}function Ka(){this.a=[]}function t9n(n,e){n.a=e}function Use(n,e){n.a=e}function Gse(n,e){n.b=e}function zse(n,e){n.b=e}function Xse(n,e){n.b=e}function bG(n,e){n.j=e}function Vse(n,e){n.g=e}function Wse(n,e){n.i=e}function Jse(n,e){n.c=e}function Qse(n,e){n.c=e}function Yse(n,e){n.d=e}function Zse(n,e){n.d=e}function _a(n,e){n.k=e}function nfe(n,e){n.c=e}function wG(n,e){n.c=e}function gG(n,e){n.a=e}function efe(n,e){n.a=e}function tfe(n,e){n.f=e}function ife(n,e){n.a=e}function rfe(n,e){n.b=e}function JO(n,e){n.d=e}function SE(n,e){n.i=e}function pG(n,e){n.o=e}function cfe(n,e){n.r=e}function ufe(n,e){n.a=e}function ofe(n,e){n.b=e}function i9n(n,e){n.e=e}function sfe(n,e){n.f=e}function mG(n,e){n.g=e}function ffe(n,e){n.e=e}function hfe(n,e){n.f=e}function lfe(n,e){n.f=e}function QO(n,e){n.a=e}function YO(n,e){n.b=e}function afe(n,e){n.n=e}function dfe(n,e){n.a=e}function bfe(n,e){n.c=e}function wfe(n,e){n.c=e}function gfe(n,e){n.c=e}function pfe(n,e){n.a=e}function mfe(n,e){n.a=e}function vfe(n,e){n.d=e}function kfe(n,e){n.d=e}function yfe(n,e){n.e=e}function jfe(n,e){n.e=e}function Efe(n,e){n.g=e}function Cfe(n,e){n.f=e}function Mfe(n,e){n.j=e}function Tfe(n,e){n.a=e}function Afe(n,e){n.a=e}function Sfe(n,e){n.b=e}function r9n(n){n.b=n.a}function c9n(n){n.c=n.d.d}function vG(n){this.a=n}function kG(n){this.a=n}function yG(n){this.a=n}function Ha(n){this.a=n}function qa(n){this.a=n}function X9(n){this.a=n}function u9n(n){this.a=n}function jG(n){this.a=n}function V9(n){this.a=n}function PE(n){this.a=n}function ol(n){this.a=n}function Sb(n){this.a=n}function o9n(n){this.a=n}function s9n(n){this.a=n}function ZO(n){this.b=n}function J3(n){this.b=n}function Q3(n){this.b=n}function nD(n){this.a=n}function f9n(n){this.a=n}function eD(n){this.c=n}function C(n){this.c=n}function h9n(n){this.c=n}function Xv(n){this.d=n}function EG(n){this.a=n}function Te(n){this.a=n}function l9n(n){this.a=n}function CG(n){this.a=n}function MG(n){this.a=n}function TG(n){this.a=n}function AG(n){this.a=n}function SG(n){this.a=n}function PG(n){this.a=n}function Y3(n){this.a=n}function a9n(n){this.a=n}function d9n(n){this.a=n}function Z3(n){this.a=n}function b9n(n){this.a=n}function w9n(n){this.a=n}function g9n(n){this.a=n}function p9n(n){this.a=n}function m9n(n){this.a=n}function v9n(n){this.a=n}function k9n(n){this.a=n}function y9n(n){this.a=n}function j9n(n){this.a=n}function E9n(n){this.a=n}function C9n(n){this.a=n}function M9n(n){this.a=n}function T9n(n){this.a=n}function A9n(n){this.a=n}function S9n(n){this.a=n}function Vv(n){this.a=n}function P9n(n){this.a=n}function I9n(n){this.a=n}function O9n(n){this.a=n}function D9n(n){this.a=n}function IE(n){this.a=n}function L9n(n){this.a=n}function N9n(n){this.a=n}function n4(n){this.a=n}function IG(n){this.a=n}function $9n(n){this.a=n}function x9n(n){this.a=n}function F9n(n){this.a=n}function B9n(n){this.a=n}function R9n(n){this.a=n}function K9n(n){this.a=n}function OG(n){this.a=n}function DG(n){this.a=n}function LG(n){this.a=n}function Wv(n){this.a=n}function OE(n){this.e=n}function e4(n){this.a=n}function _9n(n){this.a=n}function tp(n){this.a=n}function NG(n){this.a=n}function H9n(n){this.a=n}function q9n(n){this.a=n}function U9n(n){this.a=n}function G9n(n){this.a=n}function z9n(n){this.a=n}function X9n(n){this.a=n}function V9n(n){this.a=n}function W9n(n){this.a=n}function J9n(n){this.a=n}function Q9n(n){this.a=n}function Y9n(n){this.a=n}function $G(n){this.a=n}function Z9n(n){this.a=n}function n7n(n){this.a=n}function e7n(n){this.a=n}function t7n(n){this.a=n}function i7n(n){this.a=n}function r7n(n){this.a=n}function c7n(n){this.a=n}function u7n(n){this.a=n}function o7n(n){this.a=n}function s7n(n){this.a=n}function f7n(n){this.a=n}function h7n(n){this.a=n}function l7n(n){this.a=n}function a7n(n){this.a=n}function d7n(n){this.a=n}function b7n(n){this.a=n}function w7n(n){this.a=n}function g7n(n){this.a=n}function p7n(n){this.a=n}function m7n(n){this.a=n}function v7n(n){this.a=n}function k7n(n){this.a=n}function y7n(n){this.a=n}function j7n(n){this.a=n}function E7n(n){this.a=n}function C7n(n){this.a=n}function M7n(n){this.a=n}function T7n(n){this.a=n}function A7n(n){this.a=n}function S7n(n){this.a=n}function P7n(n){this.a=n}function I7n(n){this.a=n}function O7n(n){this.a=n}function D7n(n){this.a=n}function L7n(n){this.a=n}function N7n(n){this.a=n}function $7n(n){this.a=n}function x7n(n){this.a=n}function F7n(n){this.c=n}function B7n(n){this.b=n}function R7n(n){this.a=n}function K7n(n){this.a=n}function _7n(n){this.a=n}function H7n(n){this.a=n}function q7n(n){this.a=n}function U7n(n){this.a=n}function G7n(n){this.a=n}function z7n(n){this.a=n}function X7n(n){this.a=n}function V7n(n){this.a=n}function W7n(n){this.a=n}function J7n(n){this.a=n}function Q7n(n){this.a=n}function Y7n(n){this.a=n}function Z7n(n){this.a=n}function nkn(n){this.a=n}function ekn(n){this.a=n}function tkn(n){this.a=n}function ikn(n){this.a=n}function rkn(n){this.a=n}function ckn(n){this.a=n}function ukn(n){this.a=n}function okn(n){this.a=n}function skn(n){this.a=n}function fkn(n){this.a=n}function hkn(n){this.a=n}function lkn(n){this.a=n}function sl(n){this.a=n}function sg(n){this.a=n}function akn(n){this.a=n}function dkn(n){this.a=n}function bkn(n){this.a=n}function wkn(n){this.a=n}function gkn(n){this.a=n}function pkn(n){this.a=n}function mkn(n){this.a=n}function vkn(n){this.a=n}function kkn(n){this.a=n}function ykn(n){this.a=n}function jkn(n){this.a=n}function Ekn(n){this.a=n}function Ckn(n){this.a=n}function Mkn(n){this.a=n}function Tkn(n){this.a=n}function Akn(n){this.a=n}function Skn(n){this.a=n}function Pkn(n){this.a=n}function Ikn(n){this.a=n}function Okn(n){this.a=n}function Dkn(n){this.a=n}function Lkn(n){this.a=n}function Nkn(n){this.a=n}function $kn(n){this.a=n}function xkn(n){this.a=n}function Fkn(n){this.a=n}function DE(n){this.a=n}function Bkn(n){this.f=n}function Rkn(n){this.a=n}function Kkn(n){this.a=n}function _kn(n){this.a=n}function Hkn(n){this.a=n}function qkn(n){this.a=n}function Ukn(n){this.a=n}function Gkn(n){this.a=n}function zkn(n){this.a=n}function Xkn(n){this.a=n}function Vkn(n){this.a=n}function Wkn(n){this.a=n}function Jkn(n){this.a=n}function Qkn(n){this.a=n}function Ykn(n){this.a=n}function Zkn(n){this.a=n}function nyn(n){this.a=n}function eyn(n){this.a=n}function tyn(n){this.a=n}function iyn(n){this.a=n}function ryn(n){this.a=n}function cyn(n){this.a=n}function uyn(n){this.a=n}function oyn(n){this.a=n}function syn(n){this.a=n}function fyn(n){this.a=n}function hyn(n){this.a=n}function lyn(n){this.a=n}function ayn(n){this.a=n}function tD(n){this.a=n}function xG(n){this.a=n}function lt(n){this.b=n}function dyn(n){this.a=n}function byn(n){this.a=n}function wyn(n){this.a=n}function gyn(n){this.a=n}function pyn(n){this.a=n}function myn(n){this.a=n}function vyn(n){this.a=n}function kyn(n){this.b=n}function yyn(n){this.a=n}function W9(n){this.a=n}function jyn(n){this.a=n}function Eyn(n){this.a=n}function FG(n){this.c=n}function LE(n){this.e=n}function NE(n){this.a=n}function $E(n){this.a=n}function iD(n){this.a=n}function Cyn(n){this.d=n}function Myn(n){this.a=n}function BG(n){this.a=n}function RG(n){this.a=n}function Wd(n){this.e=n}function Pfe(){this.a=0}function de(){Hu(this)}function Z(){pL(this)}function rD(){sIn(this)}function Tyn(){}function Jd(){this.c=Gdn}function Ayn(n,e){n.b+=e}function Ife(n,e){e.Wb(n)}function Ofe(n){return n.a}function Dfe(n){return n.a}function Lfe(n){return n.a}function Nfe(n){return n.a}function $fe(n){return n.a}function M(n){return n.e}function xfe(){return null}function Ffe(){return null}function Bfe(){Cz(),pLe()}function Rfe(n){n.b.Of(n.e)}function Syn(n){n.b=new CD}function Jv(n,e){n.b=e-n.b}function Qv(n,e){n.a=e-n.a}function Bn(n,e){n.push(e)}function Pyn(n,e){n.sort(e)}function Iyn(n,e){e.jd(n.a)}function Kfe(n,e){gi(e,n)}function _fe(n,e,t){n.Yd(t,e)}function J9(n,e){n.e=e,e.b=n}function KG(n){uh(),this.a=n}function Oyn(n){uh(),this.a=n}function Dyn(n){uh(),this.a=n}function cD(n){m0(),this.a=n}function Lyn(n){O4(),VK.le(n)}function _G(){_G=F,new de}function Ua(){YTn.call(this)}function HG(){YTn.call(this)}function qG(){Ua.call(this)}function uD(){Ua.call(this)}function Nyn(){Ua.call(this)}function Q9(){Ua.call(this)}function Cu(){Ua.call(this)}function ip(){Ua.call(this)}function Pe(){Ua.call(this)}function Bo(){Ua.call(this)}function $yn(){Ua.call(this)}function nc(){Ua.call(this)}function xyn(){Ua.call(this)}function Fyn(){this.a=this}function xE(){this.Bb|=256}function Byn(){this.b=new GMn}function Pb(n,e){n.length=e}function FE(n,e){nn(n.a,e)}function Hfe(n,e){bnn(n.c,e)}function qfe(n,e){fi(n.b,e)}function Ufe(n,e){uA(n.a,e)}function Gfe(n,e){cx(n.a,e)}function t4(n,e){it(n.e,e)}function rp(n){jA(n.c,n.b)}function zfe(n,e){n.kc().Nb(e)}function UG(n){this.a=B5e(n)}function ni(){this.a=new de}function Ryn(){this.a=new de}function GG(){this.a=new rCn}function BE(){this.a=new Z}function oD(){this.a=new Z}function zG(){this.a=new Z}function hs(){this.a=new cbn}function Ga(){this.a=new NLn}function XG(){this.a=new _U}function VG(){this.a=new TOn}function WG(){this.a=new BAn}function Kyn(){this.a=new Z}function _yn(){this.a=new Z}function Hyn(){this.a=new Z}function JG(){this.a=new Z}function qyn(){this.d=new Z}function Uyn(){this.a=new zOn}function Gyn(){this.a=new ni}function zyn(){this.a=new de}function Xyn(){this.b=new de}function Vyn(){this.b=new Z}function QG(){this.e=new Z}function Wyn(){this.a=new Z5n}function Jyn(){this.d=new Z}function Qyn(){QIn.call(this)}function Yyn(){QIn.call(this)}function Zyn(){Z.call(this)}function YG(){qG.call(this)}function ZG(){BE.call(this)}function njn(){qC.call(this)}function ejn(){JG.call(this)}function Yv(){Tyn.call(this)}function sD(){Yv.call(this)}function cp(){Tyn.call(this)}function nz(){cp.call(this)}function tjn(){rz.call(this)}function ijn(){rz.call(this)}function rjn(){rz.call(this)}function cjn(){cz.call(this)}function Zv(){svn.call(this)}function ez(){svn.call(this)}function Mu(){Ct.call(this)}function ujn(){yjn.call(this)}function ojn(){yjn.call(this)}function sjn(){de.call(this)}function fjn(){de.call(this)}function hjn(){de.call(this)}function fD(){cxn.call(this)}function ljn(){ni.call(this)}function ajn(){xE.call(this)}function hD(){BX.call(this)}function tz(){de.call(this)}function lD(){BX.call(this)}function aD(){de.call(this)}function djn(){de.call(this)}function iz(){ME.call(this)}function bjn(){iz.call(this)}function wjn(){ME.call(this)}function gjn(){rG.call(this)}function rz(){this.a=new ni}function pjn(){this.a=new de}function mjn(){this.a=new Z}function cz(){this.a=new de}function up(){this.a=new Ct}function vjn(){this.j=new Z}function kjn(){this.a=new mEn}function yjn(){this.a=new mvn}function uz(){this.a=new Z4n}function n6(){n6=F,KK=new Ht}function dD(){dD=F,_K=new Ejn}function bD(){bD=F,HK=new jjn}function jjn(){XO.call(this,"")}function Ejn(){XO.call(this,"")}function Cjn(n){S$n.call(this,n)}function Mjn(n){S$n.call(this,n)}function oz(n){fG.call(this,n)}function sz(n){XEn.call(this,n)}function Xfe(n){XEn.call(this,n)}function Vfe(n){sz.call(this,n)}function Wfe(n){sz.call(this,n)}function Jfe(n){sz.call(this,n)}function Tjn(n){zN.call(this,n)}function Ajn(n){zN.call(this,n)}function Sjn(n){uSn.call(this,n)}function Pjn(n){Oz.call(this,n)}function e6(n){WE.call(this,n)}function fz(n){WE.call(this,n)}function Ijn(n){WE.call(this,n)}function hz(n){mje.call(this,n)}function lz(n){hz.call(this,n)}function ec(n){APn.call(this,n)}function Ojn(n){ec.call(this,n)}function op(){z9.call(this,{})}function Djn(){Djn=F,dQn=new M0n}function RE(){RE=F,GK=new STn}function Ljn(){Ljn=F,oun=new Bu}function az(){az=F,sun=new N1}function KE(){KE=F,P8=new $1}function wD(n){b4(),this.a=n}function gD(n){RQ(),this.a=n}function Qd(n){nN(),this.f=n}function pD(n){nN(),this.f=n}function Njn(n){bSn(),this.a=n}function $jn(n){n.b=null,n.c=0}function Qfe(n,e){n.e=e,bqn(n,e)}function Yfe(n,e){n.a=e,cEe(n)}function mD(n,e,t){n.a[e.g]=t}function Zfe(n,e,t){kke(t,n,e)}function nhe(n,e){Wae(e.i,n.n)}function xjn(n,e){v6e(n).Cd(e)}function ehe(n,e){n.a.ec().Mc(e)}function Fjn(n,e){return n.g-e.g}function the(n,e){return n*n/e}function on(n){return Jn(n),n}function $(n){return Jn(n),n}function Y9(n){return Jn(n),n}function ihe(n){return new AE(n)}function rhe(n){return new qb(n)}function dz(n){return Jn(n),n}function che(n){return Jn(n),n}function _E(n){ec.call(this,n)}function Ir(n){ec.call(this,n)}function Bjn(n){ec.call(this,n)}function vD(n){APn.call(this,n)}function i4(n){ec.call(this,n)}function Gn(n){ec.call(this,n)}function Or(n){ec.call(this,n)}function Rjn(n){ec.call(this,n)}function sp(n){ec.call(this,n)}function Kl(n){ec.call(this,n)}function _l(n){ec.call(this,n)}function fp(n){ec.call(this,n)}function nh(n){ec.call(this,n)}function kD(n){ec.call(this,n)}function Le(n){ec.call(this,n)}function Ku(n){Jn(n),this.a=n}function bz(n){return ld(n),n}function t6(n){TW(n,n.length)}function i6(n){return n.b==n.c}function Ib(n){return!!n&&n.b}function uhe(n){return!!n&&n.k}function ohe(n){return!!n&&n.j}function she(n,e,t){n.c.Ef(e,t)}function Kjn(n,e){n.be(e),e.ae(n)}function hp(n){uh(),this.a=Se(n)}function yD(){this.a=Oe(Se(ur))}function _jn(){throw M(new Pe)}function fhe(){throw M(new Pe)}function wz(){throw M(new Pe)}function Hjn(){throw M(new Pe)}function hhe(){throw M(new Pe)}function lhe(){throw M(new Pe)}function HE(){HE=F,O4()}function Hl(){X9.call(this,"")}function r6(){X9.call(this,"")}function x1(){X9.call(this,"")}function lp(){X9.call(this,"")}function gz(n){Ir.call(this,n)}function pz(n){Ir.call(this,n)}function eh(n){Gn.call(this,n)}function r4(n){Q3.call(this,n)}function qjn(n){r4.call(this,n)}function jD(n){BC.call(this,n)}function ED(n){JX.call(this,n,0)}function CD(){sJ.call(this,12,3)}function T(n,e){return kOn(n,e)}function qE(n,e){return o$(n,e)}function ahe(n,e){return n.a-e.a}function dhe(n,e){return n.a-e.a}function bhe(n,e){return n.a-e.a}function whe(n,e){return e in n.a}function Ujn(n){return n.a?n.b:0}function ghe(n){return n.a?n.b:0}function phe(n,e,t){e.Cd(n.a[t])}function mhe(n,e,t){e.Pe(n.a[t])}function vhe(n,e){n.b=new rr(e)}function khe(n,e){return n.b=e,n}function Gjn(n,e){return n.c=e,n}function zjn(n,e){return n.f=e,n}function yhe(n,e){return n.g=e,n}function mz(n,e){return n.a=e,n}function vz(n,e){return n.f=e,n}function jhe(n,e){return n.k=e,n}function kz(n,e){return n.a=e,n}function Ehe(n,e){return n.e=e,n}function yz(n,e){return n.e=e,n}function Che(n,e){return n.f=e,n}function Mhe(n,e){n.b=!0,n.d=e}function The(n,e){return n.b-e.b}function Ahe(n,e){return n.g-e.g}function She(n,e){return n?0:e-1}function Xjn(n,e){return n?0:e-1}function Phe(n,e){return n?e-1:0}function Ihe(n,e){return n.s-e.s}function Ohe(n,e){return e.rg(n)}function Yd(n,e){return n.b=e,n}function UE(n,e){return n.a=e,n}function Zd(n,e){return n.c=e,n}function n0(n,e){return n.d=e,n}function e0(n,e){return n.e=e,n}function jz(n,e){return n.f=e,n}function c6(n,e){return n.a=e,n}function c4(n,e){return n.b=e,n}function u4(n,e){return n.c=e,n}function an(n,e){return n.c=e,n}function Sn(n,e){return n.b=e,n}function dn(n,e){return n.d=e,n}function bn(n,e){return n.e=e,n}function Dhe(n,e){return n.f=e,n}function wn(n,e){return n.g=e,n}function gn(n,e){return n.a=e,n}function pn(n,e){return n.i=e,n}function mn(n,e){return n.j=e,n}function Lhe(n,e){ca(),ic(e,n)}function Nhe(n,e,t){Jbe(n.a,e,t)}function GE(n){$L.call(this,n)}function Vjn(n){Z5e.call(this,n)}function Wjn(n){SIn.call(this,n)}function Ez(n){SIn.call(this,n)}function F1(n){S0.call(this,n)}function Jjn(n){CN.call(this,n)}function Qjn(n){CN.call(this,n)}function Yjn(){DX.call(this,"")}function Li(){this.a=0,this.b=0}function Zjn(){this.b=0,this.a=0}function nEn(n,e){n.b=0,Zb(n,e)}function eEn(n,e){return n.k=e,n}function $he(n,e){return n.j=e,n}function xhe(n,e){n.c=e,n.b=!0}function tEn(){tEn=F,TQn=Xke()}function B1(){B1=F,voe=rke()}function iEn(){iEn=F,Ti=gye()}function Cz(){Cz=F,Oa=z4()}function o4(){o4=F,Udn=cke()}function rEn(){rEn=F,ise=uke()}function Mz(){Mz=F,yc=tEe()}function uf(n){return n.e&&n.e()}function cEn(n){return n.l|n.m<<22}function uEn(n,e){return n.c._b(e)}function oEn(n,e){return rBn(n.b,e)}function MD(n){return n?n.d:null}function Fhe(n){return n?n.g:null}function Bhe(n){return n?n.i:null}function za(n){return ll(n),n.o}function fg(n,e){return n.a+=e,n}function TD(n,e){return n.a+=e,n}function ql(n,e){return n.a+=e,n}function t0(n,e){return n.a+=e,n}function Tz(n,e){for(;n.Bd(e););}function zE(n){this.a=new ap(n)}function sEn(){throw M(new Pe)}function fEn(){throw M(new Pe)}function hEn(){throw M(new Pe)}function lEn(){throw M(new Pe)}function aEn(){throw M(new Pe)}function dEn(){throw M(new Pe)}function Ul(n){this.a=new iN(n)}function bEn(){this.a=new K5(Rln)}function wEn(){this.b=new K5(rln)}function gEn(){this.a=new K5(f1n)}function pEn(){this.b=new K5(Fq)}function mEn(){this.b=new K5(Fq)}function XE(n){this.a=0,this.b=n}function Az(n){zGn(),ILe(this,n)}function s4(n){return z1(n),n.a}function Z9(n){return n.b!=n.d.c}function Sz(n,e){return n.d[e.p]}function vEn(n,e){return XTe(n,e)}function Pz(n,e,t){n.splice(e,t)}function hg(n,e){for(;n.Re(e););}function kEn(n){n.c?Dqn(n):Lqn(n)}function yEn(){throw M(new Pe)}function jEn(){throw M(new Pe)}function EEn(){throw M(new Pe)}function CEn(){throw M(new Pe)}function MEn(){throw M(new Pe)}function TEn(){throw M(new Pe)}function AEn(){throw M(new Pe)}function SEn(){throw M(new Pe)}function PEn(){throw M(new Pe)}function IEn(){throw M(new Pe)}function Rhe(){throw M(new nc)}function Khe(){throw M(new nc)}function n7(n){this.a=new OEn(n)}function OEn(n){Ume(this,n,jje())}function e7(n){return!n||oIn(n)}function t7(n){return Zf[n]!=-1}function _he(){cP!=0&&(cP=0),uP=-1}function DEn(){RK==null&&(RK=[])}function i7(n,e){Cg.call(this,n,e)}function f4(n,e){i7.call(this,n,e)}function LEn(n,e){this.a=n,this.b=e}function NEn(n,e){this.a=n,this.b=e}function $En(n,e){this.a=n,this.b=e}function xEn(n,e){this.a=n,this.b=e}function FEn(n,e){this.a=n,this.b=e}function BEn(n,e){this.a=n,this.b=e}function REn(n,e){this.a=n,this.b=e}function h4(n,e){this.e=n,this.d=e}function Iz(n,e){this.b=n,this.c=e}function KEn(n,e){this.b=n,this.a=e}function _En(n,e){this.b=n,this.a=e}function HEn(n,e){this.b=n,this.a=e}function qEn(n,e){this.b=n,this.a=e}function UEn(n,e){this.a=n,this.b=e}function AD(n,e){this.a=n,this.b=e}function GEn(n,e){this.a=n,this.f=e}function i0(n,e){this.g=n,this.i=e}function je(n,e){this.f=n,this.g=e}function zEn(n,e){this.b=n,this.c=e}function XEn(n){KX(n.dc()),this.c=n}function Hhe(n,e){this.a=n,this.b=e}function VEn(n,e){this.a=n,this.b=e}function WEn(n){this.a=u(Se(n),15)}function Oz(n){this.a=u(Se(n),15)}function JEn(n){this.a=u(Se(n),85)}function VE(n){this.b=u(Se(n),85)}function WE(n){this.b=u(Se(n),51)}function JE(){this.q=new y.Date}function SD(n,e){this.a=n,this.b=e}function QEn(n,e){return Zc(n.b,e)}function r7(n,e){return n.b.Hc(e)}function YEn(n,e){return n.b.Ic(e)}function ZEn(n,e){return n.b.Qc(e)}function nCn(n,e){return n.b.Hc(e)}function eCn(n,e){return n.c.uc(e)}function tCn(n,e){return rt(n.c,e)}function of(n,e){return n.a._b(e)}function iCn(n,e){return n>e&&e0}function ND(n,e){return Ec(n,e)<0}function vCn(n,e){return JL(n.a,e)}function ole(n,e){yOn.call(this,n,e)}function Bz(n){wN(),uSn.call(this,n)}function Rz(n,e){bPn(n,n.length,e)}function s7(n,e){HPn(n,n.length,e)}function d6(n,e){return n.a.get(e)}function kCn(n,e){return Zc(n.e,e)}function Kz(n){return Jn(n),!1}function _z(n){this.a=u(Se(n),229)}function cC(n){In.call(this,n,21)}function uC(n,e){je.call(this,n,e)}function $D(n,e){je.call(this,n,e)}function yCn(n,e){this.b=n,this.a=e}function oC(n,e){this.d=n,this.e=e}function jCn(n,e){this.a=n,this.b=e}function ECn(n,e){this.a=n,this.b=e}function CCn(n,e){this.a=n,this.b=e}function MCn(n,e){this.a=n,this.b=e}function bp(n,e){this.a=n,this.b=e}function TCn(n,e){this.b=n,this.a=e}function Hz(n,e){this.b=n,this.a=e}function qz(n,e){je.call(this,n,e)}function Uz(n,e){je.call(this,n,e)}function lg(n,e){je.call(this,n,e)}function xD(n,e){je.call(this,n,e)}function FD(n,e){je.call(this,n,e)}function BD(n,e){je.call(this,n,e)}function sC(n,e){je.call(this,n,e)}function Gz(n,e){this.b=n,this.a=e}function fC(n,e){je.call(this,n,e)}function zz(n,e){this.b=n,this.a=e}function hC(n,e){je.call(this,n,e)}function ACn(n,e){this.b=n,this.a=e}function Xz(n,e){je.call(this,n,e)}function RD(n,e){je.call(this,n,e)}function f7(n,e){je.call(this,n,e)}function b6(n,e,t){n.splice(e,0,t)}function sle(n,e,t){n.Mb(t)&&e.Cd(t)}function fle(n,e,t){e.Pe(n.a.Ye(t))}function hle(n,e,t){e.Dd(n.a.Ze(t))}function lle(n,e,t){e.Cd(n.a.Kb(t))}function ale(n,e){return Au(n.c,e)}function dle(n,e){return Au(n.e,e)}function lC(n,e){je.call(this,n,e)}function aC(n,e){je.call(this,n,e)}function w6(n,e){je.call(this,n,e)}function Vz(n,e){je.call(this,n,e)}function ei(n,e){je.call(this,n,e)}function dC(n,e){je.call(this,n,e)}function SCn(n,e){this.a=n,this.b=e}function PCn(n,e){this.a=n,this.b=e}function ICn(n,e){this.a=n,this.b=e}function OCn(n,e){this.a=n,this.b=e}function DCn(n,e){this.a=n,this.b=e}function LCn(n,e){this.a=n,this.b=e}function NCn(n,e){this.b=n,this.a=e}function $Cn(n,e){this.b=n,this.a=e}function Wz(n,e){this.b=n,this.a=e}function d4(n,e){this.c=n,this.d=e}function xCn(n,e){this.e=n,this.d=e}function FCn(n,e){this.a=n,this.b=e}function BCn(n,e){this.a=n,this.b=e}function RCn(n,e){this.a=n,this.b=e}function KCn(n,e){this.b=n,this.a=e}function _Cn(n,e){this.b=e,this.c=n}function bC(n,e){je.call(this,n,e)}function h7(n,e){je.call(this,n,e)}function KD(n,e){je.call(this,n,e)}function Jz(n,e){je.call(this,n,e)}function g6(n,e){je.call(this,n,e)}function _D(n,e){je.call(this,n,e)}function HD(n,e){je.call(this,n,e)}function l7(n,e){je.call(this,n,e)}function Qz(n,e){je.call(this,n,e)}function qD(n,e){je.call(this,n,e)}function p6(n,e){je.call(this,n,e)}function Yz(n,e){je.call(this,n,e)}function m6(n,e){je.call(this,n,e)}function v6(n,e){je.call(this,n,e)}function Db(n,e){je.call(this,n,e)}function UD(n,e){je.call(this,n,e)}function GD(n,e){je.call(this,n,e)}function Zz(n,e){je.call(this,n,e)}function a7(n,e){je.call(this,n,e)}function ag(n,e){je.call(this,n,e)}function zD(n,e){je.call(this,n,e)}function wC(n,e){je.call(this,n,e)}function d7(n,e){je.call(this,n,e)}function Lb(n,e){je.call(this,n,e)}function gC(n,e){je.call(this,n,e)}function nX(n,e){je.call(this,n,e)}function XD(n,e){je.call(this,n,e)}function VD(n,e){je.call(this,n,e)}function WD(n,e){je.call(this,n,e)}function JD(n,e){je.call(this,n,e)}function QD(n,e){je.call(this,n,e)}function YD(n,e){je.call(this,n,e)}function ZD(n,e){je.call(this,n,e)}function HCn(n,e){this.b=n,this.a=e}function eX(n,e){je.call(this,n,e)}function qCn(n,e){this.a=n,this.b=e}function UCn(n,e){this.a=n,this.b=e}function GCn(n,e){this.a=n,this.b=e}function tX(n,e){je.call(this,n,e)}function iX(n,e){je.call(this,n,e)}function zCn(n,e){this.a=n,this.b=e}function ble(n,e){return k4(),e!=n}function b7(n){return oe(n.a),n.b}function nL(n){return yCe(n,n.c),n}function XCn(){return tEn(),new TQn}function VCn(){VC(),this.a=new kV}function WCn(){OA(),this.a=new ni}function JCn(){NN(),this.b=new ni}function QCn(n,e){this.b=n,this.d=e}function YCn(n,e){this.a=n,this.b=e}function ZCn(n,e){this.a=n,this.b=e}function nMn(n,e){this.a=n,this.b=e}function eMn(n,e){this.b=n,this.a=e}function rX(n,e){je.call(this,n,e)}function cX(n,e){je.call(this,n,e)}function pC(n,e){je.call(this,n,e)}function u0(n,e){je.call(this,n,e)}function eL(n,e){je.call(this,n,e)}function mC(n,e){je.call(this,n,e)}function uX(n,e){je.call(this,n,e)}function oX(n,e){je.call(this,n,e)}function w7(n,e){je.call(this,n,e)}function sX(n,e){je.call(this,n,e)}function tL(n,e){je.call(this,n,e)}function vC(n,e){je.call(this,n,e)}function iL(n,e){je.call(this,n,e)}function rL(n,e){je.call(this,n,e)}function cL(n,e){je.call(this,n,e)}function uL(n,e){je.call(this,n,e)}function fX(n,e){je.call(this,n,e)}function oL(n,e){je.call(this,n,e)}function hX(n,e){je.call(this,n,e)}function g7(n,e){je.call(this,n,e)}function sL(n,e){je.call(this,n,e)}function lX(n,e){je.call(this,n,e)}function p7(n,e){je.call(this,n,e)}function aX(n,e){je.call(this,n,e)}function tMn(n,e){this.b=n,this.a=e}function iMn(n,e){this.b=n,this.a=e}function rMn(n,e){this.b=n,this.a=e}function cMn(n,e){this.b=n,this.a=e}function dX(n,e){this.a=n,this.b=e}function uMn(n,e){this.a=n,this.b=e}function oMn(n,e){this.a=n,this.b=e}function V(n,e){this.a=n,this.b=e}function k6(n,e){je.call(this,n,e)}function m7(n,e){je.call(this,n,e)}function wp(n,e){je.call(this,n,e)}function y6(n,e){je.call(this,n,e)}function v7(n,e){je.call(this,n,e)}function fL(n,e){je.call(this,n,e)}function kC(n,e){je.call(this,n,e)}function j6(n,e){je.call(this,n,e)}function hL(n,e){je.call(this,n,e)}function yC(n,e){je.call(this,n,e)}function dg(n,e){je.call(this,n,e)}function k7(n,e){je.call(this,n,e)}function E6(n,e){je.call(this,n,e)}function C6(n,e){je.call(this,n,e)}function y7(n,e){je.call(this,n,e)}function jC(n,e){je.call(this,n,e)}function bg(n,e){je.call(this,n,e)}function lL(n,e){je.call(this,n,e)}function sMn(n,e){je.call(this,n,e)}function EC(n,e){je.call(this,n,e)}function fMn(n,e){this.a=n,this.b=e}function hMn(n,e){this.a=n,this.b=e}function lMn(n,e){this.a=n,this.b=e}function aMn(n,e){this.a=n,this.b=e}function dMn(n,e){this.a=n,this.b=e}function bMn(n,e){this.a=n,this.b=e}function bi(n,e){this.a=n,this.b=e}function wMn(n,e){this.a=n,this.b=e}function gMn(n,e){this.a=n,this.b=e}function pMn(n,e){this.a=n,this.b=e}function mMn(n,e){this.a=n,this.b=e}function vMn(n,e){this.a=n,this.b=e}function kMn(n,e){this.a=n,this.b=e}function yMn(n,e){this.b=n,this.a=e}function jMn(n,e){this.b=n,this.a=e}function EMn(n,e){this.b=n,this.a=e}function CMn(n,e){this.b=n,this.a=e}function MMn(n,e){this.a=n,this.b=e}function TMn(n,e){this.a=n,this.b=e}function CC(n,e){je.call(this,n,e)}function AMn(n,e){this.a=n,this.b=e}function SMn(n,e){this.a=n,this.b=e}function gp(n,e){je.call(this,n,e)}function PMn(n,e){this.f=n,this.c=e}function bX(n,e){return Au(n.g,e)}function wle(n,e){return Au(e.b,n)}function IMn(n,e){return wx(n.a,e)}function gle(n,e){return-n.b.af(e)}function ple(n,e){n&&Xe(hE,n,e)}function wX(n,e){n.i=null,kT(n,e)}function mle(n,e,t){yKn(e,oF(n,t))}function vle(n,e,t){yKn(e,oF(n,t))}function kle(n,e){VMe(n.a,u(e,58))}function OMn(n,e){U4e(n.a,u(e,12))}function MC(n,e){this.a=n,this.b=e}function DMn(n,e){this.a=n,this.b=e}function LMn(n,e){this.a=n,this.b=e}function NMn(n,e){this.a=n,this.b=e}function $Mn(n,e){this.a=n,this.b=e}function xMn(n,e){this.d=n,this.b=e}function FMn(n,e){this.e=n,this.a=e}function j7(n,e){this.b=n,this.c=e}function gX(n,e){this.i=n,this.g=e}function pX(n,e){this.d=n,this.e=e}function yle(n,e){cme(new ne(n),e)}function TC(n){return Rk(n.c,n.b)}function Kr(n){return n?n.md():null}function x(n){return n??null}function Ai(n){return typeof n===nB}function Nb(n){return typeof n===i3}function $b(n){return typeof n===dtn}function o0(n,e){return Ec(n,e)==0}function AC(n,e){return Ec(n,e)>=0}function M6(n,e){return Ec(n,e)!=0}function SC(n,e){return jve(n.Kc(),e)}function _1(n,e){return n.Rd().Xb(e)}function BMn(n){return eo(n),n.d.gc()}function PC(n){return F6(n==null),n}function T6(n,e){return n.a+=""+e,n}function Er(n,e){return n.a+=""+e,n}function A6(n,e){return n.a+=""+e,n}function Dc(n,e){return n.a+=""+e,n}function Be(n,e){return n.a+=""+e,n}function mX(n,e){return n.a+=""+e,n}function jle(n){return""+(Jn(n),n)}function RMn(n){Hu(this),f5(this,n)}function KMn(){oJ(),dW.call(this)}function _Mn(n,e){mW.call(this,n,e)}function HMn(n,e){mW.call(this,n,e)}function IC(n,e){mW.call(this,n,e)}function ir(n,e){xt(n,e,n.c.b,n.c)}function wg(n,e){xt(n,e,n.a,n.a.a)}function vX(n){return Ln(n,0),null}function qMn(){this.b=0,this.a=!1}function UMn(){this.b=0,this.a=!1}function GMn(){this.b=new ap(Qb(12))}function zMn(){zMn=F,kYn=Ce(jx())}function XMn(){XMn=F,HZn=Ce(iqn())}function VMn(){VMn=F,lre=Ce(xxn())}function kX(){kX=F,_G(),fun=new de}function sf(n){return n.a=0,n.b=0,n}function WMn(n,e){return n.a=e.g+1,n}function aL(n,e){Kb.call(this,n,e)}function Mn(n,e){Dt.call(this,n,e)}function gg(n,e){gX.call(this,n,e)}function JMn(n,e){T7.call(this,n,e)}function dL(n,e){Y4.call(this,n,e)}function Ue(n,e){iC(),Xe(yO,n,e)}function QMn(n,e){n.q.setTime(id(e))}function Ele(n){y.clearTimeout(n)}function Cle(n){return Se(n),new S6(n)}function YMn(n,e){return x(n)===x(e)}function ZMn(n,e){return n.a.a.a.cc(e)}function bL(n,e){return qo(n.a,0,e)}function yX(n){return Awe(u(n,74))}function pp(n){return wi((Jn(n),n))}function Mle(n){return wi((Jn(n),n))}function nTn(n){return Yc(n.l,n.m,n.h)}function jX(n,e){return jc(n.a,e.a)}function Tle(n,e){return KPn(n.a,e.a)}function Ale(n,e){return bt(n.a,e.a)}function th(n,e){return n.indexOf(e)}function Sle(n,e){return n.j[e.p]==2}function s0(n,e){return n==e?0:n?1:-1}function OC(n){return n<10?"0"+n:""+n}function Vr(n){return typeof n===dtn}function Ple(n){return n==rb||n==Iw}function Ile(n){return n==rb||n==Pw}function eTn(n,e){return jc(n.g,e.g)}function EX(n){return qr(n.b.b,n,0)}function tTn(){rM.call(this,0,0,0,0)}function ih(){CG.call(this,new Ql)}function CX(n,e){F4(n,0,n.length,e)}function Ole(n,e){return nn(n.a,e),e}function Dle(n,e){return xs(),e.a+=n}function Lle(n,e){return xs(),e.a+=n}function Nle(n,e){return xs(),e.c+=n}function $le(n,e){return nn(n.c,e),n}function MX(n,e){return Mo(n.a,e),n}function iTn(n){this.a=XCn(),this.b=n}function rTn(n){this.a=XCn(),this.b=n}function rr(n){this.a=n.a,this.b=n.b}function S6(n){this.a=n,GO.call(this)}function cTn(n){this.a=n,GO.call(this)}function mp(){Ho.call(this,0,0,0,0)}function DC(n){return Mo(new ii,n)}function uTn(n){return jM(u(n,123))}function fo(n){return n.vh()&&n.wh()}function pg(n){return n!=Jf&&n!=Sa}function hl(n){return n==Br||n==Xr}function mg(n){return n==us||n==Vf}function oTn(n){return n==S2||n==A2}function xle(n,e){return jc(n.g,e.g)}function sTn(n,e){return new Y4(e,n)}function Fle(n,e){return new Y4(e,n)}function TX(n){return rbe(n.b.Kc(),n.a)}function wL(n,e){um(n,e),G4(n,n.D)}function gL(n,e,t){aT(n,e),lT(n,t)}function vg(n,e,t){I0(n,e),P0(n,t)}function Ro(n,e,t){eu(n,e),tu(n,t)}function E7(n,e,t){_4(n,e),q4(n,t)}function C7(n,e,t){H4(n,e),U4(n,t)}function fTn(n,e,t){sV.call(this,n,e,t)}function AX(n){PMn.call(this,n,!0)}function hTn(){uC.call(this,"Tail",3)}function lTn(){uC.call(this,"Head",1)}function H1(n){dh(),mve.call(this,n)}function f0(n){rM.call(this,n,n,n,n)}function pL(n){n.c=K(ki,Fn,1,0,5,1)}function SX(n){return n.b&&xF(n),n.a}function PX(n){return n.b&&xF(n),n.c}function Ble(n,e){qf||(n.b=e)}function Rle(n,e){return n[n.length]=e}function Kle(n,e){return n[n.length]=e}function _le(n,e){return Yb(e,Af(n))}function Hle(n,e){return Yb(e,Af(n))}function qle(n,e){return pT(dN(n.d),e)}function Ule(n,e){return pT(dN(n.g),e)}function Gle(n,e){return pT(dN(n.j),e)}function Ni(n,e){Dt.call(this,n.b,e)}function zle(n,e){ve(Sc(n.a),DOn(e))}function Xle(n,e){ve(no(n.a),LOn(e))}function Vle(n,e,t){Ro(t,t.i+n,t.j+e)}function aTn(n,e,t){$t(n.c[e.g],e.g,t)}function Wle(n,e,t){u(n.c,71).Gi(e,t)}function mL(n,e,t){return $t(n,e,t),t}function dTn(n){nu(n.Sf(),new D9n(n))}function kg(n){return n!=null?mt(n):0}function Jle(n){return n==null?0:mt(n)}function P6(n){nt(),Wd.call(this,n)}function bTn(n){this.a=n,qV.call(this,n)}function Mf(){Mf=F,y.Math.log(2)}function Ko(){Ko=F,rl=(pCn(),Moe)}function wTn(){wTn=F,YH=new j5(aU)}function Ie(){Ie=F,new gTn,new Z}function gTn(){new de,new de,new de}function Qle(){throw M(new Kl(QJn))}function Yle(){throw M(new Kl(QJn))}function Zle(){throw M(new Kl(YJn))}function n1e(){throw M(new Kl(YJn))}function vL(n){this.a=n,VE.call(this,n)}function kL(n){this.a=n,VE.call(this,n)}function pTn(n,e){m0(),this.a=n,this.b=e}function e1e(n,e){Se(e),Tg(n).Jc(new Ru)}function Yt(n,e){QL(n.c,n.c.length,e)}function tc(n){return n.ae?1:0}function OX(n,e){return Ec(n,e)>0?n:e}function Yc(n,e,t){return{l:n,m:e,h:t}}function t1e(n,e){n.a!=null&&OMn(e,n.a)}function i1e(n){Zi(n,null),Ii(n,null)}function r1e(n,e,t){return Xe(n.g,t,e)}function yg(n,e,t){return nZ(e,t,n.c)}function c1e(n,e,t){return Xe(n.k,t,e)}function u1e(n,e,t){return GOe(n,e,t),t}function o1e(n,e){return ko(),e.n.b+=n}function vTn(n){nJ.call(this),this.b=n}function DX(n){vV.call(this),this.a=n}function kTn(){uC.call(this,"Range",2)}function LC(n){this.b=n,this.a=new Z}function yTn(n){this.b=new $bn,this.a=n}function jTn(n){n.a=new OO,n.c=new OO}function ETn(n){n.a=new de,n.d=new de}function CTn(n){$N(n,null),xN(n,null)}function MTn(n,e){return XOe(n.a,e,null)}function s1e(n,e){return Xe(n.a,e.a,e)}function Ki(n){return new V(n.a,n.b)}function LX(n){return new V(n.c,n.d)}function f1e(n){return new V(n.c,n.d)}function I6(n,e){return cOe(n.c,n.b,e)}function O(n,e){return n!=null&&Tx(n,e)}function yL(n,e){return Yve(n.Kc(),e)!=-1}function NC(n){return n.Ob()?n.Pb():null}function h1e(n){this.b=(Dn(),new eD(n))}function NX(n){this.a=n,de.call(this)}function TTn(){T7.call(this,null,null)}function ATn(){_C.call(this,null,null)}function STn(){je.call(this,"INSTANCE",0)}function PTn(){LZ(),this.a=new K5(Ion)}function ITn(n){return hh(n,0,n.length)}function l1e(n,e){return new VTn(n.Kc(),e)}function $X(n,e){return n.a.Bc(e)!=null}function OTn(n,e){me(n),n.Gc(u(e,15))}function a1e(n,e,t){n.c.bd(e,u(t,136))}function d1e(n,e,t){n.c.Ui(e,u(t,136))}function DTn(n,e){n.c&&(tW(e),rOn(e))}function b1e(n,e){n.q.setHours(e),G5(n,e)}function w1e(n,e){a0(e,n.a.a.a,n.a.a.b)}function g1e(n,e,t,i){$t(n.a[e.g],t.g,i)}function jL(n,e,t){return n.a[e.g][t.g]}function p1e(n,e){return n.e[e.c.p][e.p]}function m1e(n,e){return n.c[e.c.p][e.p]}function Tf(n,e){return n.a[e.c.p][e.p]}function v1e(n,e){return n.j[e.p]=IMe(e)}function EL(n,e){return n.a.Bc(e)!=null}function k1e(n,e){return $(R(e.a))<=n}function y1e(n,e){return $(R(e.a))>=n}function j1e(n,e){return RJ(n.f,e.Pg())}function vp(n,e){return n.a*e.a+n.b*e.b}function E1e(n,e){return n.a0?e/(n*n):e*100}function V1e(n,e){return n>0?e*e/n:e*e*100}function xb(n,e){return u(Lf(n.a,e),34)}function W1e(n,e){return ca(),Pn(n,e.e,e)}function J1e(n,e,t){return nC(),t.Mg(n,e)}function Q1e(n){return kl(),n.e.a+n.f.a/2}function Y1e(n,e,t){return kl(),t.e.a-n*e}function Z1e(n){return kl(),n.e.b+n.f.b/2}function nae(n,e,t){return kl(),t.e.b-n*e}function sAn(n){n.d=new cAn(n),n.e=new de}function fAn(){this.a=new C0,this.b=new C0}function hAn(n){this.c=n,this.a=1,this.b=1}function lAn(n){YF(),Syn(this),this.Ff(n)}function eae(n,e,t){YM(),n.pf(e)&&t.Cd(n)}function tae(n,e,t){return nn(e,jBn(n,t))}function a0(n,e,t){return n.a+=e,n.b+=t,n}function iae(n,e,t){return n.a*=e,n.b*=t,n}function ZX(n,e){return n.a=e.a,n.b=e.b,n}function HC(n){return n.a=-n.a,n.b=-n.b,n}function N6(n,e,t){return n.a-=e,n.b-=t,n}function aAn(n){Ct.call(this),c5(this,n)}function dAn(){je.call(this,"GROW_TREE",0)}function bAn(){je.call(this,"POLYOMINO",0)}function lo(n,e,t){Iu.call(this,n,e,t,2)}function rae(n,e,t){k5(Sc(n.a),e,DOn(t))}function wAn(n,e){a6(),T7.call(this,n,e)}function nV(n,e){Gl(),_C.call(this,n,e)}function gAn(n,e){Gl(),nV.call(this,n,e)}function pAn(n,e){Gl(),_C.call(this,n,e)}function cae(n,e){return n.c.Fc(u(e,136))}function uae(n,e,t){k5(no(n.a),e,LOn(t))}function mAn(n){this.c=n,eu(n,0),tu(n,0)}function PL(n,e){Ko(),oM.call(this,n,e)}function vAn(n,e){Ko(),PL.call(this,n,e)}function eV(n,e){Ko(),PL.call(this,n,e)}function tV(n,e){Ko(),oM.call(this,n,e)}function kAn(n,e){Ko(),eV.call(this,n,e)}function yAn(n,e){Ko(),tV.call(this,n,e)}function jAn(n,e){Ko(),oM.call(this,n,e)}function oae(n,e,t){return e.zl(n.e,n.c,t)}function sae(n,e,t){return e.Al(n.e,n.c,t)}function iV(n,e,t){return qA(ak(n,e),t)}function IL(n,e){return na(n.e,u(e,54))}function fae(n){return n==null?null:NDe(n)}function hae(n){return n==null?null:Aje(n)}function lae(n){return n==null?null:Jr(n)}function aae(n){return n==null?null:Jr(n)}function un(n){return F6(n==null||Nb(n)),n}function R(n){return F6(n==null||$b(n)),n}function Oe(n){return F6(n==null||Ai(n)),n}function ll(n){n.o==null&&cMe(n)}function rV(n){if(!n)throw M(new Q9)}function dae(n){if(!n)throw M(new uD)}function oe(n){if(!n)throw M(new nc)}function Fb(n){if(!n)throw M(new Cu)}function EAn(n){if(!n)throw M(new Bo)}function m4(){m4=F,aE=new ujn,new ojn}function Mg(){Mg=F,O2=new lt("root")}function cV(){cxn.call(this),this.Bb|=hr}function bae(n,e){this.d=n,c9n(this),this.b=e}function uV(n,e){i$.call(this,n),this.a=e}function oV(n,e){i$.call(this,n),this.a=e}function sV(n,e,t){VM.call(this,n,e,t,null)}function CAn(n,e,t){VM.call(this,n,e,t,null)}function P7(n,e){this.c=n,h4.call(this,n,e)}function $6(n,e){this.a=n,P7.call(this,n,e)}function fV(n){this.q=new y.Date(id(n))}function MAn(n){return n>8?0:n+1}function TAn(n,e){qf||nn(n.a,e)}function wae(n,e){return o7(),Q4(e.d.i,n)}function gae(n,e){return Hp(),new tUn(e,n)}function pae(n,e,t){return n.Ne(e,t)<=0?t:e}function mae(n,e,t){return n.Ne(e,t)<=0?e:t}function vae(n,e){return u(Lf(n.b,e),143)}function kae(n,e){return u(Lf(n.c,e),233)}function OL(n){return u(sn(n.a,n.b),294)}function AAn(n){return new V(n.c,n.d+n.a)}function SAn(n){return Jn(n),n?1231:1237}function PAn(n){return ko(),oTn(u(n,203))}function Bb(){Bb=F,ron=yn((go(),Gd))}function yae(n,e){e.a?MCe(n,e):EL(n.a,e.b)}function I7(n,e,t){++n.j,n.tj(),t$(n,e,t)}function IAn(n,e,t){++n.j,n.qj(e,n.Zi(e,t))}function OAn(n,e,t){var i;i=n.fd(e),i.Rb(t)}function hV(n,e,t){return t=So(n,e,6,t),t}function lV(n,e,t){return t=So(n,e,3,t),t}function aV(n,e,t){return t=So(n,e,9,t),t}function ch(n,e){return X7(e,xtn),n.f=e,n}function dV(n,e){return(e&et)%n.d.length}function DAn(n,e,t){return zen(n.c,n.b,e,t)}function LAn(n,e){this.c=n,S0.call(this,e)}function NAn(n,e){this.a=n,kyn.call(this,e)}function O7(n,e){this.a=n,kyn.call(this,e)}function Dt(n,e){lt.call(this,n),this.a=e}function bV(n,e){FG.call(this,n),this.a=e}function DL(n,e){FG.call(this,n),this.a=e}function jae(n){VY.call(this,0,0),this.f=n}function $An(n,e,t){return n.a+=hh(e,0,t),n}function D7(n){return!n.a&&(n.a=new C0n),n.a}function wV(n,e){var t;return t=n.e,n.e=e,t}function gV(n,e){var t;return t=e,!!n.Fe(t)}function Eae(n,e){return _n(),n==e?0:n?1:-1}function Rb(n,e){n.a.bd(n.b,e),++n.b,n.c=-1}function L7(n){n.b?L7(n.b):n.f.c.zc(n.e,n.d)}function xAn(n){Hu(n.e),n.d.b=n.d,n.d.a=n.d}function Cae(n,e,t){Xa(),t9n(n,e.Ve(n.a,t))}function pV(n,e,t){return Pp(n,u(e,22),t)}function $s(n,e){return qE(new Array(e),n)}function Mae(n){return Ae(U1(n,32))^Ae(n)}function LL(n){return String.fromCharCode(n)}function Tae(n){return n==null?null:n.message}function Aae(n,e,t){return n.apply(e,t)}function Sae(n,e){var t;t=n[DB],t.call(n,e)}function Pae(n,e){var t;t=n[DB],t.call(n,e)}function Iae(n,e){return o7(),!Q4(e.d.i,n)}function mV(n,e,t,i){rM.call(this,n,e,t,i)}function FAn(){qC.call(this),this.a=new Li}function vV(){this.n=new Li,this.o=new Li}function BAn(){this.b=new Li,this.c=new Z}function RAn(){this.a=new Z,this.b=new Z}function KAn(){this.a=new _U,this.b=new Byn}function kV(){this.b=new Ql,this.a=new Ql}function _An(){this.b=new ni,this.a=new ni}function HAn(){this.b=new de,this.a=new de}function qAn(){this.b=new wEn,this.a=new H3n}function UAn(){this.a=new n8n,this.b=new Lpn}function GAn(){this.a=new Z,this.d=new Z}function qC(){this.n=new cp,this.i=new mp}function zAn(n){this.a=(Co(n,mw),new Gc(n))}function XAn(n){this.a=(Co(n,mw),new Gc(n))}function Oae(n){return n<100?null:new F1(n)}function Dae(n,e){return n.n.a=(Jn(e),e+10)}function Lae(n,e){return n.n.a=(Jn(e),e+10)}function Nae(n,e){return e==n||km(TA(e),n)}function VAn(n,e){return Xe(n.a,e,"")==null}function $ae(n,e){var t;return t=e.qi(n.a),t}function tt(n,e){return n.a+=e.a,n.b+=e.b,n}function mi(n,e){return n.a-=e.a,n.b-=e.b,n}function xae(n){return Pb(n.j.c,0),n.a=-1,n}function yV(n,e,t){return t=So(n,e,11,t),t}function Fae(n,e,t){t!=null&&mT(e,Fx(n,t))}function Bae(n,e,t){t!=null&&vT(e,Fx(n,t))}function jp(n,e,t,i){q.call(this,n,e,t,i)}function jV(n,e,t,i){q.call(this,n,e,t,i)}function WAn(n,e,t,i){jV.call(this,n,e,t,i)}function JAn(n,e,t,i){bM.call(this,n,e,t,i)}function NL(n,e,t,i){bM.call(this,n,e,t,i)}function EV(n,e,t,i){bM.call(this,n,e,t,i)}function QAn(n,e,t,i){NL.call(this,n,e,t,i)}function CV(n,e,t,i){NL.call(this,n,e,t,i)}function Nn(n,e,t,i){EV.call(this,n,e,t,i)}function YAn(n,e,t,i){CV.call(this,n,e,t,i)}function ZAn(n,e,t,i){jW.call(this,n,e,t,i)}function Kb(n,e){Ir.call(this,k8+n+Td+e)}function MV(n,e){return n.jk().wi().ri(n,e)}function TV(n,e){return n.jk().wi().ti(n,e)}function nSn(n,e){return Jn(n),x(n)===x(e)}function An(n,e){return Jn(n),x(n)===x(e)}function Rae(n,e){return n.b.Bd(new ECn(n,e))}function Kae(n,e){return n.b.Bd(new CCn(n,e))}function eSn(n,e){return n.b.Bd(new MCn(n,e))}function _ae(n,e){return n.e=u(n.d.Kb(e),159)}function AV(n,e,t){return n.lastIndexOf(e,t)}function Hae(n,e,t){return bt(n[e.a],n[t.a])}function qae(n,e){return U(e,(cn(),Cj),n)}function Uae(n,e){return jc(e.a.d.p,n.a.d.p)}function Gae(n,e){return jc(n.a.d.p,e.a.d.p)}function zae(n,e){return bt(n.c-n.s,e.c-e.s)}function Xae(n,e){return bt(n.b.e.a,e.b.e.a)}function Vae(n,e){return bt(n.c.e.a,e.c.e.a)}function tSn(n){return n.c?qr(n.c.a,n,0):-1}function Ep(n){return n==Ud||n==tl||n==qc}function SV(n,e){this.c=n,oN.call(this,n,e)}function iSn(n,e,t){this.a=n,JX.call(this,e,t)}function rSn(n){this.c=n,IC.call(this,Ey,0)}function cSn(n,e,t){this.c=e,this.b=t,this.a=n}function N7(n){k4(),this.d=n,this.a=new Eg}function uSn(n){uh(),this.a=(Dn(),new r4(n))}function Wae(n,e){hl(n.f)?QCe(n,e):Sye(n,e)}function oSn(n,e){sbe.call(this,n,n.length,e)}function Jae(n,e){qf||e&&(n.d=e)}function sSn(n,e){return O(e,15)&&xqn(n.c,e)}function Qae(n,e,t){return u(n.c,71).Wk(e,t)}function UC(n,e,t){return u(n.c,71).Xk(e,t)}function Yae(n,e,t){return oae(n,u(e,343),t)}function PV(n,e,t){return sae(n,u(e,343),t)}function Zae(n,e,t){return PKn(n,u(e,343),t)}function fSn(n,e,t){return _ye(n,u(e,343),t)}function x6(n,e){return e==null?null:tw(n.b,e)}function IV(n){return $b(n)?(Jn(n),n):n.ue()}function GC(n){return!isNaN(n)&&!isFinite(n)}function $L(n){jTn(this),vo(this),Bi(this,n)}function _u(n){pL(this),zV(this.c,0,n.Pc())}function _o(n,e,t){this.a=n,this.b=e,this.c=t}function hSn(n,e,t){this.a=n,this.b=e,this.c=t}function lSn(n,e,t){this.d=n,this.b=t,this.a=e}function aSn(n){this.a=n,fl(),vc(Date.now())}function dSn(n){bo(n.a),GJ(n.c,n.b),n.b=null}function xL(){xL=F,Oun=new $0n,AQn=new x0n}function bSn(){bSn=F,Ioe=K(ki,Fn,1,0,5,1)}function wSn(){wSn=F,Voe=K(ki,Fn,1,0,5,1)}function OV(){OV=F,Woe=K(ki,Fn,1,0,5,1)}function uh(){uh=F,new KG((Dn(),Dn(),sr))}function nde(n){return B4(),Ee((yNn(),IQn),n)}function ede(n){return Gu(),Ee((lNn(),xQn),n)}function tde(n){return YT(),Ee((JDn(),HQn),n)}function ide(n){return cT(),Ee((QDn(),qQn),n)}function rde(n){return NA(),Ee((Jxn(),UQn),n)}function cde(n){return bf(),Ee((fNn(),XQn),n)}function ude(n){return Uu(),Ee((sNn(),WQn),n)}function ode(n){return bu(),Ee((hNn(),QQn),n)}function sde(n){return VA(),Ee((zMn(),kYn),n)}function fde(n){return N0(),Ee((ENn(),jYn),n)}function hde(n){return Vp(),Ee((MNn(),CYn),n)}function lde(n){return A5(),Ee((CNn(),AYn),n)}function ade(n){return YE(),Ee((jDn(),SYn),n)}function dde(n){return uT(),Ee((YDn(),GYn),n)}function bde(n){return i5(),Ee((aNn(),pZn),n)}function wde(n){return Vi(),Ee((u$n(),yZn),n)}function gde(n){return nm(),Ee((ANn(),TZn),n)}function pde(n){return dd(),Ee((TNn(),DZn),n)}function DV(n,e){if(!n)throw M(new Gn(e))}function v4(n){if(!n)throw M(new Or(btn))}function FL(n,e){if(n!=e)throw M(new Bo)}function gSn(n,e,t){this.a=n,this.b=e,this.c=t}function LV(n,e,t){this.a=n,this.b=e,this.c=t}function pSn(n,e,t){this.a=n,this.b=e,this.c=t}function zC(n,e,t){this.b=n,this.a=e,this.c=t}function NV(n,e,t){this.b=n,this.c=e,this.a=t}function $V(n,e,t){this.a=n,this.b=e,this.c=t}function XC(n,e,t){this.e=e,this.b=n,this.d=t}function mSn(n,e,t){this.b=n,this.a=e,this.c=t}function mde(n,e,t){return Xa(),n.a.Yd(e,t),e}function BL(n){var e;return e=new ubn,e.e=n,e}function xV(n){var e;return e=new qyn,e.b=n,e}function $7(){$7=F,CP=new sgn,MP=new fgn}function VC(){VC=F,XZn=new xgn,zZn=new Fgn}function xs(){xs=F,YZn=new G2n,ZZn=new z2n}function vde(n){return D0(),Ee((qLn(),fne),n)}function kde(n){return tr(),Ee((XMn(),HZn),n)}function yde(n){return OT(),Ee((PNn(),GZn),n)}function jde(n){return $f(),Ee((SNn(),tne),n)}function Ede(n){return ow(),Ee((o$n(),rne),n)}function Cde(n){return DA(),Ee(($xn(),hne),n)}function Mde(n){return Yp(),Ee((D$n(),lne),n)}function Tde(n){return QM(),Ee((cLn(),ane),n)}function Ade(n){return u5(),Ee((_Ln(),dne),n)}function Sde(n){return bT(),Ee((HLn(),bne),n)}function Pde(n){return o1(),Ee((s$n(),wne),n)}function Ide(n){return pk(),Ee((eLn(),gne),n)}function Ode(n){return jm(),Ee(($$n(),jne),n)}function Dde(n){return pr(),Ee((aFn(),Ene),n)}function Lde(n){return Z4(),Ee((GLn(),Cne),n)}function Nde(n){return vl(),Ee((zLn(),Tne),n)}function $de(n){return KM(),Ee((nLn(),Ane),n)}function xde(n){return Jk(),Ee((N$n(),yne),n)}function Fde(n){return hd(),Ee((ULn(),mne),n)}function Bde(n){return vA(),Ee((L$n(),vne),n)}function Rde(n){return hk(),Ee((tLn(),kne),n)}function Kde(n){return Yo(),Ee((h$n(),Sne),n)}function _de(n){return a1(),Ee((Xxn(),Yte),n)}function Hde(n){return g5(),Ee((XLn(),Zte),n)}function qde(n){return cw(),Ee((INn(),nie),n)}function Ude(n){return T5(),Ee((f$n(),eie),n)}function Gde(n){return gs(),Ee((dFn(),tie),n)}function zde(n){return lh(),Ee((ONn(),iie),n)}function Xde(n){return wk(),Ee((iLn(),rie),n)}function Vde(n){return gr(),Ee((JLn(),uie),n)}function Wde(n){return ST(),Ee((VLn(),oie),n)}function Jde(n){return d5(),Ee((WLn(),sie),n)}function Qde(n){return om(),Ee((QLn(),fie),n)}function Yde(n){return dT(),Ee((YLn(),hie),n)}function Zde(n){return DT(),Ee((ZLn(),lie),n)}function n0e(n){return O0(),Ee((oNn(),Aie),n)}function e0e(n){return n5(),Ee((rLn(),Die),n)}function t0e(n){return sh(),Ee((sLn(),Rie),n)}function i0e(n){return Sf(),Ee((fLn(),_ie),n)}function r0e(n){return lf(),Ee((hLn(),tre),n)}function c0e(n){return M0(),Ee((lLn(),fre),n)}function u0e(n){return Qp(),Ee((BNn(),hre),n)}function o0e(n){return q5(),Ee((VMn(),lre),n)}function s0e(n){return b5(),Ee((nNn(),are),n)}function f0e(n){return w5(),Ee((FNn(),$re),n)}function h0e(n){return FM(),Ee((uLn(),xre),n)}function l0e(n){return yT(),Ee((oLn(),_re),n)}function a0e(n){return wA(),Ee((l$n(),qre),n)}function d0e(n){return Ok(),Ee((eNn(),Gre),n)}function b0e(n){return ZM(),Ee((aLn(),Ure),n)}function w0e(n){return sA(),Ee((xNn(),lce),n)}function g0e(n){return AT(),Ee((tNn(),ace),n)}function p0e(n){return XT(),Ee((iNn(),dce),n)}function m0e(n){return rA(),Ee((rNn(),wce),n)}function v0e(n){return _T(),Ee((cNn(),mce),n)}function k0e(n){return GM(),Ee((dLn(),Rce),n)}function y0e(n){return V4(),Ee((ZDn(),_Zn),n)}function j0e(n){return Vn(),Ee((x$n(),xZn),n)}function E0e(n){return nT(),Ee((uNn(),Kce),n)}function C0e(n){return N$(),Ee((bLn(),_ce),n)}function M0e(n){return R5(),Ee((a$n(),qce),n)}function T0e(n){return eC(),Ee((IDn(),Gce),n)}function A0e(n){return Fk(),Ee((bNn(),Uce),n)}function S0e(n){return tC(),Ee((ODn(),Xce),n)}function P0e(n){return ck(),Ee((wLn(),Vce),n)}function I0e(n){return Yk(),Ee((d$n(),Wce),n)}function O0e(n){return f6(),Ee((DDn(),lue),n)}function D0e(n){return Ak(),Ee((gLn(),aue),n)}function L0e(n){return gf(),Ee((w$n(),mue),n)}function N0e(n){return l1(),Ee((Lxn(),kue),n)}function $0e(n){return Rh(),Ee((F$n(),yue),n)}function x0e(n){return wd(),Ee((B$n(),Aue),n)}function F0e(n){return ci(),Ee((b$n(),zue),n)}function B0e(n){return Nf(),Ee((wNn(),Xue),n)}function R0e(n){return El(),Ee((RNn(),Vue),n)}function K0e(n){return pA(),Ee((R$n(),Wue),n)}function _0e(n){return jl(),Ee((dNn(),Que),n)}function H0e(n){return To(),Ee((KNn(),Zue),n)}function q0e(n){return lw(),Ee((Wxn(),noe),n)}function U0e(n){return Fg(),Ee((g$n(),eoe),n)}function G0e(n){return Oi(),Ee((K$n(),toe),n)}function z0e(n){return zu(),Ee((_$n(),ioe),n)}function X0e(n){return tn(),Ee((p$n(),roe),n)}function V0e(n){return go(),Ee((_Nn(),foe),n)}function W0e(n){return io(),Ee((Vxn(),hoe),n)}function J0e(n){return Gp(),Ee((gNn(),loe),n)}function Q0e(n,e){return Jn(n),n+(Jn(e),e)}function Y0e(n){return RL(),Ee((pLn(),aoe),n)}function Z0e(n){return qT(),Ee((HNn(),doe),n)}function nbe(n){return LT(),Ee((qNn(),goe),n)}function k4(){k4=F,tln=(tn(),Wn),II=Zn}function RL(){RL=F,vdn=new VSn,kdn=new LPn}function ebe(n){return!n.e&&(n.e=new Z),n.e}function KL(n,e){this.c=n,this.a=e,this.b=e-n}function vSn(n,e,t){this.a=n,this.b=e,this.c=t}function _L(n,e,t){this.a=n,this.b=e,this.c=t}function FV(n,e,t){this.a=n,this.b=e,this.c=t}function BV(n,e,t){this.a=n,this.b=e,this.c=t}function kSn(n,e,t){this.a=n,this.b=e,this.c=t}function ySn(n,e,t){this.a=n,this.b=e,this.c=t}function Xl(n,e,t){this.e=n,this.a=e,this.c=t}function jSn(n,e,t){Ko(),tJ.call(this,n,e,t)}function HL(n,e,t){Ko(),RW.call(this,n,e,t)}function RV(n,e,t){Ko(),RW.call(this,n,e,t)}function KV(n,e,t){Ko(),RW.call(this,n,e,t)}function ESn(n,e,t){Ko(),HL.call(this,n,e,t)}function _V(n,e,t){Ko(),HL.call(this,n,e,t)}function CSn(n,e,t){Ko(),_V.call(this,n,e,t)}function MSn(n,e,t){Ko(),RV.call(this,n,e,t)}function TSn(n,e,t){Ko(),KV.call(this,n,e,t)}function qL(n){rM.call(this,n.d,n.c,n.a,n.b)}function HV(n){rM.call(this,n.d,n.c,n.a,n.b)}function qV(n){this.d=n,c9n(this),this.b=nwe(n.d)}function tbe(n){return Cm(),Ee((Nxn(),Poe),n)}function x7(n,e){return Se(n),Se(e),new NEn(n,e)}function Cp(n,e){return Se(n),Se(e),new RSn(n,e)}function ibe(n,e){return Se(n),Se(e),new KSn(n,e)}function rbe(n,e){return Se(n),Se(e),new qEn(n,e)}function UL(n){return oe(n.b!=0),Xo(n,n.a.a)}function cbe(n){return oe(n.b!=0),Xo(n,n.c.b)}function ube(n){return!n.c&&(n.c=new W3),n.c}function y4(n){var e;return e=new Z,b$(e,n),e}function obe(n){var e;return e=new ni,b$(e,n),e}function ASn(n){var e;return e=new GG,A$(e,n),e}function F7(n){var e;return e=new Ct,A$(e,n),e}function u(n,e){return F6(n==null||Tx(n,e)),n}function sbe(n,e,t){TPn.call(this,e,t),this.a=n}function SSn(n,e){this.c=n,this.b=e,this.a=!1}function PSn(){this.a=";,;",this.b="",this.c=""}function ISn(n,e,t){this.b=n,_Mn.call(this,e,t)}function UV(n,e,t){this.c=n,oC.call(this,e,t)}function GV(n,e,t){d4.call(this,n,e),this.b=t}function zV(n,e,t){Bnn(t,0,n,e,t.length,!1)}function Lh(n,e,t,i,r){n.b=e,n.c=t,n.d=i,n.a=r}function XV(n,e,t,i,r){n.d=e,n.c=t,n.a=i,n.b=r}function fbe(n,e){e&&(n.b=e,n.a=(z1(e),e.a))}function B7(n,e){if(!n)throw M(new Gn(e))}function Mp(n,e){if(!n)throw M(new Or(e))}function VV(n,e){if(!n)throw M(new Bjn(e))}function hbe(n,e){return ZE(),jc(n.d.p,e.d.p)}function lbe(n,e){return kl(),bt(n.e.b,e.e.b)}function abe(n,e){return kl(),bt(n.e.a,e.e.a)}function dbe(n,e){return jc(GSn(n.d),GSn(e.d))}function WC(n,e){return e&&vM(n,e.d)?e:null}function bbe(n,e){return e==(tn(),Wn)?n.c:n.d}function WV(n){return Q1(dwe(Vr(n)?ds(n):n))}function wbe(n){return new V(n.c+n.b,n.d+n.a)}function OSn(n){return n!=null&&!lx(n,N9,$9)}function gbe(n,e){return(fBn(n)<<4|fBn(e))&ui}function DSn(n,e,t,i,r){n.c=e,n.d=t,n.b=i,n.a=r}function JV(n){var e,t;e=n.b,t=n.c,n.b=t,n.c=e}function QV(n){var e,t;t=n.d,e=n.a,n.d=e,n.a=t}function pbe(n,e){var t;return t=n.c,PQ(n,e),t}function YV(n,e){return e<0?n.g=-1:n.g=e,n}function JC(n,e){return Mme(n),n.a*=e,n.b*=e,n}function LSn(n,e,t){A$n.call(this,e,t),this.d=n}function R7(n,e,t){pX.call(this,n,e),this.c=t}function QC(n,e,t){pX.call(this,n,e),this.c=t}function ZV(n){OV(),ME.call(this),this.ci(n)}function NSn(){$4(),Bwe.call(this,(R1(),Ss))}function $Sn(n){return nt(),new Nh(0,n)}function xSn(){xSn=F,AU=(Dn(),new nD(IK))}function YC(){YC=F,new hZ((bD(),HK),(dD(),_K))}function FSn(){FSn=F,pun=K(Gi,J,17,256,0,1)}function BSn(){this.b=$(R(rn((qs(),y_))))}function GL(n){this.b=n,this.a=Wa(this.b.a).Od()}function RSn(n,e){this.b=n,this.a=e,GO.call(this)}function KSn(n,e){this.a=n,this.b=e,GO.call(this)}function _Sn(n,e,t){this.a=n,gg.call(this,e,t)}function HSn(n,e,t){this.a=n,gg.call(this,e,t)}function j4(n,e,t){var i;i=new qb(t),df(n,e,i)}function nW(n,e,t){var i;return i=n[e],n[e]=t,i}function ZC(n){var e;return e=n.slice(),o$(e,n)}function nM(n){var e;return e=n.n,n.a.b+e.d+e.a}function qSn(n){var e;return e=n.n,n.e.b+e.d+e.a}function eW(n){var e;return e=n.n,n.e.a+e.b+e.c}function tW(n){n.a.b=n.b,n.b.a=n.a,n.a=n.b=null}function xe(n,e){return xt(n,e,n.c.b,n.c),!0}function mbe(n){return n.a?n.a:vN(n)}function vbe(n){return Lp(),Kh(n)==At(ia(n))}function kbe(n){return Lp(),ia(n)==At(Kh(n))}function d0(n,e){return O5(n,new d4(e.a,e.b))}function ybe(n,e){return yM(),Nx(n,e),new lIn(n,e)}function jbe(n,e){return n.c=e)throw M(new YG)}function _b(n,e){return $k(n,(Jn(e),new a9n(e)))}function Ap(n,e){return $k(n,(Jn(e),new d9n(e)))}function SPn(n,e,t){return VLe(n,u(e,12),u(t,12))}function PPn(n){return Ou(),u(n,12).g.c.length!=0}function IPn(n){return Ou(),u(n,12).e.c.length!=0}function uwe(n,e){return Hp(),bt(e.a.o.a,n.a.o.a)}function owe(n,e){e.Bb&kc&&!n.a.o&&(n.a.o=e)}function swe(n,e){e.Ug("General 'Rotator",1),jDe(n)}function fwe(n,e,t){e.qf(t,$(R(ee(n.b,t)))*n.a)}function OPn(n,e,t){return Xg(),W4(n,e)&&W4(n,t)}function _6(n){return zu(),!n.Hc(Fl)&&!n.Hc(Pa)}function hwe(n){return n.e?qJ(n.e):null}function H6(n){return Vr(n)?""+n:$qn(n)}function yW(n){var e;for(e=n;e.f;)e=e.f;return e}function lwe(n,e,t){return $t(e,0,oW(e[0],t[0])),e}function Vl(n,e,t,i){var r;r=n.i,r.i=e,r.a=t,r.b=i}function q(n,e,t,i){ti.call(this,n,e,t),this.b=i}function Ci(n,e,t,i,r){c$.call(this,n,e,t,i,r,-1)}function q6(n,e,t,i,r){ok.call(this,n,e,t,i,r,-1)}function bM(n,e,t,i){R7.call(this,n,e,t),this.b=i}function DPn(n){PMn.call(this,n,!1),this.a=!1}function LPn(){sMn.call(this,"LOOKAHEAD_LAYOUT",1)}function NPn(n){this.b=n,kp.call(this,n),RTn(this)}function $Pn(n){this.b=n,A7.call(this,n),KTn(this)}function Hb(n,e,t){this.a=n,jp.call(this,e,t,5,6)}function jW(n,e,t,i){this.b=n,ti.call(this,e,t,i)}function xPn(n,e){this.b=n,H8n.call(this,n.b),this.a=e}function FPn(n){this.a=kRn(n.a),this.b=new _u(n.b)}function EW(n,e){m0(),Hhe.call(this,n,FT(new Ku(e)))}function wM(n,e){return nt(),new BW(n,e,0)}function rN(n,e){return nt(),new BW(6,n,e)}function _i(n,e){for(Jn(e);n.Ob();)e.Cd(n.Pb())}function Zc(n,e){return Ai(e)?AN(n,e):!!wr(n.f,e)}function cN(n,e){return e.Vh()?na(n.b,u(e,54)):e}function awe(n,e){return An(n.substr(0,e.length),e)}function $h(n){return new te(new UX(n.a.length,n.a))}function gM(n){return new V(n.c+n.b/2,n.d+n.a/2)}function dwe(n){return Yc(~n.l&ro,~n.m&ro,~n.h&Il)}function uN(n){return typeof n===vy||typeof n===eB}function Hu(n){n.f=new iTn(n),n.i=new rTn(n),++n.g}function BPn(n){if(!n)throw M(new nc);return n.d}function Sp(n){var e;return e=a5(n),oe(e!=null),e}function bwe(n){var e;return e=I5e(n),oe(e!=null),e}function C4(n,e){var t;return t=n.a.gc(),BJ(e,t),t-e}function fi(n,e){var t;return t=n.a.zc(e,n),t==null}function _7(n,e){return n.a.zc(e,(_n(),wa))==null}function CW(n){return new Tn(null,vwe(n,n.length))}function MW(n,e,t){return cGn(n,u(e,42),u(t,176))}function Pp(n,e,t){return Ks(n.a,e),nW(n.b,e.g,t)}function wwe(n,e,t){E4(t,n.a.c.length),Go(n.a,t,e)}function B(n,e,t,i){xFn(e,t,n.length),gwe(n,e,t,i)}function gwe(n,e,t,i){var r;for(r=e;r0?y.Math.log(n/e):-100}function KPn(n,e){return Ec(n,e)<0?-1:Ec(n,e)>0?1:0}function H7(n,e){OTn(n,O(e,160)?e:u(e,2036).Rl())}function PW(n,e){if(n==null)throw M(new sp(e))}function vwe(n,e){return yme(e,n.length),new XSn(n,e)}function IW(n,e){return e?Bi(n,e):!1}function kwe(){return RE(),S(T(uQn,1),G,549,0,[GK])}function G6(n){return n.e==0?n:new Qa(-n.e,n.d,n.a)}function ywe(n,e){return bt(n.c.c+n.c.b,e.c.c+e.c.b)}function q7(n,e){xt(n.d,e,n.b.b,n.b),++n.a,n.c=null}function _Pn(n,e){return n.c?_Pn(n.c,e):nn(n.b,e),n}function jwe(n,e,t){var i;return i=Jb(n,e),qN(n,e,t),i}function HPn(n,e,t){var i;for(i=0;i=n.g}function $t(n,e,t){return dae(t==null||oPe(n,t)),n[e]=t}function $W(n,e){return zn(e,n.length+1),n.substr(e)}function gN(n,e){for(Jn(e);n.c=n?new Dz:Gme(n-1)}function Hi(n){return!n.a&&n.c?n.c.b:n.a}function KW(n){return O(n,616)?n:new oOn(n)}function z1(n){n.c?z1(n.c):(ea(n),n.d=!0)}function V6(n){n.c?n.c.$e():(n.d=!0,fTe(n))}function sIn(n){n.b=!1,n.c=!1,n.d=!1,n.a=!1}function fIn(n){var e,t;return e=n.c.i.c,t=n.d.i.c,e==t}function _we(n,e){var t;t=n.Ih(e),t>=0?n.ki(t):Pnn(n,e)}function hIn(n,e){n.c<0||n.b.b0;)n=n<<1|(n<0?1:0);return n}function mIn(n,e){var t;return t=new Lc(n),Bn(e.c,t),t}function vIn(n,e){n.u.Hc((zu(),Fl))&&zEe(n,e),h4e(n,e)}function mc(n,e){return x(n)===x(e)||n!=null&&rt(n,e)}function Cr(n,e){return JL(n.a,e)?n.b[u(e,22).g]:null}function nge(){return YE(),S(T(oon,1),G,489,0,[b_])}function ege(){return eC(),S(T($1n,1),G,490,0,[Bq])}function tge(){return tC(),S(T(zce,1),G,558,0,[Rq])}function ige(){return f6(),S(T(tan,1),G,539,0,[Hj])}function jM(n){return!n.n&&(n.n=new q(Ar,n,1,7)),n.n}function mN(n){return!n.c&&(n.c=new q(Qu,n,9,9)),n.c}function UW(n){return!n.c&&(n.c=new Nn(he,n,5,8)),n.c}function rge(n){return!n.b&&(n.b=new Nn(he,n,4,7)),n.b}function U7(n){return n.j.c.length=0,zW(n.c),xae(n.a),n}function P4(n){return n.e==rv&&jfe(n,Y8e(n.g,n.b)),n.e}function G7(n){return n.f==rv&&Cfe(n,q7e(n.g,n.b)),n.f}function Ve(n,e,t,i){return Hxn(n,e,t,!1),BT(n,i),n}function kIn(n,e){this.b=n,oN.call(this,n,e),RTn(this)}function yIn(n,e){this.b=n,SV.call(this,n,e),KTn(this)}function W6(n){this.d=n,this.a=this.d.b,this.b=this.d.c}function GW(n,e){this.b=n,this.c=e,this.a=new dp(this.b)}function Xi(n,e){return zn(e,n.length),n.charCodeAt(e)}function cge(n,e){DY(n,$(yl(e,"x")),$(yl(e,"y")))}function uge(n,e){DY(n,$(yl(e,"x")),$(yl(e,"y")))}function ut(n,e){return ea(n),new Tn(n,new tQ(e,n.a))}function _r(n,e){return ea(n),new Tn(n,new _J(e,n.a))}function Ub(n,e){return ea(n),new uV(n,new ILn(e,n.a))}function EM(n,e){return ea(n),new oV(n,new OLn(e,n.a))}function oge(n,e){return new GIn(u(Se(n),50),u(Se(e),50))}function sge(n,e){return bt(n.d.c+n.d.b/2,e.d.c+e.d.b/2)}function jIn(n,e,t){t.a?tu(n,e.b-n.f/2):eu(n,e.a-n.g/2)}function fge(n,e){return bt(n.g.c+n.g.b/2,e.g.c+e.g.b/2)}function hge(n,e){return $z(),bt((Jn(n),n),(Jn(e),e))}function lge(n){return n!=null&&r7(jO,n.toLowerCase())}function zW(n){var e;for(e=n.Kc();e.Ob();)e.Pb(),e.Qb()}function Tg(n){var e;return e=n.b,!e&&(n.b=e=new N8n(n)),e}function vN(n){var e;return e=Wme(n),e||null}function EIn(n,e){var t,i;return t=n/e,i=wi(t),t>i&&++i,i}function age(n,e,t){var i;i=u(n.d.Kb(t),159),i&&i.Nb(e)}function dge(n,e,t){wIe(n.a,t),zve(t),xCe(n.b,t),$Ie(e,t)}function CM(n,e,t,i){this.a=n,this.c=e,this.b=t,this.d=i}function XW(n,e,t,i){this.c=n,this.b=e,this.a=t,this.d=i}function CIn(n,e,t,i){this.c=n,this.b=e,this.d=t,this.a=i}function Ho(n,e,t,i){this.c=n,this.d=e,this.b=t,this.a=i}function MIn(n,e,t,i){this.a=n,this.d=e,this.c=t,this.b=i}function kN(n,e,t,i){this.a=n,this.e=e,this.d=t,this.c=i}function TIn(n,e,t,i){this.a=n,this.c=e,this.d=t,this.b=i}function yN(n,e,t){this.a=ktn,this.d=n,this.b=e,this.c=t}function Op(n,e,t,i){je.call(this,n,e),this.a=t,this.b=i}function AIn(n,e){this.d=(Jn(n),n),this.a=16449,this.c=e}function SIn(n){this.a=new Z,this.e=K(ye,J,53,n,0,2)}function bge(n){n.Ug("No crossing minimization",1),n.Vg()}function PIn(){ec.call(this,"There is no more element.")}function IIn(n,e,t,i){this.a=n,this.b=e,this.c=t,this.d=i}function OIn(n,e,t,i){this.a=n,this.b=e,this.c=t,this.d=i}function Za(n,e,t,i){this.e=n,this.a=e,this.c=t,this.d=i}function DIn(n,e,t,i){this.a=n,this.c=e,this.d=t,this.b=i}function LIn(n,e,t,i){Ko(),DLn.call(this,e,t,i),this.a=n}function NIn(n,e,t,i){Ko(),DLn.call(this,e,t,i),this.a=n}function jN(n,e,t){var i,r;return i=utn(n),r=e.ti(t,i),r}function al(n){var e,t;return t=(e=new Jd,e),K4(t,n),t}function EN(n){var e,t;return t=(e=new Jd,e),fnn(t,n),t}function wge(n,e){var t;return t=ee(n.f,e),HQ(e,t),null}function $In(n){return!n.b&&(n.b=new q(Vt,n,12,3)),n.b}function xIn(n){return F6(n==null||uN(n)&&n.Tm!==J2),n}function MM(n){return n.n&&(n.e!==Fzn&&n.je(),n.j=null),n}function I4(n){if(eo(n.d),n.d.d!=n.c)throw M(new Bo)}function VW(n){return oe(n.b0&&bKn(this)}function FIn(n,e){this.a=n,bae.call(this,n,u(n.d,15).fd(e))}function gge(n,e){return bt(Su(n)*ao(n),Su(e)*ao(e))}function pge(n,e){return bt(Su(n)*ao(n),Su(e)*ao(e))}function mge(n){return _0(n)&&on(un(z(n,(cn(),Nd))))}function vge(n,e){return Pn(n,u(v(e,(cn(),Cv)),17),e)}function kge(n,e){return u(v(n,(W(),T3)),15).Fc(e),e}function WW(n,e){return n.b=e.b,n.c=e.c,n.d=e.d,n.a=e.a,n}function BIn(n,e,t,i){this.b=n,this.c=i,IC.call(this,e,t)}function yge(n,e,t){n.i=0,n.e=0,e!=t&&yFn(n,e,t)}function jge(n,e,t){n.i=0,n.e=0,e!=t&&jFn(n,e,t)}function Ege(n,e,t){return s6(),J5e(u(ee(n.e,e),529),t)}function Dp(n){var e;return e=n.f,e||(n.f=new h4(n,n.c))}function RIn(n,e){return xg(n.j,e.s,e.c)+xg(e.e,n.s,n.c)}function KIn(n,e){n.e&&!n.e.a&&(Ayn(n.e,e),KIn(n.e,e))}function _In(n,e){n.d&&!n.d.a&&(Ayn(n.d,e),_In(n.d,e))}function Cge(n,e){return-bt(Su(n)*ao(n),Su(e)*ao(e))}function Mge(n){return u(n.ld(),149).Pg()+":"+Jr(n.md())}function HIn(){tF(this,new oG),this.wb=(G1(),Hn),o4()}function qIn(n){this.b=new Z,hi(this.b,this.b),this.a=n}function JW(n,e){new Ct,this.a=new Mu,this.b=n,this.c=e}function j0(){j0=F,Pun=new FU,ZK=new FU,Iun=new D0n}function Dn(){Dn=F,sr=new A0n,Wh=new P0n,hP=new I0n}function QW(){QW=F,RQn=new nbn,_Qn=new aW,KQn=new ebn}function Lp(){Lp=F,mP=new Z,m_=new de,p_=new Z}function TM(n,e){if(n==null)throw M(new sp(e));return n}function AM(n){return!n.a&&(n.a=new q(Qe,n,10,11)),n.a}function ft(n){return!n.q&&(n.q=new q(As,n,11,10)),n.q}function _(n){return!n.s&&(n.s=new q(ku,n,21,17)),n.s}function Tge(n){return Se(n),IRn(new te(re(n.a.Kc(),new En)))}function Age(n,e){return wo(n),wo(e),Fjn(u(n,22),u(e,22))}function nd(n,e,t){var i,r;i=IV(t),r=new AE(i),df(n,e,r)}function MN(n,e,t,i,r,c){ok.call(this,n,e,t,i,r,c?-2:-1)}function UIn(n,e,t,i){pX.call(this,e,t),this.b=n,this.a=i}function GIn(n,e){Vfe.call(this,new iN(n)),this.a=n,this.b=e}function YW(n){this.b=n,this.c=n,n.e=null,n.c=null,this.a=1}function Sge(n){xs();var e;e=u(n.g,10),e.n.a=n.d.c+e.d.b}function O4(){O4=F;var n,e;e=!$8e(),n=new V3,VK=e?new og:n}function TN(n){return Dn(),O(n,59)?new jD(n):new BC(n)}function SM(n){return O(n,16)?new B6(u(n,16)):obe(n.Kc())}function Pge(n){return new HTn(n,n.e.Rd().gc()*n.c.Rd().gc())}function Ige(n){return new qTn(n,n.e.Rd().gc()*n.c.Rd().gc())}function ZW(n){return n&&n.hashCode?n.hashCode():l0(n)}function AN(n,e){return e==null?!!wr(n.f,null):zbe(n.i,e)}function Oge(n,e){var t;return t=$X(n.a,e),t&&(e.d=null),t}function zIn(n,e,t){return n.f?n.f.ef(e,t):!1}function z7(n,e,t,i){$t(n.c[e.g],t.g,i),$t(n.c[t.g],e.g,i)}function SN(n,e,t,i){$t(n.c[e.g],e.g,t),$t(n.b[e.g],e.g,i)}function Dge(n,e,t){return $(R(t.a))<=n&&$(R(t.b))>=e}function XIn(n,e){this.g=n,this.d=S(T(Qh,1),b1,10,0,[e])}function VIn(n){this.c=n,this.b=new Ul(u(Se(new tbn),50))}function WIn(n){this.c=n,this.b=new Ul(u(Se(new ewn),50))}function JIn(n){this.b=n,this.a=new Ul(u(Se(new Nbn),50))}function QIn(){this.b=new ni,this.d=new Ct,this.e=new ZG}function nJ(){this.c=new Li,this.d=new Li,this.e=new Li}function E0(){this.a=new Mu,this.b=(Co(3,mw),new Gc(3))}function Wl(n,e){this.e=n,this.a=ki,this.b=Qqn(e),this.c=e}function PM(n){this.c=n.c,this.d=n.d,this.b=n.b,this.a=n.a}function YIn(n,e,t,i,r,c){this.a=n,k$.call(this,e,t,i,r,c)}function ZIn(n,e,t,i,r,c){this.a=n,k$.call(this,e,t,i,r,c)}function X1(n,e,t,i,r,c,s){return new GN(n.e,e,t,i,r,c,s)}function Lge(n,e,t){return t>=0&&An(n.substr(t,e.length),e)}function nOn(n,e){return O(e,149)&&An(n.b,u(e,149).Pg())}function Nge(n,e){return n.a?e.Gh().Kc():u(e.Gh(),71).Ii()}function eOn(n,e){var t;return t=n.b.Qc(e),WDn(t,n.b.gc()),t}function X7(n,e){if(n==null)throw M(new sp(e));return n}function Hr(n){return n.u||(Zu(n),n.u=new NAn(n,n)),n.u}function PN(n){this.a=(Dn(),O(n,59)?new jD(n):new BC(n))}function au(n){var e;return e=u(Un(n,16),29),e||n.ii()}function IM(n,e){var t;return t=za(n.Rm),e==null?t:t+": "+e}function qo(n,e,t){return Fi(e,t,n.length),n.substr(e,t-e)}function tOn(n,e){qC.call(this),lQ(this),this.a=n,this.c=e}function $ge(n){n&&IM(n,n.ie())}function xge(n){HE(),y.setTimeout(function(){throw n},0)}function Fge(){return YT(),S(T(Bun,1),G,436,0,[o_,Fun])}function Bge(){return cT(),S(T(Kun,1),G,435,0,[Run,s_])}function Rge(){return uT(),S(T(bon,1),G,432,0,[v_,vP])}function Kge(){return V4(),S(T(KZn,1),G,517,0,[dj,L_])}function _ge(){return KM(),S(T(Qsn,1),G,429,0,[fH,Jsn])}function Hge(){return pk(),S(T($sn,1),G,428,0,[WP,Nsn])}function qge(){return QM(),S(T(Asn,1),G,431,0,[Tsn,V_])}function Uge(){return wk(),S(T(qhn,1),G,430,0,[UH,GH])}function Gge(){return n5(),S(T(Oie,1),G,531,0,[r9,i9])}function zge(){return yT(),S(T(Rln,1),G,501,0,[RI,D2])}function Xge(){return sh(),S(T(Bie,1),G,523,0,[mb,y1])}function Vge(){return Sf(),S(T(Kie,1),G,522,0,[Rd,zf])}function Wge(){return lf(),S(T(ere,1),G,528,0,[zw,ja])}function Jge(){return hk(),S(T(Bsn,1),G,488,0,[Fsn,QP])}function Qge(){return GM(),S(T(S1n,1),G,491,0,[$q,A1n])}function Yge(){return N$(),S(T(N1n,1),G,492,0,[D1n,L1n])}function Zge(){return FM(),S(T(Bln,1),G,433,0,[dq,Fln])}function n2e(){return ZM(),S(T(_ln,1),G,434,0,[Kln,vq])}function e2e(){return M0(),S(T(sre,1),G,465,0,[Ea,P2])}function t2e(){return ck(),S(T(x1n,1),G,438,0,[Kq,JI])}function i2e(){return Ak(),S(T(ran,1),G,437,0,[YI,ian])}function r2e(){return RL(),S(T(dO,1),G,347,0,[vdn,kdn])}function OM(n,e,t,i){return t>=0?n.Uh(e,t,i):n.Ch(null,t,i)}function V7(n){return n.b.b==0?n.a.sf():UL(n.b)}function c2e(n){if(n.p!=5)throw M(new Cu);return Ae(n.f)}function u2e(n){if(n.p!=5)throw M(new Cu);return Ae(n.k)}function eJ(n){return x(n.a)===x((D$(),CU))&&rOe(n),n.a}function o2e(n,e){n.b=e,n.c>0&&n.b>0&&(n.g=cM(n.c,n.b,n.a))}function s2e(n,e){n.c=e,n.c>0&&n.b>0&&(n.g=cM(n.c,n.b,n.a))}function iOn(n,e){ufe(this,new V(n.a,n.b)),ofe(this,F7(e))}function C0(){Wfe.call(this,new ap(Qb(12))),KX(!0),this.a=2}function IN(n,e,t){nt(),Wd.call(this,n),this.b=e,this.a=t}function tJ(n,e,t){Ko(),LE.call(this,e),this.a=n,this.b=t}function rOn(n){var e;e=n.c.d.b,n.b=e,n.a=n.c.d,e.a=n.c.d.b=n}function f2e(n){return n.b==0?null:(oe(n.b!=0),Xo(n,n.a.a))}function Nc(n,e){return e==null?Kr(wr(n.f,null)):d6(n.i,e)}function cOn(n,e,t,i,r){return new rF(n,(B4(),i_),e,t,i,r)}function DM(n,e){return zDn(e),Lme(n,K(ye,Ke,28,e,15,1),e)}function LM(n,e){return TM(n,"set1"),TM(e,"set2"),new VEn(n,e)}function h2e(n,e){var t=XK[n.charCodeAt(0)];return t??n}function uOn(n,e){var t,i;return t=e,i=new DO,LGn(n,t,i),i.d}function ON(n,e,t,i){var r;r=new FAn,e.a[t.g]=r,Pp(n.b,i,r)}function l2e(n,e){var t;return t=Ime(n.f,e),tt(HC(t),n.f.d)}function W7(n){var e;_me(n.a),dTn(n.a),e=new IE(n.a),HY(e)}function a2e(n,e){_qn(n,!0),nu(n.e.Rf(),new NV(n,!0,e))}function d2e(n,e){return Lp(),n==At(Kh(e))||n==At(ia(e))}function b2e(n,e){return kl(),u(v(e,(lc(),Sh)),17).a==n}function wi(n){return Math.max(Math.min(n,et),-2147483648)|0}function oOn(n){this.a=u(Se(n),277),this.b=(Dn(),new XX(n))}function sOn(n,e,t){this.i=new Z,this.b=n,this.g=e,this.a=t}function iJ(n,e,t){this.a=new Z,this.e=n,this.f=e,this.c=t}function NM(n,e,t){this.c=new Z,this.e=n,this.f=e,this.b=t}function fOn(n){qC.call(this),lQ(this),this.a=n,this.c=!0}function w2e(n){function e(){}return e.prototype=n||{},new e}function g2e(n){if(n.Ae())return null;var e=n.n;return rP[e]}function J7(n){return n.Db>>16!=3?null:u(n.Cb,27)}function Af(n){return n.Db>>16!=9?null:u(n.Cb,27)}function hOn(n){return n.Db>>16!=6?null:u(n.Cb,74)}function M0(){M0=F,Ea=new cX(s3,0),P2=new cX(f3,1)}function sh(){sh=F,mb=new tX(f3,0),y1=new tX(s3,1)}function Sf(){Sf=F,Rd=new iX(_B,0),zf=new iX("UP",1)}function lOn(){lOn=F,oQn=Ce((RE(),S(T(uQn,1),G,549,0,[GK])))}function aOn(n){var e;return e=new zE(Qb(n.length)),eY(e,n),e}function dOn(n,e){return n.b+=e.b,n.c+=e.c,n.d+=e.d,n.a+=e.a,n}function p2e(n,e){return Zxn(n,e)?(W$n(n),!0):!1}function dl(n,e){if(e==null)throw M(new ip);return F8e(n,e)}function Q7(n,e){var t;t=n.q.getHours(),n.q.setDate(e),G5(n,t)}function rJ(n,e,t){var i;i=n.Ih(e),i>=0?n.bi(i,t):ten(n,e,t)}function bOn(n,e){var t;return t=n.Ih(e),t>=0?n.Wh(t):hF(n,e)}function wOn(n,e){var t;for(Se(e),t=n.a;t;t=t.c)e.Yd(t.g,t.i)}function DN(n,e,t){var i;i=vFn(n,e,t),n.b=new ET(i.c.length)}function Ag(n,e,t){$M(),n&&Xe(yU,n,e),n&&Xe(hE,n,t)}function m2e(n,e){return VC(),_n(),u(e.a,17).a0}function cJ(n){var e;return e=n.d,e=n.bj(n.f),ve(n,e),e.Ob()}function gOn(n,e){var t;return t=new fW(e),_Kn(t,n),new _u(t)}function y2e(n){if(n.p!=0)throw M(new Cu);return M6(n.f,0)}function j2e(n){if(n.p!=0)throw M(new Cu);return M6(n.k,0)}function pOn(n){return n.Db>>16!=7?null:u(n.Cb,241)}function D4(n){return n.Db>>16!=6?null:u(n.Cb,241)}function mOn(n){return n.Db>>16!=7?null:u(n.Cb,167)}function At(n){return n.Db>>16!=11?null:u(n.Cb,27)}function Gb(n){return n.Db>>16!=17?null:u(n.Cb,29)}function vOn(n){return n.Db>>16!=3?null:u(n.Cb,155)}function uJ(n){var e;return ea(n),e=new ni,ut(n,new M9n(e))}function kOn(n,e){var t=n.a=n.a||[];return t[e]||(t[e]=n.ve(e))}function E2e(n,e){var t;t=n.q.getHours(),n.q.setMonth(e),G5(n,t)}function yOn(n,e){xC(this),this.f=e,this.g=n,MM(this),this.je()}function jOn(n,e){this.a=n,this.c=Ki(this.a),this.b=new PM(e)}function EOn(n,e,t){this.a=e,this.c=n,this.b=(Se(t),new _u(t))}function COn(n,e,t){this.a=e,this.c=n,this.b=(Se(t),new _u(t))}function MOn(n){this.a=n,this.b=K(Sie,J,2043,n.e.length,0,2)}function TOn(){this.a=new ih,this.e=new ni,this.g=0,this.i=0}function $M(){$M=F,yU=new de,hE=new de,ple(MQn,new wvn)}function AOn(){AOn=F,aie=Pu(new ii,(Vi(),zr),(tr(),bj))}function oJ(){oJ=F,die=Pu(new ii,(Vi(),zr),(tr(),bj))}function SOn(){SOn=F,wie=Pu(new ii,(Vi(),zr),(tr(),bj))}function POn(){POn=F,Lie=Re(new ii,(Vi(),zr),(tr(),x8))}function ko(){ko=F,xie=Re(new ii,(Vi(),zr),(tr(),x8))}function IOn(){IOn=F,Fie=Re(new ii,(Vi(),zr),(tr(),x8))}function NN(){NN=F,Hie=Re(new ii,(Vi(),zr),(tr(),x8))}function J6(n,e,t,i,r,c){return new ml(n.e,e,n.Lj(),t,i,r,c)}function Dr(n,e,t){return e==null?Vc(n.f,null,t):$0(n.i,e,t)}function Zi(n,e){n.c&&du(n.c.g,n),n.c=e,n.c&&nn(n.c.g,n)}function $i(n,e){n.c&&du(n.c.a,n),n.c=e,n.c&&nn(n.c.a,n)}function ic(n,e){n.i&&du(n.i.j,n),n.i=e,n.i&&nn(n.i.j,n)}function Ii(n,e){n.d&&du(n.d.e,n),n.d=e,n.d&&nn(n.d.e,n)}function $N(n,e){n.a&&du(n.a.k,n),n.a=e,n.a&&nn(n.a.k,n)}function xN(n,e){n.b&&du(n.b.f,n),n.b=e,n.b&&nn(n.b.f,n)}function OOn(n,e){$we(n,n.b,n.c),u(n.b.b,68),e&&u(e.b,68).b}function C2e(n,e){return bt(u(n.c,65).c.e.b,u(e.c,65).c.e.b)}function M2e(n,e){return bt(u(n.c,65).c.e.a,u(e.c,65).c.e.a)}function T2e(n){return Y$(),_n(),u(n.a,86).d.e!=0}function xM(n,e){O(n.Cb,184)&&(u(n.Cb,184).tb=null),zc(n,e)}function FN(n,e){O(n.Cb,90)&&hw(Zu(u(n.Cb,90)),4),zc(n,e)}function A2e(n,e){LY(n,e),O(n.Cb,90)&&hw(Zu(u(n.Cb,90)),2)}function S2e(n,e){var t,i;t=e.c,i=t!=null,i&&Ip(n,new qb(e.c))}function DOn(n){var e,t;return t=(o4(),e=new Jd,e),K4(t,n),t}function LOn(n){var e,t;return t=(o4(),e=new Jd,e),K4(t,n),t}function NOn(n){for(var e;;)if(e=n.Pb(),!n.Ob())return e}function P2e(n,e,t){return nn(n.a,(yM(),Nx(e,t),new i0(e,t))),n}function $c(n,e){return dr(),a$(e)?new eM(e,n):new j7(e,n)}function Y7(n){return dh(),Ec(n,0)>=0?ta(n):G6(ta(n1(n)))}function I2e(n){var e;return e=u(ZC(n.b),9),new _o(n.a,e,n.c)}function $On(n,e){var t;return t=u(tw(Dp(n.a),e),16),t?t.gc():0}function xOn(n,e,t){var i;oBn(e,t,n.c.length),i=t-e,Pz(n.c,e,i)}function Jl(n,e,t){oBn(e,t,n.gc()),this.c=n,this.a=e,this.b=t-e}function Np(n){this.c=new Ct,this.b=n.b,this.d=n.c,this.a=n.a}function BN(n){this.a=y.Math.cos(n),this.b=y.Math.sin(n)}function ed(n,e,t,i){this.c=n,this.d=i,$N(this,e),xN(this,t)}function sJ(n,e){Xfe.call(this,new ap(Qb(n))),Co(e,Ozn),this.a=e}function FOn(n,e,t){return new rF(n,(B4(),t_),null,!1,e,t)}function BOn(n,e,t){return new rF(n,(B4(),r_),e,t,null,!1)}function O2e(){return Gu(),S(T(xr,1),G,108,0,[xun,Yr,Aw])}function D2e(){return bu(),S(T(JQn,1),G,472,0,[vf,pa,zs])}function L2e(){return Uu(),S(T(VQn,1),G,471,0,[Mh,ga,Gs])}function N2e(){return bf(),S(T(Sw,1),G,237,0,[bc,Wc,wc])}function $2e(){return i5(),S(T(Pon,1),G,391,0,[E_,j_,C_])}function x2e(){return D0(),S(T(R_,1),G,372,0,[ub,ma,cb])}function F2e(){return u5(),S(T(Psn,1),G,322,0,[B8,pj,Ssn])}function B2e(){return bT(),S(T(Osn,1),G,351,0,[Isn,VP,W_])}function R2e(){return hd(),S(T(pne,1),G,460,0,[Y_,mv,p2])}function K2e(){return Z4(),S(T(sH,1),G,299,0,[uH,oH,mj])}function _2e(){return vl(),S(T(Mne,1),G,311,0,[vj,v2,E3])}function H2e(){return g5(),S(T(Lhn,1),G,390,0,[FH,Dhn,MI])}function q2e(){return gr(),S(T(cie,1),G,463,0,[n9,Vu,Jc])}function U2e(){return ST(),S(T(zhn,1),G,387,0,[Uhn,zH,Ghn])}function G2e(){return d5(),S(T(Xhn,1),G,349,0,[VH,XH,Ij])}function z2e(){return om(),S(T(Whn,1),G,350,0,[WH,Vhn,e9])}function X2e(){return dT(),S(T(Yhn,1),G,352,0,[Qhn,JH,Jhn])}function V2e(){return DT(),S(T(Zhn,1),G,388,0,[QH,Ov,Gw])}function W2e(){return O0(),S(T(Tie,1),G,464,0,[Oj,t9,PI])}function Pf(n){return cc(S(T(Ei,1),J,8,0,[n.i.n,n.n,n.a]))}function J2e(){return b5(),S(T(gln,1),G,392,0,[wln,nq,Lj])}function ROn(){ROn=F,Fre=Pu(new ii,(Qp(),u9),(q5(),uln))}function FM(){FM=F,dq=new uX("DFS",0),Fln=new uX("BFS",1)}function KOn(n,e,t){var i;i=new E3n,i.b=e,i.a=t,++e.b,nn(n.d,i)}function Q2e(n,e,t){var i;i=new rr(t.d),tt(i,n),DY(e,i.a,i.b)}function Y2e(n,e){LTn(n,Ae(vi(w0(e,24),YA)),Ae(vi(e,YA)))}function zb(n,e){if(n<0||n>e)throw M(new Ir(Ptn+n+Itn+e))}function Ln(n,e){if(n<0||n>=e)throw M(new Ir(Ptn+n+Itn+e))}function zn(n,e){if(n<0||n>=e)throw M(new gz(Ptn+n+Itn+e))}function In(n,e){this.b=(Jn(n),n),this.a=e&vw?e:e|64|wh}function fJ(n){var e;return ea(n),e=(j0(),j0(),ZK),fT(n,e)}function Z2e(n,e,t){var i;return i=V5(n,e,!1),i.b<=e&&i.a<=t}function npe(){return nT(),S(T(O1n,1),G,439,0,[xq,I1n,P1n])}function epe(){return _T(),S(T(a1n,1),G,394,0,[l1n,Oq,h1n])}function tpe(){return XT(),S(T(f1n,1),G,445,0,[Bj,qI,Mq])}function ipe(){return rA(),S(T(bce,1),G,456,0,[Tq,Sq,Aq])}function rpe(){return Ok(),S(T(Uln,1),G,393,0,[KI,Hln,qln])}function cpe(){return AT(),S(T(s1n,1),G,300,0,[Cq,o1n,u1n])}function upe(){return jl(),S(T(ldn,1),G,346,0,[uO,M1,M9])}function ope(){return Fk(),S(T(Fq,1),G,444,0,[XI,VI,WI])}function spe(){return Nf(),S(T(Zan,1),G,278,0,[Bv,Jw,Rv])}function fpe(){return Gp(),S(T(mdn,1),G,280,0,[pdn,Yw,aO])}function T0(n){return Se(n),O(n,16)?new _u(u(n,16)):y4(n.Kc())}function hJ(n,e){return n&&n.equals?n.equals(e):x(n)===x(e)}function vi(n,e){return Q1(ewe(Vr(n)?ds(n):n,Vr(e)?ds(e):e))}function hf(n,e){return Q1(twe(Vr(n)?ds(n):n,Vr(e)?ds(e):e))}function RN(n,e){return Q1(iwe(Vr(n)?ds(n):n,Vr(e)?ds(e):e))}function hpe(n,e){var t;return t=(Jn(n),n).g,rV(!!t),Jn(e),t(e)}function _On(n,e){var t,i;return i=C4(n,e),t=n.a.fd(i),new zEn(n,t)}function lpe(n){return n.Db>>16!=6?null:u(dF(n),241)}function ape(n){if(n.p!=2)throw M(new Cu);return Ae(n.f)&ui}function dpe(n){if(n.p!=2)throw M(new Cu);return Ae(n.k)&ui}function E(n){return oe(n.ai?1:0}function GOn(n,e){var t,i;return t=s$(e),i=t,u(ee(n.c,i),17).a}function KN(n,e,t){var i;i=n.d[e.p],n.d[e.p]=n.d[t.p],n.d[t.p]=i}function Cpe(n,e,t){var i;n.n&&e&&t&&(i=new uvn,nn(n.e,i))}function _N(n,e){if(fi(n.a,e),e.d)throw M(new ec(nXn));e.d=n}function dJ(n,e){this.a=new Z,this.d=new Z,this.f=n,this.c=e}function zOn(){this.c=new PTn,this.a=new $Ln,this.b=new Xyn,lCn()}function XOn(){qp(),this.b=new de,this.a=new de,this.c=new Z}function VOn(n,e,t){this.d=n,this.j=e,this.e=t,this.o=-1,this.p=3}function WOn(n,e,t){this.d=n,this.k=e,this.f=t,this.o=-1,this.p=5}function JOn(n,e,t,i,r,c){dQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function QOn(n,e,t,i,r,c){bQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function YOn(n,e,t,i,r,c){OJ.call(this,n,e,t,i,r),c&&(this.o=-2)}function ZOn(n,e,t,i,r,c){pQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function nDn(n,e,t,i,r,c){DJ.call(this,n,e,t,i,r),c&&(this.o=-2)}function eDn(n,e,t,i,r,c){wQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function tDn(n,e,t,i,r,c){gQ.call(this,n,e,t,i,r),c&&(this.o=-2)}function iDn(n,e,t,i,r,c){LJ.call(this,n,e,t,i,r),c&&(this.o=-2)}function rDn(n,e,t,i){LE.call(this,t),this.b=n,this.c=e,this.d=i}function cDn(n,e){this.f=n,this.a=($4(),MO),this.c=MO,this.b=e}function uDn(n,e){this.g=n,this.d=($4(),TO),this.a=TO,this.b=e}function bJ(n,e){!n.c&&(n.c=new Rt(n,0)),HA(n.c,(at(),F9),e)}function Mpe(n,e){return oMe(n,e,O(e,102)&&(u(e,19).Bb&hr)!=0)}function Tpe(n,e){return KPn(vc(n.q.getTime()),vc(e.q.getTime()))}function oDn(n){return XL(n.e.Rd().gc()*n.c.Rd().gc(),16,new O8n(n))}function Ape(n){return!!n.u&&Sc(n.u.a).i!=0&&!(n.n&&Ix(n.n))}function Spe(n){return!!n.a&&no(n.a.a).i!=0&&!(n.b&&Ox(n.b))}function wJ(n,e){return e==0?!!n.o&&n.o.f!=0:Cx(n,e)}function Ppe(n,e,t){var i;return i=u(n.Zb().xc(e),16),!!i&&i.Hc(t)}function sDn(n,e,t){var i;return i=u(n.Zb().xc(e),16),!!i&&i.Mc(t)}function fDn(n,e){var t;return t=1-e,n.a[t]=jT(n.a[t],t),jT(n,e)}function hDn(n,e){var t,i;return i=vi(n,mr),t=Fs(e,32),hf(t,i)}function lDn(n,e,t){var i;i=(Se(n),new _u(n)),O7e(new EOn(i,e,t))}function Z7(n,e,t){var i;i=(Se(n),new _u(n)),D7e(new COn(i,e,t))}function fc(n,e,t,i,r,c){return Hxn(n,e,t,c),CY(n,i),MY(n,r),n}function aDn(n,e,t,i){return n.a+=""+qo(e==null?gu:Jr(e),t,i),n}function xi(n,e){this.a=n,Xv.call(this,n),zb(e,n.gc()),this.b=e}function dDn(n){this.a=K(ki,Fn,1,QQ(y.Math.max(8,n))<<1,5,1)}function nk(n){return u(xf(n,K(Qh,b1,10,n.c.length,0,1)),199)}function fh(n){return u(xf(n,K(O_,rR,18,n.c.length,0,1)),483)}function bDn(n){return n.a?n.e.length==0?n.a.a:n.a.a+(""+n.e):n.c}function Q6(n){for(;n.d>0&&n.a[--n.d]==0;);n.a[n.d++]==0&&(n.e=0)}function wDn(n){return oe(n.b.b!=n.d.a),n.c=n.b=n.b.b,--n.a,n.c.c}function Ipe(n,e,t){n.a=e,n.c=t,n.b.a.$b(),vo(n.d),Pb(n.e.a.c,0)}function gDn(n,e){var t;n.e=new uz,t=aw(e),Yt(t,n.c),Iqn(n,t,0)}function ri(n,e,t,i){var r;r=new nG,r.a=e,r.b=t,r.c=i,xe(n.a,r)}function Q(n,e,t,i){var r;r=new nG,r.a=e,r.b=t,r.c=i,xe(n.b,r)}function pDn(n,e,t){if(n<0||et)throw M(new Ir(qje(n,e,t)))}function ek(n,e){if(n<0||n>=e)throw M(new Ir(kEe(n,e)));return n}function Ope(n){if(!("stack"in n))try{throw n}catch{}return n}function Sg(n){return s6(),O(n.g,10)?u(n.g,10):null}function Dpe(n){return Tg(n).dc()?!1:(e1e(n,new Pr),!0)}function id(n){var e;return Vr(n)?(e=n,e==-0?0:e):X4e(n)}function mDn(n,e){return O(e,44)?xx(n.a,u(e,44)):!1}function vDn(n,e){return O(e,44)?xx(n.a,u(e,44)):!1}function kDn(n,e){return O(e,44)?xx(n.a,u(e,44)):!1}function gJ(n){var e;return z1(n),e=new L0n,hg(n.a,new j9n(e)),e}function pJ(){var n,e,t;return e=(t=(n=new Jd,n),t),nn(n0n,e),e}function BM(n){var e;return z1(n),e=new N0n,hg(n.a,new E9n(e)),e}function Lpe(n,e){return n.a<=n.b?(e.Dd(n.a++),!0):!1}function yDn(n){P$.call(this,n,(B4(),e_),null,!1,null,!1)}function jDn(){jDn=F,SYn=Ce((YE(),S(T(oon,1),G,489,0,[b_])))}function EDn(){EDn=F,eln=wIn(Y(1),Y(4)),nln=wIn(Y(1),Y(2))}function Npe(n,e){return new _L(e,N6(Ki(e.e),n,n),(_n(),!0))}function RM(n){return new Gc((Co(n,cB),oT(nr(nr(5,n),n/10|0))))}function $pe(n){return XL(n.e.Rd().gc()*n.c.Rd().gc(),273,new I8n(n))}function CDn(n){return u(xf(n,K(FZn,DXn,12,n.c.length,0,1)),2042)}function xpe(n){return ko(),!fr(n)&&!(!fr(n)&&n.c.i.c==n.d.i.c)}function Fpe(n,e){return _p(),u(v(e,(lc(),I2)),17).a>=n.gc()}function Y6(n,e){vLe(e,n),JV(n.d),JV(u(v(n,(cn(),mI)),214))}function HN(n,e){kLe(e,n),QV(n.d),QV(u(v(n,(cn(),mI)),214))}function Bpe(n,e,t){n.d&&du(n.d.e,n),n.d=e,n.d&&b0(n.d.e,t,n)}function Rpe(n,e,t){return t.f.c.length>0?MW(n.a,e,t):MW(n.b,e,t)}function Kpe(n,e,t){var i;i=i9e();try{return Aae(n,e,t)}finally{D3e(i)}}function A0(n,e){var t,i;return t=dl(n,e),i=null,t&&(i=t.pe()),i}function Z6(n,e){var t,i;return t=dl(n,e),i=null,t&&(i=t.se()),i}function L4(n,e){var t,i;return t=Jb(n,e),i=null,t&&(i=t.se()),i}function bl(n,e){var t,i;return t=dl(n,e),i=null,t&&(i=gnn(t)),i}function _pe(n,e,t){var i;return i=wm(t),FA(n.g,i,e),FA(n.i,e,t),e}function mJ(n,e,t){this.d=new $7n(this),this.e=n,this.i=e,this.f=t}function MDn(n,e,t,i){this.e=null,this.c=n,this.d=e,this.a=t,this.b=i}function TDn(n,e,t,i){ETn(this),this.c=n,this.e=e,this.f=t,this.b=i}function vJ(n,e,t,i){this.d=n,this.n=e,this.g=t,this.o=i,this.p=-1}function ADn(n,e,t,i){return O(t,59)?new iAn(n,e,t,i):new vW(n,e,t,i)}function N4(n){return O(n,16)?u(n,16).dc():!n.Kc().Ob()}function SDn(n){if(n.e.g!=n.b)throw M(new Bo);return!!n.c&&n.d>0}function be(n){return oe(n.b!=n.d.c),n.c=n.b,n.b=n.b.a,++n.a,n.c.c}function kJ(n,e){Jn(e),$t(n.a,n.c,e),n.c=n.c+1&n.a.length-1,JRn(n)}function V1(n,e){Jn(e),n.b=n.b-1&n.a.length-1,$t(n.a,n.b,e),JRn(n)}function PDn(n){var e;e=n.Gh(),this.a=O(e,71)?u(e,71).Ii():e.Kc()}function Hpe(n){return new In(Ame(u(n.a.md(),16).gc(),n.a.ld()),16)}function IDn(){IDn=F,Gce=Ce((eC(),S(T($1n,1),G,490,0,[Bq])))}function ODn(){ODn=F,Xce=Ce((tC(),S(T(zce,1),G,558,0,[Rq])))}function DDn(){DDn=F,lue=Ce((f6(),S(T(tan,1),G,539,0,[Hj])))}function qpe(){return dd(),S(T(Lon,1),G,389,0,[Ow,Don,P_,I_])}function Upe(){return B4(),S(T(lP,1),G,304,0,[e_,t_,i_,r_])}function Gpe(){return Vp(),S(T(EYn,1),G,332,0,[uj,cj,oj,sj])}function zpe(){return A5(),S(T(TYn,1),G,406,0,[fj,wP,gP,hj])}function Xpe(){return N0(),S(T(yYn,1),G,417,0,[rj,ij,a_,d_])}function Vpe(){return nm(),S(T(MZn,1),G,416,0,[rb,Iw,Pw,a2])}function Wpe(){return $f(),S(T(ene,1),G,421,0,[j3,lv,av,B_])}function Jpe(){return OT(),S(T(UZn,1),G,371,0,[F_,HP,qP,wj])}function Qpe(){return cw(),S(T(RH,1),G,203,0,[TI,BH,S2,A2])}function Ype(){return lh(),S(T(Hhn,1),G,284,0,[k1,_hn,HH,qH])}function Zpe(n){var e;return n.j==(tn(),ae)&&(e=mHn(n),Au(e,Zn))}function n3e(n,e){var t;t=e.a,Zi(t,e.c.d),Ii(t,e.d.d),nw(t.a,n.n)}function yJ(n,e){var t;return t=u(Lf(n.b,e),67),!t&&(t=new Ct),t}function xp(n){return s6(),O(n.g,154)?u(n.g,154):null}function e3e(n){n.a=null,n.e=null,Pb(n.b.c,0),Pb(n.f.c,0),n.c=null}function KM(){KM=F,fH=new Zz(qm,0),Jsn=new Zz("TOP_LEFT",1)}function n5(){n5=F,r9=new eX("UPPER",0),i9=new eX("LOWER",1)}function t3e(n,e){return vp(new V(e.e.a+e.f.a/2,e.e.b+e.f.b/2),n)}function LDn(n,e){return u(ho(_b(u(ot(n.k,e),15).Oc(),b2)),113)}function NDn(n,e){return u(ho(Ap(u(ot(n.k,e),15).Oc(),b2)),113)}function i3e(){return Qp(),S(T(rln,1),G,405,0,[LI,c9,u9,o9])}function r3e(){return w5(),S(T(xln,1),G,353,0,[aq,BI,lq,hq])}function c3e(){return sA(),S(T(c1n,1),G,354,0,[Eq,i1n,r1n,t1n])}function u3e(){return go(),S(T(I9,1),G,386,0,[rE,Gd,iE,Qw])}function o3e(){return To(),S(T(Yue,1),G,291,0,[nE,nl,Ta,Zj])}function s3e(){return El(),S(T(aU,1),G,223,0,[lU,Yj,Kv,F3])}function f3e(){return qT(),S(T(Cdn,1),G,320,0,[wU,ydn,Edn,jdn])}function h3e(){return LT(),S(T(woe,1),G,415,0,[gU,Tdn,Mdn,Adn])}function l3e(n){return $M(),Zc(yU,n)?u(ee(yU,n),341).Qg():null}function Uo(n,e,t){return e<0?hF(n,t):u(t,69).wk().Bk(n,n.hi(),e)}function a3e(n,e,t){var i;return i=wm(t),FA(n.j,i,e),Xe(n.k,e,t),e}function d3e(n,e,t){var i;return i=wm(t),FA(n.d,i,e),Xe(n.e,e,t),e}function $Dn(n){var e,t;return e=(B1(),t=new HO,t),n&&AA(e,n),e}function jJ(n){var e;return e=n.aj(n.i),n.i>0&&Ic(n.g,0,e,0,n.i),e}function xDn(n,e){var t;for(t=n.j.c.length;t>24}function w3e(n){if(n.p!=1)throw M(new Cu);return Ae(n.k)<<24>>24}function g3e(n){if(n.p!=7)throw M(new Cu);return Ae(n.k)<<16>>16}function p3e(n){if(n.p!=7)throw M(new Cu);return Ae(n.f)<<16>>16}function Pg(n,e){return e.e==0||n.e==0?O8:(Am(),vF(n,e))}function RDn(n,e){return x(e)===x(n)?"(this Map)":e==null?gu:Jr(e)}function m3e(n,e,t){return tN(R(Kr(wr(n.f,e))),R(Kr(wr(n.f,t))))}function v3e(n,e,t){var i;i=u(ee(n.g,t),60),nn(n.a.c,new bi(e,i))}function KDn(n,e,t){n.i=0,n.e=0,e!=t&&(jFn(n,e,t),yFn(n,e,t))}function k3e(n,e,t,i,r){var c;c=yMe(r,t,i),nn(e,dEe(r,c)),rje(n,r,e)}function EJ(n,e,t,i,r){this.i=n,this.a=e,this.e=t,this.j=i,this.f=r}function _Dn(n,e){nJ.call(this),this.a=n,this.b=e,nn(this.a.b,this)}function HDn(n){this.b=new de,this.c=new de,this.d=new de,this.a=n}function qDn(n,e){var t;return t=new lp,n.Gd(t),t.a+="..",e.Hd(t),t.a}function UDn(n,e){var t;for(t=e;t;)a0(n,t.i,t.j),t=At(t);return n}function GDn(n,e,t){var i;return i=wm(t),Xe(n.b,i,e),Xe(n.c,e,t),e}function wl(n){var e;for(e=0;n.Ob();)n.Pb(),e=nr(e,1);return oT(e)}function Fh(n,e){dr();var t;return t=u(n,69).vk(),kje(t,e),t.xl(e)}function y3e(n,e,t){if(t){var i=t.oe();n.a[e]=i(t)}else delete n.a[e]}function CJ(n,e){var t;t=n.q.getHours(),n.q.setFullYear(e+fa),G5(n,t)}function j3e(n,e){return u(e==null?Kr(wr(n.f,null)):d6(n.i,e),288)}function MJ(n,e){return n==(Vn(),zt)&&e==zt?4:n==zt||e==zt?8:32}function _M(n,e,t){return RA(n,e,t,O(e,102)&&(u(e,19).Bb&hr)!=0)}function E3e(n,e,t){return Om(n,e,t,O(e,102)&&(u(e,19).Bb&hr)!=0)}function C3e(n,e,t){return bMe(n,e,t,O(e,102)&&(u(e,19).Bb&hr)!=0)}function TJ(n){n.b!=n.c&&(n.a=K(ki,Fn,1,8,5,1),n.b=0,n.c=0)}function e5(n){return oe(n.a=0&&n.a[t]===e[t];t--);return t<0}function HM(n){var e;return n?new fW(n):(e=new ih,A$(e,n),e)}function O3e(n,e){var t,i;i=!1;do t=lFn(n,e),i=i|t;while(t);return i}function D3e(n){n&&rme((az(),sun)),--cP,n&&uP!=-1&&(Ele(uP),uP=-1)}function qM(n){nnn(),LTn(this,Ae(vi(w0(n,24),YA)),Ae(vi(n,YA)))}function JDn(){JDn=F,HQn=Ce((YT(),S(T(Bun,1),G,436,0,[o_,Fun])))}function QDn(){QDn=F,qQn=Ce((cT(),S(T(Kun,1),G,435,0,[Run,s_])))}function YDn(){YDn=F,GYn=Ce((uT(),S(T(bon,1),G,432,0,[v_,vP])))}function ZDn(){ZDn=F,_Zn=Ce((V4(),S(T(KZn,1),G,517,0,[dj,L_])))}function nLn(){nLn=F,Ane=Ce((KM(),S(T(Qsn,1),G,429,0,[fH,Jsn])))}function eLn(){eLn=F,gne=Ce((pk(),S(T($sn,1),G,428,0,[WP,Nsn])))}function tLn(){tLn=F,kne=Ce((hk(),S(T(Bsn,1),G,488,0,[Fsn,QP])))}function iLn(){iLn=F,rie=Ce((wk(),S(T(qhn,1),G,430,0,[UH,GH])))}function rLn(){rLn=F,Die=Ce((n5(),S(T(Oie,1),G,531,0,[r9,i9])))}function cLn(){cLn=F,ane=Ce((QM(),S(T(Asn,1),G,431,0,[Tsn,V_])))}function uLn(){uLn=F,xre=Ce((FM(),S(T(Bln,1),G,433,0,[dq,Fln])))}function oLn(){oLn=F,_re=Ce((yT(),S(T(Rln,1),G,501,0,[RI,D2])))}function sLn(){sLn=F,Rie=Ce((sh(),S(T(Bie,1),G,523,0,[mb,y1])))}function fLn(){fLn=F,_ie=Ce((Sf(),S(T(Kie,1),G,522,0,[Rd,zf])))}function hLn(){hLn=F,tre=Ce((lf(),S(T(ere,1),G,528,0,[zw,ja])))}function lLn(){lLn=F,fre=Ce((M0(),S(T(sre,1),G,465,0,[Ea,P2])))}function aLn(){aLn=F,Ure=Ce((ZM(),S(T(_ln,1),G,434,0,[Kln,vq])))}function dLn(){dLn=F,Rce=Ce((GM(),S(T(S1n,1),G,491,0,[$q,A1n])))}function bLn(){bLn=F,_ce=Ce((N$(),S(T(N1n,1),G,492,0,[D1n,L1n])))}function wLn(){wLn=F,Vce=Ce((ck(),S(T(x1n,1),G,438,0,[Kq,JI])))}function gLn(){gLn=F,aue=Ce((Ak(),S(T(ran,1),G,437,0,[YI,ian])))}function pLn(){pLn=F,aoe=Ce((RL(),S(T(dO,1),G,347,0,[vdn,kdn])))}function L3e(){return ci(),S(T(E9,1),G,88,0,[Wf,Xr,Br,Vf,us])}function N3e(){return tn(),S(T(lr,1),Mc,64,0,[sc,Xn,Zn,ae,Wn])}function $3e(n,e,t){return u(e==null?Vc(n.f,null,t):$0(n.i,e,t),288)}function x3e(n){return(n.k==(Vn(),zt)||n.k==Zt)&&kt(n,(W(),H8))}function XN(n){return n.c&&n.d?aJ(n.c)+"->"+aJ(n.d):"e_"+l0(n)}function qi(n,e){var t,i;for(Jn(e),i=n.Kc();i.Ob();)t=i.Pb(),e.Cd(t)}function F3e(n,e){var t;t=new op,nd(t,"x",e.a),nd(t,"y",e.b),Ip(n,t)}function B3e(n,e){var t;t=new op,nd(t,"x",e.a),nd(t,"y",e.b),Ip(n,t)}function mLn(n,e){var t;for(t=e;t;)a0(n,-t.i,-t.j),t=At(t);return n}function SJ(n,e){var t,i;for(t=e,i=0;t>0;)i+=n.a[t],t-=t&-t;return i}function Go(n,e,t){var i;return i=(Ln(e,n.c.length),n.c[e]),n.c[e]=t,i}function PJ(n,e,t){n.a.c.length=0,fOe(n,e,t),n.a.c.length==0||xSe(n,e)}function tk(n){n.i=0,s7(n.b,null),s7(n.c,null),n.a=null,n.e=null,++n.g}function UM(){UM=F,qf=!0,DQn=!1,LQn=!1,$Qn=!1,NQn=!1}function VN(n){UM(),!qf&&(this.c=n,this.e=!0,this.a=new Z)}function vLn(n,e){this.c=0,this.b=e,HMn.call(this,n,17493),this.a=this.c}function kLn(n){jzn(),Syn(this),this.a=new Ct,sY(this,n),xe(this.a,n)}function yLn(){pL(this),this.b=new V(St,St),this.a=new V(li,li)}function GM(){GM=F,$q=new fX(cin,0),A1n=new fX("TARGET_WIDTH",1)}function Ig(n,e){return(ea(n),s4(new Tn(n,new tQ(e,n.a)))).Bd(v3)}function R3e(){return Vi(),S(T(Ion,1),G,367,0,[Xs,Jh,Oc,Kc,zr])}function K3e(){return ow(),S(T(ine,1),G,375,0,[gj,zP,XP,GP,UP])}function _3e(){return o1(),S(T(Lsn,1),G,348,0,[J_,Dsn,Q_,pv,gv])}function H3e(){return T5(),S(T($hn,1),G,323,0,[Nhn,KH,_H,Y8,Z8])}function q3e(){return Yo(),S(T(hfn,1),G,171,0,[Ej,U8,ka,G8,xw])}function U3e(){return wA(),S(T(Hre,1),G,368,0,[pq,bq,mq,wq,gq])}function G3e(){return R5(),S(T(Hce,1),G,373,0,[L2,D3,g9,w9,_j])}function z3e(){return Yk(),S(T(K1n,1),G,324,0,[F1n,_q,R1n,Hq,B1n])}function X3e(){return gf(),S(T(Zh,1),G,170,0,[xn,pi,Ph,Kd,E1])}function V3e(){return Fg(),S(T(A9,1),G,256,0,[Aa,eE,adn,T9,ddn])}function W3e(n){return HE(),function(){return Kpe(n,this,arguments)}}function fr(n){return!n.c||!n.d?!1:!!n.c.i&&n.c.i==n.d.i}function IJ(n,e){return O(e,143)?An(n.c,u(e,143).c):!1}function Zu(n){return n.t||(n.t=new myn(n),k5(new Njn(n),0,n.t)),n.t}function jLn(n){this.b=n,ne.call(this,n),this.a=u(Un(this.b.a,4),129)}function ELn(n){this.b=n,yp.call(this,n),this.a=u(Un(this.b.a,4),129)}function Bs(n,e,t,i,r){LLn.call(this,e,i,r),this.c=n,this.b=t}function OJ(n,e,t,i,r){VOn.call(this,e,i,r),this.c=n,this.a=t}function DJ(n,e,t,i,r){WOn.call(this,e,i,r),this.c=n,this.a=t}function LJ(n,e,t,i,r){LLn.call(this,e,i,r),this.c=n,this.a=t}function WN(n,e){var t;return t=u(Lf(n.d,e),23),t||u(Lf(n.e,e),23)}function CLn(n,e){var t,i;return t=e.ld(),i=n.Fe(t),!!i&&mc(i.e,e.md())}function MLn(n,e){var t;return t=e.ld(),new i0(t,n.e.pc(t,u(e.md(),16)))}function J3e(n,e){var t;return t=n.a.get(e),t??K(ki,Fn,1,0,5,1)}function TLn(n){var e;return e=n.length,An(Yn.substr(Yn.length-e,e),n)}function fe(n){if(pe(n))return n.c=n.a,n.a.Pb();throw M(new nc)}function NJ(n,e){return e==0||n.e==0?n:e>0?wqn(n,e):RBn(n,-e)}function Fp(n,e){return e==0||n.e==0?n:e>0?RBn(n,e):wqn(n,-e)}function $J(n){ole.call(this,n==null?gu:Jr(n),O(n,82)?u(n,82):null)}function ALn(n){var e;return n.c||(e=n.r,O(e,90)&&(n.c=u(e,29))),n.c}function JN(n){var e;return e=new E0,Ur(e,n),U(e,(cn(),Fr),null),e}function SLn(n){var e,t;return e=n.c.i,t=n.d.i,e.k==(Vn(),Zt)&&t.k==Zt}function QN(n){var e,t,i;return e=n&ro,t=n>>22&ro,i=n<0?Il:0,Yc(e,t,i)}function Q3e(n){var e,t,i,r;for(t=n,i=0,r=t.length;i=0?n.Lh(i,t,!0):H0(n,e,t)}function Z3e(n,e,t){return bt(vp(pm(n),Ki(e.b)),vp(pm(n),Ki(t.b)))}function n4e(n,e,t){return bt(vp(pm(n),Ki(e.e)),vp(pm(n),Ki(t.e)))}function e4e(n,e){return y.Math.min(W1(e.a,n.d.d.c),W1(e.b,n.d.d.c))}function ik(n,e){n._i(n.i+1),O6(n,n.i,n.Zi(n.i,e)),n.Mi(n.i++,e),n.Ni()}function t5(n){var e,t;++n.j,e=n.g,t=n.i,n.g=null,n.i=0,n.Oi(t,e),n.Ni()}function PLn(n,e,t){var i;i=new NX(n.a),f5(i,n.a.a),Vc(i.f,e,t),n.a.a=i}function xJ(n,e,t,i){var r;for(r=0;re)throw M(new Ir(Mnn(n,e,"index")));return n}function Yl(n,e){var t;return t=(Ln(e,n.c.length),n.c[e]),Pz(n.c,e,1),t}function RJ(n,e){var t,i;return t=(Jn(n),n),i=(Jn(e),e),t==i?0:te.p?-1:0}function FLn(n){var e;return n.a||(e=n.r,O(e,156)&&(n.a=u(e,156))),n.a}function o4e(n,e,t){var i;return++n.e,--n.f,i=u(n.d[e].gd(t),136),i.md()}function s4e(n){var e,t;return e=n.ld(),t=u(n.md(),16),x7(t.Nc(),new L8n(e))}function BLn(n,e){return Zc(n.a,e)?(Bp(n.a,e),!0):!1}function Rp(n,e,t){return ek(e,n.e.Rd().gc()),ek(t,n.c.Rd().gc()),n.a[e][t]}function XM(n,e,t){this.a=n,this.b=e,this.c=t,nn(n.t,this),nn(e.i,this)}function VM(n,e,t,i){this.f=n,this.e=e,this.d=t,this.b=i,this.c=i?i.d:null}function rk(){this.b=new Ct,this.a=new Ct,this.b=new Ct,this.a=new Ct}function $4(){$4=F;var n,e;MO=(o4(),e=new xE,e),TO=(n=new fD,n)}function f4e(n){var e;return ea(n),e=new ISn(n,n.a.e,n.a.d|4),new uV(n,e)}function RLn(n){var e;for(z1(n),e=0;n.a.Bd(new W0n);)e=nr(e,1);return e}function WM(n,e){return Jn(e),n.c=0,"Initial capacity must not be negative")}function JM(){JM=F,p9=new lt("org.eclipse.elk.labels.labelManager")}function KLn(){KLn=F,ysn=new Dt("separateLayerConnections",(OT(),F_))}function lf(){lf=F,zw=new rX("REGULAR",0),ja=new rX("CRITICAL",1)}function ck(){ck=F,Kq=new lX("FIXED",0),JI=new lX("CENTER_NODE",1)}function QM(){QM=F,Tsn=new Jz("QUADRATIC",0),V_=new Jz("SCANLINE",1)}function _Ln(){_Ln=F,dne=Ce((u5(),S(T(Psn,1),G,322,0,[B8,pj,Ssn])))}function HLn(){HLn=F,bne=Ce((bT(),S(T(Osn,1),G,351,0,[Isn,VP,W_])))}function qLn(){qLn=F,fne=Ce((D0(),S(T(R_,1),G,372,0,[ub,ma,cb])))}function ULn(){ULn=F,mne=Ce((hd(),S(T(pne,1),G,460,0,[Y_,mv,p2])))}function GLn(){GLn=F,Cne=Ce((Z4(),S(T(sH,1),G,299,0,[uH,oH,mj])))}function zLn(){zLn=F,Tne=Ce((vl(),S(T(Mne,1),G,311,0,[vj,v2,E3])))}function XLn(){XLn=F,Zte=Ce((g5(),S(T(Lhn,1),G,390,0,[FH,Dhn,MI])))}function VLn(){VLn=F,oie=Ce((ST(),S(T(zhn,1),G,387,0,[Uhn,zH,Ghn])))}function WLn(){WLn=F,sie=Ce((d5(),S(T(Xhn,1),G,349,0,[VH,XH,Ij])))}function JLn(){JLn=F,uie=Ce((gr(),S(T(cie,1),G,463,0,[n9,Vu,Jc])))}function QLn(){QLn=F,fie=Ce((om(),S(T(Whn,1),G,350,0,[WH,Vhn,e9])))}function YLn(){YLn=F,hie=Ce((dT(),S(T(Yhn,1),G,352,0,[Qhn,JH,Jhn])))}function ZLn(){ZLn=F,lie=Ce((DT(),S(T(Zhn,1),G,388,0,[QH,Ov,Gw])))}function nNn(){nNn=F,are=Ce((b5(),S(T(gln,1),G,392,0,[wln,nq,Lj])))}function eNn(){eNn=F,Gre=Ce((Ok(),S(T(Uln,1),G,393,0,[KI,Hln,qln])))}function tNn(){tNn=F,ace=Ce((AT(),S(T(s1n,1),G,300,0,[Cq,o1n,u1n])))}function iNn(){iNn=F,dce=Ce((XT(),S(T(f1n,1),G,445,0,[Bj,qI,Mq])))}function rNn(){rNn=F,wce=Ce((rA(),S(T(bce,1),G,456,0,[Tq,Sq,Aq])))}function cNn(){cNn=F,mce=Ce((_T(),S(T(a1n,1),G,394,0,[l1n,Oq,h1n])))}function uNn(){uNn=F,Kce=Ce((nT(),S(T(O1n,1),G,439,0,[xq,I1n,P1n])))}function oNn(){oNn=F,Aie=Ce((O0(),S(T(Tie,1),G,464,0,[Oj,t9,PI])))}function sNn(){sNn=F,WQn=Ce((Uu(),S(T(VQn,1),G,471,0,[Mh,ga,Gs])))}function fNn(){fNn=F,XQn=Ce((bf(),S(T(Sw,1),G,237,0,[bc,Wc,wc])))}function hNn(){hNn=F,QQn=Ce((bu(),S(T(JQn,1),G,472,0,[vf,pa,zs])))}function lNn(){lNn=F,xQn=Ce((Gu(),S(T(xr,1),G,108,0,[xun,Yr,Aw])))}function aNn(){aNn=F,pZn=Ce((i5(),S(T(Pon,1),G,391,0,[E_,j_,C_])))}function dNn(){dNn=F,Que=Ce((jl(),S(T(ldn,1),G,346,0,[uO,M1,M9])))}function bNn(){bNn=F,Uce=Ce((Fk(),S(T(Fq,1),G,444,0,[XI,VI,WI])))}function wNn(){wNn=F,Xue=Ce((Nf(),S(T(Zan,1),G,278,0,[Bv,Jw,Rv])))}function gNn(){gNn=F,loe=Ce((Gp(),S(T(mdn,1),G,280,0,[pdn,Yw,aO])))}function Df(n,e){return!n.o&&(n.o=new Iu((Cc(),il),T1,n,0)),wx(n.o,e)}function h4e(n,e){var t;n.C&&(t=u(Cr(n.b,e),127).n,t.d=n.C.d,t.a=n.C.a)}function UJ(n){var e,t,i,r;r=n.d,e=n.a,t=n.b,i=n.c,n.d=t,n.a=i,n.b=r,n.c=e}function l4e(n){return!n.g&&(n.g=new CE),!n.g.b&&(n.g.b=new byn(n)),n.g.b}function uk(n){return!n.g&&(n.g=new CE),!n.g.c&&(n.g.c=new pyn(n)),n.g.c}function a4e(n){return!n.g&&(n.g=new CE),!n.g.d&&(n.g.d=new wyn(n)),n.g.d}function d4e(n){return!n.g&&(n.g=new CE),!n.g.a&&(n.g.a=new gyn(n)),n.g.a}function b4e(n,e,t,i){return t&&(i=t.Rh(e,Ot(t.Dh(),n.c.uk()),null,i)),i}function w4e(n,e,t,i){return t&&(i=t.Th(e,Ot(t.Dh(),n.c.uk()),null,i)),i}function e$(n,e,t,i){var r;return r=K(ye,Ke,28,e+1,15,1),vPe(r,n,e,t,i),r}function K(n,e,t,i,r,c){var s;return s=_Rn(r,i),r!=10&&S(T(n,c),e,t,r,s),s}function g4e(n,e,t){var i,r;for(r=new Y4(e,n),i=0;it||e=0?n.Lh(t,!0,!0):H0(n,e,!0)}function L4e(n,e,t){var i;return i=vFn(n,e,t),n.b=new ET(i.c.length),den(n,i)}function N4e(n){if(n.b<=0)throw M(new nc);return--n.b,n.a-=n.c.c,Y(n.a)}function $4e(n){var e;if(!n.a)throw M(new PIn);return e=n.a,n.a=At(n.a),e}function x4e(n){for(;!n.a;)if(!eSn(n.c,new C9n(n)))return!1;return!0}function Kp(n){var e;return Se(n),O(n,204)?(e=u(n,204),e):new _8n(n)}function F4e(n){YM(),u(n.of((qe(),Ww)),181).Fc((zu(),tE)),n.qf(sU,null)}function YM(){YM=F,wue=new Emn,pue=new Cmn,gue=M6e((qe(),sU),wue,Ma,pue)}function ZM(){ZM=F,Kln=new sX("LEAF_NUMBER",0),vq=new sX("NODE_SIZE",1)}function u$(n){n.a=K(ye,Ke,28,n.b+1,15,1),n.c=K(ye,Ke,28,n.b,15,1),n.d=0}function B4e(n,e){n.a.Ne(e.d,n.b)>0&&(nn(n.c,new GV(e.c,e.d,n.d)),n.b=e.d)}function nQ(n,e){if(n.g==null||e>=n.i)throw M(new aL(e,n.i));return n.g[e]}function kNn(n,e,t){if(rm(n,t),t!=null&&!n.fk(t))throw M(new uD);return t}function o$(n,e){return gk(e)!=10&&S(wo(e),e.Sm,e.__elementTypeId$,gk(e),n),n}function F4(n,e,t,i){var r;i=(j0(),i||Pun),r=n.slice(e,t),Tnn(r,n,e,t,-e,i)}function zo(n,e,t,i,r){return e<0?H0(n,t,i):u(t,69).wk().yk(n,n.hi(),e,i,r)}function R4e(n,e){return bt($(R(v(n,(W(),fb)))),$(R(v(e,fb))))}function yNn(){yNn=F,IQn=Ce((B4(),S(T(lP,1),G,304,0,[e_,t_,i_,r_])))}function B4(){B4=F,e_=new uC("All",0),t_=new lTn,i_=new kTn,r_=new hTn}function Uu(){Uu=F,Mh=new FD(s3,0),ga=new FD(qm,1),Gs=new FD(f3,2)}function jNn(){jNn=F,KA(),s0n=St,mse=li,f0n=new V9(St),vse=new V9(li)}function ENn(){ENn=F,jYn=Ce((N0(),S(T(yYn,1),G,417,0,[rj,ij,a_,d_])))}function CNn(){CNn=F,AYn=Ce((A5(),S(T(TYn,1),G,406,0,[fj,wP,gP,hj])))}function MNn(){MNn=F,CYn=Ce((Vp(),S(T(EYn,1),G,332,0,[uj,cj,oj,sj])))}function TNn(){TNn=F,DZn=Ce((dd(),S(T(Lon,1),G,389,0,[Ow,Don,P_,I_])))}function ANn(){ANn=F,TZn=Ce((nm(),S(T(MZn,1),G,416,0,[rb,Iw,Pw,a2])))}function SNn(){SNn=F,tne=Ce(($f(),S(T(ene,1),G,421,0,[j3,lv,av,B_])))}function PNn(){PNn=F,GZn=Ce((OT(),S(T(UZn,1),G,371,0,[F_,HP,qP,wj])))}function INn(){INn=F,nie=Ce((cw(),S(T(RH,1),G,203,0,[TI,BH,S2,A2])))}function ONn(){ONn=F,iie=Ce((lh(),S(T(Hhn,1),G,284,0,[k1,_hn,HH,qH])))}function hk(){hk=F,Fsn=new Yz(kh,0),QP=new Yz("IMPROVE_STRAIGHTNESS",1)}function DNn(n,e){var t,i;return i=e/n.c.Rd().gc()|0,t=e%n.c.Rd().gc(),Rp(n,i,t)}function LNn(n){var e;if(n.nl())for(e=n.i-1;e>=0;--e)L(n,e);return jJ(n)}function eQ(n){var e,t;if(!n.b)return null;for(t=n.b;e=t.a[0];)t=e;return t}function NNn(n){var e,t;if(!n.b)return null;for(t=n.b;e=t.a[1];)t=e;return t}function K4e(n){return O(n,180)?""+u(n,180).a:n==null?null:Jr(n)}function _4e(n){return O(n,180)?""+u(n,180).a:n==null?null:Jr(n)}function $Nn(n,e){if(e.a)throw M(new ec(nXn));fi(n.a,e),e.a=n,!n.j&&(n.j=e)}function tQ(n,e){IC.call(this,e.zd(),e.yd()&-16449),Jn(n),this.a=n,this.c=e}function H4e(n,e){return new _L(e,a0(Ki(e.e),e.f.a+n,e.f.b+n),(_n(),!1))}function q4e(n,e){return k4(),nn(n,new bi(e,Y(e.e.c.length+e.g.c.length)))}function U4e(n,e){return k4(),nn(n,new bi(e,Y(e.e.c.length+e.g.c.length)))}function xNn(){xNn=F,lce=Ce((sA(),S(T(c1n,1),G,354,0,[Eq,i1n,r1n,t1n])))}function FNn(){FNn=F,$re=Ce((w5(),S(T(xln,1),G,353,0,[aq,BI,lq,hq])))}function BNn(){BNn=F,hre=Ce((Qp(),S(T(rln,1),G,405,0,[LI,c9,u9,o9])))}function RNn(){RNn=F,Vue=Ce((El(),S(T(aU,1),G,223,0,[lU,Yj,Kv,F3])))}function KNn(){KNn=F,Zue=Ce((To(),S(T(Yue,1),G,291,0,[nE,nl,Ta,Zj])))}function _Nn(){_Nn=F,foe=Ce((go(),S(T(I9,1),G,386,0,[rE,Gd,iE,Qw])))}function HNn(){HNn=F,doe=Ce((qT(),S(T(Cdn,1),G,320,0,[wU,ydn,Edn,jdn])))}function qNn(){qNn=F,goe=Ce((LT(),S(T(woe,1),G,415,0,[gU,Tdn,Mdn,Adn])))}function nT(){nT=F,xq=new oL(mVn,0),I1n=new oL(Crn,1),P1n=new oL(kh,2)}function Wb(n,e,t,i,r){return Jn(n),Jn(e),Jn(t),Jn(i),Jn(r),new AW(n,e,i)}function UNn(n,e){var t;return t=u(Bp(n.e,e),400),t?(tW(t),t.e):null}function du(n,e){var t;return t=qr(n,e,0),t==-1?!1:(Yl(n,t),!0)}function GNn(n,e,t){var i;return z1(n),i=new LO,i.a=e,n.a.Nb(new TCn(i,t)),i.a}function G4e(n){var e;return z1(n),e=K(Pi,Tr,28,0,15,1),hg(n.a,new y9n(e)),e}function iQ(n){var e;if(!E$(n))throw M(new nc);return n.e=1,e=n.d,n.d=null,e}function n1(n){var e;return Vr(n)&&(e=0-n,!isNaN(e))?e:Q1(tm(n))}function qr(n,e,t){for(;t=0?tA(n,t,!0,!0):H0(n,e,!0)}function cQ(n){var e;return e=cd(Un(n,32)),e==null&&(iu(n),e=cd(Un(n,32))),e}function uQ(n){var e;return n.Oh()||(e=se(n.Dh())-n.ji(),n.$h().Mk(e)),n.zh()}function QNn(n,e){con=new kE,MYn=e,L8=n,u(L8.b,68),XJ(L8,con,null),aGn(L8)}function i5(){i5=F,E_=new RD("XY",0),j_=new RD("X",1),C_=new RD("Y",2)}function bu(){bu=F,vf=new BD("TOP",0),pa=new BD(qm,1),zs=new BD(Ftn,2)}function vl(){vl=F,vj=new GD(kh,0),v2=new GD("TOP",1),E3=new GD(Ftn,2)}function wk(){wk=F,UH=new nX("INPUT_ORDER",0),GH=new nX("PORT_DEGREE",1)}function R4(){R4=F,hun=Yc(ro,ro,524287),bQn=Yc(0,0,Ty),lun=QN(1),QN(2),aun=QN(0)}function a$(n){var e;return n.d!=n.r&&(e=ws(n),n.e=!!e&&e.lk()==bJn,n.d=e),n.e}function d$(n,e,t){var i;return i=n.g[e],O6(n,e,n.Zi(e,t)),n.Ri(e,t,i),n.Ni(),i}function rT(n,e){var t;return t=n.dd(e),t>=0?(n.gd(t),!0):!1}function b$(n,e){var t;for(Se(n),Se(e),t=!1;e.Ob();)t=t|n.Fc(e.Pb());return t}function Lf(n,e){var t;return t=u(ee(n.e,e),400),t?(DTn(n,t),t.e):null}function YNn(n){var e,t;return e=n/60|0,t=n%60,t==0?""+e:""+e+":"+(""+t)}function Jb(n,e){var t=n.a[e],i=(K$(),WK)[typeof t];return i?i(t):wY(typeof t)}function rc(n,e){var t,i;return ea(n),i=new _J(e,n.a),t=new rSn(i),new Tn(n,t)}function w$(n){var e;return e=n.b.c.length==0?null:sn(n.b,0),e!=null&&M$(n,0),e}function W4e(n,e){var t,i,r;r=e.c.i,t=u(ee(n.f,r),60),i=t.d.c-t.e.c,BQ(e.a,i,0)}function oQ(n,e){var t;for(++n.d,++n.c[e],t=e+1;t=0;)++e[0]}function J4e(n,e){eu(n,e==null||GC((Jn(e),e))||isNaN((Jn(e),e))?0:(Jn(e),e))}function Q4e(n,e){tu(n,e==null||GC((Jn(e),e))||isNaN((Jn(e),e))?0:(Jn(e),e))}function Y4e(n,e){I0(n,e==null||GC((Jn(e),e))||isNaN((Jn(e),e))?0:(Jn(e),e))}function Z4e(n,e){P0(n,e==null||GC((Jn(e),e))||isNaN((Jn(e),e))?0:(Jn(e),e))}function nme(n,e,t){return vp(new V(t.e.a+t.f.a/2,t.e.b+t.f.b/2),n)==(Jn(e),e)}function eme(n,e){return O(e,102)&&u(e,19).Bb&hr?new dL(e,n):new Y4(e,n)}function tme(n,e){return O(e,102)&&u(e,19).Bb&hr?new dL(e,n):new Y4(e,n)}function gk(n){return n.__elementTypeCategory$==null?10:n.__elementTypeCategory$}function e$n(n,e){return e==(xL(),xL(),AQn)?n.toLocaleLowerCase():n.toLowerCase()}function t$n(n){if(!n.e)throw M(new nc);return n.c=n.a=n.e,n.e=n.e.e,--n.d,n.a.f}function sQ(n){if(!n.c)throw M(new nc);return n.e=n.a=n.c,n.c=n.c.c,++n.d,n.a.f}function i$n(n){var e;for(++n.a,e=n.c.a.length;n.an.a[i]&&(i=t);return i}function r$n(n){var e;return e=u(v(n,(W(),ob)),313),e?e.a==n:!1}function c$n(n){var e;return e=u(v(n,(W(),ob)),313),e?e.i==n:!1}function u$n(){u$n=F,yZn=Ce((Vi(),S(T(Ion,1),G,367,0,[Xs,Jh,Oc,Kc,zr])))}function o$n(){o$n=F,rne=Ce((ow(),S(T(ine,1),G,375,0,[gj,zP,XP,GP,UP])))}function s$n(){s$n=F,wne=Ce((o1(),S(T(Lsn,1),G,348,0,[J_,Dsn,Q_,pv,gv])))}function f$n(){f$n=F,eie=Ce((T5(),S(T($hn,1),G,323,0,[Nhn,KH,_H,Y8,Z8])))}function h$n(){h$n=F,Sne=Ce((Yo(),S(T(hfn,1),G,171,0,[Ej,U8,ka,G8,xw])))}function l$n(){l$n=F,qre=Ce((wA(),S(T(Hre,1),G,368,0,[pq,bq,mq,wq,gq])))}function a$n(){a$n=F,qce=Ce((R5(),S(T(Hce,1),G,373,0,[L2,D3,g9,w9,_j])))}function d$n(){d$n=F,Wce=Ce((Yk(),S(T(K1n,1),G,324,0,[F1n,_q,R1n,Hq,B1n])))}function b$n(){b$n=F,zue=Ce((ci(),S(T(E9,1),G,88,0,[Wf,Xr,Br,Vf,us])))}function w$n(){w$n=F,mue=Ce((gf(),S(T(Zh,1),G,170,0,[xn,pi,Ph,Kd,E1])))}function g$n(){g$n=F,eoe=Ce((Fg(),S(T(A9,1),G,256,0,[Aa,eE,adn,T9,ddn])))}function p$n(){p$n=F,roe=Ce((tn(),S(T(lr,1),Mc,64,0,[sc,Xn,Zn,ae,Wn])))}function cT(){cT=F,Run=new Uz("BY_SIZE",0),s_=new Uz("BY_SIZE_AND_SHAPE",1)}function uT(){uT=F,v_=new Xz("EADES",0),vP=new Xz("FRUCHTERMAN_REINGOLD",1)}function pk(){pk=F,WP=new Qz("READING_DIRECTION",0),Nsn=new Qz("ROTATION",1)}function r5(){r5=F,PZn=new rwn,IZn=new own,AZn=new swn,SZn=new uwn,OZn=new fwn}function m$n(n){this.b=new Z,this.a=new Z,this.c=new Z,this.d=new Z,this.e=n}function v$n(n){this.g=n,this.f=new Z,this.a=y.Math.min(this.g.c.c,this.g.d.c)}function k$n(n,e,t){qC.call(this),lQ(this),this.a=n,this.c=t,this.b=e.d,this.f=e.e}function sme(n,e,t){var i,r;for(r=new C(t);r.a=0&&e0?e-1:e,eEn($he(U$n(YV(new up,t),n.n),n.j),n.k)}function Nr(n){var e,t;t=(e=new hD,e),ve((!n.q&&(n.q=new q(As,n,11,10)),n.q),t)}function fQ(n){return(n.i&2?"interface ":n.i&1?"":"class ")+(ll(n),n.o)}function oT(n){return Ec(n,et)>0?et:Ec(n,Wi)<0?Wi:Ae(n)}function Qb(n){return n<3?(Co(n,$zn),n+1):n=-.01&&n.a<=Kf&&(n.a=0),n.b>=-.01&&n.b<=Kf&&(n.b=0),n}function Og(n){Xg();var e,t;for(t=Arn,e=0;et&&(t=n[e]);return t}function C$n(n,e){var t;if(t=oy(n.Dh(),e),!t)throw M(new Gn(da+e+sK));return t}function Yb(n,e){var t;for(t=n;At(t);)if(t=At(t),t==e)return!0;return!1}function vme(n,e){var t,i,r;for(i=e.a.ld(),t=u(e.a.md(),16).gc(),r=0;rn||n>e)throw M(new pz("fromIndex: 0, toIndex: "+n+Mtn+e))}function S0(n){if(n<0)throw M(new Gn("Illegal Capacity: "+n));this.g=this.aj(n)}function hQ(n,e){return Mf(),Rs(sa),y.Math.abs(n-e)<=sa||n==e||isNaN(n)&&isNaN(e)}function m$(n,e){var t,i,r,c;for(i=n.d,r=0,c=i.length;r0&&(n.a/=e,n.b/=e),n}function jo(n){var e;return n.w?n.w:(e=lpe(n),e&&!e.Vh()&&(n.w=e),e)}function K4(n,e){var t,i;i=n.a,t=w5e(n,e,null),i!=e&&!n.e&&(t=Nm(n,e,t)),t&&t.oj()}function P$n(n,e,t){var i,r;i=e;do r=$(n.p[i.p])+t,n.p[i.p]=r,i=n.a[i.p];while(i!=e)}function I$n(n,e,t){var i=function(){return n.apply(i,arguments)};return e.apply(i,t),i}function Tme(n){var e;return n==null?null:(e=u(n,195),Bye(e,e.length))}function L(n,e){if(n.g==null||e>=n.i)throw M(new aL(e,n.i));return n.Wi(e,n.g[e])}function Ame(n,e){Dn();var t,i;for(i=new Z,t=0;t=14&&e<=16))),n}function Ee(n,e){var t;return Jn(e),t=n[":"+e],B7(!!t,"Enum constant undefined: "+e),t}function we(n,e,t,i,r,c){var s;return s=bN(n,e),G$n(t,s),s.i=r?8:0,s.f=i,s.e=r,s.g=c,s}function dQ(n,e,t,i,r){this.d=e,this.k=i,this.f=r,this.o=-1,this.p=1,this.c=n,this.a=t}function bQ(n,e,t,i,r){this.d=e,this.k=i,this.f=r,this.o=-1,this.p=2,this.c=n,this.a=t}function wQ(n,e,t,i,r){this.d=e,this.k=i,this.f=r,this.o=-1,this.p=6,this.c=n,this.a=t}function gQ(n,e,t,i,r){this.d=e,this.k=i,this.f=r,this.o=-1,this.p=7,this.c=n,this.a=t}function pQ(n,e,t,i,r){this.d=e,this.j=i,this.e=r,this.o=-1,this.p=4,this.c=n,this.a=t}function z$n(n,e){var t,i,r,c;for(i=e,r=0,c=i.length;r=0))throw M(new Gn("tolerance ("+n+") must be >= 0"));return n}function V$n(n,e){var t;return O(e,44)?n.c.Mc(e):(t=wx(n,e),VT(n,e),t)}function Mr(n,e,t){return ad(n,e),zc(n,t),e1(n,0),Zb(n,1),u1(n,!0),c1(n,!0),n}function vk(n,e){var t;if(t=n.gc(),e<0||e>t)throw M(new Kb(e,t));return new SV(n,e)}function wT(n,e){n.b=y.Math.max(n.b,e.d),n.e+=e.r+(n.a.c.length==0?0:n.c),nn(n.a,e)}function W$n(n){Fb(n.c>=0),_8e(n.d,n.c)<0&&(n.a=n.a-1&n.d.a.length-1,n.b=n.d.c),n.c=-1}function gT(n){var e,t;for(t=n.c.Cc().Kc();t.Ob();)e=u(t.Pb(),16),e.$b();n.c.$b(),n.d=0}function Fme(n){var e,t,i,r;for(t=n.a,i=0,r=t.length;i=0}function CQ(n,e){n.r>0&&n.c0&&n.g!=0&&CQ(n.i,e/n.r*n.i.d))}function MQ(n,e){var t;t=n.c,n.c=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,1,t,n.c))}function y$(n,e){var t;t=n.c,n.c=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,4,t,n.c))}function X4(n,e){var t;t=n.k,n.k=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,2,t,n.k))}function j$(n,e){var t;t=n.D,n.D=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,2,t,n.D))}function mT(n,e){var t;t=n.f,n.f=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,8,t,n.f))}function vT(n,e){var t;t=n.i,n.i=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,7,t,n.i))}function TQ(n,e){var t;t=n.a,n.a=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,8,t,n.a))}function AQ(n,e){var t;t=n.b,n.b=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,0,t,n.b))}function SQ(n,e){var t;t=n.b,n.b=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,0,t,n.b))}function PQ(n,e){var t;t=n.c,n.c=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,1,t,n.c))}function IQ(n,e){var t;t=n.d,n.d=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,1,t,n.d))}function Ume(n,e,t){var i;n.b=e,n.a=t,i=(n.a&512)==512?new gjn:new rG,n.c=rAe(i,n.b,n.a)}function oxn(n,e){return Sl(n.e,e)?(dr(),a$(e)?new eM(e,n):new j7(e,n)):new $Mn(e,n)}function Gme(n){var e,t;return 0>n?new Dz:(e=n+1,t=new vLn(e,n),new oV(null,t))}function zme(n,e){Dn();var t;return t=new ap(1),Ai(n)?Dr(t,n,e):Vc(t.f,n,e),new eD(t)}function Xme(n,e){var t,i;return t=n.c,i=e.e[n.p],i>0?u(sn(t.a,i-1),10):null}function Vme(n,e){var t,i;return t=n.o+n.p,i=e.o+e.p,te?(e<<=1,e>0?e:Y5):e}function E$(n){switch(_X(n.e!=3),n.e){case 2:return!1;case 0:return!0}return i4e(n)}function fxn(n,e){var t;return O(e,8)?(t=u(e,8),n.a==t.a&&n.b==t.b):!1}function Jme(n,e){var t;t=new kE,u(e.b,68),u(e.b,68),u(e.b,68),nu(e.a,new BV(n,t,e))}function hxn(n,e){var t,i;for(i=e.vc().Kc();i.Ob();)t=u(i.Pb(),44),Vk(n,t.ld(),t.md())}function OQ(n,e){var t;t=n.d,n.d=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,11,t,n.d))}function kT(n,e){var t;t=n.j,n.j=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,13,t,n.j))}function DQ(n,e){var t;t=n.b,n.b=e,n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,1,21,t,n.b))}function Qme(n,e){(UM(),qf?null:e.c).length==0&&TAn(e,new BU),Dr(n.a,qf?null:e.c,e)}function Yme(n,e){e.Ug("Hierarchical port constraint processing",1),g9e(n),xLe(n),e.Vg()}function D0(){D0=F,ub=new KD("START",0),ma=new KD("MIDDLE",1),cb=new KD("END",2)}function yT(){yT=F,RI=new oX("P1_NODE_PLACEMENT",0),D2=new oX("P2_EDGE_ROUTING",1)}function J1(){J1=F,y3=new lt(Jtn),jP=new lt(MXn),$8=new lt(TXn),lj=new lt(AXn)}function L0(n){var e;return FL(n.f.g,n.d),oe(n.b),n.c=n.a,e=u(n.a.Pb(),44),n.b=GQ(n),e}function LQ(n){var e;return n.b==null?(Gl(),Gl(),dE):(e=n.ul()?n.tl():n.sl(),e)}function lxn(n,e){var t;return t=e==null?-1:qr(n.b,e,0),t<0?!1:(M$(n,t),!0)}function Ks(n,e){var t;return Jn(e),t=e.g,n.b[t]?!1:($t(n.b,t,e),++n.c,!0)}function jT(n,e){var t,i;return t=1-e,i=n.a[t],n.a[t]=i.a[e],i.a[e]=n,n.b=!0,i.b=!1,i}function Zme(n,e){var t,i;for(i=e.Kc();i.Ob();)t=u(i.Pb(),272),n.b=!0,fi(n.e,t),t.b=n}function nve(n,e){var t,i;return t=u(v(n,(cn(),Hw)),8),i=u(v(e,Hw),8),bt(t.b,i.b)}function C$(n,e,t){var i,r,c;return c=e>>5,r=e&31,i=vi(U1(n.n[t][c],Ae(Fs(r,1))),3),i}function axn(n,e,t){var i,r,c;for(c=n.a.length-1,r=n.b,i=0;i0?1:0:(!n.c&&(n.c=Y7(vc(n.f))),n.c).e}function yxn(n,e){e?n.B==null&&(n.B=n.D,n.D=null):n.B!=null&&(n.D=n.B,n.B=null)}function rve(n,e){return nm(),n==rb&&e==Iw||n==Iw&&e==rb||n==a2&&e==Pw||n==Pw&&e==a2}function cve(n,e){return nm(),n==rb&&e==Pw||n==rb&&e==a2||n==Iw&&e==a2||n==Iw&&e==Pw}function jxn(n,e){return Mf(),Rs(Kf),y.Math.abs(0-e)<=Kf||e==0||isNaN(0)&&isNaN(e)?0:n/e}function Exn(n,e){return $(R(ho($k(_r(new Tn(null,new In(n.c.b,16)),new I7n(n)),e))))}function FQ(n,e){return $(R(ho($k(_r(new Tn(null,new In(n.c.b,16)),new P7n(n)),e))))}function uve(){return pr(),S(T(cH,1),G,259,0,[ZP,cs,K8,nI,yv,m2,_8,vv,kv,eI])}function ove(){return gs(),S(T(Khn,1),G,243,0,[AI,Sj,Pj,Fhn,Bhn,xhn,Rhn,SI,pb,Uw])}function sve(n,e){var t;e.Ug("General Compactor",1),t=d8e(u(z(n,(ua(),yq)),393)),t.Cg(n)}function fve(n,e){var t,i;return t=u(z(n,(ua(),_I)),17),i=u(z(e,_I),17),jc(t.a,i.a)}function BQ(n,e,t){var i,r;for(r=ge(n,0);r.b!=r.d.c;)i=u(be(r),8),i.a+=e,i.b+=t;return n}function o5(n,e,t){var i;for(i=n.b[t&n.f];i;i=i.b)if(t==i.a&&oh(e,i.g))return i;return null}function s5(n,e,t){var i;for(i=n.c[t&n.f];i;i=i.d)if(t==i.f&&oh(e,i.i))return i;return null}function hve(n,e,t){var i,r,c;for(i=0,r=0;r>>31;i!=0&&(n[t]=i)}function P$(n,e,t,i,r,c){var s;this.c=n,s=new Z,pZ(n,s,e,n.b,t,i,r,c),this.a=new xi(s,0)}function Cxn(){this.c=new XE(0),this.b=new XE(Trn),this.d=new XE(lVn),this.a=new XE(QB)}function Vo(n,e,t,i,r,c,s){je.call(this,n,e),this.d=t,this.e=i,this.c=r,this.b=c,this.a=If(s)}function Ut(n,e,t,i,r,c,s,f,h,l,a,d,g){return P_n(n,e,t,i,r,c,s,f,h,l,a,d,g),sx(n,!1),n}function lve(n){return n.b.c.i.k==(Vn(),Zt)?u(v(n.b.c.i,(W(),st)),12):n.b.c}function Mxn(n){return n.b.d.i.k==(Vn(),Zt)?u(v(n.b.d.i,(W(),st)),12):n.b.d}function ave(n){var e;return e=BM(n),o0(e.a,0)?(QE(),QE(),SQn):(QE(),new uAn(e.b))}function I$(n){var e;return e=gJ(n),o0(e.a,0)?(Ob(),Ob(),n_):(Ob(),new AL(e.b))}function O$(n){var e;return e=gJ(n),o0(e.a,0)?(Ob(),Ob(),n_):(Ob(),new AL(e.c))}function Txn(n){switch(n.g){case 2:return tn(),Wn;case 4:return tn(),Zn;default:return n}}function Axn(n){switch(n.g){case 1:return tn(),ae;case 3:return tn(),Xn;default:return n}}function Sxn(n){switch(n.g){case 0:return new hmn;case 1:return new lmn;default:return null}}function Hp(){Hp=F,x_=new Dt("edgelabelcenterednessanalysis.includelabel",(_n(),wa))}function RQ(){RQ=F,Mie=ah(WMn(Re(Re(new ii,(Vi(),Oc),(tr(),NP)),Kc,PP),zr),LP)}function Pxn(){Pxn=F,Pie=ah(WMn(Re(Re(new ii,(Vi(),Oc),(tr(),NP)),Kc,PP),zr),LP)}function D$(){D$=F,x9=new ljn,CU=S(T(ku,1),s2,179,0,[]),Joe=S(T(As,1),Gcn,62,0,[])}function V4(){V4=F,dj=new Vz("TO_INTERNAL_LTR",0),L_=new Vz("TO_INPUT_DIRECTION",1)}function Ou(){Ou=F,Ron=new wwn,Fon=new gwn,Bon=new pwn,xon=new mwn,Kon=new vwn,_on=new kwn}function dve(n,e){e.Ug(HXn,1),HY(Qhe(new IE((o6(),new kN(n,!1,!1,new qU))))),e.Vg()}function bve(n,e,t){t.Ug("DFS Treeifying phase",1),O8e(n,e),PTe(n,e),n.a=null,n.b=null,t.Vg()}function kk(n,e){return _n(),Ai(n)?RJ(n,Oe(e)):$b(n)?tN(n,R(e)):Nb(n)?rwe(n,un(e)):n.Fd(e)}function f5(n,e){var t,i;for(Jn(e),i=e.vc().Kc();i.Ob();)t=u(i.Pb(),44),n.zc(t.ld(),t.md())}function wve(n,e,t){var i;for(i=t.Kc();i.Ob();)if(!_M(n,e,i.Pb()))return!1;return!0}function gve(n,e,t,i,r){var c;return t&&(c=Ot(e.Dh(),n.c),r=t.Rh(e,-1-(c==-1?i:c),null,r)),r}function pve(n,e,t,i,r){var c;return t&&(c=Ot(e.Dh(),n.c),r=t.Th(e,-1-(c==-1?i:c),null,r)),r}function Ixn(n){var e;if(n.b==-2){if(n.e==0)e=-1;else for(e=0;n.a[e]==0;e++);n.b=e}return n.b}function mve(n){if(Jn(n),n.length==0)throw M(new eh("Zero length BigInteger"));ESe(this,n)}function KQ(n){this.i=n.gc(),this.i>0&&(this.g=this.aj(this.i+(this.i/8|0)+1),n.Qc(this.g))}function Oxn(n,e,t){this.g=n,this.d=e,this.e=t,this.a=new Z,IEe(this),Dn(),Yt(this.a,null)}function _Q(n,e){e.q=n,n.d=y.Math.max(n.d,e.r),n.b+=e.d+(n.a.c.length==0?0:n.c),nn(n.a,e)}function W4(n,e){var t,i,r,c;return r=n.c,t=n.c+n.b,c=n.d,i=n.d+n.a,e.a>r&&e.ac&&e.br?t=r:zn(e,t+1),n.a=qo(n.a,0,e)+(""+i)+$W(n.a,t)}function Kxn(n,e){n.a=nr(n.a,1),n.c=y.Math.min(n.c,e),n.b=y.Math.max(n.b,e),n.d=nr(n.d,e)}function Mve(n,e){return e1||n.Ob())return++n.a,n.g=0,e=n.i,n.Ob(),e;throw M(new nc)}function Uxn(n){switch(n.a.g){case 1:return new WCn;case 3:return new WRn;default:return new s8n}}function qQ(n,e){switch(e){case 1:return!!n.n&&n.n.i!=0;case 2:return n.k!=null}return wJ(n,e)}function vc(n){return Ay>22),r=n.h+e.h+(i>>22),Yc(t&ro,i&ro,r&Il)}function Yxn(n,e){var t,i,r;return t=n.l-e.l,i=n.m-e.m+(t>>22),r=n.h-e.h+(i>>22),Yc(t&ro,i&ro,r&Il)}function zve(n){var e,t;for(RDe(n),t=new C(n.d);t.ai)throw M(new Kb(e,i));return n.Si()&&(t=gOn(n,t)),n.Ei(e,t)}function em(n,e,t,i,r){var c,s;for(s=t;s<=r;s++)for(c=e;c<=i;c++)Rg(n,c,s)||xA(n,c,s,!0,!1)}function u6e(n){Xg();var e,t,i;for(t=K(Ei,J,8,2,0,1),i=0,e=0;e<2;e++)i+=.5,t[e]=Z9e(i,n);return t}function tm(n){var e,t,i;return e=~n.l+1&ro,t=~n.m+(e==0?1:0)&ro,i=~n.h+(e==0&&t==0?1:0)&Il,Yc(e,t,i)}function QQ(n){var e;if(n<0)return Wi;if(n==0)return 0;for(e=Y5;!(e&n);e>>=1);return e}function R$(n,e,t){return n>=128?!1:n<64?M6(vi(Fs(1,n),t),0):M6(vi(Fs(1,n-64),e),0)}function Pk(n,e,t){return t==null?(!n.q&&(n.q=new de),Bp(n.q,e)):(!n.q&&(n.q=new de),Xe(n.q,e,t)),n}function U(n,e,t){return t==null?(!n.q&&(n.q=new de),Bp(n.q,e)):(!n.q&&(n.q=new de),Xe(n.q,e,t)),n}function fFn(n){var e,t;return t=new zM,Ur(t,n),U(t,(J1(),y3),n),e=new de,$Pe(n,t,e),fDe(n,t,e),t}function hFn(n){var e,t;return e=n.t-n.k[n.o.p]*n.d+n.j[n.o.p]>n.f,t=n.u+n.e[n.o.p]*n.d>n.f*n.s*n.d,e||t}function lFn(n,e){var t,i,r,c;for(t=!1,i=n.a[e].length,c=0;c=0,"Negative initial capacity"),B7(e>=0,"Non-positive load factor"),Hu(this)}function s6e(n,e,t,i,r){var c,s;if(s=n.length,c=t.length,e<0||i<0||r<0||e+r>s||i+r>c)throw M(new qG)}function eY(n,e){Dn();var t,i,r,c,s;for(s=!1,i=e,r=0,c=i.length;r1||e>=0&&n.b<3)}function H$(n){var e,t,i;e=~n.l+1&ro,t=~n.m+(e==0?1:0)&ro,i=~n.h+(e==0&&t==0?1:0)&Il,n.l=e,n.m=t,n.h=i}function rY(n){Dn();var e,t,i;for(i=1,t=n.Kc();t.Ob();)e=t.Pb(),i=31*i+(e!=null?mt(e):0),i=i|0;return i}function d6e(n,e,t,i,r){var c;return c=Xnn(n,e),t&&H$(c),r&&(n=u7e(n,e),i?ba=tm(n):ba=Yc(n.l,n.m,n.h)),c}function yFn(n,e,t){n.g=uF(n,e,(tn(),Zn),n.b),n.d=uF(n,t,Zn,n.b),!(n.g.c==0||n.d.c==0)&&YKn(n)}function jFn(n,e,t){n.g=uF(n,e,(tn(),Wn),n.j),n.d=uF(n,t,Wn,n.j),!(n.g.c==0||n.d.c==0)&&YKn(n)}function cY(n,e){switch(e){case 7:return!!n.e&&n.e.i!=0;case 8:return!!n.d&&n.d.i!=0}return qY(n,e)}function b6e(n,e){switch(e.g){case 0:O(n.b,641)||(n.b=new Rxn);break;case 1:O(n.b,642)||(n.b=new BSn)}}function EFn(n){switch(n.g){case 0:return new gmn;default:throw M(new Gn(xS+(n.f!=null?n.f:""+n.g)))}}function CFn(n){switch(n.g){case 0:return new wmn;default:throw M(new Gn(xS+(n.f!=null?n.f:""+n.g)))}}function w6e(n,e,t){return!s4(ut(new Tn(null,new In(n.c,16)),new Z3(new hMn(e,t)))).Bd((Xa(),v3))}function MFn(n,e){return vp(pm(u(v(e,(lc(),vb)),88)),new V(n.c.e.a-n.b.e.a,n.c.e.b-n.b.e.b))<=0}function g6e(n,e){for(;n.g==null&&!n.c?cJ(n):n.g==null||n.i!=0&&u(n.g[n.i-1],51).Ob();)kle(e,CA(n))}function ld(n){var e,t;for(t=new C(n.a.b);t.ai?1:0}function v6e(n){return nn(n.c,(qp(),bue)),hQ(n.a,$(R(rn((bx(),EI)))))?new tvn:new $kn(n)}function k6e(n){for(;!n.d||!n.d.Ob();)if(n.b&&!i6(n.b))n.d=u(Sp(n.b),51);else return null;return n.d}function oY(n){switch(n.g){case 1:return lVn;default:case 2:return 0;case 3:return QB;case 4:return Trn}}function y6e(){nt();var n;return IU||(n=_1e(oa("M",!0)),n=uM(oa("M",!1),n),IU=n,IU)}function LT(){LT=F,gU=new CC("ELK",0),Tdn=new CC("JSON",1),Mdn=new CC("DOT",2),Adn=new CC("SVG",3)}function d5(){d5=F,VH=new WD("STACKED",0),XH=new WD("REVERSE_STACKED",1),Ij=new WD("SEQUENCED",2)}function b5(){b5=F,wln=new eL(kh,0),nq=new eL("MIDDLE_TO_MIDDLE",1),Lj=new eL("AVOID_OVERLAP",2)}function cm(){cm=F,Esn=new Ygn,Csn=new Zgn,JZn=new Jgn,WZn=new n2n,VZn=new Qgn,jsn=(Jn(VZn),new O0n)}function NT(){NT=F,hdn=new f0(15),Jue=new Ni((qe(),C1),hdn),C9=N3,udn=Pue,odn=Hd,fdn=K2,sdn=Vw}function Lg(n,e){var t,i,r,c,s;for(i=e,r=0,c=i.length;r=n.b.c.length||(fY(n,2*e+1),t=2*e+2,t0&&(e.Cd(t),t.i&&E5e(t))}function hY(n,e,t){var i;for(i=t-1;i>=0&&n[i]===e[i];i--);return i<0?0:ND(vi(n[i],mr),vi(e[i],mr))?-1:1}function SFn(n,e,t){var i,r;this.g=n,this.c=e,this.a=this,this.d=this,r=sxn(t),i=K(sQn,Cy,227,r,0,1),this.b=i}function X$(n,e,t,i,r){var c,s;for(s=t;s<=r;s++)for(c=e;c<=i;c++)if(Rg(n,c,s))return!0;return!1}function A6e(n,e){var t,i;for(i=n.Zb().Cc().Kc();i.Ob();)if(t=u(i.Pb(),16),t.Hc(e))return!0;return!1}function PFn(n,e,t){var i,r,c,s;for(Jn(t),s=!1,c=n.fd(e),r=t.Kc();r.Ob();)i=r.Pb(),c.Rb(i),s=!0;return s}function V$(n,e){var t,i;return i=u(Un(n.a,4),129),t=K(jU,MK,424,e,0,1),i!=null&&Ic(i,0,t,0,i.length),t}function IFn(n,e){var t;return t=new jF((n.f&256)!=0,n.i,n.a,n.d,(n.f&16)!=0,n.j,n.g,e),n.e!=null||(t.c=n),t}function S6e(n,e){var t;return n===e?!0:O(e,85)?(t=u(e,85),dnn(Wa(n),t.vc())):!1}function OFn(n,e,t){var i,r;for(r=t.Kc();r.Ob();)if(i=u(r.Pb(),44),n.Be(e,i.md()))return!0;return!1}function DFn(n,e,t){return n.d[e.p][t.p]||(O9e(n,e,t),n.d[e.p][t.p]=!0,n.d[t.p][e.p]=!0),n.a[e.p][t.p]}function P6e(n,e){var t;return!n||n==e||!kt(e,(W(),sb))?!1:(t=u(v(e,(W(),sb)),10),t!=n)}function W$(n){switch(n.i){case 2:return!0;case 1:return!1;case-1:++n.c;default:return n.$l()}}function LFn(n){switch(n.i){case-2:return!0;case-1:return!1;case 1:--n.c;default:return n._l()}}function NFn(n){yOn.call(this,"The given string does not match the expected format for individual spacings.",n)}function I6e(n,e){var t;e.Ug("Min Size Preprocessing",1),t=jnn(n),ht(n,(_h(),a9),t.a),ht(n,UI,t.b),e.Vg()}function O6e(n){var e,t,i;for(e=0,i=K(Ei,J,8,n.b,0,1),t=ge(n,0);t.b!=t.d.c;)i[e++]=u(be(t),8);return i}function J$(n,e,t){var i,r,c;for(i=new Ct,c=ge(t,0);c.b!=c.d.c;)r=u(be(c),8),xe(i,new rr(r));PFn(n,e,i)}function D6e(n,e){var t;return t=nr(n,e),ND(RN(n,e),0)|AC(RN(n,t),0)?t:nr(Ey,RN(U1(t,63),1))}function L6e(n,e){var t,i;return t=u(n.d.Bc(e),16),t?(i=n.e.hc(),i.Gc(t),n.e.d-=t.gc(),t.$b(),i):null}function $Fn(n){var e;if(e=n.a.c.length,e>0)return E4(e-1,n.a.c.length),Yl(n.a,e-1);throw M(new $yn)}function xFn(n,e,t){if(n>e)throw M(new Gn(ZA+n+Qzn+e));if(n<0||e>t)throw M(new pz(ZA+n+Stn+e+Mtn+t))}function um(n,e){n.D==null&&n.B!=null&&(n.D=n.B,n.B=null),j$(n,e==null?null:(Jn(e),e)),n.C&&n.hl(null)}function N6e(n,e){var t;t=rn((bx(),EI))!=null&&e.Sg()!=null?$(R(e.Sg()))/$(R(rn(EI))):1,Xe(n.b,e,t)}function lY(n,e){var t,i;if(i=n.c[e],i!=0)for(n.c[e]=0,n.d-=i,t=e+1;tPS?n-t>PS:t-n>PS}function XFn(n,e){var t;for(t=0;tr&&(EKn(e.q,r),i=t!=e.q.d)),i}function VFn(n,e){var t,i,r,c,s,f,h,l;return h=e.i,l=e.j,i=n.f,r=i.i,c=i.j,s=h-r,f=l-c,t=y.Math.sqrt(s*s+f*f),t}function pY(n,e){var t,i;return i=WT(n),i||(t=(UF(),$Hn(e)),i=new Cyn(t),ve(i.El(),n)),i}function Lk(n,e){var t,i;return t=u(n.c.Bc(e),16),t?(i=n.hc(),i.Gc(t),n.d-=t.gc(),t.$b(),n.mc(i)):n.jc()}function G6e(n,e){var t,i;for(i=to(n.d,1)!=0,t=!0;t;)t=!1,t=e.c.mg(e.e,i),t=t|sy(n,e,i,!1),i=!i;$Q(n)}function WFn(n,e,t,i){var r,c;n.a=e,c=i?0:1,n.f=(r=new s_n(n.c,n.a,t,c),new Kqn(t,n.a,r,n.e,n.b,n.c==(O0(),t9)))}function xT(n){var e;return oe(n.a!=n.b),e=n.d.a[n.a],EAn(n.b==n.d.c&&e!=null),n.c=n.a,n.a=n.a+1&n.d.a.length-1,e}function JFn(n){var e;if(n.c!=0)return n.c;for(e=0;e=n.c.b:n.a<=n.c.b))throw M(new nc);return e=n.a,n.a+=n.c.c,++n.b,Y(e)}function ex(n){var e;return e=new DX(n.a),Ur(e,n),U(e,(W(),st),n),e.o.a=n.g,e.o.b=n.f,e.n.a=n.i,e.n.b=n.j,e}function tx(n){return(tn(),mu).Hc(n.j)?$(R(v(n,(W(),jv)))):cc(S(T(Ei,1),J,8,0,[n.i.n,n.n,n.a])).b}function X6e(n){var e;return e=DC(Cie),u(v(n,(W(),Hc)),21).Hc((pr(),yv))&&Re(e,(Vi(),Oc),(tr(),FP)),e}function V6e(n){var e,t,i,r;for(r=new ni,i=new C(n);i.a=0?e:-e;i>0;)i%2==0?(t*=t,i=i/2|0):(r*=t,i-=1);return e<0?1/r:r}function Z6e(n,e){var t,i,r;for(r=1,t=n,i=e>=0?e:-e;i>0;)i%2==0?(t*=t,i=i/2|0):(r*=t,i-=1);return e<0?1/r:r}function na(n,e){var t,i,r,c;return c=(r=n?WT(n):null,O_n((i=e,r&&r.Gl(),i))),c==e&&(t=WT(n),t&&t.Gl()),c}function QFn(n,e,t){var i,r;return r=n.f,n.f=e,n.Db&4&&!(n.Db&1)&&(i=new Ci(n,1,0,r,e),t?t.nj(i):t=i),t}function YFn(n,e,t){var i,r;return r=n.b,n.b=e,n.Db&4&&!(n.Db&1)&&(i=new Ci(n,1,3,r,e),t?t.nj(i):t=i),t}function vY(n,e,t){var i,r;return r=n.a,n.a=e,n.Db&4&&!(n.Db&1)&&(i=new Ci(n,1,1,r,e),t?t.nj(i):t=i),t}function ZFn(n){var e,t;if(n!=null)for(t=0;t=i||e-129&&n<128?(FSn(),e=n+128,t=pun[e],!t&&(t=pun[e]=new vG(n)),t):new vG(n)}function sm(n){var e,t;return n>-129&&n<128?(nPn(),e=n+128,t=yun[e],!t&&(t=yun[e]=new yG(n)),t):new yG(n)}function tBn(n,e){var t;n.a.c.length>0&&(t=u(sn(n.a,n.a.c.length-1),579),sY(t,e))||nn(n.a,new kLn(e))}function c5e(n){xs();var e,t;e=n.d.c-n.e.c,t=u(n.g,154),nu(t.b,new p7n(e)),nu(t.c,new m7n(e)),qi(t.i,new v7n(e))}function iBn(n){var e;return e=new x1,e.a+="VerticalSegment ",Dc(e,n.e),e.a+=" ",Be(e,RX(new yD,new C(n.k))),e.a}function ix(n,e){var t,i,r;for(t=0,r=uc(n,e).Kc();r.Ob();)i=u(r.Pb(),12),t+=v(i,(W(),Xu))!=null?1:0;return t}function xg(n,e,t){var i,r,c;for(i=0,c=ge(n,0);c.b!=c.d.c&&(r=$(R(be(c))),!(r>t));)r>=e&&++i;return i}function rBn(n,e){Se(n);try{return n._b(e)}catch(t){if(t=It(t),O(t,212)||O(t,169))return!1;throw M(t)}}function yY(n,e){Se(n);try{return n.Hc(e)}catch(t){if(t=It(t),O(t,212)||O(t,169))return!1;throw M(t)}}function u5e(n,e){Se(n);try{return n.Mc(e)}catch(t){if(t=It(t),O(t,212)||O(t,169))return!1;throw M(t)}}function tw(n,e){Se(n);try{return n.xc(e)}catch(t){if(t=It(t),O(t,212)||O(t,169))return null;throw M(t)}}function o5e(n,e){Se(n);try{return n.Bc(e)}catch(t){if(t=It(t),O(t,212)||O(t,169))return null;throw M(t)}}function p5(n,e){switch(e.g){case 2:case 1:return uc(n,e);case 3:case 4:return Qo(uc(n,e))}return Dn(),Dn(),sr}function m5(n){var e;return n.Db&64?_s(n):(e=new ls(_s(n)),e.a+=" (name: ",Er(e,n.zb),e.a+=")",e.a)}function s5e(n){var e;return e=u(Lf(n.c.c,""),233),e||(e=new Np(u4(c4(new ep,""),"Other")),s1(n.c.c,"",e)),e}function jY(n,e,t){var i,r;return r=n.sb,n.sb=e,n.Db&4&&!(n.Db&1)&&(i=new Ci(n,1,4,r,e),t?t.nj(i):t=i),t}function EY(n,e,t){var i,r;return r=n.r,n.r=e,n.Db&4&&!(n.Db&1)&&(i=new Ci(n,1,8,r,n.r),t?t.nj(i):t=i),t}function f5e(n,e,t){var i,r;return i=new ml(n.e,4,13,(r=e.c,r||(On(),Yf)),null,f1(n,e),!1),t?t.nj(i):t=i,t}function h5e(n,e,t){var i,r;return i=new ml(n.e,3,13,null,(r=e.c,r||(On(),Yf)),f1(n,e),!1),t?t.nj(i):t=i,t}function r1(n,e){var t,i;return t=u(e,691),i=t.el(),!i&&t.fl(i=O(e,90)?new xMn(n,u(e,29)):new cDn(n,u(e,156))),i}function Nk(n,e,t){var i;n._i(n.i+1),i=n.Zi(e,t),e!=n.i&&Ic(n.g,e,n.g,e+1,n.i-e),$t(n.g,e,i),++n.i,n.Mi(e,t),n.Ni()}function l5e(n,e){var t;return e.a&&(t=e.a.a.length,n.a?Be(n.a,n.b):n.a=new mo(n.d),aDn(n.a,e.a,e.d.length,t)),n}function a5e(n,e){var t;n.c=e,n.a=p8e(e),n.a<54&&(n.f=(t=e.d>1?hDn(e.a[0],e.a[1]):hDn(e.a[0],0),id(e.e>0?t:n1(t))))}function $k(n,e){var t;return t=new LO,n.a.Bd(t)?(b4(),new wD(Jn(GNn(n,t.a,e)))):(z1(n),b4(),b4(),Dun)}function cBn(n,e){var t;n.c.length!=0&&(t=u(xf(n,K(Qh,b1,10,n.c.length,0,1)),199),CX(t,new rgn),Y_n(t,e))}function uBn(n,e){var t;n.c.length!=0&&(t=u(xf(n,K(Qh,b1,10,n.c.length,0,1)),199),CX(t,new cgn),Y_n(t,e))}function rt(n,e){return Ai(n)?An(n,e):$b(n)?nSn(n,e):Nb(n)?(Jn(n),x(n)===x(e)):pW(n)?n.Fb(e):hW(n)?YMn(n,e):hJ(n,e)}function Wo(n,e,t){if(e<0)Pnn(n,t);else{if(!t.rk())throw M(new Gn(da+t.xe()+p8));u(t,69).wk().Ek(n,n.hi(),e)}}function oBn(n,e,t){if(n<0||e>t)throw M(new Ir(ZA+n+Stn+e+", size: "+t));if(n>e)throw M(new Gn(ZA+n+Qzn+e))}function sBn(n){var e;return n.Db&64?_s(n):(e=new ls(_s(n)),e.a+=" (source: ",Er(e,n.d),e.a+=")",e.a)}function fBn(n){return n>=65&&n<=70?n-65+10:n>=97&&n<=102?n-97+10:n>=48&&n<=57?n-48:0}function d5e(n){VA();var e,t,i,r;for(t=jx(),i=0,r=t.length;i=0?ta(n):G6(ta(n1(n))))}function aBn(n,e,t,i,r,c){this.e=new Z,this.f=(gr(),n9),nn(this.e,n),this.d=e,this.a=t,this.b=i,this.f=r,this.c=c}function g5e(n,e,t){n.n=Va(xa,[J,SB],[376,28],14,[t,wi(y.Math.ceil(e/32))],2),n.o=e,n.p=t,n.j=e-1>>1,n.k=t-1>>1}function dBn(n){return n-=n>>1&1431655765,n=(n>>2&858993459)+(n&858993459),n=(n>>4)+n&252645135,n+=n>>8,n+=n>>16,n&63}function bBn(n,e){var t,i;for(i=new ne(n);i.e!=i.i.gc();)if(t=u(ce(i),142),x(e)===x(t))return!0;return!1}function p5e(n,e,t){var i,r,c;return c=(r=Mm(n.b,e),r),c&&(i=u(qA(ak(n,c),""),29),i)?Qnn(n,i,e,t):null}function rx(n,e,t){var i,r,c;return c=(r=Mm(n.b,e),r),c&&(i=u(qA(ak(n,c),""),29),i)?Ynn(n,i,e,t):null}function m5e(n,e){var t;if(t=Dg(n.i,e),t==null)throw M(new nh("Node did not exist in input."));return HQ(e,t),null}function v5e(n,e){var t;if(t=oy(n,e),O(t,331))return u(t,35);throw M(new Gn(da+e+"' is not a valid attribute"))}function k5(n,e,t){var i;if(i=n.gc(),e>i)throw M(new Kb(e,i));if(n.Si()&&n.Hc(t))throw M(new Gn(Vy));n.Gi(e,t)}function k5e(n,e){e.Ug("Sort end labels",1),qt(ut(rc(new Tn(null,new In(n.b,16)),new Hwn),new qwn),new Uwn),e.Vg()}function ci(){ci=F,Wf=new v7(i8,0),Xr=new v7(f3,1),Br=new v7(s3,2),Vf=new v7(_B,3),us=new v7("UP",4)}function Fk(){Fk=F,XI=new sL("P1_STRUCTURE",0),VI=new sL("P2_PROCESSING_ORDER",1),WI=new sL("P3_EXECUTION",2)}function wBn(){wBn=F,Rre=ah(ah(l6(ah(ah(l6(Re(new ii,(Qp(),c9),(q5(),ZH)),u9),lln),dln),o9),oln),bln)}function y5e(n){switch(u(v(n,(W(),Od)),311).g){case 1:U(n,Od,(vl(),E3));break;case 2:U(n,Od,(vl(),v2))}}function j5e(n){switch(n){case 0:return new rjn;case 1:return new tjn;case 2:return new ijn;default:throw M(new Q9)}}function gBn(n){switch(n.g){case 2:return Xr;case 1:return Br;case 4:return Vf;case 3:return us;default:return Wf}}function AY(n,e){switch(n.b.g){case 0:case 1:return e;case 2:case 3:return new Ho(e.d,0,e.a,e.b);default:return null}}function SY(n){switch(n.g){case 1:return Wn;case 2:return Xn;case 3:return Zn;case 4:return ae;default:return sc}}function Bk(n){switch(n.g){case 1:return ae;case 2:return Wn;case 3:return Xn;case 4:return Zn;default:return sc}}function RT(n){switch(n.g){case 1:return Zn;case 2:return ae;case 3:return Wn;case 4:return Xn;default:return sc}}function PY(n,e,t,i){switch(e){case 1:return!n.n&&(n.n=new q(Ar,n,1,7)),n.n;case 2:return n.k}return yZ(n,e,t,i)}function y5(n,e,t){var i,r;return n.Pj()?(r=n.Qj(),i=lF(n,e,t),n.Jj(n.Ij(7,Y(t),i,e,r)),i):lF(n,e,t)}function cx(n,e){var t,i,r;n.d==null?(++n.e,--n.f):(r=e.ld(),t=e.Bi(),i=(t&et)%n.d.length,o4e(n,i,RHn(n,i,t,r)))}function fm(n,e){var t;t=(n.Bb&Us)!=0,e?n.Bb|=Us:n.Bb&=-1025,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,10,t,e))}function hm(n,e){var t;t=(n.Bb&vw)!=0,e?n.Bb|=vw:n.Bb&=-4097,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,12,t,e))}function lm(n,e){var t;t=(n.Bb&$u)!=0,e?n.Bb|=$u:n.Bb&=-8193,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,15,t,e))}function am(n,e){var t;t=(n.Bb&Tw)!=0,e?n.Bb|=Tw:n.Bb&=-2049,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,11,t,e))}function E5e(n){var e;n.g&&(e=n.c.kg()?n.f:n.a,len(e.a,n.o,!0),len(e.a,n.o,!1),U(n.o,(cn(),Kt),(Oi(),Ud)))}function C5e(n){var e;if(!n.a)throw M(new Or("Cannot offset an unassigned cut."));e=n.c-n.b,n.b+=e,_In(n,e),KIn(n,e)}function M5e(n,e){var t;if(t=ee(n.k,e),t==null)throw M(new nh("Port did not exist in input."));return HQ(e,t),null}function T5e(n){var e,t;for(t=xHn(jo(n)).Kc();t.Ob();)if(e=Oe(t.Pb()),U5(n,e))return A3e((mCn(),Boe),e);return null}function pBn(n){var e,t;for(t=n.p.a.ec().Kc();t.Ob();)if(e=u(t.Pb(),218),e.f&&n.b[e.c]<-1e-10)return e;return null}function A5e(n){var e,t;for(t=Ya(new x1,91),e=!0;n.Ob();)e||(t.a+=ur),e=!1,Dc(t,n.Pb());return(t.a+="]",t).a}function S5e(n){var e,t,i;for(e=new Z,i=new C(n.b);i.ae?1:n==e?n==0?bt(1/n,1/e):0:isNaN(n)?isNaN(e)?0:1:-1}function I5e(n){var e;return e=n.a[n.c-1&n.a.length-1],e==null?null:(n.c=n.c-1&n.a.length-1,$t(n.a,n.c,null),e)}function O5e(n){var e,t,i;for(i=0,t=n.length,e=0;e=1?Xr:Vf):t}function $5e(n){switch(u(v(n,(cn(),$l)),223).g){case 1:return new Ppn;case 3:return new Npn;default:return new Spn}}function ea(n){if(n.c)ea(n.c);else if(n.d)throw M(new Or("Stream already terminated, can't be modified or used"))}function $0(n,e,t){var i;return i=n.a.get(e),n.a.set(e,t===void 0?null:t),i===void 0?(++n.c,++n.b.g):++n.d,i}function x5e(n,e,t){var i,r;for(r=n.a.ec().Kc();r.Ob();)if(i=u(r.Pb(),10),Mk(t,u(sn(e,i.p),16)))return i;return null}function OY(n,e,t){var i;return i=0,e&&(mg(n.a)?i+=e.f.a/2:i+=e.f.b/2),t&&(mg(n.a)?i+=t.f.a/2:i+=t.f.b/2),i}function F5e(n,e,t){var i;i=t,!i&&(i=YV(new up,0)),i.Ug(PXn,2),jRn(n.b,e,i.eh(1)),YIe(n,e,i.eh(1)),eLe(e,i.eh(1)),i.Vg()}function DY(n,e,t){var i,r;return i=(B1(),r=new yE,r),aT(i,e),lT(i,t),n&&ve((!n.a&&(n.a=new ti(xo,n,5)),n.a),i),i}function ox(n){var e;return n.Db&64?_s(n):(e=new ls(_s(n)),e.a+=" (identifier: ",Er(e,n.k),e.a+=")",e.a)}function sx(n,e){var t;t=(n.Bb&kc)!=0,e?n.Bb|=kc:n.Bb&=-32769,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,18,t,e))}function LY(n,e){var t;t=(n.Bb&kc)!=0,e?n.Bb|=kc:n.Bb&=-32769,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,18,t,e))}function dm(n,e){var t;t=(n.Bb&wh)!=0,e?n.Bb|=wh:n.Bb&=-16385,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,16,t,e))}function NY(n,e){var t;t=(n.Bb&hr)!=0,e?n.Bb|=hr:n.Bb&=-65537,n.Db&4&&!(n.Db&1)&&it(n,new Bs(n,1,20,t,e))}function $Y(n){var e;return e=K(fs,gh,28,2,15,1),n-=hr,e[0]=(n>>10)+Sy&ui,e[1]=(n&1023)+56320&ui,hh(e,0,e.length)}function B5e(n){var e;return e=sw(n),e>34028234663852886e22?St:e<-34028234663852886e22?li:e}function nr(n,e){var t;return Vr(n)&&Vr(e)&&(t=n+e,Ay"+td(e.c):"e_"+mt(e),n.b&&n.c?td(n.b)+"->"+td(n.c):"e_"+mt(n))}function _5e(n,e){return An(e.b&&e.c?td(e.b)+"->"+td(e.c):"e_"+mt(e),n.b&&n.c?td(n.b)+"->"+td(n.c):"e_"+mt(n))}function x0(n,e){return Mf(),Rs(sa),y.Math.abs(n-e)<=sa||n==e||isNaN(n)&&isNaN(e)?0:ne?1:s0(isNaN(n),isNaN(e))}function El(){El=F,lU=new kC(i8,0),Yj=new kC("POLYLINE",1),Kv=new kC("ORTHOGONAL",2),F3=new kC("SPLINES",3)}function _T(){_T=F,l1n=new uL("ASPECT_RATIO_DRIVEN",0),Oq=new uL("MAX_SCALE_DRIVEN",1),h1n=new uL("AREA_DRIVEN",2)}function H5e(n,e,t){var i;try{l6e(n,e,t)}catch(r){throw r=It(r),O(r,606)?(i=r,M(new $J(i))):M(r)}return e}function q5e(n){var e,t,i;for(t=0,i=n.length;te&&i.Ne(n[c-1],n[c])>0;--c)s=n[c],$t(n,c,n[c-1]),$t(n,c-1,s)}function vn(n,e){var t,i,r,c,s;if(t=e.f,s1(n.c.d,t,e),e.g!=null)for(r=e.g,c=0,s=r.length;ce){wDn(t);break}}q7(t,e)}function X5e(n,e){var t,i,r;i=Sg(e),r=$(R(rw(i,(cn(),Vs)))),t=y.Math.max(0,r/2-.5),I5(e,t,1),nn(n,new NCn(e,t))}function V5e(n,e,t){var i;t.Ug("Straight Line Edge Routing",1),t.dh(e,xrn),i=u(z(e,(Mg(),O2)),27),iGn(n,i),t.dh(e,DS)}function xY(n,e){n.n.c.length==0&&nn(n.n,new NM(n.s,n.t,n.i)),nn(n.b,e),gZ(u(sn(n.n,n.n.c.length-1),209),e),RUn(n,e)}function j5(n){var e;this.a=(e=u(n.e&&n.e(),9),new _o(e,u($s(e,e.length),9),0)),this.b=K(ki,Fn,1,this.a.a.length,5,1)}function Jr(n){var e;return Array.isArray(n)&&n.Tm===J2?za(wo(n))+"@"+(e=mt(n)>>>0,e.toString(16)):n.toString()}function W5e(n,e){return n.h==Ty&&n.m==0&&n.l==0?(e&&(ba=Yc(0,0,0)),nTn((R4(),lun))):(e&&(ba=Yc(n.l,n.m,n.h)),Yc(0,0,0))}function J5e(n,e){switch(e.g){case 2:return n.b;case 1:return n.c;case 4:return n.d;case 3:return n.a;default:return!1}}function yBn(n,e){switch(e.g){case 2:return n.b;case 1:return n.c;case 4:return n.d;case 3:return n.a;default:return!1}}function FY(n,e,t,i){switch(e){case 3:return n.f;case 4:return n.g;case 5:return n.i;case 6:return n.j}return PY(n,e,t,i)}function HT(n,e){if(e==n.d)return n.e;if(e==n.e)return n.d;throw M(new Gn("Node "+e+" not part of edge "+n))}function Q5e(n,e){var t;if(t=oy(n.Dh(),e),O(t,102))return u(t,19);throw M(new Gn(da+e+"' is not a valid reference"))}function Jo(n,e,t,i){if(e<0)ten(n,t,i);else{if(!t.rk())throw M(new Gn(da+t.xe()+p8));u(t,69).wk().Ck(n,n.hi(),e,i)}}function eo(n){var e;if(n.b){if(eo(n.b),n.b.d!=n.c)throw M(new Bo)}else n.d.dc()&&(e=u(n.f.c.xc(n.e),16),e&&(n.d=e))}function Y5e(n){Bb();var e,t,i,r;for(e=n.o.b,i=u(u(ot(n.r,(tn(),ae)),21),87).Kc();i.Ob();)t=u(i.Pb(),117),r=t.e,r.b+=e}function Z5e(n){var e,t,i;for(this.a=new ih,i=new C(n);i.a=r)return e.c+t;return e.c+e.b.gc()}function e8e(n,e){m4();var t,i,r,c;for(i=LNn(n),r=e,F4(i,0,i.length,r),t=0;t0&&(i+=r,++t);return t>1&&(i+=n.d*(t-1)),i}function i8e(n){var e,t,i,r,c;return c=enn(n),t=e7(n.c),i=!t,i&&(r=new Ka,df(c,"knownLayouters",r),e=new lyn(r),qi(n.c,e)),c}function KY(n){var e,t,i;for(i=new Hl,i.a+="[",e=0,t=n.gc();e0&&(zn(e-1,n.length),n.charCodeAt(e-1)==58)&&!lx(n,N9,$9))}function _Y(n,e){var t;return x(n)===x(e)?!0:O(e,92)?(t=u(e,92),n.e==t.e&&n.d==t.d&&I3e(n,t.a)):!1}function zp(n){switch(tn(),n.g){case 4:return Xn;case 1:return Zn;case 3:return ae;case 2:return Wn;default:return sc}}function o8e(n){var e,t;if(n.b)return n.b;for(t=qf?null:n.d;t;){if(e=qf?null:t.b,e)return e;t=qf?null:t.d}return a4(),$un}function HY(n){var e,t,i;for(i=$(R(n.a.of((qe(),iO)))),t=new C(n.a.Sf());t.a>5,e=n&31,i=K(ye,Ke,28,t+1,15,1),i[t]=1<3;)r*=10,--c;n=(n+(r>>1))/r|0}return i.i=n,!0}function Ot(n,e){var t,i,r;if(t=(n.i==null&&bh(n),n.i),i=e.Lj(),i!=-1){for(r=t.length;i=0;--i)for(e=t[i],r=0;r>1,this.k=e-1>>1}function j8e(n){YM(),u(n.of((qe(),Ma)),181).Hc((io(),hO))&&(u(n.of(Ww),181).Fc((zu(),B3)),u(n.of(Ma),181).Mc(hO))}function SBn(n){var e,t;e=n.d==(Yp(),dv),t=GZ(n),e&&!t||!e&&t?U(n.a,(cn(),Th),(Rh(),Uj)):U(n.a,(cn(),Th),(Rh(),qj))}function bx(){bx=F,nC(),EI=(cn(),gb),Qte=If(S(T(Xq,1),Ern,149,0,[Tj,Vs,M2,wb,qw,IH,Av,Sv,OH,J8,C2,Bd,T2]))}function E8e(n,e){var t;return t=u(Wr(n,qu(new ju,new yu,new Eu,S(T(xr,1),G,108,0,[(Gu(),Yr)]))),15),t.Qc(WSn(t.gc()))}function PBn(n,e){var t,i;if(i=new Y3(n.a.ad(e,!0)),i.a.gc()<=1)throw M(new ip);return t=i.a.ec().Kc(),t.Pb(),u(t.Pb(),40)}function C8e(n,e,t){var i,r;return i=$(n.p[e.i.p])+$(n.d[e.i.p])+e.n.b+e.a.b,r=$(n.p[t.i.p])+$(n.d[t.i.p])+t.n.b+t.a.b,r-i}function WY(n,e){var t;return n.i>0&&(e.lengthn.i&&$t(e,n.i,null),e}function UT(n){var e;return n.Db&64?m5(n):(e=new ls(m5(n)),e.a+=" (instanceClassName: ",Er(e,n.D),e.a+=")",e.a)}function GT(n){var e,t,i,r;for(r=0,t=0,i=n.length;t0?(n._j(),i=e==null?0:mt(e),r=(i&et)%n.d.length,t=RHn(n,r,i,e),t!=-1):!1}function IBn(n,e){var t,i;n.a=nr(n.a,1),n.c=y.Math.min(n.c,e),n.b=y.Math.max(n.b,e),n.d+=e,t=e-n.f,i=n.e+t,n.f=i-n.e-t,n.e=i}function JY(n,e){switch(e){case 3:P0(n,0);return;case 4:I0(n,0);return;case 5:eu(n,0);return;case 6:tu(n,0);return}kY(n,e)}function F0(n,e){switch(e.g){case 1:return Cp(n.j,(Ou(),Fon));case 2:return Cp(n.j,(Ou(),Ron));default:return Dn(),Dn(),sr}}function QY(n){m0();var e;switch(e=n.Pc(),e.length){case 0:return qK;case 1:return new VL(Se(e[0]));default:return new PN(q5e(e))}}function OBn(n,e){n.Xj();try{n.d.bd(n.e++,e),n.f=n.d.j,n.g=-1}catch(t){throw t=It(t),O(t,77)?M(new Bo):M(t)}}function gx(){gx=F,TU=new Tvn,zdn=new Avn,Xdn=new Svn,Vdn=new Pvn,Wdn=new Ivn,Jdn=new Ovn,Qdn=new Dvn,Ydn=new Lvn,Zdn=new Nvn}function zT(n,e){kX();var t,i;return t=D7((KE(),KE(),P8)),i=null,e==t&&(i=u(Nc(fun,n),624)),i||(i=new JPn(n),e==t&&Dr(fun,n,i)),i}function DBn(n){cw();var e;return(n.q?n.q:(Dn(),Dn(),Wh))._b((cn(),db))?e=u(v(n,db),203):e=u(v(Hi(n),W8),203),e}function rw(n,e){var t,i;return i=null,kt(n,(cn(),yI))&&(t=u(v(n,yI),96),t.pf(e)&&(i=t.of(e))),i==null&&(i=v(Hi(n),e)),i}function LBn(n,e){var t,i,r;return O(e,44)?(t=u(e,44),i=t.ld(),r=tw(n.Rc(),i),oh(r,t.md())&&(r!=null||n.Rc()._b(i))):!1}function wf(n,e){var t,i,r;return n.f>0&&(n._j(),i=e==null?0:mt(e),r=(i&et)%n.d.length,t=xnn(n,r,i,e),t)?t.md():null}function Xc(n,e,t){var i,r,c;return n.Pj()?(i=n.i,c=n.Qj(),Nk(n,i,e),r=n.Ij(3,null,e,i,c),t?t.nj(r):t=r):Nk(n,n.i,e),t}function T8e(n,e,t){var i,r;return i=new ml(n.e,4,10,(r=e.c,O(r,90)?u(r,29):(On(),Ps)),null,f1(n,e),!1),t?t.nj(i):t=i,t}function A8e(n,e,t){var i,r;return i=new ml(n.e,3,10,null,(r=e.c,O(r,90)?u(r,29):(On(),Ps)),f1(n,e),!1),t?t.nj(i):t=i,t}function NBn(n){Bb();var e;return e=new rr(u(n.e.of((qe(),K2)),8)),n.B.Hc((io(),Hv))&&(e.a<=0&&(e.a=20),e.b<=0&&(e.b=20)),e}function ta(n){dh();var e,t;return t=Ae(n),e=Ae(U1(n,32)),e!=0?new HOn(t,e):t>10||t<0?new gl(1,t):kQn[t]}function Kk(n,e){var t;return Vr(n)&&Vr(e)&&(t=n%e,Ay=0?c=c.a[1]:(r=c,c=c.a[0])}return r}function Hk(n,e,t){var i,r,c;for(r=null,c=n.b;c;){if(i=n.a.Ne(e,c.d),t&&i==0)return c;i<=0?c=c.a[0]:(r=c,c=c.a[1])}return r}function L8e(n,e,t,i){var r,c,s;return r=!1,xOe(n.f,t,i)&&(e9e(n.f,n.a[e][t],n.a[e][i]),c=n.a[e],s=c[i],c[i]=c[t],c[t]=s,r=!0),r}function BBn(n,e,t){var i,r,c,s;for(r=u(ee(n.b,t),183),i=0,s=new C(e.j);s.a>5,e&=31,r=n.d+t+(e==0?0:1),i=K(ye,Ke,28,r,15,1),Oye(i,n.a,t,e),c=new Qa(n.e,r,i),Q6(c),c}function N8e(n,e){var t,i,r;for(i=new te(re(Qt(n).a.Kc(),new En));pe(i);)if(t=u(fe(i),18),r=t.d.i,r.c==e)return!1;return!0}function nZ(n,e,t){var i,r,c,s,f;return s=n.k,f=e.k,i=t[s.g][f.g],r=R(rw(n,i)),c=R(rw(e,i)),y.Math.max((Jn(r),r),(Jn(c),c))}function $8e(){return Error.stackTraceLimit>0?(y.Error.stackTraceLimit=Error.stackTraceLimit=64,!0):"stack"in new Error}function x8e(n,e){return Mf(),Mf(),Rs(sa),(y.Math.abs(n-e)<=sa||n==e||isNaN(n)&&isNaN(e)?0:ne?1:s0(isNaN(n),isNaN(e)))>0}function eZ(n,e){return Mf(),Mf(),Rs(sa),(y.Math.abs(n-e)<=sa||n==e||isNaN(n)&&isNaN(e)?0:ne?1:s0(isNaN(n),isNaN(e)))<0}function KBn(n,e){return Mf(),Mf(),Rs(sa),(y.Math.abs(n-e)<=sa||n==e||isNaN(n)&&isNaN(e)?0:ne?1:s0(isNaN(n),isNaN(e)))<=0}function mx(n,e){for(var t=0;!e[t]||e[t]=="";)t++;for(var i=e[t++];t0&&this.b>0&&(this.g=cM(this.c,this.b,this.a))}function F8e(n,e){var t=n.a,i;e=String(e),t.hasOwnProperty(e)&&(i=t[e]);var r=(K$(),WK)[typeof i],c=r?r(i):wY(typeof i);return c}function wm(n){var e,t,i;if(i=null,e=Eh in n.a,t=!e,t)throw M(new nh("Every element must have an id."));return i=Zp(dl(n,Eh)),i}function B0(n){var e,t;for(t=a_n(n),e=null;n.c==2;)Ye(n),e||(e=(nt(),nt(),new P6(2)),pd(e,t),t=e),t.Jm(a_n(n));return t}function VT(n,e){var t,i,r;return n._j(),i=e==null?0:mt(e),r=(i&et)%n.d.length,t=xnn(n,r,i,e),t?(V$n(n,t),t.md()):null}function XBn(n,e){return n.e>e.e?1:n.ee.d?n.e:n.d=48&&n<48+y.Math.min(10,10)?n-48:n>=97&&n<97?n-97+10:n>=65&&n<65?n-65+10:-1}function B8e(n,e){if(e.c==n)return e.d;if(e.d==n)return e.c;throw M(new Gn("Input edge is not connected to the input port."))}function R8e(n){if(JT(nv,n))return _n(),ov;if(JT(cK,n))return _n(),wa;throw M(new Gn("Expecting true or false"))}function rZ(n){switch(typeof n){case nB:return t1(n);case dtn:return pp(n);case i3:return SAn(n);default:return n==null?0:l0(n)}}function ah(n,e){if(n.a<0)throw M(new Or("Did not call before(...) or after(...) before calling add(...)."));return YX(n,n.a,e),n}function cZ(n){return $M(),O(n,162)?u(ee(hE,MQn),295).Rg(n):Zc(hE,wo(n))?u(ee(hE,wo(n)),295).Rg(n):null}function iu(n){var e,t;return n.Db&32||(t=(e=u(Un(n,16),29),se(e||n.ii())-se(n.ii())),t!=0&&Xp(n,32,K(ki,Fn,1,t,5,1))),n}function Xp(n,e,t){var i;n.Db&e?t==null?jCe(n,e):(i=Rx(n,e),i==-1?n.Eb=t:$t(cd(n.Eb),i,t)):t!=null&>e(n,e,t)}function K8e(n,e,t,i){var r,c;e.c.length!=0&&(r=$Me(t,i),c=xEe(e),qt(fT(new Tn(null,new In(c,1)),new L3n),new MIn(n,t,r,i)))}function _8e(n,e){var t,i,r,c;return i=n.a.length-1,t=e-n.b&i,c=n.c-e&i,r=n.c-n.b&i,EAn(t=c?(R6e(n,e),-1):(B6e(n,e),1)}function WT(n){var e,t,i;if(i=n.Jh(),!i)for(e=0,t=n.Ph();t;t=t.Ph()){if(++e>PB)return t.Qh();if(i=t.Jh(),i||t==n)break}return i}function WBn(n,e){var t;return x(e)===x(n)?!0:!O(e,21)||(t=u(e,21),t.gc()!=n.gc())?!1:n.Ic(t)}function H8e(n,e){return n.ee.e?1:n.fe.f?1:mt(n)-mt(e)}function JT(n,e){return Jn(n),e==null?!1:An(n,e)?!0:n.length==e.length&&An(n.toLowerCase(),e.toLowerCase())}function Ml(n){var e,t;return Ec(n,-129)>0&&Ec(n,128)<0?(ZSn(),e=Ae(n)+128,t=mun[e],!t&&(t=mun[e]=new kG(n)),t):new kG(n)}function dd(){dd=F,Ow=new aC(kh,0),Don=new aC("INSIDE_PORT_SIDE_GROUPS",1),P_=new aC("GROUP_MODEL_ORDER",2),I_=new aC(tin,3)}function q8e(n){var e;return n.b||xhe(n,(e=$ae(n.e,n.a),!e||!An(cK,wf((!e.b&&(e.b=new lo((On(),ar),pc,e)),e.b),"qualified")))),n.c}function U8e(n,e){var t,i;for(t=(zn(e,n.length),n.charCodeAt(e)),i=e+1;i2e3&&(hQn=n,uP=y.setTimeout(_he,10))),cP++==0?(ime((az(),sun)),!0):!1}function r9e(n,e,t){var i;(DQn?(o8e(n),!0):LQn||$Qn?(a4(),!0):NQn&&(a4(),!1))&&(i=new aSn(e),i.b=t,aje(n,i))}function kx(n,e){var t;t=!n.A.Hc((go(),Gd))||n.q==(Oi(),qc),n.u.Hc((zu(),Fl))?t?XDe(n,e):UGn(n,e):n.u.Hc(Pa)&&(t?dDe(n,e):czn(n,e))}function eRn(n){var e;x(z(n,(qe(),B2)))===x((jl(),uO))&&(At(n)?(e=u(z(At(n),B2),346),ht(n,B2,e)):ht(n,B2,M9))}function c9e(n){var e,t;return kt(n.d.i,(cn(),Cv))?(e=u(v(n.c.i,Cv),17),t=u(v(n.d.i,Cv),17),jc(e.a,t.a)>0):!1}function tRn(n,e,t){return new Ho(y.Math.min(n.a,e.a)-t/2,y.Math.min(n.b,e.b)-t/2,y.Math.abs(n.a-e.a)+t,y.Math.abs(n.b-e.b)+t)}function iRn(n){var e;this.d=new Z,this.j=new Li,this.g=new Li,e=n.g.b,this.f=u(v(Hi(e),(cn(),Do)),88),this.e=$(R(nA(e,qw)))}function rRn(n){this.d=new Z,this.e=new Ql,this.c=K(ye,Ke,28,(tn(),S(T(lr,1),Mc,64,0,[sc,Xn,Zn,ae,Wn])).length,15,1),this.b=n}function sZ(n,e,t){var i;switch(i=t[n.g][e],n.g){case 1:case 3:return new V(0,i);case 2:case 4:return new V(i,0);default:return null}}function cRn(n,e,t){var i,r;r=u(V7(e.f),205);try{r.rf(n,t),hIn(e.f,r)}catch(c){throw c=It(c),O(c,103)?(i=c,M(i)):M(c)}}function uRn(n,e,t){var i,r,c,s,f,h;return i=null,f=Zen(z4(),e),c=null,f&&(r=null,h=Qen(f,t),s=null,h!=null&&(s=n.qf(f,h)),r=s,c=r),i=c,i}function yx(n,e,t,i){var r;if(r=n.length,e>=r)return r;for(e=e>0?e:0;ei&&$t(e,i,null),e}function oRn(n,e){var t,i;for(i=n.a.length,e.lengthi&&$t(e,i,null),e}function gm(n,e){var t,i;if(++n.j,e!=null&&(t=(i=n.a.Cb,O(i,99)?u(i,99).th():null),hCe(e,t))){Xp(n.a,4,t);return}Xp(n.a,4,u(e,129))}function u9e(n){var e;if(n==null)return null;if(e=lMe(Fc(n,!0)),e==null)throw M(new kD("Invalid hexBinary value: '"+n+"'"));return e}function QT(n,e,t){var i;e.a.length>0&&(nn(n.b,new SSn(e.a,t)),i=e.a.length,0i&&(e.a+=ITn(K(fs,gh,28,-i,15,1))))}function sRn(n,e,t){var i,r,c;if(!t[e.d])for(t[e.d]=!0,r=new C($g(e));r.a=n.b>>1)for(i=n.c,t=n.b;t>e;--t)i=i.b;else for(i=n.a.a,t=0;t=0?n.Wh(r):hF(n,i)):t<0?hF(n,i):u(i,69).wk().Bk(n,n.hi(),t)}function aRn(n){var e,t,i;for(i=(!n.o&&(n.o=new Iu((Cc(),il),T1,n,0)),n.o),t=i.c.Kc();t.e!=t.i.gc();)e=u(t.Yj(),44),e.md();return uk(i)}function rn(n){var e;if(O(n.a,4)){if(e=cZ(n.a),e==null)throw M(new Or(NVn+n.b+"'. "+LVn+(ll(lE),lE.k)+bcn));return e}else return n.a}function b9e(n,e){var t,i;if(n.j.length!=e.j.length)return!1;for(t=0,i=n.j.length;t=64&&e<128&&(r=hf(r,Fs(1,e-64)));return r}function nA(n,e){var t,i;return i=null,kt(n,(qe(),$3))&&(t=u(v(n,$3),96),t.pf(e)&&(i=t.of(e))),i==null&&Hi(n)&&(i=v(Hi(n),e)),i}function w9e(n,e){var t;return t=u(v(n,(cn(),Fr)),75),yL(e,LZn)?t?vo(t):(t=new Mu,U(n,Fr,t)):t&&U(n,Fr,null),t}function M5(){M5=F,aon=(qe(),qan),g_=Ean,DYn=$2,lon=C1,xYn=(aA(),Uun),$Yn=Hun,FYn=zun,NYn=_un,LYn=(Q$(),son),w_=PYn,hon=IYn,pP=OYn}function eA(n){switch($z(),this.c=new Z,this.d=n,n.g){case 0:case 2:this.a=qW(Oon),this.b=St;break;case 3:case 1:this.a=Oon,this.b=li}}function g9e(n){var e;Ep(u(v(n,(cn(),Kt)),101))&&(e=n.b,nHn((Ln(0,e.c.length),u(e.c[0],30))),nHn(u(sn(e,e.c.length-1),30)))}function p9e(n,e){e.Ug("Self-Loop post-processing",1),qt(ut(ut(rc(new Tn(null,new In(n.b,16)),new s2n),new f2n),new h2n),new l2n),e.Vg()}function dRn(n,e,t){var i,r;if(n.c)eu(n.c,n.c.i+e),tu(n.c,n.c.j+t);else for(r=new C(n.b);r.a=0&&(t.d=n.t);break;case 3:n.t>=0&&(t.a=n.t)}n.C&&(t.b=n.C.b,t.c=n.C.c)}function T5(){T5=F,Nhn=new d7(Crn,0),KH=new d7(sR,1),_H=new d7("LINEAR_SEGMENTS",2),Y8=new d7("BRANDES_KOEPF",3),Z8=new d7(sVn,4)}function A5(){A5=F,fj=new hC(eS,0),wP=new hC(HB,1),gP=new hC(qB,2),hj=new hC(UB,3),fj.a=!1,wP.a=!0,gP.a=!1,hj.a=!0}function Vp(){Vp=F,uj=new fC(eS,0),cj=new fC(HB,1),oj=new fC(qB,2),sj=new fC(UB,3),uj.a=!1,cj.a=!0,oj.a=!1,sj.a=!0}function Wp(n,e,t,i){var r;return t>=0?n.Sh(e,t,i):(n.Ph()&&(i=(r=n.Fh(),r>=0?n.Ah(i):n.Ph().Th(n,-1-r,null,i))),n.Ch(e,t,i))}function fZ(n,e){switch(e){case 7:!n.e&&(n.e=new Nn(Vt,n,7,4)),me(n.e);return;case 8:!n.d&&(n.d=new Nn(Vt,n,8,5)),me(n.d);return}JY(n,e)}function ht(n,e,t){return t==null?(!n.o&&(n.o=new Iu((Cc(),il),T1,n,0)),VT(n.o,e)):(!n.o&&(n.o=new Iu((Cc(),il),T1,n,0)),Vk(n.o,e,t)),n}function pRn(n,e){Dn();var t,i,r,c;for(t=n,c=e,O(n,21)&&!O(e,21)&&(t=e,c=n),r=t.Kc();r.Ob();)if(i=r.Pb(),c.Hc(i))return!1;return!0}function j9e(n,e,t,i){if(e.at.b)return!0}return!1}function Tx(n,e){return Ai(n)?!!iQn[e]:n.Sm?!!n.Sm[e]:$b(n)?!!tQn[e]:Nb(n)?!!eQn[e]:!1}function E9e(n){var e;e=n.a;do e=u(fe(new te(re(ji(e).a.Kc(),new En))),18).c.i,e.k==(Vn(),Mi)&&n.b.Fc(e);while(e.k==(Vn(),Mi));n.b=Qo(n.b)}function mRn(n,e){var t,i,r;for(r=n,i=new te(re(ji(e).a.Kc(),new En));pe(i);)t=u(fe(i),18),t.c.i.c&&(r=y.Math.max(r,t.c.i.c.p));return r}function C9e(n,e){var t,i,r;for(r=0,i=u(u(ot(n.r,e),21),87).Kc();i.Ob();)t=u(i.Pb(),117),r+=t.d.d+t.b.Mf().b+t.d.a,i.Ob()&&(r+=n.w);return r}function M9e(n,e){var t,i,r;for(r=0,i=u(u(ot(n.r,e),21),87).Kc();i.Ob();)t=u(i.Pb(),117),r+=t.d.b+t.b.Mf().a+t.d.c,i.Ob()&&(r+=n.w);return r}function vRn(n){var e,t,i,r;if(i=0,r=aw(n),r.c.length==0)return 1;for(t=new C(r);t.a=0?n.Lh(s,t,!0):H0(n,c,t)):u(c,69).wk().yk(n,n.hi(),r,t,i)}function P9e(n,e,t,i){var r,c;c=e.pf((qe(),R2))?u(e.of(R2),21):n.j,r=d5e(c),r!=(VA(),l_)&&(t&&!tZ(r)||bnn(aMe(n,r,i),e))}function I9e(n){switch(n.g){case 1:return N0(),rj;case 3:return N0(),ij;case 2:return N0(),d_;case 4:return N0(),a_;default:return null}}function O9e(n,e,t){if(n.e)switch(n.b){case 1:yge(n.c,e,t);break;case 0:jge(n.c,e,t)}else KDn(n.c,e,t);n.a[e.p][t.p]=n.c.i,n.a[t.p][e.p]=n.c.e}function kRn(n){var e,t;if(n==null)return null;for(t=K(Qh,J,199,n.length,0,2),e=0;e=0)return r;if(n.ol()){for(i=0;i=r)throw M(new Kb(e,r));if(n.Si()&&(i=n.dd(t),i>=0&&i!=e))throw M(new Gn(Vy));return n.Xi(e,t)}function hZ(n,e){if(this.a=u(Se(n),253),this.b=u(Se(e),253),n.Ed(e)>0||n==(dD(),_K)||e==(bD(),HK))throw M(new Gn("Invalid range: "+qDn(n,e)))}function yRn(n){var e,t;for(this.b=new Z,this.c=n,this.a=!1,t=new C(n.a);t.a0),(e&-e)==e)return wi(e*to(n,31)*4656612873077393e-25);do t=to(n,31),i=t%e;while(t-i+(e-1)<0);return wi(i)}function F9e(n,e,t){switch(t.g){case 1:n.a=e.a/2,n.b=0;break;case 2:n.a=e.a,n.b=e.b/2;break;case 3:n.a=e.a/2,n.b=e.b;break;case 4:n.a=0,n.b=e.b/2}}function qk(n,e,t,i){var r,c;for(r=e;r1&&(c=L9e(n,e)),c}function CRn(n){var e;return e=$(R(z(n,(qe(),Qj))))*y.Math.sqrt((!n.a&&(n.a=new q(Qe,n,10,11)),n.a).i),new V(e,e/$(R(z(n,rO))))}function Sx(n){var e;return n.f&&n.f.Vh()&&(e=u(n.f,54),n.f=u(na(n,e),84),n.f!=e&&n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,9,8,e,n.f))),n.f}function Px(n){var e;return n.i&&n.i.Vh()&&(e=u(n.i,54),n.i=u(na(n,e),84),n.i!=e&&n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,9,7,e,n.i))),n.i}function br(n){var e;return n.b&&n.b.Db&64&&(e=n.b,n.b=u(na(n,e),19),n.b!=e&&n.Db&4&&!(n.Db&1)&&it(n,new Ci(n,9,21,e,n.b))),n.b}function uA(n,e){var t,i,r;n.d==null?(++n.e,++n.f):(i=e.Bi(),uTe(n,n.f+1),r=(i&et)%n.d.length,t=n.d[r],!t&&(t=n.d[r]=n.dk()),t.Fc(e),++n.f)}function dZ(n,e,t){var i;return e.tk()?!1:e.Ik()!=-2?(i=e.ik(),i==null?t==null:rt(i,t)):e.qk()==n.e.Dh()&&t==null}function oA(){var n;Co(16,$zn),n=sxn(16),this.b=K(UK,Cy,303,n,0,1),this.c=K(UK,Cy,303,n,0,1),this.a=null,this.e=null,this.i=0,this.f=n-1,this.g=0}function Tl(n){vV.call(this),this.k=(Vn(),zt),this.j=(Co(6,mw),new Gc(6)),this.b=(Co(2,mw),new Gc(2)),this.d=new sD,this.f=new nz,this.a=n}function R9e(n){var e,t;n.c.length<=1||(e=Sqn(n,(tn(),ae)),w_n(n,u(e.a,17).a,u(e.b,17).a),t=Sqn(n,Wn),w_n(n,u(t.a,17).a,u(t.b,17).a))}function K9e(n,e,t){var i,r;for(r=n.a.b,i=r.c.length;i102?-1:n<=57?n-48:n<65?-1:n<=70?n-65+10:n<97?-1:n-97+10}function Nx(n,e){if(n==null)throw M(new sp("null key in entry: null="+e));if(e==null)throw M(new sp("null value in entry: "+n+"=null"))}function q9e(n,e){for(var t,i;n.Ob();)if(!e.Ob()||(t=n.Pb(),i=e.Pb(),!(x(t)===x(i)||t!=null&&rt(t,i))))return!1;return!e.Ob()}function ARn(n,e){var t;return t=S(T(Pi,1),Tr,28,15,[Z$(n.a[0],e),Z$(n.a[1],e),Z$(n.a[2],e)]),n.d&&(t[0]=y.Math.max(t[0],t[2]),t[2]=t[0]),t}function SRn(n,e){var t;return t=S(T(Pi,1),Tr,28,15,[$T(n.a[0],e),$T(n.a[1],e),$T(n.a[2],e)]),n.d&&(t[0]=y.Math.max(t[0],t[2]),t[2]=t[0]),t}function wZ(n,e,t){Ep(u(v(e,(cn(),Kt)),101))||(PJ(n,e,h1(e,t)),PJ(n,e,h1(e,(tn(),ae))),PJ(n,e,h1(e,Xn)),Dn(),Yt(e.j,new N7n(n)))}function PRn(n){var e,t;for(n.c||sOe(n),t=new Mu,e=new C(n.a),E(e);e.a0&&(zn(0,e.length),e.charCodeAt(0)==43)?(zn(1,e.length+1),e.substr(1)):e))}function i7e(n){var e;return n==null?null:new H1((e=Fc(n,!0),e.length>0&&(zn(0,e.length),e.charCodeAt(0)==43)?(zn(1,e.length+1),e.substr(1)):e))}function pZ(n,e,t,i,r,c,s,f){var h,l;i&&(h=i.a[0],h&&pZ(n,e,t,h,r,c,s,f),qx(n,t,i.d,r,c,s,f)&&e.Fc(i),l=i.a[1],l&&pZ(n,e,t,l,r,c,s,f))}function Rg(n,e,t){try{return o0(C$(n,e,t),1)}catch(i){throw i=It(i),O(i,333)?M(new Ir(GB+n.o+"*"+n.p+zB+e+ur+t+XB)):M(i)}}function NRn(n,e,t){try{return o0(C$(n,e,t),0)}catch(i){throw i=It(i),O(i,333)?M(new Ir(GB+n.o+"*"+n.p+zB+e+ur+t+XB)):M(i)}}function $Rn(n,e,t){try{return o0(C$(n,e,t),2)}catch(i){throw i=It(i),O(i,333)?M(new Ir(GB+n.o+"*"+n.p+zB+e+ur+t+XB)):M(i)}}function xRn(n,e){if(n.g==-1)throw M(new Cu);n.Xj();try{n.d.hd(n.g,e),n.f=n.d.j}catch(t){throw t=It(t),O(t,77)?M(new Bo):M(t)}}function r7e(n){var e,t,i,r,c;for(i=new C(n.b);i.ac&&$t(e,c,null),e}function c7e(n,e){var t,i;if(i=n.gc(),e==null){for(t=0;t0&&(h+=r),l[a]=s,s+=f*(h+i)}function BRn(n){var e,t,i;for(i=n.f,n.n=K(Pi,Tr,28,i,15,1),n.d=K(Pi,Tr,28,i,15,1),e=0;e0?n.c:0),++r;n.b=i,n.d=c}function qRn(n,e){var t;return t=S(T(Pi,1),Tr,28,15,[aZ(n,(bf(),bc),e),aZ(n,Wc,e),aZ(n,wc,e)]),n.f&&(t[0]=y.Math.max(t[0],t[2]),t[2]=t[0]),t}function d7e(n,e,t){var i;try{xA(n,e+n.j,t+n.k,!1,!0)}catch(r){throw r=It(r),O(r,77)?(i=r,M(new Ir(i.g+iS+e+ur+t+")."))):M(r)}}function b7e(n,e,t){var i;try{xA(n,e+n.j,t+n.k,!0,!1)}catch(r){throw r=It(r),O(r,77)?(i=r,M(new Ir(i.g+iS+e+ur+t+")."))):M(r)}}function URn(n){var e;kt(n,(cn(),ab))&&(e=u(v(n,ab),21),e.Hc((lw(),Js))?(e.Mc(Js),e.Fc(Qs)):e.Hc(Qs)&&(e.Mc(Qs),e.Fc(Js)))}function GRn(n){var e;kt(n,(cn(),ab))&&(e=u(v(n,ab),21),e.Hc((lw(),Zs))?(e.Mc(Zs),e.Fc(Cs)):e.Hc(Cs)&&(e.Mc(Cs),e.Fc(Zs)))}function Kx(n,e,t,i){var r,c,s,f;return n.a==null&&gje(n,e),s=e.b.j.c.length,c=t.d.p,f=i.d.p,r=f-1,r<0&&(r=s-1),c<=r?n.a[r]-n.a[c]:n.a[s-1]-n.a[c]+n.a[r]}function w7e(n){var e,t;if(!n.b)for(n.b=RM(u(n.f,27).kh().i),t=new ne(u(n.f,27).kh());t.e!=t.i.gc();)e=u(ce(t),135),nn(n.b,new pD(e));return n.b}function g7e(n){var e,t;if(!n.e)for(n.e=RM(mN(u(n.f,27)).i),t=new ne(mN(u(n.f,27)));t.e!=t.i.gc();)e=u(ce(t),123),nn(n.e,new Bkn(e));return n.e}function zRn(n){var e,t;if(!n.a)for(n.a=RM(AM(u(n.f,27)).i),t=new ne(AM(u(n.f,27)));t.e!=t.i.gc();)e=u(ce(t),27),nn(n.a,new ML(n,e));return n.a}function K0(n){var e;if(!n.C&&(n.D!=null||n.B!=null))if(e=iDe(n),e)n.hl(e);else try{n.hl(null)}catch(t){if(t=It(t),!O(t,63))throw M(t)}return n.C}function p7e(n){switch(n.q.g){case 5:gKn(n,(tn(),Xn)),gKn(n,ae);break;case 4:mGn(n,(tn(),Xn)),mGn(n,ae);break;default:y_n(n,(tn(),Xn)),y_n(n,ae)}}function m7e(n){switch(n.q.g){case 5:pKn(n,(tn(),Zn)),pKn(n,Wn);break;case 4:vGn(n,(tn(),Zn)),vGn(n,Wn);break;default:j_n(n,(tn(),Zn)),j_n(n,Wn)}}function Kg(n,e){var t,i,r;for(r=new Li,i=n.Kc();i.Ob();)t=u(i.Pb(),36),Sm(t,r.a,0),r.a+=t.f.a+e,r.b=y.Math.max(r.b,t.f.b);return r.b>0&&(r.b+=e),r}function hA(n,e){var t,i,r;for(r=new Li,i=n.Kc();i.Ob();)t=u(i.Pb(),36),Sm(t,0,r.b),r.b+=t.f.b+e,r.a=y.Math.max(r.a,t.f.a);return r.a>0&&(r.a+=e),r}function XRn(n){var e,t,i;for(i=et,t=new C(n.a);t.a>16==6?n.Cb.Th(n,5,jf,e):(i=br(u($n((t=u(Un(n,16),29),t||n.ii()),n.Db>>16),19)),n.Cb.Th(n,i.n,i.f,e))}function v7e(n){O4();var e=n.e;if(e&&e.stack){var t=e.stack,i=e+`
                                         `;return t.substring(0,i.length)==i&&(t=t.substring(i.length)),t.split(`
                                        diff --git a/assets/freedom.html-D3yZYD_4.js b/assets/freedom.html-CBf9uuEF.js
                                        similarity index 99%
                                        rename from assets/freedom.html-D3yZYD_4.js
                                        rename to assets/freedom.html-CBf9uuEF.js
                                        index ddfa9c81e7..155528c321 100644
                                        --- a/assets/freedom.html-D3yZYD_4.js
                                        +++ b/assets/freedom.html-CBf9uuEF.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as a,o as l,c as d,a as t,b as e,d as o,w as n,e as c}from"./app-5SoadDYS.js";const r={},i=c(`

                                        Freedom

                                        Freedom 是一个出站协议,可以用来向任意网络发送(正常的) TCP 或 UDP 数据。

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as p,r as a,o as l,c as d,a as t,b as e,d as o,w as n,e as c}from"./app-Bw2NG-QJ.js";const r={},i=c(`

                                        Freedom

                                        Freedom 是一个出站协议,可以用来向任意网络发送(正常的) TCP 或 UDP 数据。

                                        OutboundConfigurationObject

                                        {
                                           "domainStrategy": "AsIs",
                                           "redirect": "127.0.0.1:3366",
                                           "userLevel": 0,
                                        diff --git a/assets/freedom.html-DW3aa4An.js b/assets/freedom.html-CxIu6tCF.js
                                        similarity index 98%
                                        rename from assets/freedom.html-DW3aa4An.js
                                        rename to assets/freedom.html-CxIu6tCF.js
                                        index 3c70d8c5e8..81cbb9277d 100644
                                        --- a/assets/freedom.html-DW3aa4An.js
                                        +++ b/assets/freedom.html-CxIu6tCF.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as c,o as d,c as u,a as t,b as o,d as e,w as s,e as a}from"./app-5SoadDYS.js";const p={},r=a(`

                                        Freedom

                                        Freedom is an outbound protocol that can be used to send (normal) TCP or UDP data to any network.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as i,r as c,o as d,c as u,a as t,b as o,d as e,w as s,e as a}from"./app-Bw2NG-QJ.js";const p={},r=a(`

                                        Freedom

                                        Freedom is an outbound protocol that can be used to send (normal) TCP or UDP data to any network.

                                        OutboundConfigurationObject

                                        {
                                           "domainStrategy": "AsIs",
                                           "redirect": "127.0.0.1:3366",
                                           "userLevel": 0,
                                        diff --git a/assets/freedom.html-Dxeb5oma.js b/assets/freedom.html-D6jTnnzE.js
                                        similarity index 99%
                                        rename from assets/freedom.html-Dxeb5oma.js
                                        rename to assets/freedom.html-D6jTnnzE.js
                                        index 6b070148b8..b1618e2312 100644
                                        --- a/assets/freedom.html-Dxeb5oma.js
                                        +++ b/assets/freedom.html-D6jTnnzE.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as c,o as l,c as d,a as t,b as e,d as o,w as s,e as a}from"./app-5SoadDYS.js";const r={},i=a(`

                                        Freedom

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

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as p,r as c,o as l,c as d,a as t,b as e,d as o,w as s,e as a}from"./app-Bw2NG-QJ.js";const r={},i=a(`

                                        Freedom

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

                                        OutboundConfigurationObject

                                        {
                                           "domainStrategy": "AsIs",
                                           "redirect": "127.0.0.1:3366",
                                           "userLevel": 0,
                                        diff --git a/assets/ganttDiagram-b62c793e-B3546ou_.js b/assets/ganttDiagram-b62c793e-BY6nXXtR.js
                                        similarity index 99%
                                        rename from assets/ganttDiagram-b62c793e-B3546ou_.js
                                        rename to assets/ganttDiagram-b62c793e-BY6nXXtR.js
                                        index 3e1b5bb9a0..8f68fb1548 100644
                                        --- a/assets/ganttDiagram-b62c793e-B3546ou_.js
                                        +++ b/assets/ganttDiagram-b62c793e-BY6nXXtR.js
                                        @@ -1,4 +1,4 @@
                                        -import{au as Be,av as Ze,aw as Xe,ax as qe,ay as Dn,az as Kt,aA as Mn,aB as ye,aC as ke,aD as nt,c as wt,s as Sn,g as _n,x as Un,y as Yn,b as Fn,a as Ln,A as An,m as En,l as qt,h as Pt,i as In,j as Wn,z as On}from"./mermaid.core-CArNAncI.js";import{b as Hn,t as Ue,c as Nn,a as Vn,l as zn}from"./linear-DFdMY4Xo.js";import{i as Pn}from"./init-Gi6I4Gst.js";import"./app-5SoadDYS.js";function Rn(t,e){let n;if(e===void 0)for(const r of t)r!=null&&(n=r)&&(n=r);else{let r=-1;for(let i of t)(i=e(i,++r,t))!=null&&(n=i)&&(n=i)}return n}function Bn(t,e){let n;if(e===void 0)for(const r of t)r!=null&&(n>r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of t)(i=e(i,++r,t))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function Zn(t){return t}var Bt=1,te=2,ue=3,Rt=4,Ye=1e-6;function Xn(t){return"translate("+t+",0)"}function qn(t){return"translate(0,"+t+")"}function Gn(t){return e=>+t(e)}function jn(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),n=>+t(n)+e}function Qn(){return!this.__axis}function Ge(t,e){var n=[],r=null,i=null,s=6,a=6,k=3,Y=typeof window<"u"&&window.devicePixelRatio>1?0:.5,g=t===Bt||t===Rt?-1:1,b=t===Rt||t===te?"x":"y",U=t===Bt||t===ue?Xn:qn;function C(v){var q=r??(e.ticks?e.ticks.apply(e,n):e.domain()),y=i??(e.tickFormat?e.tickFormat.apply(e,n):Zn),L=Math.max(s,0)+k,O=e.range(),W=+O[0]+Y,B=+O[O.length-1]+Y,Z=(e.bandwidth?jn:Gn)(e.copy(),Y),Q=v.selection?v.selection():v,x=Q.selectAll(".domain").data([null]),E=Q.selectAll(".tick").data(q,e).order(),T=E.exit(),F=E.enter().append("g").attr("class","tick"),D=E.select("line"),w=E.select("text");x=x.merge(x.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),E=E.merge(F),D=D.merge(F.append("line").attr("stroke","currentColor").attr(b+"2",g*s)),w=w.merge(F.append("text").attr("fill","currentColor").attr(b,g*L).attr("dy",t===Bt?"0em":t===ue?"0.71em":"0.32em")),v!==Q&&(x=x.transition(v),E=E.transition(v),D=D.transition(v),w=w.transition(v),T=T.transition(v).attr("opacity",Ye).attr("transform",function(o){return isFinite(o=Z(o))?U(o+Y):this.getAttribute("transform")}),F.attr("opacity",Ye).attr("transform",function(o){var d=this.parentNode.__axis;return U((d&&isFinite(d=d(o))?d:Z(o))+Y)})),T.remove(),x.attr("d",t===Rt||t===te?a?"M"+g*a+","+W+"H"+Y+"V"+B+"H"+g*a:"M"+Y+","+W+"V"+B:a?"M"+W+","+g*a+"V"+Y+"H"+B+"V"+g*a:"M"+W+","+Y+"H"+B),E.attr("opacity",1).attr("transform",function(o){return U(Z(o)+Y)}),D.attr(b+"2",g*s),w.attr(b,g*L).text(y),Q.filter(Qn).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===te?"start":t===Rt?"end":"middle"),Q.each(function(){this.__axis=Z})}return C.scale=function(v){return arguments.length?(e=v,C):e},C.ticks=function(){return n=Array.from(arguments),C},C.tickArguments=function(v){return arguments.length?(n=v==null?[]:Array.from(v),C):n.slice()},C.tickValues=function(v){return arguments.length?(r=v==null?null:Array.from(v),C):r&&r.slice()},C.tickFormat=function(v){return arguments.length?(i=v,C):i},C.tickSize=function(v){return arguments.length?(s=a=+v,C):s},C.tickSizeInner=function(v){return arguments.length?(s=+v,C):s},C.tickSizeOuter=function(v){return arguments.length?(a=+v,C):a},C.tickPadding=function(v){return arguments.length?(k=+v,C):k},C.offset=function(v){return arguments.length?(Y=+v,C):Y},C}function Jn(t){return Ge(Bt,t)}function $n(t){return Ge(ue,t)}const Kn=Math.PI/180,tr=180/Math.PI,Gt=18,je=.96422,Qe=1,Je=.82521,$e=4/29,Ct=6/29,Ke=3*Ct*Ct,er=Ct*Ct*Ct;function tn(t){if(t instanceof ot)return new ot(t.l,t.a,t.b,t.opacity);if(t instanceof ut)return en(t);t instanceof Xe||(t=Dn(t));var e=ie(t.r),n=ie(t.g),r=ie(t.b),i=ee((.2225045*e+.7168786*n+.0606169*r)/Qe),s,a;return e===n&&n===r?s=a=i:(s=ee((.4360747*e+.3850649*n+.1430804*r)/je),a=ee((.0139322*e+.0971045*n+.7141733*r)/Je)),new ot(116*i-16,500*(s-i),200*(i-a),t.opacity)}function nr(t,e,n,r){return arguments.length===1?tn(t):new ot(t,e,n,r??1)}function ot(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}Be(ot,nr,Ze(qe,{brighter(t){return new ot(this.l+Gt*(t??1),this.a,this.b,this.opacity)},darker(t){return new ot(this.l-Gt*(t??1),this.a,this.b,this.opacity)},rgb(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,n=isNaN(this.b)?t:t-this.b/200;return e=je*ne(e),t=Qe*ne(t),n=Je*ne(n),new Xe(re(3.1338561*e-1.6168667*t-.4906146*n),re(-.9787684*e+1.9161415*t+.033454*n),re(.0719453*e-.2289914*t+1.4052427*n),this.opacity)}}));function ee(t){return t>er?Math.pow(t,1/3):t/Ke+$e}function ne(t){return t>Ct?t*t*t:Ke*(t-$e)}function re(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function ie(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function rr(t){if(t instanceof ut)return new ut(t.h,t.c,t.l,t.opacity);if(t instanceof ot||(t=tn(t)),t.a===0&&t.b===0)return new ut(NaN,0(t(s=new Date(+s)),s),i.ceil=s=>(t(s=new Date(s-1)),e(s,1),t(s),s),i.round=s=>{const a=i(s),k=i.ceil(s);return s-a(e(s=new Date(+s),a==null?1:Math.floor(a)),s),i.range=(s,a,k)=>{const Y=[];if(s=i.ceil(s),k=k==null?1:Math.floor(k),!(s0))return Y;let g;do Y.push(g=new Date(+s)),e(s,k),t(s);while(gK(a=>{if(a>=a)for(;t(a),!s(a);)a.setTime(a-1)},(a,k)=>{if(a>=a)if(k<0)for(;++k<=0;)for(;e(a,-1),!s(a););else for(;--k>=0;)for(;e(a,1),!s(a););}),n&&(i.count=(s,a)=>(se.setTime(+s),ae.setTime(+a),t(se),t(ae),Math.floor(n(se,ae))),i.every=s=>(s=Math.floor(s),!isFinite(s)||!(s>0)?null:s>1?i.filter(r?a=>r(a)%s===0:a=>i.count(0,a)%s===0):i)),i}const Mt=K(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);Mt.every=t=>(t=Math.floor(t),!isFinite(t)||!(t>0)?null:t>1?K(e=>{e.setTime(Math.floor(e/t)*t)},(e,n)=>{e.setTime(+e+n*t)},(e,n)=>(n-e)/t):Mt);Mt.range;const ft=1e3,rt=ft*60,ht=rt*60,dt=ht*24,pe=dt*7,Fe=dt*30,oe=dt*365,gt=K(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+e*ft)},(t,e)=>(e-t)/ft,t=>t.getUTCSeconds());gt.range;const At=K(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*ft)},(t,e)=>{t.setTime(+t+e*rt)},(t,e)=>(e-t)/rt,t=>t.getMinutes());At.range;const or=K(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+e*rt)},(t,e)=>(e-t)/rt,t=>t.getUTCMinutes());or.range;const Et=K(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*ft-t.getMinutes()*rt)},(t,e)=>{t.setTime(+t+e*ht)},(t,e)=>(e-t)/ht,t=>t.getHours());Et.range;const cr=K(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+e*ht)},(t,e)=>(e-t)/ht,t=>t.getUTCHours());cr.range;const yt=K(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*rt)/dt,t=>t.getDate()-1);yt.range;const Te=K(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/dt,t=>t.getUTCDate()-1);Te.range;const lr=K(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/dt,t=>Math.floor(t/dt));lr.range;function Tt(t){return K(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(e,n)=>{e.setDate(e.getDate()+n*7)},(e,n)=>(n-e-(n.getTimezoneOffset()-e.getTimezoneOffset())*rt)/pe)}const Ot=Tt(0),It=Tt(1),nn=Tt(2),rn=Tt(3),kt=Tt(4),sn=Tt(5),an=Tt(6);Ot.range;It.range;nn.range;rn.range;kt.range;sn.range;an.range;function vt(t){return K(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(e,n)=>{e.setUTCDate(e.getUTCDate()+n*7)},(e,n)=>(n-e)/pe)}const on=vt(0),jt=vt(1),ur=vt(2),fr=vt(3),St=vt(4),hr=vt(5),dr=vt(6);on.range;jt.range;ur.range;fr.range;St.range;hr.range;dr.range;const Wt=K(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth());Wt.range;const mr=K(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth());mr.range;const mt=K(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());mt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:K(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,n)=>{e.setFullYear(e.getFullYear()+n*t)});mt.range;const pt=K(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());pt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:K(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,n)=>{e.setUTCFullYear(e.getUTCFullYear()+n*t)});pt.range;function gr(t,e,n,r,i,s){const a=[[gt,1,ft],[gt,5,5*ft],[gt,15,15*ft],[gt,30,30*ft],[s,1,rt],[s,5,5*rt],[s,15,15*rt],[s,30,30*rt],[i,1,ht],[i,3,3*ht],[i,6,6*ht],[i,12,12*ht],[r,1,dt],[r,2,2*dt],[n,1,pe],[e,1,Fe],[e,3,3*Fe],[t,1,oe]];function k(g,b,U){const C=bL).right(a,C);if(v===a.length)return t.every(Ue(g/oe,b/oe,U));if(v===0)return Mt.every(Math.max(Ue(g,b,U),1));const[q,y]=a[C/a[v-1][2]53)return null;"w"in l||(l.w=1),"Z"in l?(N=le(Yt(l.y,0,1)),j=N.getUTCDay(),N=j>4||j===0?jt.ceil(N):jt(N),N=Te.offset(N,(l.V-1)*7),l.y=N.getUTCFullYear(),l.m=N.getUTCMonth(),l.d=N.getUTCDate()+(l.w+6)%7):(N=ce(Yt(l.y,0,1)),j=N.getDay(),N=j>4||j===0?It.ceil(N):It(N),N=yt.offset(N,(l.V-1)*7),l.y=N.getFullYear(),l.m=N.getMonth(),l.d=N.getDate()+(l.w+6)%7)}else("W"in l||"U"in l)&&("w"in l||(l.w="u"in l?l.u%7:"W"in l?1:0),j="Z"in l?le(Yt(l.y,0,1)).getUTCDay():ce(Yt(l.y,0,1)).getDay(),l.m=0,l.d="W"in l?(l.w+6)%7+l.W*7-(j+5)%7:l.w+l.U*7-(j+6)%7);return"Z"in l?(l.H+=l.Z/100|0,l.M+=l.Z%100,le(l)):ce(l)}}function T(p,A,M,l){for(var R=0,N=A.length,j=M.length,J,et;R=j)return-1;if(J=A.charCodeAt(R++),J===37){if(J=A.charAt(R++),et=Q[J in Le?A.charAt(R++):J],!et||(l=et(p,M,l))<0)return-1}else if(J!=M.charCodeAt(l++))return-1}return l}function F(p,A,M){var l=g.exec(A.slice(M));return l?(p.p=b.get(l[0].toLowerCase()),M+l[0].length):-1}function D(p,A,M){var l=v.exec(A.slice(M));return l?(p.w=q.get(l[0].toLowerCase()),M+l[0].length):-1}function w(p,A,M){var l=U.exec(A.slice(M));return l?(p.w=C.get(l[0].toLowerCase()),M+l[0].length):-1}function o(p,A,M){var l=O.exec(A.slice(M));return l?(p.m=W.get(l[0].toLowerCase()),M+l[0].length):-1}function d(p,A,M){var l=y.exec(A.slice(M));return l?(p.m=L.get(l[0].toLowerCase()),M+l[0].length):-1}function m(p,A,M){return T(p,e,A,M)}function u(p,A,M){return T(p,n,A,M)}function S(p,A,M){return T(p,r,A,M)}function c(p){return a[p.getDay()]}function X(p){return s[p.getDay()]}function f(p){return Y[p.getMonth()]}function h(p){return k[p.getMonth()]}function _(p){return i[+(p.getHours()>=12)]}function G(p){return 1+~~(p.getMonth()/3)}function H(p){return a[p.getUTCDay()]}function V(p){return s[p.getUTCDay()]}function I(p){return Y[p.getUTCMonth()]}function z(p){return k[p.getUTCMonth()]}function st(p){return i[+(p.getUTCHours()>=12)]}function it(p){return 1+~~(p.getUTCMonth()/3)}return{format:function(p){var A=x(p+="",B);return A.toString=function(){return p},A},parse:function(p){var A=E(p+="",!1);return A.toString=function(){return p},A},utcFormat:function(p){var A=x(p+="",Z);return A.toString=function(){return p},A},utcParse:function(p){var A=E(p+="",!0);return A.toString=function(){return p},A}}}var Le={"-":"",_:" ",0:"0"},tt=/^\s*\d+/,Tr=/^%/,vr=/[\\^$*+?|[\]().{}]/g;function P(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",s=i.length;return r+(s[e.toLowerCase(),n]))}function xr(t,e,n){var r=tt.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function wr(t,e,n){var r=tt.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Cr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Dr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Mr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Ae(t,e,n){var r=tt.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function Ee(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function Sr(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function _r(t,e,n){var r=tt.exec(e.slice(n,n+1));return r?(t.q=r[0]*3-3,n+r[0].length):-1}function Ur(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Ie(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Yr(t,e,n){var r=tt.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function We(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Fr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Lr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Ar(t,e,n){var r=tt.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Er(t,e,n){var r=tt.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Ir(t,e,n){var r=Tr.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Wr(t,e,n){var r=tt.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Or(t,e,n){var r=tt.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Oe(t,e){return P(t.getDate(),e,2)}function Hr(t,e){return P(t.getHours(),e,2)}function Nr(t,e){return P(t.getHours()%12||12,e,2)}function Vr(t,e){return P(1+yt.count(mt(t),t),e,3)}function cn(t,e){return P(t.getMilliseconds(),e,3)}function zr(t,e){return cn(t,e)+"000"}function Pr(t,e){return P(t.getMonth()+1,e,2)}function Rr(t,e){return P(t.getMinutes(),e,2)}function Br(t,e){return P(t.getSeconds(),e,2)}function Zr(t){var e=t.getDay();return e===0?7:e}function Xr(t,e){return P(Ot.count(mt(t)-1,t),e,2)}function ln(t){var e=t.getDay();return e>=4||e===0?kt(t):kt.ceil(t)}function qr(t,e){return t=ln(t),P(kt.count(mt(t),t)+(mt(t).getDay()===4),e,2)}function Gr(t){return t.getDay()}function jr(t,e){return P(It.count(mt(t)-1,t),e,2)}function Qr(t,e){return P(t.getFullYear()%100,e,2)}function Jr(t,e){return t=ln(t),P(t.getFullYear()%100,e,2)}function $r(t,e){return P(t.getFullYear()%1e4,e,4)}function Kr(t,e){var n=t.getDay();return t=n>=4||n===0?kt(t):kt.ceil(t),P(t.getFullYear()%1e4,e,4)}function ti(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+P(e/60|0,"0",2)+P(e%60,"0",2)}function He(t,e){return P(t.getUTCDate(),e,2)}function ei(t,e){return P(t.getUTCHours(),e,2)}function ni(t,e){return P(t.getUTCHours()%12||12,e,2)}function ri(t,e){return P(1+Te.count(pt(t),t),e,3)}function un(t,e){return P(t.getUTCMilliseconds(),e,3)}function ii(t,e){return un(t,e)+"000"}function si(t,e){return P(t.getUTCMonth()+1,e,2)}function ai(t,e){return P(t.getUTCMinutes(),e,2)}function oi(t,e){return P(t.getUTCSeconds(),e,2)}function ci(t){var e=t.getUTCDay();return e===0?7:e}function li(t,e){return P(on.count(pt(t)-1,t),e,2)}function fn(t){var e=t.getUTCDay();return e>=4||e===0?St(t):St.ceil(t)}function ui(t,e){return t=fn(t),P(St.count(pt(t),t)+(pt(t).getUTCDay()===4),e,2)}function fi(t){return t.getUTCDay()}function hi(t,e){return P(jt.count(pt(t)-1,t),e,2)}function di(t,e){return P(t.getUTCFullYear()%100,e,2)}function mi(t,e){return t=fn(t),P(t.getUTCFullYear()%100,e,2)}function gi(t,e){return P(t.getUTCFullYear()%1e4,e,4)}function yi(t,e){var n=t.getUTCDay();return t=n>=4||n===0?St(t):St.ceil(t),P(t.getUTCFullYear()%1e4,e,4)}function ki(){return"+0000"}function Ne(){return"%"}function Ve(t){return+t}function ze(t){return Math.floor(+t/1e3)}var xt,Qt;pi({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function pi(t){return xt=pr(t),Qt=xt.format,xt.parse,xt.utcFormat,xt.utcParse,xt}function Ti(t){return new Date(t)}function vi(t){return t instanceof Date?+t:+new Date(+t)}function hn(t,e,n,r,i,s,a,k,Y,g){var b=Nn(),U=b.invert,C=b.domain,v=g(".%L"),q=g(":%S"),y=g("%I:%M"),L=g("%I %p"),O=g("%a %d"),W=g("%b %d"),B=g("%B"),Z=g("%Y");function Q(x){return(Y(x)4&&(v+=7),C.add(v,n));return q.diff(y,"week")+1},k.isoWeekday=function(g){return this.$utils().u(g)?this.day()||7:this.day(this.day()%7?g:g-7)};var Y=k.startOf;k.startOf=function(g,b){var U=this.$utils(),C=!!U.u(b)||b;return U.p(g)==="isoweek"?C?this.date(this.date()-(this.isoWeekday()-1)).startOf("day"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf("day"):Y.bind(this)(g,b)}}})})(dn);var xi=dn.exports;const wi=ke(xi);var mn={exports:{}};(function(t,e){(function(n,r){t.exports=r()})(ye,function(){var n={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},r=/(\[[^[]*\])|([-_:/.,()\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,i=/\d\d/,s=/\d\d?/,a=/\d*[^-_:/,()\s\d]+/,k={},Y=function(y){return(y=+y)+(y>68?1900:2e3)},g=function(y){return function(L){this[y]=+L}},b=[/[+-]\d\d:?(\d\d)?|Z/,function(y){(this.zone||(this.zone={})).offset=function(L){if(!L||L==="Z")return 0;var O=L.match(/([+-]|\d\d)/g),W=60*O[1]+(+O[2]||0);return W===0?0:O[0]==="+"?-W:W}(y)}],U=function(y){var L=k[y];return L&&(L.indexOf?L:L.s.concat(L.f))},C=function(y,L){var O,W=k.meridiem;if(W){for(var B=1;B<=24;B+=1)if(y.indexOf(W(B,0,L))>-1){O=B>12;break}}else O=y===(L?"pm":"PM");return O},v={A:[a,function(y){this.afternoon=C(y,!1)}],a:[a,function(y){this.afternoon=C(y,!0)}],S:[/\d/,function(y){this.milliseconds=100*+y}],SS:[i,function(y){this.milliseconds=10*+y}],SSS:[/\d{3}/,function(y){this.milliseconds=+y}],s:[s,g("seconds")],ss:[s,g("seconds")],m:[s,g("minutes")],mm:[s,g("minutes")],H:[s,g("hours")],h:[s,g("hours")],HH:[s,g("hours")],hh:[s,g("hours")],D:[s,g("day")],DD:[i,g("day")],Do:[a,function(y){var L=k.ordinal,O=y.match(/\d+/);if(this.day=O[0],L)for(var W=1;W<=31;W+=1)L(W).replace(/\[|\]/g,"")===y&&(this.day=W)}],M:[s,g("month")],MM:[i,g("month")],MMM:[a,function(y){var L=U("months"),O=(U("monthsShort")||L.map(function(W){return W.slice(0,3)})).indexOf(y)+1;if(O<1)throw new Error;this.month=O%12||O}],MMMM:[a,function(y){var L=U("months").indexOf(y)+1;if(L<1)throw new Error;this.month=L%12||L}],Y:[/[+-]?\d+/,g("year")],YY:[i,function(y){this.year=Y(y)}],YYYY:[/\d{4}/,g("year")],Z:b,ZZ:b};function q(y){var L,O;L=y,O=k&&k.formats;for(var W=(y=L.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(F,D,w){var o=w&&w.toUpperCase();return D||O[w]||n[w]||O[o].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(d,m,u){return m||u.slice(1)})})).match(r),B=W.length,Z=0;Z-1)return new Date((c==="X"?1e3:1)*S);var f=q(c)(S),h=f.year,_=f.month,G=f.day,H=f.hours,V=f.minutes,I=f.seconds,z=f.milliseconds,st=f.zone,it=new Date,p=G||(h||_?1:it.getDate()),A=h||it.getFullYear(),M=0;h&&!_||(M=_>0?_-1:it.getMonth());var l=H||0,R=V||0,N=I||0,j=z||0;return st?new Date(Date.UTC(A,M,p,l,R,N,j+60*st.offset*1e3)):X?new Date(Date.UTC(A,M,p,l,R,N,j)):new Date(A,M,p,l,R,N,j)}catch{return new Date("")}}(Q,T,x),this.init(),o&&o!==!0&&(this.$L=this.locale(o).$L),w&&Q!=this.format(T)&&(this.$d=new Date("")),k={}}else if(T instanceof Array)for(var d=T.length,m=1;m<=d;m+=1){E[1]=T[m-1];var u=O.apply(this,E);if(u.isValid()){this.$d=u.$d,this.$L=u.$L,this.init();break}m===d&&(this.$d=new Date(""))}else B.call(this,Z)}}})})(mn);var Ci=mn.exports;const Di=ke(Ci);var gn={exports:{}};(function(t,e){(function(n,r){t.exports=r()})(ye,function(){return function(n,r){var i=r.prototype,s=i.format;i.format=function(a){var k=this,Y=this.$locale();if(!this.isValid())return s.bind(this)(a);var g=this.$utils(),b=(a||"YYYY-MM-DDTHH:mm:ssZ").replace(/\[([^\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(U){switch(U){case"Q":return Math.ceil((k.$M+1)/3);case"Do":return Y.ordinal(k.$D);case"gggg":return k.weekYear();case"GGGG":return k.isoWeekYear();case"wo":return Y.ordinal(k.week(),"W");case"w":case"ww":return g.s(k.week(),U==="w"?1:2,"0");case"W":case"WW":return g.s(k.isoWeek(),U==="W"?1:2,"0");case"k":case"kk":return g.s(String(k.$H===0?24:k.$H),U==="k"?1:2,"0");case"X":return Math.floor(k.$d.getTime()/1e3);case"x":return k.$d.getTime();case"z":return"["+k.offsetName()+"]";case"zzz":return"["+k.offsetName("long")+"]";default:return U}});return s.bind(this)(b)}}})})(gn);var Mi=gn.exports;const Si=ke(Mi);var he=function(){var t=function(w,o,d,m){for(d=d||{},m=w.length;m--;d[w[m]]=o);return d},e=[6,8,10,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,30,32,33,35,37],n=[1,25],r=[1,26],i=[1,27],s=[1,28],a=[1,29],k=[1,30],Y=[1,31],g=[1,9],b=[1,10],U=[1,11],C=[1,12],v=[1,13],q=[1,14],y=[1,15],L=[1,16],O=[1,18],W=[1,19],B=[1,20],Z=[1,21],Q=[1,22],x=[1,24],E=[1,32],T={trace:function(){},yy:{},symbols_:{error:2,start:3,gantt:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NL:10,weekday:11,weekday_monday:12,weekday_tuesday:13,weekday_wednesday:14,weekday_thursday:15,weekday_friday:16,weekday_saturday:17,weekday_sunday:18,dateFormat:19,inclusiveEndDates:20,topAxis:21,axisFormat:22,tickInterval:23,excludes:24,includes:25,todayMarker:26,title:27,acc_title:28,acc_title_value:29,acc_descr:30,acc_descr_value:31,acc_descr_multiline_value:32,section:33,clickStatement:34,taskTxt:35,taskData:36,click:37,callbackname:38,callbackargs:39,href:40,clickStatementDebug:41,$accept:0,$end:1},terminals_:{2:"error",4:"gantt",6:"EOF",8:"SPACE",10:"NL",12:"weekday_monday",13:"weekday_tuesday",14:"weekday_wednesday",15:"weekday_thursday",16:"weekday_friday",17:"weekday_saturday",18:"weekday_sunday",19:"dateFormat",20:"inclusiveEndDates",21:"topAxis",22:"axisFormat",23:"tickInterval",24:"excludes",25:"includes",26:"todayMarker",27:"title",28:"acc_title",29:"acc_title_value",30:"acc_descr",31:"acc_descr_value",32:"acc_descr_multiline_value",33:"section",35:"taskTxt",36:"taskData",37:"click",38:"callbackname",39:"callbackargs",40:"href"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,2],[34,2],[34,3],[34,3],[34,4],[34,3],[34,4],[34,2],[41,2],[41,3],[41,3],[41,4],[41,3],[41,4],[41,2]],performAction:function(o,d,m,u,S,c,X){var f=c.length-1;switch(S){case 1:return c[f-1];case 2:this.$=[];break;case 3:c[f-1].push(c[f]),this.$=c[f-1];break;case 4:case 5:this.$=c[f];break;case 6:case 7:this.$=[];break;case 8:u.setWeekday("monday");break;case 9:u.setWeekday("tuesday");break;case 10:u.setWeekday("wednesday");break;case 11:u.setWeekday("thursday");break;case 12:u.setWeekday("friday");break;case 13:u.setWeekday("saturday");break;case 14:u.setWeekday("sunday");break;case 15:u.setDateFormat(c[f].substr(11)),this.$=c[f].substr(11);break;case 16:u.enableInclusiveEndDates(),this.$=c[f].substr(18);break;case 17:u.TopAxis(),this.$=c[f].substr(8);break;case 18:u.setAxisFormat(c[f].substr(11)),this.$=c[f].substr(11);break;case 19:u.setTickInterval(c[f].substr(13)),this.$=c[f].substr(13);break;case 20:u.setExcludes(c[f].substr(9)),this.$=c[f].substr(9);break;case 21:u.setIncludes(c[f].substr(9)),this.$=c[f].substr(9);break;case 22:u.setTodayMarker(c[f].substr(12)),this.$=c[f].substr(12);break;case 24:u.setDiagramTitle(c[f].substr(6)),this.$=c[f].substr(6);break;case 25:this.$=c[f].trim(),u.setAccTitle(this.$);break;case 26:case 27:this.$=c[f].trim(),u.setAccDescription(this.$);break;case 28:u.addSection(c[f].substr(8)),this.$=c[f].substr(8);break;case 30:u.addTask(c[f-1],c[f]),this.$="task";break;case 31:this.$=c[f-1],u.setClickEvent(c[f-1],c[f],null);break;case 32:this.$=c[f-2],u.setClickEvent(c[f-2],c[f-1],c[f]);break;case 33:this.$=c[f-2],u.setClickEvent(c[f-2],c[f-1],null),u.setLink(c[f-2],c[f]);break;case 34:this.$=c[f-3],u.setClickEvent(c[f-3],c[f-2],c[f-1]),u.setLink(c[f-3],c[f]);break;case 35:this.$=c[f-2],u.setClickEvent(c[f-2],c[f],null),u.setLink(c[f-2],c[f-1]);break;case 36:this.$=c[f-3],u.setClickEvent(c[f-3],c[f-1],c[f]),u.setLink(c[f-3],c[f-2]);break;case 37:this.$=c[f-1],u.setLink(c[f-1],c[f]);break;case 38:case 44:this.$=c[f-1]+" "+c[f];break;case 39:case 40:case 42:this.$=c[f-2]+" "+c[f-1]+" "+c[f];break;case 41:case 43:this.$=c[f-3]+" "+c[f-2]+" "+c[f-1]+" "+c[f];break}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:17,12:n,13:r,14:i,15:s,16:a,17:k,18:Y,19:g,20:b,21:U,22:C,23:v,24:q,25:y,26:L,27:O,28:W,30:B,32:Z,33:Q,34:23,35:x,37:E},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:33,11:17,12:n,13:r,14:i,15:s,16:a,17:k,18:Y,19:g,20:b,21:U,22:C,23:v,24:q,25:y,26:L,27:O,28:W,30:B,32:Z,33:Q,34:23,35:x,37:E},t(e,[2,5]),t(e,[2,6]),t(e,[2,15]),t(e,[2,16]),t(e,[2,17]),t(e,[2,18]),t(e,[2,19]),t(e,[2,20]),t(e,[2,21]),t(e,[2,22]),t(e,[2,23]),t(e,[2,24]),{29:[1,34]},{31:[1,35]},t(e,[2,27]),t(e,[2,28]),t(e,[2,29]),{36:[1,36]},t(e,[2,8]),t(e,[2,9]),t(e,[2,10]),t(e,[2,11]),t(e,[2,12]),t(e,[2,13]),t(e,[2,14]),{38:[1,37],40:[1,38]},t(e,[2,4]),t(e,[2,25]),t(e,[2,26]),t(e,[2,30]),t(e,[2,31],{39:[1,39],40:[1,40]}),t(e,[2,37],{38:[1,41]}),t(e,[2,32],{40:[1,42]}),t(e,[2,33]),t(e,[2,35],{39:[1,43]}),t(e,[2,34]),t(e,[2,36])],defaultActions:{},parseError:function(o,d){if(d.recoverable)this.trace(o);else{var m=new Error(o);throw m.hash=d,m}},parse:function(o){var d=this,m=[0],u=[],S=[null],c=[],X=this.table,f="",h=0,_=0,G=2,H=1,V=c.slice.call(arguments,1),I=Object.create(this.lexer),z={yy:{}};for(var st in this.yy)Object.prototype.hasOwnProperty.call(this.yy,st)&&(z.yy[st]=this.yy[st]);I.setInput(o,z.yy),z.yy.lexer=I,z.yy.parser=this,typeof I.yylloc>"u"&&(I.yylloc={});var it=I.yylloc;c.push(it);var p=I.options&&I.options.ranges;typeof z.yy.parseError=="function"?this.parseError=z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function A(){var ct;return ct=u.pop()||I.lex()||H,typeof ct!="number"&&(ct instanceof Array&&(u=ct,ct=u.pop()),ct=d.symbols_[ct]||ct),ct}for(var M,l,R,N,j={},J,et,Ut,zt;;){if(l=m[m.length-1],this.defaultActions[l]?R=this.defaultActions[l]:((M===null||typeof M>"u")&&(M=A()),R=X[l]&&X[l][M]),typeof R>"u"||!R.length||!R[0]){var $t="";zt=[];for(J in X[l])this.terminals_[J]&&J>G&&zt.push("'"+this.terminals_[J]+"'");I.showPosition?$t="Parse error on line "+(h+1)+`:
                                        +import{au as Be,av as Ze,aw as Xe,ax as qe,ay as Dn,az as Kt,aA as Mn,aB as ye,aC as ke,aD as nt,c as wt,s as Sn,g as _n,x as Un,y as Yn,b as Fn,a as Ln,A as An,m as En,l as qt,h as Pt,i as In,j as Wn,z as On}from"./mermaid.core-Bq0kX0MS.js";import{b as Hn,t as Ue,c as Nn,a as Vn,l as zn}from"./linear-CopLvHML.js";import{i as Pn}from"./init-Gi6I4Gst.js";import"./app-Bw2NG-QJ.js";function Rn(t,e){let n;if(e===void 0)for(const r of t)r!=null&&(n=r)&&(n=r);else{let r=-1;for(let i of t)(i=e(i,++r,t))!=null&&(n=i)&&(n=i)}return n}function Bn(t,e){let n;if(e===void 0)for(const r of t)r!=null&&(n>r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of t)(i=e(i,++r,t))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function Zn(t){return t}var Bt=1,te=2,ue=3,Rt=4,Ye=1e-6;function Xn(t){return"translate("+t+",0)"}function qn(t){return"translate(0,"+t+")"}function Gn(t){return e=>+t(e)}function jn(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),n=>+t(n)+e}function Qn(){return!this.__axis}function Ge(t,e){var n=[],r=null,i=null,s=6,a=6,k=3,Y=typeof window<"u"&&window.devicePixelRatio>1?0:.5,g=t===Bt||t===Rt?-1:1,b=t===Rt||t===te?"x":"y",U=t===Bt||t===ue?Xn:qn;function C(v){var q=r??(e.ticks?e.ticks.apply(e,n):e.domain()),y=i??(e.tickFormat?e.tickFormat.apply(e,n):Zn),L=Math.max(s,0)+k,O=e.range(),W=+O[0]+Y,B=+O[O.length-1]+Y,Z=(e.bandwidth?jn:Gn)(e.copy(),Y),Q=v.selection?v.selection():v,x=Q.selectAll(".domain").data([null]),E=Q.selectAll(".tick").data(q,e).order(),T=E.exit(),F=E.enter().append("g").attr("class","tick"),D=E.select("line"),w=E.select("text");x=x.merge(x.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),E=E.merge(F),D=D.merge(F.append("line").attr("stroke","currentColor").attr(b+"2",g*s)),w=w.merge(F.append("text").attr("fill","currentColor").attr(b,g*L).attr("dy",t===Bt?"0em":t===ue?"0.71em":"0.32em")),v!==Q&&(x=x.transition(v),E=E.transition(v),D=D.transition(v),w=w.transition(v),T=T.transition(v).attr("opacity",Ye).attr("transform",function(o){return isFinite(o=Z(o))?U(o+Y):this.getAttribute("transform")}),F.attr("opacity",Ye).attr("transform",function(o){var d=this.parentNode.__axis;return U((d&&isFinite(d=d(o))?d:Z(o))+Y)})),T.remove(),x.attr("d",t===Rt||t===te?a?"M"+g*a+","+W+"H"+Y+"V"+B+"H"+g*a:"M"+Y+","+W+"V"+B:a?"M"+W+","+g*a+"V"+Y+"H"+B+"V"+g*a:"M"+W+","+Y+"H"+B),E.attr("opacity",1).attr("transform",function(o){return U(Z(o)+Y)}),D.attr(b+"2",g*s),w.attr(b,g*L).text(y),Q.filter(Qn).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===te?"start":t===Rt?"end":"middle"),Q.each(function(){this.__axis=Z})}return C.scale=function(v){return arguments.length?(e=v,C):e},C.ticks=function(){return n=Array.from(arguments),C},C.tickArguments=function(v){return arguments.length?(n=v==null?[]:Array.from(v),C):n.slice()},C.tickValues=function(v){return arguments.length?(r=v==null?null:Array.from(v),C):r&&r.slice()},C.tickFormat=function(v){return arguments.length?(i=v,C):i},C.tickSize=function(v){return arguments.length?(s=a=+v,C):s},C.tickSizeInner=function(v){return arguments.length?(s=+v,C):s},C.tickSizeOuter=function(v){return arguments.length?(a=+v,C):a},C.tickPadding=function(v){return arguments.length?(k=+v,C):k},C.offset=function(v){return arguments.length?(Y=+v,C):Y},C}function Jn(t){return Ge(Bt,t)}function $n(t){return Ge(ue,t)}const Kn=Math.PI/180,tr=180/Math.PI,Gt=18,je=.96422,Qe=1,Je=.82521,$e=4/29,Ct=6/29,Ke=3*Ct*Ct,er=Ct*Ct*Ct;function tn(t){if(t instanceof ot)return new ot(t.l,t.a,t.b,t.opacity);if(t instanceof ut)return en(t);t instanceof Xe||(t=Dn(t));var e=ie(t.r),n=ie(t.g),r=ie(t.b),i=ee((.2225045*e+.7168786*n+.0606169*r)/Qe),s,a;return e===n&&n===r?s=a=i:(s=ee((.4360747*e+.3850649*n+.1430804*r)/je),a=ee((.0139322*e+.0971045*n+.7141733*r)/Je)),new ot(116*i-16,500*(s-i),200*(i-a),t.opacity)}function nr(t,e,n,r){return arguments.length===1?tn(t):new ot(t,e,n,r??1)}function ot(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}Be(ot,nr,Ze(qe,{brighter(t){return new ot(this.l+Gt*(t??1),this.a,this.b,this.opacity)},darker(t){return new ot(this.l-Gt*(t??1),this.a,this.b,this.opacity)},rgb(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,n=isNaN(this.b)?t:t-this.b/200;return e=je*ne(e),t=Qe*ne(t),n=Je*ne(n),new Xe(re(3.1338561*e-1.6168667*t-.4906146*n),re(-.9787684*e+1.9161415*t+.033454*n),re(.0719453*e-.2289914*t+1.4052427*n),this.opacity)}}));function ee(t){return t>er?Math.pow(t,1/3):t/Ke+$e}function ne(t){return t>Ct?t*t*t:Ke*(t-$e)}function re(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function ie(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function rr(t){if(t instanceof ut)return new ut(t.h,t.c,t.l,t.opacity);if(t instanceof ot||(t=tn(t)),t.a===0&&t.b===0)return new ut(NaN,0(t(s=new Date(+s)),s),i.ceil=s=>(t(s=new Date(s-1)),e(s,1),t(s),s),i.round=s=>{const a=i(s),k=i.ceil(s);return s-a(e(s=new Date(+s),a==null?1:Math.floor(a)),s),i.range=(s,a,k)=>{const Y=[];if(s=i.ceil(s),k=k==null?1:Math.floor(k),!(s0))return Y;let g;do Y.push(g=new Date(+s)),e(s,k),t(s);while(gK(a=>{if(a>=a)for(;t(a),!s(a);)a.setTime(a-1)},(a,k)=>{if(a>=a)if(k<0)for(;++k<=0;)for(;e(a,-1),!s(a););else for(;--k>=0;)for(;e(a,1),!s(a););}),n&&(i.count=(s,a)=>(se.setTime(+s),ae.setTime(+a),t(se),t(ae),Math.floor(n(se,ae))),i.every=s=>(s=Math.floor(s),!isFinite(s)||!(s>0)?null:s>1?i.filter(r?a=>r(a)%s===0:a=>i.count(0,a)%s===0):i)),i}const Mt=K(()=>{},(t,e)=>{t.setTime(+t+e)},(t,e)=>e-t);Mt.every=t=>(t=Math.floor(t),!isFinite(t)||!(t>0)?null:t>1?K(e=>{e.setTime(Math.floor(e/t)*t)},(e,n)=>{e.setTime(+e+n*t)},(e,n)=>(n-e)/t):Mt);Mt.range;const ft=1e3,rt=ft*60,ht=rt*60,dt=ht*24,pe=dt*7,Fe=dt*30,oe=dt*365,gt=K(t=>{t.setTime(t-t.getMilliseconds())},(t,e)=>{t.setTime(+t+e*ft)},(t,e)=>(e-t)/ft,t=>t.getUTCSeconds());gt.range;const At=K(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*ft)},(t,e)=>{t.setTime(+t+e*rt)},(t,e)=>(e-t)/rt,t=>t.getMinutes());At.range;const or=K(t=>{t.setUTCSeconds(0,0)},(t,e)=>{t.setTime(+t+e*rt)},(t,e)=>(e-t)/rt,t=>t.getUTCMinutes());or.range;const Et=K(t=>{t.setTime(t-t.getMilliseconds()-t.getSeconds()*ft-t.getMinutes()*rt)},(t,e)=>{t.setTime(+t+e*ht)},(t,e)=>(e-t)/ht,t=>t.getHours());Et.range;const cr=K(t=>{t.setUTCMinutes(0,0,0)},(t,e)=>{t.setTime(+t+e*ht)},(t,e)=>(e-t)/ht,t=>t.getUTCHours());cr.range;const yt=K(t=>t.setHours(0,0,0,0),(t,e)=>t.setDate(t.getDate()+e),(t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*rt)/dt,t=>t.getDate()-1);yt.range;const Te=K(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/dt,t=>t.getUTCDate()-1);Te.range;const lr=K(t=>{t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCDate(t.getUTCDate()+e)},(t,e)=>(e-t)/dt,t=>Math.floor(t/dt));lr.range;function Tt(t){return K(e=>{e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)},(e,n)=>{e.setDate(e.getDate()+n*7)},(e,n)=>(n-e-(n.getTimezoneOffset()-e.getTimezoneOffset())*rt)/pe)}const Ot=Tt(0),It=Tt(1),nn=Tt(2),rn=Tt(3),kt=Tt(4),sn=Tt(5),an=Tt(6);Ot.range;It.range;nn.range;rn.range;kt.range;sn.range;an.range;function vt(t){return K(e=>{e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)},(e,n)=>{e.setUTCDate(e.getUTCDate()+n*7)},(e,n)=>(n-e)/pe)}const on=vt(0),jt=vt(1),ur=vt(2),fr=vt(3),St=vt(4),hr=vt(5),dr=vt(6);on.range;jt.range;ur.range;fr.range;St.range;hr.range;dr.range;const Wt=K(t=>{t.setDate(1),t.setHours(0,0,0,0)},(t,e)=>{t.setMonth(t.getMonth()+e)},(t,e)=>e.getMonth()-t.getMonth()+(e.getFullYear()-t.getFullYear())*12,t=>t.getMonth());Wt.range;const mr=K(t=>{t.setUTCDate(1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCMonth(t.getUTCMonth()+e)},(t,e)=>e.getUTCMonth()-t.getUTCMonth()+(e.getUTCFullYear()-t.getUTCFullYear())*12,t=>t.getUTCMonth());mr.range;const mt=K(t=>{t.setMonth(0,1),t.setHours(0,0,0,0)},(t,e)=>{t.setFullYear(t.getFullYear()+e)},(t,e)=>e.getFullYear()-t.getFullYear(),t=>t.getFullYear());mt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:K(e=>{e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)},(e,n)=>{e.setFullYear(e.getFullYear()+n*t)});mt.range;const pt=K(t=>{t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,e)=>{t.setUTCFullYear(t.getUTCFullYear()+e)},(t,e)=>e.getUTCFullYear()-t.getUTCFullYear(),t=>t.getUTCFullYear());pt.every=t=>!isFinite(t=Math.floor(t))||!(t>0)?null:K(e=>{e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,n)=>{e.setUTCFullYear(e.getUTCFullYear()+n*t)});pt.range;function gr(t,e,n,r,i,s){const a=[[gt,1,ft],[gt,5,5*ft],[gt,15,15*ft],[gt,30,30*ft],[s,1,rt],[s,5,5*rt],[s,15,15*rt],[s,30,30*rt],[i,1,ht],[i,3,3*ht],[i,6,6*ht],[i,12,12*ht],[r,1,dt],[r,2,2*dt],[n,1,pe],[e,1,Fe],[e,3,3*Fe],[t,1,oe]];function k(g,b,U){const C=bL).right(a,C);if(v===a.length)return t.every(Ue(g/oe,b/oe,U));if(v===0)return Mt.every(Math.max(Ue(g,b,U),1));const[q,y]=a[C/a[v-1][2]53)return null;"w"in l||(l.w=1),"Z"in l?(N=le(Yt(l.y,0,1)),j=N.getUTCDay(),N=j>4||j===0?jt.ceil(N):jt(N),N=Te.offset(N,(l.V-1)*7),l.y=N.getUTCFullYear(),l.m=N.getUTCMonth(),l.d=N.getUTCDate()+(l.w+6)%7):(N=ce(Yt(l.y,0,1)),j=N.getDay(),N=j>4||j===0?It.ceil(N):It(N),N=yt.offset(N,(l.V-1)*7),l.y=N.getFullYear(),l.m=N.getMonth(),l.d=N.getDate()+(l.w+6)%7)}else("W"in l||"U"in l)&&("w"in l||(l.w="u"in l?l.u%7:"W"in l?1:0),j="Z"in l?le(Yt(l.y,0,1)).getUTCDay():ce(Yt(l.y,0,1)).getDay(),l.m=0,l.d="W"in l?(l.w+6)%7+l.W*7-(j+5)%7:l.w+l.U*7-(j+6)%7);return"Z"in l?(l.H+=l.Z/100|0,l.M+=l.Z%100,le(l)):ce(l)}}function T(p,A,M,l){for(var R=0,N=A.length,j=M.length,J,et;R=j)return-1;if(J=A.charCodeAt(R++),J===37){if(J=A.charAt(R++),et=Q[J in Le?A.charAt(R++):J],!et||(l=et(p,M,l))<0)return-1}else if(J!=M.charCodeAt(l++))return-1}return l}function F(p,A,M){var l=g.exec(A.slice(M));return l?(p.p=b.get(l[0].toLowerCase()),M+l[0].length):-1}function D(p,A,M){var l=v.exec(A.slice(M));return l?(p.w=q.get(l[0].toLowerCase()),M+l[0].length):-1}function w(p,A,M){var l=U.exec(A.slice(M));return l?(p.w=C.get(l[0].toLowerCase()),M+l[0].length):-1}function o(p,A,M){var l=O.exec(A.slice(M));return l?(p.m=W.get(l[0].toLowerCase()),M+l[0].length):-1}function d(p,A,M){var l=y.exec(A.slice(M));return l?(p.m=L.get(l[0].toLowerCase()),M+l[0].length):-1}function m(p,A,M){return T(p,e,A,M)}function u(p,A,M){return T(p,n,A,M)}function S(p,A,M){return T(p,r,A,M)}function c(p){return a[p.getDay()]}function X(p){return s[p.getDay()]}function f(p){return Y[p.getMonth()]}function h(p){return k[p.getMonth()]}function _(p){return i[+(p.getHours()>=12)]}function G(p){return 1+~~(p.getMonth()/3)}function H(p){return a[p.getUTCDay()]}function V(p){return s[p.getUTCDay()]}function I(p){return Y[p.getUTCMonth()]}function z(p){return k[p.getUTCMonth()]}function st(p){return i[+(p.getUTCHours()>=12)]}function it(p){return 1+~~(p.getUTCMonth()/3)}return{format:function(p){var A=x(p+="",B);return A.toString=function(){return p},A},parse:function(p){var A=E(p+="",!1);return A.toString=function(){return p},A},utcFormat:function(p){var A=x(p+="",Z);return A.toString=function(){return p},A},utcParse:function(p){var A=E(p+="",!0);return A.toString=function(){return p},A}}}var Le={"-":"",_:" ",0:"0"},tt=/^\s*\d+/,Tr=/^%/,vr=/[\\^$*+?|[\]().{}]/g;function P(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",s=i.length;return r+(s[e.toLowerCase(),n]))}function xr(t,e,n){var r=tt.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function wr(t,e,n){var r=tt.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Cr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Dr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Mr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Ae(t,e,n){var r=tt.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function Ee(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function Sr(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function _r(t,e,n){var r=tt.exec(e.slice(n,n+1));return r?(t.q=r[0]*3-3,n+r[0].length):-1}function Ur(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Ie(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function Yr(t,e,n){var r=tt.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function We(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Fr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Lr(t,e,n){var r=tt.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Ar(t,e,n){var r=tt.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Er(t,e,n){var r=tt.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Ir(t,e,n){var r=Tr.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Wr(t,e,n){var r=tt.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Or(t,e,n){var r=tt.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Oe(t,e){return P(t.getDate(),e,2)}function Hr(t,e){return P(t.getHours(),e,2)}function Nr(t,e){return P(t.getHours()%12||12,e,2)}function Vr(t,e){return P(1+yt.count(mt(t),t),e,3)}function cn(t,e){return P(t.getMilliseconds(),e,3)}function zr(t,e){return cn(t,e)+"000"}function Pr(t,e){return P(t.getMonth()+1,e,2)}function Rr(t,e){return P(t.getMinutes(),e,2)}function Br(t,e){return P(t.getSeconds(),e,2)}function Zr(t){var e=t.getDay();return e===0?7:e}function Xr(t,e){return P(Ot.count(mt(t)-1,t),e,2)}function ln(t){var e=t.getDay();return e>=4||e===0?kt(t):kt.ceil(t)}function qr(t,e){return t=ln(t),P(kt.count(mt(t),t)+(mt(t).getDay()===4),e,2)}function Gr(t){return t.getDay()}function jr(t,e){return P(It.count(mt(t)-1,t),e,2)}function Qr(t,e){return P(t.getFullYear()%100,e,2)}function Jr(t,e){return t=ln(t),P(t.getFullYear()%100,e,2)}function $r(t,e){return P(t.getFullYear()%1e4,e,4)}function Kr(t,e){var n=t.getDay();return t=n>=4||n===0?kt(t):kt.ceil(t),P(t.getFullYear()%1e4,e,4)}function ti(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+P(e/60|0,"0",2)+P(e%60,"0",2)}function He(t,e){return P(t.getUTCDate(),e,2)}function ei(t,e){return P(t.getUTCHours(),e,2)}function ni(t,e){return P(t.getUTCHours()%12||12,e,2)}function ri(t,e){return P(1+Te.count(pt(t),t),e,3)}function un(t,e){return P(t.getUTCMilliseconds(),e,3)}function ii(t,e){return un(t,e)+"000"}function si(t,e){return P(t.getUTCMonth()+1,e,2)}function ai(t,e){return P(t.getUTCMinutes(),e,2)}function oi(t,e){return P(t.getUTCSeconds(),e,2)}function ci(t){var e=t.getUTCDay();return e===0?7:e}function li(t,e){return P(on.count(pt(t)-1,t),e,2)}function fn(t){var e=t.getUTCDay();return e>=4||e===0?St(t):St.ceil(t)}function ui(t,e){return t=fn(t),P(St.count(pt(t),t)+(pt(t).getUTCDay()===4),e,2)}function fi(t){return t.getUTCDay()}function hi(t,e){return P(jt.count(pt(t)-1,t),e,2)}function di(t,e){return P(t.getUTCFullYear()%100,e,2)}function mi(t,e){return t=fn(t),P(t.getUTCFullYear()%100,e,2)}function gi(t,e){return P(t.getUTCFullYear()%1e4,e,4)}function yi(t,e){var n=t.getUTCDay();return t=n>=4||n===0?St(t):St.ceil(t),P(t.getUTCFullYear()%1e4,e,4)}function ki(){return"+0000"}function Ne(){return"%"}function Ve(t){return+t}function ze(t){return Math.floor(+t/1e3)}var xt,Qt;pi({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function pi(t){return xt=pr(t),Qt=xt.format,xt.parse,xt.utcFormat,xt.utcParse,xt}function Ti(t){return new Date(t)}function vi(t){return t instanceof Date?+t:+new Date(+t)}function hn(t,e,n,r,i,s,a,k,Y,g){var b=Nn(),U=b.invert,C=b.domain,v=g(".%L"),q=g(":%S"),y=g("%I:%M"),L=g("%I %p"),O=g("%a %d"),W=g("%b %d"),B=g("%B"),Z=g("%Y");function Q(x){return(Y(x)4&&(v+=7),C.add(v,n));return q.diff(y,"week")+1},k.isoWeekday=function(g){return this.$utils().u(g)?this.day()||7:this.day(this.day()%7?g:g-7)};var Y=k.startOf;k.startOf=function(g,b){var U=this.$utils(),C=!!U.u(b)||b;return U.p(g)==="isoweek"?C?this.date(this.date()-(this.isoWeekday()-1)).startOf("day"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf("day"):Y.bind(this)(g,b)}}})})(dn);var xi=dn.exports;const wi=ke(xi);var mn={exports:{}};(function(t,e){(function(n,r){t.exports=r()})(ye,function(){var n={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},r=/(\[[^[]*\])|([-_:/.,()\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,i=/\d\d/,s=/\d\d?/,a=/\d*[^-_:/,()\s\d]+/,k={},Y=function(y){return(y=+y)+(y>68?1900:2e3)},g=function(y){return function(L){this[y]=+L}},b=[/[+-]\d\d:?(\d\d)?|Z/,function(y){(this.zone||(this.zone={})).offset=function(L){if(!L||L==="Z")return 0;var O=L.match(/([+-]|\d\d)/g),W=60*O[1]+(+O[2]||0);return W===0?0:O[0]==="+"?-W:W}(y)}],U=function(y){var L=k[y];return L&&(L.indexOf?L:L.s.concat(L.f))},C=function(y,L){var O,W=k.meridiem;if(W){for(var B=1;B<=24;B+=1)if(y.indexOf(W(B,0,L))>-1){O=B>12;break}}else O=y===(L?"pm":"PM");return O},v={A:[a,function(y){this.afternoon=C(y,!1)}],a:[a,function(y){this.afternoon=C(y,!0)}],S:[/\d/,function(y){this.milliseconds=100*+y}],SS:[i,function(y){this.milliseconds=10*+y}],SSS:[/\d{3}/,function(y){this.milliseconds=+y}],s:[s,g("seconds")],ss:[s,g("seconds")],m:[s,g("minutes")],mm:[s,g("minutes")],H:[s,g("hours")],h:[s,g("hours")],HH:[s,g("hours")],hh:[s,g("hours")],D:[s,g("day")],DD:[i,g("day")],Do:[a,function(y){var L=k.ordinal,O=y.match(/\d+/);if(this.day=O[0],L)for(var W=1;W<=31;W+=1)L(W).replace(/\[|\]/g,"")===y&&(this.day=W)}],M:[s,g("month")],MM:[i,g("month")],MMM:[a,function(y){var L=U("months"),O=(U("monthsShort")||L.map(function(W){return W.slice(0,3)})).indexOf(y)+1;if(O<1)throw new Error;this.month=O%12||O}],MMMM:[a,function(y){var L=U("months").indexOf(y)+1;if(L<1)throw new Error;this.month=L%12||L}],Y:[/[+-]?\d+/,g("year")],YY:[i,function(y){this.year=Y(y)}],YYYY:[/\d{4}/,g("year")],Z:b,ZZ:b};function q(y){var L,O;L=y,O=k&&k.formats;for(var W=(y=L.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(F,D,w){var o=w&&w.toUpperCase();return D||O[w]||n[w]||O[o].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(d,m,u){return m||u.slice(1)})})).match(r),B=W.length,Z=0;Z-1)return new Date((c==="X"?1e3:1)*S);var f=q(c)(S),h=f.year,_=f.month,G=f.day,H=f.hours,V=f.minutes,I=f.seconds,z=f.milliseconds,st=f.zone,it=new Date,p=G||(h||_?1:it.getDate()),A=h||it.getFullYear(),M=0;h&&!_||(M=_>0?_-1:it.getMonth());var l=H||0,R=V||0,N=I||0,j=z||0;return st?new Date(Date.UTC(A,M,p,l,R,N,j+60*st.offset*1e3)):X?new Date(Date.UTC(A,M,p,l,R,N,j)):new Date(A,M,p,l,R,N,j)}catch{return new Date("")}}(Q,T,x),this.init(),o&&o!==!0&&(this.$L=this.locale(o).$L),w&&Q!=this.format(T)&&(this.$d=new Date("")),k={}}else if(T instanceof Array)for(var d=T.length,m=1;m<=d;m+=1){E[1]=T[m-1];var u=O.apply(this,E);if(u.isValid()){this.$d=u.$d,this.$L=u.$L,this.init();break}m===d&&(this.$d=new Date(""))}else B.call(this,Z)}}})})(mn);var Ci=mn.exports;const Di=ke(Ci);var gn={exports:{}};(function(t,e){(function(n,r){t.exports=r()})(ye,function(){return function(n,r){var i=r.prototype,s=i.format;i.format=function(a){var k=this,Y=this.$locale();if(!this.isValid())return s.bind(this)(a);var g=this.$utils(),b=(a||"YYYY-MM-DDTHH:mm:ssZ").replace(/\[([^\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(U){switch(U){case"Q":return Math.ceil((k.$M+1)/3);case"Do":return Y.ordinal(k.$D);case"gggg":return k.weekYear();case"GGGG":return k.isoWeekYear();case"wo":return Y.ordinal(k.week(),"W");case"w":case"ww":return g.s(k.week(),U==="w"?1:2,"0");case"W":case"WW":return g.s(k.isoWeek(),U==="W"?1:2,"0");case"k":case"kk":return g.s(String(k.$H===0?24:k.$H),U==="k"?1:2,"0");case"X":return Math.floor(k.$d.getTime()/1e3);case"x":return k.$d.getTime();case"z":return"["+k.offsetName()+"]";case"zzz":return"["+k.offsetName("long")+"]";default:return U}});return s.bind(this)(b)}}})})(gn);var Mi=gn.exports;const Si=ke(Mi);var he=function(){var t=function(w,o,d,m){for(d=d||{},m=w.length;m--;d[w[m]]=o);return d},e=[6,8,10,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,30,32,33,35,37],n=[1,25],r=[1,26],i=[1,27],s=[1,28],a=[1,29],k=[1,30],Y=[1,31],g=[1,9],b=[1,10],U=[1,11],C=[1,12],v=[1,13],q=[1,14],y=[1,15],L=[1,16],O=[1,18],W=[1,19],B=[1,20],Z=[1,21],Q=[1,22],x=[1,24],E=[1,32],T={trace:function(){},yy:{},symbols_:{error:2,start:3,gantt:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NL:10,weekday:11,weekday_monday:12,weekday_tuesday:13,weekday_wednesday:14,weekday_thursday:15,weekday_friday:16,weekday_saturday:17,weekday_sunday:18,dateFormat:19,inclusiveEndDates:20,topAxis:21,axisFormat:22,tickInterval:23,excludes:24,includes:25,todayMarker:26,title:27,acc_title:28,acc_title_value:29,acc_descr:30,acc_descr_value:31,acc_descr_multiline_value:32,section:33,clickStatement:34,taskTxt:35,taskData:36,click:37,callbackname:38,callbackargs:39,href:40,clickStatementDebug:41,$accept:0,$end:1},terminals_:{2:"error",4:"gantt",6:"EOF",8:"SPACE",10:"NL",12:"weekday_monday",13:"weekday_tuesday",14:"weekday_wednesday",15:"weekday_thursday",16:"weekday_friday",17:"weekday_saturday",18:"weekday_sunday",19:"dateFormat",20:"inclusiveEndDates",21:"topAxis",22:"axisFormat",23:"tickInterval",24:"excludes",25:"includes",26:"todayMarker",27:"title",28:"acc_title",29:"acc_title_value",30:"acc_descr",31:"acc_descr_value",32:"acc_descr_multiline_value",33:"section",35:"taskTxt",36:"taskData",37:"click",38:"callbackname",39:"callbackargs",40:"href"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,2],[34,2],[34,3],[34,3],[34,4],[34,3],[34,4],[34,2],[41,2],[41,3],[41,3],[41,4],[41,3],[41,4],[41,2]],performAction:function(o,d,m,u,S,c,X){var f=c.length-1;switch(S){case 1:return c[f-1];case 2:this.$=[];break;case 3:c[f-1].push(c[f]),this.$=c[f-1];break;case 4:case 5:this.$=c[f];break;case 6:case 7:this.$=[];break;case 8:u.setWeekday("monday");break;case 9:u.setWeekday("tuesday");break;case 10:u.setWeekday("wednesday");break;case 11:u.setWeekday("thursday");break;case 12:u.setWeekday("friday");break;case 13:u.setWeekday("saturday");break;case 14:u.setWeekday("sunday");break;case 15:u.setDateFormat(c[f].substr(11)),this.$=c[f].substr(11);break;case 16:u.enableInclusiveEndDates(),this.$=c[f].substr(18);break;case 17:u.TopAxis(),this.$=c[f].substr(8);break;case 18:u.setAxisFormat(c[f].substr(11)),this.$=c[f].substr(11);break;case 19:u.setTickInterval(c[f].substr(13)),this.$=c[f].substr(13);break;case 20:u.setExcludes(c[f].substr(9)),this.$=c[f].substr(9);break;case 21:u.setIncludes(c[f].substr(9)),this.$=c[f].substr(9);break;case 22:u.setTodayMarker(c[f].substr(12)),this.$=c[f].substr(12);break;case 24:u.setDiagramTitle(c[f].substr(6)),this.$=c[f].substr(6);break;case 25:this.$=c[f].trim(),u.setAccTitle(this.$);break;case 26:case 27:this.$=c[f].trim(),u.setAccDescription(this.$);break;case 28:u.addSection(c[f].substr(8)),this.$=c[f].substr(8);break;case 30:u.addTask(c[f-1],c[f]),this.$="task";break;case 31:this.$=c[f-1],u.setClickEvent(c[f-1],c[f],null);break;case 32:this.$=c[f-2],u.setClickEvent(c[f-2],c[f-1],c[f]);break;case 33:this.$=c[f-2],u.setClickEvent(c[f-2],c[f-1],null),u.setLink(c[f-2],c[f]);break;case 34:this.$=c[f-3],u.setClickEvent(c[f-3],c[f-2],c[f-1]),u.setLink(c[f-3],c[f]);break;case 35:this.$=c[f-2],u.setClickEvent(c[f-2],c[f],null),u.setLink(c[f-2],c[f-1]);break;case 36:this.$=c[f-3],u.setClickEvent(c[f-3],c[f-1],c[f]),u.setLink(c[f-3],c[f-2]);break;case 37:this.$=c[f-1],u.setLink(c[f-1],c[f]);break;case 38:case 44:this.$=c[f-1]+" "+c[f];break;case 39:case 40:case 42:this.$=c[f-2]+" "+c[f-1]+" "+c[f];break;case 41:case 43:this.$=c[f-3]+" "+c[f-2]+" "+c[f-1]+" "+c[f];break}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:17,12:n,13:r,14:i,15:s,16:a,17:k,18:Y,19:g,20:b,21:U,22:C,23:v,24:q,25:y,26:L,27:O,28:W,30:B,32:Z,33:Q,34:23,35:x,37:E},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:33,11:17,12:n,13:r,14:i,15:s,16:a,17:k,18:Y,19:g,20:b,21:U,22:C,23:v,24:q,25:y,26:L,27:O,28:W,30:B,32:Z,33:Q,34:23,35:x,37:E},t(e,[2,5]),t(e,[2,6]),t(e,[2,15]),t(e,[2,16]),t(e,[2,17]),t(e,[2,18]),t(e,[2,19]),t(e,[2,20]),t(e,[2,21]),t(e,[2,22]),t(e,[2,23]),t(e,[2,24]),{29:[1,34]},{31:[1,35]},t(e,[2,27]),t(e,[2,28]),t(e,[2,29]),{36:[1,36]},t(e,[2,8]),t(e,[2,9]),t(e,[2,10]),t(e,[2,11]),t(e,[2,12]),t(e,[2,13]),t(e,[2,14]),{38:[1,37],40:[1,38]},t(e,[2,4]),t(e,[2,25]),t(e,[2,26]),t(e,[2,30]),t(e,[2,31],{39:[1,39],40:[1,40]}),t(e,[2,37],{38:[1,41]}),t(e,[2,32],{40:[1,42]}),t(e,[2,33]),t(e,[2,35],{39:[1,43]}),t(e,[2,34]),t(e,[2,36])],defaultActions:{},parseError:function(o,d){if(d.recoverable)this.trace(o);else{var m=new Error(o);throw m.hash=d,m}},parse:function(o){var d=this,m=[0],u=[],S=[null],c=[],X=this.table,f="",h=0,_=0,G=2,H=1,V=c.slice.call(arguments,1),I=Object.create(this.lexer),z={yy:{}};for(var st in this.yy)Object.prototype.hasOwnProperty.call(this.yy,st)&&(z.yy[st]=this.yy[st]);I.setInput(o,z.yy),z.yy.lexer=I,z.yy.parser=this,typeof I.yylloc>"u"&&(I.yylloc={});var it=I.yylloc;c.push(it);var p=I.options&&I.options.ranges;typeof z.yy.parseError=="function"?this.parseError=z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function A(){var ct;return ct=u.pop()||I.lex()||H,typeof ct!="number"&&(ct instanceof Array&&(u=ct,ct=u.pop()),ct=d.symbols_[ct]||ct),ct}for(var M,l,R,N,j={},J,et,Ut,zt;;){if(l=m[m.length-1],this.defaultActions[l]?R=this.defaultActions[l]:((M===null||typeof M>"u")&&(M=A()),R=X[l]&&X[l][M]),typeof R>"u"||!R.length||!R[0]){var $t="";zt=[];for(J in X[l])this.terminals_[J]&&J>G&&zt.push("'"+this.terminals_[J]+"'");I.showPosition?$t="Parse error on line "+(h+1)+`:
                                         `+I.showPosition()+`
                                         Expecting `+zt.join(", ")+", got '"+(this.terminals_[M]||M)+"'":$t="Parse error on line "+(h+1)+": Unexpected "+(M==H?"end of input":"'"+(this.terminals_[M]||M)+"'"),this.parseError($t,{text:I.match,token:this.terminals_[M]||M,line:I.yylineno,loc:it,expected:zt})}if(R[0]instanceof Array&&R.length>1)throw new Error("Parse Error: multiple actions possible at state: "+l+", token: "+M);switch(R[0]){case 1:m.push(M),S.push(I.yytext),c.push(I.yylloc),m.push(R[1]),M=null,_=I.yyleng,f=I.yytext,h=I.yylineno,it=I.yylloc;break;case 2:if(et=this.productions_[R[1]][1],j.$=S[S.length-et],j._$={first_line:c[c.length-(et||1)].first_line,last_line:c[c.length-1].last_line,first_column:c[c.length-(et||1)].first_column,last_column:c[c.length-1].last_column},p&&(j._$.range=[c[c.length-(et||1)].range[0],c[c.length-1].range[1]]),N=this.performAction.apply(j,[f,_,h,z.yy,R[1],S,c].concat(V)),typeof N<"u")return N;et&&(m=m.slice(0,-1*et*2),S=S.slice(0,-1*et),c=c.slice(0,-1*et)),m.push(this.productions_[R[1]][0]),S.push(j.$),c.push(j._$),Ut=X[m[m.length-2]][m[m.length-1]],m.push(Ut);break;case 3:return!0}}return!0}},F=function(){var w={EOF:1,parseError:function(d,m){if(this.yy.parser)this.yy.parser.parseError(d,m);else throw new Error(d)},setInput:function(o,d){return this.yy=d||this.yy||{},this._input=o,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var o=this._input[0];this.yytext+=o,this.yyleng++,this.offset++,this.match+=o,this.matched+=o;var d=o.match(/(?:\r\n?|\n).*/g);return d?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),o},unput:function(o){var d=o.length,m=o.split(/(?:\r\n?|\n)/g);this._input=o+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-d),this.offset-=d;var u=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),m.length-1&&(this.yylineno-=m.length-1);var S=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:m?(m.length===u.length?this.yylloc.first_column:0)+u[u.length-m.length].length-m[0].length:this.yylloc.first_column-d},this.options.ranges&&(this.yylloc.range=[S[0],S[0]+this.yyleng-d]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(o){this.unput(this.match.slice(o))},pastInput:function(){var o=this.matched.substr(0,this.matched.length-this.match.length);return(o.length>20?"...":"")+o.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var o=this.match;return o.length<20&&(o+=this._input.substr(0,20-o.length)),(o.substr(0,20)+(o.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var o=this.pastInput(),d=new Array(o.length+1).join("-");return o+this.upcomingInput()+`
                                        diff --git a/assets/gitGraphDiagram-942e62fe-DOX28HzV.js b/assets/gitGraphDiagram-942e62fe-CmfeKiv3.js
                                        similarity index 99%
                                        rename from assets/gitGraphDiagram-942e62fe-DOX28HzV.js
                                        rename to assets/gitGraphDiagram-942e62fe-CmfeKiv3.js
                                        index 4d1ad241b3..5965421082 100644
                                        --- a/assets/gitGraphDiagram-942e62fe-DOX28HzV.js
                                        +++ b/assets/gitGraphDiagram-942e62fe-CmfeKiv3.js
                                        @@ -1,4 +1,4 @@
                                        -import{c as C,s as vt,g as Ct,a as Ot,b as Pt,x as At,y as Gt,l as B,j as D,A as St,h as It,z as Nt,as as Ht,at as Bt}from"./mermaid.core-CArNAncI.js";import"./app-5SoadDYS.js";var mt=function(){var r=function(G,o,u,d){for(u=u||{},d=G.length;d--;u[G[d]]=o);return u},n=[1,3],l=[1,6],h=[1,4],i=[1,5],c=[2,5],p=[1,12],m=[5,7,13,19,21,23,24,26,28,31,37,40,47],x=[7,13,19,21,23,24,26,28,31,37,40],y=[7,12,13,19,21,23,24,26,28,31,37,40],a=[7,13,47],R=[1,42],_=[1,41],b=[7,13,29,32,35,38,47],f=[1,55],k=[1,56],g=[1,57],E=[7,13,32,35,42,47],z={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,GG:5,document:6,EOF:7,":":8,DIR:9,options:10,body:11,OPT:12,NL:13,line:14,statement:15,commitStatement:16,mergeStatement:17,cherryPickStatement:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,section:24,branchStatement:25,CHECKOUT:26,ref:27,BRANCH:28,ORDER:29,NUM:30,CHERRY_PICK:31,COMMIT_ID:32,STR:33,PARENT_COMMIT:34,COMMIT_TAG:35,EMPTYSTR:36,MERGE:37,COMMIT_TYPE:38,commitType:39,COMMIT:40,commit_arg:41,COMMIT_MSG:42,NORMAL:43,REVERSE:44,HIGHLIGHT:45,ID:46,";":47,$accept:0,$end:1},terminals_:{2:"error",5:"GG",7:"EOF",8:":",9:"DIR",12:"OPT",13:"NL",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"section",26:"CHECKOUT",28:"BRANCH",29:"ORDER",30:"NUM",31:"CHERRY_PICK",32:"COMMIT_ID",33:"STR",34:"PARENT_COMMIT",35:"COMMIT_TAG",36:"EMPTYSTR",37:"MERGE",38:"COMMIT_TYPE",40:"COMMIT",42:"COMMIT_MSG",43:"NORMAL",44:"REVERSE",45:"HIGHLIGHT",46:"ID",47:";"},productions_:[0,[3,2],[3,3],[3,4],[3,5],[6,0],[6,2],[10,2],[10,1],[11,0],[11,2],[14,2],[14,1],[15,1],[15,1],[15,1],[15,2],[15,2],[15,1],[15,1],[15,1],[15,2],[25,2],[25,4],[18,3],[18,5],[18,5],[18,7],[18,7],[18,5],[18,5],[18,5],[18,7],[18,7],[18,7],[18,7],[17,2],[17,4],[17,4],[17,4],[17,6],[17,6],[17,6],[17,6],[17,6],[17,6],[17,8],[17,8],[17,8],[17,8],[17,8],[17,8],[16,2],[16,3],[16,3],[16,5],[16,5],[16,3],[16,5],[16,5],[16,5],[16,5],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,3],[16,5],[16,5],[16,5],[16,5],[16,5],[16,5],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[41,0],[41,1],[39,1],[39,1],[39,1],[27,1],[27,1],[4,1],[4,1],[4,1]],performAction:function(o,u,d,s,T,t,X){var e=t.length-1;switch(T){case 2:return t[e];case 3:return t[e-1];case 4:return s.setDirection(t[e-3]),t[e-1];case 6:s.setOptions(t[e-1]),this.$=t[e];break;case 7:t[e-1]+=t[e],this.$=t[e-1];break;case 9:this.$=[];break;case 10:t[e-1].push(t[e]),this.$=t[e-1];break;case 11:this.$=t[e-1];break;case 16:this.$=t[e].trim(),s.setAccTitle(this.$);break;case 17:case 18:this.$=t[e].trim(),s.setAccDescription(this.$);break;case 19:s.addSection(t[e].substr(8)),this.$=t[e].substr(8);break;case 21:s.checkout(t[e]);break;case 22:s.branch(t[e]);break;case 23:s.branch(t[e-2],t[e]);break;case 24:s.cherryPick(t[e],"",void 0);break;case 25:s.cherryPick(t[e-2],"",void 0,t[e]);break;case 26:s.cherryPick(t[e-2],"",t[e]);break;case 27:s.cherryPick(t[e-4],"",t[e],t[e-2]);break;case 28:s.cherryPick(t[e-4],"",t[e-2],t[e]);break;case 29:s.cherryPick(t[e],"",t[e-2]);break;case 30:s.cherryPick(t[e],"","");break;case 31:s.cherryPick(t[e-2],"","");break;case 32:s.cherryPick(t[e-4],"","",t[e-2]);break;case 33:s.cherryPick(t[e-4],"","",t[e]);break;case 34:s.cherryPick(t[e-2],"",t[e-4],t[e]);break;case 35:s.cherryPick(t[e-2],"","",t[e]);break;case 36:s.merge(t[e],"","","");break;case 37:s.merge(t[e-2],t[e],"","");break;case 38:s.merge(t[e-2],"",t[e],"");break;case 39:s.merge(t[e-2],"","",t[e]);break;case 40:s.merge(t[e-4],t[e],"",t[e-2]);break;case 41:s.merge(t[e-4],"",t[e],t[e-2]);break;case 42:s.merge(t[e-4],"",t[e-2],t[e]);break;case 43:s.merge(t[e-4],t[e-2],t[e],"");break;case 44:s.merge(t[e-4],t[e-2],"",t[e]);break;case 45:s.merge(t[e-4],t[e],t[e-2],"");break;case 46:s.merge(t[e-6],t[e-4],t[e-2],t[e]);break;case 47:s.merge(t[e-6],t[e],t[e-4],t[e-2]);break;case 48:s.merge(t[e-6],t[e-4],t[e],t[e-2]);break;case 49:s.merge(t[e-6],t[e-2],t[e-4],t[e]);break;case 50:s.merge(t[e-6],t[e],t[e-2],t[e-4]);break;case 51:s.merge(t[e-6],t[e-2],t[e],t[e-4]);break;case 52:s.commit(t[e]);break;case 53:s.commit("","",s.commitType.NORMAL,t[e]);break;case 54:s.commit("","",t[e],"");break;case 55:s.commit("","",t[e],t[e-2]);break;case 56:s.commit("","",t[e-2],t[e]);break;case 57:s.commit("",t[e],s.commitType.NORMAL,"");break;case 58:s.commit("",t[e-2],s.commitType.NORMAL,t[e]);break;case 59:s.commit("",t[e],s.commitType.NORMAL,t[e-2]);break;case 60:s.commit("",t[e-2],t[e],"");break;case 61:s.commit("",t[e],t[e-2],"");break;case 62:s.commit("",t[e-4],t[e-2],t[e]);break;case 63:s.commit("",t[e-4],t[e],t[e-2]);break;case 64:s.commit("",t[e-2],t[e-4],t[e]);break;case 65:s.commit("",t[e],t[e-4],t[e-2]);break;case 66:s.commit("",t[e],t[e-2],t[e-4]);break;case 67:s.commit("",t[e-2],t[e],t[e-4]);break;case 68:s.commit(t[e],"",s.commitType.NORMAL,"");break;case 69:s.commit(t[e],"",s.commitType.NORMAL,t[e-2]);break;case 70:s.commit(t[e-2],"",s.commitType.NORMAL,t[e]);break;case 71:s.commit(t[e-2],"",t[e],"");break;case 72:s.commit(t[e],"",t[e-2],"");break;case 73:s.commit(t[e],t[e-2],s.commitType.NORMAL,"");break;case 74:s.commit(t[e-2],t[e],s.commitType.NORMAL,"");break;case 75:s.commit(t[e-4],"",t[e-2],t[e]);break;case 76:s.commit(t[e-4],"",t[e],t[e-2]);break;case 77:s.commit(t[e-2],"",t[e-4],t[e]);break;case 78:s.commit(t[e],"",t[e-4],t[e-2]);break;case 79:s.commit(t[e],"",t[e-2],t[e-4]);break;case 80:s.commit(t[e-2],"",t[e],t[e-4]);break;case 81:s.commit(t[e-4],t[e],t[e-2],"");break;case 82:s.commit(t[e-4],t[e-2],t[e],"");break;case 83:s.commit(t[e-2],t[e],t[e-4],"");break;case 84:s.commit(t[e],t[e-2],t[e-4],"");break;case 85:s.commit(t[e],t[e-4],t[e-2],"");break;case 86:s.commit(t[e-2],t[e-4],t[e],"");break;case 87:s.commit(t[e-4],t[e],s.commitType.NORMAL,t[e-2]);break;case 88:s.commit(t[e-4],t[e-2],s.commitType.NORMAL,t[e]);break;case 89:s.commit(t[e-2],t[e],s.commitType.NORMAL,t[e-4]);break;case 90:s.commit(t[e],t[e-2],s.commitType.NORMAL,t[e-4]);break;case 91:s.commit(t[e],t[e-4],s.commitType.NORMAL,t[e-2]);break;case 92:s.commit(t[e-2],t[e-4],s.commitType.NORMAL,t[e]);break;case 93:s.commit(t[e-6],t[e-4],t[e-2],t[e]);break;case 94:s.commit(t[e-6],t[e-4],t[e],t[e-2]);break;case 95:s.commit(t[e-6],t[e-2],t[e-4],t[e]);break;case 96:s.commit(t[e-6],t[e],t[e-4],t[e-2]);break;case 97:s.commit(t[e-6],t[e-2],t[e],t[e-4]);break;case 98:s.commit(t[e-6],t[e],t[e-2],t[e-4]);break;case 99:s.commit(t[e-4],t[e-6],t[e-2],t[e]);break;case 100:s.commit(t[e-4],t[e-6],t[e],t[e-2]);break;case 101:s.commit(t[e-2],t[e-6],t[e-4],t[e]);break;case 102:s.commit(t[e],t[e-6],t[e-4],t[e-2]);break;case 103:s.commit(t[e-2],t[e-6],t[e],t[e-4]);break;case 104:s.commit(t[e],t[e-6],t[e-2],t[e-4]);break;case 105:s.commit(t[e],t[e-4],t[e-2],t[e-6]);break;case 106:s.commit(t[e-2],t[e-4],t[e],t[e-6]);break;case 107:s.commit(t[e],t[e-2],t[e-4],t[e-6]);break;case 108:s.commit(t[e-2],t[e],t[e-4],t[e-6]);break;case 109:s.commit(t[e-4],t[e-2],t[e],t[e-6]);break;case 110:s.commit(t[e-4],t[e],t[e-2],t[e-6]);break;case 111:s.commit(t[e-2],t[e-4],t[e-6],t[e]);break;case 112:s.commit(t[e],t[e-4],t[e-6],t[e-2]);break;case 113:s.commit(t[e-2],t[e],t[e-6],t[e-4]);break;case 114:s.commit(t[e],t[e-2],t[e-6],t[e-4]);break;case 115:s.commit(t[e-4],t[e-2],t[e-6],t[e]);break;case 116:s.commit(t[e-4],t[e],t[e-6],t[e-2]);break;case 117:this.$="";break;case 118:this.$=t[e];break;case 119:this.$=s.commitType.NORMAL;break;case 120:this.$=s.commitType.REVERSE;break;case 121:this.$=s.commitType.HIGHLIGHT;break}},table:[{3:1,4:2,5:n,7:l,13:h,47:i},{1:[3]},{3:7,4:2,5:n,7:l,13:h,47:i},{6:8,7:c,8:[1,9],9:[1,10],10:11,13:p},r(m,[2,124]),r(m,[2,125]),r(m,[2,126]),{1:[2,1]},{7:[1,13]},{6:14,7:c,10:11,13:p},{8:[1,15]},r(x,[2,9],{11:16,12:[1,17]}),r(y,[2,8]),{1:[2,2]},{7:[1,18]},{6:19,7:c,10:11,13:p},{7:[2,6],13:[1,22],14:20,15:21,16:23,17:24,18:25,19:[1,26],21:[1,27],23:[1,28],24:[1,29],25:30,26:[1,31],28:[1,35],31:[1,34],37:[1,33],40:[1,32]},r(y,[2,7]),{1:[2,3]},{7:[1,36]},r(x,[2,10]),{4:37,7:l,13:h,47:i},r(x,[2,12]),r(a,[2,13]),r(a,[2,14]),r(a,[2,15]),{20:[1,38]},{22:[1,39]},r(a,[2,18]),r(a,[2,19]),r(a,[2,20]),{27:40,33:R,46:_},r(a,[2,117],{41:43,32:[1,46],33:[1,48],35:[1,44],38:[1,45],42:[1,47]}),{27:49,33:R,46:_},{32:[1,50],35:[1,51]},{27:52,33:R,46:_},{1:[2,4]},r(x,[2,11]),r(a,[2,16]),r(a,[2,17]),r(a,[2,21]),r(b,[2,122]),r(b,[2,123]),r(a,[2,52]),{33:[1,53]},{39:54,43:f,44:k,45:g},{33:[1,58]},{33:[1,59]},r(a,[2,118]),r(a,[2,36],{32:[1,60],35:[1,62],38:[1,61]}),{33:[1,63]},{33:[1,64],36:[1,65]},r(a,[2,22],{29:[1,66]}),r(a,[2,53],{32:[1,68],38:[1,67],42:[1,69]}),r(a,[2,54],{32:[1,71],35:[1,70],42:[1,72]}),r(E,[2,119]),r(E,[2,120]),r(E,[2,121]),r(a,[2,57],{35:[1,73],38:[1,74],42:[1,75]}),r(a,[2,68],{32:[1,78],35:[1,76],38:[1,77]}),{33:[1,79]},{39:80,43:f,44:k,45:g},{33:[1,81]},r(a,[2,24],{34:[1,82],35:[1,83]}),{32:[1,84]},{32:[1,85]},{30:[1,86]},{39:87,43:f,44:k,45:g},{33:[1,88]},{33:[1,89]},{33:[1,90]},{33:[1,91]},{33:[1,92]},{33:[1,93]},{39:94,43:f,44:k,45:g},{33:[1,95]},{33:[1,96]},{39:97,43:f,44:k,45:g},{33:[1,98]},r(a,[2,37],{35:[1,100],38:[1,99]}),r(a,[2,38],{32:[1,102],35:[1,101]}),r(a,[2,39],{32:[1,103],38:[1,104]}),{33:[1,105]},{33:[1,106],36:[1,107]},{33:[1,108]},{33:[1,109]},r(a,[2,23]),r(a,[2,55],{32:[1,110],42:[1,111]}),r(a,[2,59],{38:[1,112],42:[1,113]}),r(a,[2,69],{32:[1,115],38:[1,114]}),r(a,[2,56],{32:[1,116],42:[1,117]}),r(a,[2,61],{35:[1,118],42:[1,119]}),r(a,[2,72],{32:[1,121],35:[1,120]}),r(a,[2,58],{38:[1,122],42:[1,123]}),r(a,[2,60],{35:[1,124],42:[1,125]}),r(a,[2,73],{35:[1,127],38:[1,126]}),r(a,[2,70],{32:[1,129],38:[1,128]}),r(a,[2,71],{32:[1,131],35:[1,130]}),r(a,[2,74],{35:[1,133],38:[1,132]}),{39:134,43:f,44:k,45:g},{33:[1,135]},{33:[1,136]},{33:[1,137]},{33:[1,138]},{39:139,43:f,44:k,45:g},r(a,[2,25],{35:[1,140]}),r(a,[2,26],{34:[1,141]}),r(a,[2,31],{34:[1,142]}),r(a,[2,29],{34:[1,143]}),r(a,[2,30],{34:[1,144]}),{33:[1,145]},{33:[1,146]},{39:147,43:f,44:k,45:g},{33:[1,148]},{39:149,43:f,44:k,45:g},{33:[1,150]},{33:[1,151]},{33:[1,152]},{33:[1,153]},{33:[1,154]},{33:[1,155]},{33:[1,156]},{39:157,43:f,44:k,45:g},{33:[1,158]},{33:[1,159]},{33:[1,160]},{39:161,43:f,44:k,45:g},{33:[1,162]},{39:163,43:f,44:k,45:g},{33:[1,164]},{33:[1,165]},{33:[1,166]},{39:167,43:f,44:k,45:g},{33:[1,168]},r(a,[2,43],{35:[1,169]}),r(a,[2,44],{38:[1,170]}),r(a,[2,42],{32:[1,171]}),r(a,[2,45],{35:[1,172]}),r(a,[2,40],{38:[1,173]}),r(a,[2,41],{32:[1,174]}),{33:[1,175],36:[1,176]},{33:[1,177]},{33:[1,178]},{33:[1,179]},{33:[1,180]},r(a,[2,66],{42:[1,181]}),r(a,[2,79],{32:[1,182]}),r(a,[2,67],{42:[1,183]}),r(a,[2,90],{38:[1,184]}),r(a,[2,80],{32:[1,185]}),r(a,[2,89],{38:[1,186]}),r(a,[2,65],{42:[1,187]}),r(a,[2,78],{32:[1,188]}),r(a,[2,64],{42:[1,189]}),r(a,[2,84],{35:[1,190]}),r(a,[2,77],{32:[1,191]}),r(a,[2,83],{35:[1,192]}),r(a,[2,63],{42:[1,193]}),r(a,[2,91],{38:[1,194]}),r(a,[2,62],{42:[1,195]}),r(a,[2,85],{35:[1,196]}),r(a,[2,86],{35:[1,197]}),r(a,[2,92],{38:[1,198]}),r(a,[2,76],{32:[1,199]}),r(a,[2,87],{38:[1,200]}),r(a,[2,75],{32:[1,201]}),r(a,[2,81],{35:[1,202]}),r(a,[2,82],{35:[1,203]}),r(a,[2,88],{38:[1,204]}),{33:[1,205]},{39:206,43:f,44:k,45:g},{33:[1,207]},{33:[1,208]},{39:209,43:f,44:k,45:g},{33:[1,210]},r(a,[2,27]),r(a,[2,32]),r(a,[2,28]),r(a,[2,33]),r(a,[2,34]),r(a,[2,35]),{33:[1,211]},{33:[1,212]},{33:[1,213]},{39:214,43:f,44:k,45:g},{33:[1,215]},{39:216,43:f,44:k,45:g},{33:[1,217]},{33:[1,218]},{33:[1,219]},{33:[1,220]},{33:[1,221]},{33:[1,222]},{33:[1,223]},{39:224,43:f,44:k,45:g},{33:[1,225]},{33:[1,226]},{33:[1,227]},{39:228,43:f,44:k,45:g},{33:[1,229]},{39:230,43:f,44:k,45:g},{33:[1,231]},{33:[1,232]},{33:[1,233]},{39:234,43:f,44:k,45:g},r(a,[2,46]),r(a,[2,48]),r(a,[2,47]),r(a,[2,49]),r(a,[2,51]),r(a,[2,50]),r(a,[2,107]),r(a,[2,108]),r(a,[2,105]),r(a,[2,106]),r(a,[2,110]),r(a,[2,109]),r(a,[2,114]),r(a,[2,113]),r(a,[2,112]),r(a,[2,111]),r(a,[2,116]),r(a,[2,115]),r(a,[2,104]),r(a,[2,103]),r(a,[2,102]),r(a,[2,101]),r(a,[2,99]),r(a,[2,100]),r(a,[2,98]),r(a,[2,97]),r(a,[2,96]),r(a,[2,95]),r(a,[2,93]),r(a,[2,94])],defaultActions:{7:[2,1],13:[2,2],18:[2,3],36:[2,4]},parseError:function(o,u){if(u.recoverable)this.trace(o);else{var d=new Error(o);throw d.hash=u,d}},parse:function(o){var u=this,d=[0],s=[],T=[null],t=[],X=this.table,e="",rt=0,ft=0,wt=2,pt=1,Lt=t.slice.call(arguments,1),O=Object.create(this.lexer),F={yy:{}};for(var ct in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ct)&&(F.yy[ct]=this.yy[ct]);O.setInput(o,F.yy),F.yy.lexer=O,F.yy.parser=this,typeof O.yylloc>"u"&&(O.yylloc={});var ot=O.yylloc;t.push(ot);var Rt=O.options&&O.options.ranges;typeof F.yy.parseError=="function"?this.parseError=F.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Mt(){var q;return q=s.pop()||O.lex()||pt,typeof q!="number"&&(q instanceof Array&&(s=q,q=s.pop()),q=u.symbols_[q]||q),q}for(var N,K,V,lt,J={},it,j,bt,st;;){if(K=d[d.length-1],this.defaultActions[K]?V=this.defaultActions[K]:((N===null||typeof N>"u")&&(N=Mt()),V=X[K]&&X[K][N]),typeof V>"u"||!V.length||!V[0]){var ht="";st=[];for(it in X[K])this.terminals_[it]&&it>wt&&st.push("'"+this.terminals_[it]+"'");O.showPosition?ht="Parse error on line "+(rt+1)+`:
                                        +import{c as C,s as vt,g as Ct,a as Ot,b as Pt,x as At,y as Gt,l as B,j as D,A as St,h as It,z as Nt,as as Ht,at as Bt}from"./mermaid.core-Bq0kX0MS.js";import"./app-Bw2NG-QJ.js";var mt=function(){var r=function(G,o,u,d){for(u=u||{},d=G.length;d--;u[G[d]]=o);return u},n=[1,3],l=[1,6],h=[1,4],i=[1,5],c=[2,5],p=[1,12],m=[5,7,13,19,21,23,24,26,28,31,37,40,47],x=[7,13,19,21,23,24,26,28,31,37,40],y=[7,12,13,19,21,23,24,26,28,31,37,40],a=[7,13,47],R=[1,42],_=[1,41],b=[7,13,29,32,35,38,47],f=[1,55],k=[1,56],g=[1,57],E=[7,13,32,35,42,47],z={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,GG:5,document:6,EOF:7,":":8,DIR:9,options:10,body:11,OPT:12,NL:13,line:14,statement:15,commitStatement:16,mergeStatement:17,cherryPickStatement:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,section:24,branchStatement:25,CHECKOUT:26,ref:27,BRANCH:28,ORDER:29,NUM:30,CHERRY_PICK:31,COMMIT_ID:32,STR:33,PARENT_COMMIT:34,COMMIT_TAG:35,EMPTYSTR:36,MERGE:37,COMMIT_TYPE:38,commitType:39,COMMIT:40,commit_arg:41,COMMIT_MSG:42,NORMAL:43,REVERSE:44,HIGHLIGHT:45,ID:46,";":47,$accept:0,$end:1},terminals_:{2:"error",5:"GG",7:"EOF",8:":",9:"DIR",12:"OPT",13:"NL",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"section",26:"CHECKOUT",28:"BRANCH",29:"ORDER",30:"NUM",31:"CHERRY_PICK",32:"COMMIT_ID",33:"STR",34:"PARENT_COMMIT",35:"COMMIT_TAG",36:"EMPTYSTR",37:"MERGE",38:"COMMIT_TYPE",40:"COMMIT",42:"COMMIT_MSG",43:"NORMAL",44:"REVERSE",45:"HIGHLIGHT",46:"ID",47:";"},productions_:[0,[3,2],[3,3],[3,4],[3,5],[6,0],[6,2],[10,2],[10,1],[11,0],[11,2],[14,2],[14,1],[15,1],[15,1],[15,1],[15,2],[15,2],[15,1],[15,1],[15,1],[15,2],[25,2],[25,4],[18,3],[18,5],[18,5],[18,7],[18,7],[18,5],[18,5],[18,5],[18,7],[18,7],[18,7],[18,7],[17,2],[17,4],[17,4],[17,4],[17,6],[17,6],[17,6],[17,6],[17,6],[17,6],[17,8],[17,8],[17,8],[17,8],[17,8],[17,8],[16,2],[16,3],[16,3],[16,5],[16,5],[16,3],[16,5],[16,5],[16,5],[16,5],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,3],[16,5],[16,5],[16,5],[16,5],[16,5],[16,5],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[41,0],[41,1],[39,1],[39,1],[39,1],[27,1],[27,1],[4,1],[4,1],[4,1]],performAction:function(o,u,d,s,T,t,X){var e=t.length-1;switch(T){case 2:return t[e];case 3:return t[e-1];case 4:return s.setDirection(t[e-3]),t[e-1];case 6:s.setOptions(t[e-1]),this.$=t[e];break;case 7:t[e-1]+=t[e],this.$=t[e-1];break;case 9:this.$=[];break;case 10:t[e-1].push(t[e]),this.$=t[e-1];break;case 11:this.$=t[e-1];break;case 16:this.$=t[e].trim(),s.setAccTitle(this.$);break;case 17:case 18:this.$=t[e].trim(),s.setAccDescription(this.$);break;case 19:s.addSection(t[e].substr(8)),this.$=t[e].substr(8);break;case 21:s.checkout(t[e]);break;case 22:s.branch(t[e]);break;case 23:s.branch(t[e-2],t[e]);break;case 24:s.cherryPick(t[e],"",void 0);break;case 25:s.cherryPick(t[e-2],"",void 0,t[e]);break;case 26:s.cherryPick(t[e-2],"",t[e]);break;case 27:s.cherryPick(t[e-4],"",t[e],t[e-2]);break;case 28:s.cherryPick(t[e-4],"",t[e-2],t[e]);break;case 29:s.cherryPick(t[e],"",t[e-2]);break;case 30:s.cherryPick(t[e],"","");break;case 31:s.cherryPick(t[e-2],"","");break;case 32:s.cherryPick(t[e-4],"","",t[e-2]);break;case 33:s.cherryPick(t[e-4],"","",t[e]);break;case 34:s.cherryPick(t[e-2],"",t[e-4],t[e]);break;case 35:s.cherryPick(t[e-2],"","",t[e]);break;case 36:s.merge(t[e],"","","");break;case 37:s.merge(t[e-2],t[e],"","");break;case 38:s.merge(t[e-2],"",t[e],"");break;case 39:s.merge(t[e-2],"","",t[e]);break;case 40:s.merge(t[e-4],t[e],"",t[e-2]);break;case 41:s.merge(t[e-4],"",t[e],t[e-2]);break;case 42:s.merge(t[e-4],"",t[e-2],t[e]);break;case 43:s.merge(t[e-4],t[e-2],t[e],"");break;case 44:s.merge(t[e-4],t[e-2],"",t[e]);break;case 45:s.merge(t[e-4],t[e],t[e-2],"");break;case 46:s.merge(t[e-6],t[e-4],t[e-2],t[e]);break;case 47:s.merge(t[e-6],t[e],t[e-4],t[e-2]);break;case 48:s.merge(t[e-6],t[e-4],t[e],t[e-2]);break;case 49:s.merge(t[e-6],t[e-2],t[e-4],t[e]);break;case 50:s.merge(t[e-6],t[e],t[e-2],t[e-4]);break;case 51:s.merge(t[e-6],t[e-2],t[e],t[e-4]);break;case 52:s.commit(t[e]);break;case 53:s.commit("","",s.commitType.NORMAL,t[e]);break;case 54:s.commit("","",t[e],"");break;case 55:s.commit("","",t[e],t[e-2]);break;case 56:s.commit("","",t[e-2],t[e]);break;case 57:s.commit("",t[e],s.commitType.NORMAL,"");break;case 58:s.commit("",t[e-2],s.commitType.NORMAL,t[e]);break;case 59:s.commit("",t[e],s.commitType.NORMAL,t[e-2]);break;case 60:s.commit("",t[e-2],t[e],"");break;case 61:s.commit("",t[e],t[e-2],"");break;case 62:s.commit("",t[e-4],t[e-2],t[e]);break;case 63:s.commit("",t[e-4],t[e],t[e-2]);break;case 64:s.commit("",t[e-2],t[e-4],t[e]);break;case 65:s.commit("",t[e],t[e-4],t[e-2]);break;case 66:s.commit("",t[e],t[e-2],t[e-4]);break;case 67:s.commit("",t[e-2],t[e],t[e-4]);break;case 68:s.commit(t[e],"",s.commitType.NORMAL,"");break;case 69:s.commit(t[e],"",s.commitType.NORMAL,t[e-2]);break;case 70:s.commit(t[e-2],"",s.commitType.NORMAL,t[e]);break;case 71:s.commit(t[e-2],"",t[e],"");break;case 72:s.commit(t[e],"",t[e-2],"");break;case 73:s.commit(t[e],t[e-2],s.commitType.NORMAL,"");break;case 74:s.commit(t[e-2],t[e],s.commitType.NORMAL,"");break;case 75:s.commit(t[e-4],"",t[e-2],t[e]);break;case 76:s.commit(t[e-4],"",t[e],t[e-2]);break;case 77:s.commit(t[e-2],"",t[e-4],t[e]);break;case 78:s.commit(t[e],"",t[e-4],t[e-2]);break;case 79:s.commit(t[e],"",t[e-2],t[e-4]);break;case 80:s.commit(t[e-2],"",t[e],t[e-4]);break;case 81:s.commit(t[e-4],t[e],t[e-2],"");break;case 82:s.commit(t[e-4],t[e-2],t[e],"");break;case 83:s.commit(t[e-2],t[e],t[e-4],"");break;case 84:s.commit(t[e],t[e-2],t[e-4],"");break;case 85:s.commit(t[e],t[e-4],t[e-2],"");break;case 86:s.commit(t[e-2],t[e-4],t[e],"");break;case 87:s.commit(t[e-4],t[e],s.commitType.NORMAL,t[e-2]);break;case 88:s.commit(t[e-4],t[e-2],s.commitType.NORMAL,t[e]);break;case 89:s.commit(t[e-2],t[e],s.commitType.NORMAL,t[e-4]);break;case 90:s.commit(t[e],t[e-2],s.commitType.NORMAL,t[e-4]);break;case 91:s.commit(t[e],t[e-4],s.commitType.NORMAL,t[e-2]);break;case 92:s.commit(t[e-2],t[e-4],s.commitType.NORMAL,t[e]);break;case 93:s.commit(t[e-6],t[e-4],t[e-2],t[e]);break;case 94:s.commit(t[e-6],t[e-4],t[e],t[e-2]);break;case 95:s.commit(t[e-6],t[e-2],t[e-4],t[e]);break;case 96:s.commit(t[e-6],t[e],t[e-4],t[e-2]);break;case 97:s.commit(t[e-6],t[e-2],t[e],t[e-4]);break;case 98:s.commit(t[e-6],t[e],t[e-2],t[e-4]);break;case 99:s.commit(t[e-4],t[e-6],t[e-2],t[e]);break;case 100:s.commit(t[e-4],t[e-6],t[e],t[e-2]);break;case 101:s.commit(t[e-2],t[e-6],t[e-4],t[e]);break;case 102:s.commit(t[e],t[e-6],t[e-4],t[e-2]);break;case 103:s.commit(t[e-2],t[e-6],t[e],t[e-4]);break;case 104:s.commit(t[e],t[e-6],t[e-2],t[e-4]);break;case 105:s.commit(t[e],t[e-4],t[e-2],t[e-6]);break;case 106:s.commit(t[e-2],t[e-4],t[e],t[e-6]);break;case 107:s.commit(t[e],t[e-2],t[e-4],t[e-6]);break;case 108:s.commit(t[e-2],t[e],t[e-4],t[e-6]);break;case 109:s.commit(t[e-4],t[e-2],t[e],t[e-6]);break;case 110:s.commit(t[e-4],t[e],t[e-2],t[e-6]);break;case 111:s.commit(t[e-2],t[e-4],t[e-6],t[e]);break;case 112:s.commit(t[e],t[e-4],t[e-6],t[e-2]);break;case 113:s.commit(t[e-2],t[e],t[e-6],t[e-4]);break;case 114:s.commit(t[e],t[e-2],t[e-6],t[e-4]);break;case 115:s.commit(t[e-4],t[e-2],t[e-6],t[e]);break;case 116:s.commit(t[e-4],t[e],t[e-6],t[e-2]);break;case 117:this.$="";break;case 118:this.$=t[e];break;case 119:this.$=s.commitType.NORMAL;break;case 120:this.$=s.commitType.REVERSE;break;case 121:this.$=s.commitType.HIGHLIGHT;break}},table:[{3:1,4:2,5:n,7:l,13:h,47:i},{1:[3]},{3:7,4:2,5:n,7:l,13:h,47:i},{6:8,7:c,8:[1,9],9:[1,10],10:11,13:p},r(m,[2,124]),r(m,[2,125]),r(m,[2,126]),{1:[2,1]},{7:[1,13]},{6:14,7:c,10:11,13:p},{8:[1,15]},r(x,[2,9],{11:16,12:[1,17]}),r(y,[2,8]),{1:[2,2]},{7:[1,18]},{6:19,7:c,10:11,13:p},{7:[2,6],13:[1,22],14:20,15:21,16:23,17:24,18:25,19:[1,26],21:[1,27],23:[1,28],24:[1,29],25:30,26:[1,31],28:[1,35],31:[1,34],37:[1,33],40:[1,32]},r(y,[2,7]),{1:[2,3]},{7:[1,36]},r(x,[2,10]),{4:37,7:l,13:h,47:i},r(x,[2,12]),r(a,[2,13]),r(a,[2,14]),r(a,[2,15]),{20:[1,38]},{22:[1,39]},r(a,[2,18]),r(a,[2,19]),r(a,[2,20]),{27:40,33:R,46:_},r(a,[2,117],{41:43,32:[1,46],33:[1,48],35:[1,44],38:[1,45],42:[1,47]}),{27:49,33:R,46:_},{32:[1,50],35:[1,51]},{27:52,33:R,46:_},{1:[2,4]},r(x,[2,11]),r(a,[2,16]),r(a,[2,17]),r(a,[2,21]),r(b,[2,122]),r(b,[2,123]),r(a,[2,52]),{33:[1,53]},{39:54,43:f,44:k,45:g},{33:[1,58]},{33:[1,59]},r(a,[2,118]),r(a,[2,36],{32:[1,60],35:[1,62],38:[1,61]}),{33:[1,63]},{33:[1,64],36:[1,65]},r(a,[2,22],{29:[1,66]}),r(a,[2,53],{32:[1,68],38:[1,67],42:[1,69]}),r(a,[2,54],{32:[1,71],35:[1,70],42:[1,72]}),r(E,[2,119]),r(E,[2,120]),r(E,[2,121]),r(a,[2,57],{35:[1,73],38:[1,74],42:[1,75]}),r(a,[2,68],{32:[1,78],35:[1,76],38:[1,77]}),{33:[1,79]},{39:80,43:f,44:k,45:g},{33:[1,81]},r(a,[2,24],{34:[1,82],35:[1,83]}),{32:[1,84]},{32:[1,85]},{30:[1,86]},{39:87,43:f,44:k,45:g},{33:[1,88]},{33:[1,89]},{33:[1,90]},{33:[1,91]},{33:[1,92]},{33:[1,93]},{39:94,43:f,44:k,45:g},{33:[1,95]},{33:[1,96]},{39:97,43:f,44:k,45:g},{33:[1,98]},r(a,[2,37],{35:[1,100],38:[1,99]}),r(a,[2,38],{32:[1,102],35:[1,101]}),r(a,[2,39],{32:[1,103],38:[1,104]}),{33:[1,105]},{33:[1,106],36:[1,107]},{33:[1,108]},{33:[1,109]},r(a,[2,23]),r(a,[2,55],{32:[1,110],42:[1,111]}),r(a,[2,59],{38:[1,112],42:[1,113]}),r(a,[2,69],{32:[1,115],38:[1,114]}),r(a,[2,56],{32:[1,116],42:[1,117]}),r(a,[2,61],{35:[1,118],42:[1,119]}),r(a,[2,72],{32:[1,121],35:[1,120]}),r(a,[2,58],{38:[1,122],42:[1,123]}),r(a,[2,60],{35:[1,124],42:[1,125]}),r(a,[2,73],{35:[1,127],38:[1,126]}),r(a,[2,70],{32:[1,129],38:[1,128]}),r(a,[2,71],{32:[1,131],35:[1,130]}),r(a,[2,74],{35:[1,133],38:[1,132]}),{39:134,43:f,44:k,45:g},{33:[1,135]},{33:[1,136]},{33:[1,137]},{33:[1,138]},{39:139,43:f,44:k,45:g},r(a,[2,25],{35:[1,140]}),r(a,[2,26],{34:[1,141]}),r(a,[2,31],{34:[1,142]}),r(a,[2,29],{34:[1,143]}),r(a,[2,30],{34:[1,144]}),{33:[1,145]},{33:[1,146]},{39:147,43:f,44:k,45:g},{33:[1,148]},{39:149,43:f,44:k,45:g},{33:[1,150]},{33:[1,151]},{33:[1,152]},{33:[1,153]},{33:[1,154]},{33:[1,155]},{33:[1,156]},{39:157,43:f,44:k,45:g},{33:[1,158]},{33:[1,159]},{33:[1,160]},{39:161,43:f,44:k,45:g},{33:[1,162]},{39:163,43:f,44:k,45:g},{33:[1,164]},{33:[1,165]},{33:[1,166]},{39:167,43:f,44:k,45:g},{33:[1,168]},r(a,[2,43],{35:[1,169]}),r(a,[2,44],{38:[1,170]}),r(a,[2,42],{32:[1,171]}),r(a,[2,45],{35:[1,172]}),r(a,[2,40],{38:[1,173]}),r(a,[2,41],{32:[1,174]}),{33:[1,175],36:[1,176]},{33:[1,177]},{33:[1,178]},{33:[1,179]},{33:[1,180]},r(a,[2,66],{42:[1,181]}),r(a,[2,79],{32:[1,182]}),r(a,[2,67],{42:[1,183]}),r(a,[2,90],{38:[1,184]}),r(a,[2,80],{32:[1,185]}),r(a,[2,89],{38:[1,186]}),r(a,[2,65],{42:[1,187]}),r(a,[2,78],{32:[1,188]}),r(a,[2,64],{42:[1,189]}),r(a,[2,84],{35:[1,190]}),r(a,[2,77],{32:[1,191]}),r(a,[2,83],{35:[1,192]}),r(a,[2,63],{42:[1,193]}),r(a,[2,91],{38:[1,194]}),r(a,[2,62],{42:[1,195]}),r(a,[2,85],{35:[1,196]}),r(a,[2,86],{35:[1,197]}),r(a,[2,92],{38:[1,198]}),r(a,[2,76],{32:[1,199]}),r(a,[2,87],{38:[1,200]}),r(a,[2,75],{32:[1,201]}),r(a,[2,81],{35:[1,202]}),r(a,[2,82],{35:[1,203]}),r(a,[2,88],{38:[1,204]}),{33:[1,205]},{39:206,43:f,44:k,45:g},{33:[1,207]},{33:[1,208]},{39:209,43:f,44:k,45:g},{33:[1,210]},r(a,[2,27]),r(a,[2,32]),r(a,[2,28]),r(a,[2,33]),r(a,[2,34]),r(a,[2,35]),{33:[1,211]},{33:[1,212]},{33:[1,213]},{39:214,43:f,44:k,45:g},{33:[1,215]},{39:216,43:f,44:k,45:g},{33:[1,217]},{33:[1,218]},{33:[1,219]},{33:[1,220]},{33:[1,221]},{33:[1,222]},{33:[1,223]},{39:224,43:f,44:k,45:g},{33:[1,225]},{33:[1,226]},{33:[1,227]},{39:228,43:f,44:k,45:g},{33:[1,229]},{39:230,43:f,44:k,45:g},{33:[1,231]},{33:[1,232]},{33:[1,233]},{39:234,43:f,44:k,45:g},r(a,[2,46]),r(a,[2,48]),r(a,[2,47]),r(a,[2,49]),r(a,[2,51]),r(a,[2,50]),r(a,[2,107]),r(a,[2,108]),r(a,[2,105]),r(a,[2,106]),r(a,[2,110]),r(a,[2,109]),r(a,[2,114]),r(a,[2,113]),r(a,[2,112]),r(a,[2,111]),r(a,[2,116]),r(a,[2,115]),r(a,[2,104]),r(a,[2,103]),r(a,[2,102]),r(a,[2,101]),r(a,[2,99]),r(a,[2,100]),r(a,[2,98]),r(a,[2,97]),r(a,[2,96]),r(a,[2,95]),r(a,[2,93]),r(a,[2,94])],defaultActions:{7:[2,1],13:[2,2],18:[2,3],36:[2,4]},parseError:function(o,u){if(u.recoverable)this.trace(o);else{var d=new Error(o);throw d.hash=u,d}},parse:function(o){var u=this,d=[0],s=[],T=[null],t=[],X=this.table,e="",rt=0,ft=0,wt=2,pt=1,Lt=t.slice.call(arguments,1),O=Object.create(this.lexer),F={yy:{}};for(var ct in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ct)&&(F.yy[ct]=this.yy[ct]);O.setInput(o,F.yy),F.yy.lexer=O,F.yy.parser=this,typeof O.yylloc>"u"&&(O.yylloc={});var ot=O.yylloc;t.push(ot);var Rt=O.options&&O.options.ranges;typeof F.yy.parseError=="function"?this.parseError=F.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Mt(){var q;return q=s.pop()||O.lex()||pt,typeof q!="number"&&(q instanceof Array&&(s=q,q=s.pop()),q=u.symbols_[q]||q),q}for(var N,K,V,lt,J={},it,j,bt,st;;){if(K=d[d.length-1],this.defaultActions[K]?V=this.defaultActions[K]:((N===null||typeof N>"u")&&(N=Mt()),V=X[K]&&X[K][N]),typeof V>"u"||!V.length||!V[0]){var ht="";st=[];for(it in X[K])this.terminals_[it]&&it>wt&&st.push("'"+this.terminals_[it]+"'");O.showPosition?ht="Parse error on line "+(rt+1)+`:
                                         `+O.showPosition()+`
                                         Expecting `+st.join(", ")+", got '"+(this.terminals_[N]||N)+"'":ht="Parse error on line "+(rt+1)+": Unexpected "+(N==pt?"end of input":"'"+(this.terminals_[N]||N)+"'"),this.parseError(ht,{text:O.match,token:this.terminals_[N]||N,line:O.yylineno,loc:ot,expected:st})}if(V[0]instanceof Array&&V.length>1)throw new Error("Parse Error: multiple actions possible at state: "+K+", token: "+N);switch(V[0]){case 1:d.push(N),T.push(O.yytext),t.push(O.yylloc),d.push(V[1]),N=null,ft=O.yyleng,e=O.yytext,rt=O.yylineno,ot=O.yylloc;break;case 2:if(j=this.productions_[V[1]][1],J.$=T[T.length-j],J._$={first_line:t[t.length-(j||1)].first_line,last_line:t[t.length-1].last_line,first_column:t[t.length-(j||1)].first_column,last_column:t[t.length-1].last_column},Rt&&(J._$.range=[t[t.length-(j||1)].range[0],t[t.length-1].range[1]]),lt=this.performAction.apply(J,[e,ft,rt,F.yy,V[1],T,t].concat(Lt)),typeof lt<"u")return lt;j&&(d=d.slice(0,-1*j*2),T=T.slice(0,-1*j),t=t.slice(0,-1*j)),d.push(this.productions_[V[1]][0]),T.push(J.$),t.push(J._$),bt=X[d[d.length-2]][d[d.length-1]],d.push(bt);break;case 3:return!0}}return!0}},M=function(){var G={EOF:1,parseError:function(u,d){if(this.yy.parser)this.yy.parser.parseError(u,d);else throw new Error(u)},setInput:function(o,u){return this.yy=u||this.yy||{},this._input=o,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var o=this._input[0];this.yytext+=o,this.yyleng++,this.offset++,this.match+=o,this.matched+=o;var u=o.match(/(?:\r\n?|\n).*/g);return u?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),o},unput:function(o){var u=o.length,d=o.split(/(?:\r\n?|\n)/g);this._input=o+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-u),this.offset-=u;var s=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),d.length-1&&(this.yylineno-=d.length-1);var T=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:d?(d.length===s.length?this.yylloc.first_column:0)+s[s.length-d.length].length-d[0].length:this.yylloc.first_column-u},this.options.ranges&&(this.yylloc.range=[T[0],T[0]+this.yyleng-u]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(o){this.unput(this.match.slice(o))},pastInput:function(){var o=this.matched.substr(0,this.matched.length-this.match.length);return(o.length>20?"...":"")+o.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var o=this.match;return o.length<20&&(o+=this._input.substr(0,20-o.length)),(o.substr(0,20)+(o.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var o=this.pastInput(),u=new Array(o.length+1).join("-");return o+this.upcomingInput()+`
                                        diff --git a/assets/graph-D2qW7eTj.js b/assets/graph-C-EgwjAv.js
                                        similarity index 99%
                                        rename from assets/graph-D2qW7eTj.js
                                        rename to assets/graph-C-EgwjAv.js
                                        index 28d5b3b3ad..9d9c7d725a 100644
                                        --- a/assets/graph-D2qW7eTj.js
                                        +++ b/assets/graph-C-EgwjAv.js
                                        @@ -1 +1 @@
                                        -import{B as I,C as Ze,S as m,D as y,E as Te,F as qe,G as Xe,H as Je,I as Ee,J as G,K as X,L as Qe,M as me,N as We,O as C,P as x,Q as Oe,R as ve,T as ze,U as Z,V as Ve,W as ke,X as P,Y as en,Z as nn,_ as rn,$ as re,a0 as tn,a1 as sn,a2 as an,a3 as we,a4 as un,a5 as j,a6 as fn,a7 as on,a8 as M,a9 as te,aa as ie}from"./mermaid.core-CArNAncI.js";var dn="[object Symbol]";function J(e){return typeof e=="symbol"||I(e)&&Ze(e)==dn}function $e(e,n){for(var r=-1,t=e==null?0:e.length,i=Array(t);++r-1}function T(e){return Te(e)?qe(e):Xe(e)}var yn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,An=/^\w*$/;function Q(e,n){if(y(e))return!1;var r=typeof e;return r=="number"||r=="symbol"||r=="boolean"||e==null||J(e)?!0:An.test(e)||!yn.test(e)||n!=null&&e in Object(n)}var Tn=500;function En(e){var n=Je(e,function(t){return r.size===Tn&&r.clear(),t}),r=n.cache;return n}var mn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,On=/\\(\\)?/g,vn=En(function(e){var n=[];return e.charCodeAt(0)===46&&n.push(""),e.replace(mn,function(r,t,i,s){n.push(i?s.replace(On,"$1"):t||r)}),n});function wn(e){return e==null?"":Le(e)}function Ie(e,n){return y(e)?e:Q(e,n)?[e]:vn(wn(e))}var $n=1/0;function U(e){if(typeof e=="string"||J(e))return e;var n=e+"";return n=="0"&&1/e==-$n?"-0":n}function Ce(e,n){n=Ie(n,e);for(var r=0,t=n.length;e!=null&&ru))return!1;var l=s.get(e),g=s.get(n);if(l&&g)return l==n&&g==e;var o=-1,h=!0,A=r&Qr?new S:void 0;for(s.set(e,n),s.set(n,e);++o=Ht){var l=Kt(e);if(l)return V(l);a=!1,i=Ge,f=new S}else f=u;e:for(;++t1?i.setNode(s,r):i.setNode(s)}),this}setNode(n,r){return E(this._nodes,n)?(arguments.length>1&&(this._nodes[n]=r),this):(this._nodes[n]=arguments.length>1?r:this._defaultNodeLabelFn(n),this._isCompound&&(this._parent[n]=w,this._children[n]={},this._children[w][n]=!0),this._in[n]={},this._preds[n]={},this._out[n]={},this._sucs[n]={},++this._nodeCount,this)}node(n){return this._nodes[n]}hasNode(n){return E(this._nodes,n)}removeNode(n){var r=this;if(E(this._nodes,n)){var t=function(i){r.removeEdge(r._edgeObjs[i])};delete this._nodes[n],this._isCompound&&(this._removeFromParentsChildList(n),delete this._parent[n],v(this.children(n),function(i){r.setParent(i)}),delete this._children[n]),v(T(this._in[n]),t),delete this._in[n],delete this._preds[n],v(T(this._out[n]),t),delete this._out[n],delete this._sucs[n],--this._nodeCount}return this}setParent(n,r){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if($(r))r=w;else{r+="";for(var t=r;!$(t);t=this.parent(t))if(t===n)throw new Error("Setting "+r+" as parent of "+n+" would create a cycle");this.setNode(r)}return this.setNode(n),this._removeFromParentsChildList(n),this._parent[n]=r,this._children[r][n]=!0,this}_removeFromParentsChildList(n){delete this._children[this._parent[n]][n]}parent(n){if(this._isCompound){var r=this._parent[n];if(r!==w)return r}}children(n){if($(n)&&(n=w),this._isCompound){var r=this._children[n];if(r)return T(r)}else{if(n===w)return this.nodes();if(this.hasNode(n))return[]}}predecessors(n){var r=this._preds[n];if(r)return T(r)}successors(n){var r=this._sucs[n];if(r)return T(r)}neighbors(n){var r=this.predecessors(n);if(r)return Zt(r,this.successors(n))}isLeaf(n){var r;return this.isDirected()?r=this.successors(n):r=this.neighbors(n),r.length===0}filterNodes(n){var r=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});r.setGraph(this.graph());var t=this;v(this._nodes,function(a,u){n(u)&&r.setNode(u,a)}),v(this._edgeObjs,function(a){r.hasNode(a.v)&&r.hasNode(a.w)&&r.setEdge(a,t.edge(a))});var i={};function s(a){var u=t.parent(a);return u===void 0||r.hasNode(u)?(i[a]=u,u):u in i?i[u]:s(u)}return this._isCompound&&v(r.nodes(),function(a){r.setParent(a,s(a))}),r}setDefaultEdgeLabel(n){return te(n)||(n=M(n)),this._defaultEdgeLabelFn=n,this}edgeCount(){return this._edgeCount}edges(){return H(this._edgeObjs)}setPath(n,r){var t=this,i=arguments;return jt(n,function(s,a){return i.length>1?t.setEdge(s,a,r):t.setEdge(s,a),a}),this}setEdge(){var n,r,t,i,s=!1,a=arguments[0];typeof a=="object"&&a!==null&&"v"in a?(n=a.v,r=a.w,t=a.name,arguments.length===2&&(i=arguments[1],s=!0)):(n=a,r=arguments[1],t=arguments[3],arguments.length>2&&(i=arguments[2],s=!0)),n=""+n,r=""+r,$(t)||(t=""+t);var u=L(this._isDirected,n,r,t);if(E(this._edgeLabels,u))return s&&(this._edgeLabels[u]=i),this;if(!$(t)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(n),this.setNode(r),this._edgeLabels[u]=s?i:this._defaultEdgeLabelFn(n,r,t);var f=Xt(this._isDirected,n,r,t);return n=f.v,r=f.w,Object.freeze(f),this._edgeObjs[u]=f,ye(this._preds[r],n),ye(this._sucs[n],r),this._in[r][u]=f,this._out[n][u]=f,this._edgeCount++,this}edge(n,r,t){var i=arguments.length===1?Y(this._isDirected,arguments[0]):L(this._isDirected,n,r,t);return this._edgeLabels[i]}hasEdge(n,r,t){var i=arguments.length===1?Y(this._isDirected,arguments[0]):L(this._isDirected,n,r,t);return E(this._edgeLabels,i)}removeEdge(n,r,t){var i=arguments.length===1?Y(this._isDirected,arguments[0]):L(this._isDirected,n,r,t),s=this._edgeObjs[i];return s&&(n=s.v,r=s.w,delete this._edgeLabels[i],delete this._edgeObjs[i],Ae(this._preds[r],n),Ae(this._sucs[n],r),delete this._in[r][i],delete this._out[n][i],this._edgeCount--),this}inEdges(n,r){var t=this._in[n];if(t){var i=H(t);return r?D(i,function(s){return s.v===r}):i}}outEdges(n,r){var t=this._out[n];if(t){var i=H(t);return r?D(i,function(s){return s.w===r}):i}}nodeEdges(n,r){var t=this.inEdges(n,r);if(t)return t.concat(this.outEdges(n,r))}}Ye.prototype._nodeCount=0;Ye.prototype._edgeCount=0;function ye(e,n){e[n]?e[n]++:e[n]=1}function Ae(e,n){--e[n]||delete e[n]}function L(e,n,r,t){var i=""+n,s=""+r;if(!e&&i>s){var a=i;i=s,s=a}return i+be+s+be+($(t)?qt:t)}function Xt(e,n,r,t){var i=""+n,s=""+r;if(!e&&i>s){var a=i;i=s,s=a}var u={v:i,w:s};return t&&(u.name=t),u}function Y(e,n){return L(e,n.v,n.w,n.name)}export{Ye as G,B as a,In as b,He as c,ln as d,ee as e,v as f,$e as g,E as h,J as i,Ft as j,T as k,St as l,Ie as m,Ce as n,vt as o,wn as p,$ as q,D as r,jt as s,U as t,H as v};
                                        +import{B as I,C as Ze,S as m,D as y,E as Te,F as qe,G as Xe,H as Je,I as Ee,J as G,K as X,L as Qe,M as me,N as We,O as C,P as x,Q as Oe,R as ve,T as ze,U as Z,V as Ve,W as ke,X as P,Y as en,Z as nn,_ as rn,$ as re,a0 as tn,a1 as sn,a2 as an,a3 as we,a4 as un,a5 as j,a6 as fn,a7 as on,a8 as M,a9 as te,aa as ie}from"./mermaid.core-Bq0kX0MS.js";var dn="[object Symbol]";function J(e){return typeof e=="symbol"||I(e)&&Ze(e)==dn}function $e(e,n){for(var r=-1,t=e==null?0:e.length,i=Array(t);++r-1}function T(e){return Te(e)?qe(e):Xe(e)}var yn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,An=/^\w*$/;function Q(e,n){if(y(e))return!1;var r=typeof e;return r=="number"||r=="symbol"||r=="boolean"||e==null||J(e)?!0:An.test(e)||!yn.test(e)||n!=null&&e in Object(n)}var Tn=500;function En(e){var n=Je(e,function(t){return r.size===Tn&&r.clear(),t}),r=n.cache;return n}var mn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,On=/\\(\\)?/g,vn=En(function(e){var n=[];return e.charCodeAt(0)===46&&n.push(""),e.replace(mn,function(r,t,i,s){n.push(i?s.replace(On,"$1"):t||r)}),n});function wn(e){return e==null?"":Le(e)}function Ie(e,n){return y(e)?e:Q(e,n)?[e]:vn(wn(e))}var $n=1/0;function U(e){if(typeof e=="string"||J(e))return e;var n=e+"";return n=="0"&&1/e==-$n?"-0":n}function Ce(e,n){n=Ie(n,e);for(var r=0,t=n.length;e!=null&&ru))return!1;var l=s.get(e),g=s.get(n);if(l&&g)return l==n&&g==e;var o=-1,h=!0,A=r&Qr?new S:void 0;for(s.set(e,n),s.set(n,e);++o=Ht){var l=Kt(e);if(l)return V(l);a=!1,i=Ge,f=new S}else f=u;e:for(;++t1?i.setNode(s,r):i.setNode(s)}),this}setNode(n,r){return E(this._nodes,n)?(arguments.length>1&&(this._nodes[n]=r),this):(this._nodes[n]=arguments.length>1?r:this._defaultNodeLabelFn(n),this._isCompound&&(this._parent[n]=w,this._children[n]={},this._children[w][n]=!0),this._in[n]={},this._preds[n]={},this._out[n]={},this._sucs[n]={},++this._nodeCount,this)}node(n){return this._nodes[n]}hasNode(n){return E(this._nodes,n)}removeNode(n){var r=this;if(E(this._nodes,n)){var t=function(i){r.removeEdge(r._edgeObjs[i])};delete this._nodes[n],this._isCompound&&(this._removeFromParentsChildList(n),delete this._parent[n],v(this.children(n),function(i){r.setParent(i)}),delete this._children[n]),v(T(this._in[n]),t),delete this._in[n],delete this._preds[n],v(T(this._out[n]),t),delete this._out[n],delete this._sucs[n],--this._nodeCount}return this}setParent(n,r){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if($(r))r=w;else{r+="";for(var t=r;!$(t);t=this.parent(t))if(t===n)throw new Error("Setting "+r+" as parent of "+n+" would create a cycle");this.setNode(r)}return this.setNode(n),this._removeFromParentsChildList(n),this._parent[n]=r,this._children[r][n]=!0,this}_removeFromParentsChildList(n){delete this._children[this._parent[n]][n]}parent(n){if(this._isCompound){var r=this._parent[n];if(r!==w)return r}}children(n){if($(n)&&(n=w),this._isCompound){var r=this._children[n];if(r)return T(r)}else{if(n===w)return this.nodes();if(this.hasNode(n))return[]}}predecessors(n){var r=this._preds[n];if(r)return T(r)}successors(n){var r=this._sucs[n];if(r)return T(r)}neighbors(n){var r=this.predecessors(n);if(r)return Zt(r,this.successors(n))}isLeaf(n){var r;return this.isDirected()?r=this.successors(n):r=this.neighbors(n),r.length===0}filterNodes(n){var r=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});r.setGraph(this.graph());var t=this;v(this._nodes,function(a,u){n(u)&&r.setNode(u,a)}),v(this._edgeObjs,function(a){r.hasNode(a.v)&&r.hasNode(a.w)&&r.setEdge(a,t.edge(a))});var i={};function s(a){var u=t.parent(a);return u===void 0||r.hasNode(u)?(i[a]=u,u):u in i?i[u]:s(u)}return this._isCompound&&v(r.nodes(),function(a){r.setParent(a,s(a))}),r}setDefaultEdgeLabel(n){return te(n)||(n=M(n)),this._defaultEdgeLabelFn=n,this}edgeCount(){return this._edgeCount}edges(){return H(this._edgeObjs)}setPath(n,r){var t=this,i=arguments;return jt(n,function(s,a){return i.length>1?t.setEdge(s,a,r):t.setEdge(s,a),a}),this}setEdge(){var n,r,t,i,s=!1,a=arguments[0];typeof a=="object"&&a!==null&&"v"in a?(n=a.v,r=a.w,t=a.name,arguments.length===2&&(i=arguments[1],s=!0)):(n=a,r=arguments[1],t=arguments[3],arguments.length>2&&(i=arguments[2],s=!0)),n=""+n,r=""+r,$(t)||(t=""+t);var u=L(this._isDirected,n,r,t);if(E(this._edgeLabels,u))return s&&(this._edgeLabels[u]=i),this;if(!$(t)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(n),this.setNode(r),this._edgeLabels[u]=s?i:this._defaultEdgeLabelFn(n,r,t);var f=Xt(this._isDirected,n,r,t);return n=f.v,r=f.w,Object.freeze(f),this._edgeObjs[u]=f,ye(this._preds[r],n),ye(this._sucs[n],r),this._in[r][u]=f,this._out[n][u]=f,this._edgeCount++,this}edge(n,r,t){var i=arguments.length===1?Y(this._isDirected,arguments[0]):L(this._isDirected,n,r,t);return this._edgeLabels[i]}hasEdge(n,r,t){var i=arguments.length===1?Y(this._isDirected,arguments[0]):L(this._isDirected,n,r,t);return E(this._edgeLabels,i)}removeEdge(n,r,t){var i=arguments.length===1?Y(this._isDirected,arguments[0]):L(this._isDirected,n,r,t),s=this._edgeObjs[i];return s&&(n=s.v,r=s.w,delete this._edgeLabels[i],delete this._edgeObjs[i],Ae(this._preds[r],n),Ae(this._sucs[n],r),delete this._in[r][i],delete this._out[n][i],this._edgeCount--),this}inEdges(n,r){var t=this._in[n];if(t){var i=H(t);return r?D(i,function(s){return s.v===r}):i}}outEdges(n,r){var t=this._out[n];if(t){var i=H(t);return r?D(i,function(s){return s.w===r}):i}}nodeEdges(n,r){var t=this.inEdges(n,r);if(t)return t.concat(this.outEdges(n,r))}}Ye.prototype._nodeCount=0;Ye.prototype._edgeCount=0;function ye(e,n){e[n]?e[n]++:e[n]=1}function Ae(e,n){--e[n]||delete e[n]}function L(e,n,r,t){var i=""+n,s=""+r;if(!e&&i>s){var a=i;i=s,s=a}return i+be+s+be+($(t)?qt:t)}function Xt(e,n,r,t){var i=""+n,s=""+r;if(!e&&i>s){var a=i;i=s,s=a}var u={v:i,w:s};return t&&(u.name=t),u}function Y(e,n){return L(e,n.v,n.w,n.name)}export{Ye as G,B as a,In as b,He as c,ln as d,ee as e,v as f,$e as g,E as h,J as i,Ft as j,T as k,St as l,Ie as m,Ce as n,vt as o,wn as p,$ as q,D as r,jt as s,U as t,H as v};
                                        diff --git a/assets/grpc.html-mPuqwjqH.js b/assets/grpc.html-3wMb5fVh.js
                                        similarity index 99%
                                        rename from assets/grpc.html-mPuqwjqH.js
                                        rename to assets/grpc.html-3wMb5fVh.js
                                        index 44e0647c71..d82b5f5159 100644
                                        --- a/assets/grpc.html-mPuqwjqH.js
                                        +++ b/assets/grpc.html-3wMb5fVh.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as c,c as r,a as o,b as e,d as l,e as s}from"./app-5SoadDYS.js";const p={},d=s(`

                                        gRPC

                                        An modified transport protocol based on gRPC.

                                        gRPC is based on the HTTP/2 protocol and can theoretically be relayed by other servers that support HTTP/2, such as Nginx.

                                        gRPC and HTTP/2 has built-in multiplexing, so it is not recommended to enable mux.cool when using gRPC or HTTP/2.

                                        ⚠⚠⚠

                                        • gRPC doesn't support specifying the Host. Please enter the correct domain name in the outbound proxy address, or fill in ServerName in (x)tlsSettings, otherwise connection cannot be established.
                                        • gRPC doesn't support fallback to other services.
                                        • gRPC services are at risk of being actively probed. It is recommended to use reverse proxy tools such as Caddy or Nginx to perform path-based routing.

                                        Tip

                                        If you are using a reverse proxy such as Caddy or Nginx, please note the following:

                                        • Make sure that the reverse proxy server has enabled HTTP/2.
                                        • Use HTTP/2 or h2c (Caddy), grpc_pass (Nginx) to connect to Xray.
                                        • The path for regular mode is /\${serviceName}/Tun, and for Multi mode it is /\${serviceName}/TunMulti.
                                        • If you need to receive the client IP address, you can use the X-Real-IP header sent by Caddy / Nginx to pass the client IP.

                                        Tip

                                        If you are using fallback, please note the following:

                                        • Fallback to gRPC is not recommended, as there is a risk of being actively probed.
                                        • Please make sure that h2 is the first priority in (x)tlsSettings.alpn, otherwise gRPC (HTTP/2) may not be able to complete TLS handshake.
                                        • gRPC cannot perform path-based routing by Xray.

                                        GRPCObject

                                        GRPCObject corresponds to the grpcSettings item.

                                        {
                                        +import{_ as i,r as t,o as c,c as r,a as o,b as e,d as l,e as s}from"./app-Bw2NG-QJ.js";const p={},d=s(`

                                        gRPC

                                        An modified transport protocol based on gRPC.

                                        gRPC is based on the HTTP/2 protocol and can theoretically be relayed by other servers that support HTTP/2, such as Nginx.

                                        gRPC and HTTP/2 has built-in multiplexing, so it is not recommended to enable mux.cool when using gRPC or HTTP/2.

                                        ⚠⚠⚠

                                        • gRPC doesn't support specifying the Host. Please enter the correct domain name in the outbound proxy address, or fill in ServerName in (x)tlsSettings, otherwise connection cannot be established.
                                        • gRPC doesn't support fallback to other services.
                                        • gRPC services are at risk of being actively probed. It is recommended to use reverse proxy tools such as Caddy or Nginx to perform path-based routing.

                                        Tip

                                        If you are using a reverse proxy such as Caddy or Nginx, please note the following:

                                        • Make sure that the reverse proxy server has enabled HTTP/2.
                                        • Use HTTP/2 or h2c (Caddy), grpc_pass (Nginx) to connect to Xray.
                                        • The path for regular mode is /\${serviceName}/Tun, and for Multi mode it is /\${serviceName}/TunMulti.
                                        • If you need to receive the client IP address, you can use the X-Real-IP header sent by Caddy / Nginx to pass the client IP.

                                        Tip

                                        If you are using fallback, please note the following:

                                        • Fallback to gRPC is not recommended, as there is a risk of being actively probed.
                                        • Please make sure that h2 is the first priority in (x)tlsSettings.alpn, otherwise gRPC (HTTP/2) may not be able to complete TLS handshake.
                                        • gRPC cannot perform path-based routing by Xray.

                                        GRPCObject

                                        GRPCObject corresponds to the grpcSettings item.

                                        {
                                           "serviceName": "name",
                                           "multiMode": false,
                                           "idle_timeout": 60,
                                        diff --git a/assets/grpc.html-BiVb6JVN.js b/assets/grpc.html-BpDUzsty.js
                                        similarity index 99%
                                        rename from assets/grpc.html-BiVb6JVN.js
                                        rename to assets/grpc.html-BpDUzsty.js
                                        index 67daa7d42c..ba2ad092f3 100644
                                        --- a/assets/grpc.html-BiVb6JVN.js
                                        +++ b/assets/grpc.html-BpDUzsty.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as t,o as p,c as i,a as s,b as o,d as l,e}from"./app-5SoadDYS.js";const r={},d=e(`

                                        gRPC

                                        Режим передачи данных, основанный на HTTP/2, полностью соответствует стандарту HTTP/2 и может быть ретранслирован другими HTTP-серверами (такими как Nginx).

                                        gRPC (HTTP/2) имеет встроенное мультиплексирование, не рекомендуется включать mux.cool при использовании gRPC и HTTP/2.

                                        ⚠⚠⚠

                                        • gRPC не поддерживает указание Host. Пожалуйста, укажите правильное доменное имя в адресе исходящего прокси или укажите ServerName в (x)tlsSettings, иначе подключение не будет установлено.
                                        • gRPC не поддерживает fallback на другие сервисы.
                                        • Существует риск активного сканирования сервисов gRPC. Рекомендуется использовать обратный прокси-сервер, такой как Caddy или Nginx, для предварительного разделения трафика по пути.

                                        Подсказка

                                        Если вы используете обратный прокси-сервер, такой как Caddy или Nginx, обратите внимание на следующие моменты:

                                        • Убедитесь, что на обратном прокси-сервере включен HTTP/2.
                                        • Используйте HTTP/2 или h2c (Caddy), grpc_pass (Nginx) для подключения к Xray.
                                        • Путь в обычном режиме: /\${serviceName}/Tun, в режиме Multi: /\${serviceName}/TunMulti.
                                        • Если необходимо получать IP-адрес клиента, его можно передать через заголовок X-Real-IP, отправленный Caddy / Nginx.

                                        Подсказка

                                        Если вы используете fallback, обратите внимание на следующие моменты:

                                        • Не рекомендуется использовать fallback на gRPC, так как существует риск активного сканирования.
                                        • Убедитесь, что h2 находится на первом месте в (x)tlsSettings.alpn, иначе gRPC (HTTP/2) может не завершить TLS-рукопожатие.
                                        • gRPC не поддерживает маршрутизацию на основе path с помощью Xray.

                                        GRPCObject

                                        GRPCObject соответствует элементу grpcSettings конфигурации передачи.

                                        {
                                        +import{_ as c,r as t,o as p,c as i,a as s,b as o,d as l,e}from"./app-Bw2NG-QJ.js";const r={},d=e(`

                                        gRPC

                                        Режим передачи данных, основанный на HTTP/2, полностью соответствует стандарту HTTP/2 и может быть ретранслирован другими HTTP-серверами (такими как Nginx).

                                        gRPC (HTTP/2) имеет встроенное мультиплексирование, не рекомендуется включать mux.cool при использовании gRPC и HTTP/2.

                                        ⚠⚠⚠

                                        • gRPC не поддерживает указание Host. Пожалуйста, укажите правильное доменное имя в адресе исходящего прокси или укажите ServerName в (x)tlsSettings, иначе подключение не будет установлено.
                                        • gRPC не поддерживает fallback на другие сервисы.
                                        • Существует риск активного сканирования сервисов gRPC. Рекомендуется использовать обратный прокси-сервер, такой как Caddy или Nginx, для предварительного разделения трафика по пути.

                                        Подсказка

                                        Если вы используете обратный прокси-сервер, такой как Caddy или Nginx, обратите внимание на следующие моменты:

                                        • Убедитесь, что на обратном прокси-сервере включен HTTP/2.
                                        • Используйте HTTP/2 или h2c (Caddy), grpc_pass (Nginx) для подключения к Xray.
                                        • Путь в обычном режиме: /\${serviceName}/Tun, в режиме Multi: /\${serviceName}/TunMulti.
                                        • Если необходимо получать IP-адрес клиента, его можно передать через заголовок X-Real-IP, отправленный Caddy / Nginx.

                                        Подсказка

                                        Если вы используете fallback, обратите внимание на следующие моменты:

                                        • Не рекомендуется использовать fallback на gRPC, так как существует риск активного сканирования.
                                        • Убедитесь, что h2 находится на первом месте в (x)tlsSettings.alpn, иначе gRPC (HTTP/2) может не завершить TLS-рукопожатие.
                                        • gRPC не поддерживает маршрутизацию на основе path с помощью Xray.

                                        GRPCObject

                                        GRPCObject соответствует элементу grpcSettings конфигурации передачи.

                                        {
                                           "authority": "grpc.example.com",
                                           "serviceName": "name",
                                           "multiMode": false,
                                        diff --git a/assets/grpc.html-C_Kg2sXl.js b/assets/grpc.html-DnIgTPpb.js
                                        similarity index 99%
                                        rename from assets/grpc.html-C_Kg2sXl.js
                                        rename to assets/grpc.html-DnIgTPpb.js
                                        index b35a82b373..984f8bed11 100644
                                        --- a/assets/grpc.html-C_Kg2sXl.js
                                        +++ b/assets/grpc.html-DnIgTPpb.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as o,o as p,c as i,a as t,b as s,d as r,e}from"./app-5SoadDYS.js";const l={},d=e(`

                                        gRPC

                                        基于 gRPC 的传输方式。

                                        它基于 HTTP/2 协议,理论上可以通过其它支持 HTTP/2 的服务器(如 Nginx)进行中转。 gRPC(HTTP/2)内置多路复用,不建议使用 gRPC 与 HTTP/2 时启用 mux.cool。

                                        ⚠⚠⚠

                                        • gRPC 不支持指定 Host。请在出站代理地址中填写 正确的域名 ,或在 (x)tlsSettings 中填写 ServerName,否则无法连接。
                                        • gRPC 不支持回落到其他服务。
                                        • gRPC 服务存在被主动探测的风险。建议使用 Caddy 或 Nginx 等反向代理工具,通过 Path 前置分流。

                                        提示

                                        如果您使用 Caddy 或 Nginx 等反向代理,请注意下列事项:

                                        • 请确定反向代理服务器开启了 HTTP/2
                                        • 请使用 HTTP/2 或 h2c (Caddy),grpc_pass (Nginx) 连接到 Xray。
                                        • 普通模式的 Path 为 /\${serviceName}/Tun, Multi 模式为 /\${serviceName}/TunMulti
                                        • 如果需要接收客户端 IP,可以通过由 Caddy / Nginx 发送 X-Real-IP header 来传递客户端 IP。

                                        提示

                                        如果你正在使用回落,请注意下列事项:

                                        • 不建议回落到 gRPC,存在被主动探测的风险。
                                        • 请确认h2 位于 (x)tlsSettings.alpn 中的第一顺位,否则 gRPC(HTTP/2)可能无法完成 TLS 握手。
                                        • gRPC 无法通过进行 Path 分流。

                                        GRPCObject

                                        GRPCObject 对应传输配置的 grpcSettings 项。

                                        {
                                        +import{_ as c,r as o,o as p,c as i,a as t,b as s,d as r,e}from"./app-Bw2NG-QJ.js";const l={},d=e(`

                                        gRPC

                                        基于 gRPC 的传输方式。

                                        它基于 HTTP/2 协议,理论上可以通过其它支持 HTTP/2 的服务器(如 Nginx)进行中转。 gRPC(HTTP/2)内置多路复用,不建议使用 gRPC 与 HTTP/2 时启用 mux.cool。

                                        ⚠⚠⚠

                                        • gRPC 不支持指定 Host。请在出站代理地址中填写 正确的域名 ,或在 (x)tlsSettings 中填写 ServerName,否则无法连接。
                                        • gRPC 不支持回落到其他服务。
                                        • gRPC 服务存在被主动探测的风险。建议使用 Caddy 或 Nginx 等反向代理工具,通过 Path 前置分流。

                                        提示

                                        如果您使用 Caddy 或 Nginx 等反向代理,请注意下列事项:

                                        • 请确定反向代理服务器开启了 HTTP/2
                                        • 请使用 HTTP/2 或 h2c (Caddy),grpc_pass (Nginx) 连接到 Xray。
                                        • 普通模式的 Path 为 /\${serviceName}/Tun, Multi 模式为 /\${serviceName}/TunMulti
                                        • 如果需要接收客户端 IP,可以通过由 Caddy / Nginx 发送 X-Real-IP header 来传递客户端 IP。

                                        提示

                                        如果你正在使用回落,请注意下列事项:

                                        • 不建议回落到 gRPC,存在被主动探测的风险。
                                        • 请确认h2 位于 (x)tlsSettings.alpn 中的第一顺位,否则 gRPC(HTTP/2)可能无法完成 TLS 握手。
                                        • gRPC 无法通过进行 Path 分流。

                                        GRPCObject

                                        GRPCObject 对应传输配置的 grpcSettings 项。

                                        {
                                           "authority": "grpc.example.com",
                                           "serviceName": "name",
                                           "multiMode": false,
                                        diff --git a/assets/guide.html-DPanWeGq.js b/assets/guide.html-BjshCdoe.js
                                        similarity index 99%
                                        rename from assets/guide.html-DPanWeGq.js
                                        rename to assets/guide.html-BjshCdoe.js
                                        index cbda7e73cd..6cab7ec7f1 100644
                                        --- a/assets/guide.html-DPanWeGq.js
                                        +++ b/assets/guide.html-BjshCdoe.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as t,r as o,o as c,c as d,a as n,b as e,d as l,e as i}from"./app-5SoadDYS.js";const h={},u=i('

                                        开发规范

                                        基本

                                        版本控制

                                        Project X 的代码被托管在 github 上:

                                        ',4),p={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},_={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},g={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},m={href:"https://git-scm.com/",target:"_blank",rel:"noopener noreferrer"},f=e("h3",{id:"分支-branch",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#分支-branch"},[e("span",null,"分支(Branch)")])],-1),x=e("ul",null,[e("li",null,"本项目的主干分支为 main,"),e("li",null,"本项目的发布主分支同为 main,"),e("li",null,"需要确保 main 在任一时刻都是可编译,且可正常使用的。"),e("li",null,"如果需要开发新的功能,请新建分支进行开发,在开发完成并且经过充分测试后,合并回主干分支。"),e("li",null,"已经合并入主干且没有必要存在的分支,请删除。")],-1),v=e("h3",{id:"发布-release",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#发布-release"},[e("span",null,"发布(Release)")])],-1),X=e("ul",null,[e("li",null,[l("建立尝鲜版本和稳定版本两个发布通道 "),e("ul",null,[e("li",null,"尝鲜版本,可以为 daily build,主要用于特定情况的测试,尝鲜和获得即时反馈和再改进。"),e("li",null,"稳定版本,为定时更新(比如月更),合并稳定的修改并发布。")])])],-1),y=e("h3",{id:"引用其它项目",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#引用其它项目"},[e("span",null,"引用其它项目")])],-1),k={href:"https://pkg.go.dev/search?limit=25&m=package&q=golang.org%2Fx",target:"_blank",rel:"noopener noreferrer"},P=e("li",null,"如需引用其它项目,请事先创建 issue 讨论;",-1),T=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"不违反双方的协议,且对项目有帮助的工具,都可以使用。")])],-1),B=e("h2",{id:"开发流程",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发流程"},[e("span",null,"开发流程")])],-1),L=e("h3",{id:"写代码之前",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#写代码之前"},[e("span",null,"写代码之前")])],-1),E={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},G=e("h3",{id:"修改代码",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#修改代码"},[e("span",null,"修改代码")])],-1),R={href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"},S=e("li",null,[l("每一次 push 之前,请运行:"),e("code",null,"go generate core/format.go"),l(";")],-1),q=e("li",null,[l("如果需要修改 protobuf,例如增加新配置项,请运行:"),e("code",null,"go generate core/proto.go"),l(";")],-1),A=e("li",null,[l("提交 pull request 之前,建议测试通过:"),e("code",null,"go test ./..."),l(";")],-1),F=e("li",null,"提交 pull request 之前,建议新增代码有超过 70% 的代码覆盖率(code coverage);",-1),I=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"请注意代码的可读性。")])],-1),w=i(`

                                        Pull Request

                                        • 提交 PR 之前,请先运行 git pull https://github.com/XTLS/Xray-core.git 以确保 merge 可顺利进行;
                                        • 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR;
                                        • 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同,建议流程如下:
                                          1. 先 Fork 本项目,创建你自己的 github.com/<your_name>/Xray-core.git 仓库;
                                          2. 克隆你自己的 Xray 仓库到本地:git clone https://github.com/<your_name>/Xray-core.git
                                          3. 基于 main 分支创建新的分支,例如 git branch issue24 main
                                          4. 在新创建的分支上作修改并提交修改(commit);
                                          5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 main 分支,运行 git pull https://github.com/XTLS/Xray-core.git 拉取最新的远端代码;
                                          6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 git rebase main 执行分支合并操作。如遇到文件冲突,则需要解决冲突;
                                          7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:git push -u origin your-branch
                                          8. 最后,把自己仓库的新推送的分支往 XTLS/Xray-coremain 分支发 PR 即可;
                                          9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等;
                                          10. 耐心等待开发者的回应。

                                        对代码的修改

                                        功能性问题

                                        请提交至少一个测试用例(Test Case)来验证对现有功能的改动。

                                        性能相关

                                        请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。

                                        新功能

                                        • 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态;
                                        • 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。

                                        其它

                                        视具体情况而定。

                                        Xray 编码规范

                                        以下内容适用于 Xray 中的 Golang 代码。

                                        代码结构

                                        Xray-core
                                        +import{_ as t,r as o,o as c,c as d,a as n,b as e,d as l,e as i}from"./app-Bw2NG-QJ.js";const h={},u=i('

                                        开发规范

                                        基本

                                        版本控制

                                        Project X 的代码被托管在 github 上:

                                        ',4),p={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},_={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},g={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},m={href:"https://git-scm.com/",target:"_blank",rel:"noopener noreferrer"},f=e("h3",{id:"分支-branch",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#分支-branch"},[e("span",null,"分支(Branch)")])],-1),x=e("ul",null,[e("li",null,"本项目的主干分支为 main,"),e("li",null,"本项目的发布主分支同为 main,"),e("li",null,"需要确保 main 在任一时刻都是可编译,且可正常使用的。"),e("li",null,"如果需要开发新的功能,请新建分支进行开发,在开发完成并且经过充分测试后,合并回主干分支。"),e("li",null,"已经合并入主干且没有必要存在的分支,请删除。")],-1),v=e("h3",{id:"发布-release",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#发布-release"},[e("span",null,"发布(Release)")])],-1),X=e("ul",null,[e("li",null,[l("建立尝鲜版本和稳定版本两个发布通道 "),e("ul",null,[e("li",null,"尝鲜版本,可以为 daily build,主要用于特定情况的测试,尝鲜和获得即时反馈和再改进。"),e("li",null,"稳定版本,为定时更新(比如月更),合并稳定的修改并发布。")])])],-1),y=e("h3",{id:"引用其它项目",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#引用其它项目"},[e("span",null,"引用其它项目")])],-1),k={href:"https://pkg.go.dev/search?limit=25&m=package&q=golang.org%2Fx",target:"_blank",rel:"noopener noreferrer"},P=e("li",null,"如需引用其它项目,请事先创建 issue 讨论;",-1),T=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"不违反双方的协议,且对项目有帮助的工具,都可以使用。")])],-1),B=e("h2",{id:"开发流程",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发流程"},[e("span",null,"开发流程")])],-1),L=e("h3",{id:"写代码之前",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#写代码之前"},[e("span",null,"写代码之前")])],-1),E={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},G=e("h3",{id:"修改代码",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#修改代码"},[e("span",null,"修改代码")])],-1),R={href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"},S=e("li",null,[l("每一次 push 之前,请运行:"),e("code",null,"go generate core/format.go"),l(";")],-1),q=e("li",null,[l("如果需要修改 protobuf,例如增加新配置项,请运行:"),e("code",null,"go generate core/proto.go"),l(";")],-1),A=e("li",null,[l("提交 pull request 之前,建议测试通过:"),e("code",null,"go test ./..."),l(";")],-1),F=e("li",null,"提交 pull request 之前,建议新增代码有超过 70% 的代码覆盖率(code coverage);",-1),I=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"请注意代码的可读性。")])],-1),w=i(`

                                        Pull Request

                                        • 提交 PR 之前,请先运行 git pull https://github.com/XTLS/Xray-core.git 以确保 merge 可顺利进行;
                                        • 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR;
                                        • 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同,建议流程如下:
                                          1. 先 Fork 本项目,创建你自己的 github.com/<your_name>/Xray-core.git 仓库;
                                          2. 克隆你自己的 Xray 仓库到本地:git clone https://github.com/<your_name>/Xray-core.git
                                          3. 基于 main 分支创建新的分支,例如 git branch issue24 main
                                          4. 在新创建的分支上作修改并提交修改(commit);
                                          5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 main 分支,运行 git pull https://github.com/XTLS/Xray-core.git 拉取最新的远端代码;
                                          6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 git rebase main 执行分支合并操作。如遇到文件冲突,则需要解决冲突;
                                          7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:git push -u origin your-branch
                                          8. 最后,把自己仓库的新推送的分支往 XTLS/Xray-coremain 分支发 PR 即可;
                                          9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等;
                                          10. 耐心等待开发者的回应。

                                        对代码的修改

                                        功能性问题

                                        请提交至少一个测试用例(Test Case)来验证对现有功能的改动。

                                        性能相关

                                        请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。

                                        新功能

                                        • 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态;
                                        • 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。

                                        其它

                                        视具体情况而定。

                                        Xray 编码规范

                                        以下内容适用于 Xray 中的 Golang 代码。

                                        代码结构

                                        Xray-core
                                         ├── app        // 应用模块
                                         │   ├── router // 路由
                                         ├── common     // 公用代码
                                        diff --git a/assets/guide.html-B3137Mcd.js b/assets/guide.html-CBLCKraa.js
                                        similarity index 99%
                                        rename from assets/guide.html-B3137Mcd.js
                                        rename to assets/guide.html-CBLCKraa.js
                                        index 3990c61cf7..2769ef40c1 100644
                                        --- a/assets/guide.html-B3137Mcd.js
                                        +++ b/assets/guide.html-CBLCKraa.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as t,o as c,c as d,a as n,b as e,d as o,e as r}from"./app-5SoadDYS.js";const h={},u=r('

                                        Development Standards

                                        Basic

                                        Version Control

                                        Project X's code is hosted on GitHub:

                                        ',4),p={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},g={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},b={href:"https://git-scm.com/",target:"_blank",rel:"noopener noreferrer"},y=e("h3",{id:"branch",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#branch"},[e("span",null,"Branch")])],-1),_=e("ul",null,[e("li",null,"The main branch is the backbone of this project."),e("li",null,"The main branch is also the release branch of this project."),e("li",null,"It is necessary to ensure that main can be compiled and used normally at any time."),e("li",null,"If you need to develop new features, please create a new branch for development. After development and sufficient testing, merge it back to the main branch."),e("li",null,"Please delete branches that have been merged into the main branch and are no longer necessary.")],-1),v=e("h3",{id:"release",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#release"},[e("span",null,"Release")])],-1),x=e("ul",null,[e("li",null,[o("Create two release channels: one for the beta version and another for the stable version. "),e("ul",null,[e("li",null,"The beta version, also known as the daily build, is mainly used for specific testing, experimentation, and instant feedback and improvement."),e("li",null,"The stable version, updated regularly (e.g. monthly), merges stable modifications and releases them.")])])],-1),w=e("h3",{id:"citing-other-projects",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#citing-other-projects"},[e("span",null,"Citing other projects")])],-1),k={href:"https://pkg.go.dev/search?q=golang.org%2Fx",target:"_blank",rel:"noopener noreferrer"},P=e("li",null,"If you need to reference other projects, please create an issue for discussion beforehand;",-1),X=e("li",null,[o("Other "),e("ul",null,[e("li",null,"Tools that do not violate the agreement of both parties and are helpful to the project can be used.")])],-1),C=e("h2",{id:"development-process",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#development-process"},[e("span",null,"Development Process")])],-1),I=e("h3",{id:"before-writing-code",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#before-writing-code"},[e("span",null,"Before Writing Code")])],-1),T={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},j=e("h3",{id:"modify-the-code",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#modify-the-code"},[e("span",null,"Modify the code")])],-1),G={href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"},R=e("li",null,[o("Run "),e("code",null,"go generate core/format.go"),o(" before each push;")],-1),B=e("li",null,[o("If you need to modify protobuf, such as adding new configuration items, please run: "),e("code",null,"go generate core/proto.go"),o(";")],-1),S=e("li",null,[o("It is recommended to pass the test before submitting a pull request: "),e("code",null,"go test ./..."),o(";")],-1),L=e("li",null,"It is recommended to have more than 70% code coverage for newly added code before submitting pull requests.",-1),q=e("li",null,[o("Other "),e("ul",null,[e("li",null,"Please pay attention to the readability of the code.")])],-1),F=r(`

                                        Pull Request

                                        • Before submitting a PR, please run git pull https://github.com/xray/xray-core.git to ensure that the merge can proceed smoothly;
                                        • One PR only does one thing. If there are fixes for multiple bugs, please submit a PR for each bug;
                                        • Due to Golang's special requirements (Package path), the PR process for Go projects is different from other projects. The recommended process is as follows:
                                          1. Fork this project first and create your own github.com/<your_name>/Xray-core.git repository;
                                          2. Clone your own Xray repository to your local machine: git clone https://github.com/<your_name>/Xray-core.git;
                                          3. Create a new branch based on the main branch, for example git branch issue24 main;
                                          4. Make changes on the new branch and commit the changes;
                                          5. Before pushing the modified branch to your own repository, switch to the main branch, and run git pull https://github.com/xray/xray-core.git to pull the latest remote code;
                                          6. If new remote code is obtained in the previous step, switch to the branch you created earlier and run git rebase main to perform branch merging. If there is a file conflict, you need to resolve the conflict;
                                          7. After the previous step is completed, you can push the branch you created to your own repository: git push -u origin your-branch
                                          8. Finally, send a PR from your new pushed branch in your own repository to the main branch of xtls/Xray-core;
                                          9. Please fully describe the purpose of this PR, including the problem solved, the new feature added, or the modifications made in the title and body of the PR;
                                          10. Please be patient and wait for the developer's response.

                                        Modifying Code

                                        Functional issue

                                        Please submit at least one test case to verify changes to existing functionality.

                                        Please provide the necessary test data to demonstrate performance issues in existing code or performance improvements in new code.

                                        New Feature

                                        • If the new feature does not affect the existing functionality, please provide a toggle (such as a flag) that can be turned on/off, and keep the new feature disabled by default.
                                        • For major new features (such as adding a new protocol), please submit an issue for discussion before development.

                                        Other

                                        It depends on the specific situation.

                                        Xray Coding Guidelines

                                        The following content is applicable to Golang code in Xray.

                                        Code Structure

                                        Xray-core
                                        +import{_ as l,r as t,o as c,c as d,a as n,b as e,d as o,e as r}from"./app-Bw2NG-QJ.js";const h={},u=r('

                                        Development Standards

                                        Basic

                                        Version Control

                                        Project X's code is hosted on GitHub:

                                        ',4),p={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},f={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},g={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},b={href:"https://git-scm.com/",target:"_blank",rel:"noopener noreferrer"},y=e("h3",{id:"branch",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#branch"},[e("span",null,"Branch")])],-1),_=e("ul",null,[e("li",null,"The main branch is the backbone of this project."),e("li",null,"The main branch is also the release branch of this project."),e("li",null,"It is necessary to ensure that main can be compiled and used normally at any time."),e("li",null,"If you need to develop new features, please create a new branch for development. After development and sufficient testing, merge it back to the main branch."),e("li",null,"Please delete branches that have been merged into the main branch and are no longer necessary.")],-1),v=e("h3",{id:"release",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#release"},[e("span",null,"Release")])],-1),x=e("ul",null,[e("li",null,[o("Create two release channels: one for the beta version and another for the stable version. "),e("ul",null,[e("li",null,"The beta version, also known as the daily build, is mainly used for specific testing, experimentation, and instant feedback and improvement."),e("li",null,"The stable version, updated regularly (e.g. monthly), merges stable modifications and releases them.")])])],-1),w=e("h3",{id:"citing-other-projects",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#citing-other-projects"},[e("span",null,"Citing other projects")])],-1),k={href:"https://pkg.go.dev/search?q=golang.org%2Fx",target:"_blank",rel:"noopener noreferrer"},P=e("li",null,"If you need to reference other projects, please create an issue for discussion beforehand;",-1),X=e("li",null,[o("Other "),e("ul",null,[e("li",null,"Tools that do not violate the agreement of both parties and are helpful to the project can be used.")])],-1),C=e("h2",{id:"development-process",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#development-process"},[e("span",null,"Development Process")])],-1),I=e("h3",{id:"before-writing-code",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#before-writing-code"},[e("span",null,"Before Writing Code")])],-1),T={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},j=e("h3",{id:"modify-the-code",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#modify-the-code"},[e("span",null,"Modify the code")])],-1),G={href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"},R=e("li",null,[o("Run "),e("code",null,"go generate core/format.go"),o(" before each push;")],-1),B=e("li",null,[o("If you need to modify protobuf, such as adding new configuration items, please run: "),e("code",null,"go generate core/proto.go"),o(";")],-1),S=e("li",null,[o("It is recommended to pass the test before submitting a pull request: "),e("code",null,"go test ./..."),o(";")],-1),L=e("li",null,"It is recommended to have more than 70% code coverage for newly added code before submitting pull requests.",-1),q=e("li",null,[o("Other "),e("ul",null,[e("li",null,"Please pay attention to the readability of the code.")])],-1),F=r(`

                                        Pull Request

                                        • Before submitting a PR, please run git pull https://github.com/xray/xray-core.git to ensure that the merge can proceed smoothly;
                                        • One PR only does one thing. If there are fixes for multiple bugs, please submit a PR for each bug;
                                        • Due to Golang's special requirements (Package path), the PR process for Go projects is different from other projects. The recommended process is as follows:
                                          1. Fork this project first and create your own github.com/<your_name>/Xray-core.git repository;
                                          2. Clone your own Xray repository to your local machine: git clone https://github.com/<your_name>/Xray-core.git;
                                          3. Create a new branch based on the main branch, for example git branch issue24 main;
                                          4. Make changes on the new branch and commit the changes;
                                          5. Before pushing the modified branch to your own repository, switch to the main branch, and run git pull https://github.com/xray/xray-core.git to pull the latest remote code;
                                          6. If new remote code is obtained in the previous step, switch to the branch you created earlier and run git rebase main to perform branch merging. If there is a file conflict, you need to resolve the conflict;
                                          7. After the previous step is completed, you can push the branch you created to your own repository: git push -u origin your-branch
                                          8. Finally, send a PR from your new pushed branch in your own repository to the main branch of xtls/Xray-core;
                                          9. Please fully describe the purpose of this PR, including the problem solved, the new feature added, or the modifications made in the title and body of the PR;
                                          10. Please be patient and wait for the developer's response.

                                        Modifying Code

                                        Functional issue

                                        Please submit at least one test case to verify changes to existing functionality.

                                        Please provide the necessary test data to demonstrate performance issues in existing code or performance improvements in new code.

                                        New Feature

                                        • If the new feature does not affect the existing functionality, please provide a toggle (such as a flag) that can be turned on/off, and keep the new feature disabled by default.
                                        • For major new features (such as adding a new protocol), please submit an issue for discussion before development.

                                        Other

                                        It depends on the specific situation.

                                        Xray Coding Guidelines

                                        The following content is applicable to Golang code in Xray.

                                        Code Structure

                                        Xray-core
                                         ├── app        // Application module
                                         │   ├── router // Router
                                         ├── common     // Common code
                                        diff --git a/assets/guide.html-B4lgRyoL.js b/assets/guide.html-DIzxSc4p.js
                                        similarity index 99%
                                        rename from assets/guide.html-B4lgRyoL.js
                                        rename to assets/guide.html-DIzxSc4p.js
                                        index cbda7e73cd..6cab7ec7f1 100644
                                        --- a/assets/guide.html-B4lgRyoL.js
                                        +++ b/assets/guide.html-DIzxSc4p.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as t,r as o,o as c,c as d,a as n,b as e,d as l,e as i}from"./app-5SoadDYS.js";const h={},u=i('

                                        开发规范

                                        基本

                                        版本控制

                                        Project X 的代码被托管在 github 上:

                                        ',4),p={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},_={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},g={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},m={href:"https://git-scm.com/",target:"_blank",rel:"noopener noreferrer"},f=e("h3",{id:"分支-branch",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#分支-branch"},[e("span",null,"分支(Branch)")])],-1),x=e("ul",null,[e("li",null,"本项目的主干分支为 main,"),e("li",null,"本项目的发布主分支同为 main,"),e("li",null,"需要确保 main 在任一时刻都是可编译,且可正常使用的。"),e("li",null,"如果需要开发新的功能,请新建分支进行开发,在开发完成并且经过充分测试后,合并回主干分支。"),e("li",null,"已经合并入主干且没有必要存在的分支,请删除。")],-1),v=e("h3",{id:"发布-release",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#发布-release"},[e("span",null,"发布(Release)")])],-1),X=e("ul",null,[e("li",null,[l("建立尝鲜版本和稳定版本两个发布通道 "),e("ul",null,[e("li",null,"尝鲜版本,可以为 daily build,主要用于特定情况的测试,尝鲜和获得即时反馈和再改进。"),e("li",null,"稳定版本,为定时更新(比如月更),合并稳定的修改并发布。")])])],-1),y=e("h3",{id:"引用其它项目",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#引用其它项目"},[e("span",null,"引用其它项目")])],-1),k={href:"https://pkg.go.dev/search?limit=25&m=package&q=golang.org%2Fx",target:"_blank",rel:"noopener noreferrer"},P=e("li",null,"如需引用其它项目,请事先创建 issue 讨论;",-1),T=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"不违反双方的协议,且对项目有帮助的工具,都可以使用。")])],-1),B=e("h2",{id:"开发流程",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发流程"},[e("span",null,"开发流程")])],-1),L=e("h3",{id:"写代码之前",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#写代码之前"},[e("span",null,"写代码之前")])],-1),E={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},G=e("h3",{id:"修改代码",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#修改代码"},[e("span",null,"修改代码")])],-1),R={href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"},S=e("li",null,[l("每一次 push 之前,请运行:"),e("code",null,"go generate core/format.go"),l(";")],-1),q=e("li",null,[l("如果需要修改 protobuf,例如增加新配置项,请运行:"),e("code",null,"go generate core/proto.go"),l(";")],-1),A=e("li",null,[l("提交 pull request 之前,建议测试通过:"),e("code",null,"go test ./..."),l(";")],-1),F=e("li",null,"提交 pull request 之前,建议新增代码有超过 70% 的代码覆盖率(code coverage);",-1),I=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"请注意代码的可读性。")])],-1),w=i(`

                                        Pull Request

                                        • 提交 PR 之前,请先运行 git pull https://github.com/XTLS/Xray-core.git 以确保 merge 可顺利进行;
                                        • 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR;
                                        • 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同,建议流程如下:
                                          1. 先 Fork 本项目,创建你自己的 github.com/<your_name>/Xray-core.git 仓库;
                                          2. 克隆你自己的 Xray 仓库到本地:git clone https://github.com/<your_name>/Xray-core.git
                                          3. 基于 main 分支创建新的分支,例如 git branch issue24 main
                                          4. 在新创建的分支上作修改并提交修改(commit);
                                          5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 main 分支,运行 git pull https://github.com/XTLS/Xray-core.git 拉取最新的远端代码;
                                          6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 git rebase main 执行分支合并操作。如遇到文件冲突,则需要解决冲突;
                                          7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:git push -u origin your-branch
                                          8. 最后,把自己仓库的新推送的分支往 XTLS/Xray-coremain 分支发 PR 即可;
                                          9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等;
                                          10. 耐心等待开发者的回应。

                                        对代码的修改

                                        功能性问题

                                        请提交至少一个测试用例(Test Case)来验证对现有功能的改动。

                                        性能相关

                                        请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。

                                        新功能

                                        • 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态;
                                        • 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。

                                        其它

                                        视具体情况而定。

                                        Xray 编码规范

                                        以下内容适用于 Xray 中的 Golang 代码。

                                        代码结构

                                        Xray-core
                                        +import{_ as t,r as o,o as c,c as d,a as n,b as e,d as l,e as i}from"./app-Bw2NG-QJ.js";const h={},u=i('

                                        开发规范

                                        基本

                                        版本控制

                                        Project X 的代码被托管在 github 上:

                                        ',4),p={href:"https://github.com/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},_={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},g={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},m={href:"https://git-scm.com/",target:"_blank",rel:"noopener noreferrer"},f=e("h3",{id:"分支-branch",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#分支-branch"},[e("span",null,"分支(Branch)")])],-1),x=e("ul",null,[e("li",null,"本项目的主干分支为 main,"),e("li",null,"本项目的发布主分支同为 main,"),e("li",null,"需要确保 main 在任一时刻都是可编译,且可正常使用的。"),e("li",null,"如果需要开发新的功能,请新建分支进行开发,在开发完成并且经过充分测试后,合并回主干分支。"),e("li",null,"已经合并入主干且没有必要存在的分支,请删除。")],-1),v=e("h3",{id:"发布-release",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#发布-release"},[e("span",null,"发布(Release)")])],-1),X=e("ul",null,[e("li",null,[l("建立尝鲜版本和稳定版本两个发布通道 "),e("ul",null,[e("li",null,"尝鲜版本,可以为 daily build,主要用于特定情况的测试,尝鲜和获得即时反馈和再改进。"),e("li",null,"稳定版本,为定时更新(比如月更),合并稳定的修改并发布。")])])],-1),y=e("h3",{id:"引用其它项目",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#引用其它项目"},[e("span",null,"引用其它项目")])],-1),k={href:"https://pkg.go.dev/search?limit=25&m=package&q=golang.org%2Fx",target:"_blank",rel:"noopener noreferrer"},P=e("li",null,"如需引用其它项目,请事先创建 issue 讨论;",-1),T=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"不违反双方的协议,且对项目有帮助的工具,都可以使用。")])],-1),B=e("h2",{id:"开发流程",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发流程"},[e("span",null,"开发流程")])],-1),L=e("h3",{id:"写代码之前",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#写代码之前"},[e("span",null,"写代码之前")])],-1),E={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},G=e("h3",{id:"修改代码",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#修改代码"},[e("span",null,"修改代码")])],-1),R={href:"https://golang.org/doc/effective_go.html",target:"_blank",rel:"noopener noreferrer"},S=e("li",null,[l("每一次 push 之前,请运行:"),e("code",null,"go generate core/format.go"),l(";")],-1),q=e("li",null,[l("如果需要修改 protobuf,例如增加新配置项,请运行:"),e("code",null,"go generate core/proto.go"),l(";")],-1),A=e("li",null,[l("提交 pull request 之前,建议测试通过:"),e("code",null,"go test ./..."),l(";")],-1),F=e("li",null,"提交 pull request 之前,建议新增代码有超过 70% 的代码覆盖率(code coverage);",-1),I=e("li",null,[l("其它 "),e("ul",null,[e("li",null,"请注意代码的可读性。")])],-1),w=i(`

                                        Pull Request

                                        • 提交 PR 之前,请先运行 git pull https://github.com/XTLS/Xray-core.git 以确保 merge 可顺利进行;
                                        • 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR;
                                        • 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同,建议流程如下:
                                          1. 先 Fork 本项目,创建你自己的 github.com/<your_name>/Xray-core.git 仓库;
                                          2. 克隆你自己的 Xray 仓库到本地:git clone https://github.com/<your_name>/Xray-core.git
                                          3. 基于 main 分支创建新的分支,例如 git branch issue24 main
                                          4. 在新创建的分支上作修改并提交修改(commit);
                                          5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 main 分支,运行 git pull https://github.com/XTLS/Xray-core.git 拉取最新的远端代码;
                                          6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 git rebase main 执行分支合并操作。如遇到文件冲突,则需要解决冲突;
                                          7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:git push -u origin your-branch
                                          8. 最后,把自己仓库的新推送的分支往 XTLS/Xray-coremain 分支发 PR 即可;
                                          9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等;
                                          10. 耐心等待开发者的回应。

                                        对代码的修改

                                        功能性问题

                                        请提交至少一个测试用例(Test Case)来验证对现有功能的改动。

                                        性能相关

                                        请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。

                                        新功能

                                        • 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态;
                                        • 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。

                                        其它

                                        视具体情况而定。

                                        Xray 编码规范

                                        以下内容适用于 Xray 中的 Golang 代码。

                                        代码结构

                                        Xray-core
                                         ├── app        // 应用模块
                                         │   ├── router // 路由
                                         ├── common     // 公用代码
                                        diff --git a/assets/h2.html-B8YU87YB.js b/assets/h2.html-BoytWKP0.js
                                        similarity index 98%
                                        rename from assets/h2.html-B8YU87YB.js
                                        rename to assets/h2.html-BoytWKP0.js
                                        index b9208d3363..d478531953 100644
                                        --- a/assets/h2.html-B8YU87YB.js
                                        +++ b/assets/h2.html-BoytWKP0.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as t,o as r,c as l,a as s,b as e,d as n,w as d,e as o}from"./app-5SoadDYS.js";const u={},h=o('

                                        HTTP/2

                                        The transmission mode based on HTTP/2 fully implements the HTTP/2 standard and can be relayed by other HTTP servers (such as Nginx).

                                        Based on the recommendations of HTTP/2, both the client and server must enable TLS to use this transmission mode normally.

                                        HTTP/2 has built-in multiplexing, so it is not recommended to enable mux.cool when using HTTP/2.

                                        Tip

                                        The current version of the transmission mode based on HTTP/2 does not require TLS configuration for inbound (server-side).

                                        This makes it possible to use a plaintext HTTP/2 protocol called h2c for communication between the gateway and Xray, with external gateway components handling the TLS layer conversation in special-purpose load-balancing deployment environments.

                                        Warning

                                        ⚠️ If you are using fallback, please note the following:

                                        • Please make sure that h2 is included in (x)tlsSettings.alpn, otherwise HTTP/2 cannot complete TLS handshake.
                                        • HTTP/2 cannot perform path-based routing, so it is recommended to use SNI-based routing.

                                        HttpObject

                                        ',7),m=e("code",null,"HttpObject",-1),k=e("code",null,"httpSettings",-1),b=o(`
                                        {
                                        +import{_ as p,r as t,o as r,c as l,a as s,b as e,d as n,w as d,e as o}from"./app-Bw2NG-QJ.js";const u={},h=o('

                                        HTTP/2

                                        The transmission mode based on HTTP/2 fully implements the HTTP/2 standard and can be relayed by other HTTP servers (such as Nginx).

                                        Based on the recommendations of HTTP/2, both the client and server must enable TLS to use this transmission mode normally.

                                        HTTP/2 has built-in multiplexing, so it is not recommended to enable mux.cool when using HTTP/2.

                                        Tip

                                        The current version of the transmission mode based on HTTP/2 does not require TLS configuration for inbound (server-side).

                                        This makes it possible to use a plaintext HTTP/2 protocol called h2c for communication between the gateway and Xray, with external gateway components handling the TLS layer conversation in special-purpose load-balancing deployment environments.

                                        Warning

                                        ⚠️ If you are using fallback, please note the following:

                                        • Please make sure that h2 is included in (x)tlsSettings.alpn, otherwise HTTP/2 cannot complete TLS handshake.
                                        • HTTP/2 cannot perform path-based routing, so it is recommended to use SNI-based routing.

                                        HttpObject

                                        ',7),m=e("code",null,"HttpObject",-1),k=e("code",null,"httpSettings",-1),b=o(`
                                        {
                                           "host": ["xray.com"],
                                           "path": "/random/path",
                                           "read_idle_timeout": 10,
                                        diff --git a/assets/h2.html-CVsBKDCJ.js b/assets/h2.html-DCbNjdYm.js
                                        similarity index 98%
                                        rename from assets/h2.html-CVsBKDCJ.js
                                        rename to assets/h2.html-DCbNjdYm.js
                                        index 184b76470c..f34feb76d8 100644
                                        --- a/assets/h2.html-CVsBKDCJ.js
                                        +++ b/assets/h2.html-DCbNjdYm.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as s,o as c,c as l,a as o,b as t,d as n,e as r}from"./app-5SoadDYS.js";const i={},u=r(`

                                        HTTP/2

                                        基于 HTTP/2 的传输方式。

                                        它完整按照 HTTP/2 标准实现,可以通过其它的 HTTP 服务器(如 Nginx)进行中转。

                                        由 HTTP/2 的建议,客户端和服务器必须同时开启 TLS 才可以正常使用这个传输方式。

                                        HTTP/2 内置多路复用,不建议使用 HTTP/2 时启用 mux.cool。

                                        提示

                                        当前版本的 HTTP/2 的传输方式并不强制要求入站服务端)有 TLS 配置. 这使得可以在特殊用途的分流部署环境中,由外部网关组件完成 TLS 层对话,Xray 作为后端应用,网关和 Xray 间使用称为 h2c 的明文 http/2 进行通讯。

                                        注意

                                        ⚠️ 如果你正在使用回落,请注意下列事项:

                                        • 请确认 (x)tlsSettings.alpn 中包含 h2,否则 HTTP/2 无法完成 TLS 握手。
                                        • HTTP/2 无法通过 Path 进行分流,建议使用 SNI 分流。

                                        HttpObject

                                        HttpObject 对应传输配置的 httpSettings 项。

                                        {
                                        +import{_ as p,r as s,o as c,c as l,a as o,b as t,d as n,e as r}from"./app-Bw2NG-QJ.js";const i={},u=r(`

                                        HTTP/2

                                        基于 HTTP/2 的传输方式。

                                        它完整按照 HTTP/2 标准实现,可以通过其它的 HTTP 服务器(如 Nginx)进行中转。

                                        由 HTTP/2 的建议,客户端和服务器必须同时开启 TLS 才可以正常使用这个传输方式。

                                        HTTP/2 内置多路复用,不建议使用 HTTP/2 时启用 mux.cool。

                                        提示

                                        当前版本的 HTTP/2 的传输方式并不强制要求入站服务端)有 TLS 配置. 这使得可以在特殊用途的分流部署环境中,由外部网关组件完成 TLS 层对话,Xray 作为后端应用,网关和 Xray 间使用称为 h2c 的明文 http/2 进行通讯。

                                        注意

                                        ⚠️ 如果你正在使用回落,请注意下列事项:

                                        • 请确认 (x)tlsSettings.alpn 中包含 h2,否则 HTTP/2 无法完成 TLS 握手。
                                        • HTTP/2 无法通过 Path 进行分流,建议使用 SNI 分流。

                                        HttpObject

                                        HttpObject 对应传输配置的 httpSettings 项。

                                        {
                                           "host": ["xray.com"],
                                           "path": "/random/path",
                                           "read_idle_timeout": 10,
                                        diff --git a/assets/h2.html-OyF7YRkr.js b/assets/h2.html-llZ-kVKl.js
                                        similarity index 99%
                                        rename from assets/h2.html-OyF7YRkr.js
                                        rename to assets/h2.html-llZ-kVKl.js
                                        index 3f4bc6ffa4..ac48fb41f2 100644
                                        --- a/assets/h2.html-OyF7YRkr.js
                                        +++ b/assets/h2.html-llZ-kVKl.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as o,o as c,c as l,a as s,b as t,d as n,e as r}from"./app-5SoadDYS.js";const i={},u=r(`

                                        HTTP/2

                                        Способ передачи данных на основе HTTP/2.

                                        Он полностью реализован в соответствии со стандартом HTTP/2 и может быть перенаправлен через другие HTTP-серверы (например, Nginx).

                                        В соответствии с рекомендациями HTTP/2, клиент и сервер должны одновременно включать TLS для нормальной работы этого способа передачи.

                                        HTTP/2 имеет встроенное мультиплексирование, не рекомендуется включать mux.cool при использовании HTTP/2.

                                        Подсказка

                                        Текущая версия способа передачи HTTP/2 не требует, чтобы входящее соединение (сервер) имело конфигурацию TLS. Это позволяет в среде развертывания с разделением трафика для специальных целей использовать внешний шлюз для обработки TLS-соединения, в то время как Xray будет использоваться в качестве серверного приложения, а связь между шлюзом и Xray будет осуществляться по незашифрованному протоколу http/2, который называется h2c.

                                        Внимание

                                        ⚠️ Если вы используете fallback, обратите внимание на следующие моменты:

                                        • Убедитесь, что (x)tlsSettings.alpn содержит h2, иначе HTTP/2 не сможет завершить TLS-рукопожатие.
                                        • HTTP/2 не может быть разделен по пути, рекомендуется использовать SNI-разделение.

                                        HttpObject

                                        HttpObject соответствует элементу httpSettings конфигурации передачи.

                                        {
                                        +import{_ as p,r as o,o as c,c as l,a as s,b as t,d as n,e as r}from"./app-Bw2NG-QJ.js";const i={},u=r(`

                                        HTTP/2

                                        Способ передачи данных на основе HTTP/2.

                                        Он полностью реализован в соответствии со стандартом HTTP/2 и может быть перенаправлен через другие HTTP-серверы (например, Nginx).

                                        В соответствии с рекомендациями HTTP/2, клиент и сервер должны одновременно включать TLS для нормальной работы этого способа передачи.

                                        HTTP/2 имеет встроенное мультиплексирование, не рекомендуется включать mux.cool при использовании HTTP/2.

                                        Подсказка

                                        Текущая версия способа передачи HTTP/2 не требует, чтобы входящее соединение (сервер) имело конфигурацию TLS. Это позволяет в среде развертывания с разделением трафика для специальных целей использовать внешний шлюз для обработки TLS-соединения, в то время как Xray будет использоваться в качестве серверного приложения, а связь между шлюзом и Xray будет осуществляться по незашифрованному протоколу http/2, который называется h2c.

                                        Внимание

                                        ⚠️ Если вы используете fallback, обратите внимание на следующие моменты:

                                        • Убедитесь, что (x)tlsSettings.alpn содержит h2, иначе HTTP/2 не сможет завершить TLS-рукопожатие.
                                        • HTTP/2 не может быть разделен по пути, рекомендуется использовать SNI-разделение.

                                        HttpObject

                                        HttpObject соответствует элементу httpSettings конфигурации передачи.

                                        {
                                           "host": ["xray.com"],
                                           "path": "/random/path",
                                           "read_idle_timeout": 10,
                                        diff --git a/assets/http.html-C1EqlRMw.js b/assets/http.html-BR_9tg5w.js
                                        similarity index 98%
                                        rename from assets/http.html-C1EqlRMw.js
                                        rename to assets/http.html-BR_9tg5w.js
                                        index 1a5b493089..9ecde87f05 100644
                                        --- a/assets/http.html-C1EqlRMw.js
                                        +++ b/assets/http.html-BR_9tg5w.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as a,o as e,c as t,a as o,e as p}from"./app-5SoadDYS.js";const c={},i=p(`

                                        HTTP

                                        Протокол HTTP.

                                        Предупреждение

                                        Протокол HTTP не обеспечивает шифрования передачи, что делает его непригодным для передачи по общедоступным сетям и более уязвимым для использования в качестве скомпрометированного хоста для атак.

                                        Подсказка

                                        HTTP может проксировать только протоколы TCP и не может обрабатывать протоколы на основе UDP.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as n,r as a,o as e,c as t,a as o,e as p}from"./app-Bw2NG-QJ.js";const c={},i=p(`

                                        HTTP

                                        Протокол HTTP.

                                        Предупреждение

                                        Протокол HTTP не обеспечивает шифрования передачи, что делает его непригодным для передачи по общедоступным сетям и более уязвимым для использования в качестве скомпрометированного хоста для атак.

                                        Подсказка

                                        HTTP может проксировать только протоколы TCP и не может обрабатывать протоколы на основе UDP.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "192.168.108.1",
                                        diff --git a/assets/http.html-cSNMwEku.js b/assets/http.html-B_cAur_J.js
                                        similarity index 99%
                                        rename from assets/http.html-cSNMwEku.js
                                        rename to assets/http.html-B_cAur_J.js
                                        index eb95752dcd..7b06185e41 100644
                                        --- a/assets/http.html-cSNMwEku.js
                                        +++ b/assets/http.html-B_cAur_J.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as a,o as i,c as u,a as s,b as e,d as n,w as t,e as p}from"./app-5SoadDYS.js";const r={},d=p(`

                                        HTTP

                                        Протокол HTTP.

                                        Предупреждение

                                        Протокол HTTP не обеспечивает шифрования передачи данных, поэтому он не подходит для передачи данных через общедоступные сети и более уязвим для использования в качестве ботнета.

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

                                        СОВЕТ 1

                                        http proxy может проксировать только протокол tcp, протоколы семейства udp не поддерживаются.

                                        СОВЕТ 2

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

                                        • export http_proxy=http://127.0.0.1:8080/ (замените адрес на адрес вашего настроенного входящего HTTP-прокси)
                                        • export https_proxy=$http_proxy

                                        InboundConfigurationObject

                                        {
                                        +import{_ as l,r as a,o as i,c as u,a as s,b as e,d as n,w as t,e as p}from"./app-Bw2NG-QJ.js";const r={},d=p(`

                                        HTTP

                                        Протокол HTTP.

                                        Предупреждение

                                        Протокол HTTP не обеспечивает шифрования передачи данных, поэтому он не подходит для передачи данных через общедоступные сети и более уязвим для использования в качестве ботнета.

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

                                        СОВЕТ 1

                                        http proxy может проксировать только протокол tcp, протоколы семейства udp не поддерживаются.

                                        СОВЕТ 2

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

                                        • export http_proxy=http://127.0.0.1:8080/ (замените адрес на адрес вашего настроенного входящего HTTP-прокси)
                                        • export https_proxy=$http_proxy

                                        InboundConfigurationObject

                                        {
                                           "timeout": 0,
                                           "accounts": [
                                             {
                                        diff --git a/assets/http.html-n_9GtPPz.js b/assets/http.html-Bp5JIQRB.js
                                        similarity index 98%
                                        rename from assets/http.html-n_9GtPPz.js
                                        rename to assets/http.html-Bp5JIQRB.js
                                        index 45e45e87d6..886f8bb53b 100644
                                        --- a/assets/http.html-n_9GtPPz.js
                                        +++ b/assets/http.html-Bp5JIQRB.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as t,o as i,c as u,a as s,b as e,d as n,w as a,e as p}from"./app-5SoadDYS.js";const r={},d=p(`

                                        HTTP

                                        HTTP 协议。

                                        警告

                                        http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。

                                        http 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。

                                        TIP 1

                                        http proxy 只能代理 tcp 协议,udp 系的协议均不能通过。

                                        TIP 2

                                        在 Linux 中使用以下环境变量即可在当前 session 使用全局 HTTP 代理(很多软件都支持这一设置,也有不支持的)。

                                        • export http_proxy=http://127.0.0.1:8080/ (地址须改成你配置的 HTTP 入站代理地址)
                                        • export https_proxy=$http_proxy

                                        InboundConfigurationObject

                                        {
                                        +import{_ as l,r as t,o as i,c as u,a as s,b as e,d as n,w as a,e as p}from"./app-Bw2NG-QJ.js";const r={},d=p(`

                                        HTTP

                                        HTTP 协议。

                                        警告

                                        http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。

                                        http 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。

                                        TIP 1

                                        http proxy 只能代理 tcp 协议,udp 系的协议均不能通过。

                                        TIP 2

                                        在 Linux 中使用以下环境变量即可在当前 session 使用全局 HTTP 代理(很多软件都支持这一设置,也有不支持的)。

                                        • export http_proxy=http://127.0.0.1:8080/ (地址须改成你配置的 HTTP 入站代理地址)
                                        • export https_proxy=$http_proxy

                                        InboundConfigurationObject

                                        {
                                           "timeout": 0,
                                           "accounts": [
                                             {
                                        diff --git a/assets/http.html-_MHU72Uy.js b/assets/http.html-DXeEJWXm.js
                                        similarity index 98%
                                        rename from assets/http.html-_MHU72Uy.js
                                        rename to assets/http.html-DXeEJWXm.js
                                        index 2e2d294e3b..8018c9bc79 100644
                                        --- a/assets/http.html-_MHU72Uy.js
                                        +++ b/assets/http.html-DXeEJWXm.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as a,o as e,c as t,a as o,e as p}from"./app-5SoadDYS.js";const c={},i=p(`

                                        HTTP

                                        HTTP 协议。

                                        警告

                                        http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。

                                        提示

                                        http 只能代理 tcp 协议,udp 系的协议均不能通过。

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as n,r as a,o as e,c as t,a as o,e as p}from"./app-Bw2NG-QJ.js";const c={},i=p(`

                                        HTTP

                                        HTTP 协议。

                                        警告

                                        http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。

                                        提示

                                        http 只能代理 tcp 协议,udp 系的协议均不能通过。

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "192.168.108.1",
                                        diff --git a/assets/http.html-DQMd16Bw.js b/assets/http.html-uCWbp3V-.js
                                        similarity index 98%
                                        rename from assets/http.html-DQMd16Bw.js
                                        rename to assets/http.html-uCWbp3V-.js
                                        index 42dd26be38..7b5058f5a6 100644
                                        --- a/assets/http.html-DQMd16Bw.js
                                        +++ b/assets/http.html-uCWbp3V-.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as t,o as r,c as l,a as o,b as e,d as n,w as a,e as c}from"./app-5SoadDYS.js";const u={},d=c(`

                                        HTTP

                                        HTTP protocol.

                                        Warning

                                        The HTTP protocol does not provide encryption for transmission and is not suitable for transmission over public networks, as it can easily be used as a target for attacks.

                                        The more meaningful use of http inbound is to listen in a local network or on the local machine to provide local services for other programs.

                                        TIP 1

                                        http proxy can only proxy the TCP protocol and cannot handle protocols based on UDP.

                                        TIP 2

                                        In Linux, you can use the following environment variables to enable global HTTP proxy for the current session (many software support this setting, but some may not).

                                        • export http_proxy=http://127.0.0.1:8080/ (Change the address to the configured inbound HTTP proxy address)
                                        • export https_proxy=$http_proxy
                                        • :::

                                        InboundConfigurationObject

                                        {
                                        +import{_ as p,r as t,o as r,c as l,a as o,b as e,d as n,w as a,e as c}from"./app-Bw2NG-QJ.js";const u={},d=c(`

                                        HTTP

                                        HTTP protocol.

                                        Warning

                                        The HTTP protocol does not provide encryption for transmission and is not suitable for transmission over public networks, as it can easily be used as a target for attacks.

                                        The more meaningful use of http inbound is to listen in a local network or on the local machine to provide local services for other programs.

                                        TIP 1

                                        http proxy can only proxy the TCP protocol and cannot handle protocols based on UDP.

                                        TIP 2

                                        In Linux, you can use the following environment variables to enable global HTTP proxy for the current session (many software support this setting, but some may not).

                                        • export http_proxy=http://127.0.0.1:8080/ (Change the address to the configured inbound HTTP proxy address)
                                        • export https_proxy=$http_proxy
                                        • :::

                                        InboundConfigurationObject

                                        {
                                           "timeout": 0,
                                           "accounts": [
                                             {
                                        diff --git a/assets/http.html-DpWvFZW_.js b/assets/http.html-z9-pCapv.js
                                        similarity index 98%
                                        rename from assets/http.html-DpWvFZW_.js
                                        rename to assets/http.html-z9-pCapv.js
                                        index 927893f34c..e01ab1c105 100644
                                        --- a/assets/http.html-DpWvFZW_.js
                                        +++ b/assets/http.html-z9-pCapv.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as a,o as e,c as t,a as o,e as p}from"./app-5SoadDYS.js";const r={},c=p(`

                                        HTTP

                                        HTTP is a protocol that is used for communication over the internet. Please note that HTTP does not provide encryption for data transmission and is not suitable for transmitting sensitive information over public networks, as it can be easily targeted for attacks.

                                        Danger

                                        The HTTP protocol does not provide encryption for transmission, making it unsuitable for transmitting over public networks and more susceptible to being used as a compromised host for attacks.

                                        Tip

                                        HTTP can only proxy TCP protocols, and cannot handle UDP-based protocols.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as n,r as a,o as e,c as t,a as o,e as p}from"./app-Bw2NG-QJ.js";const r={},c=p(`

                                        HTTP

                                        HTTP is a protocol that is used for communication over the internet. Please note that HTTP does not provide encryption for data transmission and is not suitable for transmitting sensitive information over public networks, as it can be easily targeted for attacks.

                                        Danger

                                        The HTTP protocol does not provide encryption for transmission, making it unsuitable for transmitting over public networks and more susceptible to being used as a compromised host for attacks.

                                        Tip

                                        HTTP can only proxy TCP protocols, and cannot handle UDP-based protocols.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "192.168.108.1",
                                        diff --git a/assets/httpupgrade.html-DOscHx-c.js b/assets/httpupgrade.html-BraFT-Ya.js
                                        similarity index 98%
                                        rename from assets/httpupgrade.html-DOscHx-c.js
                                        rename to assets/httpupgrade.html-BraFT-Ya.js
                                        index bb413afa07..e26d715ced 100644
                                        --- a/assets/httpupgrade.html-DOscHx-c.js
                                        +++ b/assets/httpupgrade.html-BraFT-Ya.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as o,o as c,c as d,a as n,b as t,d as e,e as s}from"./app-5SoadDYS.js";const i={},l=s(`

                                        HTTPUpgrade

                                        A WebSocket-like transport protocol implementing the HTTP/1.1 upgrade and response, allowing it to be reverse proxied by web servers or CDNs just like WebSocket, but without the need to implement the remaining portions of the WebSocket protocol, yielding better performance.

                                        Standalone usage is not recommended, but rather in conjunction with other security protocols like TLS.

                                        HttpUpgradeObject

                                        The HttpUpgradeObject corresponds to the httpupgradeSettings section under transport configurations.

                                        {
                                        +import{_ as p,r as o,o as c,c as d,a as n,b as t,d as e,e as s}from"./app-Bw2NG-QJ.js";const i={},l=s(`

                                        HTTPUpgrade

                                        A WebSocket-like transport protocol implementing the HTTP/1.1 upgrade and response, allowing it to be reverse proxied by web servers or CDNs just like WebSocket, but without the need to implement the remaining portions of the WebSocket protocol, yielding better performance.

                                        Standalone usage is not recommended, but rather in conjunction with other security protocols like TLS.

                                        HttpUpgradeObject

                                        The HttpUpgradeObject corresponds to the httpupgradeSettings section under transport configurations.

                                        {
                                           "acceptProxyProtocol": false,
                                           "path": "/",
                                           "host": "xray.com",
                                        diff --git a/assets/httpupgrade.html-Fq7D8MW3.js b/assets/httpupgrade.html-CEqqB19n.js
                                        similarity index 98%
                                        rename from assets/httpupgrade.html-Fq7D8MW3.js
                                        rename to assets/httpupgrade.html-CEqqB19n.js
                                        index b6d837ca38..47ecc430d5 100644
                                        --- a/assets/httpupgrade.html-Fq7D8MW3.js
                                        +++ b/assets/httpupgrade.html-CEqqB19n.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as t,o as r,c as d,a,b as o,d as e,e as s}from"./app-5SoadDYS.js";const l={},u=s(`

                                        HTTPUpgrade

                                        一个实现了类似于 WebSocket 进行 HTTP 1.1 升级请求和响应的协议,这使得它可以像 WebSocket 一样可以被CDN或者Nginx进行反代,但无需实现 WebSocket 协议的其他部分,所以具有更高的效率。 其设计不推荐单独使用,而是和TLS等安全协议一起工作。

                                        HttpUpgradeObject

                                        HttpUpgradeObject 对应传输配置的 httpupgradeSettings 项。

                                        {
                                        +import{_ as c,r as t,o as r,c as d,a,b as o,d as e,e as s}from"./app-Bw2NG-QJ.js";const l={},u=s(`

                                        HTTPUpgrade

                                        一个实现了类似于 WebSocket 进行 HTTP 1.1 升级请求和响应的协议,这使得它可以像 WebSocket 一样可以被CDN或者Nginx进行反代,但无需实现 WebSocket 协议的其他部分,所以具有更高的效率。 其设计不推荐单独使用,而是和TLS等安全协议一起工作。

                                        HttpUpgradeObject

                                        HttpUpgradeObject 对应传输配置的 httpupgradeSettings 项。

                                        {
                                           "acceptProxyProtocol": false,
                                           "path": "/",
                                           "host": "xray.com",
                                        diff --git a/assets/httpupgrade.html-8iiyF6S8.js b/assets/httpupgrade.html-D3FZSi1K.js
                                        similarity index 98%
                                        rename from assets/httpupgrade.html-8iiyF6S8.js
                                        rename to assets/httpupgrade.html-D3FZSi1K.js
                                        index a7572c36b7..fcd22b3d1f 100644
                                        --- a/assets/httpupgrade.html-8iiyF6S8.js
                                        +++ b/assets/httpupgrade.html-D3FZSi1K.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as o,o as r,c as d,a,b as e,d as t,e as n}from"./app-5SoadDYS.js";const l={},u=n(`

                                        HTTPUpgrade

                                        Это протокол, реализующий запросы и ответы на обновление HTTP 1.1, подобно WebSocket. Это позволяет ему, как и WebSocket, быть проксируемым CDN или Nginx, но без необходимости реализации других частей протокола WebSocket, что делает его более эффективным.

                                        Его дизайн не рекомендуется для самостоятельного использования, а лучше всего работает в сочетании с TLS.

                                        HttpUpgradeObject

                                        HttpUpgradeObject соответствует пункту httpupgradeSettings в настройках передачи.

                                        {
                                        +import{_ as c,r as o,o as r,c as d,a,b as e,d as t,e as n}from"./app-Bw2NG-QJ.js";const l={},u=n(`

                                        HTTPUpgrade

                                        Это протокол, реализующий запросы и ответы на обновление HTTP 1.1, подобно WebSocket. Это позволяет ему, как и WebSocket, быть проксируемым CDN или Nginx, но без необходимости реализации других частей протокола WebSocket, что делает его более эффективным.

                                        Его дизайн не рекомендуется для самостоятельного использования, а лучше всего работает в сочетании с TLS.

                                        HttpUpgradeObject

                                        HttpUpgradeObject соответствует пункту httpupgradeSettings в настройках передачи.

                                        {
                                           "acceptProxyProtocol": false,
                                           "path": "/",
                                           "host": "xray.com",
                                        diff --git a/assets/inbound.html-BPtpNn0q.js b/assets/inbound.html-BZUQiKQt.js
                                        similarity index 99%
                                        rename from assets/inbound.html-BPtpNn0q.js
                                        rename to assets/inbound.html-BZUQiKQt.js
                                        index 1108e5fc74..8871e49161 100644
                                        --- a/assets/inbound.html-BPtpNn0q.js
                                        +++ b/assets/inbound.html-BZUQiKQt.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as t,o as d,c as u,a as o,b as e,d as n,w as c,e as s}from"./app-5SoadDYS.js";const h={},b=e("h1",{id:"inbound-proxy",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#inbound-proxy"},[e("span",null,"Inbound Proxy")])],-1),m=s(`

                                        InboundObject

                                        The InboundObject corresponds to a subelement of the inbounds item in the configuration file.

                                        {
                                        +import{_ as l,r as t,o as d,c as u,a as o,b as e,d as n,w as c,e as s}from"./app-Bw2NG-QJ.js";const h={},b=e("h1",{id:"inbound-proxy",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#inbound-proxy"},[e("span",null,"Inbound Proxy")])],-1),m=s(`

                                        InboundObject

                                        The InboundObject corresponds to a subelement of the inbounds item in the configuration file.

                                        {
                                           "inbounds": [
                                             {
                                               "listen": "127.0.0.1",
                                        diff --git a/assets/inbound.html-U-YczWsT.js b/assets/inbound.html-CdeJ4snV.js
                                        similarity index 99%
                                        rename from assets/inbound.html-U-YczWsT.js
                                        rename to assets/inbound.html-CdeJ4snV.js
                                        index befa9ec4bc..cfee324e27 100644
                                        --- a/assets/inbound.html-U-YczWsT.js
                                        +++ b/assets/inbound.html-CdeJ4snV.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as e,o as d,c as r,a as o,b as n,d as s,w as c,e as a}from"./app-5SoadDYS.js";const k={},q=n("h1",{id:"入站代理",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#入站代理"},[n("span",null,"入站代理")])],-1),b=a(`

                                        InboundObject

                                        InboundObject 对应配置文件中 inbounds 项的一个子元素。

                                        {
                                        +import{_ as i,r as e,o as d,c as r,a as o,b as n,d as s,w as c,e as a}from"./app-Bw2NG-QJ.js";const k={},q=n("h1",{id:"入站代理",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#入站代理"},[n("span",null,"入站代理")])],-1),b=a(`

                                        InboundObject

                                        InboundObject 对应配置文件中 inbounds 项的一个子元素。

                                        {
                                           "inbounds": [
                                             {
                                               "listen": "127.0.0.1",
                                        diff --git a/assets/inbound.html-xQYNwVL-.js b/assets/inbound.html-CqfgrN_A.js
                                        similarity index 99%
                                        rename from assets/inbound.html-xQYNwVL-.js
                                        rename to assets/inbound.html-CqfgrN_A.js
                                        index 0564e9bcb3..17e2883f9a 100644
                                        --- a/assets/inbound.html-xQYNwVL-.js
                                        +++ b/assets/inbound.html-CqfgrN_A.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as e,o as d,c as r,a as o,b as n,d as s,w as c,e as a}from"./app-5SoadDYS.js";const b={},k=n("h1",{id:"входящие-подключения",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#входящие-подключения"},[n("span",null,"Входящие подключения")])],-1),q=a(`

                                        InboundObject

                                        InboundObject соответствует дочернему элементу поля inbounds в конфигурационном файле.

                                        {
                                        +import{_ as i,r as e,o as d,c as r,a as o,b as n,d as s,w as c,e as a}from"./app-Bw2NG-QJ.js";const b={},k=n("h1",{id:"входящие-подключения",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#входящие-подключения"},[n("span",null,"Входящие подключения")])],-1),q=a(`

                                        InboundObject

                                        InboundObject соответствует дочернему элементу поля inbounds в конфигурационном файле.

                                        {
                                           "inbounds": [
                                             {
                                               "listen": "127.0.0.1",
                                        diff --git a/assets/index-01f381cb-fgk8rzsW.js b/assets/index-01f381cb-DWGV-_zg.js
                                        similarity index 96%
                                        rename from assets/index-01f381cb-fgk8rzsW.js
                                        rename to assets/index-01f381cb-DWGV-_zg.js
                                        index 6d61d1fc4d..26481da4a1 100644
                                        --- a/assets/index-01f381cb-fgk8rzsW.js
                                        +++ b/assets/index-01f381cb-DWGV-_zg.js
                                        @@ -1 +1 @@
                                        -import{q as N,G as A}from"./graph-D2qW7eTj.js";import{m as $,l as q}from"./layout-BlaWeSu5.js";import{c as H}from"./clone-D0wOyyCk.js";import{i as V,u as U,s as W,a as _,b as z,g as D,p as O,c as K,d as Q,e as Y,f as Z,h as J,j as p}from"./edges-066a5561-BnmFWp88.js";import{l as s,c as T,q as S,h as L}from"./mermaid.core-CArNAncI.js";import{c as I}from"./createText-ca0c5216-X7RVUogw.js";function m(e){var t={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:tt(e),edges:et(e)};return N(e.graph())||(t.value=H(e.graph())),t}function tt(e){return $(e.nodes(),function(t){var n=e.node(t),r=e.parent(t),i={v:t};return N(n)||(i.value=n),N(r)||(i.parent=r),i})}function et(e){return $(e.edges(),function(t){var n=e.edge(t),r={v:t.v,w:t.w};return N(t.name)||(r.name=t.name),N(n)||(r.value=n),r})}let l={},g={},R={};const nt=()=>{g={},R={},l={}},B=(e,t)=>(s.trace("In isDescendant",t," ",e," = ",g[t].includes(e)),!!g[t].includes(e)),it=(e,t)=>(s.info("Descendants of ",t," is ",g[t]),s.info("Edge is ",e),e.v===t||e.w===t?!1:g[t]?g[t].includes(e.v)||B(e.v,t)||B(e.w,t)||g[t].includes(e.w):(s.debug("Tilt, ",t,",not in descendants"),!1)),P=(e,t,n,r)=>{s.warn("Copying children of ",e,"root",r,"data",t.node(e),r);const i=t.children(e)||[];e!==r&&i.push(e),s.warn("Copying (nodes) clusterId",e,"nodes",i),i.forEach(a=>{if(t.children(a).length>0)P(a,t,n,r);else{const d=t.node(a);s.info("cp ",a," to ",r," with parent ",e),n.setNode(a,d),r!==t.parent(a)&&(s.warn("Setting parent",a,t.parent(a)),n.setParent(a,t.parent(a))),e!==r&&a!==e?(s.debug("Setting parent",a,e),n.setParent(a,e)):(s.info("In copy ",e,"root",r,"data",t.node(e),r),s.debug("Not Setting parent for node=",a,"cluster!==rootId",e!==r,"node!==clusterId",a!==e));const u=t.edges(a);s.debug("Copying Edges",u),u.forEach(f=>{s.info("Edge",f);const h=t.edge(f.v,f.w,f.name);s.info("Edge data",h,r);try{it(f,r)?(s.info("Copying as ",f.v,f.w,h,f.name),n.setEdge(f.v,f.w,h,f.name),s.info("newGraph edges ",n.edges(),n.edge(n.edges()[0]))):s.info("Skipping copy of edge ",f.v,"-->",f.w," rootId: ",r," clusterId:",e)}catch(w){s.error(w)}})}s.debug("Removing node",a),t.removeNode(a)})},k=(e,t)=>{const n=t.children(e);let r=[...n];for(const i of n)R[i]=e,r=[...r,...k(i,t)];return r},C=(e,t)=>{s.trace("Searching",e);const n=t.children(e);if(s.trace("Searching children of id ",e,n),n.length<1)return s.trace("This is a valid node",e),e;for(const r of n){const i=C(r,t);if(i)return s.trace("Found replacement for",e," => ",i),i}},X=e=>!l[e]||!l[e].externalConnections?e:l[e]?l[e].id:e,st=(e,t)=>{if(!e||t>10){s.debug("Opting out, no graph ");return}else s.debug("Opting in, graph ");e.nodes().forEach(function(n){e.children(n).length>0&&(s.warn("Cluster identified",n," Replacement id in edges: ",C(n,e)),g[n]=k(n,e),l[n]={id:C(n,e),clusterData:e.node(n)})}),e.nodes().forEach(function(n){const r=e.children(n),i=e.edges();r.length>0?(s.debug("Cluster identified",n,g),i.forEach(a=>{if(a.v!==n&&a.w!==n){const d=B(a.v,n),u=B(a.w,n);d^u&&(s.warn("Edge: ",a," leaves cluster ",n),s.warn("Descendants of XXX ",n,": ",g[n]),l[n].externalConnections=!0)}})):s.debug("Not a cluster ",n,g)});for(let n of Object.keys(l)){const r=l[n].id,i=e.parent(r);i!==n&&l[i]&&!l[i].externalConnections&&(l[n].id=i)}e.edges().forEach(function(n){const r=e.edge(n);s.warn("Edge "+n.v+" -> "+n.w+": "+JSON.stringify(n)),s.warn("Edge "+n.v+" -> "+n.w+": "+JSON.stringify(e.edge(n)));let i=n.v,a=n.w;if(s.warn("Fix XXX",l,"ids:",n.v,n.w,"Translating: ",l[n.v]," --- ",l[n.w]),l[n.v]&&l[n.w]&&l[n.v]===l[n.w]){s.warn("Fixing and trixing link to self - removing XXX",n.v,n.w,n.name),s.warn("Fixing and trixing - removing XXX",n.v,n.w,n.name),i=X(n.v),a=X(n.w),e.removeEdge(n.v,n.w,n.name);const d=n.w+"---"+n.v;e.setNode(d,{domId:d,id:d,labelStyle:"",labelText:r.label,padding:0,shape:"labelRect",style:""});const u=structuredClone(r),f=structuredClone(r);u.label="",u.arrowTypeEnd="none",f.label="",u.fromCluster=n.v,f.toCluster=n.v,e.setEdge(i,d,u,n.name+"-cyclic-special"),e.setEdge(d,a,f,n.name+"-cyclic-special")}else if(l[n.v]||l[n.w]){if(s.warn("Fixing and trixing - removing XXX",n.v,n.w,n.name),i=X(n.v),a=X(n.w),e.removeEdge(n.v,n.w,n.name),i!==n.v){const d=e.parent(i);l[d].externalConnections=!0,r.fromCluster=n.v}if(a!==n.w){const d=e.parent(a);l[d].externalConnections=!0,r.toCluster=n.w}s.warn("Fix Replacing with XXX",i,a,n.name),e.setEdge(i,a,r,n.name)}}),s.warn("Adjusted Graph",m(e)),F(e,0),s.trace(l)},F=(e,t)=>{if(s.warn("extractor - ",t,m(e),e.children("D")),t>10){s.error("Bailing out");return}let n=e.nodes(),r=!1;for(const i of n){const a=e.children(i);r=r||a.length>0}if(!r){s.debug("Done, no node has children",e.nodes());return}s.debug("Nodes = ",n,t);for(const i of n)if(s.debug("Extracting node",i,l,l[i]&&!l[i].externalConnections,!e.parent(i),e.node(i),e.children("D")," Depth ",t),!l[i])s.debug("Not a cluster",i,t);else if(!l[i].externalConnections&&e.children(i)&&e.children(i).length>0){s.warn("Cluster without external connections, without a parent and with children",i,t);let d=e.graph().rankdir==="TB"?"LR":"TB";l[i]&&l[i].clusterData&&l[i].clusterData.dir&&(d=l[i].clusterData.dir,s.warn("Fixing dir",l[i].clusterData.dir,d));const u=new A({multigraph:!0,compound:!0}).setGraph({rankdir:d,nodesep:50,ranksep:50,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});s.warn("Old graph before copy",m(e)),P(i,e,u,i),e.setNode(i,{clusterNode:!0,id:i,clusterData:l[i].clusterData,labelText:l[i].labelText,graph:u}),s.warn("New graph after copy node: (",i,")",m(u)),s.debug("Old graph after copy",m(e))}else s.warn("Cluster ** ",i," **not meeting the criteria !externalConnections:",!l[i].externalConnections," no parent: ",!e.parent(i)," children ",e.children(i)&&e.children(i).length>0,e.children("D"),t),s.debug(l);n=e.nodes(),s.warn("New list of nodes",n);for(const i of n){const a=e.node(i);s.warn(" Now next level",i,a),a.clusterNode&&F(a.graph,t+1)}},G=(e,t)=>{if(t.length===0)return[];let n=Object.assign(t);return t.forEach(r=>{const i=e.children(r),a=G(e,i);n=[...n,...a]}),n},rt=e=>G(e,e.children()),at=(e,t)=>{s.info("Creating subgraph rect for ",t.id,t);const n=T(),r=e.insert("g").attr("class","cluster"+(t.class?" "+t.class:"")).attr("id",t.id),i=r.insert("rect",":first-child"),a=S(n.flowchart.htmlLabels),d=r.insert("g").attr("class","cluster-label"),u=t.labelType==="markdown"?I(d,t.labelText,{style:t.labelStyle,useHtmlLabels:a}):d.node().appendChild(J(t.labelText,t.labelStyle,void 0,!0));let f=u.getBBox();if(S(n.flowchart.htmlLabels)){const c=u.children[0],o=L(u);f=c.getBoundingClientRect(),o.attr("width",f.width),o.attr("height",f.height)}const h=0*t.padding,w=h/2,x=t.width<=f.width+h?f.width+h:t.width;t.width<=f.width+h?t.diff=(f.width-t.width)/2-t.padding/2:t.diff=-t.padding/2,s.trace("Data ",t,JSON.stringify(t)),i.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("x",t.x-x/2).attr("y",t.y-t.height/2-w).attr("width",x).attr("height",t.height+h);const{subGraphTitleTopMargin:v}=D(n);a?d.attr("transform",`translate(${t.x-f.width/2}, ${t.y-t.height/2+v})`):d.attr("transform",`translate(${t.x}, ${t.y-t.height/2+v})`);const y=i.node().getBBox();return t.width=y.width,t.height=y.height,t.intersect=function(c){return p(t,c)},r},ct=(e,t)=>{const n=e.insert("g").attr("class","note-cluster").attr("id",t.id),r=n.insert("rect",":first-child"),i=0*t.padding,a=i/2;r.attr("rx",t.rx).attr("ry",t.ry).attr("x",t.x-t.width/2-a).attr("y",t.y-t.height/2-a).attr("width",t.width+i).attr("height",t.height+i).attr("fill","none");const d=r.node().getBBox();return t.width=d.width,t.height=d.height,t.intersect=function(u){return p(t,u)},n},ot=(e,t)=>{const n=T(),r=e.insert("g").attr("class",t.classes).attr("id",t.id),i=r.insert("rect",":first-child"),a=r.insert("g").attr("class","cluster-label"),d=r.append("rect"),u=a.node().appendChild(J(t.labelText,t.labelStyle,void 0,!0));let f=u.getBBox();if(S(n.flowchart.htmlLabels)){const c=u.children[0],o=L(u);f=c.getBoundingClientRect(),o.attr("width",f.width),o.attr("height",f.height)}f=u.getBBox();const h=0*t.padding,w=h/2,x=t.width<=f.width+t.padding?f.width+t.padding:t.width;t.width<=f.width+t.padding?t.diff=(f.width+t.padding*0-t.width)/2:t.diff=-t.padding/2,i.attr("class","outer").attr("x",t.x-x/2-w).attr("y",t.y-t.height/2-w).attr("width",x+h).attr("height",t.height+h),d.attr("class","inner").attr("x",t.x-x/2-w).attr("y",t.y-t.height/2-w+f.height-1).attr("width",x+h).attr("height",t.height+h-f.height-3);const{subGraphTitleTopMargin:v}=D(n);a.attr("transform",`translate(${t.x-f.width/2}, ${t.y-t.height/2-t.padding/3+(S(n.flowchart.htmlLabels)?5:3)+v})`);const y=i.node().getBBox();return t.height=y.height,t.intersect=function(c){return p(t,c)},r},lt=(e,t)=>{const n=e.insert("g").attr("class",t.classes).attr("id",t.id),r=n.insert("rect",":first-child"),i=0*t.padding,a=i/2;r.attr("class","divider").attr("x",t.x-t.width/2-a).attr("y",t.y-t.height/2).attr("width",t.width+i).attr("height",t.height+i);const d=r.node().getBBox();return t.width=d.width,t.height=d.height,t.diff=-t.padding/2,t.intersect=function(u){return p(t,u)},n},ft={rect:at,roundedWithTitle:ot,noteGroup:ct,divider:lt};let j={};const dt=(e,t)=>{s.trace("Inserting cluster");const n=t.shape||"rect";j[t.id]=ft[n](e,t)},ut=()=>{j={}},M=async(e,t,n,r,i,a)=>{s.info("Graph in recursive render: XXX",m(t),i);const d=t.graph().rankdir;s.trace("Dir in recursive render - dir:",d);const u=e.insert("g").attr("class","root");t.nodes()?s.info("Recursive render XXX",t.nodes()):s.info("No nodes found for",t),t.edges().length>0&&s.trace("Recursive edges",t.edge(t.edges()[0]));const f=u.insert("g").attr("class","clusters"),h=u.insert("g").attr("class","edgePaths"),w=u.insert("g").attr("class","edgeLabels"),x=u.insert("g").attr("class","nodes");await Promise.all(t.nodes().map(async function(c){const o=t.node(c);if(i!==void 0){const b=JSON.parse(JSON.stringify(i.clusterData));s.info("Setting data for cluster XXX (",c,") ",b,i),t.setNode(i.id,b),t.parent(c)||(s.trace("Setting parent",c,i.id),t.setParent(c,i.id,b))}if(s.info("(Insert) Node XXX"+c+": "+JSON.stringify(t.node(c))),o&&o.clusterNode){s.info("Cluster identified",c,o.width,t.node(c));const b=await M(x,o.graph,n,r,t.node(c),a),E=b.elem;U(o,E),o.diff=b.diff||0,s.info("Node bounds (abc123)",c,o,o.width,o.x,o.y),W(E,o),s.warn("Recursive render complete ",E,o)}else t.children(c).length>0?(s.info("Cluster - the non recursive path XXX",c,o.id,o,t),s.info(C(o.id,t)),l[o.id]={id:C(o.id,t),node:o}):(s.info("Node - the non recursive path",c,o.id,o),await _(x,t.node(c),d))})),t.edges().forEach(function(c){const o=t.edge(c.v,c.w,c.name);s.info("Edge "+c.v+" -> "+c.w+": "+JSON.stringify(c)),s.info("Edge "+c.v+" -> "+c.w+": ",c," ",JSON.stringify(t.edge(c))),s.info("Fix",l,"ids:",c.v,c.w,"Translating: ",l[c.v],l[c.w]),z(w,o)}),t.edges().forEach(function(c){s.info("Edge "+c.v+" -> "+c.w+": "+JSON.stringify(c))}),s.info("#############################################"),s.info("###                Layout                 ###"),s.info("#############################################"),s.info(t),q(t),s.info("Graph after layout:",m(t));let v=0;const{subGraphTitleTotalMargin:y}=D(a);return rt(t).forEach(function(c){const o=t.node(c);s.info("Position "+c+": "+JSON.stringify(t.node(c))),s.info("Position "+c+": ("+o.x,","+o.y,") width: ",o.width," height: ",o.height),o&&o.clusterNode?(o.y+=y,O(o)):t.children(c).length>0?(o.height+=y,dt(f,o),l[o.id].node=o):(o.y+=y/2,O(o))}),t.edges().forEach(function(c){const o=t.edge(c);s.info("Edge "+c.v+" -> "+c.w+": "+JSON.stringify(o),o),o.points.forEach(E=>E.y+=y/2);const b=K(h,c,o,l,n,t,r);Q(o,b)}),t.nodes().forEach(function(c){const o=t.node(c);s.info(c,o.type,o.diff),o.type==="group"&&(v=o.diff)}),{elem:u,diff:v}},bt=async(e,t,n,r,i)=>{V(e,n,r,i),Y(),Z(),ut(),nt(),s.warn("Graph at first:",JSON.stringify(m(t))),st(t),s.warn("Graph after:",JSON.stringify(m(t)));const a=T();await M(e,t,r,i,void 0,a)};export{bt as r};
                                        +import{q as N,G as A}from"./graph-C-EgwjAv.js";import{m as $,l as q}from"./layout-DSxgfneE.js";import{c as H}from"./clone-BjoOJyl6.js";import{i as V,u as U,s as W,a as _,b as z,g as D,p as O,c as K,d as Q,e as Y,f as Z,h as J,j as p}from"./edges-066a5561-CIBMFaLO.js";import{l as s,c as T,q as S,h as L}from"./mermaid.core-Bq0kX0MS.js";import{c as I}from"./createText-ca0c5216-xyt9uAlz.js";function m(e){var t={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:tt(e),edges:et(e)};return N(e.graph())||(t.value=H(e.graph())),t}function tt(e){return $(e.nodes(),function(t){var n=e.node(t),r=e.parent(t),i={v:t};return N(n)||(i.value=n),N(r)||(i.parent=r),i})}function et(e){return $(e.edges(),function(t){var n=e.edge(t),r={v:t.v,w:t.w};return N(t.name)||(r.name=t.name),N(n)||(r.value=n),r})}let l={},g={},R={};const nt=()=>{g={},R={},l={}},B=(e,t)=>(s.trace("In isDescendant",t," ",e," = ",g[t].includes(e)),!!g[t].includes(e)),it=(e,t)=>(s.info("Descendants of ",t," is ",g[t]),s.info("Edge is ",e),e.v===t||e.w===t?!1:g[t]?g[t].includes(e.v)||B(e.v,t)||B(e.w,t)||g[t].includes(e.w):(s.debug("Tilt, ",t,",not in descendants"),!1)),P=(e,t,n,r)=>{s.warn("Copying children of ",e,"root",r,"data",t.node(e),r);const i=t.children(e)||[];e!==r&&i.push(e),s.warn("Copying (nodes) clusterId",e,"nodes",i),i.forEach(a=>{if(t.children(a).length>0)P(a,t,n,r);else{const d=t.node(a);s.info("cp ",a," to ",r," with parent ",e),n.setNode(a,d),r!==t.parent(a)&&(s.warn("Setting parent",a,t.parent(a)),n.setParent(a,t.parent(a))),e!==r&&a!==e?(s.debug("Setting parent",a,e),n.setParent(a,e)):(s.info("In copy ",e,"root",r,"data",t.node(e),r),s.debug("Not Setting parent for node=",a,"cluster!==rootId",e!==r,"node!==clusterId",a!==e));const u=t.edges(a);s.debug("Copying Edges",u),u.forEach(f=>{s.info("Edge",f);const h=t.edge(f.v,f.w,f.name);s.info("Edge data",h,r);try{it(f,r)?(s.info("Copying as ",f.v,f.w,h,f.name),n.setEdge(f.v,f.w,h,f.name),s.info("newGraph edges ",n.edges(),n.edge(n.edges()[0]))):s.info("Skipping copy of edge ",f.v,"-->",f.w," rootId: ",r," clusterId:",e)}catch(w){s.error(w)}})}s.debug("Removing node",a),t.removeNode(a)})},k=(e,t)=>{const n=t.children(e);let r=[...n];for(const i of n)R[i]=e,r=[...r,...k(i,t)];return r},C=(e,t)=>{s.trace("Searching",e);const n=t.children(e);if(s.trace("Searching children of id ",e,n),n.length<1)return s.trace("This is a valid node",e),e;for(const r of n){const i=C(r,t);if(i)return s.trace("Found replacement for",e," => ",i),i}},X=e=>!l[e]||!l[e].externalConnections?e:l[e]?l[e].id:e,st=(e,t)=>{if(!e||t>10){s.debug("Opting out, no graph ");return}else s.debug("Opting in, graph ");e.nodes().forEach(function(n){e.children(n).length>0&&(s.warn("Cluster identified",n," Replacement id in edges: ",C(n,e)),g[n]=k(n,e),l[n]={id:C(n,e),clusterData:e.node(n)})}),e.nodes().forEach(function(n){const r=e.children(n),i=e.edges();r.length>0?(s.debug("Cluster identified",n,g),i.forEach(a=>{if(a.v!==n&&a.w!==n){const d=B(a.v,n),u=B(a.w,n);d^u&&(s.warn("Edge: ",a," leaves cluster ",n),s.warn("Descendants of XXX ",n,": ",g[n]),l[n].externalConnections=!0)}})):s.debug("Not a cluster ",n,g)});for(let n of Object.keys(l)){const r=l[n].id,i=e.parent(r);i!==n&&l[i]&&!l[i].externalConnections&&(l[n].id=i)}e.edges().forEach(function(n){const r=e.edge(n);s.warn("Edge "+n.v+" -> "+n.w+": "+JSON.stringify(n)),s.warn("Edge "+n.v+" -> "+n.w+": "+JSON.stringify(e.edge(n)));let i=n.v,a=n.w;if(s.warn("Fix XXX",l,"ids:",n.v,n.w,"Translating: ",l[n.v]," --- ",l[n.w]),l[n.v]&&l[n.w]&&l[n.v]===l[n.w]){s.warn("Fixing and trixing link to self - removing XXX",n.v,n.w,n.name),s.warn("Fixing and trixing - removing XXX",n.v,n.w,n.name),i=X(n.v),a=X(n.w),e.removeEdge(n.v,n.w,n.name);const d=n.w+"---"+n.v;e.setNode(d,{domId:d,id:d,labelStyle:"",labelText:r.label,padding:0,shape:"labelRect",style:""});const u=structuredClone(r),f=structuredClone(r);u.label="",u.arrowTypeEnd="none",f.label="",u.fromCluster=n.v,f.toCluster=n.v,e.setEdge(i,d,u,n.name+"-cyclic-special"),e.setEdge(d,a,f,n.name+"-cyclic-special")}else if(l[n.v]||l[n.w]){if(s.warn("Fixing and trixing - removing XXX",n.v,n.w,n.name),i=X(n.v),a=X(n.w),e.removeEdge(n.v,n.w,n.name),i!==n.v){const d=e.parent(i);l[d].externalConnections=!0,r.fromCluster=n.v}if(a!==n.w){const d=e.parent(a);l[d].externalConnections=!0,r.toCluster=n.w}s.warn("Fix Replacing with XXX",i,a,n.name),e.setEdge(i,a,r,n.name)}}),s.warn("Adjusted Graph",m(e)),F(e,0),s.trace(l)},F=(e,t)=>{if(s.warn("extractor - ",t,m(e),e.children("D")),t>10){s.error("Bailing out");return}let n=e.nodes(),r=!1;for(const i of n){const a=e.children(i);r=r||a.length>0}if(!r){s.debug("Done, no node has children",e.nodes());return}s.debug("Nodes = ",n,t);for(const i of n)if(s.debug("Extracting node",i,l,l[i]&&!l[i].externalConnections,!e.parent(i),e.node(i),e.children("D")," Depth ",t),!l[i])s.debug("Not a cluster",i,t);else if(!l[i].externalConnections&&e.children(i)&&e.children(i).length>0){s.warn("Cluster without external connections, without a parent and with children",i,t);let d=e.graph().rankdir==="TB"?"LR":"TB";l[i]&&l[i].clusterData&&l[i].clusterData.dir&&(d=l[i].clusterData.dir,s.warn("Fixing dir",l[i].clusterData.dir,d));const u=new A({multigraph:!0,compound:!0}).setGraph({rankdir:d,nodesep:50,ranksep:50,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});s.warn("Old graph before copy",m(e)),P(i,e,u,i),e.setNode(i,{clusterNode:!0,id:i,clusterData:l[i].clusterData,labelText:l[i].labelText,graph:u}),s.warn("New graph after copy node: (",i,")",m(u)),s.debug("Old graph after copy",m(e))}else s.warn("Cluster ** ",i," **not meeting the criteria !externalConnections:",!l[i].externalConnections," no parent: ",!e.parent(i)," children ",e.children(i)&&e.children(i).length>0,e.children("D"),t),s.debug(l);n=e.nodes(),s.warn("New list of nodes",n);for(const i of n){const a=e.node(i);s.warn(" Now next level",i,a),a.clusterNode&&F(a.graph,t+1)}},G=(e,t)=>{if(t.length===0)return[];let n=Object.assign(t);return t.forEach(r=>{const i=e.children(r),a=G(e,i);n=[...n,...a]}),n},rt=e=>G(e,e.children()),at=(e,t)=>{s.info("Creating subgraph rect for ",t.id,t);const n=T(),r=e.insert("g").attr("class","cluster"+(t.class?" "+t.class:"")).attr("id",t.id),i=r.insert("rect",":first-child"),a=S(n.flowchart.htmlLabels),d=r.insert("g").attr("class","cluster-label"),u=t.labelType==="markdown"?I(d,t.labelText,{style:t.labelStyle,useHtmlLabels:a}):d.node().appendChild(J(t.labelText,t.labelStyle,void 0,!0));let f=u.getBBox();if(S(n.flowchart.htmlLabels)){const c=u.children[0],o=L(u);f=c.getBoundingClientRect(),o.attr("width",f.width),o.attr("height",f.height)}const h=0*t.padding,w=h/2,x=t.width<=f.width+h?f.width+h:t.width;t.width<=f.width+h?t.diff=(f.width-t.width)/2-t.padding/2:t.diff=-t.padding/2,s.trace("Data ",t,JSON.stringify(t)),i.attr("style",t.style).attr("rx",t.rx).attr("ry",t.ry).attr("x",t.x-x/2).attr("y",t.y-t.height/2-w).attr("width",x).attr("height",t.height+h);const{subGraphTitleTopMargin:v}=D(n);a?d.attr("transform",`translate(${t.x-f.width/2}, ${t.y-t.height/2+v})`):d.attr("transform",`translate(${t.x}, ${t.y-t.height/2+v})`);const y=i.node().getBBox();return t.width=y.width,t.height=y.height,t.intersect=function(c){return p(t,c)},r},ct=(e,t)=>{const n=e.insert("g").attr("class","note-cluster").attr("id",t.id),r=n.insert("rect",":first-child"),i=0*t.padding,a=i/2;r.attr("rx",t.rx).attr("ry",t.ry).attr("x",t.x-t.width/2-a).attr("y",t.y-t.height/2-a).attr("width",t.width+i).attr("height",t.height+i).attr("fill","none");const d=r.node().getBBox();return t.width=d.width,t.height=d.height,t.intersect=function(u){return p(t,u)},n},ot=(e,t)=>{const n=T(),r=e.insert("g").attr("class",t.classes).attr("id",t.id),i=r.insert("rect",":first-child"),a=r.insert("g").attr("class","cluster-label"),d=r.append("rect"),u=a.node().appendChild(J(t.labelText,t.labelStyle,void 0,!0));let f=u.getBBox();if(S(n.flowchart.htmlLabels)){const c=u.children[0],o=L(u);f=c.getBoundingClientRect(),o.attr("width",f.width),o.attr("height",f.height)}f=u.getBBox();const h=0*t.padding,w=h/2,x=t.width<=f.width+t.padding?f.width+t.padding:t.width;t.width<=f.width+t.padding?t.diff=(f.width+t.padding*0-t.width)/2:t.diff=-t.padding/2,i.attr("class","outer").attr("x",t.x-x/2-w).attr("y",t.y-t.height/2-w).attr("width",x+h).attr("height",t.height+h),d.attr("class","inner").attr("x",t.x-x/2-w).attr("y",t.y-t.height/2-w+f.height-1).attr("width",x+h).attr("height",t.height+h-f.height-3);const{subGraphTitleTopMargin:v}=D(n);a.attr("transform",`translate(${t.x-f.width/2}, ${t.y-t.height/2-t.padding/3+(S(n.flowchart.htmlLabels)?5:3)+v})`);const y=i.node().getBBox();return t.height=y.height,t.intersect=function(c){return p(t,c)},r},lt=(e,t)=>{const n=e.insert("g").attr("class",t.classes).attr("id",t.id),r=n.insert("rect",":first-child"),i=0*t.padding,a=i/2;r.attr("class","divider").attr("x",t.x-t.width/2-a).attr("y",t.y-t.height/2).attr("width",t.width+i).attr("height",t.height+i);const d=r.node().getBBox();return t.width=d.width,t.height=d.height,t.diff=-t.padding/2,t.intersect=function(u){return p(t,u)},n},ft={rect:at,roundedWithTitle:ot,noteGroup:ct,divider:lt};let j={};const dt=(e,t)=>{s.trace("Inserting cluster");const n=t.shape||"rect";j[t.id]=ft[n](e,t)},ut=()=>{j={}},M=async(e,t,n,r,i,a)=>{s.info("Graph in recursive render: XXX",m(t),i);const d=t.graph().rankdir;s.trace("Dir in recursive render - dir:",d);const u=e.insert("g").attr("class","root");t.nodes()?s.info("Recursive render XXX",t.nodes()):s.info("No nodes found for",t),t.edges().length>0&&s.trace("Recursive edges",t.edge(t.edges()[0]));const f=u.insert("g").attr("class","clusters"),h=u.insert("g").attr("class","edgePaths"),w=u.insert("g").attr("class","edgeLabels"),x=u.insert("g").attr("class","nodes");await Promise.all(t.nodes().map(async function(c){const o=t.node(c);if(i!==void 0){const b=JSON.parse(JSON.stringify(i.clusterData));s.info("Setting data for cluster XXX (",c,") ",b,i),t.setNode(i.id,b),t.parent(c)||(s.trace("Setting parent",c,i.id),t.setParent(c,i.id,b))}if(s.info("(Insert) Node XXX"+c+": "+JSON.stringify(t.node(c))),o&&o.clusterNode){s.info("Cluster identified",c,o.width,t.node(c));const b=await M(x,o.graph,n,r,t.node(c),a),E=b.elem;U(o,E),o.diff=b.diff||0,s.info("Node bounds (abc123)",c,o,o.width,o.x,o.y),W(E,o),s.warn("Recursive render complete ",E,o)}else t.children(c).length>0?(s.info("Cluster - the non recursive path XXX",c,o.id,o,t),s.info(C(o.id,t)),l[o.id]={id:C(o.id,t),node:o}):(s.info("Node - the non recursive path",c,o.id,o),await _(x,t.node(c),d))})),t.edges().forEach(function(c){const o=t.edge(c.v,c.w,c.name);s.info("Edge "+c.v+" -> "+c.w+": "+JSON.stringify(c)),s.info("Edge "+c.v+" -> "+c.w+": ",c," ",JSON.stringify(t.edge(c))),s.info("Fix",l,"ids:",c.v,c.w,"Translating: ",l[c.v],l[c.w]),z(w,o)}),t.edges().forEach(function(c){s.info("Edge "+c.v+" -> "+c.w+": "+JSON.stringify(c))}),s.info("#############################################"),s.info("###                Layout                 ###"),s.info("#############################################"),s.info(t),q(t),s.info("Graph after layout:",m(t));let v=0;const{subGraphTitleTotalMargin:y}=D(a);return rt(t).forEach(function(c){const o=t.node(c);s.info("Position "+c+": "+JSON.stringify(t.node(c))),s.info("Position "+c+": ("+o.x,","+o.y,") width: ",o.width," height: ",o.height),o&&o.clusterNode?(o.y+=y,O(o)):t.children(c).length>0?(o.height+=y,dt(f,o),l[o.id].node=o):(o.y+=y/2,O(o))}),t.edges().forEach(function(c){const o=t.edge(c);s.info("Edge "+c.v+" -> "+c.w+": "+JSON.stringify(o),o),o.points.forEach(E=>E.y+=y/2);const b=K(h,c,o,l,n,t,r);Q(o,b)}),t.nodes().forEach(function(c){const o=t.node(c);s.info(c,o.type,o.diff),o.type==="group"&&(v=o.diff)}),{elem:u,diff:v}},bt=async(e,t,n,r,i)=>{V(e,n,r,i),Y(),Z(),ut(),nt(),s.warn("Graph at first:",JSON.stringify(m(t))),st(t),s.warn("Graph after:",JSON.stringify(m(t)));const a=T();await M(e,t,r,i,void 0,a)};export{bt as r};
                                        diff --git a/assets/index.html-BB8VT9K-.js b/assets/index.html-B-Zn3LDM.js
                                        similarity index 97%
                                        rename from assets/index.html-BB8VT9K-.js
                                        rename to assets/index.html-B-Zn3LDM.js
                                        index 106acbf4be..d6a2852a1b 100644
                                        --- a/assets/index.html-BB8VT9K-.js
                                        +++ b/assets/index.html-B-Zn3LDM.js
                                        @@ -1 +1 @@
                                        -import{_ as s,r as c,o as u,c as d,a as l,b as t,d as e,w as o}from"./app-5SoadDYS.js";const h={},_=t("h1",{id:"小小白白话文",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#小小白白话文"},[t("span",null,"小小白白话文")])],-1),i=t("p",null,[t("strong",null,"这个章节是【从零开始】的基础课,新来的同学好好看好好学哦")],-1),p={class:"custom-container tip"},m=t("p",{class:"custom-container-title"},"提示",-1),f={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"};function v(x,k){const a=c("I18nTip"),r=c("ExternalLinkIcon"),n=c("RouterLink");return u(),d("div",null,[l(a),_,i,t("div",p,[m,t("p",null,[e("Made with ❤️ by "),t("a",f,[e("@ricuhkaen"),l(r)])])]),t("p",null,[l(n,{to:"/document/level-0/ch01-preface.html"},{default:o(()=>[e("【第 1 章】 前言罗嗦篇")]),_:1}),e(" - 机场还是自建?这是个问题")]),t("p",null,[l(n,{to:"/document/level-0/ch02-preparation.html"},{default:o(()=>[e("【第 2 章】 原料准备篇")]),_:1}),e(" - 工欲善其事,必先利其器")]),t("p",null,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:o(()=>[e("【第 3 章】 远程登录篇")]),_:1}),e(" - 一桥飞架南北,天堑变通途")]),t("p",null,[l(n,{to:"/document/level-0/ch04-security.html"},{default:o(()=>[e("【第 4 章】 安全防护篇")]),_:1}),e(" - 安全不注意,亲人两行泪")]),t("p",null,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:o(()=>[e("【第 5 章】 网站建设篇")]),_:1}),e(" - 秀出你的美")]),t("p",null,[l(n,{to:"/document/level-0/ch06-certificates.html"},{default:o(()=>[e("【第 6 章】 证书管理篇")]),_:1}),e(" - 领证的才是合法的")]),t("p",null,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:o(()=>[e("【第 7 章】 Xray 服务器篇")]),_:1}),e(" - 终于等到你")]),t("p",null,[l(n,{to:"/document/level-0/ch08-xray-clients.html"},{default:o(()=>[e("【第 8 章】 Xray 客户端篇")]),_:1}),e(" - 新的开始")]),t("p",null,[l(n,{to:"/document/level-0/ch09-appendix.html"},{default:o(()=>[e("【第 9 章】 附录")]),_:1}),e(" - 考点都在这里")])])}const y=s(h,[["render",v],["__file","index.html.vue"]]);export{y as default};
                                        +import{_ as s,r as c,o as u,c as d,a as l,b as t,d as e,w as o}from"./app-Bw2NG-QJ.js";const h={},_=t("h1",{id:"小小白白话文",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#小小白白话文"},[t("span",null,"小小白白话文")])],-1),i=t("p",null,[t("strong",null,"这个章节是【从零开始】的基础课,新来的同学好好看好好学哦")],-1),p={class:"custom-container tip"},m=t("p",{class:"custom-container-title"},"提示",-1),f={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"};function v(x,k){const a=c("I18nTip"),r=c("ExternalLinkIcon"),n=c("RouterLink");return u(),d("div",null,[l(a),_,i,t("div",p,[m,t("p",null,[e("Made with ❤️ by "),t("a",f,[e("@ricuhkaen"),l(r)])])]),t("p",null,[l(n,{to:"/document/level-0/ch01-preface.html"},{default:o(()=>[e("【第 1 章】 前言罗嗦篇")]),_:1}),e(" - 机场还是自建?这是个问题")]),t("p",null,[l(n,{to:"/document/level-0/ch02-preparation.html"},{default:o(()=>[e("【第 2 章】 原料准备篇")]),_:1}),e(" - 工欲善其事,必先利其器")]),t("p",null,[l(n,{to:"/document/level-0/ch03-ssh.html"},{default:o(()=>[e("【第 3 章】 远程登录篇")]),_:1}),e(" - 一桥飞架南北,天堑变通途")]),t("p",null,[l(n,{to:"/document/level-0/ch04-security.html"},{default:o(()=>[e("【第 4 章】 安全防护篇")]),_:1}),e(" - 安全不注意,亲人两行泪")]),t("p",null,[l(n,{to:"/document/level-0/ch05-webpage.html"},{default:o(()=>[e("【第 5 章】 网站建设篇")]),_:1}),e(" - 秀出你的美")]),t("p",null,[l(n,{to:"/document/level-0/ch06-certificates.html"},{default:o(()=>[e("【第 6 章】 证书管理篇")]),_:1}),e(" - 领证的才是合法的")]),t("p",null,[l(n,{to:"/document/level-0/ch07-xray-server.html"},{default:o(()=>[e("【第 7 章】 Xray 服务器篇")]),_:1}),e(" - 终于等到你")]),t("p",null,[l(n,{to:"/document/level-0/ch08-xray-clients.html"},{default:o(()=>[e("【第 8 章】 Xray 客户端篇")]),_:1}),e(" - 新的开始")]),t("p",null,[l(n,{to:"/document/level-0/ch09-appendix.html"},{default:o(()=>[e("【第 9 章】 附录")]),_:1}),e(" - 考点都在这里")])])}const y=s(h,[["render",v],["__file","index.html.vue"]]);export{y as default};
                                        diff --git a/assets/index.html-CuC5URKY.js b/assets/index.html-B3mfyWQt.js
                                        similarity index 98%
                                        rename from assets/index.html-CuC5URKY.js
                                        rename to assets/index.html-B3mfyWQt.js
                                        index 9ea5dedba8..17a8c26542 100644
                                        --- a/assets/index.html-CuC5URKY.js
                                        +++ b/assets/index.html-B3mfyWQt.js
                                        @@ -1 +1 @@
                                        -import{_ as l,r as i,o as h,c,a as n,b as t,w as a,d as e}from"./app-5SoadDYS.js";const u={},d=t("h1",{id:"advanced-documentation",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#advanced-documentation"},[t("span",null,"Advanced Documentation")])],-1),_=t("p",null,[t("strong",null,"This chapter contains experience sharing of using Xray at an advanced level. If you are already familiar with Xray, the experience shared here can help you unleash the full power of Xray.")],-1),p=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),m={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},g=t("p",null,"An Introduction to Transparent Proxies.",-1),f=t("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32",height:"32",alt:"a"},null,-1),y={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},b=t("p",null,"Complete tutorial on configuring transparent proxy (TProxy) based on Xray.",-1),v=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),x={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},T=t("p",null,"Xray-based TProxy Transparent Proxy (IPv4 and IPv6) Configuration Tutorial",-1),k=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),w={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},P=t("p",null,"Use Nginx_TLS tunnel on both ends to hide the fingerprint.",-1),I=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),X={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},L=t("p",null,"A new way of bypassing Xray traffic in transparent proxy implemented by iptables/nftables.",-1),S=t("img",{src:"https://avatars.githubusercontent.com/u/28607089?s=32",width:"32",height:"32",alt:"a"},null,-1),C={href:"https://github.com/Zzz3m",target:"_blank",rel:"noopener noreferrer"},B=t("p",null,'Play Xray to the fullest: Implement "load balancing" based on fwmark or sendThrough.',-1),A=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),N={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},z=t("p",null,"Introduction to using WireGuard for outbound traffic added in Xray v1.6.5.",-1),E=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),G={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},Q=t("p",null,"Adapt traffic statistics and scripts compatible with Xray.",-1);function R(V,W){const s=i("I18nTip"),o=i("RouterLink"),r=i("ExternalLinkIcon");return h(),c("div",null,[n(s),d,_,t("p",null,[n(o,{to:"/en/document/level-2/transparent_proxy/transparent_proxy.html"},{default:a(()=>[e("Beginner's Guide to Transparent Proxies")]),_:1}),e(" by "),p,e(),t("a",m,[e("@kirin"),n(r)])]),g,t("p",null,[n(o,{to:"/en/document/level-2/tproxy.html"},{default:a(()=>[e("TProxy Configuration Tutorial")]),_:1}),e(" by "),f,e(),t("a",y,[e("@BioniCosmos"),n(r)])]),b,t("p",null,[n(o,{to:"/en/document/level-2/tproxy_ipv4_and_ipv6.html"},{default:a(()=>[e("TProxy Transparent Proxy (IPv4 and IPv6) Configuration Tutorial")]),_:1}),e(" by "),v,e(),t("a",x,[e("@SQLimit"),n(r)])]),T,t("p",null,[n(o,{to:"/en/document/level-2/nginx_or_haproxy_tls_tunnel.html"},{default:a(()=>[e("Nginx_TLS Tunnel Hidden Fingerprint")]),_:1}),e(" by "),k,e(),t("a",w,[e("@SQLimit"),n(r)])]),P,t("p",null,[n(o,{to:"/en/document/level-2/iptables_gid.html"},{default:a(()=>[e("[Transparent Proxy] Avoiding Xray Traffic Through gid")]),_:1}),e(" by "),I,e(),t("a",X,[e("@kirin"),n(r)])]),L,t("p",null,[n(o,{to:"/en/document/level-2/redirect.html"},{default:a(()=>[e('Redirect Specific Traffic to Specific Gateway using Xray to Achieve Global Routing "Load Balancing"')]),_:1}),e(" by "),S,e(),t("a",C,[e("@Zzz3m"),n(r)])]),B,t("p",null,[n(o,{to:"/en/document/level-2/warp.html"},{default:a(()=>[e("Enhancing Proxy Security with Cloudflare Warp")]),_:1}),e(" by "),A,e(),t("a",N,[e("@yuhan6665"),n(r)])]),z,t("p",null,[n(o,{to:"/en/document/level-2/traffic_stats.html"},{default:a(()=>[e("Xray Traffic Statistics")]),_:1}),e(" by "),E,e(),t("a",G,[e("@yuhan6665"),n(r)])]),Q])}const D=l(u,[["render",R],["__file","index.html.vue"]]);export{D as default};
                                        +import{_ as l,r as i,o as h,c,a as n,b as t,w as a,d as e}from"./app-Bw2NG-QJ.js";const u={},d=t("h1",{id:"advanced-documentation",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#advanced-documentation"},[t("span",null,"Advanced Documentation")])],-1),_=t("p",null,[t("strong",null,"This chapter contains experience sharing of using Xray at an advanced level. If you are already familiar with Xray, the experience shared here can help you unleash the full power of Xray.")],-1),p=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),m={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},g=t("p",null,"An Introduction to Transparent Proxies.",-1),f=t("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32",height:"32",alt:"a"},null,-1),y={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},b=t("p",null,"Complete tutorial on configuring transparent proxy (TProxy) based on Xray.",-1),v=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),x={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},T=t("p",null,"Xray-based TProxy Transparent Proxy (IPv4 and IPv6) Configuration Tutorial",-1),k=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),w={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},P=t("p",null,"Use Nginx_TLS tunnel on both ends to hide the fingerprint.",-1),I=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),X={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},L=t("p",null,"A new way of bypassing Xray traffic in transparent proxy implemented by iptables/nftables.",-1),S=t("img",{src:"https://avatars.githubusercontent.com/u/28607089?s=32",width:"32",height:"32",alt:"a"},null,-1),C={href:"https://github.com/Zzz3m",target:"_blank",rel:"noopener noreferrer"},B=t("p",null,'Play Xray to the fullest: Implement "load balancing" based on fwmark or sendThrough.',-1),A=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),N={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},z=t("p",null,"Introduction to using WireGuard for outbound traffic added in Xray v1.6.5.",-1),E=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),G={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},Q=t("p",null,"Adapt traffic statistics and scripts compatible with Xray.",-1);function R(V,W){const s=i("I18nTip"),o=i("RouterLink"),r=i("ExternalLinkIcon");return h(),c("div",null,[n(s),d,_,t("p",null,[n(o,{to:"/en/document/level-2/transparent_proxy/transparent_proxy.html"},{default:a(()=>[e("Beginner's Guide to Transparent Proxies")]),_:1}),e(" by "),p,e(),t("a",m,[e("@kirin"),n(r)])]),g,t("p",null,[n(o,{to:"/en/document/level-2/tproxy.html"},{default:a(()=>[e("TProxy Configuration Tutorial")]),_:1}),e(" by "),f,e(),t("a",y,[e("@BioniCosmos"),n(r)])]),b,t("p",null,[n(o,{to:"/en/document/level-2/tproxy_ipv4_and_ipv6.html"},{default:a(()=>[e("TProxy Transparent Proxy (IPv4 and IPv6) Configuration Tutorial")]),_:1}),e(" by "),v,e(),t("a",x,[e("@SQLimit"),n(r)])]),T,t("p",null,[n(o,{to:"/en/document/level-2/nginx_or_haproxy_tls_tunnel.html"},{default:a(()=>[e("Nginx_TLS Tunnel Hidden Fingerprint")]),_:1}),e(" by "),k,e(),t("a",w,[e("@SQLimit"),n(r)])]),P,t("p",null,[n(o,{to:"/en/document/level-2/iptables_gid.html"},{default:a(()=>[e("[Transparent Proxy] Avoiding Xray Traffic Through gid")]),_:1}),e(" by "),I,e(),t("a",X,[e("@kirin"),n(r)])]),L,t("p",null,[n(o,{to:"/en/document/level-2/redirect.html"},{default:a(()=>[e('Redirect Specific Traffic to Specific Gateway using Xray to Achieve Global Routing "Load Balancing"')]),_:1}),e(" by "),S,e(),t("a",C,[e("@Zzz3m"),n(r)])]),B,t("p",null,[n(o,{to:"/en/document/level-2/warp.html"},{default:a(()=>[e("Enhancing Proxy Security with Cloudflare Warp")]),_:1}),e(" by "),A,e(),t("a",N,[e("@yuhan6665"),n(r)])]),z,t("p",null,[n(o,{to:"/en/document/level-2/traffic_stats.html"},{default:a(()=>[e("Xray Traffic Statistics")]),_:1}),e(" by "),E,e(),t("a",G,[e("@yuhan6665"),n(r)])]),Q])}const D=l(u,[["render",R],["__file","index.html.vue"]]);export{D as default};
                                        diff --git a/assets/index.html-DM9ULzw6.js b/assets/index.html-BNTb1uEP.js
                                        similarity index 98%
                                        rename from assets/index.html-DM9ULzw6.js
                                        rename to assets/index.html-BNTb1uEP.js
                                        index c726bc355d..d8c7e170ca 100644
                                        --- a/assets/index.html-DM9ULzw6.js
                                        +++ b/assets/index.html-BNTb1uEP.js
                                        @@ -1 +1 @@
                                        -import{_ as r,r as s,o as i,c as d,a as t,b as e,d as n,w as o}from"./app-5SoadDYS.js";const c={},u=e("h1",{id:"quick-start",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#quick-start"},[e("span",null,"Quick Start")])],-1),h=e("blockquote",null,[e("p",null,[e("strong",null,"This chapter will tell you how to get Xray in the easiest way and start using Xray.")])],-1),m=e("h2",{id:"download-and-install",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#download-and-install"},[e("span",null,"Download and Install")])],-1),p=e("p",null,"Xray supports various platforms, and you can get various versions of Xray from various sources and methods.",-1),_=e("h2",{id:"configure-and-run",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#configure-and-run"},[e("span",null,"Configure and Run")])],-1),f=e("p",null,"After downloading and installing Xray, you need to configure it.",-1),g=e("h2",{id:"command-parameters",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#command-parameters"},[e("span",null,"Command Parameters")])],-1),v=e("p",null,"Xray has a variety of commands and parameters available, making it flexible and powerful.",-1),y=e("h2",{id:"improve-documents",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#improve-documents"},[e("span",null,"Improve Documents")])],-1),k=e("code",null,"Help us improve this page!",-1),w=e("p",null,"We are very grateful to every Contributor for their contribution! You guys make Project X even stronger!",-1),b=e("h2",{id:"beginner-tutorial",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#beginner-tutorial"},[e("span",null,"Beginner Tutorial")])],-1),x=e("p",null,"A easy tutorial for beginner.",-1),X=e("h2",{id:"getting-started-tips",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#getting-started-tips"},[e("span",null,"Getting Started Tips")])],-1),T=e("h2",{id:"advanced-documentation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#advanced-documentation"},[e("span",null,"Advanced Documentation")])],-1),C=e("p",null,"Tips for advanced user guidance",-1),P=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"Appreciations"),e("p",null,"Thank you very much for your selfless sharing of usage skills and experience, which makes Xray more and more powerful.")],-1);function A(D,I){const l=s("I18nTip"),a=s("RouterLink");return i(),d("div",null,[u,t(l),h,m,p,e("p",null,[n("Please click "),t(a,{to:"/en/document/install.html"},{default:o(()=>[n("How to Download and Install Xray")]),_:1}),n(" to get Xray")]),_,f,e("p",null,[n("Please click "),t(a,{to:"/en/document/config.html"},{default:o(()=>[n("How to Configure and Run Xray")]),_:1}),n(" to learn the easiest way to configure Xray.")]),g,v,e("p",null,[n("Please click "),t(a,{to:"/en/document/command.html"},{default:o(()=>[n("Command Parameters for Xray")]),_:1}),n(" to view more commands and parameters usages.")]),y,e("p",null,[n("If you're interested, please click "),t(a,{to:"/en/document/document.html"},{default:o(()=>[n("Documents")]),_:1}),n(" to help us improve the documents, or click the"),k]),w,b,x,e("p",null,[n("Please click "),t(a,{to:"/en/document/level-0/"},{default:o(()=>[n("小小白白话文")]),_:1}),n(" to view it.")]),X,e("p",null,[n("After you have the basics, you can explore more ways to use them through "),t(a,{to:"/en/document/level-1/"},{default:o(()=>[n("Getting Started Tips")]),_:1}),n(".")]),T,C,e("p",null,[n("Click on "),t(a,{to:"/en/document/level-2/"},{default:o(()=>[n("Advanced Documentation")]),_:1}),n(" to view it")]),P])}const R=r(c,[["render",A],["__file","index.html.vue"]]);export{R as default};
                                        +import{_ as r,r as s,o as i,c as d,a as t,b as e,d as n,w as o}from"./app-Bw2NG-QJ.js";const c={},u=e("h1",{id:"quick-start",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#quick-start"},[e("span",null,"Quick Start")])],-1),h=e("blockquote",null,[e("p",null,[e("strong",null,"This chapter will tell you how to get Xray in the easiest way and start using Xray.")])],-1),m=e("h2",{id:"download-and-install",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#download-and-install"},[e("span",null,"Download and Install")])],-1),p=e("p",null,"Xray supports various platforms, and you can get various versions of Xray from various sources and methods.",-1),_=e("h2",{id:"configure-and-run",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#configure-and-run"},[e("span",null,"Configure and Run")])],-1),f=e("p",null,"After downloading and installing Xray, you need to configure it.",-1),g=e("h2",{id:"command-parameters",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#command-parameters"},[e("span",null,"Command Parameters")])],-1),v=e("p",null,"Xray has a variety of commands and parameters available, making it flexible and powerful.",-1),y=e("h2",{id:"improve-documents",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#improve-documents"},[e("span",null,"Improve Documents")])],-1),k=e("code",null,"Help us improve this page!",-1),w=e("p",null,"We are very grateful to every Contributor for their contribution! You guys make Project X even stronger!",-1),b=e("h2",{id:"beginner-tutorial",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#beginner-tutorial"},[e("span",null,"Beginner Tutorial")])],-1),x=e("p",null,"A easy tutorial for beginner.",-1),X=e("h2",{id:"getting-started-tips",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#getting-started-tips"},[e("span",null,"Getting Started Tips")])],-1),T=e("h2",{id:"advanced-documentation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#advanced-documentation"},[e("span",null,"Advanced Documentation")])],-1),C=e("p",null,"Tips for advanced user guidance",-1),P=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"Appreciations"),e("p",null,"Thank you very much for your selfless sharing of usage skills and experience, which makes Xray more and more powerful.")],-1);function A(D,I){const l=s("I18nTip"),a=s("RouterLink");return i(),d("div",null,[u,t(l),h,m,p,e("p",null,[n("Please click "),t(a,{to:"/en/document/install.html"},{default:o(()=>[n("How to Download and Install Xray")]),_:1}),n(" to get Xray")]),_,f,e("p",null,[n("Please click "),t(a,{to:"/en/document/config.html"},{default:o(()=>[n("How to Configure and Run Xray")]),_:1}),n(" to learn the easiest way to configure Xray.")]),g,v,e("p",null,[n("Please click "),t(a,{to:"/en/document/command.html"},{default:o(()=>[n("Command Parameters for Xray")]),_:1}),n(" to view more commands and parameters usages.")]),y,e("p",null,[n("If you're interested, please click "),t(a,{to:"/en/document/document.html"},{default:o(()=>[n("Documents")]),_:1}),n(" to help us improve the documents, or click the"),k]),w,b,x,e("p",null,[n("Please click "),t(a,{to:"/en/document/level-0/"},{default:o(()=>[n("小小白白话文")]),_:1}),n(" to view it.")]),X,e("p",null,[n("After you have the basics, you can explore more ways to use them through "),t(a,{to:"/en/document/level-1/"},{default:o(()=>[n("Getting Started Tips")]),_:1}),n(".")]),T,C,e("p",null,[n("Click on "),t(a,{to:"/en/document/level-2/"},{default:o(()=>[n("Advanced Documentation")]),_:1}),n(" to view it")]),P])}const R=r(c,[["render",A],["__file","index.html.vue"]]);export{R as default};
                                        diff --git a/assets/index.html-CiIdsSO_.js b/assets/index.html-Bf7-nv__.js
                                        similarity index 98%
                                        rename from assets/index.html-CiIdsSO_.js
                                        rename to assets/index.html-Bf7-nv__.js
                                        index 04b277457e..dd56a5f946 100644
                                        --- a/assets/index.html-CiIdsSO_.js
                                        +++ b/assets/index.html-Bf7-nv__.js
                                        @@ -1 +1 @@
                                        -import{_ as i,r as a,o as h,c as u,a as n,b as t,w as s,d as e}from"./app-5SoadDYS.js";const _={},c=t("h1",{id:"продвинутая-документация",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#продвинутая-документация"},[t("span",null,"Продвинутая документация")])],-1),p=t("p",null,[t("strong",null,"В этом разделе представлены советы и рекомендации по использованию Xray для продвинутых пользователей. Если вы уже знакомы с Xray, то информация, представленная здесь, поможет вам использовать Xray по максимуму.")],-1),d=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),m={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},g=t("p",null,"Вводная статья о прозрачном проксировании.",-1),f=t("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32",height:"32",alt:"a"},null,-1),b={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},y=t("p",null,"Полное руководство по настройке прозрачного проксирования (TProxy) на основе Xray.",-1),v=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),x={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},k=t("p",null,"Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6) на основе Xray.",-1),w=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),X={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},L=t("p",null,"Создание TLS-туннеля с помощью Nginx или Haproxy на стороне клиента и сервера для скрытия отпечатков.",-1),T=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),S={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},B=t("p",null,"Новый способ исключения трафика Xray при реализации прозрачного проксирования с помощью iptables/nftables.",-1),C=t("img",{src:"https://avatars.githubusercontent.com/u/28607089?s=32",width:"32",height:"32",alt:"a"},null,-1),I={href:"https://github.com/Zzz3m",target:"_blank",rel:"noopener noreferrer"},N=t("p",null,'Использование Xray по максимуму: реализация "разделения" трафика на основе fwmark, sendThrough или sockopt.interface.',-1),z=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),P={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},Q=t("p",null,"Введение в использование исходящего подключения WireGuard, добавленного в Xray v1.6.5.",-1),E=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),V={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},G=t("p",null,"Статистика трафика и скрипты для Xray.",-1);function H(R,W){const l=a("I18nTip"),o=a("RouterLink"),r=a("ExternalLinkIcon");return h(),u("div",null,[n(l),c,p,t("p",null,[n(o,{to:"/ru/document/level-2/transparent_proxy/transparent_proxy.html"},{default:s(()=>[e("Введение в прозрачное проксирование")]),_:1}),e(" от "),d,e(),t("a",m,[e("@kirin"),n(r)])]),g,t("p",null,[n(o,{to:"/ru/document/level-2/tproxy.html"},{default:s(()=>[e("Руководство по настройке прозрачного проксирования (TProxy) ")]),_:1}),e(" от "),f,e(),t("a",b,[e("@BioniCosmos"),n(r)])]),y,t("p",null,[n(o,{to:"/ru/document/level-2/tproxy_ipv4_and_ipv6.html"},{default:s(()=>[e("Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6)")]),_:1}),e(" от "),v,e(),t("a",x,[e("@SQLimit"),n(r)])]),k,t("p",null,[n(o,{to:"/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html"},{default:s(()=>[e("Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков")]),_:1}),e(" от "),w,e(),t("a",X,[e("@SQLimit"),n(r)])]),L,t("p",null,[n(o,{to:"/ru/document/level-2/iptables_gid.html"},{default:s(()=>[e("[Прозрачное проксирование] Исключение трафика Xray с помощью GID")]),_:1}),e(" от "),T,e(),t("a",S,[e("@kirin"),n(r)])]),B,t("p",null,[n(o,{to:"/ru/document/level-2/redirect.html"},{default:s(()=>[e('Направление определенного трафика через определенный выходной узел с помощью Xray для реализации "разделения" глобальной маршрутизации')]),_:1}),e(" от "),C,e(),t("a",I,[e("@Zzz3m"),n(r)])]),N,t("p",null,[n(o,{to:"/ru/document/level-2/warp.html"},{default:s(()=>[e("Повышение безопасности проксирования с помощью Cloudflare Warp")]),_:1}),e(" от "),z,e(),t("a",P,[e("@yuhan6665"),n(r)])]),Q,t("p",null,[n(o,{to:"/ru/document/level-2/traffic_stats.html"},{default:s(()=>[e("Статистика трафика Xray")]),_:1}),e(" от "),E,e(),t("a",V,[e("@yuhan6665"),n(r)])]),G])}const D=i(_,[["render",H],["__file","index.html.vue"]]);export{D as default};
                                        +import{_ as i,r as a,o as h,c as u,a as n,b as t,w as s,d as e}from"./app-Bw2NG-QJ.js";const _={},c=t("h1",{id:"продвинутая-документация",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#продвинутая-документация"},[t("span",null,"Продвинутая документация")])],-1),p=t("p",null,[t("strong",null,"В этом разделе представлены советы и рекомендации по использованию Xray для продвинутых пользователей. Если вы уже знакомы с Xray, то информация, представленная здесь, поможет вам использовать Xray по максимуму.")],-1),d=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),m={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},g=t("p",null,"Вводная статья о прозрачном проксировании.",-1),f=t("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32",height:"32",alt:"a"},null,-1),b={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},y=t("p",null,"Полное руководство по настройке прозрачного проксирования (TProxy) на основе Xray.",-1),v=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),x={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},k=t("p",null,"Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6) на основе Xray.",-1),w=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),X={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},L=t("p",null,"Создание TLS-туннеля с помощью Nginx или Haproxy на стороне клиента и сервера для скрытия отпечатков.",-1),T=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),S={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},B=t("p",null,"Новый способ исключения трафика Xray при реализации прозрачного проксирования с помощью iptables/nftables.",-1),C=t("img",{src:"https://avatars.githubusercontent.com/u/28607089?s=32",width:"32",height:"32",alt:"a"},null,-1),I={href:"https://github.com/Zzz3m",target:"_blank",rel:"noopener noreferrer"},N=t("p",null,'Использование Xray по максимуму: реализация "разделения" трафика на основе fwmark, sendThrough или sockopt.interface.',-1),z=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),P={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},Q=t("p",null,"Введение в использование исходящего подключения WireGuard, добавленного в Xray v1.6.5.",-1),E=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),V={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},G=t("p",null,"Статистика трафика и скрипты для Xray.",-1);function H(R,W){const l=a("I18nTip"),o=a("RouterLink"),r=a("ExternalLinkIcon");return h(),u("div",null,[n(l),c,p,t("p",null,[n(o,{to:"/ru/document/level-2/transparent_proxy/transparent_proxy.html"},{default:s(()=>[e("Введение в прозрачное проксирование")]),_:1}),e(" от "),d,e(),t("a",m,[e("@kirin"),n(r)])]),g,t("p",null,[n(o,{to:"/ru/document/level-2/tproxy.html"},{default:s(()=>[e("Руководство по настройке прозрачного проксирования (TProxy) ")]),_:1}),e(" от "),f,e(),t("a",b,[e("@BioniCosmos"),n(r)])]),y,t("p",null,[n(o,{to:"/ru/document/level-2/tproxy_ipv4_and_ipv6.html"},{default:s(()=>[e("Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6)")]),_:1}),e(" от "),v,e(),t("a",x,[e("@SQLimit"),n(r)])]),k,t("p",null,[n(o,{to:"/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html"},{default:s(()=>[e("Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков")]),_:1}),e(" от "),w,e(),t("a",X,[e("@SQLimit"),n(r)])]),L,t("p",null,[n(o,{to:"/ru/document/level-2/iptables_gid.html"},{default:s(()=>[e("[Прозрачное проксирование] Исключение трафика Xray с помощью GID")]),_:1}),e(" от "),T,e(),t("a",S,[e("@kirin"),n(r)])]),B,t("p",null,[n(o,{to:"/ru/document/level-2/redirect.html"},{default:s(()=>[e('Направление определенного трафика через определенный выходной узел с помощью Xray для реализации "разделения" глобальной маршрутизации')]),_:1}),e(" от "),C,e(),t("a",I,[e("@Zzz3m"),n(r)])]),N,t("p",null,[n(o,{to:"/ru/document/level-2/warp.html"},{default:s(()=>[e("Повышение безопасности проксирования с помощью Cloudflare Warp")]),_:1}),e(" от "),z,e(),t("a",P,[e("@yuhan6665"),n(r)])]),Q,t("p",null,[n(o,{to:"/ru/document/level-2/traffic_stats.html"},{default:s(()=>[e("Статистика трафика Xray")]),_:1}),e(" от "),E,e(),t("a",V,[e("@yuhan6665"),n(r)])]),G])}const D=i(_,[["render",H],["__file","index.html.vue"]]);export{D as default};
                                        diff --git a/assets/index.html-C4BsmZBc.js b/assets/index.html-BghSFULx.js
                                        similarity index 97%
                                        rename from assets/index.html-C4BsmZBc.js
                                        rename to assets/index.html-BghSFULx.js
                                        index 921bf8f63e..234d626438 100644
                                        --- a/assets/index.html-C4BsmZBc.js
                                        +++ b/assets/index.html-BghSFULx.js
                                        @@ -1 +1 @@
                                        -import{_ as u,r as c,o as s,c as d,a as l,b as t,d as e,w as o}from"./app-5SoadDYS.js";const _={},h=t("h1",{id:"простые-разговоры-о-сложном",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#простые-разговоры-о-сложном"},[t("span",null,"Простые разговоры о сложном")])],-1),i=t("p",null,[t("strong",null,"Эта глава - базовый курс «С нуля», новичкам читать и учить обязательно")],-1),p={class:"custom-container tip"},m=t("p",{class:"custom-container-title"},"Подсказка",-1),f={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"};function v(x,k){const r=c("I18nTip"),a=c("ExternalLinkIcon"),n=c("RouterLink");return s(),d("div",null,[l(r),h,i,t("div",p,[m,t("p",null,[e("Сделано с ❤️ "),t("a",f,[e("@ricuhkaen"),l(a)])])]),t("p",null,[l(n,{to:"/ru/document/level-0/ch01-preface.html"},{default:o(()=>[e("【Глава 1】 Введение")]),_:1}),e(" - Чужой или свой сервер? Вот в чём вопрос")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch02-preparation.html"},{default:o(()=>[e("【Глава 2】 Подготовка")]),_:1}),e(" - Прежде чем браться за дело, заготовь средства")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch03-ssh.html"},{default:o(()=>[e("【Глава 3】 Удалённое подключение")]),_:1}),e(" - Мост между севером и югом, пропасть превращается в путь")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch04-security.html"},{default:o(()=>[e("【Глава 4】 Безопасность")]),_:1}),e(" - Небрежность в безопасности, и родные будут лить слёзы")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch05-webpage.html"},{default:o(()=>[e("【Глава 5】 Создание сайта")]),_:1}),e(" - Покажи свою красоту")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch06-certificates.html"},{default:o(()=>[e("【Глава 6】 Управление сертификатами")]),_:1}),e(" - Законно то, что с лицензией")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:o(()=>[e("【Глава 7】 Xray сервер")]),_:1}),e(" - Наконец-то дождались")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch08-xray-clients.html"},{default:o(()=>[e("【Глава 8】 Xray клиенты")]),_:1}),e(" - Новое начало")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch09-appendix.html"},{default:o(()=>[e("【Глава 9】 Приложение")]),_:1}),e(" - Все контрольные точки здесь")])])}const y=u(_,[["render",v],["__file","index.html.vue"]]);export{y as default};
                                        +import{_ as u,r as c,o as s,c as d,a as l,b as t,d as e,w as o}from"./app-Bw2NG-QJ.js";const _={},h=t("h1",{id:"простые-разговоры-о-сложном",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#простые-разговоры-о-сложном"},[t("span",null,"Простые разговоры о сложном")])],-1),i=t("p",null,[t("strong",null,"Эта глава - базовый курс «С нуля», новичкам читать и учить обязательно")],-1),p={class:"custom-container tip"},m=t("p",{class:"custom-container-title"},"Подсказка",-1),f={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"};function v(x,k){const r=c("I18nTip"),a=c("ExternalLinkIcon"),n=c("RouterLink");return s(),d("div",null,[l(r),h,i,t("div",p,[m,t("p",null,[e("Сделано с ❤️ "),t("a",f,[e("@ricuhkaen"),l(a)])])]),t("p",null,[l(n,{to:"/ru/document/level-0/ch01-preface.html"},{default:o(()=>[e("【Глава 1】 Введение")]),_:1}),e(" - Чужой или свой сервер? Вот в чём вопрос")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch02-preparation.html"},{default:o(()=>[e("【Глава 2】 Подготовка")]),_:1}),e(" - Прежде чем браться за дело, заготовь средства")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch03-ssh.html"},{default:o(()=>[e("【Глава 3】 Удалённое подключение")]),_:1}),e(" - Мост между севером и югом, пропасть превращается в путь")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch04-security.html"},{default:o(()=>[e("【Глава 4】 Безопасность")]),_:1}),e(" - Небрежность в безопасности, и родные будут лить слёзы")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch05-webpage.html"},{default:o(()=>[e("【Глава 5】 Создание сайта")]),_:1}),e(" - Покажи свою красоту")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch06-certificates.html"},{default:o(()=>[e("【Глава 6】 Управление сертификатами")]),_:1}),e(" - Законно то, что с лицензией")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch07-xray-server.html"},{default:o(()=>[e("【Глава 7】 Xray сервер")]),_:1}),e(" - Наконец-то дождались")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch08-xray-clients.html"},{default:o(()=>[e("【Глава 8】 Xray клиенты")]),_:1}),e(" - Новое начало")]),t("p",null,[l(n,{to:"/ru/document/level-0/ch09-appendix.html"},{default:o(()=>[e("【Глава 9】 Приложение")]),_:1}),e(" - Все контрольные точки здесь")])])}const y=u(_,[["render",v],["__file","index.html.vue"]]);export{y as default};
                                        diff --git a/assets/index.html-DKrDxjJk.js b/assets/index.html-BiwlIXs1.js
                                        similarity index 98%
                                        rename from assets/index.html-DKrDxjJk.js
                                        rename to assets/index.html-BiwlIXs1.js
                                        index 33b05ebf9d..02cef574fe 100644
                                        --- a/assets/index.html-DKrDxjJk.js
                                        +++ b/assets/index.html-BiwlIXs1.js
                                        @@ -1 +1 @@
                                        -import{_ as s,r as n,o as i,c,a as o,b as e,d as t,w as h,e as u}from"./app-5SoadDYS.js";const d={},p=u('

                                        XTLS? Xray? V2Ray?

                                        XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.

                                        • Xray-core is a superset of v2ray-core, with better overall performance and enhancements such as XTLS, and it'scompletelycompatible with v2ray-core functionality and configuration.
                                          • Only one executable file, including ctl functionality, run is the default command
                                          • Configuration iscompletelycompatible, environment variables and API calls need to be changed to start with XRAY_
                                          • Exposed raw protocol's ReadV on all platforms
                                          • Provides complete VLESS & Trojan XTLS support, both with ReadV
                                          • Provides multiple XTLS flow control modes, unrivaled performance!

                                        "Configuration compatible, overall better"

                                        Who are we?

                                        It doesn't matter who we are. What matters is that we will keep riding and never look back.

                                        Help Xray become stronger

                                        Welcome to help Xray become stronger!

                                        ',8),m=e("li",null,"🖥️ Help develop and test Xray, submit high-quality Pull requests.",-1),_={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-core/discussions",target:"_blank",rel:"noopener noreferrer"},f={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,"💬 Help group members/chat in Telegram group.",-1),y=e("li",null,[e("strong",null,"...In fact, every support for Xray will make Xray stronger")],-1),k=e("h3",{id:"telegram",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#telegram"},[e("span",null,"Telegram")])],-1),w={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},X=e("ul",null,[e("li",null,"You can chat freely above the bottom line in the discussion group, don't fight, no abuse of power."),e("li",null,"Feel free to ask questions, and try to answer those you know."),e("li",null,"No politics, No NSFW")],-1),v={href:"https://t.me/projectXtls",target:"_blank",rel:"noopener noreferrer"},x=e("ul",null,[e("li",null,"Publish the latest news of Project X")],-1),T=e("h3",{id:"thanks",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#thanks"},[e("span",null,"Thanks")])],-1),L=e("ul",null,[e("li",null,"Thanks to everyone for their support!"),e("li",null,"Thanks to all kinds of scripts, Docker images, client support... Thanks to all the big guys who helped improve the ecosystem!"),e("li",null,"Thanks to friends who have contributed to the Xray website and documentation."),e("li",null,"Thanks to friends who have made meaningful suggestions and comments."),e("li",null,"Thanks to every friend in the Telegram group who helps others.")],-1),S=e("h3",{id:"more-about-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#more-about-project-x"},[e("span",null,"More about project X")])],-1),I=e("h3",{id:"license",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#license"},[e("span",null,"License")])],-1),j={href:"https://github.com/XTLS/Xray-core/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer"},q=e("h3",{id:"stargazers-over-time",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#stargazers-over-time"},[e("span",null,"Stargazers over time")])],-1),P={href:"https://starchart.cc/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},V=e("img",{src:"https://starchart.cc/XTLS/Xray-core.svg",alt:"Stargazers over time"},null,-1);function N(E,C){const a=n("I18nTip"),r=n("ExternalLinkIcon"),l=n("RouterLink");return i(),c("div",null,[o(a),p,e("ul",null,[m,e("li",null,[t("📩 Initiate constructive or meaningful issues and discussions in "),e("a",_,[t("GitHub Issues"),o(r)]),t(" or "),e("a",b,[t("Discussion area"),o(r)]),t(".")]),e("li",null,[t("📝 Write down your usage experience and submit it to Xray's "),e("a",f,[t("documentation website"),o(r)]),t(".")]),g,y]),k,e("ul",null,[e("li",null,[e("p",null,[e("a",w,[t("Project X Discussion Group"),o(r)])]),X]),e("li",null,[e("p",null,[e("a",v,[t("Project X Channel"),o(r)])]),x])]),T,L,S,e("ul",null,[e("li",null,[t("If you would like to learn more about project X's history and growth, please click "),o(l,{to:"/en/about/news.html"},{default:h(()=>[t("here")]),_:1})])]),I,e("p",null,[e("a",j,[t("Mozilla Public License Version 2.0"),o(r)])]),q,e("p",null,[e("a",P,[V,o(r)])])])}const z=s(d,[["render",N],["__file","index.html.vue"]]);export{z as default}; +import{_ as s,r as n,o as i,c,a as o,b as e,d as t,w as h,e as u}from"./app-Bw2NG-QJ.js";const d={},p=u('

                                        XTLS? Xray? V2Ray?

                                        XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.

                                        • Xray-core is a superset of v2ray-core, with better overall performance and enhancements such as XTLS, and it'scompletelycompatible with v2ray-core functionality and configuration.
                                          • Only one executable file, including ctl functionality, run is the default command
                                          • Configuration iscompletelycompatible, environment variables and API calls need to be changed to start with XRAY_
                                          • Exposed raw protocol's ReadV on all platforms
                                          • Provides complete VLESS & Trojan XTLS support, both with ReadV
                                          • Provides multiple XTLS flow control modes, unrivaled performance!

                                        "Configuration compatible, overall better"

                                        Who are we?

                                        It doesn't matter who we are. What matters is that we will keep riding and never look back.

                                        Help Xray become stronger

                                        Welcome to help Xray become stronger!

                                        ',8),m=e("li",null,"🖥️ Help develop and test Xray, submit high-quality Pull requests.",-1),_={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-core/discussions",target:"_blank",rel:"noopener noreferrer"},f={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,"💬 Help group members/chat in Telegram group.",-1),y=e("li",null,[e("strong",null,"...In fact, every support for Xray will make Xray stronger")],-1),k=e("h3",{id:"telegram",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#telegram"},[e("span",null,"Telegram")])],-1),w={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},X=e("ul",null,[e("li",null,"You can chat freely above the bottom line in the discussion group, don't fight, no abuse of power."),e("li",null,"Feel free to ask questions, and try to answer those you know."),e("li",null,"No politics, No NSFW")],-1),v={href:"https://t.me/projectXtls",target:"_blank",rel:"noopener noreferrer"},x=e("ul",null,[e("li",null,"Publish the latest news of Project X")],-1),T=e("h3",{id:"thanks",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#thanks"},[e("span",null,"Thanks")])],-1),L=e("ul",null,[e("li",null,"Thanks to everyone for their support!"),e("li",null,"Thanks to all kinds of scripts, Docker images, client support... Thanks to all the big guys who helped improve the ecosystem!"),e("li",null,"Thanks to friends who have contributed to the Xray website and documentation."),e("li",null,"Thanks to friends who have made meaningful suggestions and comments."),e("li",null,"Thanks to every friend in the Telegram group who helps others.")],-1),S=e("h3",{id:"more-about-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#more-about-project-x"},[e("span",null,"More about project X")])],-1),I=e("h3",{id:"license",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#license"},[e("span",null,"License")])],-1),j={href:"https://github.com/XTLS/Xray-core/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer"},q=e("h3",{id:"stargazers-over-time",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#stargazers-over-time"},[e("span",null,"Stargazers over time")])],-1),P={href:"https://starchart.cc/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},V=e("img",{src:"https://starchart.cc/XTLS/Xray-core.svg",alt:"Stargazers over time"},null,-1);function N(E,C){const a=n("I18nTip"),r=n("ExternalLinkIcon"),l=n("RouterLink");return i(),c("div",null,[o(a),p,e("ul",null,[m,e("li",null,[t("📩 Initiate constructive or meaningful issues and discussions in "),e("a",_,[t("GitHub Issues"),o(r)]),t(" or "),e("a",b,[t("Discussion area"),o(r)]),t(".")]),e("li",null,[t("📝 Write down your usage experience and submit it to Xray's "),e("a",f,[t("documentation website"),o(r)]),t(".")]),g,y]),k,e("ul",null,[e("li",null,[e("p",null,[e("a",w,[t("Project X Discussion Group"),o(r)])]),X]),e("li",null,[e("p",null,[e("a",v,[t("Project X Channel"),o(r)])]),x])]),T,L,S,e("ul",null,[e("li",null,[t("If you would like to learn more about project X's history and growth, please click "),o(l,{to:"/en/about/news.html"},{default:h(()=>[t("here")]),_:1})])]),I,e("p",null,[e("a",j,[t("Mozilla Public License Version 2.0"),o(r)])]),q,e("p",null,[e("a",P,[V,o(r)])])])}const z=s(d,[["render",N],["__file","index.html.vue"]]);export{z as default}; diff --git a/assets/index.html-D5d6Z4Xz.js b/assets/index.html-BkqXAF2a.js similarity index 98% rename from assets/index.html-D5d6Z4Xz.js rename to assets/index.html-BkqXAF2a.js index ebd3d20f31..24b8d71613 100644 --- a/assets/index.html-D5d6Z4Xz.js +++ b/assets/index.html-BkqXAF2a.js @@ -1 +1 @@ -import{_ as c,r as a,o as d,c as h,a as t,b as e,d as n,w as l}from"./app-5SoadDYS.js";const r={},_=e("h1",{id:"快速入门",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#快速入门"},[e("span",null,"快速入门")])],-1),i=e("blockquote",null,[e("p",null,[e("strong",null,"这个章节将告诉您如何用最简单的方式获得 Xray,并且开始使用 Xray。")])],-1),u=e("h2",{id:"下载安装",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#下载安装"},[e("span",null,"下载安装")])],-1),p=e("p",null,"Xray 支持各种平台,并且您可以从多种渠道和方式获得 Xray 的各种版本。",-1),m=e("h2",{id:"配置运行",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#配置运行"},[e("span",null,"配置运行")])],-1),f=e("p",null,"下载并安装 Xray 后,只需对他进行配置即可使用。",-1),x=e("h2",{id:"命令参数",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#命令参数"},[e("span",null,"命令参数")])],-1),b=e("p",null,"Xray 有多种命令和参数可用,因此变得灵活和强大。",-1),X=e("h2",{id:"改进文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#改进文档"},[e("span",null,"改进文档")])],-1),y=e("code",null,"帮助我们改善此页面!",-1),v=e("p",null,"我们十分感谢每一位 Contributor 作出的贡献!是你们让 Project X 变得更加强大!",-1),k=e("h2",{id:"小小白白话文",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#小小白白话文"},[e("span",null,"小小白白话文")])],-1),B=e("p",null,"给予新手指导的使用心得",-1),C=e("h2",{id:"入门技巧",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入门技巧"},[e("span",null,"入门技巧")])],-1),N=e("h2",{id:"进阶文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#进阶文档"},[e("span",null,"进阶文档")])],-1),T=e("p",null,"给予进阶用户指导的使用技巧",-1),V=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"感谢"),e("p",null,"非常感谢大家无私分享使用技巧和心得, 使得 Xray 日益强大。")],-1);function g(w,I){const s=a("I18nTip"),o=a("RouterLink");return d(),h("div",null,[t(s),_,i,u,p,e("p",null,[n("请点击 "),t(o,{to:"/document/install.html"},{default:l(()=>[n("下载安装")]),_:1}),n(" 以获取 Xray")]),m,f,e("p",null,[n("请点击 "),t(o,{to:"/document/config.html"},{default:l(()=>[n("配置运行")]),_:1}),n(" 以学习最简单的配置方式。")]),x,b,e("p",null,[n("请点击 "),t(o,{to:"/document/command.html"},{default:l(()=>[n("命令参数")]),_:1}),n(" 查看 Xray 的更多命令和参数用法。")]),X,e("p",null,[n("如果你有兴趣,请点击 "),t(o,{to:"/document/document.html"},{default:l(()=>[n("使用文档")]),_:1}),n(" 帮助我们改进文档,或者点击页面下方的 "),y]),v,k,B,e("p",null,[n("请点击 "),t(o,{to:"/document/level-0/"},{default:l(()=>[n("小小白白话文")]),_:1}),n(" 以进行查看。")]),C,e("p",null,[n("具备了基础之后,你就可以通过 "),t(o,{to:"/document/level-1/"},{default:l(()=>[n("入门技巧")]),_:1}),n(" 来探索更多的使用方式了。")]),N,T,e("p",null,[n("点击 "),t(o,{to:"/document/level-2/"},{default:l(()=>[n("进阶文档")]),_:1}),n(" 以进行查看")]),V])}const R=c(r,[["render",g],["__file","index.html.vue"]]);export{R as default}; +import{_ as c,r as a,o as d,c as h,a as t,b as e,d as n,w as l}from"./app-Bw2NG-QJ.js";const r={},_=e("h1",{id:"快速入门",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#快速入门"},[e("span",null,"快速入门")])],-1),i=e("blockquote",null,[e("p",null,[e("strong",null,"这个章节将告诉您如何用最简单的方式获得 Xray,并且开始使用 Xray。")])],-1),u=e("h2",{id:"下载安装",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#下载安装"},[e("span",null,"下载安装")])],-1),p=e("p",null,"Xray 支持各种平台,并且您可以从多种渠道和方式获得 Xray 的各种版本。",-1),m=e("h2",{id:"配置运行",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#配置运行"},[e("span",null,"配置运行")])],-1),f=e("p",null,"下载并安装 Xray 后,只需对他进行配置即可使用。",-1),x=e("h2",{id:"命令参数",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#命令参数"},[e("span",null,"命令参数")])],-1),b=e("p",null,"Xray 有多种命令和参数可用,因此变得灵活和强大。",-1),X=e("h2",{id:"改进文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#改进文档"},[e("span",null,"改进文档")])],-1),y=e("code",null,"帮助我们改善此页面!",-1),v=e("p",null,"我们十分感谢每一位 Contributor 作出的贡献!是你们让 Project X 变得更加强大!",-1),k=e("h2",{id:"小小白白话文",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#小小白白话文"},[e("span",null,"小小白白话文")])],-1),B=e("p",null,"给予新手指导的使用心得",-1),C=e("h2",{id:"入门技巧",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入门技巧"},[e("span",null,"入门技巧")])],-1),N=e("h2",{id:"进阶文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#进阶文档"},[e("span",null,"进阶文档")])],-1),T=e("p",null,"给予进阶用户指导的使用技巧",-1),V=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"感谢"),e("p",null,"非常感谢大家无私分享使用技巧和心得, 使得 Xray 日益强大。")],-1);function g(w,I){const s=a("I18nTip"),o=a("RouterLink");return d(),h("div",null,[t(s),_,i,u,p,e("p",null,[n("请点击 "),t(o,{to:"/document/install.html"},{default:l(()=>[n("下载安装")]),_:1}),n(" 以获取 Xray")]),m,f,e("p",null,[n("请点击 "),t(o,{to:"/document/config.html"},{default:l(()=>[n("配置运行")]),_:1}),n(" 以学习最简单的配置方式。")]),x,b,e("p",null,[n("请点击 "),t(o,{to:"/document/command.html"},{default:l(()=>[n("命令参数")]),_:1}),n(" 查看 Xray 的更多命令和参数用法。")]),X,e("p",null,[n("如果你有兴趣,请点击 "),t(o,{to:"/document/document.html"},{default:l(()=>[n("使用文档")]),_:1}),n(" 帮助我们改进文档,或者点击页面下方的 "),y]),v,k,B,e("p",null,[n("请点击 "),t(o,{to:"/document/level-0/"},{default:l(()=>[n("小小白白话文")]),_:1}),n(" 以进行查看。")]),C,e("p",null,[n("具备了基础之后,你就可以通过 "),t(o,{to:"/document/level-1/"},{default:l(()=>[n("入门技巧")]),_:1}),n(" 来探索更多的使用方式了。")]),N,T,e("p",null,[n("点击 "),t(o,{to:"/document/level-2/"},{default:l(()=>[n("进阶文档")]),_:1}),n(" 以进行查看")]),V])}const R=c(r,[["render",g],["__file","index.html.vue"]]);export{R as default}; diff --git a/assets/index.html-COrJaVx-.js b/assets/index.html-Bn9iOydn.js similarity index 99% rename from assets/index.html-COrJaVx-.js rename to assets/index.html-Bn9iOydn.js index bbeacb4eac..ec2a3f17df 100644 --- a/assets/index.html-COrJaVx-.js +++ b/assets/index.html-Bn9iOydn.js @@ -1,4 +1,4 @@ -import{_ as c,r as e,o as p,c as u,a as s,b as n,d as t,w as a,e as i}from"./app-5SoadDYS.js";const r={},d=i(`

                                        This section will tell you all the details of Xray configuration. By mastering these contents, Xray will unleash its full power in your hands.

                                        Overview

                                        The configuration file of Xray is in JSON format, and the configuration format for the client and server is the same, except for the actual configuration content. It takes the following form:

                                        {
                                        +import{_ as c,r as e,o as p,c as u,a as s,b as n,d as t,w as a,e as i}from"./app-Bw2NG-QJ.js";const r={},d=i(`

                                        This section will tell you all the details of Xray configuration. By mastering these contents, Xray will unleash its full power in your hands.

                                        Overview

                                        The configuration file of Xray is in JSON format, and the configuration format for the client and server is the same, except for the actual configuration content. It takes the following form:

                                        {
                                           "log": {},
                                           "api": {},
                                           "dns": {},
                                        diff --git a/assets/index.html-Dd9_Hlk-.js b/assets/index.html-Bt40bz30.js
                                        similarity index 98%
                                        rename from assets/index.html-Dd9_Hlk-.js
                                        rename to assets/index.html-Bt40bz30.js
                                        index 0f53b69bd6..58860968f7 100644
                                        --- a/assets/index.html-Dd9_Hlk-.js
                                        +++ b/assets/index.html-Bt40bz30.js
                                        @@ -1 +1 @@
                                        -import{_ as i,r as a,o as h,c as _,a as n,b as t,w as s,d as e}from"./app-5SoadDYS.js";const c={},u=t("h1",{id:"进阶文档",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#进阶文档"},[t("span",null,"进阶文档")])],-1),d=t("p",null,[t("strong",null,"这个章节包含进阶级的 Xray 使用心得分享, 如果您已经熟悉 Xray, 那么这里的经验可以让您更加发挥 Xray 的威力")],-1),p=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),m={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},g=t("p",null,"透明代理的入门篇章。",-1),f=t("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32",height:"32",alt:"a"},null,-1),b={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},y=t("p",null,"基于 Xray 的透明代理(TProxy)配置完整教程。",-1),v=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),x={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},k=t("p",null,"基于 Xray 的 TProxy 透明代理(ipv4 and ipv6)配置教程",-1),w=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),X={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},L=t("p",null,"双端使用 Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹",-1),T=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),S={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},B=t("p",null,"在 iptables/nftables 实现的透明代理中,一种新的规避 Xray 流量的方式。",-1),C=t("img",{src:"https://avatars.githubusercontent.com/u/28607089?s=32",width:"32",height:"32",alt:"a"},null,-1),N={href:"https://github.com/Zzz3m",target:"_blank",rel:"noopener noreferrer"},z=t("p",null,"将 Xray 玩出花:基于 fwmark 、 sendThrough 或 sockopt.interface 方式实现“分流”。",-1),I=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),P={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},Q=t("p",null,"Xray v1.6.5 新增 WireGuard 出站的使用介绍。",-1),E=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),V={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},H=t("p",null,"适配 Xray 的流量统计和脚本。",-1);function R(W,Z){const l=a("I18nTip"),o=a("RouterLink"),r=a("ExternalLinkIcon");return h(),_("div",null,[n(l),u,d,t("p",null,[n(o,{to:"/document/level-2/transparent_proxy/transparent_proxy.html"},{default:s(()=>[e("透明代理入门")]),_:1}),e(" by "),p,e(),t("a",m,[e("@kirin"),n(r)])]),g,t("p",null,[n(o,{to:"/document/level-2/tproxy.html"},{default:s(()=>[e("透明代理(TProxy)配置教程 ")]),_:1}),e(" by "),f,e(),t("a",b,[e("@BioniCosmos"),n(r)])]),y,t("p",null,[n(o,{to:"/document/level-2/tproxy_ipv4_and_ipv6.html"},{default:s(()=>[e("TProxy 透明代理(ipv4 and ipv6)配置教程")]),_:1}),e(" by "),v,e(),t("a",x,[e("@SQLimit"),n(r)])]),k,t("p",null,[n(o,{to:"/document/level-2/nginx_or_haproxy_tls_tunnel.html"},{default:s(()=>[e("Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹")]),_:1}),e(" by "),w,e(),t("a",X,[e("@SQLimit"),n(r)])]),L,t("p",null,[n(o,{to:"/document/level-2/iptables_gid.html"},{default:s(()=>[e("[透明代理]通过 gid 规避 Xray 流量")]),_:1}),e(" by "),T,e(),t("a",S,[e("@kirin"),n(r)])]),B,t("p",null,[n(o,{to:"/document/level-2/redirect.html"},{default:s(()=>[e("通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”")]),_:1}),e(" by "),C,e(),t("a",N,[e("@Zzz3m"),n(r)])]),z,t("p",null,[n(o,{to:"/document/level-2/warp.html"},{default:s(()=>[e("通过 Cloudflare Warp 增强代理安全性")]),_:1}),e(" by "),I,e(),t("a",P,[e("@yuhan6665"),n(r)])]),Q,t("p",null,[n(o,{to:"/document/level-2/traffic_stats.html"},{default:s(()=>[e("Xray 流量统计")]),_:1}),e(" by "),E,e(),t("a",V,[e("@yuhan6665"),n(r)])]),H])}const j=i(c,[["render",R],["__file","index.html.vue"]]);export{j as default};
                                        +import{_ as i,r as a,o as h,c as _,a as n,b as t,w as s,d as e}from"./app-Bw2NG-QJ.js";const c={},u=t("h1",{id:"进阶文档",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#进阶文档"},[t("span",null,"进阶文档")])],-1),d=t("p",null,[t("strong",null,"这个章节包含进阶级的 Xray 使用心得分享, 如果您已经熟悉 Xray, 那么这里的经验可以让您更加发挥 Xray 的威力")],-1),p=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),m={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},g=t("p",null,"透明代理的入门篇章。",-1),f=t("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32",height:"32",alt:"a"},null,-1),b={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},y=t("p",null,"基于 Xray 的透明代理(TProxy)配置完整教程。",-1),v=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),x={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},k=t("p",null,"基于 Xray 的 TProxy 透明代理(ipv4 and ipv6)配置教程",-1),w=t("img",{src:"https://avatars.githubusercontent.com/u/110686480?s=32",width:"32",height:"32",alt:"a"},null,-1),X={href:"https://github.com/SQLimit",target:"_blank",rel:"noopener noreferrer"},L=t("p",null,"双端使用 Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹",-1),T=t("img",{src:"https://avatars2.githubusercontent.com/u/57820613?s=32",width:"32",height:"32",alt:"a"},null,-1),S={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},B=t("p",null,"在 iptables/nftables 实现的透明代理中,一种新的规避 Xray 流量的方式。",-1),C=t("img",{src:"https://avatars.githubusercontent.com/u/28607089?s=32",width:"32",height:"32",alt:"a"},null,-1),N={href:"https://github.com/Zzz3m",target:"_blank",rel:"noopener noreferrer"},z=t("p",null,"将 Xray 玩出花:基于 fwmark 、 sendThrough 或 sockopt.interface 方式实现“分流”。",-1),I=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),P={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},Q=t("p",null,"Xray v1.6.5 新增 WireGuard 出站的使用介绍。",-1),E=t("img",{src:"https://avatars.githubusercontent.com/u/1588741?s=32",width:"32",height:"32",alt:"a"},null,-1),V={href:"https://github.com/yuhan6665",target:"_blank",rel:"noopener noreferrer"},H=t("p",null,"适配 Xray 的流量统计和脚本。",-1);function R(W,Z){const l=a("I18nTip"),o=a("RouterLink"),r=a("ExternalLinkIcon");return h(),_("div",null,[n(l),u,d,t("p",null,[n(o,{to:"/document/level-2/transparent_proxy/transparent_proxy.html"},{default:s(()=>[e("透明代理入门")]),_:1}),e(" by "),p,e(),t("a",m,[e("@kirin"),n(r)])]),g,t("p",null,[n(o,{to:"/document/level-2/tproxy.html"},{default:s(()=>[e("透明代理(TProxy)配置教程 ")]),_:1}),e(" by "),f,e(),t("a",b,[e("@BioniCosmos"),n(r)])]),y,t("p",null,[n(o,{to:"/document/level-2/tproxy_ipv4_and_ipv6.html"},{default:s(()=>[e("TProxy 透明代理(ipv4 and ipv6)配置教程")]),_:1}),e(" by "),v,e(),t("a",x,[e("@SQLimit"),n(r)])]),k,t("p",null,[n(o,{to:"/document/level-2/nginx_or_haproxy_tls_tunnel.html"},{default:s(()=>[e("Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹")]),_:1}),e(" by "),w,e(),t("a",X,[e("@SQLimit"),n(r)])]),L,t("p",null,[n(o,{to:"/document/level-2/iptables_gid.html"},{default:s(()=>[e("[透明代理]通过 gid 规避 Xray 流量")]),_:1}),e(" by "),T,e(),t("a",S,[e("@kirin"),n(r)])]),B,t("p",null,[n(o,{to:"/document/level-2/redirect.html"},{default:s(()=>[e("通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”")]),_:1}),e(" by "),C,e(),t("a",N,[e("@Zzz3m"),n(r)])]),z,t("p",null,[n(o,{to:"/document/level-2/warp.html"},{default:s(()=>[e("通过 Cloudflare Warp 增强代理安全性")]),_:1}),e(" by "),I,e(),t("a",P,[e("@yuhan6665"),n(r)])]),Q,t("p",null,[n(o,{to:"/document/level-2/traffic_stats.html"},{default:s(()=>[e("Xray 流量统计")]),_:1}),e(" by "),E,e(),t("a",V,[e("@yuhan6665"),n(r)])]),H])}const j=i(c,[["render",R],["__file","index.html.vue"]]);export{j as default};
                                        diff --git a/assets/index.html-DZgNInr6.js b/assets/index.html-CH7QpluO.js
                                        similarity index 94%
                                        rename from assets/index.html-DZgNInr6.js
                                        rename to assets/index.html-CH7QpluO.js
                                        index b694779652..7ecaa84cc9 100644
                                        --- a/assets/index.html-DZgNInr6.js
                                        +++ b/assets/index.html-CH7QpluO.js
                                        @@ -1 +1 @@
                                        -import{_ as r,r as a,o as s,c as u,a as t,b as e,w as n,d as o}from"./app-5SoadDYS.js";const d={},_=e("h1",{id:"入门技巧",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入门技巧"},[e("span",null,"入门技巧")])],-1),i=e("p",null,[e("strong",null,"这个章节是入门级的 Xray 使用心得分享,主要分享一些 Xray 常用功能模块的原理说明。")],-1);function m(p,f){const c=a("I18nTip"),l=a("RouterLink");return s(),u("div",null,[t(c),_,i,e("p",null,[t(l,{to:"/document/level-1/fallbacks-lv1.html"},{default:n(()=>[o("回落 (fallbacks) 功能简析")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/routing-lv1-part1.html"},{default:n(()=>[o("路由 (routing) 功能简析(上)")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/routing-lv1-part2.html"},{default:n(()=>[o("路由 (routing) 功能简析(下)")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/work.html"},{default:n(()=>[o("Xray 的工作模式简析")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/fallbacks-with-sni.html"},{default:n(()=>[o("通过 SNI 回落功能实现伪装与按域名分流")]),_:1})])])}const v=r(d,[["render",m],["__file","index.html.vue"]]);export{v as default};
                                        +import{_ as r,r as a,o as s,c as u,a as t,b as e,w as n,d as o}from"./app-Bw2NG-QJ.js";const d={},_=e("h1",{id:"入门技巧",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#入门技巧"},[e("span",null,"入门技巧")])],-1),i=e("p",null,[e("strong",null,"这个章节是入门级的 Xray 使用心得分享,主要分享一些 Xray 常用功能模块的原理说明。")],-1);function m(p,f){const c=a("I18nTip"),l=a("RouterLink");return s(),u("div",null,[t(c),_,i,e("p",null,[t(l,{to:"/document/level-1/fallbacks-lv1.html"},{default:n(()=>[o("回落 (fallbacks) 功能简析")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/routing-lv1-part1.html"},{default:n(()=>[o("路由 (routing) 功能简析(上)")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/routing-lv1-part2.html"},{default:n(()=>[o("路由 (routing) 功能简析(下)")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/work.html"},{default:n(()=>[o("Xray 的工作模式简析")]),_:1})]),e("p",null,[t(l,{to:"/document/level-1/fallbacks-with-sni.html"},{default:n(()=>[o("通过 SNI 回落功能实现伪装与按域名分流")]),_:1})])])}const v=r(d,[["render",m],["__file","index.html.vue"]]);export{v as default};
                                        diff --git a/assets/index.html-BIFt4COA.js b/assets/index.html-COWQPvSj.js
                                        similarity index 98%
                                        rename from assets/index.html-BIFt4COA.js
                                        rename to assets/index.html-COWQPvSj.js
                                        index 02b195c383..79f2b370d3 100644
                                        --- a/assets/index.html-BIFt4COA.js
                                        +++ b/assets/index.html-COWQPvSj.js
                                        @@ -1 +1 @@
                                        -import{_ as r,r as a,o as c,c as d,a as t,b as e,d as o,w as s}from"./app-5SoadDYS.js";const p={},h=e("h1",{id:"development-guide",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#development-guide"},[e("span",null,"Development Guide")])],-1),m=e("h2",{id:"compile-documentation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#compile-documentation"},[e("span",null,"Compile Documentation")])],-1),u=e("p",null,"Xray supports multiple platforms, and you can perform cross-compilation on various platforms by yourself.",-1),_=e("h2",{id:"design-concept",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#design-concept"},[e("span",null,"Design Concept")])],-1),f=e("p",null,"Xray kernel provides a platform for secondary development.",-1),v=e("p",null,"This section explains the design goals and architecture of Xray.",-1),g=e("h2",{id:"development-standards",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#development-standards"},[e("span",null,"Development Standards")])],-1),x=e("p",null,"This section outlines the guidelines to follow when obtaining code, developing, submitting PRs, as well as the relevant coding standards.",-1),b=e("h2",{id:"protocol-details",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#protocol-details"},[e("span",null,"Protocol Details")])],-1),y=e("p",null,"Xray uses many protocols, and you can obtain a detailed description of each protocol through various means.",-1),k={id:"vless-protocol",tabindex:"-1"},w={class:"header-anchor",href:"#vless-protocol"},P=e("p",null,"VLESS is a stateless lightweight transport protocol that can serve as a bridge between Xray clients and servers.",-1),C={id:"vmess-protocol",tabindex:"-1"},D={class:"header-anchor",href:"#vmess-protocol"},X=e("p",null,"VMess is an encrypted transport protocol that can act as a bridge between Xray clients and servers.",-1),V={id:"mux-cool-protocol",tabindex:"-1"},L={class:"header-anchor",href:"#mux-cool-protocol"},S=e("p",null,"Mux.Cool protocol is a multiplexing transport protocol used to transmit multiple independent data streams within an established data stream.",-1),E={id:"mkcp-protocol",tabindex:"-1"},T={class:"header-anchor",href:"#mkcp-protocol"},I={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"};function M(B,K){const l=a("I18nTip"),n=a("RouterLink"),i=a("ExternalLinkIcon");return c(),d("div",null,[t(l),h,m,u,e("p",null,[o("Please click "),t(n,{to:"/en/development/intro/compile.html"},{default:s(()=>[o("Compile Documentation")]),_:1}),o(" to view specific compile-related content.")]),_,f,v,e("p",null,[o("Please click "),t(n,{to:"/en/development/intro/design.html"},{default:s(()=>[o("Design Principles")]),_:1}),o(" to learn about the design goals and architecture of Xray.")]),g,x,e("p",null,[o("Please click "),t(n,{to:"/en/development/intro/guide.html"},{default:s(()=>[o("Development Specification")]),_:1}),o(" to view the guidelines that should be followed during Xray development.")]),b,y,e("h3",k,[e("a",w,[e("span",null,[t(n,{to:"/en/development/protocols/vless.html"},{default:s(()=>[o("VLESS Protocol")]),_:1})])])]),P,e("h3",C,[e("a",D,[e("span",null,[t(n,{to:"/en/development/protocols/vmess.html"},{default:s(()=>[o("VMess Protocol")]),_:1})])])]),X,e("h3",V,[e("a",L,[e("span",null,[t(n,{to:"/en/development/protocols/muxcool.html"},{default:s(()=>[o("Mux.Cool Protocol")]),_:1})])])]),S,e("h3",E,[e("a",T,[e("span",null,[t(n,{to:"/en/development/protocols/mkcp.html"},{default:s(()=>[o("mKCP Protocol")]),_:1})])])]),e("p",null,[o("mKCP is a stream transmission protocol modified from the "),e("a",I,[o("KCP protocol"),t(i)]),o(" that can transmit arbitrary data streams in order.")])])}const R=r(p,[["render",M],["__file","index.html.vue"]]);export{R as default};
                                        +import{_ as r,r as a,o as c,c as d,a as t,b as e,d as o,w as s}from"./app-Bw2NG-QJ.js";const p={},h=e("h1",{id:"development-guide",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#development-guide"},[e("span",null,"Development Guide")])],-1),m=e("h2",{id:"compile-documentation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#compile-documentation"},[e("span",null,"Compile Documentation")])],-1),u=e("p",null,"Xray supports multiple platforms, and you can perform cross-compilation on various platforms by yourself.",-1),_=e("h2",{id:"design-concept",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#design-concept"},[e("span",null,"Design Concept")])],-1),f=e("p",null,"Xray kernel provides a platform for secondary development.",-1),v=e("p",null,"This section explains the design goals and architecture of Xray.",-1),g=e("h2",{id:"development-standards",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#development-standards"},[e("span",null,"Development Standards")])],-1),x=e("p",null,"This section outlines the guidelines to follow when obtaining code, developing, submitting PRs, as well as the relevant coding standards.",-1),b=e("h2",{id:"protocol-details",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#protocol-details"},[e("span",null,"Protocol Details")])],-1),y=e("p",null,"Xray uses many protocols, and you can obtain a detailed description of each protocol through various means.",-1),k={id:"vless-protocol",tabindex:"-1"},w={class:"header-anchor",href:"#vless-protocol"},P=e("p",null,"VLESS is a stateless lightweight transport protocol that can serve as a bridge between Xray clients and servers.",-1),C={id:"vmess-protocol",tabindex:"-1"},D={class:"header-anchor",href:"#vmess-protocol"},X=e("p",null,"VMess is an encrypted transport protocol that can act as a bridge between Xray clients and servers.",-1),V={id:"mux-cool-protocol",tabindex:"-1"},L={class:"header-anchor",href:"#mux-cool-protocol"},S=e("p",null,"Mux.Cool protocol is a multiplexing transport protocol used to transmit multiple independent data streams within an established data stream.",-1),E={id:"mkcp-protocol",tabindex:"-1"},T={class:"header-anchor",href:"#mkcp-protocol"},I={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"};function M(B,K){const l=a("I18nTip"),n=a("RouterLink"),i=a("ExternalLinkIcon");return c(),d("div",null,[t(l),h,m,u,e("p",null,[o("Please click "),t(n,{to:"/en/development/intro/compile.html"},{default:s(()=>[o("Compile Documentation")]),_:1}),o(" to view specific compile-related content.")]),_,f,v,e("p",null,[o("Please click "),t(n,{to:"/en/development/intro/design.html"},{default:s(()=>[o("Design Principles")]),_:1}),o(" to learn about the design goals and architecture of Xray.")]),g,x,e("p",null,[o("Please click "),t(n,{to:"/en/development/intro/guide.html"},{default:s(()=>[o("Development Specification")]),_:1}),o(" to view the guidelines that should be followed during Xray development.")]),b,y,e("h3",k,[e("a",w,[e("span",null,[t(n,{to:"/en/development/protocols/vless.html"},{default:s(()=>[o("VLESS Protocol")]),_:1})])])]),P,e("h3",C,[e("a",D,[e("span",null,[t(n,{to:"/en/development/protocols/vmess.html"},{default:s(()=>[o("VMess Protocol")]),_:1})])])]),X,e("h3",V,[e("a",L,[e("span",null,[t(n,{to:"/en/development/protocols/muxcool.html"},{default:s(()=>[o("Mux.Cool Protocol")]),_:1})])])]),S,e("h3",E,[e("a",T,[e("span",null,[t(n,{to:"/en/development/protocols/mkcp.html"},{default:s(()=>[o("mKCP Protocol")]),_:1})])])]),e("p",null,[o("mKCP is a stream transmission protocol modified from the "),e("a",I,[o("KCP protocol"),t(i)]),o(" that can transmit arbitrary data streams in order.")])])}const R=r(p,[["render",M],["__file","index.html.vue"]]);export{R as default};
                                        diff --git a/assets/index.html--jsJa64m.js b/assets/index.html-CUkf34zC.js
                                        similarity index 98%
                                        rename from assets/index.html--jsJa64m.js
                                        rename to assets/index.html-CUkf34zC.js
                                        index 9f7bd94652..ba406d6eb7 100644
                                        --- a/assets/index.html--jsJa64m.js
                                        +++ b/assets/index.html-CUkf34zC.js
                                        @@ -1 +1 @@
                                        -import{_ as s,r as n,o as i,c,a as t,b as e,d as r,w as h,e as u}from"./app-5SoadDYS.js";const _={},d=u('

                                        XTLS ? Xray ? V2Ray ?

                                        XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.

                                        • Xray-core 是 v2ray-core 的超集,含更好的整体性能和 XTLS 等一系列增强,且完全兼容 v2ray-core 的功能及配置。
                                          • 只有一个可执行文件,含 ctl 的功能,run 为默认指令
                                          • 配置上完全兼容,环境变量和 API 对应要改为以 XRAY_ 开头
                                          • 全平台开放了裸协议的 ReadV
                                          • 提供完整的 VLESS & Trojan XTLS 支持,均有 ReadV
                                          • 提供了 XTLS 多种流控模式, 性能一骑绝尘!

                                        “配置兼容,整体更好”

                                        我们是谁?

                                        It doesn't matter who we are. What matters is that we will keep riding and never look back.

                                        帮助 Xray 变得更强

                                        欢迎帮助 Xray 变得更强!

                                        ',8),p=e("li",null,"🖥️ 帮助开发和测试 Xray, 提交高质量的 Pull request.",-1),X={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-core/discussions",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},f=e("li",null,"💬 在 Telegram 群帮助群友/灌水.",-1),g=e("li",null,[e("strong",null,"...事实上,每一份对 Xray 的支持都会让 Xray 变得更强大")],-1),y=e("h3",{id:"telegram",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#telegram"},[e("span",null,"Telegram")])],-1),x={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},k=e("ul",null,[e("li",null,"交流群可在底线之上随便水,不要撕逼,没有滥权。"),e("li",null,"有问题尽管随便问,知道的尽量回答。"),e("li",null,"禁政治,禁 NSFW")],-1),L={href:"https://t.me/projectXtls",target:"_blank",rel:"noopener noreferrer"},S=e("ul",null,[e("li",null,"发布 Project X 的最新资讯")],-1),T=e("h3",{id:"致谢",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#致谢"},[e("span",null,"致谢")])],-1),v=e("ul",null,[e("li",null,"感谢所有人的支持!"),e("li",null,"感谢各类脚本、Docker 镜像、客户端支持...感谢所有帮忙完善生态的大佬们!"),e("li",null,"感谢为 Xray 网站和文档添砖加瓦的朋友们."),e("li",null,"感谢提出有意义的建议和意见的朋友们."),e("li",null,"感谢 Telegram 群每一位帮助群友的朋友.")],-1),j=e("h3",{id:"更多关于-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#更多关于-project-x"},[e("span",null,"更多关于 Project X")])],-1),w=e("h3",{id:"license",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#license"},[e("span",null,"License")])],-1),V={href:"https://github.com/XTLS/Xray-core/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer"},I=e("h3",{id:"stargazers-over-time",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#stargazers-over-time"},[e("span",null,"Stargazers over time")])],-1),P={href:"https://starchart.cc/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},E=e("img",{src:"https://starchart.cc/XTLS/Xray-core.svg",alt:"Stargazers over time"},null,-1);function N(R,q){const a=n("I18nTip"),l=n("ExternalLinkIcon"),o=n("RouterLink");return i(),c("div",null,[t(a),d,e("ul",null,[p,e("li",null,[r("📩 在 "),e("a",X,[r("GitHub Issues"),t(l)]),r(" 或 "),e("a",b,[r("讨论区"),t(l)]),r("发起建设性或有意义的 issue 与 discussion.")]),e("li",null,[r("📝 写下您的使用心得并提交至 Xray 的 "),e("a",m,[r("文档网站"),t(l)]),r(".")]),f,g]),y,e("ul",null,[e("li",null,[e("p",null,[e("a",x,[r("Project X 交流群"),t(l)])]),k]),e("li",null,[e("p",null,[e("a",L,[r("Project X 频道"),t(l)])]),S])]),T,v,j,e("ul",null,[e("li",null,[r("如果你想知道更多关于 Project X 的足迹与成长, 请点击"),t(o,{to:"/about/news.html"},{default:h(()=>[r("这里")]),_:1})])]),w,e("p",null,[e("a",V,[r("Mozilla Public License Version 2.0"),t(l)])]),I,e("p",null,[e("a",P,[E,t(l)])])])}const B=s(_,[["render",N],["__file","index.html.vue"]]);export{B as default}; +import{_ as s,r as n,o as i,c,a as t,b as e,d as r,w as h,e as u}from"./app-Bw2NG-QJ.js";const _={},d=u('

                                        XTLS ? Xray ? V2Ray ?

                                        XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.

                                        • Xray-core 是 v2ray-core 的超集,含更好的整体性能和 XTLS 等一系列增强,且完全兼容 v2ray-core 的功能及配置。
                                          • 只有一个可执行文件,含 ctl 的功能,run 为默认指令
                                          • 配置上完全兼容,环境变量和 API 对应要改为以 XRAY_ 开头
                                          • 全平台开放了裸协议的 ReadV
                                          • 提供完整的 VLESS & Trojan XTLS 支持,均有 ReadV
                                          • 提供了 XTLS 多种流控模式, 性能一骑绝尘!

                                        “配置兼容,整体更好”

                                        我们是谁?

                                        It doesn't matter who we are. What matters is that we will keep riding and never look back.

                                        帮助 Xray 变得更强

                                        欢迎帮助 Xray 变得更强!

                                        ',8),p=e("li",null,"🖥️ 帮助开发和测试 Xray, 提交高质量的 Pull request.",-1),X={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-core/discussions",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},f=e("li",null,"💬 在 Telegram 群帮助群友/灌水.",-1),g=e("li",null,[e("strong",null,"...事实上,每一份对 Xray 的支持都会让 Xray 变得更强大")],-1),y=e("h3",{id:"telegram",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#telegram"},[e("span",null,"Telegram")])],-1),x={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},k=e("ul",null,[e("li",null,"交流群可在底线之上随便水,不要撕逼,没有滥权。"),e("li",null,"有问题尽管随便问,知道的尽量回答。"),e("li",null,"禁政治,禁 NSFW")],-1),L={href:"https://t.me/projectXtls",target:"_blank",rel:"noopener noreferrer"},S=e("ul",null,[e("li",null,"发布 Project X 的最新资讯")],-1),T=e("h3",{id:"致谢",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#致谢"},[e("span",null,"致谢")])],-1),v=e("ul",null,[e("li",null,"感谢所有人的支持!"),e("li",null,"感谢各类脚本、Docker 镜像、客户端支持...感谢所有帮忙完善生态的大佬们!"),e("li",null,"感谢为 Xray 网站和文档添砖加瓦的朋友们."),e("li",null,"感谢提出有意义的建议和意见的朋友们."),e("li",null,"感谢 Telegram 群每一位帮助群友的朋友.")],-1),j=e("h3",{id:"更多关于-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#更多关于-project-x"},[e("span",null,"更多关于 Project X")])],-1),w=e("h3",{id:"license",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#license"},[e("span",null,"License")])],-1),V={href:"https://github.com/XTLS/Xray-core/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer"},I=e("h3",{id:"stargazers-over-time",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#stargazers-over-time"},[e("span",null,"Stargazers over time")])],-1),P={href:"https://starchart.cc/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},E=e("img",{src:"https://starchart.cc/XTLS/Xray-core.svg",alt:"Stargazers over time"},null,-1);function N(R,q){const a=n("I18nTip"),l=n("ExternalLinkIcon"),o=n("RouterLink");return i(),c("div",null,[t(a),d,e("ul",null,[p,e("li",null,[r("📩 在 "),e("a",X,[r("GitHub Issues"),t(l)]),r(" 或 "),e("a",b,[r("讨论区"),t(l)]),r("发起建设性或有意义的 issue 与 discussion.")]),e("li",null,[r("📝 写下您的使用心得并提交至 Xray 的 "),e("a",m,[r("文档网站"),t(l)]),r(".")]),f,g]),y,e("ul",null,[e("li",null,[e("p",null,[e("a",x,[r("Project X 交流群"),t(l)])]),k]),e("li",null,[e("p",null,[e("a",L,[r("Project X 频道"),t(l)])]),S])]),T,v,j,e("ul",null,[e("li",null,[r("如果你想知道更多关于 Project X 的足迹与成长, 请点击"),t(o,{to:"/about/news.html"},{default:h(()=>[r("这里")]),_:1})])]),w,e("p",null,[e("a",V,[r("Mozilla Public License Version 2.0"),t(l)])]),I,e("p",null,[e("a",P,[E,t(l)])])])}const B=s(_,[["render",N],["__file","index.html.vue"]]);export{B as default}; diff --git a/assets/index.html-BIpYD3t-.js b/assets/index.html-Cskgq1zk.js similarity index 98% rename from assets/index.html-BIpYD3t-.js rename to assets/index.html-Cskgq1zk.js index 362dbc832f..f94b85e3d2 100644 --- a/assets/index.html-BIpYD3t-.js +++ b/assets/index.html-Cskgq1zk.js @@ -1 +1 @@ -import{_ as r,r as l,o as d,c as h,a as t,b as e,d as o,w as s}from"./app-5SoadDYS.js";const _={},i=e("h1",{id:"开发指南",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发指南"},[e("span",null,"开发指南")])],-1),p=e("h2",{id:"编译文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#编译文档"},[e("span",null,"编译文档")])],-1),u=e("p",null,"Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。",-1),m=e("h2",{id:"设计思路",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#设计思路"},[e("span",null,"设计思路")])],-1),f=e("p",null,"Xray 内核提供了一个平台,在其之上可以进二次开发。",-1),x=e("p",null,"这个章节阐述了 Xray 的设计目标和架构。",-1),v=e("h2",{id:"开发规范",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发规范"},[e("span",null,"开发规范")])],-1),b=e("p",null,"这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。",-1),k=e("h2",{id:"协议详解",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#协议详解"},[e("span",null,"协议详解")])],-1),y=e("p",null,"Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。",-1),X={id:"vless-协议",tabindex:"-1"},C={class:"header-anchor",href:"#vless-协议"},V=e("p",null,"VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),L={id:"vmess-协议",tabindex:"-1"},E={class:"header-anchor",href:"#vmess-协议"},g=e("p",null,"VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),I={id:"mux-cool-协议",tabindex:"-1"},M={class:"header-anchor",href:"#mux-cool-协议"},P=e("p",null,"Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。",-1),S={id:"mkcp-协议",tabindex:"-1"},w={class:"header-anchor",href:"#mkcp-协议"},B={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"};function K(N,R){const a=l("I18nTip"),n=l("RouterLink"),c=l("ExternalLinkIcon");return d(),h("div",null,[t(a),i,p,u,e("p",null,[o("请点击"),t(n,{to:"/ru/development/intro/compile.html"},{default:s(()=>[o("编译文档")]),_:1}),o("以查看具体编译相关内容。")]),m,f,x,e("p",null,[o("请点击"),t(n,{to:"/ru/development/intro/design.html"},{default:s(()=>[o("设计思路")]),_:1}),o("以了解 Xray 的设计目标和架构。")]),v,b,e("p",null,[o("请点击"),t(n,{to:"/ru/development/intro/guide.html"},{default:s(()=>[o("开发规范")]),_:1}),o("查看 Xray 开发中应遵循的准则。")]),k,y,e("h3",X,[e("a",C,[e("span",null,[t(n,{to:"/ru/development/protocols/vless.html"},{default:s(()=>[o("VLESS 协议")]),_:1})])])]),V,e("h3",L,[e("a",E,[e("span",null,[t(n,{to:"/ru/development/protocols/vmess.html"},{default:s(()=>[o("VMess 协议")]),_:1})])])]),g,e("h3",I,[e("a",M,[e("span",null,[t(n,{to:"/ru/development/protocols/muxcool.html"},{default:s(()=>[o("Mux.Cool 协议")]),_:1})])])]),P,e("h3",S,[e("a",w,[e("span",null,[t(n,{to:"/ru/development/protocols/mkcp.html"},{default:s(()=>[o("mKCP 协议")]),_:1})])])]),e("p",null,[o("mKCP 是流式传输协议,由 "),e("a",B,[o("KCP 协议"),t(c)]),o("修改而来,可以按顺序传输任意的数据流。")])])}const j=r(_,[["render",K],["__file","index.html.vue"]]);export{j as default}; +import{_ as r,r as l,o as d,c as h,a as t,b as e,d as o,w as s}from"./app-Bw2NG-QJ.js";const _={},i=e("h1",{id:"开发指南",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发指南"},[e("span",null,"开发指南")])],-1),p=e("h2",{id:"编译文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#编译文档"},[e("span",null,"编译文档")])],-1),u=e("p",null,"Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。",-1),m=e("h2",{id:"设计思路",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#设计思路"},[e("span",null,"设计思路")])],-1),f=e("p",null,"Xray 内核提供了一个平台,在其之上可以进二次开发。",-1),x=e("p",null,"这个章节阐述了 Xray 的设计目标和架构。",-1),v=e("h2",{id:"开发规范",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发规范"},[e("span",null,"开发规范")])],-1),b=e("p",null,"这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。",-1),k=e("h2",{id:"协议详解",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#协议详解"},[e("span",null,"协议详解")])],-1),y=e("p",null,"Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。",-1),X={id:"vless-协议",tabindex:"-1"},C={class:"header-anchor",href:"#vless-协议"},V=e("p",null,"VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),L={id:"vmess-协议",tabindex:"-1"},E={class:"header-anchor",href:"#vmess-协议"},g=e("p",null,"VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),I={id:"mux-cool-协议",tabindex:"-1"},M={class:"header-anchor",href:"#mux-cool-协议"},P=e("p",null,"Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。",-1),S={id:"mkcp-协议",tabindex:"-1"},w={class:"header-anchor",href:"#mkcp-协议"},B={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"};function K(N,R){const a=l("I18nTip"),n=l("RouterLink"),c=l("ExternalLinkIcon");return d(),h("div",null,[t(a),i,p,u,e("p",null,[o("请点击"),t(n,{to:"/ru/development/intro/compile.html"},{default:s(()=>[o("编译文档")]),_:1}),o("以查看具体编译相关内容。")]),m,f,x,e("p",null,[o("请点击"),t(n,{to:"/ru/development/intro/design.html"},{default:s(()=>[o("设计思路")]),_:1}),o("以了解 Xray 的设计目标和架构。")]),v,b,e("p",null,[o("请点击"),t(n,{to:"/ru/development/intro/guide.html"},{default:s(()=>[o("开发规范")]),_:1}),o("查看 Xray 开发中应遵循的准则。")]),k,y,e("h3",X,[e("a",C,[e("span",null,[t(n,{to:"/ru/development/protocols/vless.html"},{default:s(()=>[o("VLESS 协议")]),_:1})])])]),V,e("h3",L,[e("a",E,[e("span",null,[t(n,{to:"/ru/development/protocols/vmess.html"},{default:s(()=>[o("VMess 协议")]),_:1})])])]),g,e("h3",I,[e("a",M,[e("span",null,[t(n,{to:"/ru/development/protocols/muxcool.html"},{default:s(()=>[o("Mux.Cool 协议")]),_:1})])])]),P,e("h3",S,[e("a",w,[e("span",null,[t(n,{to:"/ru/development/protocols/mkcp.html"},{default:s(()=>[o("mKCP 协议")]),_:1})])])]),e("p",null,[o("mKCP 是流式传输协议,由 "),e("a",B,[o("KCP 协议"),t(c)]),o("修改而来,可以按顺序传输任意的数据流。")])])}const j=r(_,[["render",K],["__file","index.html.vue"]]);export{j as default}; diff --git a/assets/index.html-LItYxUPJ.js b/assets/index.html-Cy2gOIhe.js similarity index 98% rename from assets/index.html-LItYxUPJ.js rename to assets/index.html-Cy2gOIhe.js index 46ae992f56..c9679cbdae 100644 --- a/assets/index.html-LItYxUPJ.js +++ b/assets/index.html-Cy2gOIhe.js @@ -1 +1 @@ -import{_ as c,r as a,o as d,c as r,a as t,b as e,d as n,w as o}from"./app-5SoadDYS.js";const u={},h=e("h1",{id:"быстрыи-старт",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#быстрыи-старт"},[e("span",null,"Быстрый старт")])],-1),_=e("blockquote",null,[e("p",null,[e("strong",null,"В этой главе вы узнаете, как максимально просто получить Xray и начать его использовать.")])],-1),i=e("h2",{id:"загрузка-и-установка",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#загрузка-и-установка"},[e("span",null,"Загрузка и установка")])],-1),p=e("p",null,"Xray поддерживает разнообразные платформы, и вы можете получить разные версии Xray из множества источников и различными способами.",-1),m=e("h2",{id:"настроика-и-запуск",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#настроика-и-запуск"},[e("span",null,"Настройка и запуск")])],-1),f=e("p",null,"После загрузки и установки Xray вам нужно всего лишь настроить его, чтобы начать использование.",-1),x=e("h2",{id:"команды-и-аргументы",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#команды-и-аргументы"},[e("span",null,"Команды и аргументы")])],-1),b=e("p",null,"Xray обладает множеством команд и аргументов, что делает его гибким и мощным.",-1),X=e("h2",{id:"улучшение-документации",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#улучшение-документации"},[e("span",null,"Улучшение документации")])],-1),y=e("code",null,"Помогите нам улучшить эту страницу!",-1),v=e("p",null,"Мы очень благодарны каждому участнику за вклад! Вы делаете Project X сильнее!",-1),k=e("h2",{id:"простыми-словами",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#простыми-словами"},[e("span",null,"Простыми словами")])],-1),B=e("p",null,"Практические советы для новичков.",-1),N=e("h2",{id:"базовые-навыки",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#базовые-навыки"},[e("span",null,"Базовые навыки")])],-1),T=e("h2",{id:"продвинутая-документация",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#продвинутая-документация"},[e("span",null,"Продвинутая документация")])],-1),V=e("p",null,"Практические советы для опытных пользователей.",-1),g=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"Благодарность"),e("p",null,"Огромное спасибо всем за то, что делитесь своими навыками и опытом, которые делают Xray с каждым днем ​​лучше.")],-1);function w(C,I){const s=a("I18nTip"),l=a("RouterLink");return d(),r("div",null,[h,t(s),_,i,p,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/install.html"},{default:o(()=>[n("Загрузка и установка")]),_:1}),n(", чтобы загрузить Xray.")]),m,f,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/config.html"},{default:o(()=>[n("Настройка и запуск")]),_:1}),n(", чтобы изучить самый простой способ настройки.")]),x,b,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/command.html"},{default:o(()=>[n("Команды и аргументы")]),_:1}),n(", чтобы узнать больше о командах и аргументах Xray.")]),X,e("p",null,[n("Если вы заинтересованы, перейдите в раздел "),t(l,{to:"/ru/document/document.html"},{default:o(()=>[n("Использование документации")]),_:1}),n(", чтобы помочь нам улучшить документацию, или нажмите кнопку "),y,n(" внизу страницы.")]),v,k,B,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/level-0/"},{default:o(()=>[n("Простыми словами")]),_:1}),n(" для просмотра.")]),N,e("p",null,[n("Освоив основы, вы можете перейти к разделу "),t(l,{to:"/ru/document/level-1/"},{default:o(()=>[n("Базовые навыки")]),_:1}),n(", чтобы узнать о других способах использования.")]),T,V,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/level-2/"},{default:o(()=>[n("Продвинутая документация")]),_:1}),n(" для просмотра.")]),g])}const R=c(u,[["render",w],["__file","index.html.vue"]]);export{R as default}; +import{_ as c,r as a,o as d,c as r,a as t,b as e,d as n,w as o}from"./app-Bw2NG-QJ.js";const u={},h=e("h1",{id:"быстрыи-старт",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#быстрыи-старт"},[e("span",null,"Быстрый старт")])],-1),_=e("blockquote",null,[e("p",null,[e("strong",null,"В этой главе вы узнаете, как максимально просто получить Xray и начать его использовать.")])],-1),i=e("h2",{id:"загрузка-и-установка",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#загрузка-и-установка"},[e("span",null,"Загрузка и установка")])],-1),p=e("p",null,"Xray поддерживает разнообразные платформы, и вы можете получить разные версии Xray из множества источников и различными способами.",-1),m=e("h2",{id:"настроика-и-запуск",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#настроика-и-запуск"},[e("span",null,"Настройка и запуск")])],-1),f=e("p",null,"После загрузки и установки Xray вам нужно всего лишь настроить его, чтобы начать использование.",-1),x=e("h2",{id:"команды-и-аргументы",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#команды-и-аргументы"},[e("span",null,"Команды и аргументы")])],-1),b=e("p",null,"Xray обладает множеством команд и аргументов, что делает его гибким и мощным.",-1),X=e("h2",{id:"улучшение-документации",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#улучшение-документации"},[e("span",null,"Улучшение документации")])],-1),y=e("code",null,"Помогите нам улучшить эту страницу!",-1),v=e("p",null,"Мы очень благодарны каждому участнику за вклад! Вы делаете Project X сильнее!",-1),k=e("h2",{id:"простыми-словами",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#простыми-словами"},[e("span",null,"Простыми словами")])],-1),B=e("p",null,"Практические советы для новичков.",-1),N=e("h2",{id:"базовые-навыки",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#базовые-навыки"},[e("span",null,"Базовые навыки")])],-1),T=e("h2",{id:"продвинутая-документация",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#продвинутая-документация"},[e("span",null,"Продвинутая документация")])],-1),V=e("p",null,"Практические советы для опытных пользователей.",-1),g=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"Благодарность"),e("p",null,"Огромное спасибо всем за то, что делитесь своими навыками и опытом, которые делают Xray с каждым днем ​​лучше.")],-1);function w(C,I){const s=a("I18nTip"),l=a("RouterLink");return d(),r("div",null,[h,t(s),_,i,p,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/install.html"},{default:o(()=>[n("Загрузка и установка")]),_:1}),n(", чтобы загрузить Xray.")]),m,f,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/config.html"},{default:o(()=>[n("Настройка и запуск")]),_:1}),n(", чтобы изучить самый простой способ настройки.")]),x,b,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/command.html"},{default:o(()=>[n("Команды и аргументы")]),_:1}),n(", чтобы узнать больше о командах и аргументах Xray.")]),X,e("p",null,[n("Если вы заинтересованы, перейдите в раздел "),t(l,{to:"/ru/document/document.html"},{default:o(()=>[n("Использование документации")]),_:1}),n(", чтобы помочь нам улучшить документацию, или нажмите кнопку "),y,n(" внизу страницы.")]),v,k,B,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/level-0/"},{default:o(()=>[n("Простыми словами")]),_:1}),n(" для просмотра.")]),N,e("p",null,[n("Освоив основы, вы можете перейти к разделу "),t(l,{to:"/ru/document/level-1/"},{default:o(()=>[n("Базовые навыки")]),_:1}),n(", чтобы узнать о других способах использования.")]),T,V,e("p",null,[n("Перейдите в раздел "),t(l,{to:"/ru/document/level-2/"},{default:o(()=>[n("Продвинутая документация")]),_:1}),n(" для просмотра.")]),g])}const R=c(u,[["render",w],["__file","index.html.vue"]]);export{R as default}; diff --git a/assets/index.html-DdVCvmM2.js b/assets/index.html-D3N0ZGw7.js similarity index 97% rename from assets/index.html-DdVCvmM2.js rename to assets/index.html-D3N0ZGw7.js index a0bd3d38a3..a4c6bca411 100644 --- a/assets/index.html-DdVCvmM2.js +++ b/assets/index.html-D3N0ZGw7.js @@ -1 +1 @@ -import{_ as c,r as l,o as s,c as h,a as n,b as e,d as t,w as o}from"./app-5SoadDYS.js";const u={},p=e("h1",{id:"plain-and-simple-language",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#plain-and-simple-language"},[e("span",null,"Plain and Simple Language")])],-1),d=e("p",null,[e("strong",null,"This chapter is a basic lesson of [Starting from Scratch]. New students, please watch and learn carefully.")],-1),_={class:"custom-container tip"},m=e("p",{class:"custom-container-title"},"Tip",-1),f={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"[【Chapter 5】Website Construction] - Show Your Beauty (Link to webpage.md file)",-1),y=e("p",null,"[Chapter 9] Appendix - All the exam points are here.",-1);function b(v,x){const r=l("I18nTip"),i=l("ExternalLinkIcon"),a=l("RouterLink");return s(),h("div",null,[n(r),p,d,e("div",_,[m,e("p",null,[t("Made with ❤️ by "),e("a",f,[t("@ricuhkaen"),n(i)])])]),e("p",null,[n(a,{to:"/en/document/level-0/ch01-preface.html"},{default:o(()=>[t("【Chapter 1】 Preface: Rambling")]),_:1}),t(" - Airport or Self-built? That is the question.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch02-preparation.html"},{default:o(()=>[t("Chapter 2: Preparation of Raw Materials")]),_:1}),t(" - Tools must be sharpened before they can be used proficiently.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch03-ssh.html"},{default:o(()=>[t("Chapter 3: Remote Login")]),_:1}),t(" - A bridge connecting the north and south, turning a natural obstacle into a thoroughfare.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch04-security.html"},{default:o(()=>[t("【Chapter 4】Security Protection")]),_:1}),t(" - If you don't pay attention to security, you will shed tears for your loved ones.")]),g,e("p",null,[n(a,{to:"/en/document/level-0/ch06-certificates.html"},{default:o(()=>[t("Chapter 6: Certificate Management")]),_:1}),t(" - Only those who obtain certificates are considered legitimate.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch07-xray-server.html"},{default:o(()=>[t("Chapter 7: Xray Server")]),_:1}),t(" - Finally, waited for you.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch08-xray-clients.html"},{default:o(()=>[t("Chapter 8: Xray Client")]),_:1}),t(" - A New Beginning.")]),y])}const w=c(u,[["render",b],["__file","index.html.vue"]]);export{w as default}; +import{_ as c,r as l,o as s,c as h,a as n,b as e,d as t,w as o}from"./app-Bw2NG-QJ.js";const u={},p=e("h1",{id:"plain-and-simple-language",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#plain-and-simple-language"},[e("span",null,"Plain and Simple Language")])],-1),d=e("p",null,[e("strong",null,"This chapter is a basic lesson of [Starting from Scratch]. New students, please watch and learn carefully.")],-1),_={class:"custom-container tip"},m=e("p",{class:"custom-container-title"},"Tip",-1),f={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"[【Chapter 5】Website Construction] - Show Your Beauty (Link to webpage.md file)",-1),y=e("p",null,"[Chapter 9] Appendix - All the exam points are here.",-1);function b(v,x){const r=l("I18nTip"),i=l("ExternalLinkIcon"),a=l("RouterLink");return s(),h("div",null,[n(r),p,d,e("div",_,[m,e("p",null,[t("Made with ❤️ by "),e("a",f,[t("@ricuhkaen"),n(i)])])]),e("p",null,[n(a,{to:"/en/document/level-0/ch01-preface.html"},{default:o(()=>[t("【Chapter 1】 Preface: Rambling")]),_:1}),t(" - Airport or Self-built? That is the question.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch02-preparation.html"},{default:o(()=>[t("Chapter 2: Preparation of Raw Materials")]),_:1}),t(" - Tools must be sharpened before they can be used proficiently.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch03-ssh.html"},{default:o(()=>[t("Chapter 3: Remote Login")]),_:1}),t(" - A bridge connecting the north and south, turning a natural obstacle into a thoroughfare.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch04-security.html"},{default:o(()=>[t("【Chapter 4】Security Protection")]),_:1}),t(" - If you don't pay attention to security, you will shed tears for your loved ones.")]),g,e("p",null,[n(a,{to:"/en/document/level-0/ch06-certificates.html"},{default:o(()=>[t("Chapter 6: Certificate Management")]),_:1}),t(" - Only those who obtain certificates are considered legitimate.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch07-xray-server.html"},{default:o(()=>[t("Chapter 7: Xray Server")]),_:1}),t(" - Finally, waited for you.")]),e("p",null,[n(a,{to:"/en/document/level-0/ch08-xray-clients.html"},{default:o(()=>[t("Chapter 8: Xray Client")]),_:1}),t(" - A New Beginning.")]),y])}const w=c(u,[["render",b],["__file","index.html.vue"]]);export{w as default}; diff --git a/assets/index.html-ivJHL5hH.js b/assets/index.html-D9C7rXyK.js similarity index 99% rename from assets/index.html-ivJHL5hH.js rename to assets/index.html-D9C7rXyK.js index f88e1b6263..d487a2f2fe 100644 --- a/assets/index.html-ivJHL5hH.js +++ b/assets/index.html-D9C7rXyK.js @@ -1,4 +1,4 @@ -import{_ as l,r as e,o as u,c,a as t,b as n,d as s,w as o,e as i}from"./app-5SoadDYS.js";const r={},d=i(`

                                        这个章节将告诉您所有的 Xray 配置细节,掌握这些内容,在您手中 Xray 将发挥更大威力。

                                        概述

                                        Xray 的配置文件为 json 格式, 客户端和服务端的配置格式没有区别, 只是实际的配置内容不一样。
                                        形式如下:

                                        {
                                        +import{_ as l,r as e,o as u,c,a as t,b as n,d as s,w as o,e as i}from"./app-Bw2NG-QJ.js";const r={},d=i(`

                                        这个章节将告诉您所有的 Xray 配置细节,掌握这些内容,在您手中 Xray 将发挥更大威力。

                                        概述

                                        Xray 的配置文件为 json 格式, 客户端和服务端的配置格式没有区别, 只是实际的配置内容不一样。
                                        形式如下:

                                        {
                                           "log": {},
                                           "api": {},
                                           "dns": {},
                                        diff --git a/assets/index.html-BGNLRPzE.js b/assets/index.html-DAmXAAuC.js
                                        similarity index 98%
                                        rename from assets/index.html-BGNLRPzE.js
                                        rename to assets/index.html-DAmXAAuC.js
                                        index 2e4fb0ac4d..4428d68127 100644
                                        --- a/assets/index.html-BGNLRPzE.js
                                        +++ b/assets/index.html-DAmXAAuC.js
                                        @@ -1 +1 @@
                                        -import{_ as d,r as l,o as h,c as r,a as t,b as e,d as o,w as s}from"./app-5SoadDYS.js";const _={},i=e("h1",{id:"开发指南",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发指南"},[e("span",null,"开发指南")])],-1),p=e("h2",{id:"编译文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#编译文档"},[e("span",null,"编译文档")])],-1),u=e("p",null,"Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。",-1),m=e("h2",{id:"设计思路",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#设计思路"},[e("span",null,"设计思路")])],-1),f=e("p",null,"Xray 内核提供了一个平台,在其之上可以进二次开发。",-1),x=e("p",null,"这个章节阐述了 Xray 的设计目标和架构。",-1),v=e("h2",{id:"开发规范",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发规范"},[e("span",null,"开发规范")])],-1),b=e("p",null,"这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。",-1),k=e("h2",{id:"协议详解",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#协议详解"},[e("span",null,"协议详解")])],-1),y=e("p",null,"Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。",-1),X={id:"vless-协议",tabindex:"-1"},C={class:"header-anchor",href:"#vless-协议"},V=e("p",null,"VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),L={id:"vmess-协议",tabindex:"-1"},E={class:"header-anchor",href:"#vmess-协议"},g=e("p",null,"VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),I={id:"mux-cool-协议",tabindex:"-1"},M={class:"header-anchor",href:"#mux-cool-协议"},P=e("p",null,"Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。",-1),S={id:"mkcp-协议",tabindex:"-1"},w={class:"header-anchor",href:"#mkcp-协议"},B={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"};function K(N,R){const a=l("I18nTip"),n=l("RouterLink"),c=l("ExternalLinkIcon");return h(),r("div",null,[t(a),i,p,u,e("p",null,[o("请点击"),t(n,{to:"/development/intro/compile.html"},{default:s(()=>[o("编译文档")]),_:1}),o("以查看具体编译相关内容。")]),m,f,x,e("p",null,[o("请点击"),t(n,{to:"/development/intro/design.html"},{default:s(()=>[o("设计思路")]),_:1}),o("以了解 Xray 的设计目标和架构。")]),v,b,e("p",null,[o("请点击"),t(n,{to:"/development/intro/guide.html"},{default:s(()=>[o("开发规范")]),_:1}),o("查看 Xray 开发中应遵循的准则。")]),k,y,e("h3",X,[e("a",C,[e("span",null,[t(n,{to:"/development/protocols/vless.html"},{default:s(()=>[o("VLESS 协议")]),_:1})])])]),V,e("h3",L,[e("a",E,[e("span",null,[t(n,{to:"/development/protocols/vmess.html"},{default:s(()=>[o("VMess 协议")]),_:1})])])]),g,e("h3",I,[e("a",M,[e("span",null,[t(n,{to:"/development/protocols/muxcool.html"},{default:s(()=>[o("Mux.Cool 协议")]),_:1})])])]),P,e("h3",S,[e("a",w,[e("span",null,[t(n,{to:"/development/protocols/mkcp.html"},{default:s(()=>[o("mKCP 协议")]),_:1})])])]),e("p",null,[o("mKCP 是流式传输协议,由 "),e("a",B,[o("KCP 协议"),t(c)]),o("修改而来,可以按顺序传输任意的数据流。")])])}const j=d(_,[["render",K],["__file","index.html.vue"]]);export{j as default};
                                        +import{_ as d,r as l,o as h,c as r,a as t,b as e,d as o,w as s}from"./app-Bw2NG-QJ.js";const _={},i=e("h1",{id:"开发指南",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发指南"},[e("span",null,"开发指南")])],-1),p=e("h2",{id:"编译文档",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#编译文档"},[e("span",null,"编译文档")])],-1),u=e("p",null,"Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。",-1),m=e("h2",{id:"设计思路",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#设计思路"},[e("span",null,"设计思路")])],-1),f=e("p",null,"Xray 内核提供了一个平台,在其之上可以进二次开发。",-1),x=e("p",null,"这个章节阐述了 Xray 的设计目标和架构。",-1),v=e("h2",{id:"开发规范",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#开发规范"},[e("span",null,"开发规范")])],-1),b=e("p",null,"这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。",-1),k=e("h2",{id:"协议详解",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#协议详解"},[e("span",null,"协议详解")])],-1),y=e("p",null,"Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。",-1),X={id:"vless-协议",tabindex:"-1"},C={class:"header-anchor",href:"#vless-协议"},V=e("p",null,"VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),L={id:"vmess-协议",tabindex:"-1"},E={class:"header-anchor",href:"#vmess-协议"},g=e("p",null,"VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。",-1),I={id:"mux-cool-协议",tabindex:"-1"},M={class:"header-anchor",href:"#mux-cool-协议"},P=e("p",null,"Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。",-1),S={id:"mkcp-协议",tabindex:"-1"},w={class:"header-anchor",href:"#mkcp-协议"},B={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"};function K(N,R){const a=l("I18nTip"),n=l("RouterLink"),c=l("ExternalLinkIcon");return h(),r("div",null,[t(a),i,p,u,e("p",null,[o("请点击"),t(n,{to:"/development/intro/compile.html"},{default:s(()=>[o("编译文档")]),_:1}),o("以查看具体编译相关内容。")]),m,f,x,e("p",null,[o("请点击"),t(n,{to:"/development/intro/design.html"},{default:s(()=>[o("设计思路")]),_:1}),o("以了解 Xray 的设计目标和架构。")]),v,b,e("p",null,[o("请点击"),t(n,{to:"/development/intro/guide.html"},{default:s(()=>[o("开发规范")]),_:1}),o("查看 Xray 开发中应遵循的准则。")]),k,y,e("h3",X,[e("a",C,[e("span",null,[t(n,{to:"/development/protocols/vless.html"},{default:s(()=>[o("VLESS 协议")]),_:1})])])]),V,e("h3",L,[e("a",E,[e("span",null,[t(n,{to:"/development/protocols/vmess.html"},{default:s(()=>[o("VMess 协议")]),_:1})])])]),g,e("h3",I,[e("a",M,[e("span",null,[t(n,{to:"/development/protocols/muxcool.html"},{default:s(()=>[o("Mux.Cool 协议")]),_:1})])])]),P,e("h3",S,[e("a",w,[e("span",null,[t(n,{to:"/development/protocols/mkcp.html"},{default:s(()=>[o("mKCP 协议")]),_:1})])])]),e("p",null,[o("mKCP 是流式传输协议,由 "),e("a",B,[o("KCP 协议"),t(c)]),o("修改而来,可以按顺序传输任意的数据流。")])])}const j=d(_,[["render",K],["__file","index.html.vue"]]);export{j as default};
                                        diff --git a/assets/index.html-BmR8xWDg.js b/assets/index.html-DLfjpS8M.js
                                        similarity index 94%
                                        rename from assets/index.html-BmR8xWDg.js
                                        rename to assets/index.html-DLfjpS8M.js
                                        index e6da8f7cfe..98c35ce658 100644
                                        --- a/assets/index.html-BmR8xWDg.js
                                        +++ b/assets/index.html-DLfjpS8M.js
                                        @@ -1 +1 @@
                                        -import{_ as i,r as s,o as r,c,a as e,b as n,w as l,d as o}from"./app-5SoadDYS.js";const u={},d=n("h1",{id:"beginner-s-tips",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#beginner-s-tips"},[n("span",null,"Beginner's Tips")])],-1),m=n("p",null,[n("strong",null,"This chapter is an introductory level guide on using Xray, mainly sharing the principles of some commonly used functional modules in Xray.")],-1);function _(p,f){const a=s("I18nTip"),t=s("RouterLink");return r(),c("div",null,[e(a),d,m,n("p",null,[e(t,{to:"/en/document/level-1/fallbacks-lv1.html"},{default:l(()=>[o("Analysis of Fallbacks Function")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/routing-lv1-part1.html"},{default:l(()=>[o("Analysis of Routing Function (Part 1)")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/routing-lv1-part2.html"},{default:l(()=>[o("Analysis of Routing Function (Part 2)")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/work.html"},{default:l(()=>[o("Analysis of Xray's Working Mode")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/fallbacks-with-sni.html"},{default:l(()=>[o("Fallbacks with SNI for Disguising and Domain-based Routing")]),_:1})])])}const g=i(u,[["render",_],["__file","index.html.vue"]]);export{g as default};
                                        +import{_ as i,r as s,o as r,c,a as e,b as n,w as l,d as o}from"./app-Bw2NG-QJ.js";const u={},d=n("h1",{id:"beginner-s-tips",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#beginner-s-tips"},[n("span",null,"Beginner's Tips")])],-1),m=n("p",null,[n("strong",null,"This chapter is an introductory level guide on using Xray, mainly sharing the principles of some commonly used functional modules in Xray.")],-1);function _(p,f){const a=s("I18nTip"),t=s("RouterLink");return r(),c("div",null,[e(a),d,m,n("p",null,[e(t,{to:"/en/document/level-1/fallbacks-lv1.html"},{default:l(()=>[o("Analysis of Fallbacks Function")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/routing-lv1-part1.html"},{default:l(()=>[o("Analysis of Routing Function (Part 1)")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/routing-lv1-part2.html"},{default:l(()=>[o("Analysis of Routing Function (Part 2)")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/work.html"},{default:l(()=>[o("Analysis of Xray's Working Mode")]),_:1})]),n("p",null,[e(t,{to:"/en/document/level-1/fallbacks-with-sni.html"},{default:l(()=>[o("Fallbacks with SNI for Disguising and Domain-based Routing")]),_:1})])])}const g=i(u,[["render",_],["__file","index.html.vue"]]);export{g as default};
                                        diff --git a/assets/index.html-CeWvtNHc.js b/assets/index.html-DPZpGJBw.js
                                        similarity index 99%
                                        rename from assets/index.html-CeWvtNHc.js
                                        rename to assets/index.html-DPZpGJBw.js
                                        index 9abeaa3d11..b0bd937d8a 100644
                                        --- a/assets/index.html-CeWvtNHc.js
                                        +++ b/assets/index.html-DPZpGJBw.js
                                        @@ -1 +1 @@
                                        -import{_ as s,r as n,o as c,c as i,a as l,b as e,d as r,w as h,e as u}from"./app-5SoadDYS.js";const _={},d=u('

                                        XTLS? Xray? V2Ray?

                                        XTLS — это блестящая идея для TLS, которую мы изучаем, в то время как Xray — это лучшая практика, которую мы поддерживаем.

                                        • Xray-core - это расширенная версия v2ray-core с улучшенной общей производительностью, включающая XTLS и другие улучшения. Xray-core полностью совместим с функциональностью и конфигурацией v2ray-core.
                                          • Только один исполняемый файл, включающий функциональность ctl, команда run используется по умолчанию.
                                          • Конфигурация полностью совместима, переменные среды и вызовы API должны начинаться с XRAY_
                                          • Открытый raw протокол ReadV на всех платформах.
                                          • Обеспечивает полную поддержку VLESS и Trojan XTLS, обе с ReadV.
                                          • Предоставляет несколько режимов управления потоком XTLS, непревзойденная производительность!

                                        Конфигурация без изменений, результат — значительно лучше.

                                        Кто мы?

                                        Неважно, кто мы. Важно то, что мы будем продолжать двигаться вперед и никогда не оглядываться назад.

                                        Помогите Xray стать сильнее

                                        Мы будем рады вашей помощи в развитии Xray!

                                        ',8),p=e("li",null,"🖥️ Помогите в разработке и тестировании Xray, отправляйте качественные запросы на включение (Pull Request).",-1),X={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-core/discussions",target:"_blank",rel:"noopener noreferrer"},f={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,"💬 Помогите участникам группы / общайтесь в группе Telegram.",-1),x=e("li",null,[e("strong",null,"... На самом деле, любая поддержка Xray сделает его сильнее.")],-1),y=e("h3",{id:"telegram",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#telegram"},[e("span",null,"Telegram")])],-1),m={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},L=e("ul",null,[e("li",null,"В группе обсуждения можно свободно общаться, не допускаются оскорбления и злоупотребления."),e("li",null,"Не стесняйтесь задавать вопросы, а если знаете ответ - помогите другим."),e("li",null,"Запрещены политика и контент для взрослых (NSFW).")],-1),T={href:"https://t.me/projectXtls",target:"_blank",rel:"noopener noreferrer"},k=e("ul",null,[e("li",null,"Публикация последних новостей о Project X.")],-1),S=e("h3",{id:"благодарности",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#благодарности"},[e("span",null,"Благодарности")])],-1),j=e("ul",null,[e("li",null,"Спасибо всем за вашу поддержку!"),e("li",null,"Спасибо создателям всевозможных скриптов, образов Docker, клиентам... Спасибо всем, кто помогает улучшать экосистему!"),e("li",null,"Спасибо всем, кто вносит свой вклад в веб-сайт и документацию Xray."),e("li",null,"Спасибо всем, кто высказывает ценные предложения и замечания."),e("li",null,"Спасибо каждому участнику группы Telegram, который помогает другим.")],-1),v=e("h3",{id:"подробнее-о-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#подробнее-о-project-x"},[e("span",null,"Подробнее о Project X")])],-1),V=e("h3",{id:"лицензия",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#лицензия"},[e("span",null,"Лицензия")])],-1),P={href:"https://github.com/XTLS/Xray-core/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer"},I=e("h3",{id:"динамика-звезд-на-github",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#динамика-звезд-на-github"},[e("span",null,"Динамика звезд на GitHub")])],-1),R={href:"https://starchart.cc/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},E=e("img",{src:"https://starchart.cc/XTLS/Xray-core.svg",alt:"Stargazers over time"},null,-1);function N(q,w){const a=n("I18nTip"),t=n("ExternalLinkIcon"),o=n("RouterLink");return c(),i("div",null,[l(a),d,e("ul",null,[p,e("li",null,[r("📩 Создавайте конструктивные или важные задачи и обсуждения в "),e("a",X,[r("GitHub Issues"),l(t)]),r(" или "),e("a",b,[r("Discussion area"),l(t)]),r(".")]),e("li",null,[r("📝 Поделитесь своим опытом использования и отправьте его на "),e("a",f,[r("сайт документации"),l(t)]),r(" Xray.")]),g,x]),y,e("ul",null,[e("li",null,[e("p",null,[e("a",m,[r("Группа обсуждения Project X"),l(t)])]),L]),e("li",null,[e("p",null,[e("a",T,[r("Канал Project X"),l(t)])]),k])]),S,j,v,e("ul",null,[e("li",null,[r("Если вы хотите узнать больше об истории и развитии Project X, нажмите "),l(o,{to:"/ru/about/news.html"},{default:h(()=>[r("здесь")]),_:1})])]),V,e("p",null,[e("a",P,[r("Mozilla Public License Version 2.0"),l(t)])]),I,e("p",null,[e("a",R,[E,l(t)])])])}const C=s(_,[["render",N],["__file","index.html.vue"]]);export{C as default}; +import{_ as s,r as n,o as c,c as i,a as l,b as e,d as r,w as h,e as u}from"./app-Bw2NG-QJ.js";const _={},d=u('

                                        XTLS? Xray? V2Ray?

                                        XTLS — это блестящая идея для TLS, которую мы изучаем, в то время как Xray — это лучшая практика, которую мы поддерживаем.

                                        • Xray-core - это расширенная версия v2ray-core с улучшенной общей производительностью, включающая XTLS и другие улучшения. Xray-core полностью совместим с функциональностью и конфигурацией v2ray-core.
                                          • Только один исполняемый файл, включающий функциональность ctl, команда run используется по умолчанию.
                                          • Конфигурация полностью совместима, переменные среды и вызовы API должны начинаться с XRAY_
                                          • Открытый raw протокол ReadV на всех платформах.
                                          • Обеспечивает полную поддержку VLESS и Trojan XTLS, обе с ReadV.
                                          • Предоставляет несколько режимов управления потоком XTLS, непревзойденная производительность!

                                        Конфигурация без изменений, результат — значительно лучше.

                                        Кто мы?

                                        Неважно, кто мы. Важно то, что мы будем продолжать двигаться вперед и никогда не оглядываться назад.

                                        Помогите Xray стать сильнее

                                        Мы будем рады вашей помощи в развитии Xray!

                                        ',8),p=e("li",null,"🖥️ Помогите в разработке и тестировании Xray, отправляйте качественные запросы на включение (Pull Request).",-1),X={href:"https://github.com/XTLS/Xray-core/issues",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/XTLS/Xray-core/discussions",target:"_blank",rel:"noopener noreferrer"},f={href:"https://github.com/XTLS/Xray-docs-next",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,"💬 Помогите участникам группы / общайтесь в группе Telegram.",-1),x=e("li",null,[e("strong",null,"... На самом деле, любая поддержка Xray сделает его сильнее.")],-1),y=e("h3",{id:"telegram",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#telegram"},[e("span",null,"Telegram")])],-1),m={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},L=e("ul",null,[e("li",null,"В группе обсуждения можно свободно общаться, не допускаются оскорбления и злоупотребления."),e("li",null,"Не стесняйтесь задавать вопросы, а если знаете ответ - помогите другим."),e("li",null,"Запрещены политика и контент для взрослых (NSFW).")],-1),T={href:"https://t.me/projectXtls",target:"_blank",rel:"noopener noreferrer"},k=e("ul",null,[e("li",null,"Публикация последних новостей о Project X.")],-1),S=e("h3",{id:"благодарности",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#благодарности"},[e("span",null,"Благодарности")])],-1),j=e("ul",null,[e("li",null,"Спасибо всем за вашу поддержку!"),e("li",null,"Спасибо создателям всевозможных скриптов, образов Docker, клиентам... Спасибо всем, кто помогает улучшать экосистему!"),e("li",null,"Спасибо всем, кто вносит свой вклад в веб-сайт и документацию Xray."),e("li",null,"Спасибо всем, кто высказывает ценные предложения и замечания."),e("li",null,"Спасибо каждому участнику группы Telegram, который помогает другим.")],-1),v=e("h3",{id:"подробнее-о-project-x",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#подробнее-о-project-x"},[e("span",null,"Подробнее о Project X")])],-1),V=e("h3",{id:"лицензия",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#лицензия"},[e("span",null,"Лицензия")])],-1),P={href:"https://github.com/XTLS/Xray-core/blob/main/LICENSE",target:"_blank",rel:"noopener noreferrer"},I=e("h3",{id:"динамика-звезд-на-github",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#динамика-звезд-на-github"},[e("span",null,"Динамика звезд на GitHub")])],-1),R={href:"https://starchart.cc/XTLS/Xray-core",target:"_blank",rel:"noopener noreferrer"},E=e("img",{src:"https://starchart.cc/XTLS/Xray-core.svg",alt:"Stargazers over time"},null,-1);function N(q,w){const a=n("I18nTip"),t=n("ExternalLinkIcon"),o=n("RouterLink");return c(),i("div",null,[l(a),d,e("ul",null,[p,e("li",null,[r("📩 Создавайте конструктивные или важные задачи и обсуждения в "),e("a",X,[r("GitHub Issues"),l(t)]),r(" или "),e("a",b,[r("Discussion area"),l(t)]),r(".")]),e("li",null,[r("📝 Поделитесь своим опытом использования и отправьте его на "),e("a",f,[r("сайт документации"),l(t)]),r(" Xray.")]),g,x]),y,e("ul",null,[e("li",null,[e("p",null,[e("a",m,[r("Группа обсуждения Project X"),l(t)])]),L]),e("li",null,[e("p",null,[e("a",T,[r("Канал Project X"),l(t)])]),k])]),S,j,v,e("ul",null,[e("li",null,[r("Если вы хотите узнать больше об истории и развитии Project X, нажмите "),l(o,{to:"/ru/about/news.html"},{default:h(()=>[r("здесь")]),_:1})])]),V,e("p",null,[e("a",P,[r("Mozilla Public License Version 2.0"),l(t)])]),I,e("p",null,[e("a",R,[E,l(t)])])])}const C=s(_,[["render",N],["__file","index.html.vue"]]);export{C as default}; diff --git a/assets/index.html-YDY07G7e.js b/assets/index.html-DYkoE7_u.js similarity index 96% rename from assets/index.html-YDY07G7e.js rename to assets/index.html-DYkoE7_u.js index efca2ac536..5c1a08fc57 100644 --- a/assets/index.html-YDY07G7e.js +++ b/assets/index.html-DYkoE7_u.js @@ -1 +1 @@ -import{_ as u,r as a,o as c,c as s,a as t,b as e,w as n,d as o}from"./app-5SoadDYS.js";const d={},_=e("h1",{id:"советы-для-начинающих",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#советы-для-начинающих"},[e("span",null,"Советы для начинающих")])],-1),i=e("p",null,[e("strong",null,"В этой главе вы найдете советы по использованию Xray для начинающих, в основном с описанием принципов работы часто используемых модулей Xray.")],-1);function m(p,h){const r=a("I18nTip"),l=a("RouterLink");return c(),s("div",null,[t(r),_,i,e("p",null,[t(l,{to:"/ru/document/level-1/fallbacks-lv1.html"},{default:n(()=>[o("Обзор функции Fallback")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/routing-lv1-part1.html"},{default:n(()=>[o("Обзор функции маршрутизации (routing) (часть 1)")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/routing-lv1-part2.html"},{default:n(()=>[o("Обзор функции маршрутизации (routing) (часть 2)")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/work.html"},{default:n(()=>[o("Обзор режимов работы Xray")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/fallbacks-with-sni.html"},{default:n(()=>[o("Маскировка и разделение трафика по доменам с помощью функции SNI Fallback")]),_:1})])])}const v=u(d,[["render",m],["__file","index.html.vue"]]);export{v as default}; +import{_ as u,r as a,o as c,c as s,a as t,b as e,w as n,d as o}from"./app-Bw2NG-QJ.js";const d={},_=e("h1",{id:"советы-для-начинающих",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#советы-для-начинающих"},[e("span",null,"Советы для начинающих")])],-1),i=e("p",null,[e("strong",null,"В этой главе вы найдете советы по использованию Xray для начинающих, в основном с описанием принципов работы часто используемых модулей Xray.")],-1);function m(p,h){const r=a("I18nTip"),l=a("RouterLink");return c(),s("div",null,[t(r),_,i,e("p",null,[t(l,{to:"/ru/document/level-1/fallbacks-lv1.html"},{default:n(()=>[o("Обзор функции Fallback")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/routing-lv1-part1.html"},{default:n(()=>[o("Обзор функции маршрутизации (routing) (часть 1)")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/routing-lv1-part2.html"},{default:n(()=>[o("Обзор функции маршрутизации (routing) (часть 2)")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/work.html"},{default:n(()=>[o("Обзор режимов работы Xray")]),_:1})]),e("p",null,[t(l,{to:"/ru/document/level-1/fallbacks-with-sni.html"},{default:n(()=>[o("Маскировка и разделение трафика по доменам с помощью функции SNI Fallback")]),_:1})])])}const v=u(d,[["render",m],["__file","index.html.vue"]]);export{v as default}; diff --git a/assets/index.html-NLmGgv-K.js b/assets/index.html-DyQaOch3.js similarity index 99% rename from assets/index.html-NLmGgv-K.js rename to assets/index.html-DyQaOch3.js index 2c0c30f39a..7fa75852c6 100644 --- a/assets/index.html-NLmGgv-K.js +++ b/assets/index.html-DyQaOch3.js @@ -1,4 +1,4 @@ -import{_ as l,r as e,o as u,c,a as t,b as n,d as s,w as o,e as r}from"./app-5SoadDYS.js";const i={},d=r(`

                                        В этом разделе вы узнаете все детали настройки Xray. Овладев этими знаниями, вы сможете раскрыть весь потенциал Xray.

                                        Обзор

                                        Конфигурационный файл Xray имеет формат JSON. Формат конфигурации одинаков для клиента и сервера, но фактическое содержимое отличается.
                                        Он выглядит следующим образом:

                                        {
                                        +import{_ as l,r as e,o as u,c,a as t,b as n,d as s,w as o,e as r}from"./app-Bw2NG-QJ.js";const i={},d=r(`

                                        В этом разделе вы узнаете все детали настройки Xray. Овладев этими знаниями, вы сможете раскрыть весь потенциал Xray.

                                        Обзор

                                        Конфигурационный файл Xray имеет формат JSON. Формат конфигурации одинаков для клиента и сервера, но фактическое содержимое отличается.
                                        Он выглядит следующим образом:

                                        {
                                           "log": {},
                                           "api": {},
                                           "dns": {},
                                        diff --git a/assets/infoDiagram-94cd232f-I6ioXWcf.js b/assets/infoDiagram-94cd232f-Don6DG4Z.js
                                        similarity index 98%
                                        rename from assets/infoDiagram-94cd232f-I6ioXWcf.js
                                        rename to assets/infoDiagram-94cd232f-Don6DG4Z.js
                                        index ec9a0e400b..cb98d486e1 100644
                                        --- a/assets/infoDiagram-94cd232f-I6ioXWcf.js
                                        +++ b/assets/infoDiagram-94cd232f-Don6DG4Z.js
                                        @@ -1,4 +1,4 @@
                                        -import{l as Y,aJ as D,i as M}from"./mermaid.core-CArNAncI.js";import"./app-5SoadDYS.js";var O=function(){var a=function(u,t,e,n){for(e=e||{},n=u.length;n--;e[u[n]]=t);return e},f=[6,9,10],m={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(t,e,n,s,r,i,d){switch(i.length-1,r){case 1:return s;case 4:break;case 6:s.setInfo(!0);break}},table:[{3:1,4:[1,2]},{1:[3]},a(f,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},a(f,[2,3]),a(f,[2,4]),a(f,[2,5]),a(f,[2,6])],defaultActions:{4:[2,1]},parseError:function(t,e){if(e.recoverable)this.trace(t);else{var n=new Error(t);throw n.hash=e,n}},parse:function(t){var e=this,n=[0],s=[],r=[null],i=[],d=this.table,P="",v=0,L=0,N=2,T=1,R=i.slice.call(arguments,1),o=Object.create(this.lexer),p={yy:{}};for(var E in this.yy)Object.prototype.hasOwnProperty.call(this.yy,E)&&(p.yy[E]=this.yy[E]);o.setInput(t,p.yy),p.yy.lexer=o,p.yy.parser=this,typeof o.yylloc>"u"&&(o.yylloc={});var I=o.yylloc;i.push(I);var z=o.options&&o.options.ranges;typeof p.yy.parseError=="function"?this.parseError=p.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function U(){var y;return y=s.pop()||o.lex()||T,typeof y!="number"&&(y instanceof Array&&(s=y,y=s.pop()),y=e.symbols_[y]||y),y}for(var l,g,h,w,_={},b,c,F,S;;){if(g=n[n.length-1],this.defaultActions[g]?h=this.defaultActions[g]:((l===null||typeof l>"u")&&(l=U()),h=d[g]&&d[g][l]),typeof h>"u"||!h.length||!h[0]){var A="";S=[];for(b in d[g])this.terminals_[b]&&b>N&&S.push("'"+this.terminals_[b]+"'");o.showPosition?A="Parse error on line "+(v+1)+`:
                                        +import{l as Y,aJ as D,i as M}from"./mermaid.core-Bq0kX0MS.js";import"./app-Bw2NG-QJ.js";var O=function(){var a=function(u,t,e,n){for(e=e||{},n=u.length;n--;e[u[n]]=t);return e},f=[6,9,10],m={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(t,e,n,s,r,i,d){switch(i.length-1,r){case 1:return s;case 4:break;case 6:s.setInfo(!0);break}},table:[{3:1,4:[1,2]},{1:[3]},a(f,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},a(f,[2,3]),a(f,[2,4]),a(f,[2,5]),a(f,[2,6])],defaultActions:{4:[2,1]},parseError:function(t,e){if(e.recoverable)this.trace(t);else{var n=new Error(t);throw n.hash=e,n}},parse:function(t){var e=this,n=[0],s=[],r=[null],i=[],d=this.table,P="",v=0,L=0,N=2,T=1,R=i.slice.call(arguments,1),o=Object.create(this.lexer),p={yy:{}};for(var E in this.yy)Object.prototype.hasOwnProperty.call(this.yy,E)&&(p.yy[E]=this.yy[E]);o.setInput(t,p.yy),p.yy.lexer=o,p.yy.parser=this,typeof o.yylloc>"u"&&(o.yylloc={});var I=o.yylloc;i.push(I);var z=o.options&&o.options.ranges;typeof p.yy.parseError=="function"?this.parseError=p.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function U(){var y;return y=s.pop()||o.lex()||T,typeof y!="number"&&(y instanceof Array&&(s=y,y=s.pop()),y=e.symbols_[y]||y),y}for(var l,g,h,w,_={},b,c,F,S;;){if(g=n[n.length-1],this.defaultActions[g]?h=this.defaultActions[g]:((l===null||typeof l>"u")&&(l=U()),h=d[g]&&d[g][l]),typeof h>"u"||!h.length||!h[0]){var A="";S=[];for(b in d[g])this.terminals_[b]&&b>N&&S.push("'"+this.terminals_[b]+"'");o.showPosition?A="Parse error on line "+(v+1)+`:
                                         `+o.showPosition()+`
                                         Expecting `+S.join(", ")+", got '"+(this.terminals_[l]||l)+"'":A="Parse error on line "+(v+1)+": Unexpected "+(l==T?"end of input":"'"+(this.terminals_[l]||l)+"'"),this.parseError(A,{text:o.match,token:this.terminals_[l]||l,line:o.yylineno,loc:I,expected:S})}if(h[0]instanceof Array&&h.length>1)throw new Error("Parse Error: multiple actions possible at state: "+g+", token: "+l);switch(h[0]){case 1:n.push(l),r.push(o.yytext),i.push(o.yylloc),n.push(h[1]),l=null,L=o.yyleng,P=o.yytext,v=o.yylineno,I=o.yylloc;break;case 2:if(c=this.productions_[h[1]][1],_.$=r[r.length-c],_._$={first_line:i[i.length-(c||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(c||1)].first_column,last_column:i[i.length-1].last_column},z&&(_._$.range=[i[i.length-(c||1)].range[0],i[i.length-1].range[1]]),w=this.performAction.apply(_,[P,L,v,p.yy,h[1],r,i].concat(R)),typeof w<"u")return w;c&&(n=n.slice(0,-1*c*2),r=r.slice(0,-1*c),i=i.slice(0,-1*c)),n.push(this.productions_[h[1]][0]),r.push(_.$),i.push(_._$),F=d[n[n.length-2]][n[n.length-1]],n.push(F);break;case 3:return!0}}return!0}},k=function(){var u={EOF:1,parseError:function(e,n){if(this.yy.parser)this.yy.parser.parseError(e,n);else throw new Error(e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t;var e=t.match(/(?:\r\n?|\n).*/g);return e?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var s=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var r=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===s.length?this.yylloc.first_column:0)+s[s.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[r[0],r[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+`
                                        diff --git a/assets/install.html-7roQVGaJ.js b/assets/install.html-7roQVGaJ.js
                                        new file mode 100644
                                        index 0000000000..6c1e26ffc6
                                        --- /dev/null
                                        +++ b/assets/install.html-7roQVGaJ.js
                                        @@ -0,0 +1 @@
                                        +import{_ as c,r as t,o as _,c as u,a as n,b as e,d as r,w as a,e as s}from"./app-Bw2NG-QJ.js";const d={},p=s('

                                        下载安装

                                        平台支持

                                        Xray 在以下平台中可用:

                                        • Windows 7 及之后版本(x86 / amd64 / arm32 / arm64);
                                          • Windows 7 中使用 1.8.4、1.8.6 的常规版本以及 1.8.18 以后的 win7 版本需要系统安装有 KB4474419 更新方可使用;推荐同时安装 KB4490628 以便联网后接受后续的操作系统安全更新。
                                        • macOS 10.10 Yosemite 及之后版本(amd64 / arm64);
                                        • Linux 2.6.23 及之后版本(x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                          • 包括但不限于 Debian 7 / 8、Ubuntu 12.04 / 14.04 及后续版本、CentOS 7 / 8、Arch Linux 等;
                                        • FreeBSD (x86 / amd64);
                                        • OpenBSD (x86 / amd64);

                                        下载 Xray

                                        ',5),b={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"下载对应平台的压缩包,解压后即可使用。",-1),g=e("h2",{id:"验证安装包",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#验证安装包"},[e("span",null,"验证安装包")])],-1),m=e("p",null,"Xray 提供两种验证方式:",-1),y=e("li",null,"ZIP 压缩包的 SHA1 / SHA256 摘要",-1),x=e("h2",{id:"windows-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#windows-安装方式"},[e("span",null,"Windows 安装方式")])],-1),k={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},w=e("code",null,"xray.exe",-1),X=e("a",{href:"./command"},"通过命令行带参数运行",-1),v={href:"https://scoop.sh",target:"_blank",rel:"noopener noreferrer"},S={href:"https://github.com/Qv2ray/mochi",target:"_blank",rel:"noopener noreferrer"},L=e("h2",{id:"macos-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#macos-安装方式"},[e("span",null,"macOS 安装方式")])],-1),A={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},I=e("code",null,"xray",-1),O={href:"https://brew.sh",target:"_blank",rel:"noopener noreferrer"},R=e("code",null,"brew install xray",-1),C={href:"https://github.com/N4FA/homebrew-xray",target:"_blank",rel:"noopener noreferrer"},N={href:"https://github.com/N4FA",target:"_blank",rel:"noopener noreferrer"},F=e("h2",{id:"linux-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linux-安装方式"},[e("span",null,"Linux 安装方式")])],-1),P=e("h3",{id:"安装脚本",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#安装脚本"},[e("span",null,"安装脚本")])],-1),U=e("p",null,"Linux Script",-1),M={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},D=e("strong",null,"官方脚本",-1),z={href:"https://github.com/team-cloudchaser/tempest",target:"_blank",rel:"noopener noreferrer"},B={href:"https://systemd.io",target:"_blank",rel:"noopener noreferrer"},T=e("code",null,"systemd",-1),V={href:"https://github.com/OpenRC/openrc",target:"_blank",rel:"noopener noreferrer"},W=e("p",null,"One Click",-1),E={href:"https://github.com/zxcvos/Xray-script",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/sajjaddg/xray-reality",target:"_blank",rel:"noopener noreferrer"},j={href:"https://github.com/aleskxyz/reality-ezpz",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/hello-yunshu/Xray_bash_onekey",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://github.com/LordPenguin666/XTool",target:"_blank",rel:"noopener noreferrer"},J={href:"https://github.com/mack-a/v2ray-agent",target:"_blank",rel:"noopener noreferrer"},K={href:"https://github.com/wulabing/Xray_onekey",target:"_blank",rel:"noopener noreferrer"},Y={href:"https://github.com/proxysu/ProxySU",target:"_blank",rel:"noopener noreferrer"},Q=e("p",null,"Magisk",-1),q={href:"https://github.com/Asterisk4Magisk/Xray4Magisk",target:"_blank",rel:"noopener noreferrer"},$={href:"https://github.com/E7KMbb/Xray_For_Magisk",target:"_blank",rel:"noopener noreferrer"},ee=e("h3",{id:"arch-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux"},[e("span",null,"Arch Linux")])],-1),re=e("h4",{id:"arch-user-repository",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-user-repository"},[e("span",null,"Arch User Repository")])],-1),ne={href:"https://wiki.archlinux.org/index.php/AUR_helpers",target:"_blank",rel:"noopener noreferrer"},oe={href:"https://github.com/Jguer/yay",target:"_blank",rel:"noopener noreferrer"},te=e("code",null,"yay -S xray",-1),le=e("h4",{id:"arch-linux-cn",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux-cn"},[e("span",null,"Arch Linux CN")])],-1),ae={href:"https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/",target:"_blank",rel:"noopener noreferrer"},se=e("code",null,"pacman -S xray",-1),ie=e("h3",{id:"linuxbrew",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linuxbrew"},[e("span",null,"Linuxbrew")])],-1),he=e("p",null,[r("Linuxbrew 包管理器的使用方式与 Homebrew 一致:"),e("code",null,"brew install xray")],-1),ce={id:"debian",tabindex:"-1"},_e={class:"header-anchor",href:"#debian"},ue=e("h3",{id:"gentoo",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#gentoo"},[e("span",null,"Gentoo")])],-1),de=e("p",null,"目前有三个第三方 Overlay 提供 Portage 安装脚本:",-1),pe={href:"https://github.com/gentoo-mirror/touchfish-os/tree/master/net-proxy/Xray",target:"_blank",rel:"noopener noreferrer"},be={href:"https://github.com/microcai/gentoo-zh",target:"_blank",rel:"noopener noreferrer"},fe={href:"https://github.com/JuanCldCmt/Xray-Overlay",target:"_blank",rel:"noopener noreferrer"},ge=e("p",null,"使用 layman 或 eselect-repository 添加 Overlay 至本地,然后即可安装。",-1),me=e("h2",{id:"docker-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#docker-安装方式"},[e("span",null,"Docker 安装方式")])],-1),ye={href:"https://hub.docker.com/r/teddysun/xray",target:"_blank",rel:"noopener noreferrer"},xe=s('

                                        Docker image 的文件结构

                                        • /etc/xray/config.json:配置文件
                                        • /usr/bin/xray:Xray 主程序
                                        • /usr/share/xray/geoip.dat:IP 数据文件
                                        • /usr/share/xray/geosite.dat:域名数据文件

                                        图形化客户端

                                        ',3),ke={href:"https://github.com/xiaorouji/openwrt-passwall",target:"_blank",rel:"noopener noreferrer"},we={href:"https://github.com/xiaorouji/openwrt-passwall2",target:"_blank",rel:"noopener noreferrer"},Xe={href:"https://github.com/fw876/helloworld",target:"_blank",rel:"noopener noreferrer"},ve={href:"https://github.com/yichya/luci-app-xray",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/yichya/openwrt-xray",target:"_blank",rel:"noopener noreferrer"},Le={href:"https://github.com/2dust/v2rayN",target:"_blank",rel:"noopener noreferrer"},Ae={href:"https://github.com/LorenEteval/Furious",target:"_blank",rel:"noopener noreferrer"},Ie={href:"https://github.com/InvisibleManVPN/InvisibleMan-XRayClient",target:"_blank",rel:"noopener noreferrer"},Oe={href:"https://github.com/2dust/v2rayNG",target:"_blank",rel:"noopener noreferrer"},Re={href:"https://github.com/XTLS/X-flutter",target:"_blank",rel:"noopener noreferrer"},Ce={href:"https://apps.apple.com/app/foxray/id6448898396",target:"_blank",rel:"noopener noreferrer"},Ne={href:"https://apps.apple.com/app/streisand/id6450534064",target:"_blank",rel:"noopener noreferrer"},Fe={href:"https://github.com/yanue/V2rayU",target:"_blank",rel:"noopener noreferrer"},Pe={href:"https://github.com/tzmax/V2RayXS",target:"_blank",rel:"noopener noreferrer"},Ue={href:"https://github.com/LorenEteval/Furious",target:"_blank",rel:"noopener noreferrer"},Me={href:"https://apps.apple.com/app/foxray/id6448898396",target:"_blank",rel:"noopener noreferrer"},De={href:"https://github.com/v2rayA/v2rayA",target:"_blank",rel:"noopener noreferrer"},ze={href:"https://github.com/LorenEteval/Furious",target:"_blank",rel:"noopener noreferrer"},Be=e("h1",{id:"uuid-生成器",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#uuid-生成器"},[e("span",null,"UUID 生成器")])],-1),Te={href:"https://www.uuidgenerator.net",target:"_blank",rel:"noopener noreferrer"};function Ve(We,Ee){const i=t("I18nTip"),o=t("ExternalLinkIcon"),l=t("RouterLink"),h=t("Badge");return _(),u("div",null,[n(i),p,e("p",null,[r("预编译的二进制 ZIP 格式压缩包可在 "),e("a",b,[r("Github Releases"),n(o)]),r(" 中找到。")]),f,g,m,e("ul",null,[y,e("li",null,[r("可复现构建:请参照 "),n(l,{to:"/development/intro/compile.html"},{default:a(()=>[r("编译 Xray")]),_:1})])]),x,e("ul",null,[e("li",null,[r("在 "),e("a",k,[r("Github Releases"),n(o)]),r(" 下载适用于 Windows 平台的 ZIP 压缩包,解压后可得到可执行文件 "),w,r(" ,然后"),X,r(" 即可")]),e("li",null,[r("通过 "),e("a",v,[r("Scoop"),n(o)]),r(" 包管理器安装:Xray 已经被添加到 "),e("a",S,[r("Mochi"),n(o)]),r("。")])]),L,e("ul",null,[e("li",null,[r("在 "),e("a",A,[r("Github Releases"),n(o)]),r(" 下载适用于 macOS 平台的 ZIP 压缩包,解压后可得到可执行文件 "),I,r(" ,然后"),n(l,{to:"/document/command.html"},{default:a(()=>[r("通过命令行带参数运行")]),_:1}),r(" 即可")]),e("li",null,[r("通过 "),e("a",O,[r("Homebrew"),n(o)]),r(" 包管理器安装:"),R]),e("li",null,[e("a",C,[r("homebrew-xray"),n(o)]),r(" 感谢"),e("a",N,[r("@N4FA"),n(o)])])]),F,P,e("ul",null,[e("li",null,[U,e("ul",null,[e("li",null,[e("a",M,[r("XTLS/Xray-install"),n(o)]),r(" ("),D,r(")")]),e("li",null,[e("a",z,[r("tempest"),n(o)]),r(" (支持 "),e("a",B,[T,n(o)]),r(" 以及 "),e("a",V,[r("OpenRC"),n(o)]),r("; 仅限 Linux 下使用)")])])])]),e("ul",null,[e("li",null,[W,e("ul",null,[e("li",null,[e("a",E,[r("Xray-REALITY"),n(o)]),r(", "),e("a",G,[r("xray-reality"),n(o)]),r(", "),e("a",j,[r("reality-ezpz"),n(o)])]),e("li",null,[e("a",H,[r("Xray_bash_onekey"),n(o)]),r(", "),e("a",Z,[r("XTool"),n(o)])]),e("li",null,[e("a",J,[r("v2ray-agent"),n(o)]),r(", "),e("a",K,[r("Xray_onekey"),n(o)]),r(", "),e("a",Y,[r("ProxySU"),n(o)])])])]),e("li",null,[Q,e("ul",null,[e("li",null,[e("a",q,[r("Xray4Magisk"),n(o)])]),e("li",null,[e("a",$,[r("Xray_For_Magisk"),n(o)])])])])]),ee,re,e("p",null,[r("需要使用 "),e("a",ne,[r("AUR helpers"),n(o)]),r(",以 "),e("a",oe,[r("yay"),n(o)]),r(" 为例,可通过 "),te,r(" 安装。")]),le,e("p",null,[r("首先添加 "),e("a",ae,[r("Arch Linux CN 仓库"),n(o)]),r(",然后在 root 用户下使用 "),se,r(" 安装。")]),ie,he,e("h3",ce,[e("a",_e,[e("span",null,[r("Debian "),n(h,{text:"WIP",type:"warning"})])])]),ue,de,e("ul",null,[e("li",null,[e("a",pe,[r("CHN-beta/touchfish-os"),n(o)]),r(": 个人维护,适用于 systemD 系统")]),e("li",null,[e("a",be,[r("Gentoo-zh"),n(o)]),r(": 社区维护,适用于 systemD 系统")]),e("li",null,[e("a",fe,[r("JuanCldCmt/Xray-Overlay"),n(o)]),r(":个人维护,适用于 openRC 系统,同时使用 xray 用户组运行以提高安全性")])]),ge,me,e("ul",null,[e("li",null,[e("a",ye,[r("teddysun/xray"),n(o)])])]),xe,e("ul",null,[e("li",null,[r("OpenWrt "),e("ul",null,[e("li",null,[e("a",ke,[r("PassWall"),n(o)]),r(", "),e("a",we,[r("PassWall 2"),n(o)])]),e("li",null,[e("a",Xe,[r("ShadowSocksR Plus+"),n(o)])]),e("li",null,[e("a",ve,[r("luci-app-xray"),n(o)]),r(" ("),e("a",Se,[r("openwrt-xray"),n(o)]),r(")")])])]),e("li",null,[r("Windows "),e("ul",null,[e("li",null,[e("a",Le,[r("v2rayN"),n(o)])]),e("li",null,[e("a",Ae,[r("Furious"),n(o)])]),e("li",null,[e("a",Ie,[r("Invisible Man - Xray"),n(o)])])])]),e("li",null,[r("Android "),e("ul",null,[e("li",null,[e("a",Oe,[r("v2rayNG"),n(o)])]),e("li",null,[e("a",Re,[r("X-flutter"),n(o)])])])]),e("li",null,[r("iOS & macOS arm64 "),e("ul",null,[e("li",null,[e("a",Ce,[r("FoXray"),n(o)])]),e("li",null,[e("a",Ne,[r("Streisand"),n(o)])])])]),e("li",null,[r("macOS arm64 & x64 "),e("ul",null,[e("li",null,[e("a",Fe,[r("V2rayU"),n(o)])]),e("li",null,[e("a",Pe,[r("V2RayXS"),n(o)])]),e("li",null,[e("a",Ue,[r("Furious"),n(o)])]),e("li",null,[e("a",Me,[r("FoXray"),n(o)])])])]),e("li",null,[r("Linux "),e("ul",null,[e("li",null,[e("a",De,[r("v2rayA"),n(o)])]),e("li",null,[e("a",ze,[r("Furious"),n(o)])])])])]),Be,e("p",null,[r("第三方的 UUID 生成器 "),e("a",Te,[r("uuidgenerator.net"),n(o)])])])}const je=c(d,[["render",Ve],["__file","install.html.vue"]]);export{je as default}; diff --git a/assets/install.html-Bqug4cnA.js b/assets/install.html-Bqug4cnA.js deleted file mode 100644 index f79588b0ff..0000000000 --- a/assets/install.html-Bqug4cnA.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as i,r as t,o as h,c,a as n,b as e,d as r,e as o}from"./app-5SoadDYS.js";const d={},u=o('

                                        Download and Install

                                        Platform Support

                                        • Xray is available on the following platforms:
                                          • Windows 7 and later (x86 / amd64 / arm32 / arm64);
                                          • macOS 10.10 Yosemite and later (amd64 / arm64);
                                          • Linux 2.6.23 and later (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                            • Including but not limited to Debian 7 / 8, Ubuntu 12.04 / 14.04 and subsequent versions, CentOS 7 / 8, Arch Linux, etc.;
                                          • FreeBSD (x86 / amd64);
                                          • OpenBSD (x86 / amd64);
                                          • Dragonfly BSD (amd64);

                                        Download Xray

                                        ',4),p={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},_=e("p",null,"Download the compressed package of the corresponding platform, and use it after decompression.",-1),f=e("h2",{id:"verify-the-installation-package",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#verify-the-installation-package"},[e("span",null,"Verify the Installation Package")])],-1),b=e("p",null,"Xray provides two verification methods:",-1),g=e("li",null,"SHA1/SHA256 digest of the ZIP archive",-1),m={href:"https://xtls.github.io/development/intro/compile.html",target:"_blank",rel:"noopener noreferrer"},y=e("h2",{id:"install-on-windows",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-on-windows"},[e("span",null,"Install on Windows")])],-1),x={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},k=e("code",null,"xray.exe",-1),w=e("a",{href:"./command"},"parameters",-1),v={href:"https://scoop.sh/",target:"_blank",rel:"noopener noreferrer"},S={href:"https://github.com/Qv2ray/mochi",target:"_blank",rel:"noopener noreferrer"},X=e("h2",{id:"install-on-macos",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-on-macos"},[e("span",null,"Install on macOS")])],-1),I={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},N=e("code",null,"xray",-1),A=e("a",{href:"./command"},"parameters",-1),P={href:"https://brew.sh/",target:"_blank",rel:"noopener noreferrer"},D=e("code",null,"brew install xray",-1),T={href:"https://github.com/N4FA/homebrew-xray",target:"_blank",rel:"noopener noreferrer"},R={href:"https://github.com/N4FA",target:"_blank",rel:"noopener noreferrer"},L=e("h2",{id:"install-on-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-on-linux"},[e("span",null,"Install on Linux")])],-1),U=e("h3",{id:"install-script",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-script"},[e("span",null,"Install Script")])],-1),B=e("p",null,"Linux Script",-1),O={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},F=e("p",null,"One Click",-1),M={href:"https://github.com/kirin10000/Xray-script",target:"_blank",rel:"noopener noreferrer"},C={href:"https://github.com/proxysu/ProxySU",target:"_blank",rel:"noopener noreferrer"},W={href:"https://github.com/reeceyng/v2ray-agent",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/mack-a",target:"_blank",rel:"noopener noreferrer"},Q={href:"https://github.com/reeceyng",target:"_blank",rel:"noopener noreferrer"},V=e("p",null,"Magisk",-1),j={href:"https://github.com/CerteKim/Xray4Magisk",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/E7KMbb/Xray_For_Magisk",target:"_blank",rel:"noopener noreferrer"},E=e("h3",{id:"arch-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux"},[e("span",null,"Arch Linux")])],-1),K=e("h4",{id:"arch-user-repository",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-user-repository"},[e("span",null,"Arch User Repository")])],-1),Z={href:"https://wiki.archlinux.org/index.php/AUR_helpers",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/Jguer/yay",target:"_blank",rel:"noopener noreferrer"},z=e("code",null,"yay -S xray",-1),J=e("h4",{id:"arch-linux-cn",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux-cn"},[e("span",null,"Arch Linux CN")])],-1),Y={href:"https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/",target:"_blank",rel:"noopener noreferrer"},$=e("code",null,"pacman -S xray",-1),ee=e("h3",{id:"linuxbrew",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linuxbrew"},[e("span",null,"Linuxbrew")])],-1),re=e("p",null,[r("The Linuxbrew package manager is used in the same way as Homebrew: "),e("code",null,"brew install xray")],-1),ne={id:"debian",tabindex:"-1"},ae={class:"header-anchor",href:"#debian"},te=e("h2",{id:"install-via-docker",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-via-docker"},[e("span",null,"Install via Docker")])],-1),oe={href:"https://hub.docker.com/r/teddysun/xray",target:"_blank",rel:"noopener noreferrer"},le=o('

                                        The File Structure of the Docker Image

                                        • /etc/xray/config.json: configuration file
                                        • /usr/bin/xray: Xray main program
                                        • /usr/local/share/xray/geoip.dat: IP data file
                                        • /usr/local/share/xray/geosite.dat: domain name data file

                                        GUI Client

                                        ',3),se={href:"https://github.com/xiaorouji/openwrt-passwall",target:"_blank",rel:"noopener noreferrer"},ie={href:"https://github.com/jerrykuku/luci-app-vssr",target:"_blank",rel:"noopener noreferrer"},he={href:"https://github.com/fw876/helloworld",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/yichya/luci-app-xray",target:"_blank",rel:"noopener noreferrer"},de={href:"https://github.com/yichya/openwrt-xray",target:"_blank",rel:"noopener noreferrer"},ue={href:"https://github.com/2dust/v2rayN",target:"_blank",rel:"noopener noreferrer"},pe={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/NetchX/Netch",target:"_blank",rel:"noopener noreferrer"},fe={href:"https://github.com/2dust/v2rayNG",target:"_blank",rel:"noopener noreferrer"},be={href:"https://github.com/rurirei/Kitsunebi/tree/release_xtls",target:"_blank",rel:"noopener noreferrer"},ge={href:"https://apps.apple.com/app/shadowrocket/id932747118",target:"_blank",rel:"noopener noreferrer"},me={href:"https://apps.apple.com/app/stash/id1596063349",target:"_blank",rel:"noopener noreferrer"},ye={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},xe={href:"https://github.com/tzmax/V2RayXS",target:"_blank",rel:"noopener noreferrer"},ke=e("h1",{id:"uuid-generator",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#uuid-generator"},[e("span",null,"UUID Generator")])],-1),we={href:"https://www.uuidgenerator.net",target:"_blank",rel:"noopener noreferrer"};function ve(Se,Xe){const l=t("I18nTip"),a=t("ExternalLinkIcon"),s=t("Badge");return h(),c("div",null,[n(l),u,e("p",null,[r("Precompiled binaries in ZIP format are available at "),e("a",p,[r("GitHub Releases"),n(a)]),r(" found in.")]),_,f,b,e("ul",null,[g,e("li",null,[r("Reproducible build: Please refer to "),e("a",m,[r("Compile Xray"),n(a)])])]),y,e("ul",null,[e("li",null,[r("Download the ZIP archive suitable for the Windows platform on "),e("a",x,[r("Github Releases"),n(a)]),r(". After decompression, you can get an executable file "),k,r(", and then run it with "),w,r(" through the command line.")]),e("li",null,[r("By "),e("a",v,[r("Scoop"),n(a)]),r(" Package manager installation: Xray has been added to "),e("a",S,[r("Mochi"),n(a)]),r(".")])]),X,e("ul",null,[e("li",null,[r("Download the ZIP archive suitable for the macOS platform on "),e("a",I,[r("Github Releases"),n(a)]),r(". After decompression, you can get an executable file "),N,r(", and then run it with "),A,r(" through the command line.")]),e("li",null,[r("By "),e("a",P,[r("Homebrew"),n(a)]),r(" Package manager installation: "),D]),e("li",null,[e("a",T,[r("homebrew-xray"),n(a)]),r(": Thanks "),e("a",R,[r("@N4FA"),n(a)])])]),L,U,e("ul",null,[e("li",null,[B,e("ul",null,[e("li",null,[e("a",O,[r("Xray-install"),n(a)])])])])]),e("ul",null,[e("li",null,[F,e("ul",null,[e("li",null,[e("a",M,[r("Xray-script"),n(a)])]),e("li",null,[e("a",C,[r("ProxySU"),n(a)])]),e("li",null,[e("a",W,[r("Xray-agent"),n(a)]),r(" Thanks "),e("a",G,[r("@mack-a"),n(a)]),r(),e("a",Q,[r("@Reece"),n(a)])])])]),e("li",null,[V,e("ul",null,[e("li",null,[e("a",j,[r("Xray4Magisk"),n(a)])]),e("li",null,[e("a",H,[r("Xray_For_Magisk"),n(a)])])])])]),E,K,e("p",null,[r("Need to use "),e("a",Z,[r("AUR helpers"),n(a)]),r(", "),e("a",q,[r("yay"),n(a)]),r(" as an example, it can be installed via "),z,r(".")]),J,e("p",null,[r("First add "),e("a",Y,[r("Arch Linux CN"),n(a)]),r(" repository, and then use the root user "),$,r("to install.")]),ee,re,e("h3",ne,[e("a",ae,[e("span",null,[r("Debian "),n(s,{text:"WIP",type:"warning"})])])]),te,e("ul",null,[e("li",null,[e("a",oe,[r("teddysun/xray"),n(a)])])]),le,e("ul",null,[e("li",null,[r("OpenWrt "),e("ul",null,[e("li",null,[e("a",se,[r("PassWall"),n(a)])]),e("li",null,[e("a",ie,[r("Hello World"),n(a)])]),e("li",null,[e("a",he,[r("ShadowSocksR Plus+"),n(a)])]),e("li",null,[e("a",ce,[r("luci-app-xray"),n(a)]),r(" ("),e("a",de,[r("openwrt-xray"),n(a)]),r(")")])])]),e("li",null,[r("Windows "),e("ul",null,[e("li",null,[e("a",ue,[r("v2rayN"),n(a)])]),e("li",null,[e("a",pe,[r("Qv2ray"),n(a)]),r(" (This project has been and archived)")]),e("li",null,[e("a",_e,[r("Netch (NetFilter & TUN/TAP)"),n(a)]),r(" (This project has been and archived)")])])]),e("li",null,[r("Android "),e("ul",null,[e("li",null,[e("a",fe,[r("v2rayNG"),n(a)])]),e("li",null,[e("a",be,[r("Kitsunebi"),n(a)])])])]),e("li",null,[r("iOS / macOS (ARM) "),e("ul",null,[e("li",null,[e("a",ge,[r("Shadowrocket"),n(a)])]),e("li",null,[e("a",me,[r("Stash"),n(a)])])])]),e("li",null,[r("macOS (X86/ARM) "),e("ul",null,[e("li",null,[e("a",ye,[r("Qv2ray"),n(a)]),r(" (This project has been and archived)")]),e("li",null,[e("a",xe,[r("V2RayXS"),n(a)])])])])]),ke,e("p",null,[r("Third-party UUID generator "),e("a",we,[r("uuidgenerator.net"),n(a)])])])}const Ne=i(d,[["render",ve],["__file","install.html.vue"]]);export{Ne as default}; diff --git a/assets/install.html-f63Sv7SS.js b/assets/install.html-C6eLysya.js similarity index 65% rename from assets/install.html-f63Sv7SS.js rename to assets/install.html-C6eLysya.js index 7cd4d89904..bbbbc3563c 100644 --- a/assets/install.html-f63Sv7SS.js +++ b/assets/install.html-C6eLysya.js @@ -1 +1 @@ -const e=JSON.parse('{"key":"v-0e5d7b39","path":"/document/install.html","title":"下载安装","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"平台支持","slug":"平台支持","link":"#平台支持","children":[]},{"level":2,"title":"下载 Xray","slug":"下载-xray","link":"#下载-xray","children":[]},{"level":2,"title":"验证安装包","slug":"验证安装包","link":"#验证安装包","children":[]},{"level":2,"title":"Windows 安装方式","slug":"windows-安装方式","link":"#windows-安装方式","children":[]},{"level":2,"title":"macOS 安装方式","slug":"macos-安装方式","link":"#macos-安装方式","children":[]},{"level":2,"title":"Linux 安装方式","slug":"linux-安装方式","link":"#linux-安装方式","children":[{"level":3,"title":"安装脚本","slug":"安装脚本","link":"#安装脚本","children":[]},{"level":3,"title":"Arch Linux","slug":"arch-linux","link":"#arch-linux","children":[]},{"level":3,"title":"Linuxbrew","slug":"linuxbrew","link":"#linuxbrew","children":[]},{"level":3,"title":"Debian","slug":"debian","link":"#debian","children":[]},{"level":3,"title":"Gentoo","slug":"gentoo","link":"#gentoo","children":[]}]},{"level":2,"title":"Docker 安装方式","slug":"docker-安装方式","link":"#docker-安装方式","children":[{"level":3,"title":"Docker image 的文件结构","slug":"docker-image-的文件结构","link":"#docker-image-的文件结构","children":[]}]}],"git":{"updatedTime":1699098917000,"contributors":[{"name":"JimhHan","email":"50871214+JimhHan@users.noreply.github.com","commits":3},{"name":"JuanCC","email":"72336775+JuanCldCmt@users.noreply.github.com","commits":1},{"name":"Kobe Arthur Scofield","email":"kobearthurxc@outlook.com","commits":1},{"name":"rootmelo92118","email":"32770959+rootmelo92118@users.noreply.github.com","commits":1},{"name":"yuhan6665","email":"1588741+yuhan6665@users.noreply.github.com","commits":1},{"name":"zyzh0","email":"18255331+zyzh2002@users.noreply.github.com","commits":1},{"name":"秋のかえで","email":"autmaple@protonmail.com","commits":1}]},"filePathRelative":"document/install.md","i18n":{"pathLocale":"/","sourceLink":"/document/install.html","untranslated":false,"updatedTime":1699098917000}}');export{e as data}; +const e=JSON.parse('{"key":"v-0e5d7b39","path":"/document/install.html","title":"下载安装","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"平台支持","slug":"平台支持","link":"#平台支持","children":[]},{"level":2,"title":"下载 Xray","slug":"下载-xray","link":"#下载-xray","children":[]},{"level":2,"title":"验证安装包","slug":"验证安装包","link":"#验证安装包","children":[]},{"level":2,"title":"Windows 安装方式","slug":"windows-安装方式","link":"#windows-安装方式","children":[]},{"level":2,"title":"macOS 安装方式","slug":"macos-安装方式","link":"#macos-安装方式","children":[]},{"level":2,"title":"Linux 安装方式","slug":"linux-安装方式","link":"#linux-安装方式","children":[{"level":3,"title":"安装脚本","slug":"安装脚本","link":"#安装脚本","children":[]},{"level":3,"title":"Arch Linux","slug":"arch-linux","link":"#arch-linux","children":[]},{"level":3,"title":"Linuxbrew","slug":"linuxbrew","link":"#linuxbrew","children":[]},{"level":3,"title":"Debian","slug":"debian","link":"#debian","children":[]},{"level":3,"title":"Gentoo","slug":"gentoo","link":"#gentoo","children":[]}]},{"level":2,"title":"Docker 安装方式","slug":"docker-安装方式","link":"#docker-安装方式","children":[{"level":3,"title":"Docker image 的文件结构","slug":"docker-image-的文件结构","link":"#docker-image-的文件结构","children":[]}]}],"git":{"updatedTime":1723610376000,"contributors":[{"name":"JimhHan","email":"50871214+JimhHan@users.noreply.github.com","commits":3},{"name":"JuanCC","email":"72336775+JuanCldCmt@users.noreply.github.com","commits":1},{"name":"Kobe Arthur Scofield","email":"26771058+KobeArthurScofield@users.noreply.github.com","commits":1},{"name":"Kobe Arthur Scofield","email":"kobearthurxc@outlook.com","commits":1},{"name":"rootmelo92118","email":"32770959+rootmelo92118@users.noreply.github.com","commits":1},{"name":"yuhan6665","email":"1588741+yuhan6665@users.noreply.github.com","commits":1},{"name":"zyzh0","email":"18255331+zyzh2002@users.noreply.github.com","commits":1},{"name":"秋のかえで","email":"autmaple@protonmail.com","commits":1}]},"filePathRelative":"document/install.md","i18n":{"pathLocale":"/","sourceLink":"/document/install.html","untranslated":false,"updatedTime":1723610376000}}');export{e as data}; diff --git a/assets/install.html-CJaw-WJD.js b/assets/install.html-CJaw-WJD.js deleted file mode 100644 index f967a03c74..0000000000 --- a/assets/install.html-CJaw-WJD.js +++ /dev/null @@ -1 +0,0 @@ -import{_ as c,r as o,o as u,c as _,a as n,b as e,d as r,w as a,e as s}from"./app-5SoadDYS.js";const d={},p=s('

                                        下载安装

                                        平台支持

                                        Xray 在以下平台中可用:

                                        • Windows 7 及之后版本(x86 / amd64 / arm32 / arm64);
                                        • macOS 10.10 Yosemite 及之后版本(amd64 / arm64);
                                        • Linux 2.6.23 及之后版本(x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                          • 包括但不限于 Debian 7 / 8、Ubuntu 12.04 / 14.04 及后续版本、CentOS 7 / 8、Arch Linux 等;
                                        • FreeBSD (x86 / amd64);
                                        • OpenBSD (x86 / amd64);
                                        • Dragonfly BSD (amd64);

                                        下载 Xray

                                        ',5),b={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"下载对应平台的压缩包,解压后即可使用。",-1),g=e("h2",{id:"验证安装包",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#验证安装包"},[e("span",null,"验证安装包")])],-1),m=e("p",null,"Xray 提供两种验证方式:",-1),y=e("li",null,"ZIP 压缩包的 SHA1 / SHA256 摘要",-1),x=e("h2",{id:"windows-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#windows-安装方式"},[e("span",null,"Windows 安装方式")])],-1),k={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},w=e("code",null,"xray.exe",-1),X=e("a",{href:"./command"},"通过命令行带参数运行",-1),S={href:"https://scoop.sh",target:"_blank",rel:"noopener noreferrer"},v={href:"https://github.com/Qv2ray/mochi",target:"_blank",rel:"noopener noreferrer"},N=e("h2",{id:"macos-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#macos-安装方式"},[e("span",null,"macOS 安装方式")])],-1),A={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},R=e("code",null,"xray",-1),L={href:"https://brew.sh",target:"_blank",rel:"noopener noreferrer"},O=e("code",null,"brew install xray",-1),C={href:"https://github.com/N4FA/homebrew-xray",target:"_blank",rel:"noopener noreferrer"},D={href:"https://github.com/N4FA",target:"_blank",rel:"noopener noreferrer"},I=e("h2",{id:"linux-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linux-安装方式"},[e("span",null,"Linux 安装方式")])],-1),P=e("h3",{id:"安装脚本",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#安装脚本"},[e("span",null,"安装脚本")])],-1),U=e("p",null,"Linux Script",-1),M={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=e("p",null,"One Click",-1),W={href:"https://github.com/kirin10000/Xray-script",target:"_blank",rel:"noopener noreferrer"},F={href:"https://github.com/proxysu/ProxySU",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/reeceyng/v2ray-agent",target:"_blank",rel:"noopener noreferrer"},Q={href:"https://github.com/mack-a",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/reeceyng",target:"_blank",rel:"noopener noreferrer"},T={href:"https://github.com/jiuqi9997/Xray-yes",target:"_blank",rel:"noopener noreferrer"},V={href:"https://github.com/wulabing/Xray_onekey",target:"_blank",rel:"noopener noreferrer"},j=e("p",null,"Magisk",-1),E={href:"https://github.com/CerteKim/Xray4Magisk",target:"_blank",rel:"noopener noreferrer"},K={href:"https://github.com/E7KMbb/Xray_For_Magisk",target:"_blank",rel:"noopener noreferrer"},Z=e("h3",{id:"arch-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux"},[e("span",null,"Arch Linux")])],-1),z=e("h4",{id:"arch-user-repository",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-user-repository"},[e("span",null,"Arch User Repository")])],-1),J={href:"https://wiki.archlinux.org/index.php/AUR_helpers",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/Jguer/yay",target:"_blank",rel:"noopener noreferrer"},Y=e("code",null,"yay -S xray",-1),$=e("h4",{id:"arch-linux-cn",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux-cn"},[e("span",null,"Arch Linux CN")])],-1),ee={href:"https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/",target:"_blank",rel:"noopener noreferrer"},re=e("code",null,"pacman -S xray",-1),ne=e("h3",{id:"linuxbrew",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linuxbrew"},[e("span",null,"Linuxbrew")])],-1),te=e("p",null,[r("Linuxbrew 包管理器的使用方式与 Homebrew 一致:"),e("code",null,"brew install xray")],-1),oe={id:"debian",tabindex:"-1"},le={class:"header-anchor",href:"#debian"},ae=e("h3",{id:"gentoo",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#gentoo"},[e("span",null,"Gentoo")])],-1),se=e("p",null,"目前有三个第三方 Overlay 提供 Portage 安装脚本:",-1),ie={href:"https://github.com/gentoo-mirror/touchfish-os/tree/master/net-proxy/Xray",target:"_blank",rel:"noopener noreferrer"},he={href:"https://github.com/microcai/gentoo-zh",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/JuanCldCmt/Xray-Overlay",target:"_blank",rel:"noopener noreferrer"},ue=e("p",null,"使用 layman 或 eselect-repository 添加 Overlay 至本地,然后即可安装。",-1),_e=e("h2",{id:"docker-安装方式",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#docker-安装方式"},[e("span",null,"Docker 安装方式")])],-1),de={href:"https://hub.docker.com/r/teddysun/xray",target:"_blank",rel:"noopener noreferrer"},pe=s('

                                        Docker image 的文件结构

                                        • /etc/xray/config.json:配置文件
                                        • /usr/bin/xray:Xray 主程序
                                        • /usr/share/xray/geoip.dat:IP 数据文件
                                        • /usr/share/xray/geosite.dat:域名数据文件

                                        图形化客户端

                                        ',3),be={href:"https://github.com/xiaorouji/openwrt-passwall",target:"_blank",rel:"noopener noreferrer"},fe={href:"https://github.com/jerrykuku/luci-app-vssr",target:"_blank",rel:"noopener noreferrer"},ge={href:"https://github.com/fw876/helloworld",target:"_blank",rel:"noopener noreferrer"},me={href:"https://github.com/yichya/luci-app-xray",target:"_blank",rel:"noopener noreferrer"},ye={href:"https://github.com/yichya/openwrt-xray",target:"_blank",rel:"noopener noreferrer"},xe={href:"https://github.com/2dust/v2rayN",target:"_blank",rel:"noopener noreferrer"},ke={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},we={href:"https://github.com/NetchX/Netch",target:"_blank",rel:"noopener noreferrer"},Xe={href:"https://github.com/2dust/v2rayNG",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/rurirei/Kitsunebi/tree/release_xtls",target:"_blank",rel:"noopener noreferrer"},ve={href:"https://apps.apple.com/app/shadowrocket/id932747118",target:"_blank",rel:"noopener noreferrer"},Ne={href:"https://apps.apple.com/app/stash/id1596063349",target:"_blank",rel:"noopener noreferrer"},Ae={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},Re={href:"https://github.com/tzmax/V2RayXS",target:"_blank",rel:"noopener noreferrer"},Le=e("h1",{id:"uuid-生成器",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#uuid-生成器"},[e("span",null,"UUID 生成器")])],-1),Oe={href:"https://www.uuidgenerator.net",target:"_blank",rel:"noopener noreferrer"};function Ce(De,Ie){const i=o("I18nTip"),t=o("ExternalLinkIcon"),l=o("RouterLink"),h=o("Badge");return u(),_("div",null,[n(i),p,e("p",null,[r("预编译的二进制 ZIP 格式压缩包可在 "),e("a",b,[r("Github Releases"),n(t)]),r(" 中找到。")]),f,g,m,e("ul",null,[y,e("li",null,[r("可复现构建:请参照 "),n(l,{to:"/development/intro/compile.html"},{default:a(()=>[r("编译 Xray")]),_:1})])]),x,e("ul",null,[e("li",null,[r("在 "),e("a",k,[r("Github Releases"),n(t)]),r(" 下载适用于 Windows 平台的 ZIP 压缩包,解压后可得到可执行文件 "),w,r(" ,然后"),X,r(" 即可")]),e("li",null,[r("通过 "),e("a",S,[r("Scoop"),n(t)]),r(" 包管理器安装:Xray 已经被添加到 "),e("a",v,[r("Mochi"),n(t)]),r("。")])]),N,e("ul",null,[e("li",null,[r("在 "),e("a",A,[r("Github Releases"),n(t)]),r(" 下载适用于 macOS 平台的 ZIP 压缩包,解压后可得到可执行文件 "),R,r(" ,然后"),n(l,{to:"/document/command.html"},{default:a(()=>[r("通过命令行带参数运行")]),_:1}),r(" 即可")]),e("li",null,[r("通过 "),e("a",L,[r("Homebrew"),n(t)]),r(" 包管理器安装:"),O]),e("li",null,[e("a",C,[r("homebrew-xray"),n(t)]),r(" 感谢"),e("a",D,[r("@N4FA"),n(t)])])]),I,P,e("ul",null,[e("li",null,[U,e("ul",null,[e("li",null,[e("a",M,[r("Xray-install"),n(t)])])])])]),e("ul",null,[e("li",null,[B,e("ul",null,[e("li",null,[e("a",W,[r("Xray-script"),n(t)])]),e("li",null,[e("a",F,[r("ProxySU"),n(t)])]),e("li",null,[e("a",G,[r("v2ray-agent"),n(t)]),r(" 感谢"),e("a",Q,[r("@mack-a"),n(t)]),r(),e("a",H,[r("@Reece"),n(t)])]),e("li",null,[e("a",T,[r("Xray-yes"),n(t)])]),e("li",null,[e("a",V,[r("Xray-onekey"),n(t)])])])]),e("li",null,[j,e("ul",null,[e("li",null,[e("a",E,[r("Xray4Magisk"),n(t)])]),e("li",null,[e("a",K,[r("Xray_For_Magisk"),n(t)])])])])]),Z,z,e("p",null,[r("需要使用 "),e("a",J,[r("AUR helpers"),n(t)]),r(",以 "),e("a",q,[r("yay"),n(t)]),r(" 为例,可通过 "),Y,r(" 安装。")]),$,e("p",null,[r("首先添加 "),e("a",ee,[r("Arch Linux CN 仓库"),n(t)]),r(",然后在 root 用户下使用 "),re,r(" 安装。")]),ne,te,e("h3",oe,[e("a",le,[e("span",null,[r("Debian "),n(h,{text:"WIP",type:"warning"})])])]),ae,se,e("ul",null,[e("li",null,[e("a",ie,[r("CHN-beta/touchfish-os"),n(t)]),r(": 个人维护,适用于 systemD 系统")]),e("li",null,[e("a",he,[r("Gentoo-zh"),n(t)]),r(": 社区维护,适用于 systemD 系统")]),e("li",null,[e("a",ce,[r("JuanCldCmt/Xray-Overlay"),n(t)]),r(":个人维护,适用于 openRC 系统,同时使用 xray 用户组运行以提高安全性")])]),ue,_e,e("ul",null,[e("li",null,[e("a",de,[r("teddysun/xray"),n(t)])])]),pe,e("ul",null,[e("li",null,[r("OpenWrt "),e("ul",null,[e("li",null,[e("a",be,[r("PassWall"),n(t)])]),e("li",null,[e("a",fe,[r("Hello World"),n(t)])]),e("li",null,[e("a",ge,[r("ShadowSocksR Plus+"),n(t)])]),e("li",null,[e("a",me,[r("luci-app-xray"),n(t)]),r(" ("),e("a",ye,[r("openwrt-xray"),n(t)]),r(")")])])]),e("li",null,[r("Windows "),e("ul",null,[e("li",null,[e("a",xe,[r("v2rayN"),n(t)])]),e("li",null,[e("a",ke,[r("Qv2ray"),n(t)]),r(" (该项目已冻结存档)")]),e("li",null,[e("a",we,[r("Netch (NetFilter & TUN/TAP)"),n(t)]),r(" (该项目已冻结存档)")])])]),e("li",null,[r("Android "),e("ul",null,[e("li",null,[e("a",Xe,[r("v2rayNG"),n(t)])]),e("li",null,[e("a",Se,[r("Kitsunebi"),n(t)])])])]),e("li",null,[r("iOS / macOS(使用 ARM 芯片) "),e("ul",null,[e("li",null,[e("a",ve,[r("Shadowrocket"),n(t)])]),e("li",null,[e("a",Ne,[r("Stash"),n(t)])])])]),e("li",null,[r("macOS(X86 芯片 / ARM 芯片) "),e("ul",null,[e("li",null,[e("a",Ae,[r("Qv2ray"),n(t)]),r(" (该项目已冻结存档)")]),e("li",null,[e("a",Re,[r("V2RayXS"),n(t)])])])])]),Le,e("p",null,[r("第三方的 UUID 生成器 "),e("a",Oe,[r("uuidgenerator.net"),n(t)])])])}const Ue=c(d,[["render",Ce],["__file","install.html.vue"]]);export{Ue as default}; diff --git a/assets/install.html-BrHImMB4.js b/assets/install.html-CX7I48Il.js similarity index 99% rename from assets/install.html-BrHImMB4.js rename to assets/install.html-CX7I48Il.js index 8a1a47c5b0..51adc9131b 100644 --- a/assets/install.html-BrHImMB4.js +++ b/assets/install.html-CX7I48Il.js @@ -1 +1 @@ -import{_ as c,r as o,o as u,c as _,a as n,b as e,d as r,w as a,e as s}from"./app-5SoadDYS.js";const d={},p=s('

                                        Загрузка и установка

                                        Поддерживаемые платформы

                                        Xray доступен на следующих платформах:

                                        • Windows 7 и выше (x86 / amd64 / arm32 / arm64);
                                        • macOS 10.10 Yosemite и выше (amd64 / arm64);
                                        • Linux 2.6.23 и выше (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                          • Включая, но не ограничиваясь: Debian 7 / 8, Ubuntu 12.04 / 14.04 и выше, CentOS 7 / 8, Arch Linux и др.;
                                        • FreeBSD (x86 / amd64);
                                        • OpenBSD (x86 / amd64);
                                        • Dragonfly BSD (amd64);

                                        Загрузка Xray

                                        ',5),b={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"Скачайте архив для своей платформы, распакуйте его и можете использовать.",-1),g=e("h2",{id:"проверка-установочного-пакета",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#проверка-установочного-пакета"},[e("span",null,"Проверка установочного пакета")])],-1),m=e("p",null,"Xray предлагает два способа проверки:",-1),y=e("li",null,"SHA1 / SHA256 хэш-сумма ZIP-архива;",-1),x=e("h2",{id:"установка-на-windows",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-на-windows"},[e("span",null,"Установка на Windows")])],-1),k={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},w=e("code",null,"xray.exe",-1),X=e("a",{href:"./command"},"запустите его из командной строки с параметрами",-1),S={href:"https://scoop.sh",target:"_blank",rel:"noopener noreferrer"},v={href:"https://github.com/Qv2ray/mochi",target:"_blank",rel:"noopener noreferrer"},N=e("h2",{id:"установка-на-macos",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-на-macos"},[e("span",null,"Установка на macOS")])],-1),A={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},R=e("code",null,"xray",-1),L={href:"https://brew.sh",target:"_blank",rel:"noopener noreferrer"},C=e("code",null,"brew install xray",-1),D={href:"https://github.com/N4FA/homebrew-xray",target:"_blank",rel:"noopener noreferrer"},I={href:"https://github.com/N4FA",target:"_blank",rel:"noopener noreferrer"},O=e("h2",{id:"установка-на-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-на-linux"},[e("span",null,"Установка на Linux")])],-1),P=e("h3",{id:"установочные-скрипты",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установочные-скрипты"},[e("span",null,"Установочные скрипты")])],-1),U=e("p",null,"Linux Script",-1),M={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=e("p",null,"One Click",-1),W={href:"https://github.com/kirin10000/Xray-script",target:"_blank",rel:"noopener noreferrer"},F={href:"https://github.com/proxysu/ProxySU",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/reeceyng/v2ray-agent",target:"_blank",rel:"noopener noreferrer"},Q={href:"https://github.com/mack-a",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/reeceyng",target:"_blank",rel:"noopener noreferrer"},T={href:"https://github.com/jiuqi9997/Xray-yes",target:"_blank",rel:"noopener noreferrer"},V={href:"https://github.com/wulabing/Xray_onekey",target:"_blank",rel:"noopener noreferrer"},j=e("p",null,"Magisk",-1),E={href:"https://github.com/CerteKim/Xray4Magisk",target:"_blank",rel:"noopener noreferrer"},K={href:"https://github.com/E7KMbb/Xray_For_Magisk",target:"_blank",rel:"noopener noreferrer"},Z=e("h3",{id:"arch-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux"},[e("span",null,"Arch Linux")])],-1),z=e("h4",{id:"arch-user-repository",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-user-repository"},[e("span",null,"Arch User Repository")])],-1),J={href:"https://wiki.archlinux.org/index.php/AUR_helpers",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/Jguer/yay",target:"_blank",rel:"noopener noreferrer"},Y=e("code",null,"yay -S xray",-1),$=e("h4",{id:"arch-linux-cn",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux-cn"},[e("span",null,"Arch Linux CN")])],-1),ee={href:"https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/",target:"_blank",rel:"noopener noreferrer"},re=e("code",null,"pacman -S xray",-1),ne=e("h3",{id:"linuxbrew",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linuxbrew"},[e("span",null,"Linuxbrew")])],-1),te=e("p",null,[r("Использование менеджера пакетов Linuxbrew аналогично Homebrew: "),e("code",null,"brew install xray"),r(".")],-1),oe={id:"debian",tabindex:"-1"},le={class:"header-anchor",href:"#debian"},ae=e("h3",{id:"gentoo",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#gentoo"},[e("span",null,"Gentoo")])],-1),se=e("p",null,"В настоящее время существует три оверлея сторонних разработчиков, которые предоставляют сценарии установки Portage:",-1),ie={href:"https://github.com/gentoo-mirror/touchfish-os/tree/master/net-proxy/Xray",target:"_blank",rel:"noopener noreferrer"},he={href:"https://github.com/microcai/gentoo-zh",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/JuanCldCmt/Xray-Overlay",target:"_blank",rel:"noopener noreferrer"},ue=e("p",null,"Добавьте оверлей в локальную систему с помощью layman или eselect-repository, а затем выполните установку.",-1),_e=e("h2",{id:"установка-с-помощью-docker",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-с-помощью-docker"},[e("span",null,"Установка с помощью Docker")])],-1),de={href:"https://hub.docker.com/r/teddysun/xray",target:"_blank",rel:"noopener noreferrer"},pe=s('

                                        Файловая структура образа Docker

                                        • /etc/xray/config.json: файл конфигурации;
                                        • /usr/bin/xray: основная программа Xray;
                                        • /usr/share/xray/geoip.dat: файл данных IP;
                                        • /usr/share/xray/geosite.dat: файл данных доменных имен.

                                        Графические клиенты

                                        ',3),be={href:"https://github.com/xiaorouji/openwrt-passwall",target:"_blank",rel:"noopener noreferrer"},fe={href:"https://github.com/jerrykuku/luci-app-vssr",target:"_blank",rel:"noopener noreferrer"},ge={href:"https://github.com/fw876/helloworld",target:"_blank",rel:"noopener noreferrer"},me={href:"https://github.com/yichya/luci-app-xray",target:"_blank",rel:"noopener noreferrer"},ye={href:"https://github.com/yichya/openwrt-xray",target:"_blank",rel:"noopener noreferrer"},xe={href:"https://github.com/2dust/v2rayN",target:"_blank",rel:"noopener noreferrer"},ke={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},we={href:"https://github.com/NetchX/Netch",target:"_blank",rel:"noopener noreferrer"},Xe={href:"https://github.com/2dust/v2rayNG",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/rurirei/Kitsunebi/tree/release_xtls",target:"_blank",rel:"noopener noreferrer"},ve={href:"https://apps.apple.com/app/shadowrocket/id932747118",target:"_blank",rel:"noopener noreferrer"},Ne={href:"https://apps.apple.com/app/stash/id1596063349",target:"_blank",rel:"noopener noreferrer"},Ae={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},Re={href:"https://github.com/tzmax/V2RayXS",target:"_blank",rel:"noopener noreferrer"},Le=e("h1",{id:"генератор-uuid",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#генератор-uuid"},[e("span",null,"Генератор UUID")])],-1),Ce={href:"https://www.uuidgenerator.net",target:"_blank",rel:"noopener noreferrer"};function De(Ie,Oe){const i=o("I18nTip"),t=o("ExternalLinkIcon"),l=o("RouterLink"),h=o("Badge");return u(),_("div",null,[n(i),p,e("p",null,[r("Предварительно скомпилированные ZIP-архивы с двоичными файлами можно найти в "),e("a",b,[r("Github Releases"),n(t)]),r(".")]),f,g,m,e("ul",null,[y,e("li",null,[r("Воспроизводимая сборка: см. "),n(l,{to:"/ru/development/intro/compile.html"},{default:a(()=>[r("Сборка Xray")]),_:1}),r(".")])]),x,e("ul",null,[e("li",null,[r("Скачайте ZIP-архив для Windows на "),e("a",k,[r("Github Releases"),n(t)]),r(", распакуйте его, чтобы получить исполняемый файл "),w,r(", а затем "),X,r(".")]),e("li",null,[r("Установите с помощью менеджера пакетов "),e("a",S,[r("Scoop"),n(t)]),r(": Xray был добавлен в "),e("a",v,[r("Mochi"),n(t)]),r(".")])]),N,e("ul",null,[e("li",null,[r("Скачайте ZIP-архив для macOS на "),e("a",A,[r("Github Releases"),n(t)]),r(", распакуйте его, чтобы получить исполняемый файл "),R,r(", а затем "),n(l,{to:"/ru/document/command.html"},{default:a(()=>[r("запустите его из командной строки с параметрами")]),_:1}),r(".")]),e("li",null,[r("Установите с помощью менеджера пакетов "),e("a",L,[r("Homebrew"),n(t)]),r(": "),C,r(".")]),e("li",null,[e("a",D,[r("homebrew-xray"),n(t)]),r(" Спасибо, "),e("a",I,[r("@N4FA"),n(t)]),r("!")])]),O,P,e("ul",null,[e("li",null,[U,e("ul",null,[e("li",null,[e("a",M,[r("Xray-install"),n(t)])])])])]),e("ul",null,[e("li",null,[B,e("ul",null,[e("li",null,[e("a",W,[r("Xray-script"),n(t)])]),e("li",null,[e("a",F,[r("ProxySU"),n(t)])]),e("li",null,[e("a",G,[r("v2ray-agent"),n(t)]),r(" Спасибо, "),e("a",Q,[r("@mack-a"),n(t)]),r(),e("a",H,[r("@Reece"),n(t)]),r("!")]),e("li",null,[e("a",T,[r("Xray-yes"),n(t)])]),e("li",null,[e("a",V,[r("Xray-onekey"),n(t)])])])]),e("li",null,[j,e("ul",null,[e("li",null,[e("a",E,[r("Xray4Magisk"),n(t)])]),e("li",null,[e("a",K,[r("Xray_For_Magisk"),n(t)])])])])]),Z,z,e("p",null,[r("Требуется "),e("a",J,[r("помощник AUR"),n(t)]),r(", например, "),e("a",q,[r("yay"),n(t)]),r(", установка с помощью команды "),Y,r(".")]),$,e("p",null,[r("Сначала добавьте "),e("a",ee,[r("репозиторий Arch Linux CN"),n(t)]),r(", затем установите от имени пользователя root с помощью команды "),re,r(".")]),ne,te,e("h3",oe,[e("a",le,[e("span",null,[r("Debian "),n(h,{text:"WIP",type:"warning"})])])]),ae,se,e("ul",null,[e("li",null,[e("a",ie,[r("CHN-beta/touchfish-os"),n(t)]),r(": Поддерживается отдельным пользователем, подходит для систем с systemD.")]),e("li",null,[e("a",he,[r("Gentoo-zh"),n(t)]),r(": Поддерживается сообществом, подходит для систем с systemD.")]),e("li",null,[e("a",ce,[r("JuanCldCmt/Xray-Overlay"),n(t)]),r(": Поддерживается отдельным пользователем, подходит для систем с openRC, использует группу пользователей xray для повышения безопасности.")])]),ue,_e,e("ul",null,[e("li",null,[e("a",de,[r("teddysun/xray"),n(t)])])]),pe,e("ul",null,[e("li",null,[r("OpenWrt "),e("ul",null,[e("li",null,[e("a",be,[r("PassWall"),n(t)])]),e("li",null,[e("a",fe,[r("Hello World"),n(t)])]),e("li",null,[e("a",ge,[r("ShadowSocksR Plus+"),n(t)])]),e("li",null,[e("a",me,[r("luci-app-xray"),n(t)]),r(" ("),e("a",ye,[r("openwrt-xray"),n(t)]),r(")")])])]),e("li",null,[r("Windows "),e("ul",null,[e("li",null,[e("a",xe,[r("v2rayN"),n(t)])]),e("li",null,[e("a",ke,[r("Qv2ray"),n(t)]),r(" (проект заморожен и архивирован)")]),e("li",null,[e("a",we,[r("Netch (NetFilter & TUN/TAP)"),n(t)]),r(" (проект заморожен и архивирован)")])])]),e("li",null,[r("Android "),e("ul",null,[e("li",null,[e("a",Xe,[r("v2rayNG"),n(t)])]),e("li",null,[e("a",Se,[r("Kitsunebi"),n(t)])])])]),e("li",null,[r("iOS / macOS (с чипом ARM) "),e("ul",null,[e("li",null,[e("a",ve,[r("Shadowrocket"),n(t)])]),e("li",null,[e("a",Ne,[r("Stash"),n(t)])])])]),e("li",null,[r("macOS (чип X86 / ARM) "),e("ul",null,[e("li",null,[e("a",Ae,[r("Qv2ray"),n(t)]),r(" (проект заморожен и архивирован)")]),e("li",null,[e("a",Re,[r("V2RayXS"),n(t)])])])])]),Le,e("p",null,[r("Генератор UUID от сторонних разработчиков: "),e("a",Ce,[r("uuidgenerator.net"),n(t)])])])}const Ue=c(d,[["render",De],["__file","install.html.vue"]]);export{Ue as default}; +import{_ as c,r as o,o as u,c as _,a as n,b as e,d as r,w as a,e as s}from"./app-Bw2NG-QJ.js";const d={},p=s('

                                        Загрузка и установка

                                        Поддерживаемые платформы

                                        Xray доступен на следующих платформах:

                                        • Windows 7 и выше (x86 / amd64 / arm32 / arm64);
                                        • macOS 10.10 Yosemite и выше (amd64 / arm64);
                                        • Linux 2.6.23 и выше (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                          • Включая, но не ограничиваясь: Debian 7 / 8, Ubuntu 12.04 / 14.04 и выше, CentOS 7 / 8, Arch Linux и др.;
                                        • FreeBSD (x86 / amd64);
                                        • OpenBSD (x86 / amd64);
                                        • Dragonfly BSD (amd64);

                                        Загрузка Xray

                                        ',5),b={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},f=e("p",null,"Скачайте архив для своей платформы, распакуйте его и можете использовать.",-1),g=e("h2",{id:"проверка-установочного-пакета",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#проверка-установочного-пакета"},[e("span",null,"Проверка установочного пакета")])],-1),m=e("p",null,"Xray предлагает два способа проверки:",-1),y=e("li",null,"SHA1 / SHA256 хэш-сумма ZIP-архива;",-1),x=e("h2",{id:"установка-на-windows",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-на-windows"},[e("span",null,"Установка на Windows")])],-1),k={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},w=e("code",null,"xray.exe",-1),X=e("a",{href:"./command"},"запустите его из командной строки с параметрами",-1),S={href:"https://scoop.sh",target:"_blank",rel:"noopener noreferrer"},v={href:"https://github.com/Qv2ray/mochi",target:"_blank",rel:"noopener noreferrer"},N=e("h2",{id:"установка-на-macos",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-на-macos"},[e("span",null,"Установка на macOS")])],-1),A={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},R=e("code",null,"xray",-1),L={href:"https://brew.sh",target:"_blank",rel:"noopener noreferrer"},C=e("code",null,"brew install xray",-1),D={href:"https://github.com/N4FA/homebrew-xray",target:"_blank",rel:"noopener noreferrer"},I={href:"https://github.com/N4FA",target:"_blank",rel:"noopener noreferrer"},O=e("h2",{id:"установка-на-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-на-linux"},[e("span",null,"Установка на Linux")])],-1),P=e("h3",{id:"установочные-скрипты",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установочные-скрипты"},[e("span",null,"Установочные скрипты")])],-1),U=e("p",null,"Linux Script",-1),M={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=e("p",null,"One Click",-1),W={href:"https://github.com/kirin10000/Xray-script",target:"_blank",rel:"noopener noreferrer"},F={href:"https://github.com/proxysu/ProxySU",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/reeceyng/v2ray-agent",target:"_blank",rel:"noopener noreferrer"},Q={href:"https://github.com/mack-a",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/reeceyng",target:"_blank",rel:"noopener noreferrer"},T={href:"https://github.com/jiuqi9997/Xray-yes",target:"_blank",rel:"noopener noreferrer"},V={href:"https://github.com/wulabing/Xray_onekey",target:"_blank",rel:"noopener noreferrer"},j=e("p",null,"Magisk",-1),E={href:"https://github.com/CerteKim/Xray4Magisk",target:"_blank",rel:"noopener noreferrer"},K={href:"https://github.com/E7KMbb/Xray_For_Magisk",target:"_blank",rel:"noopener noreferrer"},Z=e("h3",{id:"arch-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux"},[e("span",null,"Arch Linux")])],-1),z=e("h4",{id:"arch-user-repository",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-user-repository"},[e("span",null,"Arch User Repository")])],-1),J={href:"https://wiki.archlinux.org/index.php/AUR_helpers",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/Jguer/yay",target:"_blank",rel:"noopener noreferrer"},Y=e("code",null,"yay -S xray",-1),$=e("h4",{id:"arch-linux-cn",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux-cn"},[e("span",null,"Arch Linux CN")])],-1),ee={href:"https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/",target:"_blank",rel:"noopener noreferrer"},re=e("code",null,"pacman -S xray",-1),ne=e("h3",{id:"linuxbrew",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linuxbrew"},[e("span",null,"Linuxbrew")])],-1),te=e("p",null,[r("Использование менеджера пакетов Linuxbrew аналогично Homebrew: "),e("code",null,"brew install xray"),r(".")],-1),oe={id:"debian",tabindex:"-1"},le={class:"header-anchor",href:"#debian"},ae=e("h3",{id:"gentoo",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#gentoo"},[e("span",null,"Gentoo")])],-1),se=e("p",null,"В настоящее время существует три оверлея сторонних разработчиков, которые предоставляют сценарии установки Portage:",-1),ie={href:"https://github.com/gentoo-mirror/touchfish-os/tree/master/net-proxy/Xray",target:"_blank",rel:"noopener noreferrer"},he={href:"https://github.com/microcai/gentoo-zh",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/JuanCldCmt/Xray-Overlay",target:"_blank",rel:"noopener noreferrer"},ue=e("p",null,"Добавьте оверлей в локальную систему с помощью layman или eselect-repository, а затем выполните установку.",-1),_e=e("h2",{id:"установка-с-помощью-docker",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#установка-с-помощью-docker"},[e("span",null,"Установка с помощью Docker")])],-1),de={href:"https://hub.docker.com/r/teddysun/xray",target:"_blank",rel:"noopener noreferrer"},pe=s('

                                        Файловая структура образа Docker

                                        • /etc/xray/config.json: файл конфигурации;
                                        • /usr/bin/xray: основная программа Xray;
                                        • /usr/share/xray/geoip.dat: файл данных IP;
                                        • /usr/share/xray/geosite.dat: файл данных доменных имен.

                                        Графические клиенты

                                        ',3),be={href:"https://github.com/xiaorouji/openwrt-passwall",target:"_blank",rel:"noopener noreferrer"},fe={href:"https://github.com/jerrykuku/luci-app-vssr",target:"_blank",rel:"noopener noreferrer"},ge={href:"https://github.com/fw876/helloworld",target:"_blank",rel:"noopener noreferrer"},me={href:"https://github.com/yichya/luci-app-xray",target:"_blank",rel:"noopener noreferrer"},ye={href:"https://github.com/yichya/openwrt-xray",target:"_blank",rel:"noopener noreferrer"},xe={href:"https://github.com/2dust/v2rayN",target:"_blank",rel:"noopener noreferrer"},ke={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},we={href:"https://github.com/NetchX/Netch",target:"_blank",rel:"noopener noreferrer"},Xe={href:"https://github.com/2dust/v2rayNG",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/rurirei/Kitsunebi/tree/release_xtls",target:"_blank",rel:"noopener noreferrer"},ve={href:"https://apps.apple.com/app/shadowrocket/id932747118",target:"_blank",rel:"noopener noreferrer"},Ne={href:"https://apps.apple.com/app/stash/id1596063349",target:"_blank",rel:"noopener noreferrer"},Ae={href:"https://github.com/Qv2ray/Qv2ray",target:"_blank",rel:"noopener noreferrer"},Re={href:"https://github.com/tzmax/V2RayXS",target:"_blank",rel:"noopener noreferrer"},Le=e("h1",{id:"генератор-uuid",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#генератор-uuid"},[e("span",null,"Генератор UUID")])],-1),Ce={href:"https://www.uuidgenerator.net",target:"_blank",rel:"noopener noreferrer"};function De(Ie,Oe){const i=o("I18nTip"),t=o("ExternalLinkIcon"),l=o("RouterLink"),h=o("Badge");return u(),_("div",null,[n(i),p,e("p",null,[r("Предварительно скомпилированные ZIP-архивы с двоичными файлами можно найти в "),e("a",b,[r("Github Releases"),n(t)]),r(".")]),f,g,m,e("ul",null,[y,e("li",null,[r("Воспроизводимая сборка: см. "),n(l,{to:"/ru/development/intro/compile.html"},{default:a(()=>[r("Сборка Xray")]),_:1}),r(".")])]),x,e("ul",null,[e("li",null,[r("Скачайте ZIP-архив для Windows на "),e("a",k,[r("Github Releases"),n(t)]),r(", распакуйте его, чтобы получить исполняемый файл "),w,r(", а затем "),X,r(".")]),e("li",null,[r("Установите с помощью менеджера пакетов "),e("a",S,[r("Scoop"),n(t)]),r(": Xray был добавлен в "),e("a",v,[r("Mochi"),n(t)]),r(".")])]),N,e("ul",null,[e("li",null,[r("Скачайте ZIP-архив для macOS на "),e("a",A,[r("Github Releases"),n(t)]),r(", распакуйте его, чтобы получить исполняемый файл "),R,r(", а затем "),n(l,{to:"/ru/document/command.html"},{default:a(()=>[r("запустите его из командной строки с параметрами")]),_:1}),r(".")]),e("li",null,[r("Установите с помощью менеджера пакетов "),e("a",L,[r("Homebrew"),n(t)]),r(": "),C,r(".")]),e("li",null,[e("a",D,[r("homebrew-xray"),n(t)]),r(" Спасибо, "),e("a",I,[r("@N4FA"),n(t)]),r("!")])]),O,P,e("ul",null,[e("li",null,[U,e("ul",null,[e("li",null,[e("a",M,[r("Xray-install"),n(t)])])])])]),e("ul",null,[e("li",null,[B,e("ul",null,[e("li",null,[e("a",W,[r("Xray-script"),n(t)])]),e("li",null,[e("a",F,[r("ProxySU"),n(t)])]),e("li",null,[e("a",G,[r("v2ray-agent"),n(t)]),r(" Спасибо, "),e("a",Q,[r("@mack-a"),n(t)]),r(),e("a",H,[r("@Reece"),n(t)]),r("!")]),e("li",null,[e("a",T,[r("Xray-yes"),n(t)])]),e("li",null,[e("a",V,[r("Xray-onekey"),n(t)])])])]),e("li",null,[j,e("ul",null,[e("li",null,[e("a",E,[r("Xray4Magisk"),n(t)])]),e("li",null,[e("a",K,[r("Xray_For_Magisk"),n(t)])])])])]),Z,z,e("p",null,[r("Требуется "),e("a",J,[r("помощник AUR"),n(t)]),r(", например, "),e("a",q,[r("yay"),n(t)]),r(", установка с помощью команды "),Y,r(".")]),$,e("p",null,[r("Сначала добавьте "),e("a",ee,[r("репозиторий Arch Linux CN"),n(t)]),r(", затем установите от имени пользователя root с помощью команды "),re,r(".")]),ne,te,e("h3",oe,[e("a",le,[e("span",null,[r("Debian "),n(h,{text:"WIP",type:"warning"})])])]),ae,se,e("ul",null,[e("li",null,[e("a",ie,[r("CHN-beta/touchfish-os"),n(t)]),r(": Поддерживается отдельным пользователем, подходит для систем с systemD.")]),e("li",null,[e("a",he,[r("Gentoo-zh"),n(t)]),r(": Поддерживается сообществом, подходит для систем с systemD.")]),e("li",null,[e("a",ce,[r("JuanCldCmt/Xray-Overlay"),n(t)]),r(": Поддерживается отдельным пользователем, подходит для систем с openRC, использует группу пользователей xray для повышения безопасности.")])]),ue,_e,e("ul",null,[e("li",null,[e("a",de,[r("teddysun/xray"),n(t)])])]),pe,e("ul",null,[e("li",null,[r("OpenWrt "),e("ul",null,[e("li",null,[e("a",be,[r("PassWall"),n(t)])]),e("li",null,[e("a",fe,[r("Hello World"),n(t)])]),e("li",null,[e("a",ge,[r("ShadowSocksR Plus+"),n(t)])]),e("li",null,[e("a",me,[r("luci-app-xray"),n(t)]),r(" ("),e("a",ye,[r("openwrt-xray"),n(t)]),r(")")])])]),e("li",null,[r("Windows "),e("ul",null,[e("li",null,[e("a",xe,[r("v2rayN"),n(t)])]),e("li",null,[e("a",ke,[r("Qv2ray"),n(t)]),r(" (проект заморожен и архивирован)")]),e("li",null,[e("a",we,[r("Netch (NetFilter & TUN/TAP)"),n(t)]),r(" (проект заморожен и архивирован)")])])]),e("li",null,[r("Android "),e("ul",null,[e("li",null,[e("a",Xe,[r("v2rayNG"),n(t)])]),e("li",null,[e("a",Se,[r("Kitsunebi"),n(t)])])])]),e("li",null,[r("iOS / macOS (с чипом ARM) "),e("ul",null,[e("li",null,[e("a",ve,[r("Shadowrocket"),n(t)])]),e("li",null,[e("a",Ne,[r("Stash"),n(t)])])])]),e("li",null,[r("macOS (чип X86 / ARM) "),e("ul",null,[e("li",null,[e("a",Ae,[r("Qv2ray"),n(t)]),r(" (проект заморожен и архивирован)")]),e("li",null,[e("a",Re,[r("V2RayXS"),n(t)])])])])]),Le,e("p",null,[r("Генератор UUID от сторонних разработчиков: "),e("a",Ce,[r("uuidgenerator.net"),n(t)])])])}const Ue=c(d,[["render",De],["__file","install.html.vue"]]);export{Ue as default}; diff --git a/assets/install.html-DvdIFSLJ.js b/assets/install.html-Cmyvi2cp.js similarity index 96% rename from assets/install.html-DvdIFSLJ.js rename to assets/install.html-Cmyvi2cp.js index e484d909f5..d537af9038 100644 --- a/assets/install.html-DvdIFSLJ.js +++ b/assets/install.html-Cmyvi2cp.js @@ -1 +1 @@ -const l=JSON.parse('{"key":"v-9cb72482","path":"/ru/document/install.html","title":"Загрузка и установка","lang":"ru-RU","frontmatter":{},"headers":[{"level":2,"title":"Поддерживаемые платформы","slug":"поддерживаемые-платформы","link":"#поддерживаемые-платформы","children":[]},{"level":2,"title":"Загрузка Xray","slug":"загрузка-xray","link":"#загрузка-xray","children":[]},{"level":2,"title":"Проверка установочного пакета","slug":"проверка-установочного-пакета","link":"#проверка-установочного-пакета","children":[]},{"level":2,"title":"Установка на Windows","slug":"установка-на-windows","link":"#установка-на-windows","children":[]},{"level":2,"title":"Установка на macOS","slug":"установка-на-macos","link":"#установка-на-macos","children":[]},{"level":2,"title":"Установка на Linux","slug":"установка-на-linux","link":"#установка-на-linux","children":[{"level":3,"title":"Установочные скрипты","slug":"установочные-скрипты","link":"#установочные-скрипты","children":[]},{"level":3,"title":"Arch Linux","slug":"arch-linux","link":"#arch-linux","children":[]},{"level":3,"title":"Linuxbrew","slug":"linuxbrew","link":"#linuxbrew","children":[]},{"level":3,"title":"Debian","slug":"debian","link":"#debian","children":[]},{"level":3,"title":"Gentoo","slug":"gentoo","link":"#gentoo","children":[]}]},{"level":2,"title":"Установка с помощью Docker","slug":"установка-с-помощью-docker","link":"#установка-с-помощью-docker","children":[{"level":3,"title":"Файловая структура образа Docker","slug":"фаиловая-структура-образа-docker","link":"#фаиловая-структура-образа-docker","children":[]}]}],"git":{"updatedTime":1721140925000,"contributors":[{"name":"Nikita Korotaev","email":"104270279+iambabyninja@users.noreply.github.com","commits":1}]},"filePathRelative":"ru/document/install.md","i18n":{"pathLocale":"/ru/","sourceLink":"/document/install.html","untranslated":false,"updatedTime":1721140925000,"sourceUpdatedTime":1699098917000}}');export{l as data}; +const l=JSON.parse('{"key":"v-9cb72482","path":"/ru/document/install.html","title":"Загрузка и установка","lang":"ru-RU","frontmatter":{},"headers":[{"level":2,"title":"Поддерживаемые платформы","slug":"поддерживаемые-платформы","link":"#поддерживаемые-платформы","children":[]},{"level":2,"title":"Загрузка Xray","slug":"загрузка-xray","link":"#загрузка-xray","children":[]},{"level":2,"title":"Проверка установочного пакета","slug":"проверка-установочного-пакета","link":"#проверка-установочного-пакета","children":[]},{"level":2,"title":"Установка на Windows","slug":"установка-на-windows","link":"#установка-на-windows","children":[]},{"level":2,"title":"Установка на macOS","slug":"установка-на-macos","link":"#установка-на-macos","children":[]},{"level":2,"title":"Установка на Linux","slug":"установка-на-linux","link":"#установка-на-linux","children":[{"level":3,"title":"Установочные скрипты","slug":"установочные-скрипты","link":"#установочные-скрипты","children":[]},{"level":3,"title":"Arch Linux","slug":"arch-linux","link":"#arch-linux","children":[]},{"level":3,"title":"Linuxbrew","slug":"linuxbrew","link":"#linuxbrew","children":[]},{"level":3,"title":"Debian","slug":"debian","link":"#debian","children":[]},{"level":3,"title":"Gentoo","slug":"gentoo","link":"#gentoo","children":[]}]},{"level":2,"title":"Установка с помощью Docker","slug":"установка-с-помощью-docker","link":"#установка-с-помощью-docker","children":[{"level":3,"title":"Файловая структура образа Docker","slug":"фаиловая-структура-образа-docker","link":"#фаиловая-структура-образа-docker","children":[]}]}],"git":{"updatedTime":1721140925000,"contributors":[{"name":"Nikita Korotaev","email":"104270279+iambabyninja@users.noreply.github.com","commits":1}]},"filePathRelative":"ru/document/install.md","i18n":{"pathLocale":"/ru/","sourceLink":"/document/install.html","untranslated":false,"updatedTime":1721140925000,"sourceUpdatedTime":1723610376000,"outdated":true}}');export{l as data}; diff --git a/assets/install.html-nEQK2zvn.js b/assets/install.html-nEQK2zvn.js new file mode 100644 index 0000000000..179e76e277 --- /dev/null +++ b/assets/install.html-nEQK2zvn.js @@ -0,0 +1 @@ +import{_ as i,r as a,o as h,c,a as n,b as e,d as r,e as o}from"./app-Bw2NG-QJ.js";const d={},u=o('

                                        Download and Install

                                        Platform Support

                                        • Xray is available on the following platforms:
                                          • Windows 7 and later (x86 / amd64 / arm32 / arm64);
                                            • If you need to use these version (1.8.4, 1.8.6, 1.8.18 and later marked with win7) in Windows 7, operating system update KB4474419 is required. Concerning for Internet security, it is recommended to install KB4490628 to acqacquire later operating systems from Windows Update.
                                          • macOS 10.10 Yosemite and later (amd64 / arm64);
                                          • Linux 2.6.23 and later (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                            • Including but not limited to Debian 7 / 8, Ubuntu 12.04 / 14.04 and subsequent versions, CentOS 7 / 8, Arch Linux, etc.;
                                          • FreeBSD (x86 / amd64);
                                          • OpenBSD (x86 / amd64);

                                        Download Xray

                                        ',4),p={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},_=e("p",null,"Download the compressed package of the corresponding platform, and use it after decompression.",-1),f=e("h2",{id:"verify-the-installation-package",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#verify-the-installation-package"},[e("span",null,"Verify the Installation Package")])],-1),b=e("p",null,"Xray provides two verification methods:",-1),g=e("li",null,"SHA1/SHA256 digest of the ZIP archive",-1),m={href:"https://xtls.github.io/development/intro/compile.html",target:"_blank",rel:"noopener noreferrer"},y=e("h2",{id:"install-on-windows",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-on-windows"},[e("span",null,"Install on Windows")])],-1),x={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},k=e("code",null,"xray.exe",-1),w=e("a",{href:"./command"},"parameters",-1),v={href:"https://scoop.sh/",target:"_blank",rel:"noopener noreferrer"},X={href:"https://github.com/Qv2ray/mochi",target:"_blank",rel:"noopener noreferrer"},S=e("h2",{id:"install-on-macos",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-on-macos"},[e("span",null,"Install on macOS")])],-1),I={href:"https://github.com/xtls/Xray-core/releases",target:"_blank",rel:"noopener noreferrer"},L=e("code",null,"xray",-1),A=e("a",{href:"./command"},"parameters",-1),P={href:"https://brew.sh/",target:"_blank",rel:"noopener noreferrer"},F=e("code",null,"brew install xray",-1),N={href:"https://github.com/N4FA/homebrew-xray",target:"_blank",rel:"noopener noreferrer"},R={href:"https://github.com/N4FA",target:"_blank",rel:"noopener noreferrer"},U=e("h2",{id:"install-on-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-on-linux"},[e("span",null,"Install on Linux")])],-1),D=e("h3",{id:"install-script",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-script"},[e("span",null,"Install Script")])],-1),O=e("p",null,"Linux Script",-1),T={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},B=e("strong",null,"Official",-1),C={href:"https://github.com/team-cloudchaser/tempest",target:"_blank",rel:"noopener noreferrer"},M={href:"https://systemd.io",target:"_blank",rel:"noopener noreferrer"},V=e("code",null,"systemd",-1),W={href:"https://github.com/OpenRC/openrc",target:"_blank",rel:"noopener noreferrer"},E=e("p",null,"One Click",-1),z={href:"https://github.com/zxcvos/Xray-script",target:"_blank",rel:"noopener noreferrer"},G={href:"https://github.com/sajjaddg/xray-reality",target:"_blank",rel:"noopener noreferrer"},j={href:"https://github.com/aleskxyz/reality-ezpz",target:"_blank",rel:"noopener noreferrer"},H={href:"https://github.com/hello-yunshu/Xray_bash_onekey",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/LordPenguin666/XTool",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://github.com/mack-a/v2ray-agent",target:"_blank",rel:"noopener noreferrer"},K={href:"https://github.com/wulabing/Xray_onekey",target:"_blank",rel:"noopener noreferrer"},Y={href:"https://github.com/proxysu/ProxySU",target:"_blank",rel:"noopener noreferrer"},J=e("p",null,"Magisk",-1),Q={href:"https://github.com/Asterisk4Magisk/Xray4Magisk",target:"_blank",rel:"noopener noreferrer"},$={href:"https://github.com/E7KMbb/Xray_For_Magisk",target:"_blank",rel:"noopener noreferrer"},ee=e("h3",{id:"arch-linux",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux"},[e("span",null,"Arch Linux")])],-1),re=e("h4",{id:"arch-user-repository",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-user-repository"},[e("span",null,"Arch User Repository")])],-1),ne={href:"https://wiki.archlinux.org/index.php/AUR_helpers",target:"_blank",rel:"noopener noreferrer"},te={href:"https://github.com/Jguer/yay",target:"_blank",rel:"noopener noreferrer"},ae=e("code",null,"yay -S xray",-1),oe=e("h4",{id:"arch-linux-cn",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#arch-linux-cn"},[e("span",null,"Arch Linux CN")])],-1),le={href:"https://www.archlinuxcn.org/archlinux-cn-repo-and-mirror/",target:"_blank",rel:"noopener noreferrer"},se=e("code",null,"pacman -S xray",-1),ie=e("h3",{id:"linuxbrew",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#linuxbrew"},[e("span",null,"Linuxbrew")])],-1),he=e("p",null,[r("The Linuxbrew package manager is used in the same way as Homebrew: "),e("code",null,"brew install xray")],-1),ce={id:"debian",tabindex:"-1"},de={class:"header-anchor",href:"#debian"},ue=e("h2",{id:"install-via-docker",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#install-via-docker"},[e("span",null,"Install via Docker")])],-1),pe={href:"https://hub.docker.com/r/teddysun/xray",target:"_blank",rel:"noopener noreferrer"},_e=o('

                                        The File Structure of the Docker Image

                                        • /etc/xray/config.json: configuration file
                                        • /usr/bin/xray: Xray main program
                                        • /usr/local/share/xray/geoip.dat: IP data file
                                        • /usr/local/share/xray/geosite.dat: domain name data file

                                        GUI Client

                                        ',3),fe={href:"https://github.com/xiaorouji/openwrt-passwall",target:"_blank",rel:"noopener noreferrer"},be={href:"https://github.com/xiaorouji/openwrt-passwall2",target:"_blank",rel:"noopener noreferrer"},ge={href:"https://github.com/fw876/helloworld",target:"_blank",rel:"noopener noreferrer"},me={href:"https://github.com/yichya/luci-app-xray",target:"_blank",rel:"noopener noreferrer"},ye={href:"https://github.com/yichya/openwrt-xray",target:"_blank",rel:"noopener noreferrer"},xe={href:"https://github.com/2dust/v2rayN",target:"_blank",rel:"noopener noreferrer"},ke={href:"https://github.com/LorenEteval/Furious",target:"_blank",rel:"noopener noreferrer"},we={href:"https://github.com/InvisibleManVPN/InvisibleMan-XRayClient",target:"_blank",rel:"noopener noreferrer"},ve={href:"https://github.com/2dust/v2rayNG",target:"_blank",rel:"noopener noreferrer"},Xe={href:"https://github.com/XTLS/X-flutter",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://apps.apple.com/app/foxray/id6448898396",target:"_blank",rel:"noopener noreferrer"},Ie={href:"https://apps.apple.com/app/streisand/id6450534064",target:"_blank",rel:"noopener noreferrer"},Le={href:"https://github.com/yanue/V2rayU",target:"_blank",rel:"noopener noreferrer"},Ae={href:"https://github.com/tzmax/V2RayXS",target:"_blank",rel:"noopener noreferrer"},Pe={href:"https://github.com/LorenEteval/Furious",target:"_blank",rel:"noopener noreferrer"},Fe={href:"https://apps.apple.com/app/foxray/id6448898396",target:"_blank",rel:"noopener noreferrer"},Ne={href:"https://github.com/v2rayA/v2rayA",target:"_blank",rel:"noopener noreferrer"},Re={href:"https://github.com/LorenEteval/Furious",target:"_blank",rel:"noopener noreferrer"},Ue=e("h1",{id:"uuid-generator",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#uuid-generator"},[e("span",null,"UUID Generator")])],-1),De={href:"https://www.uuidgenerator.net",target:"_blank",rel:"noopener noreferrer"};function Oe(Te,Be){const l=a("I18nTip"),t=a("ExternalLinkIcon"),s=a("Badge");return h(),c("div",null,[n(l),u,e("p",null,[r("Precompiled binaries in ZIP format are available at "),e("a",p,[r("GitHub Releases"),n(t)]),r(" found in.")]),_,f,b,e("ul",null,[g,e("li",null,[r("Reproducible build: Please refer to "),e("a",m,[r("Compile Xray"),n(t)])])]),y,e("ul",null,[e("li",null,[r("Download the ZIP archive suitable for the Windows platform on "),e("a",x,[r("Github Releases"),n(t)]),r(". After decompression, you can get an executable file "),k,r(", and then run it with "),w,r(" through the command line.")]),e("li",null,[r("By "),e("a",v,[r("Scoop"),n(t)]),r(" Package manager installation: Xray has been added to "),e("a",X,[r("Mochi"),n(t)]),r(".")])]),S,e("ul",null,[e("li",null,[r("Download the ZIP archive suitable for the macOS platform on "),e("a",I,[r("Github Releases"),n(t)]),r(". After decompression, you can get an executable file "),L,r(", and then run it with "),A,r(" through the command line.")]),e("li",null,[r("By "),e("a",P,[r("Homebrew"),n(t)]),r(" Package manager installation: "),F]),e("li",null,[e("a",N,[r("homebrew-xray"),n(t)]),r(": Thanks "),e("a",R,[r("@N4FA"),n(t)])])]),U,D,e("ul",null,[e("li",null,[O,e("ul",null,[e("li",null,[e("a",T,[r("XTLS/Xray-install"),n(t)]),r(" ("),B,r(")")]),e("li",null,[e("a",C,[r("tempest"),n(t)]),r(" (supports "),e("a",M,[V,n(t)]),r(" and "),e("a",W,[r("OpenRC"),n(t)]),r("; Linux-only)")])])])]),e("ul",null,[e("li",null,[E,e("ul",null,[e("li",null,[e("a",z,[r("Xray-REALITY"),n(t)]),r(", "),e("a",G,[r("xray-reality"),n(t)]),r(", "),e("a",j,[r("reality-ezpz"),n(t)])]),e("li",null,[e("a",H,[r("Xray_bash_onekey"),n(t)]),r(", "),e("a",q,[r("XTool"),n(t)])]),e("li",null,[e("a",Z,[r("v2ray-agent"),n(t)]),r(", "),e("a",K,[r("Xray_onekey"),n(t)]),r(", "),e("a",Y,[r("ProxySU"),n(t)])])])]),e("li",null,[J,e("ul",null,[e("li",null,[e("a",Q,[r("Xray4Magisk"),n(t)])]),e("li",null,[e("a",$,[r("Xray_For_Magisk"),n(t)])])])])]),ee,re,e("p",null,[r("Need to use "),e("a",ne,[r("AUR helpers"),n(t)]),r(", "),e("a",te,[r("yay"),n(t)]),r(" as an example, it can be installed via "),ae,r(".")]),oe,e("p",null,[r("First add "),e("a",le,[r("Arch Linux CN"),n(t)]),r(" repository, and then use the root user "),se,r("to install.")]),ie,he,e("h3",ce,[e("a",de,[e("span",null,[r("Debian "),n(s,{text:"WIP",type:"warning"})])])]),ue,e("ul",null,[e("li",null,[e("a",pe,[r("teddysun/xray"),n(t)])])]),_e,e("ul",null,[e("li",null,[r("OpenWrt "),e("ul",null,[e("li",null,[e("a",fe,[r("PassWall"),n(t)]),r(", "),e("a",be,[r("PassWall 2"),n(t)])]),e("li",null,[e("a",ge,[r("ShadowSocksR Plus+"),n(t)])]),e("li",null,[e("a",me,[r("luci-app-xray"),n(t)]),r(" ("),e("a",ye,[r("openwrt-xray"),n(t)]),r(")")])])]),e("li",null,[r("Windows "),e("ul",null,[e("li",null,[e("a",xe,[r("v2rayN"),n(t)])]),e("li",null,[e("a",ke,[r("Furious"),n(t)])]),e("li",null,[e("a",we,[r("Invisible Man - Xray"),n(t)])])])]),e("li",null,[r("Android "),e("ul",null,[e("li",null,[e("a",ve,[r("v2rayNG"),n(t)])]),e("li",null,[e("a",Xe,[r("X-flutter"),n(t)])])])]),e("li",null,[r("iOS & macOS arm64 "),e("ul",null,[e("li",null,[e("a",Se,[r("FoXray"),n(t)])]),e("li",null,[e("a",Ie,[r("Streisand"),n(t)])])])]),e("li",null,[r("macOS arm64 & x64 "),e("ul",null,[e("li",null,[e("a",Le,[r("V2rayU"),n(t)])]),e("li",null,[e("a",Ae,[r("V2RayXS"),n(t)])]),e("li",null,[e("a",Pe,[r("Furious"),n(t)])]),e("li",null,[e("a",Fe,[r("FoXray"),n(t)])])])]),e("li",null,[r("Linux "),e("ul",null,[e("li",null,[e("a",Ne,[r("v2rayA"),n(t)])]),e("li",null,[e("a",Re,[r("Furious"),n(t)])])])])]),Ue,e("p",null,[r("Third-party UUID generator "),e("a",De,[r("uuidgenerator.net"),n(t)])])])}const Me=i(d,[["render",Oe],["__file","install.html.vue"]]);export{Me as default}; diff --git a/assets/install.html-B3katEMP.js b/assets/install.html-xlRH6Hy9.js similarity index 70% rename from assets/install.html-B3katEMP.js rename to assets/install.html-xlRH6Hy9.js index 2afcd3a582..d4858b9441 100644 --- a/assets/install.html-B3katEMP.js +++ b/assets/install.html-xlRH6Hy9.js @@ -1 +1 @@ -const l=JSON.parse('{"key":"v-439608b6","path":"/en/document/install.html","title":"Download and Install","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Platform Support","slug":"platform-support","link":"#platform-support","children":[]},{"level":2,"title":"Download Xray","slug":"download-xray","link":"#download-xray","children":[]},{"level":2,"title":"Verify the Installation Package","slug":"verify-the-installation-package","link":"#verify-the-installation-package","children":[]},{"level":2,"title":"Install on Windows","slug":"install-on-windows","link":"#install-on-windows","children":[]},{"level":2,"title":"Install on macOS","slug":"install-on-macos","link":"#install-on-macos","children":[]},{"level":2,"title":"Install on Linux","slug":"install-on-linux","link":"#install-on-linux","children":[{"level":3,"title":"Install Script","slug":"install-script","link":"#install-script","children":[]},{"level":3,"title":"Arch Linux","slug":"arch-linux","link":"#arch-linux","children":[]},{"level":3,"title":"Linuxbrew","slug":"linuxbrew","link":"#linuxbrew","children":[]},{"level":3,"title":"Debian","slug":"debian","link":"#debian","children":[]}]},{"level":2,"title":"Install via Docker","slug":"install-via-docker","link":"#install-via-docker","children":[{"level":3,"title":"The File Structure of the Docker Image","slug":"the-file-structure-of-the-docker-image","link":"#the-file-structure-of-the-docker-image","children":[]}]}],"git":{"updatedTime":1677944035000,"contributors":[{"name":"Winston2084","email":"126307318+Winston2084@users.noreply.github.com","commits":1},{"name":"hmol233","email":"82594500+hmol233@users.noreply.github.com","commits":1},{"name":"yuhan6665","email":"1588741+yuhan6665@users.noreply.github.com","commits":1}]},"filePathRelative":"en/document/install.md","i18n":{"pathLocale":"/en/","sourceLink":"/document/install.html","untranslated":false,"updatedTime":1677944035000,"sourceUpdatedTime":1699098917000,"outdated":true}}');export{l as data}; +const l=JSON.parse('{"key":"v-439608b6","path":"/en/document/install.html","title":"Download and Install","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Platform Support","slug":"platform-support","link":"#platform-support","children":[]},{"level":2,"title":"Download Xray","slug":"download-xray","link":"#download-xray","children":[]},{"level":2,"title":"Verify the Installation Package","slug":"verify-the-installation-package","link":"#verify-the-installation-package","children":[]},{"level":2,"title":"Install on Windows","slug":"install-on-windows","link":"#install-on-windows","children":[]},{"level":2,"title":"Install on macOS","slug":"install-on-macos","link":"#install-on-macos","children":[]},{"level":2,"title":"Install on Linux","slug":"install-on-linux","link":"#install-on-linux","children":[{"level":3,"title":"Install Script","slug":"install-script","link":"#install-script","children":[]},{"level":3,"title":"Arch Linux","slug":"arch-linux","link":"#arch-linux","children":[]},{"level":3,"title":"Linuxbrew","slug":"linuxbrew","link":"#linuxbrew","children":[]},{"level":3,"title":"Debian","slug":"debian","link":"#debian","children":[]}]},{"level":2,"title":"Install via Docker","slug":"install-via-docker","link":"#install-via-docker","children":[{"level":3,"title":"The File Structure of the Docker Image","slug":"the-file-structure-of-the-docker-image","link":"#the-file-structure-of-the-docker-image","children":[]}]}],"git":{"updatedTime":1723610376000,"contributors":[{"name":"Kobe Arthur Scofield","email":"26771058+KobeArthurScofield@users.noreply.github.com","commits":1},{"name":"Winston2084","email":"126307318+Winston2084@users.noreply.github.com","commits":1},{"name":"hmol233","email":"82594500+hmol233@users.noreply.github.com","commits":1},{"name":"yuhan6665","email":"1588741+yuhan6665@users.noreply.github.com","commits":1}]},"filePathRelative":"en/document/install.md","i18n":{"pathLocale":"/en/","sourceLink":"/document/install.html","untranslated":false,"updatedTime":1723610376000,"sourceUpdatedTime":1723610376000}}');export{l as data}; diff --git a/assets/iptables_gid.html-DfoRMg8P.js b/assets/iptables_gid.html-D1piuJf5.js similarity index 99% rename from assets/iptables_gid.html-DfoRMg8P.js rename to assets/iptables_gid.html-D1piuJf5.js index 238daefea8..3e8d007e6b 100644 --- a/assets/iptables_gid.html-DfoRMg8P.js +++ b/assets/iptables_gid.html-D1piuJf5.js @@ -1,4 +1,4 @@ -import{_ as l,r as t,o as i,c as o,a as n,b as a,d as s,e as p}from"./app-5SoadDYS.js";const c={},d=a("h1",{id:"прозрачное-проксирование-исключение-трафика-xray-с-помощью-gid",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#прозрачное-проксирование-исключение-трафика-xray-с-помощью-gid"},[a("span",null,"Прозрачное проксирование: Исключение трафика Xray с помощью GID")])],-1),m={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=a("strong",null,[a("a",{href:"./tproxy"},"Руководство по настройке прозрачного проксирования (TProxy)")],-1),u=a("p",null,"У такого подхода есть несколько недостатков:",-1),k={href:"https://github.com/v2ray/v2ray-core/issues/2621",target:"_blank",rel:"noopener noreferrer"},h=a("li",null,[a("p",null,"Android использует собственный механизм меток, поэтому данный метод не применим к Android")],-1),g=p('

                                        Предлагаемый в данном руководстве подход не требует использования меток, теоретически обеспечивая более высокую производительность и избегая описанных выше проблем.

                                        Идея

                                        Tproxy трафик может приниматься только пользователями с правами root (uid==0) или CAP_NET_ADMIN.

                                        Правила iptables позволяют разделять трафик на основе UID (идентификатор пользователя) и GID (идентификатор группы).

                                        Запустим Xray от имени пользователя с uid==0 и gid!=0 и настроим правила iptables, чтобы исключить трафик с этим GID, избегая проксирования трафика Xray.

                                        Настройка

                                        1. Предварительная подготовка

                                        Android

                                        ',8),D=a("li",null,"На устройстве должны быть получены root-права.",-1),B={href:"https://play.google.com/store/apps/details?id=stericson.busybox",target:"_blank",rel:"noopener noreferrer"},_=a("li",null,"Наличие терминала для выполнения команд, например, adb shell, Termux и т.д.",-1),A=p(`

                                        Другие Linux системы

                                        Необходимо наличие sudo, модуля tproxy для iptables и модуля extra.

                                        Обычно все это уже установлено в системе, для OpenWRT выполните:

                                        opkg install sudo iptables-mod-tproxy iptables-mod-extra
                                        +import{_ as l,r as t,o as i,c as o,a as n,b as a,d as s,e as p}from"./app-Bw2NG-QJ.js";const c={},d=a("h1",{id:"прозрачное-проксирование-исключение-трафика-xray-с-помощью-gid",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#прозрачное-проксирование-исключение-трафика-xray-с-помощью-gid"},[a("span",null,"Прозрачное проксирование: Исключение трафика Xray с помощью GID")])],-1),m={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=a("strong",null,[a("a",{href:"./tproxy"},"Руководство по настройке прозрачного проксирования (TProxy)")],-1),u=a("p",null,"У такого подхода есть несколько недостатков:",-1),k={href:"https://github.com/v2ray/v2ray-core/issues/2621",target:"_blank",rel:"noopener noreferrer"},h=a("li",null,[a("p",null,"Android использует собственный механизм меток, поэтому данный метод не применим к Android")],-1),g=p('

                                        Предлагаемый в данном руководстве подход не требует использования меток, теоретически обеспечивая более высокую производительность и избегая описанных выше проблем.

                                        Идея

                                        Tproxy трафик может приниматься только пользователями с правами root (uid==0) или CAP_NET_ADMIN.

                                        Правила iptables позволяют разделять трафик на основе UID (идентификатор пользователя) и GID (идентификатор группы).

                                        Запустим Xray от имени пользователя с uid==0 и gid!=0 и настроим правила iptables, чтобы исключить трафик с этим GID, избегая проксирования трафика Xray.

                                        Настройка

                                        1. Предварительная подготовка

                                        Android

                                        ',8),D=a("li",null,"На устройстве должны быть получены root-права.",-1),B={href:"https://play.google.com/store/apps/details?id=stericson.busybox",target:"_blank",rel:"noopener noreferrer"},_=a("li",null,"Наличие терминала для выполнения команд, например, adb shell, Termux и т.д.",-1),A=p(`

                                        Другие Linux системы

                                        Необходимо наличие sudo, модуля tproxy для iptables и модуля extra.

                                        Обычно все это уже установлено в системе, для OpenWRT выполните:

                                        opkg install sudo iptables-mod-tproxy iptables-mod-extra
                                         

                                        Также могут понадобиться следующие зависимости для OpenWRT, их отсутствие может помешать запуску Xray:

                                        opkg install libopenssl ca-certificates
                                         

                                        2. Добавление пользователя (пропустите для Android)

                                        Android не поддерживает файл /etc/passwd для управления пользователями, пропустите этот шаг и перейдите к следующему.

                                        grep -qw xray_tproxy /etc/passwd || echo "xray_tproxy:x:0:23333:::" >> /etc/passwd
                                         

                                        Где xray_tproxy - имя пользователя, 0 - UID, 23333 - GID. Имя пользователя и GID можно задать произвольно, UID должен быть равен 0. Проверьте, успешно ли добавлен пользователь, выполнив:

                                        sudo -u xray_tproxy id
                                        diff --git a/assets/iptables_gid.html-C7KP3nA5.js b/assets/iptables_gid.html-DlCxBcK6.js
                                        similarity index 99%
                                        rename from assets/iptables_gid.html-C7KP3nA5.js
                                        rename to assets/iptables_gid.html-DlCxBcK6.js
                                        index 8747e09699..aa3b3e221e 100644
                                        --- a/assets/iptables_gid.html-C7KP3nA5.js
                                        +++ b/assets/iptables_gid.html-DlCxBcK6.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as t,o as i,c as o,a as n,b as a,d as s,e as p}from"./app-5SoadDYS.js";const c={},d=a("h1",{id:"透明代理通过-gid-规避-xray-流量",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#透明代理通过-gid-规避-xray-流量"},[a("span",null,"透明代理通过 gid 规避 Xray 流量")])],-1),m={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},u=a("strong",null,[a("a",{href:"./tproxy"},"透明代理(TProxy)配置教程")],-1),b=a("p",null,"这么做有以下几个问题:",-1),k={href:"https://github.com/v2ray/v2ray-core/issues/2621",target:"_blank",rel:"noopener noreferrer"},g=a("li",null,[a("p",null,"安卓系统有自己的 mark 机制,该方案在安卓上不可用")],-1),h=p('

                                        本教程的方案不需要设置 mark,理论性能更高,同时也不存在上述问题。

                                        思路

                                        tproxy 流量只能被 root 权限用户(uid==0)或其他有 CAP_NET_ADMIN 权限的用户接收。

                                        iptables 规则可以通过 uid(用户 id)和 gid(用户组 id)分流。

                                        让 Xray 运行在一个 uid==0 但 gid!=0 的用户上,设置 iptables 规则不代理该 gid 的流量来规避 Xray 流量。

                                        配置过程

                                        1. 前期准备

                                        安卓系统

                                        ',8),_=a("li",null,[a("p",null,"系统已 root")],-1),A={href:"https://play.google.com/store/apps/details?id=stericson.busybox",target:"_blank",rel:"noopener noreferrer"},y=a("li",null,[a("p",null,"有一个可以执行命令的终端,可以使用 adb shell,termux 等。")],-1),x=p(`

                                        其它 Linux 系统

                                        需要依赖 sudo,iptables 的 tproxy 模块和 extra 模块。

                                        一般系统都有自带,openwrt 运行:

                                        opkg install sudo iptables-mod-tproxy iptables-mod-extra
                                        +import{_ as l,r as t,o as i,c as o,a as n,b as a,d as s,e as p}from"./app-Bw2NG-QJ.js";const c={},d=a("h1",{id:"透明代理通过-gid-规避-xray-流量",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#透明代理通过-gid-规避-xray-流量"},[a("span",null,"透明代理通过 gid 规避 Xray 流量")])],-1),m={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},u=a("strong",null,[a("a",{href:"./tproxy"},"透明代理(TProxy)配置教程")],-1),b=a("p",null,"这么做有以下几个问题:",-1),k={href:"https://github.com/v2ray/v2ray-core/issues/2621",target:"_blank",rel:"noopener noreferrer"},g=a("li",null,[a("p",null,"安卓系统有自己的 mark 机制,该方案在安卓上不可用")],-1),h=p('

                                        本教程的方案不需要设置 mark,理论性能更高,同时也不存在上述问题。

                                        思路

                                        tproxy 流量只能被 root 权限用户(uid==0)或其他有 CAP_NET_ADMIN 权限的用户接收。

                                        iptables 规则可以通过 uid(用户 id)和 gid(用户组 id)分流。

                                        让 Xray 运行在一个 uid==0 但 gid!=0 的用户上,设置 iptables 规则不代理该 gid 的流量来规避 Xray 流量。

                                        配置过程

                                        1. 前期准备

                                        安卓系统

                                        ',8),_=a("li",null,[a("p",null,"系统已 root")],-1),A={href:"https://play.google.com/store/apps/details?id=stericson.busybox",target:"_blank",rel:"noopener noreferrer"},y=a("li",null,[a("p",null,"有一个可以执行命令的终端,可以使用 adb shell,termux 等。")],-1),x=p(`

                                        其它 Linux 系统

                                        需要依赖 sudo,iptables 的 tproxy 模块和 extra 模块。

                                        一般系统都有自带,openwrt 运行:

                                        opkg install sudo iptables-mod-tproxy iptables-mod-extra
                                         

                                        另附上一些 openwrt 常用的依赖,缺少可能导致 Xray 无法运行

                                        opkg install libopenssl ca-certificates
                                         

                                        2. 添加用户(安卓用户请忽略)

                                        安卓系统不支持/etc/passwd 文件来管理用户,请忽略,直接下一步。

                                        grep -qw xray_tproxy /etc/passwd || echo "xray_tproxy:x:0:23333:::" >> /etc/passwd
                                         

                                        其中 xray_tproxy 是用户名,0 是 uid,23333 是 gid,用户名和 gid 可以自己定,uid 必须为 0。 检查用户是否添加成功,运行

                                        sudo -u xray_tproxy id
                                        diff --git a/assets/iptables_gid.html-BzWg4Lzk.js b/assets/iptables_gid.html-KGEztY8A.js
                                        similarity index 99%
                                        rename from assets/iptables_gid.html-BzWg4Lzk.js
                                        rename to assets/iptables_gid.html-KGEztY8A.js
                                        index cccd91163d..edf777c2a3 100644
                                        --- a/assets/iptables_gid.html-BzWg4Lzk.js
                                        +++ b/assets/iptables_gid.html-KGEztY8A.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as o,r,o as l,c,a as n,b as a,d as e,w as d,e as t}from"./app-5SoadDYS.js";const u={},m=a("h1",{id:"transparent-proxy-to-circumvent-xray-traffic-via-gid",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#transparent-proxy-to-circumvent-xray-traffic-via-gid"},[a("span",null,"Transparent proxy to circumvent Xray traffic via GID")])],-1),b={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},h=a("p",null,"There are several problems with this method:",-1),k={href:"https://github.com/v2ray/v2ray-core/issues/2621",target:"_blank",rel:"noopener noreferrer"},g=a("li",null,[a("p",null,"Android has its own mark mechanism and this solution is not available on Android")],-1),f=t('

                                        The solution in this tutorial does not require a mark setting and has a higher theoretical performance, as well as not having the problems mentioned above.

                                        Ideas

                                        TProxy traffic can only be received by users with root privileges (uid==0) or other users with CAP_NET_ADMIN privileges.

                                        The iptables rules can separate network traffic by uid (user id) and gid (user group id). Let Xray run on a user with uid==0 but gid!=0. Set the iptables rule to not proxy traffic for that gid to circumvent Xray traffic.

                                        Configuration Procedure

                                        1. Preliminary preparation

                                        Android

                                        ',7),y=a("li",null,[a("p",null,"System has root privilege.")],-1),x={href:"https://play.google.com/store/apps/details?id=stericson.busybox",target:"_blank",rel:"noopener noreferrer"},_=a("li",null,[a("p",null,"There is a terminal that can execute commands, you can use adb shell, termux etc.")],-1),w=t(`

                                        Other Linux system

                                        Need sudo, iptables-tproxy module and iptables-extra module。

                                        Usually the system comes with these functions. If you are using openwrt, you will need to run the following command:

                                        opkg install sudo iptables-mod-tproxy iptables-mod-extra
                                        +import{_ as o,r,o as l,c,a as n,b as a,d as e,w as d,e as t}from"./app-Bw2NG-QJ.js";const u={},m=a("h1",{id:"transparent-proxy-to-circumvent-xray-traffic-via-gid",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#transparent-proxy-to-circumvent-xray-traffic-via-gid"},[a("span",null,"Transparent proxy to circumvent Xray traffic via GID")])],-1),b={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},h=a("p",null,"There are several problems with this method:",-1),k={href:"https://github.com/v2ray/v2ray-core/issues/2621",target:"_blank",rel:"noopener noreferrer"},g=a("li",null,[a("p",null,"Android has its own mark mechanism and this solution is not available on Android")],-1),f=t('

                                        The solution in this tutorial does not require a mark setting and has a higher theoretical performance, as well as not having the problems mentioned above.

                                        Ideas

                                        TProxy traffic can only be received by users with root privileges (uid==0) or other users with CAP_NET_ADMIN privileges.

                                        The iptables rules can separate network traffic by uid (user id) and gid (user group id). Let Xray run on a user with uid==0 but gid!=0. Set the iptables rule to not proxy traffic for that gid to circumvent Xray traffic.

                                        Configuration Procedure

                                        1. Preliminary preparation

                                        Android

                                        ',7),y=a("li",null,[a("p",null,"System has root privilege.")],-1),x={href:"https://play.google.com/store/apps/details?id=stericson.busybox",target:"_blank",rel:"noopener noreferrer"},_=a("li",null,[a("p",null,"There is a terminal that can execute commands, you can use adb shell, termux etc.")],-1),w=t(`

                                        Other Linux system

                                        Need sudo, iptables-tproxy module and iptables-extra module。

                                        Usually the system comes with these functions. If you are using openwrt, you will need to run the following command:

                                        opkg install sudo iptables-mod-tproxy iptables-mod-extra
                                         

                                        Also attached are some common dependencies for openwrt, the lack of which may prevent Xray from running

                                        opkg install libopenssl ca-certificates
                                         

                                        2. Add user (Android users please ignore this section)

                                        Android does not support managing users by modifying the /etc/passwd file, please ignore it and go straight to the next step.

                                        grep -qw xray_tproxy /etc/passwd || echo "xray_tproxy:x:0:23333:::" >> /etc/passwd
                                         

                                        where xray_tproxy is the username, 0 is the uid and 23333 is the gid, the username and gid can be set by yourself, the uid must be 0. To check if the user was added successfully, run

                                        sudo -u xray_tproxy id
                                        diff --git a/assets/journeyDiagram-6625b456-CHnHUPp6.js b/assets/journeyDiagram-6625b456-Bh6Njlro.js
                                        similarity index 98%
                                        rename from assets/journeyDiagram-6625b456-CHnHUPp6.js
                                        rename to assets/journeyDiagram-6625b456-Bh6Njlro.js
                                        index b9258ae940..5be71ebf6e 100644
                                        --- a/assets/journeyDiagram-6625b456-CHnHUPp6.js
                                        +++ b/assets/journeyDiagram-6625b456-Bh6Njlro.js
                                        @@ -1,4 +1,4 @@
                                        -import{c as A,x as yt,y as ft,s as dt,g as pt,b as gt,a as mt,A as xt,h as W,i as kt}from"./mermaid.core-CArNAncI.js";import{d as _t,f as bt,a as vt,g as it}from"./svgDrawCommon-5e1cfd1d-BWP2bQZS.js";import{a as Q}from"./arc-xLaeEKkr.js";import"./app-5SoadDYS.js";import"./path-CbwjOpE9.js";var G=function(){var t=function(p,s,r,a){for(r=r||{},a=p.length;a--;r[p[a]]=s);return r},e=[6,8,10,11,12,14,16,17,18],i=[1,9],l=[1,10],n=[1,11],h=[1,12],c=[1,13],f=[1,14],y={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,taskName:18,taskData:19,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",18:"taskName",19:"taskData"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,2]],performAction:function(s,r,a,u,d,o,w){var k=o.length-1;switch(d){case 1:return o[k-1];case 2:this.$=[];break;case 3:o[k-1].push(o[k]),this.$=o[k-1];break;case 4:case 5:this.$=o[k];break;case 6:case 7:this.$=[];break;case 8:u.setDiagramTitle(o[k].substr(6)),this.$=o[k].substr(6);break;case 9:this.$=o[k].trim(),u.setAccTitle(this.$);break;case 10:case 11:this.$=o[k].trim(),u.setAccDescription(this.$);break;case 12:u.addSection(o[k].substr(8)),this.$=o[k].substr(8);break;case 13:u.addTask(o[k-1],o[k]),this.$="task";break}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:i,12:l,14:n,16:h,17:c,18:f},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:15,11:i,12:l,14:n,16:h,17:c,18:f},t(e,[2,5]),t(e,[2,6]),t(e,[2,8]),{13:[1,16]},{15:[1,17]},t(e,[2,11]),t(e,[2,12]),{19:[1,18]},t(e,[2,4]),t(e,[2,9]),t(e,[2,10]),t(e,[2,13])],defaultActions:{},parseError:function(s,r){if(r.recoverable)this.trace(s);else{var a=new Error(s);throw a.hash=r,a}},parse:function(s){var r=this,a=[0],u=[],d=[null],o=[],w=this.table,k="",R=0,Z=0,lt=2,J=1,ct=o.slice.call(arguments,1),x=Object.create(this.lexer),S={yy:{}};for(var z in this.yy)Object.prototype.hasOwnProperty.call(this.yy,z)&&(S.yy[z]=this.yy[z]);x.setInput(s,S.yy),S.yy.lexer=x,S.yy.parser=this,typeof x.yylloc>"u"&&(x.yylloc={});var Y=x.yylloc;o.push(Y);var ht=x.options&&x.options.ranges;typeof S.yy.parseError=="function"?this.parseError=S.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ut(){var T;return T=u.pop()||x.lex()||J,typeof T!="number"&&(T instanceof Array&&(u=T,T=u.pop()),T=r.symbols_[T]||T),T}for(var _,E,b,O,I={},N,$,K,B;;){if(E=a[a.length-1],this.defaultActions[E]?b=this.defaultActions[E]:((_===null||typeof _>"u")&&(_=ut()),b=w[E]&&w[E][_]),typeof b>"u"||!b.length||!b[0]){var q="";B=[];for(N in w[E])this.terminals_[N]&&N>lt&&B.push("'"+this.terminals_[N]+"'");x.showPosition?q="Parse error on line "+(R+1)+`:
                                        +import{c as A,x as yt,y as ft,s as dt,g as pt,b as gt,a as mt,A as xt,h as W,i as kt}from"./mermaid.core-Bq0kX0MS.js";import{d as _t,f as bt,a as vt,g as it}from"./svgDrawCommon-5e1cfd1d-CX_gVtbt.js";import{a as Q}from"./arc-C5d-KvsZ.js";import"./app-Bw2NG-QJ.js";import"./path-CbwjOpE9.js";var G=function(){var t=function(p,s,r,a){for(r=r||{},a=p.length;a--;r[p[a]]=s);return r},e=[6,8,10,11,12,14,16,17,18],i=[1,9],l=[1,10],n=[1,11],h=[1,12],c=[1,13],f=[1,14],y={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,taskName:18,taskData:19,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",18:"taskName",19:"taskData"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,2]],performAction:function(s,r,a,u,d,o,w){var k=o.length-1;switch(d){case 1:return o[k-1];case 2:this.$=[];break;case 3:o[k-1].push(o[k]),this.$=o[k-1];break;case 4:case 5:this.$=o[k];break;case 6:case 7:this.$=[];break;case 8:u.setDiagramTitle(o[k].substr(6)),this.$=o[k].substr(6);break;case 9:this.$=o[k].trim(),u.setAccTitle(this.$);break;case 10:case 11:this.$=o[k].trim(),u.setAccDescription(this.$);break;case 12:u.addSection(o[k].substr(8)),this.$=o[k].substr(8);break;case 13:u.addTask(o[k-1],o[k]),this.$="task";break}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:i,12:l,14:n,16:h,17:c,18:f},t(e,[2,7],{1:[2,1]}),t(e,[2,3]),{9:15,11:i,12:l,14:n,16:h,17:c,18:f},t(e,[2,5]),t(e,[2,6]),t(e,[2,8]),{13:[1,16]},{15:[1,17]},t(e,[2,11]),t(e,[2,12]),{19:[1,18]},t(e,[2,4]),t(e,[2,9]),t(e,[2,10]),t(e,[2,13])],defaultActions:{},parseError:function(s,r){if(r.recoverable)this.trace(s);else{var a=new Error(s);throw a.hash=r,a}},parse:function(s){var r=this,a=[0],u=[],d=[null],o=[],w=this.table,k="",R=0,Z=0,lt=2,J=1,ct=o.slice.call(arguments,1),x=Object.create(this.lexer),S={yy:{}};for(var z in this.yy)Object.prototype.hasOwnProperty.call(this.yy,z)&&(S.yy[z]=this.yy[z]);x.setInput(s,S.yy),S.yy.lexer=x,S.yy.parser=this,typeof x.yylloc>"u"&&(x.yylloc={});var Y=x.yylloc;o.push(Y);var ht=x.options&&x.options.ranges;typeof S.yy.parseError=="function"?this.parseError=S.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ut(){var T;return T=u.pop()||x.lex()||J,typeof T!="number"&&(T instanceof Array&&(u=T,T=u.pop()),T=r.symbols_[T]||T),T}for(var _,E,b,O,I={},N,$,K,B;;){if(E=a[a.length-1],this.defaultActions[E]?b=this.defaultActions[E]:((_===null||typeof _>"u")&&(_=ut()),b=w[E]&&w[E][_]),typeof b>"u"||!b.length||!b[0]){var q="";B=[];for(N in w[E])this.terminals_[N]&&N>lt&&B.push("'"+this.terminals_[N]+"'");x.showPosition?q="Parse error on line "+(R+1)+`:
                                         `+x.showPosition()+`
                                         Expecting `+B.join(", ")+", got '"+(this.terminals_[_]||_)+"'":q="Parse error on line "+(R+1)+": Unexpected "+(_==J?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(q,{text:x.match,token:this.terminals_[_]||_,line:x.yylineno,loc:Y,expected:B})}if(b[0]instanceof Array&&b.length>1)throw new Error("Parse Error: multiple actions possible at state: "+E+", token: "+_);switch(b[0]){case 1:a.push(_),d.push(x.yytext),o.push(x.yylloc),a.push(b[1]),_=null,Z=x.yyleng,k=x.yytext,R=x.yylineno,Y=x.yylloc;break;case 2:if($=this.productions_[b[1]][1],I.$=d[d.length-$],I._$={first_line:o[o.length-($||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-($||1)].first_column,last_column:o[o.length-1].last_column},ht&&(I._$.range=[o[o.length-($||1)].range[0],o[o.length-1].range[1]]),O=this.performAction.apply(I,[k,Z,R,S.yy,b[1],d,o].concat(ct)),typeof O<"u")return O;$&&(a=a.slice(0,-1*$*2),d=d.slice(0,-1*$),o=o.slice(0,-1*$)),a.push(this.productions_[b[1]][0]),d.push(I.$),o.push(I._$),K=w[a[a.length-2]][a[a.length-1]],a.push(K);break;case 3:return!0}}return!0}},m=function(){var p={EOF:1,parseError:function(r,a){if(this.yy.parser)this.yy.parser.parseError(r,a);else throw new Error(r)},setInput:function(s,r){return this.yy=r||this.yy||{},this._input=s,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var s=this._input[0];this.yytext+=s,this.yyleng++,this.offset++,this.match+=s,this.matched+=s;var r=s.match(/(?:\r\n?|\n).*/g);return r?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),s},unput:function(s){var r=s.length,a=s.split(/(?:\r\n?|\n)/g);this._input=s+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-r),this.offset-=r;var u=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),a.length-1&&(this.yylineno-=a.length-1);var d=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:a?(a.length===u.length?this.yylloc.first_column:0)+u[u.length-a.length].length-a[0].length:this.yylloc.first_column-r},this.options.ranges&&(this.yylloc.range=[d[0],d[0]+this.yyleng-r]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(s){this.unput(this.match.slice(s))},pastInput:function(){var s=this.matched.substr(0,this.matched.length-this.match.length);return(s.length>20?"...":"")+s.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var s=this.match;return s.length<20&&(s+=this._input.substr(0,20-s.length)),(s.substr(0,20)+(s.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var s=this.pastInput(),r=new Array(s.length+1).join("-");return s+this.upcomingInput()+`
                                        diff --git a/assets/layout-BlaWeSu5.js b/assets/layout-DSxgfneE.js
                                        similarity index 99%
                                        rename from assets/layout-BlaWeSu5.js
                                        rename to assets/layout-DSxgfneE.js
                                        index 42f2052218..748fdd7e6b 100644
                                        --- a/assets/layout-BlaWeSu5.js
                                        +++ b/assets/layout-DSxgfneE.js
                                        @@ -1 +1 @@
                                        -import{i as F,b as gn,a as zn,c as L,k as Xn,d as Un,e as Hn,g as P,j as xn,l as En,m as kn,t as jn,n as yn,o as Kn,p as Jn,f as s,G as x,h as w,q as g,r as M,v as y,s as Y}from"./graph-D2qW7eTj.js";import{R as A,ag as Qn,ah as Zn,a6 as Nn,ai as B,K as Ln,_ as ne,E as _n,D as K,a4 as ee,aj as re,a3 as J,a2 as te,Y as Cn,Q as ie,a8 as ae,ak as H}from"./mermaid.core-CArNAncI.js";var oe=/\s/;function ue(n){for(var e=n.length;e--&&oe.test(n.charAt(e)););return e}var de=/^\s+/;function fe(n){return n&&n.slice(0,ue(n)+1).replace(de,"")}var un=NaN,se=/^[-+]0x[0-9a-f]+$/i,ce=/^0b[01]+$/i,he=/^0o[0-7]+$/i,le=parseInt;function ve(n){if(typeof n=="number")return n;if(F(n))return un;if(A(n)){var e=typeof n.valueOf=="function"?n.valueOf():n;n=A(e)?e+"":e}if(typeof n!="string")return n===0?n:+n;n=fe(n);var r=ce.test(n);return r||he.test(n)?le(n.slice(2),r?2:8):se.test(n)?un:+n}var dn=1/0,pe=17976931348623157e292;function S(n){if(!n)return n===0?n:0;if(n=ve(n),n===dn||n===-dn){var e=n<0?-1:1;return e*pe}return n===n?n:0}function we(n){var e=S(n),r=e%1;return e===e?r?e-r:e:0}function _(n){var e=n==null?0:n.length;return e?gn(n):[]}function me(n){return Qn(Zn(n,void 0,_),n+"")}var be=1,ge=4;function xe(n){return zn(n,be|ge)}var In=Object.prototype,Ee=In.hasOwnProperty,ke=Nn(function(n,e){n=Object(n);var r=-1,t=e.length,i=t>2?e[2]:void 0;for(i&&B(e[0],e[1],i)&&(t=1);++r-1?i[o?e[a]:a]:void 0}}var Ne=Math.max;function Le(n,e,r){var t=n==null?0:n.length;if(!t)return-1;var i=r==null?0:we(r);return i<0&&(i=Ne(t+i,0)),Un(n,L(e),i)}var Q=ye(Le);function Rn(n,e){var r=-1,t=_n(n)?Array(n.length):[];return Hn(n,function(i,o,a){t[++r]=e(i,o,a)}),t}function m(n,e){var r=K(n)?P:Rn;return r(n,L(e))}function _e(n,e){return n==null?n:ee(n,xn(e),Ln)}function Ce(n,e){return n&&En(n,xn(e))}function Ie(n,e){return n>e}function Tn(n,e){return ne||o&&a&&d&&!u&&!f||t&&a&&d||!r&&d||!i)return 1;if(!t&&!o&&!f&&n=u)return d;var f=r[t];return d*(f=="desc"?-1:1)}}return n.index-e.index}function Se(n,e,r){e.length?e=P(e,function(o){return K(o)?function(a){return yn(a,o.length===1?o[0]:o)}:o}):e=[J];var t=-1;e=P(e,ie(L));var i=Rn(n,function(o,a,u){var d=P(e,function(f){return f(o)});return{criteria:d,index:++t,value:o}});return Me(i,function(o,a){return Pe(o,a,r)})}function Fe(n,e){return Te(n,e,function(r,t){return Kn(n,t)})}var V=me(function(n,e){return n==null?{}:Fe(n,e)}),Ae=Math.ceil,Be=Math.max;function Ge(n,e,r,t){for(var i=-1,o=Be(Ae((e-n)/(r||1)),0),a=Array(o);o--;)a[++i]=n,n+=r;return a}function Ve(n){return function(e,r,t){return t&&typeof t!="number"&&B(e,r,t)&&(r=t=void 0),e=S(e),r===void 0?(r=e,e=0):r=S(r),t=t===void 0?e1&&B(n,e[0],e[1])?e=[]:r>2&&B(e[0],e[1],e[2])&&(e=[e[0]]),Se(n,gn(e),[])}),Ye=0;function en(n){var e=++Ye;return Jn(n)+e}function De(n,e,r){for(var t=-1,i=n.length,o=e.length,a={};++t0;--u)if(a=e[u].dequeue(),a){t=t.concat(q(n,e,r,a,!0));break}}}return t}function q(n,e,r,t,i){var o=i?[]:void 0;return s(n.inEdges(t.v),function(a){var u=n.edge(a),d=n.node(a.v);i&&o.push({v:a.v,w:a.w}),d.out-=u,j(e,r,d)}),s(n.outEdges(t.v),function(a){var u=n.edge(a),d=a.w,f=n.node(d);f.in-=u,j(e,r,f)}),n.removeNode(t.v),o}function He(n,e){var r=new x,t=0,i=0;s(n.nodes(),function(u){r.setNode(u,{v:u,in:0,out:0})}),s(n.edges(),function(u){var d=r.edge(u.v,u.w)||0,f=e(u),c=d+f;r.setEdge(u.v,u.w,c),i=Math.max(i,r.node(u.v).out+=f),t=Math.max(t,r.node(u.w).in+=f)});var o=N(i+t+3).map(function(){return new qe}),a=t+1;return s(r.nodes(),function(u){j(o,a,r.node(u))}),{graph:r,buckets:o,zeroIdx:a}}function j(n,e,r){r.out?r.in?n[r.out-r.in+e].enqueue(r):n[n.length-1].enqueue(r):n[0].enqueue(r)}function je(n){var e=n.graph().acyclicer==="greedy"?Xe(n,r(n)):Ke(n);s(e,function(t){var i=n.edge(t);n.removeEdge(t),i.forwardName=t.name,i.reversed=!0,n.setEdge(t.w,t.v,i,en("rev"))});function r(t){return function(i){return t.edge(i).weight}}}function Ke(n){var e=[],r={},t={};function i(o){w(t,o)||(t[o]=!0,r[o]=!0,s(n.outEdges(o),function(a){w(r,a.w)?e.push(a):i(a.w)}),delete r[o])}return s(n.nodes(),i),e}function Je(n){s(n.edges(),function(e){var r=n.edge(e);if(r.reversed){n.removeEdge(e);var t=r.forwardName;delete r.reversed,delete r.forwardName,n.setEdge(e.w,e.v,r,t)}})}function C(n,e,r,t){var i;do i=en(t);while(n.hasNode(i));return r.dummy=e,n.setNode(i,r),i}function Qe(n){var e=new x().setGraph(n.graph());return s(n.nodes(),function(r){e.setNode(r,n.node(r))}),s(n.edges(),function(r){var t=e.edge(r.v,r.w)||{weight:0,minlen:1},i=n.edge(r);e.setEdge(r.v,r.w,{weight:t.weight+i.weight,minlen:Math.max(t.minlen,i.minlen)})}),e}function Mn(n){var e=new x({multigraph:n.isMultigraph()}).setGraph(n.graph());return s(n.nodes(),function(r){n.children(r).length||e.setNode(r,n.node(r))}),s(n.edges(),function(r){e.setEdge(r,n.edge(r))}),e}function sn(n,e){var r=n.x,t=n.y,i=e.x-r,o=e.y-t,a=n.width/2,u=n.height/2;if(!i&&!o)throw new Error("Not possible to find intersection inside of the rectangle");var d,f;return Math.abs(o)*a>Math.abs(i)*u?(o<0&&(u=-u),d=u*i/o,f=u):(i<0&&(a=-a),d=a,f=a*o/i),{x:r+d,y:t+f}}function $(n){var e=m(N(On(n)+1),function(){return[]});return s(n.nodes(),function(r){var t=n.node(r),i=t.rank;g(i)||(e[i][t.order]=r)}),e}function Ze(n){var e=R(m(n.nodes(),function(r){return n.node(r).rank}));s(n.nodes(),function(r){var t=n.node(r);w(t,"rank")&&(t.rank-=e)})}function nr(n){var e=R(m(n.nodes(),function(o){return n.node(o).rank})),r=[];s(n.nodes(),function(o){var a=n.node(o).rank-e;r[a]||(r[a]=[]),r[a].push(o)});var t=0,i=n.graph().nodeRankFactor;s(r,function(o,a){g(o)&&a%i!==0?--t:t&&s(o,function(u){n.node(u).rank+=t})})}function cn(n,e,r,t){var i={width:0,height:0};return arguments.length>=4&&(i.rank=r,i.order=t),C(n,"border",i,e)}function On(n){return E(m(n.nodes(),function(e){var r=n.node(e).rank;if(!g(r))return r}))}function er(n,e){var r={lhs:[],rhs:[]};return s(n,function(t){e(t)?r.lhs.push(t):r.rhs.push(t)}),r}function rr(n,e){return e()}function tr(n){function e(r){var t=n.children(r),i=n.node(r);if(t.length&&s(t,e),w(i,"minRank")){i.borderLeft=[],i.borderRight=[];for(var o=i.minRank,a=i.maxRank+1;oa.lim&&(u=a,d=!0);var f=M(e.edges(),function(c){return d===vn(n,n.node(c.v),u)&&d!==vn(n,n.node(c.w),u)});return nn(f,function(c){return T(e,c)})}function Dn(n,e,r,t){var i=r.v,o=r.w;n.removeEdge(i,o),n.setEdge(t.v,t.w,{}),an(n),tn(n,e),br(n,e)}function br(n,e){var r=Q(n.nodes(),function(i){return!e.node(i).parent}),t=wr(n,r);t=t.slice(1),s(t,function(i){var o=n.node(i).parent,a=e.edge(i,o),u=!1;a||(a=e.edge(o,i),u=!0),e.node(i).rank=e.node(o).rank+(u?a.minlen:-a.minlen)})}function gr(n,e,r){return n.hasEdge(e,r)}function vn(n,e,r){return r.low<=e.lim&&e.lim<=r.lim}function xr(n){switch(n.graph().ranker){case"network-simplex":pn(n);break;case"tight-tree":kr(n);break;case"longest-path":Er(n);break;default:pn(n)}}var Er=rn;function kr(n){rn(n),Sn(n)}function pn(n){k(n)}function yr(n){var e=C(n,"root",{},"_root"),r=Nr(n),t=E(y(r))-1,i=2*t+1;n.graph().nestingRoot=e,s(n.edges(),function(a){n.edge(a).minlen*=i});var o=Lr(n)+1;s(n.children(),function(a){$n(n,e,i,o,t,r,a)}),n.graph().nodeRankFactor=i}function $n(n,e,r,t,i,o,a){var u=n.children(a);if(!u.length){a!==e&&n.setEdge(e,a,{weight:0,minlen:r});return}var d=cn(n,"_bt"),f=cn(n,"_bb"),c=n.node(a);n.setParent(d,a),c.borderTop=d,n.setParent(f,a),c.borderBottom=f,s(u,function(h){$n(n,e,r,t,i,o,h);var l=n.node(h),v=l.borderTop?l.borderTop:h,p=l.borderBottom?l.borderBottom:h,b=l.borderTop?t:2*t,I=v!==p?1:i-o[a]+1;n.setEdge(d,v,{weight:b,minlen:I,nestingEdge:!0}),n.setEdge(p,f,{weight:b,minlen:I,nestingEdge:!0})}),n.parent(a)||n.setEdge(e,d,{weight:0,minlen:i+o[a]})}function Nr(n){var e={};function r(t,i){var o=n.children(t);o&&o.length&&s(o,function(a){r(a,i+1)}),e[t]=i}return s(n.children(),function(t){r(t,1)}),e}function Lr(n){return Y(n.edges(),function(e,r){return e+n.edge(r).weight},0)}function _r(n){var e=n.graph();n.removeNode(e.nestingRoot),delete e.nestingRoot,s(n.edges(),function(r){var t=n.edge(r);t.nestingEdge&&n.removeEdge(r)})}function Cr(n,e,r){var t={},i;s(r,function(o){for(var a=n.parent(o),u,d;a;){if(u=n.parent(a),u?(d=t[u],t[u]=a):(d=i,i=a),d&&d!==a){e.setEdge(d,a);return}a=u}})}function Ir(n,e,r){var t=Rr(n),i=new x({compound:!0}).setGraph({root:t}).setDefaultNodeLabel(function(o){return n.node(o)});return s(n.nodes(),function(o){var a=n.node(o),u=n.parent(o);(a.rank===e||a.minRank<=e&&e<=a.maxRank)&&(i.setNode(o),i.setParent(o,u||t),s(n[r](o),function(d){var f=d.v===o?d.w:d.v,c=i.edge(f,o),h=g(c)?0:c.weight;i.setEdge(f,o,{weight:n.edge(d).weight+h})}),w(a,"minRank")&&i.setNode(o,{borderLeft:a.borderLeft[e],borderRight:a.borderRight[e]}))}),i}function Rr(n){for(var e;n.hasNode(e=en("_root")););return e}function Tr(n,e){for(var r=0,t=1;t0;)c%2&&(h+=u[c+1]),c=c-1>>1,u[c]+=f.weight;d+=f.weight*h})),d}function Or(n){var e={},r=M(n.nodes(),function(u){return!n.children(u).length}),t=E(m(r,function(u){return n.node(u).rank})),i=m(N(t+1),function(){return[]});function o(u){if(!w(e,u)){e[u]=!0;var d=n.node(u);i[d.rank].push(u),s(n.successors(u),o)}}var a=O(r,function(u){return n.node(u).rank});return s(a,o),i}function Pr(n,e){return m(e,function(r){var t=n.inEdges(r);if(t.length){var i=Y(t,function(o,a){var u=n.edge(a),d=n.node(a.v);return{sum:o.sum+u.weight*d.order,weight:o.weight+u.weight}},{sum:0,weight:0});return{v:r,barycenter:i.sum/i.weight,weight:i.weight}}else return{v:r}})}function Sr(n,e){var r={};s(n,function(i,o){var a=r[i.v]={indegree:0,in:[],out:[],vs:[i.v],i:o};g(i.barycenter)||(a.barycenter=i.barycenter,a.weight=i.weight)}),s(e.edges(),function(i){var o=r[i.v],a=r[i.w];!g(o)&&!g(a)&&(a.indegree++,o.out.push(r[i.w]))});var t=M(r,function(i){return!i.indegree});return Fr(t)}function Fr(n){var e=[];function r(o){return function(a){a.merged||(g(a.barycenter)||g(o.barycenter)||a.barycenter>=o.barycenter)&&Ar(o,a)}}function t(o){return function(a){a.in.push(o),--a.indegree===0&&n.push(a)}}for(;n.length;){var i=n.pop();e.push(i),s(i.in.reverse(),r(i)),s(i.out,t(i))}return m(M(e,function(o){return!o.merged}),function(o){return V(o,["vs","i","barycenter","weight"])})}function Ar(n,e){var r=0,t=0;n.weight&&(r+=n.barycenter*n.weight,t+=n.weight),e.weight&&(r+=e.barycenter*e.weight,t+=e.weight),n.vs=e.vs.concat(n.vs),n.barycenter=r/t,n.weight=t,n.i=Math.min(e.i,n.i),e.merged=!0}function Br(n,e){var r=er(n,function(c){return w(c,"barycenter")}),t=r.lhs,i=O(r.rhs,function(c){return-c.i}),o=[],a=0,u=0,d=0;t.sort(Gr(!!e)),d=wn(o,i,d),s(t,function(c){d+=c.vs.length,o.push(c.vs),a+=c.barycenter*c.weight,u+=c.weight,d=wn(o,i,d)});var f={vs:_(o)};return u&&(f.barycenter=a/u,f.weight=u),f}function wn(n,e,r){for(var t;e.length&&(t=G(e)).i<=r;)e.pop(),n.push(t.vs),r++;return r}function Gr(n){return function(e,r){return e.barycenterr.barycenter?1:n?r.i-e.i:e.i-r.i}}function qn(n,e,r,t){var i=n.children(e),o=n.node(e),a=o?o.borderLeft:void 0,u=o?o.borderRight:void 0,d={};a&&(i=M(i,function(p){return p!==a&&p!==u}));var f=Pr(n,i);s(f,function(p){if(n.children(p.v).length){var b=qn(n,p.v,r,t);d[p.v]=b,w(b,"barycenter")&&Yr(p,b)}});var c=Sr(f,r);Vr(c,d);var h=Br(c,t);if(a&&(h.vs=_([a,h.vs,u]),n.predecessors(a).length)){var l=n.node(n.predecessors(a)[0]),v=n.node(n.predecessors(u)[0]);w(h,"barycenter")||(h.barycenter=0,h.weight=0),h.barycenter=(h.barycenter*h.weight+l.order+v.order)/(h.weight+2),h.weight+=2}return h}function Vr(n,e){s(n,function(r){r.vs=_(r.vs.map(function(t){return e[t]?e[t].vs:t}))})}function Yr(n,e){g(n.barycenter)?(n.barycenter=e.barycenter,n.weight=e.weight):(n.barycenter=(n.barycenter*n.weight+e.barycenter*e.weight)/(n.weight+e.weight),n.weight+=e.weight)}function Dr(n){var e=On(n),r=mn(n,N(1,e+1),"inEdges"),t=mn(n,N(e-1,-1,-1),"outEdges"),i=Or(n);bn(n,i);for(var o=Number.POSITIVE_INFINITY,a,u=0,d=0;d<4;++u,++d){$r(u%2?r:t,u%4>=2),i=$(n);var f=Tr(n,i);fa||u>e[d].lim));for(f=d,d=t;(d=n.parent(d))!==f;)o.push(d);return{path:i.concat(o.reverse()),lca:f}}function zr(n){var e={},r=0;function t(i){var o=r;s(n.children(i),t),e[i]={low:o,lim:r++}}return s(n.children(),t),e}function Xr(n,e){var r={};function t(i,o){var a=0,u=0,d=i.length,f=G(o);return s(o,function(c,h){var l=Hr(n,c),v=l?n.node(l).order:d;(l||c===f)&&(s(o.slice(u,h+1),function(p){s(n.predecessors(p),function(b){var I=n.node(b),on=I.order;(onf)&&Wn(r,l,c)})})}function i(o,a){var u=-1,d,f=0;return s(a,function(c,h){if(n.node(c).dummy==="border"){var l=n.predecessors(c);l.length&&(d=n.node(l[0]).order,t(a,f,h,u,d),f=h,u=d)}t(a,f,a.length,d,o.length)}),a}return Y(e,i),r}function Hr(n,e){if(n.node(e).dummy)return Q(n.predecessors(e),function(r){return n.node(r).dummy})}function Wn(n,e,r){if(e>r){var t=e;e=r,r=t}var i=n[e];i||(n[e]=i={}),i[r]=!0}function jr(n,e,r){if(e>r){var t=e;e=r,r=t}return w(n[e],r)}function Kr(n,e,r,t){var i={},o={},a={};return s(e,function(u){s(u,function(d,f){i[d]=d,o[d]=d,a[d]=f})}),s(e,function(u){var d=-1;s(u,function(f){var c=t(f);if(c.length){c=O(c,function(b){return a[b]});for(var h=(c.length-1)/2,l=Math.floor(h),v=Math.ceil(h);l<=v;++l){var p=c[l];o[f]===f&&d2?e[2]:void 0;for(i&&B(e[0],e[1],i)&&(t=1);++r-1?i[o?e[a]:a]:void 0}}var Ne=Math.max;function Le(n,e,r){var t=n==null?0:n.length;if(!t)return-1;var i=r==null?0:we(r);return i<0&&(i=Ne(t+i,0)),Un(n,L(e),i)}var Q=ye(Le);function Rn(n,e){var r=-1,t=_n(n)?Array(n.length):[];return Hn(n,function(i,o,a){t[++r]=e(i,o,a)}),t}function m(n,e){var r=K(n)?P:Rn;return r(n,L(e))}function _e(n,e){return n==null?n:ee(n,xn(e),Ln)}function Ce(n,e){return n&&En(n,xn(e))}function Ie(n,e){return n>e}function Tn(n,e){return ne||o&&a&&d&&!u&&!f||t&&a&&d||!r&&d||!i)return 1;if(!t&&!o&&!f&&n=u)return d;var f=r[t];return d*(f=="desc"?-1:1)}}return n.index-e.index}function Se(n,e,r){e.length?e=P(e,function(o){return K(o)?function(a){return yn(a,o.length===1?o[0]:o)}:o}):e=[J];var t=-1;e=P(e,ie(L));var i=Rn(n,function(o,a,u){var d=P(e,function(f){return f(o)});return{criteria:d,index:++t,value:o}});return Me(i,function(o,a){return Pe(o,a,r)})}function Fe(n,e){return Te(n,e,function(r,t){return Kn(n,t)})}var V=me(function(n,e){return n==null?{}:Fe(n,e)}),Ae=Math.ceil,Be=Math.max;function Ge(n,e,r,t){for(var i=-1,o=Be(Ae((e-n)/(r||1)),0),a=Array(o);o--;)a[++i]=n,n+=r;return a}function Ve(n){return function(e,r,t){return t&&typeof t!="number"&&B(e,r,t)&&(r=t=void 0),e=S(e),r===void 0?(r=e,e=0):r=S(r),t=t===void 0?e1&&B(n,e[0],e[1])?e=[]:r>2&&B(e[0],e[1],e[2])&&(e=[e[0]]),Se(n,gn(e),[])}),Ye=0;function en(n){var e=++Ye;return Jn(n)+e}function De(n,e,r){for(var t=-1,i=n.length,o=e.length,a={};++t0;--u)if(a=e[u].dequeue(),a){t=t.concat(q(n,e,r,a,!0));break}}}return t}function q(n,e,r,t,i){var o=i?[]:void 0;return s(n.inEdges(t.v),function(a){var u=n.edge(a),d=n.node(a.v);i&&o.push({v:a.v,w:a.w}),d.out-=u,j(e,r,d)}),s(n.outEdges(t.v),function(a){var u=n.edge(a),d=a.w,f=n.node(d);f.in-=u,j(e,r,f)}),n.removeNode(t.v),o}function He(n,e){var r=new x,t=0,i=0;s(n.nodes(),function(u){r.setNode(u,{v:u,in:0,out:0})}),s(n.edges(),function(u){var d=r.edge(u.v,u.w)||0,f=e(u),c=d+f;r.setEdge(u.v,u.w,c),i=Math.max(i,r.node(u.v).out+=f),t=Math.max(t,r.node(u.w).in+=f)});var o=N(i+t+3).map(function(){return new qe}),a=t+1;return s(r.nodes(),function(u){j(o,a,r.node(u))}),{graph:r,buckets:o,zeroIdx:a}}function j(n,e,r){r.out?r.in?n[r.out-r.in+e].enqueue(r):n[n.length-1].enqueue(r):n[0].enqueue(r)}function je(n){var e=n.graph().acyclicer==="greedy"?Xe(n,r(n)):Ke(n);s(e,function(t){var i=n.edge(t);n.removeEdge(t),i.forwardName=t.name,i.reversed=!0,n.setEdge(t.w,t.v,i,en("rev"))});function r(t){return function(i){return t.edge(i).weight}}}function Ke(n){var e=[],r={},t={};function i(o){w(t,o)||(t[o]=!0,r[o]=!0,s(n.outEdges(o),function(a){w(r,a.w)?e.push(a):i(a.w)}),delete r[o])}return s(n.nodes(),i),e}function Je(n){s(n.edges(),function(e){var r=n.edge(e);if(r.reversed){n.removeEdge(e);var t=r.forwardName;delete r.reversed,delete r.forwardName,n.setEdge(e.w,e.v,r,t)}})}function C(n,e,r,t){var i;do i=en(t);while(n.hasNode(i));return r.dummy=e,n.setNode(i,r),i}function Qe(n){var e=new x().setGraph(n.graph());return s(n.nodes(),function(r){e.setNode(r,n.node(r))}),s(n.edges(),function(r){var t=e.edge(r.v,r.w)||{weight:0,minlen:1},i=n.edge(r);e.setEdge(r.v,r.w,{weight:t.weight+i.weight,minlen:Math.max(t.minlen,i.minlen)})}),e}function Mn(n){var e=new x({multigraph:n.isMultigraph()}).setGraph(n.graph());return s(n.nodes(),function(r){n.children(r).length||e.setNode(r,n.node(r))}),s(n.edges(),function(r){e.setEdge(r,n.edge(r))}),e}function sn(n,e){var r=n.x,t=n.y,i=e.x-r,o=e.y-t,a=n.width/2,u=n.height/2;if(!i&&!o)throw new Error("Not possible to find intersection inside of the rectangle");var d,f;return Math.abs(o)*a>Math.abs(i)*u?(o<0&&(u=-u),d=u*i/o,f=u):(i<0&&(a=-a),d=a,f=a*o/i),{x:r+d,y:t+f}}function $(n){var e=m(N(On(n)+1),function(){return[]});return s(n.nodes(),function(r){var t=n.node(r),i=t.rank;g(i)||(e[i][t.order]=r)}),e}function Ze(n){var e=R(m(n.nodes(),function(r){return n.node(r).rank}));s(n.nodes(),function(r){var t=n.node(r);w(t,"rank")&&(t.rank-=e)})}function nr(n){var e=R(m(n.nodes(),function(o){return n.node(o).rank})),r=[];s(n.nodes(),function(o){var a=n.node(o).rank-e;r[a]||(r[a]=[]),r[a].push(o)});var t=0,i=n.graph().nodeRankFactor;s(r,function(o,a){g(o)&&a%i!==0?--t:t&&s(o,function(u){n.node(u).rank+=t})})}function cn(n,e,r,t){var i={width:0,height:0};return arguments.length>=4&&(i.rank=r,i.order=t),C(n,"border",i,e)}function On(n){return E(m(n.nodes(),function(e){var r=n.node(e).rank;if(!g(r))return r}))}function er(n,e){var r={lhs:[],rhs:[]};return s(n,function(t){e(t)?r.lhs.push(t):r.rhs.push(t)}),r}function rr(n,e){return e()}function tr(n){function e(r){var t=n.children(r),i=n.node(r);if(t.length&&s(t,e),w(i,"minRank")){i.borderLeft=[],i.borderRight=[];for(var o=i.minRank,a=i.maxRank+1;oa.lim&&(u=a,d=!0);var f=M(e.edges(),function(c){return d===vn(n,n.node(c.v),u)&&d!==vn(n,n.node(c.w),u)});return nn(f,function(c){return T(e,c)})}function Dn(n,e,r,t){var i=r.v,o=r.w;n.removeEdge(i,o),n.setEdge(t.v,t.w,{}),an(n),tn(n,e),br(n,e)}function br(n,e){var r=Q(n.nodes(),function(i){return!e.node(i).parent}),t=wr(n,r);t=t.slice(1),s(t,function(i){var o=n.node(i).parent,a=e.edge(i,o),u=!1;a||(a=e.edge(o,i),u=!0),e.node(i).rank=e.node(o).rank+(u?a.minlen:-a.minlen)})}function gr(n,e,r){return n.hasEdge(e,r)}function vn(n,e,r){return r.low<=e.lim&&e.lim<=r.lim}function xr(n){switch(n.graph().ranker){case"network-simplex":pn(n);break;case"tight-tree":kr(n);break;case"longest-path":Er(n);break;default:pn(n)}}var Er=rn;function kr(n){rn(n),Sn(n)}function pn(n){k(n)}function yr(n){var e=C(n,"root",{},"_root"),r=Nr(n),t=E(y(r))-1,i=2*t+1;n.graph().nestingRoot=e,s(n.edges(),function(a){n.edge(a).minlen*=i});var o=Lr(n)+1;s(n.children(),function(a){$n(n,e,i,o,t,r,a)}),n.graph().nodeRankFactor=i}function $n(n,e,r,t,i,o,a){var u=n.children(a);if(!u.length){a!==e&&n.setEdge(e,a,{weight:0,minlen:r});return}var d=cn(n,"_bt"),f=cn(n,"_bb"),c=n.node(a);n.setParent(d,a),c.borderTop=d,n.setParent(f,a),c.borderBottom=f,s(u,function(h){$n(n,e,r,t,i,o,h);var l=n.node(h),v=l.borderTop?l.borderTop:h,p=l.borderBottom?l.borderBottom:h,b=l.borderTop?t:2*t,I=v!==p?1:i-o[a]+1;n.setEdge(d,v,{weight:b,minlen:I,nestingEdge:!0}),n.setEdge(p,f,{weight:b,minlen:I,nestingEdge:!0})}),n.parent(a)||n.setEdge(e,d,{weight:0,minlen:i+o[a]})}function Nr(n){var e={};function r(t,i){var o=n.children(t);o&&o.length&&s(o,function(a){r(a,i+1)}),e[t]=i}return s(n.children(),function(t){r(t,1)}),e}function Lr(n){return Y(n.edges(),function(e,r){return e+n.edge(r).weight},0)}function _r(n){var e=n.graph();n.removeNode(e.nestingRoot),delete e.nestingRoot,s(n.edges(),function(r){var t=n.edge(r);t.nestingEdge&&n.removeEdge(r)})}function Cr(n,e,r){var t={},i;s(r,function(o){for(var a=n.parent(o),u,d;a;){if(u=n.parent(a),u?(d=t[u],t[u]=a):(d=i,i=a),d&&d!==a){e.setEdge(d,a);return}a=u}})}function Ir(n,e,r){var t=Rr(n),i=new x({compound:!0}).setGraph({root:t}).setDefaultNodeLabel(function(o){return n.node(o)});return s(n.nodes(),function(o){var a=n.node(o),u=n.parent(o);(a.rank===e||a.minRank<=e&&e<=a.maxRank)&&(i.setNode(o),i.setParent(o,u||t),s(n[r](o),function(d){var f=d.v===o?d.w:d.v,c=i.edge(f,o),h=g(c)?0:c.weight;i.setEdge(f,o,{weight:n.edge(d).weight+h})}),w(a,"minRank")&&i.setNode(o,{borderLeft:a.borderLeft[e],borderRight:a.borderRight[e]}))}),i}function Rr(n){for(var e;n.hasNode(e=en("_root")););return e}function Tr(n,e){for(var r=0,t=1;t0;)c%2&&(h+=u[c+1]),c=c-1>>1,u[c]+=f.weight;d+=f.weight*h})),d}function Or(n){var e={},r=M(n.nodes(),function(u){return!n.children(u).length}),t=E(m(r,function(u){return n.node(u).rank})),i=m(N(t+1),function(){return[]});function o(u){if(!w(e,u)){e[u]=!0;var d=n.node(u);i[d.rank].push(u),s(n.successors(u),o)}}var a=O(r,function(u){return n.node(u).rank});return s(a,o),i}function Pr(n,e){return m(e,function(r){var t=n.inEdges(r);if(t.length){var i=Y(t,function(o,a){var u=n.edge(a),d=n.node(a.v);return{sum:o.sum+u.weight*d.order,weight:o.weight+u.weight}},{sum:0,weight:0});return{v:r,barycenter:i.sum/i.weight,weight:i.weight}}else return{v:r}})}function Sr(n,e){var r={};s(n,function(i,o){var a=r[i.v]={indegree:0,in:[],out:[],vs:[i.v],i:o};g(i.barycenter)||(a.barycenter=i.barycenter,a.weight=i.weight)}),s(e.edges(),function(i){var o=r[i.v],a=r[i.w];!g(o)&&!g(a)&&(a.indegree++,o.out.push(r[i.w]))});var t=M(r,function(i){return!i.indegree});return Fr(t)}function Fr(n){var e=[];function r(o){return function(a){a.merged||(g(a.barycenter)||g(o.barycenter)||a.barycenter>=o.barycenter)&&Ar(o,a)}}function t(o){return function(a){a.in.push(o),--a.indegree===0&&n.push(a)}}for(;n.length;){var i=n.pop();e.push(i),s(i.in.reverse(),r(i)),s(i.out,t(i))}return m(M(e,function(o){return!o.merged}),function(o){return V(o,["vs","i","barycenter","weight"])})}function Ar(n,e){var r=0,t=0;n.weight&&(r+=n.barycenter*n.weight,t+=n.weight),e.weight&&(r+=e.barycenter*e.weight,t+=e.weight),n.vs=e.vs.concat(n.vs),n.barycenter=r/t,n.weight=t,n.i=Math.min(e.i,n.i),e.merged=!0}function Br(n,e){var r=er(n,function(c){return w(c,"barycenter")}),t=r.lhs,i=O(r.rhs,function(c){return-c.i}),o=[],a=0,u=0,d=0;t.sort(Gr(!!e)),d=wn(o,i,d),s(t,function(c){d+=c.vs.length,o.push(c.vs),a+=c.barycenter*c.weight,u+=c.weight,d=wn(o,i,d)});var f={vs:_(o)};return u&&(f.barycenter=a/u,f.weight=u),f}function wn(n,e,r){for(var t;e.length&&(t=G(e)).i<=r;)e.pop(),n.push(t.vs),r++;return r}function Gr(n){return function(e,r){return e.barycenterr.barycenter?1:n?r.i-e.i:e.i-r.i}}function qn(n,e,r,t){var i=n.children(e),o=n.node(e),a=o?o.borderLeft:void 0,u=o?o.borderRight:void 0,d={};a&&(i=M(i,function(p){return p!==a&&p!==u}));var f=Pr(n,i);s(f,function(p){if(n.children(p.v).length){var b=qn(n,p.v,r,t);d[p.v]=b,w(b,"barycenter")&&Yr(p,b)}});var c=Sr(f,r);Vr(c,d);var h=Br(c,t);if(a&&(h.vs=_([a,h.vs,u]),n.predecessors(a).length)){var l=n.node(n.predecessors(a)[0]),v=n.node(n.predecessors(u)[0]);w(h,"barycenter")||(h.barycenter=0,h.weight=0),h.barycenter=(h.barycenter*h.weight+l.order+v.order)/(h.weight+2),h.weight+=2}return h}function Vr(n,e){s(n,function(r){r.vs=_(r.vs.map(function(t){return e[t]?e[t].vs:t}))})}function Yr(n,e){g(n.barycenter)?(n.barycenter=e.barycenter,n.weight=e.weight):(n.barycenter=(n.barycenter*n.weight+e.barycenter*e.weight)/(n.weight+e.weight),n.weight+=e.weight)}function Dr(n){var e=On(n),r=mn(n,N(1,e+1),"inEdges"),t=mn(n,N(e-1,-1,-1),"outEdges"),i=Or(n);bn(n,i);for(var o=Number.POSITIVE_INFINITY,a,u=0,d=0;d<4;++u,++d){$r(u%2?r:t,u%4>=2),i=$(n);var f=Tr(n,i);fa||u>e[d].lim));for(f=d,d=t;(d=n.parent(d))!==f;)o.push(d);return{path:i.concat(o.reverse()),lca:f}}function zr(n){var e={},r=0;function t(i){var o=r;s(n.children(i),t),e[i]={low:o,lim:r++}}return s(n.children(),t),e}function Xr(n,e){var r={};function t(i,o){var a=0,u=0,d=i.length,f=G(o);return s(o,function(c,h){var l=Hr(n,c),v=l?n.node(l).order:d;(l||c===f)&&(s(o.slice(u,h+1),function(p){s(n.predecessors(p),function(b){var I=n.node(b),on=I.order;(onf)&&Wn(r,l,c)})})}function i(o,a){var u=-1,d,f=0;return s(a,function(c,h){if(n.node(c).dummy==="border"){var l=n.predecessors(c);l.length&&(d=n.node(l[0]).order,t(a,f,h,u,d),f=h,u=d)}t(a,f,a.length,d,o.length)}),a}return Y(e,i),r}function Hr(n,e){if(n.node(e).dummy)return Q(n.predecessors(e),function(r){return n.node(r).dummy})}function Wn(n,e,r){if(e>r){var t=e;e=r,r=t}var i=n[e];i||(n[e]=i={}),i[r]=!0}function jr(n,e,r){if(e>r){var t=e;e=r,r=t}return w(n[e],r)}function Kr(n,e,r,t){var i={},o={},a={};return s(e,function(u){s(u,function(d,f){i[d]=d,o[d]=d,a[d]=f})}),s(e,function(u){var d=-1;s(u,function(f){var c=t(f);if(c.length){c=O(c,function(b){return a[b]});for(var h=(c.length-1)/2,l=Math.floor(h),v=Math.ceil(h);l<=v;++l){var p=c[l];o[f]===f&&dt?1:n>=t?0:NaN}function hn(n,t){return n==null||t==null?NaN:tn?1:t>=n?0:NaN}function _(n){let t,e,r;n.length!==2?(t=$,e=(u,c)=>$(n(u),c),r=(u,c)=>n(u)-c):(t=n===$||n===hn?n:mn,e=n,r=n);function i(u,c,o=0,s=u.length){if(o>>1;e(u[h],c)<0?o=h+1:s=h}while(o>>1;e(u[h],c)<=0?o=h+1:s=h}while(oo&&r(u[h-1],c)>-r(u[h],c)?h-1:h}return{left:i,center:a,right:f}}function mn(){return 0}function ln(n){return n===null?NaN:+n}const sn=_($),dn=sn.right;_(ln).center;const gn=Math.sqrt(50),yn=Math.sqrt(10),Mn=Math.sqrt(2);function E(n,t,e){const r=(t-n)/Math.max(0,e),i=Math.floor(Math.log10(r)),f=r/Math.pow(10,i),a=f>=gn?10:f>=yn?5:f>=Mn?2:1;let u,c,o;return i<0?(o=Math.pow(10,-i)/a,u=Math.round(n*o),c=Math.round(t*o),u/ot&&--c,o=-o):(o=Math.pow(10,i)*a,u=Math.round(n/o),c=Math.round(t/o),u*ot&&--c),c0))return[];if(n===t)return[n];const r=t=i))return[];const u=f-i+1,c=new Array(u);if(r)if(a<0)for(let o=0;o=1e21?n.toLocaleString("en").replace(/,/g,""):n.toString(10)}function R(n,t){if((e=(n=t?n.toExponential(t-1):n.toExponential()).indexOf("e"))<0)return null;var e,r=n.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+n.slice(e+1)]}function v(n){return n=R(Math.abs(n)),n?n[1]:NaN}function jn(n,t){return function(e,r){for(var i=e.length,f=[],a=0,u=n[0],c=0;i>0&&u>0&&(c+u+1>r&&(u=Math.max(1,r-c)),f.push(e.substring(i-=u,i+u)),!((c+=u+1)>r));)u=n[a=(a+1)%n.length];return f.reverse().join(t)}}function Pn(n){return function(t){return t.replace(/[0-9]/g,function(e){return n[+e]})}}var zn=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function D(n){if(!(t=zn.exec(n)))throw new Error("invalid format: "+n);var t;return new G({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}D.prototype=G.prototype;function G(n){this.fill=n.fill===void 0?" ":n.fill+"",this.align=n.align===void 0?">":n.align+"",this.sign=n.sign===void 0?"-":n.sign+"",this.symbol=n.symbol===void 0?"":n.symbol+"",this.zero=!!n.zero,this.width=n.width===void 0?void 0:+n.width,this.comma=!!n.comma,this.precision=n.precision===void 0?void 0:+n.precision,this.trim=!!n.trim,this.type=n.type===void 0?"":n.type+""}G.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function Fn(n){n:for(var t=n.length,e=1,r=-1,i;e0&&(r=0);break}return r>0?n.slice(0,r)+n.slice(i+1):n}var nn;function $n(n,t){var e=R(n,t);if(!e)return n+"";var r=e[0],i=e[1],f=i-(nn=Math.max(-8,Math.min(8,Math.floor(i/3)))*3)+1,a=r.length;return f===a?r:f>a?r+new Array(f-a+1).join("0"):f>0?r.slice(0,f)+"."+r.slice(f):"0."+new Array(1-f).join("0")+R(n,Math.max(0,t+f-1))[0]}function Y(n,t){var e=R(n,t);if(!e)return n+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}const Z={"%":(n,t)=>(n*100).toFixed(t),b:n=>Math.round(n).toString(2),c:n=>n+"",d:bn,e:(n,t)=>n.toExponential(t),f:(n,t)=>n.toFixed(t),g:(n,t)=>n.toPrecision(t),o:n=>Math.round(n).toString(8),p:(n,t)=>Y(n*100,t),r:Y,s:$n,X:n=>Math.round(n).toString(16).toUpperCase(),x:n=>Math.round(n).toString(16)};function J(n){return n}var K=Array.prototype.map,Q=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function En(n){var t=n.grouping===void 0||n.thousands===void 0?J:jn(K.call(n.grouping,Number),n.thousands+""),e=n.currency===void 0?"":n.currency[0]+"",r=n.currency===void 0?"":n.currency[1]+"",i=n.decimal===void 0?".":n.decimal+"",f=n.numerals===void 0?J:Pn(K.call(n.numerals,String)),a=n.percent===void 0?"%":n.percent+"",u=n.minus===void 0?"−":n.minus+"",c=n.nan===void 0?"NaN":n.nan+"";function o(h){h=D(h);var l=h.fill,p=h.align,y=h.sign,S=h.symbol,k=h.zero,b=h.width,I=h.comma,w=h.precision,B=h.trim,d=h.type;d==="n"?(I=!0,d="g"):Z[d]||(w===void 0&&(w=12),B=!0,d="g"),(k||l==="0"&&p==="=")&&(k=!0,l="0",p="=");var en=S==="$"?e:S==="#"&&/[boxX]/.test(d)?"0"+d.toLowerCase():"",on=S==="$"?r:/[%p]/.test(d)?a:"",O=Z[d],an=/[defgprs%]/.test(d);w=w===void 0?6:/[gprs]/.test(d)?Math.max(1,Math.min(21,w)):Math.max(0,Math.min(20,w));function V(m){var N=en,g=on,x,X,j;if(d==="c")g=O(m)+g,m="";else{m=+m;var P=m<0||1/m<0;if(m=isNaN(m)?c:O(Math.abs(m),w),B&&(m=Fn(m)),P&&+m==0&&y!=="+"&&(P=!1),N=(P?y==="("?y:u:y==="-"||y==="("?"":y)+N,g=(d==="s"?Q[8+nn/3]:"")+g+(P&&y==="("?")":""),an){for(x=-1,X=m.length;++xj||j>57){g=(j===46?i+m.slice(x+1):m.slice(x))+g,m=m.slice(0,x);break}}}I&&!k&&(m=t(m,1/0));var z=N.length+m.length+g.length,M=z>1)+N+m+g+M.slice(z);break;default:m=M+N+m+g;break}return f(m)}return V.toString=function(){return h+""},V}function s(h,l){var p=o((h=D(h),h.type="f",h)),y=Math.max(-8,Math.min(8,Math.floor(v(l)/3)))*3,S=Math.pow(10,-y),k=Q[8+y/3];return function(b){return p(S*b)+k}}return{format:o,formatPrefix:s}}var F,tn,rn;Rn({thousands:",",grouping:[3],currency:["$",""]});function Rn(n){return F=En(n),tn=F.format,rn=F.formatPrefix,F}function Dn(n){return Math.max(0,-v(Math.abs(n)))}function In(n,t){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(v(t)/3)))*3-v(Math.abs(n)))}function Tn(n,t){return n=Math.abs(n),t=Math.abs(t)-n,Math.max(0,v(t)-v(n))+1}function Ln(n){return function(){return n}}function qn(n){return+n}var W=[0,1];function A(n){return n}function q(n,t){return(t-=n=+n)?function(e){return(e-n)/t}:Ln(isNaN(t)?NaN:.5)}function Cn(n,t){var e;return n>t&&(e=n,n=t,t=e),function(r){return Math.max(n,Math.min(t,r))}}function Gn(n,t,e){var r=n[0],i=n[1],f=t[0],a=t[1];return i2?Bn:Gn,c=o=null,h}function h(l){return l==null||isNaN(l=+l)?f:(c||(c=u(n.map(r),t,e)))(r(a(l)))}return h.invert=function(l){return a(i((o||(o=u(t,n.map(r),T)))(l)))},h.domain=function(l){return arguments.length?(n=Array.from(l,qn),s()):n.slice()},h.range=function(l){return arguments.length?(t=Array.from(l),s()):t.slice()},h.rangeRound=function(l){return t=Array.from(l),e=Sn,s()},h.clamp=function(l){return arguments.length?(a=l?!0:A,s()):a!==A},h.interpolate=function(l){return arguments.length?(e=l,s()):e},h.unknown=function(l){return arguments.length?(f=l,h):f},function(l,p){return r=l,i=p,s()}}function Xn(){return Vn()(A,A)}function Hn(n,t,e,r){var i=wn(n,t,e),f;switch(r=D(r??",f"),r.type){case"s":{var a=Math.max(Math.abs(n),Math.abs(t));return r.precision==null&&!isNaN(f=In(i,a))&&(r.precision=f),rn(r,a)}case"":case"e":case"g":case"p":case"r":{r.precision==null&&!isNaN(f=Tn(i,Math.max(Math.abs(n),Math.abs(t))))&&(r.precision=f-(r.type==="e"));break}case"f":case"%":{r.precision==null&&!isNaN(f=Dn(i))&&(r.precision=f-(r.type==="%")*2);break}}return tn(r)}function Un(n){var t=n.domain;return n.ticks=function(e){var r=t();return pn(r[0],r[r.length-1],e??10)},n.tickFormat=function(e,r){var i=t();return Hn(i[0],i[i.length-1],e??10,r)},n.nice=function(e){e==null&&(e=10);var r=t(),i=0,f=r.length-1,a=r[i],u=r[f],c,o,s=10;for(u0;){if(o=L(a,u,e),o===c)return r[i]=a,r[f]=u,t(r);if(o>0)a=Math.floor(a/o)*o,u=Math.ceil(u/o)*o;else if(o<0)a=Math.ceil(a*o)/o,u=Math.floor(u*o)/o;else break;c=o}return n},n}function Yn(){var n=Xn();return n.copy=function(){return On(n,Yn())},cn.apply(n,arguments),Un(n)}export{On as a,_ as b,Xn as c,Yn as l,wn as t};
                                        +import{aE as un,aF as T,aG as H,aH as U,aI as fn}from"./mermaid.core-Bq0kX0MS.js";import{i as cn}from"./init-Gi6I4Gst.js";function $(n,t){return n==null||t==null?NaN:nt?1:n>=t?0:NaN}function hn(n,t){return n==null||t==null?NaN:tn?1:t>=n?0:NaN}function _(n){let t,e,r;n.length!==2?(t=$,e=(u,c)=>$(n(u),c),r=(u,c)=>n(u)-c):(t=n===$||n===hn?n:mn,e=n,r=n);function i(u,c,o=0,s=u.length){if(o>>1;e(u[h],c)<0?o=h+1:s=h}while(o>>1;e(u[h],c)<=0?o=h+1:s=h}while(oo&&r(u[h-1],c)>-r(u[h],c)?h-1:h}return{left:i,center:a,right:f}}function mn(){return 0}function ln(n){return n===null?NaN:+n}const sn=_($),dn=sn.right;_(ln).center;const gn=Math.sqrt(50),yn=Math.sqrt(10),Mn=Math.sqrt(2);function E(n,t,e){const r=(t-n)/Math.max(0,e),i=Math.floor(Math.log10(r)),f=r/Math.pow(10,i),a=f>=gn?10:f>=yn?5:f>=Mn?2:1;let u,c,o;return i<0?(o=Math.pow(10,-i)/a,u=Math.round(n*o),c=Math.round(t*o),u/ot&&--c,o=-o):(o=Math.pow(10,i)*a,u=Math.round(n/o),c=Math.round(t/o),u*ot&&--c),c0))return[];if(n===t)return[n];const r=t=i))return[];const u=f-i+1,c=new Array(u);if(r)if(a<0)for(let o=0;o=1e21?n.toLocaleString("en").replace(/,/g,""):n.toString(10)}function R(n,t){if((e=(n=t?n.toExponential(t-1):n.toExponential()).indexOf("e"))<0)return null;var e,r=n.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+n.slice(e+1)]}function v(n){return n=R(Math.abs(n)),n?n[1]:NaN}function jn(n,t){return function(e,r){for(var i=e.length,f=[],a=0,u=n[0],c=0;i>0&&u>0&&(c+u+1>r&&(u=Math.max(1,r-c)),f.push(e.substring(i-=u,i+u)),!((c+=u+1)>r));)u=n[a=(a+1)%n.length];return f.reverse().join(t)}}function Pn(n){return function(t){return t.replace(/[0-9]/g,function(e){return n[+e]})}}var zn=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function D(n){if(!(t=zn.exec(n)))throw new Error("invalid format: "+n);var t;return new G({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}D.prototype=G.prototype;function G(n){this.fill=n.fill===void 0?" ":n.fill+"",this.align=n.align===void 0?">":n.align+"",this.sign=n.sign===void 0?"-":n.sign+"",this.symbol=n.symbol===void 0?"":n.symbol+"",this.zero=!!n.zero,this.width=n.width===void 0?void 0:+n.width,this.comma=!!n.comma,this.precision=n.precision===void 0?void 0:+n.precision,this.trim=!!n.trim,this.type=n.type===void 0?"":n.type+""}G.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function Fn(n){n:for(var t=n.length,e=1,r=-1,i;e0&&(r=0);break}return r>0?n.slice(0,r)+n.slice(i+1):n}var nn;function $n(n,t){var e=R(n,t);if(!e)return n+"";var r=e[0],i=e[1],f=i-(nn=Math.max(-8,Math.min(8,Math.floor(i/3)))*3)+1,a=r.length;return f===a?r:f>a?r+new Array(f-a+1).join("0"):f>0?r.slice(0,f)+"."+r.slice(f):"0."+new Array(1-f).join("0")+R(n,Math.max(0,t+f-1))[0]}function Y(n,t){var e=R(n,t);if(!e)return n+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}const Z={"%":(n,t)=>(n*100).toFixed(t),b:n=>Math.round(n).toString(2),c:n=>n+"",d:bn,e:(n,t)=>n.toExponential(t),f:(n,t)=>n.toFixed(t),g:(n,t)=>n.toPrecision(t),o:n=>Math.round(n).toString(8),p:(n,t)=>Y(n*100,t),r:Y,s:$n,X:n=>Math.round(n).toString(16).toUpperCase(),x:n=>Math.round(n).toString(16)};function J(n){return n}var K=Array.prototype.map,Q=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function En(n){var t=n.grouping===void 0||n.thousands===void 0?J:jn(K.call(n.grouping,Number),n.thousands+""),e=n.currency===void 0?"":n.currency[0]+"",r=n.currency===void 0?"":n.currency[1]+"",i=n.decimal===void 0?".":n.decimal+"",f=n.numerals===void 0?J:Pn(K.call(n.numerals,String)),a=n.percent===void 0?"%":n.percent+"",u=n.minus===void 0?"−":n.minus+"",c=n.nan===void 0?"NaN":n.nan+"";function o(h){h=D(h);var l=h.fill,p=h.align,y=h.sign,S=h.symbol,k=h.zero,b=h.width,I=h.comma,w=h.precision,B=h.trim,d=h.type;d==="n"?(I=!0,d="g"):Z[d]||(w===void 0&&(w=12),B=!0,d="g"),(k||l==="0"&&p==="=")&&(k=!0,l="0",p="=");var en=S==="$"?e:S==="#"&&/[boxX]/.test(d)?"0"+d.toLowerCase():"",on=S==="$"?r:/[%p]/.test(d)?a:"",O=Z[d],an=/[defgprs%]/.test(d);w=w===void 0?6:/[gprs]/.test(d)?Math.max(1,Math.min(21,w)):Math.max(0,Math.min(20,w));function V(m){var N=en,g=on,x,X,j;if(d==="c")g=O(m)+g,m="";else{m=+m;var P=m<0||1/m<0;if(m=isNaN(m)?c:O(Math.abs(m),w),B&&(m=Fn(m)),P&&+m==0&&y!=="+"&&(P=!1),N=(P?y==="("?y:u:y==="-"||y==="("?"":y)+N,g=(d==="s"?Q[8+nn/3]:"")+g+(P&&y==="("?")":""),an){for(x=-1,X=m.length;++xj||j>57){g=(j===46?i+m.slice(x+1):m.slice(x))+g,m=m.slice(0,x);break}}}I&&!k&&(m=t(m,1/0));var z=N.length+m.length+g.length,M=z>1)+N+m+g+M.slice(z);break;default:m=M+N+m+g;break}return f(m)}return V.toString=function(){return h+""},V}function s(h,l){var p=o((h=D(h),h.type="f",h)),y=Math.max(-8,Math.min(8,Math.floor(v(l)/3)))*3,S=Math.pow(10,-y),k=Q[8+y/3];return function(b){return p(S*b)+k}}return{format:o,formatPrefix:s}}var F,tn,rn;Rn({thousands:",",grouping:[3],currency:["$",""]});function Rn(n){return F=En(n),tn=F.format,rn=F.formatPrefix,F}function Dn(n){return Math.max(0,-v(Math.abs(n)))}function In(n,t){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(v(t)/3)))*3-v(Math.abs(n)))}function Tn(n,t){return n=Math.abs(n),t=Math.abs(t)-n,Math.max(0,v(t)-v(n))+1}function Ln(n){return function(){return n}}function qn(n){return+n}var W=[0,1];function A(n){return n}function q(n,t){return(t-=n=+n)?function(e){return(e-n)/t}:Ln(isNaN(t)?NaN:.5)}function Cn(n,t){var e;return n>t&&(e=n,n=t,t=e),function(r){return Math.max(n,Math.min(t,r))}}function Gn(n,t,e){var r=n[0],i=n[1],f=t[0],a=t[1];return i2?Bn:Gn,c=o=null,h}function h(l){return l==null||isNaN(l=+l)?f:(c||(c=u(n.map(r),t,e)))(r(a(l)))}return h.invert=function(l){return a(i((o||(o=u(t,n.map(r),T)))(l)))},h.domain=function(l){return arguments.length?(n=Array.from(l,qn),s()):n.slice()},h.range=function(l){return arguments.length?(t=Array.from(l),s()):t.slice()},h.rangeRound=function(l){return t=Array.from(l),e=Sn,s()},h.clamp=function(l){return arguments.length?(a=l?!0:A,s()):a!==A},h.interpolate=function(l){return arguments.length?(e=l,s()):e},h.unknown=function(l){return arguments.length?(f=l,h):f},function(l,p){return r=l,i=p,s()}}function Xn(){return Vn()(A,A)}function Hn(n,t,e,r){var i=wn(n,t,e),f;switch(r=D(r??",f"),r.type){case"s":{var a=Math.max(Math.abs(n),Math.abs(t));return r.precision==null&&!isNaN(f=In(i,a))&&(r.precision=f),rn(r,a)}case"":case"e":case"g":case"p":case"r":{r.precision==null&&!isNaN(f=Tn(i,Math.max(Math.abs(n),Math.abs(t))))&&(r.precision=f-(r.type==="e"));break}case"f":case"%":{r.precision==null&&!isNaN(f=Dn(i))&&(r.precision=f-(r.type==="%")*2);break}}return tn(r)}function Un(n){var t=n.domain;return n.ticks=function(e){var r=t();return pn(r[0],r[r.length-1],e??10)},n.tickFormat=function(e,r){var i=t();return Hn(i[0],i[i.length-1],e??10,r)},n.nice=function(e){e==null&&(e=10);var r=t(),i=0,f=r.length-1,a=r[i],u=r[f],c,o,s=10;for(u0;){if(o=L(a,u,e),o===c)return r[i]=a,r[f]=u,t(r);if(o>0)a=Math.floor(a/o)*o,u=Math.ceil(u/o)*o;else if(o<0)a=Math.ceil(a*o)/o,u=Math.floor(u*o)/o;else break;c=o}return n},n}function Yn(){var n=Xn();return n.copy=function(){return On(n,Yn())},cn.apply(n,arguments),Un(n)}export{On as a,_ as b,Xn as c,Yn as l,wn as t};
                                        diff --git a/assets/log.html-QQtue8CH.js b/assets/log.html-AttB6lyK.js
                                        similarity index 96%
                                        rename from assets/log.html-QQtue8CH.js
                                        rename to assets/log.html-AttB6lyK.js
                                        index 972b9d6261..62743c58f8 100644
                                        --- a/assets/log.html-QQtue8CH.js
                                        +++ b/assets/log.html-AttB6lyK.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as e,r as t,o as n,c as a,a as s,e as c}from"./app-5SoadDYS.js";const l={},r=c(`

                                        Log Configuration

                                        Log configuration controls how Xray outputs logs.

                                        Xray has two types of logs: access logs and error logs. You can configure the output method for each type of log separately.

                                        LogObject

                                        LogObject corresponds to the log item in the configuration file.

                                        {
                                        +import{_ as e,r as t,o as n,c as a,a as s,e as c}from"./app-Bw2NG-QJ.js";const l={},r=c(`

                                        Log Configuration

                                        Log configuration controls how Xray outputs logs.

                                        Xray has two types of logs: access logs and error logs. You can configure the output method for each type of log separately.

                                        LogObject

                                        LogObject corresponds to the log item in the configuration file.

                                        {
                                           "log": {
                                             "access": "file_path",
                                             "error": "file_path",
                                        diff --git a/assets/log.html-BAb49rK4.js b/assets/log.html-BXxmwSQO.js
                                        similarity index 96%
                                        rename from assets/log.html-BAb49rK4.js
                                        rename to assets/log.html-BXxmwSQO.js
                                        index e670243ccd..e0198b8234 100644
                                        --- a/assets/log.html-BAb49rK4.js
                                        +++ b/assets/log.html-BXxmwSQO.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as e,r as n,o as s,c as a,a as t,e as c}from"./app-5SoadDYS.js";const l={},r=c(`

                                        日志配置

                                        日志配置,控制 Xray 输出日志的方式.

                                        Xray 有两种日志, 访问日志和错误日志, 你可以分别配置两种日志的输出方式.

                                        LogObject

                                        LogObject 对应配置文件的 log 项。

                                        {
                                        +import{_ as e,r as n,o as s,c as a,a as t,e as c}from"./app-Bw2NG-QJ.js";const l={},r=c(`

                                        日志配置

                                        日志配置,控制 Xray 输出日志的方式.

                                        Xray 有两种日志, 访问日志和错误日志, 你可以分别配置两种日志的输出方式.

                                        LogObject

                                        LogObject 对应配置文件的 log 项。

                                        {
                                           "log": {
                                             "access": "文件地址",
                                             "error": "文件地址",
                                        diff --git a/assets/log.html-DguB3WSi.js b/assets/log.html-cALz2gHA.js
                                        similarity index 98%
                                        rename from assets/log.html-DguB3WSi.js
                                        rename to assets/log.html-cALz2gHA.js
                                        index f5a93578e8..97aa83f3c3 100644
                                        --- a/assets/log.html-DguB3WSi.js
                                        +++ b/assets/log.html-cALz2gHA.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as e,r as n,o as s,c as t,a,e as c}from"./app-5SoadDYS.js";const r={},l=c(`

                                        Настройка журнала

                                        Настройка журнала управляет тем, как Xray выводит журналы.

                                        Xray имеет два типа журналов: журнал доступа и журнал ошибок.
                                        Вы можете настроить способ вывода каждого типа журнала отдельно.

                                        LogObject

                                        LogObject соответствует полю log в конфигурационном файле.

                                        {
                                        +import{_ as e,r as n,o as s,c as t,a,e as c}from"./app-Bw2NG-QJ.js";const r={},l=c(`

                                        Настройка журнала

                                        Настройка журнала управляет тем, как Xray выводит журналы.

                                        Xray имеет два типа журналов: журнал доступа и журнал ошибок.
                                        Вы можете настроить способ вывода каждого типа журнала отдельно.

                                        LogObject

                                        LogObject соответствует полю log в конфигурационном файле.

                                        {
                                           "log": {
                                             "access": "путь к файлу",
                                             "error": "путь к файлу",
                                        diff --git a/assets/loopback.html-DZPmfXB9.js b/assets/loopback.html-BA_UAuXs.js
                                        similarity index 96%
                                        rename from assets/loopback.html-DZPmfXB9.js
                                        rename to assets/loopback.html-BA_UAuXs.js
                                        index 1812ab2336..9cb594d0fc 100644
                                        --- a/assets/loopback.html-DZPmfXB9.js
                                        +++ b/assets/loopback.html-BA_UAuXs.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as o,r as t,o as e,c as i,a as s,e as u}from"./app-5SoadDYS.js";const a={},d=u(`

                                        Loopback

                                        Loopback is an outbound protocol. It can send traffics through corresponding outbound to routing inbound, thus rerouting traffics to other routing rules without leaving Xray-core.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as o,r as t,o as e,c as i,a as s,e as u}from"./app-Bw2NG-QJ.js";const a={},d=u(`

                                        Loopback

                                        Loopback is an outbound protocol. It can send traffics through corresponding outbound to routing inbound, thus rerouting traffics to other routing rules without leaving Xray-core.

                                        OutboundConfigurationObject

                                        {
                                           "inboundTag": "TagUseAsInbound"
                                         }
                                         

                                        inboundTag: string

                                        Use as an inbound tag for routing.

                                        This tag can be used as inboundTag in routing rules, all traffics going through this outbound can be rerouted with routing rules with corresponding inbound tag.

                                        How to use?

                                        If you need to do some more detailed routing for traffics that have been routed by routing rules, like splitting routed traffics to TCP traffics and UDP traffics and send them to different outbounds, this can be done with loopback outbound.

                                        {
                                        diff --git a/assets/loopback.html-D7n84f8k.js b/assets/loopback.html-BvfOuAZH.js
                                        similarity index 99%
                                        rename from assets/loopback.html-D7n84f8k.js
                                        rename to assets/loopback.html-BvfOuAZH.js
                                        index 1a6dd3a5b7..fe83363d70 100644
                                        --- a/assets/loopback.html-D7n84f8k.js
                                        +++ b/assets/loopback.html-BvfOuAZH.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o as t,c as o,a as p,e}from"./app-5SoadDYS.js";const c={},u=e(`

                                        Loopback

                                        Loopback 是个出站数据协议,其作用为将经该出站传出的数据重新送入路由入站,以达到数据无需离开 Xray-core 即可再次被路由处理的效果。

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as s,r as a,o as t,c as o,a as p,e}from"./app-Bw2NG-QJ.js";const c={},u=e(`

                                        Loopback

                                        Loopback 是个出站数据协议,其作用为将经该出站传出的数据重新送入路由入站,以达到数据无需离开 Xray-core 即可再次被路由处理的效果。

                                        OutboundConfigurationObject

                                        {
                                           "inboundTag": "TagUseAsInbound"
                                         }
                                         

                                        inboundTag: string

                                        用于重新路由的入站协议标识。

                                        该标识可以在路由中用于 inboundTag ,表示该出站中的数据可以被对应的路由规则再次处理。

                                        如何使用?

                                        如果需要将已经通过路由规则分流过的流量再由其它路由规则做更细致的分流,比如由同一组路由规则分流后的 TCP 流量和 UDP 要走不同的出站,则可以使用 loopback 出站完成。

                                        {
                                        diff --git a/assets/loopback.html-CL9lvq8v.js b/assets/loopback.html-CsIs91x3.js
                                        similarity index 99%
                                        rename from assets/loopback.html-CL9lvq8v.js
                                        rename to assets/loopback.html-CsIs91x3.js
                                        index 9ab3c3df61..fdae8b9381 100644
                                        --- a/assets/loopback.html-CL9lvq8v.js
                                        +++ b/assets/loopback.html-CsIs91x3.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o as t,c as o,a as p,e}from"./app-5SoadDYS.js";const c={},u=e(`

                                        Loopback

                                        Loopback - это исходящий протокол данных, который перенаправляет данные, прошедшие через это исходящее соединение, обратно на вход маршрутизатора, что позволяет повторно обработать данные по правилам маршрутизации, не покидая Xray-core.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as s,r as a,o as t,c as o,a as p,e}from"./app-Bw2NG-QJ.js";const c={},u=e(`

                                        Loopback

                                        Loopback - это исходящий протокол данных, который перенаправляет данные, прошедшие через это исходящее соединение, обратно на вход маршрутизатора, что позволяет повторно обработать данные по правилам маршрутизации, не покидая Xray-core.

                                        OutboundConfigurationObject

                                        {
                                           "inboundTag": "TagUseAsInbound"
                                         }
                                         

                                        inboundTag: string

                                        Идентификатор входящего протокола, используемый для повторной маршрутизации.

                                        Этот идентификатор может использоваться в маршрутизации для inboundTag, указывая, что данные из этого исходящего соединения могут быть повторно обработаны соответствующими правилами маршрутизации.

                                        Как использовать?

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

                                        {
                                        diff --git a/assets/mermaid.core-CArNAncI.js b/assets/mermaid.core-Bq0kX0MS.js
                                        similarity index 98%
                                        rename from assets/mermaid.core-CArNAncI.js
                                        rename to assets/mermaid.core-Bq0kX0MS.js
                                        index e18ab8641e..fe377b332c 100644
                                        --- a/assets/mermaid.core-CArNAncI.js
                                        +++ b/assets/mermaid.core-Bq0kX0MS.js
                                        @@ -1,4 +1,4 @@
                                        -import{q as X}from"./app-5SoadDYS.js";function _h(t){for(var e=[],i=1;i
                                                   `:`
                                        ${r}
                                        `).join("").replace(bn,(r,n)=>i.renderToString(n,{throwOnError:!0,displayMode:!0,output:vs()?"mathml":"htmlAndMathml"}).replace(/\n/g," ").replace(//g,""))},Hn={getRows:Mm,sanitizeText:mi,sanitizeTextOrArray:Dm,hasBreaks:Nm,splitBreaks:Rm,lineBreakRegex:vi,removeScript:tl,getUrl:qm,evaluate:il,getMax:zm,getMin:Wm},ft=(t,e)=>e?g(t,{s:-40,l:10}):g(t,{s:-40,l:-10}),Br="#ffffff",Ar="#f2f2f2";let Ym=class{constructor(){this.background="#f4f4f4",this.primaryColor="#fff4dd",this.noteBkgColor="#fff5ad",this.noteTextColor="#333",this.THEME_COLOR_LIMIT=12,this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px"}updateColors(){var e,i,r,n,o,s,a,l,h,u,f;if(this.primaryTextColor=this.primaryTextColor||(this.darkMode?"#eee":"#333"),this.secondaryColor=this.secondaryColor||g(this.primaryColor,{h:-120}),this.tertiaryColor=this.tertiaryColor||g(this.primaryColor,{h:180,l:5}),this.primaryBorderColor=this.primaryBorderColor||ft(this.primaryColor,this.darkMode),this.secondaryBorderColor=this.secondaryBorderColor||ft(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=this.tertiaryBorderColor||ft(this.tertiaryColor,this.darkMode),this.noteBorderColor=this.noteBorderColor||ft(this.noteBkgColor,this.darkMode),this.noteBkgColor=this.noteBkgColor||"#fff5ad",this.noteTextColor=this.noteTextColor||"#333",this.secondaryTextColor=this.secondaryTextColor||C(this.secondaryColor),this.tertiaryTextColor=this.tertiaryTextColor||C(this.tertiaryColor),this.lineColor=this.lineColor||C(this.background),this.arrowheadColor=this.arrowheadColor||C(this.background),this.textColor=this.textColor||this.primaryTextColor,this.border2=this.border2||this.tertiaryBorderColor,this.nodeBkg=this.nodeBkg||this.primaryColor,this.mainBkg=this.mainBkg||this.primaryColor,this.nodeBorder=this.nodeBorder||this.primaryBorderColor,this.clusterBkg=this.clusterBkg||this.tertiaryColor,this.clusterBorder=this.clusterBorder||this.tertiaryBorderColor,this.defaultLinkColor=this.defaultLinkColor||this.lineColor,this.titleColor=this.titleColor||this.tertiaryTextColor,this.edgeLabelBackground=this.edgeLabelBackground||(this.darkMode?M(this.secondaryColor,30):this.secondaryColor),this.nodeTextColor=this.nodeTextColor||this.primaryTextColor,this.actorBorder=this.actorBorder||this.primaryBorderColor,this.actorBkg=this.actorBkg||this.mainBkg,this.actorTextColor=this.actorTextColor||this.primaryTextColor,this.actorLineColor=this.actorLineColor||"grey",this.labelBoxBkgColor=this.labelBoxBkgColor||this.actorBkg,this.signalColor=this.signalColor||this.textColor,this.signalTextColor=this.signalTextColor||this.textColor,this.labelBoxBorderColor=this.labelBoxBorderColor||this.actorBorder,this.labelTextColor=this.labelTextColor||this.actorTextColor,this.loopTextColor=this.loopTextColor||this.actorTextColor,this.activationBorderColor=this.activationBorderColor||M(this.secondaryColor,10),this.activationBkgColor=this.activationBkgColor||this.secondaryColor,this.sequenceNumberColor=this.sequenceNumberColor||C(this.lineColor),this.sectionBkgColor=this.sectionBkgColor||this.tertiaryColor,this.altSectionBkgColor=this.altSectionBkgColor||"white",this.sectionBkgColor=this.sectionBkgColor||this.secondaryColor,this.sectionBkgColor2=this.sectionBkgColor2||this.primaryColor,this.excludeBkgColor=this.excludeBkgColor||"#eeeeee",this.taskBorderColor=this.taskBorderColor||this.primaryBorderColor,this.taskBkgColor=this.taskBkgColor||this.primaryColor,this.activeTaskBorderColor=this.activeTaskBorderColor||this.primaryColor,this.activeTaskBkgColor=this.activeTaskBkgColor||L(this.primaryColor,23),this.gridColor=this.gridColor||"lightgrey",this.doneTaskBkgColor=this.doneTaskBkgColor||"lightgrey",this.doneTaskBorderColor=this.doneTaskBorderColor||"grey",this.critBorderColor=this.critBorderColor||"#ff8888",this.critBkgColor=this.critBkgColor||"red",this.todayLineColor=this.todayLineColor||"red",this.taskTextColor=this.taskTextColor||this.textColor,this.taskTextOutsideColor=this.taskTextOutsideColor||this.textColor,this.taskTextLightColor=this.taskTextLightColor||this.textColor,this.taskTextColor=this.taskTextColor||this.primaryTextColor,this.taskTextDarkColor=this.taskTextDarkColor||this.textColor,this.taskTextClickableColor=this.taskTextClickableColor||"#003163",this.personBorder=this.personBorder||this.primaryBorderColor,this.personBkg=this.personBkg||this.mainBkg,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||this.tertiaryColor,this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.nodeBorder,this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.specialStateColor=this.lineColor,this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||g(this.primaryColor,{h:30}),this.cScale4=this.cScale4||g(this.primaryColor,{h:60}),this.cScale5=this.cScale5||g(this.primaryColor,{h:90}),this.cScale6=this.cScale6||g(this.primaryColor,{h:120}),this.cScale7=this.cScale7||g(this.primaryColor,{h:150}),this.cScale8=this.cScale8||g(this.primaryColor,{h:210,l:150}),this.cScale9=this.cScale9||g(this.primaryColor,{h:270}),this.cScale10=this.cScale10||g(this.primaryColor,{h:300}),this.cScale11=this.cScale11||g(this.primaryColor,{h:330}),this.darkMode)for(let p=0;p{this[r]=e[r]}),this.updateColors(),i.forEach(r=>{this[r]=e[r]})}};const Vm=t=>{const e=new Ym;return e.calculate(t),e};let Gm=class{constructor(){this.background="#333",this.primaryColor="#1f2020",this.secondaryColor=L(this.primaryColor,16),this.tertiaryColor=g(this.primaryColor,{h:-160}),this.primaryBorderColor=C(this.background),this.secondaryBorderColor=ft(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ft(this.tertiaryColor,this.darkMode),this.primaryTextColor=C(this.primaryColor),this.secondaryTextColor=C(this.secondaryColor),this.tertiaryTextColor=C(this.tertiaryColor),this.lineColor=C(this.background),this.textColor=C(this.background),this.mainBkg="#1f2020",this.secondBkg="calculated",this.mainContrastColor="lightgrey",this.darkTextColor=L(C("#323D47"),10),this.lineColor="calculated",this.border1="#81B1DB",this.border2=ri(255,255,255,.25),this.arrowheadColor="calculated",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#181818",this.textColor="#ccc",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#F9FFFE",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="calculated",this.activationBkgColor="calculated",this.sequenceNumberColor="black",this.sectionBkgColor=M("#EAE8D9",30),this.altSectionBkgColor="calculated",this.sectionBkgColor2="#EAE8D9",this.excludeBkgColor=M(this.sectionBkgColor,10),this.taskBorderColor=ri(255,255,255,70),this.taskBkgColor="calculated",this.taskTextColor="calculated",this.taskTextLightColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor=ri(255,255,255,50),this.activeTaskBkgColor="#81B1DB",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="grey",this.critBorderColor="#E83737",this.critBkgColor="#E83737",this.taskTextDarkColor="calculated",this.todayLineColor="#DB5757",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="calculated",this.errorBkgColor="#a44141",this.errorTextColor="#ddd"}updateColors(){var e,i,r,n,o,s,a,l,h,u,f;this.secondBkg=L(this.mainBkg,16),this.lineColor=this.mainContrastColor,this.arrowheadColor=this.mainContrastColor,this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.edgeLabelBackground=L(this.labelBackground,25),this.actorBorder=this.border1,this.actorBkg=this.mainBkg,this.actorTextColor=this.mainContrastColor,this.actorLineColor=this.mainContrastColor,this.signalColor=this.mainContrastColor,this.signalTextColor=this.mainContrastColor,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.mainContrastColor,this.loopTextColor=this.mainContrastColor,this.noteBorderColor=this.secondaryBorderColor,this.noteBkgColor=this.secondBkg,this.noteTextColor=this.secondaryTextColor,this.activationBorderColor=this.border1,this.activationBkgColor=this.secondBkg,this.altSectionBkgColor=this.background,this.taskBkgColor=L(this.mainBkg,23),this.taskTextColor=this.darkTextColor,this.taskTextLightColor=this.mainContrastColor,this.taskTextOutsideColor=this.taskTextLightColor,this.gridColor=this.mainContrastColor,this.doneTaskBkgColor=this.mainContrastColor,this.taskTextDarkColor=this.darkTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#555",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.primaryBorderColor,this.specialStateColor="#f4f4f4",this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=g(this.primaryColor,{h:64}),this.fillType3=g(this.secondaryColor,{h:64}),this.fillType4=g(this.primaryColor,{h:-64}),this.fillType5=g(this.secondaryColor,{h:-64}),this.fillType6=g(this.primaryColor,{h:128}),this.fillType7=g(this.secondaryColor,{h:128}),this.cScale1=this.cScale1||"#0b0000",this.cScale2=this.cScale2||"#4d1037",this.cScale3=this.cScale3||"#3f5258",this.cScale4=this.cScale4||"#4f2f1b",this.cScale5=this.cScale5||"#6e0a0a",this.cScale6=this.cScale6||"#3b0048",this.cScale7=this.cScale7||"#995a01",this.cScale8=this.cScale8||"#154706",this.cScale9=this.cScale9||"#161722",this.cScale10=this.cScale10||"#00296f",this.cScale11=this.cScale11||"#01629c",this.cScale12=this.cScale12||"#010029",this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||g(this.primaryColor,{h:30}),this.cScale4=this.cScale4||g(this.primaryColor,{h:60}),this.cScale5=this.cScale5||g(this.primaryColor,{h:90}),this.cScale6=this.cScale6||g(this.primaryColor,{h:120}),this.cScale7=this.cScale7||g(this.primaryColor,{h:150}),this.cScale8=this.cScale8||g(this.primaryColor,{h:210}),this.cScale9=this.cScale9||g(this.primaryColor,{h:270}),this.cScale10=this.cScale10||g(this.primaryColor,{h:300}),this.cScale11=this.cScale11||g(this.primaryColor,{h:330});for(let c=0;c{this[r]=e[r]}),this.updateColors(),i.forEach(r=>{this[r]=e[r]})}};const Xm=t=>{const e=new Gm;return e.calculate(t),e};let Km=class{constructor(){this.background="#f4f4f4",this.primaryColor="#ECECFF",this.secondaryColor=g(this.primaryColor,{h:120}),this.secondaryColor="#ffffde",this.tertiaryColor=g(this.primaryColor,{h:-160}),this.primaryBorderColor=ft(this.primaryColor,this.darkMode),this.secondaryBorderColor=ft(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ft(this.tertiaryColor,this.darkMode),this.primaryTextColor=C(this.primaryColor),this.secondaryTextColor=C(this.secondaryColor),this.tertiaryTextColor=C(this.tertiaryColor),this.lineColor=C(this.background),this.textColor=C(this.background),this.background="white",this.mainBkg="#ECECFF",this.secondBkg="#ffffde",this.lineColor="#333333",this.border1="#9370DB",this.border2="#aaaa33",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#e8e8e8",this.textColor="#333",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="calculated",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="calculated",this.taskTextColor=this.taskTextLightColor,this.taskTextDarkColor="calculated",this.taskTextOutsideColor=this.taskTextDarkColor,this.taskTextClickableColor="calculated",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBorderColor="calculated",this.critBkgColor="calculated",this.todayLineColor="calculated",this.sectionBkgColor=ri(102,102,255,.49),this.altSectionBkgColor="white",this.sectionBkgColor2="#fff400",this.taskBorderColor="#534fbc",this.taskBkgColor="#8a90dd",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="#534fbc",this.activeTaskBkgColor="#bfc7ff",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222",this.updateColors()}updateColors(){var e,i,r,n,o,s,a,l,h,u,f;this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||g(this.primaryColor,{h:30}),this.cScale4=this.cScale4||g(this.primaryColor,{h:60}),this.cScale5=this.cScale5||g(this.primaryColor,{h:90}),this.cScale6=this.cScale6||g(this.primaryColor,{h:120}),this.cScale7=this.cScale7||g(this.primaryColor,{h:150}),this.cScale8=this.cScale8||g(this.primaryColor,{h:210}),this.cScale9=this.cScale9||g(this.primaryColor,{h:270}),this.cScale10=this.cScale10||g(this.primaryColor,{h:300}),this.cScale11=this.cScale11||g(this.primaryColor,{h:330}),this.cScalePeer1=this.cScalePeer1||M(this.secondaryColor,45),this.cScalePeer2=this.cScalePeer2||M(this.tertiaryColor,40);for(let c=0;c{this[r]=e[r]}),this.updateColors(),i.forEach(r=>{this[r]=e[r]})}};const Zm=t=>{const e=new Km;return e.calculate(t),e};let Jm=class{constructor(){this.background="#f4f4f4",this.primaryColor="#cde498",this.secondaryColor="#cdffb2",this.background="white",this.mainBkg="#cde498",this.secondBkg="#cdffb2",this.lineColor="green",this.border1="#13540c",this.border2="#6eaa49",this.arrowheadColor="green",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.tertiaryColor=L("#cde498",10),this.primaryBorderColor=ft(this.primaryColor,this.darkMode),this.secondaryBorderColor=ft(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ft(this.tertiaryColor,this.darkMode),this.primaryTextColor=C(this.primaryColor),this.secondaryTextColor=C(this.secondaryColor),this.tertiaryTextColor=C(this.primaryColor),this.lineColor=C(this.background),this.textColor=C(this.background),this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#333",this.edgeLabelBackground="#e8e8e8",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="#333",this.signalTextColor="#333",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="#326932",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="#6eaa49",this.altSectionBkgColor="white",this.sectionBkgColor2="#6eaa49",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="#487e3a",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}updateColors(){var e,i,r,n,o,s,a,l,h,u,f;this.actorBorder=M(this.mainBkg,20),this.actorBkg=this.mainBkg,this.labelBoxBkgColor=this.actorBkg,this.labelTextColor=this.actorTextColor,this.loopTextColor=this.actorTextColor,this.noteBorderColor=this.border2,this.noteTextColor=this.actorTextColor,this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||g(this.primaryColor,{h:30}),this.cScale4=this.cScale4||g(this.primaryColor,{h:60}),this.cScale5=this.cScale5||g(this.primaryColor,{h:90}),this.cScale6=this.cScale6||g(this.primaryColor,{h:120}),this.cScale7=this.cScale7||g(this.primaryColor,{h:150}),this.cScale8=this.cScale8||g(this.primaryColor,{h:210}),this.cScale9=this.cScale9||g(this.primaryColor,{h:270}),this.cScale10=this.cScale10||g(this.primaryColor,{h:300}),this.cScale11=this.cScale11||g(this.primaryColor,{h:330}),this.cScalePeer1=this.cScalePeer1||M(this.secondaryColor,45),this.cScalePeer2=this.cScalePeer2||M(this.tertiaryColor,40);for(let c=0;c{this[r]=e[r]}),this.updateColors(),i.forEach(r=>{this[r]=e[r]})}};const Qm=t=>{const e=new Jm;return e.calculate(t),e};class t0{constructor(){this.primaryColor="#eee",this.contrast="#707070",this.secondaryColor=L(this.contrast,55),this.background="#ffffff",this.tertiaryColor=g(this.primaryColor,{h:-160}),this.primaryBorderColor=ft(this.primaryColor,this.darkMode),this.secondaryBorderColor=ft(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=ft(this.tertiaryColor,this.darkMode),this.primaryTextColor=C(this.primaryColor),this.secondaryTextColor=C(this.secondaryColor),this.tertiaryTextColor=C(this.tertiaryColor),this.lineColor=C(this.background),this.textColor=C(this.background),this.mainBkg="#eee",this.secondBkg="calculated",this.lineColor="#666",this.border1="#999",this.border2="calculated",this.note="#ffa",this.text="#333",this.critical="#d42",this.done="#bbb",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="white",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="calculated",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="white",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBkgColor="calculated",this.critBorderColor="calculated",this.todayLineColor="calculated",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}updateColors(){var e,i,r,n,o,s,a,l,h,u,f;this.secondBkg=L(this.contrast,55),this.border2=this.contrast,this.actorBorder=L(this.border1,23),this.actorBkg=this.mainBkg,this.actorTextColor=this.text,this.actorLineColor=this.lineColor,this.signalColor=this.text,this.signalTextColor=this.text,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.text,this.loopTextColor=this.text,this.noteBorderColor="#999",this.noteBkgColor="#666",this.noteTextColor="#fff",this.cScale0=this.cScale0||"#555",this.cScale1=this.cScale1||"#F4F4F4",this.cScale2=this.cScale2||"#555",this.cScale3=this.cScale3||"#BBB",this.cScale4=this.cScale4||"#777",this.cScale5=this.cScale5||"#999",this.cScale6=this.cScale6||"#DDD",this.cScale7=this.cScale7||"#FFF",this.cScale8=this.cScale8||"#DDD",this.cScale9=this.cScale9||"#BBB",this.cScale10=this.cScale10||"#999",this.cScale11=this.cScale11||"#777";for(let c=0;c{this[r]=e[r]}),this.updateColors(),i.forEach(r=>{this[r]=e[r]})}}const e0=t=>{const e=new t0;return e.calculate(t),e},Zt={base:{getThemeVariables:Vm},dark:{getThemeVariables:Xm},default:{getThemeVariables:Zm},forest:{getThemeVariables:Qm},neutral:{getThemeVariables:e0}},Gt={flowchart:{useMaxWidth:!0,titleTopMargin:25,subGraphTitleMargin:{top:0,bottom:0},diagramPadding:8,htmlLabels:!0,nodeSpacing:50,rankSpacing:50,curve:"basis",padding:15,defaultRenderer:"dagre-wrapper",wrappingWidth:200},sequence:{useMaxWidth:!0,hideUnusedParticipants:!1,activationWidth:10,diagramMarginX:50,diagramMarginY:10,actorMargin:50,width:150,height:65,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",mirrorActors:!0,forceMenus:!1,bottomMarginAdj:1,rightAngles:!1,showSequenceNumbers:!1,actorFontSize:14,actorFontFamily:'"Open Sans", sans-serif',actorFontWeight:400,noteFontSize:14,noteFontFamily:'"trebuchet ms", verdana, arial, sans-serif',noteFontWeight:400,noteAlign:"center",messageFontSize:16,messageFontFamily:'"trebuchet ms", verdana, arial, sans-serif',messageFontWeight:400,wrap:!1,wrapPadding:10,labelBoxWidth:50,labelBoxHeight:20},gantt:{useMaxWidth:!0,titleTopMargin:25,barHeight:20,barGap:4,topPadding:50,rightPadding:75,leftPadding:75,gridLineStartPadding:35,fontSize:11,sectionFontSize:11,numberSectionStyles:4,axisFormat:"%Y-%m-%d",topAxis:!1,displayMode:"",weekday:"sunday"},journey:{useMaxWidth:!0,diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open Sans", sans-serif',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"]},class:{useMaxWidth:!0,titleTopMargin:25,arrowMarkerAbsolute:!1,dividerMargin:10,padding:5,textHeight:10,defaultRenderer:"dagre-wrapper",htmlLabels:!1},state:{useMaxWidth:!0,titleTopMargin:25,dividerMargin:10,sizeUnit:5,padding:8,textHeight:10,titleShift:-15,noteMargin:10,forkWidth:70,forkHeight:7,miniPadding:2,fontSizeFactor:5.02,fontSize:24,labelHeight:16,edgeLengthFactor:"20",compositTitleSize:35,radius:5,defaultRenderer:"dagre-wrapper"},er:{useMaxWidth:!0,titleTopMargin:25,diagramPadding:20,layoutDirection:"TB",minEntityWidth:100,minEntityHeight:75,entityPadding:15,stroke:"gray",fill:"honeydew",fontSize:12},pie:{useMaxWidth:!0,textPosition:.75},quadrantChart:{useMaxWidth:!0,chartWidth:500,chartHeight:500,titleFontSize:20,titlePadding:10,quadrantPadding:5,xAxisLabelPadding:5,yAxisLabelPadding:5,xAxisLabelFontSize:16,yAxisLabelFontSize:16,quadrantLabelFontSize:16,quadrantTextTopPadding:5,pointTextPadding:5,pointLabelFontSize:12,pointRadius:5,xAxisPosition:"top",yAxisPosition:"left",quadrantInternalBorderStrokeWidth:1,quadrantExternalBorderStrokeWidth:2},xyChart:{useMaxWidth:!0,width:700,height:500,titleFontSize:20,titlePadding:10,showTitle:!0,xAxis:{$ref:"#/$defs/XYChartAxisConfig",showLabel:!0,labelFontSize:14,labelPadding:5,showTitle:!0,titleFontSize:16,titlePadding:5,showTick:!0,tickLength:5,tickWidth:2,showAxisLine:!0,axisLineWidth:2},yAxis:{$ref:"#/$defs/XYChartAxisConfig",showLabel:!0,labelFontSize:14,labelPadding:5,showTitle:!0,titleFontSize:16,titlePadding:5,showTick:!0,tickLength:5,tickWidth:2,showAxisLine:!0,axisLineWidth:2},chartOrientation:"vertical",plotReservedSpacePercent:50},requirement:{useMaxWidth:!0,rect_fill:"#f9f9f9",text_color:"#333",rect_border_size:"0.5px",rect_border_color:"#bbb",rect_min_width:200,rect_min_height:200,fontSize:14,rect_padding:10,line_height:20},mindmap:{useMaxWidth:!0,padding:10,maxNodeWidth:200},timeline:{useMaxWidth:!0,diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open Sans", sans-serif',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"],disableMulticolor:!1},gitGraph:{useMaxWidth:!0,titleTopMargin:25,diagramPadding:8,nodeLabel:{width:75,height:100,x:-25,y:0},mainBranchName:"main",mainBranchOrder:0,showCommitLabel:!0,showBranches:!0,rotateCommitLabel:!0,parallelCommits:!1,arrowMarkerAbsolute:!1},c4:{useMaxWidth:!0,diagramMarginX:50,diagramMarginY:10,c4ShapeMargin:50,c4ShapePadding:20,width:216,height:60,boxMargin:10,c4ShapeInRow:4,nextLinePaddingX:0,c4BoundaryInRow:2,personFontSize:14,personFontFamily:'"Open Sans", sans-serif',personFontWeight:"normal",external_personFontSize:14,external_personFontFamily:'"Open Sans", sans-serif',external_personFontWeight:"normal",systemFontSize:14,systemFontFamily:'"Open Sans", sans-serif',systemFontWeight:"normal",external_systemFontSize:14,external_systemFontFamily:'"Open Sans", sans-serif',external_systemFontWeight:"normal",system_dbFontSize:14,system_dbFontFamily:'"Open Sans", sans-serif',system_dbFontWeight:"normal",external_system_dbFontSize:14,external_system_dbFontFamily:'"Open Sans", sans-serif',external_system_dbFontWeight:"normal",system_queueFontSize:14,system_queueFontFamily:'"Open Sans", sans-serif',system_queueFontWeight:"normal",external_system_queueFontSize:14,external_system_queueFontFamily:'"Open Sans", sans-serif',external_system_queueFontWeight:"normal",boundaryFontSize:14,boundaryFontFamily:'"Open Sans", sans-serif',boundaryFontWeight:"normal",messageFontSize:12,messageFontFamily:'"Open Sans", sans-serif',messageFontWeight:"normal",containerFontSize:14,containerFontFamily:'"Open Sans", sans-serif',containerFontWeight:"normal",external_containerFontSize:14,external_containerFontFamily:'"Open Sans", sans-serif',external_containerFontWeight:"normal",container_dbFontSize:14,container_dbFontFamily:'"Open Sans", sans-serif',container_dbFontWeight:"normal",external_container_dbFontSize:14,external_container_dbFontFamily:'"Open Sans", sans-serif',external_container_dbFontWeight:"normal",container_queueFontSize:14,container_queueFontFamily:'"Open Sans", sans-serif',container_queueFontWeight:"normal",external_container_queueFontSize:14,external_container_queueFontFamily:'"Open Sans", sans-serif',external_container_queueFontWeight:"normal",componentFontSize:14,componentFontFamily:'"Open Sans", sans-serif',componentFontWeight:"normal",external_componentFontSize:14,external_componentFontFamily:'"Open Sans", sans-serif',external_componentFontWeight:"normal",component_dbFontSize:14,component_dbFontFamily:'"Open Sans", sans-serif',component_dbFontWeight:"normal",external_component_dbFontSize:14,external_component_dbFontFamily:'"Open Sans", sans-serif',external_component_dbFontWeight:"normal",component_queueFontSize:14,component_queueFontFamily:'"Open Sans", sans-serif',component_queueFontWeight:"normal",external_component_queueFontSize:14,external_component_queueFontFamily:'"Open Sans", sans-serif',external_component_queueFontWeight:"normal",wrap:!0,wrapPadding:10,person_bg_color:"#08427B",person_border_color:"#073B6F",external_person_bg_color:"#686868",external_person_border_color:"#8A8A8A",system_bg_color:"#1168BD",system_border_color:"#3C7FC0",system_db_bg_color:"#1168BD",system_db_border_color:"#3C7FC0",system_queue_bg_color:"#1168BD",system_queue_border_color:"#3C7FC0",external_system_bg_color:"#999999",external_system_border_color:"#8A8A8A",external_system_db_bg_color:"#999999",external_system_db_border_color:"#8A8A8A",external_system_queue_bg_color:"#999999",external_system_queue_border_color:"#8A8A8A",container_bg_color:"#438DD5",container_border_color:"#3C7FC0",container_db_bg_color:"#438DD5",container_db_border_color:"#3C7FC0",container_queue_bg_color:"#438DD5",container_queue_border_color:"#3C7FC0",external_container_bg_color:"#B3B3B3",external_container_border_color:"#A6A6A6",external_container_db_bg_color:"#B3B3B3",external_container_db_border_color:"#A6A6A6",external_container_queue_bg_color:"#B3B3B3",external_container_queue_border_color:"#A6A6A6",component_bg_color:"#85BBF0",component_border_color:"#78A8D8",component_db_bg_color:"#85BBF0",component_db_border_color:"#78A8D8",component_queue_bg_color:"#85BBF0",component_queue_border_color:"#78A8D8",external_component_bg_color:"#CCCCCC",external_component_border_color:"#BFBFBF",external_component_db_bg_color:"#CCCCCC",external_component_db_border_color:"#BFBFBF",external_component_queue_bg_color:"#CCCCCC",external_component_queue_border_color:"#BFBFBF"},sankey:{useMaxWidth:!0,width:600,height:400,linkColor:"gradient",nodeAlignment:"justify",showValues:!0,prefix:"",suffix:""},block:{useMaxWidth:!0,padding:8},theme:"default",maxTextSize:5e4,maxEdges:500,darkMode:!1,fontFamily:'"trebuchet ms", verdana, arial, sans-serif;',logLevel:5,securityLevel:"strict",startOnLoad:!0,arrowMarkerAbsolute:!1,secure:["secure","securityLevel","startOnLoad","maxTextSize","maxEdges"],legacyMathML:!1,deterministicIds:!1,fontSize:16},rl={...Gt,deterministicIDSeed:void 0,themeCSS:void 0,themeVariables:Zt.default.getThemeVariables(),sequence:{...Gt.sequence,messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}},noteFont:function(){return{fontFamily:this.noteFontFamily,fontSize:this.noteFontSize,fontWeight:this.noteFontWeight}},actorFont:function(){return{fontFamily:this.actorFontFamily,fontSize:this.actorFontSize,fontWeight:this.actorFontWeight}}},gantt:{...Gt.gantt,tickInterval:void 0,useWidth:void 0},c4:{...Gt.c4,useWidth:void 0,personFont:function(){return{fontFamily:this.personFontFamily,fontSize:this.personFontSize,fontWeight:this.personFontWeight}},external_personFont:function(){return{fontFamily:this.external_personFontFamily,fontSize:this.external_personFontSize,fontWeight:this.external_personFontWeight}},systemFont:function(){return{fontFamily:this.systemFontFamily,fontSize:this.systemFontSize,fontWeight:this.systemFontWeight}},external_systemFont:function(){return{fontFamily:this.external_systemFontFamily,fontSize:this.external_systemFontSize,fontWeight:this.external_systemFontWeight}},system_dbFont:function(){return{fontFamily:this.system_dbFontFamily,fontSize:this.system_dbFontSize,fontWeight:this.system_dbFontWeight}},external_system_dbFont:function(){return{fontFamily:this.external_system_dbFontFamily,fontSize:this.external_system_dbFontSize,fontWeight:this.external_system_dbFontWeight}},system_queueFont:function(){return{fontFamily:this.system_queueFontFamily,fontSize:this.system_queueFontSize,fontWeight:this.system_queueFontWeight}},external_system_queueFont:function(){return{fontFamily:this.external_system_queueFontFamily,fontSize:this.external_system_queueFontSize,fontWeight:this.external_system_queueFontWeight}},containerFont:function(){return{fontFamily:this.containerFontFamily,fontSize:this.containerFontSize,fontWeight:this.containerFontWeight}},external_containerFont:function(){return{fontFamily:this.external_containerFontFamily,fontSize:this.external_containerFontSize,fontWeight:this.external_containerFontWeight}},container_dbFont:function(){return{fontFamily:this.container_dbFontFamily,fontSize:this.container_dbFontSize,fontWeight:this.container_dbFontWeight}},external_container_dbFont:function(){return{fontFamily:this.external_container_dbFontFamily,fontSize:this.external_container_dbFontSize,fontWeight:this.external_container_dbFontWeight}},container_queueFont:function(){return{fontFamily:this.container_queueFontFamily,fontSize:this.container_queueFontSize,fontWeight:this.container_queueFontWeight}},external_container_queueFont:function(){return{fontFamily:this.external_container_queueFontFamily,fontSize:this.external_container_queueFontSize,fontWeight:this.external_container_queueFontWeight}},componentFont:function(){return{fontFamily:this.componentFontFamily,fontSize:this.componentFontSize,fontWeight:this.componentFontWeight}},external_componentFont:function(){return{fontFamily:this.external_componentFontFamily,fontSize:this.external_componentFontSize,fontWeight:this.external_componentFontWeight}},component_dbFont:function(){return{fontFamily:this.component_dbFontFamily,fontSize:this.component_dbFontSize,fontWeight:this.component_dbFontWeight}},external_component_dbFont:function(){return{fontFamily:this.external_component_dbFontFamily,fontSize:this.external_component_dbFontSize,fontWeight:this.external_component_dbFontWeight}},component_queueFont:function(){return{fontFamily:this.component_queueFontFamily,fontSize:this.component_queueFontSize,fontWeight:this.component_queueFontWeight}},external_component_queueFont:function(){return{fontFamily:this.external_component_queueFontFamily,fontSize:this.external_component_queueFontSize,fontWeight:this.external_component_queueFontWeight}},boundaryFont:function(){return{fontFamily:this.boundaryFontFamily,fontSize:this.boundaryFontSize,fontWeight:this.boundaryFontWeight}},messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}}},pie:{...Gt.pie,useWidth:984},xyChart:{...Gt.xyChart,useWidth:void 0},requirement:{...Gt.requirement,useWidth:void 0},gitGraph:{...Gt.gitGraph,useMaxWidth:!1},sankey:{...Gt.sankey,useMaxWidth:!1}},nl=(t,e="")=>Object.keys(t).reduce((i,r)=>Array.isArray(t[r])?i:typeof t[r]=="object"&&t[r]!==null?[...i,e+r,...nl(t[r],"")]:[...i,e+r],[]),i0=new Set(nl(rl,"")),r0=rl,or=t=>{if(O.debug("sanitizeDirective called with",t),!(typeof t!="object"||t==null)){if(Array.isArray(t)){t.forEach(e=>or(e));return}for(const e of Object.keys(t)){if(O.debug("Checking key",e),e.startsWith("__")||e.includes("proto")||e.includes("constr")||!i0.has(e)||t[e]==null){O.debug("sanitize deleting key: ",e),delete t[e];continue}if(typeof t[e]=="object"){O.debug("sanitizing object",e),or(t[e]);continue}const i=["themeCSS","fontFamily","altFontFamily"];for(const r of i)e.includes(r)&&(O.debug("sanitizing css option",e),t[e]=n0(t[e]))}if(t.themeVariables)for(const e of Object.keys(t.themeVariables)){const i=t.themeVariables[e];i!=null&&i.match&&!i.match(/^[\d "#%(),.;A-Za-z]+$/)&&(t.themeVariables[e]="")}O.debug("After sanitization",t)}},n0=t=>{let e=0,i=0;for(const r of t){if(e{for(const{id:e,detector:i,loader:r}of t)ll(e,i,r)},ll=(t,e,i)=>{De[t]?O.error(`Detector with key ${t} already exists`):De[t]={detector:e,loader:i},O.debug(`Detector with key ${t} added${i?" with loader":""}`)},s0=t=>De[t].loader,Tn=(t,e,{depth:i=2,clobber:r=!1}={})=>{const n={depth:i,clobber:r};return Array.isArray(e)&&!Array.isArray(t)?(e.forEach(o=>Tn(t,o,n)),t):Array.isArray(e)&&Array.isArray(t)?(e.forEach(o=>{t.includes(o)||t.push(o)}),t):t===void 0||i<=0?t!=null&&typeof t=="object"&&typeof e=="object"?Object.assign(t,e):e:(e!==void 0&&typeof t=="object"&&typeof e=="object"&&Object.keys(e).forEach(o=>{typeof e[o]=="object"&&(t[o]===void 0||typeof t[o]=="object")?(t[o]===void 0&&(t[o]=Array.isArray(e[o])?[]:{}),t[o]=Tn(t[o],e[o],{depth:i-1,clobber:r})):(r||typeof t[o]!="object"&&typeof e[o]!="object")&&(t[o]=e[o])}),t)},st=Tn,a0="​",l0={curveBasis:qf,curveBasisClosed:zf,curveBasisOpen:Wf,curveBumpX:Rf,curveBumpY:Pf,curveBundle:Hf,curveCardinalClosed:Uf,curveCardinalOpen:Yf,curveCardinal:jf,curveCatmullRomClosed:Gf,curveCatmullRomOpen:Xf,curveCatmullRom:Vf,curveLinear:Nf,curveLinearClosed:Kf,curveMonotoneX:Zf,curveMonotoneY:Jf,curveNatural:Qf,curveStep:td,curveStepAfter:id,curveStepBefore:ed},h0=/\s*(?:(\w+)(?=:):|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi,c0=function(t,e){const i=hl(t,/(?:init\b)|(?:initialize\b)/);let r={};if(Array.isArray(i)){const s=i.map(a=>a.args);or(s),r=st(r,[...s])}else r=i.args;if(!r)return;let n=Lr(t,e);const o="config";return r[o]!==void 0&&(n==="flowchart-v2"&&(n="flowchart"),r[n]=r[o],delete r[o]),r},hl=function(t,e=null){try{const i=new RegExp(`[%]{2}(?![{]${h0.source})(?=[}][%]{2}).* -`,"ig");t=t.trim().replace(i,"").replace(/'/gm,'"'),O.debug(`Detecting diagram directive${e!==null?" type:"+e:""} based on the text:${t}`);let r;const n=[];for(;(r=oi.exec(t))!==null;)if(r.index===oi.lastIndex&&oi.lastIndex++,r&&!e||e&&r[1]&&r[1].match(e)||e&&r[2]&&r[2].match(e)){const o=r[1]?r[1]:r[2],s=r[3]?r[3].trim():r[4]?JSON.parse(r[4].trim()):null;n.push({type:o,args:s})}return n.length===0?{type:t,args:null}:n.length===1?n[0]:n}catch(i){return O.error(`ERROR: ${i.message} - Unable to parse directive type: '${e}' based on the text: '${t}'`),{type:void 0,args:null}}},u0=function(t){return t.replace(oi,"")},f0=function(t,e){for(const[i,r]of e.entries())if(r.match(t))return i;return-1};function d0(t,e){if(!t)return e;const i=`curve${t.charAt(0).toUpperCase()+t.slice(1)}`;return l0[i]??e}function p0(t,e){const i=t.trim();if(i)return e.securityLevel!=="loose"?Ws.sanitizeUrl(i):i}const g0=(t,...e)=>{const i=t.split("."),r=i.length-1,n=i[r];let o=window;for(let s=0;s{i+=cl(n,e),e=n});const r=i/2;return jn(t,r)}function _0(t){return t.length===1?t[0]:m0(t)}const Ss=(t,e=2)=>{const i=Math.pow(10,e);return Math.round(t*i)/i},jn=(t,e)=>{let i,r=e;for(const n of t){if(i){const o=cl(n,i);if(o=1)return{x:n.x,y:n.y};if(s>0&&s<1)return{x:Ss((1-s)*i.x+s*n.x,5),y:Ss((1-s)*i.y+s*n.y,5)}}}i=n}throw new Error("Could not find a suitable point for the given distance")},y0=(t,e,i)=>{O.info(`our points ${JSON.stringify(e)}`),e[0]!==i&&(e=e.reverse());const n=jn(e,25),o=t?10:5,s=Math.atan2(e[0].y-n.y,e[0].x-n.x),a={x:0,y:0};return a.x=Math.sin(s)*o+(e[0].x+n.x)/2,a.y=-Math.cos(s)*o+(e[0].y+n.y)/2,a};function C0(t,e,i){const r=structuredClone(i);O.info("our points",r),e!=="start_left"&&e!=="start_right"&&r.reverse();const n=25+t,o=jn(r,n),s=10+t*.5,a=Math.atan2(r[0].y-o.y,r[0].x-o.x),l={x:0,y:0};return e==="start_left"?(l.x=Math.sin(a+Math.PI)*s+(r[0].x+o.x)/2,l.y=-Math.cos(a+Math.PI)*s+(r[0].y+o.y)/2):e==="end_right"?(l.x=Math.sin(a-Math.PI)*s+(r[0].x+o.x)/2-5,l.y=-Math.cos(a-Math.PI)*s+(r[0].y+o.y)/2-5):e==="end_left"?(l.x=Math.sin(a)*s+(r[0].x+o.x)/2-5,l.y=-Math.cos(a)*s+(r[0].y+o.y)/2-5):(l.x=Math.sin(a)*s+(r[0].x+o.x)/2,l.y=-Math.cos(a)*s+(r[0].y+o.y)/2),l}function x0(t){let e="",i="";for(const r of t)r!==void 0&&(r.startsWith("color:")||r.startsWith("text-align:")?i=i+r+";":e=e+r+";");return{style:e,labelStyle:i}}let ws=0;const b0=()=>(ws++,"id-"+Math.random().toString(36).substr(2,12)+"-"+ws);function T0(t){let e="";const i="0123456789abcdef",r=i.length;for(let n=0;nT0(t.length),k0=function(){return{x:0,y:0,fill:void 0,anchor:"start",style:"#666",width:100,height:100,textMargin:0,rx:0,ry:0,valign:void 0,text:""}},S0=function(t,e){const i=e.text.replace(Hn.lineBreakRegex," "),[,r]=Yn(e.fontSize),n=t.append("text");n.attr("x",e.x),n.attr("y",e.y),n.style("text-anchor",e.anchor),n.style("font-family",e.fontFamily),n.style("font-size",r),n.style("font-weight",e.fontWeight),n.attr("fill",e.fill),e.class!==void 0&&n.attr("class",e.class);const o=n.append("tspan");return o.attr("x",e.x+e.textMargin*2),o.attr("fill",e.fill),o.text(i),n},w0=bi((t,e,i)=>{if(!t||(i=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",joinWith:"
                                        "},i),Hn.lineBreakRegex.test(t)))return t;const r=t.split(" "),n=[];let o="";return r.forEach((s,a)=>{const l=sr(`${s} `,i),h=sr(o,i);if(l>e){const{hyphenatedStrings:c,remainingWord:p}=B0(s,e,"-",i);n.push(o,...c),o=p}else h+l>=e?(n.push(o),o=s):o=[o,s].filter(Boolean).join(" ");a+1===r.length&&n.push(o)}),n.filter(s=>s!=="").join(i.joinWith)},(t,e,i)=>`${t}${e}${i.fontSize}${i.fontWeight}${i.fontFamily}${i.joinWith}`),B0=bi((t,e,i="-",r)=>{r=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:0},r);const n=[...t],o=[];let s="";return n.forEach((a,l)=>{const h=`${s}${a}`;if(sr(h,r)>=e){const f=l+1,c=n.length===f,p=`${h}${i}`;o.push(c?h:p),s=""}else s=h}),{hyphenatedStrings:o,remainingWord:s}},(t,e,i="-",r)=>`${t}${e}${i}${r.fontSize}${r.fontWeight}${r.fontFamily}`);function A0(t,e){return Un(t,e).height}function sr(t,e){return Un(t,e).width}const Un=bi((t,e)=>{const{fontSize:i=12,fontFamily:r="Arial",fontWeight:n=400}=e;if(!t)return{width:0,height:0};const[,o]=Yn(i),s=["sans-serif",r],a=t.split(Hn.lineBreakRegex),l=[],h=Tt("body");if(!h.remove)return{width:0,height:0,lineHeight:0};const u=h.append("svg");for(const c of s){let p=0;const _={width:0,height:0,lineHeight:0};for(const v of a){const k=k0();k.text=v||a0;const N=S0(u,k).style("font-size",o).style("font-weight",n).style("font-family",c),b=(N._groups||N)[0][0].getBBox();if(b.width===0&&b.height===0)throw new Error("svg element not in render tree");_.width=Math.round(Math.max(_.width,b.width)),p=Math.round(b.height),_.height+=p,_.lineHeight=Math.round(Math.max(_.lineHeight,p))}l.push(_)}u.remove();const f=isNaN(l[1].height)||isNaN(l[1].width)||isNaN(l[1].lineHeight)||l[0].height>l[1].height&&l[0].width>l[1].width&&l[0].lineHeight>l[1].lineHeight?0:1;return l[f]},(t,e)=>`${t}${e.fontSize}${e.fontWeight}${e.fontFamily}`);class L0{constructor(e=!1,i){this.count=0,this.count=i?i.length:0,this.next=e?()=>this.count++:()=>Date.now()}}let Di;const F0=function(t){return Di=Di||document.createElement("div"),t=escape(t).replace(/%26/g,"&").replace(/%23/g,"#").replace(/%3B/g,";"),Di.innerHTML=t,unescape(Di.textContent)};function ul(t){return"str"in t}const E0=(t,e,i,r)=>{var n;if(!r)return;const o=(n=t.node())==null?void 0:n.getBBox();o&&t.append("text").text(r).attr("x",o.x+o.width/2).attr("y",-i).attr("class",e)},Yn=t=>{if(typeof t=="number")return[t,t+"px"];const e=parseInt(t??"",10);return Number.isNaN(e)?[void 0,void 0]:t===String(e)?[e,t+"px"]:[e,t]};function fl(t,e){return im({},t,e)}const si={assignWithDepth:st,wrapLabel:w0,calculateTextHeight:A0,calculateTextWidth:sr,calculateTextDimensions:Un,cleanAndMerge:fl,detectInit:c0,detectDirective:hl,isSubstringInArray:f0,interpolateToCurve:d0,calcLabelPosition:_0,calcCardinalityPosition:y0,calcTerminalLabelPosition:C0,formatUrl:p0,getStylesFromArray:x0,generateId:b0,random:v0,runFunc:g0,entityDecode:F0,insertTitle:E0,parseFontSize:Yn,InitIDGenerator:L0},O0=function(t){let e=t;return e=e.replace(/style.*:\S*#.*;/g,function(i){return i.substring(0,i.length-1)}),e=e.replace(/classDef.*:\S*#.*;/g,function(i){return i.substring(0,i.length-1)}),e=e.replace(/#\w+;/g,function(i){const r=i.substring(1,i.length-1);return/^\+?\d+$/.test(r)?"fl°°"+r+"¶ß":"fl°"+r+"¶ß"}),e},M0=function(t){return t.replace(/fl°°/g,"&#").replace(/fl°/g,"&").replace(/¶ß/g,";")},Bs="10.9.1",Ne=Object.freeze(r0);let gt=st({},Ne),dl,Re=[],ai=st({},Ne);const Fr=(t,e)=>{let i=st({},t),r={};for(const n of e)ml(n),r=st(r,n);if(i=st(i,r),r.theme&&r.theme in Zt){const n=st({},dl),o=st(n.themeVariables||{},r.themeVariables);i.theme&&i.theme in Zt&&(i.themeVariables=Zt[i.theme].getThemeVariables(o))}return ai=i,_l(ai),ai},I0=t=>(gt=st({},Ne),gt=st(gt,t),t.theme&&Zt[t.theme]&&(gt.themeVariables=Zt[t.theme].getThemeVariables(t.themeVariables)),Fr(gt,Re),gt),$0=t=>{dl=st({},t)},D0=t=>(gt=st(gt,t),Fr(gt,Re),gt),pl=()=>st({},gt),gl=t=>(_l(t),st(ai,t),Pt()),Pt=()=>st({},ai),ml=t=>{t&&(["secure",...gt.secure??[]].forEach(e=>{Object.hasOwn(t,e)&&(O.debug(`Denied attempt to modify a secure key ${e}`,t[e]),delete t[e])}),Object.keys(t).forEach(e=>{e.startsWith("__")&&delete t[e]}),Object.keys(t).forEach(e=>{typeof t[e]=="string"&&(t[e].includes("<")||t[e].includes(">")||t[e].includes("url(data:"))&&delete t[e],typeof t[e]=="object"&&ml(t[e])}))},N0=t=>{or(t),t.fontFamily&&(!t.themeVariables||!t.themeVariables.fontFamily)&&(t.themeVariables={fontFamily:t.fontFamily}),Re.push(t),Fr(gt,Re)},ar=(t=gt)=>{Re=[],Fr(t,Re)},R0={LAZY_LOAD_DEPRECATED:"The configuration options lazyLoadedDiagrams and loadExternalDiagramsAtStartup are deprecated. Please use registerExternalDiagrams instead."},As={},P0=t=>{As[t]||(O.warn(R0[t]),As[t]=!0)},_l=t=>{t&&(t.lazyLoadedDiagrams||t.loadExternalDiagramsAtStartup)&&P0("LAZY_LOAD_DEPRECATED")},yl="c4",q0=t=>/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(t),z0=async()=>{const{diagram:t}=await X(()=>import("./c4Diagram-ae766693-TOZe-7Pl.js"),__vite__mapDeps([0,1,2]));return{id:yl,diagram:t}},W0={id:yl,detector:q0,loader:z0},H0=W0,Cl="flowchart",j0=(t,e)=>{var i,r;return((i=e==null?void 0:e.flowchart)==null?void 0:i.defaultRenderer)==="dagre-wrapper"||((r=e==null?void 0:e.flowchart)==null?void 0:r.defaultRenderer)==="elk"?!1:/^\s*graph/.test(t)},U0=async()=>{const{diagram:t}=await X(()=>import("./flowDiagram-b222e15a-ClSO8xjE.js"),__vite__mapDeps([3,4,5,6,7,8,9,10,11,12,13,14,15,2]));return{id:Cl,diagram:t}},Y0={id:Cl,detector:j0,loader:U0},V0=Y0,xl="flowchart-v2",G0=(t,e)=>{var i,r,n;return((i=e==null?void 0:e.flowchart)==null?void 0:i.defaultRenderer)==="dagre-d3"||((r=e==null?void 0:e.flowchart)==null?void 0:r.defaultRenderer)==="elk"?!1:/^\s*graph/.test(t)&&((n=e==null?void 0:e.flowchart)==null?void 0:n.defaultRenderer)==="dagre-wrapper"?!0:/^\s*flowchart/.test(t)},X0=async()=>{const{diagram:t}=await X(()=>import("./flowDiagram-v2-13329dc7-CD3itvv-.js"),__vite__mapDeps([16,4,7,5,8,6,9,10,11,12,13,14,15,2]));return{id:xl,diagram:t}},K0={id:xl,detector:G0,loader:X0},Z0=K0,bl="er",J0=t=>/^\s*erDiagram/.test(t),Q0=async()=>{const{diagram:t}=await X(()=>import("./erDiagram-09d1c15f-DTI3Ywn0.js"),__vite__mapDeps([17,5,6,12,13,14,2]));return{id:bl,diagram:t}},t_={id:bl,detector:J0,loader:Q0},e_=t_,Tl="gitGraph",i_=t=>/^\s*gitGraph/.test(t),r_=async()=>{const{diagram:t}=await X(()=>import("./gitGraphDiagram-942e62fe-DOX28HzV.js"),__vite__mapDeps([18,2]));return{id:Tl,diagram:t}},n_={id:Tl,detector:i_,loader:r_},o_=n_,vl="gantt",s_=t=>/^\s*gantt/.test(t),a_=async()=>{const{diagram:t}=await X(()=>import("./ganttDiagram-b62c793e-B3546ou_.js"),__vite__mapDeps([19,20,21,2]));return{id:vl,diagram:t}},l_={id:vl,detector:s_,loader:a_},h_=l_,kl="info",c_=t=>/^\s*info/.test(t),u_=async()=>{const{diagram:t}=await X(()=>import("./infoDiagram-94cd232f-I6ioXWcf.js"),__vite__mapDeps([22,2]));return{id:kl,diagram:t}},f_={id:kl,detector:c_,loader:u_},Sl="pie",d_=t=>/^\s*pie/.test(t),p_=async()=>{const{diagram:t}=await X(()=>import("./pieDiagram-bb1d19e5-BQuVNcMJ.js"),__vite__mapDeps([23,24,14,25,21,13,2]));return{id:Sl,diagram:t}},g_={id:Sl,detector:d_,loader:p_},wl="quadrantChart",m_=t=>/^\s*quadrantChart/.test(t),__=async()=>{const{diagram:t}=await X(()=>import("./quadrantDiagram-c759a472-B16G3h9g.js"),__vite__mapDeps([26,20,21,2]));return{id:wl,diagram:t}},y_={id:wl,detector:m_,loader:__},C_=y_,Bl="xychart",x_=t=>/^\s*xychart-beta/.test(t),b_=async()=>{const{diagram:t}=await X(()=>import("./xychartDiagram-f11f50a6-BfE2Gore.js"),__vite__mapDeps([27,11,21,25,20,12,13,14,2]));return{id:Bl,diagram:t}},T_={id:Bl,detector:x_,loader:b_},v_=T_,Al="requirement",k_=t=>/^\s*requirement(Diagram)?/.test(t),S_=async()=>{const{diagram:t}=await X(()=>import("./requirementDiagram-87253d64-K4iL_vop.js"),__vite__mapDeps([28,5,6,12,13,14,2]));return{id:Al,diagram:t}},w_={id:Al,detector:k_,loader:S_},B_=w_,Ll="sequence",A_=t=>/^\s*sequenceDiagram/.test(t),L_=async()=>{const{diagram:t}=await X(()=>import("./sequenceDiagram-6894f283-BOatradp.js"),__vite__mapDeps([29,1,2]));return{id:Ll,diagram:t}},F_={id:Ll,detector:A_,loader:L_},E_=F_,Fl="class",O_=(t,e)=>{var i;return((i=e==null?void 0:e.class)==null?void 0:i.defaultRenderer)==="dagre-wrapper"?!1:/^\s*classDiagram/.test(t)},M_=async()=>{const{diagram:t}=await X(()=>import("./classDiagram-fb54d2a0-C9zXAHzr.js"),__vite__mapDeps([30,31,5,6,12,13,14,2]));return{id:Fl,diagram:t}},I_={id:Fl,detector:O_,loader:M_},$_=I_,El="classDiagram",D_=(t,e)=>{var i;return/^\s*classDiagram/.test(t)&&((i=e==null?void 0:e.class)==null?void 0:i.defaultRenderer)==="dagre-wrapper"?!0:/^\s*classDiagram-v2/.test(t)},N_=async()=>{const{diagram:t}=await X(()=>import("./classDiagram-v2-a2b738ad-ChHu4we1.js"),__vite__mapDeps([32,31,5,8,6,9,10,11,12,13,14,2]));return{id:El,diagram:t}},R_={id:El,detector:D_,loader:N_},P_=R_,Ol="state",q_=(t,e)=>{var i;return((i=e==null?void 0:e.state)==null?void 0:i.defaultRenderer)==="dagre-wrapper"?!1:/^\s*stateDiagram/.test(t)},z_=async()=>{const{diagram:t}=await X(()=>import("./stateDiagram-5dee940d-BYrroPY3.js"),__vite__mapDeps([33,34,5,6,12,13,14,2]));return{id:Ol,diagram:t}},W_={id:Ol,detector:q_,loader:z_},H_=W_,Ml="stateDiagram",j_=(t,e)=>{var i;return!!(/^\s*stateDiagram-v2/.test(t)||/^\s*stateDiagram/.test(t)&&((i=e==null?void 0:e.state)==null?void 0:i.defaultRenderer)==="dagre-wrapper")},U_=async()=>{const{diagram:t}=await X(()=>import("./stateDiagram-v2-1992cada-BZne08Mr.js"),__vite__mapDeps([35,34,5,8,6,9,10,11,12,13,14,2]));return{id:Ml,diagram:t}},Y_={id:Ml,detector:j_,loader:U_},V_=Y_,Il="journey",G_=t=>/^\s*journey/.test(t),X_=async()=>{const{diagram:t}=await X(()=>import("./journeyDiagram-6625b456-CHnHUPp6.js"),__vite__mapDeps([36,1,24,14,2]));return{id:Il,diagram:t}},K_={id:Il,detector:G_,loader:X_},Z_=K_,J_=function(t,e){for(let i of e)t.attr(i[0],i[1])},Q_=function(t,e,i){let r=new Map;return i?(r.set("width","100%"),r.set("style",`max-width: ${e}px;`)):(r.set("height",t),r.set("width",e)),r},$l=function(t,e,i,r){const n=Q_(e,i,r);J_(t,n)},ty=function(t,e,i,r){const n=e.node().getBBox(),o=n.width,s=n.height;O.info(`SVG bounds: ${o}x${s}`,n);let a=0,l=0;O.info(`Graph bounds: ${a}x${l}`,t),a=o+i*2,l=s+i*2,O.info(`Calculated bounds: ${a}x${l}`),$l(e,l,a,r);const h=`${n.x-i} ${n.y-i} ${n.width+2*i} ${n.height+2*i}`;e.attr("viewBox",h)},Ui={},ey=(t,e,i)=>{let r="";return t in Ui&&Ui[t]?r=Ui[t](i):O.warn(`No theme found for ${t}`),` & { +`,"ig");t=t.trim().replace(i,"").replace(/'/gm,'"'),O.debug(`Detecting diagram directive${e!==null?" type:"+e:""} based on the text:${t}`);let r;const n=[];for(;(r=oi.exec(t))!==null;)if(r.index===oi.lastIndex&&oi.lastIndex++,r&&!e||e&&r[1]&&r[1].match(e)||e&&r[2]&&r[2].match(e)){const o=r[1]?r[1]:r[2],s=r[3]?r[3].trim():r[4]?JSON.parse(r[4].trim()):null;n.push({type:o,args:s})}return n.length===0?{type:t,args:null}:n.length===1?n[0]:n}catch(i){return O.error(`ERROR: ${i.message} - Unable to parse directive type: '${e}' based on the text: '${t}'`),{type:void 0,args:null}}},u0=function(t){return t.replace(oi,"")},f0=function(t,e){for(const[i,r]of e.entries())if(r.match(t))return i;return-1};function d0(t,e){if(!t)return e;const i=`curve${t.charAt(0).toUpperCase()+t.slice(1)}`;return l0[i]??e}function p0(t,e){const i=t.trim();if(i)return e.securityLevel!=="loose"?Ws.sanitizeUrl(i):i}const g0=(t,...e)=>{const i=t.split("."),r=i.length-1,n=i[r];let o=window;for(let s=0;s{i+=cl(n,e),e=n});const r=i/2;return jn(t,r)}function _0(t){return t.length===1?t[0]:m0(t)}const Ss=(t,e=2)=>{const i=Math.pow(10,e);return Math.round(t*i)/i},jn=(t,e)=>{let i,r=e;for(const n of t){if(i){const o=cl(n,i);if(o=1)return{x:n.x,y:n.y};if(s>0&&s<1)return{x:Ss((1-s)*i.x+s*n.x,5),y:Ss((1-s)*i.y+s*n.y,5)}}}i=n}throw new Error("Could not find a suitable point for the given distance")},y0=(t,e,i)=>{O.info(`our points ${JSON.stringify(e)}`),e[0]!==i&&(e=e.reverse());const n=jn(e,25),o=t?10:5,s=Math.atan2(e[0].y-n.y,e[0].x-n.x),a={x:0,y:0};return a.x=Math.sin(s)*o+(e[0].x+n.x)/2,a.y=-Math.cos(s)*o+(e[0].y+n.y)/2,a};function C0(t,e,i){const r=structuredClone(i);O.info("our points",r),e!=="start_left"&&e!=="start_right"&&r.reverse();const n=25+t,o=jn(r,n),s=10+t*.5,a=Math.atan2(r[0].y-o.y,r[0].x-o.x),l={x:0,y:0};return e==="start_left"?(l.x=Math.sin(a+Math.PI)*s+(r[0].x+o.x)/2,l.y=-Math.cos(a+Math.PI)*s+(r[0].y+o.y)/2):e==="end_right"?(l.x=Math.sin(a-Math.PI)*s+(r[0].x+o.x)/2-5,l.y=-Math.cos(a-Math.PI)*s+(r[0].y+o.y)/2-5):e==="end_left"?(l.x=Math.sin(a)*s+(r[0].x+o.x)/2-5,l.y=-Math.cos(a)*s+(r[0].y+o.y)/2-5):(l.x=Math.sin(a)*s+(r[0].x+o.x)/2,l.y=-Math.cos(a)*s+(r[0].y+o.y)/2),l}function x0(t){let e="",i="";for(const r of t)r!==void 0&&(r.startsWith("color:")||r.startsWith("text-align:")?i=i+r+";":e=e+r+";");return{style:e,labelStyle:i}}let ws=0;const b0=()=>(ws++,"id-"+Math.random().toString(36).substr(2,12)+"-"+ws);function T0(t){let e="";const i="0123456789abcdef",r=i.length;for(let n=0;nT0(t.length),k0=function(){return{x:0,y:0,fill:void 0,anchor:"start",style:"#666",width:100,height:100,textMargin:0,rx:0,ry:0,valign:void 0,text:""}},S0=function(t,e){const i=e.text.replace(Hn.lineBreakRegex," "),[,r]=Yn(e.fontSize),n=t.append("text");n.attr("x",e.x),n.attr("y",e.y),n.style("text-anchor",e.anchor),n.style("font-family",e.fontFamily),n.style("font-size",r),n.style("font-weight",e.fontWeight),n.attr("fill",e.fill),e.class!==void 0&&n.attr("class",e.class);const o=n.append("tspan");return o.attr("x",e.x+e.textMargin*2),o.attr("fill",e.fill),o.text(i),n},w0=bi((t,e,i)=>{if(!t||(i=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",joinWith:"
                                        "},i),Hn.lineBreakRegex.test(t)))return t;const r=t.split(" "),n=[];let o="";return r.forEach((s,a)=>{const l=sr(`${s} `,i),h=sr(o,i);if(l>e){const{hyphenatedStrings:c,remainingWord:p}=B0(s,e,"-",i);n.push(o,...c),o=p}else h+l>=e?(n.push(o),o=s):o=[o,s].filter(Boolean).join(" ");a+1===r.length&&n.push(o)}),n.filter(s=>s!=="").join(i.joinWith)},(t,e,i)=>`${t}${e}${i.fontSize}${i.fontWeight}${i.fontFamily}${i.joinWith}`),B0=bi((t,e,i="-",r)=>{r=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:0},r);const n=[...t],o=[];let s="";return n.forEach((a,l)=>{const h=`${s}${a}`;if(sr(h,r)>=e){const f=l+1,c=n.length===f,p=`${h}${i}`;o.push(c?h:p),s=""}else s=h}),{hyphenatedStrings:o,remainingWord:s}},(t,e,i="-",r)=>`${t}${e}${i}${r.fontSize}${r.fontWeight}${r.fontFamily}`);function A0(t,e){return Un(t,e).height}function sr(t,e){return Un(t,e).width}const Un=bi((t,e)=>{const{fontSize:i=12,fontFamily:r="Arial",fontWeight:n=400}=e;if(!t)return{width:0,height:0};const[,o]=Yn(i),s=["sans-serif",r],a=t.split(Hn.lineBreakRegex),l=[],h=Tt("body");if(!h.remove)return{width:0,height:0,lineHeight:0};const u=h.append("svg");for(const c of s){let p=0;const _={width:0,height:0,lineHeight:0};for(const v of a){const k=k0();k.text=v||a0;const N=S0(u,k).style("font-size",o).style("font-weight",n).style("font-family",c),b=(N._groups||N)[0][0].getBBox();if(b.width===0&&b.height===0)throw new Error("svg element not in render tree");_.width=Math.round(Math.max(_.width,b.width)),p=Math.round(b.height),_.height+=p,_.lineHeight=Math.round(Math.max(_.lineHeight,p))}l.push(_)}u.remove();const f=isNaN(l[1].height)||isNaN(l[1].width)||isNaN(l[1].lineHeight)||l[0].height>l[1].height&&l[0].width>l[1].width&&l[0].lineHeight>l[1].lineHeight?0:1;return l[f]},(t,e)=>`${t}${e.fontSize}${e.fontWeight}${e.fontFamily}`);class L0{constructor(e=!1,i){this.count=0,this.count=i?i.length:0,this.next=e?()=>this.count++:()=>Date.now()}}let Di;const F0=function(t){return Di=Di||document.createElement("div"),t=escape(t).replace(/%26/g,"&").replace(/%23/g,"#").replace(/%3B/g,";"),Di.innerHTML=t,unescape(Di.textContent)};function ul(t){return"str"in t}const E0=(t,e,i,r)=>{var n;if(!r)return;const o=(n=t.node())==null?void 0:n.getBBox();o&&t.append("text").text(r).attr("x",o.x+o.width/2).attr("y",-i).attr("class",e)},Yn=t=>{if(typeof t=="number")return[t,t+"px"];const e=parseInt(t??"",10);return Number.isNaN(e)?[void 0,void 0]:t===String(e)?[e,t+"px"]:[e,t]};function fl(t,e){return im({},t,e)}const si={assignWithDepth:st,wrapLabel:w0,calculateTextHeight:A0,calculateTextWidth:sr,calculateTextDimensions:Un,cleanAndMerge:fl,detectInit:c0,detectDirective:hl,isSubstringInArray:f0,interpolateToCurve:d0,calcLabelPosition:_0,calcCardinalityPosition:y0,calcTerminalLabelPosition:C0,formatUrl:p0,getStylesFromArray:x0,generateId:b0,random:v0,runFunc:g0,entityDecode:F0,insertTitle:E0,parseFontSize:Yn,InitIDGenerator:L0},O0=function(t){let e=t;return e=e.replace(/style.*:\S*#.*;/g,function(i){return i.substring(0,i.length-1)}),e=e.replace(/classDef.*:\S*#.*;/g,function(i){return i.substring(0,i.length-1)}),e=e.replace(/#\w+;/g,function(i){const r=i.substring(1,i.length-1);return/^\+?\d+$/.test(r)?"fl°°"+r+"¶ß":"fl°"+r+"¶ß"}),e},M0=function(t){return t.replace(/fl°°/g,"&#").replace(/fl°/g,"&").replace(/¶ß/g,";")},Bs="10.9.1",Ne=Object.freeze(r0);let gt=st({},Ne),dl,Re=[],ai=st({},Ne);const Fr=(t,e)=>{let i=st({},t),r={};for(const n of e)ml(n),r=st(r,n);if(i=st(i,r),r.theme&&r.theme in Zt){const n=st({},dl),o=st(n.themeVariables||{},r.themeVariables);i.theme&&i.theme in Zt&&(i.themeVariables=Zt[i.theme].getThemeVariables(o))}return ai=i,_l(ai),ai},I0=t=>(gt=st({},Ne),gt=st(gt,t),t.theme&&Zt[t.theme]&&(gt.themeVariables=Zt[t.theme].getThemeVariables(t.themeVariables)),Fr(gt,Re),gt),$0=t=>{dl=st({},t)},D0=t=>(gt=st(gt,t),Fr(gt,Re),gt),pl=()=>st({},gt),gl=t=>(_l(t),st(ai,t),Pt()),Pt=()=>st({},ai),ml=t=>{t&&(["secure",...gt.secure??[]].forEach(e=>{Object.hasOwn(t,e)&&(O.debug(`Denied attempt to modify a secure key ${e}`,t[e]),delete t[e])}),Object.keys(t).forEach(e=>{e.startsWith("__")&&delete t[e]}),Object.keys(t).forEach(e=>{typeof t[e]=="string"&&(t[e].includes("<")||t[e].includes(">")||t[e].includes("url(data:"))&&delete t[e],typeof t[e]=="object"&&ml(t[e])}))},N0=t=>{or(t),t.fontFamily&&(!t.themeVariables||!t.themeVariables.fontFamily)&&(t.themeVariables={fontFamily:t.fontFamily}),Re.push(t),Fr(gt,Re)},ar=(t=gt)=>{Re=[],Fr(t,Re)},R0={LAZY_LOAD_DEPRECATED:"The configuration options lazyLoadedDiagrams and loadExternalDiagramsAtStartup are deprecated. Please use registerExternalDiagrams instead."},As={},P0=t=>{As[t]||(O.warn(R0[t]),As[t]=!0)},_l=t=>{t&&(t.lazyLoadedDiagrams||t.loadExternalDiagramsAtStartup)&&P0("LAZY_LOAD_DEPRECATED")},yl="c4",q0=t=>/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(t),z0=async()=>{const{diagram:t}=await X(()=>import("./c4Diagram-ae766693-DVn8Dofm.js"),__vite__mapDeps([0,1,2]));return{id:yl,diagram:t}},W0={id:yl,detector:q0,loader:z0},H0=W0,Cl="flowchart",j0=(t,e)=>{var i,r;return((i=e==null?void 0:e.flowchart)==null?void 0:i.defaultRenderer)==="dagre-wrapper"||((r=e==null?void 0:e.flowchart)==null?void 0:r.defaultRenderer)==="elk"?!1:/^\s*graph/.test(t)},U0=async()=>{const{diagram:t}=await X(()=>import("./flowDiagram-b222e15a-CRKbP293.js"),__vite__mapDeps([3,4,5,6,7,8,9,10,11,12,13,14,15,2]));return{id:Cl,diagram:t}},Y0={id:Cl,detector:j0,loader:U0},V0=Y0,xl="flowchart-v2",G0=(t,e)=>{var i,r,n;return((i=e==null?void 0:e.flowchart)==null?void 0:i.defaultRenderer)==="dagre-d3"||((r=e==null?void 0:e.flowchart)==null?void 0:r.defaultRenderer)==="elk"?!1:/^\s*graph/.test(t)&&((n=e==null?void 0:e.flowchart)==null?void 0:n.defaultRenderer)==="dagre-wrapper"?!0:/^\s*flowchart/.test(t)},X0=async()=>{const{diagram:t}=await X(()=>import("./flowDiagram-v2-13329dc7-CUX8GDMK.js"),__vite__mapDeps([16,4,7,5,8,6,9,10,11,12,13,14,15,2]));return{id:xl,diagram:t}},K0={id:xl,detector:G0,loader:X0},Z0=K0,bl="er",J0=t=>/^\s*erDiagram/.test(t),Q0=async()=>{const{diagram:t}=await X(()=>import("./erDiagram-09d1c15f-CxugSXM3.js"),__vite__mapDeps([17,5,6,12,13,14,2]));return{id:bl,diagram:t}},t_={id:bl,detector:J0,loader:Q0},e_=t_,Tl="gitGraph",i_=t=>/^\s*gitGraph/.test(t),r_=async()=>{const{diagram:t}=await X(()=>import("./gitGraphDiagram-942e62fe-CmfeKiv3.js"),__vite__mapDeps([18,2]));return{id:Tl,diagram:t}},n_={id:Tl,detector:i_,loader:r_},o_=n_,vl="gantt",s_=t=>/^\s*gantt/.test(t),a_=async()=>{const{diagram:t}=await X(()=>import("./ganttDiagram-b62c793e-BY6nXXtR.js"),__vite__mapDeps([19,20,21,2]));return{id:vl,diagram:t}},l_={id:vl,detector:s_,loader:a_},h_=l_,kl="info",c_=t=>/^\s*info/.test(t),u_=async()=>{const{diagram:t}=await X(()=>import("./infoDiagram-94cd232f-Don6DG4Z.js"),__vite__mapDeps([22,2]));return{id:kl,diagram:t}},f_={id:kl,detector:c_,loader:u_},Sl="pie",d_=t=>/^\s*pie/.test(t),p_=async()=>{const{diagram:t}=await X(()=>import("./pieDiagram-bb1d19e5-CBxnSt2_.js"),__vite__mapDeps([23,24,14,25,21,13,2]));return{id:Sl,diagram:t}},g_={id:Sl,detector:d_,loader:p_},wl="quadrantChart",m_=t=>/^\s*quadrantChart/.test(t),__=async()=>{const{diagram:t}=await X(()=>import("./quadrantDiagram-c759a472-DYqUNjWH.js"),__vite__mapDeps([26,20,21,2]));return{id:wl,diagram:t}},y_={id:wl,detector:m_,loader:__},C_=y_,Bl="xychart",x_=t=>/^\s*xychart-beta/.test(t),b_=async()=>{const{diagram:t}=await X(()=>import("./xychartDiagram-f11f50a6-D1hL1lgg.js"),__vite__mapDeps([27,11,21,25,20,12,13,14,2]));return{id:Bl,diagram:t}},T_={id:Bl,detector:x_,loader:b_},v_=T_,Al="requirement",k_=t=>/^\s*requirement(Diagram)?/.test(t),S_=async()=>{const{diagram:t}=await X(()=>import("./requirementDiagram-87253d64-CetQ2-l9.js"),__vite__mapDeps([28,5,6,12,13,14,2]));return{id:Al,diagram:t}},w_={id:Al,detector:k_,loader:S_},B_=w_,Ll="sequence",A_=t=>/^\s*sequenceDiagram/.test(t),L_=async()=>{const{diagram:t}=await X(()=>import("./sequenceDiagram-6894f283-CpWWhZ69.js"),__vite__mapDeps([29,1,2]));return{id:Ll,diagram:t}},F_={id:Ll,detector:A_,loader:L_},E_=F_,Fl="class",O_=(t,e)=>{var i;return((i=e==null?void 0:e.class)==null?void 0:i.defaultRenderer)==="dagre-wrapper"?!1:/^\s*classDiagram/.test(t)},M_=async()=>{const{diagram:t}=await X(()=>import("./classDiagram-fb54d2a0-CnVcQW-t.js"),__vite__mapDeps([30,31,5,6,12,13,14,2]));return{id:Fl,diagram:t}},I_={id:Fl,detector:O_,loader:M_},$_=I_,El="classDiagram",D_=(t,e)=>{var i;return/^\s*classDiagram/.test(t)&&((i=e==null?void 0:e.class)==null?void 0:i.defaultRenderer)==="dagre-wrapper"?!0:/^\s*classDiagram-v2/.test(t)},N_=async()=>{const{diagram:t}=await X(()=>import("./classDiagram-v2-a2b738ad-D4iAgbOW.js"),__vite__mapDeps([32,31,5,8,6,9,10,11,12,13,14,2]));return{id:El,diagram:t}},R_={id:El,detector:D_,loader:N_},P_=R_,Ol="state",q_=(t,e)=>{var i;return((i=e==null?void 0:e.state)==null?void 0:i.defaultRenderer)==="dagre-wrapper"?!1:/^\s*stateDiagram/.test(t)},z_=async()=>{const{diagram:t}=await X(()=>import("./stateDiagram-5dee940d-RM57nRSF.js"),__vite__mapDeps([33,34,5,6,12,13,14,2]));return{id:Ol,diagram:t}},W_={id:Ol,detector:q_,loader:z_},H_=W_,Ml="stateDiagram",j_=(t,e)=>{var i;return!!(/^\s*stateDiagram-v2/.test(t)||/^\s*stateDiagram/.test(t)&&((i=e==null?void 0:e.state)==null?void 0:i.defaultRenderer)==="dagre-wrapper")},U_=async()=>{const{diagram:t}=await X(()=>import("./stateDiagram-v2-1992cada-DbY1jnSh.js"),__vite__mapDeps([35,34,5,8,6,9,10,11,12,13,14,2]));return{id:Ml,diagram:t}},Y_={id:Ml,detector:j_,loader:U_},V_=Y_,Il="journey",G_=t=>/^\s*journey/.test(t),X_=async()=>{const{diagram:t}=await X(()=>import("./journeyDiagram-6625b456-Bh6Njlro.js"),__vite__mapDeps([36,1,24,14,2]));return{id:Il,diagram:t}},K_={id:Il,detector:G_,loader:X_},Z_=K_,J_=function(t,e){for(let i of e)t.attr(i[0],i[1])},Q_=function(t,e,i){let r=new Map;return i?(r.set("width","100%"),r.set("style",`max-width: ${e}px;`)):(r.set("height",t),r.set("width",e)),r},$l=function(t,e,i,r){const n=Q_(e,i,r);J_(t,n)},ty=function(t,e,i,r){const n=e.node().getBBox(),o=n.width,s=n.height;O.info(`SVG bounds: ${o}x${s}`,n);let a=0,l=0;O.info(`Graph bounds: ${a}x${l}`,t),a=o+i*2,l=s+i*2,O.info(`Calculated bounds: ${a}x${l}`),$l(e,l,a,r);const h=`${n.x-i} ${n.y-i} ${n.width+2*i} ${n.height+2*i}`;e.attr("viewBox",h)},Ui={},ey=(t,e,i)=>{let r="";return t in Ui&&Ui[t]?r=Ui[t](i):O.warn(`No theme found for ${t}`),` & { font-family: ${i.fontFamily}; font-size: ${i.fontSize}; fill: ${i.textColor} @@ -61,7 +61,7 @@ import{q as X}from"./app-5SoadDYS.js";function _h(t){for(var e=[],i=1;i{e!==void 0&&(Ui[t]=e)},ry=ey;let Vn="",Gn="",Xn="";const Kn=t=>mi(t,Pt()),ny=()=>{Vn="",Xn="",Gn=""},oy=t=>{Vn=Kn(t).replace(/^\s+/g,"")},sy=()=>Vn,ay=t=>{Xn=Kn(t).replace(/\n\s+/g,` `)},ly=()=>Xn,hy=t=>{Gn=Kn(t)},cy=()=>Gn,uy=Object.freeze(Object.defineProperty({__proto__:null,clear:ny,getAccDescription:ly,getAccTitle:sy,getDiagramTitle:cy,setAccDescription:ay,setAccTitle:oy,setDiagramTitle:hy},Symbol.toStringTag,{value:"Module"})),fy=O,dy=Wn,Zn=Pt,Nb=gl,Rb=Ne,py=t=>mi(t,Zn()),gy=ty,my=()=>uy,lr={},hr=(t,e,i)=>{var r;if(lr[t])throw new Error(`Diagram ${t} already registered.`);lr[t]=e,i&&ll(t,i),iy(t,e.styles),(r=e.injectUtils)==null||r.call(e,fy,dy,Zn,py,gy,my(),()=>{})},Jn=t=>{if(t in lr)return lr[t];throw new _y(t)};class _y extends Error{constructor(e){super(`Diagram ${e} not found.`)}}const yy=t=>{var e;const{securityLevel:i}=Zn();let r=Tt("body");if(i==="sandbox"){const s=((e=Tt(`#i${t}`).node())==null?void 0:e.contentDocument)??document;r=Tt(s.body)}return r.select(`#${t}`)},Cy=(t,e,i)=>{O.debug(`rendering svg for syntax error -`);const r=yy(e),n=r.append("g");r.attr("viewBox","0 0 2412 512"),$l(r,100,512,!0),n.append("path").attr("class","error-icon").attr("d","m411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z"),n.append("path").attr("class","error-icon").attr("d","m459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z"),n.append("path").attr("class","error-icon").attr("d","m340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z"),n.append("path").attr("class","error-icon").attr("d","m400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z"),n.append("path").attr("class","error-icon").attr("d","m496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z"),n.append("path").attr("class","error-icon").attr("d","m436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z"),n.append("text").attr("class","error-text").attr("x",1440).attr("y",250).attr("font-size","150px").style("text-anchor","middle").text("Syntax error in text"),n.append("text").attr("class","error-text").attr("x",1250).attr("y",400).attr("font-size","100px").style("text-anchor","middle").text(`mermaid version ${i}`)},Dl={draw:Cy},xy=Dl,by={db:{},renderer:Dl,parser:{parser:{yy:{}},parse:()=>{}}},Ty=by,Nl="flowchart-elk",vy=(t,e)=>{var i;return!!(/^\s*flowchart-elk/.test(t)||/^\s*flowchart|graph/.test(t)&&((i=e==null?void 0:e.flowchart)==null?void 0:i.defaultRenderer)==="elk")},ky=async()=>{const{diagram:t}=await X(()=>import("./flowchart-elk-definition-ae0efee6-Df6_ziIo.js"),__vite__mapDeps([37,4,10,11,12,13,14,2]));return{id:Nl,diagram:t}},Sy={id:Nl,detector:vy,loader:ky},wy=Sy,Rl="timeline",By=t=>/^\s*timeline/.test(t),Ay=async()=>{const{diagram:t}=await X(()=>import("./timeline-definition-bf702344-D6E2CBeX.js"),__vite__mapDeps([38,24,14,2]));return{id:Rl,diagram:t}},Ly={id:Rl,detector:By,loader:Ay},Fy=Ly,Pl="mindmap",Ey=t=>/^\s*mindmap/.test(t),Oy=async()=>{const{diagram:t}=await X(()=>import("./mindmap-definition-307c710a-C9Lm6G_A.js"),__vite__mapDeps([39,11,2]));return{id:Pl,diagram:t}},My={id:Pl,detector:Ey,loader:Oy},Iy=My,ql="sankey",$y=t=>/^\s*sankey-beta/.test(t),Dy=async()=>{const{diagram:t}=await X(()=>import("./sankeyDiagram-707fac0f-CYIZhz1m.js"),__vite__mapDeps([40,25,21,41,2]));return{id:ql,diagram:t}},Ny={id:ql,detector:$y,loader:Dy},Ry=Ny,zl="block",Py=t=>/^\s*block-beta/.test(t),qy=async()=>{const{diagram:t}=await X(()=>import("./blockDiagram-9f4a6865-QPsisUYk.js"),__vite__mapDeps([42,9,5,10,11,12,13,14,25,21,15,41,2]));return{id:zl,diagram:t}},zy={id:zl,detector:Py,loader:qy},Wy=zy;let Ls=!1;const Qn=()=>{Ls||(Ls=!0,hr("error",Ty,t=>t.toLowerCase().trim()==="error"),hr("---",{db:{clear:()=>{}},styles:{},renderer:{draw:()=>{}},parser:{parser:{yy:{}},parse:()=>{throw new Error("Diagrams beginning with --- are not valid. If you were trying to use a YAML front-matter, please ensure that you've correctly opened and closed the YAML front-matter with un-indented `---` blocks")}},init:()=>null},t=>t.toLowerCase().trimStart().startsWith("---")),al(H0,P_,$_,e_,h_,f_,g_,B_,E_,wy,Z0,V0,Iy,Fy,o_,V_,H_,Z_,C_,Ry,v_,Wy))};class Wl{constructor(e,i={}){this.text=e,this.metadata=i,this.type="graph",this.text=O0(e),this.text+=` +`);const r=yy(e),n=r.append("g");r.attr("viewBox","0 0 2412 512"),$l(r,100,512,!0),n.append("path").attr("class","error-icon").attr("d","m411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z"),n.append("path").attr("class","error-icon").attr("d","m459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z"),n.append("path").attr("class","error-icon").attr("d","m340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z"),n.append("path").attr("class","error-icon").attr("d","m400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z"),n.append("path").attr("class","error-icon").attr("d","m496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z"),n.append("path").attr("class","error-icon").attr("d","m436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z"),n.append("text").attr("class","error-text").attr("x",1440).attr("y",250).attr("font-size","150px").style("text-anchor","middle").text("Syntax error in text"),n.append("text").attr("class","error-text").attr("x",1250).attr("y",400).attr("font-size","100px").style("text-anchor","middle").text(`mermaid version ${i}`)},Dl={draw:Cy},xy=Dl,by={db:{},renderer:Dl,parser:{parser:{yy:{}},parse:()=>{}}},Ty=by,Nl="flowchart-elk",vy=(t,e)=>{var i;return!!(/^\s*flowchart-elk/.test(t)||/^\s*flowchart|graph/.test(t)&&((i=e==null?void 0:e.flowchart)==null?void 0:i.defaultRenderer)==="elk")},ky=async()=>{const{diagram:t}=await X(()=>import("./flowchart-elk-definition-ae0efee6-H9NB2Lq2.js"),__vite__mapDeps([37,4,10,11,12,13,14,2]));return{id:Nl,diagram:t}},Sy={id:Nl,detector:vy,loader:ky},wy=Sy,Rl="timeline",By=t=>/^\s*timeline/.test(t),Ay=async()=>{const{diagram:t}=await X(()=>import("./timeline-definition-bf702344-B4DJzmYO.js"),__vite__mapDeps([38,24,14,2]));return{id:Rl,diagram:t}},Ly={id:Rl,detector:By,loader:Ay},Fy=Ly,Pl="mindmap",Ey=t=>/^\s*mindmap/.test(t),Oy=async()=>{const{diagram:t}=await X(()=>import("./mindmap-definition-307c710a-DRTTE_TY.js"),__vite__mapDeps([39,11,2]));return{id:Pl,diagram:t}},My={id:Pl,detector:Ey,loader:Oy},Iy=My,ql="sankey",$y=t=>/^\s*sankey-beta/.test(t),Dy=async()=>{const{diagram:t}=await X(()=>import("./sankeyDiagram-707fac0f-Dqx64UnQ.js"),__vite__mapDeps([40,25,21,41,2]));return{id:ql,diagram:t}},Ny={id:ql,detector:$y,loader:Dy},Ry=Ny,zl="block",Py=t=>/^\s*block-beta/.test(t),qy=async()=>{const{diagram:t}=await X(()=>import("./blockDiagram-9f4a6865-BqKpDrqb.js"),__vite__mapDeps([42,9,5,10,11,12,13,14,25,21,15,41,2]));return{id:zl,diagram:t}},zy={id:zl,detector:Py,loader:qy},Wy=zy;let Ls=!1;const Qn=()=>{Ls||(Ls=!0,hr("error",Ty,t=>t.toLowerCase().trim()==="error"),hr("---",{db:{clear:()=>{}},styles:{},renderer:{draw:()=>{}},parser:{parser:{yy:{}},parse:()=>{throw new Error("Diagrams beginning with --- are not valid. If you were trying to use a YAML front-matter, please ensure that you've correctly opened and closed the YAML front-matter with un-indented `---` blocks")}},init:()=>null},t=>t.toLowerCase().trimStart().startsWith("---")),al(H0,P_,$_,e_,h_,f_,g_,B_,E_,wy,Z0,V0,Iy,Fy,o_,V_,H_,Z_,C_,Ry,v_,Wy))};class Wl{constructor(e,i={}){this.text=e,this.metadata=i,this.type="graph",this.text=O0(e),this.text+=` `;const r=Pt();try{this.type=Lr(e,r)}catch(o){this.type="error",this.detectError=o}const n=Jn(this.type);O.debug("Type "+this.type),this.db=n.db,this.renderer=n.renderer,this.parser=n.parser,this.parser.parser.yy=this.db,this.init=n.init,this.parse()}parse(){var e,i,r,n,o;if(this.detectError)throw this.detectError;(i=(e=this.db).clear)==null||i.call(e);const s=Pt();(r=this.init)==null||r.call(this,s),this.metadata.title&&((o=(n=this.db).setDiagramTitle)==null||o.call(n,this.metadata.title)),this.parser.parse(this.text)}async render(e,i){await this.renderer.draw(this.text,e,i,this)}getParser(){return this.parser}getType(){return this.type}}const Hy=async(t,e={})=>{const i=Lr(t,Pt());try{Jn(i)}catch{const n=s0(i);if(!n)throw new sl(`Diagram ${i} not found.`);const{id:o,diagram:s}=await n();hr(o,s)}return new Wl(t,e)};let Fs=[];const jy=()=>{Fs.forEach(t=>{t()}),Fs=[]},Uy="graphics-document document";function Yy(t,e){t.attr("role",Uy),e!==""&&t.attr("aria-roledescription",e)}function Vy(t,e,i,r){if(t.insert!==void 0){if(i){const n=`chart-desc-${r}`;t.attr("aria-describedby",n),t.insert("desc",":first-child").attr("id",n).text(i)}if(e){const n=`chart-title-${r}`;t.attr("aria-labelledby",n),t.insert("title",":first-child").attr("id",n).text(e)}}}const Gy=t=>t.replace(/^\s*%%(?!{)[^\n]+\n?/gm,"").trimStart();/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */function Hl(t){return typeof t>"u"||t===null}function Xy(t){return typeof t=="object"&&t!==null}function Ky(t){return Array.isArray(t)?t:Hl(t)?[]:[t]}function Zy(t,e){var i,r,n,o;if(e)for(o=Object.keys(e),i=0,r=o.length;ia&&(o=" ... ",e=r-a+o.length),i-r>a&&(s=" ...",i=r+a-s.length),{str:o+t.slice(e,i).replace(/\t/g,"→")+s,pos:r-e+o.length}}function Jr(t,e){return ut.repeat(" ",e-t.length)+t}function sC(t,e){if(e=Object.create(e||null),!t.buffer)return null;e.maxLength||(e.maxLength=79),typeof e.indent!="number"&&(e.indent=1),typeof e.linesBefore!="number"&&(e.linesBefore=3),typeof e.linesAfter!="number"&&(e.linesAfter=2);for(var i=/\r?\n|\r|\0/g,r=[0],n=[],o,s=-1;o=i.exec(t.buffer);)n.push(o.index),r.push(o.index+o[0].length),t.position<=o.index&&s<0&&(s=r.length-2);s<0&&(s=r.length-1);var a="",l,h,u=Math.min(t.line+e.linesAfter,n.length).toString().length,f=e.maxLength-(e.indent+u+3);for(l=1;l<=e.linesBefore&&!(s-l<0);l++)h=Zr(t.buffer,r[s-l],n[s-l],t.position-(r[s]-r[s-l]),f),a=ut.repeat(" ",e.indent)+Jr((t.line-l+1).toString(),u)+" | "+h.str+` @@ -90,7 +90,7 @@ ${t.themeCSS}`),t.fontFamily!==void 0&&(r+=` */window.addEventListener("load",sh,!1)}const _b=function(t){Lt.parseError=t},dr=[];let tn=!1;const ah=async()=>{if(!tn){for(tn=!0;dr.length>0;){const t=dr.shift();if(t)try{await t()}catch(e){O.error("Error executing queue",e)}}tn=!1}},yb=async(t,e)=>new Promise((i,r)=>{const n=()=>new Promise((o,s)=>{ye.parse(t,e).then(a=>{o(a),i(a)},a=>{var l;O.error("Error parsing",a),(l=Lt.parseError)==null||l.call(Lt,a),s(a),r(a)})});dr.push(n),ah().catch(r)}),lh=(t,e,i)=>new Promise((r,n)=>{const o=()=>new Promise((s,a)=>{ye.render(t,e,i).then(l=>{s(l),r(l)},l=>{var h;O.error("Error parsing",l),(h=Lt.parseError)==null||h.call(Lt,l),a(l),n(l)})});dr.push(o),ah().catch(n)}),Lt={startOnLoad:!0,mermaidAPI:ye,parse:yb,render:lh,init:gb,run:nh,registerExternalDiagrams:mb,initialize:oh,parseError:void 0,contentLoaded:sh,setParseErrorHandler:_b,detectType:Lr},Pb=Object.freeze(Object.defineProperty({__proto__:null,default:Lt},Symbol.toStringTag,{value:"Module"}));export{as as $,ny as A,Ti as B,qe as C,nr as D,kr as E,Ng as F,Tm as G,bi as H,rr as I,Eg as J,Ua as K,Ra as L,$p as M,Dp as N,ce as O,fs as P,wg as Q,Ce as R,er as S,Np as T,Rn as U,Ip as V,qp as W,ze as X,Fg as Y,le as Z,xr as _,ly as a,Pt as a$,Pn as a0,qa as a1,ja as a2,Va as a3,Op as a4,yn as a5,Qg as a6,Up as a7,Yg as a8,Dn as a9,xb as aA,yh as aB,Ch as aC,bh as aD,Bn as aE,ne as aF,ci as aG,Do as aH,Cu as aI,yy as aJ,Ab as aK,r0 as aL,fl as aM,Yn as aN,En as aO,vb as aP,wb as aQ,Ho as aR,Wo as aS,Bb as aT,Sb as aU,bb as aV,Tb as aW,Fb as aX,Lb as aY,kb as aZ,Zm as a_,Kr as aa,yt as ab,ea as ac,Lh as ad,tg as ae,ri as af,Jg as ag,Ug as ah,tm as ai,Nn as aj,im as ak,$ as al,Rt as am,M0 as an,qf as ao,_h as ap,Nb as aq,Eb as ar,gy as as,v0 as at,wn as au,ia as av,mt as aw,Ci as ax,fu as ay,oa as az,ay as b,ks as b0,Ob as b1,a0 as b2,b0 as b3,uy as b4,xi as b5,L as b6,M as b7,Pb as b8,Zn as c,mi as d,st as e,sr as f,sy as g,Tt as h,$l as i,Hn as j,A0 as k,O as l,Ws as m,vi as n,Nf as o,x0 as p,il as q,Um as r,oy as s,d0 as t,ty as u,Rb as v,w0 as w,hy as x,cy as y,si as z}; function __vite__mapDeps(indexes) { if (!__vite__mapDeps.viteFileDeps) { - __vite__mapDeps.viteFileDeps = ["assets/c4Diagram-ae766693-TOZe-7Pl.js","assets/svgDrawCommon-5e1cfd1d-BWP2bQZS.js","assets/app-5SoadDYS.js","assets/flowDiagram-b222e15a-ClSO8xjE.js","assets/flowDb-c1833063-8FVnhkY0.js","assets/graph-D2qW7eTj.js","assets/layout-BlaWeSu5.js","assets/styles-483fbfea-B2onFAKT.js","assets/index-01f381cb-fgk8rzsW.js","assets/clone-D0wOyyCk.js","assets/edges-066a5561-BnmFWp88.js","assets/createText-ca0c5216-X7RVUogw.js","assets/line-BIqtvXUi.js","assets/array-BKyUJesY.js","assets/path-CbwjOpE9.js","assets/channel-C_7gBDjR.js","assets/flowDiagram-v2-13329dc7-CD3itvv-.js","assets/erDiagram-09d1c15f-DTI3Ywn0.js","assets/gitGraphDiagram-942e62fe-DOX28HzV.js","assets/ganttDiagram-b62c793e-B3546ou_.js","assets/linear-DFdMY4Xo.js","assets/init-Gi6I4Gst.js","assets/infoDiagram-94cd232f-I6ioXWcf.js","assets/pieDiagram-bb1d19e5-BQuVNcMJ.js","assets/arc-xLaeEKkr.js","assets/ordinal-Cboi1Yqb.js","assets/quadrantDiagram-c759a472-B16G3h9g.js","assets/xychartDiagram-f11f50a6-BfE2Gore.js","assets/requirementDiagram-87253d64-K4iL_vop.js","assets/sequenceDiagram-6894f283-BOatradp.js","assets/classDiagram-fb54d2a0-C9zXAHzr.js","assets/styles-b83b31c9-BypRRRwZ.js","assets/classDiagram-v2-a2b738ad-ChHu4we1.js","assets/stateDiagram-5dee940d-BYrroPY3.js","assets/styles-0784dbeb-C3hL6HKk.js","assets/stateDiagram-v2-1992cada-BZne08Mr.js","assets/journeyDiagram-6625b456-CHnHUPp6.js","assets/flowchart-elk-definition-ae0efee6-Df6_ziIo.js","assets/timeline-definition-bf702344-D6E2CBeX.js","assets/mindmap-definition-307c710a-C9Lm6G_A.js","assets/sankeyDiagram-707fac0f-CYIZhz1m.js","assets/Tableau10-B-NsZVaP.js","assets/blockDiagram-9f4a6865-QPsisUYk.js"] + __vite__mapDeps.viteFileDeps = ["assets/c4Diagram-ae766693-DVn8Dofm.js","assets/svgDrawCommon-5e1cfd1d-CX_gVtbt.js","assets/app-Bw2NG-QJ.js","assets/flowDiagram-b222e15a-CRKbP293.js","assets/flowDb-c1833063-Csuwz1ip.js","assets/graph-C-EgwjAv.js","assets/layout-DSxgfneE.js","assets/styles-483fbfea-BRNgjsWa.js","assets/index-01f381cb-DWGV-_zg.js","assets/clone-BjoOJyl6.js","assets/edges-066a5561-CIBMFaLO.js","assets/createText-ca0c5216-xyt9uAlz.js","assets/line-DY_oMjHu.js","assets/array-BKyUJesY.js","assets/path-CbwjOpE9.js","assets/channel-DIeeoF-2.js","assets/flowDiagram-v2-13329dc7-CUX8GDMK.js","assets/erDiagram-09d1c15f-CxugSXM3.js","assets/gitGraphDiagram-942e62fe-CmfeKiv3.js","assets/ganttDiagram-b62c793e-BY6nXXtR.js","assets/linear-CopLvHML.js","assets/init-Gi6I4Gst.js","assets/infoDiagram-94cd232f-Don6DG4Z.js","assets/pieDiagram-bb1d19e5-CBxnSt2_.js","assets/arc-C5d-KvsZ.js","assets/ordinal-Cboi1Yqb.js","assets/quadrantDiagram-c759a472-DYqUNjWH.js","assets/xychartDiagram-f11f50a6-D1hL1lgg.js","assets/requirementDiagram-87253d64-CetQ2-l9.js","assets/sequenceDiagram-6894f283-CpWWhZ69.js","assets/classDiagram-fb54d2a0-CnVcQW-t.js","assets/styles-b83b31c9-BItTogIC.js","assets/classDiagram-v2-a2b738ad-D4iAgbOW.js","assets/stateDiagram-5dee940d-RM57nRSF.js","assets/styles-0784dbeb-38-7TehO.js","assets/stateDiagram-v2-1992cada-DbY1jnSh.js","assets/journeyDiagram-6625b456-Bh6Njlro.js","assets/flowchart-elk-definition-ae0efee6-H9NB2Lq2.js","assets/timeline-definition-bf702344-B4DJzmYO.js","assets/mindmap-definition-307c710a-DRTTE_TY.js","assets/sankeyDiagram-707fac0f-Dqx64UnQ.js","assets/Tableau10-B-NsZVaP.js","assets/blockDiagram-9f4a6865-BqKpDrqb.js"] } return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]) } diff --git a/assets/metrics.html-DAUbFlMB.js b/assets/metrics.html-Bg3SRRpG.js similarity index 99% rename from assets/metrics.html-DAUbFlMB.js rename to assets/metrics.html-Bg3SRRpG.js index e5ce7ad98c..2c3ed1ad2b 100644 --- a/assets/metrics.html-DAUbFlMB.js +++ b/assets/metrics.html-Bg3SRRpG.js @@ -1,4 +1,4 @@ -import{_ as i,r as p,o as l,c as u,a,b as s,d as n,e}from"./app-5SoadDYS.js";const r={},c=e(`

                                        Metrics

                                        更直接(希望更好)的统计导出方式。

                                        相关配置

                                        可以在 inbounds 配置中增加一个 metrics 的 inbound

                                            "inbounds": [
                                        +import{_ as i,r as p,o as l,c as u,a,b as s,d as n,e}from"./app-Bw2NG-QJ.js";const r={},c=e(`

                                        Metrics

                                        更直接(希望更好)的统计导出方式。

                                        相关配置

                                        可以在 inbounds 配置中增加一个 metrics 的 inbound

                                            "inbounds": [
                                                 {
                                                     "listen": "127.0.0.1",
                                                     "port": 11111,
                                        diff --git a/assets/metrics.html-DtVeDNWQ.js b/assets/metrics.html-BhYJwMrZ.js
                                        similarity index 99%
                                        rename from assets/metrics.html-DtVeDNWQ.js
                                        rename to assets/metrics.html-BhYJwMrZ.js
                                        index d6fd23c03b..6b92a6e120 100644
                                        --- a/assets/metrics.html-DtVeDNWQ.js
                                        +++ b/assets/metrics.html-BhYJwMrZ.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as l,c as u,a,b as s,d as n,e}from"./app-5SoadDYS.js";const r={},c=e(`

                                        Metrics

                                        A more straightforward (and hopefully better) way to export metrics.

                                        It's possible to add a metrics inbound among inbounds.

                                            "inbounds": [
                                        +import{_ as i,r as p,o as l,c as u,a,b as s,d as n,e}from"./app-Bw2NG-QJ.js";const r={},c=e(`

                                        Metrics

                                        A more straightforward (and hopefully better) way to export metrics.

                                        It's possible to add a metrics inbound among inbounds.

                                            "inbounds": [
                                                 {
                                                     "listen": "127.0.0.1",
                                                     "port": 11111,
                                        diff --git a/assets/metrics.html-DZDkDmh2.js b/assets/metrics.html-Cd9LVZWS.js
                                        similarity index 99%
                                        rename from assets/metrics.html-DZDkDmh2.js
                                        rename to assets/metrics.html-Cd9LVZWS.js
                                        index 98604a2025..a87629da5d 100644
                                        --- a/assets/metrics.html-DZDkDmh2.js
                                        +++ b/assets/metrics.html-Cd9LVZWS.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as l,c as u,a,b as s,d as n,e}from"./app-5SoadDYS.js";const r={},c=e(`

                                        Метрики

                                        Более простой (и, надеюсь, лучший) способ экспорта статистики.

                                        Связанные настройки

                                        Можно добавить входящее подключение metrics в раздел inbounds:

                                            "inbounds": [
                                        +import{_ as i,r as p,o as l,c as u,a,b as s,d as n,e}from"./app-Bw2NG-QJ.js";const r={},c=e(`

                                        Метрики

                                        Более простой (и, надеюсь, лучший) способ экспорта статистики.

                                        Связанные настройки

                                        Можно добавить входящее подключение metrics в раздел inbounds:

                                            "inbounds": [
                                                 {
                                                     "listen": "127.0.0.1",
                                                     "port": 11111,
                                        diff --git a/assets/mindmap-definition-307c710a-C9Lm6G_A.js b/assets/mindmap-definition-307c710a-DRTTE_TY.js
                                        similarity index 99%
                                        rename from assets/mindmap-definition-307c710a-C9Lm6G_A.js
                                        rename to assets/mindmap-definition-307c710a-DRTTE_TY.js
                                        index 5fe94528c4..1b04a7f1b9 100644
                                        --- a/assets/mindmap-definition-307c710a-C9Lm6G_A.js
                                        +++ b/assets/mindmap-definition-307c710a-DRTTE_TY.js
                                        @@ -1,4 +1,4 @@
                                        -import{aB as hi,aC as tl,l as Er,c as ci,aJ as rl,u as al,aL as ja,d as en,h as nl,b5 as il,b6 as sl,b7 as ol,aN as ul}from"./mermaid.core-CArNAncI.js";import{c as ll}from"./createText-ca0c5216-X7RVUogw.js";import"./app-5SoadDYS.js";function Xe(t){"@babel/helpers - typeof";return Xe=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Xe(t)}function vi(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function fl(t,e){for(var r=0;rt.length)&&(e=t.length);for(var r=0,a=new Array(e);rt.length)&&(e=t.length);for(var r=0,a=new Array(e);r=t.length?{done:!0}:{done:!1,value:t[a++]}},e:function(u){throw u},f:n}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.
                                         In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i=!0,s=!1,o;return{s:function(){r=r.call(t)},n:function(){var u=r.next();return i=u.done,u},e:function(u){s=!0,o=u},f:function(){try{!i&&r.return!=null&&r.return()}finally{if(s)throw o}}}}var Ye=typeof window>"u"?null:window,Yi=Ye?Ye.navigator:null;Ye&&Ye.document;var gl=Xe(""),io=Xe({}),pl=Xe(function(){}),yl=typeof HTMLElement>"u"?"undefined":Xe(HTMLElement),xa=function(e){return e&&e.instanceString&&Ge(e.instanceString)?e.instanceString():null},ve=function(e){return e!=null&&Xe(e)==gl},Ge=function(e){return e!=null&&Xe(e)===pl},Re=function(e){return!pt(e)&&(Array.isArray?Array.isArray(e):e!=null&&e instanceof Array)},Ce=function(e){return e!=null&&Xe(e)===io&&!Re(e)&&e.constructor===Object},ml=function(e){return e!=null&&Xe(e)===io},ne=function(e){return e!=null&&Xe(e)===Xe(1)&&!isNaN(e)},bl=function(e){return ne(e)&&Math.floor(e)===e},tn=function(e){if(yl!=="undefined")return e!=null&&e instanceof HTMLElement},pt=function(e){return Ta(e)||so(e)},Ta=function(e){return xa(e)==="collection"&&e._private.single},so=function(e){return xa(e)==="collection"&&!e._private.single},gi=function(e){return xa(e)==="core"},oo=function(e){return xa(e)==="stylesheet"},El=function(e){return xa(e)==="event"},jt=function(e){return e==null?!0:!!(e===""||e.match(/^\s+$/))},wl=function(e){return typeof HTMLElement>"u"?!1:e instanceof HTMLElement},xl=function(e){return Ce(e)&&ne(e.x1)&&ne(e.x2)&&ne(e.y1)&&ne(e.y2)},Tl=function(e){return ml(e)&&Ge(e.then)},Cl=function(){return Yi&&Yi.userAgent.match(/msie|trident|edge/i)},ha=function(e,r){r||(r=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return"undefined";for(var i=[],s=0;sr?1:0},Il=function(e,r){return-1*lo(e,r)},be=Object.assign!=null?Object.assign.bind(Object):function(t){for(var e=arguments,r=1;r1&&(g-=1),g<1/6?v+(p-v)*6*g:g<1/2?p:g<2/3?v+(p-v)*(2/3-g)*6:v}var h=new RegExp("^"+Ll+"$").exec(e);if(h){if(a=parseInt(h[1]),a<0?a=(360- -1*a%360)%360:a>360&&(a=a%360),a/=360,n=parseFloat(h[2]),n<0||n>100||(n=n/100,i=parseFloat(h[3]),i<0||i>100)||(i=i/100,s=h[4],s!==void 0&&(s=parseFloat(s),s<0||s>1)))return;if(n===0)o=u=l=Math.round(i*255);else{var d=i<.5?i*(1+n):i+n-i*n,c=2*i-d;o=Math.round(255*f(c,d,a+1/3)),u=Math.round(255*f(c,d,a)),l=Math.round(255*f(c,d,a-1/3))}r=[o,u,l,s]}return r},kl=function(e){var r,a=new RegExp("^"+Dl+"$").exec(e);if(a){r=[];for(var n=[],i=1;i<=3;i++){var s=a[i];if(s[s.length-1]==="%"&&(n[i]=!0),s=parseFloat(s),n[i]&&(s=s/100*255),s<0||s>255)return;r.push(Math.floor(s))}var o=n[1]||n[2]||n[3],u=n[1]&&n[2]&&n[3];if(o&&!u)return;var l=a[4];if(l!==void 0){if(l=parseFloat(l),l<0||l>1)return;r.push(l)}}return r},Pl=function(e){return Fl[e.toLowerCase()]},Bl=function(e){return(Re(e)?e:null)||Pl(e)||Ml(e)||kl(e)||Rl(e)},Fl={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},fo=function(e){for(var r=e.map,a=e.keys,n=a.length,i=0;i=e||E<0||h&&x>=i}function y(){var S=Rn();if(g(S))return b(S);o=setTimeout(y,p(S))}function b(S){return o=void 0,d&&a?c(S):(a=n=void 0,s)}function m(){o!==void 0&&clearTimeout(o),l=0,a=u=n=o=void 0}function T(){return o===void 0?s:b(Rn())}function C(){var S=Rn(),E=g(S);if(a=arguments,n=this,u=S,E){if(o===void 0)return v(u);if(h)return clearTimeout(o),o=setTimeout(y,e),c(u)}return o===void 0&&(o=setTimeout(y,e)),s}return C.cancel=m,C.flush=T,C}var gn=xf,kn=Ye?Ye.performance:null,go=kn&&kn.now?function(){return kn.now()}:function(){return Date.now()},Tf=function(){if(Ye){if(Ye.requestAnimationFrame)return function(t){Ye.requestAnimationFrame(t)};if(Ye.mozRequestAnimationFrame)return function(t){Ye.mozRequestAnimationFrame(t)};if(Ye.webkitRequestAnimationFrame)return function(t){Ye.webkitRequestAnimationFrame(t)};if(Ye.msRequestAnimationFrame)return function(t){Ye.msRequestAnimationFrame(t)}}return function(t){t&&setTimeout(function(){t(go())},1e3/60)}}(),rn=function(e){return Tf(e)},$t=go,Nr=9261,po=65599,ia=5381,yo=function(e){for(var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Nr,a=r,n;n=e.next(),!n.done;)a=a*po+n.value|0;return a},ca=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Nr;return r*po+e|0},va=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:ia;return(r<<5)+r+e|0},Cf=function(e,r){return e*2097152+r},qt=function(e){return e[0]*2097152+e[1]},Ma=function(e,r){return[ca(e[0],r[0]),va(e[1],r[1])]},Df=function(e,r){var a={value:0,done:!1},n=0,i=e.length,s={next:function(){return n=0;n--)e[n]===r&&e.splice(n,1)},bi=function(e){e.splice(0,e.length)},Mf=function(e,r){for(var a=0;a"u"?"undefined":Xe(Set))!==kf?Set:Pf,pn=function(e,r){var a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0;if(e===void 0||r===void 0||!gi(e)){ze("An element must have a core reference and parameters set");return}var n=r.group;if(n==null&&(r.data&&r.data.source!=null&&r.data.target!=null?n="edges":n="nodes"),n!=="nodes"&&n!=="edges"){ze("An element must be of type `nodes` or `edges`; you specified `"+n+"`");return}this.length=1,this[0]=this;var i=this._private={cy:e,single:!0,data:r.data||{},position:r.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:n,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!r.selected,selectable:r.selectable===void 0?!0:!!r.selectable,locked:!!r.locked,grabbed:!1,grabbable:r.grabbable===void 0?!0:!!r.grabbable,pannable:r.pannable===void 0?n==="edges":!!r.pannable,active:!1,classes:new Ur,animation:{current:[],queue:[]},rscratch:{},scratch:r.scratch||{},edges:[],children:[],parent:r.parent&&r.parent.isNode()?r.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(i.position.x==null&&(i.position.x=0),i.position.y==null&&(i.position.y=0),r.renderedPosition){var s=r.renderedPosition,o=e.pan(),u=e.zoom();i.position={x:(s.x-o.x)/u,y:(s.y-o.y)/u}}var l=[];Re(r.classes)?l=r.classes:ve(r.classes)&&(l=r.classes.split(/\s+/));for(var f=0,h=l.length;fb?1:0},f=function(y,b,m,T,C){var S;if(m==null&&(m=0),C==null&&(C=a),m<0)throw new Error("lo must be non-negative");for(T==null&&(T=y.length);mD;0<=D?w++:w--)x.push(w);return x}).apply(this).reverse(),E=[],T=0,C=S.length;TL;0<=L?++x:--x)A.push(s(y,m));return A},p=function(y,b,m,T){var C,S,E;for(T==null&&(T=a),C=y[m];m>b;){if(E=m-1>>1,S=y[E],T(C,S)<0){y[m]=S,m=E;continue}break}return y[m]=C},g=function(y,b,m){var T,C,S,E,x;for(m==null&&(m=a),C=y.length,x=b,S=y[b],T=2*b+1;T0;){var S=b.pop(),E=g(S),x=S.id();if(d[x]=E,E!==1/0)for(var w=S.neighborhood().intersect(v),D=0;D0)for(P.unshift(k);h[V];){var F=h[V];P.unshift(F.edge),P.unshift(F.node),B=F.node,V=B.id()}return o.spawn(P)}}}},zf={kruskal:function(e){e=e||function(m){return 1};for(var r=this.byGroup(),a=r.nodes,n=r.edges,i=a.length,s=new Array(i),o=a,u=function(T){for(var C=0;C0;){if(C(),E++,T===f){for(var x=[],w=i,D=f,L=y[D];x.unshift(w),L!=null&&x.unshift(L),w=g[D],w!=null;)D=w.id(),L=y[D];return{found:!0,distance:h[T],path:this.spawn(x),steps:E}}c[T]=!0;for(var A=m._private.edges,I=0;IL&&(v[D]=L,b[D]=w,m[D]=C),!i){var A=w*f+x;!i&&v[A]>L&&(v[A]=L,b[A]=x,m[A]=C)}}}for(var I=0;I1&&arguments[1]!==void 0?arguments[1]:s,Ae=m(fe),xe=[],we=Ae;;){if(we==null)return r.spawn();var De=b(we),j=De.edge,N=De.pred;if(xe.unshift(we[0]),we.same(ge)&&xe.length>0)break;j!=null&&xe.unshift(j),we=N}return u.spawn(xe)},S=0;S=0;f--){var h=l[f],d=h[1],c=h[2];(r[d]===o&&r[c]===u||r[d]===u&&r[c]===o)&&l.splice(f,1)}for(var v=0;vn;){var i=Math.floor(Math.random()*r.length);r=qf(i,e,r),a--}return r},Wf={kargerStein:function(){var e=this,r=this.byGroup(),a=r.nodes,n=r.edges;n.unmergeBy(function(P){return P.isLoop()});var i=a.length,s=n.length,o=Math.ceil(Math.pow(Math.log(i)/Math.LN2,2)),u=Math.floor(i/Xf);if(i<2){ze("At least 2 nodes are required for Karger-Stein algorithm");return}for(var l=[],f=0;f1&&arguments[1]!==void 0?arguments[1]:0,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,n=1/0,i=r;i1&&arguments[1]!==void 0?arguments[1]:0,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,n=-1/0,i=r;i1&&arguments[1]!==void 0?arguments[1]:0,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,n=0,i=0,s=r;s1&&arguments[1]!==void 0?arguments[1]:0,a=arguments.length>2&&arguments[2]!==void 0?arguments[2]:e.length,n=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,s=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0;n?e=e.slice(r,a):(a0&&e.splice(0,r));for(var o=0,u=e.length-1;u>=0;u--){var l=e[u];s?isFinite(l)||(e[u]=-1/0,o++):e.splice(u,1)}i&&e.sort(function(d,c){return d-c});var f=e.length,h=Math.floor(f/2);return f%2!==0?e[h+1+o]:(e[h-1+o]+e[h+o])/2},eh=function(e){return Math.PI*e/180},Ra=function(e,r){return Math.atan2(r,e)-Math.PI/2},Ei=Math.log2||function(t){return Math.log(t)/Math.log(2)},Co=function(e){return e>0?1:e<0?-1:0},gr=function(e,r){return Math.sqrt(ur(e,r))},ur=function(e,r){var a=r.x-e.x,n=r.y-e.y;return a*a+n*n},th=function(e){for(var r=e.length,a=0,n=0;n=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(e.w!=null&&e.h!=null&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},ah=function(e){return{x1:e.x1,x2:e.x2,w:e.w,y1:e.y1,y2:e.y2,h:e.h}},nh=function(e){e.x1=1/0,e.y1=1/0,e.x2=-1/0,e.y2=-1/0,e.w=0,e.h=0},ih=function(e,r,a){return{x1:e.x1+r,x2:e.x2+r,y1:e.y1+a,y2:e.y2+a,w:e.w,h:e.h}},Do=function(e,r){e.x1=Math.min(e.x1,r.x1),e.x2=Math.max(e.x2,r.x2),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,r.y1),e.y2=Math.max(e.y2,r.y2),e.h=e.y2-e.y1},sh=function(e,r,a){e.x1=Math.min(e.x1,r),e.x2=Math.max(e.x2,r),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,a),e.y2=Math.max(e.y2,a),e.h=e.y2-e.y1},_a=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return e.x1-=r,e.x2+=r,e.y1-=r,e.y2+=r,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},Ha=function(e){var r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[0],a,n,i,s;if(r.length===1)a=n=i=s=r[0];else if(r.length===2)a=i=r[0],s=n=r[1];else if(r.length===4){var o=St(r,4);a=o[0],n=o[1],i=o[2],s=o[3]}return e.x1-=s,e.x2+=n,e.y1-=a,e.y2+=i,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},Qi=function(e,r){e.x1=r.x1,e.y1=r.y1,e.x2=r.x2,e.y2=r.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1},wi=function(e,r){return!(e.x1>r.x2||r.x1>e.x2||e.x2r.y2||r.y1>e.y2)},Gr=function(e,r,a){return e.x1<=r&&r<=e.x2&&e.y1<=a&&a<=e.y2},oh=function(e,r){return Gr(e,r.x,r.y)},So=function(e,r){return Gr(e,r.x1,r.y1)&&Gr(e,r.x2,r.y2)},Lo=function(e,r,a,n,i,s,o){var u=arguments.length>7&&arguments[7]!==void 0?arguments[7]:"auto",l=u==="auto"?pr(i,s):u,f=i/2,h=s/2;l=Math.min(l,f,h);var d=l!==f,c=l!==h,v;if(d){var p=a-f+l-o,g=n-h-o,y=a+f-l+o,b=g;if(v=Zt(e,r,a,n,p,g,y,b,!1),v.length>0)return v}if(c){var m=a+f+o,T=n-h+l-o,C=m,S=n+h-l+o;if(v=Zt(e,r,a,n,m,T,C,S,!1),v.length>0)return v}if(d){var E=a-f+l-o,x=n+h+o,w=a+f-l+o,D=x;if(v=Zt(e,r,a,n,E,x,w,D,!1),v.length>0)return v}if(c){var L=a-f-o,A=n-h+l-o,I=L,O=n+h-l+o;if(v=Zt(e,r,a,n,L,A,I,O,!1),v.length>0)return v}var M;{var R=a-f+l,k=n-h+l;if(M=sa(e,r,a,n,R,k,l+o),M.length>0&&M[0]<=R&&M[1]<=k)return[M[0],M[1]]}{var P=a+f-l,B=n-h+l;if(M=sa(e,r,a,n,P,B,l+o),M.length>0&&M[0]>=P&&M[1]<=B)return[M[0],M[1]]}{var V=a+f-l,F=n+h-l;if(M=sa(e,r,a,n,V,F,l+o),M.length>0&&M[0]>=V&&M[1]>=F)return[M[0],M[1]]}{var G=a-f+l,Y=n+h-l;if(M=sa(e,r,a,n,G,Y,l+o),M.length>0&&M[0]<=G&&M[1]>=Y)return[M[0],M[1]]}return[]},uh=function(e,r,a,n,i,s,o){var u=o,l=Math.min(a,i),f=Math.max(a,i),h=Math.min(n,s),d=Math.max(n,s);return l-u<=e&&e<=f+u&&h-u<=r&&r<=d+u},lh=function(e,r,a,n,i,s,o,u,l){var f={x1:Math.min(a,o,i)-l,x2:Math.max(a,o,i)+l,y1:Math.min(n,u,s)-l,y2:Math.max(n,u,s)+l};return!(ef.x2||rf.y2)},fh=function(e,r,a,n){a-=n;var i=r*r-4*e*a;if(i<0)return[];var s=Math.sqrt(i),o=2*e,u=(-r+s)/o,l=(-r-s)/o;return[u,l]},hh=function(e,r,a,n,i){var s=1e-5;e===0&&(e=s),r/=e,a/=e,n/=e;var o,u,l,f,h,d,c,v;if(u=(3*a-r*r)/9,l=-(27*n)+r*(9*a-2*(r*r)),l/=54,o=u*u*u+l*l,i[1]=0,c=r/3,o>0){h=l+Math.sqrt(o),h=h<0?-Math.pow(-h,1/3):Math.pow(h,1/3),d=l-Math.sqrt(o),d=d<0?-Math.pow(-d,1/3):Math.pow(d,1/3),i[0]=-c+h+d,c+=(h+d)/2,i[4]=i[2]=-c,c=Math.sqrt(3)*(-d+h)/2,i[3]=c,i[5]=-c;return}if(i[5]=i[3]=0,o===0){v=l<0?-Math.pow(-l,1/3):Math.pow(l,1/3),i[0]=-c+2*v,i[4]=i[2]=-(v+c);return}u=-u,f=u*u*u,f=Math.acos(l/Math.sqrt(f)),v=2*Math.sqrt(u),i[0]=-c+v*Math.cos(f/3),i[2]=-c+v*Math.cos((f+2*Math.PI)/3),i[4]=-c+v*Math.cos((f+4*Math.PI)/3)},ch=function(e,r,a,n,i,s,o,u){var l=1*a*a-4*a*i+2*a*o+4*i*i-4*i*o+o*o+n*n-4*n*s+2*n*u+4*s*s-4*s*u+u*u,f=1*9*a*i-3*a*a-3*a*o-6*i*i+3*i*o+9*n*s-3*n*n-3*n*u-6*s*s+3*s*u,h=1*3*a*a-6*a*i+a*o-a*e+2*i*i+2*i*e-o*e+3*n*n-6*n*s+n*u-n*r+2*s*s+2*s*r-u*r,d=1*a*i-a*a+a*e-i*e+n*s-n*n+n*r-s*r,c=[];hh(l,f,h,d,c);for(var v=1e-7,p=[],g=0;g<6;g+=2)Math.abs(c[g+1])=0&&c[g]<=1&&p.push(c[g]);p.push(1),p.push(0);for(var y=-1,b,m,T,C=0;C=0?Tl?(e-i)*(e-i)+(r-s)*(r-s):f-d},dt=function(e,r,a){for(var n,i,s,o,u,l=0,f=0;f=e&&e>=s||n<=e&&e<=s)u=(e-n)/(s-n)*(o-i)+i,u>r&&l++;else continue;return l%2!==0},Yt=function(e,r,a,n,i,s,o,u,l){var f=new Array(a.length),h;u[0]!=null?(h=Math.atan(u[1]/u[0]),u[0]<0?h=h+Math.PI/2:h=-h-Math.PI/2):h=u;for(var d=Math.cos(-h),c=Math.sin(-h),v=0;v0){var g=sn(f,-l);p=nn(g)}else p=f;return dt(e,r,p)},dh=function(e,r,a,n,i,s,o,u){for(var l=new Array(a.length*2),f=0;f=0&&g<=1&&b.push(g),y>=0&&y<=1&&b.push(y),b.length===0)return[];var m=b[0]*u[0]+e,T=b[0]*u[1]+r;if(b.length>1){if(b[0]==b[1])return[m,T];var C=b[1]*u[0]+e,S=b[1]*u[1]+r;return[m,T,C,S]}else return[m,T]},Bn=function(e,r,a){return r<=e&&e<=a||a<=e&&e<=r?e:e<=r&&r<=a||a<=r&&r<=e?r:a},Zt=function(e,r,a,n,i,s,o,u,l){var f=e-i,h=a-e,d=o-i,c=r-s,v=n-r,p=u-s,g=d*c-p*f,y=h*c-v*f,b=p*h-d*v;if(b!==0){var m=g/b,T=y/b,C=.001,S=0-C,E=1+C;return S<=m&&m<=E&&S<=T&&T<=E?[e+m*h,r+m*v]:l?[e+m*h,r+m*v]:[]}else return g===0||y===0?Bn(e,a,o)===o?[o,u]:Bn(e,a,i)===i?[i,s]:Bn(i,o,a)===a?[a,n]:[]:[]},pa=function(e,r,a,n,i,s,o,u){var l=[],f,h=new Array(a.length),d=!0;s==null&&(d=!1);var c;if(d){for(var v=0;v0){var p=sn(h,-u);c=nn(p)}else c=h}else c=a;for(var g,y,b,m,T=0;T2){for(var v=[f[0],f[1]],p=Math.pow(v[0]-e,2)+Math.pow(v[1]-r,2),g=1;gf&&(f=T)},get:function(m){return l[m]}},d=0;d0?R=M.edgesTo(O)[0]:R=O.edgesTo(M)[0];var k=n(R);O=O.id(),x[O]>x[A]+k&&(x[O]=x[A]+k,w.nodes.indexOf(O)<0?w.push(O):w.updateItem(O),E[O]=0,S[O]=[]),x[O]==x[A]+k&&(E[O]=E[O]+E[A],S[O].push(A))}else for(var P=0;P0;){for(var G=C.pop(),Y=0;Y0&&o.push(a[u]);o.length!==0&&i.push(n.collection(o))}return i},Nh=function(e,r){for(var a=0;a5&&arguments[5]!==void 0?arguments[5]:Rh,o=n,u,l,f=0;f=2?ea(e,r,a,0,rs,kh):ea(e,r,a,0,ts)},squaredEuclidean:function(e,r,a){return ea(e,r,a,0,rs)},manhattan:function(e,r,a){return ea(e,r,a,0,ts)},max:function(e,r,a){return ea(e,r,a,-1/0,Ph)}};zr["squared-euclidean"]=zr.squaredEuclidean;zr.squaredeuclidean=zr.squaredEuclidean;function mn(t,e,r,a,n,i){var s;return Ge(t)?s=t:s=zr[t]||zr.euclidean,e===0&&Ge(t)?s(n,i):s(e,r,a,n,i)}var Bh=tt({k:2,m:2,sensitivityThreshold:1e-4,distance:"euclidean",maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),Ti=function(e){return Bh(e)},on=function(e,r,a,n,i){var s=i!=="kMedoids",o=s?function(h){return a[h]}:function(h){return n[h](a)},u=function(d){return n[d](r)},l=a,f=r;return mn(e,n.length,o,u,l,f)},Fn=function(e,r,a){for(var n=a.length,i=new Array(n),s=new Array(n),o=new Array(r),u=null,l=0;la)return!1}return!0},zh=function(e,r,a){for(var n=0;no&&(o=r[l][f],u=f);i[u].push(e[l])}for(var h=0;h=i.threshold||i.mode==="dendrogram"&&e.length===1)return!1;var v=r[s],p=r[n[s]],g;i.mode==="dendrogram"?g={left:v,right:p,key:v.key}:g={value:v.value.concat(p.value),key:v.key},e[v.index]=g,e.splice(p.index,1),r[v.key]=g;for(var y=0;ya[p.key][b.key]&&(u=a[p.key][b.key])):i.linkage==="max"?(u=a[v.key][b.key],a[v.key][b.key]0&&n.push(i);return n},us=function(e,r,a){for(var n=[],i=0;io&&(s=l,o=r[i*e+l])}s>0&&n.push(s)}for(var f=0;fl&&(u=f,l=h)}a[i]=s[u]}return n=us(e,r,a),n},ls=function(e){for(var r=this.cy(),a=this.nodes(),n=jh(e),i={},s=0;s=L?(A=L,L=O,I=M):O>A&&(A=O);for(var R=0;R0?1:0;E[w%n.minIterations*o+G]=Y,F+=Y}if(F>0&&(w>=n.minIterations-1||w==n.maxIterations-1)){for(var _=0,q=0;q1||S>1)&&(o=!0),h[m]=[],b.outgoers().forEach(function(x){x.isEdge()&&h[m].push(x.id())})}else d[m]=[void 0,b.target().id()]}):s.forEach(function(b){var m=b.id();if(b.isNode()){var T=b.degree(!0);T%2&&(u?l?o=!0:l=m:u=m),h[m]=[],b.connectedEdges().forEach(function(C){return h[m].push(C.id())})}else d[m]=[b.source().id(),b.target().id()]});var c={found:!1,trail:void 0};if(o)return c;if(l&&u)if(i){if(f&&l!=f)return c;f=l}else{if(f&&l!=f&&u!=f)return c;f||(f=l)}else f||(f=s[0].id());var v=function(m){for(var T=m,C=[m],S,E,x;h[T].length;)S=h[T].shift(),E=d[S][0],x=d[S][1],T!=x?(h[x]=h[x].filter(function(w){return w!=S}),T=x):!i&&T!=E&&(h[E]=h[E].filter(function(w){return w!=S}),T=E),C.unshift(S),C.unshift(T);return C},p=[],g=[];for(g=v(f);g.length!=1;)h[g[0]].length==0?(p.unshift(s.getElementById(g.shift())),p.unshift(s.getElementById(g.shift()))):g=v(g.shift()).concat(g);p.unshift(s.getElementById(g.shift()));for(var y in h)if(h[y].length)return c;return c.found=!0,c.trail=this.spawn(p,!0),c}},Ba=function(){var e=this,r={},a=0,n=0,i=[],s=[],o={},u=function(d,c){for(var v=s.length-1,p=[],g=e.spawn();s[v].x!=d||s[v].y!=c;)p.push(s.pop().edge),v--;p.push(s.pop().edge),p.forEach(function(y){var b=y.connectedNodes().intersection(e);g.merge(y),b.forEach(function(m){var T=m.id(),C=m.connectedEdges().intersection(e);g.merge(m),r[T].cutVertex?g.merge(C.filter(function(S){return S.isLoop()})):g.merge(C)})}),i.push(g)},l=function h(d,c,v){d===v&&(n+=1),r[c]={id:a,low:a++,cutVertex:!1};var p=e.getElementById(c).connectedEdges().intersection(e);if(p.size()===0)i.push(e.spawn(e.getElementById(c)));else{var g,y,b,m;p.forEach(function(T){g=T.source().id(),y=T.target().id(),b=g===c?y:g,b!==v&&(m=T.id(),o[m]||(o[m]=!0,s.push({x:c,y:b,edge:T})),b in r?r[c].low=Math.min(r[c].low,r[b].id):(h(d,b,c),r[c].low=Math.min(r[c].low,r[b].low),r[c].id<=r[b].low&&(r[c].cutVertex=!0,u(c,b))))})}};e.forEach(function(h){if(h.isNode()){var d=h.id();d in r||(n=0,l(d,d),r[d].cutVertex=n>1)}});var f=Object.keys(r).filter(function(h){return r[h].cutVertex}).map(function(h){return e.getElementById(h)});return{cut:e.spawn(f),components:i}},oc={hopcroftTarjanBiconnected:Ba,htbc:Ba,htb:Ba,hopcroftTarjanBiconnectedComponents:Ba},Fa=function(){var e=this,r={},a=0,n=[],i=[],s=e.spawn(e),o=function u(l){i.push(l),r[l]={index:a,low:a++,explored:!1};var f=e.getElementById(l).connectedEdges().intersection(e);if(f.forEach(function(p){var g=p.target().id();g!==l&&(g in r||u(g),r[g].explored||(r[l].low=Math.min(r[l].low,r[g].low)))}),r[l].index===r[l].low){for(var h=e.spawn();;){var d=i.pop();if(h.merge(e.getElementById(d)),r[d].low=r[l].index,r[d].explored=!0,d===l)break}var c=h.edgesWith(h),v=h.merge(c);n.push(v),s=s.difference(v)}};return e.forEach(function(u){if(u.isNode()){var l=u.id();l in r||o(l)}}),{cut:s,components:n}},uc={tarjanStronglyConnected:Fa,tsc:Fa,tscc:Fa,tarjanStronglyConnectedComponents:Fa},ko={};[da,Gf,zf,Uf,Yf,Hf,Wf,bh,kr,Pr,Zn,Mh,Hh,Qh,nc,sc,oc,uc].forEach(function(t){be(ko,t)});/*!
                                         Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable
                                        diff --git a/assets/mkcp.html-DlmPRG7s.js b/assets/mkcp.html-BC2K7D4N.js
                                        similarity index 98%
                                        rename from assets/mkcp.html-DlmPRG7s.js
                                        rename to assets/mkcp.html-BC2K7D4N.js
                                        index d581061e2e..c5810f2148 100644
                                        --- a/assets/mkcp.html-DlmPRG7s.js
                                        +++ b/assets/mkcp.html-BC2K7D4N.js
                                        @@ -1 +1 @@
                                        -import{_ as i,r as n,o as r,c as s,a as e,b as t,d as a,e as h}from"./app-5SoadDYS.js";const o={},p=t("h1",{id:"mkcp-协议",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#mkcp-协议"},[t("span",null,"mKCP 协议")])],-1),c={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"},b=h('

                                        版本

                                        mKCP 没有版本号,不保证版本之间兼容性。

                                        依赖

                                        底层协议

                                        mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。

                                        函数

                                        ',6),_={href:"https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function",target:"_blank",rel:"noopener noreferrer"},m=t("ul",null,[t("li",null,"输入参数为任意长度的字符串;"),t("li",null,"输入出一个 32 位无符号整数;")],-1),u=h('

                                        通讯过程

                                        1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。
                                        2. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。
                                        3. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。

                                        数据格式

                                        数据包

                                        4 字节2 字节L 字节
                                        认证信息 A数据长度 L片段部分

                                        其中:

                                        • 认证信息 A = fnv(片段部分),big endian;
                                        • 片段部分可能包含多个片段;

                                        数据片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len 字节
                                        标识 Conv指令 Cmd选项 Opt时间戳 Ts序列号 Sn未确认序列号 Una长度 Len数据

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x01
                                        • 选项 Opt: 可选的值有:
                                          • 0x00: 空选项
                                          • 0x01: 对方已发出所有数据
                                        • 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian
                                        • 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1
                                        • 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn

                                        确认片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len * 4 字节
                                        标识 Conv指令 Cmd选项 Opt窗口 Wnd下一接收序列号 Sn时间戳 Ts长度 Len已收到的序列号

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x00
                                        • 选项 Opt: 同上
                                        • 窗口 Wnd: 远端主机可以接收的最大序列号
                                        • 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号
                                        • 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟
                                        • 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到

                                        注释:

                                        • 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据

                                        心跳片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节
                                        标识 Conv指令 Cmd选项 Opt未确认序列号 Una下一接收序列号 Sn延迟 Rto

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 可选的值有
                                          • 0x02: 远端主机强行终止会话
                                          • 0x03: 正常心跳
                                        • 选项 Opt: 同上
                                        • 未确认序列号 Una: 同数据片段的 Una
                                        • 下一接收序列号 Sn: 同确认片段的 Sn
                                        • 延迟 Rto: 远端主机自己计算出的延迟
                                        ',21);function f(C,x){const d=n("I18nTip"),l=n("ExternalLinkIcon");return r(),s("div",null,[e(d),p,t("p",null,[a("mKCP 是流式传输协议,由 "),t("a",c,[a("KCP 协议"),e(l)]),a(" 修改而来,可以按顺序传输任意的数据流。")]),b,t("ul",null,[t("li",null,[a("fnv: "),t("a",_,[a("FNV-1a"),e(l)]),a(" 哈希函数 "),m])]),u])}const P=i(o,[["render",f],["__file","mkcp.html.vue"]]);export{P as default}; +import{_ as i,r as n,o as r,c as s,a as e,b as t,d as a,e as h}from"./app-Bw2NG-QJ.js";const o={},p=t("h1",{id:"mkcp-协议",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#mkcp-协议"},[t("span",null,"mKCP 协议")])],-1),c={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"},b=h('

                                        版本

                                        mKCP 没有版本号,不保证版本之间兼容性。

                                        依赖

                                        底层协议

                                        mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。

                                        函数

                                        ',6),_={href:"https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function",target:"_blank",rel:"noopener noreferrer"},m=t("ul",null,[t("li",null,"输入参数为任意长度的字符串;"),t("li",null,"输入出一个 32 位无符号整数;")],-1),u=h('

                                        通讯过程

                                        1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。
                                        2. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。
                                        3. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。

                                        数据格式

                                        数据包

                                        4 字节2 字节L 字节
                                        认证信息 A数据长度 L片段部分

                                        其中:

                                        • 认证信息 A = fnv(片段部分),big endian;
                                        • 片段部分可能包含多个片段;

                                        数据片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len 字节
                                        标识 Conv指令 Cmd选项 Opt时间戳 Ts序列号 Sn未确认序列号 Una长度 Len数据

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x01
                                        • 选项 Opt: 可选的值有:
                                          • 0x00: 空选项
                                          • 0x01: 对方已发出所有数据
                                        • 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian
                                        • 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1
                                        • 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn

                                        确认片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len * 4 字节
                                        标识 Conv指令 Cmd选项 Opt窗口 Wnd下一接收序列号 Sn时间戳 Ts长度 Len已收到的序列号

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x00
                                        • 选项 Opt: 同上
                                        • 窗口 Wnd: 远端主机可以接收的最大序列号
                                        • 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号
                                        • 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟
                                        • 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到

                                        注释:

                                        • 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据

                                        心跳片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节
                                        标识 Conv指令 Cmd选项 Opt未确认序列号 Una下一接收序列号 Sn延迟 Rto

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 可选的值有
                                          • 0x02: 远端主机强行终止会话
                                          • 0x03: 正常心跳
                                        • 选项 Opt: 同上
                                        • 未确认序列号 Una: 同数据片段的 Una
                                        • 下一接收序列号 Sn: 同确认片段的 Sn
                                        • 延迟 Rto: 远端主机自己计算出的延迟
                                        ',21);function f(C,x){const d=n("I18nTip"),l=n("ExternalLinkIcon");return r(),s("div",null,[e(d),p,t("p",null,[a("mKCP 是流式传输协议,由 "),t("a",c,[a("KCP 协议"),e(l)]),a(" 修改而来,可以按顺序传输任意的数据流。")]),b,t("ul",null,[t("li",null,[a("fnv: "),t("a",_,[a("FNV-1a"),e(l)]),a(" 哈希函数 "),m])]),u])}const P=i(o,[["render",f],["__file","mkcp.html.vue"]]);export{P as default}; diff --git a/assets/mkcp.html-ET0VyK1t.js b/assets/mkcp.html-BYbEm1gj.js similarity index 99% rename from assets/mkcp.html-ET0VyK1t.js rename to assets/mkcp.html-BYbEm1gj.js index 06b57a1021..385b610f89 100644 --- a/assets/mkcp.html-ET0VyK1t.js +++ b/assets/mkcp.html-BYbEm1gj.js @@ -1,4 +1,4 @@ -import{_ as c,r as s,o as i,c as d,a,b as e,d as n,e as t}from"./app-5SoadDYS.js";const r={},l=t(`

                                        mKCP

                                        mKCP 使用 UDP 来模拟 TCP 连接。

                                        mKCP 牺牲带宽来降低延迟。传输同样的内容,mKCP 一般比 TCP 消耗更多的流量。

                                        提示

                                        请确定主机上的防火墙配置正确

                                        KcpObject

                                        KcpObject 对应传输配置的 kcpSettings 项。

                                        {
                                        +import{_ as c,r as s,o as i,c as d,a,b as e,d as n,e as t}from"./app-Bw2NG-QJ.js";const r={},l=t(`

                                        mKCP

                                        mKCP 使用 UDP 来模拟 TCP 连接。

                                        mKCP 牺牲带宽来降低延迟。传输同样的内容,mKCP 一般比 TCP 消耗更多的流量。

                                        提示

                                        请确定主机上的防火墙配置正确

                                        KcpObject

                                        KcpObject 对应传输配置的 kcpSettings 项。

                                        {
                                           "mtu": 1350,
                                           "tti": 20,
                                           "uplinkCapacity": 5,
                                        diff --git a/assets/mkcp.html-DQUcXkzK.js b/assets/mkcp.html-Clzx5P9b.js
                                        similarity index 99%
                                        rename from assets/mkcp.html-DQUcXkzK.js
                                        rename to assets/mkcp.html-Clzx5P9b.js
                                        index 67af126113..57b932bde0 100644
                                        --- a/assets/mkcp.html-DQUcXkzK.js
                                        +++ b/assets/mkcp.html-Clzx5P9b.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as o,o as p,c as d,a as n,b as t,d as e,w as l,e as s}from"./app-5SoadDYS.js";const u={},h=s('

                                        mKCP

                                        mKCP uses UDP to emulate TCP connections.

                                        mKCP sacrifices bandwidth to reduce latency. To transmit the same content, mKCP generally consumes more data than TCP.

                                        Tip

                                        Make sure the firewall on the host is configured correctly.

                                        KcpObject

                                        ',5),m=t("code",null,"KcpObject",-1),b=t("code",null,"kcpSettings",-1),f=s(`
                                        {
                                        +import{_ as r,r as o,o as p,c as d,a as n,b as t,d as e,w as l,e as s}from"./app-Bw2NG-QJ.js";const u={},h=s('

                                        mKCP

                                        mKCP uses UDP to emulate TCP connections.

                                        mKCP sacrifices bandwidth to reduce latency. To transmit the same content, mKCP generally consumes more data than TCP.

                                        Tip

                                        Make sure the firewall on the host is configured correctly.

                                        KcpObject

                                        ',5),m=t("code",null,"KcpObject",-1),b=t("code",null,"kcpSettings",-1),f=s(`
                                        {
                                           "mtu": 1350,
                                           "tti": 20,
                                           "uplinkCapacity": 5,
                                        diff --git a/assets/mkcp.html-DVsV0BBF.js b/assets/mkcp.html-D6gGU4SN.js
                                        similarity index 98%
                                        rename from assets/mkcp.html-DVsV0BBF.js
                                        rename to assets/mkcp.html-D6gGU4SN.js
                                        index d581061e2e..c5810f2148 100644
                                        --- a/assets/mkcp.html-DVsV0BBF.js
                                        +++ b/assets/mkcp.html-D6gGU4SN.js
                                        @@ -1 +1 @@
                                        -import{_ as i,r as n,o as r,c as s,a as e,b as t,d as a,e as h}from"./app-5SoadDYS.js";const o={},p=t("h1",{id:"mkcp-协议",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#mkcp-协议"},[t("span",null,"mKCP 协议")])],-1),c={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"},b=h('

                                        版本

                                        mKCP 没有版本号,不保证版本之间兼容性。

                                        依赖

                                        底层协议

                                        mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。

                                        函数

                                        ',6),_={href:"https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function",target:"_blank",rel:"noopener noreferrer"},m=t("ul",null,[t("li",null,"输入参数为任意长度的字符串;"),t("li",null,"输入出一个 32 位无符号整数;")],-1),u=h('

                                        通讯过程

                                        1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。
                                        2. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。
                                        3. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。

                                        数据格式

                                        数据包

                                        4 字节2 字节L 字节
                                        认证信息 A数据长度 L片段部分

                                        其中:

                                        • 认证信息 A = fnv(片段部分),big endian;
                                        • 片段部分可能包含多个片段;

                                        数据片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len 字节
                                        标识 Conv指令 Cmd选项 Opt时间戳 Ts序列号 Sn未确认序列号 Una长度 Len数据

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x01
                                        • 选项 Opt: 可选的值有:
                                          • 0x00: 空选项
                                          • 0x01: 对方已发出所有数据
                                        • 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian
                                        • 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1
                                        • 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn

                                        确认片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len * 4 字节
                                        标识 Conv指令 Cmd选项 Opt窗口 Wnd下一接收序列号 Sn时间戳 Ts长度 Len已收到的序列号

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x00
                                        • 选项 Opt: 同上
                                        • 窗口 Wnd: 远端主机可以接收的最大序列号
                                        • 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号
                                        • 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟
                                        • 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到

                                        注释:

                                        • 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据

                                        心跳片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节
                                        标识 Conv指令 Cmd选项 Opt未确认序列号 Una下一接收序列号 Sn延迟 Rto

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 可选的值有
                                          • 0x02: 远端主机强行终止会话
                                          • 0x03: 正常心跳
                                        • 选项 Opt: 同上
                                        • 未确认序列号 Una: 同数据片段的 Una
                                        • 下一接收序列号 Sn: 同确认片段的 Sn
                                        • 延迟 Rto: 远端主机自己计算出的延迟
                                        ',21);function f(C,x){const d=n("I18nTip"),l=n("ExternalLinkIcon");return r(),s("div",null,[e(d),p,t("p",null,[a("mKCP 是流式传输协议,由 "),t("a",c,[a("KCP 协议"),e(l)]),a(" 修改而来,可以按顺序传输任意的数据流。")]),b,t("ul",null,[t("li",null,[a("fnv: "),t("a",_,[a("FNV-1a"),e(l)]),a(" 哈希函数 "),m])]),u])}const P=i(o,[["render",f],["__file","mkcp.html.vue"]]);export{P as default}; +import{_ as i,r as n,o as r,c as s,a as e,b as t,d as a,e as h}from"./app-Bw2NG-QJ.js";const o={},p=t("h1",{id:"mkcp-协议",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#mkcp-协议"},[t("span",null,"mKCP 协议")])],-1),c={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"},b=h('

                                        版本

                                        mKCP 没有版本号,不保证版本之间兼容性。

                                        依赖

                                        底层协议

                                        mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。

                                        函数

                                        ',6),_={href:"https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function",target:"_blank",rel:"noopener noreferrer"},m=t("ul",null,[t("li",null,"输入参数为任意长度的字符串;"),t("li",null,"输入出一个 32 位无符号整数;")],-1),u=h('

                                        通讯过程

                                        1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。
                                        2. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。
                                        3. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。

                                        数据格式

                                        数据包

                                        4 字节2 字节L 字节
                                        认证信息 A数据长度 L片段部分

                                        其中:

                                        • 认证信息 A = fnv(片段部分),big endian;
                                        • 片段部分可能包含多个片段;

                                        数据片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len 字节
                                        标识 Conv指令 Cmd选项 Opt时间戳 Ts序列号 Sn未确认序列号 Una长度 Len数据

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x01
                                        • 选项 Opt: 可选的值有:
                                          • 0x00: 空选项
                                          • 0x01: 对方已发出所有数据
                                        • 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian
                                        • 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1
                                        • 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn

                                        确认片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len * 4 字节
                                        标识 Conv指令 Cmd选项 Opt窗口 Wnd下一接收序列号 Sn时间戳 Ts长度 Len已收到的序列号

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x00
                                        • 选项 Opt: 同上
                                        • 窗口 Wnd: 远端主机可以接收的最大序列号
                                        • 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号
                                        • 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟
                                        • 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到

                                        注释:

                                        • 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据

                                        心跳片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节
                                        标识 Conv指令 Cmd选项 Opt未确认序列号 Una下一接收序列号 Sn延迟 Rto

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 可选的值有
                                          • 0x02: 远端主机强行终止会话
                                          • 0x03: 正常心跳
                                        • 选项 Opt: 同上
                                        • 未确认序列号 Una: 同数据片段的 Una
                                        • 下一接收序列号 Sn: 同确认片段的 Sn
                                        • 延迟 Rto: 远端主机自己计算出的延迟
                                        ',21);function f(C,x){const d=n("I18nTip"),l=n("ExternalLinkIcon");return r(),s("div",null,[e(d),p,t("p",null,[a("mKCP 是流式传输协议,由 "),t("a",c,[a("KCP 协议"),e(l)]),a(" 修改而来,可以按顺序传输任意的数据流。")]),b,t("ul",null,[t("li",null,[a("fnv: "),t("a",_,[a("FNV-1a"),e(l)]),a(" 哈希函数 "),m])]),u])}const P=i(o,[["render",f],["__file","mkcp.html.vue"]]);export{P as default}; diff --git a/assets/mkcp.html-TS7-PC53.js b/assets/mkcp.html-DpdBDDHy.js similarity index 98% rename from assets/mkcp.html-TS7-PC53.js rename to assets/mkcp.html-DpdBDDHy.js index faf5c12a38..0b404a7acc 100644 --- a/assets/mkcp.html-TS7-PC53.js +++ b/assets/mkcp.html-DpdBDDHy.js @@ -1 +1 @@ -import{_ as d,r as i,o as h,c as r,a,b as e,d as t,e as s}from"./app-5SoadDYS.js";const l={},c=e("h1",{id:"mkcp-protocol",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#mkcp-protocol"},[e("span",null,"mKCP Protocol")])],-1),m={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"},p=s('

                                        Version

                                        mKCP has no version number and does not guarantee compatibility between versions.

                                        Dependencies

                                        Underlying Protocol

                                        mKCP is a protocol based on UDP, and all communication uses UDP transmission.

                                        Functions

                                        ',6),u={href:"https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function",target:"_blank",rel:"noopener noreferrer"},b=e("ul",null,[e("li",null,"Takes a string of arbitrary length as input parameter;"),e("li",null,"Outputs a 32-bit unsigned integer.")],-1),f=s('

                                        Communication Process

                                        1. mKCP splits data streams into several data packets for transmission. Each data stream has a unique identifier to distinguish it from other data streams. Each data packet in the data stream carries the same identifier.
                                        2. mKCP does not have a handshake process. When receiving a data packet, it determines whether it is a new call or an ongoing call based on the identifier of the data stream it carries.
                                        3. Each data packet contains several segments (Segment), which are divided into three types: data (Data), acknowledgment (ACK), and heartbeat (Ping). Each segment needs to be processed separately.

                                        Data Format

                                        Data Packet

                                        4 Bytes2 BytesL Bytes
                                        Auth AData Len LFragment

                                        as which:

                                        • Authentication information A = fnv(fragment), big endian;
                                        • The fragment may contain multiple sections.

                                        Data snippet

                                        2 bytes1 byte1 byte4 bytes4 bytes4 bytes2 bytesLen bytes
                                        Conv flagCmd flagOpt flagTimestampSequenceUnacknowledgedLen flagData

                                        as which:

                                        • Identifier Conv: Identifier for mKCP data stream
                                        • Command Cmd: Constant 0x01
                                        • Option Opt: Optional values include:
                                          • 0x00: Empty option
                                          • 0x01: Opposite party has sent all data
                                        • Timestamp Ts: Time when the current segment was sent from the remote end, big endian
                                        • Sequence Number Sn: The position of the data segment in the data stream, the sequence number of the starting segment is 0, and each new segment is sequentially added by 1
                                        • Unacknowledged Sequence Number Una: The minimum Sn that the remote host is sending and has not yet received confirmation.

                                        Confirmation snippet

                                        2 bytes1 byte1 byte4 bytes4 bytes4 bytes2 bytesLen * 4 bytes
                                        Conv IDCmdOptWndNext Seq NumberTimestampLengthReceived Seq Number

                                        as which:

                                        • Identifier Conv: Identifier of the mKCP data stream
                                        • Command Cmd: Constant 0x00
                                        • Option Opt: Same as above
                                        • Window Wnd: The maximum sequence number that the remote host can receive
                                        • Next receive sequence number Sn: The smallest sequence number of the data segment that the remote host has not received
                                        • Timestamp Ts: The timestamp of the latest received data segment by the remote host, which can be used to calculate the delay
                                        • Received sequence numbers: Each 4 bytes, indicating that the data of this sequence number has been confirmed received.

                                        as which:

                                        • The remote host expects to receive data within the serial number [Sn, Wnd) range.

                                        Heartbeat Fragments

                                        2 Bytes1 Byte1 Byte4 Bytes4 Bytes4 Bytes
                                        Conv IDCmdOptUnacknowledged Seq NoNext Receive Seq NoRto

                                        as which:

                                        • Identifier Conv: Identifier for the mKCP data stream
                                        • Command Cmd: Optional values include:
                                          • 0x02: Remote host forcibly terminates the session
                                          • 0x03: Normal heartbeat
                                        • Option Opt: Same as above
                                        • Unacknowledged sequence number Una: Same as the Una of the data fragment
                                        • Next receive sequence number Sn: Same as the Sn of the acknowledgement fragment
                                        • Delay Rto: Delay calculated by the remote host itself
                                        ',21);function y(g,v){const o=i("I18nTip"),n=i("ExternalLinkIcon");return h(),r("div",null,[a(o),c,e("p",null,[t("mKCP is a stream transfer protocol, modified from the "),e("a",m,[t("KCP protocol"),a(n)]),t(", which can transmit any data stream in order.")]),p,e("ul",null,[e("li",null,[t("fnv: "),e("a",u,[t("FNV-1a"),a(n)]),t(" hash function "),b])]),f])}const C=d(l,[["render",y],["__file","mkcp.html.vue"]]);export{C as default}; +import{_ as d,r as i,o as h,c as r,a,b as e,d as t,e as s}from"./app-Bw2NG-QJ.js";const l={},c=e("h1",{id:"mkcp-protocol",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#mkcp-protocol"},[e("span",null,"mKCP Protocol")])],-1),m={href:"https://github.com/skywind3000/kcp",target:"_blank",rel:"noopener noreferrer"},p=s('

                                        Version

                                        mKCP has no version number and does not guarantee compatibility between versions.

                                        Dependencies

                                        Underlying Protocol

                                        mKCP is a protocol based on UDP, and all communication uses UDP transmission.

                                        Functions

                                        ',6),u={href:"https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function",target:"_blank",rel:"noopener noreferrer"},b=e("ul",null,[e("li",null,"Takes a string of arbitrary length as input parameter;"),e("li",null,"Outputs a 32-bit unsigned integer.")],-1),f=s('

                                        Communication Process

                                        1. mKCP splits data streams into several data packets for transmission. Each data stream has a unique identifier to distinguish it from other data streams. Each data packet in the data stream carries the same identifier.
                                        2. mKCP does not have a handshake process. When receiving a data packet, it determines whether it is a new call or an ongoing call based on the identifier of the data stream it carries.
                                        3. Each data packet contains several segments (Segment), which are divided into three types: data (Data), acknowledgment (ACK), and heartbeat (Ping). Each segment needs to be processed separately.

                                        Data Format

                                        Data Packet

                                        4 Bytes2 BytesL Bytes
                                        Auth AData Len LFragment

                                        as which:

                                        • Authentication information A = fnv(fragment), big endian;
                                        • The fragment may contain multiple sections.

                                        Data snippet

                                        2 bytes1 byte1 byte4 bytes4 bytes4 bytes2 bytesLen bytes
                                        Conv flagCmd flagOpt flagTimestampSequenceUnacknowledgedLen flagData

                                        as which:

                                        • Identifier Conv: Identifier for mKCP data stream
                                        • Command Cmd: Constant 0x01
                                        • Option Opt: Optional values include:
                                          • 0x00: Empty option
                                          • 0x01: Opposite party has sent all data
                                        • Timestamp Ts: Time when the current segment was sent from the remote end, big endian
                                        • Sequence Number Sn: The position of the data segment in the data stream, the sequence number of the starting segment is 0, and each new segment is sequentially added by 1
                                        • Unacknowledged Sequence Number Una: The minimum Sn that the remote host is sending and has not yet received confirmation.

                                        Confirmation snippet

                                        2 bytes1 byte1 byte4 bytes4 bytes4 bytes2 bytesLen * 4 bytes
                                        Conv IDCmdOptWndNext Seq NumberTimestampLengthReceived Seq Number

                                        as which:

                                        • Identifier Conv: Identifier of the mKCP data stream
                                        • Command Cmd: Constant 0x00
                                        • Option Opt: Same as above
                                        • Window Wnd: The maximum sequence number that the remote host can receive
                                        • Next receive sequence number Sn: The smallest sequence number of the data segment that the remote host has not received
                                        • Timestamp Ts: The timestamp of the latest received data segment by the remote host, which can be used to calculate the delay
                                        • Received sequence numbers: Each 4 bytes, indicating that the data of this sequence number has been confirmed received.

                                        as which:

                                        • The remote host expects to receive data within the serial number [Sn, Wnd) range.

                                        Heartbeat Fragments

                                        2 Bytes1 Byte1 Byte4 Bytes4 Bytes4 Bytes
                                        Conv IDCmdOptUnacknowledged Seq NoNext Receive Seq NoRto

                                        as which:

                                        • Identifier Conv: Identifier for the mKCP data stream
                                        • Command Cmd: Optional values include:
                                          • 0x02: Remote host forcibly terminates the session
                                          • 0x03: Normal heartbeat
                                        • Option Opt: Same as above
                                        • Unacknowledged sequence number Una: Same as the Una of the data fragment
                                        • Next receive sequence number Sn: Same as the Sn of the acknowledgement fragment
                                        • Delay Rto: Delay calculated by the remote host itself
                                        ',21);function y(g,v){const o=i("I18nTip"),n=i("ExternalLinkIcon");return h(),r("div",null,[a(o),c,e("p",null,[t("mKCP is a stream transfer protocol, modified from the "),e("a",m,[t("KCP protocol"),a(n)]),t(", which can transmit any data stream in order.")]),p,e("ul",null,[e("li",null,[t("fnv: "),e("a",u,[t("FNV-1a"),a(n)]),t(" hash function "),b])]),f])}const C=d(l,[["render",y],["__file","mkcp.html.vue"]]);export{C as default}; diff --git a/assets/mkcp.html-DrAEdayP.js b/assets/mkcp.html-gKNEMwS8.js similarity index 99% rename from assets/mkcp.html-DrAEdayP.js rename to assets/mkcp.html-gKNEMwS8.js index 178bb4d784..bcde426f2d 100644 --- a/assets/mkcp.html-DrAEdayP.js +++ b/assets/mkcp.html-gKNEMwS8.js @@ -1,4 +1,4 @@ -import{_ as c,r as s,o as i,c as r,a,b as e,d as n,e as p}from"./app-5SoadDYS.js";const d={},l=p(`

                                        mKCP

                                        mKCP использует UDP для имитации TCP-соединения.

                                        mKCP жертвует пропускной способностью ради уменьшения задержки. При передаче одного и того же контента mKCP, как правило, потребляет больше трафика, чем TCP.

                                        Подсказка

                                        Убедитесь, что на хосте правильно настроена конфигурация брандмауэра.

                                        KcpObject

                                        KcpObject соответствует параметрам передачи kcpSettings.

                                        {
                                        +import{_ as c,r as s,o as i,c as r,a,b as e,d as n,e as p}from"./app-Bw2NG-QJ.js";const d={},l=p(`

                                        mKCP

                                        mKCP использует UDP для имитации TCP-соединения.

                                        mKCP жертвует пропускной способностью ради уменьшения задержки. При передаче одного и того же контента mKCP, как правило, потребляет больше трафика, чем TCP.

                                        Подсказка

                                        Убедитесь, что на хосте правильно настроена конфигурация брандмауэра.

                                        KcpObject

                                        KcpObject соответствует параметрам передачи kcpSettings.

                                        {
                                           "mtu": 1350,
                                           "tti": 20,
                                           "uplinkCapacity": 5,
                                        diff --git a/assets/multiple.html-BQ0iFIBh.js b/assets/multiple.html-BhUjtgl7.js
                                        similarity index 99%
                                        rename from assets/multiple.html-BQ0iFIBh.js
                                        rename to assets/multiple.html-BhUjtgl7.js
                                        index 713fdf927f..93350b6633 100644
                                        --- a/assets/multiple.html-BQ0iFIBh.js
                                        +++ b/assets/multiple.html-BhUjtgl7.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o,c as t,a as p,e}from"./app-5SoadDYS.js";const c={},l=e(`

                                        多文件配置

                                        Xray 程序支持使用多个配置文件。

                                        多配置文件的主要作用在于分散不同作用模块配置,便于管理和维护。

                                        该功能主要考虑是为了丰富 Xray 的生态链,比如对于 GUI 的客户端,一般只实现节点选择等固定的功能,对于太复杂的配置难以图形化实现;只需留一个 confdir 的自定义配置目录供配置复杂的功能;对于服务器的部署脚本,只需往 confdir 添加文件即可实现配置多种协议。

                                        多文件启动

                                        提示

                                        启动信息中会提示依次读入的每个配置文件,留意启动信息是否符合你预设的顺序。可以在每个文件名前面增加前缀数字的方式控制顺序。如 01_文件名, 02_文件名,数字越大排序越靠后。

                                        $ xray run -confdir /etc/xray/confs
                                        +import{_ as s,r as a,o,c as t,a as p,e}from"./app-Bw2NG-QJ.js";const c={},l=e(`

                                        多文件配置

                                        Xray 程序支持使用多个配置文件。

                                        多配置文件的主要作用在于分散不同作用模块配置,便于管理和维护。

                                        该功能主要考虑是为了丰富 Xray 的生态链,比如对于 GUI 的客户端,一般只实现节点选择等固定的功能,对于太复杂的配置难以图形化实现;只需留一个 confdir 的自定义配置目录供配置复杂的功能;对于服务器的部署脚本,只需往 confdir 添加文件即可实现配置多种协议。

                                        多文件启动

                                        提示

                                        启动信息中会提示依次读入的每个配置文件,留意启动信息是否符合你预设的顺序。可以在每个文件名前面增加前缀数字的方式控制顺序。如 01_文件名, 02_文件名,数字越大排序越靠后。

                                        $ xray run -confdir /etc/xray/confs
                                         

                                        也可使用 Xray.location.confdirXray_LOCATION_CONFDIR 指定 confdir

                                        参数 -confdir 的作用优先于环境变量,如果参数指定了有效的目录则不再读取环境变量中的路径。

                                        规则说明

                                        普通对象({}

                                        顶级对象后者覆盖或补充前者

                                        数组([]

                                        在 json 配置中的 inboundsoutbounds 是数组结构,他们有特殊的规则:

                                        • 查找原有 tag 相同的元素进行覆盖;若无法找到:
                                          • 对于 inbounds,添加至最后(inbounds 内元素顺序无关)
                                          • 对于 outbounds,添加至最前(outbounds 默认首选出口);但如果文件名含有 tail(大小写均可),添加至最后。

                                        配置例子

                                        假设 confs 文件夹下有以下三个配置文件。

                                        • 01.json
                                        {
                                           "log": {
                                             "loglevel": "warning"
                                        diff --git a/assets/multiple.html-CNbc9k4q.js b/assets/multiple.html-D2THR0Xm.js
                                        similarity index 99%
                                        rename from assets/multiple.html-CNbc9k4q.js
                                        rename to assets/multiple.html-D2THR0Xm.js
                                        index 57d2d35ca6..89599cd63a 100644
                                        --- a/assets/multiple.html-CNbc9k4q.js
                                        +++ b/assets/multiple.html-D2THR0Xm.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o as e,c as o,a as t,e as i}from"./app-5SoadDYS.js";const p={},l=i(`

                                        Multi-file configuration

                                        The Xray program supports the use of multiple configuration files.

                                        The main purpose of using multiple configuration files is to distribute different module configurations, making it easier to manage and maintain.

                                        This feature is mainly designed to enrich the Xray ecosystem. For example, for GUI-based clients, only fixed functions such as node selection are usually implemented, and complex configurations are difficult to implement graphically. By leaving a custom confdir configuration directory for complex functions, server deployment scripts can simply add files to confdir to implement multiple protocol configurations.

                                        Multi-file startup

                                        Tip

                                        The startup information will indicate each configuration file being read in sequence. Please pay attention to whether the startup information matches the order you have set.

                                        $ xray run -confdir /etc/xray/confs
                                        +import{_ as s,r as a,o as e,c as o,a as t,e as i}from"./app-Bw2NG-QJ.js";const p={},l=i(`

                                        Multi-file configuration

                                        The Xray program supports the use of multiple configuration files.

                                        The main purpose of using multiple configuration files is to distribute different module configurations, making it easier to manage and maintain.

                                        This feature is mainly designed to enrich the Xray ecosystem. For example, for GUI-based clients, only fixed functions such as node selection are usually implemented, and complex configurations are difficult to implement graphically. By leaving a custom confdir configuration directory for complex functions, server deployment scripts can simply add files to confdir to implement multiple protocol configurations.

                                        Multi-file startup

                                        Tip

                                        The startup information will indicate each configuration file being read in sequence. Please pay attention to whether the startup information matches the order you have set.

                                        $ xray run -confdir /etc/xray/confs
                                         

                                        You can also use Xray.location.confdir or Xray_LOCATION_CONFDIR to specify the confdir.

                                        The -confdir parameter takes precedence over the environment variable. If a valid directory is specified by the parameter, the path in the environment variable will not be read.

                                        Rule Explanation

                                        Normal Objects({}

                                        In the top-level object of JSON, the latter overrides or supplements the former.

                                        For example:

                                        • base.json
                                        {
                                           "log": {},
                                           "api": {},
                                        diff --git a/assets/multiple.html-d0Rz6O9q.js b/assets/multiple.html-DZg36_LG.js
                                        similarity index 99%
                                        rename from assets/multiple.html-d0Rz6O9q.js
                                        rename to assets/multiple.html-DZg36_LG.js
                                        index 4f13bdddb4..97d42c3859 100644
                                        --- a/assets/multiple.html-d0Rz6O9q.js
                                        +++ b/assets/multiple.html-DZg36_LG.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o,c as t,a as e,e as p}from"./app-5SoadDYS.js";const c={},l=p(`

                                        Настройка с помощью нескольких файлов

                                        Программа Xray поддерживает использование нескольких файлов конфигурации.

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

                                        Эта функция в основном предназначена для обогащения экосистемы Xray. Например, для клиентских GUI обычно реализуются только фиксированные функции, такие как выбор узла, и слишком сложные конфигурации трудно реализовать графически. Можно оставить только один пользовательский каталог конфигурации confdir для настройки сложных функций. Для сценариев развертывания сервера достаточно добавить файлы в confdir для настройки различных протоколов.

                                        Запуск с несколькими файлами

                                        Подсказка

                                        В информации о запуске будет указан каждый считываемый файл конфигурации. Убедитесь, что порядок считывания соответствует ожидаемому. Вы можете контролировать порядок, добавляя префиксы с номерами к именам файлов. Например, 01_имя_файла, 02_имя_файла, чем больше число, тем позже файл будет обработан.

                                        $ xray run -confdir /etc/xray/confs
                                        +import{_ as s,r as a,o,c as t,a as e,e as p}from"./app-Bw2NG-QJ.js";const c={},l=p(`

                                        Настройка с помощью нескольких файлов

                                        Программа Xray поддерживает использование нескольких файлов конфигурации.

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

                                        Эта функция в основном предназначена для обогащения экосистемы Xray. Например, для клиентских GUI обычно реализуются только фиксированные функции, такие как выбор узла, и слишком сложные конфигурации трудно реализовать графически. Можно оставить только один пользовательский каталог конфигурации confdir для настройки сложных функций. Для сценариев развертывания сервера достаточно добавить файлы в confdir для настройки различных протоколов.

                                        Запуск с несколькими файлами

                                        Подсказка

                                        В информации о запуске будет указан каждый считываемый файл конфигурации. Убедитесь, что порядок считывания соответствует ожидаемому. Вы можете контролировать порядок, добавляя префиксы с номерами к именам файлов. Например, 01_имя_файла, 02_имя_файла, чем больше число, тем позже файл будет обработан.

                                        $ xray run -confdir /etc/xray/confs
                                         

                                        Также можно использовать Xray.location.confdir или Xray_LOCATION_CONFDIR для указания confdir.

                                        Параметр -confdir имеет приоритет над переменной среды. Если параметр указывает на допустимый каталог, значение переменной среды игнорируется.

                                        Правила

                                        Обычные объекты ({})

                                        Последующие объекты верхнего уровня перезаписывают или дополняют предыдущие.

                                        Массивы ([])

                                        В конфигурации JSON inbounds и outbounds имеют структуру массива, для них действуют особые правила:

                                        • Поиск существующего элемента с тем же tag для перезаписи. Если элемент не найден:
                                          • Для inbounds: добавляется в конец (порядок элементов в inbounds не имеет значения).
                                          • Для outbounds: добавляется в начало (по умолчанию используется первый выход в outbounds); но если имя файла содержит tail (регистр не имеет значения), элемент добавляется в конец.

                                        Пример конфигурации

                                        Предположим, что в папке confs есть следующие три файла конфигурации:

                                        • 01.json
                                        {
                                           "log": {
                                             "loglevel": "warning"
                                        diff --git a/assets/muxcool.html-BRUL_FdO.js b/assets/muxcool.html-Ch_u4leD.js
                                        similarity index 99%
                                        rename from assets/muxcool.html-BRUL_FdO.js
                                        rename to assets/muxcool.html-Ch_u4leD.js
                                        index 8a4a5f46f1..3503050664 100644
                                        --- a/assets/muxcool.html-BRUL_FdO.js
                                        +++ b/assets/muxcool.html-Ch_u4leD.js
                                        @@ -1 +1 @@
                                        -import{_ as n,r as a,o as i,c as r,a as d,b as t,d as e,e as h}from"./app-5SoadDYS.js";const p={},s=h('

                                        Mux.Cool 协议

                                        Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

                                        版本

                                        当前版本是 1 Beta。

                                        依赖

                                        底层协议

                                        Mux.Cool 必须运行在一个已建立的可靠数据流之上。

                                        通讯过程

                                        一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。

                                        客户端行为

                                        当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。

                                        1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。
                                        2. 对于一个新的子连接,客户端必须发送状态New以通知服务器建立子连接,然后使用状态Keep来传送数据。
                                        3. 当子连接结束时,客户端发送End状态来通知服务器关闭子连接。
                                        4. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。
                                        5. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。

                                        服务器端行为

                                        当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。

                                        1. 当收到状态End时,服务器端可以关闭对目标地址的上行连接。
                                        2. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。
                                        3. 服务器不能使用New状态。
                                        4. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。

                                        传输格式

                                        Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。

                                        帧格式

                                        2 字节L 字节X 字节
                                        元数据长度 L元数据额外数据

                                        元数据

                                        元数据有若干种类型。所有类型的元数据都包含 ID 和 Opt 两项,其含义为:

                                        ',21),c=t("li",null,"对于一般 Mux 子连接,ID 由 1 开始累加",-1),x={href:"https://github.com/XTLS/Xray-core/blob/main/common/xudp/xudp.go",target:"_blank",rel:"noopener noreferrer"},b=t("li",null,[e("Opt: "),t("ul",null,[t("li",null,"D(0x01): 有额外数据")])],-1),u=h('

                                        当选项 Opt(D) 开启时,额外数据格式如下:

                                        2 字节X-2 字节
                                        长度 X-2数据

                                        新建子连接 (New)

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节8 字节
                                        ID0x01选项 Opt网络类型 N端口地址类型 T地址 AGlobal ID (XUDP)

                                        其中:

                                        • 网络类型 N:
                                          • 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。
                                          • 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • Global ID (XUDP):
                                          • 客户端计算出 UDP 来源二元组的全局独特 ID,服务端用以确保当 XUDP 断线重连时,仍使用同一个端口与目标通信。

                                        在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持子连接 (Keep)

                                        TCP

                                        2 字节1 字节1 字节
                                        ID0x02选项 Opt

                                        UDP

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节
                                        ID0x02选项 Opt网络类型 N端口地址类型 T地址 A

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 XUDP 在 Opt(D) 之后加 UDP 地址,格式同新建子连接,但没有 Global ID。

                                        关闭子连接 (End)

                                        2 字节1 字节1 字节
                                        ID0x03选项 Opt

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持连接 (KeepAlive)

                                        2 字节1 字节1 字节
                                        ID0x04选项 Opt

                                        在保持连接时:

                                        • 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。
                                        • ID 可为随机值。

                                        应用

                                        Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。

                                        在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。(注:这是一个程序内的标记,VMess 和 VLESS 并不会在数据包中发送“v1.mux.cool”地址)

                                        ',23);function D(_,f){const l=a("I18nTip"),o=a("ExternalLinkIcon");return i(),r("div",null,[d(l),s,t("ul",null,[t("li",null,[e("ID: 子连接的唯一标识 "),t("ul",null,[c,t("li",null,[e("对于 Xray 实现的 "),t("a",x,[e("Single XUDP"),d(o)]),e(",ID 始终为 0")])])]),b]),u])}const m=n(p,[["render",D],["__file","muxcool.html.vue"]]);export{m as default}; +import{_ as n,r as a,o as i,c as r,a as d,b as t,d as e,e as h}from"./app-Bw2NG-QJ.js";const p={},s=h('

                                        Mux.Cool 协议

                                        Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

                                        版本

                                        当前版本是 1 Beta。

                                        依赖

                                        底层协议

                                        Mux.Cool 必须运行在一个已建立的可靠数据流之上。

                                        通讯过程

                                        一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。

                                        客户端行为

                                        当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。

                                        1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。
                                        2. 对于一个新的子连接,客户端必须发送状态New以通知服务器建立子连接,然后使用状态Keep来传送数据。
                                        3. 当子连接结束时,客户端发送End状态来通知服务器关闭子连接。
                                        4. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。
                                        5. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。

                                        服务器端行为

                                        当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。

                                        1. 当收到状态End时,服务器端可以关闭对目标地址的上行连接。
                                        2. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。
                                        3. 服务器不能使用New状态。
                                        4. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。

                                        传输格式

                                        Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。

                                        帧格式

                                        2 字节L 字节X 字节
                                        元数据长度 L元数据额外数据

                                        元数据

                                        元数据有若干种类型。所有类型的元数据都包含 ID 和 Opt 两项,其含义为:

                                        ',21),c=t("li",null,"对于一般 Mux 子连接,ID 由 1 开始累加",-1),x={href:"https://github.com/XTLS/Xray-core/blob/main/common/xudp/xudp.go",target:"_blank",rel:"noopener noreferrer"},b=t("li",null,[e("Opt: "),t("ul",null,[t("li",null,"D(0x01): 有额外数据")])],-1),u=h('

                                        当选项 Opt(D) 开启时,额外数据格式如下:

                                        2 字节X-2 字节
                                        长度 X-2数据

                                        新建子连接 (New)

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节8 字节
                                        ID0x01选项 Opt网络类型 N端口地址类型 T地址 AGlobal ID (XUDP)

                                        其中:

                                        • 网络类型 N:
                                          • 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。
                                          • 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • Global ID (XUDP):
                                          • 客户端计算出 UDP 来源二元组的全局独特 ID,服务端用以确保当 XUDP 断线重连时,仍使用同一个端口与目标通信。

                                        在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持子连接 (Keep)

                                        TCP

                                        2 字节1 字节1 字节
                                        ID0x02选项 Opt

                                        UDP

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节
                                        ID0x02选项 Opt网络类型 N端口地址类型 T地址 A

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 XUDP 在 Opt(D) 之后加 UDP 地址,格式同新建子连接,但没有 Global ID。

                                        关闭子连接 (End)

                                        2 字节1 字节1 字节
                                        ID0x03选项 Opt

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持连接 (KeepAlive)

                                        2 字节1 字节1 字节
                                        ID0x04选项 Opt

                                        在保持连接时:

                                        • 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。
                                        • ID 可为随机值。

                                        应用

                                        Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。

                                        在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。(注:这是一个程序内的标记,VMess 和 VLESS 并不会在数据包中发送“v1.mux.cool”地址)

                                        ',23);function D(_,f){const l=a("I18nTip"),o=a("ExternalLinkIcon");return i(),r("div",null,[d(l),s,t("ul",null,[t("li",null,[e("ID: 子连接的唯一标识 "),t("ul",null,[c,t("li",null,[e("对于 Xray 实现的 "),t("a",x,[e("Single XUDP"),d(o)]),e(",ID 始终为 0")])])]),b]),u])}const m=n(p,[["render",D],["__file","muxcool.html.vue"]]);export{m as default}; diff --git a/assets/muxcool.html-Owf2QQIZ.js b/assets/muxcool.html-DyQfxg_9.js similarity index 98% rename from assets/muxcool.html-Owf2QQIZ.js rename to assets/muxcool.html-DyQfxg_9.js index 8cbb1bcf7c..7d98c25f43 100644 --- a/assets/muxcool.html-Owf2QQIZ.js +++ b/assets/muxcool.html-DyQfxg_9.js @@ -1 +1 @@ -import{_ as t,r as a,o as n,c as o,a as i,e as s}from"./app-5SoadDYS.js";const d={},h=s('

                                        Mux.Cool Protocol

                                        Mux.Cool protocol is a multiplexing transport protocol that is used to transmit multiple independent data streams within an established data stream.

                                        Version

                                        The current version is 1 Beta.

                                        Dependencies

                                        Underlying Protocol

                                        Mux.Cool must run on top of a reliable established data stream.

                                        Communication Process

                                        Within a Mux.Cool connection, multiple sub-connections can be transmitted, each with a unique ID and status. The transmission process consists of frames, with each frame used to transmit data for a specific sub-connection.

                                        Client behavior

                                        When there is a need for a connection and there are no existing available connections, the client initiates a new connection to the server, referred to as the "main connection".

                                        1. One main connection can be used to send several sub-connections. The client can decide independently how many sub-connections the main connection can handle.
                                        2. For a new sub-connection, the client must send the New status to notify the server to establish the sub-connection, and then use the Keep status to transmit data.
                                        3. When the sub-connection ends, the client sends the End status to notify the server to close the sub-connection.
                                        4. The client can decide when to close the main connection, but must ensure that the server also maintains the connection.
                                        5. The client can use the KeepAlive status to prevent the server from closing the main connection.

                                        Server-side behavior

                                        When a new sub-connection is received on the server side, the server should handle it as a normal connection.

                                        1. When the status "End" is received, the server can close the upstream connection to the target address.
                                        2. The same ID used in the request must be used to transfer sub-connection data in the server response.
                                        3. The server cannot use the "New" status.
                                        4. The server can use the KeepAlive status to avoid the client closing the main connection.

                                        Data Format

                                        Mux.Cool uses symmetric transmission format, where the client and server send and receive data in the same format.

                                        Frame Format

                                        2 BytesL BytesX Bytes
                                        Metadata Length LMetadataAdditional Data

                                        Metadata

                                        There are several types of metadata. All types of metadata contain two items, ID and Opt, with the following meanings:

                                        • ID: Unique identifier of the sub-connection
                                          • For general MUX sub-connections, the ID is accumulated starting from 1
                                          • For XUDP, the ID is always 0
                                        • Opt:
                                          • D(0x01): Additional data is available

                                        When option Opt(D) is enabled, the additional data format is as follows:

                                        2 BytesX-2 Bytes
                                        Length X-2Data
                                        2 Bytes1 Byte1 Byte1 Byte2 Bytes1 ByteA Bytes
                                        ID0x01OptionNetwork NPortType TAddress

                                        where:

                                        • Network type N:
                                          • 0x01: TCP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of TCP.
                                          • 0x02: UDP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of UDP.
                                        • Address type T:
                                          • 0x01: IPv4
                                          • 0x02: Domain name
                                          • 0x03: IPv6
                                        • Address A:
                                          • When T = 0x01, A is a 4-byte IPv4 address;
                                          • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
                                          • When T = 0x03, A is a 16-byte IPv6 address;

                                        If Opt(D) is enabled when creating a sub-connection, the data carried by this frame needs to be sent to the target host.

                                        Keep sub-connections

                                        2 Bytes1 Byte1 Byte
                                        ID0x02Option

                                        If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host. XUDP adds the UDP address after Opt(D), and the format is the same as creating a new sub-connection.

                                        End

                                        2 Bytes1 Byte1 Byte
                                        ID0x03Option

                                        If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host.

                                        KeepAlive

                                        2 Bytes1 Byte1 Byte
                                        ID0x04Option Opt

                                        While staying connected:

                                        • If Opt(D) is enabled, the data carried by this frame must be discarded.
                                        • ID can be a random value.

                                        Application

                                        The Mux.Cool protocol is agnostic to the underlying protocol and can theoretically use any reliable streaming connection to transmit Mux.Cool protocol data.

                                        In target-oriented protocols such as Shadowsocks and VMess, a specified address must be included when establishing a connection. To maintain compatibility, the Mux.Cool protocol specifies the address as "v1.mux.cool". When the target address of the main connection matches this address, the Mux.Cool forwarding method is used. Otherwise, forwarding is done in the traditional way. (Note: This is an internal tag in the program, and VMess and VLESS do not send the "v1.mux.cool" address in data packets.)

                                        ',42);function r(c,l){const e=a("I18nTip");return n(),o("div",null,[i(e),h])}const u=t(d,[["render",r],["__file","muxcool.html.vue"]]);export{u as default}; +import{_ as t,r as a,o as n,c as o,a as i,e as s}from"./app-Bw2NG-QJ.js";const d={},h=s('

                                        Mux.Cool Protocol

                                        Mux.Cool protocol is a multiplexing transport protocol that is used to transmit multiple independent data streams within an established data stream.

                                        Version

                                        The current version is 1 Beta.

                                        Dependencies

                                        Underlying Protocol

                                        Mux.Cool must run on top of a reliable established data stream.

                                        Communication Process

                                        Within a Mux.Cool connection, multiple sub-connections can be transmitted, each with a unique ID and status. The transmission process consists of frames, with each frame used to transmit data for a specific sub-connection.

                                        Client behavior

                                        When there is a need for a connection and there are no existing available connections, the client initiates a new connection to the server, referred to as the "main connection".

                                        1. One main connection can be used to send several sub-connections. The client can decide independently how many sub-connections the main connection can handle.
                                        2. For a new sub-connection, the client must send the New status to notify the server to establish the sub-connection, and then use the Keep status to transmit data.
                                        3. When the sub-connection ends, the client sends the End status to notify the server to close the sub-connection.
                                        4. The client can decide when to close the main connection, but must ensure that the server also maintains the connection.
                                        5. The client can use the KeepAlive status to prevent the server from closing the main connection.

                                        Server-side behavior

                                        When a new sub-connection is received on the server side, the server should handle it as a normal connection.

                                        1. When the status "End" is received, the server can close the upstream connection to the target address.
                                        2. The same ID used in the request must be used to transfer sub-connection data in the server response.
                                        3. The server cannot use the "New" status.
                                        4. The server can use the KeepAlive status to avoid the client closing the main connection.

                                        Data Format

                                        Mux.Cool uses symmetric transmission format, where the client and server send and receive data in the same format.

                                        Frame Format

                                        2 BytesL BytesX Bytes
                                        Metadata Length LMetadataAdditional Data

                                        Metadata

                                        There are several types of metadata. All types of metadata contain two items, ID and Opt, with the following meanings:

                                        • ID: Unique identifier of the sub-connection
                                          • For general MUX sub-connections, the ID is accumulated starting from 1
                                          • For XUDP, the ID is always 0
                                        • Opt:
                                          • D(0x01): Additional data is available

                                        When option Opt(D) is enabled, the additional data format is as follows:

                                        2 BytesX-2 Bytes
                                        Length X-2Data
                                        2 Bytes1 Byte1 Byte1 Byte2 Bytes1 ByteA Bytes
                                        ID0x01OptionNetwork NPortType TAddress

                                        where:

                                        • Network type N:
                                          • 0x01: TCP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of TCP.
                                          • 0x02: UDP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of UDP.
                                        • Address type T:
                                          • 0x01: IPv4
                                          • 0x02: Domain name
                                          • 0x03: IPv6
                                        • Address A:
                                          • When T = 0x01, A is a 4-byte IPv4 address;
                                          • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
                                          • When T = 0x03, A is a 16-byte IPv6 address;

                                        If Opt(D) is enabled when creating a sub-connection, the data carried by this frame needs to be sent to the target host.

                                        Keep sub-connections

                                        2 Bytes1 Byte1 Byte
                                        ID0x02Option

                                        If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host. XUDP adds the UDP address after Opt(D), and the format is the same as creating a new sub-connection.

                                        End

                                        2 Bytes1 Byte1 Byte
                                        ID0x03Option

                                        If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host.

                                        KeepAlive

                                        2 Bytes1 Byte1 Byte
                                        ID0x04Option Opt

                                        While staying connected:

                                        • If Opt(D) is enabled, the data carried by this frame must be discarded.
                                        • ID can be a random value.

                                        Application

                                        The Mux.Cool protocol is agnostic to the underlying protocol and can theoretically use any reliable streaming connection to transmit Mux.Cool protocol data.

                                        In target-oriented protocols such as Shadowsocks and VMess, a specified address must be included when establishing a connection. To maintain compatibility, the Mux.Cool protocol specifies the address as "v1.mux.cool". When the target address of the main connection matches this address, the Mux.Cool forwarding method is used. Otherwise, forwarding is done in the traditional way. (Note: This is an internal tag in the program, and VMess and VLESS do not send the "v1.mux.cool" address in data packets.)

                                        ',42);function r(c,l){const e=a("I18nTip");return n(),o("div",null,[i(e),h])}const u=t(d,[["render",r],["__file","muxcool.html.vue"]]);export{u as default}; diff --git a/assets/muxcool.html-CDZVHREe.js b/assets/muxcool.html-hxuFgme0.js similarity index 99% rename from assets/muxcool.html-CDZVHREe.js rename to assets/muxcool.html-hxuFgme0.js index 8a4a5f46f1..3503050664 100644 --- a/assets/muxcool.html-CDZVHREe.js +++ b/assets/muxcool.html-hxuFgme0.js @@ -1 +1 @@ -import{_ as n,r as a,o as i,c as r,a as d,b as t,d as e,e as h}from"./app-5SoadDYS.js";const p={},s=h('

                                        Mux.Cool 协议

                                        Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

                                        版本

                                        当前版本是 1 Beta。

                                        依赖

                                        底层协议

                                        Mux.Cool 必须运行在一个已建立的可靠数据流之上。

                                        通讯过程

                                        一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。

                                        客户端行为

                                        当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。

                                        1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。
                                        2. 对于一个新的子连接,客户端必须发送状态New以通知服务器建立子连接,然后使用状态Keep来传送数据。
                                        3. 当子连接结束时,客户端发送End状态来通知服务器关闭子连接。
                                        4. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。
                                        5. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。

                                        服务器端行为

                                        当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。

                                        1. 当收到状态End时,服务器端可以关闭对目标地址的上行连接。
                                        2. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。
                                        3. 服务器不能使用New状态。
                                        4. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。

                                        传输格式

                                        Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。

                                        帧格式

                                        2 字节L 字节X 字节
                                        元数据长度 L元数据额外数据

                                        元数据

                                        元数据有若干种类型。所有类型的元数据都包含 ID 和 Opt 两项,其含义为:

                                        ',21),c=t("li",null,"对于一般 Mux 子连接,ID 由 1 开始累加",-1),x={href:"https://github.com/XTLS/Xray-core/blob/main/common/xudp/xudp.go",target:"_blank",rel:"noopener noreferrer"},b=t("li",null,[e("Opt: "),t("ul",null,[t("li",null,"D(0x01): 有额外数据")])],-1),u=h('

                                        当选项 Opt(D) 开启时,额外数据格式如下:

                                        2 字节X-2 字节
                                        长度 X-2数据

                                        新建子连接 (New)

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节8 字节
                                        ID0x01选项 Opt网络类型 N端口地址类型 T地址 AGlobal ID (XUDP)

                                        其中:

                                        • 网络类型 N:
                                          • 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。
                                          • 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • Global ID (XUDP):
                                          • 客户端计算出 UDP 来源二元组的全局独特 ID,服务端用以确保当 XUDP 断线重连时,仍使用同一个端口与目标通信。

                                        在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持子连接 (Keep)

                                        TCP

                                        2 字节1 字节1 字节
                                        ID0x02选项 Opt

                                        UDP

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节
                                        ID0x02选项 Opt网络类型 N端口地址类型 T地址 A

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 XUDP 在 Opt(D) 之后加 UDP 地址,格式同新建子连接,但没有 Global ID。

                                        关闭子连接 (End)

                                        2 字节1 字节1 字节
                                        ID0x03选项 Opt

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持连接 (KeepAlive)

                                        2 字节1 字节1 字节
                                        ID0x04选项 Opt

                                        在保持连接时:

                                        • 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。
                                        • ID 可为随机值。

                                        应用

                                        Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。

                                        在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。(注:这是一个程序内的标记,VMess 和 VLESS 并不会在数据包中发送“v1.mux.cool”地址)

                                        ',23);function D(_,f){const l=a("I18nTip"),o=a("ExternalLinkIcon");return i(),r("div",null,[d(l),s,t("ul",null,[t("li",null,[e("ID: 子连接的唯一标识 "),t("ul",null,[c,t("li",null,[e("对于 Xray 实现的 "),t("a",x,[e("Single XUDP"),d(o)]),e(",ID 始终为 0")])])]),b]),u])}const m=n(p,[["render",D],["__file","muxcool.html.vue"]]);export{m as default}; +import{_ as n,r as a,o as i,c as r,a as d,b as t,d as e,e as h}from"./app-Bw2NG-QJ.js";const p={},s=h('

                                        Mux.Cool 协议

                                        Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

                                        版本

                                        当前版本是 1 Beta。

                                        依赖

                                        底层协议

                                        Mux.Cool 必须运行在一个已建立的可靠数据流之上。

                                        通讯过程

                                        一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。

                                        客户端行为

                                        当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。

                                        1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。
                                        2. 对于一个新的子连接,客户端必须发送状态New以通知服务器建立子连接,然后使用状态Keep来传送数据。
                                        3. 当子连接结束时,客户端发送End状态来通知服务器关闭子连接。
                                        4. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。
                                        5. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。

                                        服务器端行为

                                        当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。

                                        1. 当收到状态End时,服务器端可以关闭对目标地址的上行连接。
                                        2. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。
                                        3. 服务器不能使用New状态。
                                        4. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。

                                        传输格式

                                        Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。

                                        帧格式

                                        2 字节L 字节X 字节
                                        元数据长度 L元数据额外数据

                                        元数据

                                        元数据有若干种类型。所有类型的元数据都包含 ID 和 Opt 两项,其含义为:

                                        ',21),c=t("li",null,"对于一般 Mux 子连接,ID 由 1 开始累加",-1),x={href:"https://github.com/XTLS/Xray-core/blob/main/common/xudp/xudp.go",target:"_blank",rel:"noopener noreferrer"},b=t("li",null,[e("Opt: "),t("ul",null,[t("li",null,"D(0x01): 有额外数据")])],-1),u=h('

                                        当选项 Opt(D) 开启时,额外数据格式如下:

                                        2 字节X-2 字节
                                        长度 X-2数据

                                        新建子连接 (New)

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节8 字节
                                        ID0x01选项 Opt网络类型 N端口地址类型 T地址 AGlobal ID (XUDP)

                                        其中:

                                        • 网络类型 N:
                                          • 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。
                                          • 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • Global ID (XUDP):
                                          • 客户端计算出 UDP 来源二元组的全局独特 ID,服务端用以确保当 XUDP 断线重连时,仍使用同一个端口与目标通信。

                                        在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持子连接 (Keep)

                                        TCP

                                        2 字节1 字节1 字节
                                        ID0x02选项 Opt

                                        UDP

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节
                                        ID0x02选项 Opt网络类型 N端口地址类型 T地址 A

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 XUDP 在 Opt(D) 之后加 UDP 地址,格式同新建子连接,但没有 Global ID。

                                        关闭子连接 (End)

                                        2 字节1 字节1 字节
                                        ID0x03选项 Opt

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持连接 (KeepAlive)

                                        2 字节1 字节1 字节
                                        ID0x04选项 Opt

                                        在保持连接时:

                                        • 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。
                                        • ID 可为随机值。

                                        应用

                                        Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。

                                        在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。(注:这是一个程序内的标记,VMess 和 VLESS 并不会在数据包中发送“v1.mux.cool”地址)

                                        ',23);function D(_,f){const l=a("I18nTip"),o=a("ExternalLinkIcon");return i(),r("div",null,[d(l),s,t("ul",null,[t("li",null,[e("ID: 子连接的唯一标识 "),t("ul",null,[c,t("li",null,[e("对于 Xray 实现的 "),t("a",x,[e("Single XUDP"),d(o)]),e(",ID 始终为 0")])])]),b]),u])}const m=n(p,[["render",D],["__file","muxcool.html.vue"]]);export{m as default}; diff --git a/assets/news.html-IY4e89V6.js b/assets/news.html-23-ihBAh.js similarity index 99% rename from assets/news.html-IY4e89V6.js rename to assets/news.html-23-ihBAh.js index e55d484bd1..3b5e3f0c83 100644 --- a/assets/news.html-IY4e89V6.js +++ b/assets/news.html-23-ihBAh.js @@ -1 +1 @@ -import{_,r as i,o as c,c as u,a as n,b as e,d as l,w as o,e as a}from"./app-5SoadDYS.js";const d={},p=e("h1",{id:"大史记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#大史记"},[e("span",null,"大史记")])],-1),f=a('

                                        2021.4.6

                                        • VuePress Next.
                                        • With Dark Mode.

                                        2021.4.4

                                        • 本文档迎来的新的首页。
                                        • 本文档迎来了暗黑模式。
                                        • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                                        • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                                        • 🎉🎉🎉
                                        ',4),b={id:"_2021-4-1-v1-4-2",tabindex:"-1"},g={class:"header-anchor",href:"#_2021-4-1-v1-4-2"},m={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.2",target:"_blank",rel:"noopener noreferrer"},x=a('
                                        • 不是愚人节玩笑,今天更新。
                                        • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                                        • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                                        • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                                        2021.3.25

                                        没错还在变。 -_-

                                        2021.3.15

                                        文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        ',5),X={id:"_2021-3-14-v1-4-0",tabindex:"-1"},S={class:"header-anchor",href:"#_2021-3-14-v1-4-0"},k={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.0",target:"_blank",rel:"noopener noreferrer"},y=a("
                                        • Happy Pi-Day!
                                        • 这次是个大更新:
                                          • 为链式代理引入了传输层支持。
                                          • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                                          • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                                          • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                                          • 添加了 FakeDNS。
                                          • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                                        • 还是 VuePress 比较爽啊(
                                        ",1),v={id:"_2021-3-3-1-3-1",tabindex:"-1"},T={class:"header-anchor",href:"#_2021-3-3-1-3-1"},L={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.1",target:"_blank",rel:"noopener noreferrer"},D=e("ul",null,[e("li",null,"这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。"),e("li",null,[l("同时修复了一个会导致 Panic 的 bug。"),e("s",null,"Holmium_认为这是在骗、在偷袭。")]),e("li",null,"修复了几个遗留问题。")],-1),P={id:"_2021-2-14-1-3-0",tabindex:"-1"},U={class:"header-anchor",href:"#_2021-2-14-1-3-0"},H={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.0",target:"_blank",rel:"noopener noreferrer"},C=e("ul",null,[e("li",null,"Happy 🐮 Year 🎉!"),e("li",null,"v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。"),e("li",null,"OHHHHHHHHHHHH!")],-1),j={id:"_2021-01-31-1-2-4",tabindex:"-1"},B={class:"header-anchor",href:"#_2021-01-31-1-2-4"},I={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.4",target:"_blank",rel:"noopener noreferrer"},N=e("ul",null,[e("li",null,"解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。"),e("li",null,"似乎这个版本没有什么改变,但这只是暴风雨前的宁静。"),e("li",null,[l("(没错我就是先知) "),e("blockquote",null,[e("p",null,"你个傻子,你拿的是 UNO 牌。")])])],-1),E=e("h2",{id:"_2021-01-25",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-25"},[e("span",null,"2021.01.25")])],-1),V=e("li",null,[e("a",{href:"../en"},"英文版文档网站"),l("逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!")],-1),w={id:"_2021-01-22-1-2-3",tabindex:"-1"},G={class:"header-anchor",href:"#_2021-01-22-1-2-3"},R={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.3",target:"_blank",rel:"noopener noreferrer"},O=e("li",null,[l("对 SS 协议的支持"),e("strong",null,"又"),l("变强了, 支持单端口多用户!")],-1),F=e("li",null,[l("对 trojan 协议的支持也"),e("strong",null,"又"),l("变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!")],-1),M=e("li",null,[e("em",null,"(VLESS: 嘤嘤嘤)")],-1),A=e("li",null,'UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".',-1),q=e("li",null,"嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.",-1),W=e("img",{src:"https://avatars2.githubusercontent.com/u/8384161?s=32",width:"32px",height:"32px",alt:"a"},null,-1),Q={href:"https://github.com/bohanyang",target:"_blank",rel:"noopener noreferrer"},Y=e("li",null,"其他美味小樱桃, 惯例更新品尝就对啦.",-1),J=a('

                                        2021.01.19

                                        • 一些数字
                                          • 版本发布了 10   个 tag
                                          • 解决掉了 100  个 issue
                                          • 复刻了 300  个 fork
                                          • 点了 2000 个 star
                                          • 群 3000 个 人

                                        2021.01.17

                                        ',3),z=e("img",{src:"https://avatars2.githubusercontent.com/u/60207794?s=32",width:"32px",height:"32px",alt:"a"},null,-1),K={href:"https://github.com/jiuqi9997",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://xtls.github.io/en/",target:"_blank",rel:"noopener noreferrer"},$={id:"_2021-01-15-1-2-2",tabindex:"-1"},ee={class:"header-anchor",href:"#_2021-01-15-1-2-2"},le={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.2",target:"_blank",rel:"noopener noreferrer"},ne=a('
                                        • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                                        • 之前预告的 UUID 修改正式上线.(往下看往下看)
                                        • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                                        • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                                        • 当然还有其他各种小糖果.(更新品尝就对了)
                                        • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                                        2021.01.12

                                        ',2),te=e("li",null,[l("将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. "),e("ul",null,[e("li",null,'客户端写 "id": "我爱 🍉 老师 1314",'),e("li",null,[l('服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 '),e("code",null,"我爱🍉老师1314"),l(" 的 UUID 映射)")])])],-1),oe={id:"_2021-01-10-1-2-1",tabindex:"-1"},re={class:"header-anchor",href:"#_2021-01-10-1-2-1"},ae={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.1",target:"_blank",rel:"noopener noreferrer"},se=e("li",null,"(可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程)",-1),ie=e("li",null,"还有很多细节修改, 文档将会越来越规范!",-1),he={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},ue=a('
                                        • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                                        • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                                        • 日志现在看起来更顺眼.

                                        2021.01.07

                                        • 礼貌和尊重本应是社区不需要明说的准则之一。

                                        2021.01.05

                                        • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        2021.01.03

                                        ',6),de=e("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32px",height:"32px",alt:"a"},null,-1),pe={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},fe=e("li",null,"tg 群突破 2500。",-1),be=e("h2",{id:"_2021-01-01",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-01"},[e("span",null,"2021.01.01")])],-1),ge={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},me=e("p",null,"🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!",-1),xe=a('
                                      22. 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                                      23. (UDP 还会继续增强!)
                                      24. 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                                      25. (不,下面不是广告,是里程碑。)
                                      26. Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                                        • 一人扛起了所有!支持各大主流协议!
                                        • 一骑绝尘的性能!
                                        • 日趋完善的功能!
                                        • 可怕的生命力与社区亲和力!
                                      27. ',5),Xe={href:"https://github.com/XTLS/Xray-core/discussions/56",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},ke=e("s",null,"(啊,有人敲门...我一会和你们说)",-1),ye=e("h2",{id:"_2020-12-29",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-29"},[e("span",null,"2020.12.29")])],-1),ve={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Te={id:"_2020-12-25-1-1-5",tabindex:"-1"},Le={class:"header-anchor",href:"#_2020-12-25-1-1-5"},De={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.5",target:"_blank",rel:"noopener noreferrer"},Pe=e("p",null,"圣诞节快乐!",-1),Ue=e("li",null,"游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone",-1),He=e("li",null,"你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...",-1),Ce=e("li",null,"(VLESS 的 UDP fullcone 和更多增强很快就到!)",-1),je=e("li",null,"无须再担心证书验证被墙,OCSP stapling 已经上线!",-1),Be={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},Ie=e("li",null,"还有更多美味小樱桃!(不用问,更新品尝就对了)",-1),Ne=e("h2",{id:"_2020-12-24",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-24"},[e("span",null,"2020.12.24")])],-1),Ee={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},Ve=e("p",null,"大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)",-1),we={href:"https://github.com/XTLS/XTLS.github.io",target:"_blank",rel:"noopener noreferrer"},Ge=e("p",null,"仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。",-1),Re=e("h2",{id:"_2020-12-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-23"},[e("span",null,"2020.12.23")])],-1),Oe={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Fe=e("h2",{id:"_2020-12-21",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-21"},[e("span",null,"2020.12.21")])],-1),Me=e("ul",null,[e("li",null,"Project X 群人数 2000+"),e("li",null,"群消息(含游戏群) 日均破万")],-1),Ae={id:"_2020-12-18-1-1-4",tabindex:"-1"},qe={class:"header-anchor",href:"#_2020-12-18-1-1-4"},We={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.4",target:"_blank",rel:"noopener noreferrer"},Qe=e("ul",null,[e("li",null,"更低的启动内占用和内存使用优化"),e("li",null,"随意定制的 TLS 提高你的 SSL 评级"),e("li",null,"支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS"),e("li",null,"还有在您路由器上使用的 Splice 最佳使用模式建议")],-1),Ye=e("h2",{id:"_2020-12-17",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-17"},[e("span",null,"2020.12.17")])],-1),Je={href:"https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ",target:"_blank",rel:"noopener noreferrer"},ze=e("h2",{id:"_2020-12-15",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-15"},[e("span",null,"2020.12.15")])],-1),Ke={href:"https://github.com/XTLS/Xray-install/tree/dev",target:"_blank",rel:"noopener noreferrer"},Ze={id:"_2020-12-11-1-1-3",tabindex:"-1"},$e={class:"header-anchor",href:"#_2020-12-11-1-1-3"},el={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.3",target:"_blank",rel:"noopener noreferrer"},ll=e("ul",null,[e("li",null,"完整版本的 REDIRECT 透明代理模式."),e("li",null,"软路由 splice 流控模式的优化建议.")],-1),nl={id:"_2020-12-06-1-1-2",tabindex:"-1"},tl={class:"header-anchor",href:"#_2020-12-06-1-1-2"},ol={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.2",target:"_blank",rel:"noopener noreferrer"},rl=a('
                                        • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                                        • 增强了 API 兼容

                                        2020.12.04

                                        增加 splice 模式

                                        2020.11.27

                                        • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                                        • 登上了 GitHub Trending
                                        • Project X 群人数破千,频道订阅数 500+
                                        ',5),al={id:"_2020-11-25-1-0-0",tabindex:"-1"},sl={class:"header-anchor",href:"#_2020-11-25-1-0-0"},il={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.0.0",target:"_blank",rel:"noopener noreferrer"},hl=e("p",null,"Xray 的第一个版本.",-1),_l=e("ul",null,[e("li",null,"基于 v2ray-core 修改而来,改动较大"),e("li",null,"全面增强, 性能卓越, 完全兼容")],-1),cl=e("h2",{id:"_2020-11-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-11-23"},[e("span",null,"2020.11.23")])],-1),ul=e("p",null,"project X start",-1),dl=e("blockquote",null,[e("p",null,[e("s",null,"梦开始的时候")])],-1);function pl(fl,bl){const h=i("I18nTip"),t=i("ExternalLinkIcon"),r=i("Badge"),s=i("RouterLink");return c(),u("div",null,[p,n(h),f,e("h2",b,[e("a",g,[e("span",null,[l("2021.4.1 "),n(r,null,{default:o(()=>[e("a",m,[l("v1.4.2"),n(t)])]),_:1})])])]),x,e("h2",X,[e("a",S,[e("span",null,[l("2021.3.14 "),n(r,null,{default:o(()=>[e("a",k,[l("v1.4.0"),n(t)])]),_:1})])])]),y,e("h2",v,[e("a",T,[e("span",null,[l("2021.3.3 "),n(r,null,{default:o(()=>[e("a",L,[l("1.3.1"),n(t)])]),_:1})])])]),D,e("h2",P,[e("a",U,[e("span",null,[l("2021.2.14 "),n(r,null,{default:o(()=>[e("a",H,[l("1.3.0"),n(t)])]),_:1})])])]),C,e("h2",j,[e("a",B,[e("span",null,[l("2021.01.31 "),n(r,null,{default:o(()=>[e("a",I,[l("1.2.4"),n(t)])]),_:1})])])]),N,E,e("ul",null,[e("li",null,[l("全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载"),n(s,{to:"/ru/document/level-1/"},{default:o(()=>[l("秘籍第一层")]),_:1}),l("咯...")]),V]),e("h2",w,[e("a",G,[e("span",null,[l("2021.01.22 "),n(r,null,{default:o(()=>[e("a",R,[l("1.2.3"),n(t)])]),_:1})])])]),e("ul",null,[O,F,M,A,q,e("li",null,[l("向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 "),W,l(),e("a",Q,[l("@Bohan Yang"),n(t)]),l(" 致敬!")]),Y]),J,e("ul",null,[e("li",null,[l("辛苦的翻译工作开始了, 感谢"),z,l(),e("a",K,[l("@玖柒 Max"),n(t)]),l("和其他所有的翻译大佬们.")]),e("li",null,[e("a",Z,[l("English version"),n(t)])])]),e("h2",$,[e("a",ee,[e("span",null,[l("2021.01.15 "),n(r,null,{default:o(()=>[e("a",le,[l("1.2.2"),n(t)])]),_:1})])])]),ne,e("ul",null,[te,e("li",null,[l("🍉 老师的"),n(s,{to:"/ru/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("大结局, 撒花.")])]),e("h2",oe,[e("a",re,[e("span",null,[l("2021.01.10 "),n(r,null,{default:o(()=>[e("a",ae,[l("1.2.1"),n(t)])]),_:1})])])]),e("ul",null,[e("li",null,[n(s,{to:"/ru/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray!")]),se,e("li",null,[n(s,{to:"/ru/document/level-2/"},{default:o(()=>[l("透明代理")]),_:1}),l("也增加了更多文章.")]),ie,e("li",null,[l("感谢 "),e("a",he,[l("@ricuhkaen"),n(t)]),l(" , "),e("a",_e,[l("@BioniCosmos"),n(t)]),l(", "),e("a",ce,[l("@kirin"),n(t)])])]),ue,e("ul",null,[e("li",null,[l("文档仓库第一个 PR。🎉 "),n(s,{to:"/ru/document/level-2/tproxy.html"},{default:o(()=>[l("透明代理(TProxy)配置教程 ")]),_:1}),l(" ,感谢"),de,l(),e("a",pe,[l("@BioniCosmos"),n(t)])]),fe]),be,e("p",null,[l("【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 "),n(r,null,{default:o(()=>[e("a",ge,[l("1.2.0"),n(t)])]),_:1})]),me,e("ul",null,[xe,e("li",null,[l("Xray 将继续保持前行! 因此 "),e("a",Xe,[l("Xray 需要更多的英雄!!"),n(t)]),l("!")]),e("li",null,[l("PS:请品,请细品"),e("a",Se,[l("release notes"),n(t)]),l("每一句。似乎有一个小秘密小彩蛋 "),ke])]),ye,e("p",null,[l("透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, "),e("a",ve,[l("TG 群"),n(t)]),l("火热测试中")]),e("h2",Te,[e("a",Le,[e("span",null,[l("2020.12.25 "),n(r,null,{default:o(()=>[e("a",De,[l("1.1.5"),n(t)])]),_:1})])])]),Pe,e("ul",null,[Ue,He,Ce,je,e("li",null,[l("kirin 带来了一大波 脚本更新."),e("a",Be,[l("脚本在此"),n(t)])]),Ie]),Ne,e("p",null,[l("因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:"),e("a",Ee,[l("没错你正在看的就是"),n(t)])]),Ve,e("p",null,[l("文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 "),e("a",we,[l("文档的仓库"),n(t)])]),Ge,Re,e("p",null,[l("Xray-core Shadowsocks UDP FullCone 测试版, "),e("a",Oe,[l("TG 群"),n(t)]),l("火热测试中")]),Fe,Me,e("h2",Ae,[e("a",qe,[e("span",null,[l("2020.12.18 "),n(r,null,{default:o(()=>[e("a",We,[l("1.1.4"),n(t)])]),_:1})])])]),Qe,Ye,e("p",null,[l("鉴于日益增长群人数和游戏需求, 开启了"),e("a",Je,[l("TG 游戏群"),n(t)])]),ze,e("p",null,[e("a",Ke,[l("安装脚本 dev 分支"),n(t)]),l("开启, 持续更新功能中.")]),e("h2",Ze,[e("a",$e,[e("span",null,[l("2020.12.11 "),n(r,null,{default:o(()=>[e("a",el,[l("1.1.3"),n(t)])]),_:1})])])]),ll,e("h2",nl,[e("a",tl,[e("span",null,[l("2020.12.06 "),n(r,null,{default:o(()=>[e("a",ol,[l("1.1.2"),n(t)])]),_:1})])])]),rl,e("h2",al,[e("a",sl,[e("span",null,[l("2020.11.25 "),n(r,null,{default:o(()=>[e("a",il,[l("1.0.0"),n(t)])]),_:1})])])]),hl,_l,cl,ul,dl])}const ml=_(d,[["render",pl],["__file","news.html.vue"]]);export{ml as default}; +import{_,r as i,o as c,c as u,a as n,b as e,d as l,w as o,e as a}from"./app-Bw2NG-QJ.js";const d={},p=e("h1",{id:"大史记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#大史记"},[e("span",null,"大史记")])],-1),f=a('

                                        2021.4.6

                                        • VuePress Next.
                                        • With Dark Mode.

                                        2021.4.4

                                        • 本文档迎来的新的首页。
                                        • 本文档迎来了暗黑模式。
                                        • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                                        • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                                        • 🎉🎉🎉
                                        ',4),b={id:"_2021-4-1-v1-4-2",tabindex:"-1"},g={class:"header-anchor",href:"#_2021-4-1-v1-4-2"},m={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.2",target:"_blank",rel:"noopener noreferrer"},x=a('
                                        • 不是愚人节玩笑,今天更新。
                                        • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                                        • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                                        • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                                        2021.3.25

                                        没错还在变。 -_-

                                        2021.3.15

                                        文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        ',5),X={id:"_2021-3-14-v1-4-0",tabindex:"-1"},S={class:"header-anchor",href:"#_2021-3-14-v1-4-0"},k={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.0",target:"_blank",rel:"noopener noreferrer"},y=a("
                                        • Happy Pi-Day!
                                        • 这次是个大更新:
                                          • 为链式代理引入了传输层支持。
                                          • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                                          • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                                          • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                                          • 添加了 FakeDNS。
                                          • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                                        • 还是 VuePress 比较爽啊(
                                        ",1),v={id:"_2021-3-3-1-3-1",tabindex:"-1"},T={class:"header-anchor",href:"#_2021-3-3-1-3-1"},L={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.1",target:"_blank",rel:"noopener noreferrer"},D=e("ul",null,[e("li",null,"这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。"),e("li",null,[l("同时修复了一个会导致 Panic 的 bug。"),e("s",null,"Holmium_认为这是在骗、在偷袭。")]),e("li",null,"修复了几个遗留问题。")],-1),P={id:"_2021-2-14-1-3-0",tabindex:"-1"},U={class:"header-anchor",href:"#_2021-2-14-1-3-0"},H={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.0",target:"_blank",rel:"noopener noreferrer"},C=e("ul",null,[e("li",null,"Happy 🐮 Year 🎉!"),e("li",null,"v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。"),e("li",null,"OHHHHHHHHHHHH!")],-1),j={id:"_2021-01-31-1-2-4",tabindex:"-1"},B={class:"header-anchor",href:"#_2021-01-31-1-2-4"},I={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.4",target:"_blank",rel:"noopener noreferrer"},N=e("ul",null,[e("li",null,"解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。"),e("li",null,"似乎这个版本没有什么改变,但这只是暴风雨前的宁静。"),e("li",null,[l("(没错我就是先知) "),e("blockquote",null,[e("p",null,"你个傻子,你拿的是 UNO 牌。")])])],-1),E=e("h2",{id:"_2021-01-25",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-25"},[e("span",null,"2021.01.25")])],-1),V=e("li",null,[e("a",{href:"../en"},"英文版文档网站"),l("逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!")],-1),w={id:"_2021-01-22-1-2-3",tabindex:"-1"},G={class:"header-anchor",href:"#_2021-01-22-1-2-3"},R={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.3",target:"_blank",rel:"noopener noreferrer"},O=e("li",null,[l("对 SS 协议的支持"),e("strong",null,"又"),l("变强了, 支持单端口多用户!")],-1),F=e("li",null,[l("对 trojan 协议的支持也"),e("strong",null,"又"),l("变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!")],-1),M=e("li",null,[e("em",null,"(VLESS: 嘤嘤嘤)")],-1),A=e("li",null,'UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".',-1),q=e("li",null,"嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.",-1),W=e("img",{src:"https://avatars2.githubusercontent.com/u/8384161?s=32",width:"32px",height:"32px",alt:"a"},null,-1),Q={href:"https://github.com/bohanyang",target:"_blank",rel:"noopener noreferrer"},Y=e("li",null,"其他美味小樱桃, 惯例更新品尝就对啦.",-1),J=a('

                                        2021.01.19

                                        • 一些数字
                                          • 版本发布了 10   个 tag
                                          • 解决掉了 100  个 issue
                                          • 复刻了 300  个 fork
                                          • 点了 2000 个 star
                                          • 群 3000 个 人

                                        2021.01.17

                                        ',3),z=e("img",{src:"https://avatars2.githubusercontent.com/u/60207794?s=32",width:"32px",height:"32px",alt:"a"},null,-1),K={href:"https://github.com/jiuqi9997",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://xtls.github.io/en/",target:"_blank",rel:"noopener noreferrer"},$={id:"_2021-01-15-1-2-2",tabindex:"-1"},ee={class:"header-anchor",href:"#_2021-01-15-1-2-2"},le={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.2",target:"_blank",rel:"noopener noreferrer"},ne=a('
                                        • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                                        • 之前预告的 UUID 修改正式上线.(往下看往下看)
                                        • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                                        • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                                        • 当然还有其他各种小糖果.(更新品尝就对了)
                                        • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                                        2021.01.12

                                        ',2),te=e("li",null,[l("将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. "),e("ul",null,[e("li",null,'客户端写 "id": "我爱 🍉 老师 1314",'),e("li",null,[l('服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 '),e("code",null,"我爱🍉老师1314"),l(" 的 UUID 映射)")])])],-1),oe={id:"_2021-01-10-1-2-1",tabindex:"-1"},re={class:"header-anchor",href:"#_2021-01-10-1-2-1"},ae={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.1",target:"_blank",rel:"noopener noreferrer"},se=e("li",null,"(可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程)",-1),ie=e("li",null,"还有很多细节修改, 文档将会越来越规范!",-1),he={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},ue=a('
                                        • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                                        • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                                        • 日志现在看起来更顺眼.

                                        2021.01.07

                                        • 礼貌和尊重本应是社区不需要明说的准则之一。

                                        2021.01.05

                                        • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        2021.01.03

                                        ',6),de=e("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32px",height:"32px",alt:"a"},null,-1),pe={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},fe=e("li",null,"tg 群突破 2500。",-1),be=e("h2",{id:"_2021-01-01",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-01"},[e("span",null,"2021.01.01")])],-1),ge={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},me=e("p",null,"🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!",-1),xe=a('
                                      28. 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                                      29. (UDP 还会继续增强!)
                                      30. 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                                      31. (不,下面不是广告,是里程碑。)
                                      32. Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                                        • 一人扛起了所有!支持各大主流协议!
                                        • 一骑绝尘的性能!
                                        • 日趋完善的功能!
                                        • 可怕的生命力与社区亲和力!
                                      33. ',5),Xe={href:"https://github.com/XTLS/Xray-core/discussions/56",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},ke=e("s",null,"(啊,有人敲门...我一会和你们说)",-1),ye=e("h2",{id:"_2020-12-29",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-29"},[e("span",null,"2020.12.29")])],-1),ve={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Te={id:"_2020-12-25-1-1-5",tabindex:"-1"},Le={class:"header-anchor",href:"#_2020-12-25-1-1-5"},De={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.5",target:"_blank",rel:"noopener noreferrer"},Pe=e("p",null,"圣诞节快乐!",-1),Ue=e("li",null,"游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone",-1),He=e("li",null,"你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...",-1),Ce=e("li",null,"(VLESS 的 UDP fullcone 和更多增强很快就到!)",-1),je=e("li",null,"无须再担心证书验证被墙,OCSP stapling 已经上线!",-1),Be={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},Ie=e("li",null,"还有更多美味小樱桃!(不用问,更新品尝就对了)",-1),Ne=e("h2",{id:"_2020-12-24",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-24"},[e("span",null,"2020.12.24")])],-1),Ee={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},Ve=e("p",null,"大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)",-1),we={href:"https://github.com/XTLS/XTLS.github.io",target:"_blank",rel:"noopener noreferrer"},Ge=e("p",null,"仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。",-1),Re=e("h2",{id:"_2020-12-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-23"},[e("span",null,"2020.12.23")])],-1),Oe={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Fe=e("h2",{id:"_2020-12-21",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-21"},[e("span",null,"2020.12.21")])],-1),Me=e("ul",null,[e("li",null,"Project X 群人数 2000+"),e("li",null,"群消息(含游戏群) 日均破万")],-1),Ae={id:"_2020-12-18-1-1-4",tabindex:"-1"},qe={class:"header-anchor",href:"#_2020-12-18-1-1-4"},We={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.4",target:"_blank",rel:"noopener noreferrer"},Qe=e("ul",null,[e("li",null,"更低的启动内占用和内存使用优化"),e("li",null,"随意定制的 TLS 提高你的 SSL 评级"),e("li",null,"支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS"),e("li",null,"还有在您路由器上使用的 Splice 最佳使用模式建议")],-1),Ye=e("h2",{id:"_2020-12-17",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-17"},[e("span",null,"2020.12.17")])],-1),Je={href:"https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ",target:"_blank",rel:"noopener noreferrer"},ze=e("h2",{id:"_2020-12-15",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-15"},[e("span",null,"2020.12.15")])],-1),Ke={href:"https://github.com/XTLS/Xray-install/tree/dev",target:"_blank",rel:"noopener noreferrer"},Ze={id:"_2020-12-11-1-1-3",tabindex:"-1"},$e={class:"header-anchor",href:"#_2020-12-11-1-1-3"},el={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.3",target:"_blank",rel:"noopener noreferrer"},ll=e("ul",null,[e("li",null,"完整版本的 REDIRECT 透明代理模式."),e("li",null,"软路由 splice 流控模式的优化建议.")],-1),nl={id:"_2020-12-06-1-1-2",tabindex:"-1"},tl={class:"header-anchor",href:"#_2020-12-06-1-1-2"},ol={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.2",target:"_blank",rel:"noopener noreferrer"},rl=a('
                                        • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                                        • 增强了 API 兼容

                                        2020.12.04

                                        增加 splice 模式

                                        2020.11.27

                                        • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                                        • 登上了 GitHub Trending
                                        • Project X 群人数破千,频道订阅数 500+
                                        ',5),al={id:"_2020-11-25-1-0-0",tabindex:"-1"},sl={class:"header-anchor",href:"#_2020-11-25-1-0-0"},il={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.0.0",target:"_blank",rel:"noopener noreferrer"},hl=e("p",null,"Xray 的第一个版本.",-1),_l=e("ul",null,[e("li",null,"基于 v2ray-core 修改而来,改动较大"),e("li",null,"全面增强, 性能卓越, 完全兼容")],-1),cl=e("h2",{id:"_2020-11-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-11-23"},[e("span",null,"2020.11.23")])],-1),ul=e("p",null,"project X start",-1),dl=e("blockquote",null,[e("p",null,[e("s",null,"梦开始的时候")])],-1);function pl(fl,bl){const h=i("I18nTip"),t=i("ExternalLinkIcon"),r=i("Badge"),s=i("RouterLink");return c(),u("div",null,[p,n(h),f,e("h2",b,[e("a",g,[e("span",null,[l("2021.4.1 "),n(r,null,{default:o(()=>[e("a",m,[l("v1.4.2"),n(t)])]),_:1})])])]),x,e("h2",X,[e("a",S,[e("span",null,[l("2021.3.14 "),n(r,null,{default:o(()=>[e("a",k,[l("v1.4.0"),n(t)])]),_:1})])])]),y,e("h2",v,[e("a",T,[e("span",null,[l("2021.3.3 "),n(r,null,{default:o(()=>[e("a",L,[l("1.3.1"),n(t)])]),_:1})])])]),D,e("h2",P,[e("a",U,[e("span",null,[l("2021.2.14 "),n(r,null,{default:o(()=>[e("a",H,[l("1.3.0"),n(t)])]),_:1})])])]),C,e("h2",j,[e("a",B,[e("span",null,[l("2021.01.31 "),n(r,null,{default:o(()=>[e("a",I,[l("1.2.4"),n(t)])]),_:1})])])]),N,E,e("ul",null,[e("li",null,[l("全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载"),n(s,{to:"/ru/document/level-1/"},{default:o(()=>[l("秘籍第一层")]),_:1}),l("咯...")]),V]),e("h2",w,[e("a",G,[e("span",null,[l("2021.01.22 "),n(r,null,{default:o(()=>[e("a",R,[l("1.2.3"),n(t)])]),_:1})])])]),e("ul",null,[O,F,M,A,q,e("li",null,[l("向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 "),W,l(),e("a",Q,[l("@Bohan Yang"),n(t)]),l(" 致敬!")]),Y]),J,e("ul",null,[e("li",null,[l("辛苦的翻译工作开始了, 感谢"),z,l(),e("a",K,[l("@玖柒 Max"),n(t)]),l("和其他所有的翻译大佬们.")]),e("li",null,[e("a",Z,[l("English version"),n(t)])])]),e("h2",$,[e("a",ee,[e("span",null,[l("2021.01.15 "),n(r,null,{default:o(()=>[e("a",le,[l("1.2.2"),n(t)])]),_:1})])])]),ne,e("ul",null,[te,e("li",null,[l("🍉 老师的"),n(s,{to:"/ru/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("大结局, 撒花.")])]),e("h2",oe,[e("a",re,[e("span",null,[l("2021.01.10 "),n(r,null,{default:o(()=>[e("a",ae,[l("1.2.1"),n(t)])]),_:1})])])]),e("ul",null,[e("li",null,[n(s,{to:"/ru/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray!")]),se,e("li",null,[n(s,{to:"/ru/document/level-2/"},{default:o(()=>[l("透明代理")]),_:1}),l("也增加了更多文章.")]),ie,e("li",null,[l("感谢 "),e("a",he,[l("@ricuhkaen"),n(t)]),l(" , "),e("a",_e,[l("@BioniCosmos"),n(t)]),l(", "),e("a",ce,[l("@kirin"),n(t)])])]),ue,e("ul",null,[e("li",null,[l("文档仓库第一个 PR。🎉 "),n(s,{to:"/ru/document/level-2/tproxy.html"},{default:o(()=>[l("透明代理(TProxy)配置教程 ")]),_:1}),l(" ,感谢"),de,l(),e("a",pe,[l("@BioniCosmos"),n(t)])]),fe]),be,e("p",null,[l("【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 "),n(r,null,{default:o(()=>[e("a",ge,[l("1.2.0"),n(t)])]),_:1})]),me,e("ul",null,[xe,e("li",null,[l("Xray 将继续保持前行! 因此 "),e("a",Xe,[l("Xray 需要更多的英雄!!"),n(t)]),l("!")]),e("li",null,[l("PS:请品,请细品"),e("a",Se,[l("release notes"),n(t)]),l("每一句。似乎有一个小秘密小彩蛋 "),ke])]),ye,e("p",null,[l("透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, "),e("a",ve,[l("TG 群"),n(t)]),l("火热测试中")]),e("h2",Te,[e("a",Le,[e("span",null,[l("2020.12.25 "),n(r,null,{default:o(()=>[e("a",De,[l("1.1.5"),n(t)])]),_:1})])])]),Pe,e("ul",null,[Ue,He,Ce,je,e("li",null,[l("kirin 带来了一大波 脚本更新."),e("a",Be,[l("脚本在此"),n(t)])]),Ie]),Ne,e("p",null,[l("因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:"),e("a",Ee,[l("没错你正在看的就是"),n(t)])]),Ve,e("p",null,[l("文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 "),e("a",we,[l("文档的仓库"),n(t)])]),Ge,Re,e("p",null,[l("Xray-core Shadowsocks UDP FullCone 测试版, "),e("a",Oe,[l("TG 群"),n(t)]),l("火热测试中")]),Fe,Me,e("h2",Ae,[e("a",qe,[e("span",null,[l("2020.12.18 "),n(r,null,{default:o(()=>[e("a",We,[l("1.1.4"),n(t)])]),_:1})])])]),Qe,Ye,e("p",null,[l("鉴于日益增长群人数和游戏需求, 开启了"),e("a",Je,[l("TG 游戏群"),n(t)])]),ze,e("p",null,[e("a",Ke,[l("安装脚本 dev 分支"),n(t)]),l("开启, 持续更新功能中.")]),e("h2",Ze,[e("a",$e,[e("span",null,[l("2020.12.11 "),n(r,null,{default:o(()=>[e("a",el,[l("1.1.3"),n(t)])]),_:1})])])]),ll,e("h2",nl,[e("a",tl,[e("span",null,[l("2020.12.06 "),n(r,null,{default:o(()=>[e("a",ol,[l("1.1.2"),n(t)])]),_:1})])])]),rl,e("h2",al,[e("a",sl,[e("span",null,[l("2020.11.25 "),n(r,null,{default:o(()=>[e("a",il,[l("1.0.0"),n(t)])]),_:1})])])]),hl,_l,cl,ul,dl])}const ml=_(d,[["render",pl],["__file","news.html.vue"]]);export{ml as default}; diff --git a/assets/news.html-CD7xPbzv.js b/assets/news.html-B87U8xn2.js similarity index 99% rename from assets/news.html-CD7xPbzv.js rename to assets/news.html-B87U8xn2.js index 016444f87e..e4746ce449 100644 --- a/assets/news.html-CD7xPbzv.js +++ b/assets/news.html-B87U8xn2.js @@ -1 +1 @@ -import{_,r as i,o as c,c as u,a as n,b as e,d as l,w as o,e as r}from"./app-5SoadDYS.js";const d={},p=e("h1",{id:"大史记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#大史记"},[e("span",null,"大史记")])],-1),f=r('

                                        2021.4.6

                                        • VuePress Next.
                                        • With Dark Mode.

                                        2021.4.4

                                        • 本文档迎来的新的首页。
                                        • 本文档迎来了暗黑模式。
                                        • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                                        • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                                        • 🎉🎉🎉
                                        ',4),b={id:"_2021-4-1-v1-4-2",tabindex:"-1"},g={class:"header-anchor",href:"#_2021-4-1-v1-4-2"},m={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.2",target:"_blank",rel:"noopener noreferrer"},x=r('
                                        • 不是愚人节玩笑,今天更新。
                                        • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                                        • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                                        • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                                        2021.3.25

                                        没错还在变。 -_-

                                        2021.3.15

                                        文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        ',5),X={id:"_2021-3-14-v1-4-0",tabindex:"-1"},S={class:"header-anchor",href:"#_2021-3-14-v1-4-0"},k={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.0",target:"_blank",rel:"noopener noreferrer"},y=r("
                                        • Happy Pi-Day!
                                        • 这次是个大更新:
                                          • 为链式代理引入了传输层支持。
                                          • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                                          • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                                          • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                                          • 添加了 FakeDNS。
                                          • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                                        • 还是 VuePress 比较爽啊(
                                        ",1),v={id:"_2021-3-3-1-3-1",tabindex:"-1"},T={class:"header-anchor",href:"#_2021-3-3-1-3-1"},L={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.1",target:"_blank",rel:"noopener noreferrer"},D=e("ul",null,[e("li",null,"这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。"),e("li",null,[l("同时修复了一个会导致 Panic 的 bug。"),e("s",null,"Holmium_认为这是在骗、在偷袭。")]),e("li",null,"修复了几个遗留问题。")],-1),P={id:"_2021-2-14-1-3-0",tabindex:"-1"},U={class:"header-anchor",href:"#_2021-2-14-1-3-0"},H={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.0",target:"_blank",rel:"noopener noreferrer"},C=e("ul",null,[e("li",null,"Happy 🐮 Year 🎉!"),e("li",null,"v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。"),e("li",null,"OHHHHHHHHHHHH!")],-1),j={id:"_2021-01-31-1-2-4",tabindex:"-1"},B={class:"header-anchor",href:"#_2021-01-31-1-2-4"},I={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.4",target:"_blank",rel:"noopener noreferrer"},N=e("ul",null,[e("li",null,"解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。"),e("li",null,"似乎这个版本没有什么改变,但这只是暴风雨前的宁静。"),e("li",null,[l("(没错我就是先知) "),e("blockquote",null,[e("p",null,"你个傻子,你拿的是 UNO 牌。")])])],-1),E=e("h2",{id:"_2021-01-25",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-25"},[e("span",null,"2021.01.25")])],-1),V=e("li",null,[e("a",{href:"../en"},"英文版文档网站"),l("逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!")],-1),w={id:"_2021-01-22-1-2-3",tabindex:"-1"},G={class:"header-anchor",href:"#_2021-01-22-1-2-3"},R={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.3",target:"_blank",rel:"noopener noreferrer"},O=e("li",null,[l("对 SS 协议的支持"),e("strong",null,"又"),l("变强了, 支持单端口多用户!")],-1),F=e("li",null,[l("对 trojan 协议的支持也"),e("strong",null,"又"),l("变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!")],-1),M=e("li",null,[e("em",null,"(VLESS: 嘤嘤嘤)")],-1),A=e("li",null,'UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".',-1),q=e("li",null,"嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.",-1),W=e("img",{src:"https://avatars2.githubusercontent.com/u/8384161?s=32",width:"32px",height:"32px",alt:"a"},null,-1),Q={href:"https://github.com/bohanyang",target:"_blank",rel:"noopener noreferrer"},Y=e("li",null,"其他美味小樱桃, 惯例更新品尝就对啦.",-1),J=r('

                                        2021.01.19

                                        • 一些数字
                                          • 版本发布了 10   个 tag
                                          • 解决掉了 100  个 issue
                                          • 复刻了 300  个 fork
                                          • 点了 2000 个 star
                                          • 群 3000 个 人

                                        2021.01.17

                                        ',3),z=e("img",{src:"https://avatars2.githubusercontent.com/u/60207794?s=32",width:"32px",height:"32px",alt:"a"},null,-1),K={href:"https://github.com/jiuqi9997",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://xtls.github.io/en/",target:"_blank",rel:"noopener noreferrer"},$={id:"_2021-01-15-1-2-2",tabindex:"-1"},ee={class:"header-anchor",href:"#_2021-01-15-1-2-2"},le={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.2",target:"_blank",rel:"noopener noreferrer"},ne=r('
                                        • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                                        • 之前预告的 UUID 修改正式上线.(往下看往下看)
                                        • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                                        • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                                        • 当然还有其他各种小糖果.(更新品尝就对了)
                                        • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                                        2021.01.12

                                        ',2),te=e("li",null,[l("将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. "),e("ul",null,[e("li",null,'客户端写 "id": "我爱 🍉 老师 1314",'),e("li",null,[l('服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 '),e("code",null,"我爱🍉老师1314"),l(" 的 UUID 映射)")])])],-1),oe={id:"_2021-01-10-1-2-1",tabindex:"-1"},ae={class:"header-anchor",href:"#_2021-01-10-1-2-1"},re={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.1",target:"_blank",rel:"noopener noreferrer"},se=e("li",null,"(可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程)",-1),ie=e("li",null,"还有很多细节修改, 文档将会越来越规范!",-1),he={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},ue=r('
                                        • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                                        • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                                        • 日志现在看起来更顺眼.

                                        2021.01.07

                                        • 礼貌和尊重本应是社区不需要明说的准则之一。

                                        2021.01.05

                                        • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        2021.01.03

                                        ',6),de=e("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32px",height:"32px",alt:"a"},null,-1),pe={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},fe=e("li",null,"tg 群突破 2500。",-1),be=e("h2",{id:"_2021-01-01",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-01"},[e("span",null,"2021.01.01")])],-1),ge={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},me=e("p",null,"🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!",-1),xe=r('
                                      34. 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                                      35. (UDP 还会继续增强!)
                                      36. 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                                      37. (不,下面不是广告,是里程碑。)
                                      38. Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                                        • 一人扛起了所有!支持各大主流协议!
                                        • 一骑绝尘的性能!
                                        • 日趋完善的功能!
                                        • 可怕的生命力与社区亲和力!
                                      39. ',5),Xe={href:"https://github.com/XTLS/Xray-core/discussions/56",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},ke=e("s",null,"(啊,有人敲门...我一会和你们说)",-1),ye=e("h2",{id:"_2020-12-29",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-29"},[e("span",null,"2020.12.29")])],-1),ve={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Te={id:"_2020-12-25-1-1-5",tabindex:"-1"},Le={class:"header-anchor",href:"#_2020-12-25-1-1-5"},De={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.5",target:"_blank",rel:"noopener noreferrer"},Pe=e("p",null,"圣诞节快乐!",-1),Ue=e("li",null,"游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone",-1),He=e("li",null,"你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...",-1),Ce=e("li",null,"(VLESS 的 UDP fullcone 和更多增强很快就到!)",-1),je=e("li",null,"无须再担心证书验证被墙,OCSP stapling 已经上线!",-1),Be={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},Ie=e("li",null,"还有更多美味小樱桃!(不用问,更新品尝就对了)",-1),Ne=e("h2",{id:"_2020-12-24",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-24"},[e("span",null,"2020.12.24")])],-1),Ee={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},Ve=e("p",null,"大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)",-1),we={href:"https://github.com/XTLS/XTLS.github.io",target:"_blank",rel:"noopener noreferrer"},Ge=e("p",null,"仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。",-1),Re=e("h2",{id:"_2020-12-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-23"},[e("span",null,"2020.12.23")])],-1),Oe={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Fe=e("h2",{id:"_2020-12-21",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-21"},[e("span",null,"2020.12.21")])],-1),Me=e("ul",null,[e("li",null,"Project X 群人数 2000+"),e("li",null,"群消息(含游戏群) 日均破万")],-1),Ae={id:"_2020-12-18-1-1-4",tabindex:"-1"},qe={class:"header-anchor",href:"#_2020-12-18-1-1-4"},We={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.4",target:"_blank",rel:"noopener noreferrer"},Qe=e("ul",null,[e("li",null,"更低的启动内占用和内存使用优化"),e("li",null,"随意定制的 TLS 提高你的 SSL 评级"),e("li",null,"支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS"),e("li",null,"还有在您路由器上使用的 Splice 最佳使用模式建议")],-1),Ye=e("h2",{id:"_2020-12-17",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-17"},[e("span",null,"2020.12.17")])],-1),Je={href:"https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ",target:"_blank",rel:"noopener noreferrer"},ze=e("h2",{id:"_2020-12-15",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-15"},[e("span",null,"2020.12.15")])],-1),Ke={href:"https://github.com/XTLS/Xray-install/tree/dev",target:"_blank",rel:"noopener noreferrer"},Ze={id:"_2020-12-11-1-1-3",tabindex:"-1"},$e={class:"header-anchor",href:"#_2020-12-11-1-1-3"},el={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.3",target:"_blank",rel:"noopener noreferrer"},ll=e("ul",null,[e("li",null,"完整版本的 REDIRECT 透明代理模式."),e("li",null,"软路由 splice 流控模式的优化建议.")],-1),nl={id:"_2020-12-06-1-1-2",tabindex:"-1"},tl={class:"header-anchor",href:"#_2020-12-06-1-1-2"},ol={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.2",target:"_blank",rel:"noopener noreferrer"},al=r('
                                        • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                                        • 增强了 API 兼容

                                        2020.12.04

                                        增加 splice 模式

                                        2020.11.27

                                        • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                                        • 登上了 GitHub Trending
                                        • Project X 群人数破千,频道订阅数 500+
                                        ',5),rl={id:"_2020-11-25-1-0-0",tabindex:"-1"},sl={class:"header-anchor",href:"#_2020-11-25-1-0-0"},il={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.0.0",target:"_blank",rel:"noopener noreferrer"},hl=e("p",null,"Xray 的第一个版本.",-1),_l=e("ul",null,[e("li",null,"基于 v2ray-core 修改而来,改动较大"),e("li",null,"全面增强, 性能卓越, 完全兼容")],-1),cl=e("h2",{id:"_2020-11-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-11-23"},[e("span",null,"2020.11.23")])],-1),ul=e("p",null,"project X start",-1),dl=e("blockquote",null,[e("p",null,[e("s",null,"梦开始的时候")])],-1);function pl(fl,bl){const h=i("I18nTip"),t=i("ExternalLinkIcon"),a=i("Badge"),s=i("RouterLink");return c(),u("div",null,[p,n(h),f,e("h2",b,[e("a",g,[e("span",null,[l("2021.4.1 "),n(a,null,{default:o(()=>[e("a",m,[l("v1.4.2"),n(t)])]),_:1})])])]),x,e("h2",X,[e("a",S,[e("span",null,[l("2021.3.14 "),n(a,null,{default:o(()=>[e("a",k,[l("v1.4.0"),n(t)])]),_:1})])])]),y,e("h2",v,[e("a",T,[e("span",null,[l("2021.3.3 "),n(a,null,{default:o(()=>[e("a",L,[l("1.3.1"),n(t)])]),_:1})])])]),D,e("h2",P,[e("a",U,[e("span",null,[l("2021.2.14 "),n(a,null,{default:o(()=>[e("a",H,[l("1.3.0"),n(t)])]),_:1})])])]),C,e("h2",j,[e("a",B,[e("span",null,[l("2021.01.31 "),n(a,null,{default:o(()=>[e("a",I,[l("1.2.4"),n(t)])]),_:1})])])]),N,E,e("ul",null,[e("li",null,[l("全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载"),n(s,{to:"/en/document/level-1/"},{default:o(()=>[l("秘籍第一层")]),_:1}),l("咯...")]),V]),e("h2",w,[e("a",G,[e("span",null,[l("2021.01.22 "),n(a,null,{default:o(()=>[e("a",R,[l("1.2.3"),n(t)])]),_:1})])])]),e("ul",null,[O,F,M,A,q,e("li",null,[l("向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 "),W,l(),e("a",Q,[l("@Bohan Yang"),n(t)]),l(" 致敬!")]),Y]),J,e("ul",null,[e("li",null,[l("辛苦的翻译工作开始了, 感谢"),z,l(),e("a",K,[l("@玖柒 Max"),n(t)]),l("和其他所有的翻译大佬们.")]),e("li",null,[e("a",Z,[l("English version"),n(t)])])]),e("h2",$,[e("a",ee,[e("span",null,[l("2021.01.15 "),n(a,null,{default:o(()=>[e("a",le,[l("1.2.2"),n(t)])]),_:1})])])]),ne,e("ul",null,[te,e("li",null,[l("🍉 老师的"),n(s,{to:"/en/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("大结局, 撒花.")])]),e("h2",oe,[e("a",ae,[e("span",null,[l("2021.01.10 "),n(a,null,{default:o(()=>[e("a",re,[l("1.2.1"),n(t)])]),_:1})])])]),e("ul",null,[e("li",null,[n(s,{to:"/en/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray!")]),se,e("li",null,[n(s,{to:"/en/document/level-2/"},{default:o(()=>[l("透明代理")]),_:1}),l("也增加了更多文章.")]),ie,e("li",null,[l("感谢 "),e("a",he,[l("@ricuhkaen"),n(t)]),l(" , "),e("a",_e,[l("@BioniCosmos"),n(t)]),l(", "),e("a",ce,[l("@kirin"),n(t)])])]),ue,e("ul",null,[e("li",null,[l("文档仓库第一个 PR。🎉 "),n(s,{to:"/en/document/level-2/tproxy.html"},{default:o(()=>[l("透明代理(TProxy)配置教程 ")]),_:1}),l(" ,感谢"),de,l(),e("a",pe,[l("@BioniCosmos"),n(t)])]),fe]),be,e("p",null,[l("【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 "),n(a,null,{default:o(()=>[e("a",ge,[l("1.2.0"),n(t)])]),_:1})]),me,e("ul",null,[xe,e("li",null,[l("Xray 将继续保持前行! 因此 "),e("a",Xe,[l("Xray 需要更多的英雄!!"),n(t)]),l("!")]),e("li",null,[l("PS:请品,请细品"),e("a",Se,[l("release notes"),n(t)]),l("每一句。似乎有一个小秘密小彩蛋 "),ke])]),ye,e("p",null,[l("透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, "),e("a",ve,[l("TG 群"),n(t)]),l("火热测试中")]),e("h2",Te,[e("a",Le,[e("span",null,[l("2020.12.25 "),n(a,null,{default:o(()=>[e("a",De,[l("1.1.5"),n(t)])]),_:1})])])]),Pe,e("ul",null,[Ue,He,Ce,je,e("li",null,[l("kirin 带来了一大波 脚本更新."),e("a",Be,[l("脚本在此"),n(t)])]),Ie]),Ne,e("p",null,[l("因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:"),e("a",Ee,[l("没错你正在看的就是"),n(t)])]),Ve,e("p",null,[l("文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 "),e("a",we,[l("文档的仓库"),n(t)])]),Ge,Re,e("p",null,[l("Xray-core Shadowsocks UDP FullCone 测试版, "),e("a",Oe,[l("TG 群"),n(t)]),l("火热测试中")]),Fe,Me,e("h2",Ae,[e("a",qe,[e("span",null,[l("2020.12.18 "),n(a,null,{default:o(()=>[e("a",We,[l("1.1.4"),n(t)])]),_:1})])])]),Qe,Ye,e("p",null,[l("鉴于日益增长群人数和游戏需求, 开启了"),e("a",Je,[l("TG 游戏群"),n(t)])]),ze,e("p",null,[e("a",Ke,[l("安装脚本 dev 分支"),n(t)]),l("开启, 持续更新功能中.")]),e("h2",Ze,[e("a",$e,[e("span",null,[l("2020.12.11 "),n(a,null,{default:o(()=>[e("a",el,[l("1.1.3"),n(t)])]),_:1})])])]),ll,e("h2",nl,[e("a",tl,[e("span",null,[l("2020.12.06 "),n(a,null,{default:o(()=>[e("a",ol,[l("1.1.2"),n(t)])]),_:1})])])]),al,e("h2",rl,[e("a",sl,[e("span",null,[l("2020.11.25 "),n(a,null,{default:o(()=>[e("a",il,[l("1.0.0"),n(t)])]),_:1})])])]),hl,_l,cl,ul,dl])}const ml=_(d,[["render",pl],["__file","news.html.vue"]]);export{ml as default}; +import{_,r as i,o as c,c as u,a as n,b as e,d as l,w as o,e as r}from"./app-Bw2NG-QJ.js";const d={},p=e("h1",{id:"大史记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#大史记"},[e("span",null,"大史记")])],-1),f=r('

                                        2021.4.6

                                        • VuePress Next.
                                        • With Dark Mode.

                                        2021.4.4

                                        • 本文档迎来的新的首页。
                                        • 本文档迎来了暗黑模式。
                                        • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                                        • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                                        • 🎉🎉🎉
                                        ',4),b={id:"_2021-4-1-v1-4-2",tabindex:"-1"},g={class:"header-anchor",href:"#_2021-4-1-v1-4-2"},m={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.2",target:"_blank",rel:"noopener noreferrer"},x=r('
                                        • 不是愚人节玩笑,今天更新。
                                        • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                                        • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                                        • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                                        2021.3.25

                                        没错还在变。 -_-

                                        2021.3.15

                                        文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        ',5),X={id:"_2021-3-14-v1-4-0",tabindex:"-1"},S={class:"header-anchor",href:"#_2021-3-14-v1-4-0"},k={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.0",target:"_blank",rel:"noopener noreferrer"},y=r("
                                        • Happy Pi-Day!
                                        • 这次是个大更新:
                                          • 为链式代理引入了传输层支持。
                                          • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                                          • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                                          • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                                          • 添加了 FakeDNS。
                                          • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                                        • 还是 VuePress 比较爽啊(
                                        ",1),v={id:"_2021-3-3-1-3-1",tabindex:"-1"},T={class:"header-anchor",href:"#_2021-3-3-1-3-1"},L={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.1",target:"_blank",rel:"noopener noreferrer"},D=e("ul",null,[e("li",null,"这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。"),e("li",null,[l("同时修复了一个会导致 Panic 的 bug。"),e("s",null,"Holmium_认为这是在骗、在偷袭。")]),e("li",null,"修复了几个遗留问题。")],-1),P={id:"_2021-2-14-1-3-0",tabindex:"-1"},U={class:"header-anchor",href:"#_2021-2-14-1-3-0"},H={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.0",target:"_blank",rel:"noopener noreferrer"},C=e("ul",null,[e("li",null,"Happy 🐮 Year 🎉!"),e("li",null,"v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。"),e("li",null,"OHHHHHHHHHHHH!")],-1),j={id:"_2021-01-31-1-2-4",tabindex:"-1"},B={class:"header-anchor",href:"#_2021-01-31-1-2-4"},I={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.4",target:"_blank",rel:"noopener noreferrer"},N=e("ul",null,[e("li",null,"解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。"),e("li",null,"似乎这个版本没有什么改变,但这只是暴风雨前的宁静。"),e("li",null,[l("(没错我就是先知) "),e("blockquote",null,[e("p",null,"你个傻子,你拿的是 UNO 牌。")])])],-1),E=e("h2",{id:"_2021-01-25",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-25"},[e("span",null,"2021.01.25")])],-1),V=e("li",null,[e("a",{href:"../en"},"英文版文档网站"),l("逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!")],-1),w={id:"_2021-01-22-1-2-3",tabindex:"-1"},G={class:"header-anchor",href:"#_2021-01-22-1-2-3"},R={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.3",target:"_blank",rel:"noopener noreferrer"},O=e("li",null,[l("对 SS 协议的支持"),e("strong",null,"又"),l("变强了, 支持单端口多用户!")],-1),F=e("li",null,[l("对 trojan 协议的支持也"),e("strong",null,"又"),l("变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!")],-1),M=e("li",null,[e("em",null,"(VLESS: 嘤嘤嘤)")],-1),A=e("li",null,'UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".',-1),q=e("li",null,"嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.",-1),W=e("img",{src:"https://avatars2.githubusercontent.com/u/8384161?s=32",width:"32px",height:"32px",alt:"a"},null,-1),Q={href:"https://github.com/bohanyang",target:"_blank",rel:"noopener noreferrer"},Y=e("li",null,"其他美味小樱桃, 惯例更新品尝就对啦.",-1),J=r('

                                        2021.01.19

                                        • 一些数字
                                          • 版本发布了 10   个 tag
                                          • 解决掉了 100  个 issue
                                          • 复刻了 300  个 fork
                                          • 点了 2000 个 star
                                          • 群 3000 个 人

                                        2021.01.17

                                        ',3),z=e("img",{src:"https://avatars2.githubusercontent.com/u/60207794?s=32",width:"32px",height:"32px",alt:"a"},null,-1),K={href:"https://github.com/jiuqi9997",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://xtls.github.io/en/",target:"_blank",rel:"noopener noreferrer"},$={id:"_2021-01-15-1-2-2",tabindex:"-1"},ee={class:"header-anchor",href:"#_2021-01-15-1-2-2"},le={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.2",target:"_blank",rel:"noopener noreferrer"},ne=r('
                                        • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                                        • 之前预告的 UUID 修改正式上线.(往下看往下看)
                                        • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                                        • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                                        • 当然还有其他各种小糖果.(更新品尝就对了)
                                        • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                                        2021.01.12

                                        ',2),te=e("li",null,[l("将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. "),e("ul",null,[e("li",null,'客户端写 "id": "我爱 🍉 老师 1314",'),e("li",null,[l('服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 '),e("code",null,"我爱🍉老师1314"),l(" 的 UUID 映射)")])])],-1),oe={id:"_2021-01-10-1-2-1",tabindex:"-1"},ae={class:"header-anchor",href:"#_2021-01-10-1-2-1"},re={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.1",target:"_blank",rel:"noopener noreferrer"},se=e("li",null,"(可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程)",-1),ie=e("li",null,"还有很多细节修改, 文档将会越来越规范!",-1),he={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},ue=r('
                                        • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                                        • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                                        • 日志现在看起来更顺眼.

                                        2021.01.07

                                        • 礼貌和尊重本应是社区不需要明说的准则之一。

                                        2021.01.05

                                        • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        2021.01.03

                                        ',6),de=e("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32px",height:"32px",alt:"a"},null,-1),pe={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},fe=e("li",null,"tg 群突破 2500。",-1),be=e("h2",{id:"_2021-01-01",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-01"},[e("span",null,"2021.01.01")])],-1),ge={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},me=e("p",null,"🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!",-1),xe=r('
                                      40. 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                                      41. (UDP 还会继续增强!)
                                      42. 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                                      43. (不,下面不是广告,是里程碑。)
                                      44. Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                                        • 一人扛起了所有!支持各大主流协议!
                                        • 一骑绝尘的性能!
                                        • 日趋完善的功能!
                                        • 可怕的生命力与社区亲和力!
                                      45. ',5),Xe={href:"https://github.com/XTLS/Xray-core/discussions/56",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},ke=e("s",null,"(啊,有人敲门...我一会和你们说)",-1),ye=e("h2",{id:"_2020-12-29",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-29"},[e("span",null,"2020.12.29")])],-1),ve={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Te={id:"_2020-12-25-1-1-5",tabindex:"-1"},Le={class:"header-anchor",href:"#_2020-12-25-1-1-5"},De={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.5",target:"_blank",rel:"noopener noreferrer"},Pe=e("p",null,"圣诞节快乐!",-1),Ue=e("li",null,"游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone",-1),He=e("li",null,"你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...",-1),Ce=e("li",null,"(VLESS 的 UDP fullcone 和更多增强很快就到!)",-1),je=e("li",null,"无须再担心证书验证被墙,OCSP stapling 已经上线!",-1),Be={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},Ie=e("li",null,"还有更多美味小樱桃!(不用问,更新品尝就对了)",-1),Ne=e("h2",{id:"_2020-12-24",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-24"},[e("span",null,"2020.12.24")])],-1),Ee={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},Ve=e("p",null,"大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)",-1),we={href:"https://github.com/XTLS/XTLS.github.io",target:"_blank",rel:"noopener noreferrer"},Ge=e("p",null,"仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。",-1),Re=e("h2",{id:"_2020-12-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-23"},[e("span",null,"2020.12.23")])],-1),Oe={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Fe=e("h2",{id:"_2020-12-21",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-21"},[e("span",null,"2020.12.21")])],-1),Me=e("ul",null,[e("li",null,"Project X 群人数 2000+"),e("li",null,"群消息(含游戏群) 日均破万")],-1),Ae={id:"_2020-12-18-1-1-4",tabindex:"-1"},qe={class:"header-anchor",href:"#_2020-12-18-1-1-4"},We={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.4",target:"_blank",rel:"noopener noreferrer"},Qe=e("ul",null,[e("li",null,"更低的启动内占用和内存使用优化"),e("li",null,"随意定制的 TLS 提高你的 SSL 评级"),e("li",null,"支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS"),e("li",null,"还有在您路由器上使用的 Splice 最佳使用模式建议")],-1),Ye=e("h2",{id:"_2020-12-17",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-17"},[e("span",null,"2020.12.17")])],-1),Je={href:"https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ",target:"_blank",rel:"noopener noreferrer"},ze=e("h2",{id:"_2020-12-15",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-15"},[e("span",null,"2020.12.15")])],-1),Ke={href:"https://github.com/XTLS/Xray-install/tree/dev",target:"_blank",rel:"noopener noreferrer"},Ze={id:"_2020-12-11-1-1-3",tabindex:"-1"},$e={class:"header-anchor",href:"#_2020-12-11-1-1-3"},el={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.3",target:"_blank",rel:"noopener noreferrer"},ll=e("ul",null,[e("li",null,"完整版本的 REDIRECT 透明代理模式."),e("li",null,"软路由 splice 流控模式的优化建议.")],-1),nl={id:"_2020-12-06-1-1-2",tabindex:"-1"},tl={class:"header-anchor",href:"#_2020-12-06-1-1-2"},ol={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.2",target:"_blank",rel:"noopener noreferrer"},al=r('
                                        • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                                        • 增强了 API 兼容

                                        2020.12.04

                                        增加 splice 模式

                                        2020.11.27

                                        • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                                        • 登上了 GitHub Trending
                                        • Project X 群人数破千,频道订阅数 500+
                                        ',5),rl={id:"_2020-11-25-1-0-0",tabindex:"-1"},sl={class:"header-anchor",href:"#_2020-11-25-1-0-0"},il={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.0.0",target:"_blank",rel:"noopener noreferrer"},hl=e("p",null,"Xray 的第一个版本.",-1),_l=e("ul",null,[e("li",null,"基于 v2ray-core 修改而来,改动较大"),e("li",null,"全面增强, 性能卓越, 完全兼容")],-1),cl=e("h2",{id:"_2020-11-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-11-23"},[e("span",null,"2020.11.23")])],-1),ul=e("p",null,"project X start",-1),dl=e("blockquote",null,[e("p",null,[e("s",null,"梦开始的时候")])],-1);function pl(fl,bl){const h=i("I18nTip"),t=i("ExternalLinkIcon"),a=i("Badge"),s=i("RouterLink");return c(),u("div",null,[p,n(h),f,e("h2",b,[e("a",g,[e("span",null,[l("2021.4.1 "),n(a,null,{default:o(()=>[e("a",m,[l("v1.4.2"),n(t)])]),_:1})])])]),x,e("h2",X,[e("a",S,[e("span",null,[l("2021.3.14 "),n(a,null,{default:o(()=>[e("a",k,[l("v1.4.0"),n(t)])]),_:1})])])]),y,e("h2",v,[e("a",T,[e("span",null,[l("2021.3.3 "),n(a,null,{default:o(()=>[e("a",L,[l("1.3.1"),n(t)])]),_:1})])])]),D,e("h2",P,[e("a",U,[e("span",null,[l("2021.2.14 "),n(a,null,{default:o(()=>[e("a",H,[l("1.3.0"),n(t)])]),_:1})])])]),C,e("h2",j,[e("a",B,[e("span",null,[l("2021.01.31 "),n(a,null,{default:o(()=>[e("a",I,[l("1.2.4"),n(t)])]),_:1})])])]),N,E,e("ul",null,[e("li",null,[l("全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载"),n(s,{to:"/en/document/level-1/"},{default:o(()=>[l("秘籍第一层")]),_:1}),l("咯...")]),V]),e("h2",w,[e("a",G,[e("span",null,[l("2021.01.22 "),n(a,null,{default:o(()=>[e("a",R,[l("1.2.3"),n(t)])]),_:1})])])]),e("ul",null,[O,F,M,A,q,e("li",null,[l("向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 "),W,l(),e("a",Q,[l("@Bohan Yang"),n(t)]),l(" 致敬!")]),Y]),J,e("ul",null,[e("li",null,[l("辛苦的翻译工作开始了, 感谢"),z,l(),e("a",K,[l("@玖柒 Max"),n(t)]),l("和其他所有的翻译大佬们.")]),e("li",null,[e("a",Z,[l("English version"),n(t)])])]),e("h2",$,[e("a",ee,[e("span",null,[l("2021.01.15 "),n(a,null,{default:o(()=>[e("a",le,[l("1.2.2"),n(t)])]),_:1})])])]),ne,e("ul",null,[te,e("li",null,[l("🍉 老师的"),n(s,{to:"/en/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("大结局, 撒花.")])]),e("h2",oe,[e("a",ae,[e("span",null,[l("2021.01.10 "),n(a,null,{default:o(()=>[e("a",re,[l("1.2.1"),n(t)])]),_:1})])])]),e("ul",null,[e("li",null,[n(s,{to:"/en/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray!")]),se,e("li",null,[n(s,{to:"/en/document/level-2/"},{default:o(()=>[l("透明代理")]),_:1}),l("也增加了更多文章.")]),ie,e("li",null,[l("感谢 "),e("a",he,[l("@ricuhkaen"),n(t)]),l(" , "),e("a",_e,[l("@BioniCosmos"),n(t)]),l(", "),e("a",ce,[l("@kirin"),n(t)])])]),ue,e("ul",null,[e("li",null,[l("文档仓库第一个 PR。🎉 "),n(s,{to:"/en/document/level-2/tproxy.html"},{default:o(()=>[l("透明代理(TProxy)配置教程 ")]),_:1}),l(" ,感谢"),de,l(),e("a",pe,[l("@BioniCosmos"),n(t)])]),fe]),be,e("p",null,[l("【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 "),n(a,null,{default:o(()=>[e("a",ge,[l("1.2.0"),n(t)])]),_:1})]),me,e("ul",null,[xe,e("li",null,[l("Xray 将继续保持前行! 因此 "),e("a",Xe,[l("Xray 需要更多的英雄!!"),n(t)]),l("!")]),e("li",null,[l("PS:请品,请细品"),e("a",Se,[l("release notes"),n(t)]),l("每一句。似乎有一个小秘密小彩蛋 "),ke])]),ye,e("p",null,[l("透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, "),e("a",ve,[l("TG 群"),n(t)]),l("火热测试中")]),e("h2",Te,[e("a",Le,[e("span",null,[l("2020.12.25 "),n(a,null,{default:o(()=>[e("a",De,[l("1.1.5"),n(t)])]),_:1})])])]),Pe,e("ul",null,[Ue,He,Ce,je,e("li",null,[l("kirin 带来了一大波 脚本更新."),e("a",Be,[l("脚本在此"),n(t)])]),Ie]),Ne,e("p",null,[l("因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:"),e("a",Ee,[l("没错你正在看的就是"),n(t)])]),Ve,e("p",null,[l("文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 "),e("a",we,[l("文档的仓库"),n(t)])]),Ge,Re,e("p",null,[l("Xray-core Shadowsocks UDP FullCone 测试版, "),e("a",Oe,[l("TG 群"),n(t)]),l("火热测试中")]),Fe,Me,e("h2",Ae,[e("a",qe,[e("span",null,[l("2020.12.18 "),n(a,null,{default:o(()=>[e("a",We,[l("1.1.4"),n(t)])]),_:1})])])]),Qe,Ye,e("p",null,[l("鉴于日益增长群人数和游戏需求, 开启了"),e("a",Je,[l("TG 游戏群"),n(t)])]),ze,e("p",null,[e("a",Ke,[l("安装脚本 dev 分支"),n(t)]),l("开启, 持续更新功能中.")]),e("h2",Ze,[e("a",$e,[e("span",null,[l("2020.12.11 "),n(a,null,{default:o(()=>[e("a",el,[l("1.1.3"),n(t)])]),_:1})])])]),ll,e("h2",nl,[e("a",tl,[e("span",null,[l("2020.12.06 "),n(a,null,{default:o(()=>[e("a",ol,[l("1.1.2"),n(t)])]),_:1})])])]),al,e("h2",rl,[e("a",sl,[e("span",null,[l("2020.11.25 "),n(a,null,{default:o(()=>[e("a",il,[l("1.0.0"),n(t)])]),_:1})])])]),hl,_l,cl,ul,dl])}const ml=_(d,[["render",pl],["__file","news.html.vue"]]);export{ml as default}; diff --git a/assets/news.html-rpPeZ0HC.js b/assets/news.html-BrzeG0HS.js similarity index 99% rename from assets/news.html-rpPeZ0HC.js rename to assets/news.html-BrzeG0HS.js index f84224b826..47c76cf27e 100644 --- a/assets/news.html-rpPeZ0HC.js +++ b/assets/news.html-BrzeG0HS.js @@ -1 +1 @@ -import{_,r as i,o as c,c as u,a as n,b as e,d as l,w as o,e as r}from"./app-5SoadDYS.js";const d={},p=e("h1",{id:"大史记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#大史记"},[e("span",null,"大史记")])],-1),f=r('

                                        2021.4.6

                                        • VuePress Next.
                                        • With Dark Mode.

                                        2021.4.4

                                        • 本文档迎来的新的首页。
                                        • 本文档迎来了暗黑模式。
                                        • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                                        • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                                        • 🎉🎉🎉
                                        ',4),b={id:"_2021-4-1-v1-4-2",tabindex:"-1"},g={class:"header-anchor",href:"#_2021-4-1-v1-4-2"},m={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.2",target:"_blank",rel:"noopener noreferrer"},x=r('
                                        • 不是愚人节玩笑,今天更新。
                                        • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                                        • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                                        • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                                        2021.3.25

                                        没错还在变。 -_-

                                        2021.3.15

                                        文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        ',5),X={id:"_2021-3-14-v1-4-0",tabindex:"-1"},S={class:"header-anchor",href:"#_2021-3-14-v1-4-0"},k={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.0",target:"_blank",rel:"noopener noreferrer"},y=r("
                                        • Happy Pi-Day!
                                        • 这次是个大更新:
                                          • 为链式代理引入了传输层支持。
                                          • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                                          • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                                          • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                                          • 添加了 FakeDNS。
                                          • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                                        • 还是 VuePress 比较爽啊(
                                        ",1),v={id:"_2021-3-3-1-3-1",tabindex:"-1"},T={class:"header-anchor",href:"#_2021-3-3-1-3-1"},L={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.1",target:"_blank",rel:"noopener noreferrer"},D=e("ul",null,[e("li",null,"这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。"),e("li",null,[l("同时修复了一个会导致 Panic 的 bug。"),e("s",null,"Holmium_认为这是在骗、在偷袭。")]),e("li",null,"修复了几个遗留问题。")],-1),P={id:"_2021-2-14-1-3-0",tabindex:"-1"},U={class:"header-anchor",href:"#_2021-2-14-1-3-0"},H={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.0",target:"_blank",rel:"noopener noreferrer"},C=e("ul",null,[e("li",null,"Happy 🐮 Year 🎉!"),e("li",null,"v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。"),e("li",null,"OHHHHHHHHHHHH!")],-1),j={id:"_2021-01-31-1-2-4",tabindex:"-1"},B={class:"header-anchor",href:"#_2021-01-31-1-2-4"},I={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.4",target:"_blank",rel:"noopener noreferrer"},N=e("ul",null,[e("li",null,"解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。"),e("li",null,"似乎这个版本没有什么改变,但这只是暴风雨前的宁静。"),e("li",null,[l("(没错我就是先知) "),e("blockquote",null,[e("p",null,"你个傻子,你拿的是 UNO 牌。")])])],-1),E=e("h2",{id:"_2021-01-25",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-25"},[e("span",null,"2021.01.25")])],-1),V=e("li",null,[e("a",{href:"../en"},"英文版文档网站"),l("逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!")],-1),w={id:"_2021-01-22-1-2-3",tabindex:"-1"},G={class:"header-anchor",href:"#_2021-01-22-1-2-3"},R={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.3",target:"_blank",rel:"noopener noreferrer"},O=e("li",null,[l("对 SS 协议的支持"),e("strong",null,"又"),l("变强了, 支持单端口多用户!")],-1),F=e("li",null,[l("对 trojan 协议的支持也"),e("strong",null,"又"),l("变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!")],-1),M=e("li",null,[e("em",null,"(VLESS: 嘤嘤嘤)")],-1),A=e("li",null,'UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".',-1),q=e("li",null,"嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.",-1),W=e("img",{src:"https://avatars2.githubusercontent.com/u/8384161?s=32",width:"32px",height:"32px",alt:"a"},null,-1),Q={href:"https://github.com/bohanyang",target:"_blank",rel:"noopener noreferrer"},Y=e("li",null,"其他美味小樱桃, 惯例更新品尝就对啦.",-1),J=r('

                                        2021.01.19

                                        • 一些数字
                                          • 版本发布了 10   个 tag
                                          • 解决掉了 100  个 issue
                                          • 复刻了 300  个 fork
                                          • 点了 2000 个 star
                                          • 群 3000 个 人

                                        2021.01.17

                                        ',3),z=e("img",{src:"https://avatars2.githubusercontent.com/u/60207794?s=32",width:"32px",height:"32px",alt:"a"},null,-1),K={href:"https://github.com/jiuqi9997",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://xtls.github.io/en/",target:"_blank",rel:"noopener noreferrer"},$={id:"_2021-01-15-1-2-2",tabindex:"-1"},ee={class:"header-anchor",href:"#_2021-01-15-1-2-2"},le={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.2",target:"_blank",rel:"noopener noreferrer"},ne=r('
                                        • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                                        • 之前预告的 UUID 修改正式上线.(往下看往下看)
                                        • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                                        • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                                        • 当然还有其他各种小糖果.(更新品尝就对了)
                                        • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                                        2021.01.12

                                        ',2),te=e("li",null,[l("将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. "),e("ul",null,[e("li",null,'客户端写 "id": "我爱 🍉 老师 1314",'),e("li",null,[l('服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 '),e("code",null,"我爱🍉老师1314"),l(" 的 UUID 映射)")])])],-1),oe={id:"_2021-01-10-1-2-1",tabindex:"-1"},ae={class:"header-anchor",href:"#_2021-01-10-1-2-1"},re={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.1",target:"_blank",rel:"noopener noreferrer"},se=e("li",null,"(可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程)",-1),ie=e("li",null,"还有很多细节修改, 文档将会越来越规范!",-1),he={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},ue=r('
                                        • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                                        • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                                        • 日志现在看起来更顺眼.

                                        2021.01.07

                                        • 礼貌和尊重本应是社区不需要明说的准则之一。

                                        2021.01.05

                                        • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        2021.01.03

                                        ',6),de=e("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32px",height:"32px",alt:"a"},null,-1),pe={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},fe=e("li",null,"tg 群突破 2500。",-1),be=e("h2",{id:"_2021-01-01",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-01"},[e("span",null,"2021.01.01")])],-1),ge={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},me=e("p",null,"🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!",-1),xe=r('
                                      46. 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                                      47. (UDP 还会继续增强!)
                                      48. 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                                      49. (不,下面不是广告,是里程碑。)
                                      50. Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                                        • 一人扛起了所有!支持各大主流协议!
                                        • 一骑绝尘的性能!
                                        • 日趋完善的功能!
                                        • 可怕的生命力与社区亲和力!
                                      51. ',5),Xe={href:"https://github.com/XTLS/Xray-core/discussions/56",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},ke=e("s",null,"(啊,有人敲门...我一会和你们说)",-1),ye=e("h2",{id:"_2020-12-29",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-29"},[e("span",null,"2020.12.29")])],-1),ve={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Te={id:"_2020-12-25-1-1-5",tabindex:"-1"},Le={class:"header-anchor",href:"#_2020-12-25-1-1-5"},De={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.5",target:"_blank",rel:"noopener noreferrer"},Pe=e("p",null,"圣诞节快乐!",-1),Ue=e("li",null,"游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone",-1),He=e("li",null,"你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...",-1),Ce=e("li",null,"(VLESS 的 UDP fullcone 和更多增强很快就到!)",-1),je=e("li",null,"无须再担心证书验证被墙,OCSP stapling 已经上线!",-1),Be={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},Ie=e("li",null,"还有更多美味小樱桃!(不用问,更新品尝就对了)",-1),Ne=e("h2",{id:"_2020-12-24",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-24"},[e("span",null,"2020.12.24")])],-1),Ee={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},Ve=e("p",null,"大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)",-1),we={href:"https://github.com/XTLS/XTLS.github.io",target:"_blank",rel:"noopener noreferrer"},Ge=e("p",null,"仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。",-1),Re=e("h2",{id:"_2020-12-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-23"},[e("span",null,"2020.12.23")])],-1),Oe={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Fe=e("h2",{id:"_2020-12-21",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-21"},[e("span",null,"2020.12.21")])],-1),Me=e("ul",null,[e("li",null,"Project X 群人数 2000+"),e("li",null,"群消息(含游戏群) 日均破万")],-1),Ae={id:"_2020-12-18-1-1-4",tabindex:"-1"},qe={class:"header-anchor",href:"#_2020-12-18-1-1-4"},We={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.4",target:"_blank",rel:"noopener noreferrer"},Qe=e("ul",null,[e("li",null,"更低的启动内占用和内存使用优化"),e("li",null,"随意定制的 TLS 提高你的 SSL 评级"),e("li",null,"支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS"),e("li",null,"还有在您路由器上使用的 Splice 最佳使用模式建议")],-1),Ye=e("h2",{id:"_2020-12-17",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-17"},[e("span",null,"2020.12.17")])],-1),Je={href:"https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ",target:"_blank",rel:"noopener noreferrer"},ze=e("h2",{id:"_2020-12-15",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-15"},[e("span",null,"2020.12.15")])],-1),Ke={href:"https://github.com/XTLS/Xray-install/tree/dev",target:"_blank",rel:"noopener noreferrer"},Ze={id:"_2020-12-11-1-1-3",tabindex:"-1"},$e={class:"header-anchor",href:"#_2020-12-11-1-1-3"},el={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.3",target:"_blank",rel:"noopener noreferrer"},ll=e("ul",null,[e("li",null,"完整版本的 REDIRECT 透明代理模式."),e("li",null,"软路由 splice 流控模式的优化建议.")],-1),nl={id:"_2020-12-06-1-1-2",tabindex:"-1"},tl={class:"header-anchor",href:"#_2020-12-06-1-1-2"},ol={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.2",target:"_blank",rel:"noopener noreferrer"},al=r('
                                        • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                                        • 增强了 API 兼容

                                        2020.12.04

                                        增加 splice 模式

                                        2020.11.27

                                        • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                                        • 登上了 GitHub Trending
                                        • Project X 群人数破千,频道订阅数 500+
                                        ',5),rl={id:"_2020-11-25-1-0-0",tabindex:"-1"},sl={class:"header-anchor",href:"#_2020-11-25-1-0-0"},il={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.0.0",target:"_blank",rel:"noopener noreferrer"},hl=e("p",null,"Xray 的第一个版本.",-1),_l=e("ul",null,[e("li",null,"基于 v2ray-core 修改而来,改动较大"),e("li",null,"全面增强, 性能卓越, 完全兼容")],-1),cl=e("h2",{id:"_2020-11-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-11-23"},[e("span",null,"2020.11.23")])],-1),ul=e("p",null,"project X start",-1),dl=e("blockquote",null,[e("p",null,[e("s",null,"梦开始的时候")])],-1);function pl(fl,bl){const h=i("I18nTip"),t=i("ExternalLinkIcon"),a=i("Badge"),s=i("RouterLink");return c(),u("div",null,[p,n(h),f,e("h2",b,[e("a",g,[e("span",null,[l("2021.4.1 "),n(a,null,{default:o(()=>[e("a",m,[l("v1.4.2"),n(t)])]),_:1})])])]),x,e("h2",X,[e("a",S,[e("span",null,[l("2021.3.14 "),n(a,null,{default:o(()=>[e("a",k,[l("v1.4.0"),n(t)])]),_:1})])])]),y,e("h2",v,[e("a",T,[e("span",null,[l("2021.3.3 "),n(a,null,{default:o(()=>[e("a",L,[l("1.3.1"),n(t)])]),_:1})])])]),D,e("h2",P,[e("a",U,[e("span",null,[l("2021.2.14 "),n(a,null,{default:o(()=>[e("a",H,[l("1.3.0"),n(t)])]),_:1})])])]),C,e("h2",j,[e("a",B,[e("span",null,[l("2021.01.31 "),n(a,null,{default:o(()=>[e("a",I,[l("1.2.4"),n(t)])]),_:1})])])]),N,E,e("ul",null,[e("li",null,[l("全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载"),n(s,{to:"/document/level-1/"},{default:o(()=>[l("秘籍第一层")]),_:1}),l("咯...")]),V]),e("h2",w,[e("a",G,[e("span",null,[l("2021.01.22 "),n(a,null,{default:o(()=>[e("a",R,[l("1.2.3"),n(t)])]),_:1})])])]),e("ul",null,[O,F,M,A,q,e("li",null,[l("向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 "),W,l(),e("a",Q,[l("@Bohan Yang"),n(t)]),l(" 致敬!")]),Y]),J,e("ul",null,[e("li",null,[l("辛苦的翻译工作开始了, 感谢"),z,l(),e("a",K,[l("@玖柒 Max"),n(t)]),l("和其他所有的翻译大佬们.")]),e("li",null,[e("a",Z,[l("English version"),n(t)])])]),e("h2",$,[e("a",ee,[e("span",null,[l("2021.01.15 "),n(a,null,{default:o(()=>[e("a",le,[l("1.2.2"),n(t)])]),_:1})])])]),ne,e("ul",null,[te,e("li",null,[l("🍉 老师的"),n(s,{to:"/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("大结局, 撒花.")])]),e("h2",oe,[e("a",ae,[e("span",null,[l("2021.01.10 "),n(a,null,{default:o(()=>[e("a",re,[l("1.2.1"),n(t)])]),_:1})])])]),e("ul",null,[e("li",null,[n(s,{to:"/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray!")]),se,e("li",null,[n(s,{to:"/document/level-2/"},{default:o(()=>[l("透明代理")]),_:1}),l("也增加了更多文章.")]),ie,e("li",null,[l("感谢 "),e("a",he,[l("@ricuhkaen"),n(t)]),l(" , "),e("a",_e,[l("@BioniCosmos"),n(t)]),l(", "),e("a",ce,[l("@kirin"),n(t)])])]),ue,e("ul",null,[e("li",null,[l("文档仓库第一个 PR。🎉 "),n(s,{to:"/document/level-2/tproxy.html"},{default:o(()=>[l("透明代理(TProxy)配置教程 ")]),_:1}),l(" ,感谢"),de,l(),e("a",pe,[l("@BioniCosmos"),n(t)])]),fe]),be,e("p",null,[l("【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 "),n(a,null,{default:o(()=>[e("a",ge,[l("1.2.0"),n(t)])]),_:1})]),me,e("ul",null,[xe,e("li",null,[l("Xray 将继续保持前行! 因此 "),e("a",Xe,[l("Xray 需要更多的英雄!!"),n(t)]),l("!")]),e("li",null,[l("PS:请品,请细品"),e("a",Se,[l("release notes"),n(t)]),l("每一句。似乎有一个小秘密小彩蛋 "),ke])]),ye,e("p",null,[l("透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, "),e("a",ve,[l("TG 群"),n(t)]),l("火热测试中")]),e("h2",Te,[e("a",Le,[e("span",null,[l("2020.12.25 "),n(a,null,{default:o(()=>[e("a",De,[l("1.1.5"),n(t)])]),_:1})])])]),Pe,e("ul",null,[Ue,He,Ce,je,e("li",null,[l("kirin 带来了一大波 脚本更新."),e("a",Be,[l("脚本在此"),n(t)])]),Ie]),Ne,e("p",null,[l("因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:"),e("a",Ee,[l("没错你正在看的就是"),n(t)])]),Ve,e("p",null,[l("文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 "),e("a",we,[l("文档的仓库"),n(t)])]),Ge,Re,e("p",null,[l("Xray-core Shadowsocks UDP FullCone 测试版, "),e("a",Oe,[l("TG 群"),n(t)]),l("火热测试中")]),Fe,Me,e("h2",Ae,[e("a",qe,[e("span",null,[l("2020.12.18 "),n(a,null,{default:o(()=>[e("a",We,[l("1.1.4"),n(t)])]),_:1})])])]),Qe,Ye,e("p",null,[l("鉴于日益增长群人数和游戏需求, 开启了"),e("a",Je,[l("TG 游戏群"),n(t)])]),ze,e("p",null,[e("a",Ke,[l("安装脚本 dev 分支"),n(t)]),l("开启, 持续更新功能中.")]),e("h2",Ze,[e("a",$e,[e("span",null,[l("2020.12.11 "),n(a,null,{default:o(()=>[e("a",el,[l("1.1.3"),n(t)])]),_:1})])])]),ll,e("h2",nl,[e("a",tl,[e("span",null,[l("2020.12.06 "),n(a,null,{default:o(()=>[e("a",ol,[l("1.1.2"),n(t)])]),_:1})])])]),al,e("h2",rl,[e("a",sl,[e("span",null,[l("2020.11.25 "),n(a,null,{default:o(()=>[e("a",il,[l("1.0.0"),n(t)])]),_:1})])])]),hl,_l,cl,ul,dl])}const ml=_(d,[["render",pl],["__file","news.html.vue"]]);export{ml as default}; +import{_,r as i,o as c,c as u,a as n,b as e,d as l,w as o,e as r}from"./app-Bw2NG-QJ.js";const d={},p=e("h1",{id:"大史记",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#大史记"},[e("span",null,"大史记")])],-1),f=r('

                                        2021.4.6

                                        • VuePress Next.
                                        • With Dark Mode.

                                        2021.4.4

                                        • 本文档迎来的新的首页。
                                        • 本文档迎来了暗黑模式。
                                        • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                                        • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                                        • 🎉🎉🎉
                                        ',4),b={id:"_2021-4-1-v1-4-2",tabindex:"-1"},g={class:"header-anchor",href:"#_2021-4-1-v1-4-2"},m={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.2",target:"_blank",rel:"noopener noreferrer"},x=r('
                                        • 不是愚人节玩笑,今天更新。
                                        • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                                        • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                                        • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                                        2021.3.25

                                        没错还在变。 -_-

                                        2021.3.15

                                        文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        ',5),X={id:"_2021-3-14-v1-4-0",tabindex:"-1"},S={class:"header-anchor",href:"#_2021-3-14-v1-4-0"},k={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.4.0",target:"_blank",rel:"noopener noreferrer"},y=r("
                                        • Happy Pi-Day!
                                        • 这次是个大更新:
                                          • 为链式代理引入了传输层支持。
                                          • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                                          • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                                          • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                                          • 添加了 FakeDNS。
                                          • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                                        • 还是 VuePress 比较爽啊(
                                        ",1),v={id:"_2021-3-3-1-3-1",tabindex:"-1"},T={class:"header-anchor",href:"#_2021-3-3-1-3-1"},L={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.1",target:"_blank",rel:"noopener noreferrer"},D=e("ul",null,[e("li",null,"这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。"),e("li",null,[l("同时修复了一个会导致 Panic 的 bug。"),e("s",null,"Holmium_认为这是在骗、在偷袭。")]),e("li",null,"修复了几个遗留问题。")],-1),P={id:"_2021-2-14-1-3-0",tabindex:"-1"},U={class:"header-anchor",href:"#_2021-2-14-1-3-0"},H={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.3.0",target:"_blank",rel:"noopener noreferrer"},C=e("ul",null,[e("li",null,"Happy 🐮 Year 🎉!"),e("li",null,"v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。"),e("li",null,"OHHHHHHHHHHHH!")],-1),j={id:"_2021-01-31-1-2-4",tabindex:"-1"},B={class:"header-anchor",href:"#_2021-01-31-1-2-4"},I={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.4",target:"_blank",rel:"noopener noreferrer"},N=e("ul",null,[e("li",null,"解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。"),e("li",null,"似乎这个版本没有什么改变,但这只是暴风雨前的宁静。"),e("li",null,[l("(没错我就是先知) "),e("blockquote",null,[e("p",null,"你个傻子,你拿的是 UNO 牌。")])])],-1),E=e("h2",{id:"_2021-01-25",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-25"},[e("span",null,"2021.01.25")])],-1),V=e("li",null,[e("a",{href:"../en"},"英文版文档网站"),l("逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!")],-1),w={id:"_2021-01-22-1-2-3",tabindex:"-1"},G={class:"header-anchor",href:"#_2021-01-22-1-2-3"},R={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.3",target:"_blank",rel:"noopener noreferrer"},O=e("li",null,[l("对 SS 协议的支持"),e("strong",null,"又"),l("变强了, 支持单端口多用户!")],-1),F=e("li",null,[l("对 trojan 协议的支持也"),e("strong",null,"又"),l("变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!")],-1),M=e("li",null,[e("em",null,"(VLESS: 嘤嘤嘤)")],-1),A=e("li",null,'UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".',-1),q=e("li",null,"嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.",-1),W=e("img",{src:"https://avatars2.githubusercontent.com/u/8384161?s=32",width:"32px",height:"32px",alt:"a"},null,-1),Q={href:"https://github.com/bohanyang",target:"_blank",rel:"noopener noreferrer"},Y=e("li",null,"其他美味小樱桃, 惯例更新品尝就对啦.",-1),J=r('

                                        2021.01.19

                                        • 一些数字
                                          • 版本发布了 10   个 tag
                                          • 解决掉了 100  个 issue
                                          • 复刻了 300  个 fork
                                          • 点了 2000 个 star
                                          • 群 3000 个 人

                                        2021.01.17

                                        ',3),z=e("img",{src:"https://avatars2.githubusercontent.com/u/60207794?s=32",width:"32px",height:"32px",alt:"a"},null,-1),K={href:"https://github.com/jiuqi9997",target:"_blank",rel:"noopener noreferrer"},Z={href:"https://xtls.github.io/en/",target:"_blank",rel:"noopener noreferrer"},$={id:"_2021-01-15-1-2-2",tabindex:"-1"},ee={class:"header-anchor",href:"#_2021-01-15-1-2-2"},le={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.2",target:"_blank",rel:"noopener noreferrer"},ne=r('
                                        • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                                        • 之前预告的 UUID 修改正式上线.(往下看往下看)
                                        • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                                        • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                                        • 当然还有其他各种小糖果.(更新品尝就对了)
                                        • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                                        2021.01.12

                                        ',2),te=e("li",null,[l("将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户. "),e("ul",null,[e("li",null,'客户端写 "id": "我爱 🍉 老师 1314",'),e("li",null,[l('服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 '),e("code",null,"我爱🍉老师1314"),l(" 的 UUID 映射)")])])],-1),oe={id:"_2021-01-10-1-2-1",tabindex:"-1"},ae={class:"header-anchor",href:"#_2021-01-10-1-2-1"},re={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.1",target:"_blank",rel:"noopener noreferrer"},se=e("li",null,"(可能是整个互联网上, 最详细最有耐心的教你从 0 开始配置的教程)",-1),ie=e("li",null,"还有很多细节修改, 文档将会越来越规范!",-1),he={href:"https://github.com/ricuhkaen",target:"_blank",rel:"noopener noreferrer"},_e={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},ce={href:"https://github.com/kirin10000",target:"_blank",rel:"noopener noreferrer"},ue=r('
                                        • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                                        • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                                        • 日志现在看起来更顺眼.

                                        2021.01.07

                                        • 礼貌和尊重本应是社区不需要明说的准则之一。

                                        2021.01.05

                                        • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                                        2021.01.03

                                        ',6),de=e("img",{src:"https://avatars2.githubusercontent.com/u/41363844?s=32",width:"32px",height:"32px",alt:"a"},null,-1),pe={href:"https://github.com/BioniCosmos",target:"_blank",rel:"noopener noreferrer"},fe=e("li",null,"tg 群突破 2500。",-1),be=e("h2",{id:"_2021-01-01",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2021-01-01"},[e("span",null,"2021.01.01")])],-1),ge={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},me=e("p",null,"🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!",-1),xe=r('
                                      52. 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                                      53. (UDP 还会继续增强!)
                                      54. 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                                      55. (不,下面不是广告,是里程碑。)
                                      56. Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                                        • 一人扛起了所有!支持各大主流协议!
                                        • 一骑绝尘的性能!
                                        • 日趋完善的功能!
                                        • 可怕的生命力与社区亲和力!
                                      57. ',5),Xe={href:"https://github.com/XTLS/Xray-core/discussions/56",target:"_blank",rel:"noopener noreferrer"},Se={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.2.0",target:"_blank",rel:"noopener noreferrer"},ke=e("s",null,"(啊,有人敲门...我一会和你们说)",-1),ye=e("h2",{id:"_2020-12-29",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-29"},[e("span",null,"2020.12.29")])],-1),ve={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Te={id:"_2020-12-25-1-1-5",tabindex:"-1"},Le={class:"header-anchor",href:"#_2020-12-25-1-1-5"},De={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.5",target:"_blank",rel:"noopener noreferrer"},Pe=e("p",null,"圣诞节快乐!",-1),Ue=e("li",null,"游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone",-1),He=e("li",null,"你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...",-1),Ce=e("li",null,"(VLESS 的 UDP fullcone 和更多增强很快就到!)",-1),je=e("li",null,"无须再担心证书验证被墙,OCSP stapling 已经上线!",-1),Be={href:"https://github.com/XTLS/Xray-install",target:"_blank",rel:"noopener noreferrer"},Ie=e("li",null,"还有更多美味小樱桃!(不用问,更新品尝就对了)",-1),Ne=e("h2",{id:"_2020-12-24",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-24"},[e("span",null,"2020.12.24")])],-1),Ee={href:"https://xtls.github.io",target:"_blank",rel:"noopener noreferrer"},Ve=e("p",null,"大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)",-1),we={href:"https://github.com/XTLS/XTLS.github.io",target:"_blank",rel:"noopener noreferrer"},Ge=e("p",null,"仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。",-1),Re=e("h2",{id:"_2020-12-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-23"},[e("span",null,"2020.12.23")])],-1),Oe={href:"https://t.me/projectXray",target:"_blank",rel:"noopener noreferrer"},Fe=e("h2",{id:"_2020-12-21",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-21"},[e("span",null,"2020.12.21")])],-1),Me=e("ul",null,[e("li",null,"Project X 群人数 2000+"),e("li",null,"群消息(含游戏群) 日均破万")],-1),Ae={id:"_2020-12-18-1-1-4",tabindex:"-1"},qe={class:"header-anchor",href:"#_2020-12-18-1-1-4"},We={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.4",target:"_blank",rel:"noopener noreferrer"},Qe=e("ul",null,[e("li",null,"更低的启动内占用和内存使用优化"),e("li",null,"随意定制的 TLS 提高你的 SSL 评级"),e("li",null,"支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS"),e("li",null,"还有在您路由器上使用的 Splice 最佳使用模式建议")],-1),Ye=e("h2",{id:"_2020-12-17",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-17"},[e("span",null,"2020.12.17")])],-1),Je={href:"https://t.me/joinchat/UO4NixbB_XDQJOUjS6mHEQ",target:"_blank",rel:"noopener noreferrer"},ze=e("h2",{id:"_2020-12-15",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-12-15"},[e("span",null,"2020.12.15")])],-1),Ke={href:"https://github.com/XTLS/Xray-install/tree/dev",target:"_blank",rel:"noopener noreferrer"},Ze={id:"_2020-12-11-1-1-3",tabindex:"-1"},$e={class:"header-anchor",href:"#_2020-12-11-1-1-3"},el={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.3",target:"_blank",rel:"noopener noreferrer"},ll=e("ul",null,[e("li",null,"完整版本的 REDIRECT 透明代理模式."),e("li",null,"软路由 splice 流控模式的优化建议.")],-1),nl={id:"_2020-12-06-1-1-2",tabindex:"-1"},tl={class:"header-anchor",href:"#_2020-12-06-1-1-2"},ol={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.1.2",target:"_blank",rel:"noopener noreferrer"},al=r('
                                        • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                                        • 增强了 API 兼容

                                        2020.12.04

                                        增加 splice 模式

                                        2020.11.27

                                        • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                                        • 登上了 GitHub Trending
                                        • Project X 群人数破千,频道订阅数 500+
                                        ',5),rl={id:"_2020-11-25-1-0-0",tabindex:"-1"},sl={class:"header-anchor",href:"#_2020-11-25-1-0-0"},il={href:"https://github.com/XTLS/Xray-core/releases/tag/v1.0.0",target:"_blank",rel:"noopener noreferrer"},hl=e("p",null,"Xray 的第一个版本.",-1),_l=e("ul",null,[e("li",null,"基于 v2ray-core 修改而来,改动较大"),e("li",null,"全面增强, 性能卓越, 完全兼容")],-1),cl=e("h2",{id:"_2020-11-23",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_2020-11-23"},[e("span",null,"2020.11.23")])],-1),ul=e("p",null,"project X start",-1),dl=e("blockquote",null,[e("p",null,[e("s",null,"梦开始的时候")])],-1);function pl(fl,bl){const h=i("I18nTip"),t=i("ExternalLinkIcon"),a=i("Badge"),s=i("RouterLink");return c(),u("div",null,[p,n(h),f,e("h2",b,[e("a",g,[e("span",null,[l("2021.4.1 "),n(a,null,{default:o(()=>[e("a",m,[l("v1.4.2"),n(t)])]),_:1})])])]),x,e("h2",X,[e("a",S,[e("span",null,[l("2021.3.14 "),n(a,null,{default:o(()=>[e("a",k,[l("v1.4.0"),n(t)])]),_:1})])])]),y,e("h2",v,[e("a",T,[e("span",null,[l("2021.3.3 "),n(a,null,{default:o(()=>[e("a",L,[l("1.3.1"),n(t)])]),_:1})])])]),D,e("h2",P,[e("a",U,[e("span",null,[l("2021.2.14 "),n(a,null,{default:o(()=>[e("a",H,[l("1.3.0"),n(t)])]),_:1})])])]),C,e("h2",j,[e("a",B,[e("span",null,[l("2021.01.31 "),n(a,null,{default:o(()=>[e("a",I,[l("1.2.4"),n(t)])]),_:1})])])]),N,E,e("ul",null,[e("li",null,[l("全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载"),n(s,{to:"/document/level-1/"},{default:o(()=>[l("秘籍第一层")]),_:1}),l("咯...")]),V]),e("h2",w,[e("a",G,[e("span",null,[l("2021.01.22 "),n(a,null,{default:o(()=>[e("a",R,[l("1.2.3"),n(t)])]),_:1})])])]),e("ul",null,[O,F,M,A,q,e("li",null,[l("向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 "),W,l(),e("a",Q,[l("@Bohan Yang"),n(t)]),l(" 致敬!")]),Y]),J,e("ul",null,[e("li",null,[l("辛苦的翻译工作开始了, 感谢"),z,l(),e("a",K,[l("@玖柒 Max"),n(t)]),l("和其他所有的翻译大佬们.")]),e("li",null,[e("a",Z,[l("English version"),n(t)])])]),e("h2",$,[e("a",ee,[e("span",null,[l("2021.01.15 "),n(a,null,{default:o(()=>[e("a",le,[l("1.2.2"),n(t)])]),_:1})])])]),ne,e("ul",null,[te,e("li",null,[l("🍉 老师的"),n(s,{to:"/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("大结局, 撒花.")])]),e("h2",oe,[e("a",ae,[e("span",null,[l("2021.01.10 "),n(a,null,{default:o(()=>[e("a",re,[l("1.2.1"),n(t)])]),_:1})])])]),e("ul",null,[e("li",null,[n(s,{to:"/document/level-0/"},{default:o(()=>[l("小小白白话文")]),_:1}),l("连载上线啦,🍉 老师呕心沥血之作, 手把手教你从什么都不会到熟练配置 Xray!")]),se,e("li",null,[n(s,{to:"/document/level-2/"},{default:o(()=>[l("透明代理")]),_:1}),l("也增加了更多文章.")]),ie,e("li",null,[l("感谢 "),e("a",he,[l("@ricuhkaen"),n(t)]),l(" , "),e("a",_e,[l("@BioniCosmos"),n(t)]),l(", "),e("a",ce,[l("@kirin"),n(t)])])]),ue,e("ul",null,[e("li",null,[l("文档仓库第一个 PR。🎉 "),n(s,{to:"/document/level-2/tproxy.html"},{default:o(()=>[l("透明代理(TProxy)配置教程 ")]),_:1}),l(" ,感谢"),de,l(),e("a",pe,[l("@BioniCosmos"),n(t)])]),fe]),be,e("p",null,[l("【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 "),n(a,null,{default:o(()=>[e("a",ge,[l("1.2.0"),n(t)])]),_:1})]),me,e("ul",null,[xe,e("li",null,[l("Xray 将继续保持前行! 因此 "),e("a",Xe,[l("Xray 需要更多的英雄!!"),n(t)]),l("!")]),e("li",null,[l("PS:请品,请细品"),e("a",Se,[l("release notes"),n(t)]),l("每一句。似乎有一个小秘密小彩蛋 "),ke])]),ye,e("p",null,[l("透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, "),e("a",ve,[l("TG 群"),n(t)]),l("火热测试中")]),e("h2",Te,[e("a",Le,[e("span",null,[l("2020.12.25 "),n(a,null,{default:o(()=>[e("a",De,[l("1.1.5"),n(t)])]),_:1})])])]),Pe,e("ul",null,[Ue,He,Ce,je,e("li",null,[l("kirin 带来了一大波 脚本更新."),e("a",Be,[l("脚本在此"),n(t)])]),Ie]),Ne,e("p",null,[l("因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:"),e("a",Ee,[l("没错你正在看的就是"),n(t)])]),Ve,e("p",null,[l("文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 "),e("a",we,[l("文档的仓库"),n(t)])]),Ge,Re,e("p",null,[l("Xray-core Shadowsocks UDP FullCone 测试版, "),e("a",Oe,[l("TG 群"),n(t)]),l("火热测试中")]),Fe,Me,e("h2",Ae,[e("a",qe,[e("span",null,[l("2020.12.18 "),n(a,null,{default:o(()=>[e("a",We,[l("1.1.4"),n(t)])]),_:1})])])]),Qe,Ye,e("p",null,[l("鉴于日益增长群人数和游戏需求, 开启了"),e("a",Je,[l("TG 游戏群"),n(t)])]),ze,e("p",null,[e("a",Ke,[l("安装脚本 dev 分支"),n(t)]),l("开启, 持续更新功能中.")]),e("h2",Ze,[e("a",$e,[e("span",null,[l("2020.12.11 "),n(a,null,{default:o(()=>[e("a",el,[l("1.1.3"),n(t)])]),_:1})])])]),ll,e("h2",nl,[e("a",tl,[e("span",null,[l("2020.12.06 "),n(a,null,{default:o(()=>[e("a",ol,[l("1.1.2"),n(t)])]),_:1})])])]),al,e("h2",rl,[e("a",sl,[e("span",null,[l("2020.11.25 "),n(a,null,{default:o(()=>[e("a",il,[l("1.0.0"),n(t)])]),_:1})])])]),hl,_l,cl,ul,dl])}const ml=_(d,[["render",pl],["__file","news.html.vue"]]);export{ml as default}; diff --git a/assets/nginx_or_haproxy_tls_tunnel.html-DNk6WbAM.js b/assets/nginx_or_haproxy_tls_tunnel.html-CBNtMx0V.js similarity index 99% rename from assets/nginx_or_haproxy_tls_tunnel.html-DNk6WbAM.js rename to assets/nginx_or_haproxy_tls_tunnel.html-CBNtMx0V.js index 3ea8f3bc1f..f26818b752 100644 --- a/assets/nginx_or_haproxy_tls_tunnel.html-DNk6WbAM.js +++ b/assets/nginx_or_haproxy_tls_tunnel.html-CBNtMx0V.js @@ -1,4 +1,4 @@ -import{_ as o,r as s,o as p,c as r,a as e,b as a,d as n,e as i}from"./app-5SoadDYS.js";const c={},d=i('

                                        Nginx или Haproxy реализуют HTTPS-туннели, туннели HTTP/2 over HTTPS, туннели WebSocket over HTTP/2 over HTTPS, туннели gRPC over HTTP/2 over HTTPS, а также туннели gRPC over HTTP/2 over HTTPS с двусторонней аутентификацией по самозаверяющему сертификату.

                                        Создание HTTPS-туннеля с помощью Nginx на стороне клиента и сервера для скрытия отпечатков

                                        Сетевая структура:

                                        xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                                        Компиляция nginx с поддержкой --with-stream

                                        Выполните компиляцию как на клиенте, так и на сервере.

                                        curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                                        tar -zxvf nginx-1.22.1.tar.gz

                                        cd nginx-1.22.1

                                        apt install gcc make // Для компиляции требуются gcc и make

                                        ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module // На этом шаге могут потребоваться дополнительные библиотеки, установите их в соответствии с сообщениями об ошибках.

                                        make && make install

                                        После компиляции папка nginx будет находиться в /usr/local/nginx.

                                        Настройка nginx

                                        Отредактируйте конфигурационный файл nginx.conf.

                                        vim /usr/local/nginx/conf/nginx.conf

                                        Добавьте следующую конфигурацию на стороне сервера.

                                        ',17),u={href:"https://xtls.github.io/document/level-0/ch06-certificates.html",target:"_blank",rel:"noopener noreferrer"},v=i(`
                                        stream {
                                        +import{_ as o,r as s,o as p,c as r,a as e,b as a,d as n,e as i}from"./app-Bw2NG-QJ.js";const c={},d=i('

                                        Nginx или Haproxy реализуют HTTPS-туннели, туннели HTTP/2 over HTTPS, туннели WebSocket over HTTP/2 over HTTPS, туннели gRPC over HTTP/2 over HTTPS, а также туннели gRPC over HTTP/2 over HTTPS с двусторонней аутентификацией по самозаверяющему сертификату.

                                        Создание HTTPS-туннеля с помощью Nginx на стороне клиента и сервера для скрытия отпечатков

                                        Сетевая структура:

                                        xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                                        Компиляция nginx с поддержкой --with-stream

                                        Выполните компиляцию как на клиенте, так и на сервере.

                                        curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                                        tar -zxvf nginx-1.22.1.tar.gz

                                        cd nginx-1.22.1

                                        apt install gcc make // Для компиляции требуются gcc и make

                                        ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module // На этом шаге могут потребоваться дополнительные библиотеки, установите их в соответствии с сообщениями об ошибках.

                                        make && make install

                                        После компиляции папка nginx будет находиться в /usr/local/nginx.

                                        Настройка nginx

                                        Отредактируйте конфигурационный файл nginx.conf.

                                        vim /usr/local/nginx/conf/nginx.conf

                                        Добавьте следующую конфигурацию на стороне сервера.

                                        ',17),u={href:"https://xtls.github.io/document/level-0/ch06-certificates.html",target:"_blank",rel:"noopener noreferrer"},v=i(`
                                        stream {
                                             server {
                                                 listen 443 ssl;
                                                 listen [::]:443 ssl;
                                        diff --git a/assets/nginx_or_haproxy_tls_tunnel.html-DOgxvrPa.js b/assets/nginx_or_haproxy_tls_tunnel.html-CTP6KXYR.js
                                        similarity index 99%
                                        rename from assets/nginx_or_haproxy_tls_tunnel.html-DOgxvrPa.js
                                        rename to assets/nginx_or_haproxy_tls_tunnel.html-CTP6KXYR.js
                                        index 7f3cb2055a..b958f80e6f 100644
                                        --- a/assets/nginx_or_haproxy_tls_tunnel.html-DOgxvrPa.js
                                        +++ b/assets/nginx_or_haproxy_tls_tunnel.html-CTP6KXYR.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as t,r as e,o as r,c as v,a as n,b as i,d as s,e as l}from"./app-5SoadDYS.js";const u={},c=l('

                                        Nginx 或 Haproxy 实现的 HTTPS 隧道、HTTP/2 over HTTPS 隧道、WebSocket over HTTP/2 over HTTPS 隧道、gRPC over HTTP/2 over HTTPS 隧道以及自签证书双端认证的 gRPC over HTTP/2 over HTTPS 隧道

                                        客户端服务端 Nginx 构建 HTTPS 隧道隐藏指纹

                                        网路结构:

                                        xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                                        编译 nginx --with-stream

                                        在客户端及服务端均编译

                                        curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                                        tar -zxvf nginx-1.22.1.tar.gz

                                        cd nginx-1.22.1

                                        apt install gcc make //编译依赖 gcc 以及 make

                                        ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module //此步需要依赖一些库,根据报错安装相应 lib

                                        make && make install

                                        编译之后 nginx 文件夹位于 /usr/local/nginx

                                        配置 nginx

                                        编辑 nginx 配置文件 nginx.conf

                                        vim /usr/local/nginx/conf/nginx.conf

                                        服务端加入如下配置

                                        ',17),o={href:"https://xtls.github.io/document/level-0/ch06-certificates.html",target:"_blank",rel:"noopener noreferrer"},m=l(`
                                        stream {
                                        +import{_ as t,r as e,o as r,c as v,a as n,b as i,d as s,e as l}from"./app-Bw2NG-QJ.js";const u={},c=l('

                                        Nginx 或 Haproxy 实现的 HTTPS 隧道、HTTP/2 over HTTPS 隧道、WebSocket over HTTP/2 over HTTPS 隧道、gRPC over HTTP/2 over HTTPS 隧道以及自签证书双端认证的 gRPC over HTTP/2 over HTTPS 隧道

                                        客户端服务端 Nginx 构建 HTTPS 隧道隐藏指纹

                                        网路结构:

                                        xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                                        编译 nginx --with-stream

                                        在客户端及服务端均编译

                                        curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                                        tar -zxvf nginx-1.22.1.tar.gz

                                        cd nginx-1.22.1

                                        apt install gcc make //编译依赖 gcc 以及 make

                                        ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module //此步需要依赖一些库,根据报错安装相应 lib

                                        make && make install

                                        编译之后 nginx 文件夹位于 /usr/local/nginx

                                        配置 nginx

                                        编辑 nginx 配置文件 nginx.conf

                                        vim /usr/local/nginx/conf/nginx.conf

                                        服务端加入如下配置

                                        ',17),o={href:"https://xtls.github.io/document/level-0/ch06-certificates.html",target:"_blank",rel:"noopener noreferrer"},m=l(`
                                        stream {
                                             server {
                                                 listen 443 ssl;
                                                 listen [::]:443 ssl;
                                        diff --git a/assets/nginx_or_haproxy_tls_tunnel.html-DatcYtlJ.js b/assets/nginx_or_haproxy_tls_tunnel.html-KJNaWU2X.js
                                        similarity index 99%
                                        rename from assets/nginx_or_haproxy_tls_tunnel.html-DatcYtlJ.js
                                        rename to assets/nginx_or_haproxy_tls_tunnel.html-KJNaWU2X.js
                                        index 7f3cb2055a..b958f80e6f 100644
                                        --- a/assets/nginx_or_haproxy_tls_tunnel.html-DatcYtlJ.js
                                        +++ b/assets/nginx_or_haproxy_tls_tunnel.html-KJNaWU2X.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as t,r as e,o as r,c as v,a as n,b as i,d as s,e as l}from"./app-5SoadDYS.js";const u={},c=l('

                                        Nginx 或 Haproxy 实现的 HTTPS 隧道、HTTP/2 over HTTPS 隧道、WebSocket over HTTP/2 over HTTPS 隧道、gRPC over HTTP/2 over HTTPS 隧道以及自签证书双端认证的 gRPC over HTTP/2 over HTTPS 隧道

                                        客户端服务端 Nginx 构建 HTTPS 隧道隐藏指纹

                                        网路结构:

                                        xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                                        编译 nginx --with-stream

                                        在客户端及服务端均编译

                                        curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                                        tar -zxvf nginx-1.22.1.tar.gz

                                        cd nginx-1.22.1

                                        apt install gcc make //编译依赖 gcc 以及 make

                                        ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module //此步需要依赖一些库,根据报错安装相应 lib

                                        make && make install

                                        编译之后 nginx 文件夹位于 /usr/local/nginx

                                        配置 nginx

                                        编辑 nginx 配置文件 nginx.conf

                                        vim /usr/local/nginx/conf/nginx.conf

                                        服务端加入如下配置

                                        ',17),o={href:"https://xtls.github.io/document/level-0/ch06-certificates.html",target:"_blank",rel:"noopener noreferrer"},m=l(`
                                        stream {
                                        +import{_ as t,r as e,o as r,c as v,a as n,b as i,d as s,e as l}from"./app-Bw2NG-QJ.js";const u={},c=l('

                                        Nginx 或 Haproxy 实现的 HTTPS 隧道、HTTP/2 over HTTPS 隧道、WebSocket over HTTP/2 over HTTPS 隧道、gRPC over HTTP/2 over HTTPS 隧道以及自签证书双端认证的 gRPC over HTTP/2 over HTTPS 隧道

                                        客户端服务端 Nginx 构建 HTTPS 隧道隐藏指纹

                                        网路结构:

                                        xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                                        编译 nginx --with-stream

                                        在客户端及服务端均编译

                                        curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                                        tar -zxvf nginx-1.22.1.tar.gz

                                        cd nginx-1.22.1

                                        apt install gcc make //编译依赖 gcc 以及 make

                                        ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module //此步需要依赖一些库,根据报错安装相应 lib

                                        make && make install

                                        编译之后 nginx 文件夹位于 /usr/local/nginx

                                        配置 nginx

                                        编辑 nginx 配置文件 nginx.conf

                                        vim /usr/local/nginx/conf/nginx.conf

                                        服务端加入如下配置

                                        ',17),o={href:"https://xtls.github.io/document/level-0/ch06-certificates.html",target:"_blank",rel:"noopener noreferrer"},m=l(`
                                        stream {
                                             server {
                                                 listen 443 ssl;
                                                 listen [::]:443 ssl;
                                        diff --git a/assets/observatory.html-BJ2zcm9w.js b/assets/observatory.html-BzG-DGQ7.js
                                        similarity index 99%
                                        rename from assets/observatory.html-BJ2zcm9w.js
                                        rename to assets/observatory.html-BzG-DGQ7.js
                                        index c7c4bff2dd..4c332bea55 100644
                                        --- a/assets/observatory.html-BJ2zcm9w.js
                                        +++ b/assets/observatory.html-BzG-DGQ7.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as e,r as n,o as s,c as t,a,e as c}from"./app-5SoadDYS.js";const p={},u=c(`

                                        Мониторинг подключений

                                        Компонент мониторинга подключений использует HTTP-пинги для проверки состояния подключения исходящих прокси. Результаты мониторинга могут использоваться другими компонентами, например, балансировщиком нагрузки.
                                        В настоящее время доступны два режима: observatory (фоновый мониторинг подключений) и burstObservatory (мониторинг параллельных подключений).
                                        Выберите один из них в соответствии с вашими потребностями.

                                        ObservatoryObject

                                        {
                                        +import{_ as e,r as n,o as s,c as t,a,e as c}from"./app-Bw2NG-QJ.js";const p={},u=c(`

                                        Мониторинг подключений

                                        Компонент мониторинга подключений использует HTTP-пинги для проверки состояния подключения исходящих прокси. Результаты мониторинга могут использоваться другими компонентами, например, балансировщиком нагрузки.
                                        В настоящее время доступны два режима: observatory (фоновый мониторинг подключений) и burstObservatory (мониторинг параллельных подключений).
                                        Выберите один из них в соответствии с вашими потребностями.

                                        ObservatoryObject

                                        {
                                           "subjectSelector":[
                                             "outbound"
                                           ],
                                        diff --git a/assets/observatory.html-DG1jqJm8.js b/assets/observatory.html-CPlTxJvy.js
                                        similarity index 99%
                                        rename from assets/observatory.html-DG1jqJm8.js
                                        rename to assets/observatory.html-CPlTxJvy.js
                                        index 8e9ee09bd2..25f8ae5736 100644
                                        --- a/assets/observatory.html-DG1jqJm8.js
                                        +++ b/assets/observatory.html-CPlTxJvy.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as e,o as s,c as t,a,e as c}from"./app-5SoadDYS.js";const p={},u=c(`

                                        连接观测

                                        连接观测组件使用 HTTPing 的方式探测出站代理的连接状态。观测结果可以被其他组件使用,如负载均衡器。目前有 observatory (后台连接观测)和 burstObservatory (并发连接观测)两种。按需选择其中之一就行。

                                        ObservatoryObject

                                        {
                                        +import{_ as n,r as e,o as s,c as t,a,e as c}from"./app-Bw2NG-QJ.js";const p={},u=c(`

                                        连接观测

                                        连接观测组件使用 HTTPing 的方式探测出站代理的连接状态。观测结果可以被其他组件使用,如负载均衡器。目前有 observatory (后台连接观测)和 burstObservatory (并发连接观测)两种。按需选择其中之一就行。

                                        ObservatoryObject

                                        {
                                           "subjectSelector":[
                                             "outbound"
                                           ],
                                        diff --git a/assets/observatory.html-BOdfknrn.js b/assets/observatory.html-CgCiDU6P.js
                                        similarity index 99%
                                        rename from assets/observatory.html-BOdfknrn.js
                                        rename to assets/observatory.html-CgCiDU6P.js
                                        index 8e9ee09bd2..25f8ae5736 100644
                                        --- a/assets/observatory.html-BOdfknrn.js
                                        +++ b/assets/observatory.html-CgCiDU6P.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as e,o as s,c as t,a,e as c}from"./app-5SoadDYS.js";const p={},u=c(`

                                        连接观测

                                        连接观测组件使用 HTTPing 的方式探测出站代理的连接状态。观测结果可以被其他组件使用,如负载均衡器。目前有 observatory (后台连接观测)和 burstObservatory (并发连接观测)两种。按需选择其中之一就行。

                                        ObservatoryObject

                                        {
                                        +import{_ as n,r as e,o as s,c as t,a,e as c}from"./app-Bw2NG-QJ.js";const p={},u=c(`

                                        连接观测

                                        连接观测组件使用 HTTPing 的方式探测出站代理的连接状态。观测结果可以被其他组件使用,如负载均衡器。目前有 observatory (后台连接观测)和 burstObservatory (并发连接观测)两种。按需选择其中之一就行。

                                        ObservatoryObject

                                        {
                                           "subjectSelector":[
                                             "outbound"
                                           ],
                                        diff --git a/assets/outbound.html-B1Wp8iU4.js b/assets/outbound.html-Bztbl0lH.js
                                        similarity index 99%
                                        rename from assets/outbound.html-B1Wp8iU4.js
                                        rename to assets/outbound.html-Bztbl0lH.js
                                        index 8f16a5e02e..3bc218e36e 100644
                                        --- a/assets/outbound.html-B1Wp8iU4.js
                                        +++ b/assets/outbound.html-Bztbl0lH.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as t,o as l,c as d,a as s,b as n,d as o,w as a,e as c}from"./app-5SoadDYS.js";const i={},b=n("h1",{id:"исходящие-подключения",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#исходящие-подключения"},[n("span",null,"Исходящие подключения")])],-1),k=c(`

                                        OutboundObject

                                        OutboundObject соответствует дочернему элементу поля outbounds в конфигурационном файле.

                                        Подсказка

                                        Первый элемент в списке используется как основной исходящий узел.
                                        Если совпадений с правилами маршрутизации нет или ни одно правило не сработало, трафик отправляется через основной исходящий узел.

                                        {
                                        +import{_ as r,r as t,o as l,c as d,a as s,b as n,d as o,w as a,e as c}from"./app-Bw2NG-QJ.js";const i={},b=n("h1",{id:"исходящие-подключения",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#исходящие-подключения"},[n("span",null,"Исходящие подключения")])],-1),k=c(`

                                        OutboundObject

                                        OutboundObject соответствует дочернему элементу поля outbounds в конфигурационном файле.

                                        Подсказка

                                        Первый элемент в списке используется как основной исходящий узел.
                                        Если совпадений с правилами маршрутизации нет или ни одно правило не сработало, трафик отправляется через основной исходящий узел.

                                        {
                                           "outbounds": [
                                             {
                                               "sendThrough": "0.0.0.0",
                                        diff --git a/assets/outbound.html-CxLNkOG0.js b/assets/outbound.html-CGmYQFef.js
                                        similarity index 99%
                                        rename from assets/outbound.html-CxLNkOG0.js
                                        rename to assets/outbound.html-CGmYQFef.js
                                        index 7c3ef25477..86f87bddce 100644
                                        --- a/assets/outbound.html-CxLNkOG0.js
                                        +++ b/assets/outbound.html-CGmYQFef.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as c,o as r,c as l,a as o,b as n,d as e,w as s,e as a}from"./app-5SoadDYS.js";const d={},h=n("h1",{id:"outbound-proxies",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#outbound-proxies"},[n("span",null,"Outbound Proxies")])],-1),b=a(`

                                        OutboundObject

                                        The OutboundObject corresponds to a sub-element of the outbounds item in the configuration file.

                                        Tip

                                        The first element in the list serves as the main outbound. When there is no match or no successful match for the routing, the traffic is sent out by the main outbound.

                                        {
                                        +import{_ as p,r as c,o as r,c as l,a as o,b as n,d as e,w as s,e as a}from"./app-Bw2NG-QJ.js";const d={},h=n("h1",{id:"outbound-proxies",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#outbound-proxies"},[n("span",null,"Outbound Proxies")])],-1),b=a(`

                                        OutboundObject

                                        The OutboundObject corresponds to a sub-element of the outbounds item in the configuration file.

                                        Tip

                                        The first element in the list serves as the main outbound. When there is no match or no successful match for the routing, the traffic is sent out by the main outbound.

                                        {
                                           "outbounds": [
                                             {
                                               "sendThrough": "0.0.0.0",
                                        diff --git a/assets/outbound.html-bdM8vFfU.js b/assets/outbound.html-DWjB8mz5.js
                                        similarity index 99%
                                        rename from assets/outbound.html-bdM8vFfU.js
                                        rename to assets/outbound.html-DWjB8mz5.js
                                        index 898346766a..1c9a44fa17 100644
                                        --- a/assets/outbound.html-bdM8vFfU.js
                                        +++ b/assets/outbound.html-DWjB8mz5.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as d,r as e,o as l,c as i,a as s,b as n,d as o,w as a,e as c}from"./app-5SoadDYS.js";const r={},b=n("h1",{id:"出站代理-mux、xudp",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#出站代理-mux、xudp"},[n("span",null,"出站代理(Mux、XUDP)")])],-1),k=c(`

                                        OutboundObject

                                        OutboundObject 对应配置文件中 outbounds 项的一个子元素。

                                        提示

                                        列表中的第一个元素作为主 outbound。当路由匹配不存在或没有匹配成功时,流量由主 outbound 发出。

                                        {
                                        +import{_ as d,r as e,o as l,c as i,a as s,b as n,d as o,w as a,e as c}from"./app-Bw2NG-QJ.js";const r={},b=n("h1",{id:"出站代理-mux、xudp",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#出站代理-mux、xudp"},[n("span",null,"出站代理(Mux、XUDP)")])],-1),k=c(`

                                        OutboundObject

                                        OutboundObject 对应配置文件中 outbounds 项的一个子元素。

                                        提示

                                        列表中的第一个元素作为主 outbound。当路由匹配不存在或没有匹配成功时,流量由主 outbound 发出。

                                        {
                                           "outbounds": [
                                             {
                                               "sendThrough": "0.0.0.0",
                                        diff --git a/assets/pieDiagram-bb1d19e5-BQuVNcMJ.js b/assets/pieDiagram-bb1d19e5-CBxnSt2_.js
                                        similarity index 98%
                                        rename from assets/pieDiagram-bb1d19e5-BQuVNcMJ.js
                                        rename to assets/pieDiagram-bb1d19e5-CBxnSt2_.js
                                        index 3549b00770..892f864190 100644
                                        --- a/assets/pieDiagram-bb1d19e5-BQuVNcMJ.js
                                        +++ b/assets/pieDiagram-bb1d19e5-CBxnSt2_.js
                                        @@ -1,4 +1,4 @@
                                        -import{aK as q,aL as at,x as lt,y as ot,s as ct,g as ht,b as ut,a as yt,A as ft,d as pt,c as et,l as it,aM as gt,aJ as dt,aN as mt,i as _t}from"./mermaid.core-CArNAncI.js";import{a as tt}from"./arc-xLaeEKkr.js";import{o as xt}from"./ordinal-Cboi1Yqb.js";import{a as kt}from"./array-BKyUJesY.js";import{c as F}from"./path-CbwjOpE9.js";import"./app-5SoadDYS.js";import"./init-Gi6I4Gst.js";function vt(e,u){return ue?1:u>=e?0:NaN}function bt(e){return e}function St(){var e=bt,u=vt,$=null,p=F(0),g=F(q),A=F(0);function y(a){var l,d=(a=kt(a)).length,m,I,T=0,_=new Array(d),v=new Array(d),c=+p.apply(this,arguments),E=Math.min(q,Math.max(-q,g.apply(this,arguments)-c)),O,w=Math.min(Math.abs(E)/d,A.apply(this,arguments)),b=w*(E<0?-1:1),t;for(l=0;l0&&(T+=t);for(u!=null?_.sort(function(i,n){return u(v[i],v[n])}):$!=null&&_.sort(function(i,n){return $(a[i],a[n])}),l=0,I=T?(E-d*b)/T:0;l0?t*I:0)+b,v[m]={data:a[m],index:l,value:t,startAngle:c,endAngle:O,padAngle:w};return v}return y.value=function(a){return arguments.length?(e=typeof a=="function"?a:F(+a),y):e},y.sortValues=function(a){return arguments.length?(u=a,$=null,y):u},y.sort=function(a){return arguments.length?($=a,u=null,y):$},y.startAngle=function(a){return arguments.length?(p=typeof a=="function"?a:F(+a),y):p},y.endAngle=function(a){return arguments.length?(g=typeof a=="function"?a:F(+a),y):g},y.padAngle=function(a){return arguments.length?(A=typeof a=="function"?a:F(+a),y):A},y}var H=function(){var e=function(b,t,i,n){for(i=i||{},n=b.length;n--;i[b[n]]=t);return i},u=[1,3],$=[1,4],p=[1,5],g=[1,6],A=[1,10,12,14,16,18,19,20,21,22],y=[2,4],a=[1,5,10,12,14,16,18,19,20,21,22],l=[20,21,22],d=[2,7],m=[1,12],I=[1,13],T=[1,14],_=[1,15],v=[1,16],c=[1,17],E={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,PIE:5,document:6,showData:7,line:8,statement:9,txt:10,value:11,title:12,title_value:13,acc_title:14,acc_title_value:15,acc_descr:16,acc_descr_value:17,acc_descr_multiline_value:18,section:19,NEWLINE:20,";":21,EOF:22,$accept:0,$end:1},terminals_:{2:"error",5:"PIE",7:"showData",10:"txt",11:"value",12:"title",13:"title_value",14:"acc_title",15:"acc_title_value",16:"acc_descr",17:"acc_descr_value",18:"acc_descr_multiline_value",19:"section",20:"NEWLINE",21:";",22:"EOF"},productions_:[0,[3,2],[3,2],[3,3],[6,0],[6,2],[8,2],[9,0],[9,2],[9,2],[9,2],[9,2],[9,1],[9,1],[4,1],[4,1],[4,1]],performAction:function(t,i,n,r,o,s,P){var x=s.length-1;switch(o){case 3:r.setShowData(!0);break;case 6:this.$=s[x-1];break;case 8:r.addSection(s[x-1],r.cleanupValue(s[x]));break;case 9:this.$=s[x].trim(),r.setDiagramTitle(this.$);break;case 10:this.$=s[x].trim(),r.setAccTitle(this.$);break;case 11:case 12:this.$=s[x].trim(),r.setAccDescription(this.$);break;case 13:r.addSection(s[x].substr(8)),this.$=s[x].substr(8);break}},table:[{3:1,4:2,5:u,20:$,21:p,22:g},{1:[3]},{3:7,4:2,5:u,20:$,21:p,22:g},e(A,y,{6:8,7:[1,9]}),e(a,[2,14]),e(a,[2,15]),e(a,[2,16]),{1:[2,1]},e(l,d,{8:10,9:11,1:[2,2],10:m,12:I,14:T,16:_,18:v,19:c}),e(A,y,{6:18}),e(A,[2,5]),{4:19,20:$,21:p,22:g},{11:[1,20]},{13:[1,21]},{15:[1,22]},{17:[1,23]},e(l,[2,12]),e(l,[2,13]),e(l,d,{8:10,9:11,1:[2,3],10:m,12:I,14:T,16:_,18:v,19:c}),e(A,[2,6]),e(l,[2,8]),e(l,[2,9]),e(l,[2,10]),e(l,[2,11])],defaultActions:{7:[2,1]},parseError:function(t,i){if(i.recoverable)this.trace(t);else{var n=new Error(t);throw n.hash=i,n}},parse:function(t){var i=this,n=[0],r=[],o=[null],s=[],P=this.table,x="",f=0,V=0,R=2,M=1,B=s.slice.call(arguments,1),h=Object.create(this.lexer),N={yy:{}};for(var Y in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Y)&&(N.yy[Y]=this.yy[Y]);h.setInput(t,N.yy),N.yy.lexer=h,N.yy.parser=this,typeof h.yylloc>"u"&&(h.yylloc={});var J=h.yylloc;s.push(J);var st=h.options&&h.options.ranges;typeof N.yy.parseError=="function"?this.parseError=N.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function rt(){var C;return C=r.pop()||h.lex()||M,typeof C!="number"&&(C instanceof Array&&(r=C,C=r.pop()),C=i.symbols_[C]||C),C}for(var k,L,S,K,z={},j,D,X,W;;){if(L=n[n.length-1],this.defaultActions[L]?S=this.defaultActions[L]:((k===null||typeof k>"u")&&(k=rt()),S=P[L]&&P[L][k]),typeof S>"u"||!S.length||!S[0]){var Z="";W=[];for(j in P[L])this.terminals_[j]&&j>R&&W.push("'"+this.terminals_[j]+"'");h.showPosition?Z="Parse error on line "+(f+1)+`:
                                        +import{aK as q,aL as at,x as lt,y as ot,s as ct,g as ht,b as ut,a as yt,A as ft,d as pt,c as et,l as it,aM as gt,aJ as dt,aN as mt,i as _t}from"./mermaid.core-Bq0kX0MS.js";import{a as tt}from"./arc-C5d-KvsZ.js";import{o as xt}from"./ordinal-Cboi1Yqb.js";import{a as kt}from"./array-BKyUJesY.js";import{c as F}from"./path-CbwjOpE9.js";import"./app-Bw2NG-QJ.js";import"./init-Gi6I4Gst.js";function vt(e,u){return ue?1:u>=e?0:NaN}function bt(e){return e}function St(){var e=bt,u=vt,$=null,p=F(0),g=F(q),A=F(0);function y(a){var l,d=(a=kt(a)).length,m,I,T=0,_=new Array(d),v=new Array(d),c=+p.apply(this,arguments),E=Math.min(q,Math.max(-q,g.apply(this,arguments)-c)),O,w=Math.min(Math.abs(E)/d,A.apply(this,arguments)),b=w*(E<0?-1:1),t;for(l=0;l0&&(T+=t);for(u!=null?_.sort(function(i,n){return u(v[i],v[n])}):$!=null&&_.sort(function(i,n){return $(a[i],a[n])}),l=0,I=T?(E-d*b)/T:0;l0?t*I:0)+b,v[m]={data:a[m],index:l,value:t,startAngle:c,endAngle:O,padAngle:w};return v}return y.value=function(a){return arguments.length?(e=typeof a=="function"?a:F(+a),y):e},y.sortValues=function(a){return arguments.length?(u=a,$=null,y):u},y.sort=function(a){return arguments.length?($=a,u=null,y):$},y.startAngle=function(a){return arguments.length?(p=typeof a=="function"?a:F(+a),y):p},y.endAngle=function(a){return arguments.length?(g=typeof a=="function"?a:F(+a),y):g},y.padAngle=function(a){return arguments.length?(A=typeof a=="function"?a:F(+a),y):A},y}var H=function(){var e=function(b,t,i,n){for(i=i||{},n=b.length;n--;i[b[n]]=t);return i},u=[1,3],$=[1,4],p=[1,5],g=[1,6],A=[1,10,12,14,16,18,19,20,21,22],y=[2,4],a=[1,5,10,12,14,16,18,19,20,21,22],l=[20,21,22],d=[2,7],m=[1,12],I=[1,13],T=[1,14],_=[1,15],v=[1,16],c=[1,17],E={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,PIE:5,document:6,showData:7,line:8,statement:9,txt:10,value:11,title:12,title_value:13,acc_title:14,acc_title_value:15,acc_descr:16,acc_descr_value:17,acc_descr_multiline_value:18,section:19,NEWLINE:20,";":21,EOF:22,$accept:0,$end:1},terminals_:{2:"error",5:"PIE",7:"showData",10:"txt",11:"value",12:"title",13:"title_value",14:"acc_title",15:"acc_title_value",16:"acc_descr",17:"acc_descr_value",18:"acc_descr_multiline_value",19:"section",20:"NEWLINE",21:";",22:"EOF"},productions_:[0,[3,2],[3,2],[3,3],[6,0],[6,2],[8,2],[9,0],[9,2],[9,2],[9,2],[9,2],[9,1],[9,1],[4,1],[4,1],[4,1]],performAction:function(t,i,n,r,o,s,P){var x=s.length-1;switch(o){case 3:r.setShowData(!0);break;case 6:this.$=s[x-1];break;case 8:r.addSection(s[x-1],r.cleanupValue(s[x]));break;case 9:this.$=s[x].trim(),r.setDiagramTitle(this.$);break;case 10:this.$=s[x].trim(),r.setAccTitle(this.$);break;case 11:case 12:this.$=s[x].trim(),r.setAccDescription(this.$);break;case 13:r.addSection(s[x].substr(8)),this.$=s[x].substr(8);break}},table:[{3:1,4:2,5:u,20:$,21:p,22:g},{1:[3]},{3:7,4:2,5:u,20:$,21:p,22:g},e(A,y,{6:8,7:[1,9]}),e(a,[2,14]),e(a,[2,15]),e(a,[2,16]),{1:[2,1]},e(l,d,{8:10,9:11,1:[2,2],10:m,12:I,14:T,16:_,18:v,19:c}),e(A,y,{6:18}),e(A,[2,5]),{4:19,20:$,21:p,22:g},{11:[1,20]},{13:[1,21]},{15:[1,22]},{17:[1,23]},e(l,[2,12]),e(l,[2,13]),e(l,d,{8:10,9:11,1:[2,3],10:m,12:I,14:T,16:_,18:v,19:c}),e(A,[2,6]),e(l,[2,8]),e(l,[2,9]),e(l,[2,10]),e(l,[2,11])],defaultActions:{7:[2,1]},parseError:function(t,i){if(i.recoverable)this.trace(t);else{var n=new Error(t);throw n.hash=i,n}},parse:function(t){var i=this,n=[0],r=[],o=[null],s=[],P=this.table,x="",f=0,V=0,R=2,M=1,B=s.slice.call(arguments,1),h=Object.create(this.lexer),N={yy:{}};for(var Y in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Y)&&(N.yy[Y]=this.yy[Y]);h.setInput(t,N.yy),N.yy.lexer=h,N.yy.parser=this,typeof h.yylloc>"u"&&(h.yylloc={});var J=h.yylloc;s.push(J);var st=h.options&&h.options.ranges;typeof N.yy.parseError=="function"?this.parseError=N.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function rt(){var C;return C=r.pop()||h.lex()||M,typeof C!="number"&&(C instanceof Array&&(r=C,C=r.pop()),C=i.symbols_[C]||C),C}for(var k,L,S,K,z={},j,D,X,W;;){if(L=n[n.length-1],this.defaultActions[L]?S=this.defaultActions[L]:((k===null||typeof k>"u")&&(k=rt()),S=P[L]&&P[L][k]),typeof S>"u"||!S.length||!S[0]){var Z="";W=[];for(j in P[L])this.terminals_[j]&&j>R&&W.push("'"+this.terminals_[j]+"'");h.showPosition?Z="Parse error on line "+(f+1)+`:
                                         `+h.showPosition()+`
                                         Expecting `+W.join(", ")+", got '"+(this.terminals_[k]||k)+"'":Z="Parse error on line "+(f+1)+": Unexpected "+(k==M?"end of input":"'"+(this.terminals_[k]||k)+"'"),this.parseError(Z,{text:h.match,token:this.terminals_[k]||k,line:h.yylineno,loc:J,expected:W})}if(S[0]instanceof Array&&S.length>1)throw new Error("Parse Error: multiple actions possible at state: "+L+", token: "+k);switch(S[0]){case 1:n.push(k),o.push(h.yytext),s.push(h.yylloc),n.push(S[1]),k=null,V=h.yyleng,x=h.yytext,f=h.yylineno,J=h.yylloc;break;case 2:if(D=this.productions_[S[1]][1],z.$=o[o.length-D],z._$={first_line:s[s.length-(D||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(D||1)].first_column,last_column:s[s.length-1].last_column},st&&(z._$.range=[s[s.length-(D||1)].range[0],s[s.length-1].range[1]]),K=this.performAction.apply(z,[x,V,f,N.yy,S[1],o,s].concat(B)),typeof K<"u")return K;D&&(n=n.slice(0,-1*D*2),o=o.slice(0,-1*D),s=s.slice(0,-1*D)),n.push(this.productions_[S[1]][0]),o.push(z.$),s.push(z._$),X=P[n[n.length-2]][n[n.length-1]],n.push(X);break;case 3:return!0}}return!0}},O=function(){var b={EOF:1,parseError:function(i,n){if(this.yy.parser)this.yy.parser.parseError(i,n);else throw new Error(i)},setInput:function(t,i){return this.yy=i||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t;var i=t.match(/(?:\r\n?|\n).*/g);return i?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var i=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-i),this.offset-=i;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var o=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-i},this.options.ranges&&(this.yylloc.range=[o[0],o[0]+this.yyleng-i]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),i=new Array(t.length+1).join("-");return t+this.upcomingInput()+`
                                        diff --git a/assets/policy.html-D1uwT0yS.js b/assets/policy.html-B9TBd0jy.js
                                        similarity index 99%
                                        rename from assets/policy.html-D1uwT0yS.js
                                        rename to assets/policy.html-B9TBd0jy.js
                                        index c59a33277e..f06e59089a 100644
                                        --- a/assets/policy.html-D1uwT0yS.js
                                        +++ b/assets/policy.html-B9TBd0jy.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o as e,c as o,a as p,e as t}from"./app-5SoadDYS.js";const c={},l=t(`

                                        Локальные политики

                                        Локальные политики позволяют настраивать различные уровни пользователей и соответствующие им политики, например, настройки тайм-аута подключения.
                                        Каждое соединение, обрабатываемое Xray, соответствует определенному пользователю, и к нему применяются политики в соответствии с уровнем пользователя (level).

                                        PolicyObject

                                        PolicyObject соответствует полю policy в конфигурационном файле.

                                        {
                                        +import{_ as s,r as a,o as e,c as o,a as p,e as t}from"./app-Bw2NG-QJ.js";const c={},l=t(`

                                        Локальные политики

                                        Локальные политики позволяют настраивать различные уровни пользователей и соответствующие им политики, например, настройки тайм-аута подключения.
                                        Каждое соединение, обрабатываемое Xray, соответствует определенному пользователю, и к нему применяются политики в соответствии с уровнем пользователя (level).

                                        PolicyObject

                                        PolicyObject соответствует полю policy в конфигурационном файле.

                                        {
                                           "policy": {
                                             "levels": {
                                               "0": {
                                        diff --git a/assets/policy.html-Bq1Nx697.js b/assets/policy.html-D7HzBw03.js
                                        similarity index 98%
                                        rename from assets/policy.html-Bq1Nx697.js
                                        rename to assets/policy.html-D7HzBw03.js
                                        index ecfec0205e..5143b43042 100644
                                        --- a/assets/policy.html-Bq1Nx697.js
                                        +++ b/assets/policy.html-D7HzBw03.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as a,o as e,c as o,a as t,e as p}from"./app-5SoadDYS.js";const c={},l=p(`

                                        本地策略

                                        本地策略,可以设置不同的用户等级和对应的策略设置,比如连接超时设置。Xray 处理的每一个连接都对应一个用户,按照用户的等级(level)应用不同的策略。

                                        PolicyObject

                                        PolicyObject 对应配置文件的 policy 项。

                                        {
                                        +import{_ as s,r as a,o as e,c as o,a as t,e as p}from"./app-Bw2NG-QJ.js";const c={},l=p(`

                                        本地策略

                                        本地策略,可以设置不同的用户等级和对应的策略设置,比如连接超时设置。Xray 处理的每一个连接都对应一个用户,按照用户的等级(level)应用不同的策略。

                                        PolicyObject

                                        PolicyObject 对应配置文件的 policy 项。

                                        {
                                           "policy": {
                                             "levels": {
                                               "0": {
                                        diff --git a/assets/policy.html-fqGpJICm.js b/assets/policy.html-DiLfrWDT.js
                                        similarity index 98%
                                        rename from assets/policy.html-fqGpJICm.js
                                        rename to assets/policy.html-DiLfrWDT.js
                                        index 7cc87b5794..1dec9c478d 100644
                                        --- a/assets/policy.html-fqGpJICm.js
                                        +++ b/assets/policy.html-DiLfrWDT.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as s,r as e,o as a,c as o,a as t,e as p}from"./app-5SoadDYS.js";const c={},l=p(`

                                        Local Policy

                                        Local policy can be used to set different policy settings for different user levels, such as connection timeout settings. Each connection handled by Xray corresponds to a user, and different policies are applied based on the user's level.

                                        PolicyObject

                                        PolicyObject corresponds to the policy field in the configuration file.

                                        {
                                        +import{_ as s,r as e,o as a,c as o,a as t,e as p}from"./app-Bw2NG-QJ.js";const c={},l=p(`

                                        Local Policy

                                        Local policy can be used to set different policy settings for different user levels, such as connection timeout settings. Each connection handled by Xray corresponds to a user, and different policies are applied based on the user's level.

                                        PolicyObject

                                        PolicyObject corresponds to the policy field in the configuration file.

                                        {
                                           "policy": {
                                             "levels": {
                                               "0": {
                                        diff --git a/assets/quadrantDiagram-c759a472-B16G3h9g.js b/assets/quadrantDiagram-c759a472-DYqUNjWH.js
                                        similarity index 99%
                                        rename from assets/quadrantDiagram-c759a472-B16G3h9g.js
                                        rename to assets/quadrantDiagram-c759a472-DYqUNjWH.js
                                        index e773d9d965..f14b7769bc 100644
                                        --- a/assets/quadrantDiagram-c759a472-B16G3h9g.js
                                        +++ b/assets/quadrantDiagram-c759a472-DYqUNjWH.js
                                        @@ -1,4 +1,4 @@
                                        -import{a_ as vt,c as yt,aL as D,l as ot,s as Lt,g as Ct,x as zt,y as bt,a as Et,b as Dt,A as It,h as gt,i as Bt,d as wt}from"./mermaid.core-CArNAncI.js";import{l as mt}from"./linear-DFdMY4Xo.js";import"./app-5SoadDYS.js";import"./init-Gi6I4Gst.js";var pt=function(){var e=function(K,n,r,l){for(r=r||{},l=K.length;l--;r[K[l]]=n);return r},s=[1,3],h=[1,4],x=[1,5],f=[1,6],d=[1,7],c=[1,5,13,15,17,19,20,25,27,28,29,30,31,32,33,34,37,38,40,41,42,43,44,45,46,47,48,49,50],g=[1,5,6,13,15,17,19,20,25,27,28,29,30,31,32,33,34,37,38,40,41,42,43,44,45,46,47,48,49,50],i=[32,33,34],y=[2,7],p=[1,13],B=[1,17],N=[1,18],V=[1,19],I=[1,20],b=[1,21],M=[1,22],X=[1,23],C=[1,24],it=[1,25],at=[1,26],nt=[1,27],U=[1,30],Q=[1,31],T=[1,32],m=[1,33],_=[1,34],t=[1,35],A=[1,36],S=[1,37],k=[1,38],F=[1,39],P=[1,40],v=[1,41],L=[1,42],O=[1,57],Y=[1,58],z=[5,22,26,32,33,34,40,41,42,43,44,45,46,47,48,49,50,51],ht={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,SPACE:5,QUADRANT:6,document:7,line:8,statement:9,axisDetails:10,quadrantDetails:11,points:12,title:13,title_value:14,acc_title:15,acc_title_value:16,acc_descr:17,acc_descr_value:18,acc_descr_multiline_value:19,section:20,text:21,point_start:22,point_x:23,point_y:24,"X-AXIS":25,"AXIS-TEXT-DELIMITER":26,"Y-AXIS":27,QUADRANT_1:28,QUADRANT_2:29,QUADRANT_3:30,QUADRANT_4:31,NEWLINE:32,SEMI:33,EOF:34,alphaNumToken:35,textNoTagsToken:36,STR:37,MD_STR:38,alphaNum:39,PUNCTUATION:40,AMP:41,NUM:42,ALPHA:43,COMMA:44,PLUS:45,EQUALS:46,MULT:47,DOT:48,BRKT:49,UNDERSCORE:50,MINUS:51,$accept:0,$end:1},terminals_:{2:"error",5:"SPACE",6:"QUADRANT",13:"title",14:"title_value",15:"acc_title",16:"acc_title_value",17:"acc_descr",18:"acc_descr_value",19:"acc_descr_multiline_value",20:"section",22:"point_start",23:"point_x",24:"point_y",25:"X-AXIS",26:"AXIS-TEXT-DELIMITER",27:"Y-AXIS",28:"QUADRANT_1",29:"QUADRANT_2",30:"QUADRANT_3",31:"QUADRANT_4",32:"NEWLINE",33:"SEMI",34:"EOF",37:"STR",38:"MD_STR",40:"PUNCTUATION",41:"AMP",42:"NUM",43:"ALPHA",44:"COMMA",45:"PLUS",46:"EQUALS",47:"MULT",48:"DOT",49:"BRKT",50:"UNDERSCORE",51:"MINUS"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[9,0],[9,2],[9,1],[9,1],[9,1],[9,2],[9,2],[9,2],[9,1],[9,1],[12,4],[10,4],[10,3],[10,2],[10,4],[10,3],[10,2],[11,2],[11,2],[11,2],[11,2],[4,1],[4,1],[4,1],[21,1],[21,2],[21,1],[21,1],[39,1],[39,2],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[36,1],[36,1],[36,1]],performAction:function(n,r,l,o,q,a,et){var u=a.length-1;switch(q){case 12:this.$=a[u].trim(),o.setDiagramTitle(this.$);break;case 13:this.$=a[u].trim(),o.setAccTitle(this.$);break;case 14:case 15:this.$=a[u].trim(),o.setAccDescription(this.$);break;case 16:o.addSection(a[u].substr(8)),this.$=a[u].substr(8);break;case 17:o.addPoint(a[u-3],a[u-1],a[u]);break;case 18:o.setXAxisLeftText(a[u-2]),o.setXAxisRightText(a[u]);break;case 19:a[u-1].text+=" ⟶ ",o.setXAxisLeftText(a[u-1]);break;case 20:o.setXAxisLeftText(a[u]);break;case 21:o.setYAxisBottomText(a[u-2]),o.setYAxisTopText(a[u]);break;case 22:a[u-1].text+=" ⟶ ",o.setYAxisBottomText(a[u-1]);break;case 23:o.setYAxisBottomText(a[u]);break;case 24:o.setQuadrant1Text(a[u]);break;case 25:o.setQuadrant2Text(a[u]);break;case 26:o.setQuadrant3Text(a[u]);break;case 27:o.setQuadrant4Text(a[u]);break;case 31:this.$={text:a[u],type:"text"};break;case 32:this.$={text:a[u-1].text+""+a[u],type:a[u-1].type};break;case 33:this.$={text:a[u],type:"text"};break;case 34:this.$={text:a[u],type:"markdown"};break;case 35:this.$=a[u];break;case 36:this.$=a[u-1]+""+a[u];break}},table:[{3:1,4:2,5:s,6:h,32:x,33:f,34:d},{1:[3]},{3:8,4:2,5:s,6:h,32:x,33:f,34:d},{3:9,4:2,5:s,6:h,32:x,33:f,34:d},e(c,[2,4],{7:10}),e(g,[2,28]),e(g,[2,29]),e(g,[2,30]),{1:[2,1]},{1:[2,2]},e(i,y,{8:11,9:12,10:14,11:15,12:16,21:28,35:29,1:[2,3],5:p,13:B,15:N,17:V,19:I,20:b,25:M,27:X,28:C,29:it,30:at,31:nt,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),e(c,[2,5]),{4:43,32:x,33:f,34:d},e(i,y,{10:14,11:15,12:16,21:28,35:29,9:44,5:p,13:B,15:N,17:V,19:I,20:b,25:M,27:X,28:C,29:it,30:at,31:nt,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),e(i,[2,9]),e(i,[2,10]),e(i,[2,11]),{14:[1,45]},{16:[1,46]},{18:[1,47]},e(i,[2,15]),e(i,[2,16]),{21:48,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:49,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:50,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:51,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:52,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:53,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{5:O,22:[1,54],35:56,36:55,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y},e(z,[2,31]),e(z,[2,33]),e(z,[2,34]),e(z,[2,37]),e(z,[2,38]),e(z,[2,39]),e(z,[2,40]),e(z,[2,41]),e(z,[2,42]),e(z,[2,43]),e(z,[2,44]),e(z,[2,45]),e(z,[2,46]),e(z,[2,47]),e(c,[2,6]),e(i,[2,8]),e(i,[2,12]),e(i,[2,13]),e(i,[2,14]),e(i,[2,20],{36:55,35:56,5:O,26:[1,59],40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,23],{36:55,35:56,5:O,26:[1,60],40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,24],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,25],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,26],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,27],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),{23:[1,61]},e(z,[2,32]),e(z,[2,48]),e(z,[2,49]),e(z,[2,50]),e(i,[2,19],{35:29,21:62,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),e(i,[2,22],{35:29,21:63,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),{24:[1,64]},e(i,[2,18],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,21],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,17])],defaultActions:{8:[2,1],9:[2,2]},parseError:function(n,r){if(r.recoverable)this.trace(n);else{var l=new Error(n);throw l.hash=r,l}},parse:function(n){var r=this,l=[0],o=[],q=[null],a=[],et=this.table,u="",st=0,qt=0,St=2,Tt=1,kt=a.slice.call(arguments,1),E=Object.create(this.lexer),Z={yy:{}};for(var dt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,dt)&&(Z.yy[dt]=this.yy[dt]);E.setInput(n,Z.yy),Z.yy.lexer=E,Z.yy.parser=this,typeof E.yylloc>"u"&&(E.yylloc={});var ut=E.yylloc;a.push(ut);var Ft=E.options&&E.options.ranges;typeof Z.yy.parseError=="function"?this.parseError=Z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Pt(){var j;return j=o.pop()||E.lex()||Tt,typeof j!="number"&&(j instanceof Array&&(o=j,j=o.pop()),j=r.symbols_[j]||j),j}for(var W,J,H,xt,tt={},rt,$,_t,lt;;){if(J=l[l.length-1],this.defaultActions[J]?H=this.defaultActions[J]:((W===null||typeof W>"u")&&(W=Pt()),H=et[J]&&et[J][W]),typeof H>"u"||!H.length||!H[0]){var ft="";lt=[];for(rt in et[J])this.terminals_[rt]&&rt>St&<.push("'"+this.terminals_[rt]+"'");E.showPosition?ft="Parse error on line "+(st+1)+`:
                                        +import{a_ as vt,c as yt,aL as D,l as ot,s as Lt,g as Ct,x as zt,y as bt,a as Et,b as Dt,A as It,h as gt,i as Bt,d as wt}from"./mermaid.core-Bq0kX0MS.js";import{l as mt}from"./linear-CopLvHML.js";import"./app-Bw2NG-QJ.js";import"./init-Gi6I4Gst.js";var pt=function(){var e=function(K,n,r,l){for(r=r||{},l=K.length;l--;r[K[l]]=n);return r},s=[1,3],h=[1,4],x=[1,5],f=[1,6],d=[1,7],c=[1,5,13,15,17,19,20,25,27,28,29,30,31,32,33,34,37,38,40,41,42,43,44,45,46,47,48,49,50],g=[1,5,6,13,15,17,19,20,25,27,28,29,30,31,32,33,34,37,38,40,41,42,43,44,45,46,47,48,49,50],i=[32,33,34],y=[2,7],p=[1,13],B=[1,17],N=[1,18],V=[1,19],I=[1,20],b=[1,21],M=[1,22],X=[1,23],C=[1,24],it=[1,25],at=[1,26],nt=[1,27],U=[1,30],Q=[1,31],T=[1,32],m=[1,33],_=[1,34],t=[1,35],A=[1,36],S=[1,37],k=[1,38],F=[1,39],P=[1,40],v=[1,41],L=[1,42],O=[1,57],Y=[1,58],z=[5,22,26,32,33,34,40,41,42,43,44,45,46,47,48,49,50,51],ht={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,SPACE:5,QUADRANT:6,document:7,line:8,statement:9,axisDetails:10,quadrantDetails:11,points:12,title:13,title_value:14,acc_title:15,acc_title_value:16,acc_descr:17,acc_descr_value:18,acc_descr_multiline_value:19,section:20,text:21,point_start:22,point_x:23,point_y:24,"X-AXIS":25,"AXIS-TEXT-DELIMITER":26,"Y-AXIS":27,QUADRANT_1:28,QUADRANT_2:29,QUADRANT_3:30,QUADRANT_4:31,NEWLINE:32,SEMI:33,EOF:34,alphaNumToken:35,textNoTagsToken:36,STR:37,MD_STR:38,alphaNum:39,PUNCTUATION:40,AMP:41,NUM:42,ALPHA:43,COMMA:44,PLUS:45,EQUALS:46,MULT:47,DOT:48,BRKT:49,UNDERSCORE:50,MINUS:51,$accept:0,$end:1},terminals_:{2:"error",5:"SPACE",6:"QUADRANT",13:"title",14:"title_value",15:"acc_title",16:"acc_title_value",17:"acc_descr",18:"acc_descr_value",19:"acc_descr_multiline_value",20:"section",22:"point_start",23:"point_x",24:"point_y",25:"X-AXIS",26:"AXIS-TEXT-DELIMITER",27:"Y-AXIS",28:"QUADRANT_1",29:"QUADRANT_2",30:"QUADRANT_3",31:"QUADRANT_4",32:"NEWLINE",33:"SEMI",34:"EOF",37:"STR",38:"MD_STR",40:"PUNCTUATION",41:"AMP",42:"NUM",43:"ALPHA",44:"COMMA",45:"PLUS",46:"EQUALS",47:"MULT",48:"DOT",49:"BRKT",50:"UNDERSCORE",51:"MINUS"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[9,0],[9,2],[9,1],[9,1],[9,1],[9,2],[9,2],[9,2],[9,1],[9,1],[12,4],[10,4],[10,3],[10,2],[10,4],[10,3],[10,2],[11,2],[11,2],[11,2],[11,2],[4,1],[4,1],[4,1],[21,1],[21,2],[21,1],[21,1],[39,1],[39,2],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[36,1],[36,1],[36,1]],performAction:function(n,r,l,o,q,a,et){var u=a.length-1;switch(q){case 12:this.$=a[u].trim(),o.setDiagramTitle(this.$);break;case 13:this.$=a[u].trim(),o.setAccTitle(this.$);break;case 14:case 15:this.$=a[u].trim(),o.setAccDescription(this.$);break;case 16:o.addSection(a[u].substr(8)),this.$=a[u].substr(8);break;case 17:o.addPoint(a[u-3],a[u-1],a[u]);break;case 18:o.setXAxisLeftText(a[u-2]),o.setXAxisRightText(a[u]);break;case 19:a[u-1].text+=" ⟶ ",o.setXAxisLeftText(a[u-1]);break;case 20:o.setXAxisLeftText(a[u]);break;case 21:o.setYAxisBottomText(a[u-2]),o.setYAxisTopText(a[u]);break;case 22:a[u-1].text+=" ⟶ ",o.setYAxisBottomText(a[u-1]);break;case 23:o.setYAxisBottomText(a[u]);break;case 24:o.setQuadrant1Text(a[u]);break;case 25:o.setQuadrant2Text(a[u]);break;case 26:o.setQuadrant3Text(a[u]);break;case 27:o.setQuadrant4Text(a[u]);break;case 31:this.$={text:a[u],type:"text"};break;case 32:this.$={text:a[u-1].text+""+a[u],type:a[u-1].type};break;case 33:this.$={text:a[u],type:"text"};break;case 34:this.$={text:a[u],type:"markdown"};break;case 35:this.$=a[u];break;case 36:this.$=a[u-1]+""+a[u];break}},table:[{3:1,4:2,5:s,6:h,32:x,33:f,34:d},{1:[3]},{3:8,4:2,5:s,6:h,32:x,33:f,34:d},{3:9,4:2,5:s,6:h,32:x,33:f,34:d},e(c,[2,4],{7:10}),e(g,[2,28]),e(g,[2,29]),e(g,[2,30]),{1:[2,1]},{1:[2,2]},e(i,y,{8:11,9:12,10:14,11:15,12:16,21:28,35:29,1:[2,3],5:p,13:B,15:N,17:V,19:I,20:b,25:M,27:X,28:C,29:it,30:at,31:nt,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),e(c,[2,5]),{4:43,32:x,33:f,34:d},e(i,y,{10:14,11:15,12:16,21:28,35:29,9:44,5:p,13:B,15:N,17:V,19:I,20:b,25:M,27:X,28:C,29:it,30:at,31:nt,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),e(i,[2,9]),e(i,[2,10]),e(i,[2,11]),{14:[1,45]},{16:[1,46]},{18:[1,47]},e(i,[2,15]),e(i,[2,16]),{21:48,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:49,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:50,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:51,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:52,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{21:53,35:29,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L},{5:O,22:[1,54],35:56,36:55,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y},e(z,[2,31]),e(z,[2,33]),e(z,[2,34]),e(z,[2,37]),e(z,[2,38]),e(z,[2,39]),e(z,[2,40]),e(z,[2,41]),e(z,[2,42]),e(z,[2,43]),e(z,[2,44]),e(z,[2,45]),e(z,[2,46]),e(z,[2,47]),e(c,[2,6]),e(i,[2,8]),e(i,[2,12]),e(i,[2,13]),e(i,[2,14]),e(i,[2,20],{36:55,35:56,5:O,26:[1,59],40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,23],{36:55,35:56,5:O,26:[1,60],40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,24],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,25],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,26],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,27],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),{23:[1,61]},e(z,[2,32]),e(z,[2,48]),e(z,[2,49]),e(z,[2,50]),e(i,[2,19],{35:29,21:62,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),e(i,[2,22],{35:29,21:63,37:U,38:Q,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L}),{24:[1,64]},e(i,[2,18],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,21],{36:55,35:56,5:O,40:T,41:m,42:_,43:t,44:A,45:S,46:k,47:F,48:P,49:v,50:L,51:Y}),e(i,[2,17])],defaultActions:{8:[2,1],9:[2,2]},parseError:function(n,r){if(r.recoverable)this.trace(n);else{var l=new Error(n);throw l.hash=r,l}},parse:function(n){var r=this,l=[0],o=[],q=[null],a=[],et=this.table,u="",st=0,qt=0,St=2,Tt=1,kt=a.slice.call(arguments,1),E=Object.create(this.lexer),Z={yy:{}};for(var dt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,dt)&&(Z.yy[dt]=this.yy[dt]);E.setInput(n,Z.yy),Z.yy.lexer=E,Z.yy.parser=this,typeof E.yylloc>"u"&&(E.yylloc={});var ut=E.yylloc;a.push(ut);var Ft=E.options&&E.options.ranges;typeof Z.yy.parseError=="function"?this.parseError=Z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Pt(){var j;return j=o.pop()||E.lex()||Tt,typeof j!="number"&&(j instanceof Array&&(o=j,j=o.pop()),j=r.symbols_[j]||j),j}for(var W,J,H,xt,tt={},rt,$,_t,lt;;){if(J=l[l.length-1],this.defaultActions[J]?H=this.defaultActions[J]:((W===null||typeof W>"u")&&(W=Pt()),H=et[J]&&et[J][W]),typeof H>"u"||!H.length||!H[0]){var ft="";lt=[];for(rt in et[J])this.terminals_[rt]&&rt>St&<.push("'"+this.terminals_[rt]+"'");E.showPosition?ft="Parse error on line "+(st+1)+`:
                                         `+E.showPosition()+`
                                         Expecting `+lt.join(", ")+", got '"+(this.terminals_[W]||W)+"'":ft="Parse error on line "+(st+1)+": Unexpected "+(W==Tt?"end of input":"'"+(this.terminals_[W]||W)+"'"),this.parseError(ft,{text:E.match,token:this.terminals_[W]||W,line:E.yylineno,loc:ut,expected:lt})}if(H[0]instanceof Array&&H.length>1)throw new Error("Parse Error: multiple actions possible at state: "+J+", token: "+W);switch(H[0]){case 1:l.push(W),q.push(E.yytext),a.push(E.yylloc),l.push(H[1]),W=null,qt=E.yyleng,u=E.yytext,st=E.yylineno,ut=E.yylloc;break;case 2:if($=this.productions_[H[1]][1],tt.$=q[q.length-$],tt._$={first_line:a[a.length-($||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-($||1)].first_column,last_column:a[a.length-1].last_column},Ft&&(tt._$.range=[a[a.length-($||1)].range[0],a[a.length-1].range[1]]),xt=this.performAction.apply(tt,[u,qt,st,Z.yy,H[1],q,a].concat(kt)),typeof xt<"u")return xt;$&&(l=l.slice(0,-1*$*2),q=q.slice(0,-1*$),a=a.slice(0,-1*$)),l.push(this.productions_[H[1]][0]),q.push(tt.$),a.push(tt._$),_t=et[l[l.length-2]][l[l.length-1]],l.push(_t);break;case 3:return!0}}return!0}},At=function(){var K={EOF:1,parseError:function(r,l){if(this.yy.parser)this.yy.parser.parseError(r,l);else throw new Error(r)},setInput:function(n,r){return this.yy=r||this.yy||{},this._input=n,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var n=this._input[0];this.yytext+=n,this.yyleng++,this.offset++,this.match+=n,this.matched+=n;var r=n.match(/(?:\r\n?|\n).*/g);return r?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),n},unput:function(n){var r=n.length,l=n.split(/(?:\r\n?|\n)/g);this._input=n+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-r),this.offset-=r;var o=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),l.length-1&&(this.yylineno-=l.length-1);var q=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:l?(l.length===o.length?this.yylloc.first_column:0)+o[o.length-l.length].length-l[0].length:this.yylloc.first_column-r},this.options.ranges&&(this.yylloc.range=[q[0],q[0]+this.yyleng-r]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(n){this.unput(this.match.slice(n))},pastInput:function(){var n=this.matched.substr(0,this.matched.length-this.match.length);return(n.length>20?"...":"")+n.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var n=this.match;return n.length<20&&(n+=this._input.substr(0,20-n.length)),(n.substr(0,20)+(n.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var n=this.pastInput(),r=new Array(n.length+1).join("-");return n+this.upcomingInput()+`
                                        diff --git a/assets/quic.html-DpxBi39d.js b/assets/quic.html-BSX-VjGs.js
                                        similarity index 97%
                                        rename from assets/quic.html-DpxBi39d.js
                                        rename to assets/quic.html-BSX-VjGs.js
                                        index ae1b8a4c59..7d7006de53 100644
                                        --- a/assets/quic.html-DpxBi39d.js
                                        +++ b/assets/quic.html-BSX-VjGs.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as o,o as s,c as a,a as t,e as c}from"./app-5SoadDYS.js";const i={},p=c(`

                                        QUIC

                                        QUIC 全称 Quick UDP Internet Connection,是由 Google 提出的使用 UDP 进行多路并发传输的协议。其主要优势是:

                                        1. 减少了握手的延迟(1-RTT 或 0-RTT)
                                        2. 多路复用,并且没有 TCP 的阻塞问题
                                        3. 连接迁移,(主要是在客户端)当由 Wifi 转移到 4G 时,连接不会被断开。

                                        QUIC 目前处于实验期,使用了正在标准化过程中的 IETF 实现,不能保证与最终版本的兼容性。

                                        • 默认设定:
                                          • 12 字节的 Connection ID
                                          • 30 秒没有数据通过时自动断开连接 (可能会影响一些长连接的使用)

                                        QuicObject

                                        QuicObject 对应传输配置的 quicSettings 项。

                                        警告

                                        对接的两端的配置必须完全一致,否则连接失败。 QUIC 强制要求开启 TLS,在传输配置中没有开启 TLS 时,Xray 会自行签发一个证书进行 TLS 通讯。

                                        {
                                        +import{_ as n,r as o,o as s,c as a,a as t,e as c}from"./app-Bw2NG-QJ.js";const i={},p=c(`

                                        QUIC

                                        QUIC 全称 Quick UDP Internet Connection,是由 Google 提出的使用 UDP 进行多路并发传输的协议。其主要优势是:

                                        1. 减少了握手的延迟(1-RTT 或 0-RTT)
                                        2. 多路复用,并且没有 TCP 的阻塞问题
                                        3. 连接迁移,(主要是在客户端)当由 Wifi 转移到 4G 时,连接不会被断开。

                                        QUIC 目前处于实验期,使用了正在标准化过程中的 IETF 实现,不能保证与最终版本的兼容性。

                                        • 默认设定:
                                          • 12 字节的 Connection ID
                                          • 30 秒没有数据通过时自动断开连接 (可能会影响一些长连接的使用)

                                        QuicObject

                                        QuicObject 对应传输配置的 quicSettings 项。

                                        警告

                                        对接的两端的配置必须完全一致,否则连接失败。 QUIC 强制要求开启 TLS,在传输配置中没有开启 TLS 时,Xray 会自行签发一个证书进行 TLS 通讯。

                                        {
                                           "security": "none",
                                           "key": "",
                                           "header": {
                                        diff --git a/assets/quic.html-CXwWfMPP.js b/assets/quic.html-C3baIL5C.js
                                        similarity index 98%
                                        rename from assets/quic.html-CXwWfMPP.js
                                        rename to assets/quic.html-C3baIL5C.js
                                        index ae2579bf4d..1e113a76b1 100644
                                        --- a/assets/quic.html-CXwWfMPP.js
                                        +++ b/assets/quic.html-C3baIL5C.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as n,r as o,o as s,c as a,a as t,e as c}from"./app-5SoadDYS.js";const i={},p=c(`

                                        QUIC

                                        QUIC (Quick UDP Internet Connection) — это протокол, предложенный Google для многоканальной передачи данных по UDP. Его основные преимущества:

                                        1. Сокращение времени установки соединения (1-RTT или 0-RTT).
                                        2. Многоканальность и отсутствие проблем с блокировкой, как у TCP.
                                        3. Миграция соединений (в основном на стороне клиента): при переходе с Wi-Fi на 4G соединение не разрывается.

                                        QUIC в настоящее время находится в экспериментальной стадии и использует реализацию IETF, которая находится в процессе стандартизации, поэтому совместимость с финальной версией не гарантируется.

                                        • По умолчанию:
                                          • 12-байтовый Connection ID.
                                          • Автоматическое отключение соединения через 30 секунд бездействия (может повлиять на работу некоторых долгоживущих соединений).

                                        QuicObject

                                        QuicObject соответствует элементу quicSettings в конфигурации транспорта.

                                        Предупреждение

                                        Конфигурация на обоих концах соединения должна быть полностью идентичной, иначе соединение установить не удастся. QUIC требует включения TLS. Если TLS не включён в настройках транспорта, Xray сгенерирует самоподписанный сертификат для использования TLS.

                                        {
                                        +import{_ as n,r as o,o as s,c as a,a as t,e as c}from"./app-Bw2NG-QJ.js";const i={},p=c(`

                                        QUIC

                                        QUIC (Quick UDP Internet Connection) — это протокол, предложенный Google для многоканальной передачи данных по UDP. Его основные преимущества:

                                        1. Сокращение времени установки соединения (1-RTT или 0-RTT).
                                        2. Многоканальность и отсутствие проблем с блокировкой, как у TCP.
                                        3. Миграция соединений (в основном на стороне клиента): при переходе с Wi-Fi на 4G соединение не разрывается.

                                        QUIC в настоящее время находится в экспериментальной стадии и использует реализацию IETF, которая находится в процессе стандартизации, поэтому совместимость с финальной версией не гарантируется.

                                        • По умолчанию:
                                          • 12-байтовый Connection ID.
                                          • Автоматическое отключение соединения через 30 секунд бездействия (может повлиять на работу некоторых долгоживущих соединений).

                                        QuicObject

                                        QuicObject соответствует элементу quicSettings в конфигурации транспорта.

                                        Предупреждение

                                        Конфигурация на обоих концах соединения должна быть полностью идентичной, иначе соединение установить не удастся. QUIC требует включения TLS. Если TLS не включён в настройках транспорта, Xray сгенерирует самоподписанный сертификат для использования TLS.

                                        {
                                           "security": "none",
                                           "key": "",
                                           "header": {
                                        diff --git a/assets/quic.html-But08Sia.js b/assets/quic.html-C8pXs3js.js
                                        similarity index 98%
                                        rename from assets/quic.html-But08Sia.js
                                        rename to assets/quic.html-C8pXs3js.js
                                        index 7f8b276372..65a381e9bd 100644
                                        --- a/assets/quic.html-But08Sia.js
                                        +++ b/assets/quic.html-C8pXs3js.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as o,o as r,c as u,a as t,b as e,d as n,w as i,e as d}from"./app-5SoadDYS.js";const p={},h=e("h1",{id:"quic",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#quic"},[e("span",null,"QUIC")])],-1),b=e("p",null,"QUIC (Quick UDP Internet Connection) is a protocol proposed by Google for multiplexed and concurrent transmission using UDP. Its main advantages are:",-1),f=e("li",null,"Reduced number of roundtrips in handshake phase. (1-RTT or 0-RTT)",-1),m={href:"https://calendar.perfplanet.com/2020/head-of-line-blocking-in-quic-and-http-3-the-details/",target:"_blank",rel:"noopener noreferrer"},q=e("li",null,"Connection migration, (mainly on the client side) when switching from Wifi to 4G, the connection will not be interrupted.",-1),_=e("p",null,"QUIC is currently in the experimental phase and uses IETF implementation that is still being standardized, so compatibility with the final version cannot be guaranteed.",-1),k=e("li",null,"12-byte Connection ID",-1),v={href:"https://en.wikipedia.org/wiki/HTTP_persistent_connection",target:"_blank",rel:"noopener noreferrer"},g=e("h2",{id:"quicobject",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#quicobject"},[e("span",null,"QuicObject")])],-1),y=e("code",null,"QuicObject",-1),T=e("code",null,"quicSettings",-1),I={class:"custom-container danger"},w=e("p",{class:"custom-container-title"},"Danger",-1),j=e("p",null,"The configurations of both endpoints must be identical, otherwise the connection will fail.",-1),x=d(`
                                        {
                                        +import{_ as l,r as o,o as r,c as u,a as t,b as e,d as n,w as i,e as d}from"./app-Bw2NG-QJ.js";const p={},h=e("h1",{id:"quic",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#quic"},[e("span",null,"QUIC")])],-1),b=e("p",null,"QUIC (Quick UDP Internet Connection) is a protocol proposed by Google for multiplexed and concurrent transmission using UDP. Its main advantages are:",-1),f=e("li",null,"Reduced number of roundtrips in handshake phase. (1-RTT or 0-RTT)",-1),m={href:"https://calendar.perfplanet.com/2020/head-of-line-blocking-in-quic-and-http-3-the-details/",target:"_blank",rel:"noopener noreferrer"},q=e("li",null,"Connection migration, (mainly on the client side) when switching from Wifi to 4G, the connection will not be interrupted.",-1),_=e("p",null,"QUIC is currently in the experimental phase and uses IETF implementation that is still being standardized, so compatibility with the final version cannot be guaranteed.",-1),k=e("li",null,"12-byte Connection ID",-1),v={href:"https://en.wikipedia.org/wiki/HTTP_persistent_connection",target:"_blank",rel:"noopener noreferrer"},g=e("h2",{id:"quicobject",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#quicobject"},[e("span",null,"QuicObject")])],-1),y=e("code",null,"QuicObject",-1),T=e("code",null,"quicSettings",-1),I={class:"custom-container danger"},w=e("p",{class:"custom-container-title"},"Danger",-1),j=e("p",null,"The configurations of both endpoints must be identical, otherwise the connection will fail.",-1),x=d(`
                                        {
                                           "security": "none",
                                           "key": "",
                                           "header": {
                                        diff --git a/assets/redirect.html-Mplb4Dtz.js b/assets/redirect.html-DdM9qz1d.js
                                        similarity index 99%
                                        rename from assets/redirect.html-Mplb4Dtz.js
                                        rename to assets/redirect.html-DdM9qz1d.js
                                        index 64e5fa72e4..73465c4f5d 100644
                                        --- a/assets/redirect.html-Mplb4Dtz.js
                                        +++ b/assets/redirect.html-DdM9qz1d.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as l,o as r,c as u,a,w as e,b as n,e as o,d as s}from"./app-5SoadDYS.js";const k={},d=n("h1",{id:"基于-fwmark-或-sendthrough-的流量重定向",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#基于-fwmark-或-sendthrough-的流量重定向"},[n("span",null,"基于 fwmark 或 sendThrough 的流量重定向")])],-1),v=o('

                                        通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”

                                        前言

                                        之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR 路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有!

                                        通过 fwmark 或 Xray 的 sendThrough,再简单配合路由表功能即可实现:

                                        1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6
                                        2. 其余用户则走原 IPV4 或者 IPV6

                                        具体设置如下(以 Debian10 为例):

                                        1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)

                                        根据不同系统和不同软件,请参考官方安装方法

                                        2、编辑 VPN 配置文件(以 WireGuard 为例)

                                        原始文件:

                                        ',10),m=n("div",{class:"language-ini line-numbers-mode","data-ext":"ini","data-title":"ini"},[n("pre",{class:"language-ini"},[n("code",null,[n("span",{class:"token section"},[n("span",{class:"token punctuation"},"["),n("span",{class:"token section-name selector"},"Interface"),n("span",{class:"token punctuation"},"]")]),s(` +import{_ as i,r as l,o as r,c as u,a,w as e,b as n,e as o,d as s}from"./app-Bw2NG-QJ.js";const k={},d=n("h1",{id:"基于-fwmark-或-sendthrough-的流量重定向",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#基于-fwmark-或-sendthrough-的流量重定向"},[n("span",null,"基于 fwmark 或 sendThrough 的流量重定向")])],-1),v=o('

                                        通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”

                                        前言

                                        之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR 路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有!

                                        通过 fwmark 或 Xray 的 sendThrough,再简单配合路由表功能即可实现:

                                        1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6
                                        2. 其余用户则走原 IPV4 或者 IPV6

                                        具体设置如下(以 Debian10 为例):

                                        1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)

                                        根据不同系统和不同软件,请参考官方安装方法

                                        2、编辑 VPN 配置文件(以 WireGuard 为例)

                                        原始文件:

                                        ',10),m=n("div",{class:"language-ini line-numbers-mode","data-ext":"ini","data-title":"ini"},[n("pre",{class:"language-ini"},[n("code",null,[n("span",{class:"token section"},[n("span",{class:"token punctuation"},"["),n("span",{class:"token section-name selector"},"Interface"),n("span",{class:"token punctuation"},"]")]),s(` `),n("span",{class:"token key attr-name"},"PrivateKey"),s(),n("span",{class:"token punctuation"},"="),s(),n("span",{class:"token value attr-value"},"xxxxxxxxxxxxxxxxxxxx"),s(` `),n("span",{class:"token key attr-name"},"Address"),s(),n("span",{class:"token punctuation"},"="),s(),n("span",{class:"token value attr-value"},[s('"'),n("span",{class:"token inner-value"},"your wg0 v4 address"),s('"')]),s(` `),n("span",{class:"token key attr-name"},"Address"),s(),n("span",{class:"token punctuation"},"="),s(),n("span",{class:"token value attr-value"},[s('"'),n("span",{class:"token inner-value"},"your wg0 v6 address"),s('"')]),s(` diff --git a/assets/redirect.html-BDtVJCJP.js b/assets/redirect.html-ZgxF37Mu.js similarity index 99% rename from assets/redirect.html-BDtVJCJP.js rename to assets/redirect.html-ZgxF37Mu.js index f936e74151..05319b11b5 100644 --- a/assets/redirect.html-BDtVJCJP.js +++ b/assets/redirect.html-ZgxF37Mu.js @@ -1,4 +1,4 @@ -import{_ as o,r as e,o as l,c as i,a,b as s,d as n,e as c}from"./app-5SoadDYS.js";const u={},r=s("h1",{id:"基于-fwmark-或-sendthrough-的流量重定向",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#基于-fwmark-或-sendthrough-的流量重定向"},[s("span",null,"基于 fwmark 或 sendThrough 的流量重定向")])],-1),d=c(`

                                        通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”

                                        前言

                                        之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR 路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有!

                                        通过 fwmark 或 Xray 的 sendThrough/sockopt.interface,再简单配合路由表功能即可实现:

                                        1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6
                                        2. 其余用户则走原 IPV4 或者 IPV6

                                        具体设置如下(以 Debian10 为例):

                                        1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)

                                        根据不同系统和不同软件,请参考官方安装方法

                                        2、编辑 VPN 配置文件(以 WireGuard 为例)

                                        原始文件:

                                        [Interface]
                                        +import{_ as o,r as e,o as l,c as i,a,b as s,d as n,e as c}from"./app-Bw2NG-QJ.js";const u={},r=s("h1",{id:"基于-fwmark-或-sendthrough-的流量重定向",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#基于-fwmark-或-sendthrough-的流量重定向"},[s("span",null,"基于 fwmark 或 sendThrough 的流量重定向")])],-1),d=c(`

                                        通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”

                                        前言

                                        之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR 路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有!

                                        通过 fwmark 或 Xray 的 sendThrough/sockopt.interface,再简单配合路由表功能即可实现:

                                        1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6
                                        2. 其余用户则走原 IPV4 或者 IPV6

                                        具体设置如下(以 Debian10 为例):

                                        1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)

                                        根据不同系统和不同软件,请参考官方安装方法

                                        2、编辑 VPN 配置文件(以 WireGuard 为例)

                                        原始文件:

                                        [Interface]
                                         PrivateKey = <PriKey>
                                         Address = <IPv4>
                                         Address = <IPv6>
                                        diff --git a/assets/redirect.html-CcdbISF0.js b/assets/redirect.html-u-FkUyZi.js
                                        similarity index 99%
                                        rename from assets/redirect.html-CcdbISF0.js
                                        rename to assets/redirect.html-u-FkUyZi.js
                                        index d503b46b7c..90454a74f5 100644
                                        --- a/assets/redirect.html-CcdbISF0.js
                                        +++ b/assets/redirect.html-u-FkUyZi.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as o,r as e,o as l,c as i,a,b as s,d as n,e as c}from"./app-5SoadDYS.js";const u={},r=s("h1",{id:"перенаправление-трафика-на-основе-fwmark-или-sendthrough",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#перенаправление-трафика-на-основе-fwmark-или-sendthrough"},[s("span",null,"Перенаправление трафика на основе fwmark или sendThrough")])],-1),d=c(`

                                        Направление определенного трафика через определенный выходной узел с помощью Xray для реализации "разделения" глобальной маршрутизации

                                        Введение

                                        Я видел много прокси-серверов или VPN, которые перехватывают весь трафик, что приводит к неработоспособности Xray, если он установлен одновременно с ними. Многие руководства, которые я находил, предлагали решать эту проблему путем разделения трафика на основе таблиц маршрутизации CIDR. Это не очень элегантно, и если я хочу иметь возможность гибко переключаться между маршрутами и реализовывать разделение трафика по требованию, то есть ли лучший способ? Да, есть!

                                        С помощью fwmark или sendThrough/sockopt.interface в Xray и простой настройки таблицы маршрутизации можно добиться следующего:

                                        1. Xray может направлять трафик с определенным тегом, доменным именем и т.д. через определенный интерфейс. Если ваш интерфейс поддерживает dual-stack, вы можете указать IPv4 или IPv6.
                                        2. Остальной трафик будет идти через исходный интерфейс IPv4 или IPv6.

                                        Вот как это настроить (на примере Debian 10):

                                        1. Установите прокси-сервер или VPN-клиент (например, Wireguard, IPsec и т.д.)

                                        Обратитесь к официальной документации для получения инструкций по установке для вашей системы и программного обеспечения.

                                        2. Отредактируйте конфигурационный файл VPN (на примере WireGuard)

                                        Исходный файл:

                                        [Interface]
                                        +import{_ as o,r as e,o as l,c as i,a,b as s,d as n,e as c}from"./app-Bw2NG-QJ.js";const u={},r=s("h1",{id:"перенаправление-трафика-на-основе-fwmark-или-sendthrough",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#перенаправление-трафика-на-основе-fwmark-или-sendthrough"},[s("span",null,"Перенаправление трафика на основе fwmark или sendThrough")])],-1),d=c(`

                                        Направление определенного трафика через определенный выходной узел с помощью Xray для реализации "разделения" глобальной маршрутизации

                                        Введение

                                        Я видел много прокси-серверов или VPN, которые перехватывают весь трафик, что приводит к неработоспособности Xray, если он установлен одновременно с ними. Многие руководства, которые я находил, предлагали решать эту проблему путем разделения трафика на основе таблиц маршрутизации CIDR. Это не очень элегантно, и если я хочу иметь возможность гибко переключаться между маршрутами и реализовывать разделение трафика по требованию, то есть ли лучший способ? Да, есть!

                                        С помощью fwmark или sendThrough/sockopt.interface в Xray и простой настройки таблицы маршрутизации можно добиться следующего:

                                        1. Xray может направлять трафик с определенным тегом, доменным именем и т.д. через определенный интерфейс. Если ваш интерфейс поддерживает dual-stack, вы можете указать IPv4 или IPv6.
                                        2. Остальной трафик будет идти через исходный интерфейс IPv4 или IPv6.

                                        Вот как это настроить (на примере Debian 10):

                                        1. Установите прокси-сервер или VPN-клиент (например, Wireguard, IPsec и т.д.)

                                        Обратитесь к официальной документации для получения инструкций по установке для вашей системы и программного обеспечения.

                                        2. Отредактируйте конфигурационный файл VPN (на примере WireGuard)

                                        Исходный файл:

                                        [Interface]
                                         PrivateKey = <PriKey>
                                         Address = <IPv4>
                                         Address = <IPv6>
                                        diff --git a/assets/requirementDiagram-87253d64-K4iL_vop.js b/assets/requirementDiagram-87253d64-CetQ2-l9.js
                                        similarity index 98%
                                        rename from assets/requirementDiagram-87253d64-K4iL_vop.js
                                        rename to assets/requirementDiagram-87253d64-CetQ2-l9.js
                                        index f625172e07..9c291498bf 100644
                                        --- a/assets/requirementDiagram-87253d64-K4iL_vop.js
                                        +++ b/assets/requirementDiagram-87253d64-CetQ2-l9.js
                                        @@ -1,4 +1,4 @@
                                        -import{c as Te,s as Ce,g as Fe,b as Me,a as De,l as Ne,A as Pe,h as oe,i as Ye,j as ke}from"./mermaid.core-CArNAncI.js";import{G as Ue}from"./graph-D2qW7eTj.js";import{l as Be}from"./layout-BlaWeSu5.js";import{l as Qe}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";var ce=function(){var e=function(V,i,n,a){for(n=n||{},a=V.length;a--;n[V[a]]=i);return n},t=[1,3],l=[1,4],c=[1,5],u=[1,6],d=[5,6,8,9,11,13,31,32,33,34,35,36,44,62,63],p=[1,18],h=[2,7],o=[1,22],g=[1,23],R=[1,24],A=[1,25],T=[1,26],N=[1,27],v=[1,20],k=[1,28],x=[1,29],F=[62,63],de=[5,8,9,11,13,31,32,33,34,35,36,44,51,53,62,63],pe=[1,47],fe=[1,48],ye=[1,49],_e=[1,50],ge=[1,51],Ee=[1,52],Re=[1,53],O=[53,54],M=[1,64],D=[1,60],P=[1,61],Y=[1,62],U=[1,63],B=[1,65],j=[1,69],z=[1,70],X=[1,67],J=[1,68],m=[5,8,9,11,13,31,32,33,34,35,36,44,62,63],ie={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,acc_title:9,acc_title_value:10,acc_descr:11,acc_descr_value:12,acc_descr_multiline_value:13,requirementDef:14,elementDef:15,relationshipDef:16,requirementType:17,requirementName:18,STRUCT_START:19,requirementBody:20,ID:21,COLONSEP:22,id:23,TEXT:24,text:25,RISK:26,riskLevel:27,VERIFYMTHD:28,verifyType:29,STRUCT_STOP:30,REQUIREMENT:31,FUNCTIONAL_REQUIREMENT:32,INTERFACE_REQUIREMENT:33,PERFORMANCE_REQUIREMENT:34,PHYSICAL_REQUIREMENT:35,DESIGN_CONSTRAINT:36,LOW_RISK:37,MED_RISK:38,HIGH_RISK:39,VERIFY_ANALYSIS:40,VERIFY_DEMONSTRATION:41,VERIFY_INSPECTION:42,VERIFY_TEST:43,ELEMENT:44,elementName:45,elementBody:46,TYPE:47,type:48,DOCREF:49,ref:50,END_ARROW_L:51,relationship:52,LINE:53,END_ARROW_R:54,CONTAINS:55,COPIES:56,DERIVES:57,SATISFIES:58,VERIFIES:59,REFINES:60,TRACES:61,unqString:62,qString:63,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",9:"acc_title",10:"acc_title_value",11:"acc_descr",12:"acc_descr_value",13:"acc_descr_multiline_value",19:"STRUCT_START",21:"ID",22:"COLONSEP",24:"TEXT",26:"RISK",28:"VERIFYMTHD",30:"STRUCT_STOP",31:"REQUIREMENT",32:"FUNCTIONAL_REQUIREMENT",33:"INTERFACE_REQUIREMENT",34:"PERFORMANCE_REQUIREMENT",35:"PHYSICAL_REQUIREMENT",36:"DESIGN_CONSTRAINT",37:"LOW_RISK",38:"MED_RISK",39:"HIGH_RISK",40:"VERIFY_ANALYSIS",41:"VERIFY_DEMONSTRATION",42:"VERIFY_INSPECTION",43:"VERIFY_TEST",44:"ELEMENT",47:"TYPE",49:"DOCREF",51:"END_ARROW_L",53:"LINE",54:"END_ARROW_R",55:"CONTAINS",56:"COPIES",57:"DERIVES",58:"SATISFIES",59:"VERIFIES",60:"REFINES",61:"TRACES",62:"unqString",63:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,2],[4,2],[4,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[14,5],[20,5],[20,5],[20,5],[20,5],[20,2],[20,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[27,1],[27,1],[27,1],[29,1],[29,1],[29,1],[29,1],[15,5],[46,5],[46,5],[46,2],[46,1],[16,5],[16,5],[52,1],[52,1],[52,1],[52,1],[52,1],[52,1],[52,1],[18,1],[18,1],[23,1],[23,1],[25,1],[25,1],[45,1],[45,1],[48,1],[48,1],[50,1],[50,1]],performAction:function(i,n,a,r,f,s,W){var _=s.length-1;switch(f){case 4:this.$=s[_].trim(),r.setAccTitle(this.$);break;case 5:case 6:this.$=s[_].trim(),r.setAccDescription(this.$);break;case 7:this.$=[];break;case 13:r.addRequirement(s[_-3],s[_-4]);break;case 14:r.setNewReqId(s[_-2]);break;case 15:r.setNewReqText(s[_-2]);break;case 16:r.setNewReqRisk(s[_-2]);break;case 17:r.setNewReqVerifyMethod(s[_-2]);break;case 20:this.$=r.RequirementType.REQUIREMENT;break;case 21:this.$=r.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 22:this.$=r.RequirementType.INTERFACE_REQUIREMENT;break;case 23:this.$=r.RequirementType.PERFORMANCE_REQUIREMENT;break;case 24:this.$=r.RequirementType.PHYSICAL_REQUIREMENT;break;case 25:this.$=r.RequirementType.DESIGN_CONSTRAINT;break;case 26:this.$=r.RiskLevel.LOW_RISK;break;case 27:this.$=r.RiskLevel.MED_RISK;break;case 28:this.$=r.RiskLevel.HIGH_RISK;break;case 29:this.$=r.VerifyType.VERIFY_ANALYSIS;break;case 30:this.$=r.VerifyType.VERIFY_DEMONSTRATION;break;case 31:this.$=r.VerifyType.VERIFY_INSPECTION;break;case 32:this.$=r.VerifyType.VERIFY_TEST;break;case 33:r.addElement(s[_-3]);break;case 34:r.setNewElementType(s[_-2]);break;case 35:r.setNewElementDocRef(s[_-2]);break;case 38:r.addRelationship(s[_-2],s[_],s[_-4]);break;case 39:r.addRelationship(s[_-2],s[_-4],s[_]);break;case 40:this.$=r.Relationships.CONTAINS;break;case 41:this.$=r.Relationships.COPIES;break;case 42:this.$=r.Relationships.DERIVES;break;case 43:this.$=r.Relationships.SATISFIES;break;case 44:this.$=r.Relationships.VERIFIES;break;case 45:this.$=r.Relationships.REFINES;break;case 46:this.$=r.Relationships.TRACES;break}},table:[{3:1,4:2,6:t,9:l,11:c,13:u},{1:[3]},{3:8,4:2,5:[1,7],6:t,9:l,11:c,13:u},{5:[1,9]},{10:[1,10]},{12:[1,11]},e(d,[2,6]),{3:12,4:2,6:t,9:l,11:c,13:u},{1:[2,2]},{4:17,5:p,7:13,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},e(d,[2,4]),e(d,[2,5]),{1:[2,1]},{8:[1,30]},{4:17,5:p,7:31,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:32,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:33,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:34,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:35,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{18:36,62:[1,37],63:[1,38]},{45:39,62:[1,40],63:[1,41]},{51:[1,42],53:[1,43]},e(F,[2,20]),e(F,[2,21]),e(F,[2,22]),e(F,[2,23]),e(F,[2,24]),e(F,[2,25]),e(de,[2,49]),e(de,[2,50]),{1:[2,3]},{8:[2,8]},{8:[2,9]},{8:[2,10]},{8:[2,11]},{8:[2,12]},{19:[1,44]},{19:[2,47]},{19:[2,48]},{19:[1,45]},{19:[2,53]},{19:[2,54]},{52:46,55:pe,56:fe,57:ye,58:_e,59:ge,60:Ee,61:Re},{52:54,55:pe,56:fe,57:ye,58:_e,59:ge,60:Ee,61:Re},{5:[1,55]},{5:[1,56]},{53:[1,57]},e(O,[2,40]),e(O,[2,41]),e(O,[2,42]),e(O,[2,43]),e(O,[2,44]),e(O,[2,45]),e(O,[2,46]),{54:[1,58]},{5:M,20:59,21:D,24:P,26:Y,28:U,30:B},{5:j,30:z,46:66,47:X,49:J},{23:71,62:k,63:x},{23:72,62:k,63:x},e(m,[2,13]),{22:[1,73]},{22:[1,74]},{22:[1,75]},{22:[1,76]},{5:M,20:77,21:D,24:P,26:Y,28:U,30:B},e(m,[2,19]),e(m,[2,33]),{22:[1,78]},{22:[1,79]},{5:j,30:z,46:80,47:X,49:J},e(m,[2,37]),e(m,[2,38]),e(m,[2,39]),{23:81,62:k,63:x},{25:82,62:[1,83],63:[1,84]},{27:85,37:[1,86],38:[1,87],39:[1,88]},{29:89,40:[1,90],41:[1,91],42:[1,92],43:[1,93]},e(m,[2,18]),{48:94,62:[1,95],63:[1,96]},{50:97,62:[1,98],63:[1,99]},e(m,[2,36]),{5:[1,100]},{5:[1,101]},{5:[2,51]},{5:[2,52]},{5:[1,102]},{5:[2,26]},{5:[2,27]},{5:[2,28]},{5:[1,103]},{5:[2,29]},{5:[2,30]},{5:[2,31]},{5:[2,32]},{5:[1,104]},{5:[2,55]},{5:[2,56]},{5:[1,105]},{5:[2,57]},{5:[2,58]},{5:M,20:106,21:D,24:P,26:Y,28:U,30:B},{5:M,20:107,21:D,24:P,26:Y,28:U,30:B},{5:M,20:108,21:D,24:P,26:Y,28:U,30:B},{5:M,20:109,21:D,24:P,26:Y,28:U,30:B},{5:j,30:z,46:110,47:X,49:J},{5:j,30:z,46:111,47:X,49:J},e(m,[2,14]),e(m,[2,15]),e(m,[2,16]),e(m,[2,17]),e(m,[2,34]),e(m,[2,35])],defaultActions:{8:[2,2],12:[2,1],30:[2,3],31:[2,8],32:[2,9],33:[2,10],34:[2,11],35:[2,12],37:[2,47],38:[2,48],40:[2,53],41:[2,54],83:[2,51],84:[2,52],86:[2,26],87:[2,27],88:[2,28],90:[2,29],91:[2,30],92:[2,31],93:[2,32],95:[2,55],96:[2,56],98:[2,57],99:[2,58]},parseError:function(i,n){if(n.recoverable)this.trace(i);else{var a=new Error(i);throw a.hash=n,a}},parse:function(i){var n=this,a=[0],r=[],f=[null],s=[],W=this.table,_="",Z=0,me=0,Ve=2,Ie=1,qe=s.slice.call(arguments,1),E=Object.create(this.lexer),L={yy:{}};for(var ne in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ne)&&(L.yy[ne]=this.yy[ne]);E.setInput(i,L.yy),L.yy.lexer=E,L.yy.parser=this,typeof E.yylloc>"u"&&(E.yylloc={});var se=E.yylloc;s.push(se);var Oe=E.options&&E.options.ranges;typeof L.yy.parseError=="function"?this.parseError=L.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Le(){var $;return $=r.pop()||E.lex()||Ie,typeof $!="number"&&($ instanceof Array&&(r=$,$=r.pop()),$=n.symbols_[$]||$),$}for(var I,C,S,ae,Q={},ee,w,be,te;;){if(C=a[a.length-1],this.defaultActions[C]?S=this.defaultActions[C]:((I===null||typeof I>"u")&&(I=Le()),S=W[C]&&W[C][I]),typeof S>"u"||!S.length||!S[0]){var le="";te=[];for(ee in W[C])this.terminals_[ee]&&ee>Ve&&te.push("'"+this.terminals_[ee]+"'");E.showPosition?le="Parse error on line "+(Z+1)+`:
                                        +import{c as Te,s as Ce,g as Fe,b as Me,a as De,l as Ne,A as Pe,h as oe,i as Ye,j as ke}from"./mermaid.core-Bq0kX0MS.js";import{G as Ue}from"./graph-C-EgwjAv.js";import{l as Be}from"./layout-DSxgfneE.js";import{l as Qe}from"./line-DY_oMjHu.js";import"./app-Bw2NG-QJ.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";var ce=function(){var e=function(V,i,n,a){for(n=n||{},a=V.length;a--;n[V[a]]=i);return n},t=[1,3],l=[1,4],c=[1,5],u=[1,6],d=[5,6,8,9,11,13,31,32,33,34,35,36,44,62,63],p=[1,18],h=[2,7],o=[1,22],g=[1,23],R=[1,24],A=[1,25],T=[1,26],N=[1,27],v=[1,20],k=[1,28],x=[1,29],F=[62,63],de=[5,8,9,11,13,31,32,33,34,35,36,44,51,53,62,63],pe=[1,47],fe=[1,48],ye=[1,49],_e=[1,50],ge=[1,51],Ee=[1,52],Re=[1,53],O=[53,54],M=[1,64],D=[1,60],P=[1,61],Y=[1,62],U=[1,63],B=[1,65],j=[1,69],z=[1,70],X=[1,67],J=[1,68],m=[5,8,9,11,13,31,32,33,34,35,36,44,62,63],ie={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,acc_title:9,acc_title_value:10,acc_descr:11,acc_descr_value:12,acc_descr_multiline_value:13,requirementDef:14,elementDef:15,relationshipDef:16,requirementType:17,requirementName:18,STRUCT_START:19,requirementBody:20,ID:21,COLONSEP:22,id:23,TEXT:24,text:25,RISK:26,riskLevel:27,VERIFYMTHD:28,verifyType:29,STRUCT_STOP:30,REQUIREMENT:31,FUNCTIONAL_REQUIREMENT:32,INTERFACE_REQUIREMENT:33,PERFORMANCE_REQUIREMENT:34,PHYSICAL_REQUIREMENT:35,DESIGN_CONSTRAINT:36,LOW_RISK:37,MED_RISK:38,HIGH_RISK:39,VERIFY_ANALYSIS:40,VERIFY_DEMONSTRATION:41,VERIFY_INSPECTION:42,VERIFY_TEST:43,ELEMENT:44,elementName:45,elementBody:46,TYPE:47,type:48,DOCREF:49,ref:50,END_ARROW_L:51,relationship:52,LINE:53,END_ARROW_R:54,CONTAINS:55,COPIES:56,DERIVES:57,SATISFIES:58,VERIFIES:59,REFINES:60,TRACES:61,unqString:62,qString:63,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",9:"acc_title",10:"acc_title_value",11:"acc_descr",12:"acc_descr_value",13:"acc_descr_multiline_value",19:"STRUCT_START",21:"ID",22:"COLONSEP",24:"TEXT",26:"RISK",28:"VERIFYMTHD",30:"STRUCT_STOP",31:"REQUIREMENT",32:"FUNCTIONAL_REQUIREMENT",33:"INTERFACE_REQUIREMENT",34:"PERFORMANCE_REQUIREMENT",35:"PHYSICAL_REQUIREMENT",36:"DESIGN_CONSTRAINT",37:"LOW_RISK",38:"MED_RISK",39:"HIGH_RISK",40:"VERIFY_ANALYSIS",41:"VERIFY_DEMONSTRATION",42:"VERIFY_INSPECTION",43:"VERIFY_TEST",44:"ELEMENT",47:"TYPE",49:"DOCREF",51:"END_ARROW_L",53:"LINE",54:"END_ARROW_R",55:"CONTAINS",56:"COPIES",57:"DERIVES",58:"SATISFIES",59:"VERIFIES",60:"REFINES",61:"TRACES",62:"unqString",63:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,2],[4,2],[4,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[14,5],[20,5],[20,5],[20,5],[20,5],[20,2],[20,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[27,1],[27,1],[27,1],[29,1],[29,1],[29,1],[29,1],[15,5],[46,5],[46,5],[46,2],[46,1],[16,5],[16,5],[52,1],[52,1],[52,1],[52,1],[52,1],[52,1],[52,1],[18,1],[18,1],[23,1],[23,1],[25,1],[25,1],[45,1],[45,1],[48,1],[48,1],[50,1],[50,1]],performAction:function(i,n,a,r,f,s,W){var _=s.length-1;switch(f){case 4:this.$=s[_].trim(),r.setAccTitle(this.$);break;case 5:case 6:this.$=s[_].trim(),r.setAccDescription(this.$);break;case 7:this.$=[];break;case 13:r.addRequirement(s[_-3],s[_-4]);break;case 14:r.setNewReqId(s[_-2]);break;case 15:r.setNewReqText(s[_-2]);break;case 16:r.setNewReqRisk(s[_-2]);break;case 17:r.setNewReqVerifyMethod(s[_-2]);break;case 20:this.$=r.RequirementType.REQUIREMENT;break;case 21:this.$=r.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 22:this.$=r.RequirementType.INTERFACE_REQUIREMENT;break;case 23:this.$=r.RequirementType.PERFORMANCE_REQUIREMENT;break;case 24:this.$=r.RequirementType.PHYSICAL_REQUIREMENT;break;case 25:this.$=r.RequirementType.DESIGN_CONSTRAINT;break;case 26:this.$=r.RiskLevel.LOW_RISK;break;case 27:this.$=r.RiskLevel.MED_RISK;break;case 28:this.$=r.RiskLevel.HIGH_RISK;break;case 29:this.$=r.VerifyType.VERIFY_ANALYSIS;break;case 30:this.$=r.VerifyType.VERIFY_DEMONSTRATION;break;case 31:this.$=r.VerifyType.VERIFY_INSPECTION;break;case 32:this.$=r.VerifyType.VERIFY_TEST;break;case 33:r.addElement(s[_-3]);break;case 34:r.setNewElementType(s[_-2]);break;case 35:r.setNewElementDocRef(s[_-2]);break;case 38:r.addRelationship(s[_-2],s[_],s[_-4]);break;case 39:r.addRelationship(s[_-2],s[_-4],s[_]);break;case 40:this.$=r.Relationships.CONTAINS;break;case 41:this.$=r.Relationships.COPIES;break;case 42:this.$=r.Relationships.DERIVES;break;case 43:this.$=r.Relationships.SATISFIES;break;case 44:this.$=r.Relationships.VERIFIES;break;case 45:this.$=r.Relationships.REFINES;break;case 46:this.$=r.Relationships.TRACES;break}},table:[{3:1,4:2,6:t,9:l,11:c,13:u},{1:[3]},{3:8,4:2,5:[1,7],6:t,9:l,11:c,13:u},{5:[1,9]},{10:[1,10]},{12:[1,11]},e(d,[2,6]),{3:12,4:2,6:t,9:l,11:c,13:u},{1:[2,2]},{4:17,5:p,7:13,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},e(d,[2,4]),e(d,[2,5]),{1:[2,1]},{8:[1,30]},{4:17,5:p,7:31,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:32,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:33,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:34,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{4:17,5:p,7:35,8:h,9:l,11:c,13:u,14:14,15:15,16:16,17:19,23:21,31:o,32:g,33:R,34:A,35:T,36:N,44:v,62:k,63:x},{18:36,62:[1,37],63:[1,38]},{45:39,62:[1,40],63:[1,41]},{51:[1,42],53:[1,43]},e(F,[2,20]),e(F,[2,21]),e(F,[2,22]),e(F,[2,23]),e(F,[2,24]),e(F,[2,25]),e(de,[2,49]),e(de,[2,50]),{1:[2,3]},{8:[2,8]},{8:[2,9]},{8:[2,10]},{8:[2,11]},{8:[2,12]},{19:[1,44]},{19:[2,47]},{19:[2,48]},{19:[1,45]},{19:[2,53]},{19:[2,54]},{52:46,55:pe,56:fe,57:ye,58:_e,59:ge,60:Ee,61:Re},{52:54,55:pe,56:fe,57:ye,58:_e,59:ge,60:Ee,61:Re},{5:[1,55]},{5:[1,56]},{53:[1,57]},e(O,[2,40]),e(O,[2,41]),e(O,[2,42]),e(O,[2,43]),e(O,[2,44]),e(O,[2,45]),e(O,[2,46]),{54:[1,58]},{5:M,20:59,21:D,24:P,26:Y,28:U,30:B},{5:j,30:z,46:66,47:X,49:J},{23:71,62:k,63:x},{23:72,62:k,63:x},e(m,[2,13]),{22:[1,73]},{22:[1,74]},{22:[1,75]},{22:[1,76]},{5:M,20:77,21:D,24:P,26:Y,28:U,30:B},e(m,[2,19]),e(m,[2,33]),{22:[1,78]},{22:[1,79]},{5:j,30:z,46:80,47:X,49:J},e(m,[2,37]),e(m,[2,38]),e(m,[2,39]),{23:81,62:k,63:x},{25:82,62:[1,83],63:[1,84]},{27:85,37:[1,86],38:[1,87],39:[1,88]},{29:89,40:[1,90],41:[1,91],42:[1,92],43:[1,93]},e(m,[2,18]),{48:94,62:[1,95],63:[1,96]},{50:97,62:[1,98],63:[1,99]},e(m,[2,36]),{5:[1,100]},{5:[1,101]},{5:[2,51]},{5:[2,52]},{5:[1,102]},{5:[2,26]},{5:[2,27]},{5:[2,28]},{5:[1,103]},{5:[2,29]},{5:[2,30]},{5:[2,31]},{5:[2,32]},{5:[1,104]},{5:[2,55]},{5:[2,56]},{5:[1,105]},{5:[2,57]},{5:[2,58]},{5:M,20:106,21:D,24:P,26:Y,28:U,30:B},{5:M,20:107,21:D,24:P,26:Y,28:U,30:B},{5:M,20:108,21:D,24:P,26:Y,28:U,30:B},{5:M,20:109,21:D,24:P,26:Y,28:U,30:B},{5:j,30:z,46:110,47:X,49:J},{5:j,30:z,46:111,47:X,49:J},e(m,[2,14]),e(m,[2,15]),e(m,[2,16]),e(m,[2,17]),e(m,[2,34]),e(m,[2,35])],defaultActions:{8:[2,2],12:[2,1],30:[2,3],31:[2,8],32:[2,9],33:[2,10],34:[2,11],35:[2,12],37:[2,47],38:[2,48],40:[2,53],41:[2,54],83:[2,51],84:[2,52],86:[2,26],87:[2,27],88:[2,28],90:[2,29],91:[2,30],92:[2,31],93:[2,32],95:[2,55],96:[2,56],98:[2,57],99:[2,58]},parseError:function(i,n){if(n.recoverable)this.trace(i);else{var a=new Error(i);throw a.hash=n,a}},parse:function(i){var n=this,a=[0],r=[],f=[null],s=[],W=this.table,_="",Z=0,me=0,Ve=2,Ie=1,qe=s.slice.call(arguments,1),E=Object.create(this.lexer),L={yy:{}};for(var ne in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ne)&&(L.yy[ne]=this.yy[ne]);E.setInput(i,L.yy),L.yy.lexer=E,L.yy.parser=this,typeof E.yylloc>"u"&&(E.yylloc={});var se=E.yylloc;s.push(se);var Oe=E.options&&E.options.ranges;typeof L.yy.parseError=="function"?this.parseError=L.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Le(){var $;return $=r.pop()||E.lex()||Ie,typeof $!="number"&&($ instanceof Array&&(r=$,$=r.pop()),$=n.symbols_[$]||$),$}for(var I,C,S,ae,Q={},ee,w,be,te;;){if(C=a[a.length-1],this.defaultActions[C]?S=this.defaultActions[C]:((I===null||typeof I>"u")&&(I=Le()),S=W[C]&&W[C][I]),typeof S>"u"||!S.length||!S[0]){var le="";te=[];for(ee in W[C])this.terminals_[ee]&&ee>Ve&&te.push("'"+this.terminals_[ee]+"'");E.showPosition?le="Parse error on line "+(Z+1)+`:
                                         `+E.showPosition()+`
                                         Expecting `+te.join(", ")+", got '"+(this.terminals_[I]||I)+"'":le="Parse error on line "+(Z+1)+": Unexpected "+(I==Ie?"end of input":"'"+(this.terminals_[I]||I)+"'"),this.parseError(le,{text:E.match,token:this.terminals_[I]||I,line:E.yylineno,loc:se,expected:te})}if(S[0]instanceof Array&&S.length>1)throw new Error("Parse Error: multiple actions possible at state: "+C+", token: "+I);switch(S[0]){case 1:a.push(I),f.push(E.yytext),s.push(E.yylloc),a.push(S[1]),I=null,me=E.yyleng,_=E.yytext,Z=E.yylineno,se=E.yylloc;break;case 2:if(w=this.productions_[S[1]][1],Q.$=f[f.length-w],Q._$={first_line:s[s.length-(w||1)].first_line,last_line:s[s.length-1].last_line,first_column:s[s.length-(w||1)].first_column,last_column:s[s.length-1].last_column},Oe&&(Q._$.range=[s[s.length-(w||1)].range[0],s[s.length-1].range[1]]),ae=this.performAction.apply(Q,[_,me,Z,L.yy,S[1],f,s].concat(qe)),typeof ae<"u")return ae;w&&(a=a.slice(0,-1*w*2),f=f.slice(0,-1*w),s=s.slice(0,-1*w)),a.push(this.productions_[S[1]][0]),f.push(Q.$),s.push(Q._$),be=W[a[a.length-2]][a[a.length-1]],a.push(be);break;case 3:return!0}}return!0}},$e=function(){var V={EOF:1,parseError:function(n,a){if(this.yy.parser)this.yy.parser.parseError(n,a);else throw new Error(n)},setInput:function(i,n){return this.yy=n||this.yy||{},this._input=i,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var i=this._input[0];this.yytext+=i,this.yyleng++,this.offset++,this.match+=i,this.matched+=i;var n=i.match(/(?:\r\n?|\n).*/g);return n?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),i},unput:function(i){var n=i.length,a=i.split(/(?:\r\n?|\n)/g);this._input=i+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-n),this.offset-=n;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),a.length-1&&(this.yylineno-=a.length-1);var f=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:a?(a.length===r.length?this.yylloc.first_column:0)+r[r.length-a.length].length-a[0].length:this.yylloc.first_column-n},this.options.ranges&&(this.yylloc.range=[f[0],f[0]+this.yyleng-n]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(i){this.unput(this.match.slice(i))},pastInput:function(){var i=this.matched.substr(0,this.matched.length-this.match.length);return(i.length>20?"...":"")+i.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var i=this.match;return i.length<20&&(i+=this._input.substr(0,20-i.length)),(i.substr(0,20)+(i.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var i=this.pastInput(),n=new Array(i.length+1).join("-");return i+this.upcomingInput()+`
                                        diff --git a/assets/reverse.html-DFbLOQPN.js b/assets/reverse.html-BNqd15YN.js
                                        similarity index 99%
                                        rename from assets/reverse.html-DFbLOQPN.js
                                        rename to assets/reverse.html-BNqd15YN.js
                                        index 785b20feee..2ef606ac78 100644
                                        --- a/assets/reverse.html-DFbLOQPN.js
                                        +++ b/assets/reverse.html-BNqd15YN.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as l,c as u,a,b as s,d as n,w as e,e as t}from"./app-5SoadDYS.js";const r={},d=t('

                                        Обратный прокси

                                        Обратный прокси позволяет перенаправлять трафик с сервера на клиент, то есть перенаправлять трафик в обратном направлении.

                                        Принцип работы обратного прокси:

                                        • Предположим, что на хосте A запущен веб-сервер, но у этого хоста нет публичного IP-адреса, и к нему нельзя получить доступ из Интернета.
                                          У нас есть другой хост B с публичным IP-адресом.
                                          Мы хотим использовать хост B в качестве шлюза и перенаправлять трафик с B на A.
                                        • На хосте A настроен Xray, называемый bridge, и на хосте B также настроен Xray, называемый portal.
                                        • bridge устанавливает соединение с portal.
                                          Целевой адрес этого соединения можно настроить произвольно.
                                          portal получает два типа соединений: соединения от bridge и соединения от пользователей из Интернета.
                                          portal автоматически объединяет эти два типа соединений.
                                          Таким образом, bridge может получать трафик из Интернета.
                                        • После получения трафика из Интернета bridge перенаправляет его на веб-сервер на хосте A без изменений.
                                          Конечно, для этого требуется настроить маршрутизацию.
                                        • bridge выполняет динамическую балансировку нагрузки в зависимости от объема трафика.
                                        ',4),v={class:"custom-container tip"},k=s("p",{class:"custom-container-title"},"Подсказка",-1),b=s("br",null,null,-1),q=t(`

                                        Внимание

                                        Функция обратного прокси находится в стадии тестирования и может работать некорректно.

                                        ReverseObject

                                        ReverseObject соответствует полю reverse в конфигурационном файле.

                                        {
                                        +import{_ as i,r as p,o as l,c as u,a,b as s,d as n,w as e,e as t}from"./app-Bw2NG-QJ.js";const r={},d=t('

                                        Обратный прокси

                                        Обратный прокси позволяет перенаправлять трафик с сервера на клиент, то есть перенаправлять трафик в обратном направлении.

                                        Принцип работы обратного прокси:

                                        • Предположим, что на хосте A запущен веб-сервер, но у этого хоста нет публичного IP-адреса, и к нему нельзя получить доступ из Интернета.
                                          У нас есть другой хост B с публичным IP-адресом.
                                          Мы хотим использовать хост B в качестве шлюза и перенаправлять трафик с B на A.
                                        • На хосте A настроен Xray, называемый bridge, и на хосте B также настроен Xray, называемый portal.
                                        • bridge устанавливает соединение с portal.
                                          Целевой адрес этого соединения можно настроить произвольно.
                                          portal получает два типа соединений: соединения от bridge и соединения от пользователей из Интернета.
                                          portal автоматически объединяет эти два типа соединений.
                                          Таким образом, bridge может получать трафик из Интернета.
                                        • После получения трафика из Интернета bridge перенаправляет его на веб-сервер на хосте A без изменений.
                                          Конечно, для этого требуется настроить маршрутизацию.
                                        • bridge выполняет динамическую балансировку нагрузки в зависимости от объема трафика.
                                        ',4),v={class:"custom-container tip"},k=s("p",{class:"custom-container-title"},"Подсказка",-1),b=s("br",null,null,-1),q=t(`

                                        Внимание

                                        Функция обратного прокси находится в стадии тестирования и может работать некорректно.

                                        ReverseObject

                                        ReverseObject соответствует полю reverse в конфигурационном файле.

                                        {
                                           "reverse": {
                                             "bridges": [
                                               {
                                        diff --git a/assets/reverse.html-bKcExnAb.js b/assets/reverse.html-WbzNOTcU.js
                                        similarity index 99%
                                        rename from assets/reverse.html-bKcExnAb.js
                                        rename to assets/reverse.html-WbzNOTcU.js
                                        index 886290e22b..7053c3462d 100644
                                        --- a/assets/reverse.html-bKcExnAb.js
                                        +++ b/assets/reverse.html-WbzNOTcU.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as o,o as r,c as l,a,b as s,d as n,w as p,e}from"./app-5SoadDYS.js";const u={},d=e(`

                                        Reverse Proxy

                                        A reverse proxy forwards traffic from a server to a client, which is known as reverse traffic forwarding.

                                        Here's how a reverse proxy generally works:

                                        • Suppose there is a web server in host A, which does not have a public IP address and cannot be accessed directly on the Internet. There is another host B that can be accessed via the public network. Now we need to use B as the entry point to forward traffic from B to A.
                                        • Configure Xray in host A as a bridge, and also configure Xray in B as a portal.
                                        • Bridge will actively establish a connection to portal, and the destination address of this connection can be set by itself. Portal will receive two types of connections: one is the connection sent by bridge, and the other is the connection sent by public network users. Portal will automatically merge the two types of connections. So bridge can receive public network traffic.
                                        • After receiving the public network traffic, bridge will forward it unchanged to the web server in host A. Of course, this step requires the cooperation of routing.
                                        • Bridge will dynamically load balance according to the size of the traffic.

                                        Tip

                                        Reverse proxy has Mux enabled by default, so please do not enable Mux again on the outbound it uses.

                                        Warning

                                        The reverse proxy function is still in the testing phase and may have some issues.

                                        ReverseObject

                                        ReverseObject corresponds to the reverse field in the configuration file.

                                        {
                                        +import{_ as c,r as o,o as r,c as l,a,b as s,d as n,w as p,e}from"./app-Bw2NG-QJ.js";const u={},d=e(`

                                        Reverse Proxy

                                        A reverse proxy forwards traffic from a server to a client, which is known as reverse traffic forwarding.

                                        Here's how a reverse proxy generally works:

                                        • Suppose there is a web server in host A, which does not have a public IP address and cannot be accessed directly on the Internet. There is another host B that can be accessed via the public network. Now we need to use B as the entry point to forward traffic from B to A.
                                        • Configure Xray in host A as a bridge, and also configure Xray in B as a portal.
                                        • Bridge will actively establish a connection to portal, and the destination address of this connection can be set by itself. Portal will receive two types of connections: one is the connection sent by bridge, and the other is the connection sent by public network users. Portal will automatically merge the two types of connections. So bridge can receive public network traffic.
                                        • After receiving the public network traffic, bridge will forward it unchanged to the web server in host A. Of course, this step requires the cooperation of routing.
                                        • Bridge will dynamically load balance according to the size of the traffic.

                                        Tip

                                        Reverse proxy has Mux enabled by default, so please do not enable Mux again on the outbound it uses.

                                        Warning

                                        The reverse proxy function is still in the testing phase and may have some issues.

                                        ReverseObject

                                        ReverseObject corresponds to the reverse field in the configuration file.

                                        {
                                           "reverse": {
                                             "bridges": [
                                               {
                                        diff --git a/assets/reverse.html-By4y7JyT.js b/assets/reverse.html-xPEDZtAc.js
                                        similarity index 99%
                                        rename from assets/reverse.html-By4y7JyT.js
                                        rename to assets/reverse.html-xPEDZtAc.js
                                        index 92ab18d3e7..9a99201ce2 100644
                                        --- a/assets/reverse.html-By4y7JyT.js
                                        +++ b/assets/reverse.html-xPEDZtAc.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as l,c as u,a,b as s,d as n,w as e,e as t}from"./app-5SoadDYS.js";const r={},d=t('

                                        反向代理

                                        反向代理可以把服务器端的流量向客户端转发,即逆向流量转发。

                                        反向代理的大致工作原理如下:

                                        • 假设在主机 A 中有一个网页服务器,这台主机没有公网 IP,无法在公网上直接访问。另有一台主机 B,它可以由公网访问。现在我们需要把 B 作为入口,把流量从 B 转发到 A。
                                        • 在主机 A 中配置 Xray,称为bridge,在 B 中也配置 Xray,称为 portal
                                        • bridge 会向 portal 主动建立连接,此连接的目标地址可以自行设定。portal 会收到两种连接,一是由 bridge 发来的连接,二是公网用户发来的连接。portal 会自动将两类连接合并。于是 bridge 就可以收到公网流量了。
                                        • bridge 在收到公网流量之后,会将其原封不动地发给主机 A 中的网页服务器。当然,这一步需要路由的协作。
                                        • bridge 会根据流量的大小进行动态的负载均衡。
                                        ',4),v={class:"custom-container tip"},k=s("p",{class:"custom-container-title"},"提示",-1),b=t(`

                                        注意

                                        反向代理功能尚处于测试阶段,可能会有一些问题。

                                        ReverseObject

                                        ReverseObject 对应配置文件的 reverse 项。

                                        {
                                        +import{_ as i,r as p,o as l,c as u,a,b as s,d as n,w as e,e as t}from"./app-Bw2NG-QJ.js";const r={},d=t('

                                        反向代理

                                        反向代理可以把服务器端的流量向客户端转发,即逆向流量转发。

                                        反向代理的大致工作原理如下:

                                        • 假设在主机 A 中有一个网页服务器,这台主机没有公网 IP,无法在公网上直接访问。另有一台主机 B,它可以由公网访问。现在我们需要把 B 作为入口,把流量从 B 转发到 A。
                                        • 在主机 A 中配置 Xray,称为bridge,在 B 中也配置 Xray,称为 portal
                                        • bridge 会向 portal 主动建立连接,此连接的目标地址可以自行设定。portal 会收到两种连接,一是由 bridge 发来的连接,二是公网用户发来的连接。portal 会自动将两类连接合并。于是 bridge 就可以收到公网流量了。
                                        • bridge 在收到公网流量之后,会将其原封不动地发给主机 A 中的网页服务器。当然,这一步需要路由的协作。
                                        • bridge 会根据流量的大小进行动态的负载均衡。
                                        ',4),v={class:"custom-container tip"},k=s("p",{class:"custom-container-title"},"提示",-1),b=t(`

                                        注意

                                        反向代理功能尚处于测试阶段,可能会有一些问题。

                                        ReverseObject

                                        ReverseObject 对应配置文件的 reverse 项。

                                        {
                                           "reverse": {
                                             "bridges": [
                                               {
                                        diff --git a/assets/routing-lv1-part1.html-ClnBy2hd.js b/assets/routing-lv1-part1.html-Bwge_E9k.js
                                        similarity index 99%
                                        rename from assets/routing-lv1-part1.html-ClnBy2hd.js
                                        rename to assets/routing-lv1-part1.html-Bwge_E9k.js
                                        index 3f63f503e3..8329287bc0 100644
                                        --- a/assets/routing-lv1-part1.html-ClnBy2hd.js
                                        +++ b/assets/routing-lv1-part1.html-Bwge_E9k.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as u,c as r,a,b as n,d as s,w as d,e as t}from"./app-5SoadDYS.js";const k="/assets/routing-lv1-img01-trio-BaHnOt7k.png",v={},g=t('

                                        路由 (routing) 功能简析(上)

                                        如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

                                        1. 初识【路由】三兄弟

                                        要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. 入站;2. 路由;3. 出站

                                        路由三兄弟

                                        三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。

                                        所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。

                                        因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。

                                        啰嗦君

                                        路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。

                                        2. 基本功: “兄弟一条心”

                                        下图的示例,就是在客户端的 Xray 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。

                                        ',11),q=t(`

                                        下面我们来逐个分析:

                                        2.1 入站

                                        提示

                                        入站: 就是流量如何流入 Xray

                                        下面的入站配置示例,用大白话说就是:数据按照 socks 协议,通过 10808 端口,从本机 127.0.0.1 流入Xray。同时,Xray 将这个入站用 [tag] 命名为 inbound-10808

                                        {
                                        +import{_ as i,r as p,o as u,c as r,a,b as n,d as s,w as d,e as t}from"./app-Bw2NG-QJ.js";const k="/assets/routing-lv1-img01-trio-BaHnOt7k.png",v={},g=t('

                                        路由 (routing) 功能简析(上)

                                        如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

                                        1. 初识【路由】三兄弟

                                        要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. 入站;2. 路由;3. 出站

                                        路由三兄弟

                                        三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。

                                        所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。

                                        因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。

                                        啰嗦君

                                        路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。

                                        2. 基本功: “兄弟一条心”

                                        下图的示例,就是在客户端的 Xray 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。

                                        ',11),q=t(`

                                        下面我们来逐个分析:

                                        2.1 入站

                                        提示

                                        入站: 就是流量如何流入 Xray

                                        下面的入站配置示例,用大白话说就是:数据按照 socks 协议,通过 10808 端口,从本机 127.0.0.1 流入Xray。同时,Xray 将这个入站用 [tag] 命名为 inbound-10808

                                        {
                                           "inbounds": [
                                             {
                                               "tag": "inbound-10808",
                                        diff --git a/assets/routing-lv1-part1.html-DGAFkfW-.js b/assets/routing-lv1-part1.html-DxoI7gBO.js
                                        similarity index 99%
                                        rename from assets/routing-lv1-part1.html-DGAFkfW-.js
                                        rename to assets/routing-lv1-part1.html-DxoI7gBO.js
                                        index 2ef5f14b5c..d44e747a79 100644
                                        --- a/assets/routing-lv1-part1.html-DGAFkfW-.js
                                        +++ b/assets/routing-lv1-part1.html-DxoI7gBO.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as u,c as r,a,b as n,d as s,w as d,e as t}from"./app-5SoadDYS.js";const k="/assets/routing-lv1-img01-trio-BaHnOt7k.png",v={},g=t('

                                        路由 (routing) 功能简析(上)

                                        如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

                                        1. 初识【路由】三兄弟

                                        要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. 入站;2. 路由;3. 出站

                                        路由三兄弟

                                        三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。

                                        所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。

                                        因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。

                                        啰嗦君

                                        路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。

                                        2. 基本功: “兄弟一条心”

                                        下图的示例,就是在客户端的 Xray 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。

                                        ',11),q=t(`

                                        下面我们来逐个分析:

                                        2.1 入站

                                        Tip

                                        入站: 就是流量如何流入 Xray

                                        下面的入站配置示例,用大白话说就是:数据按照 socks 协议,通过 10808 端口,从本机 127.0.0.1 流入Xray。同时,Xray 将这个入站用 [tag] 命名为 inbound-10808

                                        {
                                        +import{_ as i,r as p,o as u,c as r,a,b as n,d as s,w as d,e as t}from"./app-Bw2NG-QJ.js";const k="/assets/routing-lv1-img01-trio-BaHnOt7k.png",v={},g=t('

                                        路由 (routing) 功能简析(上)

                                        如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

                                        1. 初识【路由】三兄弟

                                        要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. 入站;2. 路由;3. 出站

                                        路由三兄弟

                                        三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。

                                        所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。

                                        因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。

                                        啰嗦君

                                        路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。

                                        2. 基本功: “兄弟一条心”

                                        下图的示例,就是在客户端的 Xray 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。

                                        ',11),q=t(`

                                        下面我们来逐个分析:

                                        2.1 入站

                                        Tip

                                        入站: 就是流量如何流入 Xray

                                        下面的入站配置示例,用大白话说就是:数据按照 socks 协议,通过 10808 端口,从本机 127.0.0.1 流入Xray。同时,Xray 将这个入站用 [tag] 命名为 inbound-10808

                                        {
                                           "inbounds": [
                                             {
                                               "tag": "inbound-10808",
                                        diff --git a/assets/routing-lv1-part1.html-WNvWtpj6.js b/assets/routing-lv1-part1.html-cn16P49Z.js
                                        similarity index 99%
                                        rename from assets/routing-lv1-part1.html-WNvWtpj6.js
                                        rename to assets/routing-lv1-part1.html-cn16P49Z.js
                                        index 449cc1d887..e98985869e 100644
                                        --- a/assets/routing-lv1-part1.html-WNvWtpj6.js
                                        +++ b/assets/routing-lv1-part1.html-cn16P49Z.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as u,c as r,a as o,b as n,d as s,w as d,e as a}from"./app-5SoadDYS.js";const D="/assets/routing-lv1-img01-trio-BaHnOt7k.png",g={},k=a('

                                        Краткий обзор функции маршрутизации (routing) (часть 1)

                                        Если "мощность" Xray в основном заключается в его высокой скорости и широкой совместимости, то его "гибкость" в первую очередь связана с продуманной функцией "routing" (маршрутизация). В этой статье мы кратко рассмотрим логику этой функции и способы ее применения.

                                        1. Знакомство с тремя братьями-маршрутизаторами

                                        Чтобы понять маршрутизацию, нужно понимать, что для ее полноценной работы нужны три компонента: 1. входящий трафик (inbound); 2. маршрутизация (routing); 3. исходящий трафик (outbound).

                                        Три брата-маршрутизатора

                                        Три брата, поклявшиеся в верности, не обязательно родились в один день, но должны быть готовы умереть в один день.

                                        Поэтому запомните: если один из элементов работает неправильно, функция маршрутизации может не работать.

                                        Поскольку маршрутизация очень гибкая, чтение только технической документации может вас запутать, поэтому в этой статье мы будем использовать конкретные примеры, чтобы объяснить все пошагово.

                                        Внимание

                                        Функция маршрутизации настолько гибкая, что примеры в этой статье приведены только для объяснения соответствующих концепций. На практике, пожалуйста, корректируйте их в соответствии с вашими потребностями.

                                        2. Основы: "Братья едины"

                                        На рисунке ниже показан пример, когда входящий трафик от приложения поступает на Xray на клиенте, маршрутизируется на исходящий трафик и отправляется на VPS.

                                        ',11),q=a(`

                                        Давайте проанализируем каждый шаг:

                                        2.1 Входящий трафик

                                        Подсказка

                                        Входящий трафик (inbound): это то, как трафик попадает в Xray.

                                        Пример конфигурации входящего трафика ниже означает, что данные поступают в Xray по протоколу socks через порт 10808 с локального адреса 127.0.0.1. Xray присваивает этому входящему трафику имя inbound-10808 с помощью [tag].

                                        {
                                        +import{_ as i,r as p,o as u,c as r,a as o,b as n,d as s,w as d,e as a}from"./app-Bw2NG-QJ.js";const D="/assets/routing-lv1-img01-trio-BaHnOt7k.png",g={},k=a('

                                        Краткий обзор функции маршрутизации (routing) (часть 1)

                                        Если "мощность" Xray в основном заключается в его высокой скорости и широкой совместимости, то его "гибкость" в первую очередь связана с продуманной функцией "routing" (маршрутизация). В этой статье мы кратко рассмотрим логику этой функции и способы ее применения.

                                        1. Знакомство с тремя братьями-маршрутизаторами

                                        Чтобы понять маршрутизацию, нужно понимать, что для ее полноценной работы нужны три компонента: 1. входящий трафик (inbound); 2. маршрутизация (routing); 3. исходящий трафик (outbound).

                                        Три брата-маршрутизатора

                                        Три брата, поклявшиеся в верности, не обязательно родились в один день, но должны быть готовы умереть в один день.

                                        Поэтому запомните: если один из элементов работает неправильно, функция маршрутизации может не работать.

                                        Поскольку маршрутизация очень гибкая, чтение только технической документации может вас запутать, поэтому в этой статье мы будем использовать конкретные примеры, чтобы объяснить все пошагово.

                                        Внимание

                                        Функция маршрутизации настолько гибкая, что примеры в этой статье приведены только для объяснения соответствующих концепций. На практике, пожалуйста, корректируйте их в соответствии с вашими потребностями.

                                        2. Основы: "Братья едины"

                                        На рисунке ниже показан пример, когда входящий трафик от приложения поступает на Xray на клиенте, маршрутизируется на исходящий трафик и отправляется на VPS.

                                        ',11),q=a(`

                                        Давайте проанализируем каждый шаг:

                                        2.1 Входящий трафик

                                        Подсказка

                                        Входящий трафик (inbound): это то, как трафик попадает в Xray.

                                        Пример конфигурации входящего трафика ниже означает, что данные поступают в Xray по протоколу socks через порт 10808 с локального адреса 127.0.0.1. Xray присваивает этому входящему трафику имя inbound-10808 с помощью [tag].

                                        {
                                           "inbounds": [
                                             {
                                               "tag": "inbound-10808",
                                        diff --git a/assets/routing-lv1-part2.html-BJbHs2YK.js b/assets/routing-lv1-part2.html-CfufGIyP.js
                                        similarity index 99%
                                        rename from assets/routing-lv1-part2.html-BJbHs2YK.js
                                        rename to assets/routing-lv1-part2.html-CfufGIyP.js
                                        index 001b93622b..bdfd0e9bad 100644
                                        --- a/assets/routing-lv1-part2.html-BJbHs2YK.js
                                        +++ b/assets/routing-lv1-part2.html-CfufGIyP.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as u,c as d,a,b as s,d as n,w as e,e as o}from"./app-5SoadDYS.js";const r={},k=s("h1",{id:"路由-routing-功能简析-下",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#路由-routing-功能简析-下"},[s("span",null,"路由 (routing) 功能简析(下)")])],-1),v=s("p",null,[n("欢迎继续学习 "),s("code",null,"Xray"),n(" 的【路由】功能!")],-1),m=s("code",null,"geosite.dat",-1),q=o('

                                        如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧!

                                        5. 攻城略池 - 多种路由匹配条件

                                        [域名], [IP], [协议], etc.

                                        基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢?

                                        因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如:

                                        1. 我读了《小小白白话文》后,给 VPS 新申请了一个 proxy.yourdomain.com 的域名, 我希望它无论如何都代理,geosite.dat 里面有吗?
                                        2. 如果我还有个 direct.yourdomain.com 的域名,我希望它无论如何都直连, geosite.dat 里面有吗?
                                        3. 本机 127.0.0.1 的内部流量,是否正确直连了?(比如 docker 等)
                                        4. 路由器、本地局域网 192.168.*.* 的流量,是否正确直连了?(比如路由器、群晖等)
                                        5. 我的国内 DNS 查询(如 223.5.5.5)是否正确直连了?
                                        6. 我的国外 DNS 查询(如 1.1.1.1)是否正确代理了?
                                        7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了?
                                        8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了?
                                        9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连?
                                        10. ......

                                        我之所以说只用【域名分流】会漏洞百出,是因为 geosite.dat 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会:

                                        • 无法匹配文件里没有的新域名
                                        • 无法匹配基于 IP 地址的规则
                                        • 无法匹配基于网络协议的规则

                                        啰嗦君

                                        那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【转发给第一个出站 】。这其实就是说:

                                        • 当你的第一个出站是 [direct-out] 时:需要直连的都正确了,但需要代理的则都错误
                                        • 当你的第一个出站是 [proxy-out-vless] 时:需要代理的都正确了,但需要直连的则都错误

                                        所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?当然存在! 我们需要的只是【域名】之外更多的【分流判断依据】而已。

                                        5.1 基于指定域名分流:[domain], [full]

                                        ',11),b=o("
                                      58. 如果需要匹配某个子域名,如 a-name.yourdomain.com,我们使用 full: "a-name.yourdomain.com"
                                      59. 前面的 问题1问题2,就可以通过给 proxy.yourdomain.com 指定 [proxy-out-vless] 出站,给 direct.yourdomain.com 指定 [direct-out] 出站来解决
                                      60. 如果需要匹配 yourdomain.com 的所有子域名,我们使用 domain: "yourdomain.com" 实现
                                      61. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置
                                      62. ",4),g=s("code",null,"[domain]",-1),y=o(`

                                        上述配置如下:

                                        {
                                        +import{_ as l,r as p,o as u,c as d,a,b as s,d as n,w as e,e as o}from"./app-Bw2NG-QJ.js";const r={},k=s("h1",{id:"路由-routing-功能简析-下",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#路由-routing-功能简析-下"},[s("span",null,"路由 (routing) 功能简析(下)")])],-1),v=s("p",null,[n("欢迎继续学习 "),s("code",null,"Xray"),n(" 的【路由】功能!")],-1),m=s("code",null,"geosite.dat",-1),q=o('

                                        如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧!

                                        5. 攻城略池 - 多种路由匹配条件

                                        [域名], [IP], [协议], etc.

                                        基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢?

                                        因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如:

                                        1. 我读了《小小白白话文》后,给 VPS 新申请了一个 proxy.yourdomain.com 的域名, 我希望它无论如何都代理,geosite.dat 里面有吗?
                                        2. 如果我还有个 direct.yourdomain.com 的域名,我希望它无论如何都直连, geosite.dat 里面有吗?
                                        3. 本机 127.0.0.1 的内部流量,是否正确直连了?(比如 docker 等)
                                        4. 路由器、本地局域网 192.168.*.* 的流量,是否正确直连了?(比如路由器、群晖等)
                                        5. 我的国内 DNS 查询(如 223.5.5.5)是否正确直连了?
                                        6. 我的国外 DNS 查询(如 1.1.1.1)是否正确代理了?
                                        7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了?
                                        8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了?
                                        9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连?
                                        10. ......

                                        我之所以说只用【域名分流】会漏洞百出,是因为 geosite.dat 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会:

                                        • 无法匹配文件里没有的新域名
                                        • 无法匹配基于 IP 地址的规则
                                        • 无法匹配基于网络协议的规则

                                        啰嗦君

                                        那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【转发给第一个出站 】。这其实就是说:

                                        • 当你的第一个出站是 [direct-out] 时:需要直连的都正确了,但需要代理的则都错误
                                        • 当你的第一个出站是 [proxy-out-vless] 时:需要代理的都正确了,但需要直连的则都错误

                                        所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?当然存在! 我们需要的只是【域名】之外更多的【分流判断依据】而已。

                                        5.1 基于指定域名分流:[domain], [full]

                                        ',11),b=o("
                                      63. 如果需要匹配某个子域名,如 a-name.yourdomain.com,我们使用 full: "a-name.yourdomain.com"
                                      64. 前面的 问题1问题2,就可以通过给 proxy.yourdomain.com 指定 [proxy-out-vless] 出站,给 direct.yourdomain.com 指定 [direct-out] 出站来解决
                                      65. 如果需要匹配 yourdomain.com 的所有子域名,我们使用 domain: "yourdomain.com" 实现
                                      66. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置
                                      67. ",4),g=s("code",null,"[domain]",-1),y=o(`

                                        上述配置如下:

                                        {
                                           "routing": {
                                             "domainStrategy": "AsIs",
                                             "rules": [
                                        diff --git a/assets/routing-lv1-part2.html-B6ObFc5O.js b/assets/routing-lv1-part2.html-D-nULKCp.js
                                        similarity index 99%
                                        rename from assets/routing-lv1-part2.html-B6ObFc5O.js
                                        rename to assets/routing-lv1-part2.html-D-nULKCp.js
                                        index 1236a54b17..c8f970a6a0 100644
                                        --- a/assets/routing-lv1-part2.html-B6ObFc5O.js
                                        +++ b/assets/routing-lv1-part2.html-D-nULKCp.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as u,c as r,a,b as s,d as n,w as e,e as o}from"./app-5SoadDYS.js";const d={},k=s("h1",{id:"краткии-обзор-функции-маршрутизации-routing-часть-2",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#краткии-обзор-функции-маршрутизации-routing-часть-2"},[s("span",null,"Краткий обзор функции маршрутизации (routing) (часть 2)")])],-1),v=s("p",null,[n("Добро пожаловать на продолжение изучения "),s("strong",null,"функции маршрутизации"),n(" в "),s("code",null,"Xray"),n("!")],-1),m=s("strong",null,"функции маршрутизации",-1),q=s("code",null,"geosite.dat",-1),D=o('

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

                                        5. Покорение новых высот - Различные условия сопоставления маршрутов

                                        [домен], [IP], [протокол], etc.

                                        Разделение по домену уже позволяет нам в общих чертах разделить сетевой трафик. Почему в общих чертах?

                                        Потому что, хотя "разделение мира на три части" — это правильная стратегия, ее реализация только с помощью доменов имеет множество недостатков, например:

                                        1. После прочтения нашего руководства я зарегистрировал новый домен proxy.yourdomain.com для своего VPS и хочу, чтобы трафик на него всегда проксировался. Есть ли он в geosite.dat?
                                        2. У меня есть еще один домен direct.yourdomain.com, и я хочу, чтобы трафик на него всегда шел напрямую. Есть ли он в geosite.dat?
                                        3. Правильно ли настроен прямой доступ для локального трафика на 127.0.0.1 (например, docker)?
                                        4. Правильно ли настроен прямой доступ для трафика в моей локальной сети 192.168.*.* (например, роутер, NAS)?
                                        5. Правильно ли настроен прямой доступ для моих DNS-запросов к внутренним DNS-серверам (например, 223.5.5.5)?
                                        6. Правильно ли настроен прокси для моих DNS-запросов к внешним DNS-серверам (например, 1.1.1.1)?
                                        7. Правильно ли настроен прямой доступ для других внутренних сайтов, у которых нет доменного имени, а только IP-адрес, как у внутренних DNS-серверов?
                                        8. Правильно ли настроен прокси для других внешних сайтов, у которых нет доменного имени, а только IP-адрес, как у внешних DNS-серверов?
                                        9. Как настроить принудительное прямое подключение для торрент-трафика, который, хотя и поступает извне, может привести к блокировке VPS при проксировании?
                                        10. ......

                                        Я говорю, что разделение по домену имеет много недостатков, потому что файл geosite.dat содержит только ограниченный набор часто используемых доменов. Другими словами, полагаясь только на него, мы:

                                        • не сможем сопоставить новые домены, которых нет в файле;
                                        • не сможем сопоставить правила на основе IP-адресов;
                                        • не сможем сопоставить правила на основе сетевых протоколов.

                                        Внимание

                                        Давайте вспомним, что происходит, когда эти условия не выполняются? Верно, срабатывает скрытое правило маршрутизации: трафик перенаправляется на первый исходящий трафик. Это означает, что:

                                        • если вашим первым исходящим трафиком является [direct-out]: все, что должно идти напрямую, будет работать правильно, а все, что должно проксироваться, будет работать неправильно;
                                        • если вашим первым исходящим трафиком является [proxy-out-vless]: все, что должно проксироваться, будет работать правильно, а все, что должно идти напрямую, будет работать неправильно.

                                        Поэтому нам нужен способ, который позволит нам получить и то, и другое. Существует ли такой способ? Конечно, существует! Нам просто нужны дополнительные критерии сопоставления помимо домена.

                                        5.1 Разделение по определенному домену: [domain], [full] и т. д.

                                        ',11),g=o("
                                      68. Для сопоставления поддомена, например a-name.yourdomain.com, мы используем full: "a-name.yourdomain.com".
                                      69. Проблемы 1 и 2, описанные выше, можно решить, указав исходящий трафик [proxy-out-vless] для proxy.yourdomain.com и исходящий трафик [direct-out] для direct.yourdomain.com.
                                      70. Для сопоставления всех поддоменов yourdomain.com мы используем domain: "yourdomain.com".
                                      71. Эти два правила могут быть независимыми, чтобы настроить прямое подключение для одних поддоменов и проксирование для других.
                                      72. ",4),b=s("code",null,"[domain]",-1),y=o(`

                                        Конфигурация выглядит следующим образом:

                                        {
                                        +import{_ as l,r as p,o as u,c as r,a,b as s,d as n,w as e,e as o}from"./app-Bw2NG-QJ.js";const d={},k=s("h1",{id:"краткии-обзор-функции-маршрутизации-routing-часть-2",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#краткии-обзор-функции-маршрутизации-routing-часть-2"},[s("span",null,"Краткий обзор функции маршрутизации (routing) (часть 2)")])],-1),v=s("p",null,[n("Добро пожаловать на продолжение изучения "),s("strong",null,"функции маршрутизации"),n(" в "),s("code",null,"Xray"),n("!")],-1),m=s("strong",null,"функции маршрутизации",-1),q=s("code",null,"geosite.dat",-1),D=o('

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

                                        5. Покорение новых высот - Различные условия сопоставления маршрутов

                                        [домен], [IP], [протокол], etc.

                                        Разделение по домену уже позволяет нам в общих чертах разделить сетевой трафик. Почему в общих чертах?

                                        Потому что, хотя "разделение мира на три части" — это правильная стратегия, ее реализация только с помощью доменов имеет множество недостатков, например:

                                        1. После прочтения нашего руководства я зарегистрировал новый домен proxy.yourdomain.com для своего VPS и хочу, чтобы трафик на него всегда проксировался. Есть ли он в geosite.dat?
                                        2. У меня есть еще один домен direct.yourdomain.com, и я хочу, чтобы трафик на него всегда шел напрямую. Есть ли он в geosite.dat?
                                        3. Правильно ли настроен прямой доступ для локального трафика на 127.0.0.1 (например, docker)?
                                        4. Правильно ли настроен прямой доступ для трафика в моей локальной сети 192.168.*.* (например, роутер, NAS)?
                                        5. Правильно ли настроен прямой доступ для моих DNS-запросов к внутренним DNS-серверам (например, 223.5.5.5)?
                                        6. Правильно ли настроен прокси для моих DNS-запросов к внешним DNS-серверам (например, 1.1.1.1)?
                                        7. Правильно ли настроен прямой доступ для других внутренних сайтов, у которых нет доменного имени, а только IP-адрес, как у внутренних DNS-серверов?
                                        8. Правильно ли настроен прокси для других внешних сайтов, у которых нет доменного имени, а только IP-адрес, как у внешних DNS-серверов?
                                        9. Как настроить принудительное прямое подключение для торрент-трафика, который, хотя и поступает извне, может привести к блокировке VPS при проксировании?
                                        10. ......

                                        Я говорю, что разделение по домену имеет много недостатков, потому что файл geosite.dat содержит только ограниченный набор часто используемых доменов. Другими словами, полагаясь только на него, мы:

                                        • не сможем сопоставить новые домены, которых нет в файле;
                                        • не сможем сопоставить правила на основе IP-адресов;
                                        • не сможем сопоставить правила на основе сетевых протоколов.

                                        Внимание

                                        Давайте вспомним, что происходит, когда эти условия не выполняются? Верно, срабатывает скрытое правило маршрутизации: трафик перенаправляется на первый исходящий трафик. Это означает, что:

                                        • если вашим первым исходящим трафиком является [direct-out]: все, что должно идти напрямую, будет работать правильно, а все, что должно проксироваться, будет работать неправильно;
                                        • если вашим первым исходящим трафиком является [proxy-out-vless]: все, что должно проксироваться, будет работать правильно, а все, что должно идти напрямую, будет работать неправильно.

                                        Поэтому нам нужен способ, который позволит нам получить и то, и другое. Существует ли такой способ? Конечно, существует! Нам просто нужны дополнительные критерии сопоставления помимо домена.

                                        5.1 Разделение по определенному домену: [domain], [full] и т. д.

                                        ',11),g=o("
                                      73. Для сопоставления поддомена, например a-name.yourdomain.com, мы используем full: "a-name.yourdomain.com".
                                      74. Проблемы 1 и 2, описанные выше, можно решить, указав исходящий трафик [proxy-out-vless] для proxy.yourdomain.com и исходящий трафик [direct-out] для direct.yourdomain.com.
                                      75. Для сопоставления всех поддоменов yourdomain.com мы используем domain: "yourdomain.com".
                                      76. Эти два правила могут быть независимыми, чтобы настроить прямое подключение для одних поддоменов и проксирование для других.
                                      77. ",4),b=s("code",null,"[domain]",-1),y=o(`

                                        Конфигурация выглядит следующим образом:

                                        {
                                           "routing": {
                                             "domainStrategy": "AsIs",
                                             "rules": [
                                        diff --git a/assets/routing-lv1-part2.html-d3I02cv4.js b/assets/routing-lv1-part2.html-n2aETtQH.js
                                        similarity index 99%
                                        rename from assets/routing-lv1-part2.html-d3I02cv4.js
                                        rename to assets/routing-lv1-part2.html-n2aETtQH.js
                                        index 4f3fbd527c..7cb364b990 100644
                                        --- a/assets/routing-lv1-part2.html-d3I02cv4.js
                                        +++ b/assets/routing-lv1-part2.html-n2aETtQH.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as u,c as d,a,b as s,d as n,w as e,e as o}from"./app-5SoadDYS.js";const r={},k=s("h1",{id:"路由-routing-功能简析-下",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#路由-routing-功能简析-下"},[s("span",null,"路由 (routing) 功能简析(下)")])],-1),v=s("p",null,[n("欢迎继续学习 "),s("code",null,"Xray"),n(" 的【路由】功能!")],-1),m=s("code",null,"geosite.dat",-1),q=o('

                                        如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧!

                                        5. 攻城略池 - 多种路由匹配条件

                                        [域名], [IP], [协议], etc.

                                        基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢?

                                        因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如:

                                        1. 我读了《小小白白话文》后,给 VPS 新申请了一个 proxy.yourdomain.com 的域名, 我希望它无论如何都代理,geosite.dat 里面有吗?
                                        2. 如果我还有个 direct.yourdomain.com 的域名,我希望它无论如何都直连, geosite.dat 里面有吗?
                                        3. 本机 127.0.0.1 的内部流量,是否正确直连了?(比如 docker 等)
                                        4. 路由器、本地局域网 192.168.*.* 的流量,是否正确直连了?(比如路由器、群晖等)
                                        5. 我的国内 DNS 查询(如 223.5.5.5)是否正确直连了?
                                        6. 我的国外 DNS 查询(如 1.1.1.1)是否正确代理了?
                                        7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了?
                                        8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了?
                                        9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连?
                                        10. ......

                                        我之所以说只用【域名分流】会漏洞百出,是因为 geosite.dat 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会:

                                        • 无法匹配文件里没有的新域名
                                        • 无法匹配基于 IP 地址的规则
                                        • 无法匹配基于网络协议的规则

                                        啰嗦君

                                        那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【转发给第一个出站 】。这其实就是说:

                                        • 当你的第一个出站是 [direct-out] 时:需要直连的都正确了,但需要代理的则都错误
                                        • 当你的第一个出站是 [proxy-out-vless] 时:需要代理的都正确了,但需要直连的则都错误

                                        所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?当然存在! 我们需要的只是【域名】之外更多的【分流判断依据】而已。

                                        5.1 基于指定域名分流:[domain], [full]

                                        ',11),b=o("
                                      78. 如果需要匹配某个子域名,如 a-name.yourdomain.com,我们使用 full: "a-name.yourdomain.com"
                                      79. 前面的 问题1问题2,就可以通过给 proxy.yourdomain.com 指定 [proxy-out-vless] 出站,给 direct.yourdomain.com 指定 [direct-out] 出站来解决
                                      80. 如果需要匹配 yourdomain.com 的所有子域名,我们使用 domain: "yourdomain.com" 实现
                                      81. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置
                                      82. ",4),g=s("code",null,"[domain]",-1),y=o(`

                                        上述配置如下:

                                        {
                                        +import{_ as l,r as p,o as u,c as d,a,b as s,d as n,w as e,e as o}from"./app-Bw2NG-QJ.js";const r={},k=s("h1",{id:"路由-routing-功能简析-下",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#路由-routing-功能简析-下"},[s("span",null,"路由 (routing) 功能简析(下)")])],-1),v=s("p",null,[n("欢迎继续学习 "),s("code",null,"Xray"),n(" 的【路由】功能!")],-1),m=s("code",null,"geosite.dat",-1),q=o('

                                        如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧!

                                        5. 攻城略池 - 多种路由匹配条件

                                        [域名], [IP], [协议], etc.

                                        基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢?

                                        因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如:

                                        1. 我读了《小小白白话文》后,给 VPS 新申请了一个 proxy.yourdomain.com 的域名, 我希望它无论如何都代理,geosite.dat 里面有吗?
                                        2. 如果我还有个 direct.yourdomain.com 的域名,我希望它无论如何都直连, geosite.dat 里面有吗?
                                        3. 本机 127.0.0.1 的内部流量,是否正确直连了?(比如 docker 等)
                                        4. 路由器、本地局域网 192.168.*.* 的流量,是否正确直连了?(比如路由器、群晖等)
                                        5. 我的国内 DNS 查询(如 223.5.5.5)是否正确直连了?
                                        6. 我的国外 DNS 查询(如 1.1.1.1)是否正确代理了?
                                        7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了?
                                        8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了?
                                        9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连?
                                        10. ......

                                        我之所以说只用【域名分流】会漏洞百出,是因为 geosite.dat 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会:

                                        • 无法匹配文件里没有的新域名
                                        • 无法匹配基于 IP 地址的规则
                                        • 无法匹配基于网络协议的规则

                                        啰嗦君

                                        那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【转发给第一个出站 】。这其实就是说:

                                        • 当你的第一个出站是 [direct-out] 时:需要直连的都正确了,但需要代理的则都错误
                                        • 当你的第一个出站是 [proxy-out-vless] 时:需要代理的都正确了,但需要直连的则都错误

                                        所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?当然存在! 我们需要的只是【域名】之外更多的【分流判断依据】而已。

                                        5.1 基于指定域名分流:[domain], [full]

                                        ',11),b=o("
                                      83. 如果需要匹配某个子域名,如 a-name.yourdomain.com,我们使用 full: "a-name.yourdomain.com"
                                      84. 前面的 问题1问题2,就可以通过给 proxy.yourdomain.com 指定 [proxy-out-vless] 出站,给 direct.yourdomain.com 指定 [direct-out] 出站来解决
                                      85. 如果需要匹配 yourdomain.com 的所有子域名,我们使用 domain: "yourdomain.com" 实现
                                      86. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置
                                      87. ",4),g=s("code",null,"[domain]",-1),y=o(`

                                        上述配置如下:

                                        {
                                           "routing": {
                                             "domainStrategy": "AsIs",
                                             "rules": [
                                        diff --git a/assets/routing.html-XztNj6nv.js b/assets/routing.html-B34g5Zqk.js
                                        similarity index 99%
                                        rename from assets/routing.html-XztNj6nv.js
                                        rename to assets/routing.html-B34g5Zqk.js
                                        index 6cca675548..8ffc61a1e2 100644
                                        --- a/assets/routing.html-XztNj6nv.js
                                        +++ b/assets/routing.html-B34g5Zqk.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as s,o as u,c as p,a as t,b as e,d as o,w as c,e as n}from"./app-5SoadDYS.js";const d={},h=e("h1",{id:"routing",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#routing"},[e("span",null,"Routing")])],-1),m=e("p",null,"The routing module can send inbound data through different outbound connections according to different rules to achieve on-demand proxying.",-1),q=e("p",null,"A common use case is to split domestic and foreign traffic. Xray can use its internal mechanisms to determine the traffic from different regions and then send them to different outbound proxies.",-1),f={href:"https://xtls.github.io/document/level-1/routing-lv1-part1.html",target:"_blank",rel:"noopener noreferrer"},g=n(`

                                        RoutingObject

                                        RoutingObject corresponds to the routing item in the configuration file.

                                        {
                                        +import{_ as r,r as s,o as u,c as p,a as t,b as e,d as o,w as c,e as n}from"./app-Bw2NG-QJ.js";const d={},h=e("h1",{id:"routing",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#routing"},[e("span",null,"Routing")])],-1),m=e("p",null,"The routing module can send inbound data through different outbound connections according to different rules to achieve on-demand proxying.",-1),q=e("p",null,"A common use case is to split domestic and foreign traffic. Xray can use its internal mechanisms to determine the traffic from different regions and then send them to different outbound proxies.",-1),f={href:"https://xtls.github.io/document/level-1/routing-lv1-part1.html",target:"_blank",rel:"noopener noreferrer"},g=n(`

                                        RoutingObject

                                        RoutingObject corresponds to the routing item in the configuration file.

                                        {
                                           "routing": {
                                             "domainStrategy": "AsIs",
                                             "domainMatcher": "hybrid",
                                        diff --git a/assets/routing.html-BMa5pEvD.js b/assets/routing.html-DYlVNKuL.js
                                        similarity index 99%
                                        rename from assets/routing.html-BMa5pEvD.js
                                        rename to assets/routing.html-DYlVNKuL.js
                                        index b00c4ef958..28599bf317 100644
                                        --- a/assets/routing.html-BMa5pEvD.js
                                        +++ b/assets/routing.html-DYlVNKuL.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as i,c as r,a as s,b as n,d as o,w as e,e as t}from"./app-5SoadDYS.js";const d={},q=n("h1",{id:"маршрутизация",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#маршрутизация"},[n("span",null,"Маршрутизация")])],-1),b=n("p",null,"Модуль маршрутизации позволяет направлять входящие данные через разные исходящие подключения в соответствии с различными правилами, что позволяет реализовать проксирование по требованию.",-1),k=n("p",null,[o("Например, распространенным сценарием использования является разделение трафика на внутренний и внешний."),n("br"),o(" Xray может определять трафик из разных регионов с помощью внутренних механизмов и отправлять его через разные исходящие подключения.")],-1),v={href:"https://xtls.github.io/ru/document/level-1/routing-lv1-part1.html",target:"_blank",rel:"noopener noreferrer"},g=t(`

                                        RoutingObject

                                        RoutingObject соответствует полю routing в конфигурационном файле.

                                        {
                                        +import{_ as l,r as p,o as i,c as r,a as s,b as n,d as o,w as e,e as t}from"./app-Bw2NG-QJ.js";const d={},q=n("h1",{id:"маршрутизация",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#маршрутизация"},[n("span",null,"Маршрутизация")])],-1),b=n("p",null,"Модуль маршрутизации позволяет направлять входящие данные через разные исходящие подключения в соответствии с различными правилами, что позволяет реализовать проксирование по требованию.",-1),k=n("p",null,[o("Например, распространенным сценарием использования является разделение трафика на внутренний и внешний."),n("br"),o(" Xray может определять трафик из разных регионов с помощью внутренних механизмов и отправлять его через разные исходящие подключения.")],-1),v={href:"https://xtls.github.io/ru/document/level-1/routing-lv1-part1.html",target:"_blank",rel:"noopener noreferrer"},g=t(`

                                        RoutingObject

                                        RoutingObject соответствует полю routing в конфигурационном файле.

                                        {
                                           "routing": {
                                             "domainStrategy": "AsIs",
                                             "domainMatcher": "hybrid",
                                        diff --git a/assets/routing.html-BFdIFNzE.js b/assets/routing.html-Diz_GMQp.js
                                        similarity index 99%
                                        rename from assets/routing.html-BFdIFNzE.js
                                        rename to assets/routing.html-Diz_GMQp.js
                                        index 10ee02c627..21e5c63abc 100644
                                        --- a/assets/routing.html-BFdIFNzE.js
                                        +++ b/assets/routing.html-Diz_GMQp.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as i,c as d,a as s,b as n,d as o,w as e,e as t}from"./app-5SoadDYS.js";const r={},q=n("h1",{id:"路由",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#路由"},[n("span",null,"路由")])],-1),k=n("p",null,"路由功能模块可以将入站数据按不同规则由不同的出站连接发出,以达到按需代理的目的。",-1),b=n("p",null,"如常见用法是分流国内外流量,Xray 可以通过内部机制判断不同地区的流量,然后将它们发送到不同的出站代理。",-1),v={href:"https://xtls.github.io/document/level-1/routing-lv1-part1.html",target:"_blank",rel:"noopener noreferrer"},g=t(`

                                        RoutingObject

                                        RoutingObject 对应配置文件的 routing 项。

                                        {
                                        +import{_ as l,r as p,o as i,c as d,a as s,b as n,d as o,w as e,e as t}from"./app-Bw2NG-QJ.js";const r={},q=n("h1",{id:"路由",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#路由"},[n("span",null,"路由")])],-1),k=n("p",null,"路由功能模块可以将入站数据按不同规则由不同的出站连接发出,以达到按需代理的目的。",-1),b=n("p",null,"如常见用法是分流国内外流量,Xray 可以通过内部机制判断不同地区的流量,然后将它们发送到不同的出站代理。",-1),v={href:"https://xtls.github.io/document/level-1/routing-lv1-part1.html",target:"_blank",rel:"noopener noreferrer"},g=t(`

                                        RoutingObject

                                        RoutingObject 对应配置文件的 routing 项。

                                        {
                                           "routing": {
                                             "domainStrategy": "AsIs",
                                             "domainMatcher": "hybrid",
                                        diff --git a/assets/sankeyDiagram-707fac0f-CYIZhz1m.js b/assets/sankeyDiagram-707fac0f-Dqx64UnQ.js
                                        similarity index 99%
                                        rename from assets/sankeyDiagram-707fac0f-CYIZhz1m.js
                                        rename to assets/sankeyDiagram-707fac0f-Dqx64UnQ.js
                                        index fae7aa41b9..80f25a0aef 100644
                                        --- a/assets/sankeyDiagram-707fac0f-CYIZhz1m.js
                                        +++ b/assets/sankeyDiagram-707fac0f-Dqx64UnQ.js
                                        @@ -1,4 +1,4 @@
                                        -import{c as rt,g as mt,s as kt,a as _t,b as xt,y as vt,x as bt,A as wt,j as St,v as Lt,h as G,u as Et}from"./mermaid.core-CArNAncI.js";import{o as At}from"./ordinal-Cboi1Yqb.js";import{s as Tt}from"./Tableau10-B-NsZVaP.js";import"./app-5SoadDYS.js";import"./init-Gi6I4Gst.js";function ot(t,n){let s;if(n===void 0)for(const a of t)a!=null&&(s=a)&&(s=a);else{let a=-1;for(let u of t)(u=n(u,++a,t))!=null&&(s=u)&&(s=u)}return s}function yt(t,n){let s;if(n===void 0)for(const a of t)a!=null&&(s>a||s===void 0&&a>=a)&&(s=a);else{let a=-1;for(let u of t)(u=n(u,++a,t))!=null&&(s>u||s===void 0&&u>=u)&&(s=u)}return s}function Z(t,n){let s=0;if(n===void 0)for(let a of t)(a=+a)&&(s+=a);else{let a=-1;for(let u of t)(u=+n(u,++a,t))&&(s+=u)}return s}function Mt(t){return t.target.depth}function Nt(t){return t.depth}function Pt(t,n){return n-1-t.height}function dt(t,n){return t.sourceLinks.length?t.depth:n-1}function Ct(t){return t.targetLinks.length?t.depth:t.sourceLinks.length?yt(t.sourceLinks,Mt)-1:0}function Y(t){return function(){return t}}function lt(t,n){return H(t.source,n.source)||t.index-n.index}function at(t,n){return H(t.target,n.target)||t.index-n.index}function H(t,n){return t.y0-n.y0}function J(t){return t.value}function It(t){return t.index}function $t(t){return t.nodes}function Ot(t){return t.links}function ct(t,n){const s=t.get(n);if(!s)throw new Error("missing: "+n);return s}function ut({nodes:t}){for(const n of t){let s=n.y0,a=s;for(const u of n.sourceLinks)u.y0=s+u.width/2,s+=u.width;for(const u of n.targetLinks)u.y1=a+u.width/2,a+=u.width}}function jt(){let t=0,n=0,s=1,a=1,u=24,_=8,g,p=It,i=dt,o,c,m=$t,b=Ot,y=6;function x(){const e={nodes:m.apply(null,arguments),links:b.apply(null,arguments)};return E(e),L(e),A(e),N(e),S(e),ut(e),e}x.update=function(e){return ut(e),e},x.nodeId=function(e){return arguments.length?(p=typeof e=="function"?e:Y(e),x):p},x.nodeAlign=function(e){return arguments.length?(i=typeof e=="function"?e:Y(e),x):i},x.nodeSort=function(e){return arguments.length?(o=e,x):o},x.nodeWidth=function(e){return arguments.length?(u=+e,x):u},x.nodePadding=function(e){return arguments.length?(_=g=+e,x):_},x.nodes=function(e){return arguments.length?(m=typeof e=="function"?e:Y(e),x):m},x.links=function(e){return arguments.length?(b=typeof e=="function"?e:Y(e),x):b},x.linkSort=function(e){return arguments.length?(c=e,x):c},x.size=function(e){return arguments.length?(t=n=0,s=+e[0],a=+e[1],x):[s-t,a-n]},x.extent=function(e){return arguments.length?(t=+e[0][0],s=+e[1][0],n=+e[0][1],a=+e[1][1],x):[[t,n],[s,a]]},x.iterations=function(e){return arguments.length?(y=+e,x):y};function E({nodes:e,links:f}){for(const[h,r]of e.entries())r.index=h,r.sourceLinks=[],r.targetLinks=[];const l=new Map(e.map((h,r)=>[p(h,r,e),h]));for(const[h,r]of f.entries()){r.index=h;let{source:k,target:v}=r;typeof k!="object"&&(k=r.source=ct(l,k)),typeof v!="object"&&(v=r.target=ct(l,v)),k.sourceLinks.push(r),v.targetLinks.push(r)}if(c!=null)for(const{sourceLinks:h,targetLinks:r}of e)h.sort(c),r.sort(c)}function L({nodes:e}){for(const f of e)f.value=f.fixedValue===void 0?Math.max(Z(f.sourceLinks,J),Z(f.targetLinks,J)):f.fixedValue}function A({nodes:e}){const f=e.length;let l=new Set(e),h=new Set,r=0;for(;l.size;){for(const k of l){k.depth=r;for(const{target:v}of k.sourceLinks)h.add(v)}if(++r>f)throw new Error("circular link");l=h,h=new Set}}function N({nodes:e}){const f=e.length;let l=new Set(e),h=new Set,r=0;for(;l.size;){for(const k of l){k.height=r;for(const{source:v}of k.targetLinks)h.add(v)}if(++r>f)throw new Error("circular link");l=h,h=new Set}}function I({nodes:e}){const f=ot(e,r=>r.depth)+1,l=(s-t-u)/(f-1),h=new Array(f);for(const r of e){const k=Math.max(0,Math.min(f-1,Math.floor(i.call(null,r,f))));r.layer=k,r.x0=t+k*l,r.x1=r.x0+u,h[k]?h[k].push(r):h[k]=[r]}if(o)for(const r of h)r.sort(o);return h}function j(e){const f=yt(e,l=>(a-n-(l.length-1)*g)/Z(l,J));for(const l of e){let h=n;for(const r of l){r.y0=h,r.y1=h+r.value*f,h=r.y1+g;for(const k of r.sourceLinks)k.width=k.value*f}h=(a-h+g)/(l.length+1);for(let r=0;rl.length)-1)),j(f);for(let l=0;l0))continue;let U=(R/z-v.y0)*f;v.y0+=U,v.y1+=U,w(v)}o===void 0&&k.sort(H),P(k,l)}}function O(e,f,l){for(let h=e.length,r=h-2;r>=0;--r){const k=e[r];for(const v of k){let R=0,z=0;for(const{target:W,value:K}of v.sourceLinks){let F=K*(W.layer-v.layer);R+=V(v,W)*F,z+=F}if(!(z>0))continue;let U=(R/z-v.y0)*f;v.y0+=U,v.y1+=U,w(v)}o===void 0&&k.sort(H),P(k,l)}}function P(e,f){const l=e.length>>1,h=e[l];d(e,h.y0-g,l-1,f),C(e,h.y1+g,l+1,f),d(e,a,e.length-1,f),C(e,n,0,f)}function C(e,f,l,h){for(;l1e-6&&(r.y0+=k,r.y1+=k),f=r.y1+g}}function d(e,f,l,h){for(;l>=0;--l){const r=e[l],k=(r.y1-f)*h;k>1e-6&&(r.y0-=k,r.y1-=k),f=r.y0-g}}function w({sourceLinks:e,targetLinks:f}){if(c===void 0){for(const{source:{sourceLinks:l}}of f)l.sort(at);for(const{target:{targetLinks:l}}of e)l.sort(lt)}}function $(e){if(c===void 0)for(const{sourceLinks:f,targetLinks:l}of e)f.sort(at),l.sort(lt)}function T(e,f){let l=e.y0-(e.sourceLinks.length-1)*g/2;for(const{target:h,width:r}of e.sourceLinks){if(h===f)break;l+=r+g}for(const{source:h,width:r}of f.targetLinks){if(h===e)break;l-=r}return l}function V(e,f){let l=f.y0-(f.targetLinks.length-1)*g/2;for(const{source:h,width:r}of f.targetLinks){if(h===e)break;l+=r+g}for(const{target:h,width:r}of e.sourceLinks){if(h===f)break;l-=r}return l}return x}var tt=Math.PI,et=2*tt,D=1e-6,zt=et-D;function nt(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function gt(){return new nt}nt.prototype=gt.prototype={constructor:nt,moveTo:function(t,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,n){this._+="L"+(this._x1=+t)+","+(this._y1=+n)},quadraticCurveTo:function(t,n,s,a){this._+="Q"+ +t+","+ +n+","+(this._x1=+s)+","+(this._y1=+a)},bezierCurveTo:function(t,n,s,a,u,_){this._+="C"+ +t+","+ +n+","+ +s+","+ +a+","+(this._x1=+u)+","+(this._y1=+_)},arcTo:function(t,n,s,a,u){t=+t,n=+n,s=+s,a=+a,u=+u;var _=this._x1,g=this._y1,p=s-t,i=a-n,o=_-t,c=g-n,m=o*o+c*c;if(u<0)throw new Error("negative radius: "+u);if(this._x1===null)this._+="M"+(this._x1=t)+","+(this._y1=n);else if(m>D)if(!(Math.abs(c*p-i*o)>D)||!u)this._+="L"+(this._x1=t)+","+(this._y1=n);else{var b=s-_,y=a-g,x=p*p+i*i,E=b*b+y*y,L=Math.sqrt(x),A=Math.sqrt(m),N=u*Math.tan((tt-Math.acos((x+m-E)/(2*L*A)))/2),I=N/A,j=N/L;Math.abs(I-1)>D&&(this._+="L"+(t+I*o)+","+(n+I*c)),this._+="A"+u+","+u+",0,0,"+ +(c*b>o*y)+","+(this._x1=t+j*p)+","+(this._y1=n+j*i)}},arc:function(t,n,s,a,u,_){t=+t,n=+n,s=+s,_=!!_;var g=s*Math.cos(a),p=s*Math.sin(a),i=t+g,o=n+p,c=1^_,m=_?a-u:u-a;if(s<0)throw new Error("negative radius: "+s);this._x1===null?this._+="M"+i+","+o:(Math.abs(this._x1-i)>D||Math.abs(this._y1-o)>D)&&(this._+="L"+i+","+o),s&&(m<0&&(m=m%et+et),m>zt?this._+="A"+s+","+s+",0,1,"+c+","+(t-g)+","+(n-p)+"A"+s+","+s+",0,1,"+c+","+(this._x1=i)+","+(this._y1=o):m>D&&(this._+="A"+s+","+s+",0,"+ +(m>=tt)+","+c+","+(this._x1=t+s*Math.cos(u))+","+(this._y1=n+s*Math.sin(u))))},rect:function(t,n,s,a){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +s+"v"+ +a+"h"+-s+"Z"},toString:function(){return this._}};function ht(t){return function(){return t}}function Dt(t){return t[0]}function Bt(t){return t[1]}var Vt=Array.prototype.slice;function Rt(t){return t.source}function Ut(t){return t.target}function Wt(t){var n=Rt,s=Ut,a=Dt,u=Bt,_=null;function g(){var p,i=Vt.call(arguments),o=n.apply(this,i),c=s.apply(this,i);if(_||(_=p=gt()),t(_,+a.apply(this,(i[0]=o,i)),+u.apply(this,i),+a.apply(this,(i[0]=c,i)),+u.apply(this,i)),p)return _=null,p+""||null}return g.source=function(p){return arguments.length?(n=p,g):n},g.target=function(p){return arguments.length?(s=p,g):s},g.x=function(p){return arguments.length?(a=typeof p=="function"?p:ht(+p),g):a},g.y=function(p){return arguments.length?(u=typeof p=="function"?p:ht(+p),g):u},g.context=function(p){return arguments.length?(_=p??null,g):_},g}function Ft(t,n,s,a,u){t.moveTo(n,s),t.bezierCurveTo(n=(n+a)/2,s,n,u,a,u)}function Gt(){return Wt(Ft)}function Yt(t){return[t.source.x1,t.y0]}function Ht(t){return[t.target.x0,t.y1]}function Xt(){return Gt().source(Yt).target(Ht)}var it=function(){var t=function(p,i,o,c){for(o=o||{},c=p.length;c--;o[p[c]]=i);return o},n=[1,9],s=[1,10],a=[1,5,10,12],u={trace:function(){},yy:{},symbols_:{error:2,start:3,SANKEY:4,NEWLINE:5,csv:6,opt_eof:7,record:8,csv_tail:9,EOF:10,"field[source]":11,COMMA:12,"field[target]":13,"field[value]":14,field:15,escaped:16,non_escaped:17,DQUOTE:18,ESCAPED_TEXT:19,NON_ESCAPED_TEXT:20,$accept:0,$end:1},terminals_:{2:"error",4:"SANKEY",5:"NEWLINE",10:"EOF",11:"field[source]",12:"COMMA",13:"field[target]",14:"field[value]",18:"DQUOTE",19:"ESCAPED_TEXT",20:"NON_ESCAPED_TEXT"},productions_:[0,[3,4],[6,2],[9,2],[9,0],[7,1],[7,0],[8,5],[15,1],[15,1],[16,3],[17,1]],performAction:function(i,o,c,m,b,y,x){var E=y.length-1;switch(b){case 7:const L=m.findOrCreateNode(y[E-4].trim().replaceAll('""','"')),A=m.findOrCreateNode(y[E-2].trim().replaceAll('""','"')),N=parseFloat(y[E].trim());m.addLink(L,A,N);break;case 8:case 9:case 11:this.$=y[E];break;case 10:this.$=y[E-1];break}},table:[{3:1,4:[1,2]},{1:[3]},{5:[1,3]},{6:4,8:5,15:6,16:7,17:8,18:n,20:s},{1:[2,6],7:11,10:[1,12]},t(s,[2,4],{9:13,5:[1,14]}),{12:[1,15]},t(a,[2,8]),t(a,[2,9]),{19:[1,16]},t(a,[2,11]),{1:[2,1]},{1:[2,5]},t(s,[2,2]),{6:17,8:5,15:6,16:7,17:8,18:n,20:s},{15:18,16:7,17:8,18:n,20:s},{18:[1,19]},t(s,[2,3]),{12:[1,20]},t(a,[2,10]),{15:21,16:7,17:8,18:n,20:s},t([1,5,10],[2,7])],defaultActions:{11:[2,1],12:[2,5]},parseError:function(i,o){if(o.recoverable)this.trace(i);else{var c=new Error(i);throw c.hash=o,c}},parse:function(i){var o=this,c=[0],m=[],b=[null],y=[],x=this.table,E="",L=0,A=0,N=2,I=1,j=y.slice.call(arguments,1),S=Object.create(this.lexer),M={yy:{}};for(var O in this.yy)Object.prototype.hasOwnProperty.call(this.yy,O)&&(M.yy[O]=this.yy[O]);S.setInput(i,M.yy),M.yy.lexer=S,M.yy.parser=this,typeof S.yylloc>"u"&&(S.yylloc={});var P=S.yylloc;y.push(P);var C=S.options&&S.options.ranges;typeof M.yy.parseError=="function"?this.parseError=M.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function d(){var v;return v=m.pop()||S.lex()||I,typeof v!="number"&&(v instanceof Array&&(m=v,v=m.pop()),v=o.symbols_[v]||v),v}for(var w,$,T,V,e={},f,l,h,r;;){if($=c[c.length-1],this.defaultActions[$]?T=this.defaultActions[$]:((w===null||typeof w>"u")&&(w=d()),T=x[$]&&x[$][w]),typeof T>"u"||!T.length||!T[0]){var k="";r=[];for(f in x[$])this.terminals_[f]&&f>N&&r.push("'"+this.terminals_[f]+"'");S.showPosition?k="Parse error on line "+(L+1)+`:
                                        +import{c as rt,g as mt,s as kt,a as _t,b as xt,y as vt,x as bt,A as wt,j as St,v as Lt,h as G,u as Et}from"./mermaid.core-Bq0kX0MS.js";import{o as At}from"./ordinal-Cboi1Yqb.js";import{s as Tt}from"./Tableau10-B-NsZVaP.js";import"./app-Bw2NG-QJ.js";import"./init-Gi6I4Gst.js";function ot(t,n){let s;if(n===void 0)for(const a of t)a!=null&&(s=a)&&(s=a);else{let a=-1;for(let u of t)(u=n(u,++a,t))!=null&&(s=u)&&(s=u)}return s}function yt(t,n){let s;if(n===void 0)for(const a of t)a!=null&&(s>a||s===void 0&&a>=a)&&(s=a);else{let a=-1;for(let u of t)(u=n(u,++a,t))!=null&&(s>u||s===void 0&&u>=u)&&(s=u)}return s}function Z(t,n){let s=0;if(n===void 0)for(let a of t)(a=+a)&&(s+=a);else{let a=-1;for(let u of t)(u=+n(u,++a,t))&&(s+=u)}return s}function Mt(t){return t.target.depth}function Nt(t){return t.depth}function Pt(t,n){return n-1-t.height}function dt(t,n){return t.sourceLinks.length?t.depth:n-1}function Ct(t){return t.targetLinks.length?t.depth:t.sourceLinks.length?yt(t.sourceLinks,Mt)-1:0}function Y(t){return function(){return t}}function lt(t,n){return H(t.source,n.source)||t.index-n.index}function at(t,n){return H(t.target,n.target)||t.index-n.index}function H(t,n){return t.y0-n.y0}function J(t){return t.value}function It(t){return t.index}function $t(t){return t.nodes}function Ot(t){return t.links}function ct(t,n){const s=t.get(n);if(!s)throw new Error("missing: "+n);return s}function ut({nodes:t}){for(const n of t){let s=n.y0,a=s;for(const u of n.sourceLinks)u.y0=s+u.width/2,s+=u.width;for(const u of n.targetLinks)u.y1=a+u.width/2,a+=u.width}}function jt(){let t=0,n=0,s=1,a=1,u=24,_=8,g,p=It,i=dt,o,c,m=$t,b=Ot,y=6;function x(){const e={nodes:m.apply(null,arguments),links:b.apply(null,arguments)};return E(e),L(e),A(e),N(e),S(e),ut(e),e}x.update=function(e){return ut(e),e},x.nodeId=function(e){return arguments.length?(p=typeof e=="function"?e:Y(e),x):p},x.nodeAlign=function(e){return arguments.length?(i=typeof e=="function"?e:Y(e),x):i},x.nodeSort=function(e){return arguments.length?(o=e,x):o},x.nodeWidth=function(e){return arguments.length?(u=+e,x):u},x.nodePadding=function(e){return arguments.length?(_=g=+e,x):_},x.nodes=function(e){return arguments.length?(m=typeof e=="function"?e:Y(e),x):m},x.links=function(e){return arguments.length?(b=typeof e=="function"?e:Y(e),x):b},x.linkSort=function(e){return arguments.length?(c=e,x):c},x.size=function(e){return arguments.length?(t=n=0,s=+e[0],a=+e[1],x):[s-t,a-n]},x.extent=function(e){return arguments.length?(t=+e[0][0],s=+e[1][0],n=+e[0][1],a=+e[1][1],x):[[t,n],[s,a]]},x.iterations=function(e){return arguments.length?(y=+e,x):y};function E({nodes:e,links:f}){for(const[h,r]of e.entries())r.index=h,r.sourceLinks=[],r.targetLinks=[];const l=new Map(e.map((h,r)=>[p(h,r,e),h]));for(const[h,r]of f.entries()){r.index=h;let{source:k,target:v}=r;typeof k!="object"&&(k=r.source=ct(l,k)),typeof v!="object"&&(v=r.target=ct(l,v)),k.sourceLinks.push(r),v.targetLinks.push(r)}if(c!=null)for(const{sourceLinks:h,targetLinks:r}of e)h.sort(c),r.sort(c)}function L({nodes:e}){for(const f of e)f.value=f.fixedValue===void 0?Math.max(Z(f.sourceLinks,J),Z(f.targetLinks,J)):f.fixedValue}function A({nodes:e}){const f=e.length;let l=new Set(e),h=new Set,r=0;for(;l.size;){for(const k of l){k.depth=r;for(const{target:v}of k.sourceLinks)h.add(v)}if(++r>f)throw new Error("circular link");l=h,h=new Set}}function N({nodes:e}){const f=e.length;let l=new Set(e),h=new Set,r=0;for(;l.size;){for(const k of l){k.height=r;for(const{source:v}of k.targetLinks)h.add(v)}if(++r>f)throw new Error("circular link");l=h,h=new Set}}function I({nodes:e}){const f=ot(e,r=>r.depth)+1,l=(s-t-u)/(f-1),h=new Array(f);for(const r of e){const k=Math.max(0,Math.min(f-1,Math.floor(i.call(null,r,f))));r.layer=k,r.x0=t+k*l,r.x1=r.x0+u,h[k]?h[k].push(r):h[k]=[r]}if(o)for(const r of h)r.sort(o);return h}function j(e){const f=yt(e,l=>(a-n-(l.length-1)*g)/Z(l,J));for(const l of e){let h=n;for(const r of l){r.y0=h,r.y1=h+r.value*f,h=r.y1+g;for(const k of r.sourceLinks)k.width=k.value*f}h=(a-h+g)/(l.length+1);for(let r=0;rl.length)-1)),j(f);for(let l=0;l0))continue;let U=(R/z-v.y0)*f;v.y0+=U,v.y1+=U,w(v)}o===void 0&&k.sort(H),P(k,l)}}function O(e,f,l){for(let h=e.length,r=h-2;r>=0;--r){const k=e[r];for(const v of k){let R=0,z=0;for(const{target:W,value:K}of v.sourceLinks){let F=K*(W.layer-v.layer);R+=V(v,W)*F,z+=F}if(!(z>0))continue;let U=(R/z-v.y0)*f;v.y0+=U,v.y1+=U,w(v)}o===void 0&&k.sort(H),P(k,l)}}function P(e,f){const l=e.length>>1,h=e[l];d(e,h.y0-g,l-1,f),C(e,h.y1+g,l+1,f),d(e,a,e.length-1,f),C(e,n,0,f)}function C(e,f,l,h){for(;l1e-6&&(r.y0+=k,r.y1+=k),f=r.y1+g}}function d(e,f,l,h){for(;l>=0;--l){const r=e[l],k=(r.y1-f)*h;k>1e-6&&(r.y0-=k,r.y1-=k),f=r.y0-g}}function w({sourceLinks:e,targetLinks:f}){if(c===void 0){for(const{source:{sourceLinks:l}}of f)l.sort(at);for(const{target:{targetLinks:l}}of e)l.sort(lt)}}function $(e){if(c===void 0)for(const{sourceLinks:f,targetLinks:l}of e)f.sort(at),l.sort(lt)}function T(e,f){let l=e.y0-(e.sourceLinks.length-1)*g/2;for(const{target:h,width:r}of e.sourceLinks){if(h===f)break;l+=r+g}for(const{source:h,width:r}of f.targetLinks){if(h===e)break;l-=r}return l}function V(e,f){let l=f.y0-(f.targetLinks.length-1)*g/2;for(const{source:h,width:r}of f.targetLinks){if(h===e)break;l+=r+g}for(const{target:h,width:r}of e.sourceLinks){if(h===f)break;l-=r}return l}return x}var tt=Math.PI,et=2*tt,D=1e-6,zt=et-D;function nt(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function gt(){return new nt}nt.prototype=gt.prototype={constructor:nt,moveTo:function(t,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,n){this._+="L"+(this._x1=+t)+","+(this._y1=+n)},quadraticCurveTo:function(t,n,s,a){this._+="Q"+ +t+","+ +n+","+(this._x1=+s)+","+(this._y1=+a)},bezierCurveTo:function(t,n,s,a,u,_){this._+="C"+ +t+","+ +n+","+ +s+","+ +a+","+(this._x1=+u)+","+(this._y1=+_)},arcTo:function(t,n,s,a,u){t=+t,n=+n,s=+s,a=+a,u=+u;var _=this._x1,g=this._y1,p=s-t,i=a-n,o=_-t,c=g-n,m=o*o+c*c;if(u<0)throw new Error("negative radius: "+u);if(this._x1===null)this._+="M"+(this._x1=t)+","+(this._y1=n);else if(m>D)if(!(Math.abs(c*p-i*o)>D)||!u)this._+="L"+(this._x1=t)+","+(this._y1=n);else{var b=s-_,y=a-g,x=p*p+i*i,E=b*b+y*y,L=Math.sqrt(x),A=Math.sqrt(m),N=u*Math.tan((tt-Math.acos((x+m-E)/(2*L*A)))/2),I=N/A,j=N/L;Math.abs(I-1)>D&&(this._+="L"+(t+I*o)+","+(n+I*c)),this._+="A"+u+","+u+",0,0,"+ +(c*b>o*y)+","+(this._x1=t+j*p)+","+(this._y1=n+j*i)}},arc:function(t,n,s,a,u,_){t=+t,n=+n,s=+s,_=!!_;var g=s*Math.cos(a),p=s*Math.sin(a),i=t+g,o=n+p,c=1^_,m=_?a-u:u-a;if(s<0)throw new Error("negative radius: "+s);this._x1===null?this._+="M"+i+","+o:(Math.abs(this._x1-i)>D||Math.abs(this._y1-o)>D)&&(this._+="L"+i+","+o),s&&(m<0&&(m=m%et+et),m>zt?this._+="A"+s+","+s+",0,1,"+c+","+(t-g)+","+(n-p)+"A"+s+","+s+",0,1,"+c+","+(this._x1=i)+","+(this._y1=o):m>D&&(this._+="A"+s+","+s+",0,"+ +(m>=tt)+","+c+","+(this._x1=t+s*Math.cos(u))+","+(this._y1=n+s*Math.sin(u))))},rect:function(t,n,s,a){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +s+"v"+ +a+"h"+-s+"Z"},toString:function(){return this._}};function ht(t){return function(){return t}}function Dt(t){return t[0]}function Bt(t){return t[1]}var Vt=Array.prototype.slice;function Rt(t){return t.source}function Ut(t){return t.target}function Wt(t){var n=Rt,s=Ut,a=Dt,u=Bt,_=null;function g(){var p,i=Vt.call(arguments),o=n.apply(this,i),c=s.apply(this,i);if(_||(_=p=gt()),t(_,+a.apply(this,(i[0]=o,i)),+u.apply(this,i),+a.apply(this,(i[0]=c,i)),+u.apply(this,i)),p)return _=null,p+""||null}return g.source=function(p){return arguments.length?(n=p,g):n},g.target=function(p){return arguments.length?(s=p,g):s},g.x=function(p){return arguments.length?(a=typeof p=="function"?p:ht(+p),g):a},g.y=function(p){return arguments.length?(u=typeof p=="function"?p:ht(+p),g):u},g.context=function(p){return arguments.length?(_=p??null,g):_},g}function Ft(t,n,s,a,u){t.moveTo(n,s),t.bezierCurveTo(n=(n+a)/2,s,n,u,a,u)}function Gt(){return Wt(Ft)}function Yt(t){return[t.source.x1,t.y0]}function Ht(t){return[t.target.x0,t.y1]}function Xt(){return Gt().source(Yt).target(Ht)}var it=function(){var t=function(p,i,o,c){for(o=o||{},c=p.length;c--;o[p[c]]=i);return o},n=[1,9],s=[1,10],a=[1,5,10,12],u={trace:function(){},yy:{},symbols_:{error:2,start:3,SANKEY:4,NEWLINE:5,csv:6,opt_eof:7,record:8,csv_tail:9,EOF:10,"field[source]":11,COMMA:12,"field[target]":13,"field[value]":14,field:15,escaped:16,non_escaped:17,DQUOTE:18,ESCAPED_TEXT:19,NON_ESCAPED_TEXT:20,$accept:0,$end:1},terminals_:{2:"error",4:"SANKEY",5:"NEWLINE",10:"EOF",11:"field[source]",12:"COMMA",13:"field[target]",14:"field[value]",18:"DQUOTE",19:"ESCAPED_TEXT",20:"NON_ESCAPED_TEXT"},productions_:[0,[3,4],[6,2],[9,2],[9,0],[7,1],[7,0],[8,5],[15,1],[15,1],[16,3],[17,1]],performAction:function(i,o,c,m,b,y,x){var E=y.length-1;switch(b){case 7:const L=m.findOrCreateNode(y[E-4].trim().replaceAll('""','"')),A=m.findOrCreateNode(y[E-2].trim().replaceAll('""','"')),N=parseFloat(y[E].trim());m.addLink(L,A,N);break;case 8:case 9:case 11:this.$=y[E];break;case 10:this.$=y[E-1];break}},table:[{3:1,4:[1,2]},{1:[3]},{5:[1,3]},{6:4,8:5,15:6,16:7,17:8,18:n,20:s},{1:[2,6],7:11,10:[1,12]},t(s,[2,4],{9:13,5:[1,14]}),{12:[1,15]},t(a,[2,8]),t(a,[2,9]),{19:[1,16]},t(a,[2,11]),{1:[2,1]},{1:[2,5]},t(s,[2,2]),{6:17,8:5,15:6,16:7,17:8,18:n,20:s},{15:18,16:7,17:8,18:n,20:s},{18:[1,19]},t(s,[2,3]),{12:[1,20]},t(a,[2,10]),{15:21,16:7,17:8,18:n,20:s},t([1,5,10],[2,7])],defaultActions:{11:[2,1],12:[2,5]},parseError:function(i,o){if(o.recoverable)this.trace(i);else{var c=new Error(i);throw c.hash=o,c}},parse:function(i){var o=this,c=[0],m=[],b=[null],y=[],x=this.table,E="",L=0,A=0,N=2,I=1,j=y.slice.call(arguments,1),S=Object.create(this.lexer),M={yy:{}};for(var O in this.yy)Object.prototype.hasOwnProperty.call(this.yy,O)&&(M.yy[O]=this.yy[O]);S.setInput(i,M.yy),M.yy.lexer=S,M.yy.parser=this,typeof S.yylloc>"u"&&(S.yylloc={});var P=S.yylloc;y.push(P);var C=S.options&&S.options.ranges;typeof M.yy.parseError=="function"?this.parseError=M.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function d(){var v;return v=m.pop()||S.lex()||I,typeof v!="number"&&(v instanceof Array&&(m=v,v=m.pop()),v=o.symbols_[v]||v),v}for(var w,$,T,V,e={},f,l,h,r;;){if($=c[c.length-1],this.defaultActions[$]?T=this.defaultActions[$]:((w===null||typeof w>"u")&&(w=d()),T=x[$]&&x[$][w]),typeof T>"u"||!T.length||!T[0]){var k="";r=[];for(f in x[$])this.terminals_[f]&&f>N&&r.push("'"+this.terminals_[f]+"'");S.showPosition?k="Parse error on line "+(L+1)+`:
                                         `+S.showPosition()+`
                                         Expecting `+r.join(", ")+", got '"+(this.terminals_[w]||w)+"'":k="Parse error on line "+(L+1)+": Unexpected "+(w==I?"end of input":"'"+(this.terminals_[w]||w)+"'"),this.parseError(k,{text:S.match,token:this.terminals_[w]||w,line:S.yylineno,loc:P,expected:r})}if(T[0]instanceof Array&&T.length>1)throw new Error("Parse Error: multiple actions possible at state: "+$+", token: "+w);switch(T[0]){case 1:c.push(w),b.push(S.yytext),y.push(S.yylloc),c.push(T[1]),w=null,A=S.yyleng,E=S.yytext,L=S.yylineno,P=S.yylloc;break;case 2:if(l=this.productions_[T[1]][1],e.$=b[b.length-l],e._$={first_line:y[y.length-(l||1)].first_line,last_line:y[y.length-1].last_line,first_column:y[y.length-(l||1)].first_column,last_column:y[y.length-1].last_column},C&&(e._$.range=[y[y.length-(l||1)].range[0],y[y.length-1].range[1]]),V=this.performAction.apply(e,[E,A,L,M.yy,T[1],b,y].concat(j)),typeof V<"u")return V;l&&(c=c.slice(0,-1*l*2),b=b.slice(0,-1*l),y=y.slice(0,-1*l)),c.push(this.productions_[T[1]][0]),b.push(e.$),y.push(e._$),h=x[c[c.length-2]][c[c.length-1]],c.push(h);break;case 3:return!0}}return!0}},_=function(){var p={EOF:1,parseError:function(o,c){if(this.yy.parser)this.yy.parser.parseError(o,c);else throw new Error(o)},setInput:function(i,o){return this.yy=o||this.yy||{},this._input=i,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var i=this._input[0];this.yytext+=i,this.yyleng++,this.offset++,this.match+=i,this.matched+=i;var o=i.match(/(?:\r\n?|\n).*/g);return o?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),i},unput:function(i){var o=i.length,c=i.split(/(?:\r\n?|\n)/g);this._input=i+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-o),this.offset-=o;var m=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var b=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===m.length?this.yylloc.first_column:0)+m[m.length-c.length].length-c[0].length:this.yylloc.first_column-o},this.options.ranges&&(this.yylloc.range=[b[0],b[0]+this.yyleng-o]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(i){this.unput(this.match.slice(i))},pastInput:function(){var i=this.matched.substr(0,this.matched.length-this.match.length);return(i.length>20?"...":"")+i.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var i=this.match;return i.length<20&&(i+=this._input.substr(0,20-i.length)),(i.substr(0,20)+(i.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var i=this.pastInput(),o=new Array(i.length+1).join("-");return i+this.upcomingInput()+`
                                        diff --git a/assets/sequenceDiagram-6894f283-BOatradp.js b/assets/sequenceDiagram-6894f283-CpWWhZ69.js
                                        similarity index 99%
                                        rename from assets/sequenceDiagram-6894f283-BOatradp.js
                                        rename to assets/sequenceDiagram-6894f283-CpWWhZ69.js
                                        index 4caa61abd1..848b4f692f 100644
                                        --- a/assets/sequenceDiagram-6894f283-BOatradp.js
                                        +++ b/assets/sequenceDiagram-6894f283-CpWWhZ69.js
                                        @@ -1,4 +1,4 @@
                                        -import{g as we,y as ve,x as _e,c as st,s as $t,b as ke,a as Pe,A as Le,l as X,d as At,j as v,e as Ie,h as Lt,i as Ae,z as B,b0 as nt,b1 as wt,m as te,r as ee,a$ as Bt,aN as se,b2 as Ne}from"./mermaid.core-CArNAncI.js";import{d as Se,a as Me,g as Nt,b as zt,c as Re,e as Ce}from"./svgDrawCommon-5e1cfd1d-BWP2bQZS.js";import"./app-5SoadDYS.js";var Yt=function(){var t=function(dt,w,k,L){for(k=k||{},L=dt.length;L--;k[dt[L]]=w);return k},e=[1,2],c=[1,3],s=[1,4],i=[2,4],a=[1,9],o=[1,11],l=[1,13],p=[1,14],r=[1,16],x=[1,17],T=[1,18],u=[1,24],g=[1,25],m=[1,26],_=[1,27],I=[1,28],V=[1,29],S=[1,30],O=[1,31],R=[1,32],q=[1,33],z=[1,34],J=[1,35],$=[1,36],H=[1,37],U=[1,38],F=[1,39],W=[1,41],Z=[1,42],K=[1,43],Q=[1,44],tt=[1,45],N=[1,46],y=[1,4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,47,48,49,50,52,53,54,59,60,61,62,70],P=[4,5,16,50,52,53],j=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,50,52,53,54,59,60,61,62,70],rt=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,49,50,52,53,54,59,60,61,62,70],A=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,48,50,52,53,54,59,60,61,62,70],Gt=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,47,50,52,53,54,59,60,61,62,70],ht=[68,69,70],ot=[1,120],Mt={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,SD:6,document:7,line:8,statement:9,box_section:10,box_line:11,participant_statement:12,create:13,box:14,restOfLine:15,end:16,signal:17,autonumber:18,NUM:19,off:20,activate:21,actor:22,deactivate:23,note_statement:24,links_statement:25,link_statement:26,properties_statement:27,details_statement:28,title:29,legacy_title:30,acc_title:31,acc_title_value:32,acc_descr:33,acc_descr_value:34,acc_descr_multiline_value:35,loop:36,rect:37,opt:38,alt:39,else_sections:40,par:41,par_sections:42,par_over:43,critical:44,option_sections:45,break:46,option:47,and:48,else:49,participant:50,AS:51,participant_actor:52,destroy:53,note:54,placement:55,text2:56,over:57,actor_pair:58,links:59,link:60,properties:61,details:62,spaceList:63,",":64,left_of:65,right_of:66,signaltype:67,"+":68,"-":69,ACTOR:70,SOLID_OPEN_ARROW:71,DOTTED_OPEN_ARROW:72,SOLID_ARROW:73,DOTTED_ARROW:74,SOLID_CROSS:75,DOTTED_CROSS:76,SOLID_POINT:77,DOTTED_POINT:78,TXT:79,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",6:"SD",13:"create",14:"box",15:"restOfLine",16:"end",18:"autonumber",19:"NUM",20:"off",21:"activate",23:"deactivate",29:"title",30:"legacy_title",31:"acc_title",32:"acc_title_value",33:"acc_descr",34:"acc_descr_value",35:"acc_descr_multiline_value",36:"loop",37:"rect",38:"opt",39:"alt",41:"par",43:"par_over",44:"critical",46:"break",47:"option",48:"and",49:"else",50:"participant",51:"AS",52:"participant_actor",53:"destroy",54:"note",57:"over",59:"links",60:"link",61:"properties",62:"details",64:",",65:"left_of",66:"right_of",68:"+",69:"-",70:"ACTOR",71:"SOLID_OPEN_ARROW",72:"DOTTED_OPEN_ARROW",73:"SOLID_ARROW",74:"DOTTED_ARROW",75:"SOLID_CROSS",76:"DOTTED_CROSS",77:"SOLID_POINT",78:"DOTTED_POINT",79:"TXT"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[10,0],[10,2],[11,2],[11,1],[11,1],[9,1],[9,2],[9,4],[9,2],[9,4],[9,3],[9,3],[9,2],[9,3],[9,3],[9,2],[9,2],[9,2],[9,2],[9,2],[9,1],[9,1],[9,2],[9,2],[9,1],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[45,1],[45,4],[42,1],[42,4],[40,1],[40,4],[12,5],[12,3],[12,5],[12,3],[12,3],[24,4],[24,4],[25,3],[26,3],[27,3],[28,3],[63,2],[63,1],[58,3],[58,1],[55,1],[55,1],[17,5],[17,5],[17,4],[22,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[56,1]],performAction:function(w,k,L,b,M,h,Et){var d=h.length-1;switch(M){case 3:return b.apply(h[d]),h[d];case 4:case 9:this.$=[];break;case 5:case 10:h[d-1].push(h[d]),this.$=h[d-1];break;case 6:case 7:case 11:case 12:this.$=h[d];break;case 8:case 13:this.$=[];break;case 15:h[d].type="createParticipant",this.$=h[d];break;case 16:h[d-1].unshift({type:"boxStart",boxData:b.parseBoxData(h[d-2])}),h[d-1].push({type:"boxEnd",boxText:h[d-2]}),this.$=h[d-1];break;case 18:this.$={type:"sequenceIndex",sequenceIndex:Number(h[d-2]),sequenceIndexStep:Number(h[d-1]),sequenceVisible:!0,signalType:b.LINETYPE.AUTONUMBER};break;case 19:this.$={type:"sequenceIndex",sequenceIndex:Number(h[d-1]),sequenceIndexStep:1,sequenceVisible:!0,signalType:b.LINETYPE.AUTONUMBER};break;case 20:this.$={type:"sequenceIndex",sequenceVisible:!1,signalType:b.LINETYPE.AUTONUMBER};break;case 21:this.$={type:"sequenceIndex",sequenceVisible:!0,signalType:b.LINETYPE.AUTONUMBER};break;case 22:this.$={type:"activeStart",signalType:b.LINETYPE.ACTIVE_START,actor:h[d-1]};break;case 23:this.$={type:"activeEnd",signalType:b.LINETYPE.ACTIVE_END,actor:h[d-1]};break;case 29:b.setDiagramTitle(h[d].substring(6)),this.$=h[d].substring(6);break;case 30:b.setDiagramTitle(h[d].substring(7)),this.$=h[d].substring(7);break;case 31:this.$=h[d].trim(),b.setAccTitle(this.$);break;case 32:case 33:this.$=h[d].trim(),b.setAccDescription(this.$);break;case 34:h[d-1].unshift({type:"loopStart",loopText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.LOOP_START}),h[d-1].push({type:"loopEnd",loopText:h[d-2],signalType:b.LINETYPE.LOOP_END}),this.$=h[d-1];break;case 35:h[d-1].unshift({type:"rectStart",color:b.parseMessage(h[d-2]),signalType:b.LINETYPE.RECT_START}),h[d-1].push({type:"rectEnd",color:b.parseMessage(h[d-2]),signalType:b.LINETYPE.RECT_END}),this.$=h[d-1];break;case 36:h[d-1].unshift({type:"optStart",optText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.OPT_START}),h[d-1].push({type:"optEnd",optText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.OPT_END}),this.$=h[d-1];break;case 37:h[d-1].unshift({type:"altStart",altText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.ALT_START}),h[d-1].push({type:"altEnd",signalType:b.LINETYPE.ALT_END}),this.$=h[d-1];break;case 38:h[d-1].unshift({type:"parStart",parText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.PAR_START}),h[d-1].push({type:"parEnd",signalType:b.LINETYPE.PAR_END}),this.$=h[d-1];break;case 39:h[d-1].unshift({type:"parStart",parText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.PAR_OVER_START}),h[d-1].push({type:"parEnd",signalType:b.LINETYPE.PAR_END}),this.$=h[d-1];break;case 40:h[d-1].unshift({type:"criticalStart",criticalText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.CRITICAL_START}),h[d-1].push({type:"criticalEnd",signalType:b.LINETYPE.CRITICAL_END}),this.$=h[d-1];break;case 41:h[d-1].unshift({type:"breakStart",breakText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.BREAK_START}),h[d-1].push({type:"breakEnd",optText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.BREAK_END}),this.$=h[d-1];break;case 43:this.$=h[d-3].concat([{type:"option",optionText:b.parseMessage(h[d-1]),signalType:b.LINETYPE.CRITICAL_OPTION},h[d]]);break;case 45:this.$=h[d-3].concat([{type:"and",parText:b.parseMessage(h[d-1]),signalType:b.LINETYPE.PAR_AND},h[d]]);break;case 47:this.$=h[d-3].concat([{type:"else",altText:b.parseMessage(h[d-1]),signalType:b.LINETYPE.ALT_ELSE},h[d]]);break;case 48:h[d-3].draw="participant",h[d-3].type="addParticipant",h[d-3].description=b.parseMessage(h[d-1]),this.$=h[d-3];break;case 49:h[d-1].draw="participant",h[d-1].type="addParticipant",this.$=h[d-1];break;case 50:h[d-3].draw="actor",h[d-3].type="addParticipant",h[d-3].description=b.parseMessage(h[d-1]),this.$=h[d-3];break;case 51:h[d-1].draw="actor",h[d-1].type="addParticipant",this.$=h[d-1];break;case 52:h[d-1].type="destroyParticipant",this.$=h[d-1];break;case 53:this.$=[h[d-1],{type:"addNote",placement:h[d-2],actor:h[d-1].actor,text:h[d]}];break;case 54:h[d-2]=[].concat(h[d-1],h[d-1]).slice(0,2),h[d-2][0]=h[d-2][0].actor,h[d-2][1]=h[d-2][1].actor,this.$=[h[d-1],{type:"addNote",placement:b.PLACEMENT.OVER,actor:h[d-2].slice(0,2),text:h[d]}];break;case 55:this.$=[h[d-1],{type:"addLinks",actor:h[d-1].actor,text:h[d]}];break;case 56:this.$=[h[d-1],{type:"addALink",actor:h[d-1].actor,text:h[d]}];break;case 57:this.$=[h[d-1],{type:"addProperties",actor:h[d-1].actor,text:h[d]}];break;case 58:this.$=[h[d-1],{type:"addDetails",actor:h[d-1].actor,text:h[d]}];break;case 61:this.$=[h[d-2],h[d]];break;case 62:this.$=h[d];break;case 63:this.$=b.PLACEMENT.LEFTOF;break;case 64:this.$=b.PLACEMENT.RIGHTOF;break;case 65:this.$=[h[d-4],h[d-1],{type:"addMessage",from:h[d-4].actor,to:h[d-1].actor,signalType:h[d-3],msg:h[d],activate:!0},{type:"activeStart",signalType:b.LINETYPE.ACTIVE_START,actor:h[d-1]}];break;case 66:this.$=[h[d-4],h[d-1],{type:"addMessage",from:h[d-4].actor,to:h[d-1].actor,signalType:h[d-3],msg:h[d]},{type:"activeEnd",signalType:b.LINETYPE.ACTIVE_END,actor:h[d-4]}];break;case 67:this.$=[h[d-3],h[d-1],{type:"addMessage",from:h[d-3].actor,to:h[d-1].actor,signalType:h[d-2],msg:h[d]}];break;case 68:this.$={type:"addParticipant",actor:h[d]};break;case 69:this.$=b.LINETYPE.SOLID_OPEN;break;case 70:this.$=b.LINETYPE.DOTTED_OPEN;break;case 71:this.$=b.LINETYPE.SOLID;break;case 72:this.$=b.LINETYPE.DOTTED;break;case 73:this.$=b.LINETYPE.SOLID_CROSS;break;case 74:this.$=b.LINETYPE.DOTTED_CROSS;break;case 75:this.$=b.LINETYPE.SOLID_POINT;break;case 76:this.$=b.LINETYPE.DOTTED_POINT;break;case 77:this.$=b.parseMessage(h[d].trim().substring(1));break}},table:[{3:1,4:e,5:c,6:s},{1:[3]},{3:5,4:e,5:c,6:s},{3:6,4:e,5:c,6:s},t([1,4,5,13,14,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,50,52,53,54,59,60,61,62,70],i,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:a,5:o,8:8,9:10,12:12,13:l,14:p,17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},t(y,[2,5]),{9:47,12:12,13:l,14:p,17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},t(y,[2,7]),t(y,[2,8]),t(y,[2,14]),{12:48,50:H,52:U,53:F},{15:[1,49]},{5:[1,50]},{5:[1,53],19:[1,51],20:[1,52]},{22:54,70:N},{22:55,70:N},{5:[1,56]},{5:[1,57]},{5:[1,58]},{5:[1,59]},{5:[1,60]},t(y,[2,29]),t(y,[2,30]),{32:[1,61]},{34:[1,62]},t(y,[2,33]),{15:[1,63]},{15:[1,64]},{15:[1,65]},{15:[1,66]},{15:[1,67]},{15:[1,68]},{15:[1,69]},{15:[1,70]},{22:71,70:N},{22:72,70:N},{22:73,70:N},{67:74,71:[1,75],72:[1,76],73:[1,77],74:[1,78],75:[1,79],76:[1,80],77:[1,81],78:[1,82]},{55:83,57:[1,84],65:[1,85],66:[1,86]},{22:87,70:N},{22:88,70:N},{22:89,70:N},{22:90,70:N},t([5,51,64,71,72,73,74,75,76,77,78,79],[2,68]),t(y,[2,6]),t(y,[2,15]),t(P,[2,9],{10:91}),t(y,[2,17]),{5:[1,93],19:[1,92]},{5:[1,94]},t(y,[2,21]),{5:[1,95]},{5:[1,96]},t(y,[2,24]),t(y,[2,25]),t(y,[2,26]),t(y,[2,27]),t(y,[2,28]),t(y,[2,31]),t(y,[2,32]),t(j,i,{7:97}),t(j,i,{7:98}),t(j,i,{7:99}),t(rt,i,{40:100,7:101}),t(A,i,{42:102,7:103}),t(A,i,{7:103,42:104}),t(Gt,i,{45:105,7:106}),t(j,i,{7:107}),{5:[1,109],51:[1,108]},{5:[1,111],51:[1,110]},{5:[1,112]},{22:115,68:[1,113],69:[1,114],70:N},t(ht,[2,69]),t(ht,[2,70]),t(ht,[2,71]),t(ht,[2,72]),t(ht,[2,73]),t(ht,[2,74]),t(ht,[2,75]),t(ht,[2,76]),{22:116,70:N},{22:118,58:117,70:N},{70:[2,63]},{70:[2,64]},{56:119,79:ot},{56:121,79:ot},{56:122,79:ot},{56:123,79:ot},{4:[1,126],5:[1,128],11:125,12:127,16:[1,124],50:H,52:U,53:F},{5:[1,129]},t(y,[2,19]),t(y,[2,20]),t(y,[2,22]),t(y,[2,23]),{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,130],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,131],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,132],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{16:[1,133]},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[2,46],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,49:[1,134],50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{16:[1,135]},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[2,44],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,48:[1,136],50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{16:[1,137]},{16:[1,138]},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[2,42],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,47:[1,139],50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,140],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{15:[1,141]},t(y,[2,49]),{15:[1,142]},t(y,[2,51]),t(y,[2,52]),{22:143,70:N},{22:144,70:N},{56:145,79:ot},{56:146,79:ot},{56:147,79:ot},{64:[1,148],79:[2,62]},{5:[2,55]},{5:[2,77]},{5:[2,56]},{5:[2,57]},{5:[2,58]},t(y,[2,16]),t(P,[2,10]),{12:149,50:H,52:U,53:F},t(P,[2,12]),t(P,[2,13]),t(y,[2,18]),t(y,[2,34]),t(y,[2,35]),t(y,[2,36]),t(y,[2,37]),{15:[1,150]},t(y,[2,38]),{15:[1,151]},t(y,[2,39]),t(y,[2,40]),{15:[1,152]},t(y,[2,41]),{5:[1,153]},{5:[1,154]},{56:155,79:ot},{56:156,79:ot},{5:[2,67]},{5:[2,53]},{5:[2,54]},{22:157,70:N},t(P,[2,11]),t(rt,i,{7:101,40:158}),t(A,i,{7:103,42:159}),t(Gt,i,{7:106,45:160}),t(y,[2,48]),t(y,[2,50]),{5:[2,65]},{5:[2,66]},{79:[2,61]},{16:[2,47]},{16:[2,45]},{16:[2,43]}],defaultActions:{5:[2,1],6:[2,2],85:[2,63],86:[2,64],119:[2,55],120:[2,77],121:[2,56],122:[2,57],123:[2,58],145:[2,67],146:[2,53],147:[2,54],155:[2,65],156:[2,66],157:[2,61],158:[2,47],159:[2,45],160:[2,43]},parseError:function(w,k){if(k.recoverable)this.trace(w);else{var L=new Error(w);throw L.hash=k,L}},parse:function(w){var k=this,L=[0],b=[],M=[null],h=[],Et=this.table,d="",_t=0,Xt=0,Te=2,Jt=1,be=h.slice.call(arguments,1),Y=Object.create(this.lexer),pt={yy:{}};for(var Ct in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Ct)&&(pt.yy[Ct]=this.yy[Ct]);Y.setInput(w,pt.yy),pt.yy.lexer=Y,pt.yy.parser=this,typeof Y.yylloc>"u"&&(Y.yylloc={});var Dt=Y.yylloc;h.push(Dt);var Ee=Y.options&&Y.options.ranges;typeof pt.yy.parseError=="function"?this.parseError=pt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function me(){var lt;return lt=b.pop()||Y.lex()||Jt,typeof lt!="number"&&(lt instanceof Array&&(b=lt,lt=b.pop()),lt=k.symbols_[lt]||lt),lt}for(var G,ut,et,Vt,yt={},kt,ct,Zt,Pt;;){if(ut=L[L.length-1],this.defaultActions[ut]?et=this.defaultActions[ut]:((G===null||typeof G>"u")&&(G=me()),et=Et[ut]&&Et[ut][G]),typeof et>"u"||!et.length||!et[0]){var Ot="";Pt=[];for(kt in Et[ut])this.terminals_[kt]&&kt>Te&&Pt.push("'"+this.terminals_[kt]+"'");Y.showPosition?Ot="Parse error on line "+(_t+1)+`:
                                        +import{g as we,y as ve,x as _e,c as st,s as $t,b as ke,a as Pe,A as Le,l as X,d as At,j as v,e as Ie,h as Lt,i as Ae,z as B,b0 as nt,b1 as wt,m as te,r as ee,a$ as Bt,aN as se,b2 as Ne}from"./mermaid.core-Bq0kX0MS.js";import{d as Se,a as Me,g as Nt,b as zt,c as Re,e as Ce}from"./svgDrawCommon-5e1cfd1d-CX_gVtbt.js";import"./app-Bw2NG-QJ.js";var Yt=function(){var t=function(dt,w,k,L){for(k=k||{},L=dt.length;L--;k[dt[L]]=w);return k},e=[1,2],c=[1,3],s=[1,4],i=[2,4],a=[1,9],o=[1,11],l=[1,13],p=[1,14],r=[1,16],x=[1,17],T=[1,18],u=[1,24],g=[1,25],m=[1,26],_=[1,27],I=[1,28],V=[1,29],S=[1,30],O=[1,31],R=[1,32],q=[1,33],z=[1,34],J=[1,35],$=[1,36],H=[1,37],U=[1,38],F=[1,39],W=[1,41],Z=[1,42],K=[1,43],Q=[1,44],tt=[1,45],N=[1,46],y=[1,4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,47,48,49,50,52,53,54,59,60,61,62,70],P=[4,5,16,50,52,53],j=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,50,52,53,54,59,60,61,62,70],rt=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,49,50,52,53,54,59,60,61,62,70],A=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,48,50,52,53,54,59,60,61,62,70],Gt=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,47,50,52,53,54,59,60,61,62,70],ht=[68,69,70],ot=[1,120],Mt={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,SD:6,document:7,line:8,statement:9,box_section:10,box_line:11,participant_statement:12,create:13,box:14,restOfLine:15,end:16,signal:17,autonumber:18,NUM:19,off:20,activate:21,actor:22,deactivate:23,note_statement:24,links_statement:25,link_statement:26,properties_statement:27,details_statement:28,title:29,legacy_title:30,acc_title:31,acc_title_value:32,acc_descr:33,acc_descr_value:34,acc_descr_multiline_value:35,loop:36,rect:37,opt:38,alt:39,else_sections:40,par:41,par_sections:42,par_over:43,critical:44,option_sections:45,break:46,option:47,and:48,else:49,participant:50,AS:51,participant_actor:52,destroy:53,note:54,placement:55,text2:56,over:57,actor_pair:58,links:59,link:60,properties:61,details:62,spaceList:63,",":64,left_of:65,right_of:66,signaltype:67,"+":68,"-":69,ACTOR:70,SOLID_OPEN_ARROW:71,DOTTED_OPEN_ARROW:72,SOLID_ARROW:73,DOTTED_ARROW:74,SOLID_CROSS:75,DOTTED_CROSS:76,SOLID_POINT:77,DOTTED_POINT:78,TXT:79,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",6:"SD",13:"create",14:"box",15:"restOfLine",16:"end",18:"autonumber",19:"NUM",20:"off",21:"activate",23:"deactivate",29:"title",30:"legacy_title",31:"acc_title",32:"acc_title_value",33:"acc_descr",34:"acc_descr_value",35:"acc_descr_multiline_value",36:"loop",37:"rect",38:"opt",39:"alt",41:"par",43:"par_over",44:"critical",46:"break",47:"option",48:"and",49:"else",50:"participant",51:"AS",52:"participant_actor",53:"destroy",54:"note",57:"over",59:"links",60:"link",61:"properties",62:"details",64:",",65:"left_of",66:"right_of",68:"+",69:"-",70:"ACTOR",71:"SOLID_OPEN_ARROW",72:"DOTTED_OPEN_ARROW",73:"SOLID_ARROW",74:"DOTTED_ARROW",75:"SOLID_CROSS",76:"DOTTED_CROSS",77:"SOLID_POINT",78:"DOTTED_POINT",79:"TXT"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[10,0],[10,2],[11,2],[11,1],[11,1],[9,1],[9,2],[9,4],[9,2],[9,4],[9,3],[9,3],[9,2],[9,3],[9,3],[9,2],[9,2],[9,2],[9,2],[9,2],[9,1],[9,1],[9,2],[9,2],[9,1],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[45,1],[45,4],[42,1],[42,4],[40,1],[40,4],[12,5],[12,3],[12,5],[12,3],[12,3],[24,4],[24,4],[25,3],[26,3],[27,3],[28,3],[63,2],[63,1],[58,3],[58,1],[55,1],[55,1],[17,5],[17,5],[17,4],[22,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[56,1]],performAction:function(w,k,L,b,M,h,Et){var d=h.length-1;switch(M){case 3:return b.apply(h[d]),h[d];case 4:case 9:this.$=[];break;case 5:case 10:h[d-1].push(h[d]),this.$=h[d-1];break;case 6:case 7:case 11:case 12:this.$=h[d];break;case 8:case 13:this.$=[];break;case 15:h[d].type="createParticipant",this.$=h[d];break;case 16:h[d-1].unshift({type:"boxStart",boxData:b.parseBoxData(h[d-2])}),h[d-1].push({type:"boxEnd",boxText:h[d-2]}),this.$=h[d-1];break;case 18:this.$={type:"sequenceIndex",sequenceIndex:Number(h[d-2]),sequenceIndexStep:Number(h[d-1]),sequenceVisible:!0,signalType:b.LINETYPE.AUTONUMBER};break;case 19:this.$={type:"sequenceIndex",sequenceIndex:Number(h[d-1]),sequenceIndexStep:1,sequenceVisible:!0,signalType:b.LINETYPE.AUTONUMBER};break;case 20:this.$={type:"sequenceIndex",sequenceVisible:!1,signalType:b.LINETYPE.AUTONUMBER};break;case 21:this.$={type:"sequenceIndex",sequenceVisible:!0,signalType:b.LINETYPE.AUTONUMBER};break;case 22:this.$={type:"activeStart",signalType:b.LINETYPE.ACTIVE_START,actor:h[d-1]};break;case 23:this.$={type:"activeEnd",signalType:b.LINETYPE.ACTIVE_END,actor:h[d-1]};break;case 29:b.setDiagramTitle(h[d].substring(6)),this.$=h[d].substring(6);break;case 30:b.setDiagramTitle(h[d].substring(7)),this.$=h[d].substring(7);break;case 31:this.$=h[d].trim(),b.setAccTitle(this.$);break;case 32:case 33:this.$=h[d].trim(),b.setAccDescription(this.$);break;case 34:h[d-1].unshift({type:"loopStart",loopText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.LOOP_START}),h[d-1].push({type:"loopEnd",loopText:h[d-2],signalType:b.LINETYPE.LOOP_END}),this.$=h[d-1];break;case 35:h[d-1].unshift({type:"rectStart",color:b.parseMessage(h[d-2]),signalType:b.LINETYPE.RECT_START}),h[d-1].push({type:"rectEnd",color:b.parseMessage(h[d-2]),signalType:b.LINETYPE.RECT_END}),this.$=h[d-1];break;case 36:h[d-1].unshift({type:"optStart",optText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.OPT_START}),h[d-1].push({type:"optEnd",optText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.OPT_END}),this.$=h[d-1];break;case 37:h[d-1].unshift({type:"altStart",altText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.ALT_START}),h[d-1].push({type:"altEnd",signalType:b.LINETYPE.ALT_END}),this.$=h[d-1];break;case 38:h[d-1].unshift({type:"parStart",parText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.PAR_START}),h[d-1].push({type:"parEnd",signalType:b.LINETYPE.PAR_END}),this.$=h[d-1];break;case 39:h[d-1].unshift({type:"parStart",parText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.PAR_OVER_START}),h[d-1].push({type:"parEnd",signalType:b.LINETYPE.PAR_END}),this.$=h[d-1];break;case 40:h[d-1].unshift({type:"criticalStart",criticalText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.CRITICAL_START}),h[d-1].push({type:"criticalEnd",signalType:b.LINETYPE.CRITICAL_END}),this.$=h[d-1];break;case 41:h[d-1].unshift({type:"breakStart",breakText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.BREAK_START}),h[d-1].push({type:"breakEnd",optText:b.parseMessage(h[d-2]),signalType:b.LINETYPE.BREAK_END}),this.$=h[d-1];break;case 43:this.$=h[d-3].concat([{type:"option",optionText:b.parseMessage(h[d-1]),signalType:b.LINETYPE.CRITICAL_OPTION},h[d]]);break;case 45:this.$=h[d-3].concat([{type:"and",parText:b.parseMessage(h[d-1]),signalType:b.LINETYPE.PAR_AND},h[d]]);break;case 47:this.$=h[d-3].concat([{type:"else",altText:b.parseMessage(h[d-1]),signalType:b.LINETYPE.ALT_ELSE},h[d]]);break;case 48:h[d-3].draw="participant",h[d-3].type="addParticipant",h[d-3].description=b.parseMessage(h[d-1]),this.$=h[d-3];break;case 49:h[d-1].draw="participant",h[d-1].type="addParticipant",this.$=h[d-1];break;case 50:h[d-3].draw="actor",h[d-3].type="addParticipant",h[d-3].description=b.parseMessage(h[d-1]),this.$=h[d-3];break;case 51:h[d-1].draw="actor",h[d-1].type="addParticipant",this.$=h[d-1];break;case 52:h[d-1].type="destroyParticipant",this.$=h[d-1];break;case 53:this.$=[h[d-1],{type:"addNote",placement:h[d-2],actor:h[d-1].actor,text:h[d]}];break;case 54:h[d-2]=[].concat(h[d-1],h[d-1]).slice(0,2),h[d-2][0]=h[d-2][0].actor,h[d-2][1]=h[d-2][1].actor,this.$=[h[d-1],{type:"addNote",placement:b.PLACEMENT.OVER,actor:h[d-2].slice(0,2),text:h[d]}];break;case 55:this.$=[h[d-1],{type:"addLinks",actor:h[d-1].actor,text:h[d]}];break;case 56:this.$=[h[d-1],{type:"addALink",actor:h[d-1].actor,text:h[d]}];break;case 57:this.$=[h[d-1],{type:"addProperties",actor:h[d-1].actor,text:h[d]}];break;case 58:this.$=[h[d-1],{type:"addDetails",actor:h[d-1].actor,text:h[d]}];break;case 61:this.$=[h[d-2],h[d]];break;case 62:this.$=h[d];break;case 63:this.$=b.PLACEMENT.LEFTOF;break;case 64:this.$=b.PLACEMENT.RIGHTOF;break;case 65:this.$=[h[d-4],h[d-1],{type:"addMessage",from:h[d-4].actor,to:h[d-1].actor,signalType:h[d-3],msg:h[d],activate:!0},{type:"activeStart",signalType:b.LINETYPE.ACTIVE_START,actor:h[d-1]}];break;case 66:this.$=[h[d-4],h[d-1],{type:"addMessage",from:h[d-4].actor,to:h[d-1].actor,signalType:h[d-3],msg:h[d]},{type:"activeEnd",signalType:b.LINETYPE.ACTIVE_END,actor:h[d-4]}];break;case 67:this.$=[h[d-3],h[d-1],{type:"addMessage",from:h[d-3].actor,to:h[d-1].actor,signalType:h[d-2],msg:h[d]}];break;case 68:this.$={type:"addParticipant",actor:h[d]};break;case 69:this.$=b.LINETYPE.SOLID_OPEN;break;case 70:this.$=b.LINETYPE.DOTTED_OPEN;break;case 71:this.$=b.LINETYPE.SOLID;break;case 72:this.$=b.LINETYPE.DOTTED;break;case 73:this.$=b.LINETYPE.SOLID_CROSS;break;case 74:this.$=b.LINETYPE.DOTTED_CROSS;break;case 75:this.$=b.LINETYPE.SOLID_POINT;break;case 76:this.$=b.LINETYPE.DOTTED_POINT;break;case 77:this.$=b.parseMessage(h[d].trim().substring(1));break}},table:[{3:1,4:e,5:c,6:s},{1:[3]},{3:5,4:e,5:c,6:s},{3:6,4:e,5:c,6:s},t([1,4,5,13,14,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,50,52,53,54,59,60,61,62,70],i,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:a,5:o,8:8,9:10,12:12,13:l,14:p,17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},t(y,[2,5]),{9:47,12:12,13:l,14:p,17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},t(y,[2,7]),t(y,[2,8]),t(y,[2,14]),{12:48,50:H,52:U,53:F},{15:[1,49]},{5:[1,50]},{5:[1,53],19:[1,51],20:[1,52]},{22:54,70:N},{22:55,70:N},{5:[1,56]},{5:[1,57]},{5:[1,58]},{5:[1,59]},{5:[1,60]},t(y,[2,29]),t(y,[2,30]),{32:[1,61]},{34:[1,62]},t(y,[2,33]),{15:[1,63]},{15:[1,64]},{15:[1,65]},{15:[1,66]},{15:[1,67]},{15:[1,68]},{15:[1,69]},{15:[1,70]},{22:71,70:N},{22:72,70:N},{22:73,70:N},{67:74,71:[1,75],72:[1,76],73:[1,77],74:[1,78],75:[1,79],76:[1,80],77:[1,81],78:[1,82]},{55:83,57:[1,84],65:[1,85],66:[1,86]},{22:87,70:N},{22:88,70:N},{22:89,70:N},{22:90,70:N},t([5,51,64,71,72,73,74,75,76,77,78,79],[2,68]),t(y,[2,6]),t(y,[2,15]),t(P,[2,9],{10:91}),t(y,[2,17]),{5:[1,93],19:[1,92]},{5:[1,94]},t(y,[2,21]),{5:[1,95]},{5:[1,96]},t(y,[2,24]),t(y,[2,25]),t(y,[2,26]),t(y,[2,27]),t(y,[2,28]),t(y,[2,31]),t(y,[2,32]),t(j,i,{7:97}),t(j,i,{7:98}),t(j,i,{7:99}),t(rt,i,{40:100,7:101}),t(A,i,{42:102,7:103}),t(A,i,{7:103,42:104}),t(Gt,i,{45:105,7:106}),t(j,i,{7:107}),{5:[1,109],51:[1,108]},{5:[1,111],51:[1,110]},{5:[1,112]},{22:115,68:[1,113],69:[1,114],70:N},t(ht,[2,69]),t(ht,[2,70]),t(ht,[2,71]),t(ht,[2,72]),t(ht,[2,73]),t(ht,[2,74]),t(ht,[2,75]),t(ht,[2,76]),{22:116,70:N},{22:118,58:117,70:N},{70:[2,63]},{70:[2,64]},{56:119,79:ot},{56:121,79:ot},{56:122,79:ot},{56:123,79:ot},{4:[1,126],5:[1,128],11:125,12:127,16:[1,124],50:H,52:U,53:F},{5:[1,129]},t(y,[2,19]),t(y,[2,20]),t(y,[2,22]),t(y,[2,23]),{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,130],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,131],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,132],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{16:[1,133]},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[2,46],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,49:[1,134],50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{16:[1,135]},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[2,44],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,48:[1,136],50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{16:[1,137]},{16:[1,138]},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[2,42],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,47:[1,139],50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{4:a,5:o,8:8,9:10,12:12,13:l,14:p,16:[1,140],17:15,18:r,21:x,22:40,23:T,24:19,25:20,26:21,27:22,28:23,29:u,30:g,31:m,33:_,35:I,36:V,37:S,38:O,39:R,41:q,43:z,44:J,46:$,50:H,52:U,53:F,54:W,59:Z,60:K,61:Q,62:tt,70:N},{15:[1,141]},t(y,[2,49]),{15:[1,142]},t(y,[2,51]),t(y,[2,52]),{22:143,70:N},{22:144,70:N},{56:145,79:ot},{56:146,79:ot},{56:147,79:ot},{64:[1,148],79:[2,62]},{5:[2,55]},{5:[2,77]},{5:[2,56]},{5:[2,57]},{5:[2,58]},t(y,[2,16]),t(P,[2,10]),{12:149,50:H,52:U,53:F},t(P,[2,12]),t(P,[2,13]),t(y,[2,18]),t(y,[2,34]),t(y,[2,35]),t(y,[2,36]),t(y,[2,37]),{15:[1,150]},t(y,[2,38]),{15:[1,151]},t(y,[2,39]),t(y,[2,40]),{15:[1,152]},t(y,[2,41]),{5:[1,153]},{5:[1,154]},{56:155,79:ot},{56:156,79:ot},{5:[2,67]},{5:[2,53]},{5:[2,54]},{22:157,70:N},t(P,[2,11]),t(rt,i,{7:101,40:158}),t(A,i,{7:103,42:159}),t(Gt,i,{7:106,45:160}),t(y,[2,48]),t(y,[2,50]),{5:[2,65]},{5:[2,66]},{79:[2,61]},{16:[2,47]},{16:[2,45]},{16:[2,43]}],defaultActions:{5:[2,1],6:[2,2],85:[2,63],86:[2,64],119:[2,55],120:[2,77],121:[2,56],122:[2,57],123:[2,58],145:[2,67],146:[2,53],147:[2,54],155:[2,65],156:[2,66],157:[2,61],158:[2,47],159:[2,45],160:[2,43]},parseError:function(w,k){if(k.recoverable)this.trace(w);else{var L=new Error(w);throw L.hash=k,L}},parse:function(w){var k=this,L=[0],b=[],M=[null],h=[],Et=this.table,d="",_t=0,Xt=0,Te=2,Jt=1,be=h.slice.call(arguments,1),Y=Object.create(this.lexer),pt={yy:{}};for(var Ct in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Ct)&&(pt.yy[Ct]=this.yy[Ct]);Y.setInput(w,pt.yy),pt.yy.lexer=Y,pt.yy.parser=this,typeof Y.yylloc>"u"&&(Y.yylloc={});var Dt=Y.yylloc;h.push(Dt);var Ee=Y.options&&Y.options.ranges;typeof pt.yy.parseError=="function"?this.parseError=pt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function me(){var lt;return lt=b.pop()||Y.lex()||Jt,typeof lt!="number"&&(lt instanceof Array&&(b=lt,lt=b.pop()),lt=k.symbols_[lt]||lt),lt}for(var G,ut,et,Vt,yt={},kt,ct,Zt,Pt;;){if(ut=L[L.length-1],this.defaultActions[ut]?et=this.defaultActions[ut]:((G===null||typeof G>"u")&&(G=me()),et=Et[ut]&&Et[ut][G]),typeof et>"u"||!et.length||!et[0]){var Ot="";Pt=[];for(kt in Et[ut])this.terminals_[kt]&&kt>Te&&Pt.push("'"+this.terminals_[kt]+"'");Y.showPosition?Ot="Parse error on line "+(_t+1)+`:
                                         `+Y.showPosition()+`
                                         Expecting `+Pt.join(", ")+", got '"+(this.terminals_[G]||G)+"'":Ot="Parse error on line "+(_t+1)+": Unexpected "+(G==Jt?"end of input":"'"+(this.terminals_[G]||G)+"'"),this.parseError(Ot,{text:Y.match,token:this.terminals_[G]||G,line:Y.yylineno,loc:Dt,expected:Pt})}if(et[0]instanceof Array&&et.length>1)throw new Error("Parse Error: multiple actions possible at state: "+ut+", token: "+G);switch(et[0]){case 1:L.push(G),M.push(Y.yytext),h.push(Y.yylloc),L.push(et[1]),G=null,Xt=Y.yyleng,d=Y.yytext,_t=Y.yylineno,Dt=Y.yylloc;break;case 2:if(ct=this.productions_[et[1]][1],yt.$=M[M.length-ct],yt._$={first_line:h[h.length-(ct||1)].first_line,last_line:h[h.length-1].last_line,first_column:h[h.length-(ct||1)].first_column,last_column:h[h.length-1].last_column},Ee&&(yt._$.range=[h[h.length-(ct||1)].range[0],h[h.length-1].range[1]]),Vt=this.performAction.apply(yt,[d,Xt,_t,pt.yy,et[1],M,h].concat(be)),typeof Vt<"u")return Vt;ct&&(L=L.slice(0,-1*ct*2),M=M.slice(0,-1*ct),h=h.slice(0,-1*ct)),L.push(this.productions_[et[1]][0]),M.push(yt.$),h.push(yt._$),Zt=Et[L[L.length-2]][L[L.length-1]],L.push(Zt);break;case 3:return!0}}return!0}},ye=function(){var dt={EOF:1,parseError:function(k,L){if(this.yy.parser)this.yy.parser.parseError(k,L);else throw new Error(k)},setInput:function(w,k){return this.yy=k||this.yy||{},this._input=w,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var w=this._input[0];this.yytext+=w,this.yyleng++,this.offset++,this.match+=w,this.matched+=w;var k=w.match(/(?:\r\n?|\n).*/g);return k?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),w},unput:function(w){var k=w.length,L=w.split(/(?:\r\n?|\n)/g);this._input=w+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-k),this.offset-=k;var b=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),L.length-1&&(this.yylineno-=L.length-1);var M=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:L?(L.length===b.length?this.yylloc.first_column:0)+b[b.length-L.length].length-L[0].length:this.yylloc.first_column-k},this.options.ranges&&(this.yylloc.range=[M[0],M[0]+this.yyleng-k]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(w){this.unput(this.match.slice(w))},pastInput:function(){var w=this.matched.substr(0,this.matched.length-this.match.length);return(w.length>20?"...":"")+w.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var w=this.match;return w.length<20&&(w+=this._input.substr(0,20-w.length)),(w.substr(0,20)+(w.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var w=this.pastInput(),k=new Array(w.length+1).join("-");return w+this.upcomingInput()+`
                                        diff --git a/assets/shadowsocks.html-PFxiOWHW.js b/assets/shadowsocks.html-6NbUGUcS.js
                                        similarity index 99%
                                        rename from assets/shadowsocks.html-PFxiOWHW.js
                                        rename to assets/shadowsocks.html-6NbUGUcS.js
                                        index a6dcfe144a..6457865914 100644
                                        --- a/assets/shadowsocks.html-PFxiOWHW.js
                                        +++ b/assets/shadowsocks.html-6NbUGUcS.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as o,o as c,c as d,a as n,b as e,d as s,w as p,e as l}from"./app-5SoadDYS.js";const u={},h=e("h1",{id:"shadowsocks",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#shadowsocks"},[e("span",null,"Shadowsocks")])],-1),k={href:"https://en.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},m=l("

                                        Here are the features and compatibility of Shadowsocks:

                                        • It supports TCP and UDP packet forwarding, with the option to disable UDP.
                                        • Recommended encryption methods:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Other encryption methods:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 (also known as chacha20-ietf-poly1305)
                                          • none or plain

                                        The new protocol format of Shadowsocks 2022 improves performance and includes full replay protection, addressing security issues present in the old protocol:

                                        ",3),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},v=e("li",null,"Increasing false-positive rate of TCP replay filters over time",-1),q=e("li",null,"Lack of replay protection for UDP",-1),g=e("li",null,"TCP behaviors that can be used for active probing",-1),y=l(`

                                        Danger

                                        Using the "none" encryption method will transmit traffic in plaintext. It is not recommended to use "none" encryption on public networks to ensure security.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as i,r as o,o as c,c as d,a as n,b as e,d as s,w as p,e as l}from"./app-Bw2NG-QJ.js";const u={},h=e("h1",{id:"shadowsocks",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#shadowsocks"},[e("span",null,"Shadowsocks")])],-1),k={href:"https://en.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},m=l("

                                        Here are the features and compatibility of Shadowsocks:

                                        • It supports TCP and UDP packet forwarding, with the option to disable UDP.
                                        • Recommended encryption methods:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Other encryption methods:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 (also known as chacha20-ietf-poly1305)
                                          • none or plain

                                        The new protocol format of Shadowsocks 2022 improves performance and includes full replay protection, addressing security issues present in the old protocol:

                                        ",3),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},v=e("li",null,"Increasing false-positive rate of TCP replay filters over time",-1),q=e("li",null,"Lack of replay protection for UDP",-1),g=e("li",null,"TCP behaviors that can be used for active probing",-1),y=l(`

                                        Danger

                                        Using the "none" encryption method will transmit traffic in plaintext. It is not recommended to use "none" encryption on public networks to ensure security.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "email": "love@xray.com",
                                        diff --git a/assets/shadowsocks.html-BQWMkmYl.js b/assets/shadowsocks.html-CO6uYWSO.js
                                        similarity index 99%
                                        rename from assets/shadowsocks.html-BQWMkmYl.js
                                        rename to assets/shadowsocks.html-CO6uYWSO.js
                                        index e2f35559cc..79c021544f 100644
                                        --- a/assets/shadowsocks.html-BQWMkmYl.js
                                        +++ b/assets/shadowsocks.html-CO6uYWSO.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as a,o as i,c as u,a as o,b as s,d as n,w as p,e as l}from"./app-5SoadDYS.js";const d={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),b={href:"https://zh.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},v=l("

                                        目前兼容性如下:

                                        • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
                                        • 推荐的加密方式:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • 其他加密方式
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 或称 chacha20-ietf-poly1305
                                          • xchacha20-poly1305 或称 xchacha20-ietf-poly1305
                                          • none 或 plain

                                        Shadowsocks 2022 新协议格式提升了性能并带有完整的重放保护,解决了旧协议的以下安全问题:

                                        ",3),h={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},q=s("li",null,"原有 TCP 重放过滤器误报率随时间增加",-1),m=s("li",null,"没有 UDP 重放保护",-1),g=s("li",null,"可用于主动探测的 TCP 行为",-1),_=l(`

                                        警告

                                        "none" 不加密方式下流量将明文传输。为确保安全性, 不要在公共网络上使用。

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as r,r as a,o as i,c as u,a as o,b as s,d as n,w as p,e as l}from"./app-Bw2NG-QJ.js";const d={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),b={href:"https://zh.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},v=l("

                                        目前兼容性如下:

                                        • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
                                        • 推荐的加密方式:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • 其他加密方式
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 或称 chacha20-ietf-poly1305
                                          • xchacha20-poly1305 或称 xchacha20-ietf-poly1305
                                          • none 或 plain

                                        Shadowsocks 2022 新协议格式提升了性能并带有完整的重放保护,解决了旧协议的以下安全问题:

                                        ",3),h={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},q=s("li",null,"原有 TCP 重放过滤器误报率随时间增加",-1),m=s("li",null,"没有 UDP 重放保护",-1),g=s("li",null,"可用于主动探测的 TCP 行为",-1),_=l(`

                                        警告

                                        "none" 不加密方式下流量将明文传输。为确保安全性, 不要在公共网络上使用。

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "email": "love@xray.com",
                                        diff --git a/assets/shadowsocks.html-BRNfQWR7.js b/assets/shadowsocks.html-CvgM8qZ3.js
                                        similarity index 99%
                                        rename from assets/shadowsocks.html-BRNfQWR7.js
                                        rename to assets/shadowsocks.html-CvgM8qZ3.js
                                        index 7982681d6a..d5103ad2b9 100644
                                        --- a/assets/shadowsocks.html-BRNfQWR7.js
                                        +++ b/assets/shadowsocks.html-CvgM8qZ3.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as u,c as d,a as o,b as s,d as n,w as p,e as a}from"./app-5SoadDYS.js";const r={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),h={href:"https://zh.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},q=a("

                                        目前兼容性如下:

                                        • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
                                        • 推荐的加密方式:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • 其他加密方式
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 或称 chacha20-ietf-poly1305
                                          • xchacha20-poly1305 或称 xchacha20-ietf-poly1305
                                          • none 或 plain

                                        Shadowsocks 2022 新协议格式提升了性能并带有完整的重放保护,解决了旧协议的以下安全问题:

                                        ",3),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},m=s("li",null,"原有 TCP 重放过滤器误报率随时间增加",-1),v=s("li",null,"没有 UDP 重放保护",-1),g=s("li",null,"可用于主动探测的 TCP 行为",-1),_=a(`

                                        警告

                                        "none" 不加密方式下流量将明文传输。为确保安全性, 不要在公共网络上使用。

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as u,c as d,a as o,b as s,d as n,w as p,e as a}from"./app-Bw2NG-QJ.js";const r={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),h={href:"https://zh.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},q=a("

                                        目前兼容性如下:

                                        • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
                                        • 推荐的加密方式:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • 其他加密方式
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 或称 chacha20-ietf-poly1305
                                          • xchacha20-poly1305 或称 xchacha20-ietf-poly1305
                                          • none 或 plain

                                        Shadowsocks 2022 新协议格式提升了性能并带有完整的重放保护,解决了旧协议的以下安全问题:

                                        ",3),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},m=s("li",null,"原有 TCP 重放过滤器误报率随时间增加",-1),v=s("li",null,"没有 UDP 重放保护",-1),g=s("li",null,"可用于主动探测的 TCP 行为",-1),_=a(`

                                        警告

                                        "none" 不加密方式下流量将明文传输。为确保安全性, 不要在公共网络上使用。

                                        InboundConfigurationObject

                                        {
                                           "settings": {
                                             "network": "tcp,udp",
                                             "method": "aes-256-gcm",
                                        diff --git a/assets/shadowsocks.html-ZD0TQjd7.js b/assets/shadowsocks.html-D1p_O6W-.js
                                        similarity index 99%
                                        rename from assets/shadowsocks.html-ZD0TQjd7.js
                                        rename to assets/shadowsocks.html-D1p_O6W-.js
                                        index b0be70f9f6..2582e69066 100644
                                        --- a/assets/shadowsocks.html-ZD0TQjd7.js
                                        +++ b/assets/shadowsocks.html-D1p_O6W-.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as a,o as i,c as u,a as o,b as s,d as n,w as p,e as l}from"./app-5SoadDYS.js";const d={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),b={href:"https://ru.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},v=l("

                                        Текущая совместимость:

                                        • Поддерживает пересылку пакетов TCP и UDP, при этом UDP можно выборочно отключить;
                                        • Рекомендуемые методы шифрования:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Другие методы шифрования:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 или chacha20-ietf-poly1305
                                          • xchacha20-poly1305 или xchacha20-ietf-poly1305
                                          • none или plain

                                        Новый формат протокола Shadowsocks 2022 повышает производительность и обеспечивает полную защиту от повторов, решая следующие проблемы безопасности старого протокола:

                                        ",3),h={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},q=s("li",null,"Возрастающий коэффициент ложных срабатываний исходного фильтра повторов TCP с течением времени",-1),m=s("li",null,"Отсутствие защиты от повторов UDP",-1),g=s("li",null,"Поведение TCP, которое можно использовать для активного зондирования",-1),_=l(`

                                        Предупреждение

                                        При использовании метода шифрования "none" трафик передается в открытом виде. В целях безопасности не используйте этот метод в общедоступных сетях.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as r,r as a,o as i,c as u,a as o,b as s,d as n,w as p,e as l}from"./app-Bw2NG-QJ.js";const d={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),b={href:"https://ru.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},v=l("

                                        Текущая совместимость:

                                        • Поддерживает пересылку пакетов TCP и UDP, при этом UDP можно выборочно отключить;
                                        • Рекомендуемые методы шифрования:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Другие методы шифрования:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 или chacha20-ietf-poly1305
                                          • xchacha20-poly1305 или xchacha20-ietf-poly1305
                                          • none или plain

                                        Новый формат протокола Shadowsocks 2022 повышает производительность и обеспечивает полную защиту от повторов, решая следующие проблемы безопасности старого протокола:

                                        ",3),h={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},q=s("li",null,"Возрастающий коэффициент ложных срабатываний исходного фильтра повторов TCP с течением времени",-1),m=s("li",null,"Отсутствие защиты от повторов UDP",-1),g=s("li",null,"Поведение TCP, которое можно использовать для активного зондирования",-1),_=l(`

                                        Предупреждение

                                        При использовании метода шифрования "none" трафик передается в открытом виде. В целях безопасности не используйте этот метод в общедоступных сетях.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "email": "love@xray.com",
                                        diff --git a/assets/shadowsocks.html-DAtIli5Q.js b/assets/shadowsocks.html-D9uClIut.js
                                        similarity index 99%
                                        rename from assets/shadowsocks.html-DAtIli5Q.js
                                        rename to assets/shadowsocks.html-D9uClIut.js
                                        index 23b8cadfc6..1af9bc40b9 100644
                                        --- a/assets/shadowsocks.html-DAtIli5Q.js
                                        +++ b/assets/shadowsocks.html-D9uClIut.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as o,o as r,c as d,a as n,b as e,d as s,w as c,e as l}from"./app-5SoadDYS.js";const u={},h=e("h1",{id:"shadowsocks",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#shadowsocks"},[e("span",null,"Shadowsocks")])],-1),k={href:"https://en.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},m=l('

                                        Supported Encryption Methods

                                        The currently supported methods are following:

                                        • Recommended encryption methods:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Other encryption methods:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305/chacha20-ietf-poly1305
                                          • xchacha20-poly1305/xchacha20-ietf-poly1305
                                          • none/plain

                                        The Shadowsocks 2022 new protocol format improves performance and includes complete replay protection, addressing the following security issues in the old protocol:

                                        ',4),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,"Increasing false positive rate of the original TCP replay filter over time",-1),v=e("li",null,"Lack of UDP replay protection",-1),f=e("li",null,"TCP behaviors that can be used for active probing",-1),y=l(`

                                        Danger

                                        Traffic transmitted without encryption using the "none" method will be in plain text. Do not use it on public networks for security reasons.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as p,r as o,o as r,c as d,a as n,b as e,d as s,w as c,e as l}from"./app-Bw2NG-QJ.js";const u={},h=e("h1",{id:"shadowsocks",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#shadowsocks"},[e("span",null,"Shadowsocks")])],-1),k={href:"https://en.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},m=l('

                                        Supported Encryption Methods

                                        The currently supported methods are following:

                                        • Recommended encryption methods:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Other encryption methods:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305/chacha20-ietf-poly1305
                                          • xchacha20-poly1305/xchacha20-ietf-poly1305
                                          • none/plain

                                        The Shadowsocks 2022 new protocol format improves performance and includes complete replay protection, addressing the following security issues in the old protocol:

                                        ',4),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},g=e("li",null,"Increasing false positive rate of the original TCP replay filter over time",-1),v=e("li",null,"Lack of UDP replay protection",-1),f=e("li",null,"TCP behaviors that can be used for active probing",-1),y=l(`

                                        Danger

                                        Traffic transmitted without encryption using the "none" method will be in plain text. Do not use it on public networks for security reasons.

                                        InboundConfigurationObject

                                        {
                                           "settings": {
                                             "clients": [],
                                             "password": "password",
                                        diff --git a/assets/shadowsocks.html-Cdp8fuJA.js b/assets/shadowsocks.html-RjOSr0jT.js
                                        similarity index 99%
                                        rename from assets/shadowsocks.html-Cdp8fuJA.js
                                        rename to assets/shadowsocks.html-RjOSr0jT.js
                                        index 30c7f02ee7..dc668f22a1 100644
                                        --- a/assets/shadowsocks.html-Cdp8fuJA.js
                                        +++ b/assets/shadowsocks.html-RjOSr0jT.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as u,c as d,a as o,b as s,d as n,w as p,e as a}from"./app-5SoadDYS.js";const r={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),q={href:"https://ru.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},h=a("

                                        Текущая совместимость:

                                        • Поддерживает пересылку пакетов TCP и UDP, при этом UDP можно выборочно отключить;
                                        • Рекомендуемые методы шифрования:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Другие методы шифрования:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 или chacha20-ietf-poly1305
                                          • xchacha20-poly1305 или xchacha20-ietf-poly1305
                                          • none или plain

                                        Новый формат протокола Shadowsocks 2022 повышает производительность и обеспечивает полную защиту от повторов, решая следующие проблемы безопасности старого протокола:

                                        ",3),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},m=s("li",null,"Возрастающий коэффициент ложных срабатываний исходного фильтра повторов TCP с течением времени",-1),v=s("li",null,"Отсутствие защиты от повторов UDP",-1),g=s("li",null,"Поведение TCP, которое можно использовать для активного зондирования",-1),_=a(`

                                        Предупреждение

                                        При использовании метода шифрования "none" трафик передается в открытом виде. В целях безопасности не используйте этот метод в общедоступных сетях.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as u,c as d,a as o,b as s,d as n,w as p,e as a}from"./app-Bw2NG-QJ.js";const r={},k=s("h1",{id:"shadowsocks",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#shadowsocks"},[s("span",null,"Shadowsocks")])],-1),q={href:"https://ru.wikipedia.org/wiki/Shadowsocks",target:"_blank",rel:"noopener noreferrer"},h=a("

                                        Текущая совместимость:

                                        • Поддерживает пересылку пакетов TCP и UDP, при этом UDP можно выборочно отключить;
                                        • Рекомендуемые методы шифрования:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • Другие методы шифрования:
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 или chacha20-ietf-poly1305
                                          • xchacha20-poly1305 или xchacha20-ietf-poly1305
                                          • none или plain

                                        Новый формат протокола Shadowsocks 2022 повышает производительность и обеспечивает полную защиту от повторов, решая следующие проблемы безопасности старого протокола:

                                        ",3),b={href:"https://github.com/shadowsocks/shadowsocks-org/issues/183",target:"_blank",rel:"noopener noreferrer"},m=s("li",null,"Возрастающий коэффициент ложных срабатываний исходного фильтра повторов TCP с течением времени",-1),v=s("li",null,"Отсутствие защиты от повторов UDP",-1),g=s("li",null,"Поведение TCP, которое можно использовать для активного зондирования",-1),_=a(`

                                        Предупреждение

                                        При использовании метода шифрования "none" трафик передается в открытом виде. В целях безопасности не используйте этот метод в общедоступных сетях.

                                        InboundConfigurationObject

                                        {
                                           "settings": {
                                             "network": "tcp,udp",
                                             "method": "aes-256-gcm",
                                        diff --git a/assets/socks.html-BVR1MsG-.js b/assets/socks.html-ByoOjVOD.js
                                        similarity index 99%
                                        rename from assets/socks.html-BVR1MsG-.js
                                        rename to assets/socks.html-ByoOjVOD.js
                                        index 15a12ebc4b..afdd764a81 100644
                                        --- a/assets/socks.html-BVR1MsG-.js
                                        +++ b/assets/socks.html-ByoOjVOD.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as a,o as i,c as l,a as e,b as n,d as s,w as o,e as u}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),v={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        Danger

                                        The Socks protocol does not provide encryption for transmission and is not suitable for transmitting data over public networks.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as r,r as a,o as i,c as l,a as e,b as n,d as s,w as o,e as u}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),v={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        Danger

                                        The Socks protocol does not provide encryption for transmission and is not suitable for transmitting data over public networks.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/socks.html-DRrXLc9g.js b/assets/socks.html-CBuC3RpY.js
                                        similarity index 99%
                                        rename from assets/socks.html-DRrXLc9g.js
                                        rename to assets/socks.html-CBuC3RpY.js
                                        index ea92e60f34..e284a2804c 100644
                                        --- a/assets/socks.html-DRrXLc9g.js
                                        +++ b/assets/socks.html-CBuC3RpY.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as e,o as r,c as u,a,b as n,d as s,w as p,e as i}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),v={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},b={href:"https://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4A.protocol",target:"_blank",rel:"noopener noreferrer"},m=i(`

                                        Предупреждение

                                        Протокол Socks не обеспечивает шифрования передачи, поэтому он не подходит для передачи данных через общедоступные сети.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as l,r as e,o as r,c as u,a,b as n,d as s,w as p,e as i}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),v={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},b={href:"https://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4A.protocol",target:"_blank",rel:"noopener noreferrer"},m=i(`

                                        Предупреждение

                                        Протокол Socks не обеспечивает шифрования передачи, поэтому он не подходит для передачи данных через общедоступные сети.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/socks.html-DLTwr0bp.js b/assets/socks.html-D7ljHe8-.js
                                        similarity index 99%
                                        rename from assets/socks.html-DLTwr0bp.js
                                        rename to assets/socks.html-D7ljHe8-.js
                                        index 9769a791c6..5580269a56 100644
                                        --- a/assets/socks.html-DLTwr0bp.js
                                        +++ b/assets/socks.html-D7ljHe8-.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as e,o as r,c as i,a as o,b as n,d as s,w as c,e as p}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),b={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},q={href:"https://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4A.protocol",target:"_blank",rel:"noopener noreferrer"},v=p(`

                                        Предупреждение

                                        Протокол Socks не обеспечивает шифрование передачи данных, поэтому он не подходит для передачи данных через общедоступные сети.

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

                                        InboundConfigurationObject

                                        {
                                        +import{_ as l,r as e,o as r,c as i,a as o,b as n,d as s,w as c,e as p}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),b={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},q={href:"https://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4A.protocol",target:"_blank",rel:"noopener noreferrer"},v=p(`

                                        Предупреждение

                                        Протокол Socks не обеспечивает шифрование передачи данных, поэтому он не подходит для передачи данных через общедоступные сети.

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

                                        InboundConfigurationObject

                                        {
                                           "auth": "noauth",
                                           "accounts": [
                                             {
                                        diff --git a/assets/socks.html-D9s5DGJl.js b/assets/socks.html-DRkc0qRu.js
                                        similarity index 98%
                                        rename from assets/socks.html-D9s5DGJl.js
                                        rename to assets/socks.html-DRkc0qRu.js
                                        index 3f58162c8c..fcaef8322b 100644
                                        --- a/assets/socks.html-D9s5DGJl.js
                                        +++ b/assets/socks.html-DRkc0qRu.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as s,o as u,c as i,a as o,b as n,d as e,w as c,e as p}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"SOCKS")])],-1),h={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},v={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},b=p(`

                                        Danger

                                        The SOCKS protocol does not provide encryption for transport and is not suitable for transmitting data over public networks.

                                        The use of SOCKS inbound is more meaningful in a local area network or local environment, where it can be used to listen for incoming connections and provide local services to other programs.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as r,r as s,o as u,c as i,a as o,b as n,d as e,w as c,e as p}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"SOCKS")])],-1),h={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},v={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},b=p(`

                                        Danger

                                        The SOCKS protocol does not provide encryption for transport and is not suitable for transmitting data over public networks.

                                        The use of SOCKS inbound is more meaningful in a local area network or local environment, where it can be used to listen for incoming connections and provide local services to other programs.

                                        InboundConfigurationObject

                                        {
                                           "auth": "noauth",
                                           "accounts": [
                                             {
                                        diff --git a/assets/socks.html-D9zJ0rmt.js b/assets/socks.html-a5bSQH2X.js
                                        similarity index 98%
                                        rename from assets/socks.html-D9zJ0rmt.js
                                        rename to assets/socks.html-a5bSQH2X.js
                                        index 73e3f408b7..7d7a5f52cc 100644
                                        --- a/assets/socks.html-D9zJ0rmt.js
                                        +++ b/assets/socks.html-a5bSQH2X.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as e,o as r,c as i,a as o,b as n,d as s,w as c,e as p}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),b={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},q={href:"https://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4A.protocol",target:"_blank",rel:"noopener noreferrer"},v=p(`

                                        警告

                                        Socks 协议没有对传输加密,不适宜经公网中传输

                                        Socks 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。

                                        InboundConfigurationObject

                                        {
                                        +import{_ as l,r as e,o as r,c as i,a as o,b as n,d as s,w as c,e as p}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"socks",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#socks"},[n("span",null,"Socks")])],-1),b={href:"http://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4.protocol",target:"_blank",rel:"noopener noreferrer"},q={href:"https://ftp.icm.edu.pl/packages/socks/socks4/SOCKS4A.protocol",target:"_blank",rel:"noopener noreferrer"},v=p(`

                                        警告

                                        Socks 协议没有对传输加密,不适宜经公网中传输

                                        Socks 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。

                                        InboundConfigurationObject

                                        {
                                           "auth": "noauth",
                                           "accounts": [
                                             {
                                        diff --git a/assets/socks.html-CBCl0kQ3.js b/assets/socks.html-vsa94d6J.js
                                        similarity index 99%
                                        rename from assets/socks.html-CBCl0kQ3.js
                                        rename to assets/socks.html-vsa94d6J.js
                                        index a9b7f805c3..bd2b3568cf 100644
                                        --- a/assets/socks.html-CBCl0kQ3.js
                                        +++ b/assets/socks.html-vsa94d6J.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as o,o as l,c as r,a as n,b as a,d as s,w as t,e as u}from"./app-5SoadDYS.js";const i={},d=u(`

                                        Socks

                                        标准 Socks 协议实现,兼容 Socks 5。

                                        警告

                                        Socks 协议没有对传输加密,不适宜经公网中传输

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as c,r as o,o as l,c as r,a as n,b as a,d as s,w as t,e as u}from"./app-Bw2NG-QJ.js";const i={},d=u(`

                                        Socks

                                        标准 Socks 协议实现,兼容 Socks 5。

                                        警告

                                        Socks 协议没有对传输加密,不适宜经公网中传输

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/splithttp.html-Klo-EToo.js b/assets/splithttp.html-6TiHvgAh.js
                                        similarity index 99%
                                        rename from assets/splithttp.html-Klo-EToo.js
                                        rename to assets/splithttp.html-6TiHvgAh.js
                                        index afee3d230c..b7890bef15 100644
                                        --- a/assets/splithttp.html-Klo-EToo.js
                                        +++ b/assets/splithttp.html-6TiHvgAh.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as o,o as d,c as i,a as t,b as e,d as s,w as u,e as a}from"./app-5SoadDYS.js";const h={},T=e("h1",{id:"splithttp-h2、quic-h3",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp-h2、quic-h3"},[e("span",null,"SplitHTTP(H2、QUIC H3)")])],-1),k=a(`

                                        使用HTTP分块传输编码流式响应处理下载,使用多个HTTP POST请求进行上传。

                                        可以通过不支持WebSocket的CDN上,但仍有一些要求:

                                        • CDN必须支持HTTP分块传输,且支持流式响应而不会缓冲,核心将会发送 X-Accel-Buffering: no 以及 Content-Type: text/event-stream 以告知CDN,但是需要CDN遵守此标头。如果中间盒不支持流式响应而导致连接被挂起,则该传输很可能无法工作。

                                        目的与V2fly Meek相同,由于使用了流式响应处理下载,下行速率更为优秀,上行也经过优化但仍非常有限,也因此对 HTTP 中间盒要求更高(见上)。

                                        SplitHTTP 也接受 X-Forwarded-For header。

                                        SplitHttpObject

                                        The SplitHttpObject 对应传输配置的 splithttpSettings 项。

                                        {
                                        +import{_ as r,r as o,o as d,c as i,a as t,b as e,d as s,w as u,e as a}from"./app-Bw2NG-QJ.js";const h={},T=e("h1",{id:"splithttp-h2、quic-h3",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp-h2、quic-h3"},[e("span",null,"SplitHTTP(H2、QUIC H3)")])],-1),k=a(`

                                        使用HTTP分块传输编码流式响应处理下载,使用多个HTTP POST请求进行上传。

                                        可以通过不支持WebSocket的CDN上,但仍有一些要求:

                                        • CDN必须支持HTTP分块传输,且支持流式响应而不会缓冲,核心将会发送 X-Accel-Buffering: no 以及 Content-Type: text/event-stream 以告知CDN,但是需要CDN遵守此标头。如果中间盒不支持流式响应而导致连接被挂起,则该传输很可能无法工作。

                                        目的与V2fly Meek相同,由于使用了流式响应处理下载,下行速率更为优秀,上行也经过优化但仍非常有限,也因此对 HTTP 中间盒要求更高(见上)。

                                        SplitHTTP 也接受 X-Forwarded-For header。

                                        SplitHttpObject

                                        The SplitHttpObject 对应传输配置的 splithttpSettings 项。

                                        {
                                           "path": "/",
                                           "host": "xray.com",
                                           "headers": {
                                        diff --git a/assets/splithttp.html-9SkrgDgl.js b/assets/splithttp.html-AYHmdotS.js
                                        similarity index 99%
                                        rename from assets/splithttp.html-9SkrgDgl.js
                                        rename to assets/splithttp.html-AYHmdotS.js
                                        index 32698ef9cb..bb5d7620b1 100644
                                        --- a/assets/splithttp.html-9SkrgDgl.js
                                        +++ b/assets/splithttp.html-AYHmdotS.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as n,o as d,c as p,a as o,b as e,d as t,w as h,e as r}from"./app-5SoadDYS.js";const u={},b=e("h1",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),m=r(`

                                        Uses HTTP chunked-transfer encoding for download, and multiple HTTP requests for upload.

                                        Can be deployed on CDNs that do not support WebSocket. However, the CDN must support HTTP chunked transfer encoding in a streaming fashion, no response buffering.

                                        This transport serves the same purpose as Meek (support non-WS CDN). It has the above streaming requirement to the CDN so that download can be much faster than (v2fly) Meek, close to WebSocket performance. The upload is also optimized, but still much more limited than WebSocket.

                                        Like WebSocket transport, SplitHTTP parses the X-Forwarded-For header for logging.

                                        SplitHttpObject

                                        The SplitHttpObject corresponds to the splithttpSettings section under transport configurations.

                                        {
                                        +import{_ as l,r as n,o as d,c as p,a as o,b as e,d as t,w as h,e as r}from"./app-Bw2NG-QJ.js";const u={},b=e("h1",{id:"splithttp",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#splithttp"},[e("span",null,"SplitHTTP")])],-1),m=r(`

                                        Uses HTTP chunked-transfer encoding for download, and multiple HTTP requests for upload.

                                        Can be deployed on CDNs that do not support WebSocket. However, the CDN must support HTTP chunked transfer encoding in a streaming fashion, no response buffering.

                                        This transport serves the same purpose as Meek (support non-WS CDN). It has the above streaming requirement to the CDN so that download can be much faster than (v2fly) Meek, close to WebSocket performance. The upload is also optimized, but still much more limited than WebSocket.

                                        Like WebSocket transport, SplitHTTP parses the X-Forwarded-For header for logging.

                                        SplitHttpObject

                                        The SplitHttpObject corresponds to the splithttpSettings section under transport configurations.

                                        {
                                           "path": "/",
                                           "host": "xray.com",
                                           "headers": {
                                        diff --git a/assets/splithttp.html-C_OBv89U.js b/assets/splithttp.html-BazFP1k9.js
                                        similarity index 99%
                                        rename from assets/splithttp.html-C_OBv89U.js
                                        rename to assets/splithttp.html-BazFP1k9.js
                                        index 9522c3f81c..296c1877c2 100644
                                        --- a/assets/splithttp.html-C_OBv89U.js
                                        +++ b/assets/splithttp.html-BazFP1k9.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as n,o as d,c as i,a as t,b as o,d as e,w as u,e as a}from"./app-5SoadDYS.js";const h={},T=o("h1",{id:"splithttp",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#splithttp"},[o("span",null,"SplitHTTP")])],-1),k=a(`

                                        Используется для загрузки с помощью HTTP-фрагментированной передачи, загрузка осуществляется с помощью нескольких HTTP POST-запросов.

                                        Может использоваться через CDN, не поддерживающие WebSocket, но есть несколько требований:

                                        • CDN должен поддерживать HTTP-фрагментированную передачу и потоковые ответы без буферизации. Ядро будет отправлять X-Accel-Buffering: no и Content-Type: text/event-stream, чтобы сообщить CDN об этом, но CDN должен соблюдать этот заголовок. Если промежуточный сервер не поддерживает потоковые ответы и зависает, передача, скорее всего, не будет работать.

                                        Цель та же, что и у V2fly Meek, но благодаря использованию фрагментированной загрузки скорость загрузки выше, а скорость отдачи оптимизирована, но все еще очень ограничена, поэтому к HTTP-прокси предъявляются более высокие требования (см. выше).

                                        SplitHTTP также принимает заголовок X-Forwarded-For.

                                        SplitHttpObject

                                        SplitHttpObject соответствует элементу splithttpSettings в конфигурации транспорта.

                                        {
                                        +import{_ as r,r as n,o as d,c as i,a as t,b as o,d as e,w as u,e as a}from"./app-Bw2NG-QJ.js";const h={},T=o("h1",{id:"splithttp",tabindex:"-1"},[o("a",{class:"header-anchor",href:"#splithttp"},[o("span",null,"SplitHTTP")])],-1),k=a(`

                                        Используется для загрузки с помощью HTTP-фрагментированной передачи, загрузка осуществляется с помощью нескольких HTTP POST-запросов.

                                        Может использоваться через CDN, не поддерживающие WebSocket, но есть несколько требований:

                                        • CDN должен поддерживать HTTP-фрагментированную передачу и потоковые ответы без буферизации. Ядро будет отправлять X-Accel-Buffering: no и Content-Type: text/event-stream, чтобы сообщить CDN об этом, но CDN должен соблюдать этот заголовок. Если промежуточный сервер не поддерживает потоковые ответы и зависает, передача, скорее всего, не будет работать.

                                        Цель та же, что и у V2fly Meek, но благодаря использованию фрагментированной загрузки скорость загрузки выше, а скорость отдачи оптимизирована, но все еще очень ограничена, поэтому к HTTP-прокси предъявляются более высокие требования (см. выше).

                                        SplitHTTP также принимает заголовок X-Forwarded-For.

                                        SplitHttpObject

                                        SplitHttpObject соответствует элементу splithttpSettings в конфигурации транспорта.

                                        {
                                           "path": "/",
                                           "host": "xray.com",
                                           "headers": {
                                        diff --git a/assets/stateDiagram-5dee940d-BYrroPY3.js b/assets/stateDiagram-5dee940d-RM57nRSF.js
                                        similarity index 97%
                                        rename from assets/stateDiagram-5dee940d-BYrroPY3.js
                                        rename to assets/stateDiagram-5dee940d-RM57nRSF.js
                                        index 5db24b6f48..aaeedbcbef 100644
                                        --- a/assets/stateDiagram-5dee940d-BYrroPY3.js
                                        +++ b/assets/stateDiagram-5dee940d-RM57nRSF.js
                                        @@ -1 +1 @@
                                        -import{p as P,d as N,s as W}from"./styles-0784dbeb-C3hL6HKk.js";import{c as t,h as H,l as b,i as R,j as T,ao as v,z as U}from"./mermaid.core-CArNAncI.js";import{G as C}from"./graph-D2qW7eTj.js";import{l as F}from"./layout-BlaWeSu5.js";import{l as $}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const O=e=>e.append("circle").attr("class","start-state").attr("r",t().state.sizeUnit).attr("cx",t().state.padding+t().state.sizeUnit).attr("cy",t().state.padding+t().state.sizeUnit),X=e=>e.append("line").style("stroke","grey").style("stroke-dasharray","3").attr("x1",t().state.textHeight).attr("class","divider").attr("x2",t().state.textHeight*2).attr("y1",0).attr("y2",0),J=(e,i)=>{const o=e.append("text").attr("x",2*t().state.padding).attr("y",t().state.textHeight+2*t().state.padding).attr("font-size",t().state.fontSize).attr("class","state-title").text(i.id),c=o.node().getBBox();return e.insert("rect",":first-child").attr("x",t().state.padding).attr("y",t().state.padding).attr("width",c.width+2*t().state.padding).attr("height",c.height+2*t().state.padding).attr("rx",t().state.radius),o},Y=(e,i)=>{const o=function(l,m,w){const E=l.append("tspan").attr("x",2*t().state.padding).text(m);w||E.attr("dy",t().state.textHeight)},s=e.append("text").attr("x",2*t().state.padding).attr("y",t().state.textHeight+1.3*t().state.padding).attr("font-size",t().state.fontSize).attr("class","state-title").text(i.descriptions[0]).node().getBBox(),g=s.height,p=e.append("text").attr("x",t().state.padding).attr("y",g+t().state.padding*.4+t().state.dividerMargin+t().state.textHeight).attr("class","state-description");let a=!0,r=!0;i.descriptions.forEach(function(l){a||(o(p,l,r),r=!1),a=!1});const y=e.append("line").attr("x1",t().state.padding).attr("y1",t().state.padding+g+t().state.dividerMargin/2).attr("y2",t().state.padding+g+t().state.dividerMargin/2).attr("class","descr-divider"),x=p.node().getBBox(),d=Math.max(x.width,s.width);return y.attr("x2",d+3*t().state.padding),e.insert("rect",":first-child").attr("x",t().state.padding).attr("y",t().state.padding).attr("width",d+2*t().state.padding).attr("height",x.height+g+2*t().state.padding).attr("rx",t().state.radius),e},I=(e,i,o)=>{const c=t().state.padding,s=2*t().state.padding,g=e.node().getBBox(),p=g.width,a=g.x,r=e.append("text").attr("x",0).attr("y",t().state.titleShift).attr("font-size",t().state.fontSize).attr("class","state-title").text(i.id),x=r.node().getBBox().width+s;let d=Math.max(x,p);d===p&&(d=d+s);let l;const m=e.node().getBBox();i.doc,l=a-c,x>p&&(l=(p-d)/2+c),Math.abs(a-m.x)p&&(l=a-(x-p)/2);const w=1-t().state.textHeight;return e.insert("rect",":first-child").attr("x",l).attr("y",w).attr("class",o?"alt-composit":"composit").attr("width",d).attr("height",m.height+t().state.textHeight+t().state.titleShift+1).attr("rx","0"),r.attr("x",l+c),x<=p&&r.attr("x",a+(d-s)/2-x/2+c),e.insert("rect",":first-child").attr("x",l).attr("y",t().state.titleShift-t().state.textHeight-t().state.padding).attr("width",d).attr("height",t().state.textHeight*3).attr("rx",t().state.radius),e.insert("rect",":first-child").attr("x",l).attr("y",t().state.titleShift-t().state.textHeight-t().state.padding).attr("width",d).attr("height",m.height+3+2*t().state.textHeight).attr("rx",t().state.radius),e},_=e=>(e.append("circle").attr("class","end-state-outer").attr("r",t().state.sizeUnit+t().state.miniPadding).attr("cx",t().state.padding+t().state.sizeUnit+t().state.miniPadding).attr("cy",t().state.padding+t().state.sizeUnit+t().state.miniPadding),e.append("circle").attr("class","end-state-inner").attr("r",t().state.sizeUnit).attr("cx",t().state.padding+t().state.sizeUnit+2).attr("cy",t().state.padding+t().state.sizeUnit+2)),q=(e,i)=>{let o=t().state.forkWidth,c=t().state.forkHeight;if(i.parentId){let s=o;o=c,c=s}return e.append("rect").style("stroke","black").style("fill","black").attr("width",o).attr("height",c).attr("x",t().state.padding).attr("y",t().state.padding)},Z=(e,i,o,c)=>{let s=0;const g=c.append("text");g.style("text-anchor","start"),g.attr("class","noteText");let p=e.replace(/\r\n/g,"
                                        ");p=p.replace(/\n/g,"
                                        ");const a=p.split(T.lineBreakRegex);let r=1.25*t().state.noteMargin;for(const y of a){const x=y.trim();if(x.length>0){const d=g.append("tspan");if(d.text(x),r===0){const l=d.node().getBBox();r+=l.height}s+=r,d.attr("x",i+t().state.noteMargin),d.attr("y",o+s+1.25*t().state.noteMargin)}}return{textWidth:g.node().getBBox().width,textHeight:s}},j=(e,i)=>{i.attr("class","state-note");const o=i.append("rect").attr("x",0).attr("y",t().state.padding),c=i.append("g"),{textWidth:s,textHeight:g}=Z(e,0,0,c);return o.attr("height",g+2*t().state.noteMargin),o.attr("width",s+t().state.noteMargin*2),o},L=function(e,i){const o=i.id,c={id:o,label:i.id,width:0,height:0},s=e.append("g").attr("id",o).attr("class","stateGroup");i.type==="start"&&O(s),i.type==="end"&&_(s),(i.type==="fork"||i.type==="join")&&q(s,i),i.type==="note"&&j(i.note.text,s),i.type==="divider"&&X(s),i.type==="default"&&i.descriptions.length===0&&J(s,i),i.type==="default"&&i.descriptions.length>0&&Y(s,i);const g=s.node().getBBox();return c.width=g.width+2*t().state.padding,c.height=g.height+2*t().state.padding,c};let G=0;const K=function(e,i,o){const c=function(r){switch(r){case N.relationType.AGGREGATION:return"aggregation";case N.relationType.EXTENSION:return"extension";case N.relationType.COMPOSITION:return"composition";case N.relationType.DEPENDENCY:return"dependency"}};i.points=i.points.filter(r=>!Number.isNaN(r.y));const s=i.points,g=$().x(function(r){return r.x}).y(function(r){return r.y}).curve(v),p=e.append("path").attr("d",g(s)).attr("id","edge"+G).attr("class","transition");let a="";if(t().state.arrowMarkerAbsolute&&(a=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,a=a.replace(/\(/g,"\\("),a=a.replace(/\)/g,"\\)")),p.attr("marker-end","url("+a+"#"+c(N.relationType.DEPENDENCY)+"End)"),o.title!==void 0){const r=e.append("g").attr("class","stateLabel"),{x:y,y:x}=U.calcLabelPosition(i.points),d=T.getRows(o.title);let l=0;const m=[];let w=0,E=0;for(let u=0;u<=d.length;u++){const h=r.append("text").attr("text-anchor","middle").text(d[u]).attr("x",y).attr("y",x+l),f=h.node().getBBox();w=Math.max(w,f.width),E=Math.min(E,f.x),b.info(f.x,y,x+l),l===0&&(l=h.node().getBBox().height,b.info("Title height",l,x)),m.push(h)}let k=l*d.length;if(d.length>1){const u=(d.length-1)*l*.5;m.forEach((h,f)=>h.attr("y",x+f*l-u)),k=l*d.length}const n=r.node().getBBox();r.insert("rect",":first-child").attr("class","box").attr("x",y-w/2-t().state.padding/2).attr("y",x-k/2-t().state.padding/2-3.5).attr("width",w+t().state.padding).attr("height",k+t().state.padding),b.info(n)}G++};let B;const z={},Q=function(){},V=function(e){e.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")},D=function(e,i,o,c){B=t().state;const s=t().securityLevel;let g;s==="sandbox"&&(g=H("#i"+i));const p=s==="sandbox"?H(g.nodes()[0].contentDocument.body):H("body"),a=s==="sandbox"?g.nodes()[0].contentDocument:document;b.debug("Rendering diagram "+e);const r=p.select(`[id='${i}']`);V(r);const y=c.db.getRootDoc();A(y,r,void 0,!1,p,a,c);const x=B.padding,d=r.node().getBBox(),l=d.width+x*2,m=d.height+x*2,w=l*1.75;R(r,m,w,B.useMaxWidth),r.attr("viewBox",`${d.x-B.padding} ${d.y-B.padding} `+l+" "+m)},tt=e=>e?e.length*B.fontSizeFactor:1,A=(e,i,o,c,s,g,p)=>{const a=new C({compound:!0,multigraph:!0});let r,y=!0;for(r=0;r{const f=h.parentElement;let S=0,M=0;f&&(f.parentElement&&(S=f.parentElement.getBBox().width),M=parseInt(f.getAttribute("data-x-shift"),10),Number.isNaN(M)&&(M=0)),h.setAttribute("x1",0-M+8),h.setAttribute("x2",S-M-8)})):b.debug("No Node "+n+": "+JSON.stringify(a.node(n)))});let E=w.getBBox();a.edges().forEach(function(n){n!==void 0&&a.edge(n)!==void 0&&(b.debug("Edge "+n.v+" -> "+n.w+": "+JSON.stringify(a.edge(n))),K(i,a.edge(n),a.edge(n).relation))}),E=w.getBBox();const k={id:o||"root",label:o||"root",width:0,height:0};return k.width=E.width+2*B.padding,k.height=E.height+2*B.padding,b.debug("Doc rendered",k,a),k},et={setConf:Q,draw:D},lt={parser:P,db:N,renderer:et,styles:W,init:e=>{e.state||(e.state={}),e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute,N.clear()}};export{lt as diagram}; +import{p as P,d as N,s as W}from"./styles-0784dbeb-38-7TehO.js";import{c as t,h as H,l as b,i as R,j as T,ao as v,z as U}from"./mermaid.core-Bq0kX0MS.js";import{G as C}from"./graph-C-EgwjAv.js";import{l as F}from"./layout-DSxgfneE.js";import{l as $}from"./line-DY_oMjHu.js";import"./app-Bw2NG-QJ.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const O=e=>e.append("circle").attr("class","start-state").attr("r",t().state.sizeUnit).attr("cx",t().state.padding+t().state.sizeUnit).attr("cy",t().state.padding+t().state.sizeUnit),X=e=>e.append("line").style("stroke","grey").style("stroke-dasharray","3").attr("x1",t().state.textHeight).attr("class","divider").attr("x2",t().state.textHeight*2).attr("y1",0).attr("y2",0),J=(e,i)=>{const o=e.append("text").attr("x",2*t().state.padding).attr("y",t().state.textHeight+2*t().state.padding).attr("font-size",t().state.fontSize).attr("class","state-title").text(i.id),c=o.node().getBBox();return e.insert("rect",":first-child").attr("x",t().state.padding).attr("y",t().state.padding).attr("width",c.width+2*t().state.padding).attr("height",c.height+2*t().state.padding).attr("rx",t().state.radius),o},Y=(e,i)=>{const o=function(l,m,w){const E=l.append("tspan").attr("x",2*t().state.padding).text(m);w||E.attr("dy",t().state.textHeight)},s=e.append("text").attr("x",2*t().state.padding).attr("y",t().state.textHeight+1.3*t().state.padding).attr("font-size",t().state.fontSize).attr("class","state-title").text(i.descriptions[0]).node().getBBox(),g=s.height,p=e.append("text").attr("x",t().state.padding).attr("y",g+t().state.padding*.4+t().state.dividerMargin+t().state.textHeight).attr("class","state-description");let a=!0,r=!0;i.descriptions.forEach(function(l){a||(o(p,l,r),r=!1),a=!1});const y=e.append("line").attr("x1",t().state.padding).attr("y1",t().state.padding+g+t().state.dividerMargin/2).attr("y2",t().state.padding+g+t().state.dividerMargin/2).attr("class","descr-divider"),x=p.node().getBBox(),d=Math.max(x.width,s.width);return y.attr("x2",d+3*t().state.padding),e.insert("rect",":first-child").attr("x",t().state.padding).attr("y",t().state.padding).attr("width",d+2*t().state.padding).attr("height",x.height+g+2*t().state.padding).attr("rx",t().state.radius),e},I=(e,i,o)=>{const c=t().state.padding,s=2*t().state.padding,g=e.node().getBBox(),p=g.width,a=g.x,r=e.append("text").attr("x",0).attr("y",t().state.titleShift).attr("font-size",t().state.fontSize).attr("class","state-title").text(i.id),x=r.node().getBBox().width+s;let d=Math.max(x,p);d===p&&(d=d+s);let l;const m=e.node().getBBox();i.doc,l=a-c,x>p&&(l=(p-d)/2+c),Math.abs(a-m.x)p&&(l=a-(x-p)/2);const w=1-t().state.textHeight;return e.insert("rect",":first-child").attr("x",l).attr("y",w).attr("class",o?"alt-composit":"composit").attr("width",d).attr("height",m.height+t().state.textHeight+t().state.titleShift+1).attr("rx","0"),r.attr("x",l+c),x<=p&&r.attr("x",a+(d-s)/2-x/2+c),e.insert("rect",":first-child").attr("x",l).attr("y",t().state.titleShift-t().state.textHeight-t().state.padding).attr("width",d).attr("height",t().state.textHeight*3).attr("rx",t().state.radius),e.insert("rect",":first-child").attr("x",l).attr("y",t().state.titleShift-t().state.textHeight-t().state.padding).attr("width",d).attr("height",m.height+3+2*t().state.textHeight).attr("rx",t().state.radius),e},_=e=>(e.append("circle").attr("class","end-state-outer").attr("r",t().state.sizeUnit+t().state.miniPadding).attr("cx",t().state.padding+t().state.sizeUnit+t().state.miniPadding).attr("cy",t().state.padding+t().state.sizeUnit+t().state.miniPadding),e.append("circle").attr("class","end-state-inner").attr("r",t().state.sizeUnit).attr("cx",t().state.padding+t().state.sizeUnit+2).attr("cy",t().state.padding+t().state.sizeUnit+2)),q=(e,i)=>{let o=t().state.forkWidth,c=t().state.forkHeight;if(i.parentId){let s=o;o=c,c=s}return e.append("rect").style("stroke","black").style("fill","black").attr("width",o).attr("height",c).attr("x",t().state.padding).attr("y",t().state.padding)},Z=(e,i,o,c)=>{let s=0;const g=c.append("text");g.style("text-anchor","start"),g.attr("class","noteText");let p=e.replace(/\r\n/g,"
                                        ");p=p.replace(/\n/g,"
                                        ");const a=p.split(T.lineBreakRegex);let r=1.25*t().state.noteMargin;for(const y of a){const x=y.trim();if(x.length>0){const d=g.append("tspan");if(d.text(x),r===0){const l=d.node().getBBox();r+=l.height}s+=r,d.attr("x",i+t().state.noteMargin),d.attr("y",o+s+1.25*t().state.noteMargin)}}return{textWidth:g.node().getBBox().width,textHeight:s}},j=(e,i)=>{i.attr("class","state-note");const o=i.append("rect").attr("x",0).attr("y",t().state.padding),c=i.append("g"),{textWidth:s,textHeight:g}=Z(e,0,0,c);return o.attr("height",g+2*t().state.noteMargin),o.attr("width",s+t().state.noteMargin*2),o},L=function(e,i){const o=i.id,c={id:o,label:i.id,width:0,height:0},s=e.append("g").attr("id",o).attr("class","stateGroup");i.type==="start"&&O(s),i.type==="end"&&_(s),(i.type==="fork"||i.type==="join")&&q(s,i),i.type==="note"&&j(i.note.text,s),i.type==="divider"&&X(s),i.type==="default"&&i.descriptions.length===0&&J(s,i),i.type==="default"&&i.descriptions.length>0&&Y(s,i);const g=s.node().getBBox();return c.width=g.width+2*t().state.padding,c.height=g.height+2*t().state.padding,c};let G=0;const K=function(e,i,o){const c=function(r){switch(r){case N.relationType.AGGREGATION:return"aggregation";case N.relationType.EXTENSION:return"extension";case N.relationType.COMPOSITION:return"composition";case N.relationType.DEPENDENCY:return"dependency"}};i.points=i.points.filter(r=>!Number.isNaN(r.y));const s=i.points,g=$().x(function(r){return r.x}).y(function(r){return r.y}).curve(v),p=e.append("path").attr("d",g(s)).attr("id","edge"+G).attr("class","transition");let a="";if(t().state.arrowMarkerAbsolute&&(a=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,a=a.replace(/\(/g,"\\("),a=a.replace(/\)/g,"\\)")),p.attr("marker-end","url("+a+"#"+c(N.relationType.DEPENDENCY)+"End)"),o.title!==void 0){const r=e.append("g").attr("class","stateLabel"),{x:y,y:x}=U.calcLabelPosition(i.points),d=T.getRows(o.title);let l=0;const m=[];let w=0,E=0;for(let u=0;u<=d.length;u++){const h=r.append("text").attr("text-anchor","middle").text(d[u]).attr("x",y).attr("y",x+l),f=h.node().getBBox();w=Math.max(w,f.width),E=Math.min(E,f.x),b.info(f.x,y,x+l),l===0&&(l=h.node().getBBox().height,b.info("Title height",l,x)),m.push(h)}let k=l*d.length;if(d.length>1){const u=(d.length-1)*l*.5;m.forEach((h,f)=>h.attr("y",x+f*l-u)),k=l*d.length}const n=r.node().getBBox();r.insert("rect",":first-child").attr("class","box").attr("x",y-w/2-t().state.padding/2).attr("y",x-k/2-t().state.padding/2-3.5).attr("width",w+t().state.padding).attr("height",k+t().state.padding),b.info(n)}G++};let B;const z={},Q=function(){},V=function(e){e.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")},D=function(e,i,o,c){B=t().state;const s=t().securityLevel;let g;s==="sandbox"&&(g=H("#i"+i));const p=s==="sandbox"?H(g.nodes()[0].contentDocument.body):H("body"),a=s==="sandbox"?g.nodes()[0].contentDocument:document;b.debug("Rendering diagram "+e);const r=p.select(`[id='${i}']`);V(r);const y=c.db.getRootDoc();A(y,r,void 0,!1,p,a,c);const x=B.padding,d=r.node().getBBox(),l=d.width+x*2,m=d.height+x*2,w=l*1.75;R(r,m,w,B.useMaxWidth),r.attr("viewBox",`${d.x-B.padding} ${d.y-B.padding} `+l+" "+m)},tt=e=>e?e.length*B.fontSizeFactor:1,A=(e,i,o,c,s,g,p)=>{const a=new C({compound:!0,multigraph:!0});let r,y=!0;for(r=0;r{const f=h.parentElement;let S=0,M=0;f&&(f.parentElement&&(S=f.parentElement.getBBox().width),M=parseInt(f.getAttribute("data-x-shift"),10),Number.isNaN(M)&&(M=0)),h.setAttribute("x1",0-M+8),h.setAttribute("x2",S-M-8)})):b.debug("No Node "+n+": "+JSON.stringify(a.node(n)))});let E=w.getBBox();a.edges().forEach(function(n){n!==void 0&&a.edge(n)!==void 0&&(b.debug("Edge "+n.v+" -> "+n.w+": "+JSON.stringify(a.edge(n))),K(i,a.edge(n),a.edge(n).relation))}),E=w.getBBox();const k={id:o||"root",label:o||"root",width:0,height:0};return k.width=E.width+2*B.padding,k.height=E.height+2*B.padding,b.debug("Doc rendered",k,a),k},et={setConf:Q,draw:D},lt={parser:P,db:N,renderer:et,styles:W,init:e=>{e.state||(e.state={}),e.state.arrowMarkerAbsolute=e.arrowMarkerAbsolute,N.clear()}};export{lt as diagram}; diff --git a/assets/stateDiagram-v2-1992cada-BZne08Mr.js b/assets/stateDiagram-v2-1992cada-DbY1jnSh.js similarity index 90% rename from assets/stateDiagram-v2-1992cada-BZne08Mr.js rename to assets/stateDiagram-v2-1992cada-DbY1jnSh.js index 09fe2cd409..497933cb2a 100644 --- a/assets/stateDiagram-v2-1992cada-BZne08Mr.js +++ b/assets/stateDiagram-v2-1992cada-DbY1jnSh.js @@ -1 +1 @@ -import{p as J,d as B,s as Q,D as H,a as X,S as Z,b as F,c as I}from"./styles-0784dbeb-C3hL6HKk.js";import{G as tt}from"./graph-D2qW7eTj.js";import{l as E,c as g,h as x,z as et,i as ot,j as w}from"./mermaid.core-CArNAncI.js";import{r as st}from"./index-01f381cb-fgk8rzsW.js";import"./layout-BlaWeSu5.js";import"./app-5SoadDYS.js";import"./clone-D0wOyyCk.js";import"./edges-066a5561-BnmFWp88.js";import"./createText-ca0c5216-X7RVUogw.js";import"./line-BIqtvXUi.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const h="rect",C="rectWithTitle",nt="start",it="end",ct="divider",rt="roundedWithTitle",lt="note",at="noteGroup",_="statediagram",dt="state",Et=`${_}-${dt}`,U="transition",St="note",Tt="note-edge",pt=`${U} ${Tt}`,_t=`${_}-${St}`,ut="cluster",Dt=`${_}-${ut}`,bt="cluster-alt",ft=`${_}-${bt}`,V="parent",Y="note",At="state",N="----",ht=`${N}${Y}`,M=`${N}${V}`,m="fill:none",z="fill: #333",W="c",j="text",q="normal";let y={},d=0;const yt=function(t){const n=Object.keys(t);for(const e of n)t[e]},gt=function(t,n){return n.db.extract(n.db.getRootDocV2()),n.db.getClasses()};function $t(t){return t==null?"":t.classes?t.classes.join(" "):""}function R(t="",n=0,e="",i=N){const c=e!==null&&e.length>0?`${i}${e}`:"";return`${At}-${t}${c}-${n}`}const A=(t,n,e,i,c,r)=>{const o=e.id,u=$t(i[o]);if(o!=="root"){let T=h;e.start===!0&&(T=nt),e.start===!1&&(T=it),e.type!==H&&(T=e.type),y[o]||(y[o]={id:o,shape:T,description:w.sanitizeText(o,g()),classes:`${u} ${Et}`});const s=y[o];e.description&&(Array.isArray(s.description)?(s.shape=C,s.description.push(e.description)):s.description.length>0?(s.shape=C,s.description===o?s.description=[e.description]:s.description=[s.description,e.description]):(s.shape=h,s.description=e.description),s.description=w.sanitizeTextOrArray(s.description,g())),s.description.length===1&&s.shape===C&&(s.shape=h),!s.type&&e.doc&&(E.info("Setting cluster for ",o,G(e)),s.type="group",s.dir=G(e),s.shape=e.type===X?ct:rt,s.classes=s.classes+" "+Dt+" "+(r?ft:""));const p={labelStyle:"",shape:s.shape,labelText:s.description,classes:s.classes,style:"",id:o,dir:s.dir,domId:R(o,d),type:s.type,padding:15};if(p.centerLabel=!0,e.note){const l={labelStyle:"",shape:lt,labelText:e.note.text,classes:_t,style:"",id:o+ht+"-"+d,domId:R(o,d,Y),type:s.type,padding:15},a={labelStyle:"",shape:at,labelText:e.note.text,classes:s.classes,style:"",id:o+M,domId:R(o,d,V),type:"group",padding:0};d++;const D=o+M;t.setNode(D,a),t.setNode(l.id,l),t.setNode(o,p),t.setParent(o,D),t.setParent(l.id,D);let S=o,b=l.id;e.note.position==="left of"&&(S=l.id,b=o),t.setEdge(S,b,{arrowhead:"none",arrowType:"",style:m,labelStyle:"",classes:pt,arrowheadStyle:z,labelpos:W,labelType:j,thickness:q})}else t.setNode(o,p)}n&&n.id!=="root"&&(E.trace("Setting node ",o," to be child of its parent ",n.id),t.setParent(o,n.id)),e.doc&&(E.trace("Adding nodes children "),xt(t,e,e.doc,i,c,!r))},xt=(t,n,e,i,c,r)=>{E.trace("items",e),e.forEach(o=>{switch(o.stmt){case F:A(t,n,o,i,c,r);break;case H:A(t,n,o,i,c,r);break;case Z:{A(t,n,o.state1,i,c,r),A(t,n,o.state2,i,c,r);const u={id:"edge"+d,arrowhead:"normal",arrowTypeEnd:"arrow_barb",style:m,labelStyle:"",label:w.sanitizeText(o.description,g()),arrowheadStyle:z,labelpos:W,labelType:j,thickness:q,classes:U};t.setEdge(o.state1.id,o.state2.id,u,d),d++}break}})},G=(t,n=I)=>{let e=n;if(t.doc)for(let i=0;i{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute,B.clear()}};export{Vt as diagram}; +import{p as J,d as B,s as Q,D as H,a as X,S as Z,b as F,c as I}from"./styles-0784dbeb-38-7TehO.js";import{G as tt}from"./graph-C-EgwjAv.js";import{l as E,c as g,h as x,z as et,i as ot,j as w}from"./mermaid.core-Bq0kX0MS.js";import{r as st}from"./index-01f381cb-DWGV-_zg.js";import"./layout-DSxgfneE.js";import"./app-Bw2NG-QJ.js";import"./clone-BjoOJyl6.js";import"./edges-066a5561-CIBMFaLO.js";import"./createText-ca0c5216-xyt9uAlz.js";import"./line-DY_oMjHu.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";const h="rect",C="rectWithTitle",nt="start",it="end",ct="divider",rt="roundedWithTitle",lt="note",at="noteGroup",_="statediagram",dt="state",Et=`${_}-${dt}`,U="transition",St="note",Tt="note-edge",pt=`${U} ${Tt}`,_t=`${_}-${St}`,ut="cluster",Dt=`${_}-${ut}`,bt="cluster-alt",ft=`${_}-${bt}`,V="parent",Y="note",At="state",N="----",ht=`${N}${Y}`,M=`${N}${V}`,m="fill:none",z="fill: #333",W="c",j="text",q="normal";let y={},d=0;const yt=function(t){const n=Object.keys(t);for(const e of n)t[e]},gt=function(t,n){return n.db.extract(n.db.getRootDocV2()),n.db.getClasses()};function $t(t){return t==null?"":t.classes?t.classes.join(" "):""}function R(t="",n=0,e="",i=N){const c=e!==null&&e.length>0?`${i}${e}`:"";return`${At}-${t}${c}-${n}`}const A=(t,n,e,i,c,r)=>{const o=e.id,u=$t(i[o]);if(o!=="root"){let T=h;e.start===!0&&(T=nt),e.start===!1&&(T=it),e.type!==H&&(T=e.type),y[o]||(y[o]={id:o,shape:T,description:w.sanitizeText(o,g()),classes:`${u} ${Et}`});const s=y[o];e.description&&(Array.isArray(s.description)?(s.shape=C,s.description.push(e.description)):s.description.length>0?(s.shape=C,s.description===o?s.description=[e.description]:s.description=[s.description,e.description]):(s.shape=h,s.description=e.description),s.description=w.sanitizeTextOrArray(s.description,g())),s.description.length===1&&s.shape===C&&(s.shape=h),!s.type&&e.doc&&(E.info("Setting cluster for ",o,G(e)),s.type="group",s.dir=G(e),s.shape=e.type===X?ct:rt,s.classes=s.classes+" "+Dt+" "+(r?ft:""));const p={labelStyle:"",shape:s.shape,labelText:s.description,classes:s.classes,style:"",id:o,dir:s.dir,domId:R(o,d),type:s.type,padding:15};if(p.centerLabel=!0,e.note){const l={labelStyle:"",shape:lt,labelText:e.note.text,classes:_t,style:"",id:o+ht+"-"+d,domId:R(o,d,Y),type:s.type,padding:15},a={labelStyle:"",shape:at,labelText:e.note.text,classes:s.classes,style:"",id:o+M,domId:R(o,d,V),type:"group",padding:0};d++;const D=o+M;t.setNode(D,a),t.setNode(l.id,l),t.setNode(o,p),t.setParent(o,D),t.setParent(l.id,D);let S=o,b=l.id;e.note.position==="left of"&&(S=l.id,b=o),t.setEdge(S,b,{arrowhead:"none",arrowType:"",style:m,labelStyle:"",classes:pt,arrowheadStyle:z,labelpos:W,labelType:j,thickness:q})}else t.setNode(o,p)}n&&n.id!=="root"&&(E.trace("Setting node ",o," to be child of its parent ",n.id),t.setParent(o,n.id)),e.doc&&(E.trace("Adding nodes children "),xt(t,e,e.doc,i,c,!r))},xt=(t,n,e,i,c,r)=>{E.trace("items",e),e.forEach(o=>{switch(o.stmt){case F:A(t,n,o,i,c,r);break;case H:A(t,n,o,i,c,r);break;case Z:{A(t,n,o.state1,i,c,r),A(t,n,o.state2,i,c,r);const u={id:"edge"+d,arrowhead:"normal",arrowTypeEnd:"arrow_barb",style:m,labelStyle:"",label:w.sanitizeText(o.description,g()),arrowheadStyle:z,labelpos:W,labelType:j,thickness:q,classes:U};t.setEdge(o.state1.id,o.state2.id,u,d),d++}break}})},G=(t,n=I)=>{let e=n;if(t.doc)for(let i=0;i{t.state||(t.state={}),t.state.arrowMarkerAbsolute=t.arrowMarkerAbsolute,B.clear()}};export{Vt as diagram}; diff --git a/assets/stats.html-Cte6ShpG.js b/assets/stats.html-DsefVpMC.js similarity index 98% rename from assets/stats.html-Cte6ShpG.js rename to assets/stats.html-DsefVpMC.js index 151b46f025..8a51d02410 100644 --- a/assets/stats.html-Cte6ShpG.js +++ b/assets/stats.html-DsefVpMC.js @@ -1,4 +1,4 @@ -import{_ as c,r as e,o as p,c as i,a,b as l,d as t,w as d,e as n}from"./app-5SoadDYS.js";const g={},r=n(`

                                        Статистика

                                        Используется для настройки сбора статистики трафика Xray.

                                        StatsObject

                                        StatsObject соответствует полю stats в конфигурационном файле.

                                        {
                                        +import{_ as c,r as e,o as p,c as i,a,b as l,d as t,w as d,e as n}from"./app-Bw2NG-QJ.js";const g={},r=n(`

                                        Статистика

                                        Используется для настройки сбора статистики трафика Xray.

                                        StatsObject

                                        StatsObject соответствует полю stats в конфигурационном файле.

                                        {
                                           "stats": {}
                                         }
                                         

                                        В настоящее время для статистики не требуется никаких параметров.
                                        Если поле StatsObject присутствует, внутренняя статистика включается.

                                        `,6),u=n('

                                        Получение статистики

                                        Вы можете получить статистику с помощью соответствующих команд xray api.

                                        В настоящее время доступна следующая статистика:

                                        • Данные пользователя

                                          • user>>>[email]>>>traffic>>>uplink

                                            Исходящий трафик для определенного пользователя в байтах.

                                          • user>>>[email]>>>traffic>>>downlink

                                            Входящий трафик для определенного пользователя в байтах.

                                        Подсказка

                                        Если для пользователя не указан email, статистика для него не будет собираться.

                                        • Глобальные данные

                                          • inbound>>>[tag]>>>traffic>>>uplink

                                            Исходящий трафик для определенного входящего подключения в байтах.

                                          • inbound>>>[tag]>>>traffic>>>downlink

                                            Входящий трафик для определенного входящего подключения в байтах.

                                          • outbound>>>[tag]>>>traffic>>>uplink

                                            Исходящий трафик для определенного исходящего подключения в байтах.

                                          • outbound>>>[tag]>>>traffic>>>downlink

                                            Входящий трафик для определенного исходящего подключения в байтах.

                                        ',6);function f(h,m){const s=e("I18nTip"),o=e("RouterLink");return p(),i("div",null,[a(s),r,l("p",null,[t("После включения статистики вам нужно только включить соответствующие параметры в разделе "),a(o,{to:"/ru/config/policy.html"},{default:d(()=>[t("Политики")]),_:1}),t(", чтобы начать сбор статистики.")]),u])}const b=c(g,[["render",f],["__file","stats.html.vue"]]);export{b as default}; diff --git a/assets/stats.html-CkvTAU5q.js b/assets/stats.html-MnnldZmL.js similarity index 97% rename from assets/stats.html-CkvTAU5q.js rename to assets/stats.html-MnnldZmL.js index 863bf4128d..1e3e05047a 100644 --- a/assets/stats.html-CkvTAU5q.js +++ b/assets/stats.html-MnnldZmL.js @@ -1,4 +1,4 @@ -import{_ as c,r as e,o,c as r,a as i,b as p,d as t,w as l,e as a}from"./app-5SoadDYS.js";const d={},f=a(`

                                        Traffic Statistics

                                        Used to configure traffic statistics for Xray.

                                        StatsObject

                                        The StatsObject corresponds to the stats item in the configuration file.

                                        {
                                        +import{_ as c,r as e,o,c as r,a as i,b as p,d as t,w as l,e as a}from"./app-Bw2NG-QJ.js";const d={},f=a(`

                                        Traffic Statistics

                                        Used to configure traffic statistics for Xray.

                                        StatsObject

                                        The StatsObject corresponds to the stats item in the configuration file.

                                        {
                                           "stats": {}
                                         }
                                         

                                        Currently, no parameters are required for traffic statistics, and internal statistics will be enabled as long as the StatsObject item exists.

                                        `,6),g=a('

                                        Retrieving Traffic Statistics

                                        You can use the xray api command to retrieve traffic statistics.

                                        The current traffic statistics are as follows:

                                        • User Data

                                          • user>>>[email]>>>traffic>>>uplink

                                            The uplink traffic of a specific user, in bytes.

                                          • user>>>[email]>>>traffic>>>downlink

                                            The downlink traffic of a specific user, in bytes.

                                        Tip

                                        If the corresponding user does not have an email specified, statistics will not be enabled.

                                        • Global Data

                                          • inbound>>>[tag]>>>traffic>>>uplink

                                            The uplink traffic of a specific inbound, in bytes.

                                          • inbound>>>[tag]>>>traffic>>>downlink

                                            The downlink traffic of a specific inbound, in bytes.

                                          • outbound>>>[tag]>>>traffic>>>uplink

                                            The uplink traffic of a specific outbound, in bytes.

                                          • outbound>>>[tag]>>>traffic>>>downlink

                                            The downlink traffic of a specific outbound, in bytes.

                                        ',6);function u(h,b){const s=e("I18nTip"),n=e("RouterLink");return o(),r("div",null,[i(s),f,p("p",null,[t("After statistics are enabled, you only need to enable the corresponding items in the "),i(n,{to:"/en/config/policy.html"},{default:l(()=>[t("Policy")]),_:1}),t(" to collect the corresponding data.")]),g])}const k=c(d,[["render",u],["__file","stats.html.vue"]]);export{k as default}; diff --git a/assets/stats.html-B-9-Cpn9.js b/assets/stats.html-zgGzE1Xt.js similarity index 97% rename from assets/stats.html-B-9-Cpn9.js rename to assets/stats.html-zgGzE1Xt.js index 0f8d3e91b3..7f797f680c 100644 --- a/assets/stats.html-B-9-Cpn9.js +++ b/assets/stats.html-zgGzE1Xt.js @@ -1,4 +1,4 @@ -import{_ as c,r as a,o as i,c as p,a as e,b as l,d as t,w as d,e as n}from"./app-5SoadDYS.js";const g={},u=n(`

                                        统计信息

                                        用于配置 Xray 流量数据的统计。

                                        StatsObject

                                        StatsObject 对应配置文件的 stats 项。

                                        {
                                        +import{_ as c,r as a,o as i,c as p,a as e,b as l,d as t,w as d,e as n}from"./app-Bw2NG-QJ.js";const g={},u=n(`

                                        统计信息

                                        用于配置 Xray 流量数据的统计。

                                        StatsObject

                                        StatsObject 对应配置文件的 stats 项。

                                        {
                                           "stats": {}
                                         }
                                         

                                        目前统计信息不需要任何参数,只要 StatsObject 项存在,内部的统计即会开启。

                                        `,6),r=n('

                                        获取统计信息

                                        可以用 xray api 的相关命令获取统计信息.

                                        目前已有的统计信息如下:

                                        • 用户数据

                                          • user>>>[email]>>>traffic>>>uplink

                                            特定用户的上行流量,单位字节。

                                          • user>>>[email]>>>traffic>>>downlink

                                            特定用户的下行流量,单位字节。

                                        提示

                                        如果对应用户没有指定 Email,则不会开启统计。

                                        • 全局数据

                                          • inbound>>>[tag]>>>traffic>>>uplink

                                            特定 inbound 的上行流量,单位字节。

                                          • inbound>>>[tag]>>>traffic>>>downlink

                                            特定 inbound 的下行流量,单位字节。

                                          • outbound>>>[tag]>>>traffic>>>uplink

                                            特定 outbound 的上行流量,单位字节。

                                          • outbound>>>[tag]>>>traffic>>>downlink

                                            特定 outbound 的下行流量,单位字节。

                                        ',6);function f(h,b){const o=a("I18nTip"),s=a("RouterLink");return i(),p("div",null,[e(o),u,l("p",null,[t("开启了统计以后, 只需在 "),e(s,{to:"/config/policy.html"},{default:d(()=>[t("Policy")]),_:1}),t(" 中开启对应的项,就可以统计对应的数据。")]),r])}const _=c(g,[["render",f],["__file","stats.html.vue"]]);export{_ as default}; diff --git a/assets/styles-0784dbeb-C3hL6HKk.js b/assets/styles-0784dbeb-38-7TehO.js similarity index 99% rename from assets/styles-0784dbeb-C3hL6HKk.js rename to assets/styles-0784dbeb-38-7TehO.js index 07a818f82e..48a375062f 100644 --- a/assets/styles-0784dbeb-C3hL6HKk.js +++ b/assets/styles-0784dbeb-38-7TehO.js @@ -1,4 +1,4 @@ -import{c as Y,g as Ut,s as zt,a as Mt,b as Ht,x as Xt,y as Kt,l as D,j as ot,A as Wt,b3 as Jt}from"./mermaid.core-CArNAncI.js";var gt=function(){var t=function(C,r,n,i){for(n=n||{},i=C.length;i--;n[C[i]]=r);return n},s=[1,2],a=[1,3],h=[1,4],f=[2,4],d=[1,9],y=[1,11],k=[1,15],u=[1,16],E=[1,17],T=[1,18],R=[1,30],G=[1,19],j=[1,20],U=[1,21],z=[1,22],M=[1,23],H=[1,25],X=[1,26],K=[1,27],W=[1,28],J=[1,29],q=[1,32],Q=[1,33],Z=[1,34],tt=[1,35],w=[1,31],c=[1,4,5,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],et=[1,4,5,13,14,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],Dt=[4,5,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],ht={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,SD:6,document:7,line:8,statement:9,classDefStatement:10,cssClassStatement:11,idStatement:12,DESCR:13,"-->":14,HIDE_EMPTY:15,scale:16,WIDTH:17,COMPOSIT_STATE:18,STRUCT_START:19,STRUCT_STOP:20,STATE_DESCR:21,AS:22,ID:23,FORK:24,JOIN:25,CHOICE:26,CONCURRENT:27,note:28,notePosition:29,NOTE_TEXT:30,direction:31,acc_title:32,acc_title_value:33,acc_descr:34,acc_descr_value:35,acc_descr_multiline_value:36,classDef:37,CLASSDEF_ID:38,CLASSDEF_STYLEOPTS:39,DEFAULT:40,class:41,CLASSENTITY_IDS:42,STYLECLASS:43,direction_tb:44,direction_bt:45,direction_rl:46,direction_lr:47,eol:48,";":49,EDGE_STATE:50,STYLE_SEPARATOR:51,left_of:52,right_of:53,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",6:"SD",13:"DESCR",14:"-->",15:"HIDE_EMPTY",16:"scale",17:"WIDTH",18:"COMPOSIT_STATE",19:"STRUCT_START",20:"STRUCT_STOP",21:"STATE_DESCR",22:"AS",23:"ID",24:"FORK",25:"JOIN",26:"CHOICE",27:"CONCURRENT",28:"note",30:"NOTE_TEXT",32:"acc_title",33:"acc_title_value",34:"acc_descr",35:"acc_descr_value",36:"acc_descr_multiline_value",37:"classDef",38:"CLASSDEF_ID",39:"CLASSDEF_STYLEOPTS",40:"DEFAULT",41:"class",42:"CLASSENTITY_IDS",43:"STYLECLASS",44:"direction_tb",45:"direction_bt",46:"direction_rl",47:"direction_lr",49:";",50:"EDGE_STATE",51:"STYLE_SEPARATOR",52:"left_of",53:"right_of"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[9,1],[9,1],[9,1],[9,2],[9,3],[9,4],[9,1],[9,2],[9,1],[9,4],[9,3],[9,6],[9,1],[9,1],[9,1],[9,1],[9,4],[9,4],[9,1],[9,2],[9,2],[9,1],[10,3],[10,3],[11,3],[31,1],[31,1],[31,1],[31,1],[48,1],[48,1],[12,1],[12,1],[12,3],[12,3],[29,1],[29,1]],performAction:function(r,n,i,o,p,e,$){var l=e.length-1;switch(p){case 3:return o.setRootDoc(e[l]),e[l];case 4:this.$=[];break;case 5:e[l]!="nl"&&(e[l-1].push(e[l]),this.$=e[l-1]);break;case 6:case 7:this.$=e[l];break;case 8:this.$="nl";break;case 11:this.$=e[l];break;case 12:const B=e[l-1];B.description=o.trimColon(e[l]),this.$=B;break;case 13:this.$={stmt:"relation",state1:e[l-2],state2:e[l]};break;case 14:const ft=o.trimColon(e[l]);this.$={stmt:"relation",state1:e[l-3],state2:e[l-1],description:ft};break;case 18:this.$={stmt:"state",id:e[l-3],type:"default",description:"",doc:e[l-1]};break;case 19:var A=e[l],O=e[l-2].trim();if(e[l].match(":")){var st=e[l].split(":");A=st[0],O=[O,st[1]]}this.$={stmt:"state",id:A,type:"default",description:O};break;case 20:this.$={stmt:"state",id:e[l-3],type:"default",description:e[l-5],doc:e[l-1]};break;case 21:this.$={stmt:"state",id:e[l],type:"fork"};break;case 22:this.$={stmt:"state",id:e[l],type:"join"};break;case 23:this.$={stmt:"state",id:e[l],type:"choice"};break;case 24:this.$={stmt:"state",id:o.getDividerId(),type:"divider"};break;case 25:this.$={stmt:"state",id:e[l-1].trim(),note:{position:e[l-2].trim(),text:e[l].trim()}};break;case 28:this.$=e[l].trim(),o.setAccTitle(this.$);break;case 29:case 30:this.$=e[l].trim(),o.setAccDescription(this.$);break;case 31:case 32:this.$={stmt:"classDef",id:e[l-1].trim(),classes:e[l].trim()};break;case 33:this.$={stmt:"applyClass",id:e[l-1].trim(),styleClass:e[l].trim()};break;case 34:o.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 35:o.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 36:o.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 37:o.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 40:case 41:this.$={stmt:"state",id:e[l].trim(),type:"default",description:""};break;case 42:this.$={stmt:"state",id:e[l-2].trim(),classes:[e[l].trim()],type:"default",description:""};break;case 43:this.$={stmt:"state",id:e[l-2].trim(),classes:[e[l].trim()],type:"default",description:""};break}},table:[{3:1,4:s,5:a,6:h},{1:[3]},{3:5,4:s,5:a,6:h},{3:6,4:s,5:a,6:h},t([1,4,5,15,16,18,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],f,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:d,5:y,8:8,9:10,10:12,11:13,12:14,15:k,16:u,18:E,21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,5]),{9:36,10:12,11:13,12:14,15:k,16:u,18:E,21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,7]),t(c,[2,8]),t(c,[2,9]),t(c,[2,10]),t(c,[2,11],{13:[1,37],14:[1,38]}),t(c,[2,15]),{17:[1,39]},t(c,[2,17],{19:[1,40]}),{22:[1,41]},t(c,[2,21]),t(c,[2,22]),t(c,[2,23]),t(c,[2,24]),{29:42,30:[1,43],52:[1,44],53:[1,45]},t(c,[2,27]),{33:[1,46]},{35:[1,47]},t(c,[2,30]),{38:[1,48],40:[1,49]},{42:[1,50]},t(et,[2,40],{51:[1,51]}),t(et,[2,41],{51:[1,52]}),t(c,[2,34]),t(c,[2,35]),t(c,[2,36]),t(c,[2,37]),t(c,[2,6]),t(c,[2,12]),{12:53,23:R,50:w},t(c,[2,16]),t(Dt,f,{7:54}),{23:[1,55]},{23:[1,56]},{22:[1,57]},{23:[2,44]},{23:[2,45]},t(c,[2,28]),t(c,[2,29]),{39:[1,58]},{39:[1,59]},{43:[1,60]},{23:[1,61]},{23:[1,62]},t(c,[2,13],{13:[1,63]}),{4:d,5:y,8:8,9:10,10:12,11:13,12:14,15:k,16:u,18:E,20:[1,64],21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,19],{19:[1,65]}),{30:[1,66]},{23:[1,67]},t(c,[2,31]),t(c,[2,32]),t(c,[2,33]),t(et,[2,42]),t(et,[2,43]),t(c,[2,14]),t(c,[2,18]),t(Dt,f,{7:68}),t(c,[2,25]),t(c,[2,26]),{4:d,5:y,8:8,9:10,10:12,11:13,12:14,15:k,16:u,18:E,20:[1,69],21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,20])],defaultActions:{5:[2,1],6:[2,2],44:[2,44],45:[2,45]},parseError:function(r,n){if(n.recoverable)this.trace(r);else{var i=new Error(r);throw i.hash=n,i}},parse:function(r){var n=this,i=[0],o=[],p=[null],e=[],$=this.table,l="",A=0,O=0,st=2,B=1,ft=e.slice.call(arguments,1),S=Object.create(this.lexer),v={yy:{}};for(var dt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,dt)&&(v.yy[dt]=this.yy[dt]);S.setInput(r,v.yy),v.yy.lexer=S,v.yy.parser=this,typeof S.yylloc>"u"&&(S.yylloc={});var yt=S.yylloc;e.push(yt);var Gt=S.options&&S.options.ranges;typeof v.yy.parseError=="function"?this.parseError=v.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function jt(){var x;return x=o.pop()||S.lex()||B,typeof x!="number"&&(x instanceof Array&&(o=x,x=o.pop()),x=n.symbols_[x]||x),x}for(var _,L,m,pt,N={},it,b,Ct,rt;;){if(L=i[i.length-1],this.defaultActions[L]?m=this.defaultActions[L]:((_===null||typeof _>"u")&&(_=jt()),m=$[L]&&$[L][_]),typeof m>"u"||!m.length||!m[0]){var St="";rt=[];for(it in $[L])this.terminals_[it]&&it>st&&rt.push("'"+this.terminals_[it]+"'");S.showPosition?St="Parse error on line "+(A+1)+`: +import{c as Y,g as Ut,s as zt,a as Mt,b as Ht,x as Xt,y as Kt,l as D,j as ot,A as Wt,b3 as Jt}from"./mermaid.core-Bq0kX0MS.js";var gt=function(){var t=function(C,r,n,i){for(n=n||{},i=C.length;i--;n[C[i]]=r);return n},s=[1,2],a=[1,3],h=[1,4],f=[2,4],d=[1,9],y=[1,11],k=[1,15],u=[1,16],E=[1,17],T=[1,18],R=[1,30],G=[1,19],j=[1,20],U=[1,21],z=[1,22],M=[1,23],H=[1,25],X=[1,26],K=[1,27],W=[1,28],J=[1,29],q=[1,32],Q=[1,33],Z=[1,34],tt=[1,35],w=[1,31],c=[1,4,5,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],et=[1,4,5,13,14,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],Dt=[4,5,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],ht={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,SD:6,document:7,line:8,statement:9,classDefStatement:10,cssClassStatement:11,idStatement:12,DESCR:13,"-->":14,HIDE_EMPTY:15,scale:16,WIDTH:17,COMPOSIT_STATE:18,STRUCT_START:19,STRUCT_STOP:20,STATE_DESCR:21,AS:22,ID:23,FORK:24,JOIN:25,CHOICE:26,CONCURRENT:27,note:28,notePosition:29,NOTE_TEXT:30,direction:31,acc_title:32,acc_title_value:33,acc_descr:34,acc_descr_value:35,acc_descr_multiline_value:36,classDef:37,CLASSDEF_ID:38,CLASSDEF_STYLEOPTS:39,DEFAULT:40,class:41,CLASSENTITY_IDS:42,STYLECLASS:43,direction_tb:44,direction_bt:45,direction_rl:46,direction_lr:47,eol:48,";":49,EDGE_STATE:50,STYLE_SEPARATOR:51,left_of:52,right_of:53,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",6:"SD",13:"DESCR",14:"-->",15:"HIDE_EMPTY",16:"scale",17:"WIDTH",18:"COMPOSIT_STATE",19:"STRUCT_START",20:"STRUCT_STOP",21:"STATE_DESCR",22:"AS",23:"ID",24:"FORK",25:"JOIN",26:"CHOICE",27:"CONCURRENT",28:"note",30:"NOTE_TEXT",32:"acc_title",33:"acc_title_value",34:"acc_descr",35:"acc_descr_value",36:"acc_descr_multiline_value",37:"classDef",38:"CLASSDEF_ID",39:"CLASSDEF_STYLEOPTS",40:"DEFAULT",41:"class",42:"CLASSENTITY_IDS",43:"STYLECLASS",44:"direction_tb",45:"direction_bt",46:"direction_rl",47:"direction_lr",49:";",50:"EDGE_STATE",51:"STYLE_SEPARATOR",52:"left_of",53:"right_of"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[9,1],[9,1],[9,1],[9,2],[9,3],[9,4],[9,1],[9,2],[9,1],[9,4],[9,3],[9,6],[9,1],[9,1],[9,1],[9,1],[9,4],[9,4],[9,1],[9,2],[9,2],[9,1],[10,3],[10,3],[11,3],[31,1],[31,1],[31,1],[31,1],[48,1],[48,1],[12,1],[12,1],[12,3],[12,3],[29,1],[29,1]],performAction:function(r,n,i,o,p,e,$){var l=e.length-1;switch(p){case 3:return o.setRootDoc(e[l]),e[l];case 4:this.$=[];break;case 5:e[l]!="nl"&&(e[l-1].push(e[l]),this.$=e[l-1]);break;case 6:case 7:this.$=e[l];break;case 8:this.$="nl";break;case 11:this.$=e[l];break;case 12:const B=e[l-1];B.description=o.trimColon(e[l]),this.$=B;break;case 13:this.$={stmt:"relation",state1:e[l-2],state2:e[l]};break;case 14:const ft=o.trimColon(e[l]);this.$={stmt:"relation",state1:e[l-3],state2:e[l-1],description:ft};break;case 18:this.$={stmt:"state",id:e[l-3],type:"default",description:"",doc:e[l-1]};break;case 19:var A=e[l],O=e[l-2].trim();if(e[l].match(":")){var st=e[l].split(":");A=st[0],O=[O,st[1]]}this.$={stmt:"state",id:A,type:"default",description:O};break;case 20:this.$={stmt:"state",id:e[l-3],type:"default",description:e[l-5],doc:e[l-1]};break;case 21:this.$={stmt:"state",id:e[l],type:"fork"};break;case 22:this.$={stmt:"state",id:e[l],type:"join"};break;case 23:this.$={stmt:"state",id:e[l],type:"choice"};break;case 24:this.$={stmt:"state",id:o.getDividerId(),type:"divider"};break;case 25:this.$={stmt:"state",id:e[l-1].trim(),note:{position:e[l-2].trim(),text:e[l].trim()}};break;case 28:this.$=e[l].trim(),o.setAccTitle(this.$);break;case 29:case 30:this.$=e[l].trim(),o.setAccDescription(this.$);break;case 31:case 32:this.$={stmt:"classDef",id:e[l-1].trim(),classes:e[l].trim()};break;case 33:this.$={stmt:"applyClass",id:e[l-1].trim(),styleClass:e[l].trim()};break;case 34:o.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 35:o.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 36:o.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 37:o.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 40:case 41:this.$={stmt:"state",id:e[l].trim(),type:"default",description:""};break;case 42:this.$={stmt:"state",id:e[l-2].trim(),classes:[e[l].trim()],type:"default",description:""};break;case 43:this.$={stmt:"state",id:e[l-2].trim(),classes:[e[l].trim()],type:"default",description:""};break}},table:[{3:1,4:s,5:a,6:h},{1:[3]},{3:5,4:s,5:a,6:h},{3:6,4:s,5:a,6:h},t([1,4,5,15,16,18,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],f,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:d,5:y,8:8,9:10,10:12,11:13,12:14,15:k,16:u,18:E,21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,5]),{9:36,10:12,11:13,12:14,15:k,16:u,18:E,21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,7]),t(c,[2,8]),t(c,[2,9]),t(c,[2,10]),t(c,[2,11],{13:[1,37],14:[1,38]}),t(c,[2,15]),{17:[1,39]},t(c,[2,17],{19:[1,40]}),{22:[1,41]},t(c,[2,21]),t(c,[2,22]),t(c,[2,23]),t(c,[2,24]),{29:42,30:[1,43],52:[1,44],53:[1,45]},t(c,[2,27]),{33:[1,46]},{35:[1,47]},t(c,[2,30]),{38:[1,48],40:[1,49]},{42:[1,50]},t(et,[2,40],{51:[1,51]}),t(et,[2,41],{51:[1,52]}),t(c,[2,34]),t(c,[2,35]),t(c,[2,36]),t(c,[2,37]),t(c,[2,6]),t(c,[2,12]),{12:53,23:R,50:w},t(c,[2,16]),t(Dt,f,{7:54}),{23:[1,55]},{23:[1,56]},{22:[1,57]},{23:[2,44]},{23:[2,45]},t(c,[2,28]),t(c,[2,29]),{39:[1,58]},{39:[1,59]},{43:[1,60]},{23:[1,61]},{23:[1,62]},t(c,[2,13],{13:[1,63]}),{4:d,5:y,8:8,9:10,10:12,11:13,12:14,15:k,16:u,18:E,20:[1,64],21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,19],{19:[1,65]}),{30:[1,66]},{23:[1,67]},t(c,[2,31]),t(c,[2,32]),t(c,[2,33]),t(et,[2,42]),t(et,[2,43]),t(c,[2,14]),t(c,[2,18]),t(Dt,f,{7:68}),t(c,[2,25]),t(c,[2,26]),{4:d,5:y,8:8,9:10,10:12,11:13,12:14,15:k,16:u,18:E,20:[1,69],21:T,23:R,24:G,25:j,26:U,27:z,28:M,31:24,32:H,34:X,36:K,37:W,41:J,44:q,45:Q,46:Z,47:tt,50:w},t(c,[2,20])],defaultActions:{5:[2,1],6:[2,2],44:[2,44],45:[2,45]},parseError:function(r,n){if(n.recoverable)this.trace(r);else{var i=new Error(r);throw i.hash=n,i}},parse:function(r){var n=this,i=[0],o=[],p=[null],e=[],$=this.table,l="",A=0,O=0,st=2,B=1,ft=e.slice.call(arguments,1),S=Object.create(this.lexer),v={yy:{}};for(var dt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,dt)&&(v.yy[dt]=this.yy[dt]);S.setInput(r,v.yy),v.yy.lexer=S,v.yy.parser=this,typeof S.yylloc>"u"&&(S.yylloc={});var yt=S.yylloc;e.push(yt);var Gt=S.options&&S.options.ranges;typeof v.yy.parseError=="function"?this.parseError=v.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function jt(){var x;return x=o.pop()||S.lex()||B,typeof x!="number"&&(x instanceof Array&&(o=x,x=o.pop()),x=n.symbols_[x]||x),x}for(var _,L,m,pt,N={},it,b,Ct,rt;;){if(L=i[i.length-1],this.defaultActions[L]?m=this.defaultActions[L]:((_===null||typeof _>"u")&&(_=jt()),m=$[L]&&$[L][_]),typeof m>"u"||!m.length||!m[0]){var St="";rt=[];for(it in $[L])this.terminals_[it]&&it>st&&rt.push("'"+this.terminals_[it]+"'");S.showPosition?St="Parse error on line "+(A+1)+`: `+S.showPosition()+` Expecting `+rt.join(", ")+", got '"+(this.terminals_[_]||_)+"'":St="Parse error on line "+(A+1)+": Unexpected "+(_==B?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(St,{text:S.match,token:this.terminals_[_]||_,line:S.yylineno,loc:yt,expected:rt})}if(m[0]instanceof Array&&m.length>1)throw new Error("Parse Error: multiple actions possible at state: "+L+", token: "+_);switch(m[0]){case 1:i.push(_),p.push(S.yytext),e.push(S.yylloc),i.push(m[1]),_=null,O=S.yyleng,l=S.yytext,A=S.yylineno,yt=S.yylloc;break;case 2:if(b=this.productions_[m[1]][1],N.$=p[p.length-b],N._$={first_line:e[e.length-(b||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(b||1)].first_column,last_column:e[e.length-1].last_column},Gt&&(N._$.range=[e[e.length-(b||1)].range[0],e[e.length-1].range[1]]),pt=this.performAction.apply(N,[l,O,A,v.yy,m[1],p,e].concat(ft)),typeof pt<"u")return pt;b&&(i=i.slice(0,-1*b*2),p=p.slice(0,-1*b),e=e.slice(0,-1*b)),i.push(this.productions_[m[1]][0]),p.push(N.$),e.push(N._$),Ct=$[i[i.length-2]][i[i.length-1]],i.push(Ct);break;case 3:return!0}}return!0}},Yt=function(){var C={EOF:1,parseError:function(n,i){if(this.yy.parser)this.yy.parser.parseError(n,i);else throw new Error(n)},setInput:function(r,n){return this.yy=n||this.yy||{},this._input=r,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var r=this._input[0];this.yytext+=r,this.yyleng++,this.offset++,this.match+=r,this.matched+=r;var n=r.match(/(?:\r\n?|\n).*/g);return n?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),r},unput:function(r){var n=r.length,i=r.split(/(?:\r\n?|\n)/g);this._input=r+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-n),this.offset-=n;var o=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),i.length-1&&(this.yylineno-=i.length-1);var p=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:i?(i.length===o.length?this.yylloc.first_column:0)+o[o.length-i.length].length-i[0].length:this.yylloc.first_column-n},this.options.ranges&&(this.yylloc.range=[p[0],p[0]+this.yyleng-n]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(r){this.unput(this.match.slice(r))},pastInput:function(){var r=this.matched.substr(0,this.matched.length-this.match.length);return(r.length>20?"...":"")+r.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var r=this.match;return r.length<20&&(r+=this._input.substr(0,20-r.length)),(r.substr(0,20)+(r.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var r=this.pastInput(),n=new Array(r.length+1).join("-");return r+this.upcomingInput()+` diff --git a/assets/styles-483fbfea-B2onFAKT.js b/assets/styles-483fbfea-BRNgjsWa.js similarity index 98% rename from assets/styles-483fbfea-B2onFAKT.js rename to assets/styles-483fbfea-BRNgjsWa.js index b783716056..3e612602a3 100644 --- a/assets/styles-483fbfea-B2onFAKT.js +++ b/assets/styles-483fbfea-BRNgjsWa.js @@ -1,4 +1,4 @@ -import{G as R}from"./graph-D2qW7eTj.js";import{ab as z,ac as F,ad as j,ae as U,a9 as H,p as A,l as g,q as K,c as S,j as G,r as q,t as E,o as L,h as C,z as W,u as X,af as J}from"./mermaid.core-CArNAncI.js";import{r as Q}from"./index-01f381cb-fgk8rzsW.js";import{c as Y}from"./channel-C_7gBDjR.js";function Z(e){return typeof e=="string"?new z([document.querySelectorAll(e)],[document.documentElement]):new z([j(e)],F)}function pe(e,l){return!!e.children(l).length}function be(e){return N(e.v)+":"+N(e.w)+":"+N(e.name)}var O=/:/g;function N(e){return e?String(e).replace(O,"\\:"):""}function ee(e,l){l&&e.attr("style",l)}function fe(e,l,c){l&&e.attr("class",l).attr("class",c+" "+e.attr("class"))}function ue(e,l){var c=l.graph();if(U(c)){var a=c.transition;if(H(a))return a(e)}return e}function te(e,l){var c=e.append("foreignObject").attr("width","100000"),a=c.append("xhtml:div");a.attr("xmlns","http://www.w3.org/1999/xhtml");var i=l.label;switch(typeof i){case"function":a.insert(i);break;case"object":a.insert(function(){return i});break;default:a.html(i)}ee(a,l.labelStyle),a.style("display","inline-block"),a.style("white-space","nowrap");var d=a.node().getBoundingClientRect();return c.attr("width",d.width).attr("height",d.height),c}const P={},re=function(e){const l=Object.keys(e);for(const c of l)P[c]=e[c]},V=async function(e,l,c,a,i,d){const u=a.select(`[id="${c}"]`),n=Object.keys(e);for(const p of n){const r=e[p];let y="default";r.classes.length>0&&(y=r.classes.join(" ")),y=y+" flowchart-label";const w=A(r.styles);let t=r.text!==void 0?r.text:r.id,s;if(g.info("vertex",r,r.labelType),r.labelType==="markdown")g.info("vertex",r,r.labelType);else if(K(S().flowchart.htmlLabels))s=te(u,{label:t}).node(),s.parentNode.removeChild(s);else{const k=i.createElementNS("http://www.w3.org/2000/svg","text");k.setAttribute("style",w.labelStyle.replace("color:","fill:"));const _=t.split(G.lineBreakRegex);for(const $ of _){const v=i.createElementNS("http://www.w3.org/2000/svg","tspan");v.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),v.setAttribute("dy","1em"),v.setAttribute("x","1"),v.textContent=$,k.appendChild(v)}s=k}let b=0,o="";switch(r.type){case"round":b=5,o="rect";break;case"square":o="rect";break;case"diamond":o="question";break;case"hexagon":o="hexagon";break;case"odd":o="rect_left_inv_arrow";break;case"lean_right":o="lean_right";break;case"lean_left":o="lean_left";break;case"trapezoid":o="trapezoid";break;case"inv_trapezoid":o="inv_trapezoid";break;case"odd_right":o="rect_left_inv_arrow";break;case"circle":o="circle";break;case"ellipse":o="ellipse";break;case"stadium":o="stadium";break;case"subroutine":o="subroutine";break;case"cylinder":o="cylinder";break;case"group":o="rect";break;case"doublecircle":o="doublecircle";break;default:o="rect"}const T=await q(t,S());l.setNode(r.id,{labelStyle:w.labelStyle,shape:o,labelText:T,labelType:r.labelType,rx:b,ry:b,class:y,style:w.style,id:r.id,link:r.link,linkTarget:r.linkTarget,tooltip:d.db.getTooltip(r.id)||"",domId:d.db.lookUpDomId(r.id),haveCallback:r.haveCallback,width:r.type==="group"?500:void 0,dir:r.dir,type:r.type,props:r.props,padding:S().flowchart.padding}),g.info("setNode",{labelStyle:w.labelStyle,labelType:r.labelType,shape:o,labelText:T,rx:b,ry:b,class:y,style:w.style,id:r.id,domId:d.db.lookUpDomId(r.id),width:r.type==="group"?500:void 0,type:r.type,dir:r.dir,props:r.props,padding:S().flowchart.padding})}},M=async function(e,l,c){g.info("abc78 edges = ",e);let a=0,i={},d,u;if(e.defaultStyle!==void 0){const n=A(e.defaultStyle);d=n.style,u=n.labelStyle}for(const n of e){a++;const p="L-"+n.start+"-"+n.end;i[p]===void 0?(i[p]=0,g.info("abc78 new entry",p,i[p])):(i[p]++,g.info("abc78 new entry",p,i[p]));let r=p+"-"+i[p];g.info("abc78 new link id to be used is",p,r,i[p]);const y="LS-"+n.start,w="LE-"+n.end,t={style:"",labelStyle:""};switch(t.minlen=n.length||1,n.type==="arrow_open"?t.arrowhead="none":t.arrowhead="normal",t.arrowTypeStart="arrow_open",t.arrowTypeEnd="arrow_open",n.type){case"double_arrow_cross":t.arrowTypeStart="arrow_cross";case"arrow_cross":t.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":t.arrowTypeStart="arrow_point";case"arrow_point":t.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":t.arrowTypeStart="arrow_circle";case"arrow_circle":t.arrowTypeEnd="arrow_circle";break}let s="",b="";switch(n.stroke){case"normal":s="fill:none;",d!==void 0&&(s=d),u!==void 0&&(b=u),t.thickness="normal",t.pattern="solid";break;case"dotted":t.thickness="normal",t.pattern="dotted",t.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":t.thickness="thick",t.pattern="solid",t.style="stroke-width: 3.5px;fill:none;";break;case"invisible":t.thickness="invisible",t.pattern="solid",t.style="stroke-width: 0;fill:none;";break}if(n.style!==void 0){const o=A(n.style);s=o.style,b=o.labelStyle}t.style=t.style+=s,t.labelStyle=t.labelStyle+=b,n.interpolate!==void 0?t.curve=E(n.interpolate,L):e.defaultInterpolate!==void 0?t.curve=E(e.defaultInterpolate,L):t.curve=E(P.curve,L),n.text===void 0?n.style!==void 0&&(t.arrowheadStyle="fill: #333"):(t.arrowheadStyle="fill: #333",t.labelpos="c"),t.labelType=n.labelType,t.label=await q(n.text.replace(G.lineBreakRegex,` +import{G as R}from"./graph-C-EgwjAv.js";import{ab as z,ac as F,ad as j,ae as U,a9 as H,p as A,l as g,q as K,c as S,j as G,r as q,t as E,o as L,h as C,z as W,u as X,af as J}from"./mermaid.core-Bq0kX0MS.js";import{r as Q}from"./index-01f381cb-DWGV-_zg.js";import{c as Y}from"./channel-DIeeoF-2.js";function Z(e){return typeof e=="string"?new z([document.querySelectorAll(e)],[document.documentElement]):new z([j(e)],F)}function pe(e,l){return!!e.children(l).length}function be(e){return N(e.v)+":"+N(e.w)+":"+N(e.name)}var O=/:/g;function N(e){return e?String(e).replace(O,"\\:"):""}function ee(e,l){l&&e.attr("style",l)}function fe(e,l,c){l&&e.attr("class",l).attr("class",c+" "+e.attr("class"))}function ue(e,l){var c=l.graph();if(U(c)){var a=c.transition;if(H(a))return a(e)}return e}function te(e,l){var c=e.append("foreignObject").attr("width","100000"),a=c.append("xhtml:div");a.attr("xmlns","http://www.w3.org/1999/xhtml");var i=l.label;switch(typeof i){case"function":a.insert(i);break;case"object":a.insert(function(){return i});break;default:a.html(i)}ee(a,l.labelStyle),a.style("display","inline-block"),a.style("white-space","nowrap");var d=a.node().getBoundingClientRect();return c.attr("width",d.width).attr("height",d.height),c}const P={},re=function(e){const l=Object.keys(e);for(const c of l)P[c]=e[c]},V=async function(e,l,c,a,i,d){const u=a.select(`[id="${c}"]`),n=Object.keys(e);for(const p of n){const r=e[p];let y="default";r.classes.length>0&&(y=r.classes.join(" ")),y=y+" flowchart-label";const w=A(r.styles);let t=r.text!==void 0?r.text:r.id,s;if(g.info("vertex",r,r.labelType),r.labelType==="markdown")g.info("vertex",r,r.labelType);else if(K(S().flowchart.htmlLabels))s=te(u,{label:t}).node(),s.parentNode.removeChild(s);else{const k=i.createElementNS("http://www.w3.org/2000/svg","text");k.setAttribute("style",w.labelStyle.replace("color:","fill:"));const _=t.split(G.lineBreakRegex);for(const $ of _){const v=i.createElementNS("http://www.w3.org/2000/svg","tspan");v.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),v.setAttribute("dy","1em"),v.setAttribute("x","1"),v.textContent=$,k.appendChild(v)}s=k}let b=0,o="";switch(r.type){case"round":b=5,o="rect";break;case"square":o="rect";break;case"diamond":o="question";break;case"hexagon":o="hexagon";break;case"odd":o="rect_left_inv_arrow";break;case"lean_right":o="lean_right";break;case"lean_left":o="lean_left";break;case"trapezoid":o="trapezoid";break;case"inv_trapezoid":o="inv_trapezoid";break;case"odd_right":o="rect_left_inv_arrow";break;case"circle":o="circle";break;case"ellipse":o="ellipse";break;case"stadium":o="stadium";break;case"subroutine":o="subroutine";break;case"cylinder":o="cylinder";break;case"group":o="rect";break;case"doublecircle":o="doublecircle";break;default:o="rect"}const T=await q(t,S());l.setNode(r.id,{labelStyle:w.labelStyle,shape:o,labelText:T,labelType:r.labelType,rx:b,ry:b,class:y,style:w.style,id:r.id,link:r.link,linkTarget:r.linkTarget,tooltip:d.db.getTooltip(r.id)||"",domId:d.db.lookUpDomId(r.id),haveCallback:r.haveCallback,width:r.type==="group"?500:void 0,dir:r.dir,type:r.type,props:r.props,padding:S().flowchart.padding}),g.info("setNode",{labelStyle:w.labelStyle,labelType:r.labelType,shape:o,labelText:T,rx:b,ry:b,class:y,style:w.style,id:r.id,domId:d.db.lookUpDomId(r.id),width:r.type==="group"?500:void 0,type:r.type,dir:r.dir,props:r.props,padding:S().flowchart.padding})}},M=async function(e,l,c){g.info("abc78 edges = ",e);let a=0,i={},d,u;if(e.defaultStyle!==void 0){const n=A(e.defaultStyle);d=n.style,u=n.labelStyle}for(const n of e){a++;const p="L-"+n.start+"-"+n.end;i[p]===void 0?(i[p]=0,g.info("abc78 new entry",p,i[p])):(i[p]++,g.info("abc78 new entry",p,i[p]));let r=p+"-"+i[p];g.info("abc78 new link id to be used is",p,r,i[p]);const y="LS-"+n.start,w="LE-"+n.end,t={style:"",labelStyle:""};switch(t.minlen=n.length||1,n.type==="arrow_open"?t.arrowhead="none":t.arrowhead="normal",t.arrowTypeStart="arrow_open",t.arrowTypeEnd="arrow_open",n.type){case"double_arrow_cross":t.arrowTypeStart="arrow_cross";case"arrow_cross":t.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":t.arrowTypeStart="arrow_point";case"arrow_point":t.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":t.arrowTypeStart="arrow_circle";case"arrow_circle":t.arrowTypeEnd="arrow_circle";break}let s="",b="";switch(n.stroke){case"normal":s="fill:none;",d!==void 0&&(s=d),u!==void 0&&(b=u),t.thickness="normal",t.pattern="solid";break;case"dotted":t.thickness="normal",t.pattern="dotted",t.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":t.thickness="thick",t.pattern="solid",t.style="stroke-width: 3.5px;fill:none;";break;case"invisible":t.thickness="invisible",t.pattern="solid",t.style="stroke-width: 0;fill:none;";break}if(n.style!==void 0){const o=A(n.style);s=o.style,b=o.labelStyle}t.style=t.style+=s,t.labelStyle=t.labelStyle+=b,n.interpolate!==void 0?t.curve=E(n.interpolate,L):e.defaultInterpolate!==void 0?t.curve=E(e.defaultInterpolate,L):t.curve=E(P.curve,L),n.text===void 0?n.style!==void 0&&(t.arrowheadStyle="fill: #333"):(t.arrowheadStyle="fill: #333",t.labelpos="c"),t.labelType=n.labelType,t.label=await q(n.text.replace(G.lineBreakRegex,` `),S()),n.style===void 0&&(t.style=t.style||"stroke: #333; stroke-width: 1.5px;fill:none;"),t.labelStyle=t.labelStyle.replace("color:","fill:"),t.id=r,t.classes="flowchart-link "+y+" "+w,l.setEdge(n.start,n.end,t,a)}},le=function(e,l){return l.db.getClasses()},ae=async function(e,l,c,a){g.info("Drawing flowchart");let i=a.db.getDirection();i===void 0&&(i="TD");const{securityLevel:d,flowchart:u}=S(),n=u.nodeSpacing||50,p=u.rankSpacing||50;let r;d==="sandbox"&&(r=C("#i"+l));const y=d==="sandbox"?C(r.nodes()[0].contentDocument.body):C("body"),w=d==="sandbox"?r.nodes()[0].contentDocument:document,t=new R({multigraph:!0,compound:!0}).setGraph({rankdir:i,nodesep:n,ranksep:p,marginx:0,marginy:0}).setDefaultEdgeLabel(function(){return{}});let s;const b=a.db.getSubGraphs();g.info("Subgraphs - ",b);for(let f=b.length-1;f>=0;f--)s=b[f],g.info("Subgraph - ",s),a.db.addVertex(s.id,{text:s.title,type:s.labelType},"group",void 0,s.classes,s.dir);const o=a.db.getVertices(),T=a.db.getEdges();g.info("Edges",T);let k=0;for(k=b.length-1;k>=0;k--){s=b[k],Z("cluster").append("text");for(let f=0;f{const c=Y,a=c(e,"r"),i=c(e,"g"),d=c(e,"b");return J(a,i,d,l)},ne=e=>`.label { font-family: ${e.fontFamily}; color: ${e.nodeTextColor||e.textColor}; diff --git a/assets/styles-b83b31c9-BypRRRwZ.js b/assets/styles-b83b31c9-BItTogIC.js similarity index 99% rename from assets/styles-b83b31c9-BypRRRwZ.js rename to assets/styles-b83b31c9-BItTogIC.js index 3f4236b461..3f41c525a5 100644 --- a/assets/styles-b83b31c9-BypRRRwZ.js +++ b/assets/styles-b83b31c9-BItTogIC.js @@ -1,4 +1,4 @@ -import{s as ut,g as rt,a as at,b as lt,c as F,x as ct,y as ot,j as v,A as ht,l as At,z as We,h as z,d as pt,ar as Re}from"./mermaid.core-CArNAncI.js";var Ve=function(){var e=function(x,u,a,h){for(a=a||{},h=x.length;h--;a[x[h]]=u);return a},i=[1,17],r=[1,18],l=[1,19],o=[1,39],A=[1,40],g=[1,25],D=[1,23],B=[1,24],_=[1,31],fe=[1,32],de=[1,33],Ee=[1,34],Ce=[1,35],me=[1,36],be=[1,26],ge=[1,27],ke=[1,28],Te=[1,29],d=[1,43],Fe=[1,30],E=[1,42],C=[1,44],m=[1,41],k=[1,45],ye=[1,9],c=[1,8,9],Y=[1,56],j=[1,57],Q=[1,58],X=[1,59],H=[1,60],De=[1,61],Be=[1,62],W=[1,8,9,39],Ge=[1,74],M=[1,8,9,12,13,21,37,39,42,59,60,61,62,63,64,65,70,72],q=[1,8,9,12,13,19,21,37,39,42,46,59,60,61,62,63,64,65,70,72,74,80,95,97,98],J=[13,74,80,95,97,98],G=[13,64,65,74,80,95,97,98],Ue=[13,59,60,61,62,63,74,80,95,97,98],_e=[1,93],Z=[1,110],$=[1,108],ee=[1,102],te=[1,103],se=[1,104],ie=[1,105],ne=[1,106],ue=[1,107],re=[1,109],Se=[1,8,9,37,39,42],ae=[1,8,9,21],ze=[1,8,9,78],S=[1,8,9,21,73,74,78,80,81,82,83,84,85],Ne={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,statements:5,graphConfig:6,CLASS_DIAGRAM:7,NEWLINE:8,EOF:9,statement:10,classLabel:11,SQS:12,STR:13,SQE:14,namespaceName:15,alphaNumToken:16,className:17,classLiteralName:18,GENERICTYPE:19,relationStatement:20,LABEL:21,namespaceStatement:22,classStatement:23,memberStatement:24,annotationStatement:25,clickStatement:26,styleStatement:27,cssClassStatement:28,noteStatement:29,direction:30,acc_title:31,acc_title_value:32,acc_descr:33,acc_descr_value:34,acc_descr_multiline_value:35,namespaceIdentifier:36,STRUCT_START:37,classStatements:38,STRUCT_STOP:39,NAMESPACE:40,classIdentifier:41,STYLE_SEPARATOR:42,members:43,CLASS:44,ANNOTATION_START:45,ANNOTATION_END:46,MEMBER:47,SEPARATOR:48,relation:49,NOTE_FOR:50,noteText:51,NOTE:52,direction_tb:53,direction_bt:54,direction_rl:55,direction_lr:56,relationType:57,lineType:58,AGGREGATION:59,EXTENSION:60,COMPOSITION:61,DEPENDENCY:62,LOLLIPOP:63,LINE:64,DOTTED_LINE:65,CALLBACK:66,LINK:67,LINK_TARGET:68,CLICK:69,CALLBACK_NAME:70,CALLBACK_ARGS:71,HREF:72,STYLE:73,ALPHA:74,stylesOpt:75,CSSCLASS:76,style:77,COMMA:78,styleComponent:79,NUM:80,COLON:81,UNIT:82,SPACE:83,BRKT:84,PCT:85,commentToken:86,textToken:87,graphCodeTokens:88,textNoTagsToken:89,TAGSTART:90,TAGEND:91,"==":92,"--":93,DEFAULT:94,MINUS:95,keywords:96,UNICODE_TEXT:97,BQUOTE_STR:98,$accept:0,$end:1},terminals_:{2:"error",7:"CLASS_DIAGRAM",8:"NEWLINE",9:"EOF",12:"SQS",13:"STR",14:"SQE",19:"GENERICTYPE",21:"LABEL",31:"acc_title",32:"acc_title_value",33:"acc_descr",34:"acc_descr_value",35:"acc_descr_multiline_value",37:"STRUCT_START",39:"STRUCT_STOP",40:"NAMESPACE",42:"STYLE_SEPARATOR",44:"CLASS",45:"ANNOTATION_START",46:"ANNOTATION_END",47:"MEMBER",48:"SEPARATOR",50:"NOTE_FOR",52:"NOTE",53:"direction_tb",54:"direction_bt",55:"direction_rl",56:"direction_lr",59:"AGGREGATION",60:"EXTENSION",61:"COMPOSITION",62:"DEPENDENCY",63:"LOLLIPOP",64:"LINE",65:"DOTTED_LINE",66:"CALLBACK",67:"LINK",68:"LINK_TARGET",69:"CLICK",70:"CALLBACK_NAME",71:"CALLBACK_ARGS",72:"HREF",73:"STYLE",74:"ALPHA",76:"CSSCLASS",78:"COMMA",80:"NUM",81:"COLON",82:"UNIT",83:"SPACE",84:"BRKT",85:"PCT",88:"graphCodeTokens",90:"TAGSTART",91:"TAGEND",92:"==",93:"--",94:"DEFAULT",95:"MINUS",96:"keywords",97:"UNICODE_TEXT",98:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[4,1],[6,4],[5,1],[5,2],[5,3],[11,3],[15,1],[15,2],[17,1],[17,1],[17,2],[17,2],[17,2],[10,1],[10,2],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,2],[10,1],[22,4],[22,5],[36,2],[38,1],[38,2],[38,3],[23,1],[23,3],[23,4],[23,6],[41,2],[41,3],[25,4],[43,1],[43,2],[24,1],[24,2],[24,1],[24,1],[20,3],[20,4],[20,4],[20,5],[29,3],[29,2],[30,1],[30,1],[30,1],[30,1],[49,3],[49,2],[49,2],[49,1],[57,1],[57,1],[57,1],[57,1],[57,1],[58,1],[58,1],[26,3],[26,4],[26,3],[26,4],[26,4],[26,5],[26,3],[26,4],[26,4],[26,5],[26,4],[26,5],[26,5],[26,6],[27,3],[28,3],[75,1],[75,3],[77,1],[77,2],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[86,1],[86,1],[87,1],[87,1],[87,1],[87,1],[87,1],[87,1],[87,1],[89,1],[89,1],[89,1],[89,1],[16,1],[16,1],[16,1],[16,1],[18,1],[51,1]],performAction:function(u,a,h,n,f,t,U){var s=t.length-1;switch(f){case 8:this.$=t[s-1];break;case 9:case 11:case 12:this.$=t[s];break;case 10:case 13:this.$=t[s-1]+t[s];break;case 14:case 15:this.$=t[s-1]+"~"+t[s]+"~";break;case 16:n.addRelation(t[s]);break;case 17:t[s-1].title=n.cleanupLabel(t[s]),n.addRelation(t[s-1]);break;case 27:this.$=t[s].trim(),n.setAccTitle(this.$);break;case 28:case 29:this.$=t[s].trim(),n.setAccDescription(this.$);break;case 30:n.addClassesToNamespace(t[s-3],t[s-1]);break;case 31:n.addClassesToNamespace(t[s-4],t[s-1]);break;case 32:this.$=t[s],n.addNamespace(t[s]);break;case 33:this.$=[t[s]];break;case 34:this.$=[t[s-1]];break;case 35:t[s].unshift(t[s-2]),this.$=t[s];break;case 37:n.setCssClass(t[s-2],t[s]);break;case 38:n.addMembers(t[s-3],t[s-1]);break;case 39:n.setCssClass(t[s-5],t[s-3]),n.addMembers(t[s-5],t[s-1]);break;case 40:this.$=t[s],n.addClass(t[s]);break;case 41:this.$=t[s-1],n.addClass(t[s-1]),n.setClassLabel(t[s-1],t[s]);break;case 42:n.addAnnotation(t[s],t[s-2]);break;case 43:this.$=[t[s]];break;case 44:t[s].push(t[s-1]),this.$=t[s];break;case 45:break;case 46:n.addMember(t[s-1],n.cleanupLabel(t[s]));break;case 47:break;case 48:break;case 49:this.$={id1:t[s-2],id2:t[s],relation:t[s-1],relationTitle1:"none",relationTitle2:"none"};break;case 50:this.$={id1:t[s-3],id2:t[s],relation:t[s-1],relationTitle1:t[s-2],relationTitle2:"none"};break;case 51:this.$={id1:t[s-3],id2:t[s],relation:t[s-2],relationTitle1:"none",relationTitle2:t[s-1]};break;case 52:this.$={id1:t[s-4],id2:t[s],relation:t[s-2],relationTitle1:t[s-3],relationTitle2:t[s-1]};break;case 53:n.addNote(t[s],t[s-1]);break;case 54:n.addNote(t[s]);break;case 55:n.setDirection("TB");break;case 56:n.setDirection("BT");break;case 57:n.setDirection("RL");break;case 58:n.setDirection("LR");break;case 59:this.$={type1:t[s-2],type2:t[s],lineType:t[s-1]};break;case 60:this.$={type1:"none",type2:t[s],lineType:t[s-1]};break;case 61:this.$={type1:t[s-1],type2:"none",lineType:t[s]};break;case 62:this.$={type1:"none",type2:"none",lineType:t[s]};break;case 63:this.$=n.relationType.AGGREGATION;break;case 64:this.$=n.relationType.EXTENSION;break;case 65:this.$=n.relationType.COMPOSITION;break;case 66:this.$=n.relationType.DEPENDENCY;break;case 67:this.$=n.relationType.LOLLIPOP;break;case 68:this.$=n.lineType.LINE;break;case 69:this.$=n.lineType.DOTTED_LINE;break;case 70:case 76:this.$=t[s-2],n.setClickEvent(t[s-1],t[s]);break;case 71:case 77:this.$=t[s-3],n.setClickEvent(t[s-2],t[s-1]),n.setTooltip(t[s-2],t[s]);break;case 72:this.$=t[s-2],n.setLink(t[s-1],t[s]);break;case 73:this.$=t[s-3],n.setLink(t[s-2],t[s-1],t[s]);break;case 74:this.$=t[s-3],n.setLink(t[s-2],t[s-1]),n.setTooltip(t[s-2],t[s]);break;case 75:this.$=t[s-4],n.setLink(t[s-3],t[s-2],t[s]),n.setTooltip(t[s-3],t[s-1]);break;case 78:this.$=t[s-3],n.setClickEvent(t[s-2],t[s-1],t[s]);break;case 79:this.$=t[s-4],n.setClickEvent(t[s-3],t[s-2],t[s-1]),n.setTooltip(t[s-3],t[s]);break;case 80:this.$=t[s-3],n.setLink(t[s-2],t[s]);break;case 81:this.$=t[s-4],n.setLink(t[s-3],t[s-1],t[s]);break;case 82:this.$=t[s-4],n.setLink(t[s-3],t[s-1]),n.setTooltip(t[s-3],t[s]);break;case 83:this.$=t[s-5],n.setLink(t[s-4],t[s-2],t[s]),n.setTooltip(t[s-4],t[s-1]);break;case 84:this.$=t[s-2],n.setCssStyle(t[s-1],t[s]);break;case 85:n.setCssClass(t[s-1],t[s]);break;case 86:this.$=[t[s]];break;case 87:t[s-2].push(t[s]),this.$=t[s-2];break;case 89:this.$=t[s-1]+t[s];break}},table:[{3:1,4:2,5:3,6:4,7:[1,6],10:5,16:37,17:20,18:38,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:16,31:i,33:r,35:l,36:21,40:o,41:22,44:A,45:g,47:D,48:B,50:_,52:fe,53:de,54:Ee,55:Ce,56:me,66:be,67:ge,69:ke,73:Te,74:d,76:Fe,80:E,95:C,97:m,98:k},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,3]},e(ye,[2,5],{8:[1,46]}),{8:[1,47]},e(c,[2,16],{21:[1,48]}),e(c,[2,18]),e(c,[2,19]),e(c,[2,20]),e(c,[2,21]),e(c,[2,22]),e(c,[2,23]),e(c,[2,24]),e(c,[2,25]),e(c,[2,26]),{32:[1,49]},{34:[1,50]},e(c,[2,29]),e(c,[2,45],{49:51,57:54,58:55,13:[1,52],21:[1,53],59:Y,60:j,61:Q,62:X,63:H,64:De,65:Be}),{37:[1,63]},e(W,[2,36],{37:[1,65],42:[1,64]}),e(c,[2,47]),e(c,[2,48]),{16:66,74:d,80:E,95:C,97:m},{16:37,17:67,18:38,74:d,80:E,95:C,97:m,98:k},{16:37,17:68,18:38,74:d,80:E,95:C,97:m,98:k},{16:37,17:69,18:38,74:d,80:E,95:C,97:m,98:k},{74:[1,70]},{13:[1,71]},{16:37,17:72,18:38,74:d,80:E,95:C,97:m,98:k},{13:Ge,51:73},e(c,[2,55]),e(c,[2,56]),e(c,[2,57]),e(c,[2,58]),e(M,[2,11],{16:37,18:38,17:75,19:[1,76],74:d,80:E,95:C,97:m,98:k}),e(M,[2,12],{19:[1,77]}),{15:78,16:79,74:d,80:E,95:C,97:m},{16:37,17:80,18:38,74:d,80:E,95:C,97:m,98:k},e(q,[2,112]),e(q,[2,113]),e(q,[2,114]),e(q,[2,115]),e([1,8,9,12,13,19,21,37,39,42,59,60,61,62,63,64,65,70,72],[2,116]),e(ye,[2,6],{10:5,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:16,17:20,36:21,41:22,16:37,18:38,5:81,31:i,33:r,35:l,40:o,44:A,45:g,47:D,48:B,50:_,52:fe,53:de,54:Ee,55:Ce,56:me,66:be,67:ge,69:ke,73:Te,74:d,76:Fe,80:E,95:C,97:m,98:k}),{5:82,10:5,16:37,17:20,18:38,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:16,31:i,33:r,35:l,36:21,40:o,41:22,44:A,45:g,47:D,48:B,50:_,52:fe,53:de,54:Ee,55:Ce,56:me,66:be,67:ge,69:ke,73:Te,74:d,76:Fe,80:E,95:C,97:m,98:k},e(c,[2,17]),e(c,[2,27]),e(c,[2,28]),{13:[1,84],16:37,17:83,18:38,74:d,80:E,95:C,97:m,98:k},{49:85,57:54,58:55,59:Y,60:j,61:Q,62:X,63:H,64:De,65:Be},e(c,[2,46]),{58:86,64:De,65:Be},e(J,[2,62],{57:87,59:Y,60:j,61:Q,62:X,63:H}),e(G,[2,63]),e(G,[2,64]),e(G,[2,65]),e(G,[2,66]),e(G,[2,67]),e(Ue,[2,68]),e(Ue,[2,69]),{8:[1,89],23:90,38:88,41:22,44:A},{16:91,74:d,80:E,95:C,97:m},{43:92,47:_e},{46:[1,94]},{13:[1,95]},{13:[1,96]},{70:[1,97],72:[1,98]},{21:Z,73:$,74:ee,75:99,77:100,79:101,80:te,81:se,82:ie,83:ne,84:ue,85:re},{74:[1,111]},{13:Ge,51:112},e(c,[2,54]),e(c,[2,117]),e(M,[2,13]),e(M,[2,14]),e(M,[2,15]),{37:[2,32]},{15:113,16:79,37:[2,9],74:d,80:E,95:C,97:m},e(Se,[2,40],{11:114,12:[1,115]}),e(ye,[2,7]),{9:[1,116]},e(ae,[2,49]),{16:37,17:117,18:38,74:d,80:E,95:C,97:m,98:k},{13:[1,119],16:37,17:118,18:38,74:d,80:E,95:C,97:m,98:k},e(J,[2,61],{57:120,59:Y,60:j,61:Q,62:X,63:H}),e(J,[2,60]),{39:[1,121]},{23:90,38:122,41:22,44:A},{8:[1,123],39:[2,33]},e(W,[2,37],{37:[1,124]}),{39:[1,125]},{39:[2,43],43:126,47:_e},{16:37,17:127,18:38,74:d,80:E,95:C,97:m,98:k},e(c,[2,70],{13:[1,128]}),e(c,[2,72],{13:[1,130],68:[1,129]}),e(c,[2,76],{13:[1,131],71:[1,132]}),{13:[1,133]},e(c,[2,84],{78:[1,134]}),e(ze,[2,86],{79:135,21:Z,73:$,74:ee,80:te,81:se,82:ie,83:ne,84:ue,85:re}),e(S,[2,88]),e(S,[2,90]),e(S,[2,91]),e(S,[2,92]),e(S,[2,93]),e(S,[2,94]),e(S,[2,95]),e(S,[2,96]),e(S,[2,97]),e(S,[2,98]),e(c,[2,85]),e(c,[2,53]),{37:[2,10]},e(Se,[2,41]),{13:[1,136]},{1:[2,4]},e(ae,[2,51]),e(ae,[2,50]),{16:37,17:137,18:38,74:d,80:E,95:C,97:m,98:k},e(J,[2,59]),e(c,[2,30]),{39:[1,138]},{23:90,38:139,39:[2,34],41:22,44:A},{43:140,47:_e},e(W,[2,38]),{39:[2,44]},e(c,[2,42]),e(c,[2,71]),e(c,[2,73]),e(c,[2,74],{68:[1,141]}),e(c,[2,77]),e(c,[2,78],{13:[1,142]}),e(c,[2,80],{13:[1,144],68:[1,143]}),{21:Z,73:$,74:ee,77:145,79:101,80:te,81:se,82:ie,83:ne,84:ue,85:re},e(S,[2,89]),{14:[1,146]},e(ae,[2,52]),e(c,[2,31]),{39:[2,35]},{39:[1,147]},e(c,[2,75]),e(c,[2,79]),e(c,[2,81]),e(c,[2,82],{68:[1,148]}),e(ze,[2,87],{79:135,21:Z,73:$,74:ee,80:te,81:se,82:ie,83:ne,84:ue,85:re}),e(Se,[2,8]),e(W,[2,39]),e(c,[2,83])],defaultActions:{2:[2,1],3:[2,2],4:[2,3],78:[2,32],113:[2,10],116:[2,4],126:[2,44],139:[2,35]},parseError:function(u,a){if(a.recoverable)this.trace(u);else{var h=new Error(u);throw h.hash=a,h}},parse:function(u){var a=this,h=[0],n=[],f=[null],t=[],U=this.table,s="",le=0,Ke=0,tt=2,Ye=1,st=t.slice.call(arguments,1),b=Object.create(this.lexer),I={yy:{}};for(var ve in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ve)&&(I.yy[ve]=this.yy[ve]);b.setInput(u,I.yy),I.yy.lexer=b,I.yy.parser=this,typeof b.yylloc>"u"&&(b.yylloc={});var xe=b.yylloc;t.push(xe);var it=b.options&&b.options.ranges;typeof I.yy.parseError=="function"?this.parseError=I.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function nt(){var L;return L=n.pop()||b.lex()||Ye,typeof L!="number"&&(L instanceof Array&&(n=L,L=n.pop()),L=a.symbols_[L]||L),L}for(var T,R,y,Oe,P={},ce,N,je,oe;;){if(R=h[h.length-1],this.defaultActions[R]?y=this.defaultActions[R]:((T===null||typeof T>"u")&&(T=nt()),y=U[R]&&U[R][T]),typeof y>"u"||!y.length||!y[0]){var Ie="";oe=[];for(ce in U[R])this.terminals_[ce]&&ce>tt&&oe.push("'"+this.terminals_[ce]+"'");b.showPosition?Ie="Parse error on line "+(le+1)+`: +import{s as ut,g as rt,a as at,b as lt,c as F,x as ct,y as ot,j as v,A as ht,l as At,z as We,h as z,d as pt,ar as Re}from"./mermaid.core-Bq0kX0MS.js";var Ve=function(){var e=function(x,u,a,h){for(a=a||{},h=x.length;h--;a[x[h]]=u);return a},i=[1,17],r=[1,18],l=[1,19],o=[1,39],A=[1,40],g=[1,25],D=[1,23],B=[1,24],_=[1,31],fe=[1,32],de=[1,33],Ee=[1,34],Ce=[1,35],me=[1,36],be=[1,26],ge=[1,27],ke=[1,28],Te=[1,29],d=[1,43],Fe=[1,30],E=[1,42],C=[1,44],m=[1,41],k=[1,45],ye=[1,9],c=[1,8,9],Y=[1,56],j=[1,57],Q=[1,58],X=[1,59],H=[1,60],De=[1,61],Be=[1,62],W=[1,8,9,39],Ge=[1,74],M=[1,8,9,12,13,21,37,39,42,59,60,61,62,63,64,65,70,72],q=[1,8,9,12,13,19,21,37,39,42,46,59,60,61,62,63,64,65,70,72,74,80,95,97,98],J=[13,74,80,95,97,98],G=[13,64,65,74,80,95,97,98],Ue=[13,59,60,61,62,63,74,80,95,97,98],_e=[1,93],Z=[1,110],$=[1,108],ee=[1,102],te=[1,103],se=[1,104],ie=[1,105],ne=[1,106],ue=[1,107],re=[1,109],Se=[1,8,9,37,39,42],ae=[1,8,9,21],ze=[1,8,9,78],S=[1,8,9,21,73,74,78,80,81,82,83,84,85],Ne={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,statements:5,graphConfig:6,CLASS_DIAGRAM:7,NEWLINE:8,EOF:9,statement:10,classLabel:11,SQS:12,STR:13,SQE:14,namespaceName:15,alphaNumToken:16,className:17,classLiteralName:18,GENERICTYPE:19,relationStatement:20,LABEL:21,namespaceStatement:22,classStatement:23,memberStatement:24,annotationStatement:25,clickStatement:26,styleStatement:27,cssClassStatement:28,noteStatement:29,direction:30,acc_title:31,acc_title_value:32,acc_descr:33,acc_descr_value:34,acc_descr_multiline_value:35,namespaceIdentifier:36,STRUCT_START:37,classStatements:38,STRUCT_STOP:39,NAMESPACE:40,classIdentifier:41,STYLE_SEPARATOR:42,members:43,CLASS:44,ANNOTATION_START:45,ANNOTATION_END:46,MEMBER:47,SEPARATOR:48,relation:49,NOTE_FOR:50,noteText:51,NOTE:52,direction_tb:53,direction_bt:54,direction_rl:55,direction_lr:56,relationType:57,lineType:58,AGGREGATION:59,EXTENSION:60,COMPOSITION:61,DEPENDENCY:62,LOLLIPOP:63,LINE:64,DOTTED_LINE:65,CALLBACK:66,LINK:67,LINK_TARGET:68,CLICK:69,CALLBACK_NAME:70,CALLBACK_ARGS:71,HREF:72,STYLE:73,ALPHA:74,stylesOpt:75,CSSCLASS:76,style:77,COMMA:78,styleComponent:79,NUM:80,COLON:81,UNIT:82,SPACE:83,BRKT:84,PCT:85,commentToken:86,textToken:87,graphCodeTokens:88,textNoTagsToken:89,TAGSTART:90,TAGEND:91,"==":92,"--":93,DEFAULT:94,MINUS:95,keywords:96,UNICODE_TEXT:97,BQUOTE_STR:98,$accept:0,$end:1},terminals_:{2:"error",7:"CLASS_DIAGRAM",8:"NEWLINE",9:"EOF",12:"SQS",13:"STR",14:"SQE",19:"GENERICTYPE",21:"LABEL",31:"acc_title",32:"acc_title_value",33:"acc_descr",34:"acc_descr_value",35:"acc_descr_multiline_value",37:"STRUCT_START",39:"STRUCT_STOP",40:"NAMESPACE",42:"STYLE_SEPARATOR",44:"CLASS",45:"ANNOTATION_START",46:"ANNOTATION_END",47:"MEMBER",48:"SEPARATOR",50:"NOTE_FOR",52:"NOTE",53:"direction_tb",54:"direction_bt",55:"direction_rl",56:"direction_lr",59:"AGGREGATION",60:"EXTENSION",61:"COMPOSITION",62:"DEPENDENCY",63:"LOLLIPOP",64:"LINE",65:"DOTTED_LINE",66:"CALLBACK",67:"LINK",68:"LINK_TARGET",69:"CLICK",70:"CALLBACK_NAME",71:"CALLBACK_ARGS",72:"HREF",73:"STYLE",74:"ALPHA",76:"CSSCLASS",78:"COMMA",80:"NUM",81:"COLON",82:"UNIT",83:"SPACE",84:"BRKT",85:"PCT",88:"graphCodeTokens",90:"TAGSTART",91:"TAGEND",92:"==",93:"--",94:"DEFAULT",95:"MINUS",96:"keywords",97:"UNICODE_TEXT",98:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[4,1],[6,4],[5,1],[5,2],[5,3],[11,3],[15,1],[15,2],[17,1],[17,1],[17,2],[17,2],[17,2],[10,1],[10,2],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,2],[10,1],[22,4],[22,5],[36,2],[38,1],[38,2],[38,3],[23,1],[23,3],[23,4],[23,6],[41,2],[41,3],[25,4],[43,1],[43,2],[24,1],[24,2],[24,1],[24,1],[20,3],[20,4],[20,4],[20,5],[29,3],[29,2],[30,1],[30,1],[30,1],[30,1],[49,3],[49,2],[49,2],[49,1],[57,1],[57,1],[57,1],[57,1],[57,1],[58,1],[58,1],[26,3],[26,4],[26,3],[26,4],[26,4],[26,5],[26,3],[26,4],[26,4],[26,5],[26,4],[26,5],[26,5],[26,6],[27,3],[28,3],[75,1],[75,3],[77,1],[77,2],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[79,1],[86,1],[86,1],[87,1],[87,1],[87,1],[87,1],[87,1],[87,1],[87,1],[89,1],[89,1],[89,1],[89,1],[16,1],[16,1],[16,1],[16,1],[18,1],[51,1]],performAction:function(u,a,h,n,f,t,U){var s=t.length-1;switch(f){case 8:this.$=t[s-1];break;case 9:case 11:case 12:this.$=t[s];break;case 10:case 13:this.$=t[s-1]+t[s];break;case 14:case 15:this.$=t[s-1]+"~"+t[s]+"~";break;case 16:n.addRelation(t[s]);break;case 17:t[s-1].title=n.cleanupLabel(t[s]),n.addRelation(t[s-1]);break;case 27:this.$=t[s].trim(),n.setAccTitle(this.$);break;case 28:case 29:this.$=t[s].trim(),n.setAccDescription(this.$);break;case 30:n.addClassesToNamespace(t[s-3],t[s-1]);break;case 31:n.addClassesToNamespace(t[s-4],t[s-1]);break;case 32:this.$=t[s],n.addNamespace(t[s]);break;case 33:this.$=[t[s]];break;case 34:this.$=[t[s-1]];break;case 35:t[s].unshift(t[s-2]),this.$=t[s];break;case 37:n.setCssClass(t[s-2],t[s]);break;case 38:n.addMembers(t[s-3],t[s-1]);break;case 39:n.setCssClass(t[s-5],t[s-3]),n.addMembers(t[s-5],t[s-1]);break;case 40:this.$=t[s],n.addClass(t[s]);break;case 41:this.$=t[s-1],n.addClass(t[s-1]),n.setClassLabel(t[s-1],t[s]);break;case 42:n.addAnnotation(t[s],t[s-2]);break;case 43:this.$=[t[s]];break;case 44:t[s].push(t[s-1]),this.$=t[s];break;case 45:break;case 46:n.addMember(t[s-1],n.cleanupLabel(t[s]));break;case 47:break;case 48:break;case 49:this.$={id1:t[s-2],id2:t[s],relation:t[s-1],relationTitle1:"none",relationTitle2:"none"};break;case 50:this.$={id1:t[s-3],id2:t[s],relation:t[s-1],relationTitle1:t[s-2],relationTitle2:"none"};break;case 51:this.$={id1:t[s-3],id2:t[s],relation:t[s-2],relationTitle1:"none",relationTitle2:t[s-1]};break;case 52:this.$={id1:t[s-4],id2:t[s],relation:t[s-2],relationTitle1:t[s-3],relationTitle2:t[s-1]};break;case 53:n.addNote(t[s],t[s-1]);break;case 54:n.addNote(t[s]);break;case 55:n.setDirection("TB");break;case 56:n.setDirection("BT");break;case 57:n.setDirection("RL");break;case 58:n.setDirection("LR");break;case 59:this.$={type1:t[s-2],type2:t[s],lineType:t[s-1]};break;case 60:this.$={type1:"none",type2:t[s],lineType:t[s-1]};break;case 61:this.$={type1:t[s-1],type2:"none",lineType:t[s]};break;case 62:this.$={type1:"none",type2:"none",lineType:t[s]};break;case 63:this.$=n.relationType.AGGREGATION;break;case 64:this.$=n.relationType.EXTENSION;break;case 65:this.$=n.relationType.COMPOSITION;break;case 66:this.$=n.relationType.DEPENDENCY;break;case 67:this.$=n.relationType.LOLLIPOP;break;case 68:this.$=n.lineType.LINE;break;case 69:this.$=n.lineType.DOTTED_LINE;break;case 70:case 76:this.$=t[s-2],n.setClickEvent(t[s-1],t[s]);break;case 71:case 77:this.$=t[s-3],n.setClickEvent(t[s-2],t[s-1]),n.setTooltip(t[s-2],t[s]);break;case 72:this.$=t[s-2],n.setLink(t[s-1],t[s]);break;case 73:this.$=t[s-3],n.setLink(t[s-2],t[s-1],t[s]);break;case 74:this.$=t[s-3],n.setLink(t[s-2],t[s-1]),n.setTooltip(t[s-2],t[s]);break;case 75:this.$=t[s-4],n.setLink(t[s-3],t[s-2],t[s]),n.setTooltip(t[s-3],t[s-1]);break;case 78:this.$=t[s-3],n.setClickEvent(t[s-2],t[s-1],t[s]);break;case 79:this.$=t[s-4],n.setClickEvent(t[s-3],t[s-2],t[s-1]),n.setTooltip(t[s-3],t[s]);break;case 80:this.$=t[s-3],n.setLink(t[s-2],t[s]);break;case 81:this.$=t[s-4],n.setLink(t[s-3],t[s-1],t[s]);break;case 82:this.$=t[s-4],n.setLink(t[s-3],t[s-1]),n.setTooltip(t[s-3],t[s]);break;case 83:this.$=t[s-5],n.setLink(t[s-4],t[s-2],t[s]),n.setTooltip(t[s-4],t[s-1]);break;case 84:this.$=t[s-2],n.setCssStyle(t[s-1],t[s]);break;case 85:n.setCssClass(t[s-1],t[s]);break;case 86:this.$=[t[s]];break;case 87:t[s-2].push(t[s]),this.$=t[s-2];break;case 89:this.$=t[s-1]+t[s];break}},table:[{3:1,4:2,5:3,6:4,7:[1,6],10:5,16:37,17:20,18:38,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:16,31:i,33:r,35:l,36:21,40:o,41:22,44:A,45:g,47:D,48:B,50:_,52:fe,53:de,54:Ee,55:Ce,56:me,66:be,67:ge,69:ke,73:Te,74:d,76:Fe,80:E,95:C,97:m,98:k},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,3]},e(ye,[2,5],{8:[1,46]}),{8:[1,47]},e(c,[2,16],{21:[1,48]}),e(c,[2,18]),e(c,[2,19]),e(c,[2,20]),e(c,[2,21]),e(c,[2,22]),e(c,[2,23]),e(c,[2,24]),e(c,[2,25]),e(c,[2,26]),{32:[1,49]},{34:[1,50]},e(c,[2,29]),e(c,[2,45],{49:51,57:54,58:55,13:[1,52],21:[1,53],59:Y,60:j,61:Q,62:X,63:H,64:De,65:Be}),{37:[1,63]},e(W,[2,36],{37:[1,65],42:[1,64]}),e(c,[2,47]),e(c,[2,48]),{16:66,74:d,80:E,95:C,97:m},{16:37,17:67,18:38,74:d,80:E,95:C,97:m,98:k},{16:37,17:68,18:38,74:d,80:E,95:C,97:m,98:k},{16:37,17:69,18:38,74:d,80:E,95:C,97:m,98:k},{74:[1,70]},{13:[1,71]},{16:37,17:72,18:38,74:d,80:E,95:C,97:m,98:k},{13:Ge,51:73},e(c,[2,55]),e(c,[2,56]),e(c,[2,57]),e(c,[2,58]),e(M,[2,11],{16:37,18:38,17:75,19:[1,76],74:d,80:E,95:C,97:m,98:k}),e(M,[2,12],{19:[1,77]}),{15:78,16:79,74:d,80:E,95:C,97:m},{16:37,17:80,18:38,74:d,80:E,95:C,97:m,98:k},e(q,[2,112]),e(q,[2,113]),e(q,[2,114]),e(q,[2,115]),e([1,8,9,12,13,19,21,37,39,42,59,60,61,62,63,64,65,70,72],[2,116]),e(ye,[2,6],{10:5,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:16,17:20,36:21,41:22,16:37,18:38,5:81,31:i,33:r,35:l,40:o,44:A,45:g,47:D,48:B,50:_,52:fe,53:de,54:Ee,55:Ce,56:me,66:be,67:ge,69:ke,73:Te,74:d,76:Fe,80:E,95:C,97:m,98:k}),{5:82,10:5,16:37,17:20,18:38,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:16,31:i,33:r,35:l,36:21,40:o,41:22,44:A,45:g,47:D,48:B,50:_,52:fe,53:de,54:Ee,55:Ce,56:me,66:be,67:ge,69:ke,73:Te,74:d,76:Fe,80:E,95:C,97:m,98:k},e(c,[2,17]),e(c,[2,27]),e(c,[2,28]),{13:[1,84],16:37,17:83,18:38,74:d,80:E,95:C,97:m,98:k},{49:85,57:54,58:55,59:Y,60:j,61:Q,62:X,63:H,64:De,65:Be},e(c,[2,46]),{58:86,64:De,65:Be},e(J,[2,62],{57:87,59:Y,60:j,61:Q,62:X,63:H}),e(G,[2,63]),e(G,[2,64]),e(G,[2,65]),e(G,[2,66]),e(G,[2,67]),e(Ue,[2,68]),e(Ue,[2,69]),{8:[1,89],23:90,38:88,41:22,44:A},{16:91,74:d,80:E,95:C,97:m},{43:92,47:_e},{46:[1,94]},{13:[1,95]},{13:[1,96]},{70:[1,97],72:[1,98]},{21:Z,73:$,74:ee,75:99,77:100,79:101,80:te,81:se,82:ie,83:ne,84:ue,85:re},{74:[1,111]},{13:Ge,51:112},e(c,[2,54]),e(c,[2,117]),e(M,[2,13]),e(M,[2,14]),e(M,[2,15]),{37:[2,32]},{15:113,16:79,37:[2,9],74:d,80:E,95:C,97:m},e(Se,[2,40],{11:114,12:[1,115]}),e(ye,[2,7]),{9:[1,116]},e(ae,[2,49]),{16:37,17:117,18:38,74:d,80:E,95:C,97:m,98:k},{13:[1,119],16:37,17:118,18:38,74:d,80:E,95:C,97:m,98:k},e(J,[2,61],{57:120,59:Y,60:j,61:Q,62:X,63:H}),e(J,[2,60]),{39:[1,121]},{23:90,38:122,41:22,44:A},{8:[1,123],39:[2,33]},e(W,[2,37],{37:[1,124]}),{39:[1,125]},{39:[2,43],43:126,47:_e},{16:37,17:127,18:38,74:d,80:E,95:C,97:m,98:k},e(c,[2,70],{13:[1,128]}),e(c,[2,72],{13:[1,130],68:[1,129]}),e(c,[2,76],{13:[1,131],71:[1,132]}),{13:[1,133]},e(c,[2,84],{78:[1,134]}),e(ze,[2,86],{79:135,21:Z,73:$,74:ee,80:te,81:se,82:ie,83:ne,84:ue,85:re}),e(S,[2,88]),e(S,[2,90]),e(S,[2,91]),e(S,[2,92]),e(S,[2,93]),e(S,[2,94]),e(S,[2,95]),e(S,[2,96]),e(S,[2,97]),e(S,[2,98]),e(c,[2,85]),e(c,[2,53]),{37:[2,10]},e(Se,[2,41]),{13:[1,136]},{1:[2,4]},e(ae,[2,51]),e(ae,[2,50]),{16:37,17:137,18:38,74:d,80:E,95:C,97:m,98:k},e(J,[2,59]),e(c,[2,30]),{39:[1,138]},{23:90,38:139,39:[2,34],41:22,44:A},{43:140,47:_e},e(W,[2,38]),{39:[2,44]},e(c,[2,42]),e(c,[2,71]),e(c,[2,73]),e(c,[2,74],{68:[1,141]}),e(c,[2,77]),e(c,[2,78],{13:[1,142]}),e(c,[2,80],{13:[1,144],68:[1,143]}),{21:Z,73:$,74:ee,77:145,79:101,80:te,81:se,82:ie,83:ne,84:ue,85:re},e(S,[2,89]),{14:[1,146]},e(ae,[2,52]),e(c,[2,31]),{39:[2,35]},{39:[1,147]},e(c,[2,75]),e(c,[2,79]),e(c,[2,81]),e(c,[2,82],{68:[1,148]}),e(ze,[2,87],{79:135,21:Z,73:$,74:ee,80:te,81:se,82:ie,83:ne,84:ue,85:re}),e(Se,[2,8]),e(W,[2,39]),e(c,[2,83])],defaultActions:{2:[2,1],3:[2,2],4:[2,3],78:[2,32],113:[2,10],116:[2,4],126:[2,44],139:[2,35]},parseError:function(u,a){if(a.recoverable)this.trace(u);else{var h=new Error(u);throw h.hash=a,h}},parse:function(u){var a=this,h=[0],n=[],f=[null],t=[],U=this.table,s="",le=0,Ke=0,tt=2,Ye=1,st=t.slice.call(arguments,1),b=Object.create(this.lexer),I={yy:{}};for(var ve in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ve)&&(I.yy[ve]=this.yy[ve]);b.setInput(u,I.yy),I.yy.lexer=b,I.yy.parser=this,typeof b.yylloc>"u"&&(b.yylloc={});var xe=b.yylloc;t.push(xe);var it=b.options&&b.options.ranges;typeof I.yy.parseError=="function"?this.parseError=I.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function nt(){var L;return L=n.pop()||b.lex()||Ye,typeof L!="number"&&(L instanceof Array&&(n=L,L=n.pop()),L=a.symbols_[L]||L),L}for(var T,R,y,Oe,P={},ce,N,je,oe;;){if(R=h[h.length-1],this.defaultActions[R]?y=this.defaultActions[R]:((T===null||typeof T>"u")&&(T=nt()),y=U[R]&&U[R][T]),typeof y>"u"||!y.length||!y[0]){var Ie="";oe=[];for(ce in U[R])this.terminals_[ce]&&ce>tt&&oe.push("'"+this.terminals_[ce]+"'");b.showPosition?Ie="Parse error on line "+(le+1)+`: `+b.showPosition()+` Expecting `+oe.join(", ")+", got '"+(this.terminals_[T]||T)+"'":Ie="Parse error on line "+(le+1)+": Unexpected "+(T==Ye?"end of input":"'"+(this.terminals_[T]||T)+"'"),this.parseError(Ie,{text:b.match,token:this.terminals_[T]||T,line:b.yylineno,loc:xe,expected:oe})}if(y[0]instanceof Array&&y.length>1)throw new Error("Parse Error: multiple actions possible at state: "+R+", token: "+T);switch(y[0]){case 1:h.push(T),f.push(b.yytext),t.push(b.yylloc),h.push(y[1]),T=null,Ke=b.yyleng,s=b.yytext,le=b.yylineno,xe=b.yylloc;break;case 2:if(N=this.productions_[y[1]][1],P.$=f[f.length-N],P._$={first_line:t[t.length-(N||1)].first_line,last_line:t[t.length-1].last_line,first_column:t[t.length-(N||1)].first_column,last_column:t[t.length-1].last_column},it&&(P._$.range=[t[t.length-(N||1)].range[0],t[t.length-1].range[1]]),Oe=this.performAction.apply(P,[s,Ke,le,I.yy,y[1],f,t].concat(st)),typeof Oe<"u")return Oe;N&&(h=h.slice(0,-1*N*2),f=f.slice(0,-1*N),t=t.slice(0,-1*N)),h.push(this.productions_[y[1]][0]),f.push(P.$),t.push(P._$),je=U[h[h.length-2]][h[h.length-1]],h.push(je);break;case 3:return!0}}return!0}},et=function(){var x={EOF:1,parseError:function(a,h){if(this.yy.parser)this.yy.parser.parseError(a,h);else throw new Error(a)},setInput:function(u,a){return this.yy=a||this.yy||{},this._input=u,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var u=this._input[0];this.yytext+=u,this.yyleng++,this.offset++,this.match+=u,this.matched+=u;var a=u.match(/(?:\r\n?|\n).*/g);return a?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),u},unput:function(u){var a=u.length,h=u.split(/(?:\r\n?|\n)/g);this._input=u+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-a),this.offset-=a;var n=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),h.length-1&&(this.yylineno-=h.length-1);var f=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:h?(h.length===n.length?this.yylloc.first_column:0)+n[n.length-h.length].length-h[0].length:this.yylloc.first_column-a},this.options.ranges&&(this.yylloc.range=[f[0],f[0]+this.yyleng-a]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(u){this.unput(this.match.slice(u))},pastInput:function(){var u=this.matched.substr(0,this.matched.length-this.match.length);return(u.length>20?"...":"")+u.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var u=this.match;return u.length<20&&(u+=this._input.substr(0,20-u.length)),(u.substr(0,20)+(u.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var u=this.pastInput(),a=new Array(u.length+1).join("-");return u+this.upcomingInput()+` diff --git a/assets/svgDrawCommon-5e1cfd1d-BWP2bQZS.js b/assets/svgDrawCommon-5e1cfd1d-CX_gVtbt.js similarity index 95% rename from assets/svgDrawCommon-5e1cfd1d-BWP2bQZS.js rename to assets/svgDrawCommon-5e1cfd1d-CX_gVtbt.js index ecd86835ee..725122e8e1 100644 --- a/assets/svgDrawCommon-5e1cfd1d-BWP2bQZS.js +++ b/assets/svgDrawCommon-5e1cfd1d-CX_gVtbt.js @@ -1 +1 @@ -import{n as o,m as i}from"./mermaid.core-CArNAncI.js";const l=(s,t)=>{const e=s.append("rect");if(e.attr("x",t.x),e.attr("y",t.y),e.attr("fill",t.fill),e.attr("stroke",t.stroke),e.attr("width",t.width),e.attr("height",t.height),t.name&&e.attr("name",t.name),t.rx!==void 0&&e.attr("rx",t.rx),t.ry!==void 0&&e.attr("ry",t.ry),t.attrs!==void 0)for(const r in t.attrs)e.attr(r,t.attrs[r]);return t.class!==void 0&&e.attr("class",t.class),e},x=(s,t)=>{const e={x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:"rect"};l(s,e).lower()},d=(s,t)=>{const e=t.text.replace(o," "),r=s.append("text");r.attr("x",t.x),r.attr("y",t.y),r.attr("class","legend"),r.style("text-anchor",t.anchor),t.class!==void 0&&r.attr("class",t.class);const n=r.append("tspan");return n.attr("x",t.x+t.textMargin*2),n.text(e),r},h=(s,t,e,r)=>{const n=s.append("image");n.attr("x",t),n.attr("y",e);const a=i.sanitizeUrl(r);n.attr("xlink:href",a)},y=(s,t,e,r)=>{const n=s.append("use");n.attr("x",t),n.attr("y",e);const a=i.sanitizeUrl(r);n.attr("xlink:href",`#${a}`)},g=()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),m=()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0});export{x as a,m as b,y as c,l as d,h as e,d as f,g}; +import{n as o,m as i}from"./mermaid.core-Bq0kX0MS.js";const l=(s,t)=>{const e=s.append("rect");if(e.attr("x",t.x),e.attr("y",t.y),e.attr("fill",t.fill),e.attr("stroke",t.stroke),e.attr("width",t.width),e.attr("height",t.height),t.name&&e.attr("name",t.name),t.rx!==void 0&&e.attr("rx",t.rx),t.ry!==void 0&&e.attr("ry",t.ry),t.attrs!==void 0)for(const r in t.attrs)e.attr(r,t.attrs[r]);return t.class!==void 0&&e.attr("class",t.class),e},x=(s,t)=>{const e={x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:"rect"};l(s,e).lower()},d=(s,t)=>{const e=t.text.replace(o," "),r=s.append("text");r.attr("x",t.x),r.attr("y",t.y),r.attr("class","legend"),r.style("text-anchor",t.anchor),t.class!==void 0&&r.attr("class",t.class);const n=r.append("tspan");return n.attr("x",t.x+t.textMargin*2),n.text(e),r},h=(s,t,e,r)=>{const n=s.append("image");n.attr("x",t),n.attr("y",e);const a=i.sanitizeUrl(r);n.attr("xlink:href",a)},y=(s,t,e,r)=>{const n=s.append("use");n.attr("x",t),n.attr("y",e);const a=i.sanitizeUrl(r);n.attr("xlink:href",`#${a}`)},g=()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),m=()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0});export{x as a,m as b,y as c,l as d,h as e,d as f,g}; diff --git a/assets/tcp.html-BV6lGrTj.js b/assets/tcp.html-BnHzgywc.js similarity index 99% rename from assets/tcp.html-BV6lGrTj.js rename to assets/tcp.html-BnHzgywc.js index 2ab87b70fd..16160eaa68 100644 --- a/assets/tcp.html-BV6lGrTj.js +++ b/assets/tcp.html-BnHzgywc.js @@ -1,4 +1,4 @@ -import{_ as c,r as a,o as u,c as l,a as e,b as s,d as n,e as o}from"./app-5SoadDYS.js";const i={},r=o(`

                                        TCP

                                        Режим транспорта TCP — один из рекомендуемых в настоящее время режимов транспорта.

                                        Может использоваться в различных комбинациях с различными протоколами.

                                        TcpObject

                                        TcpObject соответствует элементу tcpSettings в конфигурации транспорта.

                                        {
                                        +import{_ as c,r as a,o as u,c as l,a as e,b as s,d as n,e as o}from"./app-Bw2NG-QJ.js";const i={},r=o(`

                                        TCP

                                        Режим транспорта TCP — один из рекомендуемых в настоящее время режимов транспорта.

                                        Может использоваться в различных комбинациях с различными протоколами.

                                        TcpObject

                                        TcpObject соответствует элементу tcpSettings в конфигурации транспорта.

                                        {
                                           "acceptProxyProtocol": false,
                                           "header": {
                                             "type": "none"
                                        diff --git a/assets/tcp.html-BHSzdt5L.js b/assets/tcp.html-C8HjBlLu.js
                                        similarity index 99%
                                        rename from assets/tcp.html-BHSzdt5L.js
                                        rename to assets/tcp.html-C8HjBlLu.js
                                        index 4d1ce0e6ba..8379db0a80 100644
                                        --- a/assets/tcp.html-BHSzdt5L.js
                                        +++ b/assets/tcp.html-C8HjBlLu.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as e,o as r,c as l,a,b as s,d as n,e as t}from"./app-5SoadDYS.js";const i={},u=t(`

                                        TCP

                                        TCP (Transmission Control Protocol) is currently one of the recommended transport protocols

                                        It can be combined with various protocols in multiple ways.

                                        TcpObject

                                        TcpObject corresponds to the tcpSettings item in the Transport Protocol.

                                        {
                                        +import{_ as c,r as e,o as r,c as l,a,b as s,d as n,e as t}from"./app-Bw2NG-QJ.js";const i={},u=t(`

                                        TCP

                                        TCP (Transmission Control Protocol) is currently one of the recommended transport protocols

                                        It can be combined with various protocols in multiple ways.

                                        TcpObject

                                        TcpObject corresponds to the tcpSettings item in the Transport Protocol.

                                        {
                                           "acceptProxyProtocol": false,
                                           "header": {
                                             "type": "none"
                                        diff --git a/assets/tcp.html-VJNns-C5.js b/assets/tcp.html-vEvGx-7r.js
                                        similarity index 99%
                                        rename from assets/tcp.html-VJNns-C5.js
                                        rename to assets/tcp.html-vEvGx-7r.js
                                        index d513adeab6..b7983f7189 100644
                                        --- a/assets/tcp.html-VJNns-C5.js
                                        +++ b/assets/tcp.html-vEvGx-7r.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as a,o as u,c as l,a as e,b as s,d as n,e as o}from"./app-5SoadDYS.js";const i={},r=o(`

                                        TCP

                                        TCP 传输模式是目前推荐使用的传输模式之一.

                                        可以和各种协议有多种组合模式.

                                        TcpObject

                                        TcpObject 对应传输配置的 tcpSettings 项。

                                        {
                                        +import{_ as c,r as a,o as u,c as l,a as e,b as s,d as n,e as o}from"./app-Bw2NG-QJ.js";const i={},r=o(`

                                        TCP

                                        TCP 传输模式是目前推荐使用的传输模式之一.

                                        可以和各种协议有多种组合模式.

                                        TcpObject

                                        TcpObject 对应传输配置的 tcpSettings 项。

                                        {
                                           "acceptProxyProtocol": false,
                                           "header": {
                                             "type": "none"
                                        diff --git a/assets/timeline-definition-bf702344-D6E2CBeX.js b/assets/timeline-definition-bf702344-B4DJzmYO.js
                                        similarity index 99%
                                        rename from assets/timeline-definition-bf702344-D6E2CBeX.js
                                        rename to assets/timeline-definition-bf702344-B4DJzmYO.js
                                        index befa7ef957..8e33bfa75c 100644
                                        --- a/assets/timeline-definition-bf702344-D6E2CBeX.js
                                        +++ b/assets/timeline-definition-bf702344-B4DJzmYO.js
                                        @@ -1,4 +1,4 @@
                                        -import{b4 as ft,A as gt,c as mt,l as E,h as G,u as xt,b5 as bt,b6 as _t,b7 as kt}from"./mermaid.core-CArNAncI.js";import{a as D}from"./arc-xLaeEKkr.js";import"./app-5SoadDYS.js";import"./path-CbwjOpE9.js";var K=function(){var n=function(g,i,r,c){for(r=r||{},c=g.length;c--;r[g[c]]=i);return r},t=[6,8,10,11,12,14,16,17,20,21],e=[1,9],a=[1,10],s=[1,11],h=[1,12],l=[1,13],p=[1,16],y=[1,17],f={trace:function(){},yy:{},symbols_:{error:2,start:3,timeline:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,period_statement:18,event_statement:19,period:20,event:21,$accept:0,$end:1},terminals_:{2:"error",4:"timeline",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",20:"period",21:"event"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,1],[18,1],[19,1]],performAction:function(i,r,c,d,u,o,$){var x=o.length-1;switch(u){case 1:return o[x-1];case 2:this.$=[];break;case 3:o[x-1].push(o[x]),this.$=o[x-1];break;case 4:case 5:this.$=o[x];break;case 6:case 7:this.$=[];break;case 8:d.getCommonDb().setDiagramTitle(o[x].substr(6)),this.$=o[x].substr(6);break;case 9:this.$=o[x].trim(),d.getCommonDb().setAccTitle(this.$);break;case 10:case 11:this.$=o[x].trim(),d.getCommonDb().setAccDescription(this.$);break;case 12:d.addSection(o[x].substr(8)),this.$=o[x].substr(8);break;case 15:d.addTask(o[x],0,""),this.$=o[x];break;case 16:d.addEvent(o[x].substr(2)),this.$=o[x];break}},table:[{3:1,4:[1,2]},{1:[3]},n(t,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:e,12:a,14:s,16:h,17:l,18:14,19:15,20:p,21:y},n(t,[2,7],{1:[2,1]}),n(t,[2,3]),{9:18,11:e,12:a,14:s,16:h,17:l,18:14,19:15,20:p,21:y},n(t,[2,5]),n(t,[2,6]),n(t,[2,8]),{13:[1,19]},{15:[1,20]},n(t,[2,11]),n(t,[2,12]),n(t,[2,13]),n(t,[2,14]),n(t,[2,15]),n(t,[2,16]),n(t,[2,4]),n(t,[2,9]),n(t,[2,10])],defaultActions:{},parseError:function(i,r){if(r.recoverable)this.trace(i);else{var c=new Error(i);throw c.hash=r,c}},parse:function(i){var r=this,c=[0],d=[],u=[null],o=[],$=this.table,x="",T=0,W=0,C=2,A=1,B=o.slice.call(arguments,1),k=Object.create(this.lexer),w={yy:{}};for(var v in this.yy)Object.prototype.hasOwnProperty.call(this.yy,v)&&(w.yy[v]=this.yy[v]);k.setInput(i,w.yy),w.yy.lexer=k,w.yy.parser=this,typeof k.yylloc>"u"&&(k.yylloc={});var I=k.yylloc;o.push(I);var P=k.options&&k.options.ranges;typeof w.yy.parseError=="function"?this.parseError=w.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function z(){var M;return M=d.pop()||k.lex()||A,typeof M!="number"&&(M instanceof Array&&(d=M,M=d.pop()),M=r.symbols_[M]||M),M}for(var _,L,S,Z,R={},O,N,Y,j;;){if(L=c[c.length-1],this.defaultActions[L]?S=this.defaultActions[L]:((_===null||typeof _>"u")&&(_=z()),S=$[L]&&$[L][_]),typeof S>"u"||!S.length||!S[0]){var J="";j=[];for(O in $[L])this.terminals_[O]&&O>C&&j.push("'"+this.terminals_[O]+"'");k.showPosition?J="Parse error on line "+(T+1)+`:
                                        +import{b4 as ft,A as gt,c as mt,l as E,h as G,u as xt,b5 as bt,b6 as _t,b7 as kt}from"./mermaid.core-Bq0kX0MS.js";import{a as D}from"./arc-C5d-KvsZ.js";import"./app-Bw2NG-QJ.js";import"./path-CbwjOpE9.js";var K=function(){var n=function(g,i,r,c){for(r=r||{},c=g.length;c--;r[g[c]]=i);return r},t=[6,8,10,11,12,14,16,17,20,21],e=[1,9],a=[1,10],s=[1,11],h=[1,12],l=[1,13],p=[1,16],y=[1,17],f={trace:function(){},yy:{},symbols_:{error:2,start:3,timeline:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,period_statement:18,event_statement:19,period:20,event:21,$accept:0,$end:1},terminals_:{2:"error",4:"timeline",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",20:"period",21:"event"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,1],[18,1],[19,1]],performAction:function(i,r,c,d,u,o,$){var x=o.length-1;switch(u){case 1:return o[x-1];case 2:this.$=[];break;case 3:o[x-1].push(o[x]),this.$=o[x-1];break;case 4:case 5:this.$=o[x];break;case 6:case 7:this.$=[];break;case 8:d.getCommonDb().setDiagramTitle(o[x].substr(6)),this.$=o[x].substr(6);break;case 9:this.$=o[x].trim(),d.getCommonDb().setAccTitle(this.$);break;case 10:case 11:this.$=o[x].trim(),d.getCommonDb().setAccDescription(this.$);break;case 12:d.addSection(o[x].substr(8)),this.$=o[x].substr(8);break;case 15:d.addTask(o[x],0,""),this.$=o[x];break;case 16:d.addEvent(o[x].substr(2)),this.$=o[x];break}},table:[{3:1,4:[1,2]},{1:[3]},n(t,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:e,12:a,14:s,16:h,17:l,18:14,19:15,20:p,21:y},n(t,[2,7],{1:[2,1]}),n(t,[2,3]),{9:18,11:e,12:a,14:s,16:h,17:l,18:14,19:15,20:p,21:y},n(t,[2,5]),n(t,[2,6]),n(t,[2,8]),{13:[1,19]},{15:[1,20]},n(t,[2,11]),n(t,[2,12]),n(t,[2,13]),n(t,[2,14]),n(t,[2,15]),n(t,[2,16]),n(t,[2,4]),n(t,[2,9]),n(t,[2,10])],defaultActions:{},parseError:function(i,r){if(r.recoverable)this.trace(i);else{var c=new Error(i);throw c.hash=r,c}},parse:function(i){var r=this,c=[0],d=[],u=[null],o=[],$=this.table,x="",T=0,W=0,C=2,A=1,B=o.slice.call(arguments,1),k=Object.create(this.lexer),w={yy:{}};for(var v in this.yy)Object.prototype.hasOwnProperty.call(this.yy,v)&&(w.yy[v]=this.yy[v]);k.setInput(i,w.yy),w.yy.lexer=k,w.yy.parser=this,typeof k.yylloc>"u"&&(k.yylloc={});var I=k.yylloc;o.push(I);var P=k.options&&k.options.ranges;typeof w.yy.parseError=="function"?this.parseError=w.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function z(){var M;return M=d.pop()||k.lex()||A,typeof M!="number"&&(M instanceof Array&&(d=M,M=d.pop()),M=r.symbols_[M]||M),M}for(var _,L,S,Z,R={},O,N,Y,j;;){if(L=c[c.length-1],this.defaultActions[L]?S=this.defaultActions[L]:((_===null||typeof _>"u")&&(_=z()),S=$[L]&&$[L][_]),typeof S>"u"||!S.length||!S[0]){var J="";j=[];for(O in $[L])this.terminals_[O]&&O>C&&j.push("'"+this.terminals_[O]+"'");k.showPosition?J="Parse error on line "+(T+1)+`:
                                         `+k.showPosition()+`
                                         Expecting `+j.join(", ")+", got '"+(this.terminals_[_]||_)+"'":J="Parse error on line "+(T+1)+": Unexpected "+(_==A?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(J,{text:k.match,token:this.terminals_[_]||_,line:k.yylineno,loc:I,expected:j})}if(S[0]instanceof Array&&S.length>1)throw new Error("Parse Error: multiple actions possible at state: "+L+", token: "+_);switch(S[0]){case 1:c.push(_),u.push(k.yytext),o.push(k.yylloc),c.push(S[1]),_=null,W=k.yyleng,x=k.yytext,T=k.yylineno,I=k.yylloc;break;case 2:if(N=this.productions_[S[1]][1],R.$=u[u.length-N],R._$={first_line:o[o.length-(N||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-(N||1)].first_column,last_column:o[o.length-1].last_column},P&&(R._$.range=[o[o.length-(N||1)].range[0],o[o.length-1].range[1]]),Z=this.performAction.apply(R,[x,W,T,w.yy,S[1],u,o].concat(B)),typeof Z<"u")return Z;N&&(c=c.slice(0,-1*N*2),u=u.slice(0,-1*N),o=o.slice(0,-1*N)),c.push(this.productions_[S[1]][0]),u.push(R.$),o.push(R._$),Y=$[c[c.length-2]][c[c.length-1]],c.push(Y);break;case 3:return!0}}return!0}},b=function(){var g={EOF:1,parseError:function(r,c){if(this.yy.parser)this.yy.parser.parseError(r,c);else throw new Error(r)},setInput:function(i,r){return this.yy=r||this.yy||{},this._input=i,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var i=this._input[0];this.yytext+=i,this.yyleng++,this.offset++,this.match+=i,this.matched+=i;var r=i.match(/(?:\r\n?|\n).*/g);return r?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),i},unput:function(i){var r=i.length,c=i.split(/(?:\r\n?|\n)/g);this._input=i+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-r),this.offset-=r;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var u=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-r},this.options.ranges&&(this.yylloc.range=[u[0],u[0]+this.yyleng-r]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(i){this.unput(this.match.slice(i))},pastInput:function(){var i=this.matched.substr(0,this.matched.length-this.match.length);return(i.length>20?"...":"")+i.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var i=this.match;return i.length<20&&(i+=this._input.substr(0,20-i.length)),(i.substr(0,20)+(i.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var i=this.pastInput(),r=new Array(i.length+1).join("-");return i+this.upcomingInput()+`
                                        diff --git a/assets/tproxy.html-DzexlIqp.js b/assets/tproxy.html-CfIjaip9.js
                                        similarity index 99%
                                        rename from assets/tproxy.html-DzexlIqp.js
                                        rename to assets/tproxy.html-CfIjaip9.js
                                        index f42dcbbe54..03db7e47ec 100644
                                        --- a/assets/tproxy.html-DzexlIqp.js
                                        +++ b/assets/tproxy.html-CfIjaip9.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as c,c as u,a,b as n,d as s,w as e,e as k}from"./app-5SoadDYS.js";const d={},v=n("h1",{id:"透明代理-tproxy-配置教程",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#透明代理-tproxy-配置教程"},[n("span",null,"透明代理(TProxy)配置教程")])],-1),m={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=n("p",null,"本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。",-1),q=n("h2",{id:"开始之前",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#开始之前"},[n("span",null,"开始之前")])],-1),g=n("p",null,"请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。",-1),y={href:"https://github.com/XTLS/Xray-core/discussions/59",target:"_blank",rel:"noopener noreferrer"},f=n("p",null,"这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。",-1),h=n("h2",{id:"xray-配置",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-配置"},[n("span",null,"Xray 配置")])],-1),R={href:"https://github.com/Loyalsoldier/v2ray-rules-dat",target:"_blank",rel:"noopener noreferrer"},_=k(`
                                        sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                                        +import{_ as i,r as p,o as c,c as u,a,b as n,d as s,w as e,e as k}from"./app-Bw2NG-QJ.js";const d={},v=n("h1",{id:"透明代理-tproxy-配置教程",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#透明代理-tproxy-配置教程"},[n("span",null,"透明代理(TProxy)配置教程")])],-1),m={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=n("p",null,"本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。",-1),q=n("h2",{id:"开始之前",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#开始之前"},[n("span",null,"开始之前")])],-1),g=n("p",null,"请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。",-1),y={href:"https://github.com/XTLS/Xray-core/discussions/59",target:"_blank",rel:"noopener noreferrer"},f=n("p",null,"这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。",-1),h=n("h2",{id:"xray-配置",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-配置"},[n("span",null,"Xray 配置")])],-1),R={href:"https://github.com/Loyalsoldier/v2ray-rules-dat",target:"_blank",rel:"noopener noreferrer"},_=k(`
                                        sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                                         sudo curl -oL /usr/local/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
                                         
                                        {
                                           "log": {
                                        diff --git a/assets/tproxy.html-BewclJzl.js b/assets/tproxy.html-DWkdG7BH.js
                                        similarity index 99%
                                        rename from assets/tproxy.html-BewclJzl.js
                                        rename to assets/tproxy.html-DWkdG7BH.js
                                        index db487e8a5c..031e5956bc 100644
                                        --- a/assets/tproxy.html-BewclJzl.js
                                        +++ b/assets/tproxy.html-DWkdG7BH.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as c,c as u,a,b as n,d as s,w as e,e as k}from"./app-5SoadDYS.js";const d={},v=n("h1",{id:"руководство-по-настроике-прозрачного-проксирования-tproxy",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#руководство-по-настроике-прозрачного-проксирования-tproxy"},[n("span",null,"Руководство по настройке прозрачного проксирования (TProxy)")])],-1),m={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=n("p",null,"Все конфигурации, представленные в этой статье, были успешно протестированы в средах Raspberry Pi 2B и Ubuntu 20.04. При использовании в других средах вам может потребоваться изменить конфигурацию.",-1),q=n("h2",{id:"перед-началом-работы",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#перед-началом-работы"},[n("span",null,"Перед началом работы")])],-1),g=n("p",null,"Убедитесь, что на вашем устройстве есть доступное сетевое подключение, сервер настроен, а клиент установлен.",-1),y={href:"https://github.com/XTLS/Xray-core/discussions/59",target:"_blank",rel:"noopener noreferrer"},f=n("p",null,[s("Хочу добавить, что многие руководства по настройке прозрачного проксирования используют Netfilter для разделения трафика, отправляя прямой трафик напрямую, минуя Xray. В этом случае необходимо включить переадресацию IP."),n("br"),s(" Другие руководства, например это, направляют весь трафик через Xray, где он разделяется модулем маршрутизации Xray. В этом случае переадресацию IP включать не нужно.")],-1),h=n("h2",{id:"настроика-xray",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#настроика-xray"},[n("span",null,"Настройка Xray")])],-1),R={href:"https://github.com/Loyalsoldier/v2ray-rules-dat",target:"_blank",rel:"noopener noreferrer"},_=k(`
                                        sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                                        +import{_ as i,r as p,o as c,c as u,a,b as n,d as s,w as e,e as k}from"./app-Bw2NG-QJ.js";const d={},v=n("h1",{id:"руководство-по-настроике-прозрачного-проксирования-tproxy",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#руководство-по-настроике-прозрачного-проксирования-tproxy"},[n("span",null,"Руководство по настройке прозрачного проксирования (TProxy)")])],-1),m={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=n("p",null,"Все конфигурации, представленные в этой статье, были успешно протестированы в средах Raspberry Pi 2B и Ubuntu 20.04. При использовании в других средах вам может потребоваться изменить конфигурацию.",-1),q=n("h2",{id:"перед-началом-работы",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#перед-началом-работы"},[n("span",null,"Перед началом работы")])],-1),g=n("p",null,"Убедитесь, что на вашем устройстве есть доступное сетевое подключение, сервер настроен, а клиент установлен.",-1),y={href:"https://github.com/XTLS/Xray-core/discussions/59",target:"_blank",rel:"noopener noreferrer"},f=n("p",null,[s("Хочу добавить, что многие руководства по настройке прозрачного проксирования используют Netfilter для разделения трафика, отправляя прямой трафик напрямую, минуя Xray. В этом случае необходимо включить переадресацию IP."),n("br"),s(" Другие руководства, например это, направляют весь трафик через Xray, где он разделяется модулем маршрутизации Xray. В этом случае переадресацию IP включать не нужно.")],-1),h=n("h2",{id:"настроика-xray",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#настроика-xray"},[n("span",null,"Настройка Xray")])],-1),R={href:"https://github.com/Loyalsoldier/v2ray-rules-dat",target:"_blank",rel:"noopener noreferrer"},_=k(`
                                        sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                                         sudo curl -oL /usr/local/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
                                         
                                        {
                                           "log": {
                                        diff --git a/assets/tproxy.html-BR9yhgN8.js b/assets/tproxy.html-DjX-7RSF.js
                                        similarity index 99%
                                        rename from assets/tproxy.html-BR9yhgN8.js
                                        rename to assets/tproxy.html-DjX-7RSF.js
                                        index f42dcbbe54..03db7e47ec 100644
                                        --- a/assets/tproxy.html-BR9yhgN8.js
                                        +++ b/assets/tproxy.html-DjX-7RSF.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as p,o as c,c as u,a,b as n,d as s,w as e,e as k}from"./app-5SoadDYS.js";const d={},v=n("h1",{id:"透明代理-tproxy-配置教程",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#透明代理-tproxy-配置教程"},[n("span",null,"透明代理(TProxy)配置教程")])],-1),m={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=n("p",null,"本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。",-1),q=n("h2",{id:"开始之前",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#开始之前"},[n("span",null,"开始之前")])],-1),g=n("p",null,"请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。",-1),y={href:"https://github.com/XTLS/Xray-core/discussions/59",target:"_blank",rel:"noopener noreferrer"},f=n("p",null,"这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。",-1),h=n("h2",{id:"xray-配置",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-配置"},[n("span",null,"Xray 配置")])],-1),R={href:"https://github.com/Loyalsoldier/v2ray-rules-dat",target:"_blank",rel:"noopener noreferrer"},_=k(`
                                        sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                                        +import{_ as i,r as p,o as c,c as u,a,b as n,d as s,w as e,e as k}from"./app-Bw2NG-QJ.js";const d={},v=n("h1",{id:"透明代理-tproxy-配置教程",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#透明代理-tproxy-配置教程"},[n("span",null,"透明代理(TProxy)配置教程")])],-1),m={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},b=n("p",null,"本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。",-1),q=n("h2",{id:"开始之前",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#开始之前"},[n("span",null,"开始之前")])],-1),g=n("p",null,"请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。",-1),y={href:"https://github.com/XTLS/Xray-core/discussions/59",target:"_blank",rel:"noopener noreferrer"},f=n("p",null,"这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。",-1),h=n("h2",{id:"xray-配置",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-配置"},[n("span",null,"Xray 配置")])],-1),R={href:"https://github.com/Loyalsoldier/v2ray-rules-dat",target:"_blank",rel:"noopener noreferrer"},_=k(`
                                        sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                                         sudo curl -oL /usr/local/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat
                                         
                                        {
                                           "log": {
                                        diff --git a/assets/tproxy_ipv4_and_ipv6.html-3o8j0gtN.js b/assets/tproxy_ipv4_and_ipv6.html-Cd8pbG7a.js
                                        similarity index 99%
                                        rename from assets/tproxy_ipv4_and_ipv6.html-3o8j0gtN.js
                                        rename to assets/tproxy_ipv4_and_ipv6.html-Cd8pbG7a.js
                                        index 30eac497fe..39e3a0e13f 100644
                                        --- a/assets/tproxy_ipv4_and_ipv6.html-3o8j0gtN.js
                                        +++ b/assets/tproxy_ipv4_and_ipv6.html-Cd8pbG7a.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as i,c as r,a,b as s,d as n,e as t}from"./app-5SoadDYS.js";const c={},u=s("h1",{id:"руководство-по-настроике-прозрачного-проксирования-tproxy-ipv4-и-ipv6",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#руководство-по-настроике-прозрачного-проксирования-tproxy-ipv4-и-ipv6"},[s("span",null,"Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6)")])],-1),d={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://xtls.github.io/document/level-2/tproxy.html#%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D",target:"_blank",rel:"noopener noreferrer"},k={href:"https://xtls.github.io/document/level-2/iptables_gid.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/chika0801/Xray-examples",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/lxhao61/integrated-examples",target:"_blank",rel:"noopener noreferrer"},g=t('

                                        Внимание

                                        При использовании других конфигураций обратите особое внимание на часть outbound с тегом proxy в конфигурации клиента. Остальные части остаются неизменными.

                                        Конфигурация сервера также должна быть изменена соответственно.

                                        Эта конфигурация предназначена для решения проблемы, когда такие сайты, как Netflix, которые по умолчанию используют IPv6, не могут быть проксированы через пограничный маршрутизатор, или когда требуется проксирование IPv6.

                                        В данной статье используется сетевая структура с пограничным маршрутизатором с одним интерфейсом.

                                        Все конфигурации, представленные в этой статье, были успешно протестированы в среде Arch Linux (Kernel: 6.0.10). В других средах настройка аналогична.

                                        Убедитесь, что установлены необходимые программы: # sudo apt install iptables ip6tables или # sudo apt install nftables.

                                        ',5),y={href:"https://github.com/XTLS/Xray-core/releases/download/v1.7.0/Xray-linux-64.zip",target:"_blank",rel:"noopener noreferrer"},h={href:"https://github.com/XTLS/Xray-install/blob/main/install-release.sh",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"# chmod 700 install-release.sh",-1),x=s("code",null,"# ./install-release.sh --local Xray-linux-64.zip",-1),R=t(`

                                        Настройка Xray

                                        Конфигурация клиента

                                        {
                                        +import{_ as l,r as p,o as i,c as r,a,b as s,d as n,e as t}from"./app-Bw2NG-QJ.js";const c={},u=s("h1",{id:"руководство-по-настроике-прозрачного-проксирования-tproxy-ipv4-и-ipv6",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#руководство-по-настроике-прозрачного-проксирования-tproxy-ipv4-и-ipv6"},[s("span",null,"Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6)")])],-1),d={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://xtls.github.io/document/level-2/tproxy.html#%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D",target:"_blank",rel:"noopener noreferrer"},k={href:"https://xtls.github.io/document/level-2/iptables_gid.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/chika0801/Xray-examples",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/lxhao61/integrated-examples",target:"_blank",rel:"noopener noreferrer"},g=t('

                                        Внимание

                                        При использовании других конфигураций обратите особое внимание на часть outbound с тегом proxy в конфигурации клиента. Остальные части остаются неизменными.

                                        Конфигурация сервера также должна быть изменена соответственно.

                                        Эта конфигурация предназначена для решения проблемы, когда такие сайты, как Netflix, которые по умолчанию используют IPv6, не могут быть проксированы через пограничный маршрутизатор, или когда требуется проксирование IPv6.

                                        В данной статье используется сетевая структура с пограничным маршрутизатором с одним интерфейсом.

                                        Все конфигурации, представленные в этой статье, были успешно протестированы в среде Arch Linux (Kernel: 6.0.10). В других средах настройка аналогична.

                                        Убедитесь, что установлены необходимые программы: # sudo apt install iptables ip6tables или # sudo apt install nftables.

                                        ',5),y={href:"https://github.com/XTLS/Xray-core/releases/download/v1.7.0/Xray-linux-64.zip",target:"_blank",rel:"noopener noreferrer"},h={href:"https://github.com/XTLS/Xray-install/blob/main/install-release.sh",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"# chmod 700 install-release.sh",-1),x=s("code",null,"# ./install-release.sh --local Xray-linux-64.zip",-1),R=t(`

                                        Настройка Xray

                                        Конфигурация клиента

                                        {
                                           "log": {
                                             "loglevel": "warning"
                                           },
                                        diff --git a/assets/tproxy_ipv4_and_ipv6.html-D1MYaJ5_.js b/assets/tproxy_ipv4_and_ipv6.html-D9QvwytN.js
                                        similarity index 99%
                                        rename from assets/tproxy_ipv4_and_ipv6.html-D1MYaJ5_.js
                                        rename to assets/tproxy_ipv4_and_ipv6.html-D9QvwytN.js
                                        index 4bb2a73252..61b6f596fb 100644
                                        --- a/assets/tproxy_ipv4_and_ipv6.html-D1MYaJ5_.js
                                        +++ b/assets/tproxy_ipv4_and_ipv6.html-D9QvwytN.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as i,c as r,a,b as s,d as n,e as t}from"./app-5SoadDYS.js";const c={},u=s("h1",{id:"tproxy-透明代理-ipv4-and-ipv6-配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#tproxy-透明代理-ipv4-and-ipv6-配置教程"},[s("span",null,"TProxy 透明代理(ipv4 and ipv6)配置教程")])],-1),d={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://xtls.github.io/document/level-2/tproxy.html#%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D",target:"_blank",rel:"noopener noreferrer"},k={href:"https://xtls.github.io/document/level-2/iptables_gid.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/chika0801/Xray-examples",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/lxhao61/integrated-examples",target:"_blank",rel:"noopener noreferrer"},g=t('

                                        注意

                                        若使用其他配置,你需要着重注意客户端配置中 outboundtagproxy 的部分,其他部分不变

                                        服务端配置也要同时改变

                                        此配置意在解决例如 Netflix 等默认使用 ipv6 连接的网站无法通过旁路由进行代理的问题,或对 ipv6 代理有需要。

                                        本文网络结构为单臂旁路由

                                        本文中所有配置已在 Arch Linux (Kernel: 6.0.10) 环境下测试成功,如在其它环境中同理

                                        注意安装相应程序 # sudo apt install iptables ip6tables# sudo apt install nftables

                                        ',5),y={href:"https://github.com/XTLS/Xray-core/releases/download/v1.7.0/Xray-linux-64.zip",target:"_blank",rel:"noopener noreferrer"},h={href:"https://github.com/XTLS/Xray-install/blob/main/install-release.sh",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"# chmod 700 install-release.sh",-1),x=s("code",null,"# ./install-release.sh --local Xray-linux-64.zip",-1),R=t(`

                                        Xray 配置

                                        客户端配置

                                        {
                                        +import{_ as l,r as p,o as i,c as r,a,b as s,d as n,e as t}from"./app-Bw2NG-QJ.js";const c={},u=s("h1",{id:"tproxy-透明代理-ipv4-and-ipv6-配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#tproxy-透明代理-ipv4-and-ipv6-配置教程"},[s("span",null,"TProxy 透明代理(ipv4 and ipv6)配置教程")])],-1),d={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://xtls.github.io/document/level-2/tproxy.html#%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D",target:"_blank",rel:"noopener noreferrer"},k={href:"https://xtls.github.io/document/level-2/iptables_gid.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/chika0801/Xray-examples",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/lxhao61/integrated-examples",target:"_blank",rel:"noopener noreferrer"},g=t('

                                        注意

                                        若使用其他配置,你需要着重注意客户端配置中 outboundtagproxy 的部分,其他部分不变

                                        服务端配置也要同时改变

                                        此配置意在解决例如 Netflix 等默认使用 ipv6 连接的网站无法通过旁路由进行代理的问题,或对 ipv6 代理有需要。

                                        本文网络结构为单臂旁路由

                                        本文中所有配置已在 Arch Linux (Kernel: 6.0.10) 环境下测试成功,如在其它环境中同理

                                        注意安装相应程序 # sudo apt install iptables ip6tables# sudo apt install nftables

                                        ',5),y={href:"https://github.com/XTLS/Xray-core/releases/download/v1.7.0/Xray-linux-64.zip",target:"_blank",rel:"noopener noreferrer"},h={href:"https://github.com/XTLS/Xray-install/blob/main/install-release.sh",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"# chmod 700 install-release.sh",-1),x=s("code",null,"# ./install-release.sh --local Xray-linux-64.zip",-1),R=t(`

                                        Xray 配置

                                        客户端配置

                                        {
                                           "log": {
                                             "loglevel": "warning"
                                           },
                                        diff --git a/assets/tproxy_ipv4_and_ipv6.html-Bk7Lv8iD.js b/assets/tproxy_ipv4_and_ipv6.html-QYKhgI6r.js
                                        similarity index 99%
                                        rename from assets/tproxy_ipv4_and_ipv6.html-Bk7Lv8iD.js
                                        rename to assets/tproxy_ipv4_and_ipv6.html-QYKhgI6r.js
                                        index fbc6a216d9..7e1d119a18 100644
                                        --- a/assets/tproxy_ipv4_and_ipv6.html-Bk7Lv8iD.js
                                        +++ b/assets/tproxy_ipv4_and_ipv6.html-QYKhgI6r.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as i,c as r,a,b as s,d as n,e as t}from"./app-5SoadDYS.js";const c={},u=s("h1",{id:"tproxy-透明代理-ipv4-and-ipv6-配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#tproxy-透明代理-ipv4-and-ipv6-配置教程"},[s("span",null,"TProxy 透明代理(ipv4 and ipv6)配置教程")])],-1),d={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://xtls.github.io/document/level-2/tproxy.html#%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D",target:"_blank",rel:"noopener noreferrer"},k={href:"https://xtls.github.io/document/level-2/iptables_gid.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/chika0801/Xray-examples",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/lxhao61/integrated-examples",target:"_blank",rel:"noopener noreferrer"},g=t('

                                        注意

                                        若使用其他配置,你需要着重注意客户端配置中 outboundtagproxy 的部分,其他部分不变

                                        服务端配置也要同时改变

                                        此配置意在解决例如 Netflix 等默认使用 ipv6 连接的网站无法通过旁路由进行代理的问题,或对 ipv6 代理有需要。

                                        本文网络结构为单臂旁路由

                                        本文中所有配置已在 Arch Linux (Kernel: 6.0.10) 环境下测试成功,如在其它环境中同理

                                        注意安装相应程序 # sudo apt install iptables ip6tables# sudo apt install nftables

                                        ',5),y={href:"https://github.com/XTLS/Xray-core/releases/download/v1.7.0/Xray-linux-64.zip",target:"_blank",rel:"noopener noreferrer"},h={href:"https://github.com/XTLS/Xray-install/blob/main/install-release.sh",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"# chmod 700 install-release.sh",-1),x=s("code",null,"# ./install-release.sh --local Xray-linux-64.zip",-1),R=t(`

                                        Xray 配置

                                        客户端配置

                                        {
                                        +import{_ as l,r as p,o as i,c as r,a,b as s,d as n,e as t}from"./app-Bw2NG-QJ.js";const c={},u=s("h1",{id:"tproxy-透明代理-ipv4-and-ipv6-配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#tproxy-透明代理-ipv4-and-ipv6-配置教程"},[s("span",null,"TProxy 透明代理(ipv4 and ipv6)配置教程")])],-1),d={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},v={href:"https://xtls.github.io/document/level-2/tproxy.html#%E5%BC%80%E5%A7%8B%E4%B9%8B%E5%89%8D",target:"_blank",rel:"noopener noreferrer"},k={href:"https://xtls.github.io/document/level-2/iptables_gid.html",target:"_blank",rel:"noopener noreferrer"},m={href:"https://github.com/XTLS/Xray-examples",target:"_blank",rel:"noopener noreferrer"},b={href:"https://github.com/chika0801/Xray-examples",target:"_blank",rel:"noopener noreferrer"},q={href:"https://github.com/lxhao61/integrated-examples",target:"_blank",rel:"noopener noreferrer"},g=t('

                                        注意

                                        若使用其他配置,你需要着重注意客户端配置中 outboundtagproxy 的部分,其他部分不变

                                        服务端配置也要同时改变

                                        此配置意在解决例如 Netflix 等默认使用 ipv6 连接的网站无法通过旁路由进行代理的问题,或对 ipv6 代理有需要。

                                        本文网络结构为单臂旁路由

                                        本文中所有配置已在 Arch Linux (Kernel: 6.0.10) 环境下测试成功,如在其它环境中同理

                                        注意安装相应程序 # sudo apt install iptables ip6tables# sudo apt install nftables

                                        ',5),y={href:"https://github.com/XTLS/Xray-core/releases/download/v1.7.0/Xray-linux-64.zip",target:"_blank",rel:"noopener noreferrer"},h={href:"https://github.com/XTLS/Xray-install/blob/main/install-release.sh",target:"_blank",rel:"noopener noreferrer"},f=s("code",null,"# chmod 700 install-release.sh",-1),x=s("code",null,"# ./install-release.sh --local Xray-linux-64.zip",-1),R=t(`

                                        Xray 配置

                                        客户端配置

                                        {
                                           "log": {
                                             "loglevel": "warning"
                                           },
                                        diff --git a/assets/traffic_stats.html-DykdoOew.js b/assets/traffic_stats.html-Ci6G_ygz.js
                                        similarity index 99%
                                        rename from assets/traffic_stats.html-DykdoOew.js
                                        rename to assets/traffic_stats.html-Ci6G_ygz.js
                                        index 9aef1f3d2a..0b1db21092 100644
                                        --- a/assets/traffic_stats.html-DykdoOew.js
                                        +++ b/assets/traffic_stats.html-Ci6G_ygz.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as o,r as a,o as l,c as i,a as t,b as s,d as n,e as c}from"./app-5SoadDYS.js";const u={},r=s("h1",{id:"руководство-по-настроике-статистики-трафика",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#руководство-по-настроике-статистики-трафика"},[s("span",null,"Руководство по настройке статистики трафика")])],-1),d={href:"https://guide.v2fly.org/advanced/traffic.html",target:"_blank",rel:"noopener noreferrer"},v=s("br",null,null,-1),k=c(`

                                        Просмотр статистики трафика

                                        Способ настройки такой же, как и для v2fly. Просмотр статистики трафика - одна из функций командной строки Xray. Порт api dokodemo-door, указанный в конфигурации, - это порт, используемый в параметре --server.

                                        xray api statsquery --server=127.0.0.1:10085 # Просмотр всей статистики трафика
                                        +import{_ as o,r as a,o as l,c as i,a as t,b as s,d as n,e as c}from"./app-Bw2NG-QJ.js";const u={},r=s("h1",{id:"руководство-по-настроике-статистики-трафика",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#руководство-по-настроике-статистики-трафика"},[s("span",null,"Руководство по настройке статистики трафика")])],-1),d={href:"https://guide.v2fly.org/advanced/traffic.html",target:"_blank",rel:"noopener noreferrer"},v=s("br",null,null,-1),k=c(`

                                        Просмотр статистики трафика

                                        Способ настройки такой же, как и для v2fly. Просмотр статистики трафика - одна из функций командной строки Xray. Порт api dokodemo-door, указанный в конфигурации, - это порт, используемый в параметре --server.

                                        xray api statsquery --server=127.0.0.1:10085 # Просмотр всей статистики трафика
                                         xray help api statsquery # statsquery - запрос соответствующих записей
                                         xray help api stats # stats - запрос одной записи
                                         

                                        Пример вывода:

                                        {
                                        diff --git a/assets/traffic_stats.html-CUSefiEt.js b/assets/traffic_stats.html-DamLfymb.js
                                        similarity index 99%
                                        rename from assets/traffic_stats.html-CUSefiEt.js
                                        rename to assets/traffic_stats.html-DamLfymb.js
                                        index 37c0f82067..f304df67c0 100644
                                        --- a/assets/traffic_stats.html-CUSefiEt.js
                                        +++ b/assets/traffic_stats.html-DamLfymb.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as o,r as a,o as l,c as i,a as t,b as s,d as n,e as c}from"./app-5SoadDYS.js";const u={},r=s("h1",{id:"流量统计配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#流量统计配置教程"},[s("span",null,"流量统计配置教程")])],-1),d={href:"https://guide.v2fly.org/advanced/traffic.html",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        查看流量信息

                                        配置方法与 v2fly 一致。 查看流量信息是 xray 命令行的其中一个功能。配置内设置的 api dokodemo-door 端口,即为 --server 参数的端口。

                                        xray api statsquery --server=127.0.0.1:10085 #查看所有流量
                                        +import{_ as o,r as a,o as l,c as i,a as t,b as s,d as n,e as c}from"./app-Bw2NG-QJ.js";const u={},r=s("h1",{id:"流量统计配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#流量统计配置教程"},[s("span",null,"流量统计配置教程")])],-1),d={href:"https://guide.v2fly.org/advanced/traffic.html",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        查看流量信息

                                        配置方法与 v2fly 一致。 查看流量信息是 xray 命令行的其中一个功能。配置内设置的 api dokodemo-door 端口,即为 --server 参数的端口。

                                        xray api statsquery --server=127.0.0.1:10085 #查看所有流量
                                         xray help api statsquery #statsquery 查询匹配的记录
                                         xray help api stats #stats 查询一个记录
                                         

                                        输出例子:

                                        {
                                        diff --git a/assets/traffic_stats.html-YbH2kcvo.js b/assets/traffic_stats.html-DmKVUaJl.js
                                        similarity index 99%
                                        rename from assets/traffic_stats.html-YbH2kcvo.js
                                        rename to assets/traffic_stats.html-DmKVUaJl.js
                                        index 37c0f82067..f304df67c0 100644
                                        --- a/assets/traffic_stats.html-YbH2kcvo.js
                                        +++ b/assets/traffic_stats.html-DmKVUaJl.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as o,r as a,o as l,c as i,a as t,b as s,d as n,e as c}from"./app-5SoadDYS.js";const u={},r=s("h1",{id:"流量统计配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#流量统计配置教程"},[s("span",null,"流量统计配置教程")])],-1),d={href:"https://guide.v2fly.org/advanced/traffic.html",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        查看流量信息

                                        配置方法与 v2fly 一致。 查看流量信息是 xray 命令行的其中一个功能。配置内设置的 api dokodemo-door 端口,即为 --server 参数的端口。

                                        xray api statsquery --server=127.0.0.1:10085 #查看所有流量
                                        +import{_ as o,r as a,o as l,c as i,a as t,b as s,d as n,e as c}from"./app-Bw2NG-QJ.js";const u={},r=s("h1",{id:"流量统计配置教程",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#流量统计配置教程"},[s("span",null,"流量统计配置教程")])],-1),d={href:"https://guide.v2fly.org/advanced/traffic.html",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        查看流量信息

                                        配置方法与 v2fly 一致。 查看流量信息是 xray 命令行的其中一个功能。配置内设置的 api dokodemo-door 端口,即为 --server 参数的端口。

                                        xray api statsquery --server=127.0.0.1:10085 #查看所有流量
                                         xray help api statsquery #statsquery 查询匹配的记录
                                         xray help api stats #stats 查询一个记录
                                         

                                        输出例子:

                                        {
                                        diff --git a/assets/transparent_proxy.html-Bq-tBj5F.js b/assets/transparent_proxy.html-Bml0Br0H.js
                                        similarity index 99%
                                        rename from assets/transparent_proxy.html-Bq-tBj5F.js
                                        rename to assets/transparent_proxy.html-Bml0Br0H.js
                                        index 461c1838da..5549239d50 100644
                                        --- a/assets/transparent_proxy.html-Bq-tBj5F.js
                                        +++ b/assets/transparent_proxy.html-Bml0Br0H.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as c,c as d,a as n,b as a,d as s,w as r,e as p}from"./app-5SoadDYS.js";const u="/assets/netfilter-DeZFCF74.png",b={},m=p('

                                        Погружение в прозрачное проксирование

                                        Что такое прозрачное проксирование?

                                        Проще говоря, прозрачное проксирование не позволяет проксируемому устройству понять, что оно проксируется. Это означает, что на проксируемом устройстве не нужно запускать какое-либо программное обеспечение для проксирования (например, Xray, V2RayNG и т. д.). Когда вы подключаетесь к сети, ваше устройство уже проксируется.

                                        Это также означает, что программное обеспечение прокси работает в другом месте, например, на маршрутизаторе, и устройства, подключенные к Интернету через маршрутизатор, автоматически проксируются.

                                        Реализация прозрачного проксирования

                                        В настоящее время существует два основных способа реализации прозрачного проксирования:

                                        tun2socks

                                        Доступно для Windows/Linux (включая Android). Поскольку процесс реализации относительно прост, существует не так много руководств, поэтому я кратко опишу его здесь.

                                        Windows

                                        ',9),v={href:"https://github.com/NetchX/Netch/releases",target:"_blank",rel:"noopener noreferrer"},k=a("code",null,"[3] [TUN/TAP] Обход локальной сети",-1),h=p("
                                      88. Включите точку доступа.

                                      89. Откройте Панель управления -> Сеть и Интернет -> Центр управления сетями и общим доступом -> Изменение параметров адаптера, найдите TAP-Windows Adapter и Microsoft Wi-Fi Direct Virtual Adapter.

                                      90. Щелкните правой кнопкой мыши TAP-Windows Adapter, Свойства -> Доступ, установите флажок Разрешить другим пользователям сети подключаться к Интернету через это подключение к Интернету, в Домашнее сетевое подключение выберите сетевое подключение Microsoft Wi-Fi Direct Virtual Adapter, нажмите ОК.

                                      91. ",3),g=p('

                                        Android

                                        1. Настройте подключение V2RayNG.

                                        2. Включите точку доступа.

                                        3. Настройки точки доступа -> Разрешить использование VPN для точки доступа (эта опция может отсутствовать в некоторых системах Android).

                                        iptables/nftables

                                        iptables и nftables реализуют прозрачное проксирование по одному и тому же принципу, в дальнейшем мы будем использовать iptables.

                                        Реализация прозрачного проксирования на основе iptables применима только к системам Linux (включая openwrt/Android). Благодаря своей эффективности по сравнению с tun2socks и возможности настройки на маршрутизаторах, она получила широкое распространение.

                                        ',5),R={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},A={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},D=p('

                                        Принцип реализации прозрачного проксирования с помощью iptables

                                        Linux использует Netfilter для управления сетью, модель Netfilter выглядит следующим образом:

                                        Netfilter

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

                                        Направление трафика от устройств локальной сети к Интернету через маршрутизатор:

                                        Цепочка PREROUTING -> Цепочка FORWARD -> Цепочка POSTINGROUTING

                                        Направление трафика от устройств локальной сети к маршрутизатору (например, вход в веб-интерфейс маршрутизатора/подключение к маршрутизатору по ssh/доступ к DNS-серверу маршрутизатора и т. д.):

                                        Цепочка PREROUTING -> Цепочка INPUT -> Хост шлюза

                                        Направление трафика от маршрутизатора к Интернету:

                                        Хост шлюза -> Цепочка OUTPUT -> Цепочка POSTINGROUTING

                                        Управляя направлением трафика цепочек PREROUTING и OUTPUT с помощью iptables и перенаправляя его на Xray, мы можем проксировать устройства локальной сети и хост шлюза.

                                        В чем сложность прозрачного проксирования?

                                        Сложность прозрачного проксирования заключается в маршрутизации, то есть в различении того, какой трафик должен быть прямым, а какой должен проксироваться, поэтому я лично считаю, что термин разделение трафика более уместен.

                                        Мы можем разделить маршрутизацию на следующие этапы по возрастанию сложности:

                                        1. Проксирование всех запросов.
                                        2. Прямое подключение для локальных IP-адресов/многоадресных IP-адресов, проксирование для остальных запросов.
                                        3. На основе пункта 2, прямое подключение для исходящих запросов, инициированных Xray.
                                        4. На основе пункта 3, прямое подключение для запросов, адресованных китайским IP-адресам, и выбор внутренних и внешних DNS-серверов для разрешения внутренних и внешних доменных имен.

                                        Три вышеупомянутых руководства описывают четвертый этап. Поэтому новичкам может быть сложно понять их, читая напрямую.

                                        Пошаговая реализация прозрачного проксирования на основе iptables-tproxy с нуля

                                        Прежде чем начать, вам необходимо иметь базовые знания:

                                        1. Примерное представление о протоколах TCP/IP, доменных именах и DNS-серверах.
                                        2. Знание того, что такое WAN-порт, LAN-порт, LAN_IP, WAN_IP и DHCP-сервер. Для пограничных маршрутизаторов есть только один сетевой порт, который мы будем называть LAN-портом.
                                        3. Базовое понимание системы Linux (знание того, как запускать команды).
                                        4. Умение писать конфигурационные файлы клиента в формате json или, по крайней мере, понимать их.

                                        Предварительная подготовка

                                        Внимание

                                        Перед началом работы не забудьте включить пересылку пакетов ipv4 в Linux с помощью команды sysctl -w net.ipv4.ip_forward=1

                                        1. Подготовьте шлюз под управлением Linux

                                        Например, маршрутизатор с прошивкой OpenWRT.

                                        2. Подготовьте исполняемый файл Xray и конфигурационный файл на шлюзе (маршрутизаторе)

                                        Конфигурационный файл прослушивает порт 12345 и включает tproxy:

                                        {
                                        +import{_ as i,r as t,o as c,c as d,a as n,b as a,d as s,w as r,e as p}from"./app-Bw2NG-QJ.js";const u="/assets/netfilter-DeZFCF74.png",b={},m=p('

                                        Погружение в прозрачное проксирование

                                        Что такое прозрачное проксирование?

                                        Проще говоря, прозрачное проксирование не позволяет проксируемому устройству понять, что оно проксируется. Это означает, что на проксируемом устройстве не нужно запускать какое-либо программное обеспечение для проксирования (например, Xray, V2RayNG и т. д.). Когда вы подключаетесь к сети, ваше устройство уже проксируется.

                                        Это также означает, что программное обеспечение прокси работает в другом месте, например, на маршрутизаторе, и устройства, подключенные к Интернету через маршрутизатор, автоматически проксируются.

                                        Реализация прозрачного проксирования

                                        В настоящее время существует два основных способа реализации прозрачного проксирования:

                                        tun2socks

                                        Доступно для Windows/Linux (включая Android). Поскольку процесс реализации относительно прост, существует не так много руководств, поэтому я кратко опишу его здесь.

                                        Windows

                                        ',9),v={href:"https://github.com/NetchX/Netch/releases",target:"_blank",rel:"noopener noreferrer"},k=a("code",null,"[3] [TUN/TAP] Обход локальной сети",-1),h=p("
                                      92. Включите точку доступа.

                                      93. Откройте Панель управления -> Сеть и Интернет -> Центр управления сетями и общим доступом -> Изменение параметров адаптера, найдите TAP-Windows Adapter и Microsoft Wi-Fi Direct Virtual Adapter.

                                      94. Щелкните правой кнопкой мыши TAP-Windows Adapter, Свойства -> Доступ, установите флажок Разрешить другим пользователям сети подключаться к Интернету через это подключение к Интернету, в Домашнее сетевое подключение выберите сетевое подключение Microsoft Wi-Fi Direct Virtual Adapter, нажмите ОК.

                                      95. ",3),g=p('

                                        Android

                                        1. Настройте подключение V2RayNG.

                                        2. Включите точку доступа.

                                        3. Настройки точки доступа -> Разрешить использование VPN для точки доступа (эта опция может отсутствовать в некоторых системах Android).

                                        iptables/nftables

                                        iptables и nftables реализуют прозрачное проксирование по одному и тому же принципу, в дальнейшем мы будем использовать iptables.

                                        Реализация прозрачного проксирования на основе iptables применима только к системам Linux (включая openwrt/Android). Благодаря своей эффективности по сравнению с tun2socks и возможности настройки на маршрутизаторах, она получила широкое распространение.

                                        ',5),R={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},A={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},D=p('

                                        Принцип реализации прозрачного проксирования с помощью iptables

                                        Linux использует Netfilter для управления сетью, модель Netfilter выглядит следующим образом:

                                        Netfilter

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

                                        Направление трафика от устройств локальной сети к Интернету через маршрутизатор:

                                        Цепочка PREROUTING -> Цепочка FORWARD -> Цепочка POSTINGROUTING

                                        Направление трафика от устройств локальной сети к маршрутизатору (например, вход в веб-интерфейс маршрутизатора/подключение к маршрутизатору по ssh/доступ к DNS-серверу маршрутизатора и т. д.):

                                        Цепочка PREROUTING -> Цепочка INPUT -> Хост шлюза

                                        Направление трафика от маршрутизатора к Интернету:

                                        Хост шлюза -> Цепочка OUTPUT -> Цепочка POSTINGROUTING

                                        Управляя направлением трафика цепочек PREROUTING и OUTPUT с помощью iptables и перенаправляя его на Xray, мы можем проксировать устройства локальной сети и хост шлюза.

                                        В чем сложность прозрачного проксирования?

                                        Сложность прозрачного проксирования заключается в маршрутизации, то есть в различении того, какой трафик должен быть прямым, а какой должен проксироваться, поэтому я лично считаю, что термин разделение трафика более уместен.

                                        Мы можем разделить маршрутизацию на следующие этапы по возрастанию сложности:

                                        1. Проксирование всех запросов.
                                        2. Прямое подключение для локальных IP-адресов/многоадресных IP-адресов, проксирование для остальных запросов.
                                        3. На основе пункта 2, прямое подключение для исходящих запросов, инициированных Xray.
                                        4. На основе пункта 3, прямое подключение для запросов, адресованных китайским IP-адресам, и выбор внутренних и внешних DNS-серверов для разрешения внутренних и внешних доменных имен.

                                        Три вышеупомянутых руководства описывают четвертый этап. Поэтому новичкам может быть сложно понять их, читая напрямую.

                                        Пошаговая реализация прозрачного проксирования на основе iptables-tproxy с нуля

                                        Прежде чем начать, вам необходимо иметь базовые знания:

                                        1. Примерное представление о протоколах TCP/IP, доменных именах и DNS-серверах.
                                        2. Знание того, что такое WAN-порт, LAN-порт, LAN_IP, WAN_IP и DHCP-сервер. Для пограничных маршрутизаторов есть только один сетевой порт, который мы будем называть LAN-портом.
                                        3. Базовое понимание системы Linux (знание того, как запускать команды).
                                        4. Умение писать конфигурационные файлы клиента в формате json или, по крайней мере, понимать их.

                                        Предварительная подготовка

                                        Внимание

                                        Перед началом работы не забудьте включить пересылку пакетов ipv4 в Linux с помощью команды sysctl -w net.ipv4.ip_forward=1

                                        1. Подготовьте шлюз под управлением Linux

                                        Например, маршрутизатор с прошивкой OpenWRT.

                                        2. Подготовьте исполняемый файл Xray и конфигурационный файл на шлюзе (маршрутизаторе)

                                        Конфигурационный файл прослушивает порт 12345 и включает tproxy:

                                        {
                                           "log": {
                                             "loglevel": "warning"
                                           },
                                        diff --git a/assets/transparent_proxy.html-DRs0jlcN.js b/assets/transparent_proxy.html-DDjaWLfB.js
                                        similarity index 99%
                                        rename from assets/transparent_proxy.html-DRs0jlcN.js
                                        rename to assets/transparent_proxy.html-DDjaWLfB.js
                                        index 05527a7284..1af7d6c915 100644
                                        --- a/assets/transparent_proxy.html-DRs0jlcN.js
                                        +++ b/assets/transparent_proxy.html-DDjaWLfB.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as l,o as c,c as d,a as n,b as a,d as s,w as r,e as p}from"./app-5SoadDYS.js";const u="/assets/netfilter-DeZFCF74.png",b={},m=p('

                                        透明代理入门

                                        什么是透明代理

                                        透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。

                                        这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。

                                        透明代理的实现

                                        透明代理的实现目前主要有两种方式:

                                        tun2socks

                                        可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。

                                        Windows

                                        ',9),v={href:"https://github.com/NetchX/Netch/releases",target:"_blank",rel:"noopener noreferrer"},k=a("code",null,"[3] [TUN/TAP] 绕过局域网",-1),h=p("
                                      96. 开启热点

                                      97. 打开控制面板->网络和 Internet->网络和共享中心->更改适配器设置,找到TAP-Windows AdapterMicrosoft Wi-Fi Direct Virtual Adapter

                                      98. 鼠标右键点击TAP-Windows Adapter属性->共享,勾选允许其他网络用户通过此计算机的 Internet 连接来连接,在家庭网络连接中选择Microsoft Wi-Fi Direct Virtual Adapter的那个网络连接,点击确定。

                                      99. ",3),g=p('

                                        Android

                                        1. 配置连接 V2RayNG

                                        2. 开启热点

                                        3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项)

                                        iptables/nftables

                                        iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。

                                        基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。

                                        ',5),R={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},A={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},_=p('

                                        iptables 实现透明代理原理

                                        Linux 使用Netfilter来管理网络,Netfilter模型如下:

                                        Netfilter

                                        假设使用路由器作为网关(即我们平时的上网方式),那么:

                                        局域网设备通过路由器访问互联网的流量方向:

                                        PREROUTING链->FORWARD链->POSTINGROUTING链

                                        局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向:

                                        PREROUTING链->INPUT链->网关本机

                                        路由器访问互联网的流量方向:

                                        网关本机->OUTPUT链->POSTINGROUTING链

                                        通过使用 iptables 操控PREROUTING链OUTPUT链的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。

                                        透明代理难在哪里

                                        透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做分流更加合适。

                                        我们可以把路由由易到难分为以下几个阶段:

                                        1. 代理全部请求

                                        2. 本地局域网 IP/组播 IP 请求直连,其它请求代理

                                        3. 在 2 的基础上直连 Xray 发起的连接请求

                                        4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。

                                        上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。

                                        从零开始一步步实现基于 iptables-tproxy 的透明代理

                                        在开始之前,你需要有一定的基础知识:

                                        1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器

                                        2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口

                                        3. 对 Linux 系统有最基础的了解(知道怎么运行命令)

                                        4. 能够手写客户端 json 文件配置,至少要能看懂

                                        前期准备工作

                                        注意

                                        在开始操作前,记得使用 sysctl -w net.ipv4.ip_forward=1 打开linux ipv4封包转发

                                        1. 准备一个运行 Linux 系统的网关

                                        比如,刷了 OpenWRT 的路由器

                                        2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件

                                        配置文件监听 12345 端口,开启 tproxy:

                                        {
                                        +import{_ as i,r as l,o as c,c as d,a as n,b as a,d as s,w as r,e as p}from"./app-Bw2NG-QJ.js";const u="/assets/netfilter-DeZFCF74.png",b={},m=p('

                                        透明代理入门

                                        什么是透明代理

                                        透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。

                                        这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。

                                        透明代理的实现

                                        透明代理的实现目前主要有两种方式:

                                        tun2socks

                                        可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。

                                        Windows

                                        ',9),v={href:"https://github.com/NetchX/Netch/releases",target:"_blank",rel:"noopener noreferrer"},k=a("code",null,"[3] [TUN/TAP] 绕过局域网",-1),h=p("
                                      100. 开启热点

                                      101. 打开控制面板->网络和 Internet->网络和共享中心->更改适配器设置,找到TAP-Windows AdapterMicrosoft Wi-Fi Direct Virtual Adapter

                                      102. 鼠标右键点击TAP-Windows Adapter属性->共享,勾选允许其他网络用户通过此计算机的 Internet 连接来连接,在家庭网络连接中选择Microsoft Wi-Fi Direct Virtual Adapter的那个网络连接,点击确定。

                                      103. ",3),g=p('

                                        Android

                                        1. 配置连接 V2RayNG

                                        2. 开启热点

                                        3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项)

                                        iptables/nftables

                                        iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。

                                        基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。

                                        ',5),R={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},A={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},_=p('

                                        iptables 实现透明代理原理

                                        Linux 使用Netfilter来管理网络,Netfilter模型如下:

                                        Netfilter

                                        假设使用路由器作为网关(即我们平时的上网方式),那么:

                                        局域网设备通过路由器访问互联网的流量方向:

                                        PREROUTING链->FORWARD链->POSTINGROUTING链

                                        局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向:

                                        PREROUTING链->INPUT链->网关本机

                                        路由器访问互联网的流量方向:

                                        网关本机->OUTPUT链->POSTINGROUTING链

                                        通过使用 iptables 操控PREROUTING链OUTPUT链的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。

                                        透明代理难在哪里

                                        透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做分流更加合适。

                                        我们可以把路由由易到难分为以下几个阶段:

                                        1. 代理全部请求

                                        2. 本地局域网 IP/组播 IP 请求直连,其它请求代理

                                        3. 在 2 的基础上直连 Xray 发起的连接请求

                                        4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。

                                        上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。

                                        从零开始一步步实现基于 iptables-tproxy 的透明代理

                                        在开始之前,你需要有一定的基础知识:

                                        1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器

                                        2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口

                                        3. 对 Linux 系统有最基础的了解(知道怎么运行命令)

                                        4. 能够手写客户端 json 文件配置,至少要能看懂

                                        前期准备工作

                                        注意

                                        在开始操作前,记得使用 sysctl -w net.ipv4.ip_forward=1 打开linux ipv4封包转发

                                        1. 准备一个运行 Linux 系统的网关

                                        比如,刷了 OpenWRT 的路由器

                                        2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件

                                        配置文件监听 12345 端口,开启 tproxy:

                                        {
                                           "log": {
                                             "loglevel": "warning"
                                           },
                                        diff --git a/assets/transparent_proxy.html-BpVZ3iLf.js b/assets/transparent_proxy.html-sYVo5ZWT.js
                                        similarity index 99%
                                        rename from assets/transparent_proxy.html-BpVZ3iLf.js
                                        rename to assets/transparent_proxy.html-sYVo5ZWT.js
                                        index 3858403d6b..c227b09deb 100644
                                        --- a/assets/transparent_proxy.html-BpVZ3iLf.js
                                        +++ b/assets/transparent_proxy.html-sYVo5ZWT.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as l,o as c,c as d,a as n,b as a,d as s,w as r,e as p}from"./app-5SoadDYS.js";const u="/assets/netfilter-DeZFCF74.png",b={},m=p('

                                        透明代理入门

                                        什么是透明代理

                                        透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。

                                        这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。

                                        透明代理的实现

                                        透明代理的实现目前主要有两种方式:

                                        tun2socks

                                        可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。

                                        Windows

                                        ',9),v={href:"https://github.com/NetchX/Netch/releases",target:"_blank",rel:"noopener noreferrer"},k=a("code",null,"[3] [TUN/TAP] 绕过局域网",-1),h=p("
                                      104. 开启热点

                                      105. 打开控制面板->网络和 Internet->网络和共享中心->更改适配器设置,找到TAP-Windows AdapterMicrosoft Wi-Fi Direct Virtual Adapter

                                      106. 鼠标右键点击TAP-Windows Adapter属性->共享,勾选允许其他网络用户通过此计算机的 Internet 连接来连接,在家庭网络连接中选择Microsoft Wi-Fi Direct Virtual Adapter的那个网络连接,点击确定。

                                      107. ",3),g=p('

                                        Android

                                        1. 配置连接 V2RayNG

                                        2. 开启热点

                                        3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项)

                                        iptables/nftables

                                        iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。

                                        基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。

                                        ',5),R={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},A={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},_=p('

                                        iptables 实现透明代理原理

                                        Linux 使用Netfilter来管理网络,Netfilter模型如下:

                                        Netfilter

                                        假设使用路由器作为网关(即我们平时的上网方式),那么:

                                        局域网设备通过路由器访问互联网的流量方向:

                                        PREROUTING链->FORWARD链->POSTINGROUTING链

                                        局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向:

                                        PREROUTING链->INPUT链->网关本机

                                        路由器访问互联网的流量方向:

                                        网关本机->OUTPUT链->POSTINGROUTING链

                                        通过使用 iptables 操控PREROUTING链OUTPUT链的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。

                                        透明代理难在哪里

                                        透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做分流更加合适。

                                        我们可以把路由由易到难分为以下几个阶段:

                                        1. 代理全部请求

                                        2. 本地局域网 IP/组播 IP 请求直连,其它请求代理

                                        3. 在 2 的基础上直连 Xray 发起的连接请求

                                        4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。

                                        上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。

                                        从零开始一步步实现基于 iptables-tproxy 的透明代理

                                        在开始之前,你需要有一定的基础知识:

                                        1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器

                                        2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口

                                        3. 对 Linux 系统有最基础的了解(知道怎么运行命令)

                                        4. 能够手写客户端 json 文件配置,至少要能看懂

                                        前期准备工作

                                        1. 准备一个运行 Linux 系统的网关

                                        比如,刷了 OpenWRT 的路由器

                                        2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件

                                        配置文件监听 12345 端口,开启 tproxy:

                                        {
                                        +import{_ as i,r as l,o as c,c as d,a as n,b as a,d as s,w as r,e as p}from"./app-Bw2NG-QJ.js";const u="/assets/netfilter-DeZFCF74.png",b={},m=p('

                                        透明代理入门

                                        什么是透明代理

                                        透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。

                                        这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。

                                        透明代理的实现

                                        透明代理的实现目前主要有两种方式:

                                        tun2socks

                                        可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。

                                        Windows

                                        ',9),v={href:"https://github.com/NetchX/Netch/releases",target:"_blank",rel:"noopener noreferrer"},k=a("code",null,"[3] [TUN/TAP] 绕过局域网",-1),h=p("
                                      108. 开启热点

                                      109. 打开控制面板->网络和 Internet->网络和共享中心->更改适配器设置,找到TAP-Windows AdapterMicrosoft Wi-Fi Direct Virtual Adapter

                                      110. 鼠标右键点击TAP-Windows Adapter属性->共享,勾选允许其他网络用户通过此计算机的 Internet 连接来连接,在家庭网络连接中选择Microsoft Wi-Fi Direct Virtual Adapter的那个网络连接,点击确定。

                                      111. ",3),g=p('

                                        Android

                                        1. 配置连接 V2RayNG

                                        2. 开启热点

                                        3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项)

                                        iptables/nftables

                                        iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。

                                        基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。

                                        ',5),R={href:"https://guide.v2fly.org/app/transparent_proxy.html",target:"_blank",rel:"noopener noreferrer"},A={href:"https://guide.v2fly.org/app/tproxy.html",target:"_blank",rel:"noopener noreferrer"},_=p('

                                        iptables 实现透明代理原理

                                        Linux 使用Netfilter来管理网络,Netfilter模型如下:

                                        Netfilter

                                        假设使用路由器作为网关(即我们平时的上网方式),那么:

                                        局域网设备通过路由器访问互联网的流量方向:

                                        PREROUTING链->FORWARD链->POSTINGROUTING链

                                        局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向:

                                        PREROUTING链->INPUT链->网关本机

                                        路由器访问互联网的流量方向:

                                        网关本机->OUTPUT链->POSTINGROUTING链

                                        通过使用 iptables 操控PREROUTING链OUTPUT链的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。

                                        透明代理难在哪里

                                        透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做分流更加合适。

                                        我们可以把路由由易到难分为以下几个阶段:

                                        1. 代理全部请求

                                        2. 本地局域网 IP/组播 IP 请求直连,其它请求代理

                                        3. 在 2 的基础上直连 Xray 发起的连接请求

                                        4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。

                                        上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。

                                        从零开始一步步实现基于 iptables-tproxy 的透明代理

                                        在开始之前,你需要有一定的基础知识:

                                        1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器

                                        2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口

                                        3. 对 Linux 系统有最基础的了解(知道怎么运行命令)

                                        4. 能够手写客户端 json 文件配置,至少要能看懂

                                        前期准备工作

                                        1. 准备一个运行 Linux 系统的网关

                                        比如,刷了 OpenWRT 的路由器

                                        2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件

                                        配置文件监听 12345 端口,开启 tproxy:

                                        {
                                           "log": {
                                             "loglevel": "warning"
                                           },
                                        diff --git a/assets/transport.html-DBN2ZByF.js b/assets/transport.html-CMtV0LnR.js
                                        similarity index 99%
                                        rename from assets/transport.html-DBN2ZByF.js
                                        rename to assets/transport.html-CMtV0LnR.js
                                        index e0fd71ac78..7f0bd5a876 100644
                                        --- a/assets/transport.html-DBN2ZByF.js
                                        +++ b/assets/transport.html-CMtV0LnR.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as c,o as i,c as r,a as t,b as n,d as s,w as e,e as a}from"./app-5SoadDYS.js";const d={},k=a('

                                        传输方式(uTLS、REALITY)

                                        传输方式(transport)是当前 Xray 节点和其它节点对接的方式。

                                        传输方式指定了稳定的数据传输的方式。通常来说,一个网络连接的两端需要有对称的传输方式。比如一端用了 WebSocket,那么另一个端也必须使用 WebSocket,否则无法建立连接。

                                        传输方式(transport)配置有两部分:

                                        1. 全局配置(TransportObject)(已弃用)

                                        2. 局部配置(StreamSettingsObject)。

                                        • 局部配置时,可以指定每个单独的入站或出站用怎样的方式传输。
                                        • 通常来说客户端和服务器对应的入站和出站需要使用同样的传输方式。当其配置指定了一种传输方式,但没有填写具体设置时,此传输方式会使用全局配置中的设置。
                                        ',6),q=a(`全局配置

                                        TransportObject(已弃用)

                                        TransportObject 对应配置文件的 transport 项。

                                        {
                                        +import{_ as u,r as c,o as i,c as r,a as t,b as n,d as s,w as e,e as a}from"./app-Bw2NG-QJ.js";const d={},k=a('

                                        传输方式(uTLS、REALITY)

                                        传输方式(transport)是当前 Xray 节点和其它节点对接的方式。

                                        传输方式指定了稳定的数据传输的方式。通常来说,一个网络连接的两端需要有对称的传输方式。比如一端用了 WebSocket,那么另一个端也必须使用 WebSocket,否则无法建立连接。

                                        传输方式(transport)配置有两部分:

                                        1. 全局配置(TransportObject)(已弃用)

                                        2. 局部配置(StreamSettingsObject)。

                                        • 局部配置时,可以指定每个单独的入站或出站用怎样的方式传输。
                                        • 通常来说客户端和服务器对应的入站和出站需要使用同样的传输方式。当其配置指定了一种传输方式,但没有填写具体设置时,此传输方式会使用全局配置中的设置。
                                        ',6),q=a(`全局配置

                                        TransportObject(已弃用)

                                        TransportObject 对应配置文件的 transport 项。

                                        {
                                           "transport": {
                                             "tcpSettings": {},
                                             "kcpSettings": {},
                                        diff --git a/assets/transport.html-BshIocQ3.js b/assets/transport.html-COHavdZy.js
                                        similarity index 99%
                                        rename from assets/transport.html-BshIocQ3.js
                                        rename to assets/transport.html-COHavdZy.js
                                        index 79269f2ed8..f53017fff9 100644
                                        --- a/assets/transport.html-BshIocQ3.js
                                        +++ b/assets/transport.html-COHavdZy.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as c,o as r,c as u,a as t,b as e,d as n,w as o,e as a}from"./app-5SoadDYS.js";const d={},h=a('

                                        Transport

                                        Transports specify how Xray communicates with peers.

                                        Transports specify how to achieve stable data transmission. Both ends of a connection often need to specify the same transport protocol to successfully establish a connection. Like, if one end uses WebSocket, the other end must also use WebSocket, or else the connection cannot be established.

                                        Transport configuration consists of two parts:

                                        1. Global config (TransportObject) (deprecated)
                                        2. Local config (StreamSettingsObject).
                                        • When locally configured, you can specify how each inbound or outbound connection is transmitted individually.
                                        • Server inbounds and client outbounds often need to use the same transport protocol. When a transport protocol is specified without local configs, the transport will fall back to global transport configs.
                                        ',6),k=a(`Global configuration (deprecated)

                                        TransportObject (deprecated)

                                        The TransportObject corresponds to the transport property in the config root.

                                        {
                                        +import{_ as l,r as c,o as r,c as u,a as t,b as e,d as n,w as o,e as a}from"./app-Bw2NG-QJ.js";const d={},h=a('

                                        Transport

                                        Transports specify how Xray communicates with peers.

                                        Transports specify how to achieve stable data transmission. Both ends of a connection often need to specify the same transport protocol to successfully establish a connection. Like, if one end uses WebSocket, the other end must also use WebSocket, or else the connection cannot be established.

                                        Transport configuration consists of two parts:

                                        1. Global config (TransportObject) (deprecated)
                                        2. Local config (StreamSettingsObject).
                                        • When locally configured, you can specify how each inbound or outbound connection is transmitted individually.
                                        • Server inbounds and client outbounds often need to use the same transport protocol. When a transport protocol is specified without local configs, the transport will fall back to global transport configs.
                                        ',6),k=a(`Global configuration (deprecated)

                                        TransportObject (deprecated)

                                        The TransportObject corresponds to the transport property in the config root.

                                        {
                                           "transport": {
                                             "tcpSettings": {},
                                             "kcpSettings": {},
                                        diff --git a/assets/transport.html-Dzmzsfae.js b/assets/transport.html-CUhGNa4n.js
                                        similarity index 99%
                                        rename from assets/transport.html-Dzmzsfae.js
                                        rename to assets/transport.html-CUhGNa4n.js
                                        index 8333d458ef..ba09a4fd42 100644
                                        --- a/assets/transport.html-Dzmzsfae.js
                                        +++ b/assets/transport.html-CUhGNa4n.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as c,o as i,c as r,a as o,b as n,d as s,w as e,e as a}from"./app-5SoadDYS.js";const d={},k=a('

                                        Транспорт

                                        Транспорт (transport) - это способ, которым текущий узел Xray взаимодействует с другими узлами.

                                        Транспорт определяет способ передачи данных. Обычно оба конца сетевого подключения должны использовать одинаковый транспорт.
                                        Например, если один конец использует WebSocket, то другой конец также должен использовать WebSocket, иначе соединение не будет установлено.

                                        Настройка транспорта (transport) состоит из двух частей:

                                        1. Глобальные настройки (TransportObject) (устарело)
                                        2. Локальные настройки (StreamSettingsObject).
                                        • Локальные настройки позволяют указать способ передачи данных для каждого отдельного входящего или исходящего подключения.
                                        • Обычно клиент и сервер должны использовать одинаковый транспорт для соответствующих входящих и исходящих подключений.
                                          Если в настройках указан тип транспорта, но не указаны конкретные параметры, будут использованы настройки из глобальной конфигурации.
                                        ',6),q=a(`Глобальные настройки

                                        TransportObject (устарело)

                                        TransportObject соответствует полю transport в конфигурационном файле.

                                        {
                                        +import{_ as u,r as c,o as i,c as r,a as o,b as n,d as s,w as e,e as a}from"./app-Bw2NG-QJ.js";const d={},k=a('

                                        Транспорт

                                        Транспорт (transport) - это способ, которым текущий узел Xray взаимодействует с другими узлами.

                                        Транспорт определяет способ передачи данных. Обычно оба конца сетевого подключения должны использовать одинаковый транспорт.
                                        Например, если один конец использует WebSocket, то другой конец также должен использовать WebSocket, иначе соединение не будет установлено.

                                        Настройка транспорта (transport) состоит из двух частей:

                                        1. Глобальные настройки (TransportObject) (устарело)
                                        2. Локальные настройки (StreamSettingsObject).
                                        • Локальные настройки позволяют указать способ передачи данных для каждого отдельного входящего или исходящего подключения.
                                        • Обычно клиент и сервер должны использовать одинаковый транспорт для соответствующих входящих и исходящих подключений.
                                          Если в настройках указан тип транспорта, но не указаны конкретные параметры, будут использованы настройки из глобальной конфигурации.
                                        ',6),q=a(`Глобальные настройки

                                        TransportObject (устарело)

                                        TransportObject соответствует полю transport в конфигурационном файле.

                                        {
                                           "transport": {
                                             "tcpSettings": {},
                                             "kcpSettings": {},
                                        diff --git a/assets/trojan.html-CGfwGdDo.js b/assets/trojan.html-C2jCtoPN.js
                                        similarity index 98%
                                        rename from assets/trojan.html-CGfwGdDo.js
                                        rename to assets/trojan.html-C2jCtoPN.js
                                        index 268d5edb96..614843c2d9 100644
                                        --- a/assets/trojan.html-CGfwGdDo.js
                                        +++ b/assets/trojan.html-C2jCtoPN.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as o,o as r,c as u,a,b as e,d as n,w as t,e as c}from"./app-5SoadDYS.js";const d={},b=e("h1",{id:"trojan",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#trojan"},[e("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        Danger

                                        Trojan is designed to work with correctly configured encrypted TLS tunnels.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as p,r as o,o as r,c as u,a,b as e,d as n,w as t,e as c}from"./app-Bw2NG-QJ.js";const d={},b=e("h1",{id:"trojan",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#trojan"},[e("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        Danger

                                        Trojan is designed to work with correctly configured encrypted TLS tunnels.

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "password": "password",
                                        diff --git a/assets/trojan.html-DmgOhScb.js b/assets/trojan.html-CSDiydOe.js
                                        similarity index 98%
                                        rename from assets/trojan.html-DmgOhScb.js
                                        rename to assets/trojan.html-CSDiydOe.js
                                        index 6f717bed37..3c8fb6e651 100644
                                        --- a/assets/trojan.html-DmgOhScb.js
                                        +++ b/assets/trojan.html-CSDiydOe.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as a,o as l,c as i,a as e,b as s,d as n,w as t,e as u}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        Danger

                                        Trojan is designed to work with correctly configured encrypted TLS tunnels.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as c,r as a,o as l,c as i,a as e,b as s,d as n,w as t,e as u}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        Danger

                                        Trojan is designed to work with correctly configured encrypted TLS tunnels.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/trojan.html-D2PfY2T3.js b/assets/trojan.html-Cs7YEsIb.js
                                        similarity index 98%
                                        rename from assets/trojan.html-D2PfY2T3.js
                                        rename to assets/trojan.html-Cs7YEsIb.js
                                        index 3251eca2bf..c9d1dca36a 100644
                                        --- a/assets/trojan.html-D2PfY2T3.js
                                        +++ b/assets/trojan.html-Cs7YEsIb.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as r,c as u,a,b as s,d as n,w as o,e as c}from"./app-5SoadDYS.js";const d={},b=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        警告

                                        Trojan 被设计工作在正确配置的加密 TLS 隧道

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as r,c as u,a,b as s,d as n,w as o,e as c}from"./app-Bw2NG-QJ.js";const d={},b=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},v=c(`

                                        警告

                                        Trojan 被设计工作在正确配置的加密 TLS 隧道

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "password": "password",
                                        diff --git a/assets/trojan.html-CgBPDtHB.js b/assets/trojan.html-WsfP1d7V.js
                                        similarity index 99%
                                        rename from assets/trojan.html-CgBPDtHB.js
                                        rename to assets/trojan.html-WsfP1d7V.js
                                        index a024ddb046..723bad3351 100644
                                        --- a/assets/trojan.html-CgBPDtHB.js
                                        +++ b/assets/trojan.html-WsfP1d7V.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as r,c as u,a,b as s,d as n,w as o,e as l}from"./app-5SoadDYS.js";const d={},b=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},v=l(`

                                        Предупреждение

                                        Trojan предназначен для работы в правильно настроенном зашифрованном TLS-туннеле.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as r,c as u,a,b as s,d as n,w as o,e as l}from"./app-Bw2NG-QJ.js";const d={},b=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},v=l(`

                                        Предупреждение

                                        Trojan предназначен для работы в правильно настроенном зашифрованном TLS-туннеле.

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "password": "password",
                                        diff --git a/assets/trojan.html-DvVg8oOZ.js b/assets/trojan.html-ZC1LUXUu.js
                                        similarity index 98%
                                        rename from assets/trojan.html-DvVg8oOZ.js
                                        rename to assets/trojan.html-ZC1LUXUu.js
                                        index 422040ae90..a9ca07b9a8 100644
                                        --- a/assets/trojan.html-DvVg8oOZ.js
                                        +++ b/assets/trojan.html-ZC1LUXUu.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as e,o as l,c as i,a,b as s,d as n,w as t,e as u}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        Предупреждение

                                        Trojan предназначен для работы в правильно настроенном зашифрованном TLS-туннеле.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as r,r as e,o as l,c as i,a,b as s,d as n,w as t,e as u}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        Предупреждение

                                        Trojan предназначен для работы в правильно настроенном зашифрованном TLS-туннеле.

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/trojan.html-GLPr9L0R.js b/assets/trojan.html-a1Coa5-Z.js
                                        similarity index 98%
                                        rename from assets/trojan.html-GLPr9L0R.js
                                        rename to assets/trojan.html-a1Coa5-Z.js
                                        index d5b4ccf375..114fb2b58e 100644
                                        --- a/assets/trojan.html-GLPr9L0R.js
                                        +++ b/assets/trojan.html-a1Coa5-Z.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as e,o as l,c as i,a,b as s,d as n,w as t,e as u}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        警告

                                        Trojan 被设计工作在正确配置的加密 TLS 隧道

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as r,r as e,o as l,c as i,a,b as s,d as n,w as t,e as u}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"trojan",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#trojan"},[s("span",null,"Trojan")])],-1),k={href:"https://trojan-gfw.github.io/trojan/protocol",target:"_blank",rel:"noopener noreferrer"},b=u(`

                                        警告

                                        Trojan 被设计工作在正确配置的加密 TLS 隧道

                                        OutboundConfigurationObject

                                        {
                                           "servers": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/vless.html-CTPUBSmN.js b/assets/vless.html-B7O7xjrb.js
                                        similarity index 99%
                                        rename from assets/vless.html-CTPUBSmN.js
                                        rename to assets/vless.html-B7O7xjrb.js
                                        index 6a6a38e96c..0bd8aeb3f6 100644
                                        --- a/assets/vless.html-CTPUBSmN.js
                                        +++ b/assets/vless.html-B7O7xjrb.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as u,c as r,a as e,b as n,d as s,w as a,e as l}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"vless",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless"},[n("span",null,"VLESS")])],-1),b=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"Предупреждение"),n("p",null,"VLESS не предусматривает встроенного шифрования, поэтому обязательным условием для его использования является наличие надежного канала, такого как TLS или REALITY.")],-1),v=n("p",null,"VLESS - это легкий транспортный протокол без сохранения состояния, который разделен на входящую и исходящую части и может служить мостом между клиентом и сервером Xray.",-1),q=l(`

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as u,c as r,a as e,b as n,d as s,w as a,e as l}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"vless",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless"},[n("span",null,"VLESS")])],-1),b=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"Предупреждение"),n("p",null,"VLESS не предусматривает встроенного шифрования, поэтому обязательным условием для его использования является наличие надежного канала, такого как TLS или REALITY.")],-1),v=n("p",null,"VLESS - это легкий транспортный протокол без сохранения состояния, который разделен на входящую и исходящую части и может служить мостом между клиентом и сервером Xray.",-1),q=l(`

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "id": "5783a3e7-e373-51cd-8642-c83782b807c5",
                                        diff --git a/assets/vless.html-BL9BeTeh.js b/assets/vless.html-BM3ph8gg.js
                                        similarity index 99%
                                        rename from assets/vless.html-BL9BeTeh.js
                                        rename to assets/vless.html-BM3ph8gg.js
                                        index 2ba21257a4..f7f952759c 100644
                                        --- a/assets/vless.html-BL9BeTeh.js
                                        +++ b/assets/vless.html-BM3ph8gg.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as a,o as r,c as u,a as s,b as n,d as e,w as t,e as l}from"./app-5SoadDYS.js";const d={},h=n("h1",{id:"vless",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless"},[n("span",null,"VLESS")])],-1),b=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"Danger"),n("p",null,"Currently, VLESS does not provide built-in encryption. Please use it with a reliable channel, such as TLS.")],-1),v=n("p",null,"VLESS is a stateless lightweight transport protocol that consists of inbound and outbound parts. It can serve as a bridge between Xray clients and servers.",-1),m=l(`

                                        InboundConfigurationObject

                                        {
                                        +import{_ as p,r as a,o as r,c as u,a as s,b as n,d as e,w as t,e as l}from"./app-Bw2NG-QJ.js";const d={},h=n("h1",{id:"vless",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless"},[n("span",null,"VLESS")])],-1),b=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"Danger"),n("p",null,"Currently, VLESS does not provide built-in encryption. Please use it with a reliable channel, such as TLS.")],-1),v=n("p",null,"VLESS is a stateless lightweight transport protocol that consists of inbound and outbound parts. It can serve as a bridge between Xray clients and servers.",-1),m=l(`

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "id": "5783a3e7-e373-51cd-8642-c83782b807c5",
                                        diff --git a/assets/vless.html-CDOsAnQk.js b/assets/vless.html-BWup8Xzq.js
                                        similarity index 99%
                                        rename from assets/vless.html-CDOsAnQk.js
                                        rename to assets/vless.html-BWup8Xzq.js
                                        index 73ae4f87ba..f3449de6e0 100644
                                        --- a/assets/vless.html-CDOsAnQk.js
                                        +++ b/assets/vless.html-BWup8Xzq.js
                                        @@ -1 +1 @@
                                        -import{_ as r,r as i,o as d,c as h,a as o,b as e,d as t,e as a}from"./app-5SoadDYS.js";const l={},c=a('

                                        VLESS Protocol

                                        VLESS is a stateless lightweight transmission protocol that can be used as a bridge between Xray clients and servers.

                                        Request & Response

                                        1 byte16 bytes1 byteM bytes1 byte2 bytes1 byteS bytesX bytes
                                        Protocol VersionEquivalent UUIDAdditional Information Length MAdditional Information ProtoBufInstructionPortAddress TypeAddressRequest Data
                                        1 Byte1 ByteN BytesY Bytes
                                        Protocol Version, consistent with the requestLength of additional information NAdditional information in ProtoBufResponse data

                                        VLESS had the aforementioned structure as early as the second alpha test version (ALPHA 2), with BETA being the fifth test version.

                                        ',6),p=e("code",null,"Response authentication",-1),u=e("code",null,"Protocol version",-1),f=e("code",null,"Additional information",-1),m={href:"https://github.com/gogo/protobuf",target:"_blank",rel:"noopener noreferrer"},y=e("p",null,'I always thought that "response authentication" was not necessary, and ALPHA replaced crypto/rand with math/rand in order to improve the performance of random number generation, which is no longer needed.',-1),b=e("p",null,'The "Protocol Version" not only serves as "Response Authentication", but also gives VLESS the ability to upgrade the protocol structure seamlessly, bringing infinite possibilities. The "Protocol Version" is 0 in the test version and 1 in the official version. If there are any incompatible protocol structural changes in the future, the version should be upgraded.',-1),g=e("p",null,"The design of VLESS server is switch version, which supports all VLESS versions at the same time. If you need to upgrade the protocol version (which may not happen), it is recommended that the server support it one month in advance, and then change the client after one month. VMess requests also have protocol versions, but their authentication information is outside, and the instruction part is highly coupled and has fixed encryption, which makes the protocol version meaningless inside. The server does not judge it, and the response does not have a protocol version. Trojan's protocol structure does not have a protocol version.",-1),v=e("p",null,"The following is a UUID. I used to think that 16 bytes were a bit long and considered shortening it. However, I later saw that Trojan used 56 printable characters (56 bytes), which completely dispelled this idea. The server needs to verify the UUID every time, so performance is also very important: VLESS's Validator has undergone multiple refactoring/upgrades. Compared with VMess, it is very concise and consumes very few resources. It can support a large number of users at the same time, and its performance is also very strong. The verification speed is extremely fast (sync.Map). API dynamically adds and deletes users, making it more efficient and smooth. https://github.com/XTLS/Xray-core/issues/158",-1),w=e("p",null,'Introducing ProtoBuf is an innovation, which will be explained in detail later. The structure from "instruction" to "address" is currently identical to VMess and also supports Mux.',-1),S={href:"https://github.com/rprx/v2ray-vless/releases",target:"_blank",rel:"noopener noreferrer"},_=a('

                                        ProtoBuf

                                        It seems that only VLESS supports embedding ProtoBuf, which is a data exchange format that encodes information tightly into binary TLV (Tag Length Value) structures.

                                        The reason is that I saw an article that said that SS has some drawbacks, such as the lack of a design error reporting mechanism, and the client cannot take further action based on different errors. (But I don't agree that all errors should be reported, otherwise it can't prevent active probing. In the next beta version, the server can return a custom string of information.) So I think a scalable structure is important, and in the future, it can also carry dynamic port instructions. Not only the response, but the request also needs a similar structure. I originally planned to design TLV by myself, but then I found that ProtoBuf is the structure, ready-made, and it is completely suitable for this purpose, and the support for various languages is also good.

                                        Currently, "Additional Information" only has Scheduler and SchedulerV, which are substitutes for MessName and MessSeed. When you don't need them, the "Additional Information Length" is 0, so there is no ProtoBuf serialization/deserialization overhead. Actually, I prefer to call this process "concatenation" because that's all pb does in principle, and the related overhead is minimal. The concatenated bytes are very compact, similar to ALPHA's solution, and those who are interested can output and compare them separately.

                                        To indicate different levels of support for additional information (Addons, which can be understood as plugins and can have many plugins in the future), the next beta version will add "Addon Version" before "Addon Length". 256-1 = 255 bytes is enough and reasonable (65535 is too much and there may be malicious padding), and only one-tenth of the existing space is used. In the future, there will not be so many addons at the same time, and most of the time there will be no addons at all. If it is not enough, you can upgrade to a newer version of VLESS.

                                        To reduce logical judgment and other expenses, it is temporarily decided that Addons will not use a multi-level structure. A month ago, there was an idea of "variable protocol format". PB can shuffle the order, but it is not necessary because the design of modern encryption will not allow bystanders to see that the headers of the two transmissions are the same.

                                        Below is an introduction to the concepts of Schedulers and Encryption, both of which are optional. One is designed to address issues related to traffic timing, while the other is designed to address cryptographic issues.

                                        Flow

                                        Flow Control (Formerly Traffic Scheduler)

                                        The Flow Control command is carried by ProtoBuf and manages the data section.

                                        I previously discovered that VMess's original "metadata obfuscation" feature didn't provide any meaningful changes in TLS but only decreased performance. Consequently, VLESS has abandoned this feature. Moreover, the term "obfuscation" is often misinterpreted as camouflage, so it has been discarded.

                                        As for camouflage, if it can't be an exact match, wouldn't it be a noticeable characteristic? If it could be an exact match, why not use the intended target for camouflage directly? Initially, I used SSR but found it only provided superficial disguises, fooling operators. Thus, I stopped using it.

                                        Purpose of Flow Control

                                        Flow Control influences macro traffic temporal characteristics rather than micro characteristics addressed by encryption. Traffic temporal characteristics can be:

                                        1. Protocol-based, e.g., Socks5 handshake when using Socks5 over TLS. Different traits on TLS are considered different protocols for monitors. Infinite schedulers equate to infinite protocols (reallocating data sent each time).
                                        2. Behavior-based, e.g., loading files, their order, and size when accessing Google's homepage. Adding another encryption layer cannot effectively conceal this information.

                                        Schedulers don't require wrapping like encryption since the header data's tiny amount is negligible compared to the remaining data.

                                        BETA 2 is anticipated to introduce two basic schedulers: Zstd compression and dynamic data expansion. Advanced operations will control and distribute at a macro level, but for now, these remain under development.

                                        Encryption

                                        Unlike VMess, which is highly coupled, VLESS allows the server and client to pre-agree on an encryption method, which is only encrypted with an outer layer. This is somewhat similar to using TLS, which does not affect any of the data carried, and can be understood as replacing TLS with pre-agreed encryption at the bottom. Compared with high coupling, this approach is more reasonable and flexible: if there is a security issue with one encryption method, it can be discarded and another one can be used directly, which is very convenient. The VLESS server also allows for different encryption methods to coexist.

                                        Compared with VMess, VLESS replaces security with encryption and disableInsecureEncryption with decryption, which solves all the problems. Currently, encryption and decryption only accept "none" and cannot be left blank (even if there are connection security checks in the future), as detailed in the VLESS configuration document. Encryption does not need to be moved out one level, firstly because it cannot reuse a lot of code, and secondly because it will affect the control granularity, which will be understood by looking at future applications.

                                        Encryption supports two types of forms. One type is completely independent and requires an additional password, suitable for private use. The other type combines with the existing UUID for encryption, which is suitable for public use.

                                        (If the first type of encryption is used and the password is publicly available in some form, such as multiple people sharing it, then a man-in-the-middle attack is not far away.)

                                        A redesigned dynamic port may be released simultaneously with encryption, and the command is carried by ProtoBuf. The specific implementation and the dynamic port of VMess will also have many differences.

                                        It is very easy to cash out encrypted currency, which adds an extra layer of writer & reader. BETA 3 is expected to support SS's aes-128-gcm and chacha20-ietf-poly1305:

                                        The encryption on the client-side can be filled with "auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654". Auto will choose the most suitable one for the current machine, 0 represents the beta version, and the last one is the password. The decryption on the server-side is also filled in a similar way, and each decryption attempt will be made when the request is received.

                                        Not all combinations need to be tried one by one: VMess encryption is divided into three parts. The first part is the authentication information, which combines UUID, alterId, and time factors. The second part is the instruction part, which is encrypted using a fixed algorithm. The instruction contains the encryption algorithm used in the data part. The third part is the important data part. It can be seen that the VMess encryption and decryption method is actually many-to-one (adapted by the server), not just combining UUID. However, it is also a relatively difficult thing to encrypt only by combining UUID. It will not be available in a short time. Considering that we now have VMessAEAD available, there is no need to rush. If VLESS introduces an encryption method that combines UUID, it is equivalent to reconstructing the entire VMess.

                                        UDP issues

                                        ',27),T={href:"https://github.com/XTLS/Xray-core/discussions/252",target:"_blank",rel:"noopener noreferrer"},V=a('

                                        Client Development Guide

                                        1. The VLESS protocol itself may have incompatible upgrades, but the parameters in the client configuration file are basically only increased and not decreased. The protocol implementation of the iOS client needs to keep up with the upgrade.
                                        2. Visual standard: Please use VLESS as the UI identifier uniformly, instead of VLess / Vless / vless. The configuration file is not affected, and the code should follow naturally.
                                        3. Encryption should be made into an input box instead of a selection box. The default value of the new configuration should be none, and if the user leaves it blank, it should be filled in with none.
                                        ',3),I={href:"https://github.com/DuckSoft",target:"_blank",rel:"noopener noreferrer"},L={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"};function A(x,E){const s=i("I18nTip"),n=i("ExternalLinkIcon");return d(),h("div",null,[o(s),c,e("p",null,[t('"'),p,t('" has been replaced with "'),u,t('" and moved to the front, allowing VLESS to upgrade and eliminate the overhead of generating pseudo-random numbers. The obfuscation-related structure has been replaced with "'),f,t('" (ProtoBuf) and moved forward, giving the protocol itself scalability, with minimal overhead ('),e("a",m,[t("gogo/protobuf"),o(n)]),t("). If there is no additional information, there is no relevant overhead.")]),y,b,g,v,w,e("p",null,[t("Overall, ALPHA 2 to BETA mainly includes: structural evolution, cleaning and integration, performance improvement, and more completeness. All of these are incremental improvements, please refer to "),e("a",S,[t("VLESS Changes"),o(n)]),t(" for details.")]),_,e("p",null,[e("a",T,[t("XUDP: VLESS & VMess & Mux UDP FullCone NAT"),o(n)])]),V,e("p",null,[t("Thank you to "),e("a",I,[t("@DuckSoft"),o(n)]),t(" for the proposal!")]),e("p",null,[t("Please see "),e("a",L,[t("VMessAEAD/VLESS Sharing Link Standard Proposal"),o(n)]),t(" for more details.")])])}const q=r(l,[["render",A],["__file","vless.html.vue"]]);export{q as default}; +import{_ as r,r as i,o as d,c as h,a as o,b as e,d as t,e as a}from"./app-Bw2NG-QJ.js";const l={},c=a('

                                        VLESS Protocol

                                        VLESS is a stateless lightweight transmission protocol that can be used as a bridge between Xray clients and servers.

                                        Request & Response

                                        1 byte16 bytes1 byteM bytes1 byte2 bytes1 byteS bytesX bytes
                                        Protocol VersionEquivalent UUIDAdditional Information Length MAdditional Information ProtoBufInstructionPortAddress TypeAddressRequest Data
                                        1 Byte1 ByteN BytesY Bytes
                                        Protocol Version, consistent with the requestLength of additional information NAdditional information in ProtoBufResponse data

                                        VLESS had the aforementioned structure as early as the second alpha test version (ALPHA 2), with BETA being the fifth test version.

                                        ',6),p=e("code",null,"Response authentication",-1),u=e("code",null,"Protocol version",-1),f=e("code",null,"Additional information",-1),m={href:"https://github.com/gogo/protobuf",target:"_blank",rel:"noopener noreferrer"},y=e("p",null,'I always thought that "response authentication" was not necessary, and ALPHA replaced crypto/rand with math/rand in order to improve the performance of random number generation, which is no longer needed.',-1),b=e("p",null,'The "Protocol Version" not only serves as "Response Authentication", but also gives VLESS the ability to upgrade the protocol structure seamlessly, bringing infinite possibilities. The "Protocol Version" is 0 in the test version and 1 in the official version. If there are any incompatible protocol structural changes in the future, the version should be upgraded.',-1),g=e("p",null,"The design of VLESS server is switch version, which supports all VLESS versions at the same time. If you need to upgrade the protocol version (which may not happen), it is recommended that the server support it one month in advance, and then change the client after one month. VMess requests also have protocol versions, but their authentication information is outside, and the instruction part is highly coupled and has fixed encryption, which makes the protocol version meaningless inside. The server does not judge it, and the response does not have a protocol version. Trojan's protocol structure does not have a protocol version.",-1),v=e("p",null,"The following is a UUID. I used to think that 16 bytes were a bit long and considered shortening it. However, I later saw that Trojan used 56 printable characters (56 bytes), which completely dispelled this idea. The server needs to verify the UUID every time, so performance is also very important: VLESS's Validator has undergone multiple refactoring/upgrades. Compared with VMess, it is very concise and consumes very few resources. It can support a large number of users at the same time, and its performance is also very strong. The verification speed is extremely fast (sync.Map). API dynamically adds and deletes users, making it more efficient and smooth. https://github.com/XTLS/Xray-core/issues/158",-1),w=e("p",null,'Introducing ProtoBuf is an innovation, which will be explained in detail later. The structure from "instruction" to "address" is currently identical to VMess and also supports Mux.',-1),S={href:"https://github.com/rprx/v2ray-vless/releases",target:"_blank",rel:"noopener noreferrer"},_=a('

                                        ProtoBuf

                                        It seems that only VLESS supports embedding ProtoBuf, which is a data exchange format that encodes information tightly into binary TLV (Tag Length Value) structures.

                                        The reason is that I saw an article that said that SS has some drawbacks, such as the lack of a design error reporting mechanism, and the client cannot take further action based on different errors. (But I don't agree that all errors should be reported, otherwise it can't prevent active probing. In the next beta version, the server can return a custom string of information.) So I think a scalable structure is important, and in the future, it can also carry dynamic port instructions. Not only the response, but the request also needs a similar structure. I originally planned to design TLV by myself, but then I found that ProtoBuf is the structure, ready-made, and it is completely suitable for this purpose, and the support for various languages is also good.

                                        Currently, "Additional Information" only has Scheduler and SchedulerV, which are substitutes for MessName and MessSeed. When you don't need them, the "Additional Information Length" is 0, so there is no ProtoBuf serialization/deserialization overhead. Actually, I prefer to call this process "concatenation" because that's all pb does in principle, and the related overhead is minimal. The concatenated bytes are very compact, similar to ALPHA's solution, and those who are interested can output and compare them separately.

                                        To indicate different levels of support for additional information (Addons, which can be understood as plugins and can have many plugins in the future), the next beta version will add "Addon Version" before "Addon Length". 256-1 = 255 bytes is enough and reasonable (65535 is too much and there may be malicious padding), and only one-tenth of the existing space is used. In the future, there will not be so many addons at the same time, and most of the time there will be no addons at all. If it is not enough, you can upgrade to a newer version of VLESS.

                                        To reduce logical judgment and other expenses, it is temporarily decided that Addons will not use a multi-level structure. A month ago, there was an idea of "variable protocol format". PB can shuffle the order, but it is not necessary because the design of modern encryption will not allow bystanders to see that the headers of the two transmissions are the same.

                                        Below is an introduction to the concepts of Schedulers and Encryption, both of which are optional. One is designed to address issues related to traffic timing, while the other is designed to address cryptographic issues.

                                        Flow

                                        Flow Control (Formerly Traffic Scheduler)

                                        The Flow Control command is carried by ProtoBuf and manages the data section.

                                        I previously discovered that VMess's original "metadata obfuscation" feature didn't provide any meaningful changes in TLS but only decreased performance. Consequently, VLESS has abandoned this feature. Moreover, the term "obfuscation" is often misinterpreted as camouflage, so it has been discarded.

                                        As for camouflage, if it can't be an exact match, wouldn't it be a noticeable characteristic? If it could be an exact match, why not use the intended target for camouflage directly? Initially, I used SSR but found it only provided superficial disguises, fooling operators. Thus, I stopped using it.

                                        Purpose of Flow Control

                                        Flow Control influences macro traffic temporal characteristics rather than micro characteristics addressed by encryption. Traffic temporal characteristics can be:

                                        1. Protocol-based, e.g., Socks5 handshake when using Socks5 over TLS. Different traits on TLS are considered different protocols for monitors. Infinite schedulers equate to infinite protocols (reallocating data sent each time).
                                        2. Behavior-based, e.g., loading files, their order, and size when accessing Google's homepage. Adding another encryption layer cannot effectively conceal this information.

                                        Schedulers don't require wrapping like encryption since the header data's tiny amount is negligible compared to the remaining data.

                                        BETA 2 is anticipated to introduce two basic schedulers: Zstd compression and dynamic data expansion. Advanced operations will control and distribute at a macro level, but for now, these remain under development.

                                        Encryption

                                        Unlike VMess, which is highly coupled, VLESS allows the server and client to pre-agree on an encryption method, which is only encrypted with an outer layer. This is somewhat similar to using TLS, which does not affect any of the data carried, and can be understood as replacing TLS with pre-agreed encryption at the bottom. Compared with high coupling, this approach is more reasonable and flexible: if there is a security issue with one encryption method, it can be discarded and another one can be used directly, which is very convenient. The VLESS server also allows for different encryption methods to coexist.

                                        Compared with VMess, VLESS replaces security with encryption and disableInsecureEncryption with decryption, which solves all the problems. Currently, encryption and decryption only accept "none" and cannot be left blank (even if there are connection security checks in the future), as detailed in the VLESS configuration document. Encryption does not need to be moved out one level, firstly because it cannot reuse a lot of code, and secondly because it will affect the control granularity, which will be understood by looking at future applications.

                                        Encryption supports two types of forms. One type is completely independent and requires an additional password, suitable for private use. The other type combines with the existing UUID for encryption, which is suitable for public use.

                                        (If the first type of encryption is used and the password is publicly available in some form, such as multiple people sharing it, then a man-in-the-middle attack is not far away.)

                                        A redesigned dynamic port may be released simultaneously with encryption, and the command is carried by ProtoBuf. The specific implementation and the dynamic port of VMess will also have many differences.

                                        It is very easy to cash out encrypted currency, which adds an extra layer of writer & reader. BETA 3 is expected to support SS's aes-128-gcm and chacha20-ietf-poly1305:

                                        The encryption on the client-side can be filled with "auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654". Auto will choose the most suitable one for the current machine, 0 represents the beta version, and the last one is the password. The decryption on the server-side is also filled in a similar way, and each decryption attempt will be made when the request is received.

                                        Not all combinations need to be tried one by one: VMess encryption is divided into three parts. The first part is the authentication information, which combines UUID, alterId, and time factors. The second part is the instruction part, which is encrypted using a fixed algorithm. The instruction contains the encryption algorithm used in the data part. The third part is the important data part. It can be seen that the VMess encryption and decryption method is actually many-to-one (adapted by the server), not just combining UUID. However, it is also a relatively difficult thing to encrypt only by combining UUID. It will not be available in a short time. Considering that we now have VMessAEAD available, there is no need to rush. If VLESS introduces an encryption method that combines UUID, it is equivalent to reconstructing the entire VMess.

                                        UDP issues

                                        ',27),T={href:"https://github.com/XTLS/Xray-core/discussions/252",target:"_blank",rel:"noopener noreferrer"},V=a('

                                        Client Development Guide

                                        1. The VLESS protocol itself may have incompatible upgrades, but the parameters in the client configuration file are basically only increased and not decreased. The protocol implementation of the iOS client needs to keep up with the upgrade.
                                        2. Visual standard: Please use VLESS as the UI identifier uniformly, instead of VLess / Vless / vless. The configuration file is not affected, and the code should follow naturally.
                                        3. Encryption should be made into an input box instead of a selection box. The default value of the new configuration should be none, and if the user leaves it blank, it should be filled in with none.
                                        ',3),I={href:"https://github.com/DuckSoft",target:"_blank",rel:"noopener noreferrer"},L={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"};function A(x,E){const s=i("I18nTip"),n=i("ExternalLinkIcon");return d(),h("div",null,[o(s),c,e("p",null,[t('"'),p,t('" has been replaced with "'),u,t('" and moved to the front, allowing VLESS to upgrade and eliminate the overhead of generating pseudo-random numbers. The obfuscation-related structure has been replaced with "'),f,t('" (ProtoBuf) and moved forward, giving the protocol itself scalability, with minimal overhead ('),e("a",m,[t("gogo/protobuf"),o(n)]),t("). If there is no additional information, there is no relevant overhead.")]),y,b,g,v,w,e("p",null,[t("Overall, ALPHA 2 to BETA mainly includes: structural evolution, cleaning and integration, performance improvement, and more completeness. All of these are incremental improvements, please refer to "),e("a",S,[t("VLESS Changes"),o(n)]),t(" for details.")]),_,e("p",null,[e("a",T,[t("XUDP: VLESS & VMess & Mux UDP FullCone NAT"),o(n)])]),V,e("p",null,[t("Thank you to "),e("a",I,[t("@DuckSoft"),o(n)]),t(" for the proposal!")]),e("p",null,[t("Please see "),e("a",L,[t("VMessAEAD/VLESS Sharing Link Standard Proposal"),o(n)]),t(" for more details.")])])}const q=r(l,[["render",A],["__file","vless.html.vue"]]);export{q as default}; diff --git a/assets/vless.html-BZ48J9S_.js b/assets/vless.html-C6f9K51N.js similarity index 99% rename from assets/vless.html-BZ48J9S_.js rename to assets/vless.html-C6f9K51N.js index b647184024..0e5dc8cd2c 100644 --- a/assets/vless.html-BZ48J9S_.js +++ b/assets/vless.html-C6f9K51N.js @@ -1,4 +1,4 @@ -import{_ as l,r as t,o as r,c as u,a as s,b as n,d as e,w as a,e as i}from"./app-5SoadDYS.js";const d={},v=n("h1",{id:"vless",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless"},[n("span",null,"VLESS")])],-1),h=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"Danger"),n("p",null,"Currently, VLESS does not have built-in encryption, please use it on a reliable channel, such as TLS.")],-1),b=n("p",null,"VLESS is a stateless lightweight transport protocol, which is divided into inbound and outbound parts, and can be used as a bridge between Xray clients and servers.",-1),m=i(`

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as l,r as t,o as r,c as u,a as s,b as n,d as e,w as a,e as i}from"./app-Bw2NG-QJ.js";const d={},v=n("h1",{id:"vless",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless"},[n("span",null,"VLESS")])],-1),h=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"Danger"),n("p",null,"Currently, VLESS does not have built-in encryption, please use it on a reliable channel, such as TLS.")],-1),b=n("p",null,"VLESS is a stateless lightweight transport protocol, which is divided into inbound and outbound parts, and can be used as a bridge between Xray clients and servers.",-1),m=i(`

                                        OutboundConfigurationObject

                                        {
                                           "vnext": [
                                             {
                                               "address": "example.com",
                                        diff --git a/assets/vless.html-daOoULRK.js b/assets/vless.html-CASW7iOO.js
                                        similarity index 99%
                                        rename from assets/vless.html-daOoULRK.js
                                        rename to assets/vless.html-CASW7iOO.js
                                        index cb051fb05e..9d7b7dce13 100644
                                        --- a/assets/vless.html-daOoULRK.js
                                        +++ b/assets/vless.html-CASW7iOO.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as u,c as r,a as e,b as n,d as s,w as a,e as l}from"./app-5SoadDYS.js";const d={},k=n("h1",{id:"vless-xtls-vision-seed",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless-xtls-vision-seed"},[n("span",null,"VLESS(XTLS Vision Seed)")])],-1),b=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"警告"),n("p",null,"目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。")],-1),v=n("p",null,"VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。",-1),q=l(`

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as u,c as r,a as e,b as n,d as s,w as a,e as l}from"./app-Bw2NG-QJ.js";const d={},k=n("h1",{id:"vless-xtls-vision-seed",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless-xtls-vision-seed"},[n("span",null,"VLESS(XTLS Vision Seed)")])],-1),b=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"警告"),n("p",null,"目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。")],-1),v=n("p",null,"VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。",-1),q=l(`

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "id": "5783a3e7-e373-51cd-8642-c83782b807c5",
                                        diff --git a/assets/vless.html-Be1YpEZ1.js b/assets/vless.html-CxxO1Anm.js
                                        similarity index 99%
                                        rename from assets/vless.html-Be1YpEZ1.js
                                        rename to assets/vless.html-CxxO1Anm.js
                                        index f8f42b8030..f7a49cf313 100644
                                        --- a/assets/vless.html-Be1YpEZ1.js
                                        +++ b/assets/vless.html-CxxO1Anm.js
                                        @@ -1 +1 @@
                                        -import{_ as h,r as n,o as d,c,a as s,b as e,d as t,e as r}from"./app-5SoadDYS.js";const l={},p=r('

                                        VLESS 协议

                                        VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        Request & Response

                                        1 字节16 字节1 字节M 字节1 字节2 字节1 字节S 字节X 字节
                                        协议版本等价 UUID附加信息长度 M附加信息 ProtoBuf指令端口地址类型地址请求数据
                                        1 字节1 字节N 字节Y 字节
                                        协议版本,与请求的一致附加信息长度 N附加信息 ProtoBuf响应数据

                                        VLESS 早在第二个测试版 ALPHA 2 时就已经是上述结构了(BETA 是第五个测试版):

                                        ',6),i={href:"https://github.com/gogo/protobuf",target:"_blank",rel:"noopener noreferrer"},u=e("p",null,"我一直觉得“响应认证”不是必要的,ALPHA 时为了提升生成随机数的性能,还用 math/rand 替换 crypto/rand,而现在都不需要了。",-1),S=e("p",null,"“协议版本”不仅能起到“响应认证”的作用,还赋予了 VLESS 无痛升级协议结构的能力,带来无限的可能性。 “协议版本”在测试版本中均为 0,正式版本中为 1,以后若有不兼容的协议结构变更则应升级版本。",-1),_=e("p",null,"VLESS 服务端的设计是 switch version,即同时支持所有 VLESS 版本。若需要升级协议版本(可能到不了这一步),推荐的做法是服务端提前一个月支持,一个月后再改客户端。VMess 请求也有协议版本,但它的认证信息在外面,指令部分则高度耦合且有固定加密,导致里面的协议版本毫无意义,服务端也没有进行判断,响应则没有协议版本。Trojan 的协议结构中没有协议版本。",-1),f=e("p",null,"接下来是 UUID,我本来觉得 16 字节有点长,曾经考虑过缩短它,但后来看到 Trojan 用了 56 个可打印字符(56 字节),就彻底打消了这个念头。服务端每次都要验证 UUID,所以性能也很重要:VLESS 的 Validator 经历了多次重构/升级,相较于 VMess,它十分简洁且耗资源很少,可以同时支持非常多的用户,性能也十分强悍,验证速度极快(sync.Map)。API 动态增删用户则更高效顺滑。 https://github.com/XTLS/Xray-core/issues/158",-1),V=e("p",null,"引入 ProtoBuf 是一个创举,等下会详细讲解。“指令”到“地址”的结构目前与 VMess 完全相同,同样支持 Mux。",-1),b={href:"https://github.com/rprx/v2ray-vless/releases",target:"_blank",rel:"noopener noreferrer"},L=r('

                                        ProtoBuf

                                        似乎只有 VLESS 可选内嵌 ProtoBuf,它是一种数据交换格式,信息被紧密编码成二进制,TLV 结构(Tag Length Value)。

                                        起因是我看到一篇文章称 SS 有一些缺点,如没有设计错误回报机制,客户端没办法根据不同的错误采取进一步的动作。 (但我并不认同所有错误都要回报,不然防不了主动探测。下一个测试版中,服务器可以返回一串自定义信息。) 于是想到一个可扩展的结构是很重要的,未来它也可以承载如动态端口指令。不止响应,请求也需要类似的结构。 本来打算自己设计 TLV,接着发觉 ProtoBuf 就是此结构、现成的轮子,完全适合用来做这件事,各语言支持等也不错。

                                        目前“附加信息”只有 Scheduler 和 SchedulerV,它们是 MessName 和 MessSeed 的替代者,当你不需要它们时,“附加信息长度”为 0,也就不会有 ProtoBuf 序列化/反序列化的开销。其实我更愿意称这个过程为“拼接”,因为 pb 实际原理上也只是这么做而已,相关开销极小。拼接后的 bytes 十分紧凑,和 ALPHA 的方案相差无几,有兴趣的可以分别输出并对比。

                                        为了指示对附加信息(Addons,也可以理解成插件,以后可以有很多个插件)的不同支持程度,下个测试版会在“附加信息长度”前新增“附加信息版本”。256 - 1 = 255 字节是够用且合理的(65535 就太多了,还可能有人恶意填充),现有的只用了十分之一,以后也不会同时有那么多附加信息,且大多数情况下是完全没有附加信息的。真不够用的话,可以升级 VLESS 版本。

                                        为了减少逻辑判断等开销,暂定 Addons 不使用多级结构。一个月前出现过“可变协议格式”的想法,pb 是可以做到打乱顺序,但没必要,因为现代加密的设计不会让旁观者看出两次传输的头部相同。

                                        下面介绍 Schedulers 和 Encryption 的构想,它们都是可选的,一个应对流量时序特征问题,一个应对密码学上的问题。

                                        Schedulers Flow

                                        中文名暂称:流量调度器(2020-09-03 更新:中文名确定为“流控”),指令由 ProtoBuf 承载,控制的是数据部分。

                                        我之前发现,VMess 原有的 shake “元数据混淆”在 TLS 上完全不会带来有意义的改变,只会降低性能,所以 VLESS 弃用了它。并且,“混淆”这个表述容易被误解成伪装,也弃用了。顺便一提,我一直是不看好伪装的:做不到完全一样,那不就是强特征吗?做得到完全一样,那为什么不直接用伪装目标?我一开始用的是 SSR,后来发现它只是表面伪装骗运营商,就再也没用过了。

                                        那么,“流量调度器”要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)。流量时序特征也可以是行为带来的,比如访问 Google 首页时加载了多少文件、顺序、每个文件的大小,多套一层加密并不能有效掩盖这些信息。

                                        Schedulers 没必要像下面的 Encryption 一样整个套在外面,因为头部的一丁点数据相对于后面的数据量来说太微不足道了。

                                        BETA 2 预计推出两个初级的 Scheduler:Zstd 压缩、数据量动态扩充。进阶操作才是从宏观层面来控制、分配,暂时咕咕。

                                        Encryption

                                        与 VMess 的高度耦合不同,VLESS 的服务端、客户端不久后可以提前约定好加密方式,仅在外面套一层加密。这有点类似于使用 TLS,不影响承载的任何数据,也可以理解成底层就是从 TLS 换成预设约定加密。相对于高度耦合,这种方式更合理且灵活:一种加密方式出了安全性问题,直接扔掉并换用其它的就行了,十分方便。VLESS 服务端还会允许不同的加密方式共存。

                                        ',15),E={href:"https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"加密支持两类形式,一类是加密完全独立,需要额外密码,适合私用,另一类是结合已有的 UUID 来加密,适合公用。 (若用第一类加密形式,且密码是以某种形式公开的,比如多人共用,那么中间人攻击就不远了) 重新设计的动态端口可能会随加密同时推出,指令由 ProtoBuf 承载,具体实现和 VMess 的动态端口也会有很多不同。",-1),y=e("p",null,"套现成加密是件很简单的事情,也就多一层 writer & reader。BETA 3 预计支持 SS 的 aes-128-gcm 和 chacha20-ietf-poly1305: 客户端的 encryption 可以填 “auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654”,auto 会选择最适合当前机器的,0 代表测试版,最后的是密码。服务端的 decryption 也是类似填法,收到请求时会逐一尝试解密。",-1),m=e("p",null,"并不是所有组合都需逐一尝试:VMess 的加密分为三段,第一段是认证信息,结合了 UUID、alterId、时间因素,第二段是指令部分,以固定算法加密,指令中含有数据部分使用的加密算法,第三段才是重要的数据部分。可以看出,VMess 的加解密方式实际上是多对一(服务端适配),而不仅是结合 UUID。但仅是结合 UUID 来加密也是件相对麻烦的事情,短时间内不会出,鉴于我们现在有 VMessAEAD 可用,也并不着急。若 VLESS 推出了结合 UUID 的加密方式,相当于重构了整个 VMess。",-1),T=e("h2",{id:"udp-issues",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#udp-issues"},[e("span",null,"UDP issues")])],-1),x={href:"https://github.com/XTLS/Xray-core/discussions/252",target:"_blank",rel:"noopener noreferrer"},A=r('

                                        客户端开发指引

                                        1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。iOS 客户端的协议实现则需紧跟升级。
                                        2. 视觉标准:UI 标识请统一用 VLESS,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。
                                        3. encryption 应做成输入框而不是选择框,新配置的默认值应为 none,若用户置空则应代填 none

                                        VLESS 分享链接标准

                                        ',3),M=e("img",{src:"https://avatars2.githubusercontent.com/u/7822648?s=32",width:"32px",height:"32px",alt:"a"},null,-1),U={href:"https://github.com/DuckSoft",target:"_blank",rel:"noopener noreferrer"},P={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"};function v(B,k){const a=n("I18nTip"),o=n("ExternalLinkIcon");return d(),c("div",null,[s(a),p,e("blockquote",null,[e("p",null,[t("“响应认证”被替换为“协议版本”并移至最前,使 VLESS 可以升级换代,同时消除了生成伪随机数的开销。混淆相关结构被替换为附加信息(ProtoBuf)并前移,赋予协议本身可扩展性,相关开销也极小("),e("a",i,[t("gogo/protobuf"),s(o)]),t("),若无附加信息则无相关开销。")])]),u,S,_,f,V,e("p",null,[t("总体上,ALPHA 2 到 BETA 主要是:结构进化、清理整合、性能提升、更加完善。这些都是一点一滴的,详见 "),e("a",b,[t("VLESS Changes"),s(o)]),t("。")]),L,e("p",null,[t('对比 VMess,VLESS 相当于把 security 换成 encryption,把 disableInsecureEncryption 换成 decryption,就解决了所有问题。目前 encryption 和 decryption 只接受 "none" 且不能留空(即使以后有连接安全性检查),详见 '),e("a",E,[t("VLESS 配置文档"),s(o)]),t("。encryption 并不需要往外移一级,一是因为无法复用很多代码,二是因为会影响控制粒度,看未来的应用就明白了。")]),g,y,m,T,e("p",null,[e("a",x,[t("XUDP:VLESS & VMess & Mux UDP FullCone NAT"),s(o)])]),A,e("p",null,[t("感谢 "),M,t(),e("a",U,[t("@DuckSoft"),s(o)]),t(" 的提案!")]),e("p",null,[t("详情请见 "),e("a",P,[t("VMessAEAD / VLESS 分享链接标准提案"),s(o)])])])}const D=h(l,[["render",v],["__file","vless.html.vue"]]);export{D as default}; +import{_ as h,r as n,o as d,c,a as s,b as e,d as t,e as r}from"./app-Bw2NG-QJ.js";const l={},p=r('

                                        VLESS 协议

                                        VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        Request & Response

                                        1 字节16 字节1 字节M 字节1 字节2 字节1 字节S 字节X 字节
                                        协议版本等价 UUID附加信息长度 M附加信息 ProtoBuf指令端口地址类型地址请求数据
                                        1 字节1 字节N 字节Y 字节
                                        协议版本,与请求的一致附加信息长度 N附加信息 ProtoBuf响应数据

                                        VLESS 早在第二个测试版 ALPHA 2 时就已经是上述结构了(BETA 是第五个测试版):

                                        ',6),i={href:"https://github.com/gogo/protobuf",target:"_blank",rel:"noopener noreferrer"},u=e("p",null,"我一直觉得“响应认证”不是必要的,ALPHA 时为了提升生成随机数的性能,还用 math/rand 替换 crypto/rand,而现在都不需要了。",-1),S=e("p",null,"“协议版本”不仅能起到“响应认证”的作用,还赋予了 VLESS 无痛升级协议结构的能力,带来无限的可能性。 “协议版本”在测试版本中均为 0,正式版本中为 1,以后若有不兼容的协议结构变更则应升级版本。",-1),_=e("p",null,"VLESS 服务端的设计是 switch version,即同时支持所有 VLESS 版本。若需要升级协议版本(可能到不了这一步),推荐的做法是服务端提前一个月支持,一个月后再改客户端。VMess 请求也有协议版本,但它的认证信息在外面,指令部分则高度耦合且有固定加密,导致里面的协议版本毫无意义,服务端也没有进行判断,响应则没有协议版本。Trojan 的协议结构中没有协议版本。",-1),f=e("p",null,"接下来是 UUID,我本来觉得 16 字节有点长,曾经考虑过缩短它,但后来看到 Trojan 用了 56 个可打印字符(56 字节),就彻底打消了这个念头。服务端每次都要验证 UUID,所以性能也很重要:VLESS 的 Validator 经历了多次重构/升级,相较于 VMess,它十分简洁且耗资源很少,可以同时支持非常多的用户,性能也十分强悍,验证速度极快(sync.Map)。API 动态增删用户则更高效顺滑。 https://github.com/XTLS/Xray-core/issues/158",-1),V=e("p",null,"引入 ProtoBuf 是一个创举,等下会详细讲解。“指令”到“地址”的结构目前与 VMess 完全相同,同样支持 Mux。",-1),b={href:"https://github.com/rprx/v2ray-vless/releases",target:"_blank",rel:"noopener noreferrer"},L=r('

                                        ProtoBuf

                                        似乎只有 VLESS 可选内嵌 ProtoBuf,它是一种数据交换格式,信息被紧密编码成二进制,TLV 结构(Tag Length Value)。

                                        起因是我看到一篇文章称 SS 有一些缺点,如没有设计错误回报机制,客户端没办法根据不同的错误采取进一步的动作。 (但我并不认同所有错误都要回报,不然防不了主动探测。下一个测试版中,服务器可以返回一串自定义信息。) 于是想到一个可扩展的结构是很重要的,未来它也可以承载如动态端口指令。不止响应,请求也需要类似的结构。 本来打算自己设计 TLV,接着发觉 ProtoBuf 就是此结构、现成的轮子,完全适合用来做这件事,各语言支持等也不错。

                                        目前“附加信息”只有 Scheduler 和 SchedulerV,它们是 MessName 和 MessSeed 的替代者,当你不需要它们时,“附加信息长度”为 0,也就不会有 ProtoBuf 序列化/反序列化的开销。其实我更愿意称这个过程为“拼接”,因为 pb 实际原理上也只是这么做而已,相关开销极小。拼接后的 bytes 十分紧凑,和 ALPHA 的方案相差无几,有兴趣的可以分别输出并对比。

                                        为了指示对附加信息(Addons,也可以理解成插件,以后可以有很多个插件)的不同支持程度,下个测试版会在“附加信息长度”前新增“附加信息版本”。256 - 1 = 255 字节是够用且合理的(65535 就太多了,还可能有人恶意填充),现有的只用了十分之一,以后也不会同时有那么多附加信息,且大多数情况下是完全没有附加信息的。真不够用的话,可以升级 VLESS 版本。

                                        为了减少逻辑判断等开销,暂定 Addons 不使用多级结构。一个月前出现过“可变协议格式”的想法,pb 是可以做到打乱顺序,但没必要,因为现代加密的设计不会让旁观者看出两次传输的头部相同。

                                        下面介绍 Schedulers 和 Encryption 的构想,它们都是可选的,一个应对流量时序特征问题,一个应对密码学上的问题。

                                        Schedulers Flow

                                        中文名暂称:流量调度器(2020-09-03 更新:中文名确定为“流控”),指令由 ProtoBuf 承载,控制的是数据部分。

                                        我之前发现,VMess 原有的 shake “元数据混淆”在 TLS 上完全不会带来有意义的改变,只会降低性能,所以 VLESS 弃用了它。并且,“混淆”这个表述容易被误解成伪装,也弃用了。顺便一提,我一直是不看好伪装的:做不到完全一样,那不就是强特征吗?做得到完全一样,那为什么不直接用伪装目标?我一开始用的是 SSR,后来发现它只是表面伪装骗运营商,就再也没用过了。

                                        那么,“流量调度器”要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)。流量时序特征也可以是行为带来的,比如访问 Google 首页时加载了多少文件、顺序、每个文件的大小,多套一层加密并不能有效掩盖这些信息。

                                        Schedulers 没必要像下面的 Encryption 一样整个套在外面,因为头部的一丁点数据相对于后面的数据量来说太微不足道了。

                                        BETA 2 预计推出两个初级的 Scheduler:Zstd 压缩、数据量动态扩充。进阶操作才是从宏观层面来控制、分配,暂时咕咕。

                                        Encryption

                                        与 VMess 的高度耦合不同,VLESS 的服务端、客户端不久后可以提前约定好加密方式,仅在外面套一层加密。这有点类似于使用 TLS,不影响承载的任何数据,也可以理解成底层就是从 TLS 换成预设约定加密。相对于高度耦合,这种方式更合理且灵活:一种加密方式出了安全性问题,直接扔掉并换用其它的就行了,十分方便。VLESS 服务端还会允许不同的加密方式共存。

                                        ',15),E={href:"https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"加密支持两类形式,一类是加密完全独立,需要额外密码,适合私用,另一类是结合已有的 UUID 来加密,适合公用。 (若用第一类加密形式,且密码是以某种形式公开的,比如多人共用,那么中间人攻击就不远了) 重新设计的动态端口可能会随加密同时推出,指令由 ProtoBuf 承载,具体实现和 VMess 的动态端口也会有很多不同。",-1),y=e("p",null,"套现成加密是件很简单的事情,也就多一层 writer & reader。BETA 3 预计支持 SS 的 aes-128-gcm 和 chacha20-ietf-poly1305: 客户端的 encryption 可以填 “auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654”,auto 会选择最适合当前机器的,0 代表测试版,最后的是密码。服务端的 decryption 也是类似填法,收到请求时会逐一尝试解密。",-1),m=e("p",null,"并不是所有组合都需逐一尝试:VMess 的加密分为三段,第一段是认证信息,结合了 UUID、alterId、时间因素,第二段是指令部分,以固定算法加密,指令中含有数据部分使用的加密算法,第三段才是重要的数据部分。可以看出,VMess 的加解密方式实际上是多对一(服务端适配),而不仅是结合 UUID。但仅是结合 UUID 来加密也是件相对麻烦的事情,短时间内不会出,鉴于我们现在有 VMessAEAD 可用,也并不着急。若 VLESS 推出了结合 UUID 的加密方式,相当于重构了整个 VMess。",-1),T=e("h2",{id:"udp-issues",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#udp-issues"},[e("span",null,"UDP issues")])],-1),x={href:"https://github.com/XTLS/Xray-core/discussions/252",target:"_blank",rel:"noopener noreferrer"},A=r('

                                        客户端开发指引

                                        1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。iOS 客户端的协议实现则需紧跟升级。
                                        2. 视觉标准:UI 标识请统一用 VLESS,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。
                                        3. encryption 应做成输入框而不是选择框,新配置的默认值应为 none,若用户置空则应代填 none

                                        VLESS 分享链接标准

                                        ',3),M=e("img",{src:"https://avatars2.githubusercontent.com/u/7822648?s=32",width:"32px",height:"32px",alt:"a"},null,-1),U={href:"https://github.com/DuckSoft",target:"_blank",rel:"noopener noreferrer"},P={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"};function v(B,k){const a=n("I18nTip"),o=n("ExternalLinkIcon");return d(),c("div",null,[s(a),p,e("blockquote",null,[e("p",null,[t("“响应认证”被替换为“协议版本”并移至最前,使 VLESS 可以升级换代,同时消除了生成伪随机数的开销。混淆相关结构被替换为附加信息(ProtoBuf)并前移,赋予协议本身可扩展性,相关开销也极小("),e("a",i,[t("gogo/protobuf"),s(o)]),t("),若无附加信息则无相关开销。")])]),u,S,_,f,V,e("p",null,[t("总体上,ALPHA 2 到 BETA 主要是:结构进化、清理整合、性能提升、更加完善。这些都是一点一滴的,详见 "),e("a",b,[t("VLESS Changes"),s(o)]),t("。")]),L,e("p",null,[t('对比 VMess,VLESS 相当于把 security 换成 encryption,把 disableInsecureEncryption 换成 decryption,就解决了所有问题。目前 encryption 和 decryption 只接受 "none" 且不能留空(即使以后有连接安全性检查),详见 '),e("a",E,[t("VLESS 配置文档"),s(o)]),t("。encryption 并不需要往外移一级,一是因为无法复用很多代码,二是因为会影响控制粒度,看未来的应用就明白了。")]),g,y,m,T,e("p",null,[e("a",x,[t("XUDP:VLESS & VMess & Mux UDP FullCone NAT"),s(o)])]),A,e("p",null,[t("感谢 "),M,t(),e("a",U,[t("@DuckSoft"),s(o)]),t(" 的提案!")]),e("p",null,[t("详情请见 "),e("a",P,[t("VMessAEAD / VLESS 分享链接标准提案"),s(o)])])])}const D=h(l,[["render",v],["__file","vless.html.vue"]]);export{D as default}; diff --git a/assets/vless.html-CccEA1M4.js b/assets/vless.html-D2jxsPHC.js similarity index 99% rename from assets/vless.html-CccEA1M4.js rename to assets/vless.html-D2jxsPHC.js index f8f42b8030..f7a49cf313 100644 --- a/assets/vless.html-CccEA1M4.js +++ b/assets/vless.html-D2jxsPHC.js @@ -1 +1 @@ -import{_ as h,r as n,o as d,c,a as s,b as e,d as t,e as r}from"./app-5SoadDYS.js";const l={},p=r('

                                        VLESS 协议

                                        VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        Request & Response

                                        1 字节16 字节1 字节M 字节1 字节2 字节1 字节S 字节X 字节
                                        协议版本等价 UUID附加信息长度 M附加信息 ProtoBuf指令端口地址类型地址请求数据
                                        1 字节1 字节N 字节Y 字节
                                        协议版本,与请求的一致附加信息长度 N附加信息 ProtoBuf响应数据

                                        VLESS 早在第二个测试版 ALPHA 2 时就已经是上述结构了(BETA 是第五个测试版):

                                        ',6),i={href:"https://github.com/gogo/protobuf",target:"_blank",rel:"noopener noreferrer"},u=e("p",null,"我一直觉得“响应认证”不是必要的,ALPHA 时为了提升生成随机数的性能,还用 math/rand 替换 crypto/rand,而现在都不需要了。",-1),S=e("p",null,"“协议版本”不仅能起到“响应认证”的作用,还赋予了 VLESS 无痛升级协议结构的能力,带来无限的可能性。 “协议版本”在测试版本中均为 0,正式版本中为 1,以后若有不兼容的协议结构变更则应升级版本。",-1),_=e("p",null,"VLESS 服务端的设计是 switch version,即同时支持所有 VLESS 版本。若需要升级协议版本(可能到不了这一步),推荐的做法是服务端提前一个月支持,一个月后再改客户端。VMess 请求也有协议版本,但它的认证信息在外面,指令部分则高度耦合且有固定加密,导致里面的协议版本毫无意义,服务端也没有进行判断,响应则没有协议版本。Trojan 的协议结构中没有协议版本。",-1),f=e("p",null,"接下来是 UUID,我本来觉得 16 字节有点长,曾经考虑过缩短它,但后来看到 Trojan 用了 56 个可打印字符(56 字节),就彻底打消了这个念头。服务端每次都要验证 UUID,所以性能也很重要:VLESS 的 Validator 经历了多次重构/升级,相较于 VMess,它十分简洁且耗资源很少,可以同时支持非常多的用户,性能也十分强悍,验证速度极快(sync.Map)。API 动态增删用户则更高效顺滑。 https://github.com/XTLS/Xray-core/issues/158",-1),V=e("p",null,"引入 ProtoBuf 是一个创举,等下会详细讲解。“指令”到“地址”的结构目前与 VMess 完全相同,同样支持 Mux。",-1),b={href:"https://github.com/rprx/v2ray-vless/releases",target:"_blank",rel:"noopener noreferrer"},L=r('

                                        ProtoBuf

                                        似乎只有 VLESS 可选内嵌 ProtoBuf,它是一种数据交换格式,信息被紧密编码成二进制,TLV 结构(Tag Length Value)。

                                        起因是我看到一篇文章称 SS 有一些缺点,如没有设计错误回报机制,客户端没办法根据不同的错误采取进一步的动作。 (但我并不认同所有错误都要回报,不然防不了主动探测。下一个测试版中,服务器可以返回一串自定义信息。) 于是想到一个可扩展的结构是很重要的,未来它也可以承载如动态端口指令。不止响应,请求也需要类似的结构。 本来打算自己设计 TLV,接着发觉 ProtoBuf 就是此结构、现成的轮子,完全适合用来做这件事,各语言支持等也不错。

                                        目前“附加信息”只有 Scheduler 和 SchedulerV,它们是 MessName 和 MessSeed 的替代者,当你不需要它们时,“附加信息长度”为 0,也就不会有 ProtoBuf 序列化/反序列化的开销。其实我更愿意称这个过程为“拼接”,因为 pb 实际原理上也只是这么做而已,相关开销极小。拼接后的 bytes 十分紧凑,和 ALPHA 的方案相差无几,有兴趣的可以分别输出并对比。

                                        为了指示对附加信息(Addons,也可以理解成插件,以后可以有很多个插件)的不同支持程度,下个测试版会在“附加信息长度”前新增“附加信息版本”。256 - 1 = 255 字节是够用且合理的(65535 就太多了,还可能有人恶意填充),现有的只用了十分之一,以后也不会同时有那么多附加信息,且大多数情况下是完全没有附加信息的。真不够用的话,可以升级 VLESS 版本。

                                        为了减少逻辑判断等开销,暂定 Addons 不使用多级结构。一个月前出现过“可变协议格式”的想法,pb 是可以做到打乱顺序,但没必要,因为现代加密的设计不会让旁观者看出两次传输的头部相同。

                                        下面介绍 Schedulers 和 Encryption 的构想,它们都是可选的,一个应对流量时序特征问题,一个应对密码学上的问题。

                                        Schedulers Flow

                                        中文名暂称:流量调度器(2020-09-03 更新:中文名确定为“流控”),指令由 ProtoBuf 承载,控制的是数据部分。

                                        我之前发现,VMess 原有的 shake “元数据混淆”在 TLS 上完全不会带来有意义的改变,只会降低性能,所以 VLESS 弃用了它。并且,“混淆”这个表述容易被误解成伪装,也弃用了。顺便一提,我一直是不看好伪装的:做不到完全一样,那不就是强特征吗?做得到完全一样,那为什么不直接用伪装目标?我一开始用的是 SSR,后来发现它只是表面伪装骗运营商,就再也没用过了。

                                        那么,“流量调度器”要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)。流量时序特征也可以是行为带来的,比如访问 Google 首页时加载了多少文件、顺序、每个文件的大小,多套一层加密并不能有效掩盖这些信息。

                                        Schedulers 没必要像下面的 Encryption 一样整个套在外面,因为头部的一丁点数据相对于后面的数据量来说太微不足道了。

                                        BETA 2 预计推出两个初级的 Scheduler:Zstd 压缩、数据量动态扩充。进阶操作才是从宏观层面来控制、分配,暂时咕咕。

                                        Encryption

                                        与 VMess 的高度耦合不同,VLESS 的服务端、客户端不久后可以提前约定好加密方式,仅在外面套一层加密。这有点类似于使用 TLS,不影响承载的任何数据,也可以理解成底层就是从 TLS 换成预设约定加密。相对于高度耦合,这种方式更合理且灵活:一种加密方式出了安全性问题,直接扔掉并换用其它的就行了,十分方便。VLESS 服务端还会允许不同的加密方式共存。

                                        ',15),E={href:"https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"加密支持两类形式,一类是加密完全独立,需要额外密码,适合私用,另一类是结合已有的 UUID 来加密,适合公用。 (若用第一类加密形式,且密码是以某种形式公开的,比如多人共用,那么中间人攻击就不远了) 重新设计的动态端口可能会随加密同时推出,指令由 ProtoBuf 承载,具体实现和 VMess 的动态端口也会有很多不同。",-1),y=e("p",null,"套现成加密是件很简单的事情,也就多一层 writer & reader。BETA 3 预计支持 SS 的 aes-128-gcm 和 chacha20-ietf-poly1305: 客户端的 encryption 可以填 “auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654”,auto 会选择最适合当前机器的,0 代表测试版,最后的是密码。服务端的 decryption 也是类似填法,收到请求时会逐一尝试解密。",-1),m=e("p",null,"并不是所有组合都需逐一尝试:VMess 的加密分为三段,第一段是认证信息,结合了 UUID、alterId、时间因素,第二段是指令部分,以固定算法加密,指令中含有数据部分使用的加密算法,第三段才是重要的数据部分。可以看出,VMess 的加解密方式实际上是多对一(服务端适配),而不仅是结合 UUID。但仅是结合 UUID 来加密也是件相对麻烦的事情,短时间内不会出,鉴于我们现在有 VMessAEAD 可用,也并不着急。若 VLESS 推出了结合 UUID 的加密方式,相当于重构了整个 VMess。",-1),T=e("h2",{id:"udp-issues",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#udp-issues"},[e("span",null,"UDP issues")])],-1),x={href:"https://github.com/XTLS/Xray-core/discussions/252",target:"_blank",rel:"noopener noreferrer"},A=r('

                                        客户端开发指引

                                        1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。iOS 客户端的协议实现则需紧跟升级。
                                        2. 视觉标准:UI 标识请统一用 VLESS,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。
                                        3. encryption 应做成输入框而不是选择框,新配置的默认值应为 none,若用户置空则应代填 none

                                        VLESS 分享链接标准

                                        ',3),M=e("img",{src:"https://avatars2.githubusercontent.com/u/7822648?s=32",width:"32px",height:"32px",alt:"a"},null,-1),U={href:"https://github.com/DuckSoft",target:"_blank",rel:"noopener noreferrer"},P={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"};function v(B,k){const a=n("I18nTip"),o=n("ExternalLinkIcon");return d(),c("div",null,[s(a),p,e("blockquote",null,[e("p",null,[t("“响应认证”被替换为“协议版本”并移至最前,使 VLESS 可以升级换代,同时消除了生成伪随机数的开销。混淆相关结构被替换为附加信息(ProtoBuf)并前移,赋予协议本身可扩展性,相关开销也极小("),e("a",i,[t("gogo/protobuf"),s(o)]),t("),若无附加信息则无相关开销。")])]),u,S,_,f,V,e("p",null,[t("总体上,ALPHA 2 到 BETA 主要是:结构进化、清理整合、性能提升、更加完善。这些都是一点一滴的,详见 "),e("a",b,[t("VLESS Changes"),s(o)]),t("。")]),L,e("p",null,[t('对比 VMess,VLESS 相当于把 security 换成 encryption,把 disableInsecureEncryption 换成 decryption,就解决了所有问题。目前 encryption 和 decryption 只接受 "none" 且不能留空(即使以后有连接安全性检查),详见 '),e("a",E,[t("VLESS 配置文档"),s(o)]),t("。encryption 并不需要往外移一级,一是因为无法复用很多代码,二是因为会影响控制粒度,看未来的应用就明白了。")]),g,y,m,T,e("p",null,[e("a",x,[t("XUDP:VLESS & VMess & Mux UDP FullCone NAT"),s(o)])]),A,e("p",null,[t("感谢 "),M,t(),e("a",U,[t("@DuckSoft"),s(o)]),t(" 的提案!")]),e("p",null,[t("详情请见 "),e("a",P,[t("VMessAEAD / VLESS 分享链接标准提案"),s(o)])])])}const D=h(l,[["render",v],["__file","vless.html.vue"]]);export{D as default}; +import{_ as h,r as n,o as d,c,a as s,b as e,d as t,e as r}from"./app-Bw2NG-QJ.js";const l={},p=r('

                                        VLESS 协议

                                        VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        Request & Response

                                        1 字节16 字节1 字节M 字节1 字节2 字节1 字节S 字节X 字节
                                        协议版本等价 UUID附加信息长度 M附加信息 ProtoBuf指令端口地址类型地址请求数据
                                        1 字节1 字节N 字节Y 字节
                                        协议版本,与请求的一致附加信息长度 N附加信息 ProtoBuf响应数据

                                        VLESS 早在第二个测试版 ALPHA 2 时就已经是上述结构了(BETA 是第五个测试版):

                                        ',6),i={href:"https://github.com/gogo/protobuf",target:"_blank",rel:"noopener noreferrer"},u=e("p",null,"我一直觉得“响应认证”不是必要的,ALPHA 时为了提升生成随机数的性能,还用 math/rand 替换 crypto/rand,而现在都不需要了。",-1),S=e("p",null,"“协议版本”不仅能起到“响应认证”的作用,还赋予了 VLESS 无痛升级协议结构的能力,带来无限的可能性。 “协议版本”在测试版本中均为 0,正式版本中为 1,以后若有不兼容的协议结构变更则应升级版本。",-1),_=e("p",null,"VLESS 服务端的设计是 switch version,即同时支持所有 VLESS 版本。若需要升级协议版本(可能到不了这一步),推荐的做法是服务端提前一个月支持,一个月后再改客户端。VMess 请求也有协议版本,但它的认证信息在外面,指令部分则高度耦合且有固定加密,导致里面的协议版本毫无意义,服务端也没有进行判断,响应则没有协议版本。Trojan 的协议结构中没有协议版本。",-1),f=e("p",null,"接下来是 UUID,我本来觉得 16 字节有点长,曾经考虑过缩短它,但后来看到 Trojan 用了 56 个可打印字符(56 字节),就彻底打消了这个念头。服务端每次都要验证 UUID,所以性能也很重要:VLESS 的 Validator 经历了多次重构/升级,相较于 VMess,它十分简洁且耗资源很少,可以同时支持非常多的用户,性能也十分强悍,验证速度极快(sync.Map)。API 动态增删用户则更高效顺滑。 https://github.com/XTLS/Xray-core/issues/158",-1),V=e("p",null,"引入 ProtoBuf 是一个创举,等下会详细讲解。“指令”到“地址”的结构目前与 VMess 完全相同,同样支持 Mux。",-1),b={href:"https://github.com/rprx/v2ray-vless/releases",target:"_blank",rel:"noopener noreferrer"},L=r('

                                        ProtoBuf

                                        似乎只有 VLESS 可选内嵌 ProtoBuf,它是一种数据交换格式,信息被紧密编码成二进制,TLV 结构(Tag Length Value)。

                                        起因是我看到一篇文章称 SS 有一些缺点,如没有设计错误回报机制,客户端没办法根据不同的错误采取进一步的动作。 (但我并不认同所有错误都要回报,不然防不了主动探测。下一个测试版中,服务器可以返回一串自定义信息。) 于是想到一个可扩展的结构是很重要的,未来它也可以承载如动态端口指令。不止响应,请求也需要类似的结构。 本来打算自己设计 TLV,接着发觉 ProtoBuf 就是此结构、现成的轮子,完全适合用来做这件事,各语言支持等也不错。

                                        目前“附加信息”只有 Scheduler 和 SchedulerV,它们是 MessName 和 MessSeed 的替代者,当你不需要它们时,“附加信息长度”为 0,也就不会有 ProtoBuf 序列化/反序列化的开销。其实我更愿意称这个过程为“拼接”,因为 pb 实际原理上也只是这么做而已,相关开销极小。拼接后的 bytes 十分紧凑,和 ALPHA 的方案相差无几,有兴趣的可以分别输出并对比。

                                        为了指示对附加信息(Addons,也可以理解成插件,以后可以有很多个插件)的不同支持程度,下个测试版会在“附加信息长度”前新增“附加信息版本”。256 - 1 = 255 字节是够用且合理的(65535 就太多了,还可能有人恶意填充),现有的只用了十分之一,以后也不会同时有那么多附加信息,且大多数情况下是完全没有附加信息的。真不够用的话,可以升级 VLESS 版本。

                                        为了减少逻辑判断等开销,暂定 Addons 不使用多级结构。一个月前出现过“可变协议格式”的想法,pb 是可以做到打乱顺序,但没必要,因为现代加密的设计不会让旁观者看出两次传输的头部相同。

                                        下面介绍 Schedulers 和 Encryption 的构想,它们都是可选的,一个应对流量时序特征问题,一个应对密码学上的问题。

                                        Schedulers Flow

                                        中文名暂称:流量调度器(2020-09-03 更新:中文名确定为“流控”),指令由 ProtoBuf 承载,控制的是数据部分。

                                        我之前发现,VMess 原有的 shake “元数据混淆”在 TLS 上完全不会带来有意义的改变,只会降低性能,所以 VLESS 弃用了它。并且,“混淆”这个表述容易被误解成伪装,也弃用了。顺便一提,我一直是不看好伪装的:做不到完全一样,那不就是强特征吗?做得到完全一样,那为什么不直接用伪装目标?我一开始用的是 SSR,后来发现它只是表面伪装骗运营商,就再也没用过了。

                                        那么,“流量调度器”要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)。流量时序特征也可以是行为带来的,比如访问 Google 首页时加载了多少文件、顺序、每个文件的大小,多套一层加密并不能有效掩盖这些信息。

                                        Schedulers 没必要像下面的 Encryption 一样整个套在外面,因为头部的一丁点数据相对于后面的数据量来说太微不足道了。

                                        BETA 2 预计推出两个初级的 Scheduler:Zstd 压缩、数据量动态扩充。进阶操作才是从宏观层面来控制、分配,暂时咕咕。

                                        Encryption

                                        与 VMess 的高度耦合不同,VLESS 的服务端、客户端不久后可以提前约定好加密方式,仅在外面套一层加密。这有点类似于使用 TLS,不影响承载的任何数据,也可以理解成底层就是从 TLS 换成预设约定加密。相对于高度耦合,这种方式更合理且灵活:一种加密方式出了安全性问题,直接扔掉并换用其它的就行了,十分方便。VLESS 服务端还会允许不同的加密方式共存。

                                        ',15),E={href:"https://github.com/rprx/v2fly-github-io/blob/master/docs/config/protocols/vless.md",target:"_blank",rel:"noopener noreferrer"},g=e("p",null,"加密支持两类形式,一类是加密完全独立,需要额外密码,适合私用,另一类是结合已有的 UUID 来加密,适合公用。 (若用第一类加密形式,且密码是以某种形式公开的,比如多人共用,那么中间人攻击就不远了) 重新设计的动态端口可能会随加密同时推出,指令由 ProtoBuf 承载,具体实现和 VMess 的动态端口也会有很多不同。",-1),y=e("p",null,"套现成加密是件很简单的事情,也就多一层 writer & reader。BETA 3 预计支持 SS 的 aes-128-gcm 和 chacha20-ietf-poly1305: 客户端的 encryption 可以填 “auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654”,auto 会选择最适合当前机器的,0 代表测试版,最后的是密码。服务端的 decryption 也是类似填法,收到请求时会逐一尝试解密。",-1),m=e("p",null,"并不是所有组合都需逐一尝试:VMess 的加密分为三段,第一段是认证信息,结合了 UUID、alterId、时间因素,第二段是指令部分,以固定算法加密,指令中含有数据部分使用的加密算法,第三段才是重要的数据部分。可以看出,VMess 的加解密方式实际上是多对一(服务端适配),而不仅是结合 UUID。但仅是结合 UUID 来加密也是件相对麻烦的事情,短时间内不会出,鉴于我们现在有 VMessAEAD 可用,也并不着急。若 VLESS 推出了结合 UUID 的加密方式,相当于重构了整个 VMess。",-1),T=e("h2",{id:"udp-issues",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#udp-issues"},[e("span",null,"UDP issues")])],-1),x={href:"https://github.com/XTLS/Xray-core/discussions/252",target:"_blank",rel:"noopener noreferrer"},A=r('

                                        客户端开发指引

                                        1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。iOS 客户端的协议实现则需紧跟升级。
                                        2. 视觉标准:UI 标识请统一用 VLESS,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。
                                        3. encryption 应做成输入框而不是选择框,新配置的默认值应为 none,若用户置空则应代填 none

                                        VLESS 分享链接标准

                                        ',3),M=e("img",{src:"https://avatars2.githubusercontent.com/u/7822648?s=32",width:"32px",height:"32px",alt:"a"},null,-1),U={href:"https://github.com/DuckSoft",target:"_blank",rel:"noopener noreferrer"},P={href:"https://github.com/XTLS/Xray-core/issues/91",target:"_blank",rel:"noopener noreferrer"};function v(B,k){const a=n("I18nTip"),o=n("ExternalLinkIcon");return d(),c("div",null,[s(a),p,e("blockquote",null,[e("p",null,[t("“响应认证”被替换为“协议版本”并移至最前,使 VLESS 可以升级换代,同时消除了生成伪随机数的开销。混淆相关结构被替换为附加信息(ProtoBuf)并前移,赋予协议本身可扩展性,相关开销也极小("),e("a",i,[t("gogo/protobuf"),s(o)]),t("),若无附加信息则无相关开销。")])]),u,S,_,f,V,e("p",null,[t("总体上,ALPHA 2 到 BETA 主要是:结构进化、清理整合、性能提升、更加完善。这些都是一点一滴的,详见 "),e("a",b,[t("VLESS Changes"),s(o)]),t("。")]),L,e("p",null,[t('对比 VMess,VLESS 相当于把 security 换成 encryption,把 disableInsecureEncryption 换成 decryption,就解决了所有问题。目前 encryption 和 decryption 只接受 "none" 且不能留空(即使以后有连接安全性检查),详见 '),e("a",E,[t("VLESS 配置文档"),s(o)]),t("。encryption 并不需要往外移一级,一是因为无法复用很多代码,二是因为会影响控制粒度,看未来的应用就明白了。")]),g,y,m,T,e("p",null,[e("a",x,[t("XUDP:VLESS & VMess & Mux UDP FullCone NAT"),s(o)])]),A,e("p",null,[t("感谢 "),M,t(),e("a",U,[t("@DuckSoft"),s(o)]),t(" 的提案!")]),e("p",null,[t("详情请见 "),e("a",P,[t("VMessAEAD / VLESS 分享链接标准提案"),s(o)])])])}const D=h(l,[["render",v],["__file","vless.html.vue"]]);export{D as default}; diff --git a/assets/vless.html-D_sclD0U.js b/assets/vless.html-XJTROLo0.js similarity index 99% rename from assets/vless.html-D_sclD0U.js rename to assets/vless.html-XJTROLo0.js index 943a31a08d..da46f911c7 100644 --- a/assets/vless.html-D_sclD0U.js +++ b/assets/vless.html-XJTROLo0.js @@ -1,4 +1,4 @@ -import{_ as i,r as a,o as u,c as r,a as e,b as n,d as s,w as t,e as p}from"./app-5SoadDYS.js";const d={},v=n("h1",{id:"vless-xtls-vision-seed",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless-xtls-vision-seed"},[n("span",null,"VLESS(XTLS Vision Seed)")])],-1),k=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"警告"),n("p",null,"目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。")],-1),b=n("p",null,"VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。",-1),q=p(`

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as i,r as a,o as u,c as r,a as e,b as n,d as s,w as t,e as p}from"./app-Bw2NG-QJ.js";const d={},v=n("h1",{id:"vless-xtls-vision-seed",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vless-xtls-vision-seed"},[n("span",null,"VLESS(XTLS Vision Seed)")])],-1),k=n("div",{class:"custom-container danger"},[n("p",{class:"custom-container-title"},"警告"),n("p",null,"目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。")],-1),b=n("p",null,"VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。",-1),q=p(`

                                        OutboundConfigurationObject

                                        {
                                           "vnext": [
                                             {
                                               "address": "example.com",
                                        diff --git a/assets/vless.html-CIaM0KTd.js b/assets/vless.html-gWexYZDk.js
                                        similarity index 99%
                                        rename from assets/vless.html-CIaM0KTd.js
                                        rename to assets/vless.html-gWexYZDk.js
                                        index 83ab1e5278..36c9bbad41 100644
                                        --- a/assets/vless.html-CIaM0KTd.js
                                        +++ b/assets/vless.html-gWexYZDk.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as a,o as u,c as r,a as e,b as s,d as n,w as t,e as p}from"./app-5SoadDYS.js";const d={},v=s("h1",{id:"vless",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#vless"},[s("span",null,"VLESS")])],-1),k=s("div",{class:"custom-container danger"},[s("p",{class:"custom-container-title"},"Предупреждение"),s("p",null,"VLESS не предусматривает встроенного шифрования, поэтому обязательным условием для его использования является наличие надежного канала, такого как TLS или REALITY.")],-1),b=s("p",null,"VLESS - это легкий транспортный протокол без сохранения состояния, который разделен на входящую и исходящую части и может служить мостом между клиентом и сервером Xray.",-1),q=p(`

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as i,r as a,o as u,c as r,a as e,b as s,d as n,w as t,e as p}from"./app-Bw2NG-QJ.js";const d={},v=s("h1",{id:"vless",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#vless"},[s("span",null,"VLESS")])],-1),k=s("div",{class:"custom-container danger"},[s("p",{class:"custom-container-title"},"Предупреждение"),s("p",null,"VLESS не предусматривает встроенного шифрования, поэтому обязательным условием для его использования является наличие надежного канала, такого как TLS или REALITY.")],-1),b=s("p",null,"VLESS - это легкий транспортный протокол без сохранения состояния, который разделен на входящую и исходящую части и может служить мостом между клиентом и сервером Xray.",-1),q=p(`

                                        OutboundConfigurationObject

                                        {
                                           "vnext": [
                                             {
                                               "address": "example.com",
                                        diff --git a/assets/vmess.html-DBKgR8RL.js b/assets/vmess.html-Blynvi6-.js
                                        similarity index 99%
                                        rename from assets/vmess.html-DBKgR8RL.js
                                        rename to assets/vmess.html-Blynvi6-.js
                                        index 9a711072e2..889100ddcd 100644
                                        --- a/assets/vmess.html-DBKgR8RL.js
                                        +++ b/assets/vmess.html-Blynvi6-.js
                                        @@ -1 +1 @@
                                        -import{_ as r,r as i,o,c as h,a as n,b as t,d as e,e as s}from"./app-5SoadDYS.js";const d={},c=s('

                                        VMess Protocol

                                        VMess is an encrypted transmission protocol that can serve as a bridge between the Xray client and server.

                                        Version

                                        The current version number is 1.

                                        Dependencies

                                        Underlying Protocol

                                        VMess is a TCP-based protocol where all data is transmitted over TCP.

                                        User ID

                                        ',8),u={href:"https://en.wikipedia.org/wiki/Universally_unique_identifier",target:"_blank",rel:"noopener noreferrer"},p=t("code",null,"de305d54-75b4-431b-adb2-eb6b9e546014",-1),y={href:"https://www.uuidgenerator.net/",target:"_blank",rel:"noopener noreferrer"},m=t("p",null,[e("User ID can be specified in the "),t("a",{href:"../../config"},"configuration file"),e(".")],-1),b=t("h3",{id:"functions",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#functions"},[t("span",null,"Functions")])],-1),f={href:"https://en.wikipedia.org/wiki/MD5",target:"_blank",rel:"noopener noreferrer"},g=t("ul",null,[t("li",null,"Input parameter is any length byte array"),t("li",null,"Output is a 16-byte array")],-1),x={href:"https://en.wikipedia.org/wiki/Hash-based_message_authentication_code",target:"_blank",rel:"noopener noreferrer"},v=t("ul",null,[t("li",null,[e("Input parameters are: "),t("ul",null,[t("li",null,"H: Hash function"),t("li",null,"K: Key, any length byte array"),t("li",null,"M: Message, any length byte array")])])],-1),k={href:"https://en.wikipedia.org/wiki/SHA-3",target:"_blank",rel:"noopener noreferrer"},_=t("ul",null,[t("li",null,"Input parameter is any length string"),t("li",null,"Output is any length string")],-1),I=s('

                                        Communication Process

                                        VMess is a stateless protocol, which means that data can be transmitted directly between the client and the server without the need for a handshake. Each data transmission has no impact on other data transmissions before or after it.

                                        When a VMess client initiates a request, the server checks whether the request comes from a legitimate client. If the validation passes, the server forwards the request and sends the obtained response back to the client.

                                        VMess uses an asymmetric format, meaning that the requests sent by the client and the responses from the server use different formats.

                                        Client Request

                                        16 BytesX BytesRemaining
                                        Authentication InformationInstruction PartData Part

                                        Authentication Information

                                        The authentication information is a 16-byte hash (hash) value, which is calculated as follows:

                                        • H = MD5
                                        • K = User ID (16 bytes)
                                        • M = UTC time accurate to seconds, with a random value of ±30 seconds from the current time (8 bytes, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        Command Section

                                        The instruction part is encrypted using AES-128-CFB.

                                        • Key: MD5(user ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV: MD5(X + X + X + X), X = []byte(time generated by authentication information) (8 bytes, Big Endian)
                                        1 Byte16 Bytes16 Bytes1 Byte1 Byte4 bits4 bits1 Byte1 Byte2 Bytes1 ByteN BytesP Bytes4 Bytes
                                        VersionData Encryption IVData Encryption KeyResponse Authentication ValueOptionsReservedEncryption MethodReservedCommandPortAddress TypeAddressRandom ValueChecksum

                                        Options Opt Details: (When a bit is 1, it means the option is enabled)

                                        01234567
                                        XXXXXMRS

                                        of which:

                                        • Version Number Ver: Always 1;
                                        • Data Encryption IV: Random value;
                                        • Data Encryption Key: Random value;
                                        • Response Authentication V: Random value;
                                        • Option Opt:
                                          • S (0x01): Standard format data stream (recommended);
                                          • R (0x02): Client expects to reuse TCP connection (deprecated in Xray 2.23+);
                                            • This item only takes effect when S is enabled;
                                          • M (0x04): Enable metadata obfuscation (recommended);
                                            • This item only takes effect when S is enabled;
                                            • When this item is enabled, the client and server need to construct two Shake instances respectively, RequestMask = Shake (request data IV), ResponseMask = Shake (response data IV).
                                          • X: Reserved
                                        • Redundancy P: Random value added before checksum value;
                                        • Encryption Method: Specify the encryption method for the data part, and the optional values are:
                                          • 0x00: AES-128-CFB;
                                          • 0x01: No encryption;
                                          • 0x02: AES-128-GCM;
                                          • 0x03: ChaCha20-Poly1305;
                                        • Instruction Cmd:
                                          • 0x01: TCP data;
                                          • 0x02: UDP data;
                                        • Port Port: Integer port number in Big Endian format;
                                        • Address Type T:
                                          • 0x01: IPv4
                                          • 0x02: Domain name
                                          • 0x03: IPv6
                                        • Address A:
                                          • When T = 0x01, A is a 4-byte IPv4 address;
                                          • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
                                          • When T = 0x03, A is a 16-byte IPv6 address;
                                        • Check F: FNV1a hash of all content in the instruction except F.

                                        Data Section

                                        When Opt(S) is enabled, this format is used for the data section. The actual request data is divided into several small chunks, and each chunk has the following format. After the server verifies all the small chunks, it will be forwarded in the basic format.

                                        2 BytesL Bytes
                                        Length LData Packet

                                        in which:

                                        • Length L: A big-endian integer with a maximum value of 2^14.
                                          • When Opt(M) is enabled, the value of L is equal to the true value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • Packet: A data packet encrypted by the specified encryption method.

                                        Before the transmission is completed, the data packet must contain actual data, in addition to the length and authentication data. When the transmission is complete, the client must send an empty data packet, that is, L = 0 (unencrypted) or the length of the authentication data (encrypted), to indicate the end of the transmission.

                                        The packets are formatted as follows, depending on the encryption method:

                                        • Unencrypted:   - L bytes: actual data;
                                        • AES-128-CFB: The entire data section is encrypted using AES-128-CFB.   - 4 bytes: FNV1a hash of actual data;   - L - 4 bytes: actual data;
                                        • AES-128-GCM: Key is the Key of the instruction section, IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: GCM authentication information
                                        • ChaCha20-Poly1305: Key = MD5 (instruction part Key) + MD5 (MD5 (instruction part Key)), IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: Poly1305 authentication information

                                        Server Response

                                        The header data is encrypted using AES-128-CFB encryption. The IV is MD5 of the data encryption IV, and the Key is MD5 of the data encryption Key. The actual response data varies depending on the encryption settings.

                                        1 Byte1 Byte1 Byte1 ByteM BytesRemaining Part
                                        Response Authentication VOption OptCommand CmdCommand Length MCommand ContentActual Response Data

                                        in which:

                                        • Response Authentication V: must match the response authentication V in the client request.
                                        • Option Opt:
                                          • 0x01: server prepares to reuse TCP connections (deprecated in Xray 2.23+).
                                        • Command Cmd:
                                          • 0x01: dynamic port command.
                                        • Actual response data:
                                          • If Opt(S) in the request is enabled, the standard format is used. Otherwise, the basic format is used.
                                          • Both formats are identical to the request data.
                                            • When Opt(M) is enabled, the value of length L is equal to the true value XOR Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte().

                                        Dynamic Port Instructions

                                        1 Byte2 Bytes16 Bytes2 Bytes1 Byte1 Byte
                                        ReservedPortUser IDAlterIDUser levelValidity period T

                                        in which:

                                        • Port: Integer port number in Big Endian format
                                        • T: Number of minutes as integer value.

                                        When the client receives a dynamic port command, the server opens a new port for communication. The client can then send data to the new port. After T minutes, the port will expire, and the client must use the main port to communicate again.

                                        Comment

                                        • To ensure forward compatibility, the values of all reserved fields must be 0.
                                        ',37);function B(M,w){const l=i("I18nTip"),a=i("ExternalLinkIcon");return o(),h("div",null,[n(l),c,t("p",null,[e("An ID is equivalent to a "),t("a",u,[e("UUID"),n(a)]),e(", which is a 16-byte long random number. Its function is similar to a token. An ID looks like: "),p,e(", it is almost entirely random and can be generated using any UUID generator, such as "),t("a",y,[e("this one"),n(a)]),e(".")]),m,b,t("ul",null,[t("li",null,[e("MD5: "),t("a",f,[e("MD5 Function"),n(a)]),g]),t("li",null,[e("HMAC: "),t("a",x,[e("HMAC Function"),n(a)]),v]),t("li",null,[e("Shake: "),t("a",k,[e("SHA3-Shake128 Function"),n(a)]),_])]),I])}const V=r(d,[["render",B],["__file","vmess.html.vue"]]);export{V as default}; +import{_ as r,r as i,o,c as h,a as n,b as t,d as e,e as s}from"./app-Bw2NG-QJ.js";const d={},c=s('

                                        VMess Protocol

                                        VMess is an encrypted transmission protocol that can serve as a bridge between the Xray client and server.

                                        Version

                                        The current version number is 1.

                                        Dependencies

                                        Underlying Protocol

                                        VMess is a TCP-based protocol where all data is transmitted over TCP.

                                        User ID

                                        ',8),u={href:"https://en.wikipedia.org/wiki/Universally_unique_identifier",target:"_blank",rel:"noopener noreferrer"},p=t("code",null,"de305d54-75b4-431b-adb2-eb6b9e546014",-1),y={href:"https://www.uuidgenerator.net/",target:"_blank",rel:"noopener noreferrer"},m=t("p",null,[e("User ID can be specified in the "),t("a",{href:"../../config"},"configuration file"),e(".")],-1),b=t("h3",{id:"functions",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#functions"},[t("span",null,"Functions")])],-1),f={href:"https://en.wikipedia.org/wiki/MD5",target:"_blank",rel:"noopener noreferrer"},g=t("ul",null,[t("li",null,"Input parameter is any length byte array"),t("li",null,"Output is a 16-byte array")],-1),x={href:"https://en.wikipedia.org/wiki/Hash-based_message_authentication_code",target:"_blank",rel:"noopener noreferrer"},v=t("ul",null,[t("li",null,[e("Input parameters are: "),t("ul",null,[t("li",null,"H: Hash function"),t("li",null,"K: Key, any length byte array"),t("li",null,"M: Message, any length byte array")])])],-1),k={href:"https://en.wikipedia.org/wiki/SHA-3",target:"_blank",rel:"noopener noreferrer"},_=t("ul",null,[t("li",null,"Input parameter is any length string"),t("li",null,"Output is any length string")],-1),I=s('

                                        Communication Process

                                        VMess is a stateless protocol, which means that data can be transmitted directly between the client and the server without the need for a handshake. Each data transmission has no impact on other data transmissions before or after it.

                                        When a VMess client initiates a request, the server checks whether the request comes from a legitimate client. If the validation passes, the server forwards the request and sends the obtained response back to the client.

                                        VMess uses an asymmetric format, meaning that the requests sent by the client and the responses from the server use different formats.

                                        Client Request

                                        16 BytesX BytesRemaining
                                        Authentication InformationInstruction PartData Part

                                        Authentication Information

                                        The authentication information is a 16-byte hash (hash) value, which is calculated as follows:

                                        • H = MD5
                                        • K = User ID (16 bytes)
                                        • M = UTC time accurate to seconds, with a random value of ±30 seconds from the current time (8 bytes, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        Command Section

                                        The instruction part is encrypted using AES-128-CFB.

                                        • Key: MD5(user ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV: MD5(X + X + X + X), X = []byte(time generated by authentication information) (8 bytes, Big Endian)
                                        1 Byte16 Bytes16 Bytes1 Byte1 Byte4 bits4 bits1 Byte1 Byte2 Bytes1 ByteN BytesP Bytes4 Bytes
                                        VersionData Encryption IVData Encryption KeyResponse Authentication ValueOptionsReservedEncryption MethodReservedCommandPortAddress TypeAddressRandom ValueChecksum

                                        Options Opt Details: (When a bit is 1, it means the option is enabled)

                                        01234567
                                        XXXXXMRS

                                        of which:

                                        • Version Number Ver: Always 1;
                                        • Data Encryption IV: Random value;
                                        • Data Encryption Key: Random value;
                                        • Response Authentication V: Random value;
                                        • Option Opt:
                                          • S (0x01): Standard format data stream (recommended);
                                          • R (0x02): Client expects to reuse TCP connection (deprecated in Xray 2.23+);
                                            • This item only takes effect when S is enabled;
                                          • M (0x04): Enable metadata obfuscation (recommended);
                                            • This item only takes effect when S is enabled;
                                            • When this item is enabled, the client and server need to construct two Shake instances respectively, RequestMask = Shake (request data IV), ResponseMask = Shake (response data IV).
                                          • X: Reserved
                                        • Redundancy P: Random value added before checksum value;
                                        • Encryption Method: Specify the encryption method for the data part, and the optional values are:
                                          • 0x00: AES-128-CFB;
                                          • 0x01: No encryption;
                                          • 0x02: AES-128-GCM;
                                          • 0x03: ChaCha20-Poly1305;
                                        • Instruction Cmd:
                                          • 0x01: TCP data;
                                          • 0x02: UDP data;
                                        • Port Port: Integer port number in Big Endian format;
                                        • Address Type T:
                                          • 0x01: IPv4
                                          • 0x02: Domain name
                                          • 0x03: IPv6
                                        • Address A:
                                          • When T = 0x01, A is a 4-byte IPv4 address;
                                          • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
                                          • When T = 0x03, A is a 16-byte IPv6 address;
                                        • Check F: FNV1a hash of all content in the instruction except F.

                                        Data Section

                                        When Opt(S) is enabled, this format is used for the data section. The actual request data is divided into several small chunks, and each chunk has the following format. After the server verifies all the small chunks, it will be forwarded in the basic format.

                                        2 BytesL Bytes
                                        Length LData Packet

                                        in which:

                                        • Length L: A big-endian integer with a maximum value of 2^14.
                                          • When Opt(M) is enabled, the value of L is equal to the true value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • Packet: A data packet encrypted by the specified encryption method.

                                        Before the transmission is completed, the data packet must contain actual data, in addition to the length and authentication data. When the transmission is complete, the client must send an empty data packet, that is, L = 0 (unencrypted) or the length of the authentication data (encrypted), to indicate the end of the transmission.

                                        The packets are formatted as follows, depending on the encryption method:

                                        • Unencrypted:   - L bytes: actual data;
                                        • AES-128-CFB: The entire data section is encrypted using AES-128-CFB.   - 4 bytes: FNV1a hash of actual data;   - L - 4 bytes: actual data;
                                        • AES-128-GCM: Key is the Key of the instruction section, IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: GCM authentication information
                                        • ChaCha20-Poly1305: Key = MD5 (instruction part Key) + MD5 (MD5 (instruction part Key)), IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: Poly1305 authentication information

                                        Server Response

                                        The header data is encrypted using AES-128-CFB encryption. The IV is MD5 of the data encryption IV, and the Key is MD5 of the data encryption Key. The actual response data varies depending on the encryption settings.

                                        1 Byte1 Byte1 Byte1 ByteM BytesRemaining Part
                                        Response Authentication VOption OptCommand CmdCommand Length MCommand ContentActual Response Data

                                        in which:

                                        • Response Authentication V: must match the response authentication V in the client request.
                                        • Option Opt:
                                          • 0x01: server prepares to reuse TCP connections (deprecated in Xray 2.23+).
                                        • Command Cmd:
                                          • 0x01: dynamic port command.
                                        • Actual response data:
                                          • If Opt(S) in the request is enabled, the standard format is used. Otherwise, the basic format is used.
                                          • Both formats are identical to the request data.
                                            • When Opt(M) is enabled, the value of length L is equal to the true value XOR Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte().

                                        Dynamic Port Instructions

                                        1 Byte2 Bytes16 Bytes2 Bytes1 Byte1 Byte
                                        ReservedPortUser IDAlterIDUser levelValidity period T

                                        in which:

                                        • Port: Integer port number in Big Endian format
                                        • T: Number of minutes as integer value.

                                        When the client receives a dynamic port command, the server opens a new port for communication. The client can then send data to the new port. After T minutes, the port will expire, and the client must use the main port to communicate again.

                                        Comment

                                        • To ensure forward compatibility, the values of all reserved fields must be 0.
                                        ',37);function B(M,w){const l=i("I18nTip"),a=i("ExternalLinkIcon");return o(),h("div",null,[n(l),c,t("p",null,[e("An ID is equivalent to a "),t("a",u,[e("UUID"),n(a)]),e(", which is a 16-byte long random number. Its function is similar to a token. An ID looks like: "),p,e(", it is almost entirely random and can be generated using any UUID generator, such as "),t("a",y,[e("this one"),n(a)]),e(".")]),m,b,t("ul",null,[t("li",null,[e("MD5: "),t("a",f,[e("MD5 Function"),n(a)]),g]),t("li",null,[e("HMAC: "),t("a",x,[e("HMAC Function"),n(a)]),v]),t("li",null,[e("Shake: "),t("a",k,[e("SHA3-Shake128 Function"),n(a)]),_])]),I])}const V=r(d,[["render",B],["__file","vmess.html.vue"]]);export{V as default}; diff --git a/assets/vmess.html-j0DrtN75.js b/assets/vmess.html-Bnv13XwA.js similarity index 99% rename from assets/vmess.html-j0DrtN75.js rename to assets/vmess.html-Bnv13XwA.js index ac72d8359a..11c5a4ab9c 100644 --- a/assets/vmess.html-j0DrtN75.js +++ b/assets/vmess.html-Bnv13XwA.js @@ -1,4 +1,4 @@ -import{_ as i,r as t,o as u,c as d,a as s,b as e,w as o,d as n,e as c}from"./app-5SoadDYS.js";const r={},b=e("h1",{id:"vmess",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#vmess"},[e("span",null,"VMess")])],-1),v=c(`

                                        警告

                                        VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 120 秒之内,时区无关。在 Linux 系统中可以安装ntp服务来自动同步系统时间。

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as u,c as d,a as s,b as e,w as o,d as n,e as c}from"./app-Bw2NG-QJ.js";const r={},b=e("h1",{id:"vmess",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#vmess"},[e("span",null,"VMess")])],-1),v=c(`

                                        警告

                                        VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 120 秒之内,时区无关。在 Linux 系统中可以安装ntp服务来自动同步系统时间。

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "id": "5783a3e7-e373-51cd-8642-c83782b807c5",
                                        diff --git a/assets/vmess.html-D9LxQYXS.js b/assets/vmess.html-BtwOPh9t.js
                                        similarity index 99%
                                        rename from assets/vmess.html-D9LxQYXS.js
                                        rename to assets/vmess.html-BtwOPh9t.js
                                        index 82e5df2815..ed7d42dd21 100644
                                        --- a/assets/vmess.html-D9LxQYXS.js
                                        +++ b/assets/vmess.html-BtwOPh9t.js
                                        @@ -1 +1 @@
                                        -import{_ as s,r as a,o as r,c as d,a as l,b as t,d as e,e as n}from"./app-5SoadDYS.js";const c={},o=n('

                                        VMess 协议

                                        VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        版本

                                        当前版本号为 1。

                                        依赖

                                        底层协议

                                        VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。

                                        用户 ID

                                        ',8),p={href:"https://en.wikipedia.org/wiki/Universally_unique_identifier",target:"_blank",rel:"noopener noreferrer"},x={href:"https://www.uuidgenerator.net/",target:"_blank",rel:"noopener noreferrer"},u=t("p",null,[e("用户 ID 可在"),t("a",{href:"../../config"},"配置文件"),e("中指定。")],-1),y=t("h3",{id:"函数",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#函数"},[t("span",null,"函数")])],-1),g={href:"https://en.wikipedia.org/wiki/MD5",target:"_blank",rel:"noopener noreferrer"},b=t("ul",null,[t("li",null,"输入参数为任意长度的 byte 数组"),t("li",null,"输出为一个 16 byte 的数组")],-1),_={href:"https://en.wikipedia.org/wiki/Hash-based_message_authentication_code",target:"_blank",rel:"noopener noreferrer"},M=t("ul",null,[t("li",null,[e("输入参数为: "),t("ul",null,[t("li",null,"H:散列函数"),t("li",null,"K:密钥,任意长度的 byte 数组"),t("li",null,"M:消息,任意长度的 byte 数组")])])],-1),f={href:"https://en.wikipedia.org/wiki/SHA-3",target:"_blank",rel:"noopener noreferrer"},V=t("ul",null,[t("li",null,"输入参数为任意长度的字符串"),t("li",null,"输出为任意长度的字符串")],-1),k=n('

                                        通讯过程

                                        VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。

                                        VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。

                                        VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。

                                        客户端请求

                                        16 字节X 字节余下部分
                                        认证信息指令部分数据部分

                                        认证信息

                                        认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下:

                                        • H = MD5
                                        • K = 用户 ID (16 字节)
                                        • M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        指令部分

                                        指令部分经过 AES-128-CFB 加密:

                                        • Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian)
                                        1 字节16 字节16 字节1 字节1 字节4 位4 位1 字节1 字节2 字节1 字节N 字节P 字节4 字节
                                        版本号 Ver数据加密 IV数据加密 Key响应认证 V选项 Opt余量 P加密方式 Sec保留指令 Cmd端口 Port地址类型 T地址 A随机值校验 F

                                        选项 Opt 细节:(当某一位为 1 时,表示该选项启用)

                                        01234567
                                        XXXXXMRS

                                        其中:

                                        • 版本号 Ver:始终为 1;
                                        • 数据加密 IV:随机值;
                                        • 数据加密 Key:随机值;
                                        • 响应认证 V:随机值;
                                        • 选项 Opt:
                                          • S (0x01):标准格式的数据流(建议开启);
                                          • R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用);
                                            • 只有当 S 开启时,这一项才有效;
                                          • M (0x04):开启元数据混淆(建议开启);
                                            • 只有当 S 开启时,这一项才有效;
                                            • 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。
                                          • X:保留
                                        • 余量 P:在校验值之前加入 P 字节的随机值;
                                        • 加密方式:指定数据部分的加密方式,可选的值有:
                                          • 0x00:AES-128-CFB;
                                          • 0x01:不加密;
                                          • 0x02:AES-128-GCM;
                                          • 0x03:ChaCha20-Poly1305;
                                        • 指令 Cmd:
                                          • 0x01:TCP 数据;
                                          • 0x02:UDP 数据;
                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • 校验 F:指令部分除 F 外所有内容的 FNV1a hash;

                                        数据部分

                                        当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。

                                        2 字节L 字节
                                        长度 L数据包

                                        其中:

                                        • 长度 L:Big Endian 格式的整型,最大值为 2^14;
                                          • 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • 数据包:由指定的加密方式加密过的数据包;

                                        在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。

                                        按加密方式不同,数据包的格式如下:

                                        • 不加密:
                                          • L 字节:实际数据;
                                        • AES-128-CFB:整个数据部分使用 AES-128-CFB 加密
                                          • 4 字节:实际数据的 FNV1a hash;
                                          • L - 4 字节:实际数据;
                                        • AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:GCM 认证信息
                                        • ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:Poly1305 认证信息

                                        服务器应答

                                        应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。

                                        1 字节1 字节1 字节1 字节M 字节余下部分
                                        响应认证 V选项 Opt指令 Cmd指令长度 M指令内容实际应答数据

                                        其中:

                                        • 响应认证 V:必须和客户端请求中的响应认证 V 一致;
                                        • 选项 Opt:
                                          • 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用);
                                        • 指令 Cmd:
                                          • 0x01:动态端口指令
                                        • 实际应答数据:
                                          • 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。
                                          • 格式均和请求数据相同。
                                            • 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

                                        动态端口指令

                                        1 字节2 字节16 字节2 字节1 字节1 字节
                                        保留端口 Port用户 IDAlterID用户等级有效时间 T

                                        其中:

                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 有效时间 T:分钟数;

                                        客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。

                                        注释

                                        • 为确保向前兼容性,所有保留字段的值必须为 0。
                                        ',37);function I(C,D){const h=a("I18nTip"),i=a("ExternalLinkIcon");return r(),d("div",null,[l(h),o,t("p",null,[e("ID 等价于 "),t("a",p,[e("UUID"),l(i)]),e(",是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如"),t("a",x,[e("这个"),l(i)]),e("。")]),u,y,t("ul",null,[t("li",null,[e("MD5: "),t("a",g,[e("MD5 函数"),l(i)]),b]),t("li",null,[e("HMAC: "),t("a",_,[e("HMAC 函数"),l(i)]),M]),t("li",null,[e("Shake: "),t("a",f,[e("SHA3-Shake128 函数"),l(i)]),V])]),k])}const P=s(c,[["render",I],["__file","vmess.html.vue"]]);export{P as default}; +import{_ as s,r as a,o as r,c as d,a as l,b as t,d as e,e as n}from"./app-Bw2NG-QJ.js";const c={},o=n('

                                        VMess 协议

                                        VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        版本

                                        当前版本号为 1。

                                        依赖

                                        底层协议

                                        VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。

                                        用户 ID

                                        ',8),p={href:"https://en.wikipedia.org/wiki/Universally_unique_identifier",target:"_blank",rel:"noopener noreferrer"},x={href:"https://www.uuidgenerator.net/",target:"_blank",rel:"noopener noreferrer"},u=t("p",null,[e("用户 ID 可在"),t("a",{href:"../../config"},"配置文件"),e("中指定。")],-1),y=t("h3",{id:"函数",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#函数"},[t("span",null,"函数")])],-1),g={href:"https://en.wikipedia.org/wiki/MD5",target:"_blank",rel:"noopener noreferrer"},b=t("ul",null,[t("li",null,"输入参数为任意长度的 byte 数组"),t("li",null,"输出为一个 16 byte 的数组")],-1),_={href:"https://en.wikipedia.org/wiki/Hash-based_message_authentication_code",target:"_blank",rel:"noopener noreferrer"},M=t("ul",null,[t("li",null,[e("输入参数为: "),t("ul",null,[t("li",null,"H:散列函数"),t("li",null,"K:密钥,任意长度的 byte 数组"),t("li",null,"M:消息,任意长度的 byte 数组")])])],-1),f={href:"https://en.wikipedia.org/wiki/SHA-3",target:"_blank",rel:"noopener noreferrer"},V=t("ul",null,[t("li",null,"输入参数为任意长度的字符串"),t("li",null,"输出为任意长度的字符串")],-1),k=n('

                                        通讯过程

                                        VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。

                                        VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。

                                        VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。

                                        客户端请求

                                        16 字节X 字节余下部分
                                        认证信息指令部分数据部分

                                        认证信息

                                        认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下:

                                        • H = MD5
                                        • K = 用户 ID (16 字节)
                                        • M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        指令部分

                                        指令部分经过 AES-128-CFB 加密:

                                        • Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian)
                                        1 字节16 字节16 字节1 字节1 字节4 位4 位1 字节1 字节2 字节1 字节N 字节P 字节4 字节
                                        版本号 Ver数据加密 IV数据加密 Key响应认证 V选项 Opt余量 P加密方式 Sec保留指令 Cmd端口 Port地址类型 T地址 A随机值校验 F

                                        选项 Opt 细节:(当某一位为 1 时,表示该选项启用)

                                        01234567
                                        XXXXXMRS

                                        其中:

                                        • 版本号 Ver:始终为 1;
                                        • 数据加密 IV:随机值;
                                        • 数据加密 Key:随机值;
                                        • 响应认证 V:随机值;
                                        • 选项 Opt:
                                          • S (0x01):标准格式的数据流(建议开启);
                                          • R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用);
                                            • 只有当 S 开启时,这一项才有效;
                                          • M (0x04):开启元数据混淆(建议开启);
                                            • 只有当 S 开启时,这一项才有效;
                                            • 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。
                                          • X:保留
                                        • 余量 P:在校验值之前加入 P 字节的随机值;
                                        • 加密方式:指定数据部分的加密方式,可选的值有:
                                          • 0x00:AES-128-CFB;
                                          • 0x01:不加密;
                                          • 0x02:AES-128-GCM;
                                          • 0x03:ChaCha20-Poly1305;
                                        • 指令 Cmd:
                                          • 0x01:TCP 数据;
                                          • 0x02:UDP 数据;
                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • 校验 F:指令部分除 F 外所有内容的 FNV1a hash;

                                        数据部分

                                        当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。

                                        2 字节L 字节
                                        长度 L数据包

                                        其中:

                                        • 长度 L:Big Endian 格式的整型,最大值为 2^14;
                                          • 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • 数据包:由指定的加密方式加密过的数据包;

                                        在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。

                                        按加密方式不同,数据包的格式如下:

                                        • 不加密:
                                          • L 字节:实际数据;
                                        • AES-128-CFB:整个数据部分使用 AES-128-CFB 加密
                                          • 4 字节:实际数据的 FNV1a hash;
                                          • L - 4 字节:实际数据;
                                        • AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:GCM 认证信息
                                        • ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:Poly1305 认证信息

                                        服务器应答

                                        应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。

                                        1 字节1 字节1 字节1 字节M 字节余下部分
                                        响应认证 V选项 Opt指令 Cmd指令长度 M指令内容实际应答数据

                                        其中:

                                        • 响应认证 V:必须和客户端请求中的响应认证 V 一致;
                                        • 选项 Opt:
                                          • 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用);
                                        • 指令 Cmd:
                                          • 0x01:动态端口指令
                                        • 实际应答数据:
                                          • 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。
                                          • 格式均和请求数据相同。
                                            • 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

                                        动态端口指令

                                        1 字节2 字节16 字节2 字节1 字节1 字节
                                        保留端口 Port用户 IDAlterID用户等级有效时间 T

                                        其中:

                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 有效时间 T:分钟数;

                                        客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。

                                        注释

                                        • 为确保向前兼容性,所有保留字段的值必须为 0。
                                        ',37);function I(C,D){const h=a("I18nTip"),i=a("ExternalLinkIcon");return r(),d("div",null,[l(h),o,t("p",null,[e("ID 等价于 "),t("a",p,[e("UUID"),l(i)]),e(",是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如"),t("a",x,[e("这个"),l(i)]),e("。")]),u,y,t("ul",null,[t("li",null,[e("MD5: "),t("a",g,[e("MD5 函数"),l(i)]),b]),t("li",null,[e("HMAC: "),t("a",_,[e("HMAC 函数"),l(i)]),M]),t("li",null,[e("Shake: "),t("a",f,[e("SHA3-Shake128 函数"),l(i)]),V])]),k])}const P=s(c,[["render",I],["__file","vmess.html.vue"]]);export{P as default}; diff --git a/assets/vmess.html-BRWJ5o8r.js b/assets/vmess.html-CWgbIYSO.js similarity index 99% rename from assets/vmess.html-BRWJ5o8r.js rename to assets/vmess.html-CWgbIYSO.js index 4dfda249a7..988dc07068 100644 --- a/assets/vmess.html-BRWJ5o8r.js +++ b/assets/vmess.html-CWgbIYSO.js @@ -1,4 +1,4 @@ -import{_ as l,r as a,o as i,c as r,a as e,b as s,w as t,d as n,e as c}from"./app-5SoadDYS.js";const d={},q=s("h1",{id:"vmess",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#vmess"},[s("span",null,"VMess")])],-1),v=c(`

                                        警告

                                        VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 120 秒之内,时区无关。在 Linux 系统中可以安装ntp服务来自动同步系统时间。

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as l,r as a,o as i,c as r,a as e,b as s,w as t,d as n,e as c}from"./app-Bw2NG-QJ.js";const d={},q=s("h1",{id:"vmess",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#vmess"},[s("span",null,"VMess")])],-1),v=c(`

                                        警告

                                        VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 120 秒之内,时区无关。在 Linux 系统中可以安装ntp服务来自动同步系统时间。

                                        OutboundConfigurationObject

                                        {
                                           "vnext": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/vmess.html-BNuNWfIe.js b/assets/vmess.html-CeLsjjaY.js
                                        similarity index 99%
                                        rename from assets/vmess.html-BNuNWfIe.js
                                        rename to assets/vmess.html-CeLsjjaY.js
                                        index 6d0ce45bf9..429fb3b70c 100644
                                        --- a/assets/vmess.html-BNuNWfIe.js
                                        +++ b/assets/vmess.html-CeLsjjaY.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as a,o as i,c as r,a as e,b as s,w as t,d as n,e as p}from"./app-5SoadDYS.js";const d={},q=s("h1",{id:"vmess",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#vmess"},[s("span",null,"VMess")])],-1),v=p(`

                                        Предупреждение

                                        VMess полагается на системное время. Убедитесь, что системное время UTC, используемое Xray, находится в пределах 120 секунд от фактического времени, независимо от часового пояса. В системах Linux вы можете установить службу ntp для автоматической синхронизации системного времени.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as l,r as a,o as i,c as r,a as e,b as s,w as t,d as n,e as p}from"./app-Bw2NG-QJ.js";const d={},q=s("h1",{id:"vmess",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#vmess"},[s("span",null,"VMess")])],-1),v=p(`

                                        Предупреждение

                                        VMess полагается на системное время. Убедитесь, что системное время UTC, используемое Xray, находится в пределах 120 секунд от фактического времени, независимо от часового пояса. В системах Linux вы можете установить службу ntp для автоматической синхронизации системного времени.

                                        OutboundConfigurationObject

                                        {
                                           "vnext": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/vmess.html-Dt2MIkqN.js b/assets/vmess.html-CzAuOHQq.js
                                        similarity index 99%
                                        rename from assets/vmess.html-Dt2MIkqN.js
                                        rename to assets/vmess.html-CzAuOHQq.js
                                        index 82e5df2815..ed7d42dd21 100644
                                        --- a/assets/vmess.html-Dt2MIkqN.js
                                        +++ b/assets/vmess.html-CzAuOHQq.js
                                        @@ -1 +1 @@
                                        -import{_ as s,r as a,o as r,c as d,a as l,b as t,d as e,e as n}from"./app-5SoadDYS.js";const c={},o=n('

                                        VMess 协议

                                        VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        版本

                                        当前版本号为 1。

                                        依赖

                                        底层协议

                                        VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。

                                        用户 ID

                                        ',8),p={href:"https://en.wikipedia.org/wiki/Universally_unique_identifier",target:"_blank",rel:"noopener noreferrer"},x={href:"https://www.uuidgenerator.net/",target:"_blank",rel:"noopener noreferrer"},u=t("p",null,[e("用户 ID 可在"),t("a",{href:"../../config"},"配置文件"),e("中指定。")],-1),y=t("h3",{id:"函数",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#函数"},[t("span",null,"函数")])],-1),g={href:"https://en.wikipedia.org/wiki/MD5",target:"_blank",rel:"noopener noreferrer"},b=t("ul",null,[t("li",null,"输入参数为任意长度的 byte 数组"),t("li",null,"输出为一个 16 byte 的数组")],-1),_={href:"https://en.wikipedia.org/wiki/Hash-based_message_authentication_code",target:"_blank",rel:"noopener noreferrer"},M=t("ul",null,[t("li",null,[e("输入参数为: "),t("ul",null,[t("li",null,"H:散列函数"),t("li",null,"K:密钥,任意长度的 byte 数组"),t("li",null,"M:消息,任意长度的 byte 数组")])])],-1),f={href:"https://en.wikipedia.org/wiki/SHA-3",target:"_blank",rel:"noopener noreferrer"},V=t("ul",null,[t("li",null,"输入参数为任意长度的字符串"),t("li",null,"输出为任意长度的字符串")],-1),k=n('

                                        通讯过程

                                        VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。

                                        VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。

                                        VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。

                                        客户端请求

                                        16 字节X 字节余下部分
                                        认证信息指令部分数据部分

                                        认证信息

                                        认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下:

                                        • H = MD5
                                        • K = 用户 ID (16 字节)
                                        • M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        指令部分

                                        指令部分经过 AES-128-CFB 加密:

                                        • Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian)
                                        1 字节16 字节16 字节1 字节1 字节4 位4 位1 字节1 字节2 字节1 字节N 字节P 字节4 字节
                                        版本号 Ver数据加密 IV数据加密 Key响应认证 V选项 Opt余量 P加密方式 Sec保留指令 Cmd端口 Port地址类型 T地址 A随机值校验 F

                                        选项 Opt 细节:(当某一位为 1 时,表示该选项启用)

                                        01234567
                                        XXXXXMRS

                                        其中:

                                        • 版本号 Ver:始终为 1;
                                        • 数据加密 IV:随机值;
                                        • 数据加密 Key:随机值;
                                        • 响应认证 V:随机值;
                                        • 选项 Opt:
                                          • S (0x01):标准格式的数据流(建议开启);
                                          • R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用);
                                            • 只有当 S 开启时,这一项才有效;
                                          • M (0x04):开启元数据混淆(建议开启);
                                            • 只有当 S 开启时,这一项才有效;
                                            • 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。
                                          • X:保留
                                        • 余量 P:在校验值之前加入 P 字节的随机值;
                                        • 加密方式:指定数据部分的加密方式,可选的值有:
                                          • 0x00:AES-128-CFB;
                                          • 0x01:不加密;
                                          • 0x02:AES-128-GCM;
                                          • 0x03:ChaCha20-Poly1305;
                                        • 指令 Cmd:
                                          • 0x01:TCP 数据;
                                          • 0x02:UDP 数据;
                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • 校验 F:指令部分除 F 外所有内容的 FNV1a hash;

                                        数据部分

                                        当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。

                                        2 字节L 字节
                                        长度 L数据包

                                        其中:

                                        • 长度 L:Big Endian 格式的整型,最大值为 2^14;
                                          • 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • 数据包:由指定的加密方式加密过的数据包;

                                        在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。

                                        按加密方式不同,数据包的格式如下:

                                        • 不加密:
                                          • L 字节:实际数据;
                                        • AES-128-CFB:整个数据部分使用 AES-128-CFB 加密
                                          • 4 字节:实际数据的 FNV1a hash;
                                          • L - 4 字节:实际数据;
                                        • AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:GCM 认证信息
                                        • ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:Poly1305 认证信息

                                        服务器应答

                                        应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。

                                        1 字节1 字节1 字节1 字节M 字节余下部分
                                        响应认证 V选项 Opt指令 Cmd指令长度 M指令内容实际应答数据

                                        其中:

                                        • 响应认证 V:必须和客户端请求中的响应认证 V 一致;
                                        • 选项 Opt:
                                          • 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用);
                                        • 指令 Cmd:
                                          • 0x01:动态端口指令
                                        • 实际应答数据:
                                          • 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。
                                          • 格式均和请求数据相同。
                                            • 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

                                        动态端口指令

                                        1 字节2 字节16 字节2 字节1 字节1 字节
                                        保留端口 Port用户 IDAlterID用户等级有效时间 T

                                        其中:

                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 有效时间 T:分钟数;

                                        客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。

                                        注释

                                        • 为确保向前兼容性,所有保留字段的值必须为 0。
                                        ',37);function I(C,D){const h=a("I18nTip"),i=a("ExternalLinkIcon");return r(),d("div",null,[l(h),o,t("p",null,[e("ID 等价于 "),t("a",p,[e("UUID"),l(i)]),e(",是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如"),t("a",x,[e("这个"),l(i)]),e("。")]),u,y,t("ul",null,[t("li",null,[e("MD5: "),t("a",g,[e("MD5 函数"),l(i)]),b]),t("li",null,[e("HMAC: "),t("a",_,[e("HMAC 函数"),l(i)]),M]),t("li",null,[e("Shake: "),t("a",f,[e("SHA3-Shake128 函数"),l(i)]),V])]),k])}const P=s(c,[["render",I],["__file","vmess.html.vue"]]);export{P as default}; +import{_ as s,r as a,o as r,c as d,a as l,b as t,d as e,e as n}from"./app-Bw2NG-QJ.js";const c={},o=n('

                                        VMess 协议

                                        VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        版本

                                        当前版本号为 1。

                                        依赖

                                        底层协议

                                        VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。

                                        用户 ID

                                        ',8),p={href:"https://en.wikipedia.org/wiki/Universally_unique_identifier",target:"_blank",rel:"noopener noreferrer"},x={href:"https://www.uuidgenerator.net/",target:"_blank",rel:"noopener noreferrer"},u=t("p",null,[e("用户 ID 可在"),t("a",{href:"../../config"},"配置文件"),e("中指定。")],-1),y=t("h3",{id:"函数",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#函数"},[t("span",null,"函数")])],-1),g={href:"https://en.wikipedia.org/wiki/MD5",target:"_blank",rel:"noopener noreferrer"},b=t("ul",null,[t("li",null,"输入参数为任意长度的 byte 数组"),t("li",null,"输出为一个 16 byte 的数组")],-1),_={href:"https://en.wikipedia.org/wiki/Hash-based_message_authentication_code",target:"_blank",rel:"noopener noreferrer"},M=t("ul",null,[t("li",null,[e("输入参数为: "),t("ul",null,[t("li",null,"H:散列函数"),t("li",null,"K:密钥,任意长度的 byte 数组"),t("li",null,"M:消息,任意长度的 byte 数组")])])],-1),f={href:"https://en.wikipedia.org/wiki/SHA-3",target:"_blank",rel:"noopener noreferrer"},V=t("ul",null,[t("li",null,"输入参数为任意长度的字符串"),t("li",null,"输出为任意长度的字符串")],-1),k=n('

                                        通讯过程

                                        VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。

                                        VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。

                                        VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。

                                        客户端请求

                                        16 字节X 字节余下部分
                                        认证信息指令部分数据部分

                                        认证信息

                                        认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下:

                                        • H = MD5
                                        • K = 用户 ID (16 字节)
                                        • M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        指令部分

                                        指令部分经过 AES-128-CFB 加密:

                                        • Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian)
                                        1 字节16 字节16 字节1 字节1 字节4 位4 位1 字节1 字节2 字节1 字节N 字节P 字节4 字节
                                        版本号 Ver数据加密 IV数据加密 Key响应认证 V选项 Opt余量 P加密方式 Sec保留指令 Cmd端口 Port地址类型 T地址 A随机值校验 F

                                        选项 Opt 细节:(当某一位为 1 时,表示该选项启用)

                                        01234567
                                        XXXXXMRS

                                        其中:

                                        • 版本号 Ver:始终为 1;
                                        • 数据加密 IV:随机值;
                                        • 数据加密 Key:随机值;
                                        • 响应认证 V:随机值;
                                        • 选项 Opt:
                                          • S (0x01):标准格式的数据流(建议开启);
                                          • R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用);
                                            • 只有当 S 开启时,这一项才有效;
                                          • M (0x04):开启元数据混淆(建议开启);
                                            • 只有当 S 开启时,这一项才有效;
                                            • 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。
                                          • X:保留
                                        • 余量 P:在校验值之前加入 P 字节的随机值;
                                        • 加密方式:指定数据部分的加密方式,可选的值有:
                                          • 0x00:AES-128-CFB;
                                          • 0x01:不加密;
                                          • 0x02:AES-128-GCM;
                                          • 0x03:ChaCha20-Poly1305;
                                        • 指令 Cmd:
                                          • 0x01:TCP 数据;
                                          • 0x02:UDP 数据;
                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • 校验 F:指令部分除 F 外所有内容的 FNV1a hash;

                                        数据部分

                                        当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。

                                        2 字节L 字节
                                        长度 L数据包

                                        其中:

                                        • 长度 L:Big Endian 格式的整型,最大值为 2^14;
                                          • 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • 数据包:由指定的加密方式加密过的数据包;

                                        在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。

                                        按加密方式不同,数据包的格式如下:

                                        • 不加密:
                                          • L 字节:实际数据;
                                        • AES-128-CFB:整个数据部分使用 AES-128-CFB 加密
                                          • 4 字节:实际数据的 FNV1a hash;
                                          • L - 4 字节:实际数据;
                                        • AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:GCM 认证信息
                                        • ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:Poly1305 认证信息

                                        服务器应答

                                        应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。

                                        1 字节1 字节1 字节1 字节M 字节余下部分
                                        响应认证 V选项 Opt指令 Cmd指令长度 M指令内容实际应答数据

                                        其中:

                                        • 响应认证 V:必须和客户端请求中的响应认证 V 一致;
                                        • 选项 Opt:
                                          • 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用);
                                        • 指令 Cmd:
                                          • 0x01:动态端口指令
                                        • 实际应答数据:
                                          • 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。
                                          • 格式均和请求数据相同。
                                            • 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

                                        动态端口指令

                                        1 字节2 字节16 字节2 字节1 字节1 字节
                                        保留端口 Port用户 IDAlterID用户等级有效时间 T

                                        其中:

                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 有效时间 T:分钟数;

                                        客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。

                                        注释

                                        • 为确保向前兼容性,所有保留字段的值必须为 0。
                                        ',37);function I(C,D){const h=a("I18nTip"),i=a("ExternalLinkIcon");return r(),d("div",null,[l(h),o,t("p",null,[e("ID 等价于 "),t("a",p,[e("UUID"),l(i)]),e(",是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如"),t("a",x,[e("这个"),l(i)]),e("。")]),u,y,t("ul",null,[t("li",null,[e("MD5: "),t("a",g,[e("MD5 函数"),l(i)]),b]),t("li",null,[e("HMAC: "),t("a",_,[e("HMAC 函数"),l(i)]),M]),t("li",null,[e("Shake: "),t("a",f,[e("SHA3-Shake128 函数"),l(i)]),V])]),k])}const P=s(c,[["render",I],["__file","vmess.html.vue"]]);export{P as default}; diff --git a/assets/vmess.html-DArYh1N-.js b/assets/vmess.html-Ds4NV6pk.js similarity index 99% rename from assets/vmess.html-DArYh1N-.js rename to assets/vmess.html-Ds4NV6pk.js index 9a2c3adba1..79d10e5f18 100644 --- a/assets/vmess.html-DArYh1N-.js +++ b/assets/vmess.html-Ds4NV6pk.js @@ -1,4 +1,4 @@ -import{_ as p,r as t,o as u,c as l,a as s,b as n,w as a,d as e,e as c}from"./app-5SoadDYS.js";const d={},h=n("h1",{id:"vmess",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vmess"},[n("span",null,"VMess")])],-1),m=c(`

                                        Danger

                                        VMess relies on system time. Please ensure that the UTC time of your system, when using Xray, has an error within 120 seconds, regardless of the time zone. On Linux systems, you can install the ntp service to automatically synchronize the system time.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as p,r as t,o as u,c as l,a as s,b as n,w as a,d as e,e as c}from"./app-Bw2NG-QJ.js";const d={},h=n("h1",{id:"vmess",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vmess"},[n("span",null,"VMess")])],-1),m=c(`

                                        Danger

                                        VMess relies on system time. Please ensure that the UTC time of your system, when using Xray, has an error within 120 seconds, regardless of the time zone. On Linux systems, you can install the ntp service to automatically synchronize the system time.

                                        OutboundConfigurationObject

                                        {
                                           "vnext": [
                                             {
                                               "address": "127.0.0.1",
                                        diff --git a/assets/vmess.html-D8czgnar.js b/assets/vmess.html-dZZBrBA9.js
                                        similarity index 99%
                                        rename from assets/vmess.html-D8czgnar.js
                                        rename to assets/vmess.html-dZZBrBA9.js
                                        index 4c95f71f18..a5f59b9410 100644
                                        --- a/assets/vmess.html-D8czgnar.js
                                        +++ b/assets/vmess.html-dZZBrBA9.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as a,o as r,c as u,a as s,b as e,w as o,d as n,e as l}from"./app-5SoadDYS.js";const d={},h=e("h1",{id:"vmess",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#vmess"},[e("span",null,"VMess")])],-1),v=l(`

                                        Danger

                                        VMess relies on system time. Please ensure that the system UTC time used by Xray is within 120 seconds of the actual time, regardless of time zone. On Linux systems, you can install the ntp service to automatically synchronize the system time.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as p,r as a,o as r,c as u,a as s,b as e,w as o,d as n,e as l}from"./app-Bw2NG-QJ.js";const d={},h=e("h1",{id:"vmess",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#vmess"},[e("span",null,"VMess")])],-1),v=l(`

                                        Danger

                                        VMess relies on system time. Please ensure that the system UTC time used by Xray is within 120 seconds of the actual time, regardless of time zone. On Linux systems, you can install the ntp service to automatically synchronize the system time.

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "id": "5783a3e7-e373-51cd-8642-c83782b807c5",
                                        diff --git a/assets/vmess.html-Dw5jQJR5.js b/assets/vmess.html-gu8tRDOO.js
                                        similarity index 99%
                                        rename from assets/vmess.html-Dw5jQJR5.js
                                        rename to assets/vmess.html-gu8tRDOO.js
                                        index cb04b95ff8..fb59f632de 100644
                                        --- a/assets/vmess.html-Dw5jQJR5.js
                                        +++ b/assets/vmess.html-gu8tRDOO.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as i,r as t,o as u,c as d,a as e,b as n,w as o,d as s,e as l}from"./app-5SoadDYS.js";const r={},v=n("h1",{id:"vmess",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vmess"},[n("span",null,"VMess")])],-1),b=l(`

                                        Предупреждение

                                        VMess полагается на системное время. Убедитесь, что системное время UTC, используемое Xray, находится в пределах 120 секунд от фактического времени, независимо от часового пояса. В системах Linux вы можете установить службу ntp для автоматической синхронизации системного времени.

                                        InboundConfigurationObject

                                        {
                                        +import{_ as i,r as t,o as u,c as d,a as e,b as n,w as o,d as s,e as l}from"./app-Bw2NG-QJ.js";const r={},v=n("h1",{id:"vmess",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#vmess"},[n("span",null,"VMess")])],-1),b=l(`

                                        Предупреждение

                                        VMess полагается на системное время. Убедитесь, что системное время UTC, используемое Xray, находится в пределах 120 секунд от фактического времени, независимо от часового пояса. В системах Linux вы можете установить службу ntp для автоматической синхронизации системного времени.

                                        InboundConfigurationObject

                                        {
                                           "clients": [
                                             {
                                               "id": "5783a3e7-e373-51cd-8642-c83782b807c5",
                                        diff --git a/assets/warp.html-DVfMNHe2.js b/assets/warp.html-9hKZfp2I.js
                                        similarity index 99%
                                        rename from assets/warp.html-DVfMNHe2.js
                                        rename to assets/warp.html-9hKZfp2I.js
                                        index cbbb8758a5..2193568148 100644
                                        --- a/assets/warp.html-DVfMNHe2.js
                                        +++ b/assets/warp.html-9hKZfp2I.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as c,c as u,a,b as n,d as s,e}from"./app-5SoadDYS.js";const i={},r=n("h1",{id:"通过-cloudflare-warp-增强代理安全性",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#通过-cloudflare-warp-增强代理安全性"},[n("span",null,"通过 Cloudflare Warp 增强代理安全性")])],-1),d=n("p",null,"Xray(1.6.5+)新加入了 WireGuard 出站,虽然增加的代码和依赖会增大 core 体积,但是我们认为这是一个很有必要的新功能,原因有三:",-1),k={href:"https://github.com/net4people/bbs/issues/129#issuecomment-1308102504",target:"_blank",rel:"noopener noreferrer"},v=n("li",null,"众所周知,大部分机场会记录用户访问域名的日志,某些机场还会审计和阻断一些用户流量。保护用户私密性的一个方法,就是在客户端使用链式代理。 Warp 使用的 WireGuard 轻量级 VPN 协议会在代理层内增加一层加密。对于机场而言,用户所有流量的目标都是 Warp,从而最大程度保护自己的隐私。",-1),q=n("li",null,"方便使用,只需要一个 core 即可完成分流,Wireguard Tun,链式代理的设置。",-1),m=e('

                                        申请 Warp 账户

                                        感谢 Cloudflare 推动自由的互联网,现在你可以免费使用 Warp 服务,连接的时候会根据出口自动选择最近的服务器

                                        方法 1:

                                        ',3),b={href:"https://github.com/ViRb3/wgcf/releases",target:"_blank",rel:"noopener noreferrer"},g=n("li",null,[s("运行 "),n("code",null,"wgcf register"),s(" 生成 "),n("code",null,"wgcf-account.toml")],-1),y=n("li",null,[s("运行 "),n("code",null,"wgcf generate"),s(" 生成 "),n("code",null,"wgcf-profile.conf"),s(" 拷贝内容如下:")],-1),h=e(`
                                        [Interface]
                                        +import{_ as l,r as p,o as c,c as u,a,b as n,d as s,e}from"./app-Bw2NG-QJ.js";const i={},r=n("h1",{id:"通过-cloudflare-warp-增强代理安全性",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#通过-cloudflare-warp-增强代理安全性"},[n("span",null,"通过 Cloudflare Warp 增强代理安全性")])],-1),d=n("p",null,"Xray(1.6.5+)新加入了 WireGuard 出站,虽然增加的代码和依赖会增大 core 体积,但是我们认为这是一个很有必要的新功能,原因有三:",-1),k={href:"https://github.com/net4people/bbs/issues/129#issuecomment-1308102504",target:"_blank",rel:"noopener noreferrer"},v=n("li",null,"众所周知,大部分机场会记录用户访问域名的日志,某些机场还会审计和阻断一些用户流量。保护用户私密性的一个方法,就是在客户端使用链式代理。 Warp 使用的 WireGuard 轻量级 VPN 协议会在代理层内增加一层加密。对于机场而言,用户所有流量的目标都是 Warp,从而最大程度保护自己的隐私。",-1),q=n("li",null,"方便使用,只需要一个 core 即可完成分流,Wireguard Tun,链式代理的设置。",-1),m=e('

                                        申请 Warp 账户

                                        感谢 Cloudflare 推动自由的互联网,现在你可以免费使用 Warp 服务,连接的时候会根据出口自动选择最近的服务器

                                        方法 1:

                                        ',3),b={href:"https://github.com/ViRb3/wgcf/releases",target:"_blank",rel:"noopener noreferrer"},g=n("li",null,[s("运行 "),n("code",null,"wgcf register"),s(" 生成 "),n("code",null,"wgcf-account.toml")],-1),y=n("li",null,[s("运行 "),n("code",null,"wgcf generate"),s(" 生成 "),n("code",null,"wgcf-profile.conf"),s(" 拷贝内容如下:")],-1),h=e(`
                                        [Interface]
                                         PrivateKey = 我的私钥
                                         Address = 172.16.0.2/32
                                         Address = 2606:4700:110:8949:fed8:2642:a640:c8e1/128
                                        diff --git a/assets/warp.html-CkXwKg50.js b/assets/warp.html-Bzz-XxvP.js
                                        similarity index 99%
                                        rename from assets/warp.html-CkXwKg50.js
                                        rename to assets/warp.html-Bzz-XxvP.js
                                        index 3a4ccf06f0..7b5bf66934 100644
                                        --- a/assets/warp.html-CkXwKg50.js
                                        +++ b/assets/warp.html-Bzz-XxvP.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as l,r as p,o as c,c as u,a,b as n,d as s,e}from"./app-5SoadDYS.js";const i={},r=n("h1",{id:"повышение-безопасности-проксирования-с-помощью-cloudflare-warp",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#повышение-безопасности-проксирования-с-помощью-cloudflare-warp"},[n("span",null,"Повышение безопасности проксирования с помощью Cloudflare Warp")])],-1),d=n("p",null,"В Xray (1.6.5+) добавлен исходящий WireGuard. Хотя это увеличивает размер ядра из-за дополнительных кода и зависимостей, мы считаем, что это важная новая функция по трем причинам:",-1),k={href:"https://github.com/net4people/bbs/issues/129#issuecomment-1308102504",target:"_blank",rel:"noopener noreferrer"},v=n("br",null,null,-1),q=n("br",null,null,-1),m=n("br",null,null,-1),b=n("li",null,[s("Как известно, большинство VPN-провайдеров ведут журналы посещенных пользователями доменов, а некоторые даже проверяют и блокируют определенный трафик."),n("br"),s(" Один из способов защиты конфиденциальности пользователей - использовать цепочку прокси-серверов на клиенте."),n("br"),s(" Warp использует легкий VPN-протокол WireGuard, который добавляет дополнительный уровень шифрования."),n("br"),s(" Для VPN-провайдера весь трафик пользователя будет направляться на Warp, что обеспечивает максимальную защиту конфиденциальности.")],-1),g=n("li",null,[s("Простота использования."),n("br"),s(" Для настройки разделения трафика, WireGuard-туннеля и цепочки прокси-серверов достаточно одного ядра.")],-1),y=e('

                                        Создание аккаунта Warp

                                        Спасибо Cloudflare за содействие свободному интернету! Теперь вы можете бесплатно пользоваться услугами Warp. При подключении автоматически выбирается ближайший сервер.

                                        Метод 1:

                                        ',3),h={href:"https://github.com/ViRb3/wgcf/releases",target:"_blank",rel:"noopener noreferrer"},_=n("li",null,[s("Запустите "),n("code",null,"wgcf register"),s(", чтобы создать файл "),n("code",null,"wgcf-account.toml"),s(".")],-1),f=n("li",null,[s("Запустите "),n("code",null,"wgcf generate"),s(", чтобы создать файл "),n("code",null,"wgcf-profile.conf"),s(". Скопируйте его содержимое:")],-1),w=e(`
                                        [Interface]
                                        +import{_ as l,r as p,o as c,c as u,a,b as n,d as s,e}from"./app-Bw2NG-QJ.js";const i={},r=n("h1",{id:"повышение-безопасности-проксирования-с-помощью-cloudflare-warp",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#повышение-безопасности-проксирования-с-помощью-cloudflare-warp"},[n("span",null,"Повышение безопасности проксирования с помощью Cloudflare Warp")])],-1),d=n("p",null,"В Xray (1.6.5+) добавлен исходящий WireGuard. Хотя это увеличивает размер ядра из-за дополнительных кода и зависимостей, мы считаем, что это важная новая функция по трем причинам:",-1),k={href:"https://github.com/net4people/bbs/issues/129#issuecomment-1308102504",target:"_blank",rel:"noopener noreferrer"},v=n("br",null,null,-1),q=n("br",null,null,-1),m=n("br",null,null,-1),b=n("li",null,[s("Как известно, большинство VPN-провайдеров ведут журналы посещенных пользователями доменов, а некоторые даже проверяют и блокируют определенный трафик."),n("br"),s(" Один из способов защиты конфиденциальности пользователей - использовать цепочку прокси-серверов на клиенте."),n("br"),s(" Warp использует легкий VPN-протокол WireGuard, который добавляет дополнительный уровень шифрования."),n("br"),s(" Для VPN-провайдера весь трафик пользователя будет направляться на Warp, что обеспечивает максимальную защиту конфиденциальности.")],-1),g=n("li",null,[s("Простота использования."),n("br"),s(" Для настройки разделения трафика, WireGuard-туннеля и цепочки прокси-серверов достаточно одного ядра.")],-1),y=e('

                                        Создание аккаунта Warp

                                        Спасибо Cloudflare за содействие свободному интернету! Теперь вы можете бесплатно пользоваться услугами Warp. При подключении автоматически выбирается ближайший сервер.

                                        Метод 1:

                                        ',3),h={href:"https://github.com/ViRb3/wgcf/releases",target:"_blank",rel:"noopener noreferrer"},_=n("li",null,[s("Запустите "),n("code",null,"wgcf register"),s(", чтобы создать файл "),n("code",null,"wgcf-account.toml"),s(".")],-1),f=n("li",null,[s("Запустите "),n("code",null,"wgcf generate"),s(", чтобы создать файл "),n("code",null,"wgcf-profile.conf"),s(". Скопируйте его содержимое:")],-1),w=e(`
                                        [Interface]
                                         PrivateKey = Мой закрытый ключ
                                         Address = 172.16.0.2/32
                                         Address = 2606:4700:110:8949:fed8:2642:a640:c8e1/128
                                        diff --git a/assets/warp.html-7HQyZ8uD.js b/assets/warp.html-CO5RmDTS.js
                                        similarity index 99%
                                        rename from assets/warp.html-7HQyZ8uD.js
                                        rename to assets/warp.html-CO5RmDTS.js
                                        index 0519cd7ab6..9f1902ffd6 100644
                                        --- a/assets/warp.html-7HQyZ8uD.js
                                        +++ b/assets/warp.html-CO5RmDTS.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as p,r as t,o as i,c as l,a,b as n,d as s,e as c}from"./app-5SoadDYS.js";const r={},u=n("h1",{id:"enhancing-proxy-security-with-cloudflare-warp",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#enhancing-proxy-security-with-cloudflare-warp"},[n("span",null,"Enhancing Proxy Security with Cloudflare Warp")])],-1),d=n("p",null,"Xray (1.6.5+) has added outbound WireGuard support. Although the added code and dependencies will increase the core size, we believe that this is a necessary new feature for three reasons:",-1),v={href:"https://github.com/net4people/bbs/issues/129#issuecomment-1308102504",target:"_blank",rel:"noopener noreferrer"},k=n("li",null,"As we all know, most airports will log the domain names visited by users, and some airports will even audit and block some user traffic. One way to protect user privacy is to use chain proxies on the client side. The WireGuard lightweight VPN protocol used by Warp adds an extra layer of encryption within the proxy layer. For airports, the target of all user traffic is Warp, thereby maximizing privacy protection.",-1),m=n("li",null,"It is easy to use, and only one core is needed to complete the split, Wireguard Tun, and chain proxy settings.",-1),b=n("h2",{id:"applying-for-a-warp-account",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#applying-for-a-warp-account"},[n("span",null,"Applying for a Warp Account")])],-1),q=n("li",null,"Thank you Cloudflare for promoting a free internet. Now you can use the Warp service for free, and the nearest server will be automatically selected based on the exit.",-1),h={href:"https://github.com/ViRb3/wgcf/releases",target:"_blank",rel:"noopener noreferrer"},g=n("li",null,[s("Run "),n("code",null,"wgcf register"),s(" to generate "),n("code",null,"wgcf-account.toml"),s(".")],-1),y=n("li",null,[s("Run "),n("code",null,"wgcf generate"),s(" to generate "),n("code",null,"wgcf-profile.conf"),s(". Copy the following content:")],-1),f=c(`
                                        [Interface]
                                        +import{_ as p,r as t,o as i,c as l,a,b as n,d as s,e as c}from"./app-Bw2NG-QJ.js";const r={},u=n("h1",{id:"enhancing-proxy-security-with-cloudflare-warp",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#enhancing-proxy-security-with-cloudflare-warp"},[n("span",null,"Enhancing Proxy Security with Cloudflare Warp")])],-1),d=n("p",null,"Xray (1.6.5+) has added outbound WireGuard support. Although the added code and dependencies will increase the core size, we believe that this is a necessary new feature for three reasons:",-1),v={href:"https://github.com/net4people/bbs/issues/129#issuecomment-1308102504",target:"_blank",rel:"noopener noreferrer"},k=n("li",null,"As we all know, most airports will log the domain names visited by users, and some airports will even audit and block some user traffic. One way to protect user privacy is to use chain proxies on the client side. The WireGuard lightweight VPN protocol used by Warp adds an extra layer of encryption within the proxy layer. For airports, the target of all user traffic is Warp, thereby maximizing privacy protection.",-1),m=n("li",null,"It is easy to use, and only one core is needed to complete the split, Wireguard Tun, and chain proxy settings.",-1),b=n("h2",{id:"applying-for-a-warp-account",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#applying-for-a-warp-account"},[n("span",null,"Applying for a Warp Account")])],-1),q=n("li",null,"Thank you Cloudflare for promoting a free internet. Now you can use the Warp service for free, and the nearest server will be automatically selected based on the exit.",-1),h={href:"https://github.com/ViRb3/wgcf/releases",target:"_blank",rel:"noopener noreferrer"},g=n("li",null,[s("Run "),n("code",null,"wgcf register"),s(" to generate "),n("code",null,"wgcf-account.toml"),s(".")],-1),y=n("li",null,[s("Run "),n("code",null,"wgcf generate"),s(" to generate "),n("code",null,"wgcf-profile.conf"),s(". Copy the following content:")],-1),f=c(`
                                        [Interface]
                                         PrivateKey = my private key
                                         Address = 172.16.0.2/32
                                         Address = 2606:4700:110:8949:fed8:2642:a640:c8e1/128
                                        diff --git a/assets/websocket.html-CQ0wGOkU.js b/assets/websocket.html-DJjmBrAj.js
                                        similarity index 98%
                                        rename from assets/websocket.html-CQ0wGOkU.js
                                        rename to assets/websocket.html-DJjmBrAj.js
                                        index 3085505295..1ec279e288 100644
                                        --- a/assets/websocket.html-CQ0wGOkU.js
                                        +++ b/assets/websocket.html-DJjmBrAj.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as d,r as t,o as p,c as i,a as s,b as o,d as e,w as l,e as n}from"./app-5SoadDYS.js";const h={},u=n(`

                                        WebSocket

                                        Uses standard WebSocket for data transmission.

                                        WebSocket connections can be proxied by other web servers (like NGINX) or by VLESS fallback paths.

                                        Tip

                                        WebSocket inbounds will parse the X-Forwarded-For header received, overriding the source address with a higher priority than the source address got from PROXY protocol.

                                        WebSocketObject

                                        WebSocketObject corresponds to the wsSettings property of the transport configs.

                                        {
                                        +import{_ as d,r as t,o as p,c as i,a as s,b as o,d as e,w as l,e as n}from"./app-Bw2NG-QJ.js";const h={},u=n(`

                                        WebSocket

                                        Uses standard WebSocket for data transmission.

                                        WebSocket connections can be proxied by other web servers (like NGINX) or by VLESS fallback paths.

                                        Tip

                                        WebSocket inbounds will parse the X-Forwarded-For header received, overriding the source address with a higher priority than the source address got from PROXY protocol.

                                        WebSocketObject

                                        WebSocketObject corresponds to the wsSettings property of the transport configs.

                                        {
                                           "acceptProxyProtocol": false,
                                           "path": "/",
                                           "host": "xray.com",
                                        diff --git a/assets/websocket.html-DsKOF98s.js b/assets/websocket.html-DzGXVtRP.js
                                        similarity index 98%
                                        rename from assets/websocket.html-DsKOF98s.js
                                        rename to assets/websocket.html-DzGXVtRP.js
                                        index 04393435e0..62d694173e 100644
                                        --- a/assets/websocket.html-DsKOF98s.js
                                        +++ b/assets/websocket.html-DzGXVtRP.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as s,o as l,c as d,a as t,b as o,d as e,w as i,e as a}from"./app-5SoadDYS.js";const u={},k=a(`

                                        WebSocket

                                        使用标准的 WebSocket 来传输数据。

                                        WebSocket 连接可以被其它 HTTP 服务器(如 Nginx)分流,也可以被 VLESS fallbacks path 分流。

                                        提示

                                        Websocket 会识别 HTTP 请求的 X-Forwarded-For 头来覆写流量的源地址,优先级高于 PROXY protocol。

                                        WebSocketObject

                                        WebSocketObject 对应传输配置的 wsSettings 项。

                                        {
                                        +import{_ as r,r as s,o as l,c as d,a as t,b as o,d as e,w as i,e as a}from"./app-Bw2NG-QJ.js";const u={},k=a(`

                                        WebSocket

                                        使用标准的 WebSocket 来传输数据。

                                        WebSocket 连接可以被其它 HTTP 服务器(如 Nginx)分流,也可以被 VLESS fallbacks path 分流。

                                        提示

                                        Websocket 会识别 HTTP 请求的 X-Forwarded-For 头来覆写流量的源地址,优先级高于 PROXY protocol。

                                        WebSocketObject

                                        WebSocketObject 对应传输配置的 wsSettings 项。

                                        {
                                           "acceptProxyProtocol": false,
                                           "path": "/",
                                           "host": "xray.com",
                                        diff --git a/assets/websocket.html-CjNLVOTf.js b/assets/websocket.html-w8ndqht7.js
                                        similarity index 98%
                                        rename from assets/websocket.html-CjNLVOTf.js
                                        rename to assets/websocket.html-w8ndqht7.js
                                        index b3b02b4afa..c4e4006034 100644
                                        --- a/assets/websocket.html-CjNLVOTf.js
                                        +++ b/assets/websocket.html-w8ndqht7.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as s,o as l,c as d,a as t,b as o,d as e,w as i,e as n}from"./app-5SoadDYS.js";const u={},k=n(`

                                        WebSocket

                                        Использует стандартный WebSocket для передачи данных.

                                        Подключение WebSocket может быть проксировано другими HTTP-серверами (например, Nginx) и VLESS fallbacks path.

                                        Подсказка

                                        WebSocket распознает заголовок X-Forwarded-For в HTTP-запросе для перезаписи исходного адреса трафика, приоритет выше, чем у PROXY protocol.

                                        WebSocketObject

                                        WebSocketObject соответствует элементу wsSettings в конфигурации транспорта.

                                        {
                                        +import{_ as r,r as s,o as l,c as d,a as t,b as o,d as e,w as i,e as n}from"./app-Bw2NG-QJ.js";const u={},k=n(`

                                        WebSocket

                                        Использует стандартный WebSocket для передачи данных.

                                        Подключение WebSocket может быть проксировано другими HTTP-серверами (например, Nginx) и VLESS fallbacks path.

                                        Подсказка

                                        WebSocket распознает заголовок X-Forwarded-For в HTTP-запросе для перезаписи исходного адреса трафика, приоритет выше, чем у PROXY protocol.

                                        WebSocketObject

                                        WebSocketObject соответствует элементу wsSettings в конфигурации транспорта.

                                        {
                                           "acceptProxyProtocol": false,
                                           "path": "/",
                                           "host": "xray.com",
                                        diff --git a/assets/wireguard.html-BMXSEvNc.js b/assets/wireguard.html-CW0kotGE.js
                                        similarity index 99%
                                        rename from assets/wireguard.html-BMXSEvNc.js
                                        rename to assets/wireguard.html-CW0kotGE.js
                                        index e498b08679..0a6447b87d 100644
                                        --- a/assets/wireguard.html-BMXSEvNc.js
                                        +++ b/assets/wireguard.html-CW0kotGE.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as r,r as a,o as u,c as i,a as e,b as s,d as n,w as l,e as o}from"./app-5SoadDYS.js";const d={},v=o(`

                                        WireGuard

                                        Стандартная реализация протокола WireGuard.

                                        Предупреждение

                                        Протокол WireGuard не предназначен для обхода блокировок, и его использование может привести к блокировке сервера из-за наличия характерных признаков.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as r,r as a,o as u,c as i,a as e,b as s,d as n,w as l,e as o}from"./app-Bw2NG-QJ.js";const d={},v=o(`

                                        WireGuard

                                        Стандартная реализация протокола WireGuard.

                                        Предупреждение

                                        Протокол WireGuard не предназначен для обхода блокировок, и его использование может привести к блокировке сервера из-за наличия характерных признаков.

                                        OutboundConfigurationObject

                                        {
                                           "secretKey": "PRIVATE_KEY",
                                           "address": [
                                             // необязательно, по умолчанию ["10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"]
                                        diff --git a/assets/wireguard.html-CYsQqFv0.js b/assets/wireguard.html-DORXKtWu.js
                                        similarity index 99%
                                        rename from assets/wireguard.html-CYsQqFv0.js
                                        rename to assets/wireguard.html-DORXKtWu.js
                                        index 2d7e38fd49..c7af4f5abb 100644
                                        --- a/assets/wireguard.html-CYsQqFv0.js
                                        +++ b/assets/wireguard.html-DORXKtWu.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as u,r as a,o as r,c as i,a as e,b as s,d as n,w as l,e as o}from"./app-5SoadDYS.js";const d={},v=o(`

                                        Wireguard

                                        标准 Wireguard 协议实现。

                                        警告

                                        Wireguard 协议并非专门为翻墙而设计,若在最外层过墙,存在特征可能导致服务器被封锁

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as u,r as a,o as r,c as i,a as e,b as s,d as n,w as l,e as o}from"./app-Bw2NG-QJ.js";const d={},v=o(`

                                        Wireguard

                                        标准 Wireguard 协议实现。

                                        警告

                                        Wireguard 协议并非专门为翻墙而设计,若在最外层过墙,存在特征可能导致服务器被封锁

                                        OutboundConfigurationObject

                                        {
                                           "secretKey": "PRIVATE_KEY",
                                           "address": [
                                             // optional, default ["10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"]
                                        diff --git a/assets/wireguard.html-BUaJgccu.js b/assets/wireguard.html-WCdNFPZm.js
                                        similarity index 99%
                                        rename from assets/wireguard.html-BUaJgccu.js
                                        rename to assets/wireguard.html-WCdNFPZm.js
                                        index b98097c1c6..205e6b4d99 100644
                                        --- a/assets/wireguard.html-BUaJgccu.js
                                        +++ b/assets/wireguard.html-WCdNFPZm.js
                                        @@ -1,4 +1,4 @@
                                        -import{_ as c,r as s,o as l,c as u,a as n,b as t,d as e,w as p,e as o}from"./app-5SoadDYS.js";const d={},v=o(`

                                        Wireguard

                                        Wireguard is a standard implementation of the Wireguard protocol.

                                        Danger

                                        The Wireguard protocol is not specifically designed for circumvention purposes. If used as the outer layer for circumvention, its characteristics may lead to server blocking.

                                        OutboundConfigurationObject

                                        {
                                        +import{_ as c,r as s,o as l,c as u,a as n,b as t,d as e,w as p,e as o}from"./app-Bw2NG-QJ.js";const d={},v=o(`

                                        Wireguard

                                        Wireguard is a standard implementation of the Wireguard protocol.

                                        Danger

                                        The Wireguard protocol is not specifically designed for circumvention purposes. If used as the outer layer for circumvention, its characteristics may lead to server blocking.

                                        OutboundConfigurationObject

                                        {
                                           "secretKey": "PRIVATE_KEY",
                                           "address": [
                                             // optional, default ["10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"]
                                        diff --git a/assets/work.html-CkI961Qb.js b/assets/work.html-DMYsHmaw.js
                                        similarity index 98%
                                        rename from assets/work.html-CkI961Qb.js
                                        rename to assets/work.html-DMYsHmaw.js
                                        index 48b91659b5..09e8f985ce 100644
                                        --- a/assets/work.html-CkI961Qb.js
                                        +++ b/assets/work.html-DMYsHmaw.js
                                        @@ -1 +1 @@
                                        -import{_ as t,r as l,o as d,c as s,a as e,b as n,d as a}from"./app-5SoadDYS.js";const A={},E=n("h1",{id:"xray-的工作模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-的工作模式"},[n("span",null,"Xray 的工作模式")])],-1),i=n("h2",{id:"单服务器模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#单服务器模式"},[n("span",null,"单服务器模式")])],-1),u=n("p",null,"与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。",-1),c=n("p",null,"一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。",-1),_=n("h2",{id:"桥接模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#桥接模式"},[n("span",null,"桥接模式")])],-1),h=n("p",null,"如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。",-1),B=n("h2",{id:"工作原理",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#工作原理"},[n("span",null,"工作原理")])],-1),p=n("p",null,"在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。",-1),D=n("ul",null,[n("li",null,[a("需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。 "),n("ul",null,[n("li",null,[a("入站连接负责与客户端(如浏览器)通信: "),n("ul",null,[n("li",null,"入站连接通常可以配置用户认证,如 ID 和密码等;"),n("li",null,"入站连接收到数据之后,会交给分发器(Dispatcher)进行分发;")])]),n("li",null,"出站连接负责将数据发给服务器,如另一台主机上的 Xray。")])]),n("li",null,[a("当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。 "),n("ul",null,[n("li",null,"路由会在必要时查询 DNS 以获取更多信息来进行判断。")])])],-1);function m(b,y){const r=l("I18nTip"),o=l("Mermaid");return d(),s("div",null,[e(r),E,i,u,e(o,{id:"mermaid-11",code:"graph%20LR;%0AA(PC)%20-.-%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(Xray/VPS);%0AD%20--%3E%20C;%0AA%20--%3E%20E(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),c,_,h,e(o,{id:"mermaid-21",code:"graph%20LR;%0AA(PC)%20-.-%3E%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(%E5%A2%99%E5%86%85%20VPS);%0AD%20--%3E%20E(%E5%A2%99%E5%A4%96%20VPS);%0AE%20--%3E%20C;%0AD%20--%3E%20F(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),B,p,e(o,{id:"mermaid-28",code:"graph%20LR;%0AA1(inbound)%20--%3E%20D(Dispatcher%20/%20Router%20/%20DNS);%0AA2(inbound)%20--%3E%20D;%0AA3(inbound)%20--%3E%20D;%0AA4(inbound)%20--%3E%20D;%0AD%20--%3E%20B1(outbound);%0AD%20--%3E%20B2(outbound);%0AD%20--%3E%20B3(outbound);%0AD%20--%3E%20B4(outbound);%0A"}),D])}const X=t(A,[["render",m],["__file","work.html.vue"]]);export{X as default};
                                        +import{_ as t,r as l,o as d,c as s,a as e,b as n,d as a}from"./app-Bw2NG-QJ.js";const A={},E=n("h1",{id:"xray-的工作模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-的工作模式"},[n("span",null,"Xray 的工作模式")])],-1),i=n("h2",{id:"单服务器模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#单服务器模式"},[n("span",null,"单服务器模式")])],-1),u=n("p",null,"与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。",-1),c=n("p",null,"一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。",-1),_=n("h2",{id:"桥接模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#桥接模式"},[n("span",null,"桥接模式")])],-1),h=n("p",null,"如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。",-1),B=n("h2",{id:"工作原理",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#工作原理"},[n("span",null,"工作原理")])],-1),p=n("p",null,"在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。",-1),D=n("ul",null,[n("li",null,[a("需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。 "),n("ul",null,[n("li",null,[a("入站连接负责与客户端(如浏览器)通信: "),n("ul",null,[n("li",null,"入站连接通常可以配置用户认证,如 ID 和密码等;"),n("li",null,"入站连接收到数据之后,会交给分发器(Dispatcher)进行分发;")])]),n("li",null,"出站连接负责将数据发给服务器,如另一台主机上的 Xray。")])]),n("li",null,[a("当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。 "),n("ul",null,[n("li",null,"路由会在必要时查询 DNS 以获取更多信息来进行判断。")])])],-1);function m(b,y){const r=l("I18nTip"),o=l("Mermaid");return d(),s("div",null,[e(r),E,i,u,e(o,{id:"mermaid-11",code:"graph%20LR;%0AA(PC)%20-.-%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(Xray/VPS);%0AD%20--%3E%20C;%0AA%20--%3E%20E(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),c,_,h,e(o,{id:"mermaid-21",code:"graph%20LR;%0AA(PC)%20-.-%3E%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(%E5%A2%99%E5%86%85%20VPS);%0AD%20--%3E%20E(%E5%A2%99%E5%A4%96%20VPS);%0AE%20--%3E%20C;%0AD%20--%3E%20F(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),B,p,e(o,{id:"mermaid-28",code:"graph%20LR;%0AA1(inbound)%20--%3E%20D(Dispatcher%20/%20Router%20/%20DNS);%0AA2(inbound)%20--%3E%20D;%0AA3(inbound)%20--%3E%20D;%0AA4(inbound)%20--%3E%20D;%0AD%20--%3E%20B1(outbound);%0AD%20--%3E%20B2(outbound);%0AD%20--%3E%20B3(outbound);%0AD%20--%3E%20B4(outbound);%0A"}),D])}const X=t(A,[["render",m],["__file","work.html.vue"]]);export{X as default};
                                        diff --git a/assets/work.html-D1MRDeII.js b/assets/work.html-DkQ-NI9U.js
                                        similarity index 98%
                                        rename from assets/work.html-D1MRDeII.js
                                        rename to assets/work.html-DkQ-NI9U.js
                                        index 48b91659b5..09e8f985ce 100644
                                        --- a/assets/work.html-D1MRDeII.js
                                        +++ b/assets/work.html-DkQ-NI9U.js
                                        @@ -1 +1 @@
                                        -import{_ as t,r as l,o as d,c as s,a as e,b as n,d as a}from"./app-5SoadDYS.js";const A={},E=n("h1",{id:"xray-的工作模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-的工作模式"},[n("span",null,"Xray 的工作模式")])],-1),i=n("h2",{id:"单服务器模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#单服务器模式"},[n("span",null,"单服务器模式")])],-1),u=n("p",null,"与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。",-1),c=n("p",null,"一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。",-1),_=n("h2",{id:"桥接模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#桥接模式"},[n("span",null,"桥接模式")])],-1),h=n("p",null,"如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。",-1),B=n("h2",{id:"工作原理",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#工作原理"},[n("span",null,"工作原理")])],-1),p=n("p",null,"在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。",-1),D=n("ul",null,[n("li",null,[a("需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。 "),n("ul",null,[n("li",null,[a("入站连接负责与客户端(如浏览器)通信: "),n("ul",null,[n("li",null,"入站连接通常可以配置用户认证,如 ID 和密码等;"),n("li",null,"入站连接收到数据之后,会交给分发器(Dispatcher)进行分发;")])]),n("li",null,"出站连接负责将数据发给服务器,如另一台主机上的 Xray。")])]),n("li",null,[a("当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。 "),n("ul",null,[n("li",null,"路由会在必要时查询 DNS 以获取更多信息来进行判断。")])])],-1);function m(b,y){const r=l("I18nTip"),o=l("Mermaid");return d(),s("div",null,[e(r),E,i,u,e(o,{id:"mermaid-11",code:"graph%20LR;%0AA(PC)%20-.-%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(Xray/VPS);%0AD%20--%3E%20C;%0AA%20--%3E%20E(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),c,_,h,e(o,{id:"mermaid-21",code:"graph%20LR;%0AA(PC)%20-.-%3E%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(%E5%A2%99%E5%86%85%20VPS);%0AD%20--%3E%20E(%E5%A2%99%E5%A4%96%20VPS);%0AE%20--%3E%20C;%0AD%20--%3E%20F(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),B,p,e(o,{id:"mermaid-28",code:"graph%20LR;%0AA1(inbound)%20--%3E%20D(Dispatcher%20/%20Router%20/%20DNS);%0AA2(inbound)%20--%3E%20D;%0AA3(inbound)%20--%3E%20D;%0AA4(inbound)%20--%3E%20D;%0AD%20--%3E%20B1(outbound);%0AD%20--%3E%20B2(outbound);%0AD%20--%3E%20B3(outbound);%0AD%20--%3E%20B4(outbound);%0A"}),D])}const X=t(A,[["render",m],["__file","work.html.vue"]]);export{X as default};
                                        +import{_ as t,r as l,o as d,c as s,a as e,b as n,d as a}from"./app-Bw2NG-QJ.js";const A={},E=n("h1",{id:"xray-的工作模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#xray-的工作模式"},[n("span",null,"Xray 的工作模式")])],-1),i=n("h2",{id:"单服务器模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#单服务器模式"},[n("span",null,"单服务器模式")])],-1),u=n("p",null,"与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。",-1),c=n("p",null,"一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。",-1),_=n("h2",{id:"桥接模式",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#桥接模式"},[n("span",null,"桥接模式")])],-1),h=n("p",null,"如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。",-1),B=n("h2",{id:"工作原理",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#工作原理"},[n("span",null,"工作原理")])],-1),p=n("p",null,"在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。",-1),D=n("ul",null,[n("li",null,[a("需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。 "),n("ul",null,[n("li",null,[a("入站连接负责与客户端(如浏览器)通信: "),n("ul",null,[n("li",null,"入站连接通常可以配置用户认证,如 ID 和密码等;"),n("li",null,"入站连接收到数据之后,会交给分发器(Dispatcher)进行分发;")])]),n("li",null,"出站连接负责将数据发给服务器,如另一台主机上的 Xray。")])]),n("li",null,[a("当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。 "),n("ul",null,[n("li",null,"路由会在必要时查询 DNS 以获取更多信息来进行判断。")])])],-1);function m(b,y){const r=l("I18nTip"),o=l("Mermaid");return d(),s("div",null,[e(r),E,i,u,e(o,{id:"mermaid-11",code:"graph%20LR;%0AA(PC)%20-.-%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(Xray/VPS);%0AD%20--%3E%20C;%0AA%20--%3E%20E(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),c,_,h,e(o,{id:"mermaid-21",code:"graph%20LR;%0AA(PC)%20-.-%3E%20B(%E9%98%B2%E7%81%AB%E5%A2%99);%0AB%20-.-%3E%20C(%E5%A2%99%E5%A4%96%E7%BD%91%E7%AB%99);%0AA%20--%3E%20D(%E5%A2%99%E5%86%85%20VPS);%0AD%20--%3E%20E(%E5%A2%99%E5%A4%96%20VPS);%0AE%20--%3E%20C;%0AD%20--%3E%20F(%E5%A2%99%E5%86%85%E7%BD%91%E7%AB%99);%0A"}),B,p,e(o,{id:"mermaid-28",code:"graph%20LR;%0AA1(inbound)%20--%3E%20D(Dispatcher%20/%20Router%20/%20DNS);%0AA2(inbound)%20--%3E%20D;%0AA3(inbound)%20--%3E%20D;%0AA4(inbound)%20--%3E%20D;%0AD%20--%3E%20B1(outbound);%0AD%20--%3E%20B2(outbound);%0AD%20--%3E%20B3(outbound);%0AD%20--%3E%20B4(outbound);%0A"}),D])}const X=t(A,[["render",m],["__file","work.html.vue"]]);export{X as default};
                                        diff --git a/assets/work.html-nHfveOL9.js b/assets/work.html-hEheaKUD.js
                                        similarity index 98%
                                        rename from assets/work.html-nHfveOL9.js
                                        rename to assets/work.html-hEheaKUD.js
                                        index fb0d7a0402..577141ee6e 100644
                                        --- a/assets/work.html-nHfveOL9.js
                                        +++ b/assets/work.html-hEheaKUD.js
                                        @@ -1 +1 @@
                                        -import{_ as B,r as a,o as r,c as t,a as n,b as D,d as o}from"./app-5SoadDYS.js";const d={},s=D("h1",{id:"режимы-работы-xray",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#режимы-работы-xray"},[D("span",null,"Режимы работы Xray")])],-1),i=D("h2",{id:"режим-одного-сервера",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#режим-одного-сервера"},[D("span",null,"Режим одного сервера")])],-1),u=D("p",null,"Как и в случае с другими прокси-инструментами, вам понадобится сервер с настроенным Xray, а затем установить и настроить клиент Xray на вашем устройстве, после чего вы сможете свободно пользоваться Интернетом.",-1),c=D("p",null,"Один сервер Xray может одновременно обслуживать несколько устройств, использующих разные протоколы проксирования. При правильной настройке Xray может распознавать и различать трафик, который нужно проксировать, и трафик, который можно отправлять напрямую, без проксирования.",-1),_=D("h2",{id:"режим-моста",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#режим-моста"},[D("span",null,"Режим моста")])],-1),h=D("p",null,"Если вы не хотите настраивать маршрутизацию на каждом устройстве, вы можете настроить промежуточный сервер, который будет принимать весь трафик от клиентов и перенаправлять его в зависимости от настроек.",-1),A=D("h2",{id:"принцип-работы",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#принцип-работы"},[D("span",null,"Принцип работы")])],-1),p=D("p",null,"Перед настройкой Xray давайте рассмотрим, как он работает. Ниже представлена схема внутреннего устройства одного процесса Xray. Несколько процессов Xray работают независимо друг от друга.",-1),E=D("ul",null,[D("li",null,[o("Для нормальной работы необходимо настроить как минимум одно входящее соединение (Inbound) и одно исходящее соединение (Outbound). "),D("ul",null,[D("li",null,[o("Входящее соединение отвечает за связь с клиентом (например, браузером): "),D("ul",null,[D("li",null,"Входящее соединение обычно можно настроить с аутентификацией пользователя, например, с использованием ID и пароля;"),D("li",null,"После получения данных входящее соединение передает их диспетчеру (Dispatcher) для распределения.")])]),D("li",null,"Исходящее соединение отвечает за отправку данных на сервер, например, на другой Xray, работающий на другом хосте.")])]),D("li",null,[o("При наличии нескольких исходящих соединений можно настроить маршрутизацию (Routing) для указания, какое исходящее соединение должно использоваться для определенного типа трафика. "),D("ul",null,[D("li",null,"При необходимости маршрутизатор обращается к DNS для получения дополнительной информации для принятия решения.")])])],-1);function m(b,y){const l=a("I18nTip"),e=a("Mermaid");return r(),t("div",null,[n(l),s,i,u,n(e,{id:"mermaid-11",code:"graph%20LR;%0AA(%D0%9F%D0%9A)%20-.-%20B(%D0%91%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80);%0AB%20-.-%3E%20C(%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0AA%20--%3E%20D(Xray/VPS);%0AD%20--%3E%20C;%0AA%20--%3E%20E(%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0A"}),c,_,h,n(e,{id:"mermaid-21",code:"graph%20LR;%0AA(%D0%9F%D0%9A)%20-.-%3E%20B(%D0%91%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80);%0AB%20-.-%3E%20C(%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0AA%20--%3E%20D(%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9%20VPS);%0AD%20--%3E%20E(%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B9%20VPS);%0AE%20--%3E%20C;%0AD%20--%3E%20F(%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0A"}),A,p,n(e,{id:"mermaid-28",code:"graph%20LR;%0AA1(inbound)%20--%3E%20D(Dispatcher%20/%20Router%20/%20DNS);%0AA2(inbound)%20--%3E%20D;%0AA3(inbound)%20--%3E%20D;%0AA4(inbound)%20--%3E%20D;%0AD%20--%3E%20B1(outbound);%0AD%20--%3E%20B2(outbound);%0AD%20--%3E%20B3(outbound);%0AD%20--%3E%20B4(outbound);%0A"}),E])}const x=B(d,[["render",m],["__file","work.html.vue"]]);export{x as default};
                                        +import{_ as B,r as a,o as r,c as t,a as n,b as D,d as o}from"./app-Bw2NG-QJ.js";const d={},s=D("h1",{id:"режимы-работы-xray",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#режимы-работы-xray"},[D("span",null,"Режимы работы Xray")])],-1),i=D("h2",{id:"режим-одного-сервера",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#режим-одного-сервера"},[D("span",null,"Режим одного сервера")])],-1),u=D("p",null,"Как и в случае с другими прокси-инструментами, вам понадобится сервер с настроенным Xray, а затем установить и настроить клиент Xray на вашем устройстве, после чего вы сможете свободно пользоваться Интернетом.",-1),c=D("p",null,"Один сервер Xray может одновременно обслуживать несколько устройств, использующих разные протоколы проксирования. При правильной настройке Xray может распознавать и различать трафик, который нужно проксировать, и трафик, который можно отправлять напрямую, без проксирования.",-1),_=D("h2",{id:"режим-моста",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#режим-моста"},[D("span",null,"Режим моста")])],-1),h=D("p",null,"Если вы не хотите настраивать маршрутизацию на каждом устройстве, вы можете настроить промежуточный сервер, который будет принимать весь трафик от клиентов и перенаправлять его в зависимости от настроек.",-1),A=D("h2",{id:"принцип-работы",tabindex:"-1"},[D("a",{class:"header-anchor",href:"#принцип-работы"},[D("span",null,"Принцип работы")])],-1),p=D("p",null,"Перед настройкой Xray давайте рассмотрим, как он работает. Ниже представлена схема внутреннего устройства одного процесса Xray. Несколько процессов Xray работают независимо друг от друга.",-1),E=D("ul",null,[D("li",null,[o("Для нормальной работы необходимо настроить как минимум одно входящее соединение (Inbound) и одно исходящее соединение (Outbound). "),D("ul",null,[D("li",null,[o("Входящее соединение отвечает за связь с клиентом (например, браузером): "),D("ul",null,[D("li",null,"Входящее соединение обычно можно настроить с аутентификацией пользователя, например, с использованием ID и пароля;"),D("li",null,"После получения данных входящее соединение передает их диспетчеру (Dispatcher) для распределения.")])]),D("li",null,"Исходящее соединение отвечает за отправку данных на сервер, например, на другой Xray, работающий на другом хосте.")])]),D("li",null,[o("При наличии нескольких исходящих соединений можно настроить маршрутизацию (Routing) для указания, какое исходящее соединение должно использоваться для определенного типа трафика. "),D("ul",null,[D("li",null,"При необходимости маршрутизатор обращается к DNS для получения дополнительной информации для принятия решения.")])])],-1);function m(b,y){const l=a("I18nTip"),e=a("Mermaid");return r(),t("div",null,[n(l),s,i,u,n(e,{id:"mermaid-11",code:"graph%20LR;%0AA(%D0%9F%D0%9A)%20-.-%20B(%D0%91%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80);%0AB%20-.-%3E%20C(%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0AA%20--%3E%20D(Xray/VPS);%0AD%20--%3E%20C;%0AA%20--%3E%20E(%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0A"}),c,_,h,n(e,{id:"mermaid-21",code:"graph%20LR;%0AA(%D0%9F%D0%9A)%20-.-%3E%20B(%D0%91%D1%80%D0%B0%D0%BD%D0%B4%D0%BC%D0%B0%D1%83%D1%8D%D1%80);%0AB%20-.-%3E%20C(%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0AA%20--%3E%20D(%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9%20VPS);%0AD%20--%3E%20E(%D0%92%D0%BD%D0%B5%D1%88%D0%BD%D0%B8%D0%B9%20VPS);%0AE%20--%3E%20C;%0AD%20--%3E%20F(%D0%92%D0%BD%D1%83%D1%82%D1%80%D0%B5%D0%BD%D0%BD%D0%B8%D0%B9%20%D1%81%D0%B0%D0%B9%D1%82);%0A"}),A,p,n(e,{id:"mermaid-28",code:"graph%20LR;%0AA1(inbound)%20--%3E%20D(Dispatcher%20/%20Router%20/%20DNS);%0AA2(inbound)%20--%3E%20D;%0AA3(inbound)%20--%3E%20D;%0AA4(inbound)%20--%3E%20D;%0AD%20--%3E%20B1(outbound);%0AD%20--%3E%20B2(outbound);%0AD%20--%3E%20B3(outbound);%0AD%20--%3E%20B4(outbound);%0A"}),E])}const x=B(d,[["render",m],["__file","work.html.vue"]]);export{x as default};
                                        diff --git a/assets/xtls.html-CNzfvmap.js b/assets/xtls.html-0Synm2Bl.js
                                        similarity index 83%
                                        rename from assets/xtls.html-CNzfvmap.js
                                        rename to assets/xtls.html-0Synm2Bl.js
                                        index 47c23f72e4..1fe8bcaa36 100644
                                        --- a/assets/xtls.html-CNzfvmap.js
                                        +++ b/assets/xtls.html-0Synm2Bl.js
                                        @@ -1 +1 @@
                                        -import{_ as a,r as t,o as c,c as l,a as n,b as e}from"./app-5SoadDYS.js";const r={},_=e("h1",{id:"глубокое-погружение-в-xtls",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#глубокое-погружение-в-xtls"},[e("span",null,"Глубокое погружение в XTLS")])],-1),d=e("blockquote",null,[e("p",null,[e("strong",null,"XTLS - это оригинальная технология Xray, которая является ключевым фактором высокой производительности Xray.")])],-1);function i(p,u){const o=t("I18nTip"),s=t("Badge");return c(),l("div",null,[n(o),_,d,n(s,{text:"WIP",type:"warning"})])}const m=a(r,[["render",i],["__file","xtls.html.vue"]]);export{m as default};
                                        +import{_ as a,r as t,o as c,c as l,a as n,b as e}from"./app-Bw2NG-QJ.js";const r={},_=e("h1",{id:"глубокое-погружение-в-xtls",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#глубокое-погружение-в-xtls"},[e("span",null,"Глубокое погружение в XTLS")])],-1),d=e("blockquote",null,[e("p",null,[e("strong",null,"XTLS - это оригинальная технология Xray, которая является ключевым фактором высокой производительности Xray.")])],-1);function i(p,u){const o=t("I18nTip"),s=t("Badge");return c(),l("div",null,[n(o),_,d,n(s,{text:"WIP",type:"warning"})])}const m=a(r,[["render",i],["__file","xtls.html.vue"]]);export{m as default};
                                        diff --git a/assets/xtls.html-BWSKIYgJ.js b/assets/xtls.html-BljC82lz.js
                                        similarity index 79%
                                        rename from assets/xtls.html-BWSKIYgJ.js
                                        rename to assets/xtls.html-BljC82lz.js
                                        index 97dddc54ad..f6fe377d38 100644
                                        --- a/assets/xtls.html-BWSKIYgJ.js
                                        +++ b/assets/xtls.html-BljC82lz.js
                                        @@ -1 +1 @@
                                        -import{_ as t,r as o,o as l,c as r,a as n,b as e}from"./app-5SoadDYS.js";const c={},i=e("h1",{id:"deep-analysis-of-xtls",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#deep-analysis-of-xtls"},[e("span",null,"Deep analysis of XTLS")])],-1),_=e("blockquote",null,[e("p",null,[e("strong",null,`"XTLS is the original black technology of Xray, and also the core driving force that makes Xray's performance far superior."`)])],-1);function d(p,f){const a=o("I18nTip"),s=o("Badge");return l(),r("div",null,[n(a),i,_,n(s,{text:"WIP",type:"warning"})])}const m=t(c,[["render",d],["__file","xtls.html.vue"]]);export{m as default};
                                        +import{_ as t,r as o,o as l,c as r,a as n,b as e}from"./app-Bw2NG-QJ.js";const c={},i=e("h1",{id:"deep-analysis-of-xtls",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#deep-analysis-of-xtls"},[e("span",null,"Deep analysis of XTLS")])],-1),_=e("blockquote",null,[e("p",null,[e("strong",null,`"XTLS is the original black technology of Xray, and also the core driving force that makes Xray's performance far superior."`)])],-1);function d(p,f){const a=o("I18nTip"),s=o("Badge");return l(),r("div",null,[n(a),i,_,n(s,{text:"WIP",type:"warning"})])}const m=t(c,[["render",d],["__file","xtls.html.vue"]]);export{m as default};
                                        diff --git a/assets/xtls.html-D7puBcBG.js b/assets/xtls.html-CDQXBW21.js
                                        similarity index 77%
                                        rename from assets/xtls.html-D7puBcBG.js
                                        rename to assets/xtls.html-CDQXBW21.js
                                        index 91fb04b8ca..f1209534c8 100644
                                        --- a/assets/xtls.html-D7puBcBG.js
                                        +++ b/assets/xtls.html-CDQXBW21.js
                                        @@ -1 +1 @@
                                        -import{_ as a,r as t,o as c,c as l,a as n,b as e}from"./app-5SoadDYS.js";const r={},_=e("h1",{id:"xtls-深度剖析",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#xtls-深度剖析"},[e("span",null,"XTLS 深度剖析")])],-1),d=e("blockquote",null,[e("p",null,[e("strong",null,"XTLS 是 Xray 的原创黑科技, 也是使 Xray 性能一骑绝尘的核心动力")])],-1);function i(p,u){const o=t("I18nTip"),s=t("Badge");return c(),l("div",null,[n(o),_,d,n(s,{text:"WIP",type:"warning"})])}const m=a(r,[["render",i],["__file","xtls.html.vue"]]);export{m as default};
                                        +import{_ as a,r as t,o as c,c as l,a as n,b as e}from"./app-Bw2NG-QJ.js";const r={},_=e("h1",{id:"xtls-深度剖析",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#xtls-深度剖析"},[e("span",null,"XTLS 深度剖析")])],-1),d=e("blockquote",null,[e("p",null,[e("strong",null,"XTLS 是 Xray 的原创黑科技, 也是使 Xray 性能一骑绝尘的核心动力")])],-1);function i(p,u){const o=t("I18nTip"),s=t("Badge");return c(),l("div",null,[n(o),_,d,n(s,{text:"WIP",type:"warning"})])}const m=a(r,[["render",i],["__file","xtls.html.vue"]]);export{m as default};
                                        diff --git a/assets/xychartDiagram-f11f50a6-BfE2Gore.js b/assets/xychartDiagram-f11f50a6-D1hL1lgg.js
                                        similarity index 99%
                                        rename from assets/xychartDiagram-f11f50a6-BfE2Gore.js
                                        rename to assets/xychartDiagram-f11f50a6-D1hL1lgg.js
                                        index da6efa1c5a..ad521fcee8 100644
                                        --- a/assets/xychartDiagram-f11f50a6-BfE2Gore.js
                                        +++ b/assets/xychartDiagram-f11f50a6-D1hL1lgg.js
                                        @@ -1,4 +1,4 @@
                                        -import{a_ as zt,a$ as ot,aM as wt,aL as Ft,s as Nt,g as Xt,x as Yt,y as St,a as Ht,b as $t,A as Ut,l as _t,aJ as qt,i as jt,d as Gt}from"./mermaid.core-CArNAncI.js";import{a as Qt}from"./createText-ca0c5216-X7RVUogw.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-DFdMY4Xo.js";import{l as pt}from"./line-BIqtvXUi.js";import"./app-5SoadDYS.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";function Zt(e,t,i){e=+e,t=+t,i=(n=arguments.length)<2?(t=e,e=0,1):n<3?1:+i;for(var s=-1,n=Math.max(0,Math.ceil((t-e)/i))|0,o=new Array(n);++s"u"&&(k.yylloc={});var tt=k.yylloc;a.push(tt);var Wt=k.options&&k.options.ranges;typeof B.yy.parseError=="function"?this.parseError=B.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ot(){var I;return I=g.pop()||k.lex()||xt,typeof I!="number"&&(I instanceof Array&&(g=I,I=g.pop()),I=l.symbols_[I]||I),I}for(var D,W,v,it,O={},q,M,dt,j;;){if(W=u[u.length-1],this.defaultActions[W]?v=this.defaultActions[W]:((D===null||typeof D>"u")&&(D=Ot()),v=F[W]&&F[W][D]),typeof v>"u"||!v.length||!v[0]){var et="";j=[];for(q in F[W])this.terminals_[q]&&q>Vt&&j.push("'"+this.terminals_[q]+"'");k.showPosition?et="Parse error on line "+(U+1)+`:
                                        +import{a_ as zt,a$ as ot,aM as wt,aL as Ft,s as Nt,g as Xt,x as Yt,y as St,a as Ht,b as $t,A as Ut,l as _t,aJ as qt,i as jt,d as Gt}from"./mermaid.core-Bq0kX0MS.js";import{a as Qt}from"./createText-ca0c5216-xyt9uAlz.js";import{i as Kt}from"./init-Gi6I4Gst.js";import{o as Jt}from"./ordinal-Cboi1Yqb.js";import{l as ft}from"./linear-CopLvHML.js";import{l as pt}from"./line-DY_oMjHu.js";import"./app-Bw2NG-QJ.js";import"./array-BKyUJesY.js";import"./path-CbwjOpE9.js";function Zt(e,t,i){e=+e,t=+t,i=(n=arguments.length)<2?(t=e,e=0,1):n<3?1:+i;for(var s=-1,n=Math.max(0,Math.ceil((t-e)/i))|0,o=new Array(n);++s"u"&&(k.yylloc={});var tt=k.yylloc;a.push(tt);var Wt=k.options&&k.options.ranges;typeof B.yy.parseError=="function"?this.parseError=B.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ot(){var I;return I=g.pop()||k.lex()||xt,typeof I!="number"&&(I instanceof Array&&(g=I,I=g.pop()),I=l.symbols_[I]||I),I}for(var D,W,v,it,O={},q,M,dt,j;;){if(W=u[u.length-1],this.defaultActions[W]?v=this.defaultActions[W]:((D===null||typeof D>"u")&&(D=Ot()),v=F[W]&&F[W][D]),typeof v>"u"||!v.length||!v[0]){var et="";j=[];for(q in F[W])this.terminals_[q]&&q>Vt&&j.push("'"+this.terminals_[q]+"'");k.showPosition?et="Parse error on line "+(U+1)+`:
                                         `+k.showPosition()+`
                                         Expecting `+j.join(", ")+", got '"+(this.terminals_[D]||D)+"'":et="Parse error on line "+(U+1)+": Unexpected "+(D==xt?"end of input":"'"+(this.terminals_[D]||D)+"'"),this.parseError(et,{text:k.match,token:this.terminals_[D]||D,line:k.yylineno,loc:tt,expected:j})}if(v[0]instanceof Array&&v.length>1)throw new Error("Parse Error: multiple actions possible at state: "+W+", token: "+D);switch(v[0]){case 1:u.push(D),b.push(k.yytext),a.push(k.yylloc),u.push(v[1]),D=null,gt=k.yyleng,x=k.yytext,U=k.yylineno,tt=k.yylloc;break;case 2:if(M=this.productions_[v[1]][1],O.$=b[b.length-M],O._$={first_line:a[a.length-(M||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(M||1)].first_column,last_column:a[a.length-1].last_column},Wt&&(O._$.range=[a[a.length-(M||1)].range[0],a[a.length-1].range[1]]),it=this.performAction.apply(O,[x,gt,U,B.yy,v[1],b,a].concat(Bt)),typeof it<"u")return it;M&&(u=u.slice(0,-1*M*2),b=b.slice(0,-1*M),a=a.slice(0,-1*M)),u.push(this.productions_[v[1]][0]),b.push(O.$),a.push(O._$),dt=F[u[u.length-2]][u[u.length-1]],u.push(dt);break;case 3:return!0}}return!0}},It=function(){var V={EOF:1,parseError:function(l,u){if(this.yy.parser)this.yy.parser.parseError(l,u);else throw new Error(l)},setInput:function(r,l){return this.yy=l||this.yy||{},this._input=r,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var r=this._input[0];this.yytext+=r,this.yyleng++,this.offset++,this.match+=r,this.matched+=r;var l=r.match(/(?:\r\n?|\n).*/g);return l?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),r},unput:function(r){var l=r.length,u=r.split(/(?:\r\n?|\n)/g);this._input=r+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-l),this.offset-=l;var g=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),u.length-1&&(this.yylineno-=u.length-1);var b=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:u?(u.length===g.length?this.yylloc.first_column:0)+g[g.length-u.length].length-u[0].length:this.yylloc.first_column-l},this.options.ranges&&(this.yylloc.range=[b[0],b[0]+this.yyleng-l]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
                                         `+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(r){this.unput(this.match.slice(r))},pastInput:function(){var r=this.matched.substr(0,this.matched.length-this.match.length);return(r.length>20?"...":"")+r.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var r=this.match;return r.length<20&&(r+=this._input.substr(0,20-r.length)),(r.substr(0,20)+(r.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var r=this.pastInput(),l=new Array(r.length+1).join("-");return r+this.upcomingInput()+`
                                        diff --git a/config/api.html b/config/api.html
                                        index ed6ac1aa3a..60ba856c5a 100644
                                        --- a/config/api.html
                                        +++ b/config/api.html
                                        @@ -24,8 +24,8 @@
                                             
                                             API 接口 | Project X
                                             
                                        -    
                                        -    
                                        +    
                                        +    
                                           
                                           
                                             

                                        API 接口

                                        API 接口配置提供了一些基于 gRPCopen in new tag的 API 接口供远程调用。

                                        可以通过 api 配置模块开启接口。当 api 配置开启时,Xray 会自建一个和 tag 同名的出站代理,须手动将所有的 API 入站连接通过 路由规则配置 指向这一出站代理。请参考本节中的 相关配置

                                        v1.8.12open in new tag 起支持简易配置模式,只配置 ApiObject 即可,不需要配置 inbounds 和 routing。但是使用简易配置时,流量统计功能不统计 API 入站连接的流量。

                                        注意

                                        大多数用户并不会用到此 API,新手可以直接忽略这一项。

                                        ApiObject

                                        ApiObject 对应配置文件的 api 项。

                                        {
                                        @@ -70,6 +70,6 @@
                                         xray.app.proxyman.command.HandlerService
                                         xray.app.stats.command.StatsService
                                         

                                        API 调用示例

                                        Xray-API-documentsopen in new tag @crossfw

                                        - + diff --git a/config/dns.html b/config/dns.html index 1a69de47e7..501cb0d4c8 100644 --- a/config/dns.html +++ b/config/dns.html @@ -24,8 +24,8 @@ 内置 DNS 服务器 | Project X - - + +

                                        内置 DNS 服务器

                                        DNS 服务器

                                        Xray 内置的 DNS 模块,主要有两大用途:

                                        • 在路由阶段, 解析域名为 IP, 并且根据域名解析得到的 IP 进行规则匹配以分流. 是否解析域名及分流和路由配置模块中 domainStrategy 的值有关, 只有在设置以下两种值时,才会使用内置 DNS 服务器进行 DNS 查询:

                                          • "IPIfNonMatch", 请求一个域名时,进行路由里面的 domain 进行匹配,若无法匹配到结果,则对这个域名使用内置 DNS 服务器进行 DNS 查询,并且使用查询返回的 IP 地址再重新进行 IP 路由匹配。
                                          • "IPOnDemand", 当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配。
                                        • 解析目标地址进行连接。

                                          • 如 在 freedom 出站中,将 domainStrategy 设置为 UseIP, 由此出站发出的请求, 会先将域名通过内置服务器解析成 IP, 然后进行连接。
                                          • 如 在 sockopt 中,将 domainStrategy 设置为 UseIP, 此出站发起的系统连接,将先由内置服务器解析为 IP, 然后进行连接。

                                        TIP 1

                                        内置 DNS 服务器所发出的 DNS 查询请求,会自动根据路由配置进行转发。

                                        TIP 2

                                        只支持最基本的 IP 查询(A 和 AAAA 记录),CNAME 记录将会重复查询直至返回 A/AAAA 记录为止。其他查询不会进入内置 DNS 服务器。

                                        DNS 处理流程

                                        若当前要查询的域名:

                                        • 命中了 hosts 中的「域名 - IP」、「域名 - IP 数组」映射,则将该 IP 或 IP 数组作为 DNS 解析结果返回。
                                        • 命中了 hosts 中的「域名 - 域名」映射,则该映射的值(另一个域名)将作为当前要查询的域名,进入 DNS 处理流程,直到解析出 IP 后返回,或返回空解析。
                                        • 没有命中 hosts,但命中了某(几)个 DNS 服务器中的 domains 域名列表,则按照命中的规则的优先级,依次使用该规则对应的 DNS 服务器进行查询。若命中的 DNS 服务器查询失败或 expectIPs 不匹配,则使用下一个命中的 DNS 服务器进行查询;否则返回解析得到的 IP。若所有命中的 DNS 服务器均查询失败或 expectIPs 不匹配,此时 DNS 组件:
                                          • 默认会进行 「DNS 回退(fallback)查询」:使用「上一轮失败查询中未被使用的、且 skipFallback 为默认值 false 的 DNS 服务器」依次查询。若查询失败或 expectIPs 不匹配,返回空解析;否则返回解析得到的 IP。
                                          • disableFallback 设置为 true,则不会进行「DNS 回退(fallback)查询」。
                                        • 既没有命中 hosts,又没有命中 DNS 服务器中的 domains 域名列表,则:
                                          • 默认使用「skipFallback 为默认值 false 的 DNS 服务器」依次查询。若第一个被选中的 DNS 服务器查询失败或 expectIPs 不匹配,则使用下一个被选中的 DNS 服务器进行查询;否则返回解析得到的 IP。若所有被选中的 DNS 服务器均查询失败或 expectIPs 不匹配,返回空解析。
                                          • 若「skipFallback 为默认值 false 的 DNS 服务器」数量为 0 或 disableFallback 设置为 true,则使用 DNS 配置中的第一个 DNS 服务器进行查询。查询失败或 expectIPs 不匹配,返回空解析;否则返回解析得到的 IP。

                                        DnsObject

                                        DnsObject 对应配置文件的 dns 项。

                                        {
                                        @@ -116,6 +116,6 @@
                                           "clientIP": "1.2.3.4"
                                         }
                                         

                                        address: address

                                        一个 DNS 服务器列表,支持的类型有两种:DNS 地址(字符串形式)和 ServerObject 。

                                        当值为 "localhost" 时,表示使用本机预设的 DNS 配置。

                                        当它的值是一个 DNS "IP" 地址时,如 "8.8.8.8",Xray 会使用此地址的指定 UDP 端口进行 DNS 查询。该查询遵循路由规则。默认使用 53 端口。

                                        当值是 "tcp://host" 的形式,如 "tcp://8.8.8.8",Xray 会使用 DNS over TCP 进行查询。该查询遵循路由规则。默认使用 53 端口。

                                        当值是 "tcp+local://host" 的形式,如 "tcp+local://8.8.8.8",Xray 会使用 TCP 本地模式 (TCPL) 进行查询。即 DNS 请求不会经过路由组件,直接通过 Freedom outbound 对外请求,以降低耗时。不指定端口时,默认使用 53 端口。

                                        当值是 "https://host:port/dns-query" 的形式,如 "https://dns.google/dns-query",Xray 会使用 DNS over HTTPS (RFC8484, 简称 DOH) 进行查询。有些服务商拥有 IP 别名的证书,可以直接写 IP 形式,比如 https://1.1.1.1/dns-query。也可使用非标准端口和路径,如 "https://a.b.c.d:8443/my-dns-query"

                                        当值是 "https+local://host:port/dns-query" 的形式,如 "https+local://dns.google/dns-query",Xray 会使用 DOH 本地模式 (DOHL) 进行查询,即 DOH 请求不会经过路由组件,直接通过 Freedom outbound 对外请求,以降低耗时。一般适合在服务端使用。也可使用非标端口和路径。

                                        当值是 "quic+local://host:port" 的形式,如 "quic+local://dns.adguard.com",Xray 会使用 DOQ 本地模式 (DOQL) 进行查询,即 DNS 请求不会经过路由组件,直接通过 Freedom outbound 对外请求。该方式需要 DNS 服务器支持 DNS over QUIC。默认使用 853 端口进行查询,可以使用非标端口。

                                        当值是 fakedns 时,将使用 FakeDNS 功能进行查询。

                                        port: number

                                        DNS 服务器端口,如 53。此项缺省时默认为 53。当使用 DOH、DOHL、DOQL 模式时该项无效,非标端口应在 URL 中指定。

                                        domains: [string]

                                        一个域名列表,此列表包含的域名,将优先使用此服务器进行查询。域名格式和 路由配置 中相同。

                                        expectIPs:[string]

                                        一个 IP 范围列表,格式和 路由配置 中相同。

                                        当配置此项时,Xray DNS 会对返回的 IP 的进行校验,只返回包含 expectIPs 列表中的地址。

                                        如果未配置此项,会原样返回 IP 地址。

                                        skipFallback: true | false

                                        true,在进行 DNS fallback 查询时将跳过此服务器, 默认为 false,即不跳过。

                                        - + diff --git a/config/fakedns.html b/config/fakedns.html index 79b74a2789..8309d3f8ba 100644 --- a/config/fakedns.html +++ b/config/fakedns.html @@ -24,8 +24,8 @@ FakeDNS | Project X - - + +

                                        FakeDNS

                                        FakeDNS 通过伪造 DNS 以获取目标域名,能够降低 DNS 查询时的延迟、配合透明代理获取目标域名。

                                        注意

                                        FakeDNS 有可能会污染本地 DNS,导致 Xray 关闭后“无法访问网络”。

                                        FakeDNSObject

                                        FakeDNSObject 对应配置文件的 fakedns 项。

                                        {
                                        @@ -130,6 +130,6 @@
                                           ]
                                         }
                                         
                                        - + diff --git a/config/features/browser_dialer.html b/config/features/browser_dialer.html index 15262b4dbf..ab844950ba 100644 --- a/config/features/browser_dialer.html +++ b/config/features/browser_dialer.html @@ -24,11 +24,11 @@ Browser Dialer | Project X - - + +

                                        Browser Dialer

                                        背景

                                        通过 uTLS,Xray 可以模拟主流浏览器的 TLS 握手指纹(具体参见 TLS 中 fingerprint 选项)。但是仍然不能保证在任意时刻 uTLS 模拟浏览器行为完全一致。

                                        对此 浏览器转发(browser dialer)open in new tag应运而生。用户在自己的浏览器中打开一个页面至 localhost:8080,这个页面利用原生 JS 充当 Xray 的网络栈,与代理服务端建立 TLS,HTTP 连接。

                                        这个方法简洁的实现了真实的浏览器的 TLS 指纹、行为特征。最大程度抗检测与抗封锁。

                                        不过目前的浏览器转发有以下缺点:

                                        • 用户需要手动开浏览器
                                        • 浏览器发出的连接必须直连 使用 tun 的用户需要特别注意容易形成死循环
                                        • 浏览器只能发出 HTTP 连接 所以目前仅支持 WebSocketSplitHTTP 传输方式
                                        • 当浏览器从 localhost:8080 页面连接至代理服务端,需要考虑 CORSopen in new tag
                                        • 因为中间经过 JS 处理数据,会有一些性能损耗
                                        • 不能使用自定义 SNI 或者 Host,也就是说 SNI == host == address。自定义 HTTP 头以及其它 tlsSettings 项会被忽略

                                        配置方法

                                        1. 准备一份 WebSocket 或 SplitHTTP 配置,注意 address 必须填域名,若需要指定 IP,请配置 DNS 或系统 hosts
                                        2. 使用环境变量启动 Xray XRAY_BROWSER_DIALER=127.0.0.1:8080。Windows 上命令为 set XRAY_BROWSER_DIALER=127.0.0.1:8080 Linux 上命令为 XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json
                                        3. 确保浏览器直连(或者在路由中将服务端地址直接由 freedom 发出),打开页面 localhost:8080,还可以 F12ConsoleNetwork
                                        4. 浏览器会限制发出的连接数,所以建议开启 Mux.Cool

                                        内部通信机制

                                        • Xray 监听地址端口 http://127.0.0.1:8080,作为 HTTP 服务,浏览器访问地址,加载网页中的 JS。
                                        • JS 主动向 http://127.0.0.1:8080 建立 WebSocket 连接,成功后,Xray 将连接发给 channel。
                                        • 需要建立连接时,Xray 从 channel 接收一个可用的连接,并发送目标 URL 和可选的 early data。
                                        • JS 成功连接到目标后告知 Xray,并继续用这个 conn 全双工双向转发数据,连接关闭行为同步。
                                        • 连接使用后就会被关闭,但 JS 会确保始终有新空闲连接可用。

                                        WebSocket

                                        v1.4.1+

                                        根据浏览器的需求,对 early data 机制进行了如下调整:

                                        • 服务端响应头会带有请求的 Sec-WebSocket-Protocol,这也初步混淆了 WSS 握手响应的长度特征。
                                        • 用于浏览器的 early data 编码是 base64.RawURLEncoding 而不是 StdEncoding,服务端做了兼容。
                                        • 此外,由于 Xray-core#375open in new tag 推荐 ?ed=2048,这个 PR 顺便将服务端一处 MaxHeaderBytes 扩至了 4096。 (虽然好像不改也没问题)

                                        SplitHTTP

                                        v1.8.19+

                                        SplitHTTP 本身支持 QUIC,如果想使用浏览器自己的 QUIC 网络栈,Chrome 可以在 chrome://flags 中设定。其它浏览器也有相关选项。

                                        原理上说 tlsSettings 项会被忽略,使用哪个 HTTP 版本将完全由浏览器决定。

                                        - + diff --git a/config/features/env.html b/config/features/env.html index d4dcfb5671..be6136b926 100644 --- a/config/features/env.html +++ b/config/features/env.html @@ -24,14 +24,14 @@ 环境变量 | Project X - - + +

                                        环境变量

                                        Xray 提供以下环境变量以供修改 Xray 的一些底层配置。

                                        资源文件路径

                                        • 名称:xray.location.assetXRAY_LOCATION_ASSET
                                        • 默认值:特定 FHSopen in new tag 目录或 Xray 文件同路径。

                                        这个环境变量指定了一个文件夹位置,这个文件夹应当包含 geoip.dat 和 geosite.dat 文件。 若无指定变量值,程序将会按以下顺序寻找资源文件:

                                        ./
                                         /usr/local/share/xray
                                         /usr/share/xray
                                         

                                        配置文件位置

                                        • 名称:xray.location.configXRAY_LOCATION_CONFIG
                                        • 默认值:和 Xray 文件同路径。

                                        这个环境变量指定了一个文件夹位置,这个文件夹应当包含 config.json 文件。

                                        多配置目录

                                        • 名称:xray.location.confdirXRAY_LOCATION_CONFDIR
                                        • 默认值:""

                                        这个目录内的 .json 文件会按文件名顺序读取,作为多配置选项。

                                        - + diff --git a/config/features/fallback.html b/config/features/fallback.html index 249fe5c39b..209487ba67 100644 --- a/config/features/fallback.html +++ b/config/features/fallback.html @@ -24,8 +24,8 @@ Fallback 回落 | Project X - - + +

                                        Fallback 回落

                                        Fallback 是 Xray 的最强大功能之一, 可有效防止主动探测, 自由配置常用端口多服务共享

                                        fallback 为 Xray 提供了高强度的防主动探测性, 并且具有独创的首包回落机制.

                                        fallback 也可以将不同类型的流量根据 path 进行分流, 从而实现一个端口, 多种服务共享.

                                        目前您可以在使用 VLESS 或者 trojan 协议时, 通过配置 fallbacks 来使用回落这一特性, 并且创造出非常丰富的组合玩法.

                                        fallbacks 配置

                                          "fallbacks": [
                                        @@ -41,6 +41,6 @@
                                           "xver": 0
                                         }
                                         

                                        fallbacks 是一个数组,这里是其中一个子元素的配置说明。

                                        fallbacks 项是可选的,只能用于 TCP+TLS 传输组合

                                        • 该项有子元素时,Inbound TLS 需设置 "alpn":["http/1.1"]。**

                                        通常,你需要先设置一组 alpnpath 均省略或为空的默认回落,然后再按需配置其它分流。

                                        VLESS 会把 TLS 解密后首包长度 < 18 或协议版本无效、身份认证失败的流量转发到 dest 指定的地址。

                                        其它传输组合必须删掉 fallbacks 项或所有子元素,此时也不会开启 Fallback,VLESS 会等待读够所需长度,协议版本无效或身份认证失败时,将直接断开连接。

                                        name: string

                                        尝试匹配 TLS SNI(Server Name Indication),空为任意,默认为 ""

                                        alpn: string

                                        尝试匹配 TLS ALPN 协商结果,空为任意,默认为 ""

                                        有需要时,VLESS 才会尝试读取 TLS ALPN 协商结果,若成功,输出 info realAlpn = 到日志。 用途:解决了 Nginx 的 h2c 服务不能同时兼容 http/1.1 的问题,Nginx 需要写两行 listen,分别用于 1.1 和 h2c。 注意:fallbacks alpn 存在 "h2" 时,Inbound TLS 需设置 "alpn":["h2","http/1.1"],以支持 h2 访问。

                                        提示

                                        Fallback 内设置的 alpn 是匹配实际协商出的 ALPN,而 Inbound TLS 设置的 alpn 是握手时可选的 ALPN 列表,两者含义不同。

                                        path: string

                                        尝试匹配首包 HTTP PATH,空为任意,默认为空,非空则必须以 / 开头,不支持 h2c。

                                        智能:有需要时,VLESS 才会尝试看一眼 PATH(不超过 55 个字节;最快算法,并不完整解析 HTTP),若成功,输出 INFO 日志 realPath =。 用途:分流其它 inbound 的 WebSocket 流量或 HTTP 伪装流量,没有多余处理、纯粹转发流量,理论性能比 Nginx 更强。

                                        注意:fallbacks 所在入站本身必须是 TCP+TLS,这是分流至其它 WS 入站用的,被分流的入站则无需配置 TLS。

                                        dest: string | number

                                        决定 TLS 解密后 TCP 流量的去向,目前支持两类地址:(该项必填,否则无法启动)

                                        1. TCP,格式为 "addr:port",其中 addr 支持 IPv4、域名、IPv6,若填写域名,也将直接发起 TCP 连接(而不走内置的 DNS)。
                                        2. Unix domain socket,格式为绝对路径,形如 "/dev/shm/domain.socket",可在开头加 @ 代表 abstractopen in new tag@@ 则代表带 padding 的 abstract。

                                        若只填 port,数字或字符串均可,形如 80"80",通常指向一个明文 http 服务(addr 会被补为 "127.0.0.1")。

                                        xver: number

                                        发送 PROXY protocolopen in new tag,专用于传递请求的真实来源 IP 和端口,填版本 1 或 2,默认为 0,即不发送。若有需要建议填 1。

                                        目前填 1 或 2,功能完全相同,只是结构不同,且前者可打印,后者为二进制。Xray 的 TCP 和 WS 入站均已支持接收 PROXY protocol。

                                        注意

                                        若你正在 配置 Nginx 接收 PROXY protocolopen in new tag,除了设置 proxy_protocol 外,还需设置 set_real_ip_from,否则可能会出问题。

                                        补充说明

                                        • 将匹配到最精确的子元素,与子元素的排列顺序无关。若配置了几个 alpn 和 path 均相同的子元素,则会以最后的为准。
                                        • 回落分流均是解密后 TCP 层的转发,而不是 HTTP 层,只在必要时检查首包 PATH。
                                        • 您可以查看更多的关于 Fallbacks 的使用技巧和心得

                                        Fallbacks 设计理论 WIP

                                        - + diff --git a/config/features/multiple.html b/config/features/multiple.html index 81191cf3d2..e3000d3fb6 100644 --- a/config/features/multiple.html +++ b/config/features/multiple.html @@ -24,8 +24,8 @@ 多文件配置 | Project X - - + +

                                        多文件配置

                                        Xray 程序支持使用多个配置文件。

                                        多配置文件的主要作用在于分散不同作用模块配置,便于管理和维护。

                                        该功能主要考虑是为了丰富 Xray 的生态链,比如对于 GUI 的客户端,一般只实现节点选择等固定的功能,对于太复杂的配置难以图形化实现;只需留一个 confdir 的自定义配置目录供配置复杂的功能;对于服务器的部署脚本,只需往 confdir 添加文件即可实现配置多种协议。

                                        多文件启动

                                        提示

                                        启动信息中会提示依次读入的每个配置文件,留意启动信息是否符合你预设的顺序。可以在每个文件名前面增加前缀数字的方式控制顺序。如 01_文件名, 02_文件名,数字越大排序越靠后。

                                        $ xray run -confdir /etc/xray/confs
                                        @@ -103,6 +103,6 @@
                                           ]
                                         }
                                         

                                        提示

                                        可以使用 xray run -confdir=./confs -dump 命令查看合并后的配置。但是因为 core 内部使用 protobuf 数据格式,所以 -dump 选项输出的配置格式会有所不同。

                                        - + diff --git a/config/features/xtls.html b/config/features/xtls.html index 79370f853d..01fb9084c4 100644 --- a/config/features/xtls.html +++ b/config/features/xtls.html @@ -24,11 +24,11 @@ XTLS 深度剖析 | Project X - - + + - + diff --git a/config/inbound.html b/config/inbound.html index 8c941286d4..84a32b3876 100644 --- a/config/inbound.html +++ b/config/inbound.html @@ -24,8 +24,8 @@ 入站代理 | Project X - - + +

                                        入站代理

                                        入站连接用于接收发来的数据,可用的协议请见入站协议

                                        InboundObject

                                        InboundObject 对应配置文件中 inbounds 项的一个子元素。

                                        {
                                        @@ -68,6 +68,6 @@
                                           "concurrency": 3
                                         }
                                         

                                        strategy: "always" | "random"

                                        端口分配策略。

                                        • "always" 表示总是分配所有已指定的端口,port 中指定了多少个端口,Xray 就会监听这些端口。
                                        • "random" 表示随机开放端口,每隔 refresh 分钟在 port 范围中随机选取 concurrency 个端口来监听。

                                        refresh: number

                                        随机端口刷新间隔,单位为分钟。最小值为 2,建议值为 5。这个属性仅当 strategy 设置为 "random" 时有效。

                                        concurrency: number

                                        随机端口数量。最小值为 1,最大值为 port 范围的三分之一。建议值为 3

                                        - + diff --git a/config/inbounds/dokodemo.html b/config/inbounds/dokodemo.html index 36285f76dc..4f2f4bc0f6 100644 --- a/config/inbounds/dokodemo.html +++ b/config/inbounds/dokodemo.html @@ -24,8 +24,8 @@ Dokodemo-Door | Project X - - + +

                                        Dokodemo-Door

                                        Dokodemo door(任意门)可以监听一个本地端口,并把所有进入此端口的数据发送至指定服务器的一个端口,从而达到端口映射的效果。

                                        InboundConfigurationObject

                                        {
                                        @@ -51,6 +51,6 @@
                                           "tag": "mc"
                                         }
                                         

                                        这时候核心会监听 127.0.0.1:25565 并通过默认出站转发至 mc.hypixel.net:25565 (一个MC服务器), 这时候再通过 Minecraft 客户端连接 127.0.0.1:25565, 就相当于通过代理连接了 Hypixel 服务器。

                                        透明代理配置样例

                                        此部分请参考透明代理(TProxy)配置教程

                                        - + diff --git a/config/inbounds/http.html b/config/inbounds/http.html index 61964aa65c..02795dfdfa 100644 --- a/config/inbounds/http.html +++ b/config/inbounds/http.html @@ -24,8 +24,8 @@ HTTP | Project X - - + +

                                        HTTP

                                        HTTP 协议。

                                        警告

                                        http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。

                                        http 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。

                                        TIP 1

                                        http proxy 只能代理 tcp 协议,udp 系的协议均不能通过。

                                        TIP 2

                                        在 Linux 中使用以下环境变量即可在当前 session 使用全局 HTTP 代理(很多软件都支持这一设置,也有不支持的)。

                                        • export http_proxy=http://127.0.0.1:8080/ (地址须改成你配置的 HTTP 入站代理地址)
                                        • export https_proxy=$http_proxy

                                        InboundConfigurationObject

                                        {
                                        @@ -44,6 +44,6 @@
                                           "pass": "my-password"
                                         }
                                         

                                        user: string

                                        用户名,字符串类型。必填。

                                        pass: string

                                        密码,字符串类型。必填。

                                        - + diff --git a/config/inbounds/shadowsocks.html b/config/inbounds/shadowsocks.html index 6ee04803f6..0657e69d76 100644 --- a/config/inbounds/shadowsocks.html +++ b/config/inbounds/shadowsocks.html @@ -24,8 +24,8 @@ Shadowsocks | Project X - - + +

                                        Shadowsocks

                                        Shadowsocksopen in new tag 协议,兼容大部分其它版本的实现。

                                        目前兼容性如下:

                                        • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
                                        • 推荐的加密方式:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • 其他加密方式
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 或称 chacha20-ietf-poly1305
                                          • xchacha20-poly1305 或称 xchacha20-ietf-poly1305
                                          • none 或 plain

                                        Shadowsocks 2022 新协议格式提升了性能并带有完整的重放保护,解决了旧协议的以下安全问题:

                                        警告

                                        "none" 不加密方式下流量将明文传输。为确保安全性, 不要在公共网络上使用。

                                        InboundConfigurationObject

                                        {
                                        @@ -50,6 +50,6 @@
                                           "email": "love@xray.com"
                                         }
                                         

                                        当存在此选项时,代表启用多用户模式.

                                        当 InboundConfigurationObject 中的 method 不为SS2022选项时,可以在此为每个用户指定 "method"。("method"中也仅支持非SS2022选项)与"password"(与此同时 InboundConfigurationObject 中的设置的 "password" 将会被忽略)。

                                        当 InboundConfigurationObject 中的 method 为SS2022选项时,出于安全考量,不再支持为单个用户设置 "method",统一为 InboundConfigurationObject 所指定的"method"

                                        注意SS2022并不会像旧SS一样忽略上层 "password", 客户端的正确密码写法应为, ServerPassword:UserPassword。如:"password": "114514:1919810"

                                        其余选项与 InboundConfigurationObject 中的含义一致。

                                        - + diff --git a/config/inbounds/socks.html b/config/inbounds/socks.html index 8e97585d76..2119e7af7e 100644 --- a/config/inbounds/socks.html +++ b/config/inbounds/socks.html @@ -24,8 +24,8 @@ Socks | Project X - - + +

                                        Socks

                                        标准 Socks 协议实现,兼容 Socks 4open in new tagSocks 4aopen in new tag 和 Socks 5。

                                        警告

                                        Socks 协议没有对传输加密,不适宜经公网中传输

                                        Socks 入站更有意义的用法是在局域网或本机环境下监听,为其他程序提供本地服务。

                                        InboundConfigurationObject

                                        {
                                        @@ -45,6 +45,6 @@
                                           "pass": "my-password"
                                         }
                                         

                                        user: string

                                        用户名,字符串类型。必填。

                                        pass: string

                                        密码,字符串类型。必填。

                                        - + diff --git a/config/inbounds/trojan.html b/config/inbounds/trojan.html index 3ba533a08a..363c585a95 100644 --- a/config/inbounds/trojan.html +++ b/config/inbounds/trojan.html @@ -24,8 +24,8 @@ Trojan | Project X - - + +

                                        Trojan

                                        Trojanopen in new tag 协议

                                        警告

                                        Trojan 被设计工作在正确配置的加密 TLS 隧道

                                        InboundConfigurationObject

                                        {
                                        @@ -48,6 +48,6 @@
                                           "level": 0
                                         }
                                         

                                        password: string

                                        必填,任意字符串。

                                        email: string

                                        邮件地址,可选,用于标识用户

                                        警告

                                        如果存在多个 ClientObject, 请注意 email 不可以重复。

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        userLevel 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        - + diff --git a/config/inbounds/vless.html b/config/inbounds/vless.html index be826c7eb1..eb698e33b4 100644 --- a/config/inbounds/vless.html +++ b/config/inbounds/vless.html @@ -24,8 +24,8 @@ VLESS(XTLS Vision Seed) | Project X - - + +

                                        VLESS(XTLS Vision Seed)

                                        警告

                                        目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。

                                        VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。

                                        VMess 不同,VLESS 不依赖于系统时间,认证方式同样为 UUID。

                                        InboundConfigurationObject

                                        {
                                        @@ -51,6 +51,6 @@
                                           "flow": "xtls-rprx-vision"
                                         }
                                         

                                        id: string

                                        VLESS 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID. 自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即

                                        • "id": "我爱🍉老师1314",
                                        • 或写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 我爱🍉老师1314 的 UUID 映射)

                                        其映射标准在 VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5open in new tag

                                        你可以使用命令 xray uuid -i "自定义字符串" 生成自定义字符串所映射的的 UUID。

                                        也可以使用命令 xray uuid 生成随机的 UUID.

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        level 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        email: string

                                        用户邮箱,用于区分不同用户的流量(会体现在日志、统计中)。

                                        flow: string

                                        流控模式,用于选择 XTLS 的算法。

                                        目前入站协议中有以下流控模式可选:

                                        • flow 或者 空字符: 使用普通 TLS 代理
                                        • xtls-rprx-vision:使用新 XTLS 模式 包含内层握手随机填充

                                        此外,目前 XTLS 仅支持 TCP+TLS/Reality

                                        - + diff --git a/config/inbounds/vmess.html b/config/inbounds/vmess.html index a4a54b0dbb..c5f1f3d50f 100644 --- a/config/inbounds/vmess.html +++ b/config/inbounds/vmess.html @@ -24,8 +24,8 @@ VMess | Project X - - + +

                                        VMess

                                        VMess 是一个加密传输协议,通常作为 Xray 客户端和服务器之间的桥梁。

                                        警告

                                        VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 120 秒之内,时区无关。在 Linux 系统中可以安装ntp服务来自动同步系统时间。

                                        InboundConfigurationObject

                                        {
                                        @@ -55,6 +55,6 @@
                                           "level": 0
                                         }
                                         

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        level 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        - + diff --git a/config/index.html b/config/index.html index 66e4eb2a9b..6ffe2ffe09 100644 --- a/config/index.html +++ b/config/index.html @@ -24,8 +24,8 @@ 配置文件 | Project X - - + +

                                        这个章节将告诉您所有的 Xray 配置细节,掌握这些内容,在您手中 Xray 将发挥更大威力。

                                        概述

                                        Xray 的配置文件为 json 格式, 客户端和服务端的配置格式没有区别, 只是实际的配置内容不一样。
                                        形式如下:

                                        {
                                        @@ -45,6 +45,6 @@
                                           "burstObservatory": {}
                                         }
                                         

                                        注意

                                        如果你刚接触 Xray, 您可以先点击查看快速入门中的配置运行, 学习最基本的配置方式, 然后查看本章节内容以掌握所有 Xray 的配置方式。

                                        基础配置模块

                                        log:LogObject

                                        日志配置,控制 Xray 输出日志的方式.

                                        api:ApiObject

                                        提供了一些 API 接口供远程调用。

                                        dns: DnsObject

                                        内置的 DNS 服务器. 如果没有配置此项,则使用系统的 DNS 设置。

                                        routing: RoutingObject

                                        路由功能。可以设置规则分流数据从不同的 outbound 发出.

                                        policy: PolicyObject

                                        本地策略,可以设置不同的用户等级和对应的策略设置。

                                        inbounds: [ InboundObject ]

                                        一个数组,每个元素是一个入站连接配置。

                                        outbounds: [ OutboundObject ]

                                        一个数组,每个元素是一个出站连接配置。

                                        transport: TransportObject

                                        用于配置 Xray 其它服务器建立和使用网络连接的方式。

                                        stats: StatsObject

                                        用于配置流量数据的统计。

                                        reverse: ReverseObject

                                        反向代理。可以把服务器端的流量向客户端转发,即逆向流量转发。

                                        fakedns: FakeDnsObject

                                        FakeDNS 配置。可配合透明代理使用,以获取实际域名。

                                        metrics: metricsObject

                                        metrics 配置。更直接(希望更好)的统计导出方式。

                                        observatory: ObservatoryObject

                                        后台连接观测。探测出站代理的连接状态。

                                        burstObservatory: BurstObservatoryObject

                                        并发连接观测。探测出站代理的连接状态。

                                        - + diff --git a/config/log.html b/config/log.html index ac625a4427..731f3ab9ff 100644 --- a/config/log.html +++ b/config/log.html @@ -24,8 +24,8 @@ 日志配置 | Project X - - + +

                                        日志配置

                                        日志配置,控制 Xray 输出日志的方式.

                                        Xray 有两种日志, 访问日志和错误日志, 你可以分别配置两种日志的输出方式.

                                        LogObject

                                        LogObject 对应配置文件的 log 项。

                                        {
                                        @@ -37,6 +37,6 @@
                                           }
                                         }
                                         

                                        access: string

                                        访问日志的文件地址,其值是一个合法的文件地址,如"/var/log/Xray/access.log"(Linux)或者"C:\\Temp\\Xray\\_access.log"(Windows)。当此项不指定或为空值时,表示将日志输出至 stdout。

                                        • 特殊值none,即关闭 access log。

                                        error: string

                                        错误日志的文件地址,其值是一个合法的文件地址,如"/var/log/Xray/error.log"(Linux)或者"C:\\Temp\\Xray\\_error.log"(Windows)。当此项不指定或为空值时,表示将日志输出至 stdout。

                                        • 特殊值none,即关闭 error log。

                                        loglevel: "debug" | "info" | "warning" | "error" | "none"

                                        error 日志的级别, 指示 error 日志需要记录的信息. 默认值为 "warning"

                                        • "debug":调试程序时用到的输出信息。同时包含所有 "info" 内容。
                                        • "info":运行时的状态信息等,不影响正常使用。同时包含所有 "warning" 内容。
                                        • "warning":发生了一些并不影响正常运行的问题时输出的信息,但有可能影响用户的体验。同时包含所有 "error" 内容。
                                        • "error":Xray 遇到了无法正常运行的问题,需要立即解决。
                                        • "none":不记录任何内容。

                                        dnsLog: bool

                                        是否启用 DNS 查询日志,例如:DOH//doh.server got answer: domain.com -> [ip1, ip2] 2.333ms

                                        - + diff --git a/config/metrics.html b/config/metrics.html index aac2975571..94ee3c73a2 100644 --- a/config/metrics.html +++ b/config/metrics.html @@ -24,8 +24,8 @@ Metrics | Project X - - + +

                                        Metrics

                                        更直接(希望更好)的统计导出方式。

                                        相关配置

                                        可以在 inbounds 配置中增加一个 metrics 的 inbound

                                            "inbounds": [
                                        @@ -242,6 +242,6 @@
                                                    id: udp
                                                    expvar_type: int
                                         

                                        And you will get a nice plot like this:

                                        160428235-2988bf69-5d6c-41ec-8267-1bd512508aa8

                                        Additional

                                        Maybe reusing the empty object stats in config file is better than adding metrics here?

                                        Edit: removed prometheus related things and added usage about expvars

                                        - + diff --git a/config/observatory.html b/config/observatory.html index f198295ba1..d7e557985c 100644 --- a/config/observatory.html +++ b/config/observatory.html @@ -24,8 +24,8 @@ 连接观测 | Project X - - + +

                                        连接观测

                                        连接观测组件使用 HTTPing 的方式探测出站代理的连接状态。观测结果可以被其他组件使用,如负载均衡器。目前有 observatory (后台连接观测)和 burstObservatory (并发连接观测)两种。按需选择其中之一就行。

                                        ObservatoryObject

                                        {
                                        @@ -50,6 +50,6 @@
                                           "timeout": "30s"
                                         }
                                         

                                        destination: string

                                        用于探测出站代理连接状态的网址。这个网址应该返回 HTTP 204 成功状态码。

                                        connectivity: string

                                        用于检测本地网络连通性的网址。空字符串表示不检测本地网络连通性。

                                        interval: string

                                        在指定时间内探测全部匹配的出站代理,每个出站代理探测 sampling + 1 次。时间格式为数字 + 单位,比如 "10s", "2h45m",支持的时间单位有 ns, us, ms, s, m, h, 分别对应纳秒、微秒、毫秒、秒、分、时。

                                        sampling: number

                                        保留最近探测结果的数量。

                                        timeout: string

                                        探测超时时间。格式和上面的 interval 相同。

                                        - + diff --git a/config/outbound.html b/config/outbound.html index aa7fa212f6..17537a1bec 100644 --- a/config/outbound.html +++ b/config/outbound.html @@ -24,8 +24,8 @@ 出站代理(Mux、XUDP) | Project X - - + +

                                        出站代理(Mux、XUDP)

                                        出站连接用于发送数据,可用的协议请见 出站协议

                                        OutboundObject

                                        OutboundObject 对应配置文件中 outbounds 项的一个子元素。

                                        提示

                                        列表中的第一个元素作为主 outbound。当路由匹配不存在或没有匹配成功时,流量由主 outbound 发出。

                                        {
                                        @@ -53,6 +53,6 @@
                                           "xudpProxyUDP443": "reject"
                                         }
                                         

                                        enabled: true | false

                                        是否启用 Mux 转发请求,默认值 false

                                        concurrency: number

                                        最大并发连接数。最小值 1,最大值 1024。省略或者填 0 时都等于 8

                                        这个数值表示了一个 TCP 连接上最多承载的子连接数量。比如设置 concurrency=8 时,当客户端发出了 8 个 TCP 请求,Xray 只会发出一条实际的 TCP 连接,客户端的 8 个请求全部由这个 TCP 连接传输。

                                        提示

                                        填负数时,如 -1,不使用 Mux 模块承载 TCP 流量。

                                        xudpConcurrency: number

                                        使用新 XUDP 聚合隧道(也就是另一条 Mux 连接)代理 UDP 流量,填写最大并发子 UoT 数量。最小值 1,最大值 1024。 省略或者填 0 时,将与 TCP 流量走同一条路,也就是传统的行为。

                                        提示

                                        填负数时,如 -1,不使用 Mux 模块承载 UDP 流量。将使用代理协议原本的 UDP 传输方式。例如 Shadowsocks 会使用原生 UDP,VLESS 会使用 UoT。

                                        xudpProxyUDP443: string

                                        控制 Mux 对于被代理的 UDP/443(QUIC)流量的处理方式:

                                        • 默认 reject 拒绝流量(一般浏览器会自动回落到 TCP HTTP2)
                                        • allow 允许走 Mux 连接。
                                        • skip 时,不使用 Mux 模块承载 UDP 443 流量。将使用代理协议原本的 UDP 传输方式。例如 Shadowsocks 会使用原生 UDP,VLESS 会使用 UoT。
                                        - + diff --git a/config/outbounds/blackhole.html b/config/outbounds/blackhole.html index 7b6a3f9d54..83e9d971b6 100644 --- a/config/outbounds/blackhole.html +++ b/config/outbounds/blackhole.html @@ -24,8 +24,8 @@ Blackhole | Project X - - + +

                                        Blackhole

                                        Blackhole(黑洞)是一个出站数据协议,它会阻碍所有数据的出站,配合 路由配置 一起使用,可以达到禁止访问某些网站的效果。

                                        OutboundConfigurationObject

                                        {
                                        @@ -37,6 +37,6 @@
                                           "type": "none"
                                         }
                                         

                                        type: "http" | "none"

                                        type"none"(默认值)时,Blackhole 将直接关闭连接。

                                        type"http" 时,Blackhole 会发回一个简单的 HTTP 403 数据包,然后关闭连接。

                                        - + diff --git a/config/outbounds/dns.html b/config/outbounds/dns.html index a16ab0831e..355b0e5100 100644 --- a/config/outbounds/dns.html +++ b/config/outbounds/dns.html @@ -24,8 +24,8 @@ DNS | Project X - - + +

                                        DNS

                                        DNS 是一个出站协议,主要用于拦截和转发 DNS 查询。

                                        此出站协议只能接收 DNS 流量(包含基于 UDP 和 TCP 协议的查询),其它类型的流量会导致错误。

                                        在处理 DNS 查询时,此出站协议会将 IP 查询(即 A 和 AAAA)转发给内置的 DNS 服务器。其它类型的查询流量将被转发至它们原本的目标地址。

                                        OutboundConfigurationObject

                                        {
                                        @@ -35,6 +35,6 @@
                                           "nonIPQuery": "drop"
                                         }
                                         

                                        network: "tcp" | "udp"

                                        修改 DNS 流量的传输层协议,可选的值有 "tcp""udp"。当不指定时,保持来源的传输方式不变。

                                        address: address

                                        修改 DNS 服务器地址。当不指定时,保持来源中指定的地址不变。

                                        port: number

                                        修改 DNS 服务器端口。当不指定时,保持来源中指定的端口不变。

                                        nonIPQuery: string

                                        控制非 IP 查询(非 A 和 AAAA),"drop" 丢弃或者 "skip" 不由内置 DNS 服务器处理,将转发给目标。默认为 "drop"

                                        DNS 配置实例 WIP

                                        - + diff --git a/config/outbounds/freedom.html b/config/outbounds/freedom.html index 399759c814..1a411c13bb 100644 --- a/config/outbounds/freedom.html +++ b/config/outbounds/freedom.html @@ -24,8 +24,8 @@ Freedom | Project X - - + +

                                        Freedom

                                        Freedom 是一个出站协议,可以用来向任意网络发送(正常的) TCP 或 UDP 数据。

                                        OutboundConfigurationObject

                                        {
                                        @@ -40,6 +40,6 @@
                                           "proxyProtocol": 0
                                         }
                                         

                                        domainStrategy: "AsIs"
                                        "UseIP" | "UseIPv6v4" | "UseIPv6" | "UseIPv4v6" | "UseIPv4"
                                        "ForceIP" | "ForceIPv6v4" | "ForceIPv6" | "ForceIPv4v6" | "ForceIPv4"

                                        默认值 "AsIs"

                                        当目标地址为域名时,配置相应的值,Freedom 的行为模式如下:

                                        • 当使用 "AsIs" 时,Xray将直接使用系统栈发起连接,优先级与选择IP取决于系统设置。出于一些原因,UDP连接如果使用域名会无视系统设置优先IPv4。
                                        • 当填写其他值时,将使用 Xray-core 内置 DNS 服务器 服务器进行解析。若不存在DNSObject,则使用系统DNS。若有多个符合条件的IP地址时,核心会随机选择一个IP作为目标IP。
                                        • "IPv4" 代表尝试仅使用IPv4进行连接,"IPv4v6" 代表尝试使用IPv4或IPv6连接,但对于双栈域名,尽量使用IPv4。(v4v6调换后同理,不再赘述)
                                        • 当在内置DNS设置了 "queryStrategy" 后,实际行为将会与这个选项取并,只有都被包含的IP类型才会被解析,如 "queryStrategy": "UseIPv4" "domainStrategy": "UseIP",实际上等同于 "domainStrategy": "UseIPv4"
                                        • 当使用 "Use" 开头的选项时,若解析结果不符合要求(如,域名只有IPv4解析结果但使用了UseIPv6),则会回落回AsIs。
                                        • 当使用 "Force" 开头的选项时,若解析结果不符合要求,则该连接会无法建立。

                                        TIP 1

                                        当使用 "UseIP""ForceIP" 模式时,并且 出站连接配置 中指定了 sendThrough 时,Freedom 会根据 sendThrough 的值自动判断所需的 IP 类型,IPv4 或 IPv6。若手动指定了单种IP类型(如UseIPv4),但与 sendThrough 指定的本地地址不匹配,将会导致连接失败。

                                        redirect: address_port

                                        Freedom 会强制将所有数据发送到指定地址(而不是 inbound 指定的地址)。

                                        其值为一个字符串,样例:"127.0.0.1:80"":1234"

                                        当地址不指定时,如 ":443",Freedom 不会修改原先的目标地址。 当端口为 0 时,如 "xray.com: 0",Freedom 不会修改原先的端口。

                                        userLevel: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        userLevel 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        fragment: map

                                        一些键值对配置项,用于控制发出的 TCP 分片,在某些情况下可以欺骗审查系统,比如绕过 SNI 黑名单。

                                        "packets":支持两种分片方式 "1-3" 是 TCP 的流切片,应用于客户端第 1 至第 3 次写数据。"tlshello" 是 TLS 握手包切片。

                                        "length":分片包长 (byte)

                                        "interval":分片间隔(ms)

                                        当其为 0 且设置 "packets": "tlshello" 时,被分片的 Client Hello 将会在一个TCP包中发送(如果其原始大小未超过MSS或MTU导致被系统自动分片)

                                        proxyProtocol: number

                                        PROXY protocol 通常配合 redirect 重定向到开启了 PROXY protocol 协议的 Nginx 或其他后端服务中。如果后端服务不支持 PROXY protocol 协议,连接将会被断开。

                                        proxyProtocol 的值为 PROXY protocol 版本号,可选 12,如不指定,默认为 0 不启用。

                                        - + diff --git a/config/outbounds/http.html b/config/outbounds/http.html index 4837108b50..f95cd75f73 100644 --- a/config/outbounds/http.html +++ b/config/outbounds/http.html @@ -24,8 +24,8 @@ HTTP | Project X - - + +

                                        HTTP

                                        HTTP 协议。

                                        警告

                                        http 协议没有对传输加密,不适宜经公网中传输,更容易成为被人用作攻击的肉鸡。

                                        提示

                                        http 只能代理 tcp 协议,udp 系的协议均不能通过。

                                        OutboundConfigurationObject

                                        {
                                        @@ -61,6 +61,6 @@
                                           "pass": "my-password"
                                         }
                                         

                                        user: string

                                        用户名,字符串类型。必填。

                                        pass: string

                                        密码,字符串类型。必填。

                                        - + diff --git a/config/outbounds/loopback.html b/config/outbounds/loopback.html index 72a6647edd..082e754d98 100644 --- a/config/outbounds/loopback.html +++ b/config/outbounds/loopback.html @@ -24,8 +24,8 @@ Loopback | Project X - - + + - + diff --git a/config/outbounds/shadowsocks.html b/config/outbounds/shadowsocks.html index f832ba24de..f4266149ac 100644 --- a/config/outbounds/shadowsocks.html +++ b/config/outbounds/shadowsocks.html @@ -24,8 +24,8 @@ Shadowsocks | Project X - - + +

                                        Shadowsocks

                                        Shadowsocksopen in new tag 协议,兼容大部分其它版本的实现。

                                        目前兼容性如下:

                                        • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
                                        • 推荐的加密方式:
                                          • 2022-blake3-aes-128-gcm
                                          • 2022-blake3-aes-256-gcm
                                          • 2022-blake3-chacha20-poly1305
                                        • 其他加密方式
                                          • aes-256-gcm
                                          • aes-128-gcm
                                          • chacha20-poly1305 或称 chacha20-ietf-poly1305
                                          • xchacha20-poly1305 或称 xchacha20-ietf-poly1305
                                          • none 或 plain

                                        Shadowsocks 2022 新协议格式提升了性能并带有完整的重放保护,解决了旧协议的以下安全问题:

                                        警告

                                        "none" 不加密方式下流量将明文传输。为确保安全性, 不要在公共网络上使用。

                                        OutboundConfigurationObject

                                        {
                                        @@ -53,6 +53,6 @@
                                           "level": 0
                                         }
                                         

                                        email: string

                                        邮件地址,可选,用于标识用户

                                        address: address

                                        Shadowsocks 服务端地址,支持 IPv4、IPv6 和域名。必填。

                                        port: number

                                        Shadowsocks 服务端端口。必填。

                                        method: string

                                        必填。

                                        password: string

                                        必填。

                                        uot: bool

                                        启用udp over tcp

                                        UoTVersion: number

                                        UDP over TCP 的实现版本。

                                        当前可选值:1, 2

                                        • Shadowsocks 2022

                                        使用与 WireGuard 类似的预共享密钥作为密码。

                                        使用 openssl rand -base64 <长度> 以生成与 shadowsocks-rust 兼容的密钥,长度取决于所使用的加密方法。

                                        加密方法密钥长度
                                        2022-blake3-aes-128-gcm16
                                        2022-blake3-aes-256-gcm32
                                        2022-blake3-chacha20-poly130532

                                        在 Go 实现中,32 位密钥始终工作。

                                        • 其他加密方法

                                        任意字符串。不限制密码长度,但短密码会更可能被破解,建议使用 16 字符或更长的密码。

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        level 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        - + diff --git a/config/outbounds/socks.html b/config/outbounds/socks.html index 136f5693e4..52fe29b60c 100644 --- a/config/outbounds/socks.html +++ b/config/outbounds/socks.html @@ -24,8 +24,8 @@ Socks | Project X - - + +

                                        Socks

                                        标准 Socks 协议实现,兼容 Socks 5。

                                        警告

                                        Socks 协议没有对传输加密,不适宜经公网中传输

                                        OutboundConfigurationObject

                                        {
                                        @@ -60,6 +60,6 @@
                                           "level": 0
                                         }
                                         

                                        user: string

                                        用户名,字符串类型。必填。

                                        pass: string

                                        密码,字符串类型。必填。

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        userLevel 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        - + diff --git a/config/outbounds/trojan.html b/config/outbounds/trojan.html index 7ae31f4c06..fa22e2081c 100644 --- a/config/outbounds/trojan.html +++ b/config/outbounds/trojan.html @@ -24,8 +24,8 @@ Trojan | Project X - - + +

                                        Trojan

                                        Trojanopen in new tag 协议

                                        警告

                                        Trojan 被设计工作在正确配置的加密 TLS 隧道

                                        OutboundConfigurationObject

                                        {
                                        @@ -47,6 +47,6 @@
                                           "level": 0
                                         }
                                         

                                        address: address

                                        服务端地址,支持 IPv4、IPv6 和域名。必填。

                                        port: number

                                        服务端端口,通常与服务端监听的端口相同。

                                        password: string

                                        密码. 必填,任意字符串。

                                        email: string

                                        邮件地址,可选,用于标识用户

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        level 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        - + diff --git a/config/outbounds/vless.html b/config/outbounds/vless.html index 2f93041379..bd152bcadb 100644 --- a/config/outbounds/vless.html +++ b/config/outbounds/vless.html @@ -24,8 +24,8 @@ VLESS(XTLS Vision Seed) | Project X - - + +

                                        VLESS(XTLS Vision Seed)

                                        警告

                                        目前 VLESS 没有自带加密,请用于可靠信道,如 TLS。

                                        VLESS 是一个无状态的轻量传输协议,它分为入站和出站两部分,可以作为 Xray 客户端和服务器之间的桥梁。

                                        VMess 不同,VLESS 不依赖于系统时间,认证方式同样为 UUID。

                                        OutboundConfigurationObject

                                        {
                                        @@ -63,6 +63,6 @@
                                           "level": 0
                                         }
                                         

                                        id: string

                                        VLESS 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID. 自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即

                                        • "id": "我爱🍉老师1314",
                                        • 或写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 我爱🍉老师1314 的 UUID 映射)

                                        其映射标准在 VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5open in new tag

                                        你可以使用命令 xray uuid -i "自定义字符串" 生成自定义字符串所映射的的 UUID,也可以使用命令 xray uuid 生成随机的 UUID。

                                        encryption: "none"

                                        需要填 "none",不能留空。

                                        该要求是为了提醒使用者没有加密,也为了以后出加密方式时,防止使用者填错属性名或填错位置导致裸奔。

                                        若未正确设置 encryption 的值,使用 Xray 或 -test 时会收到错误信息。

                                        flow: string

                                        流控模式,用于选择 XTLS 的算法。

                                        目前出站协议中有以下流控模式可选:

                                        • flow 或者 空字符: 使用普通 TLS 代理
                                        • xtls-rprx-vision:使用新 XTLS 模式 包含内层握手随机填充 支持 uTLS 模拟客户端指纹
                                        • xtls-rprx-vision-udp443:同 xtls-rprx-vision, 但是不会拦截目标为 443 端口的 UDP 流量

                                        此外,目前 XTLS 仅支持 TCP+TLS/Reality。

                                        关于 xtls-rprx-*-udp443 流控模式

                                        启用了 Xray-core 的 XTLS 时,通往 UDP 443 端口的流量默认会被拦截(一般情况下为 QUIC),这样应用就不会使用 QUIC 而会使用 TLS,XTLS 才会真正生效。实际上,QUIC 本身也不适合被代理,因为 QUIC 自带了 TCP 的功能,它作为 UDP 流量在通过 VLESS 协议传输时,底层协议为 TCP,就相当于两层阻塞控制了。

                                        若不需要拦截,请在客户端填写 xtls-rprx-*-udp443,服务端不变。

                                        关于 Splice 模式

                                        Splice 是 Linux Kernel 提供的函数,系统内核直接转发 TCP,不再经过 Xray 的内存,大大减少了数据拷贝、CPU 上下文切换的次数。

                                        Splice 模式的的使用限制:

                                        • Linux 环境
                                        • 入站协议为 Dokodemo doorSocksHTTP 等纯净的 TCP 连接, 或其它使用了 XTLS 的入站协议
                                        • 出站协议为 VLESS + XTLS

                                        此外,使用 Splice 时网速显示会滞后,这是特性,不是 bug。

                                        使用 Vision 模式 如果满足上述条件 会自动启用 Splice

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        level 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        - + diff --git a/config/outbounds/vmess.html b/config/outbounds/vmess.html index a64dec7c25..2191144ffb 100644 --- a/config/outbounds/vmess.html +++ b/config/outbounds/vmess.html @@ -24,8 +24,8 @@ VMess | Project X - - + +

                                        VMess

                                        VMess 是一个加密传输协议,通常作为 Xray 客户端和服务器之间的桥梁。

                                        警告

                                        VMess 依赖于系统时间,请确保使用 Xray 的系统 UTC 时间误差在 120 秒之内,时区无关。在 Linux 系统中可以安装ntp服务来自动同步系统时间。

                                        OutboundConfigurationObject

                                        {
                                        @@ -56,6 +56,6 @@
                                           "experiments": ""
                                         }
                                         

                                        id:string

                                        Vmess 的用户 ID,可以是任意小于 30 字节的字符串, 也可以是一个合法的 UUID.

                                        自定义字符串和其映射的 UUID 是等价的, 这意味着你将可以这样在配置文件中写 id 来标识同一用户,即

                                        • "id": "我爱🍉老师1314",
                                        • 或写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 我爱🍉老师1314 的 UUID 映射)

                                        其映射标准在 VLESS UUID 映射标准:将自定义字符串映射为一个 UUIDv5open in new tag

                                        你可以使用命令 xray uuid -i "自定义字符串" 生成自定义字符串所映射的的 UUID, 也可以使用命令 xray uuid 生成随机的 UUID。

                                        level: number

                                        用户等级,连接会使用这个用户等级对应的 本地策略

                                        level 的值, 对应 policylevel 的值。 如不指定, 默认为 0。

                                        security: "aes-128-gcm" | "chacha20-poly1305" | "auto" | "none" | "zero"

                                        加密方式,客户端将使用配置的加密方式发送数据,服务器端自动识别,无需配置。

                                        • "aes-128-gcm":推荐在 PC 上使用
                                        • "chacha20-poly1305":推荐在手机端使用
                                        • "auto":默认值,自动选择(运行框架为 AMD64、ARM64 或 s390x 时为 aes-128-gcm 加密方式,其他情况则为 Chacha20-Poly1305 加密方式)
                                        • "none":不加密
                                        • "zero":不加密,也不进行消息认证 (v1.4.0+)

                                        提示

                                        推荐使用"auto"加密方式,这样可以永久保证安全性和兼容性。

                                        "none" 伪加密方式会计算并验证数据包的校验数据,由于认证算法没有硬件支持,在部分平台可能速度比有硬件加速的 "aes-128-gcm" 还慢。

                                        "zero" 伪加密方式不会加密消息也不会计算数据的校验数据,因此理论上速度会高于其他任何加密方式。实际速度可能受到其他因素影响。

                                        不推荐在未开启 TLS 加密并强制校验证书的情况下使用 "none" "zero" 伪加密方式。 如果使用 CDN 或其他会解密 TLS 的中转平台或网络环境建立连接,不建议使用 "none" "zero" 伪加密方式。

                                        无论使用哪种加密方式, VMess 的包头都会受到加密和认证的保护。

                                        experiments: string

                                        启用的 VMess 协议实验性功能。(此处的功能为不稳定功能, 可能随时被移除)多个启用的实验之间可以用 | 字符分割,如 "AuthenticatedLength|NoTerminationSignal" 。

                                        "AuthenticatedLength" 启用认证的数据包长度实验。此实验需要同时在客户端与服务器端同时开启,并运行相同版本的程序。

                                        "NoTerminationSignal" 启用不发送断开连接标致实验。此实验可能会影响被代理的连接的稳定性。

                                        - + diff --git a/config/outbounds/wireguard.html b/config/outbounds/wireguard.html index b856b3057c..1e522c9f66 100644 --- a/config/outbounds/wireguard.html +++ b/config/outbounds/wireguard.html @@ -24,8 +24,8 @@ Wireguard | Project X - - + +

                                        Wireguard

                                        标准 Wireguard 协议实现。

                                        警告

                                        Wireguard 协议并非专门为翻墙而设计,若在最外层过墙,存在特征可能导致服务器被封锁

                                        OutboundConfigurationObject

                                        {
                                        @@ -77,6 +77,6 @@
                                           "allowedIPs": ["0.0.0.0/0"] // optional, default ["0.0.0.0/0", "::/0"]
                                         }
                                         

                                        endpoint: address

                                        服务器地址, 必填

                                        URL:端口 格式,例如 engage.cloudflareclient.com:2408
                                        IP:端口 格式,例如 162.159.192.1:2408[2606:4700:d0::a29f:c001]:2408

                                        提示

                                        当目标地址类型为 URL 时,将使用 Xray-core 内置 DNS 查询 URL 以获取 IP,IPv4 或 IPv6 优先级由 domainStrategy 的值控制。
                                        若没写 "dns" 配置,使用系统 DNS 查询 URL 以获取 IP,IPv4 或 IPv6 优先级由系统控制。

                                        publicKey: string

                                        服务器公钥,用于验证, 必填

                                        preSharedKey: string

                                        额外的对称加密密钥

                                        keepAlive: int

                                        心跳包时间间隔,单位为秒,默认为 0 表示无心跳

                                        allowedIPs: string array

                                        Wireguard 仅允许特定源 IP 的流量

                                        - + diff --git a/config/policy.html b/config/policy.html index ea6f8326e8..902b05f530 100644 --- a/config/policy.html +++ b/config/policy.html @@ -24,8 +24,8 @@ 本地策略 | Project X - - + +

                                        本地策略

                                        本地策略,可以设置不同的用户等级和对应的策略设置,比如连接超时设置。Xray 处理的每一个连接都对应一个用户,按照用户的等级(level)应用不同的策略。

                                        PolicyObject

                                        PolicyObject 对应配置文件的 policy 项。

                                        {
                                        @@ -65,6 +65,6 @@
                                           "statsOutboundDownlink": false
                                         }
                                         

                                        statsInboundUplink: true | false

                                        当值为 true 时,开启所有入站代理的上行流量统计。

                                        statsInboundDownlink: true | false

                                        当值为 true 时,开启所有入站代理的下行流量统计。

                                        statsOutboundUplink: true | false

                                        当值为 true 时,开启所有出站代理的上行流量统计。

                                        statsOutboundDownlink: true | false

                                        当值为 true 时,开启所有出站代理的下行流量统计。

                                        - + diff --git a/config/reverse.html b/config/reverse.html index 9d1d84947f..df8e544da8 100644 --- a/config/reverse.html +++ b/config/reverse.html @@ -24,8 +24,8 @@ 反向代理 | Project X - - + +

                                        反向代理

                                        反向代理可以把服务器端的流量向客户端转发,即逆向流量转发。

                                        反向代理的大致工作原理如下:

                                        • 假设在主机 A 中有一个网页服务器,这台主机没有公网 IP,无法在公网上直接访问。另有一台主机 B,它可以由公网访问。现在我们需要把 B 作为入口,把流量从 B 转发到 A。
                                        • 在主机 A 中配置 Xray,称为bridge,在 B 中也配置 Xray,称为 portal
                                        • bridge 会向 portal 主动建立连接,此连接的目标地址可以自行设定。portal 会收到两种连接,一是由 bridge 发来的连接,二是公网用户发来的连接。portal 会自动将两类连接合并。于是 bridge 就可以收到公网流量了。
                                        • bridge 在收到公网流量之后,会将其原封不动地发给主机 A 中的网页服务器。当然,这一步需要路由的协作。
                                        • bridge 会根据流量的大小进行动态的负载均衡。

                                        提示

                                        反向代理默认已开启 Mux,请不要在其用到的 outbound 上再次开启 Mux。

                                        注意

                                        反向代理功能尚处于测试阶段,可能会有一些问题。

                                        ReverseObject

                                        ReverseObject 对应配置文件的 reverse 项。

                                        {
                                        @@ -144,6 +144,6 @@
                                           ]
                                         }
                                         
                                        - + diff --git a/config/routing.html b/config/routing.html index 4c2dfdef72..9b8778e2e9 100644 --- a/config/routing.html +++ b/config/routing.html @@ -24,8 +24,8 @@ 路由 | Project X - - + +

                                        路由

                                        路由功能模块可以将入站数据按不同规则由不同的出站连接发出,以达到按需代理的目的。

                                        如常见用法是分流国内外流量,Xray 可以通过内部机制判断不同地区的流量,然后将它们发送到不同的出站代理。

                                        有关路由功能更详细的解析:路由 (routing) 功能简析open in new tag

                                        RoutingObject

                                        RoutingObject 对应配置文件的 routing 项。

                                        {
                                        @@ -102,6 +102,6 @@
                                                 }
                                             ]
                                         

                                        预定义域名列表

                                        此列表预置于每一个 Xray 的安装包中,文件名为 geosite.dat。这个文件包含了一些常见的域名,使用方式:geosite:filename,如 geosite:google 表示对文件内符合 google 内包含的域名,进行路由筛选或 DNS 筛选。

                                        常见的域名有:

                                        • category-ads:包含了常见的广告域名。
                                        • category-ads-all:包含了常见的广告域名,以及广告提供商的域名。
                                        • cn:相当于 geolocation-cntld-cn 的合集。
                                        • apple:包含了 Apple 旗下绝大部分域名。
                                        • google:包含了 Google 旗下绝大部分域名。
                                        • microsoft:包含了 Microsoft 旗下绝大部分域名。
                                        • facebook:包含了 Facebook 旗下绝大部分域名。
                                        • twitter:包含了 Twitter 旗下绝大部分域名。
                                        • telegram:包含了 Telegram 旗下绝大部分域名。
                                        • geolocation-cn:包含了常见的大陆站点域名。
                                        • geolocation-!cn:包含了常见的非大陆站点域名。
                                        • tld-cn:包含了 CNNIC 管理的用于中国大陆的顶级域名,如以 .cn.中国 结尾的域名。
                                        • tld-!cn:包含了非中国大陆使用的顶级域名,如以 .hk(香港)、.tw(台湾)、.jp(日本)、.sg(新加坡)、.us(美国).ca(加拿大)等结尾的域名。

                                        你也可以在这里查看完整的域名列表 Domain list communityopen in new tag

                                        - + diff --git a/config/stats.html b/config/stats.html index c7e29df85a..376d91b90c 100644 --- a/config/stats.html +++ b/config/stats.html @@ -24,14 +24,14 @@ 统计信息 | Project X - - + +

                                        统计信息

                                        用于配置 Xray 流量数据的统计。

                                        StatsObject

                                        StatsObject 对应配置文件的 stats 项。

                                        {
                                           "stats": {}
                                         }
                                         

                                        目前统计信息不需要任何参数,只要 StatsObject 项存在,内部的统计即会开启。

                                        开启了统计以后, 只需在 Policy 中开启对应的项,就可以统计对应的数据。

                                        获取统计信息

                                        可以用 xray api 的相关命令获取统计信息.

                                        目前已有的统计信息如下:

                                        • 用户数据

                                          • user>>>[email]>>>traffic>>>uplink

                                            特定用户的上行流量,单位字节。

                                          • user>>>[email]>>>traffic>>>downlink

                                            特定用户的下行流量,单位字节。

                                        提示

                                        如果对应用户没有指定 Email,则不会开启统计。

                                        • 全局数据

                                          • inbound>>>[tag]>>>traffic>>>uplink

                                            特定 inbound 的上行流量,单位字节。

                                          • inbound>>>[tag]>>>traffic>>>downlink

                                            特定 inbound 的下行流量,单位字节。

                                          • outbound>>>[tag]>>>traffic>>>uplink

                                            特定 outbound 的上行流量,单位字节。

                                          • outbound>>>[tag]>>>traffic>>>downlink

                                            特定 outbound 的下行流量,单位字节。

                                        - + diff --git a/config/transport.html b/config/transport.html index 75e3517644..5daaf6bd75 100644 --- a/config/transport.html +++ b/config/transport.html @@ -24,8 +24,8 @@ 传输方式(uTLS、REALITY) | Project X - - + +

                                        传输方式(uTLS、REALITY)

                                        传输方式(transport)是当前 Xray 节点和其它节点对接的方式。

                                        传输方式指定了稳定的数据传输的方式。通常来说,一个网络连接的两端需要有对称的传输方式。比如一端用了 WebSocket,那么另一个端也必须使用 WebSocket,否则无法建立连接。

                                        传输方式(transport)配置有两部分:

                                        1. 全局配置(TransportObject)(已弃用)

                                        2. 局部配置(StreamSettingsObject)。

                                        • 局部配置时,可以指定每个单独的入站或出站用怎样的方式传输。
                                        • 通常来说客户端和服务器对应的入站和出站需要使用同样的传输方式。当其配置指定了一种传输方式,但没有填写具体设置时,此传输方式会使用全局配置中的设置。
                                        全局配置

                                        TransportObject(已弃用)

                                        TransportObject 对应配置文件的 transport 项。

                                        {
                                        @@ -187,6 +187,6 @@
                                           }
                                         ]
                                         

                                        type: ""

                                        必填,设置的类型,目前可选int或str.

                                        level: ""

                                        可选,协议级别,用于指定生效范围,默认为6, 即TCP.

                                        opt: ""

                                        操作的选项名称,使用十进制(此处示例为 TCP_CONGESTION 的值 定义为 0xd 转换为10进制即为13)

                                        value: ""

                                        要设置的选项值,此处示例为设置为bbr.

                                        当 type 指定为 int 时需要使用十进制数字。

                                        最近更改:
                                        Contributors: 风扇滑翔翼, JimhHan, xqzr, Jim Han, yuhan6665, ちか, tdjnodj, mmmray, Binbin Qian, Chuei Kan, Daniel Ding, Kobe Arthur Scofield, KoriIku, Lumière Élevé, Mikhail Samodurov, WaterLemons2k, Winston2084, Yang Lu, chika0801, flowerinsnow, lelemka0, lxsq, pvqogw
                                        - + diff --git a/config/transports/domainsocket.html b/config/transports/domainsocket.html index 57989f4c42..40c913affe 100644 --- a/config/transports/domainsocket.html +++ b/config/transports/domainsocket.html @@ -24,8 +24,8 @@ Domain Socket | Project X - - + +

                                        Domain Socket

                                        警告

                                        推荐写到 inboundslisten 处,传输方式可选 TCP、WebSocket、HTTP/2. 未来这里的 DomainSocket 可能会被弃用。

                                        Domain Socket 使用标准的 Unix domain socket 来传输数据。

                                        它的优势是使用了操作系统内建的传输通道,而不会占用网络缓存。 理论上相比起本地环回网络(local loopback)来说,Domain socket 速度略快一些。

                                        目前仅可用于支持 Unix domain socket 的平台,如 Linux 和 macOS。在 Windows 10 Build 17036 前不可用。

                                        如果指定了 domain socket 作为传输方式,在入站出站代理中配置的端口和 IP 地址将会失效,所有的传输由 domain socket 取代。

                                        DomainSocketObject

                                        DomainSocketObject 对应传输配置的 dsSettings 项。

                                        {
                                        @@ -34,6 +34,6 @@
                                           "padding": false
                                         }
                                         

                                        path: string

                                        一个合法的文件路径。

                                        警告

                                        在运行 Xray 之前,这个文件必须不存在。

                                        abstract: true | false

                                        是否为 abstract domain socket,默认值 false

                                        padding: true | false

                                        abstract domain socket 是否带 padding,默认值 false

                                        - + diff --git a/config/transports/grpc.html b/config/transports/grpc.html index 4b0904c7c6..a6f7717d27 100644 --- a/config/transports/grpc.html +++ b/config/transports/grpc.html @@ -24,8 +24,8 @@ gRPC | Project X - - + +

                                        gRPC

                                        基于 gRPC 的传输方式。

                                        它基于 HTTP/2 协议,理论上可以通过其它支持 HTTP/2 的服务器(如 Nginx)进行中转。 gRPC(HTTP/2)内置多路复用,不建议使用 gRPC 与 HTTP/2 时启用 mux.cool。

                                        ⚠⚠⚠

                                        • gRPC 不支持指定 Host。请在出站代理地址中填写 正确的域名 ,或在 (x)tlsSettings 中填写 ServerName,否则无法连接。
                                        • gRPC 不支持回落到其他服务。
                                        • gRPC 服务存在被主动探测的风险。建议使用 Caddy 或 Nginx 等反向代理工具,通过 Path 前置分流。

                                        提示

                                        如果您使用 Caddy 或 Nginx 等反向代理,请注意下列事项:

                                        • 请确定反向代理服务器开启了 HTTP/2
                                        • 请使用 HTTP/2 或 h2c (Caddy),grpc_pass (Nginx) 连接到 Xray。
                                        • 普通模式的 Path 为 /${serviceName}/Tun, Multi 模式为 /${serviceName}/TunMulti
                                        • 如果需要接收客户端 IP,可以通过由 Caddy / Nginx 发送 X-Real-IP header 来传递客户端 IP。

                                        提示

                                        如果你正在使用回落,请注意下列事项:

                                        • 不建议回落到 gRPC,存在被主动探测的风险。
                                        • 请确认h2 位于 (x)tlsSettings.alpn 中的第一顺位,否则 gRPC(HTTP/2)可能无法完成 TLS 握手。
                                        • gRPC 无法通过进行 Path 分流。

                                        GRPCObject

                                        GRPCObject 对应传输配置的 grpcSettings 项。

                                        {
                                        @@ -39,6 +39,6 @@
                                           "initial_windows_size": 0
                                         }
                                         

                                        authority: string

                                        一个字符串,可以当 Host 来用,实现一些其它用途。

                                        serviceName: string

                                        一个字符串,指定服务名称,类似于 HTTP/2 中的 Path。 客户端会使用此名称进行通信,服务端会验证服务名称是否匹配。

                                        提示

                                        serviceName 起始为斜杠时可以自定义 path,至少要两个斜杠。
                                        例如在服务端填写 "serviceName": "/my/sample/path1|path2",客户端可填写 "serviceName": "/my/sample/path1""/my/sample/path2"

                                        user_agent: string

                                        提示

                                        只需出站客户端)配置。

                                        设置 gRPC 的用户代理,可能能防止某些 CDN 阻止 gRPC 流量。

                                        multiMode: true | false BETA

                                        true 启用 multiMode,默认值为: false

                                        这是一个 实验性 选项,可能不会被长期保留,也不保证跨版本兼容。此模式在 测试环境中 能够带来约 20% 的性能提升,实际效果因传输速率不同而不同。

                                        提示

                                        只需出站客户端)配置。

                                        idle_timeout: number

                                        单位秒,当这段时间内没有数据传输时,将会进行健康检查。如果此值设置为 10 以下,将会使用 10,即最小值。

                                        提示

                                        如果没有使用 Caddy 或 Nginx 等反向代理工具(通常不会),设为 60 以下,服务端可能发送意外的 h2 GOAWAY 帧以关闭现有连接。

                                        健康检查默认不启用

                                        提示

                                        只需出站客户端)配置。

                                        提示

                                        可能会解决一些“断流”问题。

                                        health_check_timeout: number

                                        单位秒,健康检查的超时时间。如果在这段时间内没有完成健康检查,且仍然没有数据传输时,即认为健康检查失败。默认值为 20

                                        提示

                                        只需出站客户端)配置。

                                        permit_without_stream: true | false

                                        true 允许在没有子连接时进行健康检查。默认值为 false

                                        提示

                                        只需出站客户端)配置。

                                        initial_windows_size: number

                                        h2 Stream 初始窗口大小。当值小于等于 0 时,此功能不生效。当值大于 65535 时,动态窗口机制(Dynamic Window)会被禁用。默认值为 0,即不生效。

                                        提示

                                        只需出站客户端)配置。

                                        提示

                                        通过 Cloudflare CDN 时,可将值设为 65536 及以上,即禁用动态窗口机制(Dynamic Window),可防止 Cloudflare CDN 发送意外的 h2 GOAWAY 帧以关闭现有连接。

                                        - + diff --git a/config/transports/h2.html b/config/transports/h2.html index c9f0b7542e..13b79a4f2f 100644 --- a/config/transports/h2.html +++ b/config/transports/h2.html @@ -24,8 +24,8 @@ HTTP/2 | Project X - - + +

                                        HTTP/2

                                        基于 HTTP/2 的传输方式。

                                        它完整按照 HTTP/2 标准实现,可以通过其它的 HTTP 服务器(如 Nginx)进行中转。

                                        由 HTTP/2 的建议,客户端和服务器必须同时开启 TLS 才可以正常使用这个传输方式。

                                        HTTP/2 内置多路复用,不建议使用 HTTP/2 时启用 mux.cool。

                                        提示

                                        当前版本的 HTTP/2 的传输方式并不强制要求入站服务端)有 TLS 配置. 这使得可以在特殊用途的分流部署环境中,由外部网关组件完成 TLS 层对话,Xray 作为后端应用,网关和 Xray 间使用称为 h2c 的明文 http/2 进行通讯。

                                        注意

                                        ⚠️ 如果你正在使用回落,请注意下列事项:

                                        • 请确认 (x)tlsSettings.alpn 中包含 h2,否则 HTTP/2 无法完成 TLS 握手。
                                        • HTTP/2 无法通过 Path 进行分流,建议使用 SNI 分流。

                                        HttpObject

                                        HttpObject 对应传输配置的 httpSettings 项。

                                        {
                                        @@ -39,6 +39,6 @@
                                           }
                                         }
                                         

                                        host: [string]

                                        一个字符串数组,每一个元素是一个域名。

                                        客户端会随机从列表中选出一个域名进行通信,服务器会验证域名是否在列表中。

                                        提示

                                        若不写 "httpSettings""host": [] 值留空时,会使用默认值 "www.example.com",需要两端 "host" 值一致才能连接成功。"host": [""] 不是值留空。

                                        path: string

                                        HTTP 路径,由 / 开头, 客户端和服务器必须一致。

                                        默认值为 "/"

                                        read_idle_timeout: number

                                        单位秒,当这段时间内没有接收到数据时,将会进行健康检查。

                                        健康检查默认不启用

                                        提示

                                        只需出站客户端)配置。

                                        提示

                                        可能会解决一些“断流”问题。

                                        health_check_timeout: number

                                        单位秒,健康检查的超时时间。如果在这段时间内没有完成健康检查,即认为健康检查失败。默认值为 15

                                        提示

                                        只需出站客户端)配置。

                                        method: string

                                        HTTP 方法。默认值为 "PUT"

                                        设置时应参照此处open in new tag列出值。

                                        headers: map{ string: [string] }

                                        仅客户端,自定义 HTTP 头,一个键值对,每个键表示一个 HTTP 头名称,对应值为一个数组。

                                        - + diff --git a/config/transports/httpupgrade.html b/config/transports/httpupgrade.html index 728a76f823..afc1a74034 100644 --- a/config/transports/httpupgrade.html +++ b/config/transports/httpupgrade.html @@ -24,8 +24,8 @@ HTTPUpgrade | Project X - - + +

                                        HTTPUpgrade

                                        一个实现了类似于 WebSocket 进行 HTTP 1.1 升级请求和响应的协议,这使得它可以像 WebSocket 一样可以被CDN或者Nginx进行反代,但无需实现 WebSocket 协议的其他部分,所以具有更高的效率。 其设计不推荐单独使用,而是和TLS等安全协议一起工作。

                                        HttpUpgradeObject

                                        HttpUpgradeObject 对应传输配置的 httpupgradeSettings 项。

                                        {
                                        @@ -37,6 +37,6 @@
                                           }
                                         }
                                         

                                        acceptProxyProtocol: true | false

                                        仅用于 inbound,指示是否接收 PROXY protocol。

                                        PROXY protocolopen in new tag 专用于传递请求的真实来源 IP 和端口,若你不了解它,请先忽略该项

                                        常见的反代软件(如 HAProxy、Nginx)都可以配置发送它,VLESS fallbacks xver 也可以发送它。

                                        填写 true 时,最底层 TCP 连接建立后,请求方必须先发送 PROXY protocol v1 或 v2,否则连接会被关闭。

                                        path: string

                                        HTTPUpgrade 所使用的 HTTP 协议路径,默认值为 "/"

                                        如果客户端路径中包含 ed 参数(如 /mypath?ed=2560),将会启用 Early Data 以降低延迟,其值为首包长度阈值。如果首包长度超过此值,就不会启用 Early Data。建议的值为2560。

                                        host: string

                                        HTTPUpgrade 的HTTP请求中所发送的host,默认值为空。若服务端值为空时,不验证客户端发送来的host值。

                                        当在服务端指定该值,或在 headers 中指定host,将会校验与客户端请求host是否一致。

                                        客户端选择发送的host优先级 host > headers > address

                                        headers: map {string: string}

                                        仅客户端,自定义 HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是字符串。

                                        默认值为空。

                                        - + diff --git a/config/transports/mkcp.html b/config/transports/mkcp.html index 01b31c4670..fdcd0b3947 100644 --- a/config/transports/mkcp.html +++ b/config/transports/mkcp.html @@ -24,8 +24,8 @@ mKCP | Project X - - + +

                                        mKCP

                                        mKCP 使用 UDP 来模拟 TCP 连接。

                                        mKCP 牺牲带宽来降低延迟。传输同样的内容,mKCP 一般比 TCP 消耗更多的流量。

                                        提示

                                        请确定主机上的防火墙配置正确

                                        KcpObject

                                        KcpObject 对应传输配置的 kcpSettings 项。

                                        {
                                        @@ -47,6 +47,6 @@
                                           "domain": "example.com"
                                         }
                                         

                                        type: string

                                        伪装类型,可选的值有:

                                        • "none":默认值,不进行伪装,发送的数据是没有特征的数据包。
                                        • "srtp":伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。
                                        • "utp":伪装成 uTP 数据包,会被识别为 BT 下载数据。
                                        • "wechat-video":伪装成微信视频通话的数据包。
                                        • "dtls":伪装成 DTLS 1.2 数据包。
                                        • "wireguard":伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议)
                                        • "dns":某些校园网在未登录的情况下允许DNS查询,给KCP添加DNS头,把流量伪装成dns请求,可以绕过某些校园网登录。

                                        domain: string

                                        配合伪装类型 "dns" 使用,可随便填一个域名。

                                        鸣谢

                                        对 KCP 协议的改进

                                        更小的协议头

                                        原生 KCP 协议使用了 24 字节的固定头部,而 mKCP 修改为数据包 18 字节,确认(ACK)包 16 字节。更小的头部有助于躲避特征检查,并加快传输速度。

                                        另外,原生 KCP 的单个确认包只能确认一个数据包已收到,也就是说当 KCP 需要确认 100 个数据已收到时,它会发出 24 * 100 = 2400 字节的数据。其中包含了大量重复的头部数据,造成带宽的浪费。mKCP 会对多个确认包进行压缩,100 个确认包只需要 16 + 2 + 100 * 4 = 418 字节,相当于原生的六分之一。

                                        确认包重传

                                        原生 KCP 协议的确认(ACK)包只发送一次,如果确认包丢失,则一定会导致数据重传,造成不必要的带宽浪费。而 mKCP 会以一定的频率重发确认包,直到发送方确认为止。单个确认包的大小为 22 字节,相比起数据包的 1000 字节以上,重传确认包的代价要小得多。

                                        连接状态控制

                                        mKCP 可以有效地开启和关闭连接。当远程主机主动关闭连接时,连接会在两秒钟之内释放;当远程主机断线时,连接会在最多 30 秒内释放。

                                        原生 KCP 不支持这个场景。

                                        - + diff --git a/config/transports/quic.html b/config/transports/quic.html index fe175ea8f8..7db2a7b570 100644 --- a/config/transports/quic.html +++ b/config/transports/quic.html @@ -24,8 +24,8 @@ QUIC | Project X - - + +

                                        QUIC

                                        QUIC 全称 Quick UDP Internet Connection,是由 Google 提出的使用 UDP 进行多路并发传输的协议。其主要优势是:

                                        1. 减少了握手的延迟(1-RTT 或 0-RTT)
                                        2. 多路复用,并且没有 TCP 的阻塞问题
                                        3. 连接迁移,(主要是在客户端)当由 Wifi 转移到 4G 时,连接不会被断开。

                                        QUIC 目前处于实验期,使用了正在标准化过程中的 IETF 实现,不能保证与最终版本的兼容性。

                                        • 默认设定:
                                          • 12 字节的 Connection ID
                                          • 30 秒没有数据通过时自动断开连接 (可能会影响一些长连接的使用)

                                        QuicObject

                                        QuicObject 对应传输配置的 quicSettings 项。

                                        警告

                                        对接的两端的配置必须完全一致,否则连接失败。 QUIC 强制要求开启 TLS,在传输配置中没有开启 TLS 时,Xray 会自行签发一个证书进行 TLS 通讯。

                                        {
                                        @@ -39,6 +39,6 @@
                                           "type": "none"
                                         }
                                         

                                        type: string

                                        伪装类型,可选的值有:

                                        • "none":默认值,不进行伪装,发送的数据是没有特征的数据包。
                                        • "srtp":伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。
                                        • "utp":伪装成 uTP 数据包,会被识别为 BT 下载数据。
                                        • "wechat-video":伪装成微信视频通话的数据包。
                                        • "dtls":伪装成 DTLS 1.2 数据包。
                                        • "wireguard":伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议)

                                        提示

                                        当加密和伪装都不启用时,数据包即为原始的 QUIC 数据包,可以与其它的 QUIC 工具对接。 为了避免被探测,建议加密或伪装至少开启一项。

                                        - + diff --git a/config/transports/splithttp.html b/config/transports/splithttp.html index 0570a8e466..b9191c28db 100644 --- a/config/transports/splithttp.html +++ b/config/transports/splithttp.html @@ -24,8 +24,8 @@ SplitHTTP(H2、QUIC H3) | Project X - - + +

                                        SplitHTTP(H2、QUIC H3)

                                        v1.8.16+

                                        使用HTTP分块传输编码流式响应处理下载,使用多个HTTP POST请求进行上传。

                                        可以通过不支持WebSocket的CDN上,但仍有一些要求:

                                        • CDN必须支持HTTP分块传输,且支持流式响应而不会缓冲,核心将会发送 X-Accel-Buffering: no 以及 Content-Type: text/event-stream 以告知CDN,但是需要CDN遵守此标头。如果中间盒不支持流式响应而导致连接被挂起,则该传输很可能无法工作。

                                        目的与V2fly Meek相同,由于使用了流式响应处理下载,下行速率更为优秀,上行也经过优化但仍非常有限,也因此对 HTTP 中间盒要求更高(见上)。

                                        SplitHTTP 也接受 X-Forwarded-For header。

                                        SplitHttpObject

                                        The SplitHttpObject 对应传输配置的 splithttpSettings 项。

                                        {
                                        @@ -40,6 +40,6 @@
                                           "noSSEHeader": false
                                         }
                                         

                                        path: string

                                        SplitHTTP 所使用的 HTTP 协议路径,默认值为 "/"

                                        host: string

                                        SplitHTTP 的HTTP请求中所发送的host,默认值为空。若服务端值为空时,不验证客户端发送来的host值。

                                        当在服务端指定该值,或在 headers 中指定host,将会校验与客户端请求host是否一致。

                                        客户端选择发送的host优先级 host > headers > address

                                        headers: map {string: string}

                                        仅客户端,自定义 HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是字符串。

                                        scMaxEachPostBytes: int/string

                                        上传分块的最大大小,单位为字节,默认值为 1000000, 即 1MB.

                                        客户端设置的大小必须低于该值,否则当发送的 POST 请求大于服务端设置的值时,请求会被拒绝。

                                        这个值应该小于CDN或其他HTTP反向代理所允许的最大请求体,否则将抛出 HTTP 413 错误。

                                        也可以是字符串 "500000-1000000" 的形式,核心每次会在范围内随机选择一个值,以减少指纹。

                                        scMaxConcurrentPosts: int/string

                                        单个连接上传post的最大并发数,默认为100.

                                        上传并发同时也受(也主要受) scMinPostsIntervalMs 控制,故该值仅做保险。

                                        客户端实际发起的数量必须低于服务端。(实际情况下由于上述很难达到上限,所以事实上客户端设置的值可以超过服务端,但不建议这么做)

                                        也可以是字符串 "50-100" 的形式,核心每次会在范围内随机选择一个值,以减少指纹。

                                        scMinPostsIntervalMs: int/string

                                        仅客户端,发起POST上传请求的最小间隔。默认值为 30.

                                        也可以是字符串 "10-50" 的形式,核心每次会在范围内随机选择一个值,以减少指纹。

                                        noSSEHeader: bool

                                        仅服务端,不发送 Content-Type: text/event-stream 响应头,默认 false (即会发送)

                                        HTTP 版本

                                        客户端行为

                                        默认情况下,客户端将会默认在未启用 TLS 时使用 http/1.1, 启用 TLS 时,使用 h2.

                                        当启用 TLS 时,允许在 TLS 设置的 alpn 数组内设置 http/1.1 h2 h3 来指定具体的http版本(仅当该数组只有一个元素时生效,若填入多个元素则返回默认行为)

                                        服务端行为

                                        默认情况下,客户端将会默认监听 TCP, 此时可以处理 http/1.1 和 h2 流量。

                                        当启用 TLS 时,允许在 TLS 设置的 alpn 数组内设置 h3, 此时服务端将改为监听 UDP 端口, 处理 h3 流量。

                                        小提示

                                        由于该协议为标准的 HTTP 请求,所以对于 HTTP 版本的转换并不敏感,各种中间盒都可能转换 HTTP 版本。

                                        列如:你希望使用 h3 连接 Cloudflare, 但是Cloudflare 不会使用 h3 回源, 而是使用 http/1.1 或 h2 回源,此时客户端 alpn 应为 h3, 而服务端就不应为 h3, 因为发往服务端的请求不是 h3.

                                        Browser Dialer

                                        如果使用HTTPS,该传输还支持 Browser Dialer

                                        协议细节

                                        讨论详见 #3412open in new tag#3462open in new tag 以下是简述和简要兼容实现要求

                                        1. 使用 GET /<UUID> 开始下载。服务器立即回复 200 OKTransfer Encoding:chunked , 并立即发送一个两字节的有效负载,以强制HTTP中间盒刷新标头。

                                        2. 使用 POST /<UUID>/<seq> 开始发送上行数据. seq 作用类似于 TCP 序列号,从0开始,数据包可以被同时发送,服务端必须按序列号将数据重组。序列号不应重置。

                                          客户端可以以任意决定打开上行与下行请求的顺序,任何一种都可以启动会话,但是必须要在30秒内打开 GET 连接,否则会话将被终止。

                                        3. GET 请求将一直保持在打开状态直到连接被终止,服务端和客户端都可以关闭连接。具体行为取决于HTTP版本。

                                        建议:

                                        • 不要期望CDN会正确传输所有标头,这个协议的目的是为了穿透不支持WS的CDN,而这些CDN的行为通常不怎么友好。

                                        • 应当假设所有HTTP连接都不支持流式请求,所以上行连接发送的的每个包的大小应该基于延迟、吞吐量以及中间盒本身的限制考虑(类似TCP的MTU与纳格算法)。

                                        - + diff --git a/config/transports/tcp.html b/config/transports/tcp.html index aac7f4322c..db7d6281d5 100644 --- a/config/transports/tcp.html +++ b/config/transports/tcp.html @@ -24,8 +24,8 @@ TCP | Project X - - + +

                                        TCP

                                        TCP 传输模式是目前推荐使用的传输模式之一.

                                        可以和各种协议有多种组合模式.

                                        TcpObject

                                        TcpObject 对应传输配置的 tcpSettings 项。

                                        {
                                        @@ -69,6 +69,6 @@
                                           }
                                         }
                                         

                                        version: string

                                        HTTP 版本,默认值为 "1.1"

                                        status: string

                                        HTTP 状态,默认值为 "200"

                                        reason: string

                                        HTTP 状态说明,默认值为 "OK"

                                        headers: map {string, [ string ]}

                                        HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是一个数组。

                                        每次请求会附上所有的键,并随机选择一个对应的值。默认值见上方示例。

                                        - + diff --git a/config/transports/websocket.html b/config/transports/websocket.html index 70541b3213..728a7e99eb 100644 --- a/config/transports/websocket.html +++ b/config/transports/websocket.html @@ -24,8 +24,8 @@ WebSocket | Project X - - + +

                                        WebSocket

                                        使用标准的 WebSocket 来传输数据。

                                        WebSocket 连接可以被其它 HTTP 服务器(如 Nginx)分流,也可以被 VLESS fallbacks path 分流。

                                        提示

                                        Websocket 会识别 HTTP 请求的 X-Forwarded-For 头来覆写流量的源地址,优先级高于 PROXY protocol。

                                        WebSocketObject

                                        WebSocketObject 对应传输配置的 wsSettings 项。

                                        {
                                        @@ -37,6 +37,6 @@
                                           }
                                         }
                                         

                                        acceptProxyProtocol: true | false

                                        仅用于 inbound,指示是否接收 PROXY protocol。

                                        PROXY protocolopen in new tag 专用于传递请求的真实来源 IP 和端口,若你不了解它,请先忽略该项

                                        常见的反代软件(如 HAProxy、Nginx)都可以配置发送它,VLESS fallbacks xver 也可以发送它。

                                        填写 true 时,最底层 TCP 连接建立后,请求方必须先发送 PROXY protocol v1 或 v2,否则连接会被关闭。

                                        path: string

                                        WebSocket 所使用的 HTTP 协议路径,默认值为 "/"

                                        如果客户端路径中包含 ed 参数(如 /mypath?ed=2560),将会启用 Early Data 以降低延迟,在升级的同时使用 Sec-WebSocket-Protocol 头承载首包数据,其值为首包长度阈值。如果首包长度超过此值,就不会启用 Early Data。推荐值为 2560,最大值为8192,过大的值可能导致部分兼容问题,如果遇到兼容性问题,可以尝试调低阈值。

                                        host: string

                                        WebSocket 的HTTP请求中所发送的host,默认值为空。若服务端值为空时,不验证客户端发送来的host值。

                                        当在服务端指定该值,或在 headers 中指定host,将会校验与客户端请求host是否一致。

                                        客户端选择发送的host优先级 host > headers > address

                                        headers: map {string: string}

                                        仅客户端,自定义 HTTP 头,一个键值对,每个键表示一个 HTTP 头的名称,对应的值是字符串。

                                        默认值为空。

                                        Browser Dialer

                                        使用浏览器处理 TLS,详见 Browser Dialer

                                        - + diff --git a/development/index.html b/development/index.html index 3c1fc52df5..c69edde138 100644 --- a/development/index.html +++ b/development/index.html @@ -24,11 +24,11 @@ 开发指南 | Project X - - + +

                                        开发指南

                                        编译文档

                                        Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。

                                        请点击编译文档以查看具体编译相关内容。

                                        设计思路

                                        Xray 内核提供了一个平台,在其之上可以进二次开发。

                                        这个章节阐述了 Xray 的设计目标和架构。

                                        请点击设计思路以了解 Xray 的设计目标和架构。

                                        开发规范

                                        这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。

                                        请点击开发规范查看 Xray 开发中应遵循的准则。

                                        协议详解

                                        Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。

                                        VLESS 协议

                                        VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        VMess 协议

                                        VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        Mux.Cool 协议

                                        Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

                                        mKCP 协议

                                        mKCP 是流式传输协议,由 KCP 协议open in new tag修改而来,可以按顺序传输任意的数据流。

                                        - + diff --git a/development/intro/compile.html b/development/intro/compile.html index 879040d3df..4cb9fc822e 100644 --- a/development/intro/compile.html +++ b/development/intro/compile.html @@ -24,8 +24,8 @@ 编译文档 | Project X - - + +

                                        编译文档

                                        前序工作

                                        Xray 使用 Golangopen in new tag 作为编程语言,你需要先安装最新版本 Golang 才能够编译。

                                        如果你不幸使用 Windows, 请 务必 使用 Powershell

                                        拉取 Xray 源代码

                                        git clone https://github.com/XTLS/Xray-core.git
                                        @@ -40,6 +40,6 @@
                                         
                                         go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
                                         

                                        上传到服务器后,记得在服务器终端内执行 chmod +x xray

                                        提示

                                        执行 go tool dist list 查看所有支持的系统与架构。

                                        可复现构建:

                                        按照上述步骤,能够编译与 Release 中完全相同的二进制文件。

                                        注意

                                        请先确认您使用的 Golang 版本与编译 Release 的一致。

                                        - + diff --git a/development/intro/design.html b/development/intro/design.html index 287246bce9..c986500c0c 100644 --- a/development/intro/design.html +++ b/development/intro/design.html @@ -24,11 +24,11 @@ 设计目标 | Project X - - + +

                                        设计目标

                                        • Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验;
                                        • 以跨平台为首要原则,以减少二次开发的成本;

                                        架构

                                        Architecture

                                        内核分为三层:应用层、代理层和传输层。

                                        每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。

                                        应用层

                                        应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。

                                        应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。

                                        重要模块列表:

                                        • Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理;
                                        • Router: 路由模块,详见 路由配置
                                        • DNS: 内置的 DNS 服务器模块;
                                        • Proxy Manager: 代理管理器;

                                        代理层

                                        代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。

                                        两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。

                                        入站代理

                                        出站代理

                                        传输层

                                        传输层提供一些网络数据传输相关的工具模块。

                                        - + diff --git a/development/intro/guide.html b/development/intro/guide.html index e38559dff1..92584a9d41 100644 --- a/development/intro/guide.html +++ b/development/intro/guide.html @@ -24,8 +24,8 @@ 开发规范 | Project X - - + +

                                        开发规范

                                        基本

                                        版本控制

                                        Project X 的代码被托管在 github 上:

                                        您可以使用 Gitopen in new tag 来获取代码。

                                        分支(Branch)

                                        • 本项目的主干分支为 main,
                                        • 本项目的发布主分支同为 main,
                                        • 需要确保 main 在任一时刻都是可编译,且可正常使用的。
                                        • 如果需要开发新的功能,请新建分支进行开发,在开发完成并且经过充分测试后,合并回主干分支。
                                        • 已经合并入主干且没有必要存在的分支,请删除。

                                        发布(Release)

                                        WIP
                                        • 建立尝鲜版本和稳定版本两个发布通道
                                          • 尝鲜版本,可以为 daily build,主要用于特定情况的测试,尝鲜和获得即时反馈和再改进。
                                          • 稳定版本,为定时更新(比如月更),合并稳定的修改并发布。

                                        引用其它项目

                                        • Golang
                                          • 产品代码建议使用 Golang 标准库和 golang.org/x/open in new tag 下的库;
                                          • 如需引用其它项目,请事先创建 issue 讨论;
                                        • 其它
                                          • 不违反双方的协议,且对项目有帮助的工具,都可以使用。

                                        开发流程

                                        写代码之前

                                        发现任何问题,或对项目有任何想法,请创建 issueopen in new tag 讨论以减少重复劳动和消耗在代码上的时间。

                                        修改代码

                                        • Golang
                                          • 请参考 Effective Goopen in new tag
                                          • 每一次 push 之前,请运行:go generate core/format.go
                                          • 如果需要修改 protobuf,例如增加新配置项,请运行:go generate core/proto.go
                                          • 提交 pull request 之前,建议测试通过:go test ./...
                                          • 提交 pull request 之前,建议新增代码有超过 70% 的代码覆盖率(code coverage);
                                        • 其它
                                          • 请注意代码的可读性。

                                        Pull Request

                                        • 提交 PR 之前,请先运行 git pull https://github.com/XTLS/Xray-core.git 以确保 merge 可顺利进行;
                                        • 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR;
                                        • 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同,建议流程如下:
                                          1. 先 Fork 本项目,创建你自己的 github.com/<your_name>/Xray-core.git 仓库;
                                          2. 克隆你自己的 Xray 仓库到本地:git clone https://github.com/<your_name>/Xray-core.git
                                          3. 基于 main 分支创建新的分支,例如 git branch issue24 main
                                          4. 在新创建的分支上作修改并提交修改(commit);
                                          5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 main 分支,运行 git pull https://github.com/XTLS/Xray-core.git 拉取最新的远端代码;
                                          6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 git rebase main 执行分支合并操作。如遇到文件冲突,则需要解决冲突;
                                          7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:git push -u origin your-branch
                                          8. 最后,把自己仓库的新推送的分支往 XTLS/Xray-coremain 分支发 PR 即可;
                                          9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等;
                                          10. 耐心等待开发者的回应。

                                        对代码的修改

                                        功能性问题

                                        请提交至少一个测试用例(Test Case)来验证对现有功能的改动。

                                        性能相关

                                        请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。

                                        新功能

                                        • 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态;
                                        • 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。

                                        其它

                                        视具体情况而定。

                                        Xray 编码规范

                                        以下内容适用于 Xray 中的 Golang 代码。

                                        代码结构

                                        Xray-core
                                        @@ -40,6 +40,6 @@
                                         │   ├── vmess
                                         ├── transport  // 传输模块
                                         

                                        编码规范

                                        基本与 Golang 官方所推荐做法一致,有一些例外。写在这里以方便大家熟悉 Golang。

                                        命名

                                        • 文件和目录名尽量使用单个英文单词,比如 hello.go;
                                          • 如果实在没办法,则目录使用连接线/文件名使用下划线连接两个(或多个单词),比如 hello-world/hello_again.go;
                                          • 测试代码使用 _test.go 结尾;
                                        • 类型使用 Pascal 命名法,比如 ConnectionHandler;
                                          • 对缩写不强制小写,即 HTML 不必写成 Html;
                                        • 公开成员变量也使用 Pascal 命名法;
                                        • 私有成员变量使用 小驼峰式命名法open in new tag ,如 privateAttribute
                                        • 为了方便重构,方法建议全部使用 Pascal 命名法;
                                          • 完全私有的类型放入 internal

                                        内容组织

                                        • 一个文件包含一个主要类型,及其相关的私有函数等;
                                        • 测试相关的文件,如 Mock 等工具类,放入 testing 子目录。
                                        - + diff --git a/development/protocols/mkcp.html b/development/protocols/mkcp.html index fc802b1f1e..fc3c7ffbc6 100644 --- a/development/protocols/mkcp.html +++ b/development/protocols/mkcp.html @@ -24,11 +24,11 @@ mKCP 协议 | Project X - - + +

                                        mKCP 协议

                                        mKCP 是流式传输协议,由 KCP 协议open in new tag 修改而来,可以按顺序传输任意的数据流。

                                        版本

                                        mKCP 没有版本号,不保证版本之间兼容性。

                                        依赖

                                        底层协议

                                        mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。

                                        函数

                                        • fnv: FNV-1aopen in new tag 哈希函数
                                          • 输入参数为任意长度的字符串;
                                          • 输入出一个 32 位无符号整数;

                                        通讯过程

                                        1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。
                                        2. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。
                                        3. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。

                                        数据格式

                                        数据包

                                        4 字节2 字节L 字节
                                        认证信息 A数据长度 L片段部分

                                        其中:

                                        • 认证信息 A = fnv(片段部分),big endian;
                                        • 片段部分可能包含多个片段;

                                        数据片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len 字节
                                        标识 Conv指令 Cmd选项 Opt时间戳 Ts序列号 Sn未确认序列号 Una长度 Len数据

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x01
                                        • 选项 Opt: 可选的值有:
                                          • 0x00: 空选项
                                          • 0x01: 对方已发出所有数据
                                        • 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian
                                        • 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1
                                        • 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn

                                        确认片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len * 4 字节
                                        标识 Conv指令 Cmd选项 Opt窗口 Wnd下一接收序列号 Sn时间戳 Ts长度 Len已收到的序列号

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 常量 0x00
                                        • 选项 Opt: 同上
                                        • 窗口 Wnd: 远端主机可以接收的最大序列号
                                        • 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号
                                        • 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟
                                        • 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到

                                        注释:

                                        • 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据

                                        心跳片段

                                        2 字节1 字节1 字节4 字节4 字节4 字节
                                        标识 Conv指令 Cmd选项 Opt未确认序列号 Una下一接收序列号 Sn延迟 Rto

                                        其中:

                                        • 标识 Conv: mKCP 数据流的标识
                                        • 指令 Cmd: 可选的值有
                                          • 0x02: 远端主机强行终止会话
                                          • 0x03: 正常心跳
                                        • 选项 Opt: 同上
                                        • 未确认序列号 Una: 同数据片段的 Una
                                        • 下一接收序列号 Sn: 同确认片段的 Sn
                                        • 延迟 Rto: 远端主机自己计算出的延迟
                                        - + diff --git a/development/protocols/muxcool.html b/development/protocols/muxcool.html index 819ce0aaf3..162591cc5c 100644 --- a/development/protocols/muxcool.html +++ b/development/protocols/muxcool.html @@ -24,11 +24,11 @@ Mux.Cool 协议 | Project X - - + +

                                        Mux.Cool 协议

                                        Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

                                        版本

                                        当前版本是 1 Beta。

                                        依赖

                                        底层协议

                                        Mux.Cool 必须运行在一个已建立的可靠数据流之上。

                                        通讯过程

                                        一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。

                                        客户端行为

                                        当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。

                                        1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。
                                        2. 对于一个新的子连接,客户端必须发送状态New以通知服务器建立子连接,然后使用状态Keep来传送数据。
                                        3. 当子连接结束时,客户端发送End状态来通知服务器关闭子连接。
                                        4. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。
                                        5. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。

                                        服务器端行为

                                        当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。

                                        1. 当收到状态End时,服务器端可以关闭对目标地址的上行连接。
                                        2. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。
                                        3. 服务器不能使用New状态。
                                        4. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。

                                        传输格式

                                        Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。

                                        帧格式

                                        2 字节L 字节X 字节
                                        元数据长度 L元数据额外数据

                                        元数据

                                        元数据有若干种类型。所有类型的元数据都包含 ID 和 Opt 两项,其含义为:

                                        • ID: 子连接的唯一标识
                                        • Opt:
                                          • D(0x01): 有额外数据

                                        当选项 Opt(D) 开启时,额外数据格式如下:

                                        2 字节X-2 字节
                                        长度 X-2数据

                                        新建子连接 (New)

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节8 字节
                                        ID0x01选项 Opt网络类型 N端口地址类型 T地址 AGlobal ID (XUDP)

                                        其中:

                                        • 网络类型 N:
                                          • 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。
                                          • 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • Global ID (XUDP):
                                          • 客户端计算出 UDP 来源二元组的全局独特 ID,服务端用以确保当 XUDP 断线重连时,仍使用同一个端口与目标通信。

                                        在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持子连接 (Keep)

                                        TCP

                                        2 字节1 字节1 字节
                                        ID0x02选项 Opt

                                        UDP

                                        2 字节1 字节1 字节1 字节2 字节1 字节A 字节
                                        ID0x02选项 Opt网络类型 N端口地址类型 T地址 A

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 XUDP 在 Opt(D) 之后加 UDP 地址,格式同新建子连接,但没有 Global ID。

                                        关闭子连接 (End)

                                        2 字节1 字节1 字节
                                        ID0x03选项 Opt

                                        在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

                                        保持连接 (KeepAlive)

                                        2 字节1 字节1 字节
                                        ID0x04选项 Opt

                                        在保持连接时:

                                        • 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。
                                        • ID 可为随机值。

                                        应用

                                        Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。

                                        在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。(注:这是一个程序内的标记,VMess 和 VLESS 并不会在数据包中发送“v1.mux.cool”地址)

                                        - + diff --git a/development/protocols/vless.html b/development/protocols/vless.html index 45b4cc73a0..10115a467a 100644 --- a/development/protocols/vless.html +++ b/development/protocols/vless.html @@ -24,11 +24,11 @@ VLESS 协议 | Project X - - + +

                                        VLESS 协议

                                        VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        Request & Response

                                        1 字节16 字节1 字节M 字节1 字节2 字节1 字节S 字节X 字节
                                        协议版本等价 UUID附加信息长度 M附加信息 ProtoBuf指令端口地址类型地址请求数据
                                        1 字节1 字节N 字节Y 字节
                                        协议版本,与请求的一致附加信息长度 N附加信息 ProtoBuf响应数据

                                        VLESS 早在第二个测试版 ALPHA 2 时就已经是上述结构了(BETA 是第五个测试版):

                                        “响应认证”被替换为“协议版本”并移至最前,使 VLESS 可以升级换代,同时消除了生成伪随机数的开销。混淆相关结构被替换为附加信息(ProtoBuf)并前移,赋予协议本身可扩展性,相关开销也极小(gogo/protobufopen in new tag),若无附加信息则无相关开销。

                                        我一直觉得“响应认证”不是必要的,ALPHA 时为了提升生成随机数的性能,还用 math/rand 替换 crypto/rand,而现在都不需要了。

                                        “协议版本”不仅能起到“响应认证”的作用,还赋予了 VLESS 无痛升级协议结构的能力,带来无限的可能性。 “协议版本”在测试版本中均为 0,正式版本中为 1,以后若有不兼容的协议结构变更则应升级版本。

                                        VLESS 服务端的设计是 switch version,即同时支持所有 VLESS 版本。若需要升级协议版本(可能到不了这一步),推荐的做法是服务端提前一个月支持,一个月后再改客户端。VMess 请求也有协议版本,但它的认证信息在外面,指令部分则高度耦合且有固定加密,导致里面的协议版本毫无意义,服务端也没有进行判断,响应则没有协议版本。Trojan 的协议结构中没有协议版本。

                                        接下来是 UUID,我本来觉得 16 字节有点长,曾经考虑过缩短它,但后来看到 Trojan 用了 56 个可打印字符(56 字节),就彻底打消了这个念头。服务端每次都要验证 UUID,所以性能也很重要:VLESS 的 Validator 经历了多次重构/升级,相较于 VMess,它十分简洁且耗资源很少,可以同时支持非常多的用户,性能也十分强悍,验证速度极快(sync.Map)。API 动态增删用户则更高效顺滑。 https://github.com/XTLS/Xray-core/issues/158

                                        引入 ProtoBuf 是一个创举,等下会详细讲解。“指令”到“地址”的结构目前与 VMess 完全相同,同样支持 Mux。

                                        总体上,ALPHA 2 到 BETA 主要是:结构进化、清理整合、性能提升、更加完善。这些都是一点一滴的,详见 VLESS Changesopen in new tag

                                        ProtoBuf

                                        似乎只有 VLESS 可选内嵌 ProtoBuf,它是一种数据交换格式,信息被紧密编码成二进制,TLV 结构(Tag Length Value)。

                                        起因是我看到一篇文章称 SS 有一些缺点,如没有设计错误回报机制,客户端没办法根据不同的错误采取进一步的动作。 (但我并不认同所有错误都要回报,不然防不了主动探测。下一个测试版中,服务器可以返回一串自定义信息。) 于是想到一个可扩展的结构是很重要的,未来它也可以承载如动态端口指令。不止响应,请求也需要类似的结构。 本来打算自己设计 TLV,接着发觉 ProtoBuf 就是此结构、现成的轮子,完全适合用来做这件事,各语言支持等也不错。

                                        目前“附加信息”只有 Scheduler 和 SchedulerV,它们是 MessName 和 MessSeed 的替代者,当你不需要它们时,“附加信息长度”为 0,也就不会有 ProtoBuf 序列化/反序列化的开销。其实我更愿意称这个过程为“拼接”,因为 pb 实际原理上也只是这么做而已,相关开销极小。拼接后的 bytes 十分紧凑,和 ALPHA 的方案相差无几,有兴趣的可以分别输出并对比。

                                        为了指示对附加信息(Addons,也可以理解成插件,以后可以有很多个插件)的不同支持程度,下个测试版会在“附加信息长度”前新增“附加信息版本”。256 - 1 = 255 字节是够用且合理的(65535 就太多了,还可能有人恶意填充),现有的只用了十分之一,以后也不会同时有那么多附加信息,且大多数情况下是完全没有附加信息的。真不够用的话,可以升级 VLESS 版本。

                                        为了减少逻辑判断等开销,暂定 Addons 不使用多级结构。一个月前出现过“可变协议格式”的想法,pb 是可以做到打乱顺序,但没必要,因为现代加密的设计不会让旁观者看出两次传输的头部相同。

                                        下面介绍 Schedulers 和 Encryption 的构想,它们都是可选的,一个应对流量时序特征问题,一个应对密码学上的问题。

                                        Schedulers Flow

                                        中文名暂称:流量调度器(2020-09-03 更新:中文名确定为“流控”),指令由 ProtoBuf 承载,控制的是数据部分。

                                        我之前发现,VMess 原有的 shake “元数据混淆”在 TLS 上完全不会带来有意义的改变,只会降低性能,所以 VLESS 弃用了它。并且,“混淆”这个表述容易被误解成伪装,也弃用了。顺便一提,我一直是不看好伪装的:做不到完全一样,那不就是强特征吗?做得到完全一样,那为什么不直接用伪装目标?我一开始用的是 SSR,后来发现它只是表面伪装骗运营商,就再也没用过了。

                                        那么,“流量调度器”要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)。流量时序特征也可以是行为带来的,比如访问 Google 首页时加载了多少文件、顺序、每个文件的大小,多套一层加密并不能有效掩盖这些信息。

                                        Schedulers 没必要像下面的 Encryption 一样整个套在外面,因为头部的一丁点数据相对于后面的数据量来说太微不足道了。

                                        BETA 2 预计推出两个初级的 Scheduler:Zstd 压缩、数据量动态扩充。进阶操作才是从宏观层面来控制、分配,暂时咕咕。

                                        Encryption

                                        与 VMess 的高度耦合不同,VLESS 的服务端、客户端不久后可以提前约定好加密方式,仅在外面套一层加密。这有点类似于使用 TLS,不影响承载的任何数据,也可以理解成底层就是从 TLS 换成预设约定加密。相对于高度耦合,这种方式更合理且灵活:一种加密方式出了安全性问题,直接扔掉并换用其它的就行了,十分方便。VLESS 服务端还会允许不同的加密方式共存。

                                        对比 VMess,VLESS 相当于把 security 换成 encryption,把 disableInsecureEncryption 换成 decryption,就解决了所有问题。目前 encryption 和 decryption 只接受 "none" 且不能留空(即使以后有连接安全性检查),详见 VLESS 配置文档open in new tag。encryption 并不需要往外移一级,一是因为无法复用很多代码,二是因为会影响控制粒度,看未来的应用就明白了。

                                        加密支持两类形式,一类是加密完全独立,需要额外密码,适合私用,另一类是结合已有的 UUID 来加密,适合公用。 (若用第一类加密形式,且密码是以某种形式公开的,比如多人共用,那么中间人攻击就不远了) 重新设计的动态端口可能会随加密同时推出,指令由 ProtoBuf 承载,具体实现和 VMess 的动态端口也会有很多不同。

                                        套现成加密是件很简单的事情,也就多一层 writer & reader。BETA 3 预计支持 SS 的 aes-128-gcm 和 chacha20-ietf-poly1305: 客户端的 encryption 可以填 “auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654”,auto 会选择最适合当前机器的,0 代表测试版,最后的是密码。服务端的 decryption 也是类似填法,收到请求时会逐一尝试解密。

                                        并不是所有组合都需逐一尝试:VMess 的加密分为三段,第一段是认证信息,结合了 UUID、alterId、时间因素,第二段是指令部分,以固定算法加密,指令中含有数据部分使用的加密算法,第三段才是重要的数据部分。可以看出,VMess 的加解密方式实际上是多对一(服务端适配),而不仅是结合 UUID。但仅是结合 UUID 来加密也是件相对麻烦的事情,短时间内不会出,鉴于我们现在有 VMessAEAD 可用,也并不着急。若 VLESS 推出了结合 UUID 的加密方式,相当于重构了整个 VMess。

                                        UDP issues

                                        XUDP:VLESS & VMess & Mux UDP FullCone NATopen in new tag

                                        客户端开发指引

                                        1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。iOS 客户端的协议实现则需紧跟升级。
                                        2. 视觉标准:UI 标识请统一用 VLESS,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。
                                        3. encryption 应做成输入框而不是选择框,新配置的默认值应为 none,若用户置空则应代填 none

                                        VLESS 分享链接标准

                                        感谢 a @DuckSoftopen in new tag 的提案!

                                        详情请见 VMessAEAD / VLESS 分享链接标准提案open in new tag

                                        - + diff --git a/development/protocols/vmess.html b/development/protocols/vmess.html index c76833c461..3192df1fc4 100644 --- a/development/protocols/vmess.html +++ b/development/protocols/vmess.html @@ -24,11 +24,11 @@ VMess 协议 | Project X - - + +

                                        VMess 协议

                                        VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

                                        版本

                                        当前版本号为 1。

                                        依赖

                                        底层协议

                                        VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。

                                        用户 ID

                                        ID 等价于 UUIDopen in new tag,是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如这个open in new tag

                                        用户 ID 可在配置文件中指定。

                                        函数

                                        通讯过程

                                        VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。

                                        VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。

                                        VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。

                                        客户端请求

                                        16 字节X 字节余下部分
                                        认证信息指令部分数据部分

                                        认证信息

                                        认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下:

                                        • H = MD5
                                        • K = 用户 ID (16 字节)
                                        • M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian)
                                        • Hash = HMAC(H, K, M)

                                        指令部分

                                        指令部分经过 AES-128-CFB 加密:

                                        • Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
                                        • IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian)
                                        1 字节16 字节16 字节1 字节1 字节4 位4 位1 字节1 字节2 字节1 字节N 字节P 字节4 字节
                                        版本号 Ver数据加密 IV数据加密 Key响应认证 V选项 Opt余量 P加密方式 Sec保留指令 Cmd端口 Port地址类型 T地址 A随机值校验 F

                                        选项 Opt 细节:(当某一位为 1 时,表示该选项启用)

                                        01234567
                                        XXXXXMRS

                                        其中:

                                        • 版本号 Ver:始终为 1;
                                        • 数据加密 IV:随机值;
                                        • 数据加密 Key:随机值;
                                        • 响应认证 V:随机值;
                                        • 选项 Opt:
                                          • S (0x01):标准格式的数据流(建议开启);
                                          • R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用);
                                            • 只有当 S 开启时,这一项才有效;
                                          • M (0x04):开启元数据混淆(建议开启);
                                            • 只有当 S 开启时,这一项才有效;
                                            • 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。
                                          • X:保留
                                        • 余量 P:在校验值之前加入 P 字节的随机值;
                                        • 加密方式:指定数据部分的加密方式,可选的值有:
                                          • 0x00:AES-128-CFB;
                                          • 0x01:不加密;
                                          • 0x02:AES-128-GCM;
                                          • 0x03:ChaCha20-Poly1305;
                                        • 指令 Cmd:
                                          • 0x01:TCP 数据;
                                          • 0x02:UDP 数据;
                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 地址类型 T:
                                          • 0x01:IPv4
                                          • 0x02:域名
                                          • 0x03:IPv6
                                        • 地址 A:
                                          • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
                                          • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
                                          • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
                                        • 校验 F:指令部分除 F 外所有内容的 FNV1a hash;

                                        数据部分

                                        当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。

                                        2 字节L 字节
                                        长度 L数据包

                                        其中:

                                        • 长度 L:Big Endian 格式的整型,最大值为 2^14;
                                          • 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
                                        • 数据包:由指定的加密方式加密过的数据包;

                                        在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。

                                        按加密方式不同,数据包的格式如下:

                                        • 不加密:
                                          • L 字节:实际数据;
                                        • AES-128-CFB:整个数据部分使用 AES-128-CFB 加密
                                          • 4 字节:实际数据的 FNV1a hash;
                                          • L - 4 字节:实际数据;
                                        • AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:GCM 认证信息
                                        • ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
                                          • L - 16 字节:实际数据;
                                          • 16 字节:Poly1305 认证信息

                                        服务器应答

                                        应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。

                                        1 字节1 字节1 字节1 字节M 字节余下部分
                                        响应认证 V选项 Opt指令 Cmd指令长度 M指令内容实际应答数据

                                        其中:

                                        • 响应认证 V:必须和客户端请求中的响应认证 V 一致;
                                        • 选项 Opt:
                                          • 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用);
                                        • 指令 Cmd:
                                          • 0x01:动态端口指令
                                        • 实际应答数据:
                                          • 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。
                                          • 格式均和请求数据相同。
                                            • 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

                                        动态端口指令

                                        1 字节2 字节16 字节2 字节1 字节1 字节
                                        保留端口 Port用户 IDAlterID用户等级有效时间 T

                                        其中:

                                        • 端口 Port:Big Endian 格式的整型端口号;
                                        • 有效时间 T:分钟数;

                                        客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。

                                        注释

                                        • 为确保向前兼容性,所有保留字段的值必须为 0。
                                        - + diff --git a/document/command.html b/document/command.html index 5963fa7390..5522aa2510 100644 --- a/document/command.html +++ b/document/command.html @@ -24,8 +24,8 @@ 命令参数 | Project X - - + +

                                        命令参数

                                        提示

                                        Xray 使用 Go 风格的命令及参数

                                        获取基本命令

                                        您可以运行 xray help 来获得所有 xray 最基础的用法, 以及可用的命令及说明。

                                        Xray is a platform for building proxies.
                                        @@ -116,6 +116,6 @@
                                         

                                        xray x25519

                                        生成 x25519 密钥对。

                                        使用方法:

                                        xray x25519 [-i "(base64.RawURLEncoding)" --std-encoding ]
                                         

                                        xray wg

                                        生成 wireguard curve25519 密钥对。

                                        使用方法:

                                        xray wg [-i "(base64.StdEncoding)"]
                                         

                                        提示

                                        -config 没有指定时,Xray 将先后尝试从以下路径加载 config.json :

                                        • 工作目录(Working Directory)
                                        • 环境变量Xray.location.asset 所指定的路径
                                        - + diff --git a/document/config.html b/document/config.html index cbe9f3fd10..f8f55dea6d 100644 --- a/document/config.html +++ b/document/config.html @@ -24,8 +24,8 @@ 配置运行 | Project X - - + +

                                        配置运行

                                        下载并安装 了 Xray 之后,您需要对它进行一下配置。

                                        为了演示,这里只介绍简单的配置方式。更多的模板: Xray-examplesopen in new tag

                                        如需配置更复杂的功能,请参考更详细的 配置文件 中相关说明。

                                        警告

                                        为了避免你的流量被解密,
                                        你应该使用 xray uuiduuidgen 生成一个独一无二的uuid
                                        在服务端上,放入 inbounds[0].settings.clients[0].id
                                        在客户端内,放入 outbounds[0].settings.vnext[0].users[0].id

                                        服务端配置

                                        你需要一台防火墙外的服务器,来运行服务器端的 Xray。配置如下:

                                        {
                                        @@ -93,6 +93,6 @@
                                           }
                                         }
                                         

                                        上述配置唯一要更改的地方是你的服务器 IP 和用户 uuid,配置中已注明。上述配置会把除局域网(比如访问路由器)和国内IP段(比如访问bilibili、acfun)以外的所有流量转发至你的服务器。

                                        运行

                                        • 在 Windows 和 macOS 中,配置文件通常是 Xray 同目录下的 config.json 文件。
                                          • 直接运行 XrayXray.exe 即可。
                                        • 在 Linux 中,配置文件通常位于 /etc/xray//usr/local/etc/xray/ 目录下。
                                          • 运行 xray run -c /etc/xray/config.json
                                          • 或使用 systemd 等工具将 Xray 作为服务在后台运行。

                                        更多详细的说明可以参考 配置文档小小白话文

                                        - + diff --git a/document/document.html b/document/document.html index b72206636a..5aa4455cb3 100644 --- a/document/document.html +++ b/document/document.html @@ -24,14 +24,14 @@ 为 Project X 的文档贡献 | Project X - - + +

                                        为 Project X 的文档贡献

                                        欢迎您为 Project X 的文档做出贡献,我们感谢每一位 Contributor 的贡献!是你们让 Xray 更加强大!

                                        改进文档

                                        Project X 的文档托管在 GitHubopen in new tag 上.

                                        您可以通过以下步骤, 提交您对文档的改动:

                                        1. Project X 文档仓库open in new tag 打开仓库, 点击右上角的 fork, fork 一份文档仓库的镜像到您自己的 github 仓库.

                                        2. 使用任何您喜欢的工具, 从您克隆的仓库获得文档的克隆, 如:

                                        git clone https://github.com/XTLS/Xray-docs-next.git
                                         
                                        1. 基于 main 分支创建新的分支, 如:
                                        git checkout -b your-branch
                                         
                                        1. 在新分支上做修改。

                                          注:推荐 中文文案排版指北open in new tag

                                        2. 修改完成后,请使用 Prettieropen in new tag 格式化您的更改。

                                          注:存在格式问题的 PR,将有可能被拒绝。

                                        3. 提交修改,并推送到您的仓库中

                                        git push -u origin your-branch
                                         
                                        1. 打开 GitHub, 点击 'Pull request' 向 Project X 文档仓库open in new tag 提交 PR。

                                        2. 请在 PR 的标题和正文中,概述此次 PR 新增/修改的内容等;

                                        3. 等待回应, 如果 PR 被 merge, 您做的修改将直接呈现在 Project X 文档网站open in new tag

                                        发现问题?

                                        如果您发现文档出错,可以改进文档或提交一个 Issue。

                                        - + diff --git a/document/index.html b/document/index.html index a2b5f31805..2c3dee7c3b 100644 --- a/document/index.html +++ b/document/index.html @@ -24,11 +24,11 @@ 快速入门 | Project X - - + +

                                        快速入门

                                        这个章节将告诉您如何用最简单的方式获得 Xray,并且开始使用 Xray。

                                        下载安装

                                        Xray 支持各种平台,并且您可以从多种渠道和方式获得 Xray 的各种版本。

                                        请点击 下载安装 以获取 Xray

                                        配置运行

                                        下载并安装 Xray 后,只需对他进行配置即可使用。

                                        请点击 配置运行 以学习最简单的配置方式。

                                        命令参数

                                        Xray 有多种命令和参数可用,因此变得灵活和强大。

                                        请点击 命令参数 查看 Xray 的更多命令和参数用法。

                                        改进文档

                                        如果你有兴趣,请点击 使用文档 帮助我们改进文档,或者点击页面下方的 帮助我们改善此页面!

                                        我们十分感谢每一位 Contributor 作出的贡献!是你们让 Project X 变得更加强大!

                                        小小白白话文

                                        给予新手指导的使用心得

                                        请点击 小小白白话文 以进行查看。

                                        入门技巧

                                        具备了基础之后,你就可以通过 入门技巧 来探索更多的使用方式了。

                                        进阶文档

                                        给予进阶用户指导的使用技巧

                                        点击 进阶文档 以进行查看

                                        感谢

                                        非常感谢大家无私分享使用技巧和心得, 使得 Xray 日益强大。

                                        - + diff --git a/document/install.html b/document/install.html index 0d313cc1b4..40b3bcedc9 100644 --- a/document/install.html +++ b/document/install.html @@ -24,11 +24,11 @@ 下载安装 | Project X - - + + -

                                        下载安装

                                        平台支持

                                        Xray 在以下平台中可用:

                                        • Windows 7 及之后版本(x86 / amd64 / arm32 / arm64);
                                        • macOS 10.10 Yosemite 及之后版本(amd64 / arm64);
                                        • Linux 2.6.23 及之后版本(x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                          • 包括但不限于 Debian 7 / 8、Ubuntu 12.04 / 14.04 及后续版本、CentOS 7 / 8、Arch Linux 等;
                                        • FreeBSD (x86 / amd64);
                                        • OpenBSD (x86 / amd64);
                                        • Dragonfly BSD (amd64);

                                        下载 Xray

                                        预编译的二进制 ZIP 格式压缩包可在 Github Releasesopen in new tag 中找到。

                                        下载对应平台的压缩包,解压后即可使用。

                                        验证安装包

                                        Xray 提供两种验证方式:

                                        • ZIP 压缩包的 SHA1 / SHA256 摘要
                                        • 可复现构建:请参照 编译 Xray

                                        Windows 安装方式

                                        macOS 安装方式

                                        Linux 安装方式

                                        安装脚本

                                        Arch Linux

                                        Arch User Repository

                                        需要使用 AUR helpersopen in new tag,以 yayopen in new tag 为例,可通过 yay -S xray 安装。

                                        Arch Linux CN

                                        首先添加 Arch Linux CN 仓库open in new tag,然后在 root 用户下使用 pacman -S xray 安装。

                                        Linuxbrew

                                        Linuxbrew 包管理器的使用方式与 Homebrew 一致:brew install xray

                                        Debian WIP

                                        Gentoo

                                        目前有三个第三方 Overlay 提供 Portage 安装脚本:

                                        使用 layman 或 eselect-repository 添加 Overlay 至本地,然后即可安装。

                                        Docker 安装方式

                                        Docker image 的文件结构

                                        • /etc/xray/config.json:配置文件
                                        • /usr/bin/xray:Xray 主程序
                                        • /usr/share/xray/geoip.dat:IP 数据文件
                                        • /usr/share/xray/geosite.dat:域名数据文件

                                        图形化客户端

                                        UUID 生成器

                                        第三方的 UUID 生成器 uuidgenerator.netopen in new tag

                                        - +

                                        下载安装

                                        平台支持

                                        Xray 在以下平台中可用:

                                        • Windows 7 及之后版本(x86 / amd64 / arm32 / arm64);
                                          • Windows 7 中使用 1.8.4、1.8.6 的常规版本以及 1.8.18 以后的 win7 版本需要系统安装有 KB4474419 更新方可使用;推荐同时安装 KB4490628 以便联网后接受后续的操作系统安全更新。
                                        • macOS 10.10 Yosemite 及之后版本(amd64 / arm64);
                                        • Linux 2.6.23 及之后版本(x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                                          • 包括但不限于 Debian 7 / 8、Ubuntu 12.04 / 14.04 及后续版本、CentOS 7 / 8、Arch Linux 等;
                                        • FreeBSD (x86 / amd64);
                                        • OpenBSD (x86 / amd64);

                                        下载 Xray

                                        预编译的二进制 ZIP 格式压缩包可在 Github Releasesopen in new tag 中找到。

                                        下载对应平台的压缩包,解压后即可使用。

                                        验证安装包

                                        Xray 提供两种验证方式:

                                        • ZIP 压缩包的 SHA1 / SHA256 摘要
                                        • 可复现构建:请参照 编译 Xray

                                        Windows 安装方式

                                        macOS 安装方式

                                        Linux 安装方式

                                        安装脚本

                                        Arch Linux

                                        Arch User Repository

                                        需要使用 AUR helpersopen in new tag,以 yayopen in new tag 为例,可通过 yay -S xray 安装。

                                        Arch Linux CN

                                        首先添加 Arch Linux CN 仓库open in new tag,然后在 root 用户下使用 pacman -S xray 安装。

                                        Linuxbrew

                                        Linuxbrew 包管理器的使用方式与 Homebrew 一致:brew install xray

                                        Debian WIP

                                        Gentoo

                                        目前有三个第三方 Overlay 提供 Portage 安装脚本:

                                        使用 layman 或 eselect-repository 添加 Overlay 至本地,然后即可安装。

                                        Docker 安装方式

                                        Docker image 的文件结构

                                        • /etc/xray/config.json:配置文件
                                        • /usr/bin/xray:Xray 主程序
                                        • /usr/share/xray/geoip.dat:IP 数据文件
                                        • /usr/share/xray/geosite.dat:域名数据文件

                                        图形化客户端

                                        UUID 生成器

                                        第三方的 UUID 生成器 uuidgenerator.netopen in new tag

                                        + diff --git a/document/level-0/ch01-preface.html b/document/level-0/ch01-preface.html index 925545e4c9..0c0ec30247 100644 --- a/document/level-0/ch01-preface.html +++ b/document/level-0/ch01-preface.html @@ -24,11 +24,11 @@ 【第 1 章】 小小白白话文 | Project X - - + +

                                        【第 1 章】 小小白白话文

                                        1.1 这篇文档是写给谁的?

                                        一句话:写给 ① 零基础 ② 希望学习自建 VPS 的新人。

                                        1.2 这篇文档不是写给谁的?

                                        包括但不限于:各路大神大能、懒得自己折腾的小白、已经会折腾的高手、确定要用机场的土豪、确定要用一键脚本的逍遥派...... 总之只要有技术基础、或不愿不想自建的同学,您直接关闭本文即可,因为这篇文章大概是入不了您的法眼的,更可能会让您生一肚子闲气,那多划不来。

                                        1.3 郑重声明及其他声明

                                        郑重声明:

                                        鄙人技术奇菜无比,故本文必然挂一漏万破绽百出。您若发现问题还请温柔提醒,莫要人参公鸡。

                                        免责声明:

                                        本文内容请您自行判断是否可信可靠可用,若您根据本文内容建立和使用 VPS 服务器时出了任何问题和不良结果,鄙人概不负责。

                                        啰嗦声明:

                                        基于本文【零基础用户】的目标受众,许多内容会尽力详尽说明,所以语言偏啰嗦,请做好心理准备。

                                        1.4 为什么自建是个难题?

                                        要回答这个问题,就需要稍微多说一点背景信息了。

                                        一、科学上网这件事

                                        科学上网这件事情,说来已经发展了近二十年(震惊!!!.jpg)。最初,自己稍微动动手即可(改改 host、连一下 ssh)、后来需要找一个网页代理,再后来需要写一个私有协议(比如 Shadowsocks)等等。

                                        随着 GFW 技术这十几年来不断的迭代升级,若要完成【自己动手科学上网】这个目标,需要做的事情已经包括但不限于:

                                        • 了解 Linux 系统基本命令
                                        • 了解网络传输协议
                                        • 有技术和经济能力完成 VPS 购买及管理
                                        • 有技术和经济能力完成域名购买及管理
                                        • 有技术能力完成 TLS 证书申请 等等。

                                        这就让【自建 VPS 科学上网】这个曾经简单的行为逐渐变成了令新人望而生畏的挑战。

                                        二、零基础用户的无奈

                                        零基础的非技术用户,如果完成上面这一连串的操作,势必要学习大量的知识,但稍微搜索之后,新人只怕会更加迷茫:大量的信息散布在互联网的各个角落:博客、问答网站、群组、论坛、GitHub、Telegram、YouTube 等等等等)。这些信息纷乱复杂、水平良莠不齐、甚至可能互相矛盾。基本上就是不把新人彻底弄晕誓不罢休。

                                        面对这些杂乱无章的信息,新人突然就从【信息匮乏】变成了【信息过剩】。若是几番连蒙带猜的折腾以失败告终(大概率如此)的话,他的积极性势必大受挫折。在这个过程中,若他又恰好去了一些不太友好的地方去求助,恐怕还要雪上加霜的被嘲讽一番:“这么菜,用机场不就行了,瞎折腾什么啊!”、“先去学会 Linux 再回来问吧”。

                                        这时候,大概也只有一声“呵呵”可以表达心情了。

                                        1.5 “用机场不就行了?”

                                        首先,我想反问一下那些冷嘲热讽的人:“用机场”真的就是万灵药吗?

                                        其次,我认为“不懂”和“不想懂”是有本质区别的。态度恶劣的巨婴伸手党自然惹人厌烦,但真心自学却不得要领的人不该受到无端的白眼和歧视,也正是这种对新人不加区分的恶劣社区氛围促使我写下本文。那么闲话少说,我们来看看机场的优势与劣势究竟如何:

                                        一、“机场“的优势

                                        所谓“机场”,就是“线路提供商”。他负责完成 1.4 提到的那一串技术操作和管理,用户则付费获得使用权。所以,它的优点至少有:

                                        1. 用户操作简单:扫码操作、一键添加规则等
                                        2. 线路选择多:可解锁不同国家、地区的网络服务;比如 iplc 等专线服务、游戏加速服务等
                                        3. 接入节点多:所以抵抗节点封锁的能力强一些,封了一个就换下一个

                                        二、“机场”的风险

                                        “方便”这枚硬币的另一面就是“风险”,基于“机场”的技术特点和市场情况,它的风险至少有:

                                        1. “机场”可完全获得用户信息:用户在网上的所有痕迹,都【必然】经过且【非常可能】长期存储在其服务器上,这些记录无法受到任何具备法律效力的用户隐私协议的约束(窥视、记录你的一举一动
                                        2. “机场”缺乏市场管理:不可避免存在着以欺诈为目标的恶意商家(主动跑路
                                        3. “机场”面临监管压力:大机场相对有保障的同时,也无法避免树大招风。2020 年间,已经有几个大机场停运、跑路的事件发生,用户的正常使用受到严重干扰(被动跑路
                                        4. “机场”技术水平难以确定:线路质量良莠不齐,挂羊头卖狗肉的现象屡见不鲜(速度慢、掉线多、连不上

                                        1.6 那么你到底要不要自建呢?

                                        现在,你已经看到了机场的优势和风险,要用什么,就请各位充分思考并自行决定。毕竟,最适合你的方案才是最好的方案。

                                        It's Your Choice!

                                        1. 如果决定使用机场的话,现在,你可以关闭本文了。

                                        2. 如果你决定自建,那就请继续阅读后面的章节吧!!

                                        总之,本文的目标就是成为零基础用户的知识起点,提供对每一步充分的讲解和演示,清清楚楚(甚至婆婆妈妈、絮絮叨叨、啰啰嗦嗦)的协助新人完成【从输入第一条命令开始,完成 VPS 服务器部署,并成功在客户端完成科学上网】的全程。并在这个过程中帮助新人逐步接触和熟悉 Linux 的基础操作,为之后的进一步自学打下基础。

                                        1.7 题外啰嗦几句

                                        1. 墙外的信息泥沙俱下,请务必学会理性、独立的思辨,不要随意站队,不要轻信猎奇的信息。

                                        2. 衷心希望大家获得更顺畅的网络后,可以获取更新鲜的知识、更丰富的娱乐、接触更美好的世界、结交更多志同道合的朋友,但不要成为任何有不可告人目的之人的替罪羊。

                                        3. 你的互联网身份依然是你的身份,绝对的匿名化是极为困难的,所以请务必遵守你个人所在地区和 IP 所在地区的相关法律法规。无论何时,自我保护都是最基本的底线。

                                        1.8 你的进度

                                        ⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

                                        - + diff --git a/document/level-0/ch02-preparation.html b/document/level-0/ch02-preparation.html index 5d0f199a1c..1c4096b28a 100644 --- a/document/level-0/ch02-preparation.html +++ b/document/level-0/ch02-preparation.html @@ -24,11 +24,11 @@ 【第 2 章】原料准备篇 | Project X - - + +

                                        【第 2 章】原料准备篇

                                        这一章比较特殊,因为涉及到金钱交易行为,本文基于项目的中立立场,不做具体的推荐。我能做的,是告诉你需要准备哪些东西。

                                        2.1 获取一台 VPS

                                        你需要获取一台健康的、IP 没有被墙的 VPS,并在管理后台做下面这些基础准备:

                                        1. 在 VPS 的后台安装 Debian 10 64bit 系统
                                        2. 小本本记下 VPS 的 IP 地址(本文会用 "100.200.300.400" 来表示)

                                          提示

                                          这是一个故意写错的非法 IP,请替换成你的真实 IP)

                                        3. 小本本记下 VPS 的 SSH 远程登陆端口(Port)
                                        4. 小本本记下 SSH 远程登录的用户名和密码

                                        购买 VPS 是一个比较复杂的事情,建议先去学习一下相关知识,选择适合自己的经济能力和线路需求的即可。另外可以选择薅一些国际大厂的羊毛(比如甲骨文和谷歌提供的永久免费或限时免费的套餐)。总之,务必量力而行。

                                        说明

                                        关于选择 Debian 10 作为操作系统,这里稍微多说一句:不管你在网上听说了什么,不管哪个大神告诉你 XXX 版的 Linux 更好、XXX 版的 Linux 更牛,这些 Linux 的派系之争跟现在的你半毛钱关系也没有!使用 Debian 10 足以让你的 VPS 服务器在安全、稳健运行的同时得到足够的优化(如 cloud 专用内核、及时的 bbr 支持等)。等你对 Linux 熟悉之后,再回头去尝试其他的 Linux 发行版也不迟。

                                        2.2 获取一个心仪的域名

                                        你需要获取一个域名、并在 DNS 设置中添加一条 A 记录,指向你 VPS 的 IP 地址

                                        1. 请选择靠谱的国际域名服务商。选择一些常见的域名后缀就行,注意不要用 .cn 后缀。
                                        2. 在 DNS 设置中,添加一条指向你 VPS 的 IP 地址的 A 记录(A 记录的名字可以随便起,本文会用 "a-name" 来表示。完整的域名则会用 "二级域名.你的域名.com" 或者 "a-name.yourdomain.com" 来表示)。效果如下图:

                                        添加A记录

                                        提示

                                        不是一个真实可用的网址,请替换成你的真实网址

                                        2.3 你本地电脑上需要安装的软件

                                        1. SSH 远程登录工具

                                        2. 远程文件拷贝工具

                                        3. 靠谱的文本编辑器

                                        2.4 你的进度

                                        如果上面的原材料你都准备好了的话,你已经拿到了开启新世界大门的钥匙。那还等什么,让我们快点进入下一章,走进这扇门吧!

                                        ⬛⬛⬜⬜⬜⬜⬜⬜ 25%

                                        - + diff --git a/document/level-0/ch03-ssh.html b/document/level-0/ch03-ssh.html index 0e21ce38e7..1e56610612 100644 --- a/document/level-0/ch03-ssh.html +++ b/document/level-0/ch03-ssh.html @@ -24,13 +24,13 @@ 【第 3 章】远程登录篇 | Project X - - + +

                                        【第 3 章】远程登录篇

                                        3.1 远程登录 VPS (PuTTY)

                                        首先,鉴于零基础人群中 Windows 的用户基数最大,所以本文以 Windows 为例进行展示。

                                        其次,虽然 Windows 10 之后的 PowerShell 和 WSL 也可以达到很好的 SSH 操作体验。但是因为并非所有版本的 Windows 都有最新的组件,故本文还是以老牌的 PuTTY 为例,进行 SSH 远程登录的操作详解。(使用其他工具的话、在 SSH 登陆之后的操作都是一样的)

                                        下面就跟我一步步操作吧。

                                        1. 进入 PuTTY 的官网open in new tag,选择适合你操作系统的版本下载。(本文以 64 位版本为例)

                                          下载PuTTY

                                        2. 安装运行后,将会看到 PuTTY 的主界面。现在请拿出你上一章记东西的小本本,在下图的对应位置填入你 VPS 的IP 地址(VPS IP)端口(VPS PORT)。为了方便以后使用时不用重复输入,我们可以保存会话 (Saved Sessions),未来使用时只要按 Load 即可一键载入设置。

                                          设置PuTTY

                                        3. 我建议将 Connection 中的 keepalive 设置为 60 秒,防止你一段时间没有操作之后 SSH 自动断线。另外务必再次保存设置。

                                          防止频繁断线

                                        注意

                                        对 PuTTY 的任何设置更新都要再次手动保存 Session,不然关闭后就会丢失

                                        1. 点击 Open 就会进入 SSH 连接窗口,对应下图输入用户名与密码,与你的 VPS 远程主机建立连接。(本文假设默认用户名是 root,另外,在 Linux 系统输入密码的时候,是不会出现 ****** 这种提示符的,这样可以避免密码长度泄漏,不是你的键盘坏掉了哦!)

                                          SSH远程登录

                                        3.2 成功登录 SSH!初识命令行界面!

                                        1. 如果你的信息都填写正确,你将会看到类似下图的界面,说明已登录成功:

                                          初次登录VPS

                                          这个界面,就等于远程服务器的【桌面】,但它没有你熟悉的图标和鼠标,没有绚丽的色彩,有的只是简单文字,这就是【命令行界面】- Command Line Interface,或者缩写为 CLI

                                          接下来的所有操作,都需要你像电影里的黑客一样,在这个命令行界面中完成。也许你会觉得陌生,但请相信我,使用命令行既不可怕,也不神秘。说到底,它只不过是把你习惯的鼠标操作变成了文字指令而已,你说一句,它做一句

                                        2. 现在,你可以稍微观察并熟悉一下命令行环境,这个界面其实已经告诉了你一些有用的信息了,比如系统内核版本(比如图内是 4.19.37-5)、上次登录时间及 IP 等。当然根据 VPS 的不同,你看到的界面可能会略有不同。

                                        3. 请注意命令行最下面一行,闪动的光标左边,有一串字符。图中显示的是root@vps-server:~#,这一串要怎么理解呢?很简单:

                                          • 现在的用户是 root
                                          • root 所在的服务器是 vps-server
                                          • root 现在所在的文件夹是 ~
                                          • # 之后是你可以输入命令的地方

                                          前两个很直观,无需多说。第三个是关于 Linux 的文件夹系统,现在也不需要过于深入,你只需要知道,"~"就是【当前用户的大本营】。第四个,提示符#,你也不用管,只需要知道,未来文章中会写一些需要你输入的命令,都会以 "#" 或者 "$" 开头,提示你后面是你输入命令的地方。(所以你复制命令的时候,只需要复制后面的内容,不要复制提示符)

                                        3.3 第一次更新 Linux 的软件!

                                        1. 正如你的手机,无论安卓还是 iPhone,为了 APP 及时更新(获取安全补丁和新功能),都会时不时从应用商店获得更新信息,并且提示你有多少个 APP 可更新。Linux 系统也有逻辑十分类似的更新机制。所以只要你会更新手机 APP,就能学会更新 Linux 软件!

                                        2. Linux 下,每个 APP 都叫做一个“包” (package)。管理 APP 的程序自然就叫做“包管理器”(Package Manager)。你可以通过它安装、更新、卸载各种软件、甚至更新 Linux 系统本身。Linux 下的包管理器非常强大,此处按下不表,现在你只需要知道 Debian 系统的包管理器叫做 apt 即可。接下来,我们就先使用 apt 做一次软件的全面更新,让你熟悉它的基本操作。

                                        3. 小小白白 Linux 基础命令:

                                          编号命令名称命令说明
                                          cmd-01apt update查询软件更新
                                          cmd-02apt upgrade执行软件更新
                                        4. 现在请输入第一条命令,获取更新信息

                                          apt update
                                           
                                        5. 然后请输入第二条命令,并在询问是否继续安装 (Y/n) 时输入 y 并回车确认,开始安装

                                          apt upgrade
                                           
                                        6. 完整流程演示如下:

                                          初次软件更新流程演示

                                        3.4 你的进度

                                        恭喜你又迈出了坚实的一步! 现在,你已经可以通过 SSH 来登录你的远程服务器了!那登录进去之后,除了升级软件之外,应该再做点什么呢?敬请进入下一章一探究竟吧!

                                        ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%

                                        - + diff --git a/document/level-0/ch04-security.html b/document/level-0/ch04-security.html index 0e1ebe6bff..8f9900e987 100644 --- a/document/level-0/ch04-security.html +++ b/document/level-0/ch04-security.html @@ -24,8 +24,8 @@ 【第 4 章】安全防护篇 | Project X - - + +

                                        【第 4 章】安全防护篇

                                        4.1 为什么要做安全防护

                                        Linux 服务器的安全防护是一个纷繁复杂的巨大课题。无数的网站、APP、服务、甚至线下基础设施都建立在 Linux 的基石之上,这背后牵涉到巨大的经济利益和商业价值,当然也就就意味着黑灰产有巨大的攻击动力。但是这些服务是如此重要、根本不允许出现重大的安全漏洞。于是无数的运维专业人员都在安全攻防的战场上拼搏努力,这才让大家能享受到基本稳定的现代化数字生活。

                                        现在,你拥有了一台 VPS,并且将会敞开他的数据访问渠道来达到流量转发的目标,那就相当于你已经置身于安全攻防战场的第一线、直面所有风险。但与此同时,新人由于知识和信息的不足,看待安全问题是总是难免两极分化:要么觉得轻如鸿毛和自己没有半点关系,要么觉得重于泰山甚至惶惶不可终日。

                                        • 对于前者,我的建议是:安全无小事,尽量多查一些安全方面的信息,免得自己真的受了损失才后悔莫及

                                        • 对于后者,我的建议是:不用紧张,我们的服务器仍不具有太高的价值、一般不会吸引到高水平的攻击,需要面对的基本都是一些自动化脚本的恶意扫描和登录尝试,跟着本文做一些基础的防护即可

                                        4.2 具体的风险到底是什么

                                        就像我们在《远程登录篇》配置的一样,任何人只需要知道【IP 地址】+【端口】+【用户名】+【密码】这四个要素,就能登录你的 VPS 服务器。那很显然,这四要素的安全就是我们要防护的底线。我们来逐一分析:

                                        1. 【IP 地址】:恶意脚本会随机尝试和扫描 IP 段,可以简单认为是公开信息、无法隐藏

                                        2. 【端口】:如果使用默认端口,那么【端口 = 22

                                        3. 【用户名】:如果使用默认用户,那么【用户名 = root

                                        4. 【密码】:密码不存在默认值,一定是由 VPS 后台随机生成或由你自行设置的。也就是说,如果你的服务器都是默认设置,则四要素中的三个已经是已知的,那么你整个服务器的安全,就全部寄托在一串小小的密码上了。这时有几种情况:

                                          • 如果你用了 VPS 管理后台随机生成密码,它一般包含随机的十几个大小写混杂的字母和符号,相对比较安全

                                          • 如果你为了好记、把密码改成了类似123456这种超弱的密码,破解你的 VPS 服务器可谓不费吹灰之力

                                          • 如果你为了好记、把密码改成了比较复杂、但在别的地方用过的密码,其实也并不安全。你要明白黑客手里有作弊器,比如说密码表,包含数万、数十万、数百万甚至更多曾经泄漏的真实密码)

                                        5. 但你要明白,没有哪个黑客真的要坐在电脑前一次一次的尝试你的密码,全部的攻击尝试都是恶意脚本自动进行的,它会 24 小时不眠不休的工作。也许每天你酣睡之时,你的服务器都在经受着一轮又一轮的冲击。

                                          一旦密码被成功撞破,意味着你的四要素全部被攻击者掌握,恶意脚本就会快速登录服务器、获取服务器的最高 root 控制权、安装部署它的恶意服务,然后就可以用你的服务器来 24 小时做各种坏事(比如挖矿、传播病毒、发送垃圾邮件、欺诈邮件、做 BT 中继、甚至暗网公众节点等等等等)。如果恶意脚本比较克制,其实可以做到相当的隐蔽性。而新人一般也不会去观察留意 VPS 的登录记录、进程变化、CPU 占用变化、流量变化等指标,你其实就很难发现自己被黑了。直到你的 VPS 服务商封禁你的账号、或者收到律师函为止。

                                        6. 别忘了,你获得 VPS 时大概率需要使用真实的支付信息,你登录各种网站、社交平台时也会留下你的 IP 地址,这些都与你的身份有直接或者间接的关系。于是,一旦这些坏事发生,它们就不可避免的与你产生了关联。

                                        4.3 我们要做的安全防护有哪些

                                        基于上述分析,我们要做的,自然就是对【端口】、【用户名】、【密码】这三要素进行加强,来降低被攻破的风险:

                                        1. 【端口】:将 SSH 远程登录端口修改为【非 22 端口】 (4.4)
                                        2. 【用户名】:建立【非 root】的新用户、并禁用 root 用户 SSH 远程登录 (4.5、4.6)
                                        3. 【密码】:SSH 启用 RSA 密钥验证登录、同时禁用密码验证登录 (4.7)

                                        记得按顺序来,别把自己锁在门外了。

                                        4.4 将 SSH 远程登录端口修改为非 22 端口

                                        现在,我们来解决【端口 = 22】的问题。(注意:有些 VPS 服务商,默认的端口已经是非 22 端口,那么你可以忽略这一步,当然也可以跟着本文改成别的端口)

                                        1. 小小白白 Linux 基础命令:

                                          编号命令名称命令说明
                                          cmd-03nano文本编辑器
                                          cmd-04systemctl restart重启某个服务
                                        2. 小小白白 Linux 基础配置文件

                                          编号配置文件位置文件说明
                                          conf-01/etc/ssh/sshd_configSSH 远程登录程序设置
                                        3. 我们要做的第一件事,当然就是【用nano这个文本编辑器打开SSH远程登录程序设置】,在 Windows 下,你会【找到文件并双击】,在 Linux 下该怎么办呢?仔细看看上面的命令说明,是不是就很简单了?没错,就是:

                                          nano /etc/ssh/sshd_config
                                          @@ -40,6 +40,6 @@
                                           
                                        4. 修改 SSH 配置。这个我们已经用了很多次,但现在我们已经从无所不能的root变成了普通用户vpsadmin,此时的我们是没有权限直接编辑 SSH 配置的。这时候就需要使用sudo命令了:

                                          sudo nano /etc/ssh/sshd_config
                                           
                                        5. 找到(ctrl+w) PasswordAuthentication 改成 no

                                        6. 找到(ctrl+w) PubkeyAuthentication 改成 yes,然后保存(ctrl+o)退出(ctrl+x)

                                        7. 重启 SSH 服务。(啰嗦君:别忘了现在需要使用sudo来获得权限)

                                          sudo systemctl restart ssh
                                           
                                        8. 完整流程如下:

                                          SSH开启密钥验证并禁用密码验证

                                      112. VPS 端已经设置好了公钥,现在要给 PuTTY 指定私钥位置供登录时使用(啰嗦君:别忘了保存 Session)

                                        PuTTY指定私钥位置

                                      113. 至此,【密钥登录】已成功开启、【密码验证】已成功关闭、并且还给 PuTTY 保存了默认的登录用户名和私钥。未来使用 PuTTY 登录时,载入VPS-SERVER配置后,点击Open就可以一键登录了。

                                        如果你给私钥设置了密码保护,登录时当然还需要输入这个密码才能使用密钥,如下图:

                                        输入私钥密码

                                      114. 别忘了给WinSCP也做对应的密钥设置,否则之后想要传输文件时就无法登录了:

                                        WinSCP指定私钥位置

                                      注意

                                      任何需要借助 SSH 进行登录的软件都需要密钥验证了,软件过多,无法逐一展示,请根据你的需要自行设置好哦

                                      4.8 你的进度

                                      到这里为止,你的 VPS 已经完成了【端口】、【用户名】、【密码】这三要素的基本安全保障,虽然远称不上固若金汤,但一般的恶意脚本应该已经无法对你造成伤害了!

                                      现在我们终于有了一个安全的系统基础,下一章,我们就可以开始逐步安装配置 Xray 需要的基础设施了!(什么基础设施呢?一个网页,一张证书)

                                      ⬛⬛⬛⬛⬜⬜⬜⬜ 50%

                                  4. - + diff --git a/document/level-0/ch05-webpage.html b/document/level-0/ch05-webpage.html index 567a50aaff..03e58a4db1 100644 --- a/document/level-0/ch05-webpage.html +++ b/document/level-0/ch05-webpage.html @@ -24,8 +24,8 @@ 【第 5 章】网站建设篇 | Project X - - + +

                                    【第 5 章】网站建设篇

                                    5.1 为什么要做一个网站?

                                    新人也许会迷惑,为什么科学上网还要建一个网站?我不会编程啊,是不是特别麻烦?

                                    先回答第一个问题,建网站的原因有:

                                    1. 申请合法的 TLS 证书(非常重要)
                                    2. 提供合理的回落,防止主动探测攻击,提高安全性
                                    3. 建设一个伪装站(如博客、私人网盘、多媒体网站、游戏网站等),直接访问时有合理的前台,使流量使用看上去更合理。

                                    再回答第二个问题:

                                    1. 本文作为演示,仅仅使用了一个最简单的【单文件 html 页面 + Nginx】来搭建,以此完成上面的目标,所以【非常简单】
                                    2. 这个网站完全可以不仅仅是伪装,而是真的做大做强,这个复杂性就完全取决于你了
                                    3. 对于“伪装”和“网站运营”这个目标,需要的就是各不相同、秀出真我,需要的同学可以自行搜索学习。这个内容已经完全偏离了科学上网,本文就不深入解析了。

                                    5.2 登录 VPS、安装运行 Nginx

                                    1. 这里用到的,都是之前已经详解过的命令,所以就不重复讲解了。看不懂的同学可以看看前面的章节哦。

                                      sudo apt update && sudo apt install nginx
                                      @@ -90,6 +90,6 @@
                                               }
                                       

                                      特别注意!

                                      如我在【第 3 步】中的提示所说,请务必确保 /home/vpsadmin/www/webpage 改成你的实际文件路径。

                                    2. nginx 重新载入配置使其生效

                                      sudo systemctl reload nginx
                                       
                                    3. 完整的设置流程如下:

                                      网页设置演示

                                    4. 此时如果你访问 http://二级域名.你的域名.com,你看到这样的页面则说明成功:

                                      http网页成功

                                  5.4 常见错误的说明

                                  首先,如果你一路按照文章的说明来操作,并且足够细心,那肯定不会出错。所以,我并不打算修改本文的写法。

                                  那为什么依然有很多同学卡在了这一步,网页怎么也打不开呢?基本上就是两个字:粗心。因为这里配置可能出现的问题只有两种,原因也只有两个。

                                  一、两种问题:

                                  • nginx.conf 里面的 /home/vpsadmin/www/webpage 这一条,与你的实际文件路径不符,nginx 找不到文件
                                  • 路径正确,但 nginx 无权读取

                                  二、两个原因:

                                  • 使用了【非 root 用户】,但仍然直接拷贝文中的命令不加修改。(这基本就等于抄答案时把同学的名字一起抄过去了)
                                  • 坚持使用【 root 用户】

                                  碰到错误的同学,就回过头仔细看一下【5.3】中【第 3 步】和【第 5-2 步】的说明吧。

                                  注意

                                  本文前期已经用了大量篇幅说明了使用【非 root 用户】对安全的重要性,全文也是基于此而写。所以,因使用【 root 用户】而导致的问题并不在本文的设计范围里。

                                  但我相信,坚持使用【 root 用户】的同学应该是有主见、动手能力强、或者有一定 Linux 基础的同学。问题的症结我已经全部说明了,我相信你一定可以自行解决。

                                  5.5 你的进度

                                  至此,Xray 的第一个基础设施【网页】已经就位,我们马上就进入第二个基础设施【证书】吧!

                                  ⬛⬛⬛⬛⬛⬜⬜⬜ 62.5%

                              - + diff --git a/document/level-0/ch06-certificates.html b/document/level-0/ch06-certificates.html index 229829d57a..b74c7008cd 100644 --- a/document/level-0/ch06-certificates.html +++ b/document/level-0/ch06-certificates.html @@ -24,8 +24,8 @@ 【第 6 章】证书管理篇 | Project X - - + +

                              【第 6 章】证书管理篇

                              6.1 申请 TLS 证书

                              接下来我们要做的,是为我们的域名申请一个真实的 TLS 证书,使网站具备标准 TLS 加密的能力及 HTTPS 访问的能力。这就是 Xray 等现阶段安全代理工具确保流量充分加密最重要的工具。

                              注意

                              请不要轻易使用自签证书。它并没有让操作简单太多,但增加了无谓的风险(如中间人攻击)。

                              这里我会使用一个叫做 acme.shopen in new tag 的证书管理工具,它简单、轻量、高效,并可完成证书自动更新。

                              另外,我相信,现在你已经逐渐熟悉了 Linux 的基础操作,所以已经多次出现的命令从本章开始不再重复截图、只做简单的描述。如果实在想不起来怎么用的话,就稍微复习一下前面的章节吧。

                              6.2 安装 acme.sh

                              1. 小小白白 Linux 基础命令:

                                编号命令名称命令说明
                                cmd-12wget访问(或下载)某个网页文件
                                cmd-13acme.shacme.sh 证书管理相关的命令
                              2. 运行安装脚本

                                wget -O -  https://get.acme.sh | sh
                                @@ -136,6 +136,6 @@
                                 [Mon 14 Feb 2022 03:00:25 PM CST] Installing key to: /etc/xray/cert/cert.key
                                 [Mon 14 Feb 2022 03:00:25 PM CST] Installing full chain to: /etc/xray/cert/fullchain.crt
                                 

                              6.6 你的进度

                              至此,Xray 所需要的两个基础设施终于全部就位!千呼万唤始出来的 Xray 马上就要揭开面纱,我们终于要进入最激动人心章节啦!

                              ⬛⬛⬛⬛⬛⬛⬜⬜ 75%

                              - + diff --git a/document/level-0/ch07-xray-server.html b/document/level-0/ch07-xray-server.html index 8536416cf3..d431905265 100644 --- a/document/level-0/ch07-xray-server.html +++ b/document/level-0/ch07-xray-server.html @@ -24,8 +24,8 @@ 【第 7 章】Xray 服务器篇 | Project X - - + +

                              【第 7 章】Xray 服务器篇

                              7.1 博观而约取,厚积而薄发

                              本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!)

                              其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连nano都无法正确使用,也不会用WinSCP,远程手写编辑出来的config.json自然错误百出,连查错也变得举步维艰。

                              注意

                              经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray 时会有一种【水到渠成】的轻快感觉。

                              后面要做的事情非常简单:

                              1. 安装
                              2. 配置(如安装 TLS 证书、config.json
                              3. 运行
                              4. 优化(如更新内核、开启bbr、网站http访问自动跳转https等)

                              7.2 安装 Xray

                              首先,Xray 的官方载体,就是 xray-coreopen in new tag 开源项目(基于 MPL 2.0 开源协议)生成的二进制程序。你把这个二进制放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。主要区别来源于【配置】。

                              安装时,直接使用官方安装脚本就很简单直接。它提供了多种安装选项,有兴趣的可以去官方的安装脚本仓库open in new tag中看看脚本的说明,本文使用的是【非 root 用户】安装模式

                              写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。

                              1. 小小白白 Linux 基础命令:

                                编号命令名称命令说明
                                cmd-14rm删除命令
                              2. 将安装脚本下载至本地:

                                wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
                                @@ -188,6 +188,6 @@
                                 
                                1. 修改 Xray 的回落设置,将回落从 80 端口改为 8080 端口。(找到 "dest": 80, 并改成 "dest": 8080
                                sudo nano /usr/local/etc/xray/config.json
                                 
                                1. 重启 Xray 服务,即完成了设置
                                sudo systemctl restart xray
                                 
                                1. 完整流程演示如下:

                                http自动跳转https

                                1. 当你输入 http://a-name.yourdomain.com的时候,它应该已经会自动跳转 https 了

                                http自动跳转https生效

                                7.9 服务器优化之三:更丰富的回落

                                如果你需要更丰富的回落功能,可以参考 《回落 (fallbacks) 功能简析》

                                7.10 你的进度

                                恭喜!!到这一步,你已经拥有了可以正常科学上网的服务器、同时也有了可以防止主动探测攻击的伪装网站。接下来,只要给你的客户端装上合适的软件,就可以享受顺畅的网络了!

                                ⬛⬛⬛⬛⬛⬛⬛⬜ 87.5%

                                7.11 重要勘误

                                1. 初版中Xray配置文件config.json文件夹位置错误。若你已经根据之前的位置进行了操作,Xray会无法正确启动。故勘误说明于此,请自查,造成不便十分抱歉!
                                • 正确位置:/usr/local/etc/xray/config.json
                                • 错误位置:/usr/local/etc/config.json

                                受影响章节:

                                • 7.4 配置Xray - 3. 使用nano创建Xray的配置文件
                                • 7.8 服务器优化之二 - 6. 修改Xray的回落设置
                                1. 初版中修改Nginx配置文件nginx.conf时内容错误(网页文件夹位置错误),若你已经根据之前的位置进行了操作,Nginx会无法找到正确的网站。请自查,造成不便十分抱歉!
                                • 正确文件夹位置:root /home/vpsadmin/www/webpage;
                                • 错误文件夹位置:root /var/www/website/html

                                受影响章节:

                                • 7.8 服务器优化之二 - 4. 在与 80 端口同级的位置增加一个本地端口监听来提供网页展示
                              - + diff --git a/document/level-0/ch08-xray-clients.html b/document/level-0/ch08-xray-clients.html index 422f308aa8..300a7db6ef 100644 --- a/document/level-0/ch08-xray-clients.html +++ b/document/level-0/ch08-xray-clients.html @@ -24,8 +24,8 @@ 【第 8 章】Xray 客户端篇 | Project X - - + +

                              【第 8 章】Xray 客户端篇

                              8.1 Xray 的工作原理简述

                              要正确的配置和使用Xray,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置):

                              Xray数据流向

                              这其中的关键点是:

                              1. APP 要主动或借助转发工具,将数据【流入(inbounds)】Xray 客户端

                              2. 流量进入客户端后,会被【客户端路由(routing)】按规则处理后,向不同方向【流出(outbounds)Xray 客户端。比如:

                                1. 国内流量直连(direct
                                2. 国外流量转发 VPS(proxy
                                3. 广告流量屏蔽(block
                              3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(inbounds)】 Xray 服务器端

                              4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(routing)】按规则处理后,向不同方向【流出(outbounds)】:

                                1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(direct
                                2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(proxy
                                3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(block

                              注意

                              请务必记得,Xray 的路由配置非常灵活,上面的说明只是无限可能性中的一种。

                              借助 geosite.datgeoip.dat 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 GFWList 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。)

                              现在,《路由 (routing) 功能简析》 已经上线,我建议对路由功能有兴趣的同学,先继续跟着本文完成客户端的基础配置,之后再去这里详细学习。

                              8.2 客户端与服务器端正确连接

                              现在你已经理解了 Xray 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉PuTTY如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。

                              实际上,Xray的连接要素是由不同的协议决定的。本文在第 7 章的配置文件 config.json 里,我们使用 Xray 下独特而强大的 VLESS 协议 + XTLS 流控。所以看看那个配置文件的内容就能知道,这个协议组合的连接要素有:

                              • 服务器【地址】: a-name.yourdomain.com
                              • 服务器【端口】: 443
                              • 连接的【协议】: vless
                              • 连接的【流控】: xtls-rprx-vision (vision 模式适合全平台)
                              • 连接的【验证】: uuiduuid-uuid-uuid-uuiduuiduuid
                              • 连接的【安全】: "allowInsecure": false

                              鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。

                              注意

                              许多工具其实是同时支持 xray-corev2fly-core 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦!

                              到这一步,你的全套配置就已经可以正常使用啦!

                              8.3 附加题 1:在 PC 端手工配置 xray-core

                              虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把xray-core 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 xray-core 做客户端呢?

                              为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势:

                              • 第一时间获得最新版而无需等待 APP 升级适配

                              • 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能)

                              • 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现)

                              它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤:

                              1. 首先请从 Xray 官方的 GitHub 仓库 Release 页面open in new tag 获取对应平台的版本,并解压缩到合适的文件夹

                              2. 在合适的文件夹建立空白配置文件:config.json (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了)

                              3. 至于什么是“合适的文件夹”?这就取决于具体的平台了~

                              4. 填写客户端配置

                                • 我就以 8.1 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 8.2 的连接要素,写成一个配置文件
                                • 请将 uuid 替换成与你服务器一致的 uuid
                                • 请将 address 替换成你的真实域名
                                • 请将 serverName 替换成你的真实域名
                                • 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了
                                // REFERENCE:
                                @@ -181,6 +181,6 @@
                                 

                              8.4 附加题 2:在 PC 端手工运行 xray-core

                              写好了配置文件该,要怎么让 xray-core 运行起来呢?双击好像并没有反应啊?

                              首先,你要找到电脑上的【命令行界面】。

                              1. Linux 桌面、macOS 系统的同学肯定已经比较熟悉了,搜索 Console 或者 Terminal 就可以
                              2. Windows 就可以搜索使用 Cmd 或者 Powershell 等程序(WSL 的同学你坐下,你的 Console 当然也可以)

                              其次,我们要做的事情是【让 xray 找到并读取配置文件 config.json,然后运行】,所以:

                              1. 在 Windows 下,假设你的 Xray 程序位置是 C:\Xray-windows-64\xray.exe,配置文件位置是C:\Xray-windows-64\config.json,那么正确的启动命令就是:

                                C:\Xray-windows-64\xray.exe -c C:\Xray-windows-64\config.json
                                 

                                说明

                                这里的 -c 就是指定配置文件路径的参数,告诉 xray 去后面的位置找配置文件

                              2. 相似的,在 Linux 和 macOS 下,假设你的 Xray 程序位置是 /usr/local/bin/xray,配置文件位置是/usr/local/etc/xray/config.json,那么正确的启动命令就是

                                /usr/local/bin/xray -c /usr/local/etc/xray/config.json
                                 

                                说明

                                每个系统都有系统路径变量,所以写 Xray 程序时不一定要写绝对路径。但是写了肯定没错,所以我就如此演示了。

                              8.5 附加题 3:在 PC 端开机自动运行 xray-core

                              如果你真的尝试了手动运行 xray-core,你一定会发现这个方式还有点小问题:

                              1. 每次运行 Xray 都要出现一个黑乎乎的窗口,很丑
                              2. 不能开机自动运行,每次都要手工输入,十分不方便

                              我可以肯定的告诉你:完全可以解决。但是具体的解决方式,就当作课外作业留给大家吧!(友情提示,文档站的问答区有线索哦)

                              8.6 圆满完成!

                              我相信,有耐心看到这里的同学,都是兼具好奇心和行动力的学习派!我现在要郑重的恭喜你,因为到了这里,你已经完完整整的【从第一条命令开始,完成了 VPS 服务器部署,并成功的在客户端配置使用 Xray】了!这毫无疑问是一个巨大的胜利!

                              我相信,你现在一定对Linux不再恐惧,对Xray不再陌生了吧!

                              至此,小小白白话文圆满结束!

                              ⬛⬛⬛⬛⬛⬛⬛⬛ 100%

                              8.7 TO INFINITY AND BEYOND!

                              但现在你看到的,远远不是 Xray 的全貌。

                              Xray是一个强大而丰富的网络工具集合,平台化的提供了众多模块,可以像瑞士军刀一样,通过灵活的配置组合解决各种不同的问题。而本文,仅仅蜻蜓点水的用了最简单最直观的配置来做基础演示

                              如果你觉得现在已经完全够用了,那就好好的享受它给你带来的信息自由。但如果你的好奇心依然不能停歇,那就去继续挖掘它无限的可能性吧!

                              需要更多信息,可以到这里寻找:

                              1. xtls.github.ioopen in new tag - 官方文档站
                              2. 官方 Telegram 群组open in new tag - 活跃而友善的官方讨论社区

                              TO INFINITY AND BEYOND!

                              不算后记的后记

                              希望我陪你走过的这一段小小的旅程,可以成为你网络生活中的一份小小助力。

                              这篇文章里的工具和信息难免会一点点的陈旧过时,但你一定会逐渐成长为大佬。未来的某个时间,若你能偶尔想起这篇教程、想起我写下本文的初衷,那我衷心希望你能够薪火相传、把最新的知识分享给后来人,让这一份小小的助力在社区里坚定的传递下去。

                              这是个大雪封山乌云密布的世界,人们孤独的走在各自的路上试图寻找阳光,如果大家偶尔交汇时不能守望相助互相鼓励,那最终剩下的,恐怕只有【千山鸟飞绝 万径人踪灭】的凄凉了吧。

                              - + diff --git a/document/level-0/ch09-appendix.html b/document/level-0/ch09-appendix.html index 8d08ef6644..36f3effaea 100644 --- a/document/level-0/ch09-appendix.html +++ b/document/level-0/ch09-appendix.html @@ -24,11 +24,11 @@ 【第 9 章】附录 | Project X - - + +

                              【第 9 章】附录

                              1. 小小白白 Linux 基础命令索引

                              编号命令名称命令说明出现篇章
                              cmd-01apt update查询软件更新《远程登录篇》
                              cmd-02apt upgrade执行软件更新《远程登录篇》
                              cmd-03nano文本编辑器《安全防护篇》
                              cmd-04systemctl restart重启某个服务《安全防护篇》
                              cmd-05adduser给系统新增用户《安全防护篇》
                              cmd-06apt install安装某个软件《安全防护篇》
                              cmd-07visudo修改 sudo 权限设置专用编辑器《安全防护篇》
                              cmd-08sudoroot权限运行某个命令《安全防护篇》
                              cmd-09chmod修改目标文件/文件夹的权限《安全防护篇》
                              cmd-10mkdir新建文件夹《网站建设篇》
                              cmd-11systemctl reload重新加载某个服务《网站建设篇》
                              cmd-12wget访问(或下载)某个网页文件《证书管理篇》
                              cmd-13acme.shacme.sh 证书管理相关的命令《证书管理篇》
                              cmd-14rm删除命令《Xray 服务器篇》
                              cmd-15crontab -e编辑当前用户的定时任务《Xray 服务器篇》
                              cmd-16touch建立空白文件《Xray 服务器篇》
                              cmd-17systemctlsystemd基本服务管理命令《Xray 服务器篇》
                              cmd-18reboot重启 Linux 系统《Xray 服务器篇》

                              2. 小小白白 Linux 重要配置文件索引

                              编号配置文件位置文件说明出现篇章
                              conf-01/etc/ssh/sshd_configSSH 远程登录程序设置《远程登录篇》
                              conf-02/etc/nginx/nginx.confNginx 程序设置《网站建设篇》
                              conf-03/etc/apt/sources.listapt 软件源列表《Xray 服务器篇》
                              conf-04/etc/apt/sources.list.d/vpsadmin.list用户自定义软件源列表列表《Xray 服务器篇》
                              conf-05crontab -e当前用户的定时任务《Xray 服务器篇》
                              conf-06/etc/sysctl.conf手动设置 kernel 参数《Xray 服务器篇》
                              conf-07/etc/sysctl.d/vpsadmin.conf用户自定义 kernel 参数配置文件《Xray 服务器篇》

                              3. 小小白白 Xray 重要文件索引

                              编号配置文件位置文件说明出现篇章
                              xray-01/usr/local/etc/xray/config.jsonXray 程序设置《Xray 服务器篇》
                              xray-02/home/vpsadmin/xray_cert/xray.certTLS 证书《Xray 服务器篇》
                              xray-03/home/vpsadmin/xray_cert/xray.keyTLS 私钥《Xray 服务器篇》
                              xray-04/home/vpsadmin/xray_log/access.logXray 访问日志《Xray 服务器篇》
                              xray-05/home/vpsadmin/xray_log/error.logXray 错误日志《Xray 服务器篇》
                              - + diff --git a/document/level-0/index.html b/document/level-0/index.html index c7d0f94566..d3edb3832c 100644 --- a/document/level-0/index.html +++ b/document/level-0/index.html @@ -24,11 +24,11 @@ 小小白白话文 | Project X - - + +

                              小小白白话文

                              这个章节是【从零开始】的基础课,新来的同学好好看好好学哦

                              提示

                              Made with ❤️ by @ricuhkaenopen in new tag

                              【第 1 章】 前言罗嗦篇 - 机场还是自建?这是个问题

                              【第 2 章】 原料准备篇 - 工欲善其事,必先利其器

                              【第 3 章】 远程登录篇 - 一桥飞架南北,天堑变通途

                              【第 4 章】 安全防护篇 - 安全不注意,亲人两行泪

                              【第 5 章】 网站建设篇 - 秀出你的美

                              【第 6 章】 证书管理篇 - 领证的才是合法的

                              【第 7 章】 Xray 服务器篇 - 终于等到你

                              【第 8 章】 Xray 客户端篇 - 新的开始

                              【第 9 章】 附录 - 考点都在这里

                              - + diff --git a/document/level-1/fallbacks-lv1.html b/document/level-1/fallbacks-lv1.html index ee265c5776..45ac1ca005 100644 --- a/document/level-1/fallbacks-lv1.html +++ b/document/level-1/fallbacks-lv1.html @@ -24,8 +24,8 @@ 回落 (fallbacks) 功能简析 | Project X - - + +

                              回落 (fallbacks) 功能简析

                              在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

                              1. 回顾《小小白白话文》中的回落

                              如果你用了《小小白白话文》中的Xray 配置,并完成了HTTP 自动跳转 HTTPS 优化,那么你已经有了基于 VLESS 协议的简易回落:

                              {
                              @@ -200,6 +200,6 @@
                                 }
                               }
                               
                            2. 至此,我们就能够完整的画出模板的回落路线了:

                            6. 结语

                            至此,Xray 的【回落】功能就介绍完了。希望本文能够对你理解 Xray 的强大有所帮助。

                            7. 附加题

                            我再无耻的留一个附加题:本文详解的 VLESS-TCP-XTLS-WHATEVERopen in new tag 模板?是否有可以优化的地方?

                            提示:HTTP 自动跳转 HTTPS

                      - + diff --git a/document/level-1/fallbacks-with-sni.html b/document/level-1/fallbacks-with-sni.html index e5778ba9ed..a5758200be 100644 --- a/document/level-1/fallbacks-with-sni.html +++ b/document/level-1/fallbacks-with-sni.html @@ -24,8 +24,8 @@ SNI 回落 | Project X - - + +

                      通过 SNI 回落功能实现伪装与按域名分流

                      VLESS 是一种很轻的协议,和 Trojan 一样,不对流量进行复杂的加密和混淆,而是大隐隐于市,通过 TLS 协议加密,混杂在其他 HTTPS 流量中,在墙内外穿进穿出。为了更好的伪装以应对主动探测,Fallbacks 回落功能随 VLESS 同时出现。这篇教程将演示如何使用 Xray 中 VLESS 入站协议的回落功能配合 Nginx 或 Caddy 在保证伪装完全的前提下实现按域名分流。

                      应用情景

                      由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题:

                      • Xray 监听其他常用端口(如 22、3389、8443)

                        这个方案是最简单的,但不够完美。

                      • Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用

                        这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。

                      • Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy

                        这个方案难度适中,也是此教程接下来想要演示的方案。

                      SNI 简介

                      服务器名称指示(英语:Server Name Indication,缩写:SNI)是 TLS 的一个扩展协议。熟悉反向代理的朋友都知道,如果想要通过域名将流量代理到正确的内容上,需要以下配置:

                      proxy_set_header Host 主机名;
                      @@ -210,6 +210,6 @@
                           redir https://{host}{uri} permanent
                       }
                       

                      参考

                      1. 服务器名称指示 - 维基百科,自由的百科全书open in new tag
                      2. Home · acmesh-official/acme.sh Wikiopen in new tag
                      3. HTTP/2 - 维基百科,自由的百科全书open in new tag

                      引用


                      1. 常见问题 - Let's Encrypt - 免费的 SSL/TLS 证书open in new tag ↩︎

                      2. Proxy Protocol - HAProxy Technologiesopen in new tag ↩︎

                      3. proxy protocol 介绍及 nginx 配置 - 简书open in new tag ↩︎

                      4. v2fly-github-io/vless.md at master · rprx/v2fly-github-ioopen in new tag ↩︎

                      - + diff --git a/document/level-1/index.html b/document/level-1/index.html index 883b2e9d25..2dfbd872ad 100644 --- a/document/level-1/index.html +++ b/document/level-1/index.html @@ -24,11 +24,11 @@ 入门技巧 | Project X - - + +
                      - + diff --git a/document/level-1/routing-lv1-part1.html b/document/level-1/routing-lv1-part1.html index e1f90b9c24..4cda613f7f 100644 --- a/document/level-1/routing-lv1-part1.html +++ b/document/level-1/routing-lv1-part1.html @@ -24,8 +24,8 @@ 路由 (routing) 功能简析(上) | Project X - - + +

                      路由 (routing) 功能简析(上)

                      如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

                      1. 初识【路由】三兄弟

                      要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. 入站;2. 路由;3. 出站

                      路由三兄弟

                      三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。

                      所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。

                      因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。

                      啰嗦君

                      路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。

                      2. 基本功: “兄弟一条心”

                      下图的示例,就是在客户端的 Xray 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。

                      下面我们来逐个分析:

                      2.1 入站

                      提示

                      入站: 就是流量如何流入 Xray

                      下面的入站配置示例,用大白话说就是:数据按照 socks 协议,通过 10808 端口,从本机 127.0.0.1 流入Xray。同时,Xray 将这个入站用 [tag] 命名为 inbound-10808

                      {
                      @@ -141,6 +141,6 @@
                         ]
                       }
                       

                      此时,路由规则其实变成了:

                      这就是路由功能的灵活之处了,你可以自由的改变它的顺序来实现不同的设计。

                      至此,我们已经解释完了 【如何利用 geosite.dat 文件,通过路由规则,根据【域名】来分流网络流量】。

                      5. 攻城略池 - 多种路由匹配条件

                      请确保你已经读懂了上面的内容,因为这样,你就已经理解了【路由】功能的工作逻辑。有了这个基础,我们就可以继续分析【路由】功能更多更详细的配置方式和匹配条件了。

                      等你看完后面的内容,就完全可以自由的定制属于自己的路由规则啦!还等什么,让我们一起进入 《路由 (routing) 功能简析(下)》 吧!

                      - + diff --git a/document/level-1/routing-lv1-part2.html b/document/level-1/routing-lv1-part2.html index 3f69f28b57..6c7367d631 100644 --- a/document/level-1/routing-lv1-part2.html +++ b/document/level-1/routing-lv1-part2.html @@ -24,8 +24,8 @@ 路由 (routing) 功能简析(下) | Project X - - + +

                      路由 (routing) 功能简析(下)

                      欢迎继续学习 Xray 的【路由】功能!

                      《路由 (routing) 功能简析(上)》 中,我们已经对【路由】功能的工作逻辑有了清晰的理解,也基于 geosite.dat 文件做了简单的域名分流配置。

                      如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧!

                      5. 攻城略池 - 多种路由匹配条件

                      [域名], [IP], [协议], etc.

                      基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢?

                      因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如:

                      1. 我读了《小小白白话文》后,给 VPS 新申请了一个 proxy.yourdomain.com 的域名, 我希望它无论如何都代理,geosite.dat 里面有吗?
                      2. 如果我还有个 direct.yourdomain.com 的域名,我希望它无论如何都直连, geosite.dat 里面有吗?
                      3. 本机 127.0.0.1 的内部流量,是否正确直连了?(比如 docker 等)
                      4. 路由器、本地局域网 192.168.*.* 的流量,是否正确直连了?(比如路由器、群晖等)
                      5. 我的国内 DNS 查询(如 223.5.5.5)是否正确直连了?
                      6. 我的国外 DNS 查询(如 1.1.1.1)是否正确代理了?
                      7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了?
                      8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了?
                      9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连?
                      10. ......

                      我之所以说只用【域名分流】会漏洞百出,是因为 geosite.dat 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会:

                      • 无法匹配文件里没有的新域名
                      • 无法匹配基于 IP 地址的规则
                      • 无法匹配基于网络协议的规则

                      啰嗦君

                      那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【转发给第一个出站 】。这其实就是说:

                      • 当你的第一个出站是 [direct-out] 时:需要直连的都正确了,但需要代理的则都错误
                      • 当你的第一个出站是 [proxy-out-vless] 时:需要代理的都正确了,但需要直连的则都错误

                      所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?当然存在! 我们需要的只是【域名】之外更多的【分流判断依据】而已。

                      5.1 基于指定域名分流:[domain], [full]

                      1. 如果需要匹配某个子域名,如 a-name.yourdomain.com,我们使用 full: "a-name.yourdomain.com"
                      2. 前面的 问题1问题2,就可以通过给 proxy.yourdomain.com 指定 [proxy-out-vless] 出站,给 direct.yourdomain.com 指定 [direct-out] 出站来解决
                      3. 如果需要匹配 yourdomain.com 的所有子域名,我们使用 domain: "yourdomain.com" 实现
                      4. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置
                      5. 另外,[domain] 还支持正则表达式等匹配方式。详情请参考 《基础配置模块 - 路由》文档

                      上述配置如下:

                      {
                      @@ -187,6 +187,6 @@
                         }
                       }
                       

                      其实,第 6 点已经是我整理过的规则了,原则就是【相同的匹配依据可以合并,不同的匹配依据保持独立】。

                      8. 明修栈道、暗渡陈仓

                      [domain] 转化 [ip] 的密道:domainStrategy

                      我们在 5.4 中提交了多种流量判断的【依据】,其中一种是域名 [domain]、一种是 [IP]

                      如果你初步了解过 DNS 的运作过程,就会知道,我们对一个域名 [domain] 发起访问请求时,其实需要先向 DNS 发起请求来解析域名 [domain] 对应的 [IP],在得到 [IP] 后再向它发起实际请求。

                      所以,面对入站的一次域名请求,Xray 其实有两次机会去判断它的类型。那么,究竟是否要用这两次机会呢?这就是由 domainStrategy 这个配置来决定的。它有三个选项:

                      • AsIs
                      • IPIfNonMatch
                      • IPOnDemand

                      按么我们逐个来解释一下:

                      8.1 域名策略: "AsIs"

                      就是 "As Domain Is",也就是说 【域名什么样,就什么样,不多折腾】。

                      简单粗暴理解就是说【仅用 [domain] 来匹配】。

                      提示

                      AsIs 的实际意义为 【如原先所示,不加修改】,🍉 老师这里描述的不是很恰当。

                      这个方式的处理都在 Xray 内部完成,没有与外界的数据往来,所以速度最快。它的兜底策略也很清晰:即前面所说的、无法匹配的域名自动转入第一条出站处理。所以,对于常规使用路由功能这最推荐的策略。

                      8.2 域名策略: "IPIfNonMatch"

                      就是 "lookup IP if (there's) no matching rule",也就是说【如果其他所有规则都匹配不上,那就转化成 IP 去匹配 IP 规则】。

                      简单粗暴理解就是说【先把访问目标和其他所有类型规则匹配,如果匹配不上,那就通过 DNS 查询转化成 IP,再从头和所有规则匹配一次】。

                      该策略下没有命中任何规则的这一部分域名,会需要再经历 DNS 查询过程、以及第二轮规则匹配的过程,其耗时会多于 AsIs 策略,所以并不是首选推荐的策略。

                      8.3 域名策略: "IPOnDemand"

                      这里其实说 Demand IP 更准确些,也就是说【当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配】。

                      简单粗暴理解就是说【只要路由规则中有 IP 类规则,那么所有基于域名 [domain] 的请求都要解析成 [IP] 然后去匹配 [IP] 类规则】。

                      它要对所有首次域名访问进行 DNS 解析,所以首次查询比较耗时。虽然由于 XrayDNS 缓存机制的存在,后续对相同域名的访问速度会重回巅峰,但总体来说也不是首选推荐的策略。

                      啰嗦君

                      domainStrategy 仅对域名生效,不要搞混了哦~

                      9. 思考题

                      迄今为止,我们都是在【单入站】和【单出站】的基础上,讲解【路由】内部的各种配置逻辑。

                      但是,如你所知,Xray 本身是支持多端口,多协议的。那么,如果我问你:

                      1. 我希望 VLESS 协议将我日常的网页浏览和 APP 流量转发给美国的大流量服务器
                      2. 我希望 trojan 协议将我的所有 Netflix 流量转发给日本的服务器解锁各种二次元
                      3. 我希望 shadowsocks 协议将我所有的游戏流量转发给香港的服务器达到最低的延迟
                      4. 我希望有一个独立的端口,能够把 telegram 的流量全都转发给 VPS
                      5. 我希望有一个独立的端口,能够把 bittorrent 下载流量全都转发给欧洲大盘鸡
                      6. 我希望......

                      这些想法,是否能通过【路由】功能配置实现呢?

                      答案当然是 【完全可以】 啦! 但是这些对于 level-1 来说已经超纲了,就留给各位自由的探索吧!

                      10. 结语

                      至此,Xray 的【路由】功能就介绍完了。希望本文能够对你理解 Xray 的灵活有所帮助。

                      11. 尾注

                      • 现在你可以重新阅读一遍 路由,看看是否有更加深刻的理解。
                      • 🍉🍉🍉🍉🍉 😄
                      - + diff --git a/document/level-1/work.html b/document/level-1/work.html index eca8e6d003..f1aa7ddfa5 100644 --- a/document/level-1/work.html +++ b/document/level-1/work.html @@ -24,11 +24,11 @@ Xray 的工作模式 | Project X - - + +

                      Xray 的工作模式

                      单服务器模式

                      与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。

                      一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。

                      桥接模式

                      如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。

                      工作原理

                      在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。

                      • 需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。
                        • 入站连接负责与客户端(如浏览器)通信:
                          • 入站连接通常可以配置用户认证,如 ID 和密码等;
                          • 入站连接收到数据之后,会交给分发器(Dispatcher)进行分发;
                        • 出站连接负责将数据发给服务器,如另一台主机上的 Xray。
                      • 当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。
                        • 路由会在必要时查询 DNS 以获取更多信息来进行判断。
                      - + diff --git a/document/level-2/index.html b/document/level-2/index.html index b782e292ba..489ae4d83c 100644 --- a/document/level-2/index.html +++ b/document/level-2/index.html @@ -24,11 +24,11 @@ 进阶文档 | Project X - - + +

                      进阶文档

                      这个章节包含进阶级的 Xray 使用心得分享, 如果您已经熟悉 Xray, 那么这里的经验可以让您更加发挥 Xray 的威力

                      透明代理入门 by a @kirinopen in new tag

                      透明代理的入门篇章。

                      透明代理(TProxy)配置教程 by a @BioniCosmosopen in new tag

                      基于 Xray 的透明代理(TProxy)配置完整教程。

                      TProxy 透明代理(ipv4 and ipv6)配置教程 by a @SQLimitopen in new tag

                      基于 Xray 的 TProxy 透明代理(ipv4 and ipv6)配置教程

                      Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹 by a @SQLimitopen in new tag

                      双端使用 Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹

                      [透明代理]通过 gid 规避 Xray 流量 by a @kirinopen in new tag

                      在 iptables/nftables 实现的透明代理中,一种新的规避 Xray 流量的方式。

                      通过 Xray 将特定的流量指向特定出口,实现全局路由“分流” by a @Zzz3mopen in new tag

                      将 Xray 玩出花:基于 fwmark 、 sendThrough 或 sockopt.interface 方式实现“分流”。

                      通过 Cloudflare Warp 增强代理安全性 by a @yuhan6665open in new tag

                      Xray v1.6.5 新增 WireGuard 出站的使用介绍。

                      Xray 流量统计 by a @yuhan6665open in new tag

                      适配 Xray 的流量统计和脚本。

                      - + diff --git a/document/level-2/iptables_gid.html b/document/level-2/iptables_gid.html index 69be6598aa..03116f7bb0 100644 --- a/document/level-2/iptables_gid.html +++ b/document/level-2/iptables_gid.html @@ -24,8 +24,8 @@ GID 透明代理 | Project X - - + +

                      透明代理通过 gid 规避 Xray 流量

                      在现有的 iptables 透明代理白话文(新 V2Ray 白话文指南-透明代理open in new tag新 V2Ray 白话文指南-透明代理(TPROXY)open in new tag透明代理(TProxy)配置教程)教程中,对 Xray 流量的规避处理是打 mark 实现的。即对 Xray 出站流量打 mark,通过设置 iptables 规则对对应 mark 的流量直连,来规避 Xray 流量,防止回环。

                      这么做有以下几个问题:

                      1. 莫名流量进入 PREROUTING 链open in new tag

                      2. 安卓系统有自己的 mark 机制,该方案在安卓上不可用

                      本教程的方案不需要设置 mark,理论性能更高,同时也不存在上述问题。

                      思路

                      tproxy 流量只能被 root 权限用户(uid==0)或其他有 CAP_NET_ADMIN 权限的用户接收。

                      iptables 规则可以通过 uid(用户 id)和 gid(用户组 id)分流。

                      让 Xray 运行在一个 uid==0 但 gid!=0 的用户上,设置 iptables 规则不代理该 gid 的流量来规避 Xray 流量。

                      配置过程

                      1. 前期准备

                      安卓系统

                      1. 系统已 root

                      2. 安装 busyboxopen in new tag

                      3. 有一个可以执行命令的终端,可以使用 adb shell,termux 等。

                      其它 Linux 系统

                      需要依赖 sudo,iptables 的 tproxy 模块和 extra 模块。

                      一般系统都有自带,openwrt 运行:

                      opkg install sudo iptables-mod-tproxy iptables-mod-extra
                      @@ -126,6 +126,6 @@
                       ip6tables -t mangle -A OUTPUT -p tcp -j XRAY6_MASK
                       ip6tables -t mangle -A OUTPUT -p udp -j XRAY6_MASK
                       
                      - + diff --git a/document/level-2/nginx_or_haproxy_tls_tunnel.html b/document/level-2/nginx_or_haproxy_tls_tunnel.html index 83439b0361..2256bdceb9 100644 --- a/document/level-2/nginx_or_haproxy_tls_tunnel.html +++ b/document/level-2/nginx_or_haproxy_tls_tunnel.html @@ -24,8 +24,8 @@ Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹 | Project X - - + +

                      Nginx 或 Haproxy 实现的 HTTPS 隧道、HTTP/2 over HTTPS 隧道、WebSocket over HTTP/2 over HTTPS 隧道、gRPC over HTTP/2 over HTTPS 隧道以及自签证书双端认证的 gRPC over HTTP/2 over HTTPS 隧道

                      客户端服务端 Nginx 构建 HTTPS 隧道隐藏指纹

                      网路结构:

                      xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

                      编译 nginx --with-stream

                      在客户端及服务端均编译

                      curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

                      tar -zxvf nginx-1.22.1.tar.gz

                      cd nginx-1.22.1

                      apt install gcc make //编译依赖 gcc 以及 make

                      ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module //此步需要依赖一些库,根据报错安装相应 lib

                      make && make install

                      编译之后 nginx 文件夹位于 /usr/local/nginx

                      配置 nginx

                      编辑 nginx 配置文件 nginx.conf

                      vim /usr/local/nginx/conf/nginx.conf

                      服务端加入如下配置

                      服务器申请证书不再赘述,参考白话文open in new tag

                      stream {
                      @@ -548,6 +548,6 @@
                       backend web
                           server web /dev/shm/h1h2c.sock
                       

                      xray 配置

                      简单的 gRPC 配置,无需 TLS,配置见文档,配置的 serviceName 可用于分流。

                      - + diff --git a/document/level-2/redirect.html b/document/level-2/redirect.html index 7856a2e071..c106592d7b 100644 --- a/document/level-2/redirect.html +++ b/document/level-2/redirect.html @@ -24,8 +24,8 @@ 出站流量重定向 | Project X - - + +

                      基于 fwmark 或 sendThrough 的流量重定向

                      通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”

                      前言

                      之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR 路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有!

                      通过 fwmark 或 Xray 的 sendThrough/sockopt.interface,再简单配合路由表功能即可实现:

                      1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6
                      2. 其余用户则走原 IPV4 或者 IPV6

                      具体设置如下(以 Debian10 为例):

                      1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)

                      根据不同系统和不同软件,请参考官方安装方法

                      2、编辑 VPN 配置文件(以 WireGuard 为例)

                      原始文件:

                      [Interface]
                      @@ -168,6 +168,6 @@
                       

                      开机自启

                      systemctl enable wg-quick@wg0
                       systemctl start wg-quick@wg0
                       

                      验证 IPv4/IPv6

                      在代理上 运行 curl ip-api.com -4/-6 / 浏览器访问ip-api.com

                      后记

                      本文本意是可以避免的多余的流量浪费,将路由和分流的功能交给 Xray 处理。避免了维护路由表的繁琐工作。顺便技术提升 UP。

                      感谢

                      XTLS/Xray-coreopen in new tag; v2fly/v2ray-coreopen in new tag; WireGuardopen in new tag; @p3terxopen in new tag; @w; @Hiram; @Luminous; @Ln; @JackChou;

                      - + diff --git a/document/level-2/tproxy.html b/document/level-2/tproxy.html index a9f070910f..f8cbefea75 100644 --- a/document/level-2/tproxy.html +++ b/document/level-2/tproxy.html @@ -24,8 +24,8 @@ TProxy 透明代理 | Project X - - + +

                      透明代理(TProxy)配置教程

                      本配置基于TProxy 透明代理的新 V2Ray 白话文教程open in new tag,加入了 Xray 的新特性,使用 VLESS + XTLS Vision 方案,并将旧教程中默认出站代理的分流方式改为默认出站直连,使用者请按照实际情况进行修改。

                      本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。

                      开始之前

                      请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。

                      需注意的是,目前很多透明代理教程都会将 Linux 系统的 IP 转发打开,但这样会导致 Splice 性能下降。详情请参考大案牍术破案纪实第三篇--我们是如何破解 Splice 性能下降甚至低于 Direct 之谜的open in new tag

                      这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。

                      Xray 配置

                      为了更好的分流体验,请替换默认路由规则文件为 Loyalsoldier/v2ray-rules-datopen in new tag,否则 Xray-core 将无法加载本配置。

                      sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
                      @@ -281,6 +281,6 @@
                       [Install]
                       WantedBy=multi-user.target
                       
                - + diff --git a/document/level-2/tproxy_ipv4_and_ipv6.html b/document/level-2/tproxy_ipv4_and_ipv6.html index 1f9d638938..f34c6ab61e 100644 --- a/document/level-2/tproxy_ipv4_and_ipv6.html +++ b/document/level-2/tproxy_ipv4_and_ipv6.html @@ -24,8 +24,8 @@ TProxy 透明代理 (ipv4 and ipv6) | Project X - - + +

                TProxy 透明代理(ipv4 and ipv6)配置教程

                本配置参考了TProxy 透明代理的新 V2Ray 白话文教程open in new tag透明代理(TProxy)配置教程open in new tag以及透明代理通过 gid 规避 Xray 流量open in new tag,加入了透明代理对 ipv6 的支持,并且使用 VLESS-TCP-XTLS-RPRX-Vision 方案对抗封锁 (推荐使用 1.7.2 及之后版本)。

                关于 Xray 的配置并不是本文重点,使用者可依实际情况进行修改,具体可以参考官方文档示例open in new tag或其他优秀示例 比如@chika0801open in new tag 又如@lxhao61open in new tag

                注意

                若使用其他配置,你需要着重注意客户端配置中 outboundtagproxy 的部分,其他部分不变

                服务端配置也要同时改变

                此配置意在解决例如 Netflix 等默认使用 ipv6 连接的网站无法通过旁路由进行代理的问题,或对 ipv6 代理有需要。

                本文网络结构为单臂旁路由

                本文中所有配置已在 Arch Linux (Kernel: 6.0.10) 环境下测试成功,如在其它环境中同理

                注意安装相应程序 # sudo apt install iptables ip6tables# sudo apt install nftables

                若旁路由未安装 xray 程序,可以手动下载相应 xray 程序如 Xray-linux-64.zipopen in new tag ,然后复制 install-release.shopen in new tag 文件到旁路由,赋予可执行权限 # chmod 700 install-release.sh,然后使用 # ./install-release.sh --local Xray-linux-64.zip 根据提示进行本地安装。

                Xray 配置

                客户端配置

                {
                @@ -429,6 +429,6 @@
                 [Install]
                 WantedBy=multi-user.target
                 
                1. 最后执行 systemctl enable tproxyrules 命令。

                tproxyrules.service

                注意其中主路由器 IP 地址,根据实际修改

                ExecStartPre=/bin/sh -c 'until ping -c1 192.168.31.1; do sleep 1; done;' 命令为确保获得 IP 地址后再执行命令,否则会诡异报错,其中 IP 地址为主路由器地址,根据实际修改。

                注意

                如果通过 dhcpcd 等设置了静态 IP 及网关,则上述相关 ip route add/del 设置需删除

                局域网设备上网设置

                此处假定旁路由 ipv4, ipv6 地址分别为192.168.31.100, fd00:6868:6868::8866, 旁路由的 ipv4, ipv6 地址可由命令ip add获得。

                方法一

                局域网设备上网有两种方式,第一种就是在使用设备上进行静态 IP 的配置,将网关指向旁路由 IP。注意绝大部分手机仅支持手动配置 ipv4 网关,不支持手动配置 ipv6 网关,除非 root 后进行相关设置。

                以 windows 设备为例,可以先开启 DHCP 记录自动分配的 IP 以参考,然后手写静态配置。

                DNS 设置

                此配置劫持 DNS 流量,DNS 可以随便写

                建议设置为旁路由 IP,防止 DNS 泄露

                image image

                方法二

                局域网设备上网的第二种方式,是在路由器上进行网关设置,这种方法对于连接到此路由器的设备无需做任何设置即可科学上网,但注意有些路由器不支持 ipv6 的网关设置,有 ipv6 需求的设备仍需在所需设备上单独手动配置 ipv6 相关设置参考方法一。

                image

                Finally

                按照以上方法设置后设备即可双栈访问,进入测试网站比如 https://ipv6-test.com/ 可以看到如下结果 (需要代理此网站才能看到如下结果)

                image

                写在最后

                如今 ipv6 并未完全普及,我们日常访问的流量 99%仍为 ipv4 流量;很多 VPS 商家虽然提供 ipv6 地址,但线路优化非常垃圾,甚至处于不可用状态,为何要加入 ipV6 的设置?

                可以看到目前 ipv6 处于很尴尬的境地,各种设备对于 ipv6 的支持很烂,但是都在逐步完善,同时 Windows 系统对于 ipv6 的优先级也在提高,很多浏览器也会优先进行 ipv6 的解析以及访问,很多网站也开始默认使用 ipv6 进行访问(比如 Netflix, 如果没有配置 ipv6, 浏览器打开 Netflix 会显示 Not Available 是因为没有代理 Netflix 的 ipv6 请求,当然可以选择禁用 Windows 的 ipv6,但支持 ipv6 的 pt 站就无法使用)

                这种情况下 ipv4 无法完全胜任网络冲浪的需求,即使是那 1%的流量,遇到了也会让人头疼不已。

                而可以预见 ipv6 也会逐步与 ipv4 分庭抗礼,所以有必要加入 ipv6 的设置。

                - + diff --git a/document/level-2/traffic_stats.html b/document/level-2/traffic_stats.html index dd1b368599..ba070c4c36 100644 --- a/document/level-2/traffic_stats.html +++ b/document/level-2/traffic_stats.html @@ -24,8 +24,8 @@ 流量统计 | Project X - - + +

                流量统计配置教程

                请熟悉流量统计 白话文教程open in new tag,本文在其基础上适配了 Xray(1.5.9+)。

                查看流量信息

                配置方法与 v2fly 一致。 查看流量信息是 xray 命令行的其中一个功能。配置内设置的 api dokodemo-door 端口,即为 --server 参数的端口。

                xray api statsquery --server=127.0.0.1:10085 #查看所有流量
                @@ -120,6 +120,6 @@
                 print_sum "$DATA" "user"
                 echo "-----------------------------"
                 
                - + diff --git a/document/level-2/transparent_proxy/transparent_proxy.html b/document/level-2/transparent_proxy/transparent_proxy.html index bb6d16ff20..2f33510f72 100644 --- a/document/level-2/transparent_proxy/transparent_proxy.html +++ b/document/level-2/transparent_proxy/transparent_proxy.html @@ -24,8 +24,8 @@ 透明代理入门 | Project X - - + +

                透明代理入门

                什么是透明代理

                透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。

                这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。

                透明代理的实现

                透明代理的实现目前主要有两种方式:

                tun2socks

                可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。

                Windows

                1. 安装 Netchopen in new tag ,使用模式[3] [TUN/TAP] 绕过局域网启动。

                2. 开启热点

                3. 打开控制面板->网络和 Internet->网络和共享中心->更改适配器设置,找到TAP-Windows AdapterMicrosoft Wi-Fi Direct Virtual Adapter

                4. 鼠标右键点击TAP-Windows Adapter属性->共享,勾选允许其他网络用户通过此计算机的 Internet 连接来连接,在家庭网络连接中选择Microsoft Wi-Fi Direct Virtual Adapter的那个网络连接,点击确定。

                Android

                1. 配置连接 V2RayNG

                2. 开启热点

                3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项)

                iptables/nftables

                iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。

                基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。

                现存的三篇白话文透明代理教程其实讲的都是基于这种方案的透明代理实现,它们是: 新 V2Ray 白话文指南-透明代理open in new tag新 V2Ray 白话文指南-透明代理(TPROXY)open in new tag透明代理(TProxy)配置教程 。其中第一篇是基于 iptables-redirect 模式,已经过时了,不建议使用,仅供参考。第二篇和第三篇讲的都是基于 iptables-tproxy 模式的透明代理实现。

                iptables 实现透明代理原理

                Linux 使用Netfilter来管理网络,Netfilter模型如下:

                Netfilter

                假设使用路由器作为网关(即我们平时的上网方式),那么:

                局域网设备通过路由器访问互联网的流量方向:

                PREROUTING链->FORWARD链->POSTINGROUTING链

                局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向:

                PREROUTING链->INPUT链->网关本机

                路由器访问互联网的流量方向:

                网关本机->OUTPUT链->POSTINGROUTING链

                通过使用 iptables 操控PREROUTING链OUTPUT链的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。

                透明代理难在哪里

                透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做分流更加合适。

                我们可以把路由由易到难分为以下几个阶段:

                1. 代理全部请求

                2. 本地局域网 IP/组播 IP 请求直连,其它请求代理

                3. 在 2 的基础上直连 Xray 发起的连接请求

                4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。

                上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。

                从零开始一步步实现基于 iptables-tproxy 的透明代理

                在开始之前,你需要有一定的基础知识:

                1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器

                2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口

                3. 对 Linux 系统有最基础的了解(知道怎么运行命令)

                4. 能够手写客户端 json 文件配置,至少要能看懂

                前期准备工作

                注意

                在开始操作前,记得使用 sysctl -w net.ipv4.ip_forward=1 打开linux ipv4封包转发

                1. 准备一个运行 Linux 系统的网关

                比如,刷了 OpenWRT 的路由器

                2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件

                配置文件监听 12345 端口,开启 tproxy:

                {
                @@ -111,6 +111,6 @@
                 iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK
                 iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK
                 

                但是这么配置有个缺点,如果使用 CDN 或者 VPS 很多的话,就不好写规则了。

                1. 通过 mark 规避

                三个白话文教程都是使用这种方法规避,自行参考,这里不再赘述。

                1. 通过 gid 规避(推荐)

                参考 [透明代理]通过 gid 规避 Xray 流量

                这样就完成了第三阶段的代理,也就是平时说的全局代理。但是记得把网关的 DNS 服务器设置为国外的 DNS 服务器,否则可能依然返回被污染的结果。

                第四阶段

                其实,并不是所有人都需要实现第四阶段。全局代理对于大部分情况已经适用。

                特别是对于旁路由而言。需要代理时,将网关调成旁路由的 IP,不需要代理时,将网关换回主路由 IP。

                至于第四阶段的具体实现,那三篇白话文教程讲的都是。在理解了上面的内容后,再去看那三篇白话文教程,就比较容易理解了。

                代理 ipv6

                上面的规则只对 ipv4 生效,如果还想要代理 ipv6 请求,则使用 ip6tables 命令,用法与 iptables 基本相同。参考 [透明代理]通过 gid 规避 Xray 流量#4-设置 iptables 规则

                iptables 透明代理的其它注意事项

                1. 如果作为代理的网关作为主路由,要在PREROUTING链规则中加一条iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN,即在第一阶段使用、第二阶段被删除的指令。如果不写,WAN 口中同网段的其它人可以将网关填写成你的 WAN_IP,从而蹭你的透明代理用,还可能带来一定的危险性。

                2. 新 V2Ray 白话文指南-透明代理(TPROXY)#设置网关open in new tag 中的第三条说:手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。实际上,Ubuntu、CentOS、debian 等系统就算开启了 IP 转发,PC 也不能正常上网,这是正常的。事实上只有 OpenWRT 能做到文中所描述的那样,据 @BioniCosmosopen in new tag 点拨,这是由于一般的 Linux 系统没有 Masquery 规则。

                3. too many open files 问题open in new tag ,解决方法见 [透明代理]通过 gid 规避 Xray 流量-配置最大文件大开数&运行 Xray 客户端

                4. 避免已有连接的包二次通过 TPROXY ,待补充...

                5. 主路由、单臂路由与旁路由,待补充...

                - + diff --git a/document/level-2/warp.html b/document/level-2/warp.html index 298ea2844f..efcfcc284c 100644 --- a/document/level-2/warp.html +++ b/document/level-2/warp.html @@ -24,8 +24,8 @@ 通过 Cloudflare Warp 增强代理安全性 | Project X - - + +

                通过 Cloudflare Warp 增强代理安全性

                Xray(1.6.5+)新加入了 WireGuard 出站,虽然增加的代码和依赖会增大 core 体积,但是我们认为这是一个很有必要的新功能,原因有三:

                1. 通过近期的一些讨论和实验open in new tag,我们知道代理回国流量是不安全的。一种应对方式是将回国流量路由至黑洞,它的缺点是由于 geosite 和 geoip 更新的不及时或者新手不知道如何在客户端适当分流,结果流量进入黑洞,影响使用体验。 这时我们只需要将回国流量导入 Cloudflare Warp,可以在不影响使用体验的情况下达到同样的安全性。
                2. 众所周知,大部分机场会记录用户访问域名的日志,某些机场还会审计和阻断一些用户流量。保护用户私密性的一个方法,就是在客户端使用链式代理。 Warp 使用的 WireGuard 轻量级 VPN 协议会在代理层内增加一层加密。对于机场而言,用户所有流量的目标都是 Warp,从而最大程度保护自己的隐私。
                3. 方便使用,只需要一个 core 即可完成分流,Wireguard Tun,链式代理的设置。

                申请 Warp 账户

                感谢 Cloudflare 推动自由的互联网,现在你可以免费使用 Warp 服务,连接的时候会根据出口自动选择最近的服务器

                方法 1:

                1. 使用一台 vps,下载 wgcfopen in new tag
                2. 运行 wgcf register 生成 wgcf-account.toml
                3. 运行 wgcf generate 生成 wgcf-profile.conf 拷贝内容如下:
                [Interface]
                @@ -187,6 +187,6 @@
                    ]
                 }
                 
                - + diff --git a/en/about/news.html b/en/about/news.html index 3ee3edddbf..439ac98812 100644 --- a/en/about/news.html +++ b/en/about/news.html @@ -24,11 +24,11 @@ 大史记 | Project X - - + +

                大史记

                2021.4.6

                • VuePress Next.
                • With Dark Mode.

                2021.4.4

                • 本文档迎来的新的首页。
                • 本文档迎来了暗黑模式。
                • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
                • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
                • 🎉🎉🎉

                2021.4.1 v1.4.2open in new tag

                • 不是愚人节玩笑,今天更新。
                • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
                • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
                • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

                2021.3.25

                没错还在变。 -_-

                2021.3.15

                文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                2021.3.14 v1.4.0open in new tag

                • Happy Pi-Day!
                • 这次是个大更新:
                  • 为链式代理引入了传输层支持。
                  • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
                  • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
                  • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
                  • 添加了 FakeDNS。
                  • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
                • 还是 VuePress 比较爽啊(

                2021.3.3 1.3.1open in new tag

                • 这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。
                • 同时修复了一个会导致 Panic 的 bug。Holmium_认为这是在骗、在偷袭。
                • 修复了几个遗留问题。

                2021.2.14 1.3.0open in new tag

                • Happy 🐮 Year 🎉!
                • v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。
                • OHHHHHHHHHHHH!

                2021.01.31 1.2.4open in new tag

                • 解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。
                • 似乎这个版本没有什么改变,但这只是暴风雨前的宁静。
                • (没错我就是先知)

                  你个傻子,你拿的是 UNO 牌。

                2021.01.25

                • 全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载秘籍第一层咯...
                • 英文版文档网站逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!

                2021.01.22 1.2.3open in new tag

                • 对 SS 协议的支持变强了, 支持单端口多用户!
                • 对 trojan 协议的支持也变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!
                • (VLESS: 嘤嘤嘤)
                • UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".
                • 嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.
                • 向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 a @Bohan Yangopen in new tag 致敬!
                • 其他美味小樱桃, 惯例更新品尝就对啦.

                2021.01.19

                • 一些数字
                  • 版本发布了 10   个 tag
                  • 解决掉了 100  个 issue
                  • 复刻了 300  个 fork
                  • 点了 2000 个 star
                  • 群 3000 个 人

                2021.01.17

                2021.01.15 1.2.2open in new tag

                • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
                • 之前预告的 UUID 修改正式上线.(往下看往下看)
                • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
                • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
                • 当然还有其他各种小糖果.(更新品尝就对了)
                • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

                2021.01.12

                • 将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户.
                  • 客户端写 "id": "我爱 🍉 老师 1314",
                  • 服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 我爱🍉老师1314 的 UUID 映射)
                • 🍉 老师的小小白白话文大结局, 撒花.

                2021.01.10 1.2.1open in new tag

                • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
                • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
                • 日志现在看起来更顺眼.

                2021.01.07

                • 礼貌和尊重本应是社区不需要明说的准则之一。

                2021.01.05

                • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

                2021.01.03

                2021.01.01

                【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 1.2.0open in new tag

                🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!

                • 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
                • (UDP 还会继续增强!)
                • 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
                • (不,下面不是广告,是里程碑。)
                • Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
                  • 一人扛起了所有!支持各大主流协议!
                  • 一骑绝尘的性能!
                  • 日趋完善的功能!
                  • 可怕的生命力与社区亲和力!
                • Xray 将继续保持前行! 因此 Xray 需要更多的英雄!!open in new tag
                • PS:请品,请细品release notesopen in new tag每一句。似乎有一个小秘密小彩蛋 (啊,有人敲门...我一会和你们说)

                2020.12.29

                透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, TG 群open in new tag火热测试中

                2020.12.25 1.1.5open in new tag

                圣诞节快乐!

                • 游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone
                • 你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...
                • (VLESS 的 UDP fullcone 和更多增强很快就到!)
                • 无须再担心证书验证被墙,OCSP stapling 已经上线!
                • kirin 带来了一大波 脚本更新.脚本在此open in new tag
                • 还有更多美味小樱桃!(不用问,更新品尝就对了)

                2020.12.24

                因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:没错你正在看的就是open in new tag

                大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)

                文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 文档的仓库open in new tag

                仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。

                2020.12.23

                Xray-core Shadowsocks UDP FullCone 测试版, TG 群open in new tag火热测试中

                2020.12.21

                • Project X 群人数 2000+
                • 群消息(含游戏群) 日均破万

                2020.12.18 1.1.4open in new tag

                • 更低的启动内占用和内存使用优化
                • 随意定制的 TLS 提高你的 SSL 评级
                • 支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS
                • 还有在您路由器上使用的 Splice 最佳使用模式建议

                2020.12.17

                鉴于日益增长群人数和游戏需求, 开启了TG 游戏群open in new tag

                2020.12.15

                安装脚本 dev 分支open in new tag开启, 持续更新功能中.

                2020.12.11 1.1.3open in new tag

                • 完整版本的 REDIRECT 透明代理模式.
                • 软路由 splice 流控模式的优化建议.

                2020.12.06 1.1.2open in new tag

                • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
                • 增强了 API 兼容

                2020.12.04

                增加 splice 模式

                2020.11.27

                • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
                • 登上了 GitHub Trending
                • Project X 群人数破千,频道订阅数 500+

                2020.11.25 1.0.0open in new tag

                Xray 的第一个版本.

                • 基于 v2ray-core 修改而来,改动较大
                • 全面增强, 性能卓越, 完全兼容

                2020.11.23

                project X start

                梦开始的时候

                - + diff --git a/en/config/api.html b/en/config/api.html index 45c140a2cf..178b5df1f9 100644 --- a/en/config/api.html +++ b/en/config/api.html @@ -24,8 +24,8 @@ API Interface | Project X - - + +

                API Interface

                API interface configuration provides a set of APIs based on gRPCopen in new tag for remote invocation.

                The interface can be enabled through the api configuration module. When the api configuration is enabled, Xray will create an outbound proxy automatically. All incoming API connections need to be manually routed to this outbound proxy through routing rule configuration.

                Please refer to the related configuration in this section.

                Warning

                Most users do not need to use this API. Novices can ignore this page entirely.

                ApiObject

                ApiObject corresponds to the api item in the configuration file.

                {
                @@ -70,6 +70,6 @@
                 xray.app.proxyman.command.HandlerService
                 xray.app.stats.command.StatsService
                 

                API Calling Example

                Xray-API-documentsopen in new tag @crossfw

                - + diff --git a/en/config/dns.html b/en/config/dns.html index b3f37c85d4..bda2843f7f 100644 --- a/en/config/dns.html +++ b/en/config/dns.html @@ -24,8 +24,8 @@ Built-in DNS Server | Project X - - + +

                Built-in DNS Server

                DNS Server

                The DNS module built into Xray has two main purposes:

                • During the routing phase, it resolves domain names to IP addresses and performs traffic splitting based on the results of domain name resolution and the value of domainStrategy in the routing configuration module. The built-in DNS server is only used for DNS queries when either of the following values is set:
                  • "IPIfNonMatch": When a domain name is requested, it first tries to match it against the domain entries in the routing configuration. If no match is found, the built-in DNS server is used to perform a DNS query for the domain name, and the returned IP address is used to perform IP routing matching again.
                  • "IPOnDemand": When a domain name is matched against any IP-based rule, it is immediately resolved to an IP address for matching.
                • It resolves the target address for connection.
                  • In the freedom outbound setting, if domainStrategy is set to UseIP, requests made through the outbound proxy will first resolve the domain name to an IP address using the built-in server before making the connection.
                  • In the sockopt setting, if domainStrategy is set to UseIP, system connections initiated through the outbound proxy will first be resolved to an IP address using the built-in server before making the connection.

                TIP 1

                DNS queries sent by the built-in DNS server are automatically forwarded based on the routing configuration.

                TIP 2

                Only basic IP queries (A and AAAA records) are supported. CNAME records will be queried repeatedly until an A/AAAA record is returned. Other queries will not enter the built-in DNS server.

                DNS Processing Flow

                If the domain name to be queried:

                • Matches the mapping of "domain name - IP" or "domain name - IP array" in the hosts, then the IP or IP array will be returned as the DNS resolution result.

                • Matches the mapping of "domain name - domain name" in the hosts, then the value of this mapping (another domain name) will be used as the domain name to be queried, and enter the DNS processing flow until an IP is resolved and returned, or an empty resolution is returned.

                • Does not match hosts, but matches the domains list in one or more DNS servers, then according to the priority of the matching rule, use the DNS server corresponding to the rule to perform the query in sequence. If the DNS server that is hit fails to query or expectIPs does not match, then use the next hit DNS server to perform the query. Otherwise, return the resolved IP. If all hit DNS servers fail to query or expectIPs does not match, then the DNS component:

                  • By default, it will perform "DNS fallback query": use the "DNS server that has not been used in the last failed query and has a default value of false for skipFallback" to perform the query in sequence. If the query fails or expectIPs does not match, return an empty resolution; otherwise, return the resolved IP.
                  • If disableFallback is set to true, "DNS fallback query" will not be performed.
                • If neither hosts nor the domains list in DNS servers matches, then:

                  • By default, use the "DNS server that has a default value of false for skipFallback" to perform the query in sequence. If the first selected DNS server fails to query or expectIPs does not match, then use the next selected DNS server to perform the query. Otherwise, return the resolved IP. If all selected DNS servers fail to query or expectIPs does not match, return an empty resolution.
                  • If the number of "DNS servers that have a default value of false for skipFallback" is 0 or disableFallback is set to true, use the first DNS server in the DNS configuration to perform the query. If the query fails or expectIPs does not match, return an empty resolution; otherwise, return the resolved IP.

                DnsObject

                DnsObject corresponds to the dns section in the configuration file.

                {
                @@ -116,6 +116,6 @@
                   "clientIP": "1.2.3.4"
                 }
                 

                address: address

                A list of DNS servers, which can be either DNS addresses (in string form) or ServerObjects.

                When the value is "localhost", it means using the local DNS configuration.

                When the value is a DNS "IP" address, such as "8.8.8.8", Xray will use the specified UDP port of this address for DNS queries. The query follows routing rules. By default, port 53 is used.

                When the value is in the form of "tcp://host", such as "tcp://8.8.8.8", Xray will use DNS over TCP for the query. The query follows routing rules. By default, port 53 is used.

                When the value is in the form of "tcp+local://host", such as "tcp+local://8.8.8.8", Xray will use TCP local mode (TCPL) for the query. That is, the DNS request will not go through the routing component and will be sent directly through the Freedom outbound to reduce latency. When no port is specified, port 53 is used by default.

                When the value is in the form of "https://host:port/dns-query", such as "https://dns.google/dns-query", Xray will use DNS over HTTPS (RFC8484, abbreviated as DOH) for the query. Some service providers have IP alias certificates, which can be directly written in IP form, such as https://1.1.1.1/dns-query. Non-standard ports and paths can also be used, such as "https://a.b.c.d:8443/my-dns-query".

                When the value is in the form of "https+local://host:port/dns-query", such as "https+local://dns.google/dns-query", Xray will use DOH local mode (DOHL) for the query, which means that the DOH request will not go through the routing component and will be sent directly through the Freedom outbound to reduce latency. This is generally suitable for server-side use. Non-standard ports and paths can also be used.

                When the value is in the form of "quic+local://host:port", such as "quic+local://dns.adguard.com", Xray will use DOQ local mode (DOQL) for the query, which means that the DNS request will not go through the routing component and will be sent directly through the Freedom outbound. This method requires DNS server support for DNS over QUIC. By default, port 853 is used for the query, and non-standard ports can be used.

                When the value is fakedns, FakeDNS functionality will be used for the query.

                port: number

                The port number of the DNS server, such as 53. If not specified, the default is 53. This item is not applicable when using DOH, DOHL, or DOQL modes, and non-standard ports should be specified in the URL.

                domains: [string]

                A list of domain names. The domain names in this list will be queried using this server first. The format of domain names is the same as in routing configuration.

                expectIPs: [string]

                A list of IP ranges in the same format as in routing configuration.

                When this item is configured, Xray DNS will verify the returned IP addresses and only return addresses that are included in the expectIPs list.

                If this item is not configured, the IP address will be returned as is.

                skipFallback: true | false

                true means to skip this server when performing DNS fallback queries, and the default is false, which means not to skip.

                - + diff --git a/en/config/fakedns.html b/en/config/fakedns.html index 30388a3969..09ea367335 100644 --- a/en/config/fakedns.html +++ b/en/config/fakedns.html @@ -24,8 +24,8 @@ FakeDNS | Project X - - + +

                FakeDNS

                FakeDNS is used to obtain target domain names by forging DNS, which can reduce the delay in DNS queries and work with transparent proxies to obtain target domain names.

                Warning

                FakeDNS may contaminate the local DNS and cause "network unreachable" after Xray is closed.

                FakeDNSObject

                FakeDNSObject corresponds to the fakedns item in the configuration file.

                {
                @@ -130,6 +130,6 @@
                   ]
                 }
                 
                - + diff --git a/en/config/features/browser_dialer.html b/en/config/features/browser_dialer.html index f22cbd1ce6..ef65e1072a 100644 --- a/en/config/features/browser_dialer.html +++ b/en/config/features/browser_dialer.html @@ -24,11 +24,11 @@ Browser Dialer | Project X - - + +

                Warning

                This translation was modified on 18 July 2024 and an updated version (20 July 2024) is available on the source page. View the original page

                Browser Dialer

                BETA v1.4.1+

                Background

                Xray generally uses uTLS to mimic the behavior of popular browsers, and it can be controlled through the fingerprint setting. However, the fingerprints produced by uTLS are an imperfect replica of the real thing, and because uTLS is a popular library, they may be targeted themselves.

                So the idea of browser dialeropen in new tag is that Xray uses a real browser to establish TLS connections. The way this works is that Xray hosts a small website on localhost:8080, the user opens this website in a browser of their choice, and JavaScript on that page will act as Xray's networking stack (HTTP client, TLS client).

                The TLS fingerprinting behavior is perfect this way, and so it may be possible to revive servers that open fine as websites in the browser, but do not connect using any proxying software.

                However, there are many drawbacks:

                • The user has to launch a browser next to the Xray client just for opening the proxy connection.
                • The browser dialer must not be tunneled through the proxy itself, otherwise there is a loop. TUN users should be cautious.
                • The browser can only speak standard HTTP, which means that only WebSocket and SplitHTTP are supported
                • CORSopen in new tag needs to be considered when making requests from one website (localhost:8080) to another (proxy.example.com:443)
                • The browser tunnels your traffic using JavaScript, so there is a significant performance penalty (or, battery drain)
                • The configuration to be used with browser dialer cannot use custom SNI or host headers. SNI == host == address. Custom HTTP headers and tlsSettings are ignored entirely.

                Configuration

                1. Prepare a usable WebSocket or SplitHTTP configuration. Be aware of the above restrictions.
                2. Launch Xray with XRAY_BROWSER_DIALER=127.0.0.1:8080. On Windows, this can be done as set XRAY_BROWSER_DIALER=... and then launching the core from the console, on Linux the core can be launched as XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json.
                3. Open a browser that is not tunneled through the proxy, or modify the config's routing such that the Xray server's domain goes to freedom directly from the client. Browse to localhost:8080, and open the developer console with F12 to monitor for errors.
                4. For better performance and to bypass arbitrary connection limits enforced by the browser, it is recommended to enable Mux.Cool.

                Inner workings

                • Xray listens on http://127.0.0.1:8080, and the browser accesses http://127.0.0.1:8080 to load the JS in the webpage.
                • The JS actively establishes a WebSocket connection to http://127.0.0.1:8080. Xray will use this connection to send instructions, but for now it goes into a connection pool (implemented as Go channel).
                • When a connection needs to be established, Xray receives an available connection from the pool and sends the protocol name, target URL and optional early data.
                • Once the JS successfully connects to the target, it informs Xray and continues to use this conn to bi-directionally forward data.
                • After the connection to the server is closed, the connection to localhost is also closed, but the JS ensures that there is always at least one idle connection available.

                WebSocket

                v1.4.1+

                According to the browser's needs, the early data mechanism has been adjusted as follows:

                • The server response header will contain the requested Sec-WebSocket-Protocol, which also initially obfuscates the length characteristic of the WSS handshake response.
                • The encoding used for early data for browsers is base64.RawURLEncoding instead of StdEncoding, and the server has made it compatible.
                • In addition, due to Xray-core#375open in new tag recommendations for ?ed=2048, this PR also increased server MaxHeaderBytes by 4096. (Although it seems like it would work without modification.)

                SplitHTTP

                v1.8.19+

                SplitHTTP supports QUIC, but the browser's own QUIC stack may be used as well. In Chrome this can be done through chrome://flags, in other browsers it may already be enabled or need a different flag.

                In general, tlsSettings are completely ignored when Browser Dialer is used. Xray does not have any control over which HTTP version the browser selects.

                - + diff --git a/en/config/features/env.html b/en/config/features/env.html index 3bd2410ed2..a4a98f23c2 100644 --- a/en/config/features/env.html +++ b/en/config/features/env.html @@ -24,14 +24,14 @@ Environment Variables | Project X - - + +

                Environment Variables

                Xray provides the following environment variables for modifying some of its underlying configurations.

                Xray Asset Location

                • Name:xray.location.asset or XRAY_LOCATION_ASSET
                • Default value:specified FHSopen in new tag directory or the same path as the Xray file.

                This environment variable specifies a folder location that should contain the geoip.dat and geosite.dat files. If no variable value is specified, the program will search for resource files in the following order:

                ./
                 /usr/local/share/xray
                 /usr/share/xray
                 

                Configuration File Location

                • Name:xray.location.config or XRAY_LOCATION_CONFIG
                • Default value: Same path as the Xray file.

                This environment variable specifies a folder location that should contain the config.json file.

                Multiple Configuration Directories

                • Name:xray.location.confdir or XRAY_LOCATION_CONFDIR
                • Default value:""

                The .json files in this directory will be read in alphabetical order by filename and used as options for multiple configurations.

                - + diff --git a/en/config/features/fallback.html b/en/config/features/fallback.html index c9de330ea5..fa54bbea35 100644 --- a/en/config/features/fallback.html +++ b/en/config/features/fallback.html @@ -24,8 +24,8 @@ Fallback | Project X - - + +

                Fallback

                Fallback is one of the most powerful features of Xray, which can effectively prevent active probing and allows you to use one port for multiple services

                Fallback provides Xray with high-strength anti-active probing capabilities and has a unique first-packet fallback mechanism.

                Fallback can also divide traffic of different types based on path for multi-service sharing on a single port.

                Currently, you can use the fallback feature by configuring fallbacks when using VLESS or Trojan protocols, thus creating an unimaginable combo of services becomes REALITY.

                fallbacks configuration

                  "fallbacks": [
                @@ -41,6 +41,6 @@
                   "xver": 0
                 }
                 

                The fallbacks object is optional and can only be used for the TCP+TLS transport combination.

                • When fallbacks configure with any child elements,"alpn":["http/1.1"] needs to be configured in Inbound TLS.

                Usually, you need to set up a default fallback with both alpn and path omitted or empty, and then configure other routing rules as needed.

                VLESS will forward traffic with TLS decrypted first packet length <18, invalid protocol version, or failed authentication to the address specified by dest.

                For other transport combinations, you must remove the fallbacks object or all its child elements. At this point, no fallbacks will be enabled, and VLESS will wait until it reads enough data. If the protocol version is invalid or authentication fails, the connection will be terminated directly.

                name: string

                Attempt to match the TLS SNI (Server Name Indication), where an empty value matches any SNI. The default value is "", which means empty value.

                alpn: string

                Attempt to match the result of TLS ALPN negotiation, where an empty value matches any ALPN result. The default value is "" , which means empty value.

                VLESS will read the TLS ALPN negotiation result only when necessary. If successful, it will output realAlpn = info to the log. Purpose: To solve the problem of Nginx's inability to simultaneously support http/1.1 and h2c services. Nginx needs to write two lines of listen, one for 1.1 and one for h2c. Note: When "h2" is included in fallbacks alpn, the Inbound TLS needs to be set as "alpn":["h2","http/1.1"] to support h2 access.

                Tip

                The alpn set in the Fallback is used to match the actual negotiated ALPN, while the alpn set in the Inbound TLS represents the list of optional ALPNs during the handshake. These two have different meanings.

                path: string

                Attempt to match the first packet HTTP PATH, where an empty value matches any PATH and a default value is empty. If non-empty, it must start with /, and h2c is not supported.

                Smart: VLESS will only attempt to check the PATH (no more than 55 bytes; the fastest algorithm that does not fully parse HTTP) when necessary. If successful, it will output realPath = in the INFO log. Purpose: To route other inbound WebSocket traffic or HTTP disguised traffic, without additional processing, purely forwarding traffic, and theoretically better performance than Nginx.

                Note: The inbound where fallbacks is located must be TCP+TLS. This is for routing to other WebSocket inbound, while the inbound being routed doesn't need to configure TLS.

                dest: string | number

                Determines the destination of decrypted TLS TCP traffic, which currently supports two types of addresses: (this field is required, otherwise it cannot be started)

                1. TCP, in the format of "addr:port", where addr supports IPv4, domain names, and IPv6. If a domain name is entered, a direct TCP connection will be made (rather than using the built-in DNS resolver).
                2. Unix domain socket, in the format of an absolute path, such as "/dev/shm/domain.socket", which can be prefixed with @ to represent abstractopen in new tag, and @@ to represent padded abstract.

                If only the port is specified, both numbers and strings are accepted, such as 80 or "80". This usually points to a plaintext HTTP service (and the addr will be filled in as "127.0.0.1").

                xver: number

                Sends the PROXY protocolopen in new tag protocol, which is used to transmit the real source IP and port of the request. The version can be set to 1 or 2, with a default value of 0, which means no PROXY protocol is sent. Version 1 is recommended if needed.

                Currently, versions 1 and 2 have the same functionality but different structures, where version 1 is printable while version 2 is binary. Xray's TCP and WebSocket inbound already support receiving the PROXY protocol.

                Warning

                If you are configuring Nginx to receive the PROXY protocolopen in new tag, you need to not only set proxy_protocol, but also set_real_ip_from to avoid potential issues.

                Additional Information

                • Matches the most precise sub-element, regardless of the order of arrangement of the sub-elements. If several sub-elements have the same alpn and path configurations, the last one specified will be used.
                • Fallback routing is performed at the decrypted TCP layer rather than the HTTP layer, and the first packet PATH is only checked when necessary.
                • You can learn more about tips and experiences in using Fallbacks by visiting

                Fallbacks design theory WIP

                - + diff --git a/en/config/features/multiple.html b/en/config/features/multiple.html index 4766f9f89c..17b1e64e0b 100644 --- a/en/config/features/multiple.html +++ b/en/config/features/multiple.html @@ -24,8 +24,8 @@ Multi-file configuration | Project X - - + +

                Multi-file configuration

                The Xray program supports the use of multiple configuration files.

                The main purpose of using multiple configuration files is to distribute different module configurations, making it easier to manage and maintain.

                This feature is mainly designed to enrich the Xray ecosystem. For example, for GUI-based clients, only fixed functions such as node selection are usually implemented, and complex configurations are difficult to implement graphically. By leaving a custom confdir configuration directory for complex functions, server deployment scripts can simply add files to confdir to implement multiple protocol configurations.

                Multi-file startup

                Tip

                The startup information will indicate each configuration file being read in sequence. Please pay attention to whether the startup information matches the order you have set.

                $ xray run -confdir /etc/xray/confs
                @@ -103,6 +103,6 @@
                 
                 0 directories, 10 files
                 
                - + diff --git a/en/config/features/xtls.html b/en/config/features/xtls.html index b920332471..c061c8282f 100644 --- a/en/config/features/xtls.html +++ b/en/config/features/xtls.html @@ -24,11 +24,11 @@ Deep analysis of XTLS | Project X - - + + - + diff --git a/en/config/inbound.html b/en/config/inbound.html index 7ea9c8ef31..02a3285905 100644 --- a/en/config/inbound.html +++ b/en/config/inbound.html @@ -24,8 +24,8 @@ Inbound Proxy | Project X - - + +

                Warning

                This translation was modified on 12 March 2023 and an updated version (4 July 2024) is available on the source page. View the original page

                Inbound Proxy

                Inbound connections are used to receive incoming data and the available protocols are listed in inbound protocols.

                InboundObject

                The InboundObject corresponds to a subelement of the inbounds item in the configuration file.

                {
                @@ -62,6 +62,6 @@
                   "concurrency": 3
                 }
                 

                strategy: "always" | "random"

                The port allocation strategy.

                • "always" means all specified ports in port will be allocated, and Xray will listen on these ports.
                • "random" means ports will be randomly selected from the port range every refresh minutes, and concurrency ports will be listened on.

                refresh: number

                The interval for refreshing randomly allocated ports in minutes. The minimum value is 2, and it is recommended to set to 5. This property is only effective when strategy is set to "random".

                concurrency: number

                The number of randomly allocated ports. The minimum value is 1, and the maximum value is one-third of the port range. It is recommended to set to 3.

                - + diff --git a/en/config/inbounds/dokodemo.html b/en/config/inbounds/dokodemo.html index 81e7701ba3..a87f4b1b6c 100644 --- a/en/config/inbounds/dokodemo.html +++ b/en/config/inbounds/dokodemo.html @@ -24,8 +24,8 @@ Dokodemo-Door | Project X - - + +

                Warning

                This translation was modified on 14 June 2023 and an updated version (26 May 2024) is available on the source page. View the original page

                Dokodemo-Door

                Dokodemo door (Anywhere Door) can listen to a local port and forward all incoming data on this port to a specified server's port, achieving the effect of port mapping.

                InboundConfigurationObject

                {
                @@ -37,6 +37,6 @@
                   "userLevel": 0
                 }
                 

                address: address

                The address to forward the traffic to. It can be an IP address like "1.2.3.4" or a domain name like "xray.com". It is a string type.

                When followRedirect (see below) is set to true, address can be empty.

                port: number

                The specified port on the destination address to forward the traffic to. It should be in the range 1,655351,65535. It is a numeric value and is a required parameter.

                network: "tcp" | "udp" | "tcp,udp"

                The supported network protocol type. For example, when specified as "tcp", it will only receive TCP traffic. The default value is "tcp".

                timeout: number

                The idle timeout in seconds. The default value is 300. When handling a connection, if no data is transmitted within the timeout period, the connection will be terminated.

                followRedirect: true | false

                When set to true, dokodemo-door will recognize data forwarded by iptables and forward it to the corresponding destination address.

                Refer to the tproxy setting in the Transport Configuration for more information.

                userLevel: number

                The user level that the connection will use to determine the corresponding Local Policy.

                The value of userLevel corresponds to the value of level in the policy. If not specified, the default value is 0.

                Transparent Proxy Configuration Example

                Please refer to the Transparent Proxy (TProxy) Configuration Tutorial for this section.

                - + diff --git a/en/config/inbounds/http.html b/en/config/inbounds/http.html index eb73d31746..7193ff6a08 100644 --- a/en/config/inbounds/http.html +++ b/en/config/inbounds/http.html @@ -24,8 +24,8 @@ HTTP | Project X - - + +

                Warning

                This translation was modified on 14 June 2023 and an updated version (9 July 2023) is available on the source page. View the original page

                HTTP

                HTTP protocol.

                Warning

                The HTTP protocol does not provide encryption for transmission and is not suitable for transmission over public networks, as it can easily be used as a target for attacks.

                The more meaningful use of http inbound is to listen in a local network or on the local machine to provide local services for other programs.

                TIP 1

                http proxy can only proxy the TCP protocol and cannot handle protocols based on UDP.

                TIP 2

                In Linux, you can use the following environment variables to enable global HTTP proxy for the current session (many software support this setting, but some may not).

                • export http_proxy=http://127.0.0.1:8080/ (Change the address to the configured inbound HTTP proxy address)
                • export https_proxy=$http_proxy
                • :::

                InboundConfigurationObject

                {
                @@ -44,6 +44,6 @@
                   "pass": "my-password"
                 }
                 

                user: string

                The username. It is a string and is required.

                pass: string

                The password. It is a string and is required.

                - + diff --git a/en/config/inbounds/shadowsocks.html b/en/config/inbounds/shadowsocks.html index a49bddc58e..e8e2a56cd2 100644 --- a/en/config/inbounds/shadowsocks.html +++ b/en/config/inbounds/shadowsocks.html @@ -24,8 +24,8 @@ Shadowsocks | Project X - - + +

                Warning

                This translation was modified on 18 August 2023 and an updated version (1 June 2024) is available on the source page. View the original page

                Shadowsocks

                The Shadowsocksopen in new tag protocol is compatible with most other implementations of Shadowsocks. The server supports TCP and UDP packet forwarding, with an option to selectively disable UDP.

                Supported Encryption Methods

                The currently supported methods are following:

                • Recommended encryption methods:
                  • 2022-blake3-aes-128-gcm
                  • 2022-blake3-aes-256-gcm
                  • 2022-blake3-chacha20-poly1305
                • Other encryption methods:
                  • aes-256-gcm
                  • aes-128-gcm
                  • chacha20-poly1305/chacha20-ietf-poly1305
                  • xchacha20-poly1305/xchacha20-ietf-poly1305
                  • none/plain

                The Shadowsocks 2022 new protocol format improves performance and includes complete replay protection, addressing the following security issues in the old protocol:

                Danger

                Traffic transmitted without encryption using the "none" method will be in plain text. Do not use it on public networks for security reasons.

                InboundConfigurationObject

                {
                @@ -47,6 +47,6 @@
                 

                method: string, any of the supported methods

                Required.

                password: string

                Required. For Shadowsocks 2022 a pre-shared base64 random key similar to WireGuard's keys should be used as the password. The command

                openssl rand -base64 <length>
                 

                could used to generate a key. The length of the required key for shadowsocks-rust implementation depends on the encryption method:

                Encryption MethodKey Length
                2022-blake3-aes-128-gcm16
                2022-blake3-aes-256-gcm32
                2022-blake3-chacha20-poly130532

                In the go-shadowsocks implementation written in Golang, a 32-byte key always works.

                For any other encryption method any string could be used. There is no limitation on the password length, but shorter passwords are more susceptible to cracking. It is recommended to use a random-generated password of 16 characters or longer. The following example generates 40-characters length password:

                sudo strings /dev/urandom | grep -o '[[:alnum:]]' | head -n 40 | tr -d '\n'; echo
                 

                level: number

                The user level that the connection will use to determine the corresponding Local Policy.

                The value of level corresponds to the value of level in the policy. If not specified, the default value is 0.

                email: string

                The user's email, used to differentiate traffic from different users for logs or statistics.

                - + diff --git a/en/config/inbounds/socks.html b/en/config/inbounds/socks.html index 4c0116e1d1..59035fc612 100644 --- a/en/config/inbounds/socks.html +++ b/en/config/inbounds/socks.html @@ -24,8 +24,8 @@ SOCKS | Project X - - + +

                SOCKS

                The standard SOCKS protocol implementation is compatible with SOCKS 4open in new tag, SOCKS 4a, and SOCKS 5open in new tag.

                Danger

                The SOCKS protocol does not provide encryption for transport and is not suitable for transmitting data over public networks.

                The use of SOCKS inbound is more meaningful in a local area network or local environment, where it can be used to listen for incoming connections and provide local services to other programs.

                InboundConfigurationObject

                {
                @@ -45,6 +45,6 @@
                   "pass": "my-password"
                 }
                 

                user: string

                The username as a string. Required.

                pass: string

                The password as a string. Required.

                - + diff --git a/en/config/inbounds/trojan.html b/en/config/inbounds/trojan.html index 2600149356..7c63fd48bf 100644 --- a/en/config/inbounds/trojan.html +++ b/en/config/inbounds/trojan.html @@ -24,8 +24,8 @@ Trojan | Project X - - + +

                Trojan

                The Trojanopen in new tag protocol.

                Danger

                Trojan is designed to work with correctly configured encrypted TLS tunnels.

                InboundConfigurationObject

                {
                @@ -48,6 +48,6 @@
                   "level": 0
                 }
                 

                password: string

                Required. Any string.

                email: string

                Email address. Optional. Used to identify the user.

                Danger

                If there are multiple ClientObjects, please make sure that the email addresses are not duplicated.

                level: number

                The user level that the connection will use to determine the corresponding Local Policy.

                The value of level corresponds to the value of level in the policy. If not specified, the default value is 0.

                - + diff --git a/en/config/inbounds/vless.html b/en/config/inbounds/vless.html index c9e5ce3221..aa031344b6 100644 --- a/en/config/inbounds/vless.html +++ b/en/config/inbounds/vless.html @@ -24,8 +24,8 @@ VLESS | Project X - - + +

                Warning

                This translation was modified on 27 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

                VLESS

                Danger

                Currently, VLESS does not provide built-in encryption. Please use it with a reliable channel, such as TLS.

                VLESS is a stateless lightweight transport protocol that consists of inbound and outbound parts. It can serve as a bridge between Xray clients and servers.

                Unlike VMess, VLESS does not rely on system time. The authentication method is still UUID-based.

                InboundConfigurationObject

                {
                @@ -51,6 +51,6 @@
                   "flow": "xtls-rprx-vision"
                 }
                 

                id: string

                The user ID for VLESS. It can be any string less than 30 bytes or a valid UUID. Custom strings and their corresponding UUIDs are equivalent, which means you can use either of the following in the configuration file to identify the same user:

                • "id": "我爱🍉老师1314"
                • "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (This UUID is the mapping of the string "我爱 🍉 老师 1314")

                The mapping standard is described in the VLESS UUID Mapping Standard: Mapping a Custom String to a UUIDv5open in new tag.

                You can use the command xray uuid -i "custom string" to generate the UUID corresponding to a custom string.

                You can also use the command xray uuid to generate a random UUID.

                level: number

                The user level that the connection will use to determine the corresponding Local Policy.

                The value of level corresponds to the value of level in the policy. If not specified, the default value is 0.

                email: string

                User email address used to differentiate traffic from different users (reflected in logs and statistics).

                flow: string

                Flow control mode used to select the XTLS algorithm.

                Currently, the following flow control modes are available for inbound protocols:

                • No flow or empty string: Use regular TLS proxy.
                • xtls-rprx-vision: Use the new XTLS mode, including inner-handshake random padding.

                Additionally, XTLS currently only supports TCP+TLS/Reality.

                - + diff --git a/en/config/inbounds/vmess.html b/en/config/inbounds/vmess.html index cd760d069c..5f8851d688 100644 --- a/en/config/inbounds/vmess.html +++ b/en/config/inbounds/vmess.html @@ -24,8 +24,8 @@ VMess | Project X - - + +

                VMess

                VMess is an encrypted transport protocol that is commonly used as a bridge between Xray clients and servers.

                Danger

                VMess relies on system time. Please ensure that the system UTC time used by Xray is within 120 seconds of the actual time, regardless of time zone. On Linux systems, you can install the ntp service to automatically synchronize the system time.

                InboundConfigurationObject

                {
                @@ -55,6 +55,6 @@
                   "level": 0
                 }
                 

                level: number

                The user level that the connection will use to determine the corresponding Local Policy.

                The value of level corresponds to the value of level in the policy. If not specified, the default value is 0.

              - + diff --git a/en/config/index.html b/en/config/index.html index be13fe5067..c1de918958 100644 --- a/en/config/index.html +++ b/en/config/index.html @@ -24,8 +24,8 @@ Configurations | Project X - - + +

              This section will tell you all the details of Xray configuration. By mastering these contents, Xray will unleash its full power in your hands.

              Overview

              The configuration file of Xray is in JSON format, and the configuration format for the client and server is the same, except for the actual configuration content. It takes the following form:

              {
              @@ -45,6 +45,6 @@
                 "burstObservatory": {}
               }
               

              Warning

              If you are new to Xray, you can first click to view configuration and running in the Quick Start guide, to learn the most basic configuration method, and then refer to the contents of this section to master all the configuration methods of Xray.

              Basic Configuration Modules

              log:LogObject

              Log configurations, controlling how Xray emits logs.

              api:ApiObject

              Configures how Xray provides API interfaces for calling remotely.

              dns: DnsObject

              Configures the built-in DNS server. System DNS will be used if not configured.

              routing: RoutingObject

              Configures routing. Specify rules to route connections through different outbounds.

              policy: PolicyObject

              Local policy configurations, specifying different user levels and corresponding policies.

              inbounds: [ InboundObject ]

              An array of inbound connection configurations.

              outbounds: [ OutboundObject ]

              An array of outbound connection configurations.

              transport: TransportObject

              Configures how Xray establishes and uses network connections to other servers.

              stats: StatsObject

              Configures traffic statistics.

              reverse: ReverseObject

              Configures the built-in reverse proxy. You can forward server traffic to the client, effectively achieving reverse proxying.

              fakedns: FakeDnsObject

              FakeDNS configuration. Can be used with a transparent proxy to obtain the actual domains.

              metrics: metricsObject

              Metrics configuration. A more straightforward (and hopefully better) way to export metrics.

              observatory: ObservatoryObject

              Background connection observation. Detect the connection status of outbound proxies.

              burstObservatory: BurstObservatoryObject

              Concurrent connection observation. Detect the connection status of outbound proxies.

              - + diff --git a/en/config/log.html b/en/config/log.html index 043e3726be..1311489393 100644 --- a/en/config/log.html +++ b/en/config/log.html @@ -24,8 +24,8 @@ Log Configuration | Project X - - + +

              Log Configuration

              Log configuration controls how Xray outputs logs.

              Xray has two types of logs: access logs and error logs. You can configure the output method for each type of log separately.

              LogObject

              LogObject corresponds to the log item in the configuration file.

              {
              @@ -37,6 +37,6 @@
                 }
               }
               

              access: string

              The file path for the access log. The value is a valid file path, such as "/var/log/Xray/access.log" (Linux) or "C:\\Temp\\Xray\\_access.log" (Windows). When this item is not specified or is an empty value, the log is output to stdout.

              • The special value none disables access logs.

              error: string

              The file path for the error log. The value is a valid file path, such as "/var/log/Xray/error.log" (Linux) or "C:\\Temp\\Xray\\_error.log" (Windows). When this item is not specified or is an empty value, the log is output to stdout.

              • The special value none disables error logs.

              loglevel: "debug" | "info" | "warning" | "error" | "none"

              The log level for error logs, indicating the information that needs to be recorded. The default value is "warning".

              • "debug": Output information used for debugging the program. Includes all "info" content.
              • "info": Runtime status information, etc., which does not affect normal use. Includes all "warning" content.
              • "warning": Information output when there are some problems that do not affect normal operation but may affect user experience. Includes all "error" content.
              • "error": Xray encountered a problem that cannot be run normally and needs to be resolved immediately.
              • "none": Do not record any content.

              dnsLog: bool

              Whether to enable DNS query logs, for example: DOH//doh.server got answer: domain.com -> [ip1, ip2] 2.333ms.

              - + diff --git a/en/config/metrics.html b/en/config/metrics.html index d447125857..e72702c164 100644 --- a/en/config/metrics.html +++ b/en/config/metrics.html @@ -24,8 +24,8 @@ Metrics | Project X - - + +

              Metrics

              A more straightforward (and hopefully better) way to export metrics.

              It's possible to add a metrics inbound among inbounds.

                  "inbounds": [
              @@ -242,6 +242,6 @@
                          id: udp
                          expvar_type: int
               

              And you will get a nice plot like this:

              160428235-2988bf69-5d6c-41ec-8267-1bd512508aa8

              Additional

              Maybe reusing the empty object stats in config file is better than adding metrics here?

              Edit: removed prometheus related things and added usage about expvars

              - + diff --git a/en/config/observatory.html b/en/config/observatory.html index 0c70b038a7..bd4cea767a 100644 --- a/en/config/observatory.html +++ b/en/config/observatory.html @@ -24,8 +24,8 @@ 连接观测 | Project X - - + +

              Notice

              This page has not yet been translated, see how you can help here.

              连接观测

              连接观测组件使用 HTTPing 的方式探测出站代理的连接状态。观测结果可以被其他组件使用,如负载均衡器。目前有 observatory (后台连接观测)和 burstObservatory (并发连接观测)两种。按需选择其中之一就行。

              ObservatoryObject

              {
              @@ -50,6 +50,6 @@
                 "timeout": "30s"
               }
               

              destination: string

              用于探测出站代理连接状态的网址。这个网址应该返回 HTTP 204 成功状态码。

              connectivity: string

              用于检测本地网络连通性的网址。空字符串表示不检测本地网络连通性。

              interval: string

              在指定时间内探测全部匹配的出站代理,每个出站代理探测 sampling + 1 次。时间格式为数字 + 单位,比如 "10s", "2h45m",支持的时间单位有 ns, us, ms, s, m, h, 分别对应纳秒、微秒、毫秒、秒、分、时。

              sampling: number

              保留最近探测结果的数量。

              timeout: string

              探测超时时间。格式和上面的 interval 相同。

              - + diff --git a/en/config/outbound.html b/en/config/outbound.html index 4ec2a914ca..980fdbcdd8 100644 --- a/en/config/outbound.html +++ b/en/config/outbound.html @@ -24,8 +24,8 @@ Outbound Proxies | Project X - - + +

              Warning

              This translation was modified on 12 March 2023 and an updated version (7 August 2024) is available on the source page. View the original page

              Outbound Proxies

              Outbound connections are used for sending data and can use any of the available protocols listed in outbound protocols.

              OutboundObject

              The OutboundObject corresponds to a sub-element of the outbounds item in the configuration file.

              Tip

              The first element in the list serves as the main outbound. When there is no match or no successful match for the routing, the traffic is sent out by the main outbound.

              {
              @@ -51,6 +51,6 @@
                 "concurrency": 8
               }
               

              enabled: true | false

              Whether to enable Mux forwarding requests, default is false.

              concurrency: number

              Maximum concurrent connections. Minimum value is 1, maximum value is 1024, default is 8.

              This value represents the maximum number of Mux connections that can be carried on a TCP connection. For example, when concurrency=8 is set, if the client sends 8 TCP requests, Xray will only send one actual TCP connection, and all 8 requests from the client will be transmitted through this TCP connection.

              Tip

              When filling in a negative number, such as -1, the mux module is not loaded.

              - + diff --git a/en/config/outbounds/blackhole.html b/en/config/outbounds/blackhole.html index 781b4c9a8f..c85e46a0fe 100644 --- a/en/config/outbounds/blackhole.html +++ b/en/config/outbounds/blackhole.html @@ -24,8 +24,8 @@ Blackhole | Project X - - + +

              Blackhole

              Blackhole is an outbound data protocol that blocks all outbound data. When used in conjunction with routing configurations, it can be used to block access to certain websites.

              OutboundConfigurationObject

              {
              @@ -37,6 +37,6 @@
                 "type": "none"
               }
               

              type: "http" | "none"

              When type is set to "none" (default value), the blackhole will simply close the connection.

              When type is set to "http", the blackhole will send a simple HTTP 403 packet as the response and then close the connection.

              - + diff --git a/en/config/outbounds/dns.html b/en/config/outbounds/dns.html index a3252b0aa0..f6efc033c9 100644 --- a/en/config/outbounds/dns.html +++ b/en/config/outbounds/dns.html @@ -24,8 +24,8 @@ DNS | Project X - - + +

              DNS

              DNS is an outbound protocol used for intercepting and forwarding DNS queries.

              This outbound protocol can only handle DNS traffic, including queries based on UDP and TCP protocols. Other types of traffic will result in an error.

              When handling DNS queries, this outbound protocol will forward IP queries (A and AAAA) to the built-in DNS server. Other types of query traffic will be forwarded to their original destination addresses.

              OutboundConfigurationObject

              {
              @@ -35,6 +35,6 @@
                 "nonIPQuery": "drop"
               }
               

              network: "tcp" | "udp"

              Modifies the transport layer protocol for DNS traffic. The possible values are "tcp" and "udp". When not specified, the original transport method will be retained.

              address: address

              Modifies the DNS server address. When not specified, the original address specified in the source will be retained.

              port: number

              Modifies the DNS server port. When not specified, the original port specified in the source will be retained.

              nonIPQuery: string

              Control non IP queries (neither A or AAAA), "drop" this request or "skip" processing in DNS module,the request will be forwarded to target. By default is "drop".

              DNS Configuration Example WIP

              - + diff --git a/en/config/outbounds/freedom.html b/en/config/outbounds/freedom.html index 86322681ce..c9dc31a675 100644 --- a/en/config/outbounds/freedom.html +++ b/en/config/outbounds/freedom.html @@ -24,8 +24,8 @@ Freedom | Project X - - + +

              Warning

              This translation was modified on 11 July 2024 and an updated version (10 August 2024) is available on the source page. View the original page

              Freedom

              Freedom is an outbound protocol that can be used to send (normal) TCP or UDP data to any network.

              OutboundConfigurationObject

              {
              @@ -40,6 +40,6 @@
                 "proxyProtocol": 0
               }
               

              domainStrategy: "AsIs" | "UseIP" | "UseIPv4" | "UseIPv6"

              When the destination address is a domain name, configure the corresponding value for Freedom's behavior:

              • "AsIs": Freedom resolves the domain name using the system DNS server and connects to it.
              • "UseIP", "UseIPv4", and "UseIPv6": Xray resolves the domain name using the built-in DNS server and connects to it. The default value is "AsIs".

              TIP 1

              When using the "UseIP" mode and the sendThrough field is specified in the outbound connection configuration, Freedom will automatically determine the required IP type, IPv4 or IPv6, based on the value of sendThrough.

              TIP 2

              When using the "UseIPv4" or "UseIPv6" mode, Freedom will only use the corresponding IPv4 or IPv6 address. If sendThrough specifies a mismatched local address, the connection will fail.

              redirect: address_port

              Freedom will force all data to be sent to the specified address (instead of the address specified in the inbound).

              It is a string value, for example: "127.0.0.1:80", ":1234".

              When the address is not specified, such as ":443", Freedom will not modify the original destination address. When the port is 0, such as "xray.com:0", Freedom will not modify the original port.

              userLevel: number

              User level. The connection will use the corresponding local policy for this user level.

              The value of userLevel corresponds to the value of level in the policy. If not specified, the default value is 0.

              fragment: map

              A key-value map used to control TCP fragmentation,under some circumstances it can cheat the censor system, like bypass a SNI blacklist.

              "packets":support two different methods. "1-3" is for segmentation at TCP layer, applying to the beginning 1 to 3 data writes by the client. "tlshello" is for TLS client hello packet fragmentation.

              "length": length to make the cut

              "interval": time between fragments(ms)

              proxyProtocol: number

              The value of proxyProtocol represents the PROXY Protocol version. default value is 0.

              - + diff --git a/en/config/outbounds/http.html b/en/config/outbounds/http.html index e08a49f559..75d765fd80 100644 --- a/en/config/outbounds/http.html +++ b/en/config/outbounds/http.html @@ -24,8 +24,8 @@ HTTP | Project X - - + +

              HTTP

              HTTP is a protocol that is used for communication over the internet. Please note that HTTP does not provide encryption for data transmission and is not suitable for transmitting sensitive information over public networks, as it can be easily targeted for attacks.

              Danger

              The HTTP protocol does not provide encryption for transmission, making it unsuitable for transmitting over public networks and more susceptible to being used as a compromised host for attacks.

              Tip

              HTTP can only proxy TCP protocols, and cannot handle UDP-based protocols.

              OutboundConfigurationObject

              {
              @@ -57,6 +57,6 @@
                 "pass": "my-password"
               }
               

              user: string

              The username. Required.

              pass: string

              The password. Required.

              - + diff --git a/en/config/outbounds/loopback.html b/en/config/outbounds/loopback.html index 6233daceed..edd2fca7a9 100644 --- a/en/config/outbounds/loopback.html +++ b/en/config/outbounds/loopback.html @@ -24,8 +24,8 @@ Loopback | Project X - - + + - + diff --git a/en/config/outbounds/shadowsocks.html b/en/config/outbounds/shadowsocks.html index f9084a8e1a..6603ae04df 100644 --- a/en/config/outbounds/shadowsocks.html +++ b/en/config/outbounds/shadowsocks.html @@ -24,8 +24,8 @@ Shadowsocks | Project X - - + +

              Warning

              This translation was modified on 14 June 2023 and an updated version (14 July 2023) is available on the source page. View the original page

              Shadowsocks

              Shadowsocksopen in new tag protocol is compatible with most other implementations.

              Here are the features and compatibility of Shadowsocks:

              • It supports TCP and UDP packet forwarding, with the option to disable UDP.
              • Recommended encryption methods:
                • 2022-blake3-aes-128-gcm
                • 2022-blake3-aes-256-gcm
                • 2022-blake3-chacha20-poly1305
              • Other encryption methods:
                • aes-256-gcm
                • aes-128-gcm
                • chacha20-poly1305 (also known as chacha20-ietf-poly1305)
                • none or plain

              The new protocol format of Shadowsocks 2022 improves performance and includes full replay protection, addressing security issues present in the old protocol:

              Danger

              Using the "none" encryption method will transmit traffic in plaintext. It is not recommended to use "none" encryption on public networks to ensure security.

              OutboundConfigurationObject

              {
              @@ -51,6 +51,6 @@
                 "level": 0
               }
               

              email: string

              Email address (optional) used to identify the user.

              address: address

              The address of the Shadowsocks server, supporting IPv4, IPv6, and domain names. Required.

              port: number

              The port of the Shadowsocks server. Required.

              method: string

              Encryption method. Required.

              password: string

              Password. Required.

              uot: bool

              When enabled, UDP over TCP (UOT) will be used.

              • Shadowsocks 2022

              Use a pre-shared key (PSK) similar to WireGuard as the password.

              To generate a compatible key with shadowsocks-rust, use openssl rand -base64 <length>, where the length depends on the encryption method used.

              Encryption MethodKey Length
              2022-blake3-aes-128-gcm16
              2022-blake3-aes-256-gcm32
              2022-blake3-chacha20-poly130532

              In the Go implementation, a 32-byte key always works.

              • Other encryption methods

              Any string can be used as a password. There is no limit on the password length, but shorter passwords are more susceptible to cracking. It is recommended to use a password of 16 characters or longer.

              level: number

              User level. Connections will use the corresponding local policy associated with this user level.

              The level value corresponds to the level value in the policy. If not specified, the default value is 0.

              - + diff --git a/en/config/outbounds/socks.html b/en/config/outbounds/socks.html index 20c6f0bcce..e876d5bf0c 100644 --- a/en/config/outbounds/socks.html +++ b/en/config/outbounds/socks.html @@ -24,8 +24,8 @@ Socks | Project X - - + +

              Socks

              The Socks protocol is a standard protocol implementation that is compatible with Socks 5open in new tag.

              Danger

              The Socks protocol does not provide encryption for transmission and is not suitable for transmitting data over public networks.

              OutboundConfigurationObject

              {
              @@ -60,6 +60,6 @@
                 "level": 0
               }
               

              user: string

              The username. Required.

              pass: string

              The password. Required.

              level: number

              The user level. Connections will use the corresponding local policy associated with this user level.

              The level value corresponds to the level value in the policy. If not specified, the default value is 0.

              - + diff --git a/en/config/outbounds/trojan.html b/en/config/outbounds/trojan.html index ab9f7099e0..7639a0e845 100644 --- a/en/config/outbounds/trojan.html +++ b/en/config/outbounds/trojan.html @@ -24,8 +24,8 @@ Trojan | Project X - - + +

              Trojan

              Trojanopen in new tag protocol

              Danger

              Trojan is designed to work with correctly configured encrypted TLS tunnels.

              OutboundConfigurationObject

              {
              @@ -47,6 +47,6 @@
                 "level": 0
               }
               

              address: address

              The server address, which can be an IPv4, IPv6, or domain name. Required.

              port: number

              The server port, usually the same port that the server is listening on.

              password: string

              The password for authentication. Required. It can be any string.

              email: string

              The email address, optional, used to identify the user.

              level: number

              The user level. Connections will use the corresponding local policy associated with this user level.

              The level value corresponds to the level value in the policy. If not specified, the default value is 0.

              - + diff --git a/en/config/outbounds/vless.html b/en/config/outbounds/vless.html index 5baf4cdd66..0c54ad0e7f 100644 --- a/en/config/outbounds/vless.html +++ b/en/config/outbounds/vless.html @@ -24,8 +24,8 @@ VLESS | Project X - - + +

              Warning

              This translation was modified on 27 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

              VLESS

              Danger

              Currently, VLESS does not have built-in encryption, please use it on a reliable channel, such as TLS.

              VLESS is a stateless lightweight transport protocol, which is divided into inbound and outbound parts, and can be used as a bridge between Xray clients and servers.

              Unlike VMess, VLESS does not rely on system time, and the authentication method is also UUID.

              OutboundConfigurationObject

              {
              @@ -63,6 +63,6 @@
                 "level": 0
               }
               

              id: string

              The user ID of VLESS, which can be any string less than 30 bytes, or a valid UUID. Custom strings and their mapped UUIDs are equivalent, which means you can write an id in the configuration file to identify the same user, i.e.

              • Write "id": "I love 🍉 teacher 1314",
              • Or write "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (this UUID is the UUID mapping of I love 🍉 teacher 1314)

              The mapping standard is in VLESS UUID mapping standard: mapping custom strings to a UUIDv5open in new tag

              You can use the command xray uuid -i "custom string" to generate the UUID mapped by the custom string, or use the command xray uuid to generate a random UUID.

              encryption: "none"

              Need to fill in "none", cannot be left empty.

              This requirement is to remind users that there is no encryption and to prevent users from filling in the wrong attribute name or location, causing exposure when encryption methods come out in the future.

              If the value of encryption is not set correctly, an error message will be received when using Xray or -test.

              flow: string

              Flow control mode, used to select the XTLS algorithm.

              Currently, there are the following flow control modes available in the outbound protocol:

              • No flow or empty string: Use regular TLS proxy.
              • xtls-rprx-vision: using the new XTLS mode includes inner handshake random padding supports uTLS client fingerprint simulation
              • xtls-rprx-vision-udp443: same as xtls-rprx-vision, but allows UDP traffic with a destination of port 443

              Additionally, XTLS currently only supports TCP+TLS/Reality.

              About xtls-rprx-*-udp443 flow control mode

              When using Xray-core's XTLS, traffic to UDP port 443 is blocked by default (generally for QUIC), so the application will use TLS instead of QUIC, and XTLS will take effect. In fact, QUIC itself is not suitable for proxying because it has its own TCP functionality. When it is transmitted as UDP traffic through the VLESS protocol, the underlying protocol is TCP, which is equivalent to two layers of TCP.

              If you do not need to block it, please fill in xtls-rprx-*-udp443 on the client side and do not change the server side.

              About Splice mode

              Splice is a function provided by the Linux Kernel. The system kernel directly forwards TCP without going through Xray's memory, greatly reducing the number of data copies and CPU context switches.

              The usage restrictions of Splice mode are:

              • Linux environment
              • Inbound protocols are Dokodemo door, Socks, HTTP, etc., pure TCP connections, or other inbound protocols that use XTLS
              • Outbound protocol is VLESS + XTLS
              • It is worth noting that when using the mKCP protocol, Splice will not be used (yes, although there is no error, it is not used at all)

              In addition, when using Splice, the speed display will lag behind, which is a feature, not a bug.

              Using Vision mode will automatically enable Splice if the above conditions are met.

              level: number

              User level, the connection will use the local policy corresponding to this user level.

              The value of level corresponds to the value of level in policy. If not specified, the default is 0.

              - + diff --git a/en/config/outbounds/vmess.html b/en/config/outbounds/vmess.html index 42a25ac4e2..5e5cb24708 100644 --- a/en/config/outbounds/vmess.html +++ b/en/config/outbounds/vmess.html @@ -24,8 +24,8 @@ VMess | Project X - - + +

              Warning

              This translation was modified on 3 July 2023 and an updated version (7 January 2024) is available on the source page. View the original page

              VMess

              VMess is an encrypted transport protocol commonly used as a bridge between Xray clients and servers.

              Danger

              VMess relies on system time. Please ensure that the UTC time of your system, when using Xray, has an error within 120 seconds, regardless of the time zone. On Linux systems, you can install the ntp service to automatically synchronize the system time.

              OutboundConfigurationObject

              {
              @@ -54,6 +54,6 @@
                 "level": 0
               }
               

              id: string

              The user ID for VMess, which can be any string less than 30 bytes or a valid UUID.

              Custom strings and their corresponding UUIDs are equivalent. This means that you can use either a custom string or its corresponding UUID to identify the same user in the configuration file. For example:

              • Write "id": "我爱🍉老师1314",
              • Or write "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (this UUID is the mapping of the custom string "我爱 🍉 老师 1314")

              The mapping standard is described in the VLESS UUID Mapping Standard: Mapping a Custom String to a UUIDv5open in new tag.

              You can use the command xray uuid -i "custom string" to generate the UUID corresponding to a custom string, or use the command xray uuid to generate a random UUID.

              level: number

              The user level. Connections will use the corresponding local policy associated with this user level.

              The level value corresponds to the level value in the policy. If not specified, the default value is 0.

              security: "aes-128-gcm" | "chacha20-poly1305" | "auto" | "none" | "zero"

              The encryption method. The client will use the configured encryption method to send data, and the server will automatically recognize it without the need for configuration.

              • "aes-128-gcm": Recommended for use on PCs.
              • "chacha20-poly1305": Recommended for use on mobile devices.
              • "auto": Default value. Automatically selects the encryption method (uses aes-128-gcm when running on AMD64, ARM64, or s390x architecture, and Chacha20-Poly1305 in other cases).
              • "none": No encryption.
              • "zero": No encryption and no message authentication (v1.4.0+).

              Tip

              It is recommended to use the "auto" encryption method as it ensures long-term security and compatibility.

              The "none" pseudo-encryption method calculates and verifies the packet's checksum. However, due to the lack of hardware support for the authentication algorithm, it may be slower than the hardware-accelerated "aes-128-gcm" on some platforms.

              The "zero" pseudo-encryption method neither encrypts the message nor calculates the checksum, theoretically providing higher speed than any other encryption method. The actual speed may be influenced by other factors.

              It is not recommended to use the "none" or "zero" pseudo-encryption methods without enabling TLS encryption and forcibly verifying certificates. If you use a CDN or other intermediate platforms or network environments that decrypt TLS connections, it is not recommended to use the "none" or "zero" pseudo-encryption methods.

              Regardless of the encryption method used, the VMess packet header is protected by encryption and authentication.

              - + diff --git a/en/config/outbounds/wireguard.html b/en/config/outbounds/wireguard.html index 1da0d40d03..e654a680b4 100644 --- a/en/config/outbounds/wireguard.html +++ b/en/config/outbounds/wireguard.html @@ -24,8 +24,8 @@ Wireguard | Project X - - + +

              Warning

              This translation was modified on 26 December 2023 and an updated version (3 February 2024) is available on the source page. View the original page

              Wireguard

              Wireguard is a standard implementation of the Wireguard protocol.

              Danger

              The Wireguard protocol is not specifically designed for circumvention purposes. If used as the outer layer for circumvention, its characteristics may lead to server blocking.

              OutboundConfigurationObject

              {
              @@ -69,6 +69,6 @@
                 "allowedIPs": ["0.0.0.0/0"] // optional, default ["0.0.0.0/0", "::/0"]
               }
               

              endpoint: address

              The server address. Required.

              URL:port format, e.g. engage.cloudflareclient.com:2408.
              IP:port format, e.g. 162.159.192.1:2408 or [2606:4700:d0::a29f:c001]:2408.

              publicKey: string

              The server's public key used for verification. Required.

              preSharedKey: string

              An additional symmetric encryption key.

              keepAlive: int

              The interval of keep-alive packets in seconds. The default is 0, which means no keep-alive.

              allowedIPs: string array

              Only allow traffic from specific source IP addresses in Wireguard.

              - + diff --git a/en/config/policy.html b/en/config/policy.html index 1d5955ae0a..5479f732bc 100644 --- a/en/config/policy.html +++ b/en/config/policy.html @@ -24,8 +24,8 @@ Local Policy | Project X - - + +

              Local Policy

              Local policy can be used to set different policy settings for different user levels, such as connection timeout settings. Each connection handled by Xray corresponds to a user, and different policies are applied based on the user's level.

              PolicyObject

              PolicyObject corresponds to the policy field in the configuration file.

              {
              @@ -65,6 +65,6 @@
                 "statsOutboundDownlink": false
               }
               

              statsInboundUplink: true | false

              When set to true, enables upstream traffic statistics for all inbound proxies.

              statsInboundDownlink: true | false

              When set to true, enables downstream traffic statistics for all inbound proxies.

              statsOutboundUplink: true | false

              When set to true, enables upstream traffic statistics for all outbound proxies.

              statsOutboundDownlink: true | false

              When set to true, enables downstream traffic statistics for all outbound proxies.

              - + diff --git a/en/config/reverse.html b/en/config/reverse.html index 6443d3080b..99dcaeb8bf 100644 --- a/en/config/reverse.html +++ b/en/config/reverse.html @@ -24,8 +24,8 @@ Reverse Proxy | Project X - - + +

              Reverse Proxy

              A reverse proxy forwards traffic from a server to a client, which is known as reverse traffic forwarding.

              Here's how a reverse proxy generally works:

              • Suppose there is a web server in host A, which does not have a public IP address and cannot be accessed directly on the Internet. There is another host B that can be accessed via the public network. Now we need to use B as the entry point to forward traffic from B to A.
              • Configure Xray in host A as a bridge, and also configure Xray in B as a portal.
              • Bridge will actively establish a connection to portal, and the destination address of this connection can be set by itself. Portal will receive two types of connections: one is the connection sent by bridge, and the other is the connection sent by public network users. Portal will automatically merge the two types of connections. So bridge can receive public network traffic.
              • After receiving the public network traffic, bridge will forward it unchanged to the web server in host A. Of course, this step requires the cooperation of routing.
              • Bridge will dynamically load balance according to the size of the traffic.

              Tip

              Reverse proxy has Mux enabled by default, so please do not enable Mux again on the outbound it uses.

              Warning

              The reverse proxy function is still in the testing phase and may have some issues.

              ReverseObject

              ReverseObject corresponds to the reverse field in the configuration file.

              {
              @@ -144,6 +144,6 @@
                 ]
               }
               
              - + diff --git a/en/config/routing.html b/en/config/routing.html index ddd2687a95..c4c36b3bea 100644 --- a/en/config/routing.html +++ b/en/config/routing.html @@ -24,8 +24,8 @@ Routing | Project X - - + +

              Warning

              This translation was modified on 6 August 2024 and an updated version (10 August 2024) is available on the source page. View the original page

              Routing

              The routing module can send inbound data through different outbound connections according to different rules to achieve on-demand proxying.

              A common use case is to split domestic and foreign traffic. Xray can use its internal mechanisms to determine the traffic from different regions and then send them to different outbound proxies.

              For a more detailed analysis of the routing function, please refer to Routing Function Analysisopen in new tag.

              RoutingObject

              RoutingObject corresponds to the routing item in the configuration file.

              {
              @@ -57,6 +57,6 @@
                 "selector": []
               }
               

              tag: string

              The identifier of this load balancer, used to match balancerTag in RuleObject.

              selector: [ string ]

              An array of strings, each of which will be used to match the prefix of the outbound identifier. For example, in the following outbound identifiers: [ "a", "ab", "c", "ba" ], "selector": ["a"] will match [ "a", "ab" ].

              If multiple outbounds are matched, the load balancer currently selects one randomly as the final outbound.

              Predefined Domain Lists

              This list is included in every Xray installation package, and the file name is geosite.dat. This file contains some common domain names, which can be used as geosite:filename to perform routing or DNS filtering for domain names that match those in the file.

              Common domain lists include:

              • category-ads: Contains common advertising domain names.
              • category-ads-all: Contains common advertising domain names and advertising provider domain names.
              • cn: Equivalent to the combination of geolocation-cn and tld-cn.
              • apple: Contains most of the domain names under Apple.
              • google: Contains most of the domain names under Google.
              • microsoft: Contains most of the domain names under Microsoft.
              • facebook: Contains most of the domain names under Facebook.
              • twitter: Contains most of the domain names under Twitter.
              • telegram: Contains most of the domain names under Telegram.
              • geolocation-cn: Contains common domain names of mainland Chinese websites.
              • geolocation-!cn: Contains common domain names of non-mainland Chinese websites.
              • tld-cn: Contains top-level domain names managed by CNNIC for mainland China, such as domain names ending in .cn and .中国.
              • tld-!cn: Contains top-level domain names used outside mainland China, such as domain names ending in .hk (Hong Kong), .tw (Taiwan), .jp (Japan), .sg (Singapore), .us (United States), and .ca (Canada).

              You can also find the complete list of domain names here: Domain list communityopen in new tag.

              - + diff --git a/en/config/stats.html b/en/config/stats.html index 1c6d7858ee..891cbc363c 100644 --- a/en/config/stats.html +++ b/en/config/stats.html @@ -24,14 +24,14 @@ Traffic Statistics | Project X - - + +

              Traffic Statistics

              Used to configure traffic statistics for Xray.

              StatsObject

              The StatsObject corresponds to the stats item in the configuration file.

              {
                 "stats": {}
               }
               

              Currently, no parameters are required for traffic statistics, and internal statistics will be enabled as long as the StatsObject item exists.

              After statistics are enabled, you only need to enable the corresponding items in the Policy to collect the corresponding data.

              Retrieving Traffic Statistics

              You can use the xray api command to retrieve traffic statistics.

              The current traffic statistics are as follows:

              • User Data

                • user>>>[email]>>>traffic>>>uplink

                  The uplink traffic of a specific user, in bytes.

                • user>>>[email]>>>traffic>>>downlink

                  The downlink traffic of a specific user, in bytes.

              Tip

              If the corresponding user does not have an email specified, statistics will not be enabled.

              • Global Data

                • inbound>>>[tag]>>>traffic>>>uplink

                  The uplink traffic of a specific inbound, in bytes.

                • inbound>>>[tag]>>>traffic>>>downlink

                  The downlink traffic of a specific inbound, in bytes.

                • outbound>>>[tag]>>>traffic>>>uplink

                  The uplink traffic of a specific outbound, in bytes.

                • outbound>>>[tag]>>>traffic>>>downlink

                  The downlink traffic of a specific outbound, in bytes.

              - + diff --git a/en/config/transport.html b/en/config/transport.html index 7d155014b5..cbe3bf2626 100644 --- a/en/config/transport.html +++ b/en/config/transport.html @@ -24,8 +24,8 @@ Transport | Project X - - + +

              Transport

              Transports specify how Xray communicates with peers.

              Transports specify how to achieve stable data transmission. Both ends of a connection often need to specify the same transport protocol to successfully establish a connection. Like, if one end uses WebSocket, the other end must also use WebSocket, or else the connection cannot be established.

              Transport configuration consists of two parts:

              1. Global config (TransportObject) (deprecated)
              2. Local config (StreamSettingsObject).
              • When locally configured, you can specify how each inbound or outbound connection is transmitted individually.
              • Server inbounds and client outbounds often need to use the same transport protocol. When a transport protocol is specified without local configs, the transport will fall back to global transport configs.
              Global configuration (deprecated)

              TransportObject (deprecated)

              The TransportObject corresponds to the transport property in the config root.

              {
              @@ -182,6 +182,6 @@
                 }
               ]
               

              type: ""

              Required, the type of setting, valid values are int or str.

              level: ""

              Optional, protocol level, used to specify the effective range, the default is 6, which is TCP.

              opt: ""

              The option name of the operation, using decimal (the example here is that the value of TCP_CONGESTION is defined as 0xd and converted to decimal is 13)

              value: ""

              The option value to be set, the example here is set to bbr.

              Decimal numbers are required when type is specified as int.

              - + diff --git a/en/config/transports/domainsocket.html b/en/config/transports/domainsocket.html index a244b94dfb..5d352255af 100644 --- a/en/config/transports/domainsocket.html +++ b/en/config/transports/domainsocket.html @@ -24,8 +24,8 @@ Domain Socket | Project X - - + +

              Domain Socket

              Danger

              We recommend writing it to the listen field in inboundsand the transport mode can be TCP, WebSocket, or HTTP/2.

              Note that the DomainSocket option here may be deprecated in the future.

              Domain Socket uses standard Unix domain sockets to transmit data.

              The advantage of using DomainSocket is that it uses the built-in transport channel of the operating system and does not occupy the network cache. Theoretically, it is slightly faster than local loopback networks.

              Currently, it can only be used on platforms that support Unix domain sockets, such as Linux and macOS. It is not available until Windows 10 Build 17036.

              If DomainSocket is specified as the transport mode, the ports and IP addresses configured in the inbound and outbound proxies will be invalidated, and all transports will be replaced by DomainSocket.

              DomainSocketObject

              DomainSocketObject corresponds to the dsSettings item.

              {
              @@ -34,6 +34,6 @@
                 "padding": false
               }
               

              path: string

              A valid file path.

              Danger

              This file must not exist before running Xray.

              abstract: true | false

              Whether it is an abstract domain socket, with a default value of false.

              padding: true | false

              Whether the abstract domain socket has padding, with a default value of false.

              - + diff --git a/en/config/transports/grpc.html b/en/config/transports/grpc.html index 1fce895432..7491795cdd 100644 --- a/en/config/transports/grpc.html +++ b/en/config/transports/grpc.html @@ -24,8 +24,8 @@ gRPC | Project X - - + +

              Warning

              This translation was modified on 28 March 2023 and an updated version (27 March 2024) is available on the source page. View the original page

              gRPC

              An modified transport protocol based on gRPC.

              gRPC is based on the HTTP/2 protocol and can theoretically be relayed by other servers that support HTTP/2, such as Nginx.

              gRPC and HTTP/2 has built-in multiplexing, so it is not recommended to enable mux.cool when using gRPC or HTTP/2.

              ⚠⚠⚠

              • gRPC doesn't support specifying the Host. Please enter the correct domain name in the outbound proxy address, or fill in ServerName in (x)tlsSettings, otherwise connection cannot be established.
              • gRPC doesn't support fallback to other services.
              • gRPC services are at risk of being actively probed. It is recommended to use reverse proxy tools such as Caddy or Nginx to perform path-based routing.

              Tip

              If you are using a reverse proxy such as Caddy or Nginx, please note the following:

              • Make sure that the reverse proxy server has enabled HTTP/2.
              • Use HTTP/2 or h2c (Caddy), grpc_pass (Nginx) to connect to Xray.
              • The path for regular mode is /${serviceName}/Tun, and for Multi mode it is /${serviceName}/TunMulti.
              • If you need to receive the client IP address, you can use the X-Real-IP header sent by Caddy / Nginx to pass the client IP.

              Tip

              If you are using fallback, please note the following:

              • Fallback to gRPC is not recommended, as there is a risk of being actively probed.
              • Please make sure that h2 is the first priority in (x)tlsSettings.alpn, otherwise gRPC (HTTP/2) may not be able to complete TLS handshake.
              • gRPC cannot perform path-based routing by Xray.

              GRPCObject

              GRPCObject corresponds to the grpcSettings item.

              {
              @@ -37,6 +37,6 @@
                 "initial_windows_size": 0
               }
               

              serviceName: string

              A string that specifies the service name, similar to the path in HTTP/2.

              The client will use this name for communication, and the server will verify whether the service name matches.

              multiMode: true | false BETA

              true enables multiMode, with a default value of false.

              This is an experimental option that may not be retained for the long term, and cross-version compatibility is not guaranteed. This mode can bring about a performance improvement of around 20% in test environments, but actual effects may vary depending on the transmission rate.

              Tip

              Only need to be configured in outbound (client).

              idle_timeout: number

              The health check is performed when no data transmission occurs for a certain period of time, measured in seconds. If this value is set to less than 10, 10 will be used as the minimum value.

              Tip

              If you are not using reverse proxy tools such as Caddy or Nginx (which is usually the case), if this value is set to less than 60, the server may send "unexpected h2 GOAWAY" frames to close existing connections.

              By default, the health check is not enabled.

              Tip

              Only need to be configured in outbound (client).

              Tip

              Enabling health checks may help solve some "connection drop" issues.

              health_check_timeout: number

              The timeout for the health check, measured in seconds. If the health check is not completed within this time period, it is considered to have failed. The default value is 20

              Tip

              Only need to be configured in outbound (client).

              permit_without_stream: true | false

              true allows health checks to be performed when there are no sub-connections. The default value is false.

              Tip

              Only need to be configured in outbound (client).

              initial_windows_size: number

              The initial window size of the h2 stream. When the value is less than or equal to 0, this feature does not take effect. When the value is greater than 65535, the Dynamic Window mechanism will be disabled. The default value is 0, which means it is not effective.

              Tip

              Only need to be configured in outbound (client).

              Tip

              When using Cloudflare CDN, set the value to 35536 or higher to disable the Dynamic Window mechanism and prevent Cloudflare CDN from sending "unexpected h2 GOAWAY" frames to close existing connections.

              - + diff --git a/en/config/transports/h2.html b/en/config/transports/h2.html index b389289a90..5e35bdee66 100644 --- a/en/config/transports/h2.html +++ b/en/config/transports/h2.html @@ -24,8 +24,8 @@ HTTP/2 | Project X - - + +

              Warning

              This translation was modified on 28 March 2023 and an updated version (29 July 2024) is available on the source page. View the original page

              HTTP/2

              The transmission mode based on HTTP/2 fully implements the HTTP/2 standard and can be relayed by other HTTP servers (such as Nginx).

              Based on the recommendations of HTTP/2, both the client and server must enable TLS to use this transmission mode normally.

              HTTP/2 has built-in multiplexing, so it is not recommended to enable mux.cool when using HTTP/2.

              Tip

              The current version of the transmission mode based on HTTP/2 does not require TLS configuration for inbound (server-side).

              This makes it possible to use a plaintext HTTP/2 protocol called h2c for communication between the gateway and Xray, with external gateway components handling the TLS layer conversation in special-purpose load-balancing deployment environments.

              Warning

              ⚠️ If you are using fallback, please note the following:

              • Please make sure that h2 is included in (x)tlsSettings.alpn, otherwise HTTP/2 cannot complete TLS handshake.
              • HTTP/2 cannot perform path-based routing, so it is recommended to use SNI-based routing.

              HttpObject

              HttpObject corresponds to the httpSettings in the Transport Protocol,

              {
              @@ -39,6 +39,6 @@
                 }
               }
               

              host: [string]

              A string array, where each element is a domain name.

              The client will randomly select a domain name from the list for communication, and the server will verify whether the domain name is in the list.

              path: string

              The HTTP path starts with / and must be the same value between the client and server.

              The default value is /

              read_idle_timeout: number

              The connection health check is performed when no data has been received for a certain period of time, measured in seconds.

              By default, the health check is disabled.

              Tip

              Only need to be configured in outbound (client).

              Tip

              Enabling health checks may help solve some "connection drop" issues.

              health_check_timeout: number

              The timeout for the health check, measured in seconds. If the health check is not completed within this time period, it is considered to have failed. The default value is 15

              Tip

              Only need to be configured in outbound (client).

              method: string

              HTTP request method. The default value is PUT

              Please refer this thisopen in new tag when configure.

              headers: map{ string: [string] }

              Custom HTTP headers, defined as key-value pairs. Each key represents an HTTP header name and its corresponding value is an array.

              - + diff --git a/en/config/transports/httpupgrade.html b/en/config/transports/httpupgrade.html index a3dd866e12..4dacf5a24b 100644 --- a/en/config/transports/httpupgrade.html +++ b/en/config/transports/httpupgrade.html @@ -24,8 +24,8 @@ HTTPUpgrade | Project X - - + +

              Warning

              This translation was modified on 30 March 2024 and an updated version (29 July 2024) is available on the source page. View the original page

              HTTPUpgrade

              A WebSocket-like transport protocol implementing the HTTP/1.1 upgrade and response, allowing it to be reverse proxied by web servers or CDNs just like WebSocket, but without the need to implement the remaining portions of the WebSocket protocol, yielding better performance.

              Standalone usage is not recommended, but rather in conjunction with other security protocols like TLS.

              HttpUpgradeObject

              The HttpUpgradeObject corresponds to the httpupgradeSettings section under transport configurations.

              {
              @@ -37,6 +37,6 @@
                 }
               }
               

              acceptProxyProtocol: true | false

              For inbounds only. Specifies whether to accept the PROXY protocol.

              The PROXY protocolopen in new tag is used to pass the real IP address and port of a connection along. Ignore it if you have no knowledge regarding this.

              Common reverse proxies (e.g. HAProxy, NGINX) and VLESS fallbacks xver can be configured for its inclusion.

              When true, the downstream must first send PROXY protocol version 1 or 2 after establishing the underlying TCP connection, or the connection will be closed.

              path: string

              HTTP path used by the HTTPUpgrade connection. Defaults to "/".

              If the path property include an ed query field (e.g. /mypath?ed=2560), "early data" will be used to decrease latency, with the value defining the threshold of the first packet's size. If the size of the first packet exceeds the defined value, "early data" will not be applied. The recommended value is 2560.

              host: string

              HTTP Host sent by the HTTPUpgrade connection. Empty by default. If this value is empty on the server, the host header sent by clients will not be validated.

              If the Host header has been defined on the server in any way, the server will validate if the Host header matches.

              The current priority of the Host header sent by clients: host > headers > address

              headers: map {string: string}

              Customized HTTP headers defined in key-value pairs. Defaults to empty.

              - + diff --git a/en/config/transports/mkcp.html b/en/config/transports/mkcp.html index 405b3aee93..783d87b36b 100644 --- a/en/config/transports/mkcp.html +++ b/en/config/transports/mkcp.html @@ -24,8 +24,8 @@ mKCP | Project X - - + +

              Warning

              This translation was modified on 1 April 2023 and an updated version (2 January 2024) is available on the source page. View the original page

              mKCP

              mKCP uses UDP to emulate TCP connections.

              mKCP sacrifices bandwidth to reduce latency. To transmit the same content, mKCP generally consumes more data than TCP.

              Tip

              Make sure the firewall on the host is configured correctly.

              KcpObject

              KcpObject corresponds to the kcpSettings in the Transport Protocol,

              {
              @@ -45,6 +45,6 @@
                 "type": "none"
               }
               

              type: string

              Type of obfuscation. Corresponding inbound and outbound must have the same value. Choices are:

              • "none":Default value. No obfuscation is used.
              • "srtp":Obfuscated as SRTP traffic. It may be recognized as video calls such as Facetime.
              • "utp":Obfuscated as uTP traffic. It may be recognized as Bittorrent traffic.
              • "wechat-video":Obfuscated to WeChat traffic.
              • "dtls":Obfuscated as DTLS 1.2 packets.
              • "wireguard":Obfuscated as WireGuard packets. (NOT true WireGuard protocol)

              Special Thanks

              Improvements to the KCP protocol

              smaller protocol header

              The original KCP protocol uses a fixed header of 24 bytes, while mKCP modifies it to 18 bytes for data packets and 16 bytes for acknowledgement (ACK) packets. A smaller header helps evade feature detection and speeds up transmission.

              In addition, the original KCP can only confirm that one packet has been received with a single ACK packet. This means that when KCP needs to confirm that 100 packets have been received, it will send out 2400 bytes of data (24 x 100), including a large amount of repeated header information that wastes bandwidth. mKCP compresses multiple ACK packets, so 100 ACK packets only require 418 bytes (16 + 2 + 100 x 4), which is equivalent to one-sixth of the original KCP.

              ACK packet retransmission

              In the original KCP protocol, an ACK packet is only sent once. If an ACK packet is lost, it will cause unnecessary bandwidth waste due to data retransmission. In contrast, mKCP retransmits ACK packets at a certain frequency until they are confirmed by the sender. The size of a single ACK packet is 22 bytes, much smaller than the data packets which are over 1000 bytes. Therefore, the cost of retransmitting ACK packets is much lower.

              Connection state control

              mKCP can effectively initiate and close connections. When the remote host initiates disconnection, the connection will be released within two seconds. When the remote host lost connection, the connection will be released within a maximum of 30 seconds.

              The original KCP does not support this scenario.

              - + diff --git a/en/config/transports/quic.html b/en/config/transports/quic.html index 021b0f317c..26e2aad830 100644 --- a/en/config/transports/quic.html +++ b/en/config/transports/quic.html @@ -24,8 +24,8 @@ QUIC | Project X - - + +

              QUIC

              QUIC (Quick UDP Internet Connection) is a protocol proposed by Google for multiplexed and concurrent transmission using UDP. Its main advantages are:

              1. Reduced number of roundtrips in handshake phase. (1-RTT or 0-RTT)
              2. Multiplexing, and no Head-of-Line blockingopen in new tag problem.
              3. Connection migration, (mainly on the client side) when switching from Wifi to 4G, the connection will not be interrupted.

              QUIC is currently in the experimental phase and uses IETF implementation that is still being standardized, so compatibility with the final version cannot be guaranteed.

              • Default settings:

              QuicObject

              QuicObject corresponds to the quicSettings item in the Transport Protocol.

              Danger

              The configurations of both endpoints must be identical, otherwise the connection will fail.

              QUIC requires TLS to be enabled and if it is not enabled in the Transport Protocol, Xray will issue a self-signed certificate for TLS communication.

              {
              @@ -39,6 +39,6 @@
                 "type": "none"
               }
               

              type: string

              Type of obfuscation. Corresponding inbound and outbound proxy must have the same settings. Choices are:

              • "none": Default value. No obfuscation is used.
              • "srtp": Obfuscated as SRTP traffic. It may be recognized as video calls such as Facetime.
              • "utp": Obfuscated as uTP traffic. It may be recognized as Bittorrent traffic.
              • "wechat-video": Obfuscated to WeChat traffic.
              • "dtls": Obfuscated as DTLS 1.2 packets.
              • "wireguard": Obfuscated as WireGuard packets. (NOT true WireGuard protocol)

              Tip

              When neither encryption nor obfuscation is enabled, QUIC transport is compatible with other QUIC tools. However it is recommended to enable either or both for better undetectable communication.

              - + diff --git a/en/config/transports/splithttp.html b/en/config/transports/splithttp.html index 20999d7234..41d95e2617 100644 --- a/en/config/transports/splithttp.html +++ b/en/config/transports/splithttp.html @@ -24,8 +24,8 @@ SplitHTTP | Project X - - + +

              Warning

              This translation was modified on 29 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

              SplitHTTP

              v1.8.16+

              Uses HTTP chunked-transfer encoding for download, and multiple HTTP requests for upload.

              Can be deployed on CDNs that do not support WebSocket. However, the CDN must support HTTP chunked transfer encoding in a streaming fashion, no response buffering.

              This transport serves the same purpose as Meek (support non-WS CDN). It has the above streaming requirement to the CDN so that download can be much faster than (v2fly) Meek, close to WebSocket performance. The upload is also optimized, but still much more limited than WebSocket.

              Like WebSocket transport, SplitHTTP parses the X-Forwarded-For header for logging.

              SplitHttpObject

              The SplitHttpObject corresponds to the splithttpSettings section under transport configurations.

              {
              @@ -40,6 +40,6 @@
                 "noSSEHeader": false
               }
               

              path: string

              HTTP path used by the connection. Defaults to "/".

              host: string

              HTTP Host sent by the connection. Empty by default. If this value is empty on the server, the host header sent by clients will not be validated.

              If the Host header has been defined on the server in any way, the server will validate if the Host header matches.

              The current priority of the Host header sent by clients: host > headers > address

              headers: map {string: string}

              Customized HTTP headers defined in key-value pairs. Defaults to empty.

              scMaxEachPostBytes: int/string

              The maximum size of upload chunks, in bytes. The client defaults to 1MB and the server defaults to 2MB.

              The size set by the client must be lower than this value, otherwise when the POST request is sent larger than the value set by the server, the request will be rejected.

              This value should be smaller than the maximum request body allowed by the CDN or other HTTP reverse proxy, otherwise an HTTP 413 error will be thrown.

              It can also be in the form of a string "1000000-2000000". The core will randomly select a value within the range each time to reduce fingerprints.

              scMaxConcurrentPosts: int/string

              The number of concurrent uploads to run. Defaults to 100 on the client, and 200 on the server.

              The value on the client must not be higher than on the server. Otherwise, connectivity issues will occur. In practice, the upload concurrency is also limited by minUploadIntervalMs, so the actual concurrency on the client side will be much lower.

              It can also be in the form of a string "100-200", and the core will randomly select a value within the range each time to reduce fingerprints.

              scMinPostsIntervalMs: int/string

              (Client-only) How much time to pass between upload requests at a minimum. Defaults to 30 (milliseconds).

              It can also be in the form of a string "10-50", and the core will randomly select a value within the range each time to reduce fingerprints.

              noSSEHeader

              (Server-only) Do not send the Content-Type: text/event-stream response header. Defaults to false (the header will be sent)

              HTTP versions

              Added in 1.8.21: HTTP/3 support

              SplitHTTP supports http/1.1, h2 and h3 ALPN values. If the value is not set, h2 (prior-knowledge) is assumed when TLS is enabled, and http/1.1 without TLS. If the value is set to h3, the client will attempt to connect as HTTP/3, so UDP instead of TCP.

              The server listens to HTTP/1.1 and h2 by default, but if h3 ALPN is set on the server, it will listen as HTTP/3.

              Please note that nginx, Caddy and all CDN will almost certainly translate client requests to a different HTTP version for forwarding, and so the server may have to be configured with a different ALPN value than the client. If you use a CDN, it is very unlikely that h3 is a correct value for the server, even if the client speaks h3.

              Troubleshooting

              • If a connection hangs, the CDN may not support streaming downloads. You can use curl -Nv https://example.com/abcdef to initiate a download and see for yourself (see protocol details).

                If you do not see 200 OK and a response body of ok, then the CDN is buffering the response body. Please ensure that all HTTP middleboxes along the path between client and server observe X-Accel-Buffering: no from their origin server. If your chain is xray -> nginx -> CDN -> xray, nginx may strip this response header and you have to re-add it.

              Browser Dialer

              v1.8.17+

              If uTLS is not enough, SplitHTTP's TLS can be handled by a browser using Browser Dialer

              Protocol details

              See #3412open in new tag and #3462open in new tag for extensive discussion and revision of the protocol. Here is a summary, and the minimum needed to be compatible:

              1. GET /<UUID> opens the download. The server immediately responds with 200 OK, and immediately sends the string ok (arbitrary length, such as ooook) to force HTTP middleboxes into flushing headers.

                The server will send the X-Accel-Buffering: no and Content-Type: text/event-stream headers to force CDN into not buffering the response body. In HTTP/1.1 it may also send Transfer-Encoding: chunked.

              2. Client uploads using POST /<UUID>/<seq>. seq starts at 0 and can be used like TCP seq number, and multiple "packets" may be sent concurrently. The server has to reassemble the "packets" live. The sequence number never resets for simplicity reasons.

                The client may open upload and download in any order, either one starts a session. However, eventually GET needs to be opened (current deadline is hardcoded to 30 seconds) If not, the session will be terminated.

              3. The GET request is kept open until the tunneled connection has to be terminated. Either server or client can close.

                How this actually works depends on the HTTP version. For example, in HTTP/1.1 it is only possible to disrupt chunked-transfer by closing the TCP connection, in other versions the stream is closed or aborted.

              Recommendations:

              • Do not assume any custom headers are transferred correctly by the CDN. This transport is built for CDN who do not support WebSocket, these CDN tend to not be very modern (or good).

              • It should be assumed there is no streaming upload within a HTTP request, so the size of a packet should be chosen to optimize between latency, throughput, and any size limits imposed by the CDN (just like TCP, nagle's algorithm and MTU...)

              • HTTP/1.1 and h2 should be supported by server and client, and it should be expected that the CDN will translate arbitrarily between versions. A HTTP/1.1 server may indirectly end up talking to a h2 client, and vice versa.

              - + diff --git a/en/config/transports/tcp.html b/en/config/transports/tcp.html index b0a5a082e5..56f473b82e 100644 --- a/en/config/transports/tcp.html +++ b/en/config/transports/tcp.html @@ -24,8 +24,8 @@ TCP | Project X - - + +

              TCP

              TCP (Transmission Control Protocol) is currently one of the recommended transport protocols

              It can be combined with various protocols in multiple ways.

              TcpObject

              TcpObject corresponds to the tcpSettings item in the Transport Protocol.

              {
              @@ -69,6 +69,6 @@
                 }
               }
               

              version: string

              HTTP version, default is "1.1"

              status: string

              HTTP status, default is "200"

              reason: string

              HTTP status description, default value is "OK"

              headers: map {string, [ string ]}

              HTTP header, a key-value pair, each key represents the name of an HTTP header, and the corresponding value is an array.

              Each request will include all the keys and randomly select a corresponding value. Please refer to the default values shown in the example above.

              - + diff --git a/en/config/transports/websocket.html b/en/config/transports/websocket.html index a5ae8368cc..b069f92767 100644 --- a/en/config/transports/websocket.html +++ b/en/config/transports/websocket.html @@ -24,8 +24,8 @@ WebSocket | Project X - - + +

              Warning

              This translation was modified on 30 March 2024 and an updated version (29 July 2024) is available on the source page. View the original page

              WebSocket

              Uses standard WebSocket for data transmission.

              WebSocket connections can be proxied by other web servers (like NGINX) or by VLESS fallback paths.

              Tip

              WebSocket inbounds will parse the X-Forwarded-For header received, overriding the source address with a higher priority than the source address got from PROXY protocol.

              WebSocketObject

              WebSocketObject corresponds to the wsSettings property of the transport configs.

              {
              @@ -37,6 +37,6 @@
                 }
               }
               

              acceptProxyProtocol: true | false

              Only used by inbounds. Indicates whether to accept the PROXY protocol.

              The PROXY protocolopen in new tag is used to transmit the real source IP and port of connections. If you are not familiar with this, leave it alone.

              Commonplace reverse proxy software solutions (like HAProxy and NGINX) can be configured to have source IPs and ports sent with PROXY protocol. Same goes to VLESS fallbacks xver.

              When true, after the underlying TCP connection is established, the downstream must first send the source IPs and ports in PROXY protocol v1 or v2, or the connection will be terminated.

              path: string

              The HTTP path used by the WebSocket connection. Defaults to "/".

              If path contains the ed query parameter, early data will be activated for latency reduction, and its value will be the length threshold of the first packet. If the length of the first packet exceeds this value, early data won't be activated. The recommended value is 2560, with a maximum of 8192. Compatibility problems can occur when the value is set too high. Try lowering the threshold when encountering such problems.

              host: string

              The Host header sent in HTTP requests. Defaults to an empty string. Servers will not validate the Host header sent by clients when left blank.

              If the Host header has been defined on the server in any way, the server will validate if the Host header matches.

              The current priority of the Host header sent by clients: host > headers > address

              headers: map {string: string}

              Customized HTTP headers defined in key-value pairs. Defaults to empty.

              Browser Dialer

              Use the browser to handle TLS, see Browser Dialer

              - + diff --git a/en/development/index.html b/en/development/index.html index 7425621a01..c8b0139aa7 100644 --- a/en/development/index.html +++ b/en/development/index.html @@ -24,11 +24,11 @@ Development Guide | Project X - - + +

              Development Guide

              Compile Documentation

              Xray supports multiple platforms, and you can perform cross-compilation on various platforms by yourself.

              Please click Compile Documentation to view specific compile-related content.

              Design Concept

              Xray kernel provides a platform for secondary development.

              This section explains the design goals and architecture of Xray.

              Please click Design Principles to learn about the design goals and architecture of Xray.

              Development Standards

              This section outlines the guidelines to follow when obtaining code, developing, submitting PRs, as well as the relevant coding standards.

              Please click Development Specification to view the guidelines that should be followed during Xray development.

              Protocol Details

              Xray uses many protocols, and you can obtain a detailed description of each protocol through various means.

              VLESS Protocol

              VLESS is a stateless lightweight transport protocol that can serve as a bridge between Xray clients and servers.

              VMess Protocol

              VMess is an encrypted transport protocol that can act as a bridge between Xray clients and servers.

              Mux.Cool Protocol

              Mux.Cool protocol is a multiplexing transport protocol used to transmit multiple independent data streams within an established data stream.

              mKCP Protocol

              mKCP is a stream transmission protocol modified from the KCP protocolopen in new tag that can transmit arbitrary data streams in order.

              - + diff --git a/en/development/intro/compile.html b/en/development/intro/compile.html index e9a2877b85..b23508b97c 100644 --- a/en/development/intro/compile.html +++ b/en/development/intro/compile.html @@ -24,8 +24,8 @@ Compile the document | Project X - - + +

              Compile the document

              Preparatory Work

              Xray uses Golangopen in new tag as its programming language, so you need to install the latest version of Golang first in order to compile.

              If you happen to use Windows, please make sure to use Powershell.

              Pull Xray source code

              git clone https://github.com/XTLS/Xray-core.git
              @@ -38,6 +38,6 @@
               $env:GOOS="linux"
               $env:GOARCH="amd64"
               

              go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main```

              After uploading to the server, remember to execute chmod +x xray in the server terminal.

              Tip

              Execute go tool dist list to view all supported systems and architectures.

              Reproducible Build:

              Following the above steps, it is possible to compile and release an identical binary file as the one in Release.

              Warning

              Please confirm that you are using the same Golang version as the one used to compile the release.

            - + diff --git a/en/development/intro/design.html b/en/development/intro/design.html index 3feec9efdd..b9eb980ab6 100644 --- a/en/development/intro/design.html +++ b/en/development/intro/design.html @@ -24,11 +24,11 @@ Design Objectives | Project X - - + +

            Design Objectives

            • Xray Kernel provides a platform that supports essential network proxy functions and can be developed upon to provide a better user experience.
            • Cross-platform is the primary principle to reduce the cost of secondary development.

            Architecture

            Architecture

            The kernel is divided into three layers: the application layer, the proxy layer, and the transport layer.

            Each layer contains several modules, which are independent of each other. Modules of the same type can be seamlessly replaced.

            Application Layer

            The application layer contains some commonly used functions in proxy layers, which are abstracted for reuse in different proxy modules.

            The modules at the application layer should be implemented purely in software and should not be dependent on hardware or platform-related technologies.

            List of Important Modules:

            • Dispatcher: Used to transfer data received by the inbound agent to the outbound agent;
            • Router: Routing module, see Routing Configuration for details;
            • DNS: Built-in DNS server module;
            • Proxy Manager: Proxy manager;

            Proxy Layer

            The proxy layer is divided into two parts: Inbound Proxy and Outbound Proxy.

            The two parts are independent of each other, where the inbound proxy does not rely on a specific outbound proxy, and vice versa.

            Inbound Proxy

            Outbound Proxy

            Transport Layer

            The transport layer provides a set of tools and modules related to network data transmission.

            - + diff --git a/en/development/intro/guide.html b/en/development/intro/guide.html index 0b34fd92b6..2c1fca7e48 100644 --- a/en/development/intro/guide.html +++ b/en/development/intro/guide.html @@ -24,8 +24,8 @@ Development Standards | Project X - - + +

            Warning

            This translation was modified on 19 May 2023 and an updated version (13 February 2024) is available on the source page. View the original page

            Development Standards

            Basic

            Version Control

            Project X's code is hosted on GitHub:

            You can use Gitopen in new tag to get the code.

            Branch

            • The main branch is the backbone of this project.
            • The main branch is also the release branch of this project.
            • It is necessary to ensure that main can be compiled and used normally at any time.
            • If you need to develop new features, please create a new branch for development. After development and sufficient testing, merge it back to the main branch.
            • Please delete branches that have been merged into the main branch and are no longer necessary.

            Release

            WIP (Note: this is not translatable as it is a technical tag)
            • Create two release channels: one for the beta version and another for the stable version.
              • The beta version, also known as the daily build, is mainly used for specific testing, experimentation, and instant feedback and improvement.
              • The stable version, updated regularly (e.g. monthly), merges stable modifications and releases them.

            Citing other projects

            • Golang
              • It is recommended to use the Golang standard library and libraries under golang.org/x/open in new tag for product code;
              • If you need to reference other projects, please create an issue for discussion beforehand;
            • Other
              • Tools that do not violate the agreement of both parties and are helpful to the project can be used.

            Development Process

            Before Writing Code

            If you encounter any issues or have any ideas for the project, please create an issueopen in new tag for discussion to reduce redundant work and save time spent on coding.

            Modify the code

            • Golang
              • Please refer to Effective Goopen in new tag;
              • Run go generate core/format.go before each push;
              • If you need to modify protobuf, such as adding new configuration items, please run: go generate core/proto.go;
              • It is recommended to pass the test before submitting a pull request: go test ./...;
              • It is recommended to have more than 70% code coverage for newly added code before submitting pull requests.
            • Other
              • Please pay attention to the readability of the code.

            Pull Request

            • Before submitting a PR, please run git pull https://github.com/xray/xray-core.git to ensure that the merge can proceed smoothly;
            • One PR only does one thing. If there are fixes for multiple bugs, please submit a PR for each bug;
            • Due to Golang's special requirements (Package path), the PR process for Go projects is different from other projects. The recommended process is as follows:
              1. Fork this project first and create your own github.com/<your_name>/Xray-core.git repository;
              2. Clone your own Xray repository to your local machine: git clone https://github.com/<your_name>/Xray-core.git;
              3. Create a new branch based on the main branch, for example git branch issue24 main;
              4. Make changes on the new branch and commit the changes;
              5. Before pushing the modified branch to your own repository, switch to the main branch, and run git pull https://github.com/xray/xray-core.git to pull the latest remote code;
              6. If new remote code is obtained in the previous step, switch to the branch you created earlier and run git rebase main to perform branch merging. If there is a file conflict, you need to resolve the conflict;
              7. After the previous step is completed, you can push the branch you created to your own repository: git push -u origin your-branch
              8. Finally, send a PR from your new pushed branch in your own repository to the main branch of xtls/Xray-core;
              9. Please fully describe the purpose of this PR, including the problem solved, the new feature added, or the modifications made in the title and body of the PR;
              10. Please be patient and wait for the developer's response.

            Modifying Code

            Functional issue

            Please submit at least one test case to verify changes to existing functionality.

            Please provide the necessary test data to demonstrate performance issues in existing code or performance improvements in new code.

            New Feature

            • If the new feature does not affect the existing functionality, please provide a toggle (such as a flag) that can be turned on/off, and keep the new feature disabled by default.
            • For major new features (such as adding a new protocol), please submit an issue for discussion before development.

            Other

            It depends on the specific situation.

            Xray Coding Guidelines

            The following content is applicable to Golang code in Xray.

            Code Structure

            Xray-core
            @@ -40,6 +40,6 @@
             │   ├── vmess
             ├── transport  // Transport module
             

            Coding Standards

            Basic practices are consistent with the recommendations of the official Golang, with a few exceptions. Written here to help everyone familiarize themselves with Golang.

            Naming

            • Use a single English word for file and directory names, such as hello.go;
              • If not possible, use a hyphen for directories / underscore for files to connect two (or more) words, such as hello-world/hello_again.go;
              • Use _test.go to name test code files;
            • Use PascalCase for types, such as ConnectionHandler;
              • Do not force lowercase for abbreviations, i.e. HTML does not need to be written as Html;
            • Use PascalCase for public member variables;
            • Use camelCase for private member variables, such as privateAttribute;
            • For easy refactoring, it is recommended to use PascalCase for all methods;
              • Place completely private types in internal.

            Content Organization

            • A file contains a main type and its related private functions;
            • Testing-related files, such as Mock tools, should be placed in the testing subdirectory.
            - + diff --git a/en/development/protocols/mkcp.html b/en/development/protocols/mkcp.html index 98ec4ed37f..774d8849fe 100644 --- a/en/development/protocols/mkcp.html +++ b/en/development/protocols/mkcp.html @@ -24,11 +24,11 @@ mKCP Protocol | Project X - - + +

            mKCP Protocol

            mKCP is a stream transfer protocol, modified from the KCP protocolopen in new tag, which can transmit any data stream in order.

            Version

            mKCP has no version number and does not guarantee compatibility between versions.

            Dependencies

            Underlying Protocol

            mKCP is a protocol based on UDP, and all communication uses UDP transmission.

            Functions

            • fnv: FNV-1aopen in new tag hash function
              • Takes a string of arbitrary length as input parameter;
              • Outputs a 32-bit unsigned integer.

            Communication Process

            1. mKCP splits data streams into several data packets for transmission. Each data stream has a unique identifier to distinguish it from other data streams. Each data packet in the data stream carries the same identifier.
            2. mKCP does not have a handshake process. When receiving a data packet, it determines whether it is a new call or an ongoing call based on the identifier of the data stream it carries.
            3. Each data packet contains several segments (Segment), which are divided into three types: data (Data), acknowledgment (ACK), and heartbeat (Ping). Each segment needs to be processed separately.

            Data Format

            Data Packet

            4 Bytes2 BytesL Bytes
            Auth AData Len LFragment

            as which:

            • Authentication information A = fnv(fragment), big endian;
            • The fragment may contain multiple sections.

            Data snippet

            2 bytes1 byte1 byte4 bytes4 bytes4 bytes2 bytesLen bytes
            Conv flagCmd flagOpt flagTimestampSequenceUnacknowledgedLen flagData

            as which:

            • Identifier Conv: Identifier for mKCP data stream
            • Command Cmd: Constant 0x01
            • Option Opt: Optional values include:
              • 0x00: Empty option
              • 0x01: Opposite party has sent all data
            • Timestamp Ts: Time when the current segment was sent from the remote end, big endian
            • Sequence Number Sn: The position of the data segment in the data stream, the sequence number of the starting segment is 0, and each new segment is sequentially added by 1
            • Unacknowledged Sequence Number Una: The minimum Sn that the remote host is sending and has not yet received confirmation.

            Confirmation snippet

            2 bytes1 byte1 byte4 bytes4 bytes4 bytes2 bytesLen * 4 bytes
            Conv IDCmdOptWndNext Seq NumberTimestampLengthReceived Seq Number

            as which:

            • Identifier Conv: Identifier of the mKCP data stream
            • Command Cmd: Constant 0x00
            • Option Opt: Same as above
            • Window Wnd: The maximum sequence number that the remote host can receive
            • Next receive sequence number Sn: The smallest sequence number of the data segment that the remote host has not received
            • Timestamp Ts: The timestamp of the latest received data segment by the remote host, which can be used to calculate the delay
            • Received sequence numbers: Each 4 bytes, indicating that the data of this sequence number has been confirmed received.

            as which:

            • The remote host expects to receive data within the serial number [Sn, Wnd) range.

            Heartbeat Fragments

            2 Bytes1 Byte1 Byte4 Bytes4 Bytes4 Bytes
            Conv IDCmdOptUnacknowledged Seq NoNext Receive Seq NoRto

            as which:

            • Identifier Conv: Identifier for the mKCP data stream
            • Command Cmd: Optional values include:
              • 0x02: Remote host forcibly terminates the session
              • 0x03: Normal heartbeat
            • Option Opt: Same as above
            • Unacknowledged sequence number Una: Same as the Una of the data fragment
            • Next receive sequence number Sn: Same as the Sn of the acknowledgement fragment
            • Delay Rto: Delay calculated by the remote host itself
            - + diff --git a/en/development/protocols/muxcool.html b/en/development/protocols/muxcool.html index 2a255d6732..04eedcbb71 100644 --- a/en/development/protocols/muxcool.html +++ b/en/development/protocols/muxcool.html @@ -24,11 +24,11 @@ Mux.Cool Protocol | Project X - - + +

            Mux.Cool Protocol

            Mux.Cool protocol is a multiplexing transport protocol that is used to transmit multiple independent data streams within an established data stream.

            Version

            The current version is 1 Beta.

            Dependencies

            Underlying Protocol

            Mux.Cool must run on top of a reliable established data stream.

            Communication Process

            Within a Mux.Cool connection, multiple sub-connections can be transmitted, each with a unique ID and status. The transmission process consists of frames, with each frame used to transmit data for a specific sub-connection.

            Client behavior

            When there is a need for a connection and there are no existing available connections, the client initiates a new connection to the server, referred to as the "main connection".

            1. One main connection can be used to send several sub-connections. The client can decide independently how many sub-connections the main connection can handle.
            2. For a new sub-connection, the client must send the New status to notify the server to establish the sub-connection, and then use the Keep status to transmit data.
            3. When the sub-connection ends, the client sends the End status to notify the server to close the sub-connection.
            4. The client can decide when to close the main connection, but must ensure that the server also maintains the connection.
            5. The client can use the KeepAlive status to prevent the server from closing the main connection.

            Server-side behavior

            When a new sub-connection is received on the server side, the server should handle it as a normal connection.

            1. When the status "End" is received, the server can close the upstream connection to the target address.
            2. The same ID used in the request must be used to transfer sub-connection data in the server response.
            3. The server cannot use the "New" status.
            4. The server can use the KeepAlive status to avoid the client closing the main connection.

            Data Format

            Mux.Cool uses symmetric transmission format, where the client and server send and receive data in the same format.

            Frame Format

            2 BytesL BytesX Bytes
            Metadata Length LMetadataAdditional Data

            Metadata

            There are several types of metadata. All types of metadata contain two items, ID and Opt, with the following meanings:

            • ID: Unique identifier of the sub-connection
              • For general MUX sub-connections, the ID is accumulated starting from 1
              • For XUDP, the ID is always 0
            • Opt:
              • D(0x01): Additional data is available

            When option Opt(D) is enabled, the additional data format is as follows:

            2 BytesX-2 Bytes
            Length X-2Data
            2 Bytes1 Byte1 Byte1 Byte2 Bytes1 ByteA Bytes
            ID0x01OptionNetwork NPortType TAddress

            where:

            • Network type N:
              • 0x01: TCP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of TCP.
              • 0x02: UDP, indicating that the traffic of the current sub-connection should be sent to the destination in the way of UDP.
            • Address type T:
              • 0x01: IPv4
              • 0x02: Domain name
              • 0x03: IPv6
            • Address A:
              • When T = 0x01, A is a 4-byte IPv4 address;
              • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
              • When T = 0x03, A is a 16-byte IPv6 address;

            If Opt(D) is enabled when creating a sub-connection, the data carried by this frame needs to be sent to the target host.

            Keep sub-connections

            2 Bytes1 Byte1 Byte
            ID0x02Option

            If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host. XUDP adds the UDP address after Opt(D), and the format is the same as creating a new sub-connection.

            End

            2 Bytes1 Byte1 Byte
            ID0x03Option

            If Opt(D) is enabled while maintaining sub-connections, the data carried by this frame needs to be sent to the target host.

            KeepAlive

            2 Bytes1 Byte1 Byte
            ID0x04Option Opt

            While staying connected:

            • If Opt(D) is enabled, the data carried by this frame must be discarded.
            • ID can be a random value.

            Application

            The Mux.Cool protocol is agnostic to the underlying protocol and can theoretically use any reliable streaming connection to transmit Mux.Cool protocol data.

            In target-oriented protocols such as Shadowsocks and VMess, a specified address must be included when establishing a connection. To maintain compatibility, the Mux.Cool protocol specifies the address as "v1.mux.cool". When the target address of the main connection matches this address, the Mux.Cool forwarding method is used. Otherwise, forwarding is done in the traditional way. (Note: This is an internal tag in the program, and VMess and VLESS do not send the "v1.mux.cool" address in data packets.)

            - + diff --git a/en/development/protocols/vless.html b/en/development/protocols/vless.html index f3ac242fb7..768c20b569 100644 --- a/en/development/protocols/vless.html +++ b/en/development/protocols/vless.html @@ -24,11 +24,11 @@ VLESS Protocol | Project X - - + +

            VLESS Protocol

            VLESS is a stateless lightweight transmission protocol that can be used as a bridge between Xray clients and servers.

            Request & Response

            1 byte16 bytes1 byteM bytes1 byte2 bytes1 byteS bytesX bytes
            Protocol VersionEquivalent UUIDAdditional Information Length MAdditional Information ProtoBufInstructionPortAddress TypeAddressRequest Data
            1 Byte1 ByteN BytesY Bytes
            Protocol Version, consistent with the requestLength of additional information NAdditional information in ProtoBufResponse data

            VLESS had the aforementioned structure as early as the second alpha test version (ALPHA 2), with BETA being the fifth test version.

            "Response authentication" has been replaced with "Protocol version" and moved to the front, allowing VLESS to upgrade and eliminate the overhead of generating pseudo-random numbers. The obfuscation-related structure has been replaced with "Additional information" (ProtoBuf) and moved forward, giving the protocol itself scalability, with minimal overhead (gogo/protobufopen in new tag). If there is no additional information, there is no relevant overhead.

            I always thought that "response authentication" was not necessary, and ALPHA replaced crypto/rand with math/rand in order to improve the performance of random number generation, which is no longer needed.

            The "Protocol Version" not only serves as "Response Authentication", but also gives VLESS the ability to upgrade the protocol structure seamlessly, bringing infinite possibilities. The "Protocol Version" is 0 in the test version and 1 in the official version. If there are any incompatible protocol structural changes in the future, the version should be upgraded.

            The design of VLESS server is switch version, which supports all VLESS versions at the same time. If you need to upgrade the protocol version (which may not happen), it is recommended that the server support it one month in advance, and then change the client after one month. VMess requests also have protocol versions, but their authentication information is outside, and the instruction part is highly coupled and has fixed encryption, which makes the protocol version meaningless inside. The server does not judge it, and the response does not have a protocol version. Trojan's protocol structure does not have a protocol version.

            The following is a UUID. I used to think that 16 bytes were a bit long and considered shortening it. However, I later saw that Trojan used 56 printable characters (56 bytes), which completely dispelled this idea. The server needs to verify the UUID every time, so performance is also very important: VLESS's Validator has undergone multiple refactoring/upgrades. Compared with VMess, it is very concise and consumes very few resources. It can support a large number of users at the same time, and its performance is also very strong. The verification speed is extremely fast (sync.Map). API dynamically adds and deletes users, making it more efficient and smooth. https://github.com/XTLS/Xray-core/issues/158

            Introducing ProtoBuf is an innovation, which will be explained in detail later. The structure from "instruction" to "address" is currently identical to VMess and also supports Mux.

            Overall, ALPHA 2 to BETA mainly includes: structural evolution, cleaning and integration, performance improvement, and more completeness. All of these are incremental improvements, please refer to VLESS Changesopen in new tag for details.

            ProtoBuf

            It seems that only VLESS supports embedding ProtoBuf, which is a data exchange format that encodes information tightly into binary TLV (Tag Length Value) structures.

            The reason is that I saw an article that said that SS has some drawbacks, such as the lack of a design error reporting mechanism, and the client cannot take further action based on different errors. (But I don't agree that all errors should be reported, otherwise it can't prevent active probing. In the next beta version, the server can return a custom string of information.) So I think a scalable structure is important, and in the future, it can also carry dynamic port instructions. Not only the response, but the request also needs a similar structure. I originally planned to design TLV by myself, but then I found that ProtoBuf is the structure, ready-made, and it is completely suitable for this purpose, and the support for various languages is also good.

            Currently, "Additional Information" only has Scheduler and SchedulerV, which are substitutes for MessName and MessSeed. When you don't need them, the "Additional Information Length" is 0, so there is no ProtoBuf serialization/deserialization overhead. Actually, I prefer to call this process "concatenation" because that's all pb does in principle, and the related overhead is minimal. The concatenated bytes are very compact, similar to ALPHA's solution, and those who are interested can output and compare them separately.

            To indicate different levels of support for additional information (Addons, which can be understood as plugins and can have many plugins in the future), the next beta version will add "Addon Version" before "Addon Length". 256-1 = 255 bytes is enough and reasonable (65535 is too much and there may be malicious padding), and only one-tenth of the existing space is used. In the future, there will not be so many addons at the same time, and most of the time there will be no addons at all. If it is not enough, you can upgrade to a newer version of VLESS.

            To reduce logical judgment and other expenses, it is temporarily decided that Addons will not use a multi-level structure. A month ago, there was an idea of "variable protocol format". PB can shuffle the order, but it is not necessary because the design of modern encryption will not allow bystanders to see that the headers of the two transmissions are the same.

            Below is an introduction to the concepts of Schedulers and Encryption, both of which are optional. One is designed to address issues related to traffic timing, while the other is designed to address cryptographic issues.

            Flow

            Flow Control (Formerly Traffic Scheduler)

            The Flow Control command is carried by ProtoBuf and manages the data section.

            I previously discovered that VMess's original "metadata obfuscation" feature didn't provide any meaningful changes in TLS but only decreased performance. Consequently, VLESS has abandoned this feature. Moreover, the term "obfuscation" is often misinterpreted as camouflage, so it has been discarded.

            As for camouflage, if it can't be an exact match, wouldn't it be a noticeable characteristic? If it could be an exact match, why not use the intended target for camouflage directly? Initially, I used SSR but found it only provided superficial disguises, fooling operators. Thus, I stopped using it.

            Purpose of Flow Control

            Flow Control influences macro traffic temporal characteristics rather than micro characteristics addressed by encryption. Traffic temporal characteristics can be:

            1. Protocol-based, e.g., Socks5 handshake when using Socks5 over TLS. Different traits on TLS are considered different protocols for monitors. Infinite schedulers equate to infinite protocols (reallocating data sent each time).
            2. Behavior-based, e.g., loading files, their order, and size when accessing Google's homepage. Adding another encryption layer cannot effectively conceal this information.

            Schedulers don't require wrapping like encryption since the header data's tiny amount is negligible compared to the remaining data.

            BETA 2 is anticipated to introduce two basic schedulers: Zstd compression and dynamic data expansion. Advanced operations will control and distribute at a macro level, but for now, these remain under development.

            Encryption

            Unlike VMess, which is highly coupled, VLESS allows the server and client to pre-agree on an encryption method, which is only encrypted with an outer layer. This is somewhat similar to using TLS, which does not affect any of the data carried, and can be understood as replacing TLS with pre-agreed encryption at the bottom. Compared with high coupling, this approach is more reasonable and flexible: if there is a security issue with one encryption method, it can be discarded and another one can be used directly, which is very convenient. The VLESS server also allows for different encryption methods to coexist.

            Compared with VMess, VLESS replaces security with encryption and disableInsecureEncryption with decryption, which solves all the problems. Currently, encryption and decryption only accept "none" and cannot be left blank (even if there are connection security checks in the future), as detailed in the VLESS configuration document. Encryption does not need to be moved out one level, firstly because it cannot reuse a lot of code, and secondly because it will affect the control granularity, which will be understood by looking at future applications.

            Encryption supports two types of forms. One type is completely independent and requires an additional password, suitable for private use. The other type combines with the existing UUID for encryption, which is suitable for public use.

            (If the first type of encryption is used and the password is publicly available in some form, such as multiple people sharing it, then a man-in-the-middle attack is not far away.)

            A redesigned dynamic port may be released simultaneously with encryption, and the command is carried by ProtoBuf. The specific implementation and the dynamic port of VMess will also have many differences.

            It is very easy to cash out encrypted currency, which adds an extra layer of writer & reader. BETA 3 is expected to support SS's aes-128-gcm and chacha20-ietf-poly1305:

            The encryption on the client-side can be filled with "auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654". Auto will choose the most suitable one for the current machine, 0 represents the beta version, and the last one is the password. The decryption on the server-side is also filled in a similar way, and each decryption attempt will be made when the request is received.

            Not all combinations need to be tried one by one: VMess encryption is divided into three parts. The first part is the authentication information, which combines UUID, alterId, and time factors. The second part is the instruction part, which is encrypted using a fixed algorithm. The instruction contains the encryption algorithm used in the data part. The third part is the important data part. It can be seen that the VMess encryption and decryption method is actually many-to-one (adapted by the server), not just combining UUID. However, it is also a relatively difficult thing to encrypt only by combining UUID. It will not be available in a short time. Considering that we now have VMessAEAD available, there is no need to rush. If VLESS introduces an encryption method that combines UUID, it is equivalent to reconstructing the entire VMess.

            UDP issues

            XUDP: VLESS & VMess & Mux UDP FullCone NATopen in new tag

            Client Development Guide

            1. The VLESS protocol itself may have incompatible upgrades, but the parameters in the client configuration file are basically only increased and not decreased. The protocol implementation of the iOS client needs to keep up with the upgrade.
            2. Visual standard: Please use VLESS as the UI identifier uniformly, instead of VLess / Vless / vless. The configuration file is not affected, and the code should follow naturally.
            3. Encryption should be made into an input box instead of a selection box. The default value of the new configuration should be none, and if the user leaves it blank, it should be filled in with none.

            Thank you to @DuckSoftopen in new tag for the proposal!

            Please see VMessAEAD/VLESS Sharing Link Standard Proposalopen in new tag for more details.

            - + diff --git a/en/development/protocols/vmess.html b/en/development/protocols/vmess.html index 592258ef12..a673e10d84 100644 --- a/en/development/protocols/vmess.html +++ b/en/development/protocols/vmess.html @@ -24,11 +24,11 @@ VMess Protocol | Project X - - + +

            VMess Protocol

            VMess is an encrypted transmission protocol that can serve as a bridge between the Xray client and server.

            Version

            The current version number is 1.

            Dependencies

            Underlying Protocol

            VMess is a TCP-based protocol where all data is transmitted over TCP.

            User ID

            An ID is equivalent to a UUIDopen in new tag, which is a 16-byte long random number. Its function is similar to a token. An ID looks like: de305d54-75b4-431b-adb2-eb6b9e546014, it is almost entirely random and can be generated using any UUID generator, such as this oneopen in new tag.

            User ID can be specified in the configuration file.

            Functions

            Communication Process

            VMess is a stateless protocol, which means that data can be transmitted directly between the client and the server without the need for a handshake. Each data transmission has no impact on other data transmissions before or after it.

            When a VMess client initiates a request, the server checks whether the request comes from a legitimate client. If the validation passes, the server forwards the request and sends the obtained response back to the client.

            VMess uses an asymmetric format, meaning that the requests sent by the client and the responses from the server use different formats.

            Client Request

            16 BytesX BytesRemaining
            Authentication InformationInstruction PartData Part

            Authentication Information

            The authentication information is a 16-byte hash (hash) value, which is calculated as follows:

            • H = MD5
            • K = User ID (16 bytes)
            • M = UTC time accurate to seconds, with a random value of ±30 seconds from the current time (8 bytes, Big Endian)
            • Hash = HMAC(H, K, M)

            Command Section

            The instruction part is encrypted using AES-128-CFB.

            • Key: MD5(user ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
            • IV: MD5(X + X + X + X), X = []byte(time generated by authentication information) (8 bytes, Big Endian)
            1 Byte16 Bytes16 Bytes1 Byte1 Byte4 bits4 bits1 Byte1 Byte2 Bytes1 ByteN BytesP Bytes4 Bytes
            VersionData Encryption IVData Encryption KeyResponse Authentication ValueOptionsReservedEncryption MethodReservedCommandPortAddress TypeAddressRandom ValueChecksum

            Options Opt Details: (When a bit is 1, it means the option is enabled)

            01234567
            XXXXXMRS

            of which:

            • Version Number Ver: Always 1;
            • Data Encryption IV: Random value;
            • Data Encryption Key: Random value;
            • Response Authentication V: Random value;
            • Option Opt:
              • S (0x01): Standard format data stream (recommended);
              • R (0x02): Client expects to reuse TCP connection (deprecated in Xray 2.23+);
                • This item only takes effect when S is enabled;
              • M (0x04): Enable metadata obfuscation (recommended);
                • This item only takes effect when S is enabled;
                • When this item is enabled, the client and server need to construct two Shake instances respectively, RequestMask = Shake (request data IV), ResponseMask = Shake (response data IV).
              • X: Reserved
            • Redundancy P: Random value added before checksum value;
            • Encryption Method: Specify the encryption method for the data part, and the optional values are:
              • 0x00: AES-128-CFB;
              • 0x01: No encryption;
              • 0x02: AES-128-GCM;
              • 0x03: ChaCha20-Poly1305;
            • Instruction Cmd:
              • 0x01: TCP data;
              • 0x02: UDP data;
            • Port Port: Integer port number in Big Endian format;
            • Address Type T:
              • 0x01: IPv4
              • 0x02: Domain name
              • 0x03: IPv6
            • Address A:
              • When T = 0x01, A is a 4-byte IPv4 address;
              • When T = 0x02, A is a 1-byte length (L) + L-byte domain name;
              • When T = 0x03, A is a 16-byte IPv6 address;
            • Check F: FNV1a hash of all content in the instruction except F.

            Data Section

            When Opt(S) is enabled, this format is used for the data section. The actual request data is divided into several small chunks, and each chunk has the following format. After the server verifies all the small chunks, it will be forwarded in the basic format.

            2 BytesL Bytes
            Length LData Packet

            in which:

            • Length L: A big-endian integer with a maximum value of 2^14.
              • When Opt(M) is enabled, the value of L is equal to the true value xor Mask. Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
            • Packet: A data packet encrypted by the specified encryption method.

            Before the transmission is completed, the data packet must contain actual data, in addition to the length and authentication data. When the transmission is complete, the client must send an empty data packet, that is, L = 0 (unencrypted) or the length of the authentication data (encrypted), to indicate the end of the transmission.

            The packets are formatted as follows, depending on the encryption method:

            • Unencrypted:   - L bytes: actual data;
            • AES-128-CFB: The entire data section is encrypted using AES-128-CFB.   - 4 bytes: FNV1a hash of actual data;   - L - 4 bytes: actual data;
            • AES-128-GCM: Key is the Key of the instruction section, IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: GCM authentication information
            • ChaCha20-Poly1305: Key = MD5 (instruction part Key) + MD5 (MD5 (instruction part Key)), IV = count (2 bytes) + IV (10 bytes). count starts at 0 and increases by 1 for each packet; IV is the 3rd to 12th byte of the instruction section IV.   - L - 16 bytes: actual data;   - 16 bytes: Poly1305 authentication information

            Server Response

            The header data is encrypted using AES-128-CFB encryption. The IV is MD5 of the data encryption IV, and the Key is MD5 of the data encryption Key. The actual response data varies depending on the encryption settings.

            1 Byte1 Byte1 Byte1 ByteM BytesRemaining Part
            Response Authentication VOption OptCommand CmdCommand Length MCommand ContentActual Response Data

            in which:

            • Response Authentication V: must match the response authentication V in the client request.
            • Option Opt:
              • 0x01: server prepares to reuse TCP connections (deprecated in Xray 2.23+).
            • Command Cmd:
              • 0x01: dynamic port command.
            • Actual response data:
              • If Opt(S) in the request is enabled, the standard format is used. Otherwise, the basic format is used.
              • Both formats are identical to the request data.
                • When Opt(M) is enabled, the value of length L is equal to the true value XOR Mask. Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte().

            Dynamic Port Instructions

            1 Byte2 Bytes16 Bytes2 Bytes1 Byte1 Byte
            ReservedPortUser IDAlterIDUser levelValidity period T

            in which:

            • Port: Integer port number in Big Endian format
            • T: Number of minutes as integer value.

            When the client receives a dynamic port command, the server opens a new port for communication. The client can then send data to the new port. After T minutes, the port will expire, and the client must use the main port to communicate again.

            Comment

            • To ensure forward compatibility, the values of all reserved fields must be 0.
            - + diff --git a/en/document/command.html b/en/document/command.html index 2741606ea7..831626f075 100644 --- a/en/document/command.html +++ b/en/document/command.html @@ -24,8 +24,8 @@ Command Parameters | Project X - - + +

            Warning

            This translation was modified on 24 December 2023 and an updated version (11 August 2024) is available on the source page. View the original page

            Command Parameters

            Tip

            Xray uses Go-style commands and parameters

            Get Basic Commands

            You can run xray helpto get the most basic usage of all xray, as well as available commands and instructions.

            Xray is a platform for building proxies.
            @@ -76,6 +76,6 @@
             

            xray x25519

            Generate x25519 key pair。

            Usage:

            xray x25519 [-i "(base64.RawURLEncoding)" --std-encoding]
             

            xray wg

            Generate wireguard curve25519 key pair。

            Usage:

            xray wg [-i "(base64.StdEncoding)"]
             

            Tip

            When -config is not specified, Xray will try to load config.json from the following paths:

            - + diff --git a/en/document/config.html b/en/document/config.html index c66ebef953..6d47b6d0dc 100644 --- a/en/document/config.html +++ b/en/document/config.html @@ -24,8 +24,8 @@ Configure and Run | Project X - - + +

            Warning

            This translation was modified on 14 May 2023 and an updated version (26 December 2023) is available on the source page. View the original page

            Configure and Run

            After downloading and installing Xray, you need to configure it.

            For demonstration purposes, only a simple configuration method is introduced here. For more templates, please refer to Xray-examplesopen in new tag.

            If you need to set up more advanced features, please refer to the relevant instructions in the more detailed configuration file.

            Server Configuration

            You need a server outside the firewall to run server-side Xray. The configuration is as follows:

            {
            @@ -93,6 +93,6 @@
               }
             }
             

            The only thing you need to modify in the above configuration is your server's IP address, which is indicated in the configuration. This configuration will redirect all traffic to your server, except for traffic on the local area network (such as the access router).

            Run

            • On Windows and macOS, the configuration files are usually named config.json.
              • To start Xray, simply run Xray or Xray.exe.
            • On Linux, the configuration files are usually located in /etc/xray/ or /usr/local/etc/xray/.
              • To start Xray, run the command xray run -c /etc/xray/config.json.
              • Alternatively, you can use a tool like systemd to run Xray as a background service.

            For more detailed instructions, please refer to the Configuration Document and Layman's Terms.

            - + diff --git a/en/document/document.html b/en/document/document.html index 904aa53453..251180bb54 100644 --- a/en/document/document.html +++ b/en/document/document.html @@ -24,14 +24,14 @@ Contribute to Project X's Document | Project X - - + +

            Warning

            This translation was modified on 4 March 2023 and an updated version (13 February 2024) is available on the source page. View the original page

            Contribute to Project X's Document

            Contributions to Project X's Document are welcome, and we appreciate every Contributor's contribution! You guys make Xray stronger!

            Improve Document

            Document for Project X is hosted on GitHubopen in new tag.

            You can submit your changes to the Document by following these steps:

            1. Open the repository from Project X Documentopen in new tag, click fork in the upper right corner, fork a mirror image of the document repository to your own GitHub repository.

            2. Get a clone of the docs from the repository you cloned using whatever tool you like, like:

            git clone https://github.com/XTLS/Xray-docs-next.git
             
            1. Create a new branch based on the main branch, such as:
            git checkout -b your-branch
             
            1. Make changes on the new branch.

            2. After modification, please use Prettieropen in new tagFormat your changes.

              Note: Pull requests with formatting issues may be rejected.

            3. Submit the changes and push them to your repository

            git push -u origin your-branch
             
            1. Open GitHub, click 'Pull request' to submit a pull request to Project X Documentopen in new tag.

            2. Please outline the new/modified content of this pull request in the title and body of the pull request;

            3. Waiting for a response, if the pull request is merged, your changes will be directly displayed on Project X Document Websiteopen in new tag.

            Found Problems?

            If you find an error in the document, you can improve the documentation or submit an issue.

            - + diff --git a/en/document/index.html b/en/document/index.html index 77bd4202cf..097208f7b6 100644 --- a/en/document/index.html +++ b/en/document/index.html @@ -24,11 +24,11 @@ Quick Start | Project X - - + +

            Quick Start

            Warning

            This translation was modified on 4 March 2023 and an updated version (26 December 2023) is available on the source page. View the original page

            This chapter will tell you how to get Xray in the easiest way and start using Xray.

            Download and Install

            Xray supports various platforms, and you can get various versions of Xray from various sources and methods.

            Please click How to Download and Install Xray to get Xray

            Configure and Run

            After downloading and installing Xray, you need to configure it.

            Please click How to Configure and Run Xray to learn the easiest way to configure Xray.

            Command Parameters

            Xray has a variety of commands and parameters available, making it flexible and powerful.

            Please click Command Parameters for Xray to view more commands and parameters usages.

            Improve Documents

            If you're interested, please click Documents to help us improve the documents, or click theHelp us improve this page!

            We are very grateful to every Contributor for their contribution! You guys make Project X even stronger!

            Beginner Tutorial

            A easy tutorial for beginner.

            Please click 小小白白话文 to view it.

            Getting Started Tips

            After you have the basics, you can explore more ways to use them through Getting Started Tips.

            Advanced Documentation

            Tips for advanced user guidance

            Click on Advanced Documentation to view it

            Appreciations

            Thank you very much for your selfless sharing of usage skills and experience, which makes Xray more and more powerful.

            - + diff --git a/en/document/install.html b/en/document/install.html index 389b6a2e77..2c1d0f4312 100644 --- a/en/document/install.html +++ b/en/document/install.html @@ -24,11 +24,11 @@ Download and Install | Project X - - + + -

            Warning

            This translation was modified on 4 March 2023 and an updated version (4 November 2023) is available on the source page. View the original page

            Download and Install

            Platform Support

            • Xray is available on the following platforms:
              • Windows 7 and later (x86 / amd64 / arm32 / arm64);
              • macOS 10.10 Yosemite and later (amd64 / arm64);
              • Linux 2.6.23 and later (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                • Including but not limited to Debian 7 / 8, Ubuntu 12.04 / 14.04 and subsequent versions, CentOS 7 / 8, Arch Linux, etc.;
              • FreeBSD (x86 / amd64);
              • OpenBSD (x86 / amd64);
              • Dragonfly BSD (amd64);

            Download Xray

            Precompiled binaries in ZIP format are available at GitHub Releasesopen in new tag found in.

            Download the compressed package of the corresponding platform, and use it after decompression.

            Verify the Installation Package

            Xray provides two verification methods:

            Install on Windows

            Install on macOS

            Install on Linux

            Install Script

            Arch Linux

            Arch User Repository

            Need to use AUR helpersopen in new tag, yayopen in new tag as an example, it can be installed via yay -S xray.

            Arch Linux CN

            First add Arch Linux CNopen in new tag repository, and then use the root user pacman -S xrayto install.

            Linuxbrew

            The Linuxbrew package manager is used in the same way as Homebrew: brew install xray

            Debian WIP

            Install via Docker

            The File Structure of the Docker Image

            • /etc/xray/config.json: configuration file
            • /usr/bin/xray: Xray main program
            • /usr/local/share/xray/geoip.dat: IP data file
            • /usr/local/share/xray/geosite.dat: domain name data file

            GUI Client

            UUID Generator

            Third-party UUID generator uuidgenerator.netopen in new tag

            - +

            Download and Install

            Platform Support

            • Xray is available on the following platforms:
              • Windows 7 and later (x86 / amd64 / arm32 / arm64);
                • If you need to use these version (1.8.4, 1.8.6, 1.8.18 and later marked with win7) in Windows 7, operating system update KB4474419 is required. Concerning for Internet security, it is recommended to install KB4490628 to acqacquire later operating systems from Windows Update.
              • macOS 10.10 Yosemite and later (amd64 / arm64);
              • Linux 2.6.23 and later (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
                • Including but not limited to Debian 7 / 8, Ubuntu 12.04 / 14.04 and subsequent versions, CentOS 7 / 8, Arch Linux, etc.;
              • FreeBSD (x86 / amd64);
              • OpenBSD (x86 / amd64);

            Download Xray

            Precompiled binaries in ZIP format are available at GitHub Releasesopen in new tag found in.

            Download the compressed package of the corresponding platform, and use it after decompression.

            Verify the Installation Package

            Xray provides two verification methods:

            Install on Windows

            Install on macOS

            Install on Linux

            Install Script

            Arch Linux

            Arch User Repository

            Need to use AUR helpersopen in new tag, yayopen in new tag as an example, it can be installed via yay -S xray.

            Arch Linux CN

            First add Arch Linux CNopen in new tag repository, and then use the root user pacman -S xrayto install.

            Linuxbrew

            The Linuxbrew package manager is used in the same way as Homebrew: brew install xray

            Debian WIP

            Install via Docker

            The File Structure of the Docker Image

            • /etc/xray/config.json: configuration file
            • /usr/bin/xray: Xray main program
            • /usr/local/share/xray/geoip.dat: IP data file
            • /usr/local/share/xray/geosite.dat: domain name data file

            GUI Client

            UUID Generator

            Third-party UUID generator uuidgenerator.netopen in new tag

            + diff --git a/en/document/level-0/ch01-preface.html b/en/document/level-0/ch01-preface.html index 45012314ad..9dfb6cd1fb 100644 --- a/en/document/level-0/ch01-preface.html +++ b/en/document/level-0/ch01-preface.html @@ -24,11 +24,11 @@ [Chapter 1] Simple and Plain Language | Project X - - + +

            [Chapter 1] Simple and Plain Language

            1.1 Who is this document written for?

            One sentence: Written for newbies who are (1) absolute beginners and (2) interested in learning how to build their own VPS.

            1.2 Who is this document not written for?

            Including but not limited to: experts and professionals, beginners who are too lazy to tinker on their own, advanced users who already know how to tinker, wealthy users who insist on using airport services, and those who prefer using one-click scripts. In short, if you have a technical background or don't want to build it yourself, you can close this article directly, because this article may not be suitable for you and may even make you upset.

            1.3 Declaration and Other Statements

            Declaration:

            My technical skills are extremely limited, so this article is inevitably full of errors and flaws. If you find any problems, please kindly point them out and don't be too harsh on me.

            Disclaimer:

            Please judge the reliability and usability of the content of this article by yourself. If you encounter any problems or negative results when establishing and using a VPS server based on the content of this article, I am not responsible for it.

            Verbose statement:

            Considering the target audience of this article, which is "users with zero experience", many details will be explained in great detail, so the language may be verbose. Please be mentally prepared for this.

            1.4 Why is self-hosting a challenge?

            To answer this question, we need to provide a little more background information.

            1. On the matter of accessing the internet through scientific means

            The act of accessing the internet using scientific methods has been around for almost 20 years (shocking!!!.jpg). Initially, one could do it with a little effort (changing the host file, using SSH), then one had to find a web proxy, and later, one had to develop a private protocol (such as Shadowsocks) and so on.

            With the continuous iteration and upgrade of GFW technology over the past decade, to achieve the goal of [building your own scientific Internet access], the things that need to be done include but are not limited to:

            • Understand basic Linux commands
            • Understand network transmission protocols
            • Have the technical and financial ability to purchase and manage a VPS
            • Have the technical and financial ability to purchase and manage a domain name
            • Have the technical ability to apply for a TLS certificate, and so on.

            This has turned the once simple act of [setting up a self-built VPS for accessing the internet in a secure and unrestricted manner] into a daunting challenge that intimidates newcomers.

            1. Helplessness of Zero-based Users

            For non-technical users with zero foundation, if they complete the above series of operations, they will inevitably need to learn a lot of knowledge. However, after a little searching, newbies are likely to become even more confused: a large amount of information is scattered in various corners of the Internet: blogs, Q&A sites, groups, forums, GitHub, Telegram, YouTube, and so on. These pieces of information are chaotic and complex, with varying levels of quality, and may even contradict each other. Basically, they won't stop until they completely confuse the newcomer.

            Faced with such chaotic information, newcomers suddenly shift from [information scarcity] to [information overload]. If they fail after several attempts of groping and guessing (which is highly probable), their enthusiasm is bound to be greatly frustrated. In this process, if they happen to seek help in some unfriendly places, they may be ridiculed even more: "You're so inexperienced, just use the airport, why bother messing around!" "Go learn Linux first before coming back to ask."

            At this moment, probably only an "hehe" can express the mood.

            1.5 "Why not just use the airport?"

            First of all, I would like to respond to those who ridicule and criticize by asking a question: Is using the airport really a panacea?

            Secondly, I believe that there is a fundamental difference between "not understanding" and "not wanting to understand". The bad attitude of some people who just want handouts is naturally annoying, but those who sincerely want to learn but don't know how should not be subject to unjustified contempt and discrimination. It is precisely this kind of bad community atmosphere that does not distinguish between newcomers that prompted me to write this article. So without further ado, let's take a look at the advantages and disadvantages of the airport:

            1. 稳定性高:机场节点数量多,分布广泛,避免了单点故障的风险,保证了整个网络的稳定性。
            2. 速度快:机场的节点通常采用高速服务器和优化的网络架构,网络速度较快,能够满足用户的高速上网需求。
            3. 安全性高:机场通常会采用严格的安全措施,如流量加密、防火墙等,保护用户数据的安全性。
            4. 稳定性高:机场通常采用专业的运维团队进行管理和维护,保证了服务的稳定性和可靠性。
            5. 服务质量高:机场通常会提供完善的客户服务,及时解决用户的问题和反馈,提升用户的满意度。

            The so-called "airport" refers to the "line provider". They are responsible for completing the technical operations and management mentioned in section 1.4, while users pay for the right to use the service. Therefore, its advantages include at least:

            1. Simple User Operation: Scan code operation, one-click rule addition, etc.
            2. Multiple Line Options: Can unlock network services in different countries and regions, such as iplc dedicated line services, game acceleration services, etc.
            3. Multiple Access Nodes: Therefore, it has a stronger ability to resist node blocking, if one is blocked, just switch to another one.
            • Risks of "Airport"

            "The other side of the coin of 'convenience' is 'risk'. Based on the technical characteristics and market conditions of the 'airport', its risks include at least:"

            1. "Airport" can fully obtain user information: All the traces left by users online will inevitably and very likely be stored on their servers for a long time. These records cannot be restricted by any legally binding user privacy agreement. ("Snooping and recording your every move")
            2. "Airport" lacks market management: There are inevitably malicious merchants who target fraud. ("Actively run away")
            3. "Airport" faces regulatory pressure: While large airports are relatively secure, they cannot avoid attracting attention. In 2020, several large airports experienced shutdowns and runaways, seriously disrupting users' normal usage. ("Passively run away")
            4. "Airport" technical level is difficult to determine: The quality of the line varies greatly, and the phenomenon of falsely advertising quality services is common. ("Slow speed, frequent disconnections, unable to connect")

            1.6 So should you build your own website?

            Now that you have seen the advantages and risks of the airport, please think carefully and make your own decision on what to use. After all, the best plan is the one that suits you best.

            It's Your Choice!

            1. If you decide to use the airport, you can close this article now.

            2. If you decide to build it yourself, please continue reading the following chapters!

            In short, the goal of this article is to serve as a starting point for users with zero experience, providing thorough explanations and demonstrations for each step, even if it may seem overly detailed or repetitive. The aim is to assist beginners in completing the entire process of deploying a VPS server from the first command input to successfully accessing the internet via the client, and gradually introducing them to basic Linux operations, laying a foundation for further self-learning.

            1.7 Some digressions

            1. There is a wealth of information outside of the wall, so please learn to think rationally and independently. Don't take sides easily and don't believe in sensational information.

            2. We sincerely hope that with a smoother internet, everyone can access fresher knowledge, richer entertainment, experience a better world, and make more like-minded friends, but do not become a scapegoat for anyone with ulterior motives.

            3. Your internet identity is still your identity, and achieving absolute anonymity is extremely difficult. Therefore, please be sure to comply with the relevant laws and regulations in your personal location and the location of your IP address. Self-protection is always the most basic bottom line.

            1.8 Your Progress

            ⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

            - + diff --git a/en/document/level-0/ch02-preparation.html b/en/document/level-0/ch02-preparation.html index 5eef89e9ff..5e9c9f7bb0 100644 --- a/en/document/level-0/ch02-preparation.html +++ b/en/document/level-0/ch02-preparation.html @@ -24,11 +24,11 @@ [Chapter 2] Preparation of Raw Materials | Project X - - + +

            [Chapter 2] Preparation of Raw Materials

            This chapter is rather special because it involves monetary transactions. This article takes a neutral stance on the project and does not make specific recommendations. What I can do is to tell you what you need to prepare.

            2.1 Acquiring a VPS

            You need to obtain a healthy VPS with an unblocked IP, and perform the following basic preparations in the management console:

            1. Install Debian 10 64-bit system in the backend of VPS.
            2. Write down the IP address of VPS in a notebook (this article will use "100.200.300.400" as an example, which is an intentionally incorrect and illegal IP address. Please replace it with your real IP address).
            3. Write down the SSH remote login port of VPS in a notebook.
            4. Write down the username and password for SSH remote login in a notebook.

            Buying a VPS is a relatively complex matter. It is recommended to first learn the relevant knowledge and choose one that suits your own economic ability and line requirements. In addition, you can choose to take advantage of some benefits offered by international giants (such as permanent free or limited-time free packages offered by Oracle and Google). In any case, you must act within your means.

            Explanation

            Regarding the choice of Debian 10 as the operating system, let me elaborate a bit: No matter what you have heard online, no matter which guru has told you that XXX version of Linux is better or XXX version of Linux is more powerful, these sectarian disputes have nothing to do with you right now! Using Debian 10 is enough to optimize your VPS server for security, stability, and performance (such as using cloud-optimized kernel, timely support of BBR, etc.). After you become familiar with Linux, you can try other Linux distributions.

            2.2 Obtaining a Desired Domain Name

            You need to obtain a domain name and add an A record in the DNS settings, pointing to the IP address of your VPS.

            1. Please choose a reliable international domain name service provider. Choose some common domain name suffixes, and make sure not to use the .cn suffix.
            2. In the DNS settings, add an A record pointing to the IP address of your VPS (the name of the A record can be anything, and in this article, it will be represented by "a-name"). The complete domain name will be represented by "subdomain.yourdomain.com" or "a-name.yourdomain.com". The effect is as shown in the picture below:

            Add A Record

            Tip

            This is not a real usable website. Please replace it with your real website URL.

            2.3 Software you need to install on your local computer

            1. SSH remote login tool
            1. Remote file copying tool
            1. Reliable text editor

            2.4 Your Progress

            If you have all the raw materials ready as mentioned above, you have already obtained the key to unlocking the door to a new world. So, what are you waiting for? Let's quickly move on to the next chapter and step through this door!

            ⬛⬛⬜⬜⬜⬜⬜⬜ 25%

            - + diff --git a/en/document/level-0/ch03-ssh.html b/en/document/level-0/ch03-ssh.html index 0882a34874..7b4e2890ec 100644 --- a/en/document/level-0/ch03-ssh.html +++ b/en/document/level-0/ch03-ssh.html @@ -24,13 +24,13 @@ [Chapter 3] Remote Login | Project X - - + +

            [Chapter 3] Remote Login

            3.1 Remote Login to VPS (PuTTY)

            First of all, considering that the user base of Windows is the largest among the zero-based population, this article uses Windows as an example for demonstration.

            Secondly, although PowerShell and WSL after Windows 10 can also achieve a good SSH operation experience, not all versions of Windows have the latest components. Therefore, this article uses the classic PuTTY as an example to provide a detailed explanation of SSH remote login operation. (If you use other tools, the operations after the SSH login are the same.)

            Follow me step by step and let's start the operation.

            1. Go to the official websiteopen in new tag of PuTTY and download the version that suits your operating system (this article uses the 64-bit version as an example).

            Download PuTTY

            1. After installation and running, you will see the main interface of PuTTY. Now please take out your notebook from the previous chapter where you wrote down the IP address (VPS IP) and port (VPS PORT) of your VPS in the corresponding positions of the following figure. In order to save time and avoid repeatedly entering these details in the future, we can save the session (Saved Sessions), and simply load it in the future with one click.

            PuTTY Settings

            1. I suggest setting keepalive to 60 seconds in the Connection to prevent SSH from automatically disconnecting after a period of inactivity. Be sure to save the settings again.

            Prevent frequent disconnection

            Attention

            Any update to the PuTTY configuration needs to be manually saved to the session again. Otherwise, it will be lost after closing.

            1. Click on Open to enter the SSH connection window, then enter the username and password corresponding to the following figure to establish a connection with your VPS remote host. (This article assumes that the default username is root. Also, when entering a password in the Linux system, there will be no prompt like ******, which can avoid password length leakage. It's not that your keyboard is broken!)

            SSH Remote Login

            3.2 Successfully Logging in SSH! Introduction to Command Line Interface!

            1. If you have filled in your information correctly, you will see a similar interface as the picture below, indicating that you have successfully logged in:

            Logging in to VPS for the first time

            This interface is equivalent to the "desktop" of a remote server, but it does not have familiar icons and a mouse, nor does it have colorful graphics. Instead, all you see is simple text. This is the "Command Line Interface" - shortened as CLI.

            All the following operations require you to act like a hacker in a movie and complete them in this command-line interface. Maybe you will feel unfamiliar, but please believe me, using the command-line interface is neither scary nor mysterious. In the end, it just turns your familiar mouse operations into textual commands, you say it, it does it.

            1. Now, you can observe and familiarize yourself with the command line environment a little bit. This interface has actually provided you with some useful information, such as the system kernel version (e.g. 4.19.37-5 in the picture), last login time and IP address. Of course, depending on the VPS, the interface you see may be slightly different.

            2. Please pay attention to the line at the bottom of the command line, to the left of the flashing cursor, there is a string of characters. The one shown in the figure is root@vps-server:~#. How to understand this string? It's very simple:

            • The current user is root
            • The server where root is located is vps-server
            • The current directory where root is located is ~
            • After # is the place where you can input commands.

            The first two are pretty straightforward, no need to explain further. The third one is about the folder system in Linux. You don't need to go too deep into it for now. Just know that "~" represents the home directory of the current user. As for the fourth one, the prompt symbol "#", you don't need to worry about it either. Just know that in future articles, there will be some commands that you need to input, and they will be preceded by "#" or "$" to indicate where you should input the command. (So when you copy the command, just copy the content after the prompt symbol and don't copy the prompt symbol itself.)

            3.3 Updating software on Linux for the first time!

            1. Just like your phone, whether it's Android or iPhone, in order to keep your apps up-to-date (to get security patches and new features), you will occasionally receive update notifications from the app store, telling you how many apps need to be updated. Linux systems also have a similar update mechanism that works logically. So as long as you know how to update phone apps, you can learn how to update Linux software!

            2. In Linux, each application is called a "package". The program that manages the applications is naturally called a "package manager". You can use it to install, update, and uninstall various software, and even update the Linux system itself. Package managers in Linux are very powerful, but we won't go into details here. For now, you only need to know that the package manager for the Debian system is called apt. Next, we will first use apt to do a comprehensive update of the software to familiarize you with its basic operations.

            3. Tiny White Linux Basic Commands:

            NumberCommand NameCommand Description
            cmd-01apt updateQuery software updates
            cmd-02apt upgradePerform software updates
            1. Now, please enter the first command to get update information.
            apt update
             

            This is a command used in a Linux terminal to update the package list from the repositories configured on the system.

            1. Then enter the second command, and when asked if you want to continue installing (Y/n), type y and press enter to confirm and start the installation.
            apt upgrade
             

            This is a command in the shell terminal to upgrade the installed packages on a Debian or Ubuntu Linux system.

            1. The complete demonstration of the process is as follows:

            Demonstration of the software update process for the first time

            3.4 Your Progress

            Congratulations on taking another solid step! Now, you can log in to your remote server via SSH! After logging in, besides upgrading the software, what else should you do? Please enter the next chapter to find out!

            ⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%

            - + diff --git a/en/document/level-0/ch04-security.html b/en/document/level-0/ch04-security.html index dfbe2a287a..02c31db703 100644 --- a/en/document/level-0/ch04-security.html +++ b/en/document/level-0/ch04-security.html @@ -24,8 +24,8 @@ [Chapter 4] Security and Protection | Project X - - + +

            [Chapter 4] Security and Protection

            4.1 Why Do We Need Security Protection?

            Security protection for Linux servers is a complex and huge subject. Countless websites, apps, services, and even offline infrastructure are built on the foundation of Linux, which involves huge economic benefits and commercial value. This also means that there is a huge motivation for black and gray industries to launch attacks. However, these services are so important that major security vulnerabilities are not allowed. Therefore, countless operation and maintenance professionals are working hard on the battlefield of security attacks and defense, which enables us to enjoy a basic stable modern digital life.

            Now, you have a VPS and will open its data access channel to achieve the goal of traffic forwarding, which means you are now on the front line of the security battle and face all risks. However, at the same time, newcomers tend to have a polarized view of security issues due to lack of knowledge and information: either they feel it is as light as a feather and has nothing to do with them, or they feel it is as heavy as Mount Tai and feel anxious all day long.

            • For the former, my suggestion is: safety is of utmost importance. Try to gather more information on safety issues to avoid regretting after experiencing losses.

            • For the latter, my suggestion is: don't worry too much, our servers still don't have too much value and generally won't attract high-level attacks. The basic threats we need to face are mostly malicious scans and login attempts from some automated scripts. Just follow this article to do some basic protection.

            4.2 What are the specific risks

            Just like the configuration we did in the "Remote Login" section, anyone who knows the four elements of [IP address] + [port] + [username] + [password] can log in to your VPS server. So obviously, the security of these four elements is the bottom line that we need to protect. Let's analyze them one by one:

            1. [IP Address]: Malicious scripts randomly attempt to scan IP ranges, which can be regarded as public information and cannot be hidden.

            2. [Port]: If you are using the default port, then [Port = 22].

            3. [Username]: If using the default user, then [Username = root]

            4. [Password]: There is no default value for the password. It must be randomly generated by the VPS backend or set by you. In other words, if all the settings of your server are default, then three of the four elements are already known. Therefore, the security of your entire server relies on a small password. In this case, there are several situations:

            • If you use a VPS management background to generate passwords randomly, it usually contains random uppercase and lowercase letters, symbols, and is relatively secure.

            • If you changed your password to something super weak like 123456 just for the sake of easy memorization, hacking into your VPS server would be a piece of cake.

            • If you change your password to a more complex one that you have used elsewhere just for the sake of easy memory, it is not really safe. You should understand that hackers have cheats in their hands, such as password tables, which contain tens of thousands, hundreds of thousands, millions, or even more real leaked passwords.

            1. But you should understand that no hacker really sits in front of a computer and tries your password repeatedly. All attack attempts are carried out automatically by malicious scripts, which work tirelessly for 24 hours. Perhaps while you are sleeping soundly every night, your server is enduring round after round of attacks.

            Once the password is successfully cracked, it means that all four of your elements have been mastered by the attacker. The malicious script will quickly log in to the server, obtain the highest root control of the server, install and deploy its malicious services, and then use your server to do all kinds of bad things 24 hours a day (such as mining, spreading viruses, sending spam emails, fraudulent emails, acting as a BT relay, and even dark web public nodes, and so on). If the malicious script is relatively restrained, it can actually achieve considerable concealment. Generally, newcomers will not observe and pay attention to indicators such as login records, process changes, CPU usage changes, and traffic changes of the VPS, so it is difficult for you to discover that you have been hacked. Until your VPS service provider blocks your account or you receive a lawyer's letter.

            1. Don't forget that when you obtain a VPS, you probably need to use your real payment information, and when you log in to various websites and social platforms, your IP address will also be recorded, which has a direct or indirect relationship with your identity. Therefore, once these bad things happen, they will inevitably be associated with you.

            4.3 What security measures do we need to take

            Based on the above analysis, what we need to do is to strengthen the three elements of [port], [username], and [password] to reduce the risk of being hacked.

            1. [Port]: Modify the SSH remote login port to a [non-22 port] (4.4).
            2. [Username]: Create a [non-root] new user and disable root user SSH remote login (4.5, 4.6).
            3. [Password]: Enable RSA key verification for SSH login and disable password verification login (4.7).

            Remember to follow the order and don't lock yourself out.

            4.4 Change the SSH Remote Login Port to a Non-22 Port

            Now, let's solve the problem of "port = 22". (Note: some VPS service providers have non-22 ports set as default, so you can ignore this step if that's the case. Of course, you can also follow this article to change it to another port.)

            1. Basic commands of Little White Linux:
            IDCommand NameDescription
            cmd-03nanoText editor
            cmd-04systemctl restartRestart a service
            1. Basic Configuration Files of Little White Linux
            NumberConfiguration File LocationFile Description
            conf-01/etc/ssh/sshd_configSSH Remote Login Program Settings
            1. The first thing we need to do, of course, is to [open the SSH remote login program settings with the text editor nano]. In Windows, you will [find the file and double-click] it. What should you do in Linux? Take a close look at the command instructions above, isn't it simple? Yes, it is:
            nano /etc/ssh/sshd_config
            @@ -40,6 +40,6 @@
             

            This is a command in shell script to change the permissions of the authorized_keys file to 600 for the current user's SSH directory (~/.ssh/).

            1. Modify SSH configuration. We have used this many times, but now that we have changed from the almighty root to the ordinary user vpsadmin, we do not have the permission to edit SSH configuration directly. At this time, we need to use the sudo command:
            sudo nano /etc/ssh/sshd_config
             

            (This is a command in the shell/terminal to open the sshd_config file located in the /etc/ssh/ directory with the sudo privilege using the nano text editor.)

            1. Find (ctrl+w) PasswordAuthentication and change it to no.

            2. Find (ctrl+w) PubkeyAuthentication, change it to yes, then save (ctrl+o) and exit (ctrl+x).

            3. Restart the SSH service. (Note: Don't forget to use sudo to gain permission.)

            sudo systemctl restart ssh
             

            This is a command in the shell terminal to restart the SSH service with root privileges using the systemctl command.

            1. The complete process is as follows:

            Enable SSH key verification and disable password verification

            1. The public key has been set up on the VPS end. Now we need to specify the private key location for PuTTY to use when logging in. (Reminder: Don't forget to save the session.)

            Specify private key location in PuTTY

            1. Now, the [Key-based login] has been successfully enabled, [Password authentication] has been successfully disabled, and the default login username and private key have been saved for PuTTY. In the future, when using PuTTY to log in, simply load the VPS-SERVER configuration, click Open, and you can log in with just one click.

            If you have set a password for your private key, you need to enter this password to use the key when logging in, as shown in the following figure:

            Enter Private Key Password

            1. Don't forget to set the corresponding key for WinSCP, otherwise you won't be able to log in when you want to transfer files later.

            WinSCP Specify Private Key Location

            Warning

            Any software that requires SSH login needs key verification. As there are too many software, it is impossible to show them one by one. Please set it up according to your needs.

            4.8 Your Progress

            Up to this point, your VPS has completed the basic security measures of [port], [username], and [password]. Although it is not completely impregnable, most malicious scripts should no longer be able to harm you.

            Now that we finally have a secure system foundation, in the next chapter, we can start step by step to install and configure the infrastructure that Xray needs! (What infrastructure? A web page, a certificate)

            ⬛⬛⬛⬛⬜⬜⬜⬜ 50%

            - + diff --git a/en/document/level-0/ch05-webpage.html b/en/document/level-0/ch05-webpage.html index 886d36e331..9b5b970aaf 100644 --- a/en/document/level-0/ch05-webpage.html +++ b/en/document/level-0/ch05-webpage.html @@ -24,8 +24,8 @@ Chapter 5: Website Building | Project X - - + +

            Warning

            This translation was modified on 19 May 2023 and an updated version (17 March 2024) is available on the source page. View the original page

            Chapter 5: Website Building

            5.1 Why should you create a website?

            Some newcomers may be confused: why do I need to build a website for securing an open digital environment? I don't know how to code! Isn't it very complicated?

            First, let's answer the first question. The reasons for building a website are:

            1. Apply for a legitimate TLS certificate (very important)
            2. Provide reasonable fallback to prevent active probing attacks and improve security
            3. Set up a camouflage site (such as a blog, private cloud storage, multimedia site, game site, etc.) with a reasonable frontend when directly accessed, making traffic usage look more legitimate.

            Now let's answer the second question:

            1. As a demonstration, this article uses only the simplest "single-file HTML page + Nginx" setup to achieve the above objectives, so it is very easy.
            2. This website can not only be used for camouflage but also for real development and growth. The complexity depends entirely on you.
            3. For the goals of "camouflage" and "website operation", uniqueness and personalization are needed. Students who need this can search and learn by themselves. This content has completely deviated from scientific online access, so this article will not go into depth.

            5.2 Log in to VPS, install and run Nginx

            1. Here we use commands that have been explained in detail before, so they won't be repeated. If you don't understand, please refer to the previous chapters.

              sudo apt update && sudo apt install nginx
              @@ -75,6 +75,6 @@
                       }
               

              Be extra careful!

              As mentioned in Step 3 of section 5.3, make sure to change /home/vpsadmin/www/webpage to your actual file path.

            2. Make nginx reload the configuration to take effect.

              sudo systemctl reload nginx
               
            3. The complete setup process is as follows:

              Web page settings demonstration

            4. Now, if you visit http://subdomain.your_domain.com, you should see this page, indicating success:

              http web page success

          5.4 Common error explanations

          First of all, if you follow the instructions in the article step by step and are careful enough, you will definitely not encounter any errors. So, I don't intend to change how this article is written.

          Then why do some students still get stuck at this step, and the web page just won't open? There are basically two words: carelessness. Because there are only two possible issues with the configuration here, and there are only two reasons for them.

          I. Two types of issues:

          • In nginx.conf, the /home/vpsadmin/www/webpage does not match the actual file path; nginx cannot find the file
          • The path is correct, but nginx doesn't have permission to access it

          II. Two reasons:

          • Use a non-root user but still directly copy the commands in the text without modification. (This is basically like copying the name of another student when copying answers)
          • Insist on using a root user

          If you encounter any errors, please carefully review the explanations in Steps 3 and 5-2 of Section 5.3.

          Warning

          In the early stages of this article, a lot of space has been devoted to explaining the importance of using a non-root user for security, and the entire article is written based on this premise. So, issues caused by using a root user are not within the scope of this article.

          But I believe that students who persist in using the root user should have their own opinions, strong hands-on ability, or have a certain foundation in Linux. I have already explained the crux of the problem, and I believe you can solve it on your own.

          5.5 Your Progress

          So far, Xray's first infrastructure [webpage] has been established. Let's now move on to the second infrastructure [certificate]!

          ⬛⬛⬛⬛⬛⬜⬜⬜ 62.5%

        - + diff --git a/en/document/level-0/ch06-certificates.html b/en/document/level-0/ch06-certificates.html index 5e404a995a..6d26bf4cdb 100644 --- a/en/document/level-0/ch06-certificates.html +++ b/en/document/level-0/ch06-certificates.html @@ -24,8 +24,8 @@ [Chapter 6] Certificate Management | Project X - - + +

        [Chapter 6] Certificate Management

        6.1 Applying for a TLS Certificate

        Next, we need to apply for a real TLS certificate for our domain name, so that the website has the ability to encrypt with standard TLS and the ability to access via HTTPS. This is the most important tool for Xray and other current security proxy tools to ensure fully encrypted traffic.

        Warning

        Please do not use self-signed certificates lightly. It does not make the operation much simpler, but adds unnecessary risks (such as man-in-the-middle attacks).

        Here, I will use a certificate management tool called acme.shopen in new tag, which is simple, lightweight, efficient, and capable of automatically updating certificates.

        In addition, I believe that you have gradually become familiar with the basic operations of Linux. Therefore, from this chapter on, commands that have appeared multiple times will no longer have screenshots and will only be briefly described. If you really can't remember how to use them, just review the previous chapters.

        6.2 Install acme.sh

        1. Basic Linux commands for beginners:

          NumberCommandDescription
          cmd-12wgetRetrieve (or download) a webpage file
          cmd-13acme.shCommands related to acme.sh certificate management
        2. Run the installation script.

        wget -O - https://get.acme.sh | sh
        @@ -139,6 +139,6 @@
         [Mon 14 Feb 2022 03:00:25 PM CST] Installing key to: /etc/xray/cert/cert.key
         [Mon 14 Feb 2022 03:00:25 PM CST] Installing full chain to: /etc/xray/cert/fullchain.crt
         

        (Note: This is a shell command for installing a SSL certificate using acme.sh. The command is specifying the domain, file paths for the certificate, private key, and full chain, as well as indicating that an ECC certificate should be used.)

        6.6 Your Progress

        At this point, the two basic infrastructures required by Xray are finally in place! Xray, which has been eagerly awaited, is about to be revealed, and we are finally about to enter the most exciting chapter!

        ⬛⬛⬛⬛⬛⬛⬜⬜ 75%

        - + diff --git a/en/document/level-0/ch07-xray-server.html b/en/document/level-0/ch07-xray-server.html index f249416e76..e7314c2521 100644 --- a/en/document/level-0/ch07-xray-server.html +++ b/en/document/level-0/ch07-xray-server.html @@ -24,8 +24,8 @@ 【第 7 章】Xray 服务器篇 | Project X - - + +

        Warning

        This translation was modified on 4 March 2023 and an updated version (10 May 2024) is available on the source page. View the original page

        【第 7 章】Xray 服务器篇

        7.1 博观而约取,厚积而薄发

        本文撰写过程中,大佬开玩笑的吐槽到:你这教程,居然连载了 6 章都还没到 Xray,不知道的还以为你是“手把手教你建网站”教程呢。(我竟无法反驳.jpg!)

        其实这样的结构是我多番思考之后的决定,毕竟只有打好基础,才能在后面事半功倍快速反超。我在群里看到许多新人连nano都无法正确使用,也不会用WinSCP,远程手写编辑出来的config.json自然错误百出,连查错也变得举步维艰。

        Warning

        经过了前 6 章的准备,各位已经跟我一起翻越了 Linux 基本操作、VPS 远程管理、网页搭建、域名管理、证书申请等等几座大山。是不是回头看看,觉得其实非常简单呢?现在我们有了如此扎实的准备,接下来安装和配置 Xray 时会有一种【水到渠成】的轻快感觉。

        后面要做的事情非常简单:

        1. 安装
        2. 配置(如安装 TLS 证书、config.json
        3. 运行
        4. 优化(如更新内核、开启bbr、网站http访问自动跳转https等)

        7.2 安装 Xray

        首先,Xray 的官方载体,就是 xray-coreopen in new tag 开源项目(基于 MPL 2.0 开源协议)生成的二进制程序。你把这个二进制放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。主要区别来源于【配置】。

        安装时,直接使用官方安装脚本就很简单直接。它提供了多种安装选项,有兴趣的可以去官方的安装脚本仓库open in new tag中看看脚本的说明,本文使用的是【非 root 用户】安装模式

        写本文时,安装脚本在使用非 root 账户时有一些小 bug,所以我决定正好把这几步分开操作,可以顺便说明一下 Linux 下的删除命令。

        1. 小小白白 Linux 基础命令:

          编号命令名称命令说明
          cmd-14rm删除命令
        2. 将安装脚本下载至本地:

          wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
          @@ -188,6 +188,6 @@
           
          1. 修改 Xray 的回落设置,将回落从 80 端口改为 8080 端口。(找到 "dest": 80, 并改成 "dest": 8080
          sudo nano /usr/local/etc/xray/config.json
           
          1. 重启 Xray 服务,即完成了设置
          sudo systemctl restart xray
           
          1. 完整流程演示如下:

          http自动跳转https

          1. 当你输入 http://a-name.yourdomain.com的时候,它应该已经会自动跳转 https 了

          http自动跳转https生效

          7.9 服务器优化之三:更丰富的回落

          如果你需要更丰富的回落功能,可以参考 《回落 (fallbacks) 功能简析》

          7.10 你的进度

          恭喜!!到这一步,你已经拥有了可以正常科学上网的服务器、同时也有了可以防止主动探测攻击的伪装网站。接下来,只要给你的客户端装上合适的软件,就可以享受顺畅的网络了!

          ⬛⬛⬛⬛⬛⬛⬛⬜ 87.5%

          7.11 重要勘误

          1. 初版中Xray配置文件config.json文件夹位置错误。若你已经根据之前的位置进行了操作,Xray会无法正确启动。故勘误说明于此,请自查,造成不便十分抱歉!
          • 正确位置:/usr/local/etc/xray/config.json
          • 错误位置:/usr/local/etc/config.json

          受影响章节:

          • 7.4 配置Xray - 3. 使用nano创建Xray的配置文件
          • 7.8 服务器优化之二 - 6. 修改Xray的回落设置
          1. 初版中修改Nginx配置文件nginx.conf时内容错误(网页文件夹位置错误),若你已经根据之前的位置进行了操作,Nginx会无法找到正确的网站。请自查,造成不便十分抱歉!
          • 正确文件夹位置:root /home/vpsadmin/www/webpage;
          • 错误文件夹位置:root /var/www/website/html

          受影响章节:

          • 7.8 服务器优化之二 - 4. 在与 80 端口同级的位置增加一个本地端口监听来提供网页展示
        - + diff --git a/en/document/level-0/ch08-xray-clients.html b/en/document/level-0/ch08-xray-clients.html index c0d6578177..6fd279d670 100644 --- a/en/document/level-0/ch08-xray-clients.html +++ b/en/document/level-0/ch08-xray-clients.html @@ -24,8 +24,8 @@ 【第 8 章】Xray 客户端篇 | Project X - - + +

        【第 8 章】Xray 客户端篇

        8.1 Xray 的工作原理简述

        要正确的配置和使用Xray,就需要正确的理解其工作原理,对于新人,可以先看看下面简化的示意图(省略了许多复杂的设置):

        Xray数据流向

        这其中的关键点是:

        1. APP 要主动或借助转发工具,将数据【流入(inbounds)】Xray 客户端

        2. 流量进入客户端后,会被【客户端路由(routing)】按规则处理后,向不同方向【流出(outbounds)Xray 客户端。比如:

          1. 国内流量直连(direct
          2. 国外流量转发 VPS(proxy
          3. 广告流量屏蔽(block
        3. 向 VPS 转发的国外流量,会跨过防火墙,【流入(inbounds)】 Xray 服务器端

        4. 流量进入服务器端后,与客户端一样,会被【服务器端路由(routing)】按规则处理后,向不同方向【流出(outbounds)】:

          1. 因为已经在防火墙之外,所以流量默认直连,你就可以访问到不存在网站们了(direct
          2. 如果需要在不同的 VPS 之间做链式转发,就可以继续配置转发规则(proxy
          3. 你可以在服务器端继续禁用各种你想禁用的流量,如广告、BT 下载等(block

        注意

        请务必记得,Xray 的路由配置非常灵活,上面的说明只是无限可能性中的一种。

        借助 geosite.datgeoip.dat 这两个文件,可以很灵活的从【域名】和【IP】这两个角度、不留死角的控制流量流出的方向。这比曾经单一笼统的 GFWList 强大很多很多,可以做到非常细致的微调:比如可以指定 Apple 域名直连或转发、指定亚马逊域名代理或转发,百度的域名屏蔽等等。。。)

        现在,《路由 (routing) 功能简析》 已经上线,我建议对路由功能有兴趣的同学,先继续跟着本文完成客户端的基础配置,之后再去这里详细学习。

        8.2 客户端与服务器端正确连接

        现在你已经理解了 Xray 的工作原理,那么接下来的配置,其实就是【告诉你的客户端如何连接 VPS 服务器】。这和你已经很熟悉的、告诉PuTTY如何远程连接服务器是一样的。只不过 Xray 连接时的要素不止是【IP 地址】+【端口】+【用户名】+【密码】这四要素了。

        实际上,Xray的连接要素是由不同的协议决定的。本文在第 7 章的配置文件 config.json 里,我们使用 Xray 下独特而强大的 VLESS 协议 + XTLS 流控。所以看看那个配置文件的内容就能知道,这个协议组合的连接要素有:

        • 服务器【地址】: a-name.yourdomain.com
        • 服务器【端口】: 443
        • 连接的【协议】: vless
        • 连接的【流控】: xtls-rprx-vision (vision 模式适合全平台)
        • 连接的【验证】: uuiduuid-uuid-uuid-uuiduuiduuid
        • 连接的【安全】: "allowInsecure": false

        鉴于新人一般都会使用手机 APP 或者电脑的 GUI 客户端,我就把常用的客户端罗列在下面。每个客户端都有自己独特的配置界面,逐一截图展示并不现实,所以请你务必仔细阅读这些客户端的说明、然后把上述要素填入合适的地方即可。

        注意

        许多工具其实是同时支持 xray-corev2fly-core 的,但默认内置的不一定是哪个,所以别忘记检查一下是否是你想要的那个在工作哦!

        到这一步,你的全套配置就已经可以正常使用啦!

        8.3 附加题 1:在 PC 端手工配置 xray-core

        虽然到上面一步已经可以结束了,但是如果你是个好奇心强、记忆力好的的同学,一定会想起来我在上一章说过,你把xray-core 的二进制文件“放在服务器运行,它就是服务器端;你把它下载到本地电脑运行,它就是客户端。” 那究竟要怎样直接使用 xray-core 做客户端呢?

        为了回答这个问题,我加入了附加题章节,有一点点超纲,有一点点麻烦,但费这个笔墨是因为这个方式有它的优势:

        • 第一时间获得最新版而无需等待 APP 升级适配

        • 灵活自由的路由配置能力(当然 GUI 客户端中 Qv2ray 的高级路由编辑器非常强大,也可以完整实现 xray-core 的路由配置功能)

        • 节约系统资源 (GUI 界面一定会有资源消耗,消耗的多少则取决于客户端的实现)

        它的劣势应该就是【需要手写配置文件】有点麻烦了。但其实,你想想,服务器上你已经成功的写过一次了,现在又有什么区别呢?接下来,还是老样子,我们分解一下步骤:

        1. 首先请从 Xray 官方的 GitHub 仓库 Release 页面open in new tag 获取对应平台的版本,并解压缩到合适的文件夹

        2. 在合适的文件夹建立空白配置文件:config.json (自己常用平台下新建文件大家肯定都会,这就真不用啰嗦了)

        3. 至于什么是“合适的文件夹”?这就取决于具体的平台了~

        4. 填写客户端配置

          • 我就以 8.1 原理说明里展示的基本三类分流(国内流量直连、国际流量转发 VPS、广告流量屏蔽),结合 8.2 的连接要素,写成一个配置文件
          • 请将 uuid 替换成与你服务器一致的 uuid
          • 请将 address 替换成你的真实域名
          • 请将 serverName 替换成你的真实域名
          • 各个配置模块的说明我都已经(很啰嗦的)放在对应的配置点上了
          // REFERENCE:
          @@ -181,6 +181,6 @@
           

        8.4 附加题 2:在 PC 端手工运行 xray-core

        写好了配置文件该,要怎么让 xray-core 运行起来呢?双击好像并没有反应啊?

        首先,你要找到电脑上的【命令行界面】。

        1. Linux 桌面、macOS 系统的同学肯定已经比较熟悉了,搜索 Console 或者 Terminal 就可以
        2. Windows 就可以搜索使用 Cmd 或者 Powershell 等程序(WSL 的同学你坐下,你的 Console 当然也可以)

        其次,我们要做的事情是【让 xray 找到并读取配置文件 config.json,然后运行】,所以:

        1. 在 Windows 下,假设你的 Xray 程序位置是 C:\Xray-windows-64\xray.exe,配置文件位置是C:\Xray-windows-64\config.json,那么正确的启动命令就是:

          C:\Xray-windows-64\xray.exe -c C:\Xray-windows-64\config.json
           

          说明

          这里的 -c 就是指定配置文件路径的参数,告诉 xray 去后面的位置找配置文件

        2. 相似的,在 Linux 和 macOS 下,假设你的 Xray 程序位置是 /usr/local/bin/xray,配置文件位置是/usr/local/etc/xray/config.json,那么正确的启动命令就是

          /usr/local/bin/xray -c /usr/local/etc/xray/config.json
           

          说明

          每个系统都有系统路径变量,所以写 Xray 程序时不一定要写绝对路径。但是写了肯定没错,所以我就如此演示了。

        8.5 附加题 3:在 PC 端开机自动运行 xray-core

        如果你真的尝试了手动运行 xray-core,你一定会发现这个方式还有点小问题:

        1. 每次运行 Xray 都要出现一个黑乎乎的窗口,很丑
        2. 不能开机自动运行,每次都要手工输入,十分不方便

        我可以肯定的告诉你:完全可以解决。但是具体的解决方式,就当作课外作业留给大家吧!(友情提示,文档站的问答区有线索哦)

        8.6 圆满完成!

        我相信,有耐心看到这里的同学,都是兼具好奇心和行动力的学习派!我现在要郑重的恭喜你,因为到了这里,你已经完完整整的【从第一条命令开始,完成了 VPS 服务器部署,并成功的在客户端配置使用 Xray】了!这毫无疑问是一个巨大的胜利!

        我相信,你现在一定对Linux不再恐惧,对Xray不再陌生了吧!

        至此,小小白白话文圆满结束!

        ⬛⬛⬛⬛⬛⬛⬛⬛ 100%

        8.7 TO INFINITY AND BEYOND!

        但现在你看到的,远远不是 Xray 的全貌。

        Xray是一个强大而丰富的网络工具集合,平台化的提供了众多模块,可以像瑞士军刀一样,通过灵活的配置组合解决各种不同的问题。而本文,仅仅蜻蜓点水的用了最简单最直观的配置来做基础演示

        如果你觉得现在已经完全够用了,那就好好的享受它给你带来的信息自由。但如果你的好奇心依然不能停歇,那就去继续挖掘它无限的可能性吧!

        需要更多信息,可以到这里寻找:

        1. xtls.github.ioopen in new tag - 官方文档站
        2. 官方 Telegram 群组open in new tag - 活跃而友善的官方讨论社区

        TO INFINITY AND BEYOND!

        不算后记的后记

        希望我陪你走过的这一段小小的旅程,可以成为你网络生活中的一份小小助力。

        这篇文章里的工具和信息难免会一点点的陈旧过时,但你一定会逐渐成长为大佬。未来的某个时间,若你能偶尔想起这篇教程、想起我写下本文的初衷,那我衷心希望你能够薪火相传、把最新的知识分享给后来人,让这一份小小的助力在社区里坚定的传递下去。

        这是个大雪封山乌云密布的世界,人们孤独的走在各自的路上试图寻找阳光,如果大家偶尔交汇时不能守望相助互相鼓励,那最终剩下的,恐怕只有【千山鸟飞绝 万径人踪灭】的凄凉了吧。

        - + diff --git a/en/document/level-0/ch09-appendix.html b/en/document/level-0/ch09-appendix.html index e2f24ee5ec..0010493883 100644 --- a/en/document/level-0/ch09-appendix.html +++ b/en/document/level-0/ch09-appendix.html @@ -24,11 +24,11 @@ 【第 9 章】附录 | Project X - - + +

        【第 9 章】附录

        1. 小小白白 Linux 基础命令索引

        编号命令名称命令说明出现篇章
        cmd-01apt update查询软件更新《远程登录篇》
        cmd-02apt upgrade执行软件更新《远程登录篇》
        cmd-03nano文本编辑器《安全防护篇》
        cmd-04systemctl restart重启某个服务《安全防护篇》
        cmd-05adduser给系统新增用户《安全防护篇》
        cmd-06apt install安装某个软件《安全防护篇》
        cmd-07visudo修改 sudo 权限设置专用编辑器《安全防护篇》
        cmd-08sudoroot权限运行某个命令《安全防护篇》
        cmd-09chmod修改目标文件/文件夹的权限《安全防护篇》
        cmd-10mkdir新建文件夹《网站建设篇》
        cmd-11systemctl reload重新加载某个服务《网站建设篇》
        cmd-12wget访问(或下载)某个网页文件《证书管理篇》
        cmd-13acme.shacme.sh 证书管理相关的命令《证书管理篇》
        cmd-14rm删除命令《Xray 服务器篇》
        cmd-15crontab -e编辑当前用户的定时任务《Xray 服务器篇》
        cmd-16touch建立空白文件《Xray 服务器篇》
        cmd-17systemctlsystemd基本服务管理命令《Xray 服务器篇》
        cmd-18reboot重启 Linux 系统《Xray 服务器篇》

        2. 小小白白 Linux 重要配置文件索引

        编号配置文件位置文件说明出现篇章
        conf-01/etc/ssh/sshd_configSSH 远程登录程序设置《远程登录篇》
        conf-02/etc/nginx/nginx.confNginx 程序设置《网站建设篇》
        conf-03/etc/apt/sources.listapt 软件源列表《Xray 服务器篇》
        conf-04/etc/apt/sources.list.d/vpsadmin.list用户自定义软件源列表列表《Xray 服务器篇》
        conf-05crontab -e当前用户的定时任务《Xray 服务器篇》
        conf-06/etc/sysctl.conf手动设置 kernel 参数《Xray 服务器篇》
        conf-07/etc/sysctl.d/vpsadmin.conf用户自定义 kernel 参数配置文件《Xray 服务器篇》

        3. 小小白白 Xray 重要文件索引

        编号配置文件位置文件说明出现篇章
        xray-01/usr/local/etc/xray/config.jsonXray 程序设置《Xray 服务器篇》
        xray-02/home/vpsadmin/xray_cert/xray.certTLS 证书《Xray 服务器篇》
        xray-03/home/vpsadmin/xray_cert/xray.keyTLS 私钥《Xray 服务器篇》
        xray-04/home/vpsadmin/xray_log/access.logXray 访问日志《Xray 服务器篇》
        xray-05/home/vpsadmin/xray_log/error.logXray 错误日志《Xray 服务器篇》
        - + diff --git a/en/document/level-0/index.html b/en/document/level-0/index.html index 2539f5c4f7..5a4dc403bc 100644 --- a/en/document/level-0/index.html +++ b/en/document/level-0/index.html @@ -24,11 +24,11 @@ Plain and Simple Language | Project X - - + +

        Plain and Simple Language

        This chapter is a basic lesson of [Starting from Scratch]. New students, please watch and learn carefully.

        Tip

        Made with ❤️ by @ricuhkaenopen in new tag

        【Chapter 1】 Preface: Rambling - Airport or Self-built? That is the question.

        Chapter 2: Preparation of Raw Materials - Tools must be sharpened before they can be used proficiently.

        Chapter 3: Remote Login - A bridge connecting the north and south, turning a natural obstacle into a thoroughfare.

        【Chapter 4】Security Protection - If you don't pay attention to security, you will shed tears for your loved ones.

        [【Chapter 5】Website Construction] - Show Your Beauty (Link to webpage.md file)

        Chapter 6: Certificate Management - Only those who obtain certificates are considered legitimate.

        Chapter 7: Xray Server - Finally, waited for you.

        Chapter 8: Xray Client - A New Beginning.

        [Chapter 9] Appendix - All the exam points are here.

        - + diff --git a/en/document/level-1/fallbacks-lv1.html b/en/document/level-1/fallbacks-lv1.html index 15417156bf..75741b0039 100644 --- a/en/document/level-1/fallbacks-lv1.html +++ b/en/document/level-1/fallbacks-lv1.html @@ -24,8 +24,8 @@ 回落 (fallbacks) 功能简析 | Project X - - + +

        Warning

        This translation was modified on 4 March 2023 and an updated version (8 April 2024) is available on the source page. View the original page

        回落 (fallbacks) 功能简析

        在使用 Xray 的过程中,你一定无数次的听说了【回落】这个功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

        1. 回顾《小小白白话文》中的回落

        如果你用了《小小白白话文》中的Xray 配置,并完成了HTTP 自动跳转 HTTPS 优化,那么你已经有了基于 VLESS 协议的简易回落:

        {
        @@ -200,6 +200,6 @@
           }
         }
         
      4. 至此,我们就能够完整的画出模板的回落路线了:

      6. 结语

      至此,Xray 的【回落】功能就介绍完了。希望本文能够对你理解 Xray 的强大有所帮助。

      7. 附加题

      我再无耻的留一个附加题:本文详解的 VLESS-TCP-XTLS-WHATEVERopen in new tag 模板?是否有可以优化的地方?

      提示:HTTP 自动跳转 HTTPS

- + diff --git a/en/document/level-1/fallbacks-with-sni.html b/en/document/level-1/fallbacks-with-sni.html index 96235540c3..887a78a768 100644 --- a/en/document/level-1/fallbacks-with-sni.html +++ b/en/document/level-1/fallbacks-with-sni.html @@ -24,8 +24,8 @@ SNI fallback | Project X - - + +

Implementing camouflage and domain-based routing through SNI fallback function

VLESS is a lightweight protocol that, like Trojan, does not perform complex encryption and obfuscation on traffic. Instead, it is encrypted through the TLS protocol and mixed in with other HTTPS traffic, making it difficult to detect. In order to better disguise itself and respond to active probing, the fallback function appeared with VLESS at the same time. This tutorial will demonstrate how to use the fallback function of VLESS inbound protocol in Xray, combined with Nginx or Caddy, to achieve domain name-based traffic routing while ensuring complete disguise.

Application Scenarios

Due to XTLS, Xray needs to listen on port 443, which means that if there is a website running on the server, it cannot run or needs to run on another port, which is obviously unreasonable. There are three solutions to this problem:

  • Xray monitors other commonly used ports (such as 22, 3389, 8443).

This plan is the simplest, but not perfect enough.

  • Nginx or HAProxy listens on port 443, uses SNI for L4 load balancing, and achieves port multiplexing through reverse proxy.

This plan is relatively complicated and requires some understanding of using Nginx or HAProxy. We will not explain it in too much detail here.

  • Xray listens on port 443, and uses Fallbacks feature to split website traffic based on SNI and fallbacks it to Nginx or Caddy.

This plan has a moderate level of difficulty and is the scheme that this tutorial will demonstrate next.

Introduction to SNI

Server Name Indication (SNI) is an extension protocol of TLS. Friends who are familiar with reverse proxies know that the following configuration is required if you want to proxy traffic to the correct content through a domain name:

proxy_set_header Host hostname;
@@ -211,6 +211,6 @@
     redir https://{host}{uri} permanent
 }
 

Reference

  1. Server Name Indication - Wikipedia, the free encyclopediaopen in new tag
  2. Home · acmesh-official/acme.sh Wikiopen in new tag
  3. HTTP/2 - Wikipedia, the free encyclopediaopen in new tag

Quotation


  1. Proxy Protocol - HAProxy Technologiesopen in new tag ↩︎

  2. Introduction to Proxy Protocol and Nginx Configuration - Jianshuopen in new tag ↩︎

  3. v2fly-github-io/vless.md at master · rprx/v2fly-github-ioopen in new tag ↩︎

- + diff --git a/en/document/level-1/index.html b/en/document/level-1/index.html index 44fcfc8c4e..61bc01b744 100644 --- a/en/document/level-1/index.html +++ b/en/document/level-1/index.html @@ -24,11 +24,11 @@ Beginner's Tips | Project X - - + +
- + diff --git a/en/document/level-1/routing-lv1-part1.html b/en/document/level-1/routing-lv1-part1.html index 1a64b15317..161351b5ef 100644 --- a/en/document/level-1/routing-lv1-part1.html +++ b/en/document/level-1/routing-lv1-part1.html @@ -24,8 +24,8 @@ 路由 (routing) 功能简析(上) | Project X - - + +

路由 (routing) 功能简析(上)

如果说 Xray 的【强大】主要体现在它极致的速度和广泛的兼容性。那么 Xray 的【灵活】,则主要应该归功于它巧妙的【路由】功能。本文就稍微说明一下这个功能的逻辑以及使用方式。

1. 初识【路由】三兄弟

要理解路由,就要理解完整的路由功能需要有三兄弟来合力完成:1. 入站;2. 路由;3. 出站

路由三兄弟

三兄弟桃园结义,不求同年同月同日生,但求同年同月同日死。

所以谨记:任何一个元素错误,就可能导致路由功能无法正常工作。

因为路由的灵活性非常高,只看技术文档很容易把自己绕晕,所以本文我们用几个具体的示例来逐层讲解。

啰嗦君

路由功能实在过于灵活,所以本文的示例,都是为了讲解对应的概念,实际使用时请根据自己的需求进行调整。

2. 基本功: “兄弟一条心”

下图的示例,就是在客户端的 Xray 入站接收 APP 数据、在路由 100%转发给出站,并从出站流向 VPS。

下面我们来逐个分析:

2.1 入站

Tip

入站: 就是流量如何流入 Xray

下面的入站配置示例,用大白话说就是:数据按照 socks 协议,通过 10808 端口,从本机 127.0.0.1 流入Xray。同时,Xray 将这个入站用 [tag] 命名为 inbound-10808

{
@@ -141,6 +141,6 @@
   ]
 }
 

此时,路由规则其实变成了:

这就是路由功能的灵活之处了,你可以自由的改变它的顺序来实现不同的设计。

至此,我们已经解释完了 【如何利用 geosite.dat 文件,通过路由规则,根据【域名】来分流网络流量】。

5. 攻城略池 - 多种路由匹配条件

请确保你已经读懂了上面的内容,因为这样,你就已经理解了【路由】功能的工作逻辑。有了这个基础,我们就可以继续分析【路由】功能更多更详细的配置方式和匹配条件了。

等你看完后面的内容,就完全可以自由的定制属于自己的路由规则啦!还等什么,让我们一起进入 《路由 (routing) 功能简析(下)》 吧!

- + diff --git a/en/document/level-1/routing-lv1-part2.html b/en/document/level-1/routing-lv1-part2.html index 5292ba2510..29920095f1 100644 --- a/en/document/level-1/routing-lv1-part2.html +++ b/en/document/level-1/routing-lv1-part2.html @@ -24,8 +24,8 @@ 路由 (routing) 功能简析(下) | Project X - - + +

路由 (routing) 功能简析(下)

欢迎继续学习 Xray 的【路由】功能!

《路由 (routing) 功能简析(上)》 中,我们已经对【路由】功能的工作逻辑有了清晰的理解,也基于 geosite.dat 文件做了简单的域名分流配置。

如前面所说,域名分流仅仅是【路由】功能的牛刀小试而已。下面就让我们来看看除了域名之外,还什么可以用做分流依据的东西吧!

5. 攻城略池 - 多种路由匹配条件

[域名], [IP], [协议], etc.

基于域名的分流,已经可以让我们对网络流量进行基本合理的分流。为什么说【基本合理】呢?

因为【三分天下】虽然是正确的战略方向,但如果只用【域名】来实现这个战略,其实漏洞百出,比如:

  1. 我读了《小小白白话文》后,给 VPS 新申请了一个 proxy.yourdomain.com 的域名, 我希望它无论如何都代理,geosite.dat 里面有吗?
  2. 如果我还有个 direct.yourdomain.com 的域名,我希望它无论如何都直连, geosite.dat 里面有吗?
  3. 本机 127.0.0.1 的内部流量,是否正确直连了?(比如 docker 等)
  4. 路由器、本地局域网 192.168.*.* 的流量,是否正确直连了?(比如路由器、群晖等)
  5. 我的国内 DNS 查询(如 223.5.5.5)是否正确直连了?
  6. 我的国外 DNS 查询(如 1.1.1.1)是否正确代理了?
  7. 其他类似国内公共 DNS 一样没有域名、只有 IP 地址的国内网站,是否正确直连了?
  8. 其他类似国外公共 DNS 一样没有域名、只有 IP 地址的国外网站,是否正确代理了?
  9. BT 下载的流量,虽然来源是国外,但如果通过 VPS 下载很可能导致违规使用被封,这该如何强制直连?
  10. ......

我之所以说只用【域名分流】会漏洞百出,是因为 geosite.dat 文件内只包含了一部分常用的域名。换言之,仅仅依赖它,则会:

  • 无法匹配文件里没有的新域名
  • 无法匹配基于 IP 地址的规则
  • 无法匹配基于网络协议的规则

啰嗦君

那我们来复习一下,当上面这些情况无法匹配时,会发生什么?对了,会触发隐藏路由规则,即【转发给第一个出站 】。这其实就是说:

  • 当你的第一个出站是 [direct-out] 时:需要直连的都正确了,但需要代理的则都错误
  • 当你的第一个出站是 [proxy-out-vless] 时:需要代理的都正确了,但需要直连的则都错误

所以,我们需要一个办法,让我们鱼与熊掌兼得。这样的办法是否存在呢?当然存在! 我们需要的只是【域名】之外更多的【分流判断依据】而已。

5.1 基于指定域名分流:[domain], [full]

  1. 如果需要匹配某个子域名,如 a-name.yourdomain.com,我们使用 full: "a-name.yourdomain.com"
  2. 前面的 问题1问题2,就可以通过给 proxy.yourdomain.com 指定 [proxy-out-vless] 出站,给 direct.yourdomain.com 指定 [direct-out] 出站来解决
  3. 如果需要匹配 yourdomain.com 的所有子域名,我们使用 domain: "yourdomain.com" 实现
  4. 上述两个可以成为两个独立的路由规则,达到某些子域名直连,其他子域名代理的配置
  5. 另外,[domain] 还支持正则表达式等匹配方式。详情请参考 《基础配置模块 - 路由》文档

上述配置如下:

{
@@ -187,6 +187,6 @@
   }
 }
 

其实,第 6 点已经是我整理过的规则了,原则就是【相同的匹配依据可以合并,不同的匹配依据保持独立】。

8. 明修栈道、暗渡陈仓

[domain] 转化 [ip] 的密道:domainStrategy

我们在 5.4 中提交了多种流量判断的【依据】,其中一种是域名 [domain]、一种是 [IP]

如果你初步了解过 DNS 的运作过程,就会知道,我们对一个域名 [domain] 发起访问请求时,其实需要先向 DNS 发起请求来解析域名 [domain] 对应的 [IP],在得到 [IP] 后再向它发起实际请求。

所以,面对入站的一次域名请求,Xray 其实有两次机会去判断它的类型。那么,究竟是否要用这两次机会呢?这就是由 domainStrategy 这个配置来决定的。它有三个选项:

  • AsIs
  • IPIfNonMatch
  • IPOnDemand

按么我们逐个来解释一下:

8.1 域名策略: "AsIs"

就是 "As Domain Is",也就是说 【域名什么样,就什么样,不多折腾】。

简单粗暴理解就是说【仅用 [domain] 来匹配】。

Tip

AsIs 的实际意义为 【如原先所示,不加修改】,🍉 老师这里描述的不是很恰当。

这个方式的处理都在 Xray 内部完成,没有与外界的数据往来,所以速度最快。它的兜底策略也很清晰:即前面所说的、无法匹配的域名自动转入第一条出站处理。所以,对于常规使用路由功能这最推荐的策略。

8.2 域名策略: "IPIfNonMatch"

就是 "lookup IP if (there's) no matching rule",也就是说【如果其他所有规则都匹配不上,那就转化成 IP 去匹配 IP 规则】。

简单粗暴理解就是说【先把访问目标和其他所有类型规则匹配,如果匹配不上,那就通过 DNS 查询转化成 IP,再从头和所有规则匹配一次】。

该策略下没有命中任何规则的这一部分域名,会需要再经历 DNS 查询过程、以及第二轮规则匹配的过程,其耗时会多于 AsIs 策略,所以并不是首选推荐的策略。

8.3 域名策略: "IPOnDemand"

这里其实说 Demand IP 更准确些,也就是说【当匹配时碰到任何基于 IP 的规则,将域名立即解析为 IP 进行匹配】。

简单粗暴理解就是说【只要路由规则中有 IP 类规则,那么所有基于域名 [domain] 的请求都要解析成 [IP] 然后去匹配 [IP] 类规则】。

它要对所有首次域名访问进行 DNS 解析,所以首次查询比较耗时。虽然由于 XrayDNS 缓存机制的存在,后续对相同域名的访问速度会重回巅峰,但总体来说也不是首选推荐的策略。

啰嗦君

domainStrategy 仅对域名生效,不要搞混了哦~

9. 思考题

迄今为止,我们都是在【单入站】和【单出站】的基础上,讲解【路由】内部的各种配置逻辑。

但是,如你所知,Xray 本身是支持多端口,多协议的。那么,如果我问你:

  1. 我希望 VLESS 协议将我日常的网页浏览和 APP 流量转发给美国的大流量服务器
  2. 我希望 trojan 协议将我的所有 Netflix 流量转发给日本的服务器解锁各种二次元
  3. 我希望 shadowsocks 协议将我所有的游戏流量转发给香港的服务器达到最低的延迟
  4. 我希望有一个独立的端口,能够把 telegram 的流量全都转发给 VPS
  5. 我希望有一个独立的端口,能够把 bittorrent 下载流量全都转发给欧洲大盘鸡
  6. 我希望......

这些想法,是否能通过【路由】功能配置实现呢?

答案当然是 【完全可以】 啦! 但是这些对于 level-1 来说已经超纲了,就留给各位自由的探索吧!

10. 结语

至此,Xray 的【路由】功能就介绍完了。希望本文能够对你理解 Xray 的灵活有所帮助。

11. 尾注

  • 现在你可以重新阅读一遍 路由,看看是否有更加深刻的理解。
  • 🍉🍉🍉🍉🍉 😄
- + diff --git a/en/document/level-1/work.html b/en/document/level-1/work.html index dc01aef43b..c8bae60821 100644 --- a/en/document/level-1/work.html +++ b/en/document/level-1/work.html @@ -24,11 +24,11 @@ Xray 的工作模式 | Project X - - + +

Xray 的工作模式

单服务器模式

与其它的网络代理工具一样,你需要一台配置了 Xray 的服务器,然后在自己的设备上安装并配置 Xray 客户端,然后即可流畅地访问互联网。

一个 Xray 服务器可同时支持多台设备使用不同的代理协议访问。同时,经过合理的配置,Xray 可以识别并区分需要代理以及不需要代理的流量,直连的流量不需要绕路。

桥接模式

如果你不想在每一台设备上都配置路由,你也可以设置一台中转服务器,用于接收客户端发来的所有流量,然后在服务器中进行转发判断。

工作原理

在配置 Xray 之前,不妨先来看一下 Xray 的工作原理,以下是单个 Xray 进程的内部结构示意图。多个 Xray 之间相互独立,互不影响。

  • 需要配置至少一个入站连接(Inbound)和一个出站连接(Outbound)才可以正常工作。
    • 入站连接负责与客户端(如浏览器)通信:
      • 入站连接通常可以配置用户认证,如 ID 和密码等;
      • 入站连接收到数据之后,会交给分发器(Dispatcher)进行分发;
    • 出站连接负责将数据发给服务器,如另一台主机上的 Xray。
  • 当有多个出站连接时,可以配置路由(Routing)来指定某一类流量由某一个出站连接发出。
    • 路由会在必要时查询 DNS 以获取更多信息来进行判断。
- + diff --git a/en/document/level-2/index.html b/en/document/level-2/index.html index 002bc36c29..8edab051a1 100644 --- a/en/document/level-2/index.html +++ b/en/document/level-2/index.html @@ -24,11 +24,11 @@ Advanced Documentation | Project X - - + +

Advanced Documentation

This chapter contains experience sharing of using Xray at an advanced level. If you are already familiar with Xray, the experience shared here can help you unleash the full power of Xray.

Beginner's Guide to Transparent Proxies by a @kirinopen in new tag

An Introduction to Transparent Proxies.

TProxy Configuration Tutorial by a @BioniCosmosopen in new tag

Complete tutorial on configuring transparent proxy (TProxy) based on Xray.

TProxy Transparent Proxy (IPv4 and IPv6) Configuration Tutorial by a @SQLimitopen in new tag

Xray-based TProxy Transparent Proxy (IPv4 and IPv6) Configuration Tutorial

Nginx_TLS Tunnel Hidden Fingerprint by a @SQLimitopen in new tag

Use Nginx_TLS tunnel on both ends to hide the fingerprint.

[Transparent Proxy] Avoiding Xray Traffic Through gid by a @kirinopen in new tag

A new way of bypassing Xray traffic in transparent proxy implemented by iptables/nftables.

Redirect Specific Traffic to Specific Gateway using Xray to Achieve Global Routing "Load Balancing" by a @Zzz3mopen in new tag

Play Xray to the fullest: Implement "load balancing" based on fwmark or sendThrough.

Enhancing Proxy Security with Cloudflare Warp by a @yuhan6665open in new tag

Introduction to using WireGuard for outbound traffic added in Xray v1.6.5.

Xray Traffic Statistics by a @yuhan6665open in new tag

Adapt traffic statistics and scripts compatible with Xray.

- + diff --git a/en/document/level-2/iptables_gid.html b/en/document/level-2/iptables_gid.html index 9af85fc64b..744e48212a 100644 --- a/en/document/level-2/iptables_gid.html +++ b/en/document/level-2/iptables_gid.html @@ -24,8 +24,8 @@ Transparent proxy via GID | Project X - - + +

Transparent proxy to circumvent Xray traffic via GID

Warning

This translation was modified on 26 May 2021 and an updated version (14 October 2021) is available on the source page. View the original page

In the existing transparent proxy configuration(New V2Ray vernacular tutorial on transparent proxyopen in new tagNew V2Ray vernacular tutorial on transparent proxy (TProxy)open in new tagTransparent proxy(TProxy)configuration tutorial)tutorials, the circumvention of Xray traffic is achieved by using mark. That is, mark outbound traffics and set up iptables rules which directly connect traffics corresponding to the mark, to circumvent the Xray traffic and prevent loop back.

There are several problems with this method:

  1. Inexplicable traffic into PREROUTING chainopen in new tag

  2. Android has its own mark mechanism and this solution is not available on Android

The solution in this tutorial does not require a mark setting and has a higher theoretical performance, as well as not having the problems mentioned above.

Ideas

TProxy traffic can only be received by users with root privileges (uid==0) or other users with CAP_NET_ADMIN privileges.

The iptables rules can separate network traffic by uid (user id) and gid (user group id). Let Xray run on a user with uid==0 but gid!=0. Set the iptables rule to not proxy traffic for that gid to circumvent Xray traffic.

Configuration Procedure

1. Preliminary preparation

Android

  1. System has root privilege.

  2. Install busyboxopen in new tag

  3. There is a terminal that can execute commands, you can use adb shell, termux etc.

Other Linux system

Need sudo, iptables-tproxy module and iptables-extra module。

Usually the system comes with these functions. If you are using openwrt, you will need to run the following command:

opkg install sudo iptables-mod-tproxy iptables-mod-extra
@@ -113,6 +113,6 @@
 ip6tables -t mangle -A XRAY6_MASK -j MARK --set-mark 1
 ip6tables -t mangle -A OUTPUT -m owner ! --gid-owner 23333 ! -p icmp -j XRAY6_MASK
 
- + diff --git a/en/document/level-2/nginx_or_haproxy_tls_tunnel.html b/en/document/level-2/nginx_or_haproxy_tls_tunnel.html index df217d454c..05fc725660 100644 --- a/en/document/level-2/nginx_or_haproxy_tls_tunnel.html +++ b/en/document/level-2/nginx_or_haproxy_tls_tunnel.html @@ -24,8 +24,8 @@ Nginx 或 Haproxy 搭建 TLS 隧道隐藏指纹 | Project X - - + +

Nginx 或 Haproxy 实现的 HTTPS 隧道、HTTP/2 over HTTPS 隧道、WebSocket over HTTP/2 over HTTPS 隧道、gRPC over HTTP/2 over HTTPS 隧道以及自签证书双端认证的 gRPC over HTTP/2 over HTTPS 隧道

客户端服务端 Nginx 构建 HTTPS 隧道隐藏指纹

网路结构:

xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

编译 nginx --with-stream

在客户端及服务端均编译

curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

tar -zxvf nginx-1.22.1.tar.gz

cd nginx-1.22.1

apt install gcc make //编译依赖 gcc 以及 make

./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module //此步需要依赖一些库,根据报错安装相应 lib

make && make install

编译之后 nginx 文件夹位于 /usr/local/nginx

配置 nginx

编辑 nginx 配置文件 nginx.conf

vim /usr/local/nginx/conf/nginx.conf

服务端加入如下配置

服务器申请证书不再赘述,参考白话文open in new tag

stream {
@@ -548,6 +548,6 @@
 backend web
     server web /dev/shm/h1h2c.sock
 

xray 配置

简单的 gRPC 配置,无需 TLS,配置见文档,配置的 serviceName 可用于分流。

- + diff --git a/en/document/level-2/redirect.html b/en/document/level-2/redirect.html index bf7843618d..ded9f71bac 100644 --- a/en/document/level-2/redirect.html +++ b/en/document/level-2/redirect.html @@ -24,8 +24,8 @@ 出站流量重定向 | Project X - - + +

基于 fwmark 或 sendThrough 的流量重定向

Warning

This translation was modified on 26 May 2021 and an updated version (24 December 2023) is available on the source page. View the original page

通过 Xray 将特定的流量指向特定出口,实现全局路由“分流”

前言

之前在网络上看到许多代理或者 VPN 会接管全局路由,如果与 Xray 同时安装,会导致 Xray 失效。参考了网络上许多教程,及时分流,也是通过维护一张或者多张 CIDR 路由表来实现的。这种情况下并不优雅,如果我想可以任意替换,实现按需分流,那有没有更好的办法呢?有!

通过 fwmark 或 Xray 的 sendThrough,再简单配合路由表功能即可实现:

  1. Xray 可设置指定的 Tag、域名等走指定接口。如果您的接口是双栈的,可以指定 IPV4 或者 IPV6
  2. 其余用户则走原 IPV4 或者 IPV6

具体设置如下(以 Debian10 为例):

1、安装代理或者 VPN 软件(例如 Wireguard、IPsec 等)

根据不同系统和不同软件,请参考官方安装方法

2、编辑 VPN 配置文件(以 WireGuard 为例)

原始文件:

[Interface]
@@ -240,6 +240,6 @@
 

开机自启

systemctl enable wg-quick@wg0
 systemctl start wg-quick@wg0
 

验证 IPv4/IPv6

自行验证 Google 搜索 myip

后记

本文本意是可以避免的多余的流量浪费,将路由和分流的功能交给 Xray 处理。避免了维护路由表的繁琐工作。顺便技术提升 UP。

感谢

@Xray-core @V2ray-core @WireGuard @p3terx @w @Hiram @Luminous @Ln @JackChou

- + diff --git a/en/document/level-2/tproxy.html b/en/document/level-2/tproxy.html index cc4f2afb44..6b9b160ab7 100644 --- a/en/document/level-2/tproxy.html +++ b/en/document/level-2/tproxy.html @@ -24,8 +24,8 @@ TProxy 透明代理 | Project X - - + +

透明代理(TProxy)配置教程

本配置基于TProxy 透明代理的新 V2Ray 白话文教程open in new tag,加入了 Xray 的新特性,使用 VLESS + XTLS Vision 方案,并将旧教程中默认出站代理的分流方式改为默认出站直连,使用者请按照实际情况进行修改。

本文中所有配置已在 Raspberry Pi 2B、Ubuntu 20.04 环境下测试成功,如在其它环境中使用请自行调整配置。

开始之前

请检查您的设备是否有可用的网络连接,且服务端已经配置成功,客户端已经安装完毕。

需注意的是,目前很多透明代理教程都会将 Linux 系统的 IP 转发打开,但这样会导致 Splice 性能下降。详情请参考大案牍术破案纪实第三篇--我们是如何破解 Splice 性能下降甚至低于 Direct 之谜的open in new tag

这里我想要补充的是,很多透明代理教程会使用 Netfilter 进行分流,使直连流量直接发出而不经过 Xray,这时必须开启 IP 转发;也有的教程,如本文,会将所有流量导入 Xray 之中,由 Xray 的路由模块进行分流,这时无需开启 IP 转发。

Xray 配置

为了更好的分流体验,请替换默认路由规则文件为 Loyalsoldier/v2ray-rules-datopen in new tag,否则 Xray-core 将无法加载本配置。

sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
@@ -281,6 +281,6 @@
 [Install]
 WantedBy=multi-user.target
 
- + diff --git a/en/document/level-2/tproxy_ipv4_and_ipv6.html b/en/document/level-2/tproxy_ipv4_and_ipv6.html index 1d1aee4e41..f11893460b 100644 --- a/en/document/level-2/tproxy_ipv4_and_ipv6.html +++ b/en/document/level-2/tproxy_ipv4_and_ipv6.html @@ -24,8 +24,8 @@ TProxy 透明代理 (ipv4 and ipv6) | Project X - - + +

TProxy 透明代理(ipv4 and ipv6)配置教程

Warning

This translation was modified on 4 March 2023 and an updated version (12 March 2023) is available on the source page. View the original page

本配置参考了TProxy 透明代理的新 V2Ray 白话文教程open in new tag透明代理(TProxy)配置教程open in new tag以及透明代理通过 gid 规避 Xray 流量open in new tag,加入了透明代理对 ipv6 的支持,并且使用 VLESS-TCP-XTLS-RPRX-Vision 方案对抗封锁 (推荐使用 1.7.2 及之后版本)。

关于 Xray 的配置并不是本文重点,使用者可依实际情况进行修改,具体可以参考官方文档示例open in new tag或其他优秀示例 比如@chika0801open in new tag 又如@lxhao61open in new tag

注意

若使用其他配置,你需要着重注意客户端配置中 outboundtagproxy 的部分,其他部分不变

服务端配置也要同时改变

此配置意在解决例如 Netflix 等默认使用 ipv6 连接的网站无法通过旁路由进行代理的问题,或对 ipv6 代理有需要。

本文网络结构为单臂旁路由

本文中所有配置已在 Arch Linux (Kernel: 6.0.10) 环境下测试成功,如在其它环境中同理

注意安装相应程序 # sudo apt install iptables ip6tables# sudo apt install nftables

若旁路由未安装 xray 程序,可以手动下载相应 xray 程序如 Xray-linux-64.zipopen in new tag ,然后复制 install-release.shopen in new tag 文件到旁路由,赋予可执行权限 # chmod 700 install-release.sh,然后使用 # ./install-release.sh --local Xray-linux-64.zip 根据提示进行本地安装。

Xray 配置

客户端配置

{
@@ -430,6 +430,6 @@
 [Install]
 WantedBy=multi-user.target
 
  1. 最后执行 systemctl enable tproxyrules 命令。

tproxyrules.service

注意其中主路由器 IP 地址,根据实际修改

ExecStartPre=/bin/sh -c 'until ping -c1 192.168.31.1; do sleep 1; done;' 命令为确保获得 IP 地址后再执行命令,否则会诡异报错,其中 IP 地址为主路由器地址,根据实际修改。

注意

如果通过 dhcpcd 等设置了静态 IP 及网关,则上述相关 ip route add/del 设置需删除

局域网设备上网设置

此处假定旁路由 ipv4, ipv6 地址分别为192.168.31.100, fd00:6868:6868::8866, 旁路由的 ipv4, ipv6 地址可由命令ip add获得。

方法一

局域网设备上网有两种方式,第一种就是在使用设备上进行静态 IP 的配置,将网关指向旁路由 IP。注意绝大部分手机仅支持手动配置 ipv4 网关,不支持手动配置 ipv6 网关,除非 root 后进行相关设置。

以 windows 设备为例,可以先开启 DHCP 记录自动分配的 IP 以参考,然后手写静态配置。

DNS 设置

此配置劫持 DNS 流量,DNS 可以随便写

image image

方法二

局域网设备上网的第二种方式,是在路由器上进行网关设置,这种方法对于连接到此路由器的设备无需做任何设置即可科学上网,但注意有些路由器不支持 ipv6 的网关设置,有 ipv6 需求的设备仍需在所需设备上单独手动配置 ipv6 相关设置参考方法一。

image

Finally

按照以上方法设置后设备即可双栈访问,进入测试网站比如 https://ipv6-test.com/ 可以看到如下结果 (需要代理此网站才能看到如下结果)

image

写在最后

如今 ipv6 并未完全普及,我们日常访问的流量 99%仍为 ipv4 流量;很多 VPS 商家虽然提供 ipv6 地址,但线路优化非常垃圾,甚至处于不可用状态,为何要加入 ipV6 的设置?

可以看到目前 ipv6 处于很尴尬的境地,各种设备对于 ipv6 的支持很烂,但是都在逐步完善,同时 Windows 系统对于 ipv6 的优先级也在提高,很多浏览器也会优先进行 ipv6 的解析以及访问,很多网站也开始默认使用 ipv6 进行访问(比如 Netflix, 如果没有配置 ipv6, 浏览器打开 Netflix 会显示 Not Available 是因为没有代理 Netflix 的 ipv6 请求,当然可以选择禁用 Windows 的 ipv6,但支持 ipv6 的 pt 站就无法使用)

这种情况下 ipv4 无法完全胜任网络冲浪的需求,即使是那 1%的流量,遇到了也会让人头疼不已。

而可以预见 ipv6 也会逐步与 ipv4 分庭抗礼,所以有必要加入 ipv6 的设置。

- + diff --git a/en/document/level-2/traffic_stats.html b/en/document/level-2/traffic_stats.html index 6d62b5cca1..4eb6732057 100644 --- a/en/document/level-2/traffic_stats.html +++ b/en/document/level-2/traffic_stats.html @@ -24,8 +24,8 @@ 流量统计 | Project X - - + +

流量统计配置教程

请熟悉流量统计 白话文教程open in new tag,本文在其基础上适配了 Xray(1.5.9+)。

查看流量信息

配置方法与 v2fly 一致。 查看流量信息是 xray 命令行的其中一个功能。配置内设置的 api dokodemo-door 端口,即为 --server 参数的端口。

xray api statsquery --server=127.0.0.1:10085 #查看所有流量
@@ -120,6 +120,6 @@
 print_sum "$DATA" "user"
 echo "-----------------------------"
 
- + diff --git a/en/document/level-2/transparent_proxy/transparent_proxy.html b/en/document/level-2/transparent_proxy/transparent_proxy.html index 85557dd3cf..81cce15864 100644 --- a/en/document/level-2/transparent_proxy/transparent_proxy.html +++ b/en/document/level-2/transparent_proxy/transparent_proxy.html @@ -24,8 +24,8 @@ 透明代理入门 | Project X - - + +

Warning

This translation was modified on 26 May 2021 and an updated version (26 December 2023) is available on the source page. View the original page

透明代理入门

什么是透明代理

透明代理简单地说就是不让被代理的设备感觉到自己被代理了。简单地说就是,被代理的设备上不需要运行任何代理软件(比如 Xray、V2RayNG 等),当你连接上网络时,你的设备已经被代理了。

这也意味着,代理的软件运行在别的地方,比如运行在路由器中,通过路由器上网的设备就自动被代理了。

透明代理的实现

透明代理的实现目前主要有两种方式:

tun2socks

可用 Windows/Linux(包括安卓)实现。因为实现过程比较简单,很少有教程,我这里简单描述一下。

Windows

  1. 安装 Netchopen in new tag ,使用模式[3] [TUN/TAP] 绕过局域网启动。

  2. 开启热点

  3. 打开控制面板->网络和 Internet->网络和共享中心->更改适配器设置,找到TAP-Windows AdapterMicrosoft Wi-Fi Direct Virtual Adapter

  4. 鼠标右键点击TAP-Windows Adapter属性->共享,勾选允许其他网络用户通过此计算机的 Internet 连接来连接,在家庭网络连接中选择Microsoft Wi-Fi Direct Virtual Adapter的那个网络连接,点击确定。

Android

  1. 配置连接 V2RayNG

  2. 开启热点

  3. 热点设置 -> 允许热点使用 VPN(部分安卓系统可能没有这个选项)

iptables/nftables

iptables 与 nftables 实现透明代理的原理相同,下文统一使用 iptables。

基于 iptables 的透明代理实现只能用于 Linux 系统(包括 openwrt/安卓)。由于其比 tun2socks 更高效率以及适合在路由器中配置而广泛使用。

现存的三篇白话文透明代理教程其实讲的都是基于这种方案的透明代理实现,它们是: 新 V2Ray 白话文指南-透明代理open in new tag新 V2Ray 白话文指南-透明代理(TPROXY)open in new tag透明代理(TProxy)配置教程 。其中第一篇是基于 iptables-redirect 模式,已经过时了,不建议使用,仅供参考。第二篇和第三篇讲的都是基于 iptables-tproxy 模式的透明代理实现。

iptables 实现透明代理原理

Linux 使用Netfilter来管理网络,Netfilter模型如下:

Netfilter

假设使用路由器作为网关(即我们平时的上网方式),那么:

局域网设备通过路由器访问互联网的流量方向:

PREROUTING链->FORWARD链->POSTINGROUTING链

局域网设备访问路由器的流量(如登陆路由器 web 管理界面/ssh 连接路由器/访问路由器的 dns 服务器等)方向:

PREROUTING链->INPUT链->网关本机

路由器访问互联网的流量方向:

网关本机->OUTPUT链->POSTINGROUTING链

通过使用 iptables 操控PREROUTING链OUTPUT链的流量走向,转发到 Xray,就可以代理局域网设备和网关本机。

透明代理难在哪里

透明代理的难点就在于路由,所谓路由,就是区分哪些流量是直连的,哪些该被代理,所以我个人认为叫做分流更加合适。

我们可以把路由由易到难分为以下几个阶段:

  1. 代理全部请求

  2. 本地局域网 IP/组播 IP 请求直连,其它请求代理

  3. 在 2 的基础上直连 Xray 发起的连接请求

  4. 在 3 的基础上直连指向中国大陆 IP 的连接请求,并对国内外域名选择国内外 DNS 服务器解析。

上面说的三篇教程,都是在第四阶段。所以新手直接阅读可能显得有点难懂。

从零开始一步步实现基于 iptables-tproxy 的透明代理

在开始之前,你需要有一定的基础知识:

  1. 大概知道什么是 TCP/IP 协议、域名和 DNS 服务器

  2. 知道什么是 WAN 口,LAN 口,LAN_IP,WAN_IP 以及 DHCP 服务器。对于旁路由,只有一个网口,这里称其为 LAN 口

  3. 对 Linux 系统有最基础的了解(知道怎么运行命令)

  4. 能够手写客户端 json 文件配置,至少要能看懂

前期准备工作

1. 准备一个运行 Linux 系统的网关

比如,刷了 OpenWRT 的路由器

2. 在网关(路由器)准备好 Xray 可执行文件以及配置文件

配置文件监听 12345 端口,开启 tproxy:

{
@@ -107,6 +107,6 @@
 iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK
 iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK
 

但是这么配置有个缺点,如果使用 CDN 或者 VPS 很多的话,就不好写规则了。

  1. 通过 mark 规避

三个白话文教程都是使用这种方法规避,自行参考,这里不再赘述。

  1. 通过 gid 规避(推荐)

参考 [透明代理]通过 gid 规避 Xray 流量

这样就完成了第三阶段的代理,也就是平时说的全局代理。但是记得把网关的 DNS 服务器设置为国外的 DNS 服务器,否则可能依然返回被污染的结果。

第四阶段

其实,并不是所有人都需要实现第四阶段。全局代理对于大部分情况已经适用。

特别是对于旁路由而言。需要代理时,将网关调成旁路由的 IP,不需要代理时,将网关换回主路由 IP。

至于第四阶段的具体实现,那三篇白话文教程讲的都是。在理解了上面的内容后,再去看那三篇白话文教程,就比较容易理解了。

代理 ipv6

上面的规则只对 ipv4 生效,如果还想要代理 ipv6 请求,则使用 ip6tables 命令,用法与 iptables 基本相同。参考 [透明代理]通过 gid 规避 Xray 流量#4-设置 iptables 规则

iptables 透明代理的其它注意事项

  1. 如果作为代理的网关作为主路由,要在PREROUTING链规则中加一条iptables -t mangle -A XRAY ! -s 网关LAN_IP地址段 -j RETURN,即在第一阶段使用、第二阶段被删除的指令。如果不写,WAN 口中同网段的其它人可以将网关填写成你的 WAN_IP,从而蹭你的透明代理用,还可能带来一定的危险性。

  2. 新 V2Ray 白话文指南-透明代理(TPROXY)#设置网关open in new tag 中的第三条说:手动配置 PC 的网络,将默认网关指向树莓派的地址即 192.168.1.22。此时 PC 应当能正常上网(由于还没设置代理,“正常”是指可以上国内的网站)。实际上,Ubuntu、CentOS、debian 等系统就算开启了 IP 转发,PC 也不能正常上网,这是正常的。事实上只有 OpenWRT 能做到文中所描述的那样,据 @BioniCosmosopen in new tag 点拨,这是由于一般的 Linux 系统没有 Masquery 规则。

  3. too many open files 问题open in new tag ,解决方法见 [透明代理]通过 gid 规避 Xray 流量-配置最大文件大开数&运行 Xray 客户端

  4. 关于开启 ip_forward,待补充...

  5. 避免已有连接的包二次通过 TPROXY ,待补充...

  6. 主路由、单臂路由与旁路由,待补充...

- + diff --git a/en/document/level-2/warp.html b/en/document/level-2/warp.html index 935b8f2874..cd8ca5099f 100644 --- a/en/document/level-2/warp.html +++ b/en/document/level-2/warp.html @@ -24,8 +24,8 @@ Enhancing Proxy Security with Cloudflare Warp | Project X - - + +

Enhancing Proxy Security with Cloudflare Warp

Warning

This translation was modified on 19 May 2023 and an updated version (6 April 2024) is available on the source page. View the original page

Xray (1.6.5+) has added outbound WireGuard support. Although the added code and dependencies will increase the core size, we believe that this is a necessary new feature for three reasons:

  1. Through recent discussions and experimentsopen in new tag, we know that proxying the traffic back to China is not safe. One way to deal with this is to route the back-to-China traffic to a black hole, but the downside is that due to the delay in geosite and geoip updates or the lack of knowledge on how to properly split the traffic on the client side, the traffic ends up going to the black hole, affecting the user experience. In this case, we only need to import the back-to-China traffic into Cloudflare Warp, which can achieve the same level of security without affecting the user experience.
  2. As we all know, most airports will log the domain names visited by users, and some airports will even audit and block some user traffic. One way to protect user privacy is to use chain proxies on the client side. The WireGuard lightweight VPN protocol used by Warp adds an extra layer of encryption within the proxy layer. For airports, the target of all user traffic is Warp, thereby maximizing privacy protection.
  3. It is easy to use, and only one core is needed to complete the split, Wireguard Tun, and chain proxy settings.

Applying for a Warp Account

  1. Thank you Cloudflare for promoting a free internet. Now you can use the Warp service for free, and the nearest server will be automatically selected based on the exit.
  2. Use a VPS and download wgcfopen in new tag.
  3. Run wgcf register to generate wgcf-account.toml.
  4. Run wgcf generate to generate wgcf-profile.conf. Copy the following content:
[Interface]
@@ -111,6 +111,6 @@
    ]
 }
 
- + diff --git a/en/index.html b/en/index.html index 59b9854559..1cfd49dec9 100644 --- a/en/index.html +++ b/en/index.html @@ -24,8 +24,8 @@ Project X - - + +
Project X

Project X

Fear not the clouds that obscure the view, golden eyes like a torch brighten the sky

Start here → Configuration guide →

High-speed protocol

Original VLESS and XTLS protocols, free from redundant encryption, release CPU power

Free combination

Perfect fallback mechanism, effectively prevent active detection, multi-service sharing ports @@ -34,6 +34,6 @@

Full compatibility

Fully compatible with v2ray-core configuration files and API calls

Affinity

Active community discussions and contributions, MPL 2.0 open source license

XTLS? Xray? V2Ray?

XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.

  • Xray-core is a superset of v2ray-core, with better overall performance and enhancements such as XTLS, and it'scompletelycompatible with v2ray-core functionality and configuration.
    • Only one executable file, including ctl functionality, run is the default command
    • Configuration iscompletelycompatible, environment variables and API calls need to be changed to start with XRAY_
    • Exposed raw protocol's ReadV on all platforms
    • Provides complete VLESS & Trojan XTLS support, both with ReadV
    • Provides multiple XTLS flow control modes, unrivaled performance!

"Configuration compatible, overall better"

Who are we?

It doesn't matter who we are. What matters is that we will keep riding and never look back.

Help Xray become stronger

Welcome to help Xray become stronger!

Telegram

Thanks

  • Thanks to everyone for their support!
  • Thanks to all kinds of scripts, Docker images, client support... Thanks to all the big guys who helped improve the ecosystem!
  • Thanks to friends who have contributed to the Xray website and documentation.
  • Thanks to friends who have made meaningful suggestions and comments.
  • Thanks to every friend in the Telegram group who helps others.

More about project X

  • If you would like to learn more about project X's history and growth, please click here

License

Mozilla Public License Version 2.0open in new tag

Stargazers over time

Stargazers over timeopen in new tag

- + diff --git a/index.html b/index.html index 491544eb00..1faf52938f 100644 --- a/index.html +++ b/index.html @@ -24,8 +24,8 @@ Project X - - + +
Project X

Project X

不畏浮云遮望眼 · 金睛如炬耀苍穹

由此开始 → 配置指南 →

极速协议

原创 VLESS 与 XTLS 协议,摆脱冗余加密,释放CPU算力

自由组合

完善的回落机制,有效防止主动探测,多服务共享端口 @@ -34,6 +34,6 @@

完整兼容

完整兼容 v2ray-core 配置文件与 API 调用

亲和力

活跃的社区讨论及贡献,MPL 2.0 开源许可协议

XTLS ? Xray ? V2Ray ?

XTLS are brilliant ideas for TLS we study, while Xray is the best practice we maintain.

  • Xray-core 是 v2ray-core 的超集,含更好的整体性能和 XTLS 等一系列增强,且完全兼容 v2ray-core 的功能及配置。
    • 只有一个可执行文件,含 ctl 的功能,run 为默认指令
    • 配置上完全兼容,环境变量和 API 对应要改为以 XRAY_ 开头
    • 全平台开放了裸协议的 ReadV
    • 提供完整的 VLESS & Trojan XTLS 支持,均有 ReadV
    • 提供了 XTLS 多种流控模式, 性能一骑绝尘!

“配置兼容,整体更好”

我们是谁?

It doesn't matter who we are. What matters is that we will keep riding and never look back.

帮助 Xray 变得更强

欢迎帮助 Xray 变得更强!

Telegram

致谢

  • 感谢所有人的支持!
  • 感谢各类脚本、Docker 镜像、客户端支持...感谢所有帮忙完善生态的大佬们!
  • 感谢为 Xray 网站和文档添砖加瓦的朋友们.
  • 感谢提出有意义的建议和意见的朋友们.
  • 感谢 Telegram 群每一位帮助群友的朋友.

更多关于 Project X

  • 如果你想知道更多关于 Project X 的足迹与成长, 请点击这里

License

Mozilla Public License Version 2.0open in new tag

Stargazers over time

Stargazers over timeopen in new tag

- + diff --git a/ru/about/news.html b/ru/about/news.html index 1beb789e6a..e51aea1f49 100644 --- a/ru/about/news.html +++ b/ru/about/news.html @@ -24,11 +24,11 @@ 大史记 | Project X - - + +

大史记

2021.4.6

  • VuePress Next.
  • With Dark Mode.

2021.4.4

  • 本文档迎来的新的首页。
  • 本文档迎来了暗黑模式。
  • 当然,暗黑模式还有各种各样的问题。具体的内容还需要慢慢调整。
  • 另:Telegram 群聊突破了 5000 人!还加入了 Anti-Spam 机器人!
  • 🎉🎉🎉

2021.4.1 v1.4.2Открыть в новой вкладке

  • 不是愚人节玩笑,今天更新。
  • 加入 Browser Dialer,用与改变 TLS 指纹与行为。
  • 加入 uTLS,用与改变 TLS Client Hello 的指纹。
  • 顺便修复了一大堆奇妙的问题,具体的内容见更新日志。

2021.3.25

没错还在变。 -_-

2021.3.15

文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

2021.3.14 v1.4.0Открыть в новой вкладке

  • Happy Pi-Day!
  • 这次是个大更新:
    • 为链式代理引入了传输层支持。
    • 为 Dialer 引入了 Domain Strategy,解决奇妙的 DNS 问题。
    • 添加了 gRPC 传输方式,与更快一点的 Multi Mode。
    • 添加了 WebSocket Early-Data 功能,减少了 WebSocket 的延迟。
    • 添加了 FakeDNS。
    • 还修复了系列的问题,添加了各类功能,详情请见更新日志。
  • 还是 VuePress 比较爽啊(

2021.3.3 1.3.1Открыть в новой вкладке

  • 这个版本使用了 Golang 1.16,正式原生支持 Apple Silicon。
  • 同时修复了一个会导致 Panic 的 bug。Holmium_认为这是在骗、在偷袭。
  • 修复了几个遗留问题。

2021.2.14 1.3.0Открыть в новой вкладке

  • Happy 🐮 Year 🎉!
  • v1.3.0 通过非常巧妙的机制实现了 V 系协议全部 FullCone,同时保证了一定的兼容性。
  • OHHHHHHHHHHHH!

2021.01.31 1.2.4Открыть в новой вкладке

  • 解决两个“连接至标准 Socks 服务端时可能出错”的历史遗留问题。
  • 似乎这个版本没有什么改变,但这只是暴风雨前的宁静。
  • (没错我就是先知)

    你个傻子,你拿的是 UNO 牌。

2021.01.25

  • 全互联网最好最详细的秘籍入门篇同学们练熟了吗? 🍉 老师开始连载秘籍第一层咯...
  • 英文版文档网站逐渐增加内容 ing, 感谢各位大佬的辛苦付出~!

2021.01.22 1.2.3Открыть в новой вкладке

  • 对 SS 协议的支持变强了, 支持单端口多用户!
  • 对 trojan 协议的支持也变强了, trojan 的回落也解锁 SNI 分流的新姿势啦~!
  • (VLESS: 嘤嘤嘤)
  • UDP 奇奇怪怪的 BUG 被干掉了, 一个字, "稳定".
  • 嗅探可以排除你不想嗅探的域名, 可以开启一些新玩法.
  • 向发现问题->开 issue->自行测试->自行分析->自行找到问题->自行解决->然后给上下游提交 PR 的大佬 a @Bohan YangОткрыть в новой вкладке 致敬!
  • 其他美味小樱桃, 惯例更新品尝就对啦.

2021.01.19

  • 一些数字
    • 版本发布了 10   个 tag
    • 解决掉了 100  个 issue
    • 复刻了 300  个 fork
    • 点了 2000 个 star
    • 群 3000 个 人

2021.01.17

2021.01.15 1.2.2Открыть в новой вкладке

  • 回落分流又解锁了奇怪的新姿势! 回落中可以根据 SNI 分流啦~!
  • 之前预告的 UUID 修改正式上线.(往下看往下看)
  • 日志现在看起来比上一次顺眼又更顺眼了一丢丢.
  • 远程 DOH 和其他的 DNS 模式一样学会了走路由分流.
  • 当然还有其他各种小糖果.(更新品尝就对了)
  • 啊, 还有, 世界上第一個 M1 上跑起 Xray 的男人是 Anthony TSE

2021.01.12

  • 将要到来的 UUID 修改, 支持自定义字符串和 UUID 之间的映射. 这意味着你将可以这样在配置文件中写 id 来对应用户.
    • 客户端写 "id": "我爱 🍉 老师 1314",
    • 服务端写 "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (此 UUID 是 我爱🍉老师1314 的 UUID 映射)
  • 🍉 老师的小小白白话文大结局, 撒花.

2021.01.10 1.2.1Открыть в новой вкладке

  • 大量的 UDP 相关修复, 甚至可以在育碧的土豆服务器上玩彩虹六号!
  • Google Voice 应该也可以正常使用 v2rayNG 拨打了.
  • 日志现在看起来更顺眼.

2021.01.07

  • 礼貌和尊重本应是社区不需要明说的准则之一。

2021.01.05

  • 文档网站正在悄悄的进行着某些神秘的变化。。。,🙊🙊🙊

2021.01.03

2021.01.01

【祝大家新年快乐,嗨皮牛耶!】🎆🎇🎆 1.2.0Открыть в новой вкладке

🎁 在元旦的最后几分钟,v1.2.0 它来了,带着周五必更的惯例,带着各位贡献大佬的心血以及 @rprxx 的黑眼圈,不负众望的来了!

  • 圣诞礼物v1.1.5后的元旦礼物 🎁,游戏玩家大福利,全面 FullCone。
  • (UDP 还会继续增强!)
  • 如果你已经拆过圣诞礼物,这次还有比圣诞礼物更精美的包装和小糖果哦。(同样不用问,更新品尝就对了)
  • (不,下面不是广告,是里程碑。)
  • Xray 是有史以来第一个不受限制的多协议平台:只需 Xray 即可解决问题,无需借力其它实现。
    • 一人扛起了所有!支持各大主流协议!
    • 一骑绝尘的性能!
    • 日趋完善的功能!
    • 可怕的生命力与社区亲和力!
  • Xray 将继续保持前行! 因此 Xray 需要更多的英雄!!Открыть в новой вкладке
  • PS:请品,请细品release notesОткрыть в новой вкладке每一句。似乎有一个小秘密小彩蛋 (啊,有人敲门...我一会和你们说)

2020.12.29

透明代理的游戏玩家利好! Xray-core tproxy 入站, socks 出站 UDP FullCone 测试版, TG 群Открыть в новой вкладке火热测试中

2020.12.25 1.1.5Открыть в новой вкладке

圣诞节快乐!

  • 游戏玩家的圣诞礼物!你可以用 xray 爽快的打游戏啦!因为有了 SS/trojan UDP fullcone
  • 你可以用你喜欢的格式写配置文件了,比如 yaml,比如 toml...
  • (VLESS 的 UDP fullcone 和更多增强很快就到!)
  • 无须再担心证书验证被墙,OCSP stapling 已经上线!
  • kirin 带来了一大波 脚本更新.脚本在此Открыть в новой вкладке
  • 还有更多美味小樱桃!(不用问,更新品尝就对了)

2020.12.24

因为某些不可描述的原因,Xray 的文档网站已在发布日前偷跑上线。 网址为:没错你正在看的就是Открыть в новой вкладке

大家可以查阅各种内容也欢迎纠错/提出建议(可发往文档 github 仓库的 issue 区)

文档网站需要不断完善和增加内容,以及完善设计。 因此更欢迎大家一起为文档建设添砖加瓦。 文档的仓库Открыть в новой вкладке

仓库的 readme 中有简略教程说明如何帮助 xray 改进文档网站. 欢迎大家查看,纠错,修改,增加心得。

2020.12.23

Xray-core Shadowsocks UDP FullCone 测试版, TG 群Открыть в новой вкладке火热测试中

2020.12.21

  • Project X 群人数 2000+
  • 群消息(含游戏群) 日均破万

2020.12.18 1.1.4Открыть в новой вкладке

  • 更低的启动内占用和内存使用优化
  • 随意定制的 TLS 提高你的 SSL 评级
  • 支持 XTLS 入站的 Splice 以及支持 trojan 的 XTLS
  • 还有在您路由器上使用的 Splice 最佳使用模式建议

2020.12.17

鉴于日益增长群人数和游戏需求, 开启了TG 游戏群Открыть в новой вкладке

2020.12.15

安装脚本 dev 分支Открыть в новой вкладке开启, 持续更新功能中.

2020.12.11 1.1.3Открыть в новой вкладке

  • 完整版本的 REDIRECT 透明代理模式.
  • 软路由 splice 流控模式的优化建议.

2020.12.06 1.1.2Открыть в новой вкладке

  • 流控增加 splice 模式, Linux 限定, 性能一骑绝尘.
  • 增强了 API 兼容

2020.12.04

增加 splice 模式

2020.11.27

  • Project X 的 GitHub 主仓库 Xray-core 已获 500+ stars
  • 登上了 GitHub Trending
  • Project X 群人数破千,频道订阅数 500+

2020.11.25 1.0.0Открыть в новой вкладке

Xray 的第一个版本.

  • 基于 v2ray-core 修改而来,改动较大
  • 全面增强, 性能卓越, 完全兼容

2020.11.23

project X start

梦开始的时候

- + diff --git a/ru/config/api.html b/ru/config/api.html index 2bcbda9405..1e4ae00622 100644 --- a/ru/config/api.html +++ b/ru/config/api.html @@ -24,8 +24,8 @@ API | Project X - - + +

API

Настройка API предоставляет API-интерфейсы на основе gRPCОткрыть в новой вкладке для удаленного вызова.

Интерфейсы можно включить с помощью модуля конфигурации api. Когда API включен, Xray создает исходящее подключение с тем же тегом, что и тег API.
Необходимо вручную направить все входящие API-подключения на это исходящее подключение с помощью правил маршрутизации.
См. раздел Связанные настройки в этом документе.

Начиная с версии v1.8.12Открыть в новой вкладке поддерживается упрощенный режим настройки, в котором достаточно указать только ApiObject, без необходимости настройки inbounds и routing.
Однако при использовании упрощенной настройки статистика трафика не учитывает трафик входящих API-подключений.

Внимание

Большинству пользователей не нужен этот API, новички могут просто пропустить этот раздел.

ApiObject

ApiObject соответствует полю api в конфигурационном файле.

{
@@ -70,6 +70,6 @@
 xray.app.proxyman.command.HandlerService
 xray.app.stats.command.StatsService
 

Примеры вызова API

Xray-API-documentsОткрыть в новой вкладке @crossfw

- + diff --git a/ru/config/dns.html b/ru/config/dns.html index f4cf1a71e0..0ee7fe0138 100644 --- a/ru/config/dns.html +++ b/ru/config/dns.html @@ -24,8 +24,8 @@ Встроенный DNS-сервер | Project X - - + +

Встроенный DNS-сервер

DNS-сервер

Встроенный DNS-модуль Xray имеет два основных назначения:

  • Разрешение доменных имен в IP-адреса на этапе маршрутизации и сопоставление правил с полученными IP-адресами для разделения трафика.
    Разрешение доменных имен и разделение трафика зависят от значения параметра domainStrategy в модуле конфигурации маршрутизации.
    Встроенный DNS-сервер будет использоваться для DNS-запросов только при следующих значениях:

    • "IPIfNonMatch": при запросе доменного имени Xray сопоставляет его с доменами, указанными в правилах маршрутизации.
      Если совпадение не найдено, встроенный DNS-сервер используется для разрешения доменного имени, а затем полученный IP-адрес снова сопоставляется с правилами маршрутизации на основе IP-адресов.
    • "IPOnDemand": при сопоставлении правил, основанных на IP-адресах, доменное имя немедленно разрешается в IP-адрес для сопоставления.
  • Разрешение целевого адреса для подключения.

    • Например, в исходящем подключении freedom, если параметр domainStrategy установлен в UseIP, исходящие запросы будут сначала разрешать доменное имя в IP-адрес с помощью встроенного DNS-сервера, а затем устанавливать соединение.
    • Например, в sockopt, если параметр domainStrategy установлен в UseIP, системные соединения, инициированные этим исходящим подключением, будут сначала разрешать доменное имя в IP-адрес с помощью встроенного DNS-сервера, а затем устанавливать соединение.

Совет 1

DNS-запросы, отправляемые встроенным DNS-сервером, автоматически перенаправляются в соответствии с конфигурацией маршрутизации.

Совет 2

Поддерживаются только базовые запросы IP-адресов (записи A и AAAA). Записи CNAME будут запрашиваться повторно до тех пор, пока не будет возвращена запись A/AAAA. Другие запросы не обрабатываются встроенным DNS-сервером.

Процесс обработки DNS-запросов

Если запрашиваемое доменное имя:

  • Соответствует сопоставлению "домен - IP" или "домен - массив IP" в hosts, то этот IP-адрес или массив IP-адресов возвращается в качестве результата DNS-разрешения.
  • Соответствует сопоставлению "домен - домен" в hosts, то значение этого сопоставления (другой домен) используется в качестве текущего запрашиваемого доменного имени, и процесс обработки DNS-запросов продолжается до тех пор, пока не будет разрешен IP-адрес или не будет возвращен пустой результат.
  • Не соответствует hosts, но соответствует списку доменов domains одного (или нескольких) DNS-серверов, то запросы отправляются на соответствующие DNS-серверы в порядке приоритета.
    Если запрос к DNS-серверу завершается неудачей или expectIPs не совпадает, используется следующий подходящий DNS-сервер.
    В противном случае возвращается полученный IP-адрес.
    Если запросы ко всем подходящим DNS-серверам завершаются неудачей или expectIPs не совпадает, компонент DNS:
    • По умолчанию выполняет "резервный (fallback) запрос DNS": запросы отправляются на "DNS-серверы, которые не использовались в предыдущем раунде неудачных запросов и для которых skipFallback имеет значение по умолчанию false".
      Если запрос завершается неудачей или expectIPs не совпадает, возвращается пустой результат.
      В противном случае возвращается полученный IP-адрес.
    • Если disableFallback установлен в true, "резервный (fallback) запрос DNS" не выполняется.
  • Не соответствует hosts и не соответствует списку доменов domains ни одного DNS-сервера, то:
    • По умолчанию запросы отправляются на "DNS-серверы, для которых skipFallback имеет значение по умолчанию false".
      Если запрос к первому выбранному DNS-серверу завершается неудачей или expectIPs не совпадает, используется следующий выбранный DNS-сервер.
      В противном случае возвращается полученный IP-адрес.
      Если запросы ко всем выбранным DNS-серверам завершаются неудачей или expectIPs не совпадает, возвращается пустой результат.
    • Если количество "DNS-серверов, для которых skipFallback имеет значение по умолчанию false", равно 0 или disableFallback установлен в true, используется первый DNS-сервер в конфигурации DNS.
      Если запрос завершается неудачей или expectIPs не совпадает, возвращается пустой результат.
      В противном случае возвращается полученный IP-адрес.

DnsObject

DnsObject соответствует полю dns в конфигурационном файле.

{
@@ -116,6 +116,6 @@
   "clientIP": "1.2.3.4"
 }
 

address: address

Адрес DNS-сервера.
Поддерживаются два типа: адрес DNS (в виде строки) и ServerObject.

Значение "localhost" означает использование локальных настроек DNS.

Если значение - это адрес DNS "IP", например "8.8.8.8", Xray будет использовать указанный UDP-порт этого адреса для DNS-запросов.
Запрос будет следовать правилам маршрутизации.
По умолчанию используется порт 53.

Если значение имеет вид "tcp://host", например "tcp://8.8.8.8", Xray будет использовать DNS over TCP для запросов.
Запрос будет следовать правилам маршрутизации.
По умолчанию используется порт 53.

Если значение имеет вид "tcp+local://host", например "tcp+local://8.8.8.8", Xray будет использовать локальный режим TCP (TCPL) для запросов.
Это означает, что DNS-запросы не будут проходить через компонент маршрутизации, а будут отправляться непосредственно через исходящее подключение Freedom для сокращения времени ожидания.
Если порт не указан, по умолчанию используется порт 53.

Если значение имеет вид "https://host:port/dns-query", например "https://dns.google/dns-query", Xray будет использовать DNS over HTTPS (RFC8484, сокращенно DOH) для запросов.
Некоторые провайдеры имеют сертификаты с IP-псевдонимами, поэтому можно использовать IP-адрес напрямую, например https://1.1.1.1/dns-query.
Также можно использовать нестандартные порты и пути, например "https://a.b.c.d:8443/my-dns-query".

Если значение имеет вид "https+local://host:port/dns-query", например "https+local://dns.google/dns-query", Xray будет использовать локальный режим DOH (DOHL) для запросов.
Это означает, что DOH-запросы не будут проходить через компонент маршрутизации, а будут отправляться непосредственно через исходящее подключение Freedom для сокращения времени ожидания.
Обычно этот режим подходит для использования на сервере.
Также можно использовать нестандартные порты и пути.

Если значение имеет вид "quic+local://host:port", например "quic+local://dns.adguard.com", Xray будет использовать локальный режим DOQ (DOQL) для запросов.
Это означает, что DNS-запросы не будут проходить через компонент маршрутизации, а будут отправляться непосредственно через исходящее подключение Freedom.
Этот режим требует, чтобы DNS-сервер поддерживал DNS over QUIC.
По умолчанию для запросов используется порт 853, можно использовать нестандартный порт.

Если значение равно fakedns, для запросов будет использоваться FakeDNS.

port: number

Порт DNS-сервера, например 53.
По умолчанию используется порт 53.
Этот параметр не используется в режимах DOH, DOHL, DOQL.
Нестандартный порт должен быть указан в URL.

domains: [string]

Список доменов, для которых в первую очередь будет использоваться этот сервер.
Формат доменных имен такой же, как и в конфигурации маршрутизации.

expectIPs: [string]

Список диапазонов IP-адресов, формат такой же, как и в конфигурации маршрутизации.

Если этот параметр настроен, DNS Xray будет проверять возвращаемые IP-адреса и возвращать только те, которые входят в список expectIPs.

Если этот параметр не настроен, IP-адреса возвращаются без изменений.

skipFallback: true | false

true - пропустить этот сервер при выполнении резервных (fallback) DNS-запросов, по умолчанию false (не пропускать).

- + diff --git a/ru/config/fakedns.html b/ru/config/fakedns.html index ade4656989..66c1428a77 100644 --- a/ru/config/fakedns.html +++ b/ru/config/fakedns.html @@ -24,8 +24,8 @@ FakeDNS | Project X - - + +

FakeDNS

FakeDNS подменяет DNS-записи, чтобы получить целевое доменное имя, что позволяет сократить время DNS-запросов и получить целевое доменное имя при использовании прозрачного проксирования.

Внимание

FakeDNS может загрязнить локальный DNS-кэш, что может привести к "недоступности сети" после отключения Xray.

FakeDNSObject

FakeDNSObject соответствует полю fakedns в конфигурационном файле.

{
@@ -130,6 +130,6 @@
   ]
 }
 
- + diff --git a/ru/config/features/browser_dialer.html b/ru/config/features/browser_dialer.html index 2de7c32e46..c8fc07768e 100644 --- a/ru/config/features/browser_dialer.html +++ b/ru/config/features/browser_dialer.html @@ -24,11 +24,11 @@ Browser Dialer | Project X - - + +

Warning

This translation was modified on 18 July 2024 and an updated version (20 July 2024) is available on the source page. View the original page

Browser Dialer

БЕТА v1.4.1+

Предыстория

Xray обычно использует uTLS для имитации поведения популярных браузеров, и им можно управлять с помощью настройки fingerprint. Однако отпечатки, создаваемые uTLS, являются несовершенной копией реальных, и поскольку uTLS является популярной библиотекой, они сами могут стать целью.

Итак, идея Browser DialerОткрыть в новой вкладке заключается в том, что Xray использует настоящий браузер для установления TLS-соединений. Это работает так: Xray запускает небольшой веб-сайт на localhost:8080, пользователь открывает этот веб-сайт в выбранном им браузере, а JavaScript на этой странице будет действовать как сетевой стек Xray (HTTP-клиент, TLS-клиент).

Таким образом, поведение снятия отпечатков TLS является идеальным, и поэтому может быть возможно оживить серверы, которые отлично открываются как веб-сайты в браузере, но не подключаются с использованием какого-либо программного обеспечения для проксирования.

Однако есть много недостатков:

  • Пользователь должен запускать браузер рядом с клиентом Xray только для открытия прокси-соединения.
  • Browser Dialer не должен быть туннелирован через сам прокси, иначе возникнет петля. Пользователи TUN должны быть осторожны.
  • Браузер может работать только со стандартным HTTP, что означает, что поддерживаются только WebSocket и SplitHTTP.
  • CORSОткрыть в новой вкладке необходимо учитывать при выполнении запросов с одного веб-сайта (localhost:8080) на другой (proxy.example.com:443).
  • Браузер туннелирует ваш трафик с помощью JavaScript, поэтому наблюдается значительное снижение производительности (или разрядка аккумулятора).
  • Конфигурация, используемая с Browser Dialer, не может использовать собственные заголовки SNI или хоста. SNI == host == address. Пользовательские заголовки HTTP и tlsSettings игнорируются полностью.

Конфигурация

  1. Подготовьте рабочую конфигурацию WebSocket или SplitHTTP. Помните о вышеуказанных ограничениях.
  2. Запустите Xray с помощью XRAY_BROWSER_DIALER=127.0.0.1:8080. В Windows это можно сделать как set XRAY_BROWSER_DIALER=..., а затем запустить ядро из консоли, в Linux ядро можно запустить как XRAY_BROWSER_DIALER=127.0.0.1:8080 ./xray -c config.json.
  3. Откройте браузер, который не туннелирован через прокси, или измените маршрутизацию конфигурации таким образом, чтобы домен сервера Xray переходил к freedom непосредственно с клиента. Перейдите по адресу localhost:8080 и откройте консоль разработчика с помощью F12, чтобы отслеживать ошибки.
  4. Для повышения производительности и обхода произвольных ограничений на подключение, применяемых браузером, рекомендуется включить Mux.Cool.

Внутренняя работа

  • Xray прослушивает http://127.0.0.1:8080, а браузер обращается к http://127.0.0.1:8080, чтобы загрузить JS на веб-страницу.
  • JS активно устанавливает соединение WebSocket с http://127.0.0.1:8080. Xray будет использовать это соединение для отправки инструкций, но пока оно попадает в пул соединений (реализованный как канал Go).
  • Когда необходимо установить соединение, Xray получает доступное соединение из пула и отправляет имя протокола, целевой URL-адрес и необязательные ранние данные.
  • Как только JS успешно подключается к цели, он сообщает об этом Xray и продолжает использовать это соединение для двунаправленной пересылки данных.
  • После закрытия соединения с сервером соединение с localhost также закрывается, но JS гарантирует, что всегда доступно как минимум одно незанятое соединение.

WebSocket

v1.4.1+

В соответствии с потребностями браузера механизм ранних данных был скорректирован следующим образом:

  • Заголовок ответа сервера будет содержать запрошенный Sec-WebSocket-Protocol, который также изначально obfuscates the length characteristic of the WSS handshake response.
  • Кодировка, используемая для ранних данных для браузеров, - это base64.RawURLEncoding вместо StdEncoding, и сервер сделал ее совместимой.
  • Кроме того, в связи с Xray-core#375Открыть в новой вкладке рекомендациями по ?ed=2048 этот PR также увеличил сервер MaxHeaderBytes на 4096. (Хотя, похоже, это будет работать и без модификации.)

SplitHTTP

v1.8.19+

SplitHTTP поддерживает QUIC, но также может использоваться собственный стек QUIC браузера. В Chrome это можно сделать через chrome://flags, в других браузерах он может быть уже включен или для него может потребоваться другой флаг.

В общем, tlsSettings полностью игнорируются при использовании Browser Dialer. Xray никак не контролирует, какую версию HTTP выбирает браузер.

- + diff --git a/ru/config/features/env.html b/ru/config/features/env.html index 479188cbbe..5a4a4265d8 100644 --- a/ru/config/features/env.html +++ b/ru/config/features/env.html @@ -24,14 +24,14 @@ Переменные среды | Project X - - + +

Переменные среды

Xray предоставляет следующие переменные среды для изменения некоторых базовых настроек Xray.

Путь к файлам ресурсов

  • Название: xray.location.asset или XRAY_LOCATION_ASSET.
  • Значение по умолчанию: Определенный каталог FHSОткрыть в новой вкладке или тот же каталог, что и файл Xray.

Эта переменная среды указывает расположение папки, которая должна содержать файлы geoip.dat и geosite.dat. Если значение переменной не указано, программа будет искать файлы ресурсов в следующем порядке:

./
 /usr/local/share/xray
 /usr/share/xray
 

Расположение файла конфигурации

  • Название: xray.location.config или XRAY_LOCATION_CONFIG.
  • Значение по умолчанию: Тот же каталог, что и файл Xray.

Эта переменная среды указывает расположение папки, которая должна содержать файл config.json.

Каталог с несколькими конфигурациями

  • Название: xray.location.confdir или XRAY_LOCATION_CONFDIR.
  • Значение по умолчанию: "".

Файлы .json в этом каталоге будут читаться в порядке имен файлов как параметры конфигурации.

- + diff --git a/ru/config/features/fallback.html b/ru/config/features/fallback.html index 2030bcb2eb..530be97bf9 100644 --- a/ru/config/features/fallback.html +++ b/ru/config/features/fallback.html @@ -24,8 +24,8 @@ Fallback | Project X - - + +

Fallback

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

Fallback обеспечивает Xray высокой степенью защиты от активного зондирования и имеет уникальный механизм резервирования первого пакета.

Fallback также может разделять трафик различных типов по пути, что позволяет совместно использовать один порт для нескольких служб.

В настоящее время вы можете использовать функцию fallback при использовании протоколов VLESS или Trojan, настроив fallbacks, и создавать очень разнообразные комбинации.

Настройка fallbacks

  "fallbacks": [
@@ -41,6 +41,6 @@
   "xver": 0
 }
 

fallbacks - это массив, здесь приведено описание конфигурации одного из его элементов.

Элемент fallbacks является необязательным и может использоваться только для комбинации транспорта TCP+TLS.

  • Если этот элемент имеет дочерние элементы, в Inbound TLS необходимо установить "alpn":["http/1.1"].

Обычно сначала нужно настроить набор резервных путей по умолчанию с опущенными или пустыми alpn и path, а затем настроить другие разделения по мере необходимости.

VLESS будет перенаправлять трафик с длиной первого пакета после дешифрования TLS менее 18 байт, неверной версией протокола или неудачной аутентификацией на адрес, указанный в dest.

Для других комбинаций транспорта необходимо удалить элемент fallbacks или все его дочерние элементы. В этом случае Fallback не будет включен, VLESS будет ждать считывания необходимой длины, а в случае неверной версии протокола или сбоя аутентификации соединение будет немедленно разорвано.

name: string

Попытка сопоставить TLS SNI (указание имени сервера), любое значение или пустая строка, по умолчанию "".

alpn: string

Попытка сопоставить результат согласования TLS ALPN, любое значение или пустая строка, по умолчанию "".

При необходимости VLESS попытается прочитать результат согласования TLS ALPN, и в случае успеха выведет в лог realAlpn =. Назначение: решает проблему несовместимости службы h2c Nginx с http/1.1, для которой в Nginx требуется написать две строки listen, по одной для 1.1 и h2c. Примечание: если в fallbacks alpn присутствует "h2", в Inbound TLS необходимо установить "alpn":["h2","http/1.1"] для поддержки доступа h2.

Подсказка

alpn, установленный в Fallback, соответствует фактически согласованному ALPN, а alpn, установленный в Inbound TLS, - это список дополнительных ALPN во время рукопожатия. Это разные вещи.

path: string

Попытка сопоставить HTTP-путь первого пакета, любое значение или пустая строка, по умолчанию пустая строка, если не пустая, то должна начинаться с /, h2c не поддерживается.

Интеллектуальность: при необходимости VLESS попытается просмотреть PATH (не более 55 байт; самый быстрый алгоритм, не выполняет полный разбор HTTP) и в случае успеха выведет в INFO-лог realPath =. Назначение: разделение трафика WebSocket или HTTP-маскировки для других входящих соединений, без лишней обработки, чистая переадресация трафика, теоретически более высокая производительность, чем у Nginx.

Примечание: входящее соединение, в котором находится fallbacks, должно быть TCP+TLS, это необходимо для разделения трафика на другие входящие соединения WS, входящие соединения, на которые разделяется трафик, не нуждаются в настройке TLS.

dest: string | number

Определяет, куда перенаправляется TCP-трафик после дешифрования TLS, в настоящее время поддерживаются два типа адресов (это поле является обязательным, иначе запуск невозможен):

  1. TCP, формат "addr:port", где addr поддерживает IPv4, доменное имя, IPv6, если указано доменное имя, TCP-соединение будет установлено напрямую (без использования встроенного DNS).
  2. Unix domain socket, формат - абсолютный путь, например, "/dev/shm/domain.socket", в начале можно добавить @ для обозначения abstractОткрыть в новой вкладке, @@ - для обозначения abstract с заполнением.

Если указан только порт, можно использовать число или строку, например, 80, "80", обычно указывает на службу http в открытом виде (addr будет дополнен до "127.0.0.1").

xver: number

Отправка PROXY protocolОткрыть в новой вкладке, специально для передачи реального исходного IP-адреса и порта запроса, заполняется версией 1 или 2, по умолчанию 0, то есть не отправляется. При необходимости рекомендуется указать 1.

В настоящее время при указании 1 или 2 функциональность полностью идентична, отличается только структура, причем первая может быть распечатана, а вторая - двоичная. Входящие TCP- и WS-соединения Xray уже поддерживают прием PROXY protocol.

Внимание

Если вы настраиваете Nginx на прием PROXY protocolОткрыть в новой вкладке, помимо установки proxy_protocol, необходимо также установить set_real_ip_from, иначе могут возникнуть проблемы.

Дополнительные замечания

  • Будет выполнено сопоставление с наиболее точным дочерним элементом, порядок дочерних элементов не имеет значения. Если настроено несколько дочерних элементов с одинаковыми alpn и path, будет использоваться последний.
  • Резервирование и разделение трафика - это переадресация на уровне TCP после дешифрования, а не на уровне HTTP, проверка PATH первого пакета выполняется только при необходимости.
  • Вы можете просмотреть больше советов и рекомендаций по использованию Fallbacks:

Теория Fallbacks В разработке

- + diff --git a/ru/config/features/multiple.html b/ru/config/features/multiple.html index 21ebe3bf3e..4164a19fb5 100644 --- a/ru/config/features/multiple.html +++ b/ru/config/features/multiple.html @@ -24,8 +24,8 @@ Настройка с помощью нескольких файлов | Project X - - + +

Настройка с помощью нескольких файлов

Программа Xray поддерживает использование нескольких файлов конфигурации.

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

Эта функция в основном предназначена для обогащения экосистемы Xray. Например, для клиентских GUI обычно реализуются только фиксированные функции, такие как выбор узла, и слишком сложные конфигурации трудно реализовать графически. Можно оставить только один пользовательский каталог конфигурации confdir для настройки сложных функций. Для сценариев развертывания сервера достаточно добавить файлы в confdir для настройки различных протоколов.

Запуск с несколькими файлами

Подсказка

В информации о запуске будет указан каждый считываемый файл конфигурации. Убедитесь, что порядок считывания соответствует ожидаемому. Вы можете контролировать порядок, добавляя префиксы с номерами к именам файлов. Например, 01_имя_файла, 02_имя_файла, чем больше число, тем позже файл будет обработан.

$ xray run -confdir /etc/xray/confs
@@ -103,6 +103,6 @@
   ]
 }
 

Подсказка

Вы можете использовать команду xray run -confdir=./confs -dump для просмотра объединенной конфигурации. Однако, поскольку ядро использует формат данных protobuf, формат вывода конфигурации для параметра -dump будет отличаться.

- + diff --git a/ru/config/features/xtls.html b/ru/config/features/xtls.html index e009bfa8f5..06622a4cda 100644 --- a/ru/config/features/xtls.html +++ b/ru/config/features/xtls.html @@ -24,11 +24,11 @@ Глубокое погружение в XTLS | Project X - - + +

Глубокое погружение в XTLS

XTLS - это оригинальная технология Xray, которая является ключевым фактором высокой производительности Xray.

WIP
- + diff --git a/ru/config/inbound.html b/ru/config/inbound.html index 46018f7e40..2cd9fa284f 100644 --- a/ru/config/inbound.html +++ b/ru/config/inbound.html @@ -24,8 +24,8 @@ Входящие подключения | Project X - - + +

Входящие подключения

Входящие подключения используются для приема данных. Доступные протоколы см. в разделе Входящие протоколы.

InboundObject

InboundObject соответствует дочернему элементу поля inbounds в конфигурационном файле.

{
@@ -68,6 +68,6 @@
   "concurrency": 3
 }
 

strategy: "always" | "random"

Стратегия выделения портов.

  • "always" - всегда выделять все указанные порты.
    Xray будет прослушивать все порты, указанные в port.
  • "random" - случайным образом открывать порты.
    Каждые refresh минут Xray будет случайным образом выбирать concurrency портов из диапазона, указанного в port, и прослушивать их.

refresh: number

Интервал обновления случайных портов в минутах.
Минимальное значение - 2, рекомендуемое значение - 5.
Этот параметр действителен только при strategy = "random".

concurrency: number

Количество случайных портов.
Минимальное значение - 1, максимальное значение - треть от диапазона портов, указанного в port.
Рекомендуемое значение - 3.

- + diff --git a/ru/config/inbounds/dokodemo.html b/ru/config/inbounds/dokodemo.html index 5999914648..29c30254b5 100644 --- a/ru/config/inbounds/dokodemo.html +++ b/ru/config/inbounds/dokodemo.html @@ -24,8 +24,8 @@ Dokodemo-Door | Project X - - + +

Dokodemo-Door

Dokodemo door может прослушивать локальный порт и отправлять все данные, поступающие на этот порт, на порт указанного сервера, тем самым реализуя перенаправление портов.

InboundConfigurationObject

{
@@ -51,6 +51,6 @@
   "tag": "mc"
 }
 

В этом случае ядро будет прослушивать 127.0.0.1:25565 и перенаправлять трафик через исходящее соединение по умолчанию на mc.hypixel.net:25565 (сервер MC). При подключении клиента Minecraft к 127.0.0.1:25565 будет осуществлено подключение к серверу Hypixel через прокси.

Пример настройки прозрачного прокси

Эту часть см. в разделе Руководство по настройке прозрачного прокси (TProxy).

- + diff --git a/ru/config/inbounds/http.html b/ru/config/inbounds/http.html index d6bdb6dd3c..f5f8c6f7d5 100644 --- a/ru/config/inbounds/http.html +++ b/ru/config/inbounds/http.html @@ -24,8 +24,8 @@ HTTP | Project X - - + +

HTTP

Протокол HTTP.

Предупреждение

Протокол HTTP не обеспечивает шифрования передачи данных, поэтому он не подходит для передачи данных через общедоступные сети и более уязвим для использования в качестве ботнета.

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

СОВЕТ 1

http proxy может проксировать только протокол tcp, протоколы семейства udp не поддерживаются.

СОВЕТ 2

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

  • export http_proxy=http://127.0.0.1:8080/ (замените адрес на адрес вашего настроенного входящего HTTP-прокси)
  • export https_proxy=$http_proxy

InboundConfigurationObject

{
@@ -44,6 +44,6 @@
   "pass": "my-password"
 }
 

user: string

Имя пользователя, тип данных: строка. Обязательный параметр.

pass: string

Пароль, тип данных: строка. Обязательный параметр.

- + diff --git a/ru/config/inbounds/shadowsocks.html b/ru/config/inbounds/shadowsocks.html index ab7c1feb91..b89c9976ec 100644 --- a/ru/config/inbounds/shadowsocks.html +++ b/ru/config/inbounds/shadowsocks.html @@ -24,8 +24,8 @@ Shadowsocks | Project X - - + +

Shadowsocks

Протокол ShadowsocksОткрыть в новой вкладке, совместимый с большинством других реализаций.

Текущая совместимость:

  • Поддерживает пересылку пакетов TCP и UDP, при этом UDP можно выборочно отключить;
  • Рекомендуемые методы шифрования:
    • 2022-blake3-aes-128-gcm
    • 2022-blake3-aes-256-gcm
    • 2022-blake3-chacha20-poly1305
  • Другие методы шифрования:
    • aes-256-gcm
    • aes-128-gcm
    • chacha20-poly1305 или chacha20-ietf-poly1305
    • xchacha20-poly1305 или xchacha20-ietf-poly1305
    • none или plain

Новый формат протокола Shadowsocks 2022 повышает производительность и обеспечивает полную защиту от повторов, решая следующие проблемы безопасности старого протокола:

Предупреждение

При использовании метода шифрования "none" трафик передается в открытом виде. В целях безопасности не используйте этот метод в общедоступных сетях.

InboundConfigurationObject

{
@@ -50,6 +50,6 @@
   "email": "love@xray.com"
 }
 

Наличие этой опции означает включение многопользовательского режима.

Если method в InboundConfigurationObject не является опцией SS2022, можно указать "method" для каждого пользователя. ("method" также поддерживает только опции, не относящиеся к SS2022) и "password" (при этом "password", установленный в InboundConfigurationObject, будет игнорироваться).

Если method в InboundConfigurationObject является опцией SS2022, то из соображений безопасности больше не поддерживается установка "method" для отдельных пользователей, используется единый "method", указанный в InboundConfigurationObject.

Обратите внимание, что SS2022, в отличие от старого SS, не игнорирует "password" верхнего уровня, правильный способ записи пароля клиента: ServerPassword:UserPassword. Например: "password": "114514:1919810"

Остальные опции имеют то же значение, что и в InboundConfigurationObject.

- + diff --git a/ru/config/inbounds/socks.html b/ru/config/inbounds/socks.html index d0352f13d6..64516c39ac 100644 --- a/ru/config/inbounds/socks.html +++ b/ru/config/inbounds/socks.html @@ -24,8 +24,8 @@ Socks | Project X - - + +

Socks

Стандартная реализация протокола Socks, совместимая с Socks 4Открыть в новой вкладке, Socks 4aОткрыть в новой вкладке и Socks 5.

Предупреждение

Протокол Socks не обеспечивает шифрование передачи данных, поэтому он не подходит для передачи данных через общедоступные сети.

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

InboundConfigurationObject

{
@@ -45,6 +45,6 @@
   "pass": "my-password"
 }
 

user: string

Имя пользователя, тип данных: строка. Обязательный параметр.

pass: string

Пароль, тип данных: строка. Обязательный параметр.

- + diff --git a/ru/config/inbounds/trojan.html b/ru/config/inbounds/trojan.html index 7509ce7a77..b2c5469e65 100644 --- a/ru/config/inbounds/trojan.html +++ b/ru/config/inbounds/trojan.html @@ -24,8 +24,8 @@ Trojan | Project X - - + +

Trojan

Протокол TrojanОткрыть в новой вкладке.

Предупреждение

Trojan предназначен для работы в правильно настроенном зашифрованном TLS-туннеле.

InboundConfigurationObject

{
@@ -48,6 +48,6 @@
   "level": 0
 }
 

password: string

Обязательный параметр, любая строка.

email: string

Адрес электронной почты, необязательный параметр, используется для идентификации пользователя.

Предупреждение

Если существует несколько объектов ClientObject, убедитесь, что адреса электронной почты не дублируются.

level: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение userLevel соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

- + diff --git a/ru/config/inbounds/vless.html b/ru/config/inbounds/vless.html index d463d96ea9..d6420634a2 100644 --- a/ru/config/inbounds/vless.html +++ b/ru/config/inbounds/vless.html @@ -24,8 +24,8 @@ VLESS | Project X - - + +

Warning

This translation was modified on 27 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

VLESS

Предупреждение

VLESS не предусматривает встроенного шифрования, поэтому обязательным условием для его использования является наличие надежного канала, такого как TLS или REALITY.

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

В отличие от VMess, VLESS не зависит от системного времени, аутентификация также осуществляется с помощью UUID.

InboundConfigurationObject

{
@@ -51,6 +51,6 @@
   "flow": "xtls-rprx-vision"
 }
 

id: string

Идентификатор пользователя VLESS, может быть любой строкой длиной менее 30 байт или допустимым UUID. Пользовательская строка и ее UUID-отображение эквивалентны, это означает, что вы можете использовать следующие способы записи id в файле конфигурации для идентификации одного и того же пользователя:

  • Напишите "id": "Я люблю арбуз учителя 1314",
  • Или напишите "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (этот UUID является UUID-отображением строки "Я люблю арбуз учителя 1314")

Стандарт сопоставления описан в VLESS UUID Mapping Standard: Mapping Custom Strings to a UUIDv5Открыть в новой вкладке.

Вы можете использовать команду xray uuid -i "Пользовательская строка" для генерации UUID, соответствующего пользовательской строке.

Вы также можете использовать команду xray uuid для генерации случайного UUID.

level: number

Уровень пользователя, для подключения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение level соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

email: string

Адрес электронной почты пользователя, используется для разделения трафика разных пользователей (отображается в журналах, статистике).

flow: string

Режим управления потоком, используется для выбора алгоритма XTLS.

В настоящее время для входящего протокола доступны следующие режимы управления потоком:

  • Отсутствует flow или пустая строка: используется обычный TLS-прокси
  • xtls-rprx-vision: используется новый режим XTLS, включает случайное заполнение внутреннего рукопожатия

Кроме того, в настоящее время XTLS поддерживает только TCP+TLS/Reality.

- + diff --git a/ru/config/inbounds/vmess.html b/ru/config/inbounds/vmess.html index 68c0353207..1f5bdedf89 100644 --- a/ru/config/inbounds/vmess.html +++ b/ru/config/inbounds/vmess.html @@ -24,8 +24,8 @@ VMess | Project X - - + +

VMess

VMess - это зашифрованный транспортный протокол, который обычно используется в качестве моста между клиентами и серверами Xray.

Предупреждение

VMess полагается на системное время. Убедитесь, что системное время UTC, используемое Xray, находится в пределах 120 секунд от фактического времени, независимо от часового пояса. В системах Linux вы можете установить службу ntp для автоматической синхронизации системного времени.

InboundConfigurationObject

{
@@ -55,6 +55,6 @@
   "level": 0
 }
 

level: number

Уровень пользователя, который будет использоваться соединением для определения соответствующей локальной политики.

Значение level соответствует значению level в policy. Если не указано, используется значение по умолчанию - 0.

- + diff --git a/ru/config/index.html b/ru/config/index.html index 55837589be..26e0ba82bf 100644 --- a/ru/config/index.html +++ b/ru/config/index.html @@ -24,8 +24,8 @@ Конфигурационный файл | Project X - - + +

В этом разделе вы узнаете все детали настройки Xray. Овладев этими знаниями, вы сможете раскрыть весь потенциал Xray.

Обзор

Конфигурационный файл Xray имеет формат JSON. Формат конфигурации одинаков для клиента и сервера, но фактическое содержимое отличается.
Он выглядит следующим образом:

{
@@ -45,6 +45,6 @@
   "burstObservatory": {}
 }
 

Внимание

Если вы новичок в Xray, вы можете сначала прочитать раздел Настройка и запуск в кратком руководстве, чтобы узнать об основных способах настройки, а затем прочитать этот раздел, чтобы узнать обо всех способах настройки Xray.

Основные модули конфигурации

log: LogObject

Настройка журнала, управляющая способом вывода журналов Xray.

api: ApiObject

Предоставляет API-интерфейсы для удаленного вызова.

dns: DnsObject

Встроенный DNS-сервер. Если этот параметр не настроен, используются системные настройки DNS.

routing: RoutingObject

Функция маршрутизации. Позволяет настроить правила для разделения трафика и отправки его через разные исходящие подключения.

policy: PolicyObject

Локальная политика, позволяющая настроить разные уровни пользователей и соответствующие им политики.

inbounds: [ InboundObject ]

Массив, каждый элемент которого представляет собой конфигурацию входящего подключения.

outbounds: [ OutboundObject ]

Массив, каждый элемент которого представляет собой конфигурацию исходящего подключения.

transport: TransportObject

Используется для настройки способа, которым Xray устанавливает и использует сетевые подключения к другим серверам.

stats: StatsObject

Используется для настройки сбора статистики трафика.

reverse: ReverseObject

Обратный прокси. Позволяет перенаправлять трафик с сервера на клиент, т.е. перенаправлять трафик в обратном направлении.

fakedns: FakeDnsObject

Настройка FakeDNS. Может использоваться совместно с прозрачным проксированием для получения фактических доменных имен.

metrics: metricsObject

Настройка метрик. Более прямой (и, надеемся, лучший) способ экспорта статистики.

observatory: ObservatoryObject

Мониторинг фоновых подключений. Обнаружение состояния подключения исходящего прокси.

burstObservatory: BurstObservatoryObject

Мониторинг параллельных подключений. Обнаружение состояния подключения исходящего прокси.

- + diff --git a/ru/config/log.html b/ru/config/log.html index 91cc3d11c7..a64b41c08a 100644 --- a/ru/config/log.html +++ b/ru/config/log.html @@ -24,8 +24,8 @@ Настройка журнала | Project X - - + +

Настройка журнала

Настройка журнала управляет тем, как Xray выводит журналы.

Xray имеет два типа журналов: журнал доступа и журнал ошибок.
Вы можете настроить способ вывода каждого типа журнала отдельно.

LogObject

LogObject соответствует полю log в конфигурационном файле.

{
@@ -37,6 +37,6 @@
   }
 }
 

access: string

Путь к файлу журнала доступа.
Значение должно быть допустимым путем к файлу, например "/var/log/Xray/access.log" (Linux) или "C:\\Temp\\Xray\\_access.log" (Windows).
Если этот параметр не указан или имеет пустое значение, журнал выводится в stdout.

  • Специальное значение none отключает журнал доступа.

error: string

Путь к файлу журнала ошибок.
Значение должно быть допустимым путем к файлу, например "/var/log/Xray/error.log" (Linux) или "C:\\Temp\\Xray\\_error.log" (Windows).
Если этот параметр не указан или имеет пустое значение, журнал выводится в stdout.

  • Специальное значение none отключает журнал ошибок.

loglevel: "debug" | "info" | "warning" | "error" | "none"

Уровень журнала ошибок, указывающий, какую информацию следует записывать в журнал ошибок.
Значение по умолчанию - "warning".

  • "debug": информация, используемая при отладке программы.
    Включает всю информацию уровня "info".
  • "info": информация о состоянии во время выполнения и т.д., не влияющая на нормальную работу.
    Включает всю информацию уровня "warning".
  • "warning": информация, выводимая при возникновении проблем, не влияющих на нормальную работу, но которые могут повлиять на работу пользователя.
    Включает всю информацию уровня "error".
  • "error": Xray столкнулся с проблемой, которая не позволяет ему работать нормально, и ее необходимо немедленно решить.
  • "none": не записывать ничего.

dnsLog: bool

Включить ведение журнала DNS-запросов, например: DOH//doh.server got answer: domain.com -> [ip1, ip2] 2.333ms.

- + diff --git a/ru/config/metrics.html b/ru/config/metrics.html index 0f4f7346c9..25190188e4 100644 --- a/ru/config/metrics.html +++ b/ru/config/metrics.html @@ -24,8 +24,8 @@ Метрики | Project X - - + +

Метрики

Более простой (и, надеюсь, лучший) способ экспорта статистики.

Связанные настройки

Можно добавить входящее подключение metrics в раздел inbounds:

    "inbounds": [
@@ -242,6 +242,6 @@
            id: udp
            expvar_type: int
 

И вы получите красивый график, подобный этому:

160428235-2988bf69-5d6c-41ec-8267-1bd512508aa8

Дополнительно

Возможно, лучше использовать пустой объект stats в конфигурационном файле, чем добавлять metrics?

Изменение: удалены настройки, связанные с Prometheus, и добавлено использование expvars.

- + diff --git a/ru/config/observatory.html b/ru/config/observatory.html index 5fb585bfe7..e1e9bf392e 100644 --- a/ru/config/observatory.html +++ b/ru/config/observatory.html @@ -24,8 +24,8 @@ Мониторинг подключений | Project X - - + +

Мониторинг подключений

Компонент мониторинга подключений использует HTTP-пинги для проверки состояния подключения исходящих прокси. Результаты мониторинга могут использоваться другими компонентами, например, балансировщиком нагрузки.
В настоящее время доступны два режима: observatory (фоновый мониторинг подключений) и burstObservatory (мониторинг параллельных подключений).
Выберите один из них в соответствии с вашими потребностями.

ObservatoryObject

{
@@ -50,6 +50,6 @@
   "timeout": "30s"
 }
 

destination: string

URL-адрес, используемый для проверки состояния подключения исходящего прокси.
Этот URL-адрес должен возвращать код состояния HTTP 204.

connectivity: string

URL-адрес, используемый для проверки подключения к локальной сети.
Пустая строка означает, что проверка подключения к локальной сети не выполняется.

interval: string

Проверить все соответствующие исходящие прокси в течение указанного времени, отправляя sampling + 1 запросов на каждый прокси.
Формат времени: число + единица измерения, например "10s", "2h45m".
Поддерживаемые единицы измерения: ns, us, ms, s, m, h (наносекунды, микросекунды, миллисекунды, секунды, минуты, часы).

sampling: number

Количество последних результатов проверок, которые нужно сохранить.

timeout: string

Время ожидания ответа при проверке.
Формат такой же, как и у interval.

- + diff --git a/ru/config/outbound.html b/ru/config/outbound.html index ada46095ce..f6e6c526d5 100644 --- a/ru/config/outbound.html +++ b/ru/config/outbound.html @@ -24,8 +24,8 @@ Исходящие подключения | Project X - - + +

Warning

This translation was modified on 16 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

Исходящие подключения

Исходящие подключения используются для отправки данных. Доступные протоколы см. в разделе Исходящие протоколы.

OutboundObject

OutboundObject соответствует дочернему элементу поля outbounds в конфигурационном файле.

Подсказка

Первый элемент в списке используется как основной исходящий узел.
Если совпадений с правилами маршрутизации нет или ни одно правило не сработало, трафик отправляется через основной исходящий узел.

{
@@ -53,6 +53,6 @@
   "xudpProxyUDP443": "reject"
 }
 

enabled: true | false

Включить пересылку запросов через Mux.
Значение по умолчанию - false.

concurrency: number

Максимальное количество одновременных подключений.
Минимальное значение - 1, максимальное значение - 1024.
Если этот параметр опущен или равен 0, используется значение 8.

Это значение определяет максимальное количество дочерних соединений, которые могут быть мультиплексированы по одному TCP-соединению.
Например, если concurrency равен 8, то при отправке 8 TCP-запросов клиентом Xray создаст только одно фактическое TCP-соединение, и все 8 запросов клиента будут передаваться по этому соединению.

Подсказка

Если указать отрицательное значение, например -1, трафик TCP не будет проходить через Mux.

xudpConcurrency: number

Использовать новый агрегированный туннель XUDP (т.е. другое Mux-соединение) для проксирования UDP-трафика.
Укажите максимальное количество одновременных дочерних UoT-подключений.
Минимальное значение - 1, максимальное значение - 1024.
Если этот параметр опущен или равен 0, UDP-трафик будет использовать тот же путь, что и TCP-трафик (традиционное поведение).

Подсказка

Если указать отрицательное значение, например -1, трафик UDP не будет проходить через Mux.
Будет использоваться исходный способ передачи UDP-трафика для данного протокола прокси.
Например, Shadowsocks будет использовать нативный UDP, а VLESS будет использовать UoT.

xudpProxyUDP443: string

Управление обработкой проксируемого трафика UDP/443 (QUIC) в Mux:

  • По умолчанию reject - отклонять трафик (обычно браузеры автоматически переключаются на TCP HTTP/2).
  • allow - разрешить трафик через Mux.
  • skip - не использовать Mux для трафика UDP/443.
    Будет использоваться исходный способ передачи UDP-трафика для данного протокола прокси.
    Например, Shadowsocks будет использовать нативный UDP, а VLESS будет использовать UoT.
- + diff --git a/ru/config/outbounds/blackhole.html b/ru/config/outbounds/blackhole.html index e65564c896..b27cefe4e2 100644 --- a/ru/config/outbounds/blackhole.html +++ b/ru/config/outbounds/blackhole.html @@ -24,8 +24,8 @@ Blackhole | Project X - - + +

Blackhole

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

OutboundConfigurationObject

{
@@ -37,6 +37,6 @@
   "type": "none"
 }
 

type: "http" | "none"

Если type равен "none" (значение по умолчанию), Blackhole просто закроет соединение.

Если type равен "http", Blackhole вернет простой пакет HTTP 403, а затем закроет соединение.

- + diff --git a/ru/config/outbounds/dns.html b/ru/config/outbounds/dns.html index 0e6e7139d1..2404947b53 100644 --- a/ru/config/outbounds/dns.html +++ b/ru/config/outbounds/dns.html @@ -24,8 +24,8 @@ DNS | Project X - - + +

DNS

DNS — это исходящий протокол, который в основном используется для перехвата и пересылки DNS-запросов.

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

При обработке DNS-запросов этот исходящий протокол перенаправляет IP-запросы (то есть A и AAAA) на встроенный DNS-сервер. Другие типы запросов будут перенаправлены на их исходные адреса назначения.

OutboundConfigurationObject

{
@@ -35,6 +35,6 @@
   "nonIPQuery": "drop"
 }
 

network: "tcp" | "udp"

Изменяет транспортный протокол DNS-трафика, возможные значения: "tcp" и "udp". Если не указан, сохраняется исходный транспортный протокол.

address: address

Изменяет адрес DNS-сервера. Если не указан, сохраняется адрес, указанный в источнике.

port: number

Изменяет порт DNS-сервера. Если не указан, сохраняется порт, указанный в источнике.

nonIPQuery: string

Управляет не IP-запросами (не A и AAAA), "drop" - отбрасывать или "skip" - не обрабатывать встроенным DNS-сервером, а пересылать на целевой сервер. Значение по умолчанию: "drop".

Пример настройки DNS WIP

- + diff --git a/ru/config/outbounds/freedom.html b/ru/config/outbounds/freedom.html index f3a01d344e..217e40e93b 100644 --- a/ru/config/outbounds/freedom.html +++ b/ru/config/outbounds/freedom.html @@ -24,8 +24,8 @@ Freedom | Project X - - + +

Warning

This translation was modified on 16 July 2024 and an updated version (10 August 2024) is available on the source page. View the original page

Freedom

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

OutboundConfigurationObject

{
@@ -40,6 +40,6 @@
   "proxyProtocol": 0
 }
 

domainStrategy: "AsIs"
"UseIP" | "UseIPv6v4" | "UseIPv6" | "UseIPv4v6" | "UseIPv4"
"ForceIP" | "ForceIPv6v4" | "ForceIPv6" | "ForceIPv4v6" | "ForceIPv4"

Значение по умолчанию: "AsIs".

Если целевой адрес является доменным именем, настройте соответствующее значение для режима работы Freedom:

  • При использовании "AsIs" Xray будет напрямую использовать системный стек для установления соединения, приоритет и выбор IP будут зависеть от системных настроек. По некоторым причинам UDP-соединения, использующие доменные имена, будут игнорировать системные настройки и отдавать приоритет IPv4.
  • При указании других значений для разрешения будет использоваться встроенный DNS-сервер Xray-core. Если DNSObject отсутствует, будет использоваться системный DNS. Если существует несколько подходящих IP-адресов, ядро случайным образом выберет один IP-адрес в качестве целевого.
  • "IPv4" означает попытку подключения только с использованием IPv4, "IPv4v6" - попытку подключения с использованием IPv4 или IPv6, но с предпочтением IPv4 для доменных имен с поддержкой обоих протоколов. (То же самое относится и к v4v6, но в обратном порядке, поэтому здесь не приводится).
  • Если в настройках встроенного DNS указан параметр "queryStrategy", фактическое поведение будет объединено с этой опцией, и будут разрешаться только те типы IP, которые включены в обе опции. Например, "queryStrategy": "UseIPv4" и "domainStrategy": "UseIP" фактически эквивалентны "domainStrategy": "UseIPv4".
  • При использовании опций, начинающихся с "Use", если результаты разрешения не соответствуют требованиям (например, доменное имя имеет только результат разрешения IPv4, но используется UseIPv6), будет выполнен откат к AsIs.
  • При использовании опций, начинающихся с "Force", если результаты разрешения не соответствуют требованиям, соединение не будет установлено.

СОВЕТ 1

При использовании режимов "UseIP" или "ForceIP" и указании sendThrough в конфигурации исходящего соединения Freedom будет автоматически определять необходимый тип IP (IPv4 или IPv6) на основе значения sendThrough. Если вручную указать один тип IP (например, UseIPv4), но он не совпадает с локальным адресом, указанным в sendThrough, соединение не будет установлено.

redirect: адрес_порт

Freedom будет принудительно отправлять все данные на указанный адрес (а не на адрес, указанный во входящем соединении).

Его значение представляет собой строку, например: "127.0.0.1:80", ":1234".

Если адрес не указан, например, ":443", Freedom не будет изменять исходный целевой адрес. Если порт равен 0, например, "xray.com: 0", Freedom не будет изменять исходный порт.

userLevel: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение userLevel соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

fragment: map

Некоторые пары "ключ-значение" для управления исходящей TCP-фрагментацией, которые в некоторых случаях могут обмануть систему цензуры, например, обойти черный список SNI.

"packets": поддерживаются два режима фрагментации: "1-3" - это фрагментация потока TCP, применяемая к первым трем операциям записи данных на стороне клиента. "tlshello" - это фрагментация пакета TLS-рукопожатия.

"length": длина фрагмента пакета (в байтах).

"interval": интервал фрагментации (в миллисекундах).

proxyProtocol: number

Протокол PROXY обычно используется в сочетании с redirect для перенаправления на Nginx или другой сервер, на котором включен протокол PROXY. Если сервер не поддерживает протокол PROXY, соединение будет разорвано.

Значение proxyProtocol - это номер версии протокола PROXY, возможные значения: 1 или 2. Если не указано, используется значение по умолчанию - 0 (протокол не используется).

- + diff --git a/ru/config/outbounds/http.html b/ru/config/outbounds/http.html index 8d5ca0b2ae..32b8db53c3 100644 --- a/ru/config/outbounds/http.html +++ b/ru/config/outbounds/http.html @@ -24,8 +24,8 @@ HTTP | Project X - - + +

HTTP

Протокол HTTP.

Предупреждение

Протокол HTTP не обеспечивает шифрования передачи, что делает его непригодным для передачи по общедоступным сетям и более уязвимым для использования в качестве скомпрометированного хоста для атак.

Подсказка

HTTP может проксировать только протоколы TCP и не может обрабатывать протоколы на основе UDP.

OutboundConfigurationObject

{
@@ -61,6 +61,6 @@
   "pass": "my-password"
 }
 

user: string

Имя пользователя, тип данных: строка. Обязательный параметр.

pass: string

Пароль, тип данных: строка. Обязательный параметр.

- + diff --git a/ru/config/outbounds/loopback.html b/ru/config/outbounds/loopback.html index f12e927154..e0103e43b4 100644 --- a/ru/config/outbounds/loopback.html +++ b/ru/config/outbounds/loopback.html @@ -24,8 +24,8 @@ Loopback | Project X - - + +

Loopback

Loopback - это исходящий протокол данных, который перенаправляет данные, прошедшие через это исходящее соединение, обратно на вход маршрутизатора, что позволяет повторно обработать данные по правилам маршрутизации, не покидая Xray-core.

OutboundConfigurationObject

{
@@ -65,6 +65,6 @@
   }
 }
 
- + diff --git a/ru/config/outbounds/shadowsocks.html b/ru/config/outbounds/shadowsocks.html index 4f2d0182ed..dbd045cfff 100644 --- a/ru/config/outbounds/shadowsocks.html +++ b/ru/config/outbounds/shadowsocks.html @@ -24,8 +24,8 @@ Shadowsocks | Project X - - + +

Shadowsocks

Протокол ShadowsocksОткрыть в новой вкладке, совместимый с большинством других реализаций.

Текущая совместимость:

  • Поддерживает пересылку пакетов TCP и UDP, при этом UDP можно выборочно отключить;
  • Рекомендуемые методы шифрования:
    • 2022-blake3-aes-128-gcm
    • 2022-blake3-aes-256-gcm
    • 2022-blake3-chacha20-poly1305
  • Другие методы шифрования:
    • aes-256-gcm
    • aes-128-gcm
    • chacha20-poly1305 или chacha20-ietf-poly1305
    • xchacha20-poly1305 или xchacha20-ietf-poly1305
    • none или plain

Новый формат протокола Shadowsocks 2022 повышает производительность и обеспечивает полную защиту от повторов, решая следующие проблемы безопасности старого протокола:

Предупреждение

При использовании метода шифрования "none" трафик передается в открытом виде. В целях безопасности не используйте этот метод в общедоступных сетях.

OutboundConfigurationObject

{
@@ -53,6 +53,6 @@
   "level": 0
 }
 

email: string

Адрес электронной почты, необязательный параметр, используется для идентификации пользователя.

address: address

Адрес сервера Shadowsocks, поддерживаются IPv4, IPv6 и доменные имена. Обязательный параметр.

port: number

Порт сервера Shadowsocks. Обязательный параметр.

method: string

Обязательный параметр.

password: string

Обязательный параметр.

uot: bool

Включить udp over tcp.

UoTVersion: number

Версия реализации UDP over TCP.

Допустимые значения: 1, 2.

  • Shadowsocks 2022

В качестве пароля используется предварительный общий ключ, аналогичный ключам WireGuard.

Используйте openssl rand -base64 <длина>, чтобы сгенерировать ключ, совместимый с shadowsocks-rust, длина зависит от используемого метода шифрования.

Метод шифрованияДлина ключа
2022-blake3-aes-128-gcm16
2022-blake3-aes-256-gcm32
2022-blake3-chacha20-poly130532

В реализации Go всегда работают 32-битные ключи.

  • Другие методы шифрования

Любая строка. Длина пароля не ограничена, но короткие пароли более уязвимы для взлома, рекомендуется использовать пароли длиной 16 символов или более.

level: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение level соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

- + diff --git a/ru/config/outbounds/socks.html b/ru/config/outbounds/socks.html index 4bb507e714..4c70468e63 100644 --- a/ru/config/outbounds/socks.html +++ b/ru/config/outbounds/socks.html @@ -24,8 +24,8 @@ Socks | Project X - - + +

Socks

Стандартная реализация протокола Socks, совместимая с Socks 4Открыть в новой вкладке, Socks 4aОткрыть в новой вкладке и Socks 5.

Предупреждение

Протокол Socks не обеспечивает шифрования передачи, поэтому он не подходит для передачи данных через общедоступные сети.

OutboundConfigurationObject

{
@@ -60,6 +60,6 @@
   "level": 0
 }
 

user: string

Имя пользователя, тип данных: строка. Обязательный параметр.

pass: string

Пароль, тип данных: строка. Обязательный параметр.

level: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение userLevel соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

- + diff --git a/ru/config/outbounds/trojan.html b/ru/config/outbounds/trojan.html index 5b69e641c2..5521305258 100644 --- a/ru/config/outbounds/trojan.html +++ b/ru/config/outbounds/trojan.html @@ -24,8 +24,8 @@ Trojan | Project X - - + +

Trojan

Протокол TrojanОткрыть в новой вкладке.

Предупреждение

Trojan предназначен для работы в правильно настроенном зашифрованном TLS-туннеле.

OutboundConfigurationObject

{
@@ -47,6 +47,6 @@
   "level": 0
 }
 

address: address

Адрес сервера, поддерживаются IPv4, IPv6 и доменные имена. Обязательный параметр.

port: number

Порт сервера, обычно тот же, что и порт, прослушиваемый сервером.

password: string

Пароль. Обязательный параметр, любая строка.

email: string

Адрес электронной почты, необязательный параметр, используется для идентификации пользователя.

level: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение level соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

- + diff --git a/ru/config/outbounds/vless.html b/ru/config/outbounds/vless.html index 001bbcee0f..58a3381b39 100644 --- a/ru/config/outbounds/vless.html +++ b/ru/config/outbounds/vless.html @@ -24,8 +24,8 @@ VLESS | Project X - - + +

Warning

This translation was modified on 27 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

VLESS

Предупреждение

VLESS не предусматривает встроенного шифрования, поэтому обязательным условием для его использования является наличие надежного канала, такого как TLS или REALITY.

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

В отличие от VMess, VLESS не зависит от системного времени, аутентификация также осуществляется с помощью UUID.

OutboundConfigurationObject

{
@@ -63,6 +63,6 @@
   "level": 0
 }
 

id: string

Идентификатор пользователя VLESS, может быть любой строкой длиной менее 30 байт или допустимым UUID. Пользовательская строка и ее UUID-отображение эквивалентны, это означает, что вы можете использовать следующие способы записи id в файле конфигурации для идентификации одного и того же пользователя:

  • Напишите "id": "Я люблю арбуз учителя 1314",
  • Или напишите "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (этот UUID является UUID-отображением строки "Я люблю арбуз учителя 1314")

Стандарт сопоставления описан в VLESS UUID Mapping Standard: Mapping Custom Strings to a UUIDv5Открыть в новой вкладке.

Вы можете использовать команду xray uuid -i "Пользовательская строка" для генерации UUID, соответствующего пользовательской строке. Вы также можете использовать команду xray uuid для генерации случайного UUID.

encryption: "none"

Необходимо указать "none", значение не может быть пустым.

Это требование призвано напомнить пользователю об отсутствии шифрования, а также предотвратить ошибки пользователей при вводе имени атрибута или его расположения в будущем, когда будут доступны методы шифрования.

Если значение encryption установлено неверно, при использовании Xray или -test будет выдано сообщение об ошибке.

flow: string

Режим управления потоком, используется для выбора алгоритма XTLS.

В настоящее время для исходящего протокола доступны следующие режимы управления потоком:

  • Отсутствует flow или пустая строка: используется обычный TLS-прокси.
  • xtls-rprx-vision: используется новый режим XTLS, включает случайное заполнение внутреннего рукопожатия, поддерживает uTLS для имитации отпечатка клиента.
  • xtls-rprx-vision-udp443: аналогично xtls-rprx-vision, но разрешает UDP-трафик, направленный на порт 443.

Кроме того, в настоящее время XTLS поддерживает только TCP+TLS/Reality.

О режимах управления потоком xtls-rprx-*-udp443

Когда XTLS в Xray-core включен, трафик, направленный на UDP-порт 443 (обычно QUIC), по умолчанию блокируется, чтобы приложение не использовало QUIC, а использовало TLS, чтобы XTLS действительно вступил в силу. Фактически, QUIC сам по себе не подходит для проксирования, поскольку QUIC имеет встроенные функции TCP, и когда он передается по протоколу VLESS как UDP-трафик, базовый протокол - TCP, что эквивалентно двум уровням TCP.

Если блокировка не требуется, укажите xtls-rprx-*-udp443 на стороне клиента, на стороне сервера оставляйте без изменений.

О режиме Splice

Splice - это функция, предоставляемая ядром Linux, где ядро системы напрямую пересылает TCP, минуя память Xray, что значительно сокращает количество операций копирования данных и переключения контекста процессора.

Ограничения использования режима Splice:

  • Среда Linux.
  • Входящий протокол: Dokodemo door, Socks, HTTP и другие чистые TCP-соединения или другие входящие протоколы, использующие XTLS.
  • Исходящий протокол: VLESS + XTLS.
  • Обратите внимание, что при использовании протокола mKCP Splice не будет использоваться (да, хотя ошибки и нет, на самом деле он не используется).

Кроме того, при использовании Splice отображение скорости сети будет запаздывать, это особенность, а не ошибка.

При использовании режима Vision Splice будет включен автоматически, если выполнены вышеуказанные условия.

level: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение level соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

- + diff --git a/ru/config/outbounds/vmess.html b/ru/config/outbounds/vmess.html index cd71076787..2d1e540f28 100644 --- a/ru/config/outbounds/vmess.html +++ b/ru/config/outbounds/vmess.html @@ -24,8 +24,8 @@ VMess | Project X - - + +

VMess

VMess - это зашифрованный транспортный протокол, который обычно используется в качестве моста между клиентами и серверами Xray.

Предупреждение

VMess полагается на системное время. Убедитесь, что системное время UTC, используемое Xray, находится в пределах 120 секунд от фактического времени, независимо от часового пояса. В системах Linux вы можете установить службу ntp для автоматической синхронизации системного времени.

OutboundConfigurationObject

{
@@ -56,6 +56,6 @@
   "experiments": ""
 }
 

id: string

Идентификатор пользователя VMess, может быть любой строкой длиной менее 30 байт или допустимым UUID.

Пользовательская строка и соответствующий ей UUID эквивалентны, что означает, что вы можете использовать любой из следующих вариантов в файле конфигурации для идентификации одного и того же пользователя:

  • Напишите "id": "Я люблю арбуз учителя 1314",
  • Или напишите "id": "5783a3e7-e373-51cd-8642-c83782b807c5" (этот UUID является сопоставлением строки "Я люблю арбуз учителя 1314")

Стандарт сопоставления описан в VLESS UUID Mapping Standard: Mapping Custom Strings to a UUIDv5Открыть в новой вкладке.

Вы можете использовать команду xray uuid -i "пользовательская строка" для создания UUID, соответствующего пользовательской строке. Вы также можете использовать команду xray uuid для создания случайного UUID.

level: number

Уровень пользователя, для соединения будет использоваться локальная политика, соответствующая этому уровню пользователя.

Значение level соответствует значению level в разделе policy. Если не указано, используется значение по умолчанию - 0.

security: "aes-128-gcm" | "chacha20-poly1305" | "auto" | "none" | "zero"

Метод шифрования. Клиент будет отправлять данные с использованием настроенного метода шифрования, сервер автоматически распознает его, настройка на сервере не требуется.

  • "aes-128-gcm": рекомендуется для использования на ПК.
  • "chacha20-poly1305": рекомендуется для использования на мобильных устройствах.
  • "auto": значение по умолчанию, автоматический выбор (метод шифрования aes-128-gcm, если платформа выполнения - AMD64, ARM64 или s390x, в противном случае - Chacha20-Poly1305).
  • "none": без шифрования.
  • "zero": без шифрования и проверки подлинности сообщений (v1.4.0+).

Подсказка

Рекомендуется использовать метод шифрования "auto", чтобы обеспечить безопасность и совместимость в долгосрочной перспективе.

Метод псевдошифрования "none" будет вычислять и проверять контрольные суммы пакетов данных, но поскольку алгоритм аутентификации не имеет аппаратной поддержки, на некоторых платформах он может быть медленнее, чем "aes-128-gcm" с аппаратным ускорением.

Метод псевдошифрования "zero" не шифрует сообщения и не вычисляет контрольные суммы данных, поэтому теоретически он должен быть быстрее любого другого метода шифрования. Фактическая скорость может зависеть от других факторов.

Не рекомендуется использовать методы псевдошифрования "none" и "zero" без включенного TLS-шифрования и обязательной проверки сертификатов. Если для установления соединения используется CDN или другая промежуточная платформа, расшифровывающая TLS, или сетевая среда, не рекомендуется использовать методы псевдошифрования "none" и "zero".

Независимо от используемого метода шифрования, заголовок пакета VMess защищен шифрованием и аутентификацией.

experiments: string

Включенные экспериментальные функции протокола VMess. (Функции здесь нестабильны и могут быть удалены в любое время). Несколько включенных экспериментов можно разделить символом |, например, "AuthenticatedLength|NoTerminationSignal".

"AuthenticatedLength" включает эксперимент с аутентифицированной длиной пакета. Этот эксперимент необходимо включить одновременно на клиенте и сервере, а также запустить одну и ту же версию программы.

"NoTerminationSignal" включает эксперимент с отключением сигнала завершения соединения. Этот эксперимент может повлиять на стабильность проксируемого соединения.

- + diff --git a/ru/config/outbounds/wireguard.html b/ru/config/outbounds/wireguard.html index e55391a9f7..2e13582821 100644 --- a/ru/config/outbounds/wireguard.html +++ b/ru/config/outbounds/wireguard.html @@ -24,8 +24,8 @@ WireGuard | Project X - - + +

WireGuard

Стандартная реализация протокола WireGuard.

Предупреждение

Протокол WireGuard не предназначен для обхода блокировок, и его использование может привести к блокировке сервера из-за наличия характерных признаков.

OutboundConfigurationObject

{
@@ -77,6 +77,6 @@
   "allowedIPs": ["0.0.0.0/0"] // необязательно, по умолчанию ["0.0.0.0/0", "::/0"]
 }
 

endpoint: address

Адрес сервера, обязательный параметр.

Формат URL:порт, например, engage.cloudflareclient.com:2408
Формат IP:порт, например, 162.159.192.1:2408 или [2606:4700:d0::a29f:c001]:2408.

Подсказка

Если целевой адрес имеет тип URL, для получения IP-адреса будет использоваться встроенный DNS-сервер Xray-core, приоритет IPv4 или IPv6 определяется значением domainStrategy.
Если конфигурация "dns" не указана, для получения IP-адреса будет использоваться системный DNS, а приоритет IPv4 или IPv6 будет определяться системой.

publicKey: string

Публичный ключ сервера, используемый для аутентификации, обязательный параметр.

preSharedKey: string

Дополнительный ключ симметричного шифрования.

keepAlive: int

Интервал отправки keep-alive пакетов в секундах, значение по умолчанию - 0, что означает отсутствие keep-alive.

allowedIPs: string array

WireGuard разрешает трафик только от определенных исходных IP-адресов.

- + diff --git a/ru/config/policy.html b/ru/config/policy.html index 4ed59c5dc6..a22437f611 100644 --- a/ru/config/policy.html +++ b/ru/config/policy.html @@ -24,8 +24,8 @@ Локальные политики | Project X - - + +

Локальные политики

Локальные политики позволяют настраивать различные уровни пользователей и соответствующие им политики, например, настройки тайм-аута подключения.
Каждое соединение, обрабатываемое Xray, соответствует определенному пользователю, и к нему применяются политики в соответствии с уровнем пользователя (level).

PolicyObject

PolicyObject соответствует полю policy в конфигурационном файле.

{
@@ -65,6 +65,6 @@
   "statsOutboundDownlink": false
 }
 

statsInboundUplink: true | false

Если значение равно true, включить учет исходящего трафика для всех входящих подключений.

statsInboundDownlink: true | false

Если значение равно true, включить учет входящего трафика для всех входящих подключений.

statsOutboundUplink: true | false

Если значение равно true, включить учет исходящего трафика для всех исходящих подключений.

statsOutboundDownlink: true | false

Если значение равно true, включить учет входящего трафика для всех исходящих подключений.

- + diff --git a/ru/config/reverse.html b/ru/config/reverse.html index 6023f489e6..ce40be9926 100644 --- a/ru/config/reverse.html +++ b/ru/config/reverse.html @@ -24,8 +24,8 @@ Обратный прокси | Project X - - + +

Обратный прокси

Обратный прокси позволяет перенаправлять трафик с сервера на клиент, то есть перенаправлять трафик в обратном направлении.

Принцип работы обратного прокси:

  • Предположим, что на хосте A запущен веб-сервер, но у этого хоста нет публичного IP-адреса, и к нему нельзя получить доступ из Интернета.
    У нас есть другой хост B с публичным IP-адресом.
    Мы хотим использовать хост B в качестве шлюза и перенаправлять трафик с B на A.
  • На хосте A настроен Xray, называемый bridge, и на хосте B также настроен Xray, называемый portal.
  • bridge устанавливает соединение с portal.
    Целевой адрес этого соединения можно настроить произвольно.
    portal получает два типа соединений: соединения от bridge и соединения от пользователей из Интернета.
    portal автоматически объединяет эти два типа соединений.
    Таким образом, bridge может получать трафик из Интернета.
  • После получения трафика из Интернета bridge перенаправляет его на веб-сервер на хосте A без изменений.
    Конечно, для этого требуется настроить маршрутизацию.
  • bridge выполняет динамическую балансировку нагрузки в зависимости от объема трафика.

Подсказка

Обратный прокси по умолчанию использует Mux.
Не включайте Mux для исходящих подключений, используемых обратным прокси.

Внимание

Функция обратного прокси находится в стадии тестирования и может работать некорректно.

ReverseObject

ReverseObject соответствует полю reverse в конфигурационном файле.

{
@@ -144,6 +144,6 @@
   ]
 }
 
- + diff --git a/ru/config/routing.html b/ru/config/routing.html index 3c0cbaa5c1..8a1e5836ae 100644 --- a/ru/config/routing.html +++ b/ru/config/routing.html @@ -24,8 +24,8 @@ Маршрутизация | Project X - - + +

Warning

This translation was modified on 6 August 2024 and an updated version (10 August 2024) is available on the source page. View the original page

Маршрутизация

Модуль маршрутизации позволяет направлять входящие данные через разные исходящие подключения в соответствии с различными правилами, что позволяет реализовать проксирование по требованию.

Например, распространенным сценарием использования является разделение трафика на внутренний и внешний.
Xray может определять трафик из разных регионов с помощью внутренних механизмов и отправлять его через разные исходящие подключения.

Более подробное описание функции маршрутизации: Введение в маршрутизацию (routing)Открыть в новой вкладке.

RoutingObject

RoutingObject соответствует полю routing в конфигурационном файле.

{
@@ -102,6 +102,6 @@
         }
     ]
 

Предопределенные списки доменов

Этот список включен в каждый установочный пакет Xray и называется geosite.dat.
Этот файл содержит некоторые распространенные доменные имена.
Формат использования: geosite:filename, например geosite:google означает сопоставление с доменными именами, указанными в файле в разделе google, для маршрутизации или фильтрации DNS.

Распространенные доменные имена:

  • category-ads: содержит доменные имена распространенных рекламных сервисов.
  • category-ads-all: содержит доменные имена распространенных рекламных сервисов, а также доменные имена поставщиков рекламы.
  • cn: эквивалентно объединению geolocation-cn и tld-cn.
  • apple: содержит большинство доменных имен Apple.
  • google: содержит большинство доменных имен Google.
  • microsoft: содержит большинство доменных имен Microsoft.
  • facebook: содержит большинство доменных имен Facebook.
  • twitter: содержит большинство доменных имен Twitter.
  • telegram: содержит большинство доменных имен Telegram.
  • geolocation-cn: содержит доменные имена распространенных сайтов, расположенных в Китае.
  • geolocation-!cn: содержит доменные имена распространенных сайтов, расположенных за пределами Китая.
  • tld-cn: содержит доменные имена верхнего уровня, управляемые CNNIC и используемые в Китае, например, домены, оканчивающиеся на .cn, .中国.
  • tld-!cn: содержит доменные имена верхнего уровня, не используемые в Китае, например, домены, оканчивающиеся на .hk (Гонконг), .tw (Тайвань), .jp (Япония), .sg (Сингапур), .us (США), .ca (Канада) и т.д.

Вы также можете просмотреть полный список доменов здесь: Domain list communityОткрыть в новой вкладке.

- + diff --git a/ru/config/stats.html b/ru/config/stats.html index 50858b8203..3754237519 100644 --- a/ru/config/stats.html +++ b/ru/config/stats.html @@ -24,14 +24,14 @@ Статистика | Project X - - + +

Статистика

Используется для настройки сбора статистики трафика Xray.

StatsObject

StatsObject соответствует полю stats в конфигурационном файле.

{
   "stats": {}
 }
 

В настоящее время для статистики не требуется никаких параметров.
Если поле StatsObject присутствует, внутренняя статистика включается.

После включения статистики вам нужно только включить соответствующие параметры в разделе Политики, чтобы начать сбор статистики.

Получение статистики

Вы можете получить статистику с помощью соответствующих команд xray api.

В настоящее время доступна следующая статистика:

  • Данные пользователя

    • user>>>[email]>>>traffic>>>uplink

      Исходящий трафик для определенного пользователя в байтах.

    • user>>>[email]>>>traffic>>>downlink

      Входящий трафик для определенного пользователя в байтах.

Подсказка

Если для пользователя не указан email, статистика для него не будет собираться.

  • Глобальные данные

    • inbound>>>[tag]>>>traffic>>>uplink

      Исходящий трафик для определенного входящего подключения в байтах.

    • inbound>>>[tag]>>>traffic>>>downlink

      Входящий трафик для определенного входящего подключения в байтах.

    • outbound>>>[tag]>>>traffic>>>uplink

      Исходящий трафик для определенного исходящего подключения в байтах.

    • outbound>>>[tag]>>>traffic>>>downlink

      Входящий трафик для определенного исходящего подключения в байтах.

- + diff --git a/ru/config/transport.html b/ru/config/transport.html index c484681de8..7ffebef979 100644 --- a/ru/config/transport.html +++ b/ru/config/transport.html @@ -24,8 +24,8 @@ Транспорт | Project X - - + +

Транспорт

Транспорт (transport) - это способ, которым текущий узел Xray взаимодействует с другими узлами.

Транспорт определяет способ передачи данных. Обычно оба конца сетевого подключения должны использовать одинаковый транспорт.
Например, если один конец использует WebSocket, то другой конец также должен использовать WebSocket, иначе соединение не будет установлено.

Настройка транспорта (transport) состоит из двух частей:

  1. Глобальные настройки (TransportObject) (устарело)
  2. Локальные настройки (StreamSettingsObject).
  • Локальные настройки позволяют указать способ передачи данных для каждого отдельного входящего или исходящего подключения.
  • Обычно клиент и сервер должны использовать одинаковый транспорт для соответствующих входящих и исходящих подключений.
    Если в настройках указан тип транспорта, но не указаны конкретные параметры, будут использованы настройки из глобальной конфигурации.
Глобальные настройки

TransportObject (устарело)

TransportObject соответствует полю transport в конфигурационном файле.

{
@@ -187,6 +187,6 @@
   }
 ]
 

type: ""

Обязательный параметр, тип настройки, в настоящее время доступны int и str.

level: ""

Необязательный параметр, уровень протокола, используемый для указания области действия.
Значение по умолчанию - 6 (TCP).

opt: ""

Название настраиваемого параметра в десятичном формате (в этом примере используется значение TCP_CONGESTION, которое равно 0xd в шестнадцатеричном формате и 13 в десятичном формате).

value: ""

Значение, которое нужно установить.
В этом примере используется значение bbr.

Если type равен int, значение должно быть десятичным числом.

- + diff --git a/ru/config/transports/domainsocket.html b/ru/config/transports/domainsocket.html index 567bf46c62..1096c89b4a 100644 --- a/ru/config/transports/domainsocket.html +++ b/ru/config/transports/domainsocket.html @@ -24,8 +24,8 @@ DomainSocket | Project X - - + +

DomainSocket

Предупреждение

Рекомендуется прописать в разделе listen файла inbounds. В качестве способа передачи можно выбрать TCP, WebSocket, HTTP/2. В будущем использование DomainSocket может быть прекращено.

DomainSocket использует стандартные доменные сокеты Unix для передачи данных.

Его преимущество заключается в использовании встроенного в операционную систему канала передачи, не занимающего сетевой буфер. Теоретически, по сравнению с локальной петлей (local loopback), доменный сокет работает немного быстрее.

В настоящее время он доступен только на платформах, поддерживающих доменные сокеты Unix, таких как Linux и macOS. Недоступно в Windows 10 до сборки 17036.

Если в качестве способа передачи указан DomainSocket, то порт и IP-адрес, настроенные во входящем и исходящем прокси, будут недействительны, и вся передача будет осуществляться через DomainSocket.

DomainSocketObject

DomainSocketObject соответствует элементу dsSettings конфигурации передачи.

{
@@ -34,6 +34,6 @@
   "padding": false
 }
 

path: string

Допустимый путь к файлу.

Предупреждение

Этот файл не должен существовать до запуска Xray.

abstract: true | false

Является ли сокет абстрактным доменным сокетом, значение по умолчанию false.

padding: true | false

Использовать ли padding для абстрактного доменного сокета, значение по умолчанию false.

- + diff --git a/ru/config/transports/grpc.html b/ru/config/transports/grpc.html index 31c19079f6..5c9082f8db 100644 --- a/ru/config/transports/grpc.html +++ b/ru/config/transports/grpc.html @@ -24,8 +24,8 @@ gRPC | Project X - - + +

gRPC

Режим передачи данных, основанный на HTTP/2, полностью соответствует стандарту HTTP/2 и может быть ретранслирован другими HTTP-серверами (такими как Nginx).

gRPC (HTTP/2) имеет встроенное мультиплексирование, не рекомендуется включать mux.cool при использовании gRPC и HTTP/2.

⚠⚠⚠

  • gRPC не поддерживает указание Host. Пожалуйста, укажите правильное доменное имя в адресе исходящего прокси или укажите ServerName в (x)tlsSettings, иначе подключение не будет установлено.
  • gRPC не поддерживает fallback на другие сервисы.
  • Существует риск активного сканирования сервисов gRPC. Рекомендуется использовать обратный прокси-сервер, такой как Caddy или Nginx, для предварительного разделения трафика по пути.

Подсказка

Если вы используете обратный прокси-сервер, такой как Caddy или Nginx, обратите внимание на следующие моменты:

  • Убедитесь, что на обратном прокси-сервере включен HTTP/2.
  • Используйте HTTP/2 или h2c (Caddy), grpc_pass (Nginx) для подключения к Xray.
  • Путь в обычном режиме: /${serviceName}/Tun, в режиме Multi: /${serviceName}/TunMulti.
  • Если необходимо получать IP-адрес клиента, его можно передать через заголовок X-Real-IP, отправленный Caddy / Nginx.

Подсказка

Если вы используете fallback, обратите внимание на следующие моменты:

  • Не рекомендуется использовать fallback на gRPC, так как существует риск активного сканирования.
  • Убедитесь, что h2 находится на первом месте в (x)tlsSettings.alpn, иначе gRPC (HTTP/2) может не завершить TLS-рукопожатие.
  • gRPC не поддерживает маршрутизацию на основе path с помощью Xray.

GRPCObject

GRPCObject соответствует элементу grpcSettings конфигурации передачи.

{
@@ -39,6 +39,6 @@
   "initial_windows_size": 0
 }
 

authority: string

Строка, которая может использоваться как Host для реализации некоторых других целей.

serviceName: string

Строка, указывающая имя сервиса, аналогично пути в HTTP/2. Клиент будет использовать это имя для связи, а сервер будет проверять, совпадает ли имя сервиса.

Подсказка

Когда serviceName начинается с косой черты, можно настроить собственный путь, используя как минимум две косые черты.
Например, если на сервере указано "serviceName": "/my/sample/path1|path2", то на клиенте можно указать "serviceName": "/my/sample/path1" или "/my/sample/path2".

user_agent: string

Подсказка

Необходимо настроить только в outbound (клиент).

Установка пользовательского агента gRPC, может предотвратить блокировку трафика gRPC некоторыми CDN.

multiMode: true | false BETA

true включает multiMode, значение по умолчанию: false.

Это экспериментальная опция, которая может быть удалена в будущем, и ее совместимость между версиями не гарантируется. Этот режим может обеспечить прирост производительности примерно на 20% в тестовой среде, фактическая производительность зависит от скорости передачи.

Подсказка

Необходимо настроить только в outbound (клиент).

idle_timeout: number

Проверка работоспособности выполняется, если в течение определенного периода времени, измеряемого в секундах, не происходит передача данных. Если это значение меньше 10, то в качестве минимального значения будет использоваться 10.

Подсказка

Если не используется обратный прокси-сервер, такой как Caddy или Nginx (обычно не используется), и это значение установлено меньше 60, сервер может отправить непредвиденный кадр h2 GOAWAY, чтобы закрыть существующее соединение.

По умолчанию проверка работоспособности отключена.

Подсказка

Необходимо настроить только в outbound (клиент).

Подсказка

Может решить некоторые проблемы с "обрывом" соединения.

health_check_timeout: number

Время ожидания ответа проверки работоспособности в секундах. Если в течение этого времени проверка работоспособности не будет завершена и по-прежнему не будет передачи данных, проверка работоспособности будет считаться неудачной. Значение по умолчанию: 20.

Подсказка

Настройка требуется только на стороне исходящего соединения (клиента).

permit_without_stream: true | false

true разрешает проверку работоспособности, если нет дочерних подключений. Значение по умолчанию: false.

Подсказка

Необходимо настроить только в outbound (клиент).

initial_windows_size: number

Начальный размер окна h2 Stream. Если значение меньше или равно 0, эта функция не действует. Если значение больше 65535, механизм динамического окна будет отключен. Значение по умолчанию: 0, то есть не действует.

Подсказка

Необходимо настроить только в outbound (клиент).

Подсказка

При использовании CDN Cloudflare можно установить значение 65536 или выше, чтобы отключить механизм динамического окна, что предотвратит отправку непредвиденных кадров h2 GOAWAY CDN Cloudflare для закрытия существующего соединения.

- + diff --git a/ru/config/transports/h2.html b/ru/config/transports/h2.html index 5a4694dbeb..9a557ce8f1 100644 --- a/ru/config/transports/h2.html +++ b/ru/config/transports/h2.html @@ -24,8 +24,8 @@ HTTP/2 | Project X - - + +

Warning

This translation was modified on 16 July 2024 and an updated version (29 July 2024) is available on the source page. View the original page

HTTP/2

Способ передачи данных на основе HTTP/2.

Он полностью реализован в соответствии со стандартом HTTP/2 и может быть перенаправлен через другие HTTP-серверы (например, Nginx).

В соответствии с рекомендациями HTTP/2, клиент и сервер должны одновременно включать TLS для нормальной работы этого способа передачи.

HTTP/2 имеет встроенное мультиплексирование, не рекомендуется включать mux.cool при использовании HTTP/2.

Подсказка

Текущая версия способа передачи HTTP/2 не требует, чтобы входящее соединение (сервер) имело конфигурацию TLS. Это позволяет в среде развертывания с разделением трафика для специальных целей использовать внешний шлюз для обработки TLS-соединения, в то время как Xray будет использоваться в качестве серверного приложения, а связь между шлюзом и Xray будет осуществляться по незашифрованному протоколу http/2, который называется h2c.

Внимание

⚠️ Если вы используете fallback, обратите внимание на следующие моменты:

  • Убедитесь, что (x)tlsSettings.alpn содержит h2, иначе HTTP/2 не сможет завершить TLS-рукопожатие.
  • HTTP/2 не может быть разделен по пути, рекомендуется использовать SNI-разделение.

HttpObject

HttpObject соответствует элементу httpSettings конфигурации передачи.

{
@@ -39,6 +39,6 @@
   }
 }
 

host: [string]

Массив строк, каждый элемент которого является доменным именем.

Клиент будет случайным образом выбирать доменное имя из списка для связи, а сервер будет проверять, находится ли доменное имя в списке.

Подсказка

Если не указать "httpSettings" или оставить значение "host": [] пустым, то будет использоваться значение по умолчанию "www.example.com". Для успешного подключения значение "host" должно быть одинаковым на обеих сторонах. "host": [""] не является пустым значением.

path: string

HTTP-путь, начинающийся с /, должен быть одинаковым у клиента и сервера.

Значение по умолчанию: "/".

read_idle_timeout: number

Время в секундах, по истечении которого, если данные не были получены, будет выполнена проверка работоспособности.

По умолчанию проверка работоспособности не включена.

Подсказка

Настройка требуется только на стороне исходящего соединения (клиента).

Подсказка

Может решить некоторые проблемы с "обрывом" соединения.

health_check_timeout: number

Время ожидания ответа проверки работоспособности в секундах. Если в течение этого времени проверка работоспособности не будет завершена, она будет считаться неудачной. Значение по умолчанию: 15.

Подсказка

Настройка требуется только на стороне исходящего соединения (клиента).

method: string

HTTP-метод. Значение по умолчанию: "PUT".

При настройке следует использовать значения, перечисленные здесьОткрыть в новой вкладке.

headers: map{ string: [string] }

Пользовательские HTTP-заголовки, пара ключ-значение, где каждый ключ представляет собой имя HTTP-заголовка, а значение представляет собой массив.

- + diff --git a/ru/config/transports/httpupgrade.html b/ru/config/transports/httpupgrade.html index 9790bfaae3..e13031d49e 100644 --- a/ru/config/transports/httpupgrade.html +++ b/ru/config/transports/httpupgrade.html @@ -24,8 +24,8 @@ HTTPUpgrade | Project X - - + +

Warning

This translation was modified on 16 July 2024 and an updated version (29 July 2024) is available on the source page. View the original page

HTTPUpgrade

Это протокол, реализующий запросы и ответы на обновление HTTP 1.1, подобно WebSocket. Это позволяет ему, как и WebSocket, быть проксируемым CDN или Nginx, но без необходимости реализации других частей протокола WebSocket, что делает его более эффективным.

Его дизайн не рекомендуется для самостоятельного использования, а лучше всего работает в сочетании с TLS.

HttpUpgradeObject

HttpUpgradeObject соответствует пункту httpupgradeSettings в настройках передачи.

{
@@ -37,6 +37,6 @@
   }
 }
 

acceptProxyProtocol: true | false

Используется только для входящих соединений и указывает, принимать ли протокол PROXY.

PROXY protocolОткрыть в новой вкладке предназначен для передачи реального IP-адреса и порта запроса. Если вы не знакомы с ним, проигнорируйте этот пункт.

Распространенные программы для reverse прокси (например, HAProxy, Nginx) и VLESS fallbacks xver могут быть настроены для его включения.

При установке значения true, после установления TCP-соединения на самом нижнем уровне, запрашивающая сторона должна сначала отправить PROXY protocol v1 или v2, в противном случае соединение будет закрыто.

path: string

HTTP-путь, используемый HTTPUpgrade, по умолчанию "/".

Если в пути клиента содержится параметр ed (например, /mypath?ed=2560), будет активирована функция Early Data для уменьшения задержки, ее значение - порог длины первого пакета. Если длина первого пакета превышает это значение, Early Data не будет активирована. Рекомендуемое значение - 2560.

host: string

Хост, отправляемый в HTTP-запросе HTTPUpgrade, по умолчанию пустой. Если значение на стороне сервера пустое, значение хоста, отправляемое клиентом, не проверяется.

Когда на стороне сервера указано это значение или в headers указан хост, будет проверено соответствие хоста запроса клиента.

Приоритет выбора хоста, отправляемого клиентом: host > headers > address

headers: map {string: string}

Пользовательские HTTP-заголовки, пара ключ-значение, где каждый ключ представляет имя HTTP-заголовка, а соответствующее значение - строка.

По умолчанию пустое.

- + diff --git a/ru/config/transports/mkcp.html b/ru/config/transports/mkcp.html index 01652aaa30..a84810d525 100644 --- a/ru/config/transports/mkcp.html +++ b/ru/config/transports/mkcp.html @@ -24,8 +24,8 @@ mKCP | Project X - - + +

mKCP

mKCP использует UDP для имитации TCP-соединения.

mKCP жертвует пропускной способностью ради уменьшения задержки. При передаче одного и того же контента mKCP, как правило, потребляет больше трафика, чем TCP.

Подсказка

Убедитесь, что на хосте правильно настроена конфигурация брандмауэра.

KcpObject

KcpObject соответствует параметрам передачи kcpSettings.

{
@@ -47,6 +47,6 @@
   "domain": "example.com"
 }
 

type: string

Тип маскировки, доступные значения:

  • "none": значение по умолчанию, не применяется маскировка, отправляемые данные не имеют никаких отличительных признаков.
  • "srtp": маскировка под SRTP-пакеты, будет идентифицироваться как данные видеозвонка (например, FaceTime).
  • "utp": маскировка под uTP-пакеты, будет идентифицироваться как данные загрузки BT.
  • "wechat-video": маскировка под пакеты видеозвонка WeChat.
  • "dtls": маскировка под DTLS 1.2-пакеты.
  • "wireguard": маскировка под WireGuard-пакеты. (Это не настоящий протокол WireGuard).
  • "dns": некоторые корпоративные сети разрешают DNS-запросы без авторизации, добавление DNS-заголовка к KCP-пакетам позволяет обойти некоторые корпоративные сети.

domain: string

Используется совместно с типом маскировки "dns", можно указать произвольный домен.

Благодарности

Улучшения протокола KCP

Более компактный заголовок протокола

Протокол KCP использует заголовок размером 24 байта, а mKCP уменьшил его до 18 байт для пакета данных и 16 байт для пакета подтверждения. Более компактный заголовок помогает избежать обнаружения по признакам и ускоряет передачу данных.

Кроме того, в оригинальном KCP каждый пакет подтверждения может подтвердить только один пакет данных, то есть, если KCP нужно подтвердить получение 100 пакетов данных, он отправит 24 * 100 = 2400 байт данных. В этом случае многократно повторяются заголовки, что приводит к ненужному расходу полосы пропускания. mKCP сжимает несколько пакетов подтверждения, 100 пакетов подтверждения занимают всего 16 + 2 + 100 * 4 = 418 байт, что в шесть раз меньше, чем в оригинальном KCP.

Передача пакетов подтверждения

В оригинальном KCP пакет подтверждения отправляется только один раз, если пакет подтверждения потерян, то обязательно произойдет повторная передача данных, что приводит к ненужному расходу полосы пропускания. mKCP будет повторно отправлять пакеты подтверждения с определенной частотой, пока отправитель не получит подтверждение. Размер одного пакета подтверждения составляет 22 байта, что значительно меньше, чем размер пакета данных, который составляет более 1000 байт, поэтому повторная передача пакета подтверждения имеет гораздо меньшую цену.

Управление состоянием соединения

mKCP может эффективно управлять состоянием соединения. Когда удаленный хост инициализирует закрытие соединения, соединение будет закрыто в течение двух секунд; когда удаленный хост теряет соединение, соединение будет закрыто в течение максимум 30 секунд.

Оригинальный KCP не поддерживает этот сценарий.

- + diff --git a/ru/config/transports/quic.html b/ru/config/transports/quic.html index 00377742db..b1fb4b1ddd 100644 --- a/ru/config/transports/quic.html +++ b/ru/config/transports/quic.html @@ -24,8 +24,8 @@ QUIC | Project X - - + +

QUIC

QUIC (Quick UDP Internet Connection) — это протокол, предложенный Google для многоканальной передачи данных по UDP. Его основные преимущества:

  1. Сокращение времени установки соединения (1-RTT или 0-RTT).
  2. Многоканальность и отсутствие проблем с блокировкой, как у TCP.
  3. Миграция соединений (в основном на стороне клиента): при переходе с Wi-Fi на 4G соединение не разрывается.

QUIC в настоящее время находится в экспериментальной стадии и использует реализацию IETF, которая находится в процессе стандартизации, поэтому совместимость с финальной версией не гарантируется.

  • По умолчанию:
    • 12-байтовый Connection ID.
    • Автоматическое отключение соединения через 30 секунд бездействия (может повлиять на работу некоторых долгоживущих соединений).

QuicObject

QuicObject соответствует элементу quicSettings в конфигурации транспорта.

Предупреждение

Конфигурация на обоих концах соединения должна быть полностью идентичной, иначе соединение установить не удастся. QUIC требует включения TLS. Если TLS не включён в настройках транспорта, Xray сгенерирует самоподписанный сертификат для использования TLS.

{
@@ -39,6 +39,6 @@
   "type": "none"
 }
 

type: string

Тип маскировки. Допустимые значения:

  • "none": значение по умолчанию, маскировка не используется, отправляемые данные не имеют характерных признаков.
  • "srtp": маскировка под SRTP-трафик (например, FaceTime).
  • "utp": маскировка под uTP-трафик (например, BitTorrent).
  • "wechat-video": маскировка под видеозвонки WeChat.
  • "dtls": маскировка под DTLS 1.2.
  • "wireguard": маскировка под WireGuard (не является настоящим WireGuard).

Подсказка

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

Для предотвращения обнаружения рекомендуется включить хотя бы шифрование или маскировку.

- + diff --git a/ru/config/transports/splithttp.html b/ru/config/transports/splithttp.html index a33cbea9ab..efa32c1289 100644 --- a/ru/config/transports/splithttp.html +++ b/ru/config/transports/splithttp.html @@ -24,8 +24,8 @@ SplitHTTP | Project X - - + +

Warning

This translation was modified on 18 July 2024 and an updated version (7 August 2024) is available on the source page. View the original page

SplitHTTP

v1.8.16+

Используется для загрузки с помощью HTTP-фрагментированной передачи, загрузка осуществляется с помощью нескольких HTTP POST-запросов.

Может использоваться через CDN, не поддерживающие WebSocket, но есть несколько требований:

  • CDN должен поддерживать HTTP-фрагментированную передачу и потоковые ответы без буферизации. Ядро будет отправлять X-Accel-Buffering: no и Content-Type: text/event-stream, чтобы сообщить CDN об этом, но CDN должен соблюдать этот заголовок. Если промежуточный сервер не поддерживает потоковые ответы и зависает, передача, скорее всего, не будет работать.

Цель та же, что и у V2fly Meek, но благодаря использованию фрагментированной загрузки скорость загрузки выше, а скорость отдачи оптимизирована, но все еще очень ограничена, поэтому к HTTP-прокси предъявляются более высокие требования (см. выше).

SplitHTTP также принимает заголовок X-Forwarded-For.

SplitHttpObject

SplitHttpObject соответствует элементу splithttpSettings в конфигурации транспорта.

{
@@ -38,6 +38,6 @@
   "maxConcurrentUploads": 10 
 }
 

path: string

Путь HTTP-протокола, используемый SplitHTTP, значение по умолчанию — "/".

host: string

Хост, отправляемый в HTTP-запросе SplitHTTP, по умолчанию пуст. Если значение на стороне сервера пустое, значение хоста, отправленное клиентом, не проверяется.

Если это значение указано на стороне сервера или host указан в headers, то проверяется соответствие хоста запроса клиента.

Приоритет выбора хоста для отправки клиентом: host > headers > address.

headers: map {string: string}

Пользовательские HTTP-заголовки, пары ключ-значение, где каждый ключ представляет имя HTTP-заголовка, а соответствующее значение является строкой.

maxUploadSize: int

Максимальный размер фрагмента загрузки в байтах, по умолчанию 1 МБ.

Это значение должно быть меньше максимального размера тела запроса, разрешенного CDN или другим обратным HTTP-прокси, иначе будет выдаваться ошибка HTTP 413.

Увеличение этого значения может увеличить скорость загрузки.

maxConcurrentUploads: int

Максимальное количество одновременных загрузок, по умолчанию 10, соединения будут использоваться повторно, насколько это возможно.

Если соединение нестабильно или потребление памяти на сервере слишком велико, попробуйте уменьшить это значение.

Значение, установленное клиентом, должно быть меньше, чем на сервере, иначе это может привести к проблемам с подключением.

Детали протокола

Подробное обсуждение см. #3412Открыть в новой вкладке и #3462Открыть в новой вкладке. Ниже приведено краткое описание и требования к совместимой реализации:

  1. Загрузка начинается с GET /<UUID>. Сервер немедленно отвечает 200 OK и Transfer Encoding:chunked и немедленно отправляет двухбайтовую полезную нагрузку, чтобы принудительно обновить заголовки HTTP-прокси.

  2. Отправка данных начинается с POST /<UUID>/<seq>. seq действует как порядковый номер TCP, начиная с 0, пакеты данных могут отправляться одновременно, сервер должен пересобрать данные по порядковому номеру. Порядковый номер не следует сбрасывать.

    Клиент может свободно выбирать порядок открытия исходящих и нисходящих запросов, любой из них может инициировать сеанс, но соединение GET должно быть открыто в течение 30 секунд, иначе сеанс будет разорван.

  3. Запрос GET будет оставаться открытым до тех пор, пока соединение не будет разорвано, и сервер, и клиент могут закрыть соединение. Конкретное поведение зависит от версии HTTP.

Рекомендации:

  • Не ожидайте, что CDN будет правильно передавать все заголовки, цель этого протокола — обойти CDN, не поддерживающие WS, а поведение этих CDN обычно не очень дружелюбное.

  • Следует предполагать, что все HTTP-соединения не поддерживают потоковые запросы, поэтому размер каждого пакета, отправляемого исходящим соединением, должен определяться с учетом задержки, пропускной способности и ограничений самого промежуточного сервера (аналогично MTU TCP и алгоритму Нейгла).

  • Что касается версий HTTP, ядро временно не поддерживает h2c, поэтому при отсутствии HTTPS Xray отправляет только запросы http/1.1.

Во избежание дополнительных сложностей, связанных с согласованием ALPN, клиент Xray использует h2 при использовании HTTPS. Вы также можете вручную указать alpn как http/1.1 или h3 в настройках TLS клиента, чтобы использовать соответствующую версию HTTP для отправки запросов. Сервер Xray, с другой стороны, совместим со всеми типами входящих соединений, включая h2c (h3 пока не поддерживается), поскольку входящие соединения могут использовать различные типы запросов из-за перенаправления через промежуточные узлы.

BrowserDialer

При использовании HTTPS этот транспорт также поддерживает BrowserDialer.

- + diff --git a/ru/config/transports/tcp.html b/ru/config/transports/tcp.html index ed1abfb6dc..3db3f4795e 100644 --- a/ru/config/transports/tcp.html +++ b/ru/config/transports/tcp.html @@ -24,8 +24,8 @@ TCP | Project X - - + +

TCP

Режим транспорта TCP — один из рекомендуемых в настоящее время режимов транспорта.

Может использоваться в различных комбинациях с различными протоколами.

TcpObject

TcpObject соответствует элементу tcpSettings в конфигурации транспорта.

{
@@ -69,6 +69,6 @@
   }
 }
 

version: string

Версия HTTP, значение по умолчанию — "1.1".

status: string

Состояние HTTP, значение по умолчанию — "200".

reason: string

Описание состояния HTTP, значение по умолчанию — "OK".

headers: map {string, [ string ]}

HTTP-заголовки, пары ключ-значение, где каждый ключ представляет имя HTTP-заголовка, а соответствующее значение является массивом.

Каждый запрос будет содержать все ключи и случайно выбранное соответствующее значение. Значение по умолчанию см. в примере выше.

- + diff --git a/ru/config/transports/websocket.html b/ru/config/transports/websocket.html index 4e001683b4..fa925ac9d2 100644 --- a/ru/config/transports/websocket.html +++ b/ru/config/transports/websocket.html @@ -24,8 +24,8 @@ WebSocket | Project X - - + +

Warning

This translation was modified on 16 July 2024 and an updated version (29 July 2024) is available on the source page. View the original page

WebSocket

Использует стандартный WebSocket для передачи данных.

Подключение WebSocket может быть проксировано другими HTTP-серверами (например, Nginx) и VLESS fallbacks path.

Подсказка

WebSocket распознает заголовок X-Forwarded-For в HTTP-запросе для перезаписи исходного адреса трафика, приоритет выше, чем у PROXY protocol.

WebSocketObject

WebSocketObject соответствует элементу wsSettings в конфигурации транспорта.

{
@@ -37,6 +37,6 @@
   }
 }
 

acceptProxyProtocol: true | false

Только для входящих подключений, указывает, следует ли принимать PROXY protocol.

PROXY protocolОткрыть в новой вкладке используется для передачи реального исходного IP-адреса и порта запроса, если вы не знаете, что это такое, проигнорируйте этот параметр.

Распространенные программы-обработчики обратного прокси (например, HAProxy, Nginx) можно настроить на его отправку, VLESS fallbacks xver также может его отправлять.

Если установлено значение true, то после установления TCP-соединения на самом нижнем уровне запрашивающая сторона должна сначала отправить PROXY protocol v1 или v2, иначе соединение будет закрыто.

path: string

Путь, используемый WebSocket в HTTP-протоколе, значение по умолчанию — "/".

Если в пути клиента есть параметр ed (например, /mypath?ed=2560), будет активирован Early Data для уменьшения задержки.

host: string

Хост, отправляемый в HTTP-запросе WebSocket, значение по умолчанию — пустое. Если значение на стороне сервера пустое, значение хоста, отправленное клиентом, не проверяется.

Если это значение указано на стороне сервера или host указан в headers, то проверяется соответствие хоста запроса клиента.

Приоритет выбора хоста для отправки клиентом: host > headers > address.

headers: map {string: string}

Пользовательские HTTP-заголовки, пары ключ-значение, где каждый ключ представляет имя HTTP-заголовка, а соответствующее значение является строкой.

Значение по умолчанию: пустое.

Browser Dialer

Использует браузер для обработки TLS, подробнее см. в Browser Dialer.

- + diff --git a/ru/development/index.html b/ru/development/index.html index 0d331ba008..6d9d58332f 100644 --- a/ru/development/index.html +++ b/ru/development/index.html @@ -24,11 +24,11 @@ 开发指南 | Project X - - + +

开发指南

编译文档

Xray 支持各种平台, 您可以在多种平台上自行进行交叉编译。

请点击编译文档以查看具体编译相关内容。

设计思路

Xray 内核提供了一个平台,在其之上可以进二次开发。

这个章节阐述了 Xray 的设计目标和架构。

请点击设计思路以了解 Xray 的设计目标和架构。

开发规范

这个章节阐述了获取代码,进行开发,提交 PR 的流程中需要遵循的准则, 以及相关的编码规范。

请点击开发规范查看 Xray 开发中应遵循的准则。

协议详解

Xray 用到了很多种协议, 您可以通过各种途径获得协议的详细描述。

VLESS 协议

VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

VMess 协议

VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

Mux.Cool 协议

Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

mKCP 协议

mKCP 是流式传输协议,由 KCP 协议Открыть в новой вкладке修改而来,可以按顺序传输任意的数据流。

- + diff --git a/ru/development/intro/compile.html b/ru/development/intro/compile.html index ac665068e3..03af22d0ee 100644 --- a/ru/development/intro/compile.html +++ b/ru/development/intro/compile.html @@ -24,8 +24,8 @@ 编译文档 | Project X - - + +

编译文档

前序工作

Xray 使用 GolangОткрыть в новой вкладке 作为编程语言,你需要先安装最新版本 Golang 才能够编译。

如果你不幸使用 Windows, 请 务必 使用 Powershell

拉取 Xray 源代码

git clone https://github.com/XTLS/Xray-core.git
@@ -40,6 +40,6 @@
 
 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
 

上传到服务器后,记得在服务器终端内执行 chmod +x xray

Подсказка

执行 go tool dist list 查看所有支持的系统与架构。

可复现构建:

按照上述步骤,能够编译与 Release 中完全相同的二进制文件。

Внимание

请先确认您使用的 Golang 版本与编译 Release 的一致。

- + diff --git a/ru/development/intro/design.html b/ru/development/intro/design.html index af19ca0a3d..ded759f3b1 100644 --- a/ru/development/intro/design.html +++ b/ru/development/intro/design.html @@ -24,11 +24,11 @@ 设计目标 | Project X - - + +

设计目标

  • Xray 内核提供了一个平台,支持必要的网络代理功能,在其之上可以进二次开发,以提供更好的用户体验;
  • 以跨平台为首要原则,以减少二次开发的成本;

架构

Architecture

内核分为三层:应用层、代理层和传输层。

每一层内包含数个模块,模块间互相独立,同类型的模块可无缝替换。

应用层

应用层包含一些代理层中常用的功能,这些功能被抽象出来,以便在不同的代理模块中复用。

应用层的模块应为纯软件实现,与硬件或平台相关的技术无关。

重要模块列表:

  • Dispatcher: 用于把入站代理所接收到的数据,传送给出站代理;
  • Router: 路由模块,详见 路由配置
  • DNS: 内置的 DNS 服务器模块;
  • Proxy Manager: 代理管理器;

代理层

代理层分为两部分:入站代理(Inbound Proxy)和出站代理(Outbound Proxy)。

两部分相互独立,入站代理不依赖于某个特定的出站代理,反之亦然。

入站代理

出站代理

传输层

传输层提供一些网络数据传输相关的工具模块。

- + diff --git a/ru/development/intro/guide.html b/ru/development/intro/guide.html index bc635e6137..dd0e4ad786 100644 --- a/ru/development/intro/guide.html +++ b/ru/development/intro/guide.html @@ -24,8 +24,8 @@ 开发规范 | Project X - - + +

开发规范

基本

版本控制

Project X 的代码被托管在 github 上:

您可以使用 GitОткрыть в новой вкладке 来获取代码。

分支(Branch)

  • 本项目的主干分支为 main,
  • 本项目的发布主分支同为 main,
  • 需要确保 main 在任一时刻都是可编译,且可正常使用的。
  • 如果需要开发新的功能,请新建分支进行开发,在开发完成并且经过充分测试后,合并回主干分支。
  • 已经合并入主干且没有必要存在的分支,请删除。

发布(Release)

WIP
  • 建立尝鲜版本和稳定版本两个发布通道
    • 尝鲜版本,可以为 daily build,主要用于特定情况的测试,尝鲜和获得即时反馈和再改进。
    • 稳定版本,为定时更新(比如月更),合并稳定的修改并发布。

引用其它项目

开发流程

写代码之前

发现任何问题,或对项目有任何想法,请创建 issueОткрыть в новой вкладке 讨论以减少重复劳动和消耗在代码上的时间。

修改代码

  • Golang
    • 请参考 Effective GoОткрыть в новой вкладке
    • 每一次 push 之前,请运行:go generate core/format.go
    • 如果需要修改 protobuf,例如增加新配置项,请运行:go generate core/proto.go
    • 提交 pull request 之前,建议测试通过:go test ./...
    • 提交 pull request 之前,建议新增代码有超过 70% 的代码覆盖率(code coverage);
  • 其它
    • 请注意代码的可读性。

Pull Request

  • 提交 PR 之前,请先运行 git pull https://github.com/XTLS/Xray-core.git 以确保 merge 可顺利进行;
  • 一个 PR 只做一件事,如有对多个 bug 的修复,请对每一个 bug 提交一个 PR;
  • 由于 Golang 的特殊需求(Package path),Go 项目的 PR 流程和其它项目有所不同,建议流程如下:
    1. 先 Fork 本项目,创建你自己的 github.com/<your_name>/Xray-core.git 仓库;
    2. 克隆你自己的 Xray 仓库到本地:git clone https://github.com/<your_name>/Xray-core.git
    3. 基于 main 分支创建新的分支,例如 git branch issue24 main
    4. 在新创建的分支上作修改并提交修改(commit);
    5. 在推送(push)修改完成的分支到自己的仓库前,先切换到 main 分支,运行 git pull https://github.com/XTLS/Xray-core.git 拉取最新的远端代码;
    6. 如果上一步拉取得到了新的远端代码,则切换到之前自己创建的分支,运行 git rebase main 执行分支合并操作。如遇到文件冲突,则需要解决冲突;
    7. 上一步处理完毕后,就可以把自己创建的分支推送到自己的仓库:git push -u origin your-branch
    8. 最后,把自己仓库的新推送的分支往 XTLS/Xray-coremain 分支发 PR 即可;
    9. 请在 PR 的标题和正文中,完整表述此次 PR 解决的问题 / 新增的功能 / 代码所做的修改的用意等;
    10. 耐心等待开发者的回应。

对代码的修改

功能性问题

请提交至少一个测试用例(Test Case)来验证对现有功能的改动。

性能相关

请提交必要的测试数据来证明现有代码的性能缺陷,或是新增代码的性能提升。

新功能

  • 如果新增功能对已有功能不影响,请提供可以开启/关闭的开关(如 flag),并使新功能保持默认关闭的状态;
  • 大型新功能(比如增加一个新的协议)开发之前,请先提交一个 issue,讨论完毕之后再进行开发。

其它

视具体情况而定。

Xray 编码规范

以下内容适用于 Xray 中的 Golang 代码。

代码结构

Xray-core
@@ -40,6 +40,6 @@
 │   ├── vmess
 ├── transport  // 传输模块
 

编码规范

基本与 Golang 官方所推荐做法一致,有一些例外。写在这里以方便大家熟悉 Golang。

命名

  • 文件和目录名尽量使用单个英文单词,比如 hello.go;
    • 如果实在没办法,则目录使用连接线/文件名使用下划线连接两个(或多个单词),比如 hello-world/hello_again.go;
    • 测试代码使用 _test.go 结尾;
  • 类型使用 Pascal 命名法,比如 ConnectionHandler;
    • 对缩写不强制小写,即 HTML 不必写成 Html;
  • 公开成员变量也使用 Pascal 命名法;
  • 私有成员变量使用 小驼峰式命名法Открыть в новой вкладке ,如 privateAttribute
  • 为了方便重构,方法建议全部使用 Pascal 命名法;
    • 完全私有的类型放入 internal

内容组织

  • 一个文件包含一个主要类型,及其相关的私有函数等;
  • 测试相关的文件,如 Mock 等工具类,放入 testing 子目录。
- + diff --git a/ru/development/protocols/mkcp.html b/ru/development/protocols/mkcp.html index 4488f116de..719394252e 100644 --- a/ru/development/protocols/mkcp.html +++ b/ru/development/protocols/mkcp.html @@ -24,11 +24,11 @@ mKCP 协议 | Project X - - + +

mKCP 协议

mKCP 是流式传输协议,由 KCP 协议Открыть в новой вкладке 修改而来,可以按顺序传输任意的数据流。

版本

mKCP 没有版本号,不保证版本之间兼容性。

依赖

底层协议

mKCP 是一个基于 UDP 的协议,所有通讯使用 UDP 传输。

函数

通讯过程

  1. mKCP 将数据流拆成若干个数据包进行发送。一个数据流有一个唯一标识,用以区分不同的数据流。数据流中的每一个数据包都携带了同样的标识。
  2. mKCP 没有握手过程,当收到一个数据包时,根据其携带的数据流的标识来判断是否为新的通话,或是正在进行中的通话。
  3. 每一个数据包中包含若干个片段(Segment),片段分为三类:数据(Data)、确认(ACK)、心跳(Ping)。每个片段需要单独处理。

数据格式

数据包

4 字节2 字节L 字节
认证信息 A数据长度 L片段部分

其中:

  • 认证信息 A = fnv(片段部分),big endian;
  • 片段部分可能包含多个片段;

数据片段

2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len 字节
标识 Conv指令 Cmd选项 Opt时间戳 Ts序列号 Sn未确认序列号 Una长度 Len数据

其中:

  • 标识 Conv: mKCP 数据流的标识
  • 指令 Cmd: 常量 0x01
  • 选项 Opt: 可选的值有:
    • 0x00: 空选项
    • 0x01: 对方已发出所有数据
  • 时间戳 Ts: 当前片段从远端发送出来时的时间,big endian
  • 序列号 Sn: 该数据片段时数据流中的位置,起始片段的序列号为 0,之后每个新片段按顺序加 1
  • 未确认序列号 Una: 远端主机正在发送的,且尚未收到确认的最小的 Sn

确认片段

2 字节1 字节1 字节4 字节4 字节4 字节2 字节Len * 4 字节
标识 Conv指令 Cmd选项 Opt窗口 Wnd下一接收序列号 Sn时间戳 Ts长度 Len已收到的序列号

其中:

  • 标识 Conv: mKCP 数据流的标识
  • 指令 Cmd: 常量 0x00
  • 选项 Opt: 同上
  • 窗口 Wnd: 远端主机可以接收的最大序列号
  • 下一接收序列号 Sn: 远端主机未收到的数据片段中的最小序列号
  • 时间戳 Ts: 远端主机最新收到的数据片段的时间戳,可用于计算延迟
  • 已收到的序列号: 每个 4 字节,表示此序列号的数据已经确认收到

注释:

  • 远程主机期待收到序列号 [Sn, Wnd) 范围内的数据

心跳片段

2 字节1 字节1 字节4 字节4 字节4 字节
标识 Conv指令 Cmd选项 Opt未确认序列号 Una下一接收序列号 Sn延迟 Rto

其中:

  • 标识 Conv: mKCP 数据流的标识
  • 指令 Cmd: 可选的值有
    • 0x02: 远端主机强行终止会话
    • 0x03: 正常心跳
  • 选项 Opt: 同上
  • 未确认序列号 Una: 同数据片段的 Una
  • 下一接收序列号 Sn: 同确认片段的 Sn
  • 延迟 Rto: 远端主机自己计算出的延迟
- + diff --git a/ru/development/protocols/muxcool.html b/ru/development/protocols/muxcool.html index 9ccbafe18c..f6e93c772e 100644 --- a/ru/development/protocols/muxcool.html +++ b/ru/development/protocols/muxcool.html @@ -24,11 +24,11 @@ Mux.Cool 协议 | Project X - - + +

Mux.Cool 协议

Mux.Cool 协议是一个多路复用传输协议,用于在一条已建立的数据流中传输多个各自独立的数据流。

版本

当前版本是 1 Beta。

依赖

底层协议

Mux.Cool 必须运行在一个已建立的可靠数据流之上。

通讯过程

一个 Mux.Cool 连接中可传输若干个子连接,每个子连接有一个独立的 ID 和状态。传输过程由帧(Frame)组成,每一帧用于传输一个特定的子连接的数据。

客户端行为

当有连接需求时并且没有现有可用的连接时,客户端向服务器发起一个新连接,以下称为“主连接”。

  1. 一个主连接可用于发送若干个子连接。客户端可自主决定主连接可承载的子连接数量。
  2. 对于一个新的子连接,客户端必须发送状态New以通知服务器建立子连接,然后使用状态Keep来传送数据。
  3. 当子连接结束时,客户端发送End状态来通知服务器关闭子连接。
  4. 客户端可自行决定何时关闭主连接,但必须确定服务器也同时保持连接。
  5. 客户端可使用 KeepAlive 状态来避免服务器关闭主连接。

服务器端行为

当服务器端接收到新的子连接时,服务器应当按正常的连接来处理。

  1. 当收到状态End时,服务器端可以关闭对目标地址的上行连接。
  2. 在服务器的响应中,必须使用与请求相同的 ID 来传输子连接的数据。
  3. 服务器不能使用New状态。
  4. 服务器可使用 KeepAlive 状态来避免客户端关闭主连接。

传输格式

Mux.Cool 使用对称传输格式,即客户端和服务器发送和接收相同格式的数据。

帧格式

2 字节L 字节X 字节
元数据长度 L元数据额外数据

元数据

元数据有若干种类型。所有类型的元数据都包含 ID 和 Opt 两项,其含义为:

当选项 Opt(D) 开启时,额外数据格式如下:

2 字节X-2 字节
长度 X-2数据

新建子连接 (New)

2 字节1 字节1 字节1 字节2 字节1 字节A 字节8 字节
ID0x01选项 Opt网络类型 N端口地址类型 T地址 AGlobal ID (XUDP)

其中:

  • 网络类型 N:
    • 0x01:TCP,表示当前子连接的流量应当以 TCP 的方式发送至目标。
    • 0x02:UDP,表示当前子连接的流量应当以 UDP 的方式发送至目标。
  • 地址类型 T:
    • 0x01:IPv4
    • 0x02:域名
    • 0x03:IPv6
  • 地址 A:
    • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
    • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
    • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
  • Global ID (XUDP):
    • 客户端计算出 UDP 来源二元组的全局独特 ID,服务端用以确保当 XUDP 断线重连时,仍使用同一个端口与目标通信。

在新建子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

保持子连接 (Keep)

TCP

2 字节1 字节1 字节
ID0x02选项 Opt

UDP

2 字节1 字节1 字节1 字节2 字节1 字节A 字节
ID0x02选项 Opt网络类型 N端口地址类型 T地址 A

在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。 XUDP 在 Opt(D) 之后加 UDP 地址,格式同新建子连接,但没有 Global ID。

关闭子连接 (End)

2 字节1 字节1 字节
ID0x03选项 Opt

在保持子连接时,若 Opt(D) 开启,则这一帧所带的数据需要被发往目标主机。

保持连接 (KeepAlive)

2 字节1 字节1 字节
ID0x04选项 Opt

在保持连接时:

  • 若 Opt(D) 开启,则这一帧所带的数据必须被丢弃。
  • ID 可为随机值。

应用

Mux.Cool 协议与底层协议无关,理论上可以使用任何可靠的流式连接来传输 Mux.Cool 的协议数据。

在目标导向的协议如 Shadowsocks 和 VMess 协议中,连接建立时必须包含一个指定的地址。 为了保持兼容性,Mux.Cool 协议指定地址为“v1.mux.cool”。即当主连接的目标地址与之匹配时,则进行 Mux.Cool 方式的转发,否则按传统方式进行转发。(注:这是一个程序内的标记,VMess 和 VLESS 并不会在数据包中发送“v1.mux.cool”地址)

- + diff --git a/ru/development/protocols/vless.html b/ru/development/protocols/vless.html index 057ff40107..77dd60c7bd 100644 --- a/ru/development/protocols/vless.html +++ b/ru/development/protocols/vless.html @@ -24,11 +24,11 @@ VLESS 协议 | Project X - - + +

VLESS 协议

VLESS 是一个无状态的轻量传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

Request & Response

1 字节16 字节1 字节M 字节1 字节2 字节1 字节S 字节X 字节
协议版本等价 UUID附加信息长度 M附加信息 ProtoBuf指令端口地址类型地址请求数据
1 字节1 字节N 字节Y 字节
协议版本,与请求的一致附加信息长度 N附加信息 ProtoBuf响应数据

VLESS 早在第二个测试版 ALPHA 2 时就已经是上述结构了(BETA 是第五个测试版):

“响应认证”被替换为“协议版本”并移至最前,使 VLESS 可以升级换代,同时消除了生成伪随机数的开销。混淆相关结构被替换为附加信息(ProtoBuf)并前移,赋予协议本身可扩展性,相关开销也极小(gogo/protobufОткрыть в новой вкладке),若无附加信息则无相关开销。

我一直觉得“响应认证”不是必要的,ALPHA 时为了提升生成随机数的性能,还用 math/rand 替换 crypto/rand,而现在都不需要了。

“协议版本”不仅能起到“响应认证”的作用,还赋予了 VLESS 无痛升级协议结构的能力,带来无限的可能性。 “协议版本”在测试版本中均为 0,正式版本中为 1,以后若有不兼容的协议结构变更则应升级版本。

VLESS 服务端的设计是 switch version,即同时支持所有 VLESS 版本。若需要升级协议版本(可能到不了这一步),推荐的做法是服务端提前一个月支持,一个月后再改客户端。VMess 请求也有协议版本,但它的认证信息在外面,指令部分则高度耦合且有固定加密,导致里面的协议版本毫无意义,服务端也没有进行判断,响应则没有协议版本。Trojan 的协议结构中没有协议版本。

接下来是 UUID,我本来觉得 16 字节有点长,曾经考虑过缩短它,但后来看到 Trojan 用了 56 个可打印字符(56 字节),就彻底打消了这个念头。服务端每次都要验证 UUID,所以性能也很重要:VLESS 的 Validator 经历了多次重构/升级,相较于 VMess,它十分简洁且耗资源很少,可以同时支持非常多的用户,性能也十分强悍,验证速度极快(sync.Map)。API 动态增删用户则更高效顺滑。 https://github.com/XTLS/Xray-core/issues/158

引入 ProtoBuf 是一个创举,等下会详细讲解。“指令”到“地址”的结构目前与 VMess 完全相同,同样支持 Mux。

总体上,ALPHA 2 到 BETA 主要是:结构进化、清理整合、性能提升、更加完善。这些都是一点一滴的,详见 VLESS ChangesОткрыть в новой вкладке

ProtoBuf

似乎只有 VLESS 可选内嵌 ProtoBuf,它是一种数据交换格式,信息被紧密编码成二进制,TLV 结构(Tag Length Value)。

起因是我看到一篇文章称 SS 有一些缺点,如没有设计错误回报机制,客户端没办法根据不同的错误采取进一步的动作。 (但我并不认同所有错误都要回报,不然防不了主动探测。下一个测试版中,服务器可以返回一串自定义信息。) 于是想到一个可扩展的结构是很重要的,未来它也可以承载如动态端口指令。不止响应,请求也需要类似的结构。 本来打算自己设计 TLV,接着发觉 ProtoBuf 就是此结构、现成的轮子,完全适合用来做这件事,各语言支持等也不错。

目前“附加信息”只有 Scheduler 和 SchedulerV,它们是 MessName 和 MessSeed 的替代者,当你不需要它们时,“附加信息长度”为 0,也就不会有 ProtoBuf 序列化/反序列化的开销。其实我更愿意称这个过程为“拼接”,因为 pb 实际原理上也只是这么做而已,相关开销极小。拼接后的 bytes 十分紧凑,和 ALPHA 的方案相差无几,有兴趣的可以分别输出并对比。

为了指示对附加信息(Addons,也可以理解成插件,以后可以有很多个插件)的不同支持程度,下个测试版会在“附加信息长度”前新增“附加信息版本”。256 - 1 = 255 字节是够用且合理的(65535 就太多了,还可能有人恶意填充),现有的只用了十分之一,以后也不会同时有那么多附加信息,且大多数情况下是完全没有附加信息的。真不够用的话,可以升级 VLESS 版本。

为了减少逻辑判断等开销,暂定 Addons 不使用多级结构。一个月前出现过“可变协议格式”的想法,pb 是可以做到打乱顺序,但没必要,因为现代加密的设计不会让旁观者看出两次传输的头部相同。

下面介绍 Schedulers 和 Encryption 的构想,它们都是可选的,一个应对流量时序特征问题,一个应对密码学上的问题。

Schedulers Flow

中文名暂称:流量调度器(2020-09-03 更新:中文名确定为“流控”),指令由 ProtoBuf 承载,控制的是数据部分。

我之前发现,VMess 原有的 shake “元数据混淆”在 TLS 上完全不会带来有意义的改变,只会降低性能,所以 VLESS 弃用了它。并且,“混淆”这个表述容易被误解成伪装,也弃用了。顺便一提,我一直是不看好伪装的:做不到完全一样,那不就是强特征吗?做得到完全一样,那为什么不直接用伪装目标?我一开始用的是 SSR,后来发现它只是表面伪装骗运营商,就再也没用过了。

那么,“流量调度器”要解决什么问题?它影响的是宏观流量时序特征,而不是微观特征,后者是加密要解决的事情。流量时序特征可以是协议带来的,比如 Socks5 over TLS 时的 Socks5 握手 ,TLS 上不同的这种特征对于监测者来说就是不同的协议,此时无限 Schedulers 就相当于无限协议(重新分配每次发送的数据量大小等)。流量时序特征也可以是行为带来的,比如访问 Google 首页时加载了多少文件、顺序、每个文件的大小,多套一层加密并不能有效掩盖这些信息。

Schedulers 没必要像下面的 Encryption 一样整个套在外面,因为头部的一丁点数据相对于后面的数据量来说太微不足道了。

BETA 2 预计推出两个初级的 Scheduler:Zstd 压缩、数据量动态扩充。进阶操作才是从宏观层面来控制、分配,暂时咕咕。

Encryption

与 VMess 的高度耦合不同,VLESS 的服务端、客户端不久后可以提前约定好加密方式,仅在外面套一层加密。这有点类似于使用 TLS,不影响承载的任何数据,也可以理解成底层就是从 TLS 换成预设约定加密。相对于高度耦合,这种方式更合理且灵活:一种加密方式出了安全性问题,直接扔掉并换用其它的就行了,十分方便。VLESS 服务端还会允许不同的加密方式共存。

对比 VMess,VLESS 相当于把 security 换成 encryption,把 disableInsecureEncryption 换成 decryption,就解决了所有问题。目前 encryption 和 decryption 只接受 "none" 且不能留空(即使以后有连接安全性检查),详见 VLESS 配置文档Открыть в новой вкладке。encryption 并不需要往外移一级,一是因为无法复用很多代码,二是因为会影响控制粒度,看未来的应用就明白了。

加密支持两类形式,一类是加密完全独立,需要额外密码,适合私用,另一类是结合已有的 UUID 来加密,适合公用。 (若用第一类加密形式,且密码是以某种形式公开的,比如多人共用,那么中间人攻击就不远了) 重新设计的动态端口可能会随加密同时推出,指令由 ProtoBuf 承载,具体实现和 VMess 的动态端口也会有很多不同。

套现成加密是件很简单的事情,也就多一层 writer & reader。BETA 3 预计支持 SS 的 aes-128-gcm 和 chacha20-ietf-poly1305: 客户端的 encryption 可以填 “auto: ss_aes-128-gcm_0_123456, ss_chacha20-ietf-poly1305_0_987654”,auto 会选择最适合当前机器的,0 代表测试版,最后的是密码。服务端的 decryption 也是类似填法,收到请求时会逐一尝试解密。

并不是所有组合都需逐一尝试:VMess 的加密分为三段,第一段是认证信息,结合了 UUID、alterId、时间因素,第二段是指令部分,以固定算法加密,指令中含有数据部分使用的加密算法,第三段才是重要的数据部分。可以看出,VMess 的加解密方式实际上是多对一(服务端适配),而不仅是结合 UUID。但仅是结合 UUID 来加密也是件相对麻烦的事情,短时间内不会出,鉴于我们现在有 VMessAEAD 可用,也并不着急。若 VLESS 推出了结合 UUID 的加密方式,相当于重构了整个 VMess。

UDP issues

XUDP:VLESS & VMess & Mux UDP FullCone NATОткрыть в новой вкладке

客户端开发指引

  1. VLESS 协议本身还会有不兼容升级,但客户端配置文件参数基本上是只增不减的。iOS 客户端的协议实现则需紧跟升级。
  2. 视觉标准:UI 标识请统一用 VLESS,而不是 VLess / Vless / vless,配置文件不受影响,代码内则顺其自然。
  3. encryption 应做成输入框而不是选择框,新配置的默认值应为 none,若用户置空则应代填 none

VLESS 分享链接标准

感谢 a @DuckSoftОткрыть в новой вкладке 的提案!

详情请见 VMessAEAD / VLESS 分享链接标准提案Открыть в новой вкладке

- + diff --git a/ru/development/protocols/vmess.html b/ru/development/protocols/vmess.html index 64bec47773..c873546f02 100644 --- a/ru/development/protocols/vmess.html +++ b/ru/development/protocols/vmess.html @@ -24,11 +24,11 @@ VMess 协议 | Project X - - + +

VMess 协议

VMess 是一个加密传输协议,可以作为 Xray 客户端和服务器之间的桥梁。

版本

当前版本号为 1。

依赖

底层协议

VMess 是一个基于 TCP 的协议,所有数据使用 TCP 传输。

用户 ID

ID 等价于 UUIDОткрыть в новой вкладке,是一个 16 字节长的随机数,它的作用相当于一个令牌(Token)。 一个 ID 形如:de305d54-75b4-431b-adb2-eb6b9e546014,几乎完全随机,可以使用任何的 UUID 生成器来生成,比如这个Открыть в новой вкладке

用户 ID 可在配置文件中指定。

函数

通讯过程

VMess 是一个无状态协议,即客户端和服务器之间不需要握手即可直接传输数据,每一次数据传输对之前和之后的其它数据传输没有影响。

VMess 的客户端发起一次请求,服务器判断该请求是否来自一个合法的客户端。如验证通过,则转发该请求,并把获得的响应发回给客户端。

VMess 使用非对称格式,即客户端发出的请求和服务器端的响应使用了不同的格式。

客户端请求

16 字节X 字节余下部分
认证信息指令部分数据部分

认证信息

认证信息是一个 16 字节的哈希(hash)值,它的计算方式如下:

  • H = MD5
  • K = 用户 ID (16 字节)
  • M = UTC 时间,精确到秒,取值为当前时间的前后 30 秒随机值(8 字节, Big Endian)
  • Hash = HMAC(H, K, M)

指令部分

指令部分经过 AES-128-CFB 加密:

  • Key:MD5(用户 ID + []byte('c48619fe-8f02-49e0-b9e9-edf763e17e21'))
  • IV:MD5(X + X + X + X),X = []byte(认证信息生成的时间) (8 字节, Big Endian)
1 字节16 字节16 字节1 字节1 字节4 位4 位1 字节1 字节2 字节1 字节N 字节P 字节4 字节
版本号 Ver数据加密 IV数据加密 Key响应认证 V选项 Opt余量 P加密方式 Sec保留指令 Cmd端口 Port地址类型 T地址 A随机值校验 F

选项 Opt 细节:(当某一位为 1 时,表示该选项启用)

01234567
XXXXXMRS

其中:

  • 版本号 Ver:始终为 1;
  • 数据加密 IV:随机值;
  • 数据加密 Key:随机值;
  • 响应认证 V:随机值;
  • 选项 Opt:
    • S (0x01):标准格式的数据流(建议开启);
    • R (0x02):客户端期待重用 TCP 连接(Xray 2.23+ 弃用);
      • 只有当 S 开启时,这一项才有效;
    • M (0x04):开启元数据混淆(建议开启);
      • 只有当 S 开启时,这一项才有效;
      • 当其项开启时,客户端和服务器端需要分别构造两个 Shake 实例,分别为 RequestMask = Shake(请求数据 IV), ResponseMask = Shake(响应数据 IV)。
    • X:保留
  • 余量 P:在校验值之前加入 P 字节的随机值;
  • 加密方式:指定数据部分的加密方式,可选的值有:
    • 0x00:AES-128-CFB;
    • 0x01:不加密;
    • 0x02:AES-128-GCM;
    • 0x03:ChaCha20-Poly1305;
  • 指令 Cmd:
    • 0x01:TCP 数据;
    • 0x02:UDP 数据;
  • 端口 Port:Big Endian 格式的整型端口号;
  • 地址类型 T:
    • 0x01:IPv4
    • 0x02:域名
    • 0x03:IPv6
  • 地址 A:
    • 当 T = 0x01 时,A 为 4 字节 IPv4 地址;
    • 当 T = 0x02 时,A 为 1 字节长度(L) + L 字节域名;
    • 当 T = 0x03 时,A 为 16 字节 IPv6 地址;
  • 校验 F:指令部分除 F 外所有内容的 FNV1a hash;

数据部分

当 Opt(S) 开启时,数据部分使用此格式。实际的请求数据被分割为若干个小块,每个小块的格式如下。服务器校验完所有的小块之后,再按基本格式的方式进行转发。

2 字节L 字节
长度 L数据包

其中:

  • 长度 L:Big Endian 格式的整型,最大值为 2^14;
    • 当 Opt(M) 开启时,L 的值 = 真实值 xor Mask。Mask = (RequestMask.NextByte() << 8) + RequestMask.NextByte();
  • 数据包:由指定的加密方式加密过的数据包;

在传输结束之前,数据包中必须有实际数据,即除了长度和认证数据之外的数据。当传输结束时,客户端必须发送一个空的数据包,即 L = 0(不加密) 或认证数据长度(有加密),来表示传输结束。

按加密方式不同,数据包的格式如下:

  • 不加密:
    • L 字节:实际数据;
  • AES-128-CFB:整个数据部分使用 AES-128-CFB 加密
    • 4 字节:实际数据的 FNV1a hash;
    • L - 4 字节:实际数据;
  • AES-128-GCM:Key 为指令部分的 Key,IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
    • L - 16 字节:实际数据;
    • 16 字节:GCM 认证信息
  • ChaCha20-Poly1305:Key = MD5(指令部分 Key) + MD5(MD5(指令部分 Key)),IV = count (2 字节) + IV (10 字节)。count 从 0 开始递增,每个数据包加 1;IV 为 指令部分 IV 的第 3 至第 12 字节。
    • L - 16 字节:实际数据;
    • 16 字节:Poly1305 认证信息

服务器应答

应答头部数据使用 AES-128-CFB 加密,IV 为 MD5(数据加密 IV),Key 为 MD5(数据加密 Key)。实际应答数据视加密设置不同而不同。

1 字节1 字节1 字节1 字节M 字节余下部分
响应认证 V选项 Opt指令 Cmd指令长度 M指令内容实际应答数据

其中:

  • 响应认证 V:必须和客户端请求中的响应认证 V 一致;
  • 选项 Opt:
    • 0x01:服务器端准备重用 TCP 连接(Xray 2.23+ 弃用);
  • 指令 Cmd:
    • 0x01:动态端口指令
  • 实际应答数据:
    • 如果请求中的 Opt(S) 开启,则使用标准格式,否则使用基本格式。
    • 格式均和请求数据相同。
      • 当 Opt(M) 开启时,长度 L 的值 = 真实值 xor Mask。Mask = (ResponseMask.NextByte() << 8) + ResponseMask.NextByte();

动态端口指令

1 字节2 字节16 字节2 字节1 字节1 字节
保留端口 Port用户 IDAlterID用户等级有效时间 T

其中:

  • 端口 Port:Big Endian 格式的整型端口号;
  • 有效时间 T:分钟数;

客户端在收到动态端口指令时,服务器已开放新的端口用于通信,这时客户端可以将数据发往新的端口。在 T 分钟之后,这个端口将失效,客户端必须重新使用主端口进行通信。

注释

  • 为确保向前兼容性,所有保留字段的值必须为 0。
- + diff --git a/ru/document/command.html b/ru/document/command.html index cf12d82d5d..1c6609c1bf 100644 --- a/ru/document/command.html +++ b/ru/document/command.html @@ -24,8 +24,8 @@ Командные аргументы | Project X - - + +

Warning

This translation was modified on 16 July 2024 and an updated version (11 August 2024) is available on the source page. View the original page

Командные аргументы

Подсказка

Xray использует команды и аргументы в стиле Go.

Базовые команды

Вы можете запустить xray help, чтобы получить список всех базовых команд Xray, а также их описание и примеры использования.

Xray is a platform for building proxies.
@@ -80,6 +80,6 @@
 

xray x25519

Генерация пары ключей x25519.

Использование:

xray x25519 [-i "(base64.RawURLEncoding)" --std-encoding ]
 

xray wg

Генерация пары ключей curve25519 для WireGuard.

Использование:

xray wg [-i "(base64.StdEncoding)"]
 

Подсказка

Если -config не указан, Xray попытается загрузить config.json из следующих мест:

- + diff --git a/ru/document/config.html b/ru/document/config.html index 1d66f09580..0b33c58bf7 100644 --- a/ru/document/config.html +++ b/ru/document/config.html @@ -24,8 +24,8 @@ Настройка и запуск | Project X - - + +

Настройка и запуск

После того, как вы скачали и установили Xray, вам потребуется его настроить.

В данном руководстве мы рассмотрим только простой способ настройки. Дополнительные шаблоны: Xray-examplesОткрыть в новой вкладке

Для настройки более сложных функций обратитесь к подробным инструкциям в разделе Файл конфигурации.

Предупреждение

Во избежание расшифровки вашего трафика
следует сгенерировать уникальный UUID с помощью команды xray uuid или uuidgen,
который затем нужно вставить на стороне сервера в поле inbounds[0].settings.clients[0].id,
а на стороне клиента - в поле outbounds[0].settings.vnext[0].users[0].id.

Настройка сервера

Вам понадобится сервер с публичным IP-адресом (не за NAT), на котором будет запущен Xray. Конфигурация сервера:

{
@@ -93,6 +93,6 @@
   }
 }
 

Единственное, что вам нужно изменить в приведенной выше конфигурации, - это IP-адрес вашего сервера и UUID пользователя, как указано в комментариях. Эта конфигурация будет перенаправлять весь трафик на ваш сервер, за исключением локальной сети (например, доступ к маршрутизатору) и диапазонов IP-адресов Китая (например, доступ к bilibili, acfun).

Запуск

  • В Windows и macOS файл конфигурации обычно находится в том же каталоге, что и Xray, и называется config.json.
    • Просто запустите Xray или Xray.exe.
  • В Linux файл конфигурации обычно находится в каталоге /etc/xray/ или /usr/local/etc/xray/.
    • Запустите команду xray run -c /etc/xray/config.json.
    • Или используйте systemd или другой инструмент для запуска Xray как службы в фоновом режиме.

Более подробную информацию можно найти в документации по конфигурации и в разделе Простыми словами.

- + diff --git a/ru/document/document.html b/ru/document/document.html index 9846796159..e74c2a2349 100644 --- a/ru/document/document.html +++ b/ru/document/document.html @@ -24,14 +24,14 @@ Вклад в документацию Project X | Project X - - + +

Вклад в документацию Project X

Мы приветствуем ваш вклад в документацию Project X и благодарим каждого контрибьютора за помощь! Вы делаете Xray лучше!

Улучшение документации

Документация Project X размещена на GitHubОткрыть в новой вкладке.

Вы можете внести изменения в документацию, выполнив следующие действия:

  1. Откройте репозиторий документации Project XОткрыть в новой вкладке, нажмите кнопку "Fork" в правом верхнем углу, чтобы создать копию репозитория документации в вашей учетной записи GitHub.

  2. Используйте любой удобный инструмент для клонирования документации из вашего репозитория, например:

git clone https://github.com/XTLS/Xray-docs-next.git
 
  1. Создайте новую ветку на основе ветки main, например:
git checkout -b your-branch
 
  1. Внесите изменения в новую ветку.

    Примечание: рекомендуем придерживаться Руководства по оформлению текстов на китайском языкеОткрыть в новой вкладке (на китайском).

  2. После внесения изменений отформатируйте их с помощью PrettierОткрыть в новой вкладке.

    Примечание: запросы на включение (PR) с ошибками форматирования могут быть отклонены.

  3. Зафиксируйте изменения и отправьте их в ваш репозиторий:

git push -u origin your-branch
 
  1. Откройте GitHub, перейдите в раздел "Pull requests" и создайте новый запрос на включение (PR) в репозиторий документации Project XОткрыть в новой вкладке.

  2. В заголовке и описании PR кратко опишите внесенные изменения.

  3. Дождитесь ответа. Если ваш PR будет принят, изменения появятся на сайте документации Project XОткрыть в новой вкладке.

Нашли ошибку?

Если вы обнаружили ошибку в документации, вы можете внести исправления или создать задачу (Issue).

- + diff --git a/ru/document/index.html b/ru/document/index.html index 9530f27179..24206ba30b 100644 --- a/ru/document/index.html +++ b/ru/document/index.html @@ -24,11 +24,11 @@ Быстрый старт | Project X - - + +

Быстрый старт

В этой главе вы узнаете, как максимально просто получить Xray и начать его использовать.

Загрузка и установка

Xray поддерживает разнообразные платформы, и вы можете получить разные версии Xray из множества источников и различными способами.

Перейдите в раздел Загрузка и установка, чтобы загрузить Xray.

Настройка и запуск

После загрузки и установки Xray вам нужно всего лишь настроить его, чтобы начать использование.

Перейдите в раздел Настройка и запуск, чтобы изучить самый простой способ настройки.

Команды и аргументы

Xray обладает множеством команд и аргументов, что делает его гибким и мощным.

Перейдите в раздел Команды и аргументы, чтобы узнать больше о командах и аргументах Xray.

Улучшение документации

Если вы заинтересованы, перейдите в раздел Использование документации, чтобы помочь нам улучшить документацию, или нажмите кнопку Помогите нам улучшить эту страницу! внизу страницы.

Мы очень благодарны каждому участнику за вклад! Вы делаете Project X сильнее!

Простыми словами

Практические советы для новичков.

Перейдите в раздел Простыми словами для просмотра.

Базовые навыки

Освоив основы, вы можете перейти к разделу Базовые навыки, чтобы узнать о других способах использования.

Продвинутая документация

Практические советы для опытных пользователей.

Перейдите в раздел Продвинутая документация для просмотра.

Благодарность

Огромное спасибо всем за то, что делитесь своими навыками и опытом, которые делают Xray с каждым днем ​​лучше.

- + diff --git a/ru/document/install.html b/ru/document/install.html index 20d064fa77..142ba26278 100644 --- a/ru/document/install.html +++ b/ru/document/install.html @@ -24,11 +24,11 @@ Загрузка и установка | Project X - - + + -

Загрузка и установка

Поддерживаемые платформы

Xray доступен на следующих платформах:

  • Windows 7 и выше (x86 / amd64 / arm32 / arm64);
  • macOS 10.10 Yosemite и выше (amd64 / arm64);
  • Linux 2.6.23 и выше (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
    • Включая, но не ограничиваясь: Debian 7 / 8, Ubuntu 12.04 / 14.04 и выше, CentOS 7 / 8, Arch Linux и др.;
  • FreeBSD (x86 / amd64);
  • OpenBSD (x86 / amd64);
  • Dragonfly BSD (amd64);

Загрузка Xray

Предварительно скомпилированные ZIP-архивы с двоичными файлами можно найти в Github ReleasesОткрыть в новой вкладке.

Скачайте архив для своей платформы, распакуйте его и можете использовать.

Проверка установочного пакета

Xray предлагает два способа проверки:

  • SHA1 / SHA256 хэш-сумма ZIP-архива;
  • Воспроизводимая сборка: см. Сборка Xray.

Установка на Windows

Установка на macOS

Установка на Linux

Установочные скрипты

Arch Linux

Arch User Repository

Требуется помощник AURОткрыть в новой вкладке, например, yayОткрыть в новой вкладке, установка с помощью команды yay -S xray.

Arch Linux CN

Сначала добавьте репозиторий Arch Linux CNОткрыть в новой вкладке, затем установите от имени пользователя root с помощью команды pacman -S xray.

Linuxbrew

Использование менеджера пакетов Linuxbrew аналогично Homebrew: brew install xray.

Debian WIP

Gentoo

В настоящее время существует три оверлея сторонних разработчиков, которые предоставляют сценарии установки Portage:

Добавьте оверлей в локальную систему с помощью layman или eselect-repository, а затем выполните установку.

Установка с помощью Docker

Файловая структура образа Docker

  • /etc/xray/config.json: файл конфигурации;
  • /usr/bin/xray: основная программа Xray;
  • /usr/share/xray/geoip.dat: файл данных IP;
  • /usr/share/xray/geosite.dat: файл данных доменных имен.

Графические клиенты

Генератор UUID

Генератор UUID от сторонних разработчиков: uuidgenerator.netОткрыть в новой вкладке

- +

Warning

This translation was modified on 16 July 2024 and an updated version (14 August 2024) is available on the source page. View the original page

Загрузка и установка

Поддерживаемые платформы

Xray доступен на следующих платформах:

  • Windows 7 и выше (x86 / amd64 / arm32 / arm64);
  • macOS 10.10 Yosemite и выше (amd64 / arm64);
  • Linux 2.6.23 и выше (x86 / amd64 / arm / arm64 / mips64 / mips / ppc64 / s390x / riscv64);
    • Включая, но не ограничиваясь: Debian 7 / 8, Ubuntu 12.04 / 14.04 и выше, CentOS 7 / 8, Arch Linux и др.;
  • FreeBSD (x86 / amd64);
  • OpenBSD (x86 / amd64);
  • Dragonfly BSD (amd64);

Загрузка Xray

Предварительно скомпилированные ZIP-архивы с двоичными файлами можно найти в Github ReleasesОткрыть в новой вкладке.

Скачайте архив для своей платформы, распакуйте его и можете использовать.

Проверка установочного пакета

Xray предлагает два способа проверки:

  • SHA1 / SHA256 хэш-сумма ZIP-архива;
  • Воспроизводимая сборка: см. Сборка Xray.

Установка на Windows

Установка на macOS

Установка на Linux

Установочные скрипты

Arch Linux

Arch User Repository

Требуется помощник AURОткрыть в новой вкладке, например, yayОткрыть в новой вкладке, установка с помощью команды yay -S xray.

Arch Linux CN

Сначала добавьте репозиторий Arch Linux CNОткрыть в новой вкладке, затем установите от имени пользователя root с помощью команды pacman -S xray.

Linuxbrew

Использование менеджера пакетов Linuxbrew аналогично Homebrew: brew install xray.

Debian WIP

Gentoo

В настоящее время существует три оверлея сторонних разработчиков, которые предоставляют сценарии установки Portage:

Добавьте оверлей в локальную систему с помощью layman или eselect-repository, а затем выполните установку.

Установка с помощью Docker

Файловая структура образа Docker

  • /etc/xray/config.json: файл конфигурации;
  • /usr/bin/xray: основная программа Xray;
  • /usr/share/xray/geoip.dat: файл данных IP;
  • /usr/share/xray/geosite.dat: файл данных доменных имен.

Графические клиенты

Генератор UUID

Генератор UUID от сторонних разработчиков: uuidgenerator.netОткрыть в новой вкладке

+ diff --git a/ru/document/level-0/ch01-preface.html b/ru/document/level-0/ch01-preface.html index c3a0064389..68fae57709 100644 --- a/ru/document/level-0/ch01-preface.html +++ b/ru/document/level-0/ch01-preface.html @@ -24,11 +24,11 @@ 【Глава 1】 Простыми словами | Project X - - + +

【Глава 1】 Простыми словами

1.1 Для кого эта документация?

В двух словах: для ① новичков без опыта ② желающих научиться настраивать свой собственный VPS.

1.2 Для кого эта документация не предназначена?

В том числе, но не ограничиваясь: для всевозможных гуру и экспертов, для тех, кто слишком ленив, чтобы во всём разбираться самостоятельно, для тех, кто уже умеет настраивать VPS, для тех, кто точно решил пользоваться платными VPN-сервисами, для тех, кто предпочитает использовать готовые скрипты... Короче говоря, если у вас есть технические знания или вы не хотите настраивать всё сами, можете смело закрывать эту статью. Скорее всего, она покажется вам бесполезной и даже может вызвать раздражение, а оно вам надо?

1.3 Важное замечание и другие примечания

Важное замечание:

Я не являюсь техническим экспертом, поэтому в этой статье неизбежны пробелы и неточности. Если вы обнаружите какие-либо ошибки, пожалуйста, дайте мне знать об этом деликатно, без лишних эмоций.

Отказ от ответственности:

Пожалуйста, относитесь к информации, представленной в этой статье, критически и проверяйте её самостоятельно. Я не несу никакой ответственности за любые проблемы или негативные последствия, возникшие в результате использования информации из этой статьи.

Предупреждение о многословности:

Поскольку эта статья предназначена для новичков без опыта, многие вещи будут объяснены максимально подробно. Поэтому будьте готовы к тому, что текст будет довольно многословным.

1.4 Почему самостоятельная настройка — это сложно?

Чтобы ответить на этот вопрос, нужно немного углубиться в историю вопроса.

Во-первых, обход блокировок существует уже почти двадцать лет (Шок! Ужас!). Сначала для этого достаточно было пары манипуляций (поправить файл hosts, подключиться по SSH), потом понадобились веб-прокси, затем — собственные протоколы (например, Shadowsocks) и так далее.

По мере того, как технологии блокировок совершенствовались на протяжении последних десятилетий, для самостоятельного обхода блокировок теперь нужно уметь:

  • Разбираться в основных командах Linux.
  • Понимать принципы работы сетевых протоколов.
  • Иметь технические навыки и средства для покупки и управления VPS.
  • Иметь технические навыки и средства для покупки и управления доменными именами.
  • Уметь получать TLS-сертификаты.
  • И многое другое.

Всё это превратило некогда простую задачу в пугающее испытание для новичков.

Во-вторых, о проблемах новичков.

Начинающим пользователям без технического бэкграунда, чтобы разобраться во всех этих премудростях, приходится изучать огромные массивы информации, разбросанной по всему интернету: блогам, форумам, группам в мессенджерах, репозиториям на GitHub, видео на YouTube и так далее.

Вся эта информация часто оказывается противоречивой, неполной или попросту неверной. Новичкам остаётся только гадать, кому верить и как всё это работает на самом деле.

В итоге вместо нехватки информации новички сталкиваются с её избытком. После нескольких (скорее всего, неудачных) попыток разобраться во всём этом, их энтузиазм угасает. А если по пути им ещё и «посчастливится» обратиться за помощью не в то место, их могут ещё и высмеять: «Ну ты и нуб, проще уж платным VPN пользоваться, зачем изобретать велосипед?» или «Сначала Linux изучи, потом приходи».

В такие моменты остаётся только горько усмехнуться.

1.5 «Почему бы просто не пользоваться платным VPN?»

Во-первых, я хотел бы спросить у любителей подобных советов: разве платные VPN — это панацея?

Во-вторых, я считаю, что «не знать» и «не хотеть знать» — это две большие разницы. Конечно, инфантилы, которые хотят всё и сразу, не прилагая никаких усилий, вызывают только раздражение. Но люди, которые искренне хотят разобраться во всём сами, не заслуживают презрения и издёвок. Именно эта нетерпимость к новичкам и побудила меня написать эту статью.

Давайте разберёмся, в чём плюсы и минусы платных VPN-сервисов.

Плюсы:

  1. Простота использования: сканирование QR-кода, добавление правил в один клик и т.д.
  2. Большой выбор серверов: доступ к ресурсам разных стран и регионов; например, выделенные серверы с низкой задержкой (iplc), серверы для онлайн-игр и т.д.
  3. Множество точек подключения: выше устойчивость к блокировкам, если один сервер заблокируют, можно подключиться к другому.

Риски:

За удобство приходится платить, и в случае с платными VPN-сервисами риски следующие:

  1. VPN-провайдер имеет полный доступ к вашим данным: всё, что вы делаете в интернете, обязательно проходит и с большой вероятностью хранится на серверах провайдера. Эти данные никак не защищены пользовательским соглашением или законом о защите персональных данных (вас могут отслеживать и записывать всё, что вы делаете).
  2. Отсутствие регулирования рынка: высока вероятность нарваться на мошенников (провайдер может в любой момент исчезнуть с вашими деньгами).
  3. Давление со стороны регулирующих органов: крупные VPN-провайдеры, с одной стороны, кажутся более надёжными, но, с другой стороны, чаще привлекают к себе внимание властей. В 2020 году было несколько случаев закрытия и прекращения работы крупных VPN-провайдеров, что привело к серьёзным неудобствам для пользователей (провайдер может быть вынужден прекратить работу).
  4. Непрозрачность технических решений: качество предоставляемых услуг может сильно варьироваться, не редки случаи обмана (низкая скорость, частые обрывы связи, невозможность подключения).

1.6 Так стоит ли настраивать VPN самостоятельно?

Теперь, когда вы знаете о плюсах и минусах платных VPN, решать вам. В конце концов, лучший вариант — тот, который подходит именно вам.

Выбор за вами!

  1. Если вы решили воспользоваться платным VPN, можете закрыть эту статью.

  2. Если же вы решили настроить всё самостоятельно, продолжайте чтение!

Цель этой статьи — стать отправной точкой для новичков, предоставить подробное пошаговое руководство по настройке VPN-сервера на VPS, начиная с ввода первой команды и заканчивая успешным подключением к заблокированным ресурсам.

В процессе настройки вы познакомитесь с основными командами Linux, что станет хорошей базой для дальнейшего изучения этой операционной системы.

1.7 Немного лирики

  1. В интернете много дезинформации, поэтому важно научиться критически мыслить, не поддаваться на провокации и не верить всему, что пишут.
  2. Искренне надеюсь, что, получив доступ к свободному интернету, вы сможете узнавать больше нового, наслаждаться разнообразным контентом, знакомиться с интересными людьми и находить единомышленников.
  3. Ваша личность в интернете — это всё ещё вы. Добиться полной анонимности крайне сложно, поэтому не забывайте о законах вашей страны и стран, IP-адреса которых вы используете. Всегда помните о собственной безопасности.

1.8 Ваш прогресс

⬛⬜⬜⬜⬜⬜⬜⬜ 12.5%

- + diff --git a/ru/document/level-0/ch02-preparation.html b/ru/document/level-0/ch02-preparation.html index efa98c5f61..c517082936 100644 --- a/ru/document/level-0/ch02-preparation.html +++ b/ru/document/level-0/ch02-preparation.html @@ -24,11 +24,11 @@ 【Глава 2】 Подготовка | Project X - - + +

【Глава 2】 Подготовка

Эта глава особенная, поскольку затрагивает финансовые операции. В соответствии с нейтральной позицией проекта, здесь не будет конкретных рекомендаций. Всё, что я могу сделать, — это рассказать, что вам понадобится.

2.1 Приобретение VPS

Вам нужно получить работающий VPS с не заблокированным IP-адресом и выполнить следующие базовые действия в панели управления:

  1. Установить на VPS операционную систему Debian 10 64-bit.
  2. Записать IP-адрес VPS (в этой статье он будет обозначаться как "100.200.300.400").

    Подсказка

    Это неверный IP-адрес, используемый только в качестве примера. Не забудьте заменить его на свой реальный IP-адрес.

  3. Записать порт (Port) SSH для удалённого подключения к VPS.
  4. Записать имя пользователя и пароль для удалённого подключения по SSH.

Выбор и покупка VPS — дело непростое. Рекомендуем сначала изучить этот вопрос и выбрать тариф, который соответствует вашим финансовым возможностям и требованиям к скорости и качеству связи. Также можно воспользоваться бесплатными (постоянными или временными) предложениями от крупных облачных провайдеров, таких как Oracle Cloud и Google Cloud. Главное — не влезайте в долги.

Пояснение

Несколько слов о выборе Debian 10 в качестве операционной системы. Что бы вы ни слышали в интернете, какой бы дистрибутив Linux ни советовали вам гуру, все эти споры о том, какой Linux лучше, не имеют к вам никакого отношения! Debian 10 — это надёжная и стабильная операционная система, которая отлично подходит для работы VPN-сервера и достаточно оптимизирована (например, имеет специальное ядро для облачных сред и своевременную поддержку BBR). Когда вы освоитесь с Linux, можете попробовать и другие дистрибутивы.

2.2 Выбор доменного имени

Вам нужно получить доменное имя и добавить A-запись, указывающую на IP-адрес вашего VPS, в настройках DNS.

  1. Выберите надёжного международного регистратора доменных имён. Доменная зона (расширение домена) может быть любой, главное — не используйте .cn.
  2. В настройках DNS добавьте A-запись, указывающую на IP-адрес вашего VPS (имя A-записи может быть любым, в этой статье оно будет обозначаться как "a-name". Полное доменное имя будет выглядеть как "a-name.yourdomain.com"). Должно получиться примерно так:

Добавление A-записи

Подсказка

Это не настоящий URL-адрес. Не забудьте заменить его на свой реальный адрес.

2.3 Необходимое программное обеспечение

  1. SSH-клиент для удалённого подключения:

  2. Программа для передачи файлов:

  3. Хороший текстовый редактор:

2.4 Ваш прогресс

Если вы выполнили все пункты из этого раздела, у вас уже есть всё необходимое, чтобы открыть для себя новый мир. Так чего же мы ждём? Давайте перейдём к следующей главе и сделаем это!

⬛⬛⬜⬜⬜⬜⬜⬜ 25%

- + diff --git a/ru/document/level-0/ch03-ssh.html b/ru/document/level-0/ch03-ssh.html index b9430ef0b5..b29144ede6 100644 --- a/ru/document/level-0/ch03-ssh.html +++ b/ru/document/level-0/ch03-ssh.html @@ -24,13 +24,13 @@ 【Глава 3】 Удалённое подключение | Project X - - + +

【Глава 3】 Удалённое подключение

3.1 Удалённое подключение к VPS (PuTTY)

Во-первых, поскольку Windows является самой распространённой операционной системой среди новичков, в этой статье мы будем использовать её в качестве примера.

Во-вторых, хотя PowerShell и WSL в Windows 10 и выше также предоставляют удобные инструменты для работы по SSH, не все версии Windows имеют эти компоненты. Поэтому в этой статье мы рассмотрим подключение по SSH с помощью старого доброго PuTTY. (После подключения по SSH действия во всех программах будут одинаковыми.)

Итак, давайте начнём.

  1. Перейдите на официальный сайтОткрыть в новой вкладке PuTTY и скачайте версию, подходящую для вашей операционной системы (в этой статье мы будем использовать 64-битную версию).

    Скачать PuTTY

  2. Запустите PuTTY. Откроется главное окно программы. Теперь возьмите блокнот, в который вы записывали информацию в предыдущей главе, и введите IP-адрес и порт вашего VPS в соответствующие поля (на скриншоте ниже). Чтобы не вводить эти данные каждый раз, можно сохранить сеанс (Saved Sessions). В дальнейшем вы сможете загрузить сохранённые настройки одним кликом.

    Настройка PuTTY

  3. Рекомендуем установить значение keepalive в разделе Connection равным 60 секундам, чтобы предотвратить разрыв SSH-соединения, если вы долгое время не будете выполнять никаких действий. Не забудьте снова сохранить настройки.

    Предотвращение разрывов соединения

Внимание

После любых изменений настроек PuTTY необходимо сохранить сеанс, иначе они будут потеряны при закрытии программы.

  1. Нажмите кнопку "Open", чтобы открыть окно SSH-подключения. Введите имя пользователя и пароль для подключения к вашему VPS (в этой статье предполагается, что имя пользователя по умолчанию — root. Обратите внимание, что при вводе пароля в Linux не отображаются символы ******. Это сделано для того, чтобы скрыть длину пароля. Не пугайтесь, ваша клавиатура в порядке!).

    Подключение по SSH

3.2 Успешное подключение по SSH! Знакомство с командной строкой!

  1. Если вы всё сделали правильно, вы увидите примерно такой экран, как на рисунке ниже. Это означает, что вы успешно подключились к серверу:

    Первое подключение к VPS

    Этот экран — аналог «рабочего стола» на удалённом сервере, но здесь нет привычных значков, курсора мыши и ярких цветов. Только текст. Это и есть командная строкаCommand Line Interface или сокращённо CLI.

    Все дальнейшие действия вам придётся выполнять в командной строке, как хакер в кино. Возможно, поначалу это покажется вам непривычным, но поверьте, в использовании командной строки нет ничего страшного или сложного. По сути, это всего лишь способ взаимодействия с компьютером с помощью текстовых команд вместо графического интерфейса. Вы пишете команду, а компьютер её выполняет.

  2. Теперь можете немного осмотреться и познакомиться с командной строкой. На этом экране уже есть полезная информация, например, версия ядра системы (в данном случае 4.19.37-5), время последнего входа в систему, IP-адрес и т.д. Конечно, в зависимости от VPS, ваш экран может выглядеть немного иначе.

  3. Обратите внимание на последнюю строку командной строки. Слева от мигающего курсора находится набор символов. В данном случае это root@vps-server:~#. Что это значит? Всё просто:

    • Текущий пользователь: root.
    • Имя сервера, на котором работает пользователь root: vps-server.
    • Текущий каталог, в котором находится пользователь root: ~.
    • Символ # указывает на то, что после него можно вводить команды.

    Первые два пункта интуитивно понятны и не требуют пояснений. Третий пункт относится к файловой системе Linux. Сейчас вам не нужно вдаваться в подробности, достаточно знать, что ~ — это «домашний каталог» текущего пользователя. Четвёртый пункт, символ #, также не требует особого внимания. Просто знайте, что в дальнейшем все команды, которые вам нужно будет вводить, будут начинаться с # или $. Это будет означать, что после этого символа нужно ввести команду (поэтому при копировании команд копируйте только текст после, без символа # или $).

3.3 Первое обновление программного обеспечения Linux!

  1. Так же, как и ваш телефон, будь то Android или iPhone, Linux нуждается в регулярном обновлении программного обеспечения для получения исправлений безопасности и новых функций. В Linux каждое приложение называется «пакетом» (package). А программа, которая управляет пакетами, называется «менеджером пакетов» (Package Manager). С помощью менеджера пакетов можно устанавливать, обновлять и удалять программы, а также обновлять саму систему Linux. Менеджеры пакетов Linux очень мощные, но сейчас вам достаточно знать, что в Debian используется менеджер пакетов apt. Давайте обновим систему с помощью apt, чтобы вы познакомились с его основными функциями.

  2. Базовые команды Linux:

    НомерКомандаОписание
    cmd-01apt updateПроверить обновления
    cmd-02apt upgradeУстановить обновления
  3. Введите первую команду, чтобы получить информацию об обновлениях:

    apt update
     
  4. Затем введите вторую команду. При появлении запроса на подтверждение установки (Y/n) введите y и нажмите Enter, чтобы начать установку.

    apt upgrade
     
  5. Весь процесс показан на гифке ниже:

    Демонстрация процесса обновления

3.4 Ваш прогресс

Поздравляем, вы сделали ещё один важный шаг! Теперь вы умеете подключаться к своему серверу по SSH! Но что делать после подключения, кроме обновления системы? Узнаем в следующей главе!

⬛⬛⬛⬜⬜⬜⬜⬜ 37.5%

- + diff --git a/ru/document/level-0/ch04-security.html b/ru/document/level-0/ch04-security.html index 04ee533c53..70589abebe 100644 --- a/ru/document/level-0/ch04-security.html +++ b/ru/document/level-0/ch04-security.html @@ -24,8 +24,8 @@ 【Глава 4】 Обеспечение безопасности | Project X - - + +

【Глава 4】 Обеспечение безопасности

4.1 Зачем нужна безопасность?

Безопасность Linux-серверов — это обширная и сложная тема. Бесчисленные веб-сайты, приложения, сервисы и даже критически важная инфраструктура построены на базе Linux. За всем этим стоят огромные деньги и коммерческие интересы, что, естественно, привлекает злоумышленников. В то же время надёжная работа этих сервисов крайне важна, поэтому любые серьёзные уязвимости недопустимы. Именно поэтому множество специалистов по безопасности изо дня в день ведут борьбу на передовой, обеспечивая стабильную работу цифрового мира, к которому мы все привыкли.

Теперь, когда у вас есть собственный VPS-сервер, и вы собираетесь открыть на нём порты для перенаправления трафика, вы фактически оказываетесь на передовой этой борьбы и подвергаетесь тем же рискам. В то же время, новички, не обладающие достаточными знаниями и информацией, склонны впадать в крайности: либо они считают, что им ничего не угрожает, либо же, наоборот, впадают в паранойю.

  • Первым я бы посоветовал не относиться к безопасности легкомысленно и изучить этот вопрос более подробно, чтобы потом не пришлось кусать локти.

  • Вторым я бы посоветовал не паниковать. Ваш сервер вряд ли представляет собой лакомую цель для серьёзных злоумышленников, поэтому вам достаточно базовых мер защиты от автоматических сканеров и ботов, о которых мы и поговорим в этой главе.

4.2 Какие именно риски существуют?

Как мы уже говорили в главе про удалённое подключение, для доступа к вашему VPS достаточно знать четыре вещи: IP-адрес, порт, имя пользователя и пароль. Очевидно, что эти четыре элемента нужно защищать в первую очередь. Давайте разберём каждый из них:

  1. IP-адрес: злоумышленники могут сканировать целые диапазоны IP-адресов в поисках уязвимых серверов. Ваш IP-адрес — это публичная информация, которую невозможно скрыть.

  2. Порт: если вы используете настройки по умолчанию, то порт SSH равен 22.

  3. Имя пользователя: если вы используете настройки по умолчанию, то имя пользователя — root.

  4. Пароль: пароль не имеет значения по умолчанию. Он либо генерируется автоматически при создании VPS, либо задаётся вами. Таким образом, если вы не меняли настройки сервера, то три из четырёх элементов уже известны злоумышленникам, и вся безопасность вашего сервера держится на одном только пароле. Возможны следующие варианты:

    • Вы используете автоматически сгенерированный пароль из панели управления VPS. Такие пароли обычно состоят из случайного набора символов (букв в разных регистрах, цифр и спецсимволов) и достаточно надёжны.

    • Вы установили простой пароль, например, 123456. Взломать такой сервер не составит труда.

    • Вы установили сложный пароль, который используете где-то ещё. Это тоже небезопасно. Злоумышленники используют специальные программы, которые перебирают миллионы ранее скомпрометированных паролей из утечек данных.

  5. Важно понимать, что никакой хакер не будет лично подбирать ваш пароль. Все атаки выполняются автоматически с помощью специальных скриптов, которые работают круглосуточно. Пока вы спите, ваш сервер может подвергаться атакам.

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

  6. Не забывайте, что при покупке VPS вы, скорее всего, указывали свои реальные платёжные данные. А при посещении сайтов и использовании социальных сетей ваш IP-адрес также сохраняется. Всё это может быть использовано против вас. Поэтому, если на вашем сервере произойдёт что-то противозаконное, отвечать за это придётся вам.

4.3 Какие меры безопасности нужно предпринять?

Исходя из всего вышесказанного, нам нужно защитить порт, имя пользователя и пароль, чтобы снизить риск взлома. Для этого необходимо:

  1. Изменить порт SSH на нестандартный (отличный от 22) (см. раздел 4.4).
  2. Создать нового пользователя (не root) и запретить удалённое подключение по SSH для пользователя root (см. разделы 4.5 и 4.6).
  3. Настроить аутентификацию по SSH-ключам и запретить аутентификацию по паролю (см. раздел 4.7).

Выполняйте эти действия по порядку, чтобы не оказаться случайно заблокированным на своём же сервере.

4.4 Изменение порта SSH

Давайте решим проблему с портом SSH, который по умолчанию равен 22 (обратите внимание: у некоторых хостинг-провайдеров порт SSH по умолчанию уже отличается от 22. В этом случае вы можете пропустить этот шаг, но можете и изменить порт ещё раз, следуя инструкциям ниже).

  1. Базовые команды Linux:

    НомерКомандаОписание
    cmd-03nanoТекстовый редактор
    cmd-04systemctl restartПерезапуск службы
  2. Важные файлы конфигурации Linux:

    НомерПуть к файлуОписание
    conf-01/etc/ssh/sshd_configНастройки SSH-сервера
  3. Первое, что нужно сделать, — это открыть файл настроек SSH-сервера (/etc/ssh/sshd_config) в текстовом редакторе nano. В Windows вы бы просто нашли этот файл и дважды кликнули по нему. А как это сделать в Linux? Если вы внимательно читали предыдущие разделы, то наверняка уже догадались! Правильно, нужно выполнить команду:

    nano /etc/ssh/sshd_config
    @@ -40,6 +40,6 @@
     
  4. Откройте файл настроек SSH. Мы уже делали это раньше, но теперь мы работаем не под пользователем root, а под пользователем vpsadmin. У этого пользователя нет прав на редактирование системных файлов, поэтому нужно использовать команду sudo:

    sudo nano /etc/ssh/sshd_config
     
  5. Найдите (Ctrl+W) строку PasswordAuthentication и измените значение на no.

  6. Найдите (Ctrl+W) строку PubkeyAuthentication и измените значение на yes. Сохраните изменения (Ctrl+O) и выйдите из редактора (Ctrl+X).

  7. Перезапустите SSH-сервер (не забудьте, что теперь вам нужно использовать команду sudo):

    sudo systemctl restart ssh
     
  8. Весь процесс показан на гифке ниже:

    Включение аутентификации по ключам и отключение аутентификации по паролю

  • Теперь, когда на сервере настроен публичный ключ, нужно указать PuTTY путь к приватному ключу (не забудьте сохранить сеанс!).

    Путь к приватному ключу в PuTTY

  • Готово! Теперь у вас настроена аутентификация по SSH-ключам, а аутентификация по паролю отключена. Кроме того, вы сохранили имя пользователя и путь к приватному ключу в сеансе PuTTY. Теперь для подключения к VPS достаточно будет выбрать сохранённый сеанс VPS-SERVER и нажать кнопку «Open».

    Если вы установили пароль для защиты приватного ключа, вам нужно будет ввести его при подключении, как показано на скриншоте ниже:

    Парольная фраза для приватного ключа

  • Не забудьте настроить аутентификацию по ключам и в WinSCP. В противном случае вы не сможете подключаться к серверу для передачи файлов:

    Путь к приватному ключу в WinSCP

  • Внимание

    Теперь для подключения к вашему серверу по SSH требуется авторизация по ключам. Мы рассмотрели настройку PuTTY и WinSCP, но существует множество других программ, которые также используют SSH. Настройте их самостоятельно при необходимости.

    4.8 Ваш прогресс

    На этом этапе ваш VPS защищён базовыми мерами безопасности. Конечно, это не панацея, но большинство автоматизированных атак вам уже не страшны!

    Теперь у нас есть надёжный фундамент, и в следующей главе мы можем приступить к установке и настройке необходимых компонентов Xray (а именно, веб-сервера и SSL-сертификата).

    ⬛⬛⬛⬛⬜⬜⬜⬜ 50%

    - + diff --git a/ru/document/level-0/ch05-webpage.html b/ru/document/level-0/ch05-webpage.html index fb77468cda..1fedd37c4e 100644 --- a/ru/document/level-0/ch05-webpage.html +++ b/ru/document/level-0/ch05-webpage.html @@ -24,8 +24,8 @@ 【Глава 5】 Создание веб-сайта | Project X - - + +

    【Глава 5】 Создание веб-сайта

    5.1 Зачем нужен веб-сайт?

    Начинающие пользователи могут задаться вопросом: зачем создавать веб-сайт для обхода блокировок? Я не программист, это же сложно?

    Начнём с первого вопроса. Веб-сайт нужен для того, чтобы:

    1. Получить действующий SSL-сертификат (это очень важно).
    2. Обеспечить маскировку трафика (fallback) и защититься от атак, направленных на выявление VPN-серверов.
    3. Создать сайт-прикрытие (например, блог, облачное хранилище, медиа-портал, игровой сайт), который будет отображаться при прямом доступе к серверу, делая использование VPN менее заметным.

    Теперь ответим на второй вопрос:

    1. В этой статье мы создадим максимально простой веб-сайт, состоящий из одного HTML-файла и работающий на веб-сервере Nginx, чтобы решить поставленные выше задачи. Это очень просто.
    2. Этот веб-сайт не обязательно должен быть просто прикрытием. Вы можете развивать его и превратить в полноценный проект. Всё зависит от ваших желаний и возможностей.
    3. Создание сайта-прикрытия и его продвижение — это отдельная большая тема, которая выходит за рамки этой статьи. Если вам интересно, вы можете найти информацию об этом в интернете.

    5.2 Подключение к VPS и установка Nginx

    1. В этом разделе мы будем использовать команды, которые уже были подробно рассмотрены ранее. Если вы что-то не понимаете, вернитесь и перечитайте предыдущие главы.

      sudo apt update && sudo apt install nginx
      @@ -90,6 +90,6 @@
               }
       

      Важно!

      Как уже говорилось в 3-м шаге, убедитесь, что путь /home/vpsadmin/www/webpage соответствует реальному пути к вашему файлу.

    2. Перезагрузите Nginx, чтобы применить изменения.

      sudo systemctl reload nginx
       
    3. Весь процесс настройки показан на гифке ниже:

      Настройка веб-сайта

    4. Теперь, если вы откроете в браузере адрес http://поддомен.ваш_домен.com, вы должны увидеть созданную нами страницу:

      Веб-сайт работает

    5.4 Распространённые ошибки

    Вообще, если вы внимательно следовали инструкциям, ошибок быть не должно. Однако на этом этапе многие пользователи сталкиваются с проблемами. В чём же дело? Ответ прост: невнимательность. Здесь возможны только две ошибки, и обе они связаны с невнимательностью.

    Ошибки:

    • Путь /home/vpsadmin/www/webpage в файле nginx.conf не соответствует реальному пути к файлу index.html. Nginx не может найти файл.
    • Путь указан верно, но у Nginx нет прав на чтение файла.

    Причины:

    • Вы работаете не под пользователем root, но скопировали команды из статьи без изменений (как будто списали домашнее задание вместе с именем одноклассника).
    • Вы работаете под пользователем root.

    Если у вас возникли проблемы, вернитесь к разделу 5.3 и внимательно перечитайте пункты 3 и 6.2.

    Внимание

    В предыдущих главах мы много говорили о важности использования пользователя, отличного от root, и вся статья написана с учётом этого. Поэтому проблемы, связанные с использованием root, не рассматриваются в рамках этой статьи.

    Однако я уверен, что те, кто всё-таки работает под root, достаточно опытны и смогут решить эти проблемы самостоятельно.

    5.5 Ваш прогресс

    Первый компонент Xray — веб-сайт — готов. Давайте перейдём ко второму компоненту — SSL-сертификату!

    ⬛⬛⬛⬛⬛⬜⬜⬜ 62.5%

    - + diff --git a/ru/document/level-0/ch06-certificates.html b/ru/document/level-0/ch06-certificates.html index 6b96924717..62fba0e397 100644 --- a/ru/document/level-0/ch06-certificates.html +++ b/ru/document/level-0/ch06-certificates.html @@ -24,8 +24,8 @@ 【Глава 6】 Управление сертификатами | Project X - - + +

    【Глава 6】 Управление сертификатами

    6.1 Получение SSL-сертификата

    Теперь нам нужно получить действующий SSL-сертификат для нашего доменного имени, чтобы веб-сайт работал по протоколу HTTPS. Это важнейший инструмент для обеспечения безопасности трафика при использовании современных VPN-сервисов, таких как Xray.

    Внимание

    Не используйте самоподписанные сертификаты. Это ненамного упростит задачу, но создаст дополнительные риски (например, возможность атак типа «человек посередине»).

    Мы будем использовать инструмент для управления сертификатами acme.shОткрыть в новой вкладке. Он простой, лёгкий, эффективный и умеет автоматически обновлять сертификаты.

    Я уверен, что вы уже освоились с базовыми командами Linux, поэтому скриншоты с выводом команд, которые мы уже использовали ранее, будут опущены. Если вы забыли, как выполнять ту или иную команду, вернитесь и перечитайте предыдущие главы.

    6.2 Установка acme.sh

    1. Базовые команды Linux:

      НомерКомандаОписание
      cmd-12wgetЗагрузка файла из интернета
      cmd-13acme.shУправление сертификатами
    2. Запустите скрипт установки:

      wget -O -  https://get.acme.sh | sh
      @@ -136,6 +136,6 @@
       [Mon 14 Feb 2022 03:00:25 PM CST] Installing key to: /etc/xray/cert/cert.key
       [Mon 14 Feb 2022 03:00:25 PM CST] Installing full chain to: /etc/xray/cert/fullchain.crt
       

    6.6 Ваш прогресс

    Наконец-то все необходимые компоненты Xray готовы! Мы подошли к самому интересному — установке и настройке самого Xray!

    ⬛⬛⬛⬛⬛⬛⬜⬜ 75%

    - + diff --git a/ru/document/level-0/ch07-xray-server.html b/ru/document/level-0/ch07-xray-server.html index 20e3cee8fc..6ad35996ef 100644 --- a/ru/document/level-0/ch07-xray-server.html +++ b/ru/document/level-0/ch07-xray-server.html @@ -24,8 +24,8 @@ 【Глава 7】Настройка Xray на сервере | Project X - - + +

    【Глава 7】Настройка Xray на сервере

    7.1 Познать многое, усвоить нужное; копить постепенно, тратить осмотрительно

    Во время написания этого руководства один знакомый в шутку заметил: "Твое руководство уже 6 глав публикуется, а до Xray всё никак не дойдёт. Кто не знает, подумает, что это руководство "Создание сайта с нуля". (И ведь не поспоришь! 😂)

    На самом деле такая структура — результат моего осознанного решения. Ведь только заложив прочный фундамент, можно в дальнейшем двигаться вперёд семимильными шагами. Я видел в чатах много новичков, которые не могут правильно использовать даже nano, не говоря уже о WinSCP. Из-за этого их config.json, написанные вручную на удалённом сервере, пестрят ошибками, а поиск и исправление этих ошибок превращается в мучение.

    Внимание

    Пройдя первые 6 глав, мы вместе с вами преодолели несколько важных этапов: освоили базовые операции Linux, научились удалённо управлять VPS, разобрались с установкой веб-сервера, управлением доменными именами, получением SSL-сертификатов. Оглядываясь назад, разве всё это кажется таким уж сложным? Теперь, имея такой солидный багаж знаний, мы подойдём к установке и настройке Xray с чувством лёгкости и уверенности, ведь всё уже готово!

    Дальнейшие шаги предельно просты:

    1. Установка
    2. Настройка (например, установка TLS-сертификата, настройка config.json)
    3. Запуск
    4. Оптимизация (например, обновление ядра, включение bbr, автоматическое перенаправление http-запросов на https и т. д.)

    7.2 Установка Xray

    Xray основан на проекте с открытым исходным кодом xray-coreОткрыть в новой вкладке (лицензия MPL 2.0). Запущенный на сервере, скомпилированный бинарный файл этого проекта, работает как серверная часть Xray; запущенный на локальном компьютере, он становится клиентской частью. Основное различие заключается в конфигурации.

    Для установки воспользуемся официальным скриптом. Он предлагает несколько вариантов установки. Вы можете ознакомиться с ними в репозитории скриптовОткрыть в новой вкладке. В данном руководстве мы будем использовать установку от имени непривилегированного пользователя.

    На момент написания руководства в скрипте есть небольшая ошибка при установке от имени непривилегированного пользователя, поэтому мы выполним эти шаги вручную. Заодно рассмотрим команду удаления файлов в Linux.

    1. Базовые команды Linux:

      НомерКомандаОписание
      cmd-14rmУдаление файлов
    2. Скачиваем установочный скрипт:

      wget https://github.com/XTLS/Xray-install/raw/main/install-release.sh
      @@ -187,6 +187,6 @@
       
    3. Изменяем настройки перенаправления в файле конфигурации Xray, заменив порт 80 на 8080 (находим "dest": 80 и меняем на "dest": 8080):

      sudo nano /usr/local/etc/xray/config.json
       
    4. Перезапускаем Xray:

      sudo systemctl restart xray
       
    5. Весь процесс показан на гифке:

      Автоматическое перенаправление HTTP на HTTPS

    6. Теперь, если вы попытаетесь открыть сайт по адресу http://sub.yourdomain.com, он должен автоматически перенаправиться на HTTPS:

      Проверка автоматического перенаправления HTTP на HTTPS

    7.9 Оптимизация сервера: более гибкая настройка перенаправления

    Если вам нужны более гибкие настройки перенаправления, обратитесь к статье «Разбор функции Fallback».

    7.10 Ваши успехи

    Поздравляю! На этом этапе у вас есть работающий сервер с обходом блокировок и сайт-приманка, который защитит вас от сканирования. Теперь достаточно установить клиентское приложение на ваше устройство — и можно наслаждаться свободным интернетом!

    ⬛⬛⬛⬛⬛⬛⬛⬜ 87.5%

    7.11 Важные исправления

    1. В первоначальной версии руководства был указан неверный путь к файлу конфигурации Xray (config.json). Если вы настроили Xray по старой инструкции, то он не запустится. Приносим извинения за неудобства!

      • Верный путь: /usr/local/etc/xray/config.json
      • Неверный путь: /usr/local/etc/config.json

      Затронутые разделы:

      • 7.4 Настройка Xray - 3. Создание файла конфигурации Xray с помощью nano
      • 7.8 Оптимизация сервера: автоматическое перенаправление HTTP на HTTPS - 6. Изменяем настройки перенаправления в файле конфигурации Xray
    2. В первоначальной версии руководства была ошибка в настройках Nginx (неверный путь к папке с файлами сайта). Если вы настроили Nginx по старой инструкции, то сайт не будет работать. Приносим извинения за неудобства!

      • Верный путь: root /home/vpsadmin/www/webpage;
      • Неверный путь: root /var/www/website/html

      Затронутые разделы:

      • 7.8 Оптимизация сервера: автоматическое перенаправление HTTP на HTTPS - 4. Добавляем новый сервер, который будет прослушивать локальный порт и отдавать файлы сайта.
    - + diff --git a/ru/document/level-0/ch08-xray-clients.html b/ru/document/level-0/ch08-xray-clients.html index 1bc242ad95..3f30013b7c 100644 --- a/ru/document/level-0/ch08-xray-clients.html +++ b/ru/document/level-0/ch08-xray-clients.html @@ -24,8 +24,8 @@ 【Глава 8】Настройка Xray на клиенте | Project X - - + +

    【Глава 8】Настройка Xray на клиенте

    8.1 Как работает Xray: краткое описание

    Чтобы правильно настраивать и использовать Xray, важно понимать принципы его работы. Новичкам поможет упрощённая схема, на которой не показаны некоторые сложные моменты:

    Поток данных в Xray

    Ключевые моменты:

    1. Приложение должно самостоятельно или с помощью стороннего инструмента перенаправить трафик на входящее подключение (inbounds) клиента Xray.

    2. Поступивший на клиент трафик обрабатывается модулем маршрутизации (routing) в соответствии с заданными правилами и перенаправляется на разные исходящие подключения (outbounds) клиента Xray, например:

      • Трафик на китайские ресурсы — напрямую (direct)
      • Трафик на зарубежные ресурсы — через VPS (proxy)
      • Рекламный трафик — блокируется (block)
    3. Трафик на зарубежные ресурсы, перенаправленный на VPS, проходит через Великий Китайский Файрвол и попадает на входящее подключение (inbounds) сервера Xray.

    4. Как и на клиенте, трафик, поступивший на сервер, обрабатывается модулем маршрутизации (routing) в соответствии с заданными правилами и перенаправляется на разные исходящие подключения (outbounds):

      • Поскольку сервер находится за пределами Китая, трафик по умолчанию идёт напрямую, что позволяет получить доступ к заблокированным ресурсам (direct).
      • При необходимости можно настроить перенаправление трафика на другие VPS (proxy).
      • На сервере также можно блокировать нежелательный трафик, например, рекламу или торренты (block).

    Внимание!

    Важно помнить, что маршрутизация в Xray очень гибкая, и описанный выше сценарий — лишь один из множества возможных.

    Используя файлы geosite.dat и geoip.dat, можно очень гибко управлять маршрутизацией трафика по доменным именам и IP-адресам. Это гораздо удобнее, чем устаревший GFWList, поскольку позволяет очень точно настроить правила: например, можно разрешить прямое подключение к доменам Apple, перенаправить трафик на домены Amazon через прокси-сервер, блокировать доступ к доменам Baidu и т. д.

    Более подробно о маршрутизации в Xray читайте в статье «Разбор функции маршрутизации (routing)». Советую сначала дочитать эту главу и настроить базовый клиент, а потом уже углубляться в тонкости маршрутизации.

    8.2 Подключение клиента к серверу

    Теперь, когда вы понимаете принципы работы Xray, настройка клиента сводится к тому, чтобы сообщить ему, как подключиться к вашему VPS. Это как настроить PuTTY для подключения к серверу, только в случае с Xray параметров подключения больше, чем IP-адрес, порт, имя пользователя и пароль.

    Набор параметров подключения в Xray зависит от используемого протокола. В главе 7 мы настроили сервер на использование протокола VLESS с шифрованием XTLS. Посмотрим на файл конфигурации сервера, чтобы узнать, какие параметры нужны для подключения:

    • Адрес сервера: sub.yourdomain.com
    • Порт сервера: 443
    • Протокол: vless
    • Поток: xtls-rprx-vision (режим vision подходит для всех платформ)
    • Идентификатор: uuiduuid-uuid-uuid-uuid-uuiduuiduuid
    • Безопасность: "allowInsecure": false

    Ниже приведен список популярных клиентов Xray для мобильных и настольных устройств. Каждый клиент имеет свой собственный интерфейс, поэтому я не буду делать скриншоты для каждого из них. Внимательно изучите документацию к выбранному клиенту и укажите нужные параметры подключения.

    Внимание!

    Многие клиенты поддерживают как xray-core, так и v2fly-core. Но по умолчанию может использоваться не тот, который вам нужен. Убедитесь, что вы выбрали нужный инструмент!

    На этом этапе ваша система готова к работе!

    8.3 Дополнительное задание 1: настройка xray-core на ПК вручную

    Хотя на предыдущем шаге мы уже всё настроили, любознательным и обладающим хорошей памятью читателям наверняка вспомнятся мои слова из предыдущей главы о том, что xray-core можно запускать как на сервере, так и на клиенте. Так как же использовать xray-core в качестве клиента?

    Чтобы ответить на этот вопрос, я добавил этот раздел с дополнительным заданием. Оно немного выходит за рамки основного материала и может показаться сложным, но у него есть свои преимущества:

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

    Недостаток этого способа заключается в том, что вам придётся настраивать клиент вручную, редактируя файл конфигурации. Но ведь на сервере вы уже делали это, так что ничего сложного здесь нет. Давайте разберёмся по шагам:

    1. Скачайте последнюю версию xray-core для вашей платформы из репозитория на GitHubОткрыть в новой вкладке и распакуйте архив в удобное место.

    2. Создайте пустой файл конфигурации config.json в той же папке (думаю, с этим проблем не возникнет).

    3. Что значит "удобное место"? Это зависит от платформы.

    4. Заполните файл конфигурации.

      • Я написал пример конфигурации, основанный на схеме из раздела 8.1 (прямое подключение к китайским ресурсам, проксирование трафика на зарубежные ресурсы через VPS, блокировка рекламы) и параметрах подключения из раздела 8.2.
      • Замените uuid на идентификатор из вашей конфигурации сервера.
      • Замените address на доменное имя вашего сервера.
      • Замените serverName на доменное имя вашего сервера.
      • Я добавил подробные комментарии к каждому разделу конфигурации.
      // ССЫЛКИ:
      @@ -183,6 +183,6 @@
       

    8.4 Дополнительное задание 2: запуск xray-core на ПК

    Итак, мы создали файл конфигурации. Как теперь запустить xray-core? Двойной клик по файлу не работает!

    Во-первых, вам нужно открыть командную строку.

    1. Пользователи Linux и macOS наверняка знают, как это сделать. Просто найдите приложение «Терминал».
    2. В Windows используйте «Командную строку» или PowerShell (пользователи WSL, можете использовать привычный вам «Терминал»).

    Во-вторых, нам нужно указать xray путь к файлу конфигурации config.json и запустить его.

    1. В Windows, если файл xray.exe находится в папке C:\Xray-windows-64\, а файл config.json — в той же папке, то команда запуска будет выглядеть так:

      C:\Xray-windows-64\xray.exe -c C:\Xray-windows-64\config.json
       

      Подсказка

      Параметр -c указывает путь к файлу конфигурации.

    2. Аналогично, в Linux и macOS, если файл xray находится в папке /usr/local/bin/, а файл config.json — в папке /usr/local/etc/xray/, то команда запуска будет выглядеть так:

      /usr/local/bin/xray -c /usr/local/etc/xray/config.json
       

      Подсказка

      В каждом системе есть переменные окружения, которые хранят пути к часто используемым папкам. Поэтому указывать полный путь к файлу xray не обязательно. Но я всё же указал его для надёжности.

    8.5 Дополнительное задание 3: автозапуск xray-core на ПК

    Если вы попробовали запускать xray-core вручную, то наверняка заметили следующие недостатки:

    1. При каждом запуске Xray открывается чёрное окно консоли, что не очень красиво.
    2. Xray не запускается автоматически при загрузке системы, поэтому его приходится запускать вручную каждый раз.

    Спешу вас обрадовать: эти проблемы решаемы! Но как именно их решить, я оставлю вам в качестве домашнего задания (подсказка: загляните в раздел FAQ на сайте документации).

    8.6 Финишная прямая!

    Уверен, что те, кто дочитал до этого места, — это любознательные и целеустремлённые люди, которые готовы учиться новому! Я от всей души поздравляю вас, ведь вы самостоятельно, начиная с самых азов, настроили сервер VPS и клиент Xray! Это огромная победа!

    Надеюсь, теперь вы больше не боитесь Linux и разобрались с тем, как работает Xray.

    На этом наше повествование завершается!

    ⬛⬛⬛⬛⬛⬛⬛⬛ 100%

    8.7 В бесконечность и далее!

    Но это ещё не всё, что может Xray.

    Xray — это мощный и многофункциональный инструмент, который можно использовать для решения самых разных задач. В этом руководстве мы лишь поверхностно рассмотрели самые простые и наглядные варианты его настройки.

    Если вам достаточно и этого, то наслаждайтесь свободой в интернете! Но если ваш пытливый ум жаждет новых знаний, то продолжайте изучать безграничные возможности Xray!

    Дополнительную информацию можно найти здесь:

    1. xtls.github.ioОткрыть в новой вкладке — официальная документация
    2. Официальная группа в TelegramОткрыть в новой вкладке — активное и дружелюбное сообщество

    В бесконечность и далее!

    Вместо послесловия

    Надеюсь, это небольшое путешествие, в которое я вас отправил, поможет вам сделать интернет лучше.

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

    Мы живём в мире, где царят тьма и цензура. Люди бродят в одиночестве в поисках лучика света. И если мы не будем помогать друг другу и поддерживать друг друга на этом пути, то в конце концов нас ждёт лишь печальная картина запустения.

    - + diff --git a/ru/document/level-0/ch09-appendix.html b/ru/document/level-0/ch09-appendix.html index d387b20fc1..361fd6ee5c 100644 --- a/ru/document/level-0/ch09-appendix.html +++ b/ru/document/level-0/ch09-appendix.html @@ -24,11 +24,11 @@ [Глава 9] Приложение | Project X - - + +

    [Глава 9] Приложение

    1. Индекс основных команд Linux для начинающих

    НомерНазвание командыОписание командыГлава
    cmd-01apt updateОбновление списка пакетовГлава о удаленном подключении
    cmd-02apt upgradeОбновление пакетов системыГлава о удаленном подключении
    cmd-03nanoТекстовый редакторГлава о безопасности
    cmd-04systemctl restartПерезапуск сервисаГлава о безопасности
    cmd-05adduserДобавление пользователяГлава о безопасности
    cmd-06apt installУстановка пакетаГлава о безопасности
    cmd-07visudoРедактор для настройки sudoГлава о безопасности
    cmd-08sudoВыполнение команды от имени rootГлава о безопасности
    cmd-09chmodИзменение прав доступа к файлу/папкеГлава о безопасности
    cmd-10mkdirСоздание папкиГлава о создании сайта
    cmd-11systemctl reloadПерезагрузка конфигурации сервисаГлава о создании сайта
    cmd-12wgetЗагрузка файла/страницы из сетиГлава об управлении сертификатами
    cmd-13acme.shУправление сертификатами с помощью acme.shГлава об управлении сертификатами
    cmd-14rmУдаление файлов/папокГлава о Xray сервере
    cmd-15crontab -eРедактирование crontab текущего пользователяГлава о Xray сервере
    cmd-16touchСоздание пустого файлаГлава о Xray сервере
    cmd-17systemctlБазовые команды управления сервисами systemdГлава о Xray сервере
    cmd-18rebootПерезагрузка LinuxГлава о Xray сервере

    2. Индекс важных конфигурационных файлов Linux

    НомерРасположение файлаОписание файлаГлава
    conf-01/etc/ssh/sshd_configКонфигурация SSH сервераГлава о удаленном подключении
    conf-02/etc/nginx/nginx.confКонфигурация NginxГлава о создании сайта
    conf-03/etc/apt/sources.listСписок репозиториев APTГлава о Xray сервере
    conf-04/etc/apt/sources.list.d/vpsadmin.listСписок пользовательских репозиториев APTГлава о Xray сервере
    conf-05crontab -eCrontab текущего пользователяГлава о Xray сервере
    conf-06/etc/sysctl.confНастройки ядра LinuxГлава о Xray сервере
    conf-07/etc/sysctl.d/vpsadmin.confПользовательские настройки ядра LinuxГлава о Xray сервере

    3. Индекс важных файлов Xray

    НомерРасположение файлаОписание файлаГлава
    xray-01/usr/local/etc/xray/config.jsonКонфигурация XrayГлава о Xray сервере
    xray-02/home/vpsadmin/xray_cert/xray.certTLS сертификатГлава о Xray сервере
    xray-03/home/vpsadmin/xray_cert/xray.keyTLS ключГлава о Xray сервере
    xray-04/home/vpsadmin/xray_log/access.logЛог доступа XrayГлава о Xray сервере
    xray-05/home/vpsadmin/xray_log/error.logЛог ошибок XrayГлава о Xray сервере
    - + diff --git a/ru/document/level-0/index.html b/ru/document/level-0/index.html index 04db9951cb..fa7bd3a10c 100644 --- a/ru/document/level-0/index.html +++ b/ru/document/level-0/index.html @@ -24,11 +24,11 @@ Простые разговоры о сложном | Project X - - + +

    Простые разговоры о сложном

    Эта глава - базовый курс «С нуля», новичкам читать и учить обязательно

    Подсказка

    Сделано с ❤️ @ricuhkaenОткрыть в новой вкладке

    【Глава 1】 Введение - Чужой или свой сервер? Вот в чём вопрос

    【Глава 2】 Подготовка - Прежде чем браться за дело, заготовь средства

    【Глава 3】 Удалённое подключение - Мост между севером и югом, пропасть превращается в путь

    【Глава 4】 Безопасность - Небрежность в безопасности, и родные будут лить слёзы

    【Глава 5】 Создание сайта - Покажи свою красоту

    【Глава 6】 Управление сертификатами - Законно то, что с лицензией

    【Глава 7】 Xray сервер - Наконец-то дождались

    【Глава 8】 Xray клиенты - Новое начало

    【Глава 9】 Приложение - Все контрольные точки здесь

    - + diff --git a/ru/document/level-1/fallbacks-lv1.html b/ru/document/level-1/fallbacks-lv1.html index 7c86acc275..51a24b309b 100644 --- a/ru/document/level-1/fallbacks-lv1.html +++ b/ru/document/level-1/fallbacks-lv1.html @@ -24,8 +24,8 @@ Обзор функции Fallback | Project X - - + +

    Обзор функции Fallback

    При использовании Xray вы наверняка много раз слышали о функции "fallback". В этой статье мы кратко рассмотрим логику этой функции и способы ее применения.

    1. Что такое Fallback в простых словах

    Если вы использовали конфигурацию Xray из нашего руководства и настроили автоматическое перенаправление HTTP на HTTPS, то у вас уже есть простой fallback на основе протокола VLESS:

    {
    @@ -200,6 +200,6 @@
       }
     }
     
  • Теперь мы можем нарисовать полную схему fallback:

  • 6. Заключение

    На этом обзор функции "fallback" в Xray завершен. Надеемся, что эта статья поможет вам лучше понять возможности Xray.

    7. Дополнительное задание

    Позвольте мне нагло оставить вам дополнительное задание: есть ли что-то, что можно оптимизировать в шаблоне VLESS-TCP-XTLS-WHATEVERОткрыть в новой вкладке, описанном в этой статье?

    Подсказка: автоматическое перенаправление HTTP на HTTPS.

    - + diff --git a/ru/document/level-1/fallbacks-with-sni.html b/ru/document/level-1/fallbacks-with-sni.html index 3d6ca249d4..d67f5be42e 100644 --- a/ru/document/level-1/fallbacks-with-sni.html +++ b/ru/document/level-1/fallbacks-with-sni.html @@ -24,8 +24,8 @@ SNI Fallback | Project X - - + +

    Маскировка и разделение трафика по доменам с помощью функции SNI Fallback

    VLESS - это очень легкий протокол, который, как и Trojan, не использует сложного шифрования и обфускации трафика. Вместо этого он, подобно тому, как искусный мастер кунг-фу скрывает свою силу, шифрует трафик с помощью протокола TLS, маскируя его под обычный HTTPS-трафик и позволяя ему беспрепятственно проходить через Великий китайский файрвол. Для лучшей маскировки от активного зондирования вместе с VLESS была представлена функция Fallbacks (резервирование). В этой статье мы рассмотрим, как использовать функцию Fallbacks входящего протокола VLESS в Xray совместно с Nginx или Caddy для реализации разделения трафика по доменам при обеспечении полной маскировки.

    Сценарии использования

    Из-за XTLS Xray необходимо прослушивать порт 443, что создает проблему, если на сервере уже запущен веб-сайт - сайт либо не сможет работать, либо его придется запускать на другом порту, что нежелательно. Есть три способа решить эту проблему:

    • Xray прослушивает другие часто используемые порты (например, 22, 3389, 8443).

      Это самое простое решение, но оно не идеально.

    • Nginx или HAProxy прослушивает порт 443 и выполняет обратное проксирование на уровне L4 с разделением трафика по SNI, что позволяет использовать один порт для нескольких сервисов.

      Этот вариант более сложный и требует определенных знаний Nginx или HAProxy, поэтому мы не будем его здесь подробно рассматривать.

    • Xray прослушивает порт 443 и использует функцию Fallbacks для перенаправления трафика веб-сайта на Nginx или Caddy на основе SNI.

      Этот вариант имеет среднюю сложность и является тем, который мы рассмотрим в этом руководстве.

    Что такое SNI

    SNI (Server Name Indication) - это расширение протокола TLS. Те, кто знаком с обратным проксированием, знают, что для правильной маршрутизации трафика по доменному имени необходимо следующее правило:

    proxy_set_header Host имя_хоста;
    @@ -210,6 +210,6 @@
         redir https://{host}{uri} permanent
     }
     

    Ссылки

    1. Указание имени сервера - ВикипедияОткрыть в новой вкладке
    2. Home · acmesh-official/acme.sh WikiОткрыть в новой вкладке
    3. HTTP/2 - ВикипедияОткрыть в новой вкладке

    Примечания


    1. Часто задаваемые вопросы - Let's Encrypt - бесплатные SSL/TLS сертификатыОткрыть в новой вкладке ↩︎

    2. Proxy Protocol - HAProxy TechnologiesОткрыть в новой вкладке ↩︎

    3. proxy protocol 介绍及 nginx 配置 - 简书Открыть в новой вкладке ↩︎

    4. v2fly-github-io/vless.md at master · rprx/v2fly-github-ioОткрыть в новой вкладке ↩︎

    - + diff --git a/ru/document/level-1/index.html b/ru/document/level-1/index.html index 7b0b8bc09c..0ed042d043 100644 --- a/ru/document/level-1/index.html +++ b/ru/document/level-1/index.html @@ -24,11 +24,11 @@ Советы для начинающих | Project X - - + +
    - + diff --git a/ru/document/level-1/routing-lv1-part1.html b/ru/document/level-1/routing-lv1-part1.html index 094d2d2203..e7779613ea 100644 --- a/ru/document/level-1/routing-lv1-part1.html +++ b/ru/document/level-1/routing-lv1-part1.html @@ -24,8 +24,8 @@ Краткий обзор функции маршрутизации (routing) (часть 1) | Project X - - + +

    Краткий обзор функции маршрутизации (routing) (часть 1)

    Если "мощность" Xray в основном заключается в его высокой скорости и широкой совместимости, то его "гибкость" в первую очередь связана с продуманной функцией "routing" (маршрутизация). В этой статье мы кратко рассмотрим логику этой функции и способы ее применения.

    1. Знакомство с тремя братьями-маршрутизаторами

    Чтобы понять маршрутизацию, нужно понимать, что для ее полноценной работы нужны три компонента: 1. входящий трафик (inbound); 2. маршрутизация (routing); 3. исходящий трафик (outbound).

    Три брата-маршрутизатора

    Три брата, поклявшиеся в верности, не обязательно родились в один день, но должны быть готовы умереть в один день.

    Поэтому запомните: если один из элементов работает неправильно, функция маршрутизации может не работать.

    Поскольку маршрутизация очень гибкая, чтение только технической документации может вас запутать, поэтому в этой статье мы будем использовать конкретные примеры, чтобы объяснить все пошагово.

    Внимание

    Функция маршрутизации настолько гибкая, что примеры в этой статье приведены только для объяснения соответствующих концепций. На практике, пожалуйста, корректируйте их в соответствии с вашими потребностями.

    2. Основы: "Братья едины"

    На рисунке ниже показан пример, когда входящий трафик от приложения поступает на Xray на клиенте, маршрутизируется на исходящий трафик и отправляется на VPS.

    Давайте проанализируем каждый шаг:

    2.1 Входящий трафик

    Подсказка

    Входящий трафик (inbound): это то, как трафик попадает в Xray.

    Пример конфигурации входящего трафика ниже означает, что данные поступают в Xray по протоколу socks через порт 10808 с локального адреса 127.0.0.1. Xray присваивает этому входящему трафику имя inbound-10808 с помощью [tag].

    {
    @@ -141,6 +141,6 @@
       ]
     }
     

    Теперь правила маршрутизации выглядят так:

    В этом и заключается гибкость функции маршрутизации - вы можете свободно менять порядок правил для достижения различных результатов.

    На этом мы закончили объяснение того, как использовать файл geosite.dat для разделения сетевого трафика по доменному имени с помощью правил маршрутизации.

    5. Покорение новых высот - Различные условия сопоставления маршрутов

    Пожалуйста, убедитесь, что вы хорошо усвоили материал, изложенный выше, поскольку это основа для понимания принципов работы функции маршрутизации. Имея эту базу, мы можем двигаться дальше и рассмотреть более подробные параметры конфигурации и условия сопоставления.

    После того, как вы прочитаете следующий раздел, вы сможете свободно настраивать свои собственные правила маршрутизации! Так чего же мы ждем? Давайте перейдем к части 2!

    - + diff --git a/ru/document/level-1/routing-lv1-part2.html b/ru/document/level-1/routing-lv1-part2.html index d2505b0877..cc461e0614 100644 --- a/ru/document/level-1/routing-lv1-part2.html +++ b/ru/document/level-1/routing-lv1-part2.html @@ -24,8 +24,8 @@ Краткий обзор функции маршрутизации (routing) (часть 2) | Project X - - + +

    Краткий обзор функции маршрутизации (routing) (часть 2)

    Добро пожаловать на продолжение изучения функции маршрутизации в Xray!

    В части 1 мы разобрались с логикой работы функции маршрутизации и настроили простое разделение трафика по домену на основе файла geosite.dat.

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

    5. Покорение новых высот - Различные условия сопоставления маршрутов

    [домен], [IP], [протокол], etc.

    Разделение по домену уже позволяет нам в общих чертах разделить сетевой трафик. Почему в общих чертах?

    Потому что, хотя "разделение мира на три части" — это правильная стратегия, ее реализация только с помощью доменов имеет множество недостатков, например:

    1. После прочтения нашего руководства я зарегистрировал новый домен proxy.yourdomain.com для своего VPS и хочу, чтобы трафик на него всегда проксировался. Есть ли он в geosite.dat?
    2. У меня есть еще один домен direct.yourdomain.com, и я хочу, чтобы трафик на него всегда шел напрямую. Есть ли он в geosite.dat?
    3. Правильно ли настроен прямой доступ для локального трафика на 127.0.0.1 (например, docker)?
    4. Правильно ли настроен прямой доступ для трафика в моей локальной сети 192.168.*.* (например, роутер, NAS)?
    5. Правильно ли настроен прямой доступ для моих DNS-запросов к внутренним DNS-серверам (например, 223.5.5.5)?
    6. Правильно ли настроен прокси для моих DNS-запросов к внешним DNS-серверам (например, 1.1.1.1)?
    7. Правильно ли настроен прямой доступ для других внутренних сайтов, у которых нет доменного имени, а только IP-адрес, как у внутренних DNS-серверов?
    8. Правильно ли настроен прокси для других внешних сайтов, у которых нет доменного имени, а только IP-адрес, как у внешних DNS-серверов?
    9. Как настроить принудительное прямое подключение для торрент-трафика, который, хотя и поступает извне, может привести к блокировке VPS при проксировании?
    10. ......

    Я говорю, что разделение по домену имеет много недостатков, потому что файл geosite.dat содержит только ограниченный набор часто используемых доменов. Другими словами, полагаясь только на него, мы:

    • не сможем сопоставить новые домены, которых нет в файле;
    • не сможем сопоставить правила на основе IP-адресов;
    • не сможем сопоставить правила на основе сетевых протоколов.

    Внимание

    Давайте вспомним, что происходит, когда эти условия не выполняются? Верно, срабатывает скрытое правило маршрутизации: трафик перенаправляется на первый исходящий трафик. Это означает, что:

    • если вашим первым исходящим трафиком является [direct-out]: все, что должно идти напрямую, будет работать правильно, а все, что должно проксироваться, будет работать неправильно;
    • если вашим первым исходящим трафиком является [proxy-out-vless]: все, что должно проксироваться, будет работать правильно, а все, что должно идти напрямую, будет работать неправильно.

    Поэтому нам нужен способ, который позволит нам получить и то, и другое. Существует ли такой способ? Конечно, существует! Нам просто нужны дополнительные критерии сопоставления помимо домена.

    5.1 Разделение по определенному домену: [domain], [full] и т. д.

    1. Для сопоставления поддомена, например a-name.yourdomain.com, мы используем full: "a-name.yourdomain.com".
    2. Проблемы 1 и 2, описанные выше, можно решить, указав исходящий трафик [proxy-out-vless] для proxy.yourdomain.com и исходящий трафик [direct-out] для direct.yourdomain.com.
    3. Для сопоставления всех поддоменов yourdomain.com мы используем domain: "yourdomain.com".
    4. Эти два правила могут быть независимыми, чтобы настроить прямое подключение для одних поддоменов и проксирование для других.
    5. Кроме того, [domain] поддерживает сопоставление с помощью регулярных выражений. Подробнее см. документацию по модулю маршрутизации.

    Конфигурация выглядит следующим образом:

    {
    @@ -187,6 +187,6 @@
       }
     }
     

    На самом деле, в пункте 6 я уже привел упорядоченные правила, принцип которых заключается в том, что одинаковые критерии сопоставления можно объединять, а разные критерии сопоставления должны быть разделены.

    8. Скрытые пути

    Секретный проход для преобразования [domain] в [ip]: domainStrategy

    В пункте 5.4 мы рассмотрели различные критерии для сопоставления трафика, среди которых были домен [domain] и IP-адрес [IP].

    Если вы знакомы с принципами работы DNS, то знаете, что при обращении к домену [domain] сначала нужно отправить запрос на DNS-сервер, чтобы получить IP-адрес [IP], соответствующий домену, а затем отправить фактический запрос на этот IP-адрес.

    Поэтому у Xray есть два шанса определить тип входящего запроса к домену. Использовать ли эти два шанса, решает параметр domainStrategy. Он имеет три значения:

    • AsIs
    • IPIfNonMatch
    • IPOnDemand

    Давайте рассмотрим каждое из них:

    8.1 Стратегия домена: "AsIs"

    "As Domain Is" означает "как есть, без лишних действий".

    Проще говоря, "сопоставлять только по домену".

    Подсказка

    AsIs на самом деле означает "как есть, без изменений". Описание 🍉-sensei не совсем точное.

    В этом режиме вся обработка выполняется внутри Xray без обмена данными с внешним миром, поэтому скорость максимальна. Стратегия обработки несопоставимых доменов также ясна: как уже говорилось ранее, они автоматически перенаправляются на первый исходящий трафик. Поэтому это наиболее рекомендуемая стратегия для обычного использования функции маршрутизации.

    8.2 Стратегия домена: "IPIfNonMatch"

    "lookup IP if (there's) no matching rule" означает "искать IP-адрес, если не найдено совпадений по другим правилам".

    Проще говоря, "сначала сопоставить целевой адрес со всеми правилами, а если совпадений не найдено, то получить IP-адрес через DNS и снова сопоставить его со всеми правилами".

    В этом режиме домены, не сопоставленные ни с одним правилом, будут проходить через DNS-запрос и второй этап сопоставления правил, что займет больше времени, чем в режиме AsIs. Поэтому это не самая рекомендуемая стратегия.

    8.3 Стратегия домена: "IPOnDemand"

    "Demand IP" означает "запрашивать IP-адрес".

    Проще говоря, "если в правилах маршрутизации есть правила на основе IP-адреса, то все запросы на основе домена [domain] будут преобразованы в IP-адреса [IP] и сопоставлены с правилами на основе IP-адреса".

    В этом режиме все запросы к доменам будут проходить через DNS-запрос, поэтому первый запрос будет медленным. Хотя благодаря механизму кэширования DNS в Xray последующие запросы к тому же домену будут быстрыми, в целом это не самая рекомендуемая стратегия.

    Внимание

    domainStrategy действует только для доменов, не путайте!

    9. Задание для размышления

    До сих пор мы рассматривали логику конфигурации маршрутизации на основе одного входящего и одного исходящего трафика.

    Но, как вы знаете, Xray поддерживает несколько портов и протоколов. Что, если я спрошу вас:

    1. Я хочу, чтобы протокол VLESS перенаправлял мой обычный веб-трафик и трафик приложений на высокоскоростной сервер в США.
    2. Я хочу, чтобы протокол trojan перенаправлял весь мой трафик Netflix на сервер в Японии, чтобы разблокировать все аниме.
    3. Я хочу, чтобы протокол shadowsocks перенаправлял весь мой игровой трафик на сервер в Гонконге для минимальной задержки.
    4. Я хочу, чтобы был отдельный порт, который перенаправлял бы весь трафик telegram на VPS.
    5. Я хочу, чтобы был отдельный порт, который перенаправлял бы весь торрент-трафик на мощный сервер в Европе.
    6. Я хочу......

    Можно ли реализовать эти сценарии с помощью функции маршрутизации?

    Ответ, конечно же, да! Однако, это выходит за рамки уровня 1, поэтому я оставлю это вам для самостоятельного изучения!

    10. Заключение

    На этом обзор функции маршрутизации в Xray завершен. Надеюсь, эта статья помогла вам лучше понять гибкость Xray.

    11. Примечания

    • Теперь вы можете перечитать раздел Маршрутизация и посмотреть, стало ли вам что-то понятнее.
    • 🍉🍉🍉🍉🍉 😄
    - + diff --git a/ru/document/level-1/work.html b/ru/document/level-1/work.html index 07b8a9e404..6c0029291a 100644 --- a/ru/document/level-1/work.html +++ b/ru/document/level-1/work.html @@ -24,11 +24,11 @@ Режимы работы Xray | Project X - - + +

    Режимы работы Xray

    Режим одного сервера

    Как и в случае с другими прокси-инструментами, вам понадобится сервер с настроенным Xray, а затем установить и настроить клиент Xray на вашем устройстве, после чего вы сможете свободно пользоваться Интернетом.

    Один сервер Xray может одновременно обслуживать несколько устройств, использующих разные протоколы проксирования. При правильной настройке Xray может распознавать и различать трафик, который нужно проксировать, и трафик, который можно отправлять напрямую, без проксирования.

    Режим моста

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

    Принцип работы

    Перед настройкой Xray давайте рассмотрим, как он работает. Ниже представлена схема внутреннего устройства одного процесса Xray. Несколько процессов Xray работают независимо друг от друга.

    • Для нормальной работы необходимо настроить как минимум одно входящее соединение (Inbound) и одно исходящее соединение (Outbound).
      • Входящее соединение отвечает за связь с клиентом (например, браузером):
        • Входящее соединение обычно можно настроить с аутентификацией пользователя, например, с использованием ID и пароля;
        • После получения данных входящее соединение передает их диспетчеру (Dispatcher) для распределения.
      • Исходящее соединение отвечает за отправку данных на сервер, например, на другой Xray, работающий на другом хосте.
    • При наличии нескольких исходящих соединений можно настроить маршрутизацию (Routing) для указания, какое исходящее соединение должно использоваться для определенного типа трафика.
      • При необходимости маршрутизатор обращается к DNS для получения дополнительной информации для принятия решения.
    - + diff --git a/ru/document/level-2/index.html b/ru/document/level-2/index.html index b1a92cb82e..20a622ef88 100644 --- a/ru/document/level-2/index.html +++ b/ru/document/level-2/index.html @@ -24,11 +24,11 @@ Продвинутая документация | Project X - - + +

    Продвинутая документация

    В этом разделе представлены советы и рекомендации по использованию Xray для продвинутых пользователей. Если вы уже знакомы с Xray, то информация, представленная здесь, поможет вам использовать Xray по максимуму.

    Введение в прозрачное проксирование от a @kirinОткрыть в новой вкладке

    Вводная статья о прозрачном проксировании.

    Руководство по настройке прозрачного проксирования (TProxy) от a @BioniCosmosОткрыть в новой вкладке

    Полное руководство по настройке прозрачного проксирования (TProxy) на основе Xray.

    Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6) от a @SQLimitОткрыть в новой вкладке

    Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6) на основе Xray.

    Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков от a @SQLimitОткрыть в новой вкладке

    Создание TLS-туннеля с помощью Nginx или Haproxy на стороне клиента и сервера для скрытия отпечатков.

    [Прозрачное проксирование] Исключение трафика Xray с помощью GID от a @kirinОткрыть в новой вкладке

    Новый способ исключения трафика Xray при реализации прозрачного проксирования с помощью iptables/nftables.

    Направление определенного трафика через определенный выходной узел с помощью Xray для реализации "разделения" глобальной маршрутизации от a @Zzz3mОткрыть в новой вкладке

    Использование Xray по максимуму: реализация "разделения" трафика на основе fwmark, sendThrough или sockopt.interface.

    Повышение безопасности проксирования с помощью Cloudflare Warp от a @yuhan6665Открыть в новой вкладке

    Введение в использование исходящего подключения WireGuard, добавленного в Xray v1.6.5.

    Статистика трафика Xray от a @yuhan6665Открыть в новой вкладке

    Статистика трафика и скрипты для Xray.

    - + diff --git a/ru/document/level-2/iptables_gid.html b/ru/document/level-2/iptables_gid.html index 282e1508ff..464830c5a2 100644 --- a/ru/document/level-2/iptables_gid.html +++ b/ru/document/level-2/iptables_gid.html @@ -24,8 +24,8 @@ GID Прозрачное проксирование | Project X - - + +

    Прозрачное проксирование: Исключение трафика Xray с помощью GID

    В существующих русскоязычных руководствах по прозрачному проксированию с использованием iptables (Новое руководство по V2Ray на русском языке - Прозрачное проксированиеОткрыть в новой вкладке, Новое руководство по V2Ray на русском языке - Прозрачное проксирование (TPROXY)Открыть в новой вкладке, Руководство по настройке прозрачного проксирования (TProxy)) исключение трафика Xray осуществляется с помощью меток. Исходящий трафик Xray помечается, а затем с помощью правил iptables трафик с соответствующей меткой направляется напрямую, минуя Xray и предотвращая зацикливание.

    У такого подхода есть несколько недостатков:

    1. Необъяснимый трафик попадает в цепочку PREROUTINGОткрыть в новой вкладке

    2. Android использует собственный механизм меток, поэтому данный метод не применим к Android

    Предлагаемый в данном руководстве подход не требует использования меток, теоретически обеспечивая более высокую производительность и избегая описанных выше проблем.

    Идея

    Tproxy трафик может приниматься только пользователями с правами root (uid==0) или CAP_NET_ADMIN.

    Правила iptables позволяют разделять трафик на основе UID (идентификатор пользователя) и GID (идентификатор группы).

    Запустим Xray от имени пользователя с uid==0 и gid!=0 и настроим правила iptables, чтобы исключить трафик с этим GID, избегая проксирования трафика Xray.

    Настройка

    1. Предварительная подготовка

    Android

    1. На устройстве должны быть получены root-права.
    2. Установите busyboxОткрыть в новой вкладке.
    3. Наличие терминала для выполнения команд, например, adb shell, Termux и т.д.

    Другие Linux системы

    Необходимо наличие sudo, модуля tproxy для iptables и модуля extra.

    Обычно все это уже установлено в системе, для OpenWRT выполните:

    opkg install sudo iptables-mod-tproxy iptables-mod-extra
    @@ -125,6 +125,6 @@
     ip6tables -t mangle -A OUTPUT -p tcp -j XRAY6_MASK
     ip6tables -t mangle -A OUTPUT -p udp -j XRAY6_MASK
     
    - + diff --git a/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html b/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html index 1e91cf2408..997b380f46 100644 --- a/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html +++ b/ru/document/level-2/nginx_or_haproxy_tls_tunnel.html @@ -24,8 +24,8 @@ Создание TLS-туннеля с помощью Nginx или Haproxy для скрытия отпечатков | Project X - - + +

    Nginx или Haproxy реализуют HTTPS-туннели, туннели HTTP/2 over HTTPS, туннели WebSocket over HTTP/2 over HTTPS, туннели gRPC over HTTP/2 over HTTPS, а также туннели gRPC over HTTP/2 over HTTPS с двусторонней аутентификацией по самозаверяющему сертификату.

    Создание HTTPS-туннеля с помощью Nginx на стороне клиента и сервера для скрытия отпечатков

    Сетевая структура:

    xray_client ---tcp--- nginx_client ---HTTPS--- nginx_sever ---tcp--- xray_server

    Компиляция nginx с поддержкой --with-stream

    Выполните компиляцию как на клиенте, так и на сервере.

    curl -O -L http://nginx.org/download/nginx-1.22.1.tar.gz

    tar -zxvf nginx-1.22.1.tar.gz

    cd nginx-1.22.1

    apt install gcc make // Для компиляции требуются gcc и make

    ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module // На этом шаге могут потребоваться дополнительные библиотеки, установите их в соответствии с сообщениями об ошибках.

    make && make install

    После компиляции папка nginx будет находиться в /usr/local/nginx.

    Настройка nginx

    Отредактируйте конфигурационный файл nginx.conf.

    vim /usr/local/nginx/conf/nginx.conf

    Добавьте следующую конфигурацию на стороне сервера.

    Получение сертификата для сервера не рассматривается в данном руководстве. Обратитесь к документацииОткрыть в новой вкладке.

    stream {
    @@ -557,6 +557,6 @@
     backend web
         server web /dev/shm/h1h2c.sock
     

    Настройка Xray

    Простая конфигурация gRPC, TLS не требуется. Конфигурация см. в документации. Параметр serviceName можно использовать для разделения трафика.

    - + diff --git a/ru/document/level-2/redirect.html b/ru/document/level-2/redirect.html index df4e0f48eb..a652a7174d 100644 --- a/ru/document/level-2/redirect.html +++ b/ru/document/level-2/redirect.html @@ -24,8 +24,8 @@ Перенаправление исходящего трафика | Project X - - + +

    Перенаправление трафика на основе fwmark или sendThrough

    Направление определенного трафика через определенный выходной узел с помощью Xray для реализации "разделения" глобальной маршрутизации

    Введение

    Я видел много прокси-серверов или VPN, которые перехватывают весь трафик, что приводит к неработоспособности Xray, если он установлен одновременно с ними. Многие руководства, которые я находил, предлагали решать эту проблему путем разделения трафика на основе таблиц маршрутизации CIDR. Это не очень элегантно, и если я хочу иметь возможность гибко переключаться между маршрутами и реализовывать разделение трафика по требованию, то есть ли лучший способ? Да, есть!

    С помощью fwmark или sendThrough/sockopt.interface в Xray и простой настройки таблицы маршрутизации можно добиться следующего:

    1. Xray может направлять трафик с определенным тегом, доменным именем и т.д. через определенный интерфейс. Если ваш интерфейс поддерживает dual-stack, вы можете указать IPv4 или IPv6.
    2. Остальной трафик будет идти через исходный интерфейс IPv4 или IPv6.

    Вот как это настроить (на примере Debian 10):

    1. Установите прокси-сервер или VPN-клиент (например, Wireguard, IPsec и т.д.)

    Обратитесь к официальной документации для получения инструкций по установке для вашей системы и программного обеспечения.

    2. Отредактируйте конфигурационный файл VPN (на примере WireGuard)

    Исходный файл:

    [Interface]
    @@ -169,6 +169,6 @@
     

    Настройте автоматический запуск:

    systemctl enable wg-quick@wg0
     systemctl start wg-quick@wg0
     

    Проверьте IPv4/IPv6:

    На прокси-сервере выполните команду curl ip-api.com -4/-6 / откройте в браузере сайт ip-api.com

    Послесловие

    Цель этой статьи - показать, как избежать ненужных затрат трафика, переложив функции маршрутизации и разделения трафика на Xray. Это позволяет избежать утомительной работы по обслуживанию таблиц маршрутизации и повышает технический уровень.

    Благодарности

    XTLS/Xray-coreОткрыть в новой вкладке; v2fly/v2ray-coreОткрыть в новой вкладке; WireGuardОткрыть в новой вкладке; @p3terxОткрыть в новой вкладке; @w; @Hiram; @Luminous; @Ln; @JackChou;

    - + diff --git a/ru/document/level-2/tproxy.html b/ru/document/level-2/tproxy.html index 7122363672..92d7d397b5 100644 --- a/ru/document/level-2/tproxy.html +++ b/ru/document/level-2/tproxy.html @@ -24,8 +24,8 @@ Прозрачное проксирование TProxy | Project X - - + +

    Руководство по настройке прозрачного проксирования (TProxy)

    Эта конфигурация основана на Новом руководстве по V2Ray на русском языке - Прозрачное проксирование (TPROXY)Открыть в новой вкладке с добавлением новых функций Xray, использованием схемы VLESS + XTLS Vision и изменением режима разделения трафика с проксирования по умолчанию на прямое подключение по умолчанию. Пользователи должны настроить конфигурацию в соответствии со своими потребностями.

    Все конфигурации, представленные в этой статье, были успешно протестированы в средах Raspberry Pi 2B и Ubuntu 20.04. При использовании в других средах вам может потребоваться изменить конфигурацию.

    Перед началом работы

    Убедитесь, что на вашем устройстве есть доступное сетевое подключение, сервер настроен, а клиент установлен.

    Обратите внимание, что многие руководства по настройке прозрачного проксирования предлагают включить переадресацию IP в системе Linux, но это может привести к снижению производительности Splice. Дополнительную информацию см. в статье Расследование снижения производительности Splice до уровня ниже, чем DirectОткрыть в новой вкладке.

    Хочу добавить, что многие руководства по настройке прозрачного проксирования используют Netfilter для разделения трафика, отправляя прямой трафик напрямую, минуя Xray. В этом случае необходимо включить переадресацию IP.
    Другие руководства, например это, направляют весь трафик через Xray, где он разделяется модулем маршрутизации Xray. В этом случае переадресацию IP включать не нужно.

    Настройка Xray

    Для лучшего разделения трафика замените файл правил маршрутизации по умолчанию на Loyalsoldier/v2ray-rules-datОткрыть в новой вкладке, иначе Xray-core не сможет загрузить эту конфигурацию.

    sudo curl -oL /usr/local/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
    @@ -281,6 +281,6 @@
     [Install]
     WantedBy=multi-user.target
     
    - + diff --git a/ru/document/level-2/tproxy_ipv4_and_ipv6.html b/ru/document/level-2/tproxy_ipv4_and_ipv6.html index f65be523a8..dd656b7397 100644 --- a/ru/document/level-2/tproxy_ipv4_and_ipv6.html +++ b/ru/document/level-2/tproxy_ipv4_and_ipv6.html @@ -24,8 +24,8 @@ Прозрачное проксирование TProxy (ipv4 и ipv6) | Project X - - + +

    Руководство по настройке прозрачного проксирования TProxy (ipv4 и ipv6)

    Эта конфигурация основана на Новом руководстве по V2Ray на русском языке - Прозрачное проксирование (TPROXY)Открыть в новой вкладке, Руководстве по настройке прозрачного проксирования (TProxy)Открыть в новой вкладке и Прозрачное проксирование: Исключение трафика Xray с помощью GIDОткрыть в новой вкладке. Она включает поддержку IPv6 для прозрачного проксирования и использует схему VLESS-TCP-XTLS-RPRX-Vision для обхода блокировок (рекомендуется использовать версии 1.7.2 и выше).

    Настройка Xray не является основной темой данной статьи. Пользователи могут изменять ее в соответствии со своими потребностями. Подробную информацию можно найти в примерах официальной документацииОткрыть в новой вкладке или в других отличных примерах, таких как @chika0801Открыть в новой вкладке и @lxhao61Открыть в новой вкладке.

    Внимание

    При использовании других конфигураций обратите особое внимание на часть outbound с тегом proxy в конфигурации клиента. Остальные части остаются неизменными.

    Конфигурация сервера также должна быть изменена соответственно.

    Эта конфигурация предназначена для решения проблемы, когда такие сайты, как Netflix, которые по умолчанию используют IPv6, не могут быть проксированы через пограничный маршрутизатор, или когда требуется проксирование IPv6.

    В данной статье используется сетевая структура с пограничным маршрутизатором с одним интерфейсом.

    Все конфигурации, представленные в этой статье, были успешно протестированы в среде Arch Linux (Kernel: 6.0.10). В других средах настройка аналогична.

    Убедитесь, что установлены необходимые программы: # sudo apt install iptables ip6tables или # sudo apt install nftables.

    Если на пограничном маршрутизаторе не установлена программа Xray, можно вручную скачать соответствующую версию Xray, например Xray-linux-64.zipОткрыть в новой вкладке, а затем скопировать файл install-release.shОткрыть в новой вкладке на пограничный маршрутизатор. Предоставьте файлу права на выполнение # chmod 700 install-release.sh и запустите его с помощью команды # ./install-release.sh --local Xray-linux-64.zip. Следуйте инструкциям для локальной установки.

    Настройка Xray

    Конфигурация клиента

    {
    @@ -437,6 +437,6 @@
     [Install]
     WantedBy=multi-user.target
     
    1. Выполните команду systemctl enable tproxyrules.

    tproxyrules.service

    Обратите внимание на IP-адрес основного маршрутизатора и измените его в соответствии с вашей конфигурацией.

    Команда ExecStartPre=/bin/sh -c 'until ping -c1 192.168.31.1; do sleep 1; done;' гарантирует, что команды будут выполнены только после получения IP-адреса, иначе могут возникнуть странные ошибки. IP-адрес - это адрес основного маршрутизатора, измените его в соответствии с вашей конфигурацией.

    Внимание

    Если вы настроили статический IP-адрес и шлюз с помощью dhcpcd и т.д., удалите соответствующие строки ip route add/del из приведенных выше конфигураций.

    Настройка доступа к интернету на устройствах локальной сети

    Предположим, что IPv4- и IPv6-адреса пограничного маршрутизатора - 192.168.31.100 и fd00:6868:6868::8866 соответственно. IP-адреса пограничного маршрутизатора можно узнать с помощью команды ip add.

    Метод 1

    Есть два способа настроить доступ к интернету на устройствах локальной сети.
    Первый способ - настроить статический IP-адрес на каждом устройстве и указать IP-адрес пограничного маршрутизатора в качестве шлюза.
    Обратите внимание, что большинство мобильных устройств поддерживают только ручную настройку IPv4-шлюза и не поддерживают ручную настройку IPv6-шлюза, если не получены root-права и не выполнены соответствующие настройки.

    В качестве примера рассмотрим устройство Windows.
    Можно сначала включить DHCP и записать автоматически назначенный IP-адрес для справки, а затем вручную настроить статический IP-адрес.

    Настройка DNS

    В этой конфигурации перехватывается DNS-трафик, поэтому DNS можно указать произвольно.

    Рекомендуется указать IP-адрес пограничного маршрутизатора, чтобы избежать утечки DNS.

    image image

    Метод 2

    Второй способ настроить доступ к интернету на устройствах локальной сети - указать пограничный маршрутизатор в качестве шлюза в настройках маршрутизатора.
    Этот метод не требует настройки на каждом устройстве, подключенном к маршрутизатору, но обратите внимание, что некоторые маршрутизаторы не поддерживают настройку IPv6-шлюза, поэтому устройствам, которым требуется IPv6, необходимо вручную настроить IPv6 в соответствии с методом 1.

    image

    Результаты

    После настройки в соответствии с вышеуказанными инструкциями устройства смогут получать доступ к интернету по IPv4 и IPv6.
    На тестовом сайте, например https://ipv6-test.com/, вы увидите следующие результаты (сайт должен быть проксирован, чтобы увидеть эти результаты):

    image

    Заключение

    В настоящее время IPv6 еще не получил широкого распространения, и 99% трафика, к которому мы обращаемся, по-прежнему приходится на IPv4.
    Многие провайдеры VPS

    - + diff --git a/ru/document/level-2/traffic_stats.html b/ru/document/level-2/traffic_stats.html index fa352fe464..5ac5754c7f 100644 --- a/ru/document/level-2/traffic_stats.html +++ b/ru/document/level-2/traffic_stats.html @@ -24,8 +24,8 @@ Статистика трафика | Project X - - + +

    Руководство по настройке статистики трафика

    Ознакомьтесь с руководством по статистике трафикаОткрыть в новой вкладке.
    Эта статья адаптирует его для Xray (1.5.9+).

    Просмотр статистики трафика

    Способ настройки такой же, как и для v2fly. Просмотр статистики трафика - одна из функций командной строки Xray. Порт api dokodemo-door, указанный в конфигурации, - это порт, используемый в параметре --server.

    xray api statsquery --server=127.0.0.1:10085 # Просмотр всей статистики трафика
    @@ -120,6 +120,6 @@
     print_sum "$DATA" "user"
     echo "-----------------------------"
     
    - + diff --git a/ru/document/level-2/transparent_proxy/transparent_proxy.html b/ru/document/level-2/transparent_proxy/transparent_proxy.html index 6710a96b04..60c4c3dfd4 100644 --- a/ru/document/level-2/transparent_proxy/transparent_proxy.html +++ b/ru/document/level-2/transparent_proxy/transparent_proxy.html @@ -24,8 +24,8 @@ Другие замечания по прозрачному проксированию с помощью iptables | Project X - - + +

    Погружение в прозрачное проксирование

    Что такое прозрачное проксирование?

    Проще говоря, прозрачное проксирование не позволяет проксируемому устройству понять, что оно проксируется. Это означает, что на проксируемом устройстве не нужно запускать какое-либо программное обеспечение для проксирования (например, Xray, V2RayNG и т. д.). Когда вы подключаетесь к сети, ваше устройство уже проксируется.

    Это также означает, что программное обеспечение прокси работает в другом месте, например, на маршрутизаторе, и устройства, подключенные к Интернету через маршрутизатор, автоматически проксируются.

    Реализация прозрачного проксирования

    В настоящее время существует два основных способа реализации прозрачного проксирования:

    tun2socks

    Доступно для Windows/Linux (включая Android). Поскольку процесс реализации относительно прост, существует не так много руководств, поэтому я кратко опишу его здесь.

    Windows

    1. Установите NetchОткрыть в новой вкладке, используя режим [3] [TUN/TAP] Обход локальной сети для запуска.

    2. Включите точку доступа.

    3. Откройте Панель управления -> Сеть и Интернет -> Центр управления сетями и общим доступом -> Изменение параметров адаптера, найдите TAP-Windows Adapter и Microsoft Wi-Fi Direct Virtual Adapter.

    4. Щелкните правой кнопкой мыши TAP-Windows Adapter, Свойства -> Доступ, установите флажок Разрешить другим пользователям сети подключаться к Интернету через это подключение к Интернету, в Домашнее сетевое подключение выберите сетевое подключение Microsoft Wi-Fi Direct Virtual Adapter, нажмите ОК.

    Android

    1. Настройте подключение V2RayNG.

    2. Включите точку доступа.

    3. Настройки точки доступа -> Разрешить использование VPN для точки доступа (эта опция может отсутствовать в некоторых системах Android).

    iptables/nftables

    iptables и nftables реализуют прозрачное проксирование по одному и тому же принципу, в дальнейшем мы будем использовать iptables.

    Реализация прозрачного проксирования на основе iptables применима только к системам Linux (включая openwrt/Android). Благодаря своей эффективности по сравнению с tun2socks и возможности настройки на маршрутизаторах, она получила широкое распространение.

    Существующие три русскоязычных руководства по прозрачному проксированию на самом деле описывают реализацию прозрачного проксирования на основе этого решения: Новое руководство по V2Ray на русском языке - Прозрачное проксированиеОткрыть в новой вкладке, Новое руководство по V2Ray на русском языке - Прозрачное проксирование (TPROXY)Открыть в новой вкладке, Руководство по настройке прозрачного проксирования (TProxy). Первое основано на устаревшем режиме iptables-redirect, который не рекомендуется использовать и приводится только для справки. Второе и третье описывают реализацию прозрачного проксирования на основе режима iptables-tproxy.

    Принцип реализации прозрачного проксирования с помощью iptables

    Linux использует Netfilter для управления сетью, модель Netfilter выглядит следующим образом:

    Netfilter

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

    Направление трафика от устройств локальной сети к Интернету через маршрутизатор:

    Цепочка PREROUTING -> Цепочка FORWARD -> Цепочка POSTINGROUTING

    Направление трафика от устройств локальной сети к маршрутизатору (например, вход в веб-интерфейс маршрутизатора/подключение к маршрутизатору по ssh/доступ к DNS-серверу маршрутизатора и т. д.):

    Цепочка PREROUTING -> Цепочка INPUT -> Хост шлюза

    Направление трафика от маршрутизатора к Интернету:

    Хост шлюза -> Цепочка OUTPUT -> Цепочка POSTINGROUTING

    Управляя направлением трафика цепочек PREROUTING и OUTPUT с помощью iptables и перенаправляя его на Xray, мы можем проксировать устройства локальной сети и хост шлюза.

    В чем сложность прозрачного проксирования?

    Сложность прозрачного проксирования заключается в маршрутизации, то есть в различении того, какой трафик должен быть прямым, а какой должен проксироваться, поэтому я лично считаю, что термин разделение трафика более уместен.

    Мы можем разделить маршрутизацию на следующие этапы по возрастанию сложности:

    1. Проксирование всех запросов.
    2. Прямое подключение для локальных IP-адресов/многоадресных IP-адресов, проксирование для остальных запросов.
    3. На основе пункта 2, прямое подключение для исходящих запросов, инициированных Xray.
    4. На основе пункта 3, прямое подключение для запросов, адресованных китайским IP-адресам, и выбор внутренних и внешних DNS-серверов для разрешения внутренних и внешних доменных имен.

    Три вышеупомянутых руководства описывают четвертый этап. Поэтому новичкам может быть сложно понять их, читая напрямую.

    Пошаговая реализация прозрачного проксирования на основе iptables-tproxy с нуля

    Прежде чем начать, вам необходимо иметь базовые знания:

    1. Примерное представление о протоколах TCP/IP, доменных именах и DNS-серверах.
    2. Знание того, что такое WAN-порт, LAN-порт, LAN_IP, WAN_IP и DHCP-сервер. Для пограничных маршрутизаторов есть только один сетевой порт, который мы будем называть LAN-портом.
    3. Базовое понимание системы Linux (знание того, как запускать команды).
    4. Умение писать конфигурационные файлы клиента в формате json или, по крайней мере, понимать их.

    Предварительная подготовка

    Внимание

    Перед началом работы не забудьте включить пересылку пакетов ipv4 в Linux с помощью команды sysctl -w net.ipv4.ip_forward=1

    1. Подготовьте шлюз под управлением Linux

    Например, маршрутизатор с прошивкой OpenWRT.

    2. Подготовьте исполняемый файл Xray и конфигурационный файл на шлюзе (маршрутизаторе)

    Конфигурационный файл прослушивает порт 12345 и включает tproxy:

    {
    @@ -111,6 +111,6 @@
     iptables -t mangle -A OUTPUT -p tcp -j XRAY_MASK
     iptables -t mangle -A OUTPUT -p udp -j XRAY_MASK
     

    Однако у этого метода есть недостаток: если используется CDN или много VPS, то написание правил становится неудобным.

    1. Исключение с помощью меток

    Три вышеупомянутых русскоязычных руководства используют этот метод исключения, обратитесь к ним, мы не будем повторяться здесь.

    1. Исключение с помощью gid (рекомендуется)

    См. [Прозрачное проксирование] Исключение трафика Xray с помощью gid

    На этом третий этап проксирования, также известный как глобальное проксирование, завершен. Но не забудьте установить DNS-сервер шлюза на зарубежный DNS-сервер, иначе вы все равно можете получить загрязненные результаты.

    Четвертый этап

    На самом деле, не всем нужно реализовывать четвертый этап. Глобальное проксирование подходит для большинства случаев.

    Особенно для пограничных маршрутизаторов. При необходимости проксирования установите шлюз на IP-адрес пограничного маршрутизатора, при отсутствии необходимости проксирования - на IP-адрес основного маршрутизатора.

    Что касается конкретной реализации четвертого этапа, то об этом подробно рассказывается в трех вышеупомянутых русскоязычных руководствах. После того, как вы поймете вышеизложенное, вам будет легче понять эти руководства.

    Проксирование IPv6

    Вышеуказанные правила действительны только для IPv4, если вы хотите проксировать запросы IPv6, используйте команду ip6tables, ее использование в основном такое же, как и у iptables. См. [[Прозрачное проксирование] Исключение трафика Xray с помощью gid # 4-Настройка правил iptables](../iptables_gid # 4-Настройка правил iptables.md)

    Другие замечания по прозрачному проксированию с помощью iptables

    1. Если шлюз, выступающий в качестве прокси, также является основным маршрутизатором, необходимо добавить правило iptables -t mangle -A XRAY ! -s Диапазон LAN-адресов шлюза -j RETURN в цепочку PREROUTING, то есть команду, использованную на первом этапе и удаленную на втором этапе. Если этого не сделать, другие люди в той же подсети, что и WAN-порт, смогут использовать ваш WAN_IP в качестве шлюза, чтобы злоупотреблять вашим прозрачным прокси, что может быть небезопасно.

    2. В [Новое руководство по V2Ray на русском языке - Прозрачное проксирование (TPROXY) # Настройка шлюза](https://guide.v2fly.org/app/tproxy.html # Настройка шлюза) третий пункт гласит: Настройте сеть ПК вручную, указав в качестве шлюза по умолчанию адрес Raspberry Pi, то есть 192.168.1.22. Теперь ПК должен иметь доступ к Интернету (поскольку проксирование еще не настроено, “доступ” означает возможность доступа к внутренним веб-сайтам). На самом деле, даже если включена переадресация IP, ПК под управлением Ubuntu, CentOS, Debian и других систем не смогут получить доступ к Интернету, это нормально. Фактически, только OpenWRT может сделать то, что описано в статье, как указал @BioniCosmosОткрыть в новой вкладке, это связано с тем, что в обычных системах Linux нет правил Masquerade.

    3. Проблема too many open filesОткрыть в новой вкладке, см. решение в [Прозрачное проксирование] Исключение трафика Xray с помощью gid - Настройка максимального количества открытых файлов и запуск клиента Xray

    4. Избегайте повторного прохождения пакетов с существующими подключениями через TPROXY, будет дополнено...

    5. Основной маршрутизатор, однорукий маршрутизатор и пограничный маршрутизатор, будет дополнено...

    - + diff --git a/ru/document/level-2/warp.html b/ru/document/level-2/warp.html index 3dbd5adaf2..3d9f3651ff 100644 --- a/ru/document/level-2/warp.html +++ b/ru/document/level-2/warp.html @@ -24,8 +24,8 @@ Повышение безопасности проксирования с помощью Cloudflare Warp | Project X - - + +

    Повышение безопасности проксирования с помощью Cloudflare Warp

    В Xray (1.6.5+) добавлен исходящий WireGuard. Хотя это увеличивает размер ядра из-за дополнительных кода и зависимостей, мы считаем, что это важная новая функция по трем причинам:

    1. Из недавних обсуждений и экспериментовОткрыть в новой вкладке мы знаем, что проксирование трафика в Китай небезопасно.
      Одним из способов решения этой проблемы является перенаправление трафика в Китай в черный дыры.
      Недостаток этого метода заключается в том, что geosite и geoip обновляются нерегулярно, и новички могут не знать, как правильно настроить разделение трафика на клиенте, в результате чего трафик попадает в черный дыры, что снижает удобство использования.
      В этом случае мы можем просто перенаправить трафик в Китай через Cloudflare Warp, что обеспечит такую же безопасность без ущерба для удобства использования.
    2. Как известно, большинство VPN-провайдеров ведут журналы посещенных пользователями доменов, а некоторые даже проверяют и блокируют определенный трафик.
      Один из способов защиты конфиденциальности пользователей - использовать цепочку прокси-серверов на клиенте.
      Warp использует легкий VPN-протокол WireGuard, который добавляет дополнительный уровень шифрования.
      Для VPN-провайдера весь трафик пользователя будет направляться на Warp, что обеспечивает максимальную защиту конфиденциальности.
    3. Простота использования.
      Для настройки разделения трафика, WireGuard-туннеля и цепочки прокси-серверов достаточно одного ядра.

    Создание аккаунта Warp

    Спасибо Cloudflare за содействие свободному интернету! Теперь вы можете бесплатно пользоваться услугами Warp. При подключении автоматически выбирается ближайший сервер.

    Метод 1:

    1. Используйте VPS и загрузите wgcfОткрыть в новой вкладке.
    2. Запустите wgcf register, чтобы создать файл wgcf-account.toml.
    3. Запустите wgcf generate, чтобы создать файл wgcf-profile.conf. Скопируйте его содержимое:
    [Interface]
    @@ -187,6 +187,6 @@
        ]
     }
     
    - + diff --git a/ru/index.html b/ru/index.html index db923f5294..3df811208f 100644 --- a/ru/index.html +++ b/ru/index.html @@ -24,8 +24,8 @@ Project X - - + +
    Project X

    Project X

    Не бойтесь облаков, застилающих вид – золотые глаза, словно факел, озаряют небо.

    Начать здесь → Руководство по конфигурации →

    Высокоскоростной протокол

    Оригинальные протоколы VLESS и XTLS, свободные от избыточного шифрования, высвобождают вычислительную мощность процессора.

    Свободная комбинация

    Безупречный механизм fallback, эффективно предотвращающий активное зондирование, совместное использование портов несколькими сервисами @@ -34,6 +34,6 @@

    Полная совместимость

    Полная совместимость с конфигурационными файлами и вызовами API v2ray-core.

    Сообщество

    Активные обсуждения и вклад сообщества, лицензия с открытым исходным кодом MPL 2.0.

    XTLS? Xray? V2Ray?

    XTLS — это блестящая идея для TLS, которую мы изучаем, в то время как Xray — это лучшая практика, которую мы поддерживаем.

    • Xray-core - это расширенная версия v2ray-core с улучшенной общей производительностью, включающая XTLS и другие улучшения. Xray-core полностью совместим с функциональностью и конфигурацией v2ray-core.
      • Только один исполняемый файл, включающий функциональность ctl, команда run используется по умолчанию.
      • Конфигурация полностью совместима, переменные среды и вызовы API должны начинаться с XRAY_
      • Открытый raw протокол ReadV на всех платформах.
      • Обеспечивает полную поддержку VLESS и Trojan XTLS, обе с ReadV.
      • Предоставляет несколько режимов управления потоком XTLS, непревзойденная производительность!

    Конфигурация без изменений, результат — значительно лучше.

    Кто мы?

    Неважно, кто мы. Важно то, что мы будем продолжать двигаться вперед и никогда не оглядываться назад.

    Помогите Xray стать сильнее

    Мы будем рады вашей помощи в развитии Xray!

    Telegram

    Благодарности

    • Спасибо всем за вашу поддержку!
    • Спасибо создателям всевозможных скриптов, образов Docker, клиентам... Спасибо всем, кто помогает улучшать экосистему!
    • Спасибо всем, кто вносит свой вклад в веб-сайт и документацию Xray.
    • Спасибо всем, кто высказывает ценные предложения и замечания.
    • Спасибо каждому участнику группы Telegram, который помогает другим.

    Подробнее о Project X

    • Если вы хотите узнать больше об истории и развитии Project X, нажмите здесь

    Лицензия

    Mozilla Public License Version 2.0Открыть в новой вкладке

    Динамика звезд на GitHub

    Stargazers over timeОткрыть в новой вкладке

    - +