[
  {
    "path": ".github/ISSUE_TEMPLATE/----.md",
    "content": "---\nname: 提交建议\nabout: 对这个项目提出一个建议\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**详细描述建议的内容**\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug--.md",
    "content": "---\nname: bug反馈 about: bug反馈 title: 'bug反馈'\nlabels: ''\nassignees: ''\n---\n\n> 请仔细填写每一项，并回复自己详细的错误信息\n\n- 不符合的issue会被直接关闭\n\n**1.描述出现的问题**\n\n```\n# \n```\n\n**2.是否直接安装失败**\n\n- 否\n\n**3.是否重新build系统后尝试**\n\n- 否\n\n**4.直接安装失败的错误内容或者截图**\n\n-\n\n**5.系统版本【例：Centos8】**\n> 最新版本脚本不支持Centos6\n> 是否更换Debian系统后再次安装\n\n- 否\n\n**6.脚本版本**\n\n- \n\n**7.安装类型**\n\n- 个性化安装/全部安装\n\n**8.安装的核心版本**\n\n- Xray-core【version】\n\n**9.出现问题的协议类型**\n\n- \n\n**10.尝试重装后是否100%复现**\n\n- 否\n\n**11.是否仔细检查客户端与服务端的配置是否相同**\n\n- 否\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: bug反馈 \nabout: 请按照模版提交\nassignees: ''\n---\n\n不按照模版提交，一律关闭，反馈之前请仔细阅读[脚本异常处理](https://www.v2ray-agent.com/archives/1684115970026)，[客户端使用教程](https://www.v2ray-agent.com/archives/1695534611317)、[八合一脚本从入门到精通](https://www.v2ray-agent.com/archives/1710141233)。\n\n如果低版本升级高版本出现问题，建议使用**20.卸载脚本**卸载后重新安装\n\n\n## 1.问题描述\n- 尽可能的将复现步骤描述清楚\n```\n参考示例：vasma->2->2->0,7,9,10，选择后一路回车，安装完毕后选择7->1 查看账号 **VLESS gRPC TLS [仅CDN推荐]**不展示等。\n```\n\n## 2.安装失败的log或者截图\n```\n请在这里填写\n```\n\n## 3.系统版本\n```\n请在这里填写\n```\n\n## 4.脚本版本\n```\n请在这里填写\n```\n\n## 5.服务端安装的内核、协议、安装方式\n- 核心（1.xray-core、2.sing-box）\n```\n请在这里填写\n```\n- 安装方式（1.全部安装、2.任意组合安装）\n```\n请填写\n```  \n- 协议(0.VLESS+TLS_Vision+TCP)\n```\n可以用数字代替，比如0.VLESS+TLS_Vision+TCP-->0\n```  \n## 6.客户端版本\n```\n# 比如v2rayNG 1.18\n请在这里填写\n```\n"
  },
  {
    "path": ".github/workflows/create_release.yml",
    "content": "name: Release Check\n\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - master\n\npermissions:\n  contents: write\n\njobs:\n  check-release:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout repo\n        uses: actions/checkout@v4\n\n      - name: Read version from install.sh\n        id: version\n        run: |\n          FILE_VERSION=$(grep -oP '当前版本：v[0-9]+\\.[0-9]+\\.[0-9]+' install.sh | sed 's/当前版本：//')\n          echo \"file_version=$FILE_VERSION\" >> $GITHUB_OUTPUT\n          echo $FILE_VERSION\n\n      - name: Get latest release\n        id: latest\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const {data:latest} = await github.rest.repos.getLatestRelease({\n              owner: context.repo.owner,\n              repo: context.repo.repo\n            }).catch(() => ({ data: null }));\n            return latest ? latest.tag_name: \"\";\n          result-encoding: string\n\n      - name: Create release and cleanup old ones\n        if: ${{ steps.version.outputs.file_version != steps.latest.outputs.tag }}\n        uses: actions/github-script@v7\n        with:\n          script: |\n            const tag = \"${{ steps.version.outputs.file_version }}\";\n            \n            const commits = await github.rest.repos.listCommits({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              per_page: 1\n            });\n            const lastMessage = commits.data[0].commit.message;\n            \n            const release = await github.rest.repos.createRelease({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              tag_name: tag,\n              body: lastMessage\n            }).catch(err => console.log(`Skip release ${err.message}`));\n            \n            const { data: releases } = await github.rest.repos.listReleases({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              per_page: 100\n            });\n            console.log(`releases:${releases}`)\n            \n            const oldReleases = releases.slice(3);\n            for (const rel of oldReleases) {\n              console.log(`🗑 Deleting old release ${rel.tag_name} (id=${rel.id})`);\n              await github.rest.repos.deleteRelease({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                release_id: rel.id\n              }).catch(err => console.log(`Skip release ${rel.id}: ${err.message}`));\n              await github.rest.git.deleteRef({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                ref: `tags/${rel.tag_name}`\n              }).catch(err => console.log(`Skip tag ${rel.tag_name}: ${err.message}`));\n            }\n"
  },
  {
    "path": ".gitignore",
    "content": "# Created by .ignore support plugin (hsz.mobi)\n.idea\nfodder/.DS_Store\n.github/FUNDING.yml\n.DS_Store\nGEMINI.md\nGEMINI.zh-CN.md\n"
  },
  {
    "path": "LICENSE",
    "content": "GNU AFFERO GENERAL PUBLIC LICENSE\n   Version 3, 19 November 2007\n\nCopyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\nEveryone is permitted to copy and distribute verbatim copies\nof this license document, but changing it is not allowed.\n\n        Preamble\n\nThe GNU Affero General Public License is a free, copyleft license for\nsoftware and other kinds of works, specifically designed to ensure\ncooperation with the community in the case of network server software.\n\nThe licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nour General Public Licenses are intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.\n\nWhen we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\nDevelopers that use our General Public Licenses protect your rights\nwith two steps: (1) assert copyright on the software, and (2) offer\nyou this License which gives you legal permission to copy, distribute\nand/or modify the software.\n\nA secondary benefit of defending all users' freedom is that\nimprovements made in alternate versions of the program, if they\nreceive widespread use, become available for other developers to\nincorporate.  Many developers of free software are heartened and\nencouraged by the resulting cooperation.  However, in the case of\nsoftware used on network servers, this result may fail to come about.\nThe GNU General Public License permits making a modified version and\nletting the public access it on a server without ever releasing its\nsource code to the public.\n\nThe GNU Affero General Public License is designed specifically to\nensure that, in such cases, the modified source code becomes available\nto the community.  It requires the operator of a network server to\nprovide the source code of the modified version running there to the\nusers of that server.  Therefore, public use of a modified version, on\na publicly accessible server, gives the public access to the source\ncode of the modified version.\n\nAn older license, called the Affero General Public License and\npublished by Affero, was designed to accomplish similar goals.  This is\na different license, not a version of the Affero GPL, but Affero has\nreleased a new version of the Affero GPL which permits relicensing under\nthis license.\n\nThe precise terms and conditions for copying, distribution and\nmodification follow.\n\n   TERMS AND CONDITIONS\n\n0. Definitions.\n\n\"This License\" refers to version 3 of the GNU Affero General Public License.\n\n\"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n\"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\nTo \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\nA \"covered work\" means either the unmodified Program or a work based\non the Program.\n\nTo \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\nTo \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\nAn interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n1. Source Code.\n\nThe \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\nA \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\nThe \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\nThe \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\nThe Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\nThe Corresponding Source for a work in source code form is that\nsame work.\n\n2. Basic Permissions.\n\nAll rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\nYou may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\nConveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\nNo covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\nWhen you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n4. Conveying Verbatim Copies.\n\nYou may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\nYou may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n5. Conveying Modified Source Versions.\n\nYou may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\na) The work must carry prominent notices stating that you modified\nit, and giving a relevant date.\n\nb) The work must carry prominent notices stating that it is\nreleased under this License and any conditions added under section\n7.  This requirement modifies the requirement in section 4 to\n\"keep intact all notices\".\n\nc) You must license the entire work, as a whole, under this\nLicense to anyone who comes into possession of a copy.  This\nLicense will therefore apply, along with any applicable section 7\nadditional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged.  This License gives no\npermission to license the work in any other way, but it does not\ninvalidate such permission if you have separately received it.\n\nd) If the work has interactive user interfaces, each must display\nAppropriate Legal Notices; however, if the Program has interactive\ninterfaces that do not display Appropriate Legal Notices, your\nwork need not make them do so.\n\nA compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n6. Conveying Non-Source Forms.\n\nYou may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\na) Convey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by the\nCorresponding Source fixed on a durable physical medium\ncustomarily used for software interchange.\n\nb) Convey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by a\nwritten offer, valid for at least three years and valid for as\nlong as you offer spare parts or customer support for that product\nmodel, to give anyone who possesses the object code either (1) a\ncopy of the Corresponding Source for all the software in the\nproduct that is covered by this License, on a durable physical\nmedium customarily used for software interchange, for a price no\nmore than your reasonable cost of physically performing this\nconveying of source, or (2) access to copy the\nCorresponding Source from a network server at no charge.\n\nc) Convey individual copies of the object code with a copy of the\nwritten offer to provide the Corresponding Source.  This\nalternative is allowed only occasionally and noncommercially, and\nonly if you received the object code with such an offer, in accord\nwith subsection 6b.\n\nd) Convey the object code by offering access from a designated\nplace (gratis or for a charge), and offer equivalent access to the\nCorresponding Source in the same way through the same place at no\nfurther charge.  You need not require recipients to copy the\nCorresponding Source along with the object code.  If the place to\ncopy the object code is a network server, the Corresponding Source\nmay be on a different server (operated by you or a third party)\nthat supports equivalent copying facilities, provided you maintain\nclear directions next to the object code saying where to find the\nCorresponding Source.  Regardless of what server hosts the\nCorresponding Source, you remain obligated to ensure that it is\navailable for as long as needed to satisfy these requirements.\n\ne) Convey the object code using peer-to-peer transmission, provided\nyou inform other peers where the object code and Corresponding\nSource of the work are being offered to the general public at no\ncharge under subsection 6d.\n\nA separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\nA \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n\"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\nIf you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\nThe requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\nCorresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n7. Additional Terms.\n\n\"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\nWhen you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\nNotwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\na) Disclaiming warranty or limiting liability differently from the\nterms of sections 15 and 16 of this License; or\n\nb) Requiring preservation of specified reasonable legal notices or\nauthor attributions in that material or in the Appropriate Legal\nNotices displayed by works containing it; or\n\nc) Prohibiting misrepresentation of the origin of that material, or\nrequiring that modified versions of such material be marked in\nreasonable ways as different from the original version; or\n\nd) Limiting the use for publicity purposes of names of licensors or\nauthors of the material; or\n\ne) Declining to grant rights under trademark law for use of some\ntrade names, trademarks, or service marks; or\n\nf) Requiring indemnification of licensors and authors of that\nmaterial by anyone who conveys the material (or modified versions of\nit) with contractual assumptions of liability to the recipient, for\nany liability that these contractual assumptions directly impose on\nthose licensors and authors.\n\nAll other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\nIf you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\nAdditional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n8. Termination.\n\nYou may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\nHowever, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\nMoreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\nTermination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n9. Acceptance Not Required for Having Copies.\n\nYou are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n10. Automatic Licensing of Downstream Recipients.\n\nEach time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\nAn \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\nYou may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n11. Patents.\n\nA \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\nA contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\nEach contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\nIn the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\nIf you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\nIf, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\nA patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\nNothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n12. No Surrender of Others' Freedom.\n\nIf conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n13. Remote Network Interaction; Use with the GNU General Public License.\n\nNotwithstanding any other provision of this License, if you modify the\nProgram, your modified version must prominently offer all users\ninteracting with it remotely through a computer network (if your version\nsupports such interaction) an opportunity to receive the Corresponding\nSource of your version by providing access to the Corresponding Source\nfrom a network server at no charge, through some standard or customary\nmeans of facilitating copying of software.  This Corresponding Source\nshall include the Corresponding Source for any work covered by version 3\nof the GNU General Public License that is incorporated pursuant to the\nfollowing paragraph.\n\nNotwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the work with which it is combined will remain governed by version\n3 of the GNU General Public License.\n\n14. Revised Versions of this License.\n\nThe Free Software Foundation may publish revised and/or new versions of\nthe GNU Affero General Public License from time to time.  Such new versions\nwill be similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU Affero General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU Affero General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\nIf the Program specifies that a proxy can decide which future\nversions of the GNU Affero General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\nLater license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n15. Disclaimer of Warranty.\n\nTHERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n16. Limitation of Liability.\n\nIN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n17. Interpretation of Sections 15 and 16.\n\nIf the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n END OF TERMS AND CONDITIONS\n\nHow to Apply These Terms to Your New Programs\n\nIf you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\nTo do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n<one line to give the program's name and a brief idea of what it does.>\nCopyright (C) <year>  <name of author>\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published\nby the Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf your software can interact with users remotely through a computer\nnetwork, you should also make sure that it provides a way for users to\nget its source.  For example, if your program is a web application, its\ninterface could display a \"Source\" link that leads users to an archive\nof the code.  There are many ways you could offer source, and different\nsolutions will be better for different programs; see section 13 for the\nspecific requirements.\n\nYou should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU AGPL, see\n<http://www.gnu.org/licenses/>.\n"
  },
  {
    "path": "README.md",
    "content": "# v2ray-agent\n\n- [感谢 JetBrains 提供的非商业开源软件开发授权](https://www.jetbrains.com/?from=v2ray-agent)\n\n\n[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/v2rayAgentChannel)\n[![Telegram Group](https://img.shields.io/badge/Telegram-Group-blue)](https://t.me/technologyshare)\n[![Official Website](https://img.shields.io/badge/Website-v2ray--agent.com-blue)](https://www.v2ray-agent.com/)\n[![English Version](https://img.shields.io/badge/English-Version-blue)](documents/en/README_EN.md)\n\nXray-core/sing-box 一键脚本快速安装\n\n## 功能\n\n*   **多核心支持:** 支持 Xray-core 和 sing-box.\n*   **多协议支持:** 支持 VLESS, VMess, Trojan, Hysteria2, Tuic, NaiveProxy 等多种协议.\n*   **自动TLS:** 自动申请和续订 SSL 证书.\n*   **易于管理:** 提供简单的菜单来管理用户、端口和配置.\n*   **订阅支持:** 生成和管理订阅链接.\n*   **分流管理:** 提供wireguard、IPv6、Socks5、DNS、VMess(ws)、SNI反向代理，可用于解锁流媒体、规避IP验证等作用.\n*   **目标域名管理:** 提供域名黑名单管理，可用于禁止访问指定网站.\n*   **BT下载管理:** 可用于禁止下载P2P相关内容.\n*   **更多内容请访问[官方网站](https://www.v2ray-agent.com/categories/jiao-cheng)、[备用](https://www.592083.com/categories/jiao-cheng)、[X](https://x.com/v2rayagent)**\n\n## 快速开始\n\n### 安装\n\n```\nwget -P /root -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh\" && chmod 700 /root/install.sh && /root/install.sh\n```\n\n### 使用\n\n安装后，运行以下命令可再次打开管理菜单:\n\n```\nvasma\n```\n\n## 文档和指南\n\n*   [八合一脚本从入门到精通](https://www.v2ray-agent.com/archives/1710141233)\n*   [脚本快速搭建教程](https://www.v2ray-agent.com/archives/1682491479771)\n*   [脚本使用注意事项](https://www.v2ray-agent.com/archives/1679931532764)\n*   [脚本异常处理](https://www.v2ray-agent.com/archives/1684115970026)   \n*   [VPS选购攻略](https://www.v2ray-agent.com/archives/1679975663984)\n*   [垃圾VPS大救星，hysteria2最新协议一键搭建](https://www.v2ray-agent.com/archives/1697162969693)\n*   [RackNerd低价 联通AS4837套餐，年付10美起](https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan)\n*   [搬瓦工优质套餐推荐](https://www.v2ray-agent.com/archives/2023nian-ban-wa-gong-ji-fang-tui-jian)\n*   [DMIT优质套餐推荐](https://www.v2ray-agent.com/archives/1679159868033)\n\n## 社区与支持\n\n*   **Telegram:** [频道](https://t.me/v2rayAgentChannel) | [群组](https://t.me/technologyshare)\n*   **网站:** [官网](https://www.v2ray-agent.com/) | [备用](https://www.592083.xyz/)\n*   **反馈:** [提交 issue](https://github.com/mack-a/v2ray-agent/issues)\n*   **X:** [链接](https://x.com/v2rayagent)\n\n## 捐赠\n\n感谢您对开源项目的关注和支持。如果您觉得这个项目对您有帮助，欢迎通过以下方式进行捐赠。\n\n*   [购买VPS捐赠](https://www.v2ray-agent.com/categories/vps)\n*   [通过虚拟币向我捐赠](https://www.v2ray-agent.com/1679123834836)\n\n## 许可证\n\n本项根据 [AGPL-3.0 许可证](LICENSE) 授权.\n"
  },
  {
    "path": "documents/donation.md",
    "content": "# 您可以通过虚拟向我捐赠\n\n## Ethereum Mainnet/HECO/BSC\n- USDT/ETH/BNB/HT\n```\n0xB08b731653515b083deE362fefFc45d5eb96c35d\n```\n<img src=\"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/donation/main.png\" width=300>\n"
  },
  {
    "path": "documents/donation_aff.md",
    "content": "- [TG群](https://t.me/technologyshare)、[TG频道-更新通知](https://t.me/joinchat/VuYxsKnlIQp3VRw-)\n\n> [更加详细的推荐可以点击查看](https://www.v2ray-agent.com/categories/vps)\n\n# 网络差异比较大，买之前建议执行以下两个步骤\n- 测试一下testIP的丢包，traceroute一下testIP的路由，是否商家宣传的一样\n- 以下商家仅作为推荐，实际效果需自测\n- 便宜机器都可能会出现Google人机验证问题（因为滥用），可以套warp解决（脚本中有此功能）\n- 谨记一分钱一分货\n\n<!-- more -->\n\n# 1.CN2 GIA\n## 1.推荐理由\n- 可用作主力机\n- 电信国际精品网络，CN2线路中的顶级产品，回程基本全部走59.43高速节点\n- 线路一般比较稳定，延迟一般180ms以下，晚高峰基本上不丢包\n\n## 2.推荐商家\n### 1.[搬瓦工](https://bandwagonhost.com/cart.php?aff=64917)\n- 老牌商家在vps圈声望比较高，非常稳定，补货后基本很快会被抢空\n- 6.81%折扣码：BWHNCXNVXV\n- 12%优惠码：BWHNY2022\n\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|购买链接\n---|---|---|---|---|---|---|---\nCN2 GIA 限量版|1G|1核|20G|500G|1Gbps|89.99 USD/年|[购买链接](https://bandwagonhost.com/aff.php?aff=64917&pid=105)\nCN2 GIA|1G|2核|20G|1T|2.5Gbps|169.99 USD/年|[购买链接](https://bandwagonhost.com/aff.php?aff=64917&pid=87)\nHONG KONG CN2 GIA|2G|2核|40G|500G|1Gbps|$899.99 USD/年|[购买链接](https://bandwagonhost.com/aff.php?aff=64917&pid=95)\n\n### 2.Gigsgigscloud\n- 老牌商家，成立较早，工单回复慢\n- 退款需要符合条件，需耐心等待，处理比较慢\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|折扣码|购买链接\n---|---|---|---|---|---|---|---|---\nLAX:SimpleCloud V01 电信gia 联通9929|500M|1核|20G|1T|1Gbps|12 USD/月|5% 折扣码 GYP1WPSCQV0T|[购买链接](https://clientarea.gigsgigscloud.com/?affid=3361)\nCLOUD V JP:Japan Tokyo Premium 三网 CN2 GIA|1G|1核|20G|250G|100Mbps|48 USD/月|5% 折扣码 03K5VKLPPALX|[购买链接](https://clientarea.gigsgigscloud.com/?affid=3361)\n\n### 3.Dmit\n- 去程路由：电信联通走CN2 GIA，移动CMI\n- 回程路由：三网CN2 GIA\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|购买链接\n---|---|---|---|---|---|---|---\nLosAngles PVM.LAX.Pro.TINY|1G|1核|10G|650G|500Mbps|28.88 USD/季|[购买链接](https://www.dmit.io/aff.php?aff=3084&a=add&pid=100)\n\n# 2.联通 AS9929（A网）\n\n## 1.推荐理由\n- 价格略贵，可用作主力机，一般网络都很稳定\n- 相对于联通AS4837（民用），延迟更低、更稳定\n- 适合联通用户，同样也贵一些\n- 有些厂商三网回程都走AS9929，这样的商家同样比较适合移动和电信\n\n## 2.推荐商家\n### 1.olink\n- 三网回程强制都走AS9929\n- 优惠一：终身九折折扣码 OLINK\n- 优惠二：\n```\n预计周期优惠：（可与优惠一叠加）\n半年付：仅需支付5个月（买半年只需要支付5个月） 半年付28刀 月均4.5刀\n年付：仅需支付9个月（买一年只需要支付9个月） 年付50刀 月均4刀多一点\n```\n- 在线测速：http://speedtest.olink.cloud\n- 测试 IP（美国圣何塞）：104.165.62.200\n- 测试 IP（德国法兰克福）：31.22.111.254\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|购买链接\n---|---|---|---|---|---|---|---\nSan Jose Premium VPS|1G|1核|10G|500G|1Gbps|7 USD/月|[购买链接](https://www.olink.cloud/clients/aff.php?aff=281)\n\n### 2.Gigsgigscloud\n- 老牌商家，成立较早，工单回复慢\n- 退款需要符合条件，需耐心等待，处理比较慢\n- 下面这个套餐只有联通是AS9929，电信是gia\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|折扣码|购买链接\n---|---|---|---|---|---|---|---|---\nLAX:SimpleCloud V01 电信gia 联通AS9929|500M|1核|20G|1T|1Gbps|12 USD/月|5% 折扣码 GYP1WPSCQV0T|[购买链接](https://clientarea.gigsgigscloud.com/?affid=3361)\n\n\n# 3.联通 AS4837（普通民用网）\n## 1.推荐理由\n- 价格便宜，当备用机很香，晚高峰视本地网络环境不同，可能略炸\n- 比如适合联通，电信尚可，一般都可以YouTube流畅1080p\n- 相对其他线路比较便宜，适合对网络要求不是特别高，预算有限的用户\n\n\n## 2.推荐商家\n\n### 1.racknerd\n- 流量双向计费，比如3T实际可用1.5T\n- 洛杉矶动态路由，有时候会很拉垮\n- sanjose大概率会跳Google人机验证，可通过warp或者任意门解锁解决此问题\n\n套餐名称|内存|CPU| 硬盘(SSD) |流量|带宽|价格|购买链接\n---|-------|---|---|---|---|---|---\n768 MB KVM VPS Special|768MB|1核| 10 GB NVMe SSD Storage           |2T|1Gbps|$11.88 USD|[购买链接](https://my.racknerd.com/aff.php?aff=2705&pid=679)\n1 GB KVM VPS (New Year 2022)|1G|1核| 20 GB Pure SSD                   |2T|1Gbps|$13.98 USD|[购买链接](https://my.racknerd.com/aff.php?aff=2705&pid=621)\n1 GB KVM VPS Special |1G|1核| 20 GB SSD Cached RAID-10 Storage |3T|1Gbps|$14.98 USD|[购买链接](https://my.racknerd.com/aff.php?aff=2705&pid=680)\n2 GB KVM VPS Special |2G|2核| 25 GB Pure SSD                   |4T|1Gbps|$29.98 USD|[购买链接](https://my.racknerd.com/aff.php?aff=2705&pid=681)\n3 GB KVM VPS (New Year 2022)|3G|1核| 50 GB Pure SSD                   |6T|1Gbps|$31.98 USD|[购买链接](https://my.racknerd.com/aff.php?aff=2705&pid=623)\n\n\n### 2.dmit\n- 位置：sanjose\n- 流量双向计费\n- 联通4837，10Gbps超大带宽\n- 数据中心目前处于OpenBeta，不保证SLA\n- 新购享受年付7折优惠、半年付8折优惠\n- 年付七折优惠码：Lite-Annually-Recur-30OFF\n- 半年付八折优惠码：Lite-Semi-Annually-Recur-20OFF\n\n#### 非使用优惠介绍\n- 如果再不使用优惠码的情况下订购年付产品可享受【买一赠一】\n- 赠品第一年免费（仅限首年，这意味着赠品也要求为年付）\n- 赠品可以拆分为多个订单（要求不高于原订单价格）\n- 赠品可以请求创建在其他账户（工单内备注）\n- 通过工单请求赠品，每个订单只允许请求一次，10月26日 23：59（UTC）之前提交工单，不支持TINY系列\n\n套餐名称| 内存    |CPU|硬盘(SSD)|流量|带宽|价格|购买链接\n---|-------|---|---|---|---|---|---\nPVM.SJC.TINY| 768MB |1vCPU|10G|2T|10Gbps|$6.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=145)\nPVM.SJC.STARTER| 1.5G  |1vCPU|20G|4T|10Gbps|$12.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=146)\nPVM.SJC.MINI| 2G    |2vCPU|40G|6T|10Gbps|$21.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=147)\nPVM.SJC.MICRO| 4G    |2vCPU|80G|8T|10Gbps|$32.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=148)\nPVM.SJC.MEDIUM| 4G    |4vCPU|120G|12T|10Gbps|$49.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=149)\nPVM.SJC.LARGE| 8G    |4vCPU|200G|22T|10Gbps|$99.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=150)\nPVM.SJC.GIANT| 16G   |8vCPU|400G|44T|10Gbps|$199.9 USD/月|[点击购买](https://www.dmit.io/aff.php?aff=3084&a=add&pid=151)\n\n\n# 4.联通 日本软银\n\n## 1.推荐理由\n- 可用作主力机\n- 线路一般比较稳定，延迟一般80ms以下，晚高峰基本上不丢包\n\n## 2.推荐商家\n### 1.[搬瓦工](https://bandwagonhost.com/cart.php?aff=64917)\n- 老牌商家在vps圈声望比较高，非常稳定，补货后基本很快会被抢空\n- 不接受退款\n- 6.81%折扣码：BWHNCXNVXV\n- location是【JP-Equinix Osaka Softbank】\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|购买链接\n---|---|---|--|---|---|---|---\n软银/CN2 GIA 限量版|1G|1核|20G|500G|1Gbps|89.99 USD/年|[购买链接](https://bandwagonhost.com/aff.php?aff=64917&pid=105)\n软银/CN2 GIA|1G|2核|20G|1T|2.5Gbps|169.99 USD/年|[购买链接](https://bandwagonhost.com/aff.php?aff=64917&pid=87)\n软银/CN2 GIA|1G|3核|40G|2T|2.5Gbps|299.99 USD/年|[购买链接](https://bandwagonhost.com/aff.php?aff=64917&pid=88)\n\n### 2.Gigsgigscloud\n- 老牌商家，成立较早，工单回复慢\n- 退款需要符合条件，需耐心等待，处理比较慢\n\n套餐名称|内存|CPU|硬盘|流量|带宽|价格|折扣码|购买链接\n---|---|---|---|---|---|---|---|---\nCLOUD K JP: JAPAN TOKYO SOFTBANK IP TRANSIT|512M|1核|10G|500G|100Mbps|8.2 USD/月|5% 折扣码 0P559NYMKTTW|[购买链接](https://clientarea.gigsgigscloud.com/?affid=3361)\n\n\n# 5.CMI\n## 1.推荐理由\n- 回程三网CMI\n- 可用作主力机\n- 移动国际精品网络\n- 线路大多数情况下比较稳定，偶尔会被打\n\n### 1.DMIT HongKong Lite\n- [TOS](https://t.me/DMIT_INC_CN/544)\n- 流量双向计费\n- 去程有可能更换\n- 线路实测为主\n- [speedtest](http://dmit-hkg-lite.gubo.org/speedtest/)\n- 不建议非移动用户购买\n- lite路由可能会随时更改，买之前请多次测试回程和去程路由\n- 测试ip：103.135.248.22\n\n#### 去程\n\n- 联通、电信 绕日NTT（4837->日本NTT->HK PCCW【2022-5-9】\n- 移动CMI\n\n#### 回程\n- 移动CMI\n\n#### 折扣码【仅适用于 STARTER 及以上规格的 Lite 产品，TINY 不包含在内】\n- 年付七折：Lite-Annually-Recur-30OFF\n- 半年付八折：Lite-Semi-Annually-Recur-20OFF\n\n\n\n套餐名称| 内存 |CPU|硬盘(SSD)|流量|带宽|价格|购买链接\n---|---|---|---|---|---|---|---\nPVM.HKG.Lite.TINY| 0.75G |1 vCPU|10 GB SSD|2T|1Gbps|$6.9 USD/月|[购买链接](https://www.dmit.io/aff.php?aff=3084&a=add&pid=109)\nPVM.HKG.Lite.STARTER| 1.5G |1 vCPU|20 GB SSD|4T|1Gbps|$12.9 USD/月|[购买链接](https://www.dmit.io/aff.php?aff=3084&a=add&pid=110)\nPVM.HKG.Lite.MINI| 2G |2 vCPU|40 GB SSD|6T|2Gbps|$21.9 USD/月|[购买链接](https://www.dmit.io/aff.php?aff=3084&a=add&pid=111)\nPVM.HKG.Lite.MICRO| 4G |2 vCPU|60 GB SSD|8T|2Gbps|$32.9 USD/月|[购买链接](https://www.dmit.io/aff.php?aff=3084&a=add&pid=111)\nPVM.HKG.Lite.MINI| 4G |4 vCPU|80 GB SSD|6T|2Gbps|$49.9 USD/月|[购买链接](https://www.dmit.io/aff.php?aff=3084&a=add&pid=111)\n\n\n### 2.RFCHOST Hong Kong 3 Premium\n#### 去程【截止发文日期2022-4-19】\n\n- 电信CN2-PCCW\n- 联通去程4837-4134-CN2-PCCW\n- 移动CMI\n\n#### 回程\n- 三网CMI\n\n#### 折扣码（九折）\n- hkg3openup\n\n#### TestIP\n- 199.15.77.1\n\n\n套餐名称| 内存 |CPU|硬盘(SSD)|流量|带宽|价格|购买链接\n---|---|---|---|---|---|---|---\nHKG3-Premium-Micro| 512MB |1 CPU|8 GB SSD|500G（只计算出方向流量）|500Mbps|$9.9 USD/月|[购买链接](https://my.rfchost.com/aff.php?aff=899)\nHKG3-Premium-Mini| 1.5G |1 CPU|10 GB SSD|1T|1Gbps|$12.99 USD/月|[购买链接](https://my.rfchost.com/aff.php?aff=899)\nHKG3-Premium-Medium| 2G |2 CPU|20 GB SSD|2T|1Gbps|$21.9 USD/月|[购买链接](https://my.rfchost.com/aff.php?aff=899)\n"
  },
  {
    "path": "documents/en/README_EN.md",
    "content": "# v2ray-agent\n\n- [Thanks to JetBrains for providing non-commercial open source software development authorization](https://www.jetbrains.com/?from=v2ray-agent)\n\n\n[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)\n[![Telegram Channel](https://img.shields.io/badge/Telegram-Channel-blue)](https://t.me/v2rayAgentChannel)\n[![Telegram Group](https://img.shields.io/badge/Telegram-Group-blue)](https://t.me/technologyshare)\n[![Official Website](https://img.shields.io/badge/Website-v2ray--agent.com-blue)](https://www.v2ray-agent.com/)\n[![English Version](https://img.shields.io/badge/English-Version-blue)](documents/en/README_EN.md)\n\nXray-core/sing-box One-click Quick Install Script\n\n## Features\n\n*   **Multi-core Support:** Supports Xray-core and sing-box.\n*   **Multi-protocol Support:** Supports various protocols like VLESS, VMess, Trojan, Hysteria2, Tuic, NaiveProxy.\n*   **Automatic TLS:** Automatically applies for and renews SSL certificates.\n*   **Easy Management:** Provides a simple menu to manage users, ports, and configurations.\n*   **Subscription Support:** Generates and manages subscription links.\n*   **Traffic Splitting Management:** Provides wireguard, IPv6, Socks5, DNS, VMess(ws), SNI reverse proxy, which can be used to unlock streaming media, evade IP verification, etc.\n*   **Target Domain Management:** Provides domain name blacklist management, which can be used to prohibit access to specified websites.\n*   **BT Download Management:** Can be used to prohibit the download of P2P-related content.\n*   **For more content, please visit the [Official Website](https://www.v2ray-agent.com/categories/jiao-cheng), [Backup](https://www.592083.com/categories/jiao-cheng)**\n\n## Quick Start\n\n### Installation\n\n```\nbash wget -P /root -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh\" && chmod 700 /root/install.sh && /root/install.sh\n```\n\n### Usage\n\nAfter installation, run the following command to open the management menu again:\n\n```\nvasma\n```\n\n## Documentation and Guides\n\n*   [From Beginner to Master with the 8-in-1 Script](https://www.v2ray-agent.com/archives/1710141233)\n*   [Quick Script Setup Tutorial](https://www.v2ray-agent.com/archives/1682491479771)\n*   [Script Usage Precautions](https://www.v2ray-agent.com/archives/1679931532764)\n*   [Script Exception Handling](https://www.v2ray-agent.com/archives/1684115970026)   \n*   [VPS Purchasing Guide](https://www.v2ray-agent.com/archives/1679975663984)\n*   [Junk VPS Savior, one-click setup of the latest hysteria2 protocol](https://www.v2ray-agent.com/archives/1697162969693)\n*   [RackNerd Low-cost Unicom AS4837 Package, starting from $10/year](https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan)\n*   [Recommended High-Quality Bandwagon Host Packages](https://www.v2ray-agent.com/archives/2023nian-ban-wa-gong-ji-fang-tui-jian)\n*   [Recommended High-Quality DMIT Packages](https://www.v2ray-agent.com/archives/1679159868033)\n\n## Community & Support\n\n*   **Telegram:** [Channel](https://t.me/v2rayAgentChannel) | [Group](https://t.me/technologyshare)\n*   **Website:** [Official](https://www.v2ray-agent.com/) | [Backup](https://www.592083.xyz/)\n*   **Feedback:** [Submit an issue](https://github.com/mack-a/v2ray-agent/issues)\n\n## Donation\n\nThank you for your attention and support for this open source project. If you find this project helpful, you are welcome to donate in the following ways.\n\n*   [Donate by purchasing a VPS](https://www.v2ray-agent.com/categories/vps)\n*   [Donate to me via cryptocurrency](https://www.v2ray-agent.com/1679123834836)\n\n## License\n\nThis project is licensed under the [AGPL-3.0 License](LICENSE).\n"
  },
  {
    "path": "documents/install_tools.md",
    "content": "# 安装wget、curl\n- Centos\n```\nyum update && yum install -y wget curl\n```\n\n- Debian\n```\napt update && apt install wget curl -y\n```\n\n- Ubuntu\n```\napt-get update && apt-get install wget -y\n```\n"
  },
  {
    "path": "documents/nginx_proxy.md",
    "content": "# 1.打开Nginx配置文件\n\n```\nvim /etc/nginx/conf.d/alone.conf\n```\n\n# 2.添加配置\n\n- 如需配置HTTP1.1，找到31300端口所在的server【文件最后，非return 403那条】\n- 如需配置HTTP2.0，找到31302端口所在的server\n\n> 下方使用配置HTTP1.1反向代理作为示例\n\n```\n# 如果要添加到根路由，则添加到localtion /下面\nlocation / {\n\tadd_header Strict-Transport-Security \"max-age=15552000; preload\" always;\n\tproxy_pass http://127.0.0.1:3003/;\n}\n\n# 如果只需要添加额外的路径，则额外写一个location，路径可自定义\nlocation /test {\n\tproxy_pass http://127.0.0.1:3003/;\n}\n\n# 完整配置，HTTP2.0则同理，写入到31302端口所在的server即可\nserver {\n\tlisten 127.0.0.1:31300;\n\tserver_name xx;\n\troot /usr/share/nginx/html;\n\tlocation /s/ {\n\t\tadd_header Content-Type text/plain;\n\t\talias /etc/v2ray-agent/subscribe/;\n\t}\n\tlocation / {\n\t\tadd_header Strict-Transport-Security \"max-age=15552000; preload\" always;\n\t\tproxy_pass http://127.0.0.1:3003/;\n\t}\n    \tlocation /test {\n\t\tproxy_pass http://127.0.0.1:3003/;\n\t}\n}\n```\n"
  },
  {
    "path": "documents/optimize_V2Ray.md",
    "content": "内容转移至此[教程](https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip)\n"
  },
  {
    "path": "documents/sing-box.json",
    "content": "{\n  \"log\": {\n    \"disabled\": false,\n    \"level\": \"info\",\n    \"timestamp\": true\n  },\n  \"experimental\": {\n    \"clash_api\": {\n      \"external_controller\": \"127.0.0.1:9090\",\n      \"external_ui\": \"metacubexd\",\n      \"external_ui_download_url\": \"https://gh-proxy.com/https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip\",\n      \"external_ui_download_detour\": \"direct\",\n      \"default_mode\": \"rule\"\n    },\n    \"cache_file\": {\n      \"enabled\": true\n    }\n  },\n  \"dns\": {\n    \"servers\": [\n      {\n        \"tag\": \"dns_proxy\",\n        \"type\": \"https\",\n        \"server\": \"1.1.1.1\",\n        \"server_port\": 443,\n        \"detour\": \"自动选择\",\n        \"path\": \"/dns-query\",\n        \"domain_resolver\": \"dns_resolver\"\n      },\n      {\n        \"tag\": \"dns_direct\",\n        \"type\": \"h3\",\n        \"server\": \"dns.alidns.com\",\n        \"server_port\": 443,\n        \"path\": \"/dns-query\",\n        \"domain_resolver\": \"dns_resolver\"\n      },\n      {\n        \"tag\": \"google\",\n        \"type\": \"tls\",\n        \"server\": \"8.8.4.4\",\n        \"domain_resolver\": \"dns_resolver\"\n      },\n      {\n        \"tag\": \"dns_resolver\",\n        \"type\": \"udp\",\n        \"server\": \"114.114.114.114\"\n      },\n      {\n        \"type\": \"local\",\n        \"tag\": \"local\"\n      }\n    ],\n    \"rules\": [\n      {\n        \"action\": \"route\",\n        \"clash_mode\": \"direct\",\n        \"server\": \"dns_direct\"\n      },\n      {\n        \"action\": \"route\",\n        \"clash_mode\": \"global\",\n        \"server\": \"dns_proxy\"\n      },\n      {\n        \"action\": \"route\",\n        \"rule_set\": \"geosite-cn\",\n        \"server\": \"dns_direct\"\n      },\n      {\n        \"action\": \"route\",\n        \"rule_set\": \"geosite-geolocation-!cn\",\n        \"server\": \"dns_proxy\"\n      }\n    ],\n    \"independent_cache\": true,\n    \"strategy\": \"prefer_ipv4\",\n    \"final\": \"dns_direct\"\n  },\n  \"inbounds\": [\n    {\n      \"type\": \"tun\",\n      \"tag\": \"tun-in\",\n      \"stack\": \"system\",\n      \"address\": [\n        \"172.18.0.1/30\",\n        \"fdfe:dcba:9876::1/126\"\n      ],\n      \"route_address\": [\n        \"0.0.0.0/1\",\n        \"128.0.0.0/1\",\n        \"::/1\",\n        \"8000::/1\"\n      ],\n      \"route_exclude_address\": [\n        \"192.168.0.0/16\",\n        \"10.0.0.0/8\",\n        \"172.16.0.0/12\",\n        \"fc00::/7\"\n      ],\n      \"mtu\": 9000,\n      \"auto_route\": true,\n      \"strict_route\": true,\n      \"sniff\": true\n    },\n    {\n      \"type\": \"mixed\",\n      \"listen\": \"127.0.0.1\",\n      \"listen_port\": 1082,\n      \"sniff\": true,\n      \"users\": []\n    }\n  ],\n  \"outbounds\": [\n    {\n      \"type\": \"urltest\",\n      \"tag\": \"自动选择\",\n      \"outbounds\": [\n      ],\n      \"url\": \"https://www.gstatic.com/generate_204\",\n      \"interval\": \"3m\",\n      \"tolerance\": 50,\n      \"interrupt_exist_connections\": false\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"手动切换\",\n      \"outbounds\": [\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"Telegram\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"YouTube\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"netflix\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"OpenAI\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"Apple\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\",\n        \"direct\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"Google\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"Microsoft\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\",\n        \"direct\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"Github\",\n      \"outbounds\": [\n        \"手动切换\",\n        \"自动选择\",\n        \"direct\"\n      ]\n    },\n    {\n      \"type\": \"selector\",\n      \"tag\": \"本地直连\",\n      \"outbounds\": [\n        \"direct\",\n        \"手动切换\",\n        \"自动选择\"\n      ],\n      \"default\": \"direct\"\n    },\n    {\n      \"tag\": \"direct\",\n      \"type\": \"direct\"\n    }\n  ],\n  \"route\": {\n    \"default_domain_resolver\": {\n      \"server\": \"dns_resolver\",\n      \"strategy\": \"prefer_ipv4\"\n    },\n    \"rule_set\": [\n      {\n        \"tag\": \"geosite-category-ads-all\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/category-ads-all.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-telegram\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/telegram.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geoip-telegram\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geoip/telegram.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-youtube\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/youtube.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-netflix\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/netflix.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geoip-netflix\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geoip/netflix.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-openai@ads\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/openai@ads.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-openai\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/openai.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-apple\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/apple.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-google\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/google.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geoip-google\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geoip/google.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-microsoft\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/microsoft.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-geolocation-!cn\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/geolocation-!cn.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-github\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/github.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-private\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/private.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geosite-cn\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/cn.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geoip-private\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geoip/private.srs\",\n        \"update_interval\": \"1d\"\n      },\n      {\n        \"tag\": \"geoip-cn\",\n        \"type\": \"remote\",\n        \"format\": \"binary\",\n        \"url\": \"https://gh-proxy.com/https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geoip/cn.srs\",\n        \"update_interval\": \"1d\"\n      }\n    ],\n    \"rules\": [\n      {\n        \"action\": \"sniff\"\n      },\n      {\n        \"protocol\": \"dns\",\n        \"action\": \"hijack-dns\"\n      },\n      {\n        \"ip_is_private\": true,\n        \"outbound\": \"direct\"\n      },\n      {\n        \"clash_mode\": \"global\",\n        \"outbound\": \"手动切换\"\n      },\n      {\n        \"clash_mode\": \"direct\",\n        \"outbound\": \"本地直连\"\n      },\n      {\n        \"type\": \"logical\",\n        \"mode\": \"or\",\n        \"rules\": [\n          {\n            \"rule_set\": \"geosite-category-ads-all\"\n          },\n          {\n            \"domain_regex\": \"^stun\\\\..+\"\n          },\n          {\n            \"domain_keyword\": [\n              \"stun\",\n              \"httpdns\"\n            ]\n          },\n          {\n            \"protocol\": \"stun\"\n          }\n        ],\n        \"action\": \"reject\",\n        \"method\": \"default\",\n        \"no_drop\": false\n      },\n      {\n        \"rule_set\": [\n          \"geosite-telegram\",\n          \"geoip-telegram\"\n        ],\n        \"outbound\": \"Telegram\"\n      },\n      {\n        \"rule_set\": \"geosite-youtube\",\n        \"outbound\": \"YouTube\"\n      },\n      {\n        \"rule_set\": [\n          \"geosite-netflix\",\n          \"geoip-netflix\"\n        ],\n        \"outbound\": \"netflix\"\n      },\n      {\n        \"rule_set\": \"geosite-openai@ads\",\n        \"action\": \"reject\",\n        \"method\": \"default\",\n        \"no_drop\": false\n      },\n      {\n        \"rule_set\": \"geosite-openai\",\n        \"outbound\": \"OpenAI\"\n      },\n      {\n        \"rule_set\": \"geosite-apple\",\n        \"outbound\": \"Apple\"\n      },\n      {\n        \"rule_set\": [\n          \"geosite-google\",\n          \"geoip-google\"\n        ],\n        \"outbound\": \"Google\"\n      },\n      {\n        \"rule_set\": \"geosite-microsoft\",\n        \"outbound\": \"Microsoft\"\n      },\n      {\n        \"rule_set\": \"geosite-github\",\n        \"outbound\": \"Github\"\n      },\n      {\n        \"rule_set\": \"geosite-geolocation-!cn\",\n        \"outbound\": \"手动切换\"\n      },\n      {\n        \"rule_set\": [\n          \"geosite-private\",\n          \"geosite-cn\",\n          \"geoip-private\",\n          \"geoip-cn\"\n        ],\n        \"outbound\": \"本地直连\"\n      }\n    ],\n    \"final\": \"本地直连\",\n    \"auto_detect_interface\": true\n  }\n}\n\n"
  },
  {
    "path": "fodder/blog/check",
    "content": ""
  },
  {
    "path": "install.sh",
    "content": "#!/usr/bin/env bash\n# 检测区\n# -------------------------------------------------------------\n# 检查系统\nexport LANG=en_US.UTF-8\n\nechoContent() {\n    case $1 in\n    # 红色\n    \"red\")\n        # shellcheck disable=SC2154\n        ${echoType} \"\\033[31m${printN}$2 \\033[0m\"\n        ;;\n        # 天蓝色\n    \"skyBlue\")\n        ${echoType} \"\\033[1;36m${printN}$2 \\033[0m\"\n        ;;\n        # 绿色\n    \"green\")\n        ${echoType} \"\\033[32m${printN}$2 \\033[0m\"\n        ;;\n        # 白色\n    \"white\")\n        ${echoType} \"\\033[37m${printN}$2 \\033[0m\"\n        ;;\n    \"magenta\")\n        ${echoType} \"\\033[31m${printN}$2 \\033[0m\"\n        ;;\n        # 黄色\n    \"yellow\")\n        ${echoType} \"\\033[33m${printN}$2 \\033[0m\"\n        ;;\n    esac\n}\n# 检查SELinux状态\ncheckCentosSELinux() {\n    if command -v getenforce >/dev/null 2>&1 && [ \"$(getenforce)\" == \"Enforcing\" ]; then\n        echoContent yellow \"# 注意事项\"\n        echoContent yellow \"检测到SELinux已开启，请手动关闭，教程如下\"\n        echoContent yellow \"https://www.v2ray-agent.com/archives/1684115970026#centos-%E5%85%B3%E9%97%ADselinux\"\n        exit 0\n    fi\n}\ncheckSystem() {\n    if [[ -n $(find /etc -name \"redhat-release\") ]] || grep </proc/version -q -i \"centos\"; then\n        mkdir -p /etc/yum.repos.d\n\n        if [[ -f \"/etc/centos-release\" ]]; then\n            centosVersion=$(rpm -q centos-release | awk -F \"[-]\" '{print $3}' | awk -F \"[.]\" '{print $1}')\n\n            if [[ -z \"${centosVersion}\" ]] && grep </etc/centos-release -q -i \"release 8\"; then\n                centosVersion=8\n            fi\n        fi\n\n        release=\"centos\"\n        installType='yum -y install'\n        removeType='yum -y remove'\n        #        upgrade=\"yum update -y --skip-broken\"\n        checkCentosSELinux\n    elif { [[ -f \"/etc/issue\" ]] && grep -qi \"Alpine\" /etc/issue; } || { [[ -f \"/proc/version\" ]] && grep -qi \"Alpine\" /proc/version; }; then\n        release=\"alpine\"\n        installType='apk add'\n        upgrade=\"apk update\"\n        removeType='apk del'\n        nginxConfigPath=/etc/nginx/http.d/\n    elif { [[ -f \"/etc/issue\" ]] && grep -qi \"debian\" /etc/issue; } || { [[ -f \"/proc/version\" ]] && grep -qi \"debian\" /proc/version; } || { [[ -f \"/etc/os-release\" ]] && grep -qi \"ID=debian\" /etc/issue; }; then\n        release=\"debian\"\n        installType='apt -y install'\n        upgrade=\"apt update\"\n        updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'\n        removeType='apt -y autoremove'\n\n    elif { [[ -f \"/etc/issue\" ]] && grep -qi \"ubuntu\" /etc/issue; } || { [[ -f \"/proc/version\" ]] && grep -qi \"ubuntu\" /proc/version; }; then\n        release=\"ubuntu\"\n        installType='apt -y install'\n        upgrade=\"apt update\"\n        updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'\n        removeType='apt -y autoremove'\n        if grep </etc/issue -q -i \"16.\"; then\n            release=\n        fi\n    fi\n\n    if [[ -z ${release} ]]; then\n        echoContent red \"\\n本脚本不支持此系统，请将下方日志反馈给开发者\\n\"\n        echoContent yellow \"$(cat /etc/issue)\"\n        echoContent yellow \"$(cat /proc/version)\"\n        exit 0\n    fi\n}\n\n# 检查CPU提供商\ncheckCPUVendor() {\n    if [[ -n $(which uname) ]]; then\n        if [[ \"$(uname)\" == \"Linux\" ]]; then\n            case \"$(uname -m)\" in\n            'amd64' | 'x86_64')\n                xrayCoreCPUVendor=\"Xray-linux-64\"\n                #                v2rayCoreCPUVendor=\"v2ray-linux-64\"\n                warpRegCoreCPUVendor=\"main-linux-amd64\"\n                singBoxCoreCPUVendor=\"-linux-amd64\"\n                ;;\n            'armv8' | 'aarch64')\n                cpuVendor=\"arm\"\n                xrayCoreCPUVendor=\"Xray-linux-arm64-v8a\"\n                #                v2rayCoreCPUVendor=\"v2ray-linux-arm64-v8a\"\n                warpRegCoreCPUVendor=\"main-linux-arm64\"\n                singBoxCoreCPUVendor=\"-linux-arm64\"\n                ;;\n            *)\n                echo \"  不支持此CPU架构--->\"\n                exit 1\n                ;;\n            esac\n        fi\n    else\n        echoContent red \"  无法识别此CPU架构，默认amd64、x86_64--->\"\n        xrayCoreCPUVendor=\"Xray-linux-64\"\n        #        v2rayCoreCPUVendor=\"v2ray-linux-64\"\n    fi\n}\n\n# 初始化全局变量\ninitVar() {\n    installType='yum -y install'\n    removeType='yum -y remove'\n    upgrade=\"yum -y update\"\n    echoType='echo -e'\n    #    sudoCMD=\"\"\n\n    # 核心支持的cpu版本\n    xrayCoreCPUVendor=\"\"\n    warpRegCoreCPUVendor=\"\"\n    cpuVendor=\"\"\n\n    # 域名\n    domain=\n    # 安装总进度\n    totalProgress=1\n\n    # 1.xray-core安装\n    # 2.v2ray-core 安装\n    # 3.v2ray-core[xtls] 安装\n    coreInstallType=\n\n    # 核心安装path\n    # coreInstallPath=\n\n    # v2ctl Path\n    ctlPath=\n    # 1.全部安装\n    # 2.个性化安装\n    # v2rayAgentInstallType=\n\n    # 当前的个性化安装方式 01234\n    currentInstallProtocolType=\n\n    # 当前alpn的顺序\n    currentAlpn=\n\n    # 前置类型\n    frontingType=\n\n    # 选择的个性化安装方式\n    selectCustomInstallType=\n\n    # v2ray-core、xray-core配置文件的路径\n    configPath=\n\n    # xray-core reality状态\n    realityStatus=\n\n    # sing-box配置文件路径\n    singBoxConfigPath=\n\n    # sing-box端口\n\n    singBoxVLESSVisionPort=\n    singBoxVLESSRealityVisionPort=\n    singBoxVLESSRealityGRPCPort=\n    singBoxHysteria2Port=\n    singBoxTrojanPort=\n    singBoxTuicPort=\n    singBoxNaivePort=\n    singBoxVMessWSPort=\n    singBoxVLESSWSPort=\n    singBoxVMessHTTPUpgradePort=\n\n    # nginx订阅端口\n    subscribePort=\n\n    subscribeType=\n\n    # sing-box reality serverName publicKey\n    singBoxVLESSRealityGRPCServerName=\n    singBoxVLESSRealityVisionServerName=\n    singBoxVLESSRealityPublicKey=\n\n    # xray-core reality serverName publicKey\n    xrayVLESSRealityServerName=\n    xrayVLESSRealityPort=\n    xrayVLESSRealityXHTTPServerName=\n    xrayVLESSRealityXHTTPort=\n    #    xrayVLESSRealityPublicKey=\n\n    #    interfaceName=\n    # 端口跳跃\n    portHoppingStart=\n    portHoppingEnd=\n    portHopping=\n\n    hysteria2PortHoppingStart=\n    hysteria2PortHoppingEnd=\n    hysteria2PortHopping=\n\n    #    tuicPortHoppingStart=\n    #    tuicPortHoppingEnd=\n    #    tuicPortHopping=\n\n    # tuic配置文件路径\n    #    tuicConfigPath=\n    tuicAlgorithm=\n    tuicPort=\n\n    # 配置文件的path\n    currentPath=\n\n    # 配置文件的host\n    currentHost=\n\n    # 安装时选择的core类型\n    selectCoreType=\n\n    # 默认core版本\n    #    v2rayCoreVersion=\n\n    # 随机路径\n    customPath=\n\n    # centos version\n    centosVersion=\n\n    # UUID\n    currentUUID=\n\n    # clients\n    currentClients=\n\n    # previousClients\n    #    previousClients=\n\n    localIP=\n\n    # 定时任务执行任务名称 RenewTLS-更新证书 UpdateGeo-更新geo文件\n    cronName=$1\n\n    # tls安装失败后尝试的次数\n    installTLSCount=\n\n    # BTPanel状态\n    #\tBTPanelStatus=\n    # 宝塔域名\n    btDomain=\n    # nginx配置文件路径\n    nginxConfigPath=/etc/nginx/conf.d/\n    nginxStaticPath=/usr/share/nginx/html/\n\n    # 是否为预览版\n    prereleaseStatus=false\n\n    # ssl类型\n    sslType=\n    # SSL CF API Token\n    cfAPIToken=\n\n    # ssl邮箱\n    sslEmail=\n\n    # 检查天数\n    sslRenewalDays=90\n\n    # dns ssl状态\n    #    dnsSSLStatus=\n\n    # dns tls domain\n    dnsTLSDomain=\n    ipType=\n\n    # 该域名是否通过dns安装通配符证书\n    #    installDNSACMEStatus=\n\n    # 自定义端口\n    customPort=\n\n    # hysteria端口\n    hysteriaPort=\n\n    # hysteria协议\n    #    hysteriaProtocol=\n\n    # hysteria延迟\n    #    hysteriaLag=\n\n    # hysteria下行速度\n    hysteria2ClientDownloadSpeed=\n\n    # hysteria上行速度\n    hysteria2ClientUploadSpeed=\n\n    # Reality\n    realityPrivateKey=\n    realityServerName=\n    realityDestDomain=\n\n    # 端口状态\n    #    isPortOpen=\n    # 通配符域名状态\n    #    wildcardDomainStatus=\n    # 通过nginx检查的端口\n    #    nginxIPort=\n\n    # wget show progress\n    wgetShowProgressStatus=\n\n    # warp\n    reservedWarpReg=\n    publicKeyWarpReg=\n    addressWarpReg=\n    secretKeyWarpReg=\n\n    # 上次安装配置状态\n    lastInstallationConfig=\n\n}\n\n# 读取tls证书详情\nreadAcmeTLS() {\n    local readAcmeDomain=\n    if [[ -n \"${currentHost}\" ]]; then\n        readAcmeDomain=\"${currentHost}\"\n    fi\n\n    if [[ -n \"${domain}\" ]]; then\n        readAcmeDomain=\"${domain}\"\n    fi\n\n    dnsTLSDomain=$(echo \"${readAcmeDomain}\" | awk -F \".\" '{$1=\"\";print $0}' | sed 's/^[[:space:]]*//' | sed 's/ /./g')\n    if [[ -d \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc\" && -f \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.key\" && -f \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer\" ]]; then\n        installedDNSAPIStatus=true\n    fi\n}\n\n# 读取默认自定义端口\nreadCustomPort() {\n    if [[ -n \"${configPath}\" && -z \"${realityStatus}\" && \"${coreInstallType}\" == \"1\" ]]; then\n        local port=\n        port=$(jq -r .inbounds[0].port \"${configPath}${frontingType}.json\")\n        if [[ \"${port}\" != \"443\" ]]; then\n            customPort=${port}\n        fi\n    fi\n}\n\n# 读取nginx订阅端口\nreadNginxSubscribe() {\n    subscribeType=\"https\"\n    if [[ -f \"${nginxConfigPath}subscribe.conf\" ]]; then\n        if grep -q \"sing-box\" \"${nginxConfigPath}subscribe.conf\"; then\n            subscribePort=$(grep \"listen\" \"${nginxConfigPath}subscribe.conf\" | awk '{print $2}')\n            subscribeDomain=$(grep \"server_name\" \"${nginxConfigPath}subscribe.conf\" | awk '{print $2}')\n            subscribeDomain=${subscribeDomain//;/}\n            if [[ -n \"${currentHost}\" && \"${subscribeDomain}\" != \"${currentHost}\" ]]; then\n                subscribePort=\n                subscribeType=\n            else\n                if ! grep \"listen\" \"${nginxConfigPath}subscribe.conf\" | grep -q \"ssl\"; then\n                    subscribeType=\"http\"\n                fi\n            fi\n\n        fi\n    fi\n}\n\n# 检测安装方式\nreadInstallType() {\n    coreInstallType=\n    configPath=\n    singBoxConfigPath=\n\n    # 1.检测安装目录\n    if [[ -d \"/etc/v2ray-agent\" ]]; then\n        if [[ -f \"/etc/v2ray-agent/xray/xray\" ]]; then\n            # 检测xray-core\n            if [[ -d \"/etc/v2ray-agent/xray/conf\" ]] && [[ -f \"/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json\" || -f \"/etc/v2ray-agent/xray/conf/02_trojan_TCP_inbounds.json\" || -f \"/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json\" ]]; then\n                # xray-core\n                configPath=/etc/v2ray-agent/xray/conf/\n                ctlPath=/etc/v2ray-agent/xray/xray\n                coreInstallType=1\n                if [[ -f \"${configPath}07_VLESS_vision_reality_inbounds.json\" ]]; then\n                    realityStatus=1\n                fi\n                if [[ -f \"/etc/v2ray-agent/sing-box/sing-box\" ]] && [[ -f \"/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json\" || -f \"/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json\" || -f \"/etc/v2ray-agent/sing-box/conf/config/20_socks5_inbounds.json\" ]]; then\n                    singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/\n                fi\n            fi\n        elif [[ -f \"/etc/v2ray-agent/sing-box/sing-box\" && -f \"/etc/v2ray-agent/sing-box/conf/config.json\" ]]; then\n            # 检测sing-box\n            ctlPath=/etc/v2ray-agent/sing-box/sing-box\n            coreInstallType=2\n            configPath=/etc/v2ray-agent/sing-box/conf/config/\n            singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/\n        fi\n    fi\n}\n\n# 读取协议类型\nreadInstallProtocolType() {\n    currentInstallProtocolType=\n    frontingType=\n\n    xrayVLESSRealityPort=\n    xrayVLESSRealityServerName=\n\n    xrayVLESSRealityXHTTPort=\n    xrayVLESSRealityXHTTPServerName=\n\n    #    currentRealityXHTTPPrivateKey=\n    currentRealityXHTTPPublicKey=\n\n    currentRealityPrivateKey=\n    currentRealityPublicKey=\n\n    currentRealityMldsa65Seed=\n    currentRealityMldsa65Verify=\n\n    singBoxVLESSVisionPort=\n    singBoxHysteria2Port=\n    singBoxTrojanPort=\n\n    frontingTypeReality=\n    singBoxVLESSRealityVisionPort=\n    singBoxVLESSRealityVisionServerName=\n    singBoxVLESSRealityGRPCPort=\n    singBoxVLESSRealityGRPCServerName=\n    singBoxAnyTLSPort=\n    singBoxTuicPort=\n    singBoxNaivePort=\n    singBoxVMessWSPort=\n    singBoxSocks5Port=\n\n    while read -r row; do\n        if echo \"${row}\" | grep -q VLESS_TCP_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}0,\"\n            frontingType=02_VLESS_TCP_inbounds\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                singBoxVLESSVisionPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q VLESS_WS_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}1,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=03_VLESS_WS_inbounds\n                singBoxVLESSWSPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q VLESS_XHTTP_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}12,\"\n            xrayVLESSRealityXHTTPort=$(jq -r .inbounds[0].port \"${row}.json\")\n\n            xrayVLESSRealityXHTTPServerName=$(jq -r .inbounds[0].streamSettings.realitySettings.serverNames[0] \"${row}.json\")\n\n            currentRealityXHTTPPublicKey=$(jq -r .inbounds[0].streamSettings.realitySettings.publicKey \"${row}.json\")\n            #            currentRealityXHTTPPrivateKey=$(jq -r .inbounds[0].streamSettings.realitySettings.privateKey \"${row}.json\")\n\n            #            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n            #                frontingType=03_VLESS_WS_inbounds\n            #                singBoxVLESSWSPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            #            fi\n        fi\n\n        if echo \"${row}\" | grep -q trojan_gRPC_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}2,\"\n        fi\n        if echo \"${row}\" | grep -q VMess_WS_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}3,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=05_VMess_WS_inbounds\n                singBoxVMessWSPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q trojan_TCP_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}4,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=04_trojan_TCP_inbounds\n                singBoxTrojanPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q VLESS_gRPC_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}5,\"\n        fi\n        if echo \"${row}\" | grep -q hysteria2_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}6,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=06_hysteria2_inbounds\n                singBoxHysteria2Port=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q VLESS_vision_reality_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}7,\"\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                xrayVLESSRealityServerName=$(jq -r .inbounds[1].streamSettings.realitySettings.serverNames[0] \"${row}.json\")\n                realityServerName=${xrayVLESSRealityServerName}\n                xrayVLESSRealityPort=$(jq -r .inbounds[0].port \"${row}.json\")\n\n                realityDomainPort=$(jq -r .inbounds[1].streamSettings.realitySettings.target \"${row}.json\" | awk -F '[:]' '{print $2}')\n\n                currentRealityPublicKey=$(jq -r .inbounds[1].streamSettings.realitySettings.publicKey \"${row}.json\")\n                currentRealityPrivateKey=$(jq -r .inbounds[1].streamSettings.realitySettings.privateKey \"${row}.json\")\n\n                currentRealityMldsa65Seed=$(jq -r .inbounds[1].streamSettings.realitySettings.mldsa65Seed \"${row}.json\")\n                currentRealityMldsa65Verify=$(jq -r .inbounds[1].streamSettings.realitySettings.mldsa65Verify \"${row}.json\")\n\n                frontingTypeReality=07_VLESS_vision_reality_inbounds\n\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingTypeReality=07_VLESS_vision_reality_inbounds\n                singBoxVLESSRealityVisionPort=$(jq -r .inbounds[0].listen_port \"${row}.json\")\n                singBoxVLESSRealityVisionServerName=$(jq -r .inbounds[0].tls.server_name \"${row}.json\")\n                realityDomainPort=$(jq -r .inbounds[0].tls.reality.handshake.server_port \"${row}.json\")\n\n                realityServerName=${singBoxVLESSRealityVisionServerName}\n                if [[ -f \"${configPath}reality_key\" ]]; then\n                    singBoxVLESSRealityPublicKey=$(grep \"publicKey\" <\"${configPath}reality_key\" | awk -F \"[:]\" '{print $2}')\n\n                    currentRealityPrivateKey=$(jq -r .inbounds[0].tls.reality.private_key \"${row}.json\")\n                    currentRealityPublicKey=$(grep \"publicKey\" <\"${configPath}reality_key\" | awk -F \"[:]\" '{print $2}')\n                fi\n            fi\n        fi\n        if echo \"${row}\" | grep -q VLESS_vision_gRPC_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}8,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingTypeReality=08_VLESS_vision_gRPC_inbounds\n                singBoxVLESSRealityGRPCPort=$(jq -r .inbounds[0].listen_port \"${row}.json\")\n                singBoxVLESSRealityGRPCServerName=$(jq -r .inbounds[0].tls.server_name \"${row}.json\")\n                if [[ -f \"${configPath}reality_key\" ]]; then\n                    singBoxVLESSRealityPublicKey=$(grep \"publicKey\" <\"${configPath}reality_key\" | awk -F \"[:]\" '{print $2}')\n                fi\n            fi\n        fi\n        if echo \"${row}\" | grep -q tuic_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}9,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=09_tuic_inbounds\n                singBoxTuicPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q naive_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}10,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=10_naive_inbounds\n                singBoxNaivePort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q anytls_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}13,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=13_anytls_inbounds\n                singBoxAnyTLSPort=$(jq .inbounds[0].listen_port \"${row}.json\")\n            fi\n        fi\n        if echo \"${row}\" | grep -q VMess_HTTPUpgrade_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}11,\"\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                frontingType=11_VMess_HTTPUpgrade_inbounds\n                singBoxVMessHTTPUpgradePort=$(grep 'listen' <${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf | awk '{print $2}')\n            fi\n        fi\n        if echo \"${row}\" | grep -q socks5_inbounds; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}20,\"\n            singBoxSocks5Port=$(jq .inbounds[0].listen_port \"${row}.json\")\n        fi\n\n    done < <(find ${configPath} -name \"*inbounds.json\" | sort | awk -F \"[.]\" '{print $1}')\n\n    if [[ \"${coreInstallType}\" == \"1\" && -n \"${singBoxConfigPath}\" ]]; then\n        if [[ -f \"${singBoxConfigPath}06_hysteria2_inbounds.json\" ]]; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}6,\"\n            singBoxHysteria2Port=$(jq .inbounds[0].listen_port \"${singBoxConfigPath}06_hysteria2_inbounds.json\")\n        fi\n        if [[ -f \"${singBoxConfigPath}09_tuic_inbounds.json\" ]]; then\n            currentInstallProtocolType=\"${currentInstallProtocolType}9,\"\n            singBoxTuicPort=$(jq .inbounds[0].listen_port \"${singBoxConfigPath}09_tuic_inbounds.json\")\n        fi\n    fi\n    if [[ \"${currentInstallProtocolType:0:1}\" != \",\" ]]; then\n        currentInstallProtocolType=\",${currentInstallProtocolType}\"\n    fi\n}\n\n# 检查是否安装宝塔\ncheckBTPanel() {\n    if [[ -n $(pgrep -f \"BT-Panel\") ]]; then\n        # 读取域名\n        if [[ -d '/www/server/panel/vhost/cert/' && -n $(find /www/server/panel/vhost/cert/*/fullchain.pem) ]]; then\n            if [[ -z \"${currentHost}\" ]]; then\n                echoContent skyBlue \"\\n读取宝塔配置\\n\"\n\n                find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F \"[/]\" '{print $7}' | awk '{print NR\"\"\":\"$0}'\n\n                read -r -p \"请输入编号选择:\" selectBTDomain\n            else\n                selectBTDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F \"[/]\" '{print $7}' | awk '{print NR\"\"\":\"$0}' | grep \"${currentHost}\" | cut -d \":\" -f 1)\n            fi\n\n            if [[ -n \"${selectBTDomain}\" ]]; then\n                btDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F \"[/]\" '{print $7}' | awk '{print NR\"\"\":\"$0}' | grep -e \"^${selectBTDomain}:\" | cut -d \":\" -f 2)\n\n                if [[ -z \"${btDomain}\" ]]; then\n                    echoContent red \" ---> 选择错误，请重新选择\"\n                    checkBTPanel\n                else\n                    domain=${btDomain}\n                    if [[ ! -f \"/etc/v2ray-agent/tls/${btDomain}.crt\" && ! -f \"/etc/v2ray-agent/tls/${btDomain}.key\" ]]; then\n                        ln -s \"/www/server/panel/vhost/cert/${btDomain}/fullchain.pem\" \"/etc/v2ray-agent/tls/${btDomain}.crt\"\n                        ln -s \"/www/server/panel/vhost/cert/${btDomain}/privkey.pem\" \"/etc/v2ray-agent/tls/${btDomain}.key\"\n                    fi\n\n                    nginxStaticPath=\"/www/wwwroot/${btDomain}/html/\"\n\n                    mkdir -p \"/www/wwwroot/${btDomain}/html/\"\n\n                    if [[ -f \"/www/wwwroot/${btDomain}/.user.ini\" ]]; then\n                        chattr -i \"/www/wwwroot/${btDomain}/.user.ini\"\n                    fi\n                    nginxConfigPath=\"/www/server/panel/vhost/nginx/\"\n                fi\n            else\n                echoContent red \" ---> 选择错误，请重新选择\"\n                checkBTPanel\n            fi\n        fi\n    fi\n}\ncheck1Panel() {\n    if [[ -n $(pgrep -f \"1panel\") ]]; then\n        # 读取域名\n        if [[ -d '/opt/1panel/apps/openresty/openresty/www/sites/' && -n $(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem) ]]; then\n            if [[ -z \"${currentHost}\" ]]; then\n                echoContent skyBlue \"\\n读取1Panel配置\\n\"\n\n                find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F \"[/]\" '{print $9}' | awk '{print NR\"\"\":\"$0}'\n\n                read -r -p \"请输入编号选择:\" selectBTDomain\n            else\n                selectBTDomain=$(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F \"[/]\" '{print $9}' | awk '{print NR\"\"\":\"$0}' | grep \"${currentHost}\" | cut -d \":\" -f 1)\n            fi\n\n            if [[ -n \"${selectBTDomain}\" ]]; then\n                btDomain=$(find /opt/1panel/apps/openresty/openresty/www/sites/*/ssl/fullchain.pem | awk -F \"[/]\" '{print $9}' | awk '{print NR\"\"\":\"$0}' | grep \"${selectBTDomain}:\" | cut -d \":\" -f 2)\n\n                if [[ -z \"${btDomain}\" ]]; then\n                    echoContent red \" ---> 选择错误，请重新选择\"\n                    check1Panel\n                else\n                    domain=${btDomain}\n                    if [[ ! -f \"/etc/v2ray-agent/tls/${btDomain}.crt\" && ! -f \"/etc/v2ray-agent/tls/${btDomain}.key\" ]]; then\n                        ln -s \"/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/ssl/fullchain.pem\" \"/etc/v2ray-agent/tls/${btDomain}.crt\"\n                        ln -s \"/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/ssl/privkey.pem\" \"/etc/v2ray-agent/tls/${btDomain}.key\"\n                    fi\n\n                    nginxStaticPath=\"/opt/1panel/apps/openresty/openresty/www/sites/${btDomain}/index/\"\n                fi\n            else\n                echoContent red \" ---> 选择错误，请重新选择\"\n                check1Panel\n            fi\n        fi\n    fi\n}\n# 读取当前alpn的顺序\nreadInstallAlpn() {\n    if [[ -n \"${currentInstallProtocolType}\" && -z \"${realityStatus}\" ]]; then\n        local alpn\n        alpn=$(jq -r .inbounds[0].streamSettings.tlsSettings.alpn[0] ${configPath}${frontingType}.json)\n        if [[ -n ${alpn} ]]; then\n            currentAlpn=${alpn}\n        fi\n    fi\n}\n\n# 检查防火墙\nallowPort() {\n    local type=$2\n    if [[ -z \"${type}\" ]]; then\n        type=tcp\n    fi\n    # 如果防火墙启动状态则添加相应的开放端口\n    if command -v dpkg >/dev/null 2>&1 && dpkg -l | grep -q \"^[[:space:]]*ii[[:space:]]\\+ufw\"; then\n        if ufw status | grep -q \"Status: active\"; then\n            if ! ufw status | grep -q \"$1/${type}\"; then\n                sudo ufw allow \"$1/${type}\"\n                checkUFWAllowPort \"$1\"\n            fi\n        fi\n    elif systemctl status firewalld 2>/dev/null | grep -q \"active (running)\"; then\n        local updateFirewalldStatus=\n        if ! firewall-cmd --list-ports --permanent | grep -qw \"$1/${type}\"; then\n            updateFirewalldStatus=true\n            local firewallPort=$1\n            if echo \"${firewallPort}\" | grep -q \":\"; then\n                firewallPort=$(echo \"${firewallPort}\" | awk -F \":\" '{print $1\"-\"$2}')\n            fi\n            firewall-cmd --zone=public --add-port=\"${firewallPort}/${type}\" --permanent\n            checkFirewalldAllowPort \"${firewallPort}\"\n        fi\n\n        if echo \"${updateFirewalldStatus}\" | grep -q \"true\"; then\n            firewall-cmd --reload\n        fi\n    elif rc-update show 2>/dev/null | grep -q ufw; then\n        if ufw status | grep -q \"Status: active\"; then\n            if ! ufw status | grep -q \"$1/${type}\"; then\n                sudo ufw allow \"$1/${type}\"\n                checkUFWAllowPort \"$1\"\n            fi\n        fi\n    elif dpkg -l | grep -q \"^[[:space:]]*ii[[:space:]]\\+netfilter-persistent\" && systemctl status netfilter-persistent 2>/dev/null | grep -q \"active (exited)\"; then\n        local updateFirewalldStatus=\n        if ! iptables -L | grep -q \"$1/${type}(mack-a)\"; then\n            updateFirewalldStatus=true\n            iptables -I INPUT -p \"${type}\" --dport \"$1\" -m comment --comment \"allow $1/${type}(mack-a)\" -j ACCEPT\n        fi\n\n        if echo \"${updateFirewalldStatus}\" | grep -q \"true\"; then\n            netfilter-persistent save\n        fi\n    fi\n}\n# 获取公网IP\ngetPublicIP() {\n    local type=4\n    if [[ -n \"$1\" ]]; then\n        type=$1\n    fi\n    if [[ -n \"${currentHost}\" && -z \"$1\" ]] && [[ \"${singBoxVLESSRealityVisionServerName}\" == \"${currentHost}\" || \"${singBoxVLESSRealityGRPCServerName}\" == \"${currentHost}\" || \"${xrayVLESSRealityServerName}\" == \"${currentHost}\" ]]; then\n        echo \"${currentHost}\"\n    else\n        local currentIP=\n        currentIP=$(curl -s \"-${type}\" http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | awk -F \"[=]\" '{print $2}')\n        if [[ -z \"${currentIP}\" && -z \"$1\" ]]; then\n            currentIP=$(curl -s \"-6\" http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | awk -F \"[=]\" '{print $2}')\n        fi\n        echo \"${currentIP}\"\n    fi\n\n}\n\n# 输出ufw端口开放状态\ncheckUFWAllowPort() {\n    if ufw status | grep -q \"$1\"; then\n        echoContent green \" ---> $1端口开放成功\"\n    else\n        echoContent red \" ---> $1端口开放失败\"\n        exit 0\n    fi\n}\n\n# 输出firewall-cmd端口开放状态\ncheckFirewalldAllowPort() {\n    if firewall-cmd --list-ports --permanent | grep -q \"$1\"; then\n        echoContent green \" ---> $1端口开放成功\"\n    else\n        echoContent red \" ---> $1端口开放失败\"\n        exit 0\n    fi\n}\n\n# 读取Tuic配置\nreadSingBoxConfig() {\n    tuicPort=\n    hysteriaPort=\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n        if [[ -f \"${singBoxConfigPath}09_tuic_inbounds.json\" ]]; then\n            tuicPort=$(jq -r '.inbounds[0].listen_port' \"${singBoxConfigPath}09_tuic_inbounds.json\")\n            tuicAlgorithm=$(jq -r '.inbounds[0].congestion_control' \"${singBoxConfigPath}09_tuic_inbounds.json\")\n        fi\n        if [[ -f \"${singBoxConfigPath}06_hysteria2_inbounds.json\" ]]; then\n            hysteriaPort=$(jq -r '.inbounds[0].listen_port' \"${singBoxConfigPath}06_hysteria2_inbounds.json\")\n            hysteria2ClientUploadSpeed=$(jq -r '.inbounds[0].down_mbps' \"${singBoxConfigPath}06_hysteria2_inbounds.json\")\n            hysteria2ClientDownloadSpeed=$(jq -r '.inbounds[0].up_mbps' \"${singBoxConfigPath}06_hysteria2_inbounds.json\")\n        fi\n    fi\n}\n\n# 读取上次安装的配置\nreadLastInstallationConfig() {\n    if [[ -n \"${configPath}\" ]]; then\n        read -r -p \"读取到上次安装的配置，是否使用 ？[y/n]:\" lastInstallationConfigStatus\n        if [[ \"${lastInstallationConfigStatus}\" == \"y\" ]]; then\n            lastInstallationConfig=true\n        fi\n    fi\n}\n# 卸载 sing-box\nunInstallSingBox() {\n    local type=$1\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        if grep -q 'tuic' </etc/v2ray-agent/sing-box/conf/config.json && [[ \"${type}\" == \"tuic\" ]]; then\n            rm \"${singBoxConfigPath}09_tuic_inbounds.json\"\n            echoContent green \" ---> 删除sing-box tuic配置成功\"\n        fi\n\n        if grep -q 'hysteria2' </etc/v2ray-agent/sing-box/conf/config.json && [[ \"${type}\" == \"hysteria2\" ]]; then\n            rm \"${singBoxConfigPath}06_hysteria2_inbounds.json\"\n            echoContent green \" ---> 删除sing-box hysteria2配置成功\"\n        fi\n        rm \"${singBoxConfigPath}config.json\"\n    fi\n\n    readInstallType\n\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        echoContent yellow \" ---> 检测到有其他配置，保留sing-box核心\"\n        handleSingBox stop\n        handleSingBox start\n    else\n        handleSingBox stop\n        rm /etc/systemd/system/sing-box.service\n        rm -rf /etc/v2ray-agent/sing-box/*\n        echoContent green \" ---> sing-box 卸载完成\"\n    fi\n}\n\n# 检查文件目录以及path路径\nreadConfigHostPathUUID() {\n    currentPath=\n    currentDefaultPort=\n    currentUUID=\n    currentClients=\n    currentHost=\n    currentPort=\n    currentCDNAddress=\n    singBoxVMessWSPath=\n    singBoxVLESSWSPath=\n    singBoxVMessHTTPUpgradePath=\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        # 安装\n        if [[ -n \"${frontingType}\" ]]; then\n            currentHost=$(jq -r .inbounds[0].streamSettings.tlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}')\n\n            currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json)\n\n            local defaultPortFile=\n            defaultPortFile=$(find ${configPath}* | grep \"default\")\n\n            if [[ -n \"${defaultPortFile}\" ]]; then\n                currentDefaultPort=$(echo \"${defaultPortFile}\" | awk -F [_] '{print $4}')\n            else\n                currentDefaultPort=$(jq -r .inbounds[0].port ${configPath}${frontingType}.json)\n            fi\n            currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json)\n            currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}${frontingType}.json)\n        fi\n\n        # reality\n        if echo ${currentInstallProtocolType} | grep -q \",7,\"; then\n\n            currentClients=$(jq -r .inbounds[1].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json)\n            currentUUID=$(jq -r .inbounds[1].settings.clients[0].id ${configPath}07_VLESS_vision_reality_inbounds.json)\n            xrayVLESSRealityVisionPort=$(jq -r .inbounds[0].port ${configPath}07_VLESS_vision_reality_inbounds.json)\n            if [[ \"${currentPort}\" == \"${xrayVLESSRealityVisionPort}\" ]]; then\n                xrayVLESSRealityVisionPort=\"${currentDefaultPort}\"\n            fi\n        fi\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        if [[ -n \"${frontingType}\" ]]; then\n            currentHost=$(jq -r .inbounds[0].tls.server_name ${configPath}${frontingType}.json)\n            if echo ${currentInstallProtocolType} | grep -q \",11,\" && [[ \"${currentHost}\" == \"null\" ]]; then\n                currentHost=$(grep 'server_name' <${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf | awk '{print $2}')\n                currentHost=${currentHost//;/}\n            fi\n            currentUUID=$(jq -r .inbounds[0].users[0].uuid ${configPath}${frontingType}.json)\n            currentClients=$(jq -r .inbounds[0].users ${configPath}${frontingType}.json)\n        else\n            currentUUID=$(jq -r .inbounds[0].users[0].uuid ${configPath}${frontingTypeReality}.json)\n            currentClients=$(jq -r .inbounds[0].users ${configPath}${frontingTypeReality}.json)\n        fi\n    fi\n\n    # 读取path\n    if [[ -n \"${configPath}\" && -n \"${frontingType}\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            local fallback\n            fallback=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.path)' ${configPath}${frontingType}.json | head -1)\n\n            local path\n            path=$(echo \"${fallback}\" | jq -r .path | awk -F \"[/]\" '{print $2}')\n\n            if [[ $(echo \"${fallback}\" | jq -r .dest) == 31297 ]]; then\n                currentPath=$(echo \"${path}\" | awk -F \"[w][s]\" '{print $1}')\n            elif [[ $(echo \"${fallback}\" | jq -r .dest) == 31299 ]]; then\n                currentPath=$(echo \"${path}\" | awk -F \"[v][w][s]\" '{print $1}')\n            fi\n\n            # 尝试读取alpn h2 Path\n            if [[ -z \"${currentPath}\" ]]; then\n                dest=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.alpn)|.dest' ${configPath}${frontingType}.json | head -1)\n                if [[ \"${dest}\" == \"31302\" || \"${dest}\" == \"31304\" ]]; then\n                    checkBTPanel\n                    check1Panel\n                    if grep -q \"trojangrpc {\" <${nginxConfigPath}alone.conf; then\n                        currentPath=$(grep \"trojangrpc {\" <${nginxConfigPath}alone.conf | awk -F \"[/]\" '{print $2}' | awk -F \"[t][r][o][j][a][n]\" '{print $1}')\n                    elif grep -q \"grpc {\" <${nginxConfigPath}alone.conf; then\n                        currentPath=$(grep \"grpc {\" <${nginxConfigPath}alone.conf | head -1 | awk -F \"[/]\" '{print $2}' | awk -F \"[g][r][p][c]\" '{print $1}')\n                    fi\n                fi\n            fi\n            if [[ -z \"${currentPath}\" && -f \"${configPath}12_VLESS_XHTTP_inbounds.json\" ]]; then\n                currentPath=$(jq -r .inbounds[0].streamSettings.xhttpSettings.path \"${configPath}12_VLESS_XHTTP_inbounds.json\" | awk -F \"[x][H][T][T][P]\" '{print $1}' | awk -F \"[/]\" '{print $2}')\n            fi\n        elif [[ \"${coreInstallType}\" == \"2\" && -f \"${singBoxConfigPath}05_VMess_WS_inbounds.json\" ]]; then\n            singBoxVMessWSPath=$(jq -r .inbounds[0].transport.path \"${singBoxConfigPath}05_VMess_WS_inbounds.json\")\n            currentPath=$(jq -r .inbounds[0].transport.path \"${singBoxConfigPath}05_VMess_WS_inbounds.json\" | awk -F \"[/]\" '{print $2}')\n        fi\n        if [[ \"${coreInstallType}\" == \"2\" && -f \"${singBoxConfigPath}03_VLESS_WS_inbounds.json\" ]]; then\n            singBoxVLESSWSPath=$(jq -r .inbounds[0].transport.path \"${singBoxConfigPath}03_VLESS_WS_inbounds.json\")\n            currentPath=$(jq -r .inbounds[0].transport.path \"${singBoxConfigPath}03_VLESS_WS_inbounds.json\" | awk -F \"[/]\" '{print $2}')\n            currentPath=${currentPath::-2}\n        fi\n        if [[ \"${coreInstallType}\" == \"2\" && -f \"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json\" ]]; then\n            singBoxVMessHTTPUpgradePath=$(jq -r .inbounds[0].transport.path \"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json\")\n            currentPath=$(jq -r .inbounds[0].transport.path \"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json\" | awk -F \"[/]\" '{print $2}')\n            # currentPath=${currentPath::-2}\n        fi\n    fi\n    if [[ -f \"/etc/v2ray-agent/cdn\" ]] && [[ -n \"$(head -1 /etc/v2ray-agent/cdn)\" ]]; then\n        currentCDNAddress=$(head -1 /etc/v2ray-agent/cdn)\n    else\n        currentCDNAddress=\"${currentHost}\"\n    fi\n}\n\n# 状态展示\nshowInstallStatus() {\n    if [[ -n \"${coreInstallType}\" ]]; then\n        if [[ \"${coreInstallType}\" == 1 ]]; then\n            if [[ -n $(pgrep -f \"xray/xray\") ]]; then\n                echoContent yellow \"\\n核心: Xray-core[运行中]\"\n            else\n                echoContent yellow \"\\n核心: Xray-core[未运行]\"\n            fi\n\n        elif [[ \"${coreInstallType}\" == 2 ]]; then\n            if [[ -n $(pgrep -f \"sing-box/sing-box\") ]]; then\n                echoContent yellow \"\\n核心: sing-box[运行中]\"\n            else\n                echoContent yellow \"\\n核心: sing-box[未运行]\"\n            fi\n        fi\n        # 读取协议类型\n        readInstallProtocolType\n\n        if [[ -n ${currentInstallProtocolType} ]]; then\n            echoContent yellow \"已安装协议: \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",0,\"; then\n            echoContent yellow \"VLESS+TCP[TLS_Vision] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",1,\"; then\n            echoContent yellow \"VLESS+WS[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",2,\"; then\n            echoContent yellow \"Trojan+gRPC[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",3,\"; then\n            echoContent yellow \"VMess+WS[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",4,\"; then\n            echoContent yellow \"Trojan+TCP[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",5,\"; then\n            echoContent yellow \"VLESS+gRPC[TLS] \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",6,\"; then\n            echoContent yellow \"Hysteria2 \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",7,\"; then\n            echoContent yellow \"VLESS+Reality+Vision \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",8,\"; then\n            echoContent yellow \"VLESS+Reality+gRPC \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",9,\"; then\n            echoContent yellow \"Tuic \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",10,\"; then\n            echoContent yellow \"Naive \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",11,\"; then\n            echoContent yellow \"VMess+TLS+HTTPUpgrade \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",12,\"; then\n            echoContent yellow \"VLESS+Reality+XHTTP \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",13,\"; then\n            echoContent yellow \"AnyTLS \\c\"\n        fi\n    fi\n}\n\n# 清理旧残留\ncleanUp() {\n    if [[ \"$1\" == \"xrayDel\" ]]; then\n        handleXray stop\n        rm -rf /etc/v2ray-agent/xray/*\n    elif [[ \"$1\" == \"singBoxDel\" ]]; then\n        handleSingBox stop\n        rm -rf /etc/v2ray-agent/sing-box/conf/config.json >/dev/null 2>&1\n        rm -rf /etc/v2ray-agent/sing-box/conf/config/* >/dev/null 2>&1\n    fi\n}\ninitVar \"$1\"\ncheckSystem\ncheckCPUVendor\n\nreadInstallType\nreadInstallProtocolType\nreadConfigHostPathUUID\nreadCustomPort\nreadSingBoxConfig\n# -------------------------------------------------------------\n\n# 初始化安装目录\nmkdirTools() {\n    mkdir -p /etc/v2ray-agent/tls\n    mkdir -p /etc/v2ray-agent/subscribe_local/default\n    mkdir -p /etc/v2ray-agent/subscribe_local/clashMeta\n\n    mkdir -p /etc/v2ray-agent/subscribe_remote/default\n    mkdir -p /etc/v2ray-agent/subscribe_remote/clashMeta\n\n    mkdir -p /etc/v2ray-agent/subscribe/default\n    mkdir -p /etc/v2ray-agent/subscribe/clashMetaProfiles\n    mkdir -p /etc/v2ray-agent/subscribe/clashMeta\n\n    mkdir -p /etc/v2ray-agent/subscribe/sing-box\n    mkdir -p /etc/v2ray-agent/subscribe/sing-box_profiles\n    mkdir -p /etc/v2ray-agent/subscribe_local/sing-box\n\n    mkdir -p /etc/v2ray-agent/xray/conf\n    mkdir -p /etc/v2ray-agent/xray/reality_scan\n    mkdir -p /etc/v2ray-agent/xray/tmp\n    mkdir -p /etc/systemd/system/\n    mkdir -p /tmp/v2ray-agent-tls/\n\n    mkdir -p /etc/v2ray-agent/warp\n\n    mkdir -p /etc/v2ray-agent/sing-box/conf/config\n\n    mkdir -p /usr/share/nginx/html/\n}\n# 检测root\ncheckRoot() {\n    if [ \"$(id -u)\" -ne 0 ]; then\n        #        sudoCMD=\"sudo\"\n        echo \"检测到非 Root 用户，将使用 sudo 执行命令...\"\n    fi\n}\n# 安装工具包\ninstallTools() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 安装工具\"\n    # 修复ubuntu个别系统问题\n    if [[ \"${release}\" == \"ubuntu\" ]]; then\n        dpkg --configure -a\n    fi\n\n    if [[ -n $(pgrep -f \"apt\") ]]; then\n        pgrep -f apt | xargs kill -9\n    fi\n\n    echoContent green \" ---> 检查、安装更新【新机器会很慢，如长时间无反应，请手动停止后重新执行】\"\n\n    if [[ \"${release}\" != \"centos\" ]]; then\n        ${upgrade} >/etc/v2ray-agent/install.log 2>&1\n    fi\n\n    if grep <\"/etc/v2ray-agent/install.log\" -q \"changed\"; then\n        ${updateReleaseInfoChange} >/dev/null 2>&1\n    fi\n\n    if [[ \"${release}\" == \"centos\" ]]; then\n        rm -rf /var/run/yum.pid\n        ${installType} epel-release >/dev/null 2>&1\n    fi\n\n    if ! sudo --version >/dev/null 2>&1; then\n        echoContent green \" ---> 安装sudo\"\n        ${installType} sudo >/dev/null 2>&1\n    fi\n\n    if ! wget --help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装wget\"\n        ${installType} wget >/dev/null 2>&1\n    fi\n\n    if ! command -v netfilter-persistent >/dev/null 2>&1; then\n        if [[ \"${release}\" != \"centos\" ]]; then\n            echoContent green \" ---> 安装iptables\"\n            echo \"iptables-persistent iptables-persistent/autosave_v4 boolean true\" | sudo debconf-set-selections\n            echo \"iptables-persistent iptables-persistent/autosave_v6 boolean true\" | sudo debconf-set-selections\n            ${installType} iptables-persistent >/dev/null 2>&1\n        fi\n    fi\n\n    if ! curl --help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装curl\"\n        ${installType} curl >/dev/null 2>&1\n    fi\n\n    if ! unzip >/dev/null 2>&1; then\n        echoContent green \" ---> 安装unzip\"\n        ${installType} unzip >/dev/null 2>&1\n    fi\n\n    if ! socat -h >/dev/null 2>&1; then\n        echoContent green \" ---> 安装socat\"\n        ${installType} socat >/dev/null 2>&1\n    fi\n\n    if ! tar --help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装tar\"\n        ${installType} tar >/dev/null 2>&1\n    fi\n\n    if ! crontab -l >/dev/null 2>&1; then\n        echoContent green \" ---> 安装crontabs\"\n        if [[ \"${release}\" == \"ubuntu\" || \"${release}\" == \"debian\" ]]; then\n            ${installType} cron >/dev/null 2>&1\n        else\n            ${installType} crontabs >/dev/null 2>&1\n        fi\n    fi\n    if ! jq --help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装jq\"\n        ${installType} jq >/dev/null 2>&1\n    fi\n\n    if ! command -v ld >/dev/null 2>&1; then\n        echoContent green \" ---> 安装binutils\"\n        ${installType} binutils >/dev/null 2>&1\n    fi\n\n    if ! openssl help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装openssl\"\n        ${installType} openssl >/dev/null 2>&1\n    fi\n\n    if ! ping6 --help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装ping6\"\n        ${installType} inetutils-ping >/dev/null 2>&1\n    fi\n\n    if ! qrencode --help >/dev/null 2>&1; then\n        echoContent green \" ---> 安装qrencode\"\n        ${installType} qrencode >/dev/null 2>&1\n    fi\n\n    if ! command -v lsb_release >/dev/null 2>&1; then\n        if [[ \"${release}\" == \"ubuntu\" || \"${release}\" == \"debian\" ]]; then\n            ${installType} lsb-release >/dev/null 2>&1\n        elif [[ \"${release}\" == \"centos\" ]]; then\n            ${installType} redhat-lsb-core >/dev/null 2>&1\n        else\n            ${installType} lsb-release >/dev/null 2>&1\n        fi\n    fi\n\n    if ! lsof -h >/dev/null 2>&1; then\n        echoContent green \" ---> 安装lsof\"\n        ${installType} lsof >/dev/null 2>&1\n    fi\n\n    if ! dig -h >/dev/null 2>&1; then\n        echoContent green \" ---> 安装dig\"\n        if echo \"${installType}\" | grep -qw \"apt\"; then\n            ${installType} dnsutils >/dev/null 2>&1\n        elif echo \"${installType}\" | grep -qw \"yum\"; then\n            ${installType} bind-utils >/dev/null 2>&1\n        elif echo \"${installType}\" | grep -qw \"apk\"; then\n            ${installType} bind-tools >/dev/null 2>&1\n        fi\n    fi\n\n    # 检测nginx版本，并提供是否卸载的选项\n    if echo \"${selectCustomInstallType}\" | grep -qwE \",7,|,8,|,7,8,\"; then\n        echoContent green \" ---> 检测到无需依赖Nginx的服务，跳过安装\"\n    else\n        if ! nginx >/dev/null 2>&1; then\n            echoContent green \" ---> 安装nginx\"\n            installNginxTools\n        else\n            nginxVersion=$(nginx -v 2>&1)\n            nginxVersion=$(echo \"${nginxVersion}\" | awk -F \"[n][g][i][n][x][/]\" '{print $2}' | awk -F \"[.]\" '{print $2}')\n            if [[ ${nginxVersion} -lt 14 ]]; then\n                read -r -p \"读取到当前的Nginx版本不支持gRPC，会导致安装失败，是否卸载Nginx后重新安装 ？[y/n]:\" unInstallNginxStatus\n                if [[ \"${unInstallNginxStatus}\" == \"y\" ]]; then\n                    ${removeType} nginx >/dev/null 2>&1\n                    echoContent yellow \" ---> nginx卸载完成\"\n                    echoContent green \" ---> 安装nginx\"\n                    installNginxTools >/dev/null 2>&1\n                else\n                    exit 0\n                fi\n            fi\n        fi\n    fi\n\n    #    if ! command -v semanage >/dev/null 2>&1 && [[ \"${release}\" == \"centos\" ]]; then\n    #        if command -v getenforce >/dev/null 2>&1 && [ \"$(getenforce)\" == \"Enforcing\" ]; then\n    #            if [[ \"${centosVersion}\" == \"7\" ]]; then\n    #                policyCoreUtils=\"policycoreutils-python\"\n    #            elif [[ \"${centosVersion}\" == \"8\" || \"${centosVersion}\" == \"9\" || \"${centosVersion}\" == \"10\" ]]; then\n    #                policyCoreUtils=\"policycoreutils-python-utils\"\n    #            fi\n    #            echoContent green \" ---> 安装semanage\"\n    #\n    #            if [[ -n \"${policyCoreUtils}\" ]]; then\n    #                ${installType} bash-completion >/dev/null 2>&1\n    #                ${installType} ${policyCoreUtils} >/dev/null 2>&1\n    #            fi\n    #            if [[ -n $(which semanage) ]]; then\n    #                semanage port -a -t http_port_t -p tcp 31300\n    #            fi\n    #        fi\n    #    fi\n\n    if [[ \"${selectCustomInstallType}\" == \"7\" ]]; then\n        echoContent green \" ---> 检测到无需依赖证书的服务，跳过安装\"\n    else\n        if [[ ! -d \"$HOME/.acme.sh\" ]] || [[ -d \"$HOME/.acme.sh\" && -z $(find \"$HOME/.acme.sh/acme.sh\") ]]; then\n            echoContent green \" ---> 安装acme.sh\"\n            curl -s https://get.acme.sh | sh >/etc/v2ray-agent/tls/acme.log 2>&1\n\n            if [[ ! -d \"$HOME/.acme.sh\" ]] || [[ -z $(find \"$HOME/.acme.sh/acme.sh\") ]]; then\n                echoContent red \"  acme安装失败--->\"\n                tail -n 100 /etc/v2ray-agent/tls/acme.log\n                echoContent yellow \"错误排查:\"\n                echoContent red \"  1.获取Github文件失败，请等待Github恢复后尝试，恢复进度可查看 [https://www.githubstatus.com/]\"\n                echoContent red \"  2.acme.sh脚本出现bug，可查看[https://github.com/acmesh-official/acme.sh] issues\"\n                echoContent red \"  3.如纯IPv6机器，请设置NAT64,可执行下方命令，如果添加下方命令还是不可用，请尝试更换其他NAT64\"\n                echoContent skyBlue \"  sed -i \\\"1i\\\\\\nameserver 2a00:1098:2b::1\\\\\\nnameserver 2a00:1098:2c::1\\\\\\nnameserver 2a01:4f8:c2c:123f::1\\\\\\nnameserver 2a01:4f9:c010:3f02::1\\\" /etc/resolv.conf\"\n                exit 0\n            fi\n        fi\n    fi\n\n}\n# 开机启动\nbootStartup() {\n    local serviceName=$1\n    if [[ \"${release}\" == \"alpine\" ]]; then\n        rc-update add \"${serviceName}\" default\n    else\n        systemctl daemon-reload\n        systemctl enable \"${serviceName}\"\n    fi\n}\n# 安装Nginx\ninstallNginxTools() {\n\n    if [[ \"${release}\" == \"debian\" ]]; then\n        sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1\n        echo \"deb http://nginx.org/packages/mainline/debian $(lsb_release -cs) nginx\" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1\n        echo -e \"Package: *\\nPin: origin nginx.org\\nPin: release o=nginx\\nPin-Priority: 900\\n\" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1\n        curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1\n        # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key\n        sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"ubuntu\" ]]; then\n        sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1\n        echo \"deb http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx\" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1\n        echo -e \"Package: *\\nPin: origin nginx.org\\nPin: release o=nginx\\nPin-Priority: 900\\n\" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1\n        curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1\n        # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key\n        sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"centos\" ]]; then\n        ${installType} yum-utils >/dev/null 2>&1\n        cat <<EOF >/etc/yum.repos.d/nginx.repo\n[nginx-stable]\nname=nginx stable repo\nbaseurl=http://nginx.org/packages/centos/\\$releasever/\\$basearch/\ngpgcheck=1\nenabled=1\ngpgkey=https://nginx.org/keys/nginx_signing.key\nmodule_hotfixes=true\n\n[nginx-mainline]\nname=nginx mainline repo\nbaseurl=http://nginx.org/packages/mainline/centos/\\$releasever/\\$basearch/\ngpgcheck=1\nenabled=0\ngpgkey=https://nginx.org/keys/nginx_signing.key\nmodule_hotfixes=true\nEOF\n        sudo yum-config-manager --enable nginx-mainline >/dev/null 2>&1\n    elif [[ \"${release}\" == \"alpine\" ]]; then\n        rm \"${nginxConfigPath}default.conf\"\n    fi\n    ${installType} nginx >/dev/null 2>&1\n    bootStartup nginx\n}\n\n# 安装warp\ninstallWarp() {\n    if [[ \"${cpuVendor}\" == \"arm\" ]]; then\n        echoContent red \" ---> 官方WARP客户端不支持ARM架构\"\n        exit 0\n    fi\n\n    ${installType} gnupg2 -y >/dev/null 2>&1\n    if [[ \"${release}\" == \"debian\" ]]; then\n        curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1\n        echo \"deb http://pkg.cloudflareclient.com/ $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"ubuntu\" ]]; then\n        curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1\n        echo \"deb http://pkg.cloudflareclient.com/ focal main\" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"centos\" ]]; then\n        ${installType} yum-utils >/dev/null 2>&1\n        sudo rpm -ivh \"http://pkg.cloudflareclient.com/cloudflare-release-el${centosVersion}.rpm\" >/dev/null 2>&1\n    fi\n\n    echoContent green \" ---> 安装WARP\"\n    ${installType} cloudflare-warp >/dev/null 2>&1\n    if [[ -z $(which warp-cli) ]]; then\n        echoContent red \" ---> 安装WARP失败\"\n        exit 0\n    fi\n    systemctl enable warp-svc\n    warp-cli --accept-tos register\n    warp-cli --accept-tos set-mode proxy\n    warp-cli --accept-tos set-proxy-port 31303\n    warp-cli --accept-tos connect\n    warp-cli --accept-tos enable-always-on\n\n    local warpStatus=\n    warpStatus=$(curl -s --socks5 127.0.0.1:31303 https://www.cloudflare.com/cdn-cgi/trace | grep \"warp\" | cut -d \"=\" -f 2)\n\n    if [[ \"${warpStatus}\" == \"on\" ]]; then\n        echoContent green \" ---> WARP启动成功\"\n    fi\n}\n\n# 通过dns检查域名的IP\ncheckDNSIP() {\n    local domain=$1\n    local dnsIP=\n    ipType=4\n    dnsIP=$(dig @1.1.1.1 +time=2 +short \"${domain}\" | grep -E \"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$\")\n    if [[ -z \"${dnsIP}\" ]]; then\n        dnsIP=$(dig @8.8.8.8 +time=2 +short \"${domain}\" | grep -E \"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$\")\n    fi\n    if echo \"${dnsIP}\" | grep -q \"timed out\" || [[ -z \"${dnsIP}\" ]]; then\n        echo\n        echoContent red \" ---> 无法通过DNS获取域名 IPv4 地址\"\n        echoContent green \" ---> 尝试检查域名 IPv6 地址\"\n        dnsIP=$(dig @2606:4700:4700::1111 +time=2 aaaa +short \"${domain}\")\n        ipType=6\n        if echo \"${dnsIP}\" | grep -q \"network unreachable\" || [[ -z \"${dnsIP}\" ]]; then\n            echoContent red \" ---> 无法通过DNS获取域名IPv6地址，退出安装\"\n            exit 0\n        fi\n    fi\n    local publicIP=\n\n    publicIP=$(getPublicIP \"${ipType}\")\n    if [[ \"${publicIP}\" != \"${dnsIP}\" ]]; then\n        echoContent red \" ---> 域名解析IP与当前服务器IP不一致\\n\"\n        echoContent yellow \" ---> 请检查域名解析是否生效以及正确\"\n        echoContent green \" ---> 当前VPS IP：${publicIP}\"\n        echoContent green \" ---> DNS解析 IP：${dnsIP}\"\n        exit 0\n    else\n        echoContent green \" ---> 域名IP校验通过\"\n    fi\n}\n# 检查端口实际开放状态\ncheckPortOpen() {\n    handleSingBox stop >/dev/null 2>&1\n    handleXray stop >/dev/null 2>&1\n\n    local port=$1\n    local domain=$2\n    local checkPortOpenResult=\n    allowPort \"${port}\"\n\n    if [[ -z \"${btDomain}\" ]]; then\n\n        handleNginx stop\n        # 初始化nginx配置\n        touch ${nginxConfigPath}checkPortOpen.conf\n        local listenIPv6PortConfig=\n\n        if [[ -n $(curl -s -6 -m 4 http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | cut -d \"=\" -f 2) ]]; then\n            listenIPv6PortConfig=\"listen [::]:${port};\"\n        fi\n        cat <<EOF >${nginxConfigPath}checkPortOpen.conf\nserver {\n    listen ${port};\n    ${listenIPv6PortConfig}\n    server_name ${domain};\n    location /checkPort {\n        return 200 'fjkvymb6len';\n    }\n    location /ip {\n        proxy_set_header Host \\$host;\n        proxy_set_header X-Real-IP \\$remote_addr;\n        proxy_set_header REMOTE-HOST \\$remote_addr;\n        proxy_set_header X-Forwarded-For \\$proxy_add_x_forwarded_for;\n        default_type text/plain;\n        return 200 \\$proxy_add_x_forwarded_for;\n    }\n}\nEOF\n        handleNginx start\n        # 检查域名+端口的开放\n        checkPortOpenResult=$(curl -s -m 10 \"http://${domain}:${port}/checkPort\")\n        localIP=$(curl -s -m 10 \"http://${domain}:${port}/ip\")\n        rm \"${nginxConfigPath}checkPortOpen.conf\"\n        handleNginx stop\n        if [[ \"${checkPortOpenResult}\" == \"fjkvymb6len\" ]]; then\n            echoContent green \" ---> 检测到${port}端口已开放\"\n        else\n            echoContent green \" ---> 未检测到${port}端口开放，退出安装\"\n            if echo \"${checkPortOpenResult}\" | grep -q \"cloudflare\"; then\n                echoContent yellow \" ---> 请关闭云朵后等待三分钟重新尝试\"\n            else\n                if [[ -z \"${checkPortOpenResult}\" ]]; then\n                    echoContent red \" ---> 请检查是否有网页防火墙，比如Oracle等云服务商\"\n                    echoContent red \" ---> 检查是否自己安装过nginx并且有配置冲突，可以尝试DD纯净系统后重新尝试\"\n                else\n                    echoContent red \" ---> 错误日志：${checkPortOpenResult}，请将此错误日志通过issues提交反馈\"\n                fi\n            fi\n            exit 0\n        fi\n        checkIP \"${localIP}\"\n    fi\n}\n\n# 初始化Nginx申请证书配置\ninitTLSNginxConfig() {\n    handleNginx stop\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 初始化Nginx申请证书配置\"\n    if [[ -n \"${currentHost}\" && -z \"${lastInstallationConfig}\" ]]; then\n        echo\n        read -r -p \"读取到上次安装记录，是否使用上次安装时的域名 ？[y/n]:\" historyDomainStatus\n        if [[ \"${historyDomainStatus}\" == \"y\" ]]; then\n            domain=${currentHost}\n            echoContent yellow \"\\n ---> 域名: ${domain}\"\n        else\n            echo\n            echoContent yellow \"请输入要配置的域名 例: www.v2ray-agent.com --->\"\n            read -r -p \"域名:\" domain\n        fi\n    elif [[ -n \"${currentHost}\" && -n \"${lastInstallationConfig}\" ]]; then\n        domain=${currentHost}\n    else\n        echo\n        echoContent yellow \"请输入要配置的域名 例: www.v2ray-agent.com --->\"\n        read -r -p \"域名:\" domain\n    fi\n\n    if [[ -z ${domain} ]]; then\n        echoContent red \"  域名不可为空--->\"\n        initTLSNginxConfig 3\n    else\n        dnsTLSDomain=$(echo \"${domain}\" | awk -F \".\" '{$1=\"\";print $0}' | sed 's/^[[:space:]]*//' | sed 's/ /./g')\n        if [[ \"${selectCoreType}\" == \"1\" ]]; then\n            customPortFunction\n        fi\n        # 修改配置\n        handleNginx stop\n    fi\n}\n\n# 删除nginx默认的配置\nremoveNginxDefaultConf() {\n    if [[ -f ${nginxConfigPath}default.conf ]]; then\n        if [[ \"$(grep -c \"server_name\" <${nginxConfigPath}default.conf)\" == \"1\" ]] && [[ \"$(grep -c \"server_name  localhost;\" <${nginxConfigPath}default.conf)\" == \"1\" ]]; then\n            echoContent green \" ---> 删除Nginx默认配置\"\n            rm -rf ${nginxConfigPath}default.conf >/dev/null 2>&1\n        fi\n    fi\n}\n# 修改nginx重定向配置\nupdateRedirectNginxConf() {\n    local redirectDomain=\n    redirectDomain=${domain}:${port}\n\n    local nginxH2Conf=\n    nginxH2Conf=\"listen 127.0.0.1:31302 http2 so_keepalive=on proxy_protocol;\"\n    nginxVersion=$(nginx -v 2>&1)\n\n    if echo \"${nginxVersion}\" | grep -q \"1.25\" && [[ $(echo \"${nginxVersion}\" | awk -F \"[.]\" '{print $3}') -gt 0 ]] || [[ $(echo \"${nginxVersion}\" | awk -F \"[.]\" '{print $2}') -gt 25 ]]; then\n        nginxH2Conf=\"listen 127.0.0.1:31302 so_keepalive=on proxy_protocol;http2 on;\"\n    fi\n\n    cat <<EOF >${nginxConfigPath}alone.conf\n    server {\n    \t\tlisten 127.0.0.1:31300;\n    \t\tserver_name _;\n    \t\treturn 403;\n    }\nEOF\n\n    if echo \"${selectCustomInstallType}\" | grep -qE \",2,|,5,\" || [[ -z \"${selectCustomInstallType}\" ]]; then\n\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\t${nginxH2Conf}\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\n    set_real_ip_from 127.0.0.1;\n    real_ip_header proxy_protocol;\n\n\tclient_header_timeout 1071906480m;\n    keepalive_timeout 1071906480m;\n\n    location /${currentPath}grpc {\n    \tif (\\$content_type !~ \"application/grpc\") {\n    \t\treturn 404;\n    \t}\n \t\tclient_max_body_size 0;\n\t\tgrpc_set_header X-Real-IP \\$proxy_add_x_forwarded_for;\n\t\tclient_body_timeout 1071906480m;\n\t\tgrpc_read_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31301;\n\t}\n\n\tlocation /${currentPath}trojangrpc {\n\t\tif (\\$content_type !~ \"application/grpc\") {\n            \t\treturn 404;\n\t\t}\n \t\tclient_max_body_size 0;\n\t\tgrpc_set_header X-Real-IP \\$proxy_add_x_forwarded_for;\n\t\tclient_body_timeout 1071906480m;\n\t\tgrpc_read_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31304;\n\t}\n\tlocation / {\n    }\n}\nEOF\n    elif echo \"${selectCustomInstallType}\" | grep -q \",5,\" || [[ -z \"${selectCustomInstallType}\" ]]; then\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\t${nginxH2Conf}\n\n\tset_real_ip_from 127.0.0.1;\n    real_ip_header proxy_protocol;\n\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\n\tlocation /${currentPath}grpc {\n\t\tclient_max_body_size 0;\n\t\tkeepalive_requests 4294967296;\n\t\tclient_body_timeout 1071906480m;\n \t\tsend_timeout 1071906480m;\n \t\tlingering_close always;\n \t\tgrpc_read_timeout 1071906480m;\n \t\tgrpc_send_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31301;\n\t}\n\tlocation / {\n    }\n}\nEOF\n\n    elif echo \"${selectCustomInstallType}\" | grep -q \",2,\" || [[ -z \"${selectCustomInstallType}\" ]]; then\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\t${nginxH2Conf}\n\n\tset_real_ip_from 127.0.0.1;\n    real_ip_header proxy_protocol;\n\n    server_name ${domain};\n\troot ${nginxStaticPath};\n\n\tlocation /${currentPath}trojangrpc {\n\t\tclient_max_body_size 0;\n\t\t# keepalive_time 1071906480m;\n\t\tkeepalive_requests 4294967296;\n\t\tclient_body_timeout 1071906480m;\n \t\tsend_timeout 1071906480m;\n \t\tlingering_close always;\n \t\tgrpc_read_timeout 1071906480m;\n \t\tgrpc_send_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31301;\n\t}\n\tlocation / {\n    }\n}\nEOF\n    else\n\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\t${nginxH2Conf}\n\n\tset_real_ip_from 127.0.0.1;\n    real_ip_header proxy_protocol;\n\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\n\tlocation / {\n\t}\n}\nEOF\n    fi\n\n    cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\tlisten 127.0.0.1:31300 proxy_protocol;\n\tserver_name ${domain};\n\n\tset_real_ip_from 127.0.0.1;\n\treal_ip_header proxy_protocol;\n\n\troot ${nginxStaticPath};\n\tlocation / {\n\t}\n}\nEOF\n    handleNginx stop\n}\n# singbox Nginx config\nsingBoxNginxConfig() {\n    local type=$1\n    local port=$2\n\n    local nginxH2Conf=\n    nginxH2Conf=\"listen ${port} http2 so_keepalive=on ssl;\"\n    nginxVersion=$(nginx -v 2>&1)\n\n    local singBoxNginxSSL=\n    singBoxNginxSSL=\"ssl_certificate /etc/v2ray-agent/tls/${domain}.crt;ssl_certificate_key /etc/v2ray-agent/tls/${domain}.key;\"\n\n    if echo \"${nginxVersion}\" | grep -q \"1.25\" && [[ $(echo \"${nginxVersion}\" | awk -F \"[.]\" '{print $3}') -gt 0 ]] || [[ $(echo \"${nginxVersion}\" | awk -F \"[.]\" '{print $2}') -gt 25 ]]; then\n        nginxH2Conf=\"listen ${port} so_keepalive=on ssl;http2 on;\"\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",11,\" || [[ \"$1\" == \"all\" ]]; then\n        cat <<EOF >>${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf\nserver {\n\t${nginxH2Conf}\n\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n    ${singBoxNginxSSL}\n\n    ssl_protocols              TLSv1.2 TLSv1.3;\n    ssl_ciphers                TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;\n    ssl_prefer_server_ciphers  on;\n\n    resolver                   1.1.1.1 valid=60s;\n    resolver_timeout           2s;\n    client_max_body_size 100m;\n\n    location /${currentPath} {\n    \tif (\\$http_upgrade != \"websocket\") {\n            return 444;\n        }\n\n        proxy_pass                          http://127.0.0.1:31306;\n        proxy_http_version                  1.1;\n        proxy_set_header Upgrade            \\$http_upgrade;\n        proxy_set_header Connection         \"upgrade\";\n        proxy_set_header X-Real-IP          \\$remote_addr;\n        proxy_set_header X-Forwarded-For    \\$proxy_add_x_forwarded_for;\n        proxy_set_header Host               \\$host;\n        proxy_redirect                      off;\n\t}\n}\nEOF\n    fi\n}\n\n# 检查ip\ncheckIP() {\n    echoContent skyBlue \"\\n ---> 检查域名ip中\"\n    local localIP=$1\n\n    if [[ -z ${localIP} ]] || ! echo \"${localIP}\" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q '\\.' && ! echo \"${localIP}\" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q ':'; then\n        echoContent red \"\\n ---> 未检测到当前域名的ip\"\n        echoContent skyBlue \" ---> 请依次进行下列检查\"\n        echoContent yellow \" --->  1.检查域名是否书写正确\"\n        echoContent yellow \" --->  2.检查域名dns解析是否正确\"\n        echoContent yellow \" --->  3.如解析正确，请等待dns生效，预计三分钟内生效\"\n        echoContent yellow \" --->  4.如报Nginx启动问题，请手动启动nginx查看错误，如自己无法处理请提issues\"\n        echo\n        echoContent skyBlue \" ---> 如以上设置都正确，请重新安装纯净系统后再次尝试\"\n\n        if [[ -n ${localIP} ]]; then\n            echoContent yellow \" ---> 检测返回值异常，建议手动卸载nginx后重新执行脚本\"\n            echoContent red \" ---> 异常结果：${localIP}\"\n        fi\n        exit 0\n    else\n        if echo \"${localIP}\" | awk -F \"[,]\" '{print $2}' | grep -q \".\" || echo \"${localIP}\" | awk -F \"[,]\" '{print $2}' | grep -q \":\"; then\n            echoContent red \"\\n ---> 检测到多个ip，请确认是否关闭cloudflare的云朵\"\n            echoContent yellow \" ---> 关闭云朵后等待三分钟后重试\"\n            echoContent yellow \" ---> 检测到的ip如下:[${localIP}]\"\n            exit 0\n        fi\n        echoContent green \" ---> 检查当前域名IP正确\"\n    fi\n}\n# 自定义email\ncustomSSLEmail() {\n    if echo \"$1\" | grep -q \"validate email\"; then\n        read -r -p \"是否重新输入邮箱地址[y/n]:\" sslEmailStatus\n        if [[ \"${sslEmailStatus}\" == \"y\" ]]; then\n            sed '/ACCOUNT_EMAIL/d' /root/.acme.sh/account.conf >/root/.acme.sh/account.conf_tmp && mv /root/.acme.sh/account.conf_tmp /root/.acme.sh/account.conf\n        else\n            exit 0\n        fi\n    fi\n\n    if [[ -d \"/root/.acme.sh\" && -f \"/root/.acme.sh/account.conf\" ]]; then\n        if ! grep -q \"ACCOUNT_EMAIL\" <\"/root/.acme.sh/account.conf\" && ! echo \"${sslType}\" | grep -q \"letsencrypt\"; then\n            read -r -p \"请输入邮箱地址:\" sslEmail\n            if echo \"${sslEmail}\" | grep -q \"@\"; then\n                echo \"ACCOUNT_EMAIL='${sslEmail}'\" >>/root/.acme.sh/account.conf\n                echoContent green \" ---> 添加完毕\"\n            else\n                echoContent yellow \"请重新输入正确的邮箱格式[例: username@example.com]\"\n                customSSLEmail\n            fi\n        fi\n    fi\n\n}\n# DNS API申请证书\nswitchDNSAPI() {\n    read -r -p \"是否使用DNS API申请证书[支持NAT]？[y/n]:\" dnsAPIStatus\n    if [[ \"${dnsAPIStatus}\" == \"y\" ]]; then\n        echoContent red \"\\n==============================================================\"\n        echoContent yellow \"1.cloudflare[默认]\"\n        echoContent yellow \"2.aliyun\"\n        echoContent red \"==============================================================\"\n        read -r -p \"请选择[回车]使用默认:\" selectDNSAPIType\n        case ${selectDNSAPIType} in\n        1)\n            dnsAPIType=\"cloudflare\"\n            ;;\n        2)\n            dnsAPIType=\"aliyun\"\n            ;;\n        *)\n            dnsAPIType=\"cloudflare\"\n            ;;\n        esac\n        initDNSAPIConfig \"${dnsAPIType}\"\n    fi\n}\n# 初始化dns配置\ninitDNSAPIConfig() {\n    if [[ \"$1\" == \"cloudflare\" ]]; then\n        echoContent yellow \"\\n CF_Token参考配置教程：https://www.v2ray-agent.com/archives/1701160377972\\n\"\n        read -r -p \"请输入API Token:\" cfAPIToken\n        if [[ -z \"${cfAPIToken}\" ]]; then\n            echoContent red \" ---> 输入为空，请重新输入\"\n            initDNSAPIConfig \"$1\"\n        else\n            echo\n            if ! echo \"${dnsTLSDomain}\" | grep -q \"\\.\" || [[ -z $(echo \"${dnsTLSDomain}\" | awk -F \"[.]\" '{print $1}') ]]; then\n                echoContent green \" ---> 不支持此域名申请通配符证书，建议使用此格式[xx.xx.xx]\"\n                exit 0\n            fi\n            read -r -p \"是否使用*.${dnsTLSDomain}进行API申请通配符证书？[y/n]:\" dnsAPIStatus\n        fi\n    elif [[ \"$1\" == \"aliyun\" ]]; then\n        read -r -p \"请输入Ali Key:\" aliKey\n        read -r -p \"请输入Ali Secret:\" aliSecret\n        if [[ -z \"${aliKey}\" || -z \"${aliSecret}\" ]]; then\n            echoContent red \" ---> 输入为空，请重新输入\"\n            initDNSAPIConfig \"$1\"\n        else\n            echo\n            if ! echo \"${dnsTLSDomain}\" | grep -q \"\\.\" || [[ -z $(echo \"${dnsTLSDomain}\" | awk -F \"[.]\" '{print $1}') ]]; then\n                echoContent green \" ---> 不支持此域名申请通配符证书，建议使用此格式[xx.xx.xx]\"\n                exit 0\n            fi\n            read -r -p \"是否使用*.${dnsTLSDomain}进行API申请通配符证书？[y/n]:\" dnsAPIStatus\n        fi\n    fi\n}\n# 选择ssl安装类型\nswitchSSLType() {\n    if [[ -z \"${sslType}\" ]]; then\n        echoContent red \"\\n==============================================================\"\n        echoContent yellow \"1.letsencrypt[默认]\"\n        echoContent yellow \"2.zerossl\"\n        echoContent yellow \"3.buypass[不支持DNS申请]\"\n        echoContent red \"==============================================================\"\n        read -r -p \"请选择[回车]使用默认:\" selectSSLType\n        case ${selectSSLType} in\n        1)\n            sslType=\"letsencrypt\"\n            ;;\n        2)\n            sslType=\"zerossl\"\n            ;;\n        3)\n            sslType=\"buypass\"\n            ;;\n        *)\n            sslType=\"letsencrypt\"\n            ;;\n        esac\n        if [[ -n \"${dnsAPIType}\" && \"${sslType}\" == \"buypass\" ]]; then\n            echoContent red \" ---> buypass不支持API申请证书\"\n            exit 0\n        fi\n        echo \"${sslType}\" >/etc/v2ray-agent/tls/ssl_type\n    fi\n}\n\n# 选择acme安装证书方式\nselectAcmeInstallSSL() {\n    #    local sslIPv6=\n    #    local currentIPType=\n    if [[ \"${ipType}\" == \"6\" ]]; then\n        sslIPv6=\"--listen-v6\"\n    fi\n    #    currentIPType=$(curl -s \"-${ipType}\" http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | cut -d \"=\" -f 2)\n\n    #    if [[ -z \"${currentIPType}\" ]]; then\n    #                currentIPType=$(curl -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | cut -d \"=\" -f 2)\n    #        if [[ -n \"${currentIPType}\" ]]; then\n    #            sslIPv6=\"--listen-v6\"\n    #        fi\n    #    fi\n\n    acmeInstallSSL\n\n    readAcmeTLS\n}\n\n# 安装SSL证书\nacmeInstallSSL() {\n    local dnsAPIDomain=\"${tlsDomain}\"\n    if [[ \"${dnsAPIStatus}\" == \"y\" ]]; then\n        dnsAPIDomain=\"*.${dnsTLSDomain}\"\n    fi\n\n    if [[ \"${dnsAPIType}\" == \"cloudflare\" ]]; then\n        echoContent green \" ---> DNS API 生成证书中\"\n        sudo CF_Token=\"${cfAPIToken}\" \"$HOME/.acme.sh/acme.sh\" --issue -d \"${dnsAPIDomain}\" -d \"${dnsTLSDomain}\" --dns dns_cf -k ec-256 --server \"${sslType}\" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n    elif [[ \"${dnsAPIType}\" == \"aliyun\" ]]; then\n        echoContent green \" --->  DNS API 生成证书中\"\n        sudo Ali_Key=\"${aliKey}\" Ali_Secret=\"${aliSecret}\" \"$HOME/.acme.sh/acme.sh\" --issue -d \"${dnsAPIDomain}\" -d \"${dnsTLSDomain}\" --dns dns_ali -k ec-256 --server \"${sslType}\" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n    else\n        echoContent green \" ---> 生成证书中\"\n        sudo \"$HOME/.acme.sh/acme.sh\" --issue -d \"${tlsDomain}\" --standalone -k ec-256 --server \"${sslType}\" ${sslIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n    fi\n}\n# 自定义端口\ncustomPortFunction() {\n    local historyCustomPortStatus=\n    if [[ -n \"${customPort}\" || -n \"${currentPort}\" ]]; then\n        echo\n        if [[ -z \"${lastInstallationConfig}\" ]]; then\n            read -r -p \"读取到上次安装时的端口，是否使用上次安装时的端口？[y/n]:\" historyCustomPortStatus\n            if [[ \"${historyCustomPortStatus}\" == \"y\" ]]; then\n                port=${currentPort}\n                echoContent yellow \"\\n ---> 端口: ${port}\"\n            fi\n        elif [[ -n \"${lastInstallationConfig}\" ]]; then\n            port=${currentPort}\n        fi\n    fi\n    if [[ -z \"${currentPort}\" ]] || [[ \"${historyCustomPortStatus}\" == \"n\" ]]; then\n        echo\n\n        if [[ -n \"${btDomain}\" ]]; then\n            echoContent yellow \"请输入端口[不可与BT Panel/1Panel端口相同，回车随机]\"\n            read -r -p \"端口:\" port\n            if [[ -z \"${port}\" ]]; then\n                port=$((RANDOM % 20001 + 10000))\n            fi\n        else\n            echo\n            echoContent yellow \"请输入端口[默认: 443]，可自定义端口[回车使用默认]\"\n            read -r -p \"端口:\" port\n            if [[ -z \"${port}\" ]]; then\n                port=443\n            fi\n            if [[ \"${port}\" == \"${xrayVLESSRealityPort}\" ]]; then\n                handleXray stop\n            fi\n        fi\n\n        if [[ -n \"${port}\" ]]; then\n            if ((port >= 1 && port <= 65535)); then\n                allowPort \"${port}\"\n                echoContent yellow \"\\n ---> 端口: ${port}\"\n                if [[ -z \"${btDomain}\" ]]; then\n                    checkDNSIP \"${domain}\"\n                    removeNginxDefaultConf\n                    checkPortOpen \"${port}\" \"${domain}\"\n                fi\n            else\n                echoContent red \" ---> 端口输入错误\"\n                exit 0\n            fi\n        else\n            echoContent red \" ---> 端口不可为空\"\n            exit 0\n        fi\n    fi\n}\n\n# 检测端口是否占用\ncheckPort() {\n    if [[ -n \"$1\" ]] && lsof -i \"tcp:$1\" | grep -q LISTEN; then\n        echoContent red \"\\n ---> $1端口被占用，请手动关闭后安装\\n\"\n        lsof -i \"tcp:$1\" | grep LISTEN\n        exit 0\n    fi\n}\n\n# 安装TLS\ninstallTLS() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 申请TLS证书\\n\"\n    readAcmeTLS\n    local tlsDomain=${domain}\n\n    # 安装tls\n    if [[ -f \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" && -f \"/etc/v2ray-agent/tls/${tlsDomain}.key\" && -n $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]] || [[ -d \"$HOME/.acme.sh/${tlsDomain}_ecc\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer\" ]] || [[ \"${installedDNSAPIStatus}\" == \"true\" ]]; then\n        echoContent green \" ---> 检测到证书\"\n        renewalTLS\n\n        if [[ -z $(find /etc/v2ray-agent/tls/ -name \"${tlsDomain}.crt\") ]] || [[ -z $(find /etc/v2ray-agent/tls/ -name \"${tlsDomain}.key\") ]] || [[ -z $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]]; then\n            if [[ \"${installedDNSAPIStatus}\" == \"true\" ]]; then\n                sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"*.${dnsTLSDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" --keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n            else\n                sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"${tlsDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" --keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n            fi\n\n        else\n            if [[ -d \"$HOME/.acme.sh/${tlsDomain}_ecc\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer\" ]] || [[ \"${installedDNSAPIStatus}\" == \"true\" ]]; then\n                if [[ -z \"${lastInstallationConfig}\" ]]; then\n                    echoContent yellow \" ---> 如未过期或者自定义证书请选择[n]\\n\"\n                    read -r -p \"是否重新安装？[y/n]:\" reInstallStatus\n                    if [[ \"${reInstallStatus}\" == \"y\" ]]; then\n                        rm -rf /etc/v2ray-agent/tls/*\n                        installTLS \"$1\"\n                    fi\n                fi\n            fi\n        fi\n\n    elif [[ -d \"$HOME/.acme.sh\" ]] && [[ ! -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer\" || ! -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key\" ]]; then\n        switchDNSAPI\n        if [[ -z \"${dnsAPIType}\" ]]; then\n            echoContent yellow \"\\n ---> 不采用API申请证书\"\n            echoContent green \" ---> 安装TLS证书，需要依赖80端口\"\n            allowPort 80\n        fi\n\n        switchSSLType\n        customSSLEmail\n        selectAcmeInstallSSL\n\n        if [[ \"${installedDNSAPIStatus}\" == \"true\" ]]; then\n            sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"*.${dnsTLSDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" --keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n        else\n            sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"${tlsDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" --keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n        fi\n\n        if [[ ! -f \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" || ! -f \"/etc/v2ray-agent/tls/${tlsDomain}.key\" ]] || [[ -z $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.key\") || -z $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]]; then\n            tail -n 10 /etc/v2ray-agent/tls/acme.log\n            if [[ ${installTLSCount} == \"1\" ]]; then\n                echoContent red \" ---> TLS安装失败，请检查acme日志\"\n                exit 0\n            fi\n\n            installTLSCount=1\n            echo\n\n            if tail -n 10 /etc/v2ray-agent/tls/acme.log | grep -q \"Could not validate email address as valid\"; then\n                echoContent red \" ---> 邮箱无法通过SSL厂商验证，请重新输入\"\n                echo\n                customSSLEmail \"validate email\"\n                installTLS \"$1\"\n            else\n                installTLS \"$1\"\n            fi\n        fi\n\n        echoContent green \" ---> TLS生成成功\"\n    else\n        echoContent yellow \" ---> 未安装acme.sh\"\n        exit 0\n    fi\n}\n\n# 初始化随机字符串\ninitRandomPath() {\n    local chars=\"abcdefghijklmnopqrtuxyz\"\n    local initCustomPath=\n    for i in {1..4}; do\n        echo \"${i}\" >/dev/null\n        initCustomPath+=\"${chars:RANDOM%${#chars}:1}\"\n    done\n    customPath=${initCustomPath}\n}\n\n# 自定义/随机路径\nrandomPathFunction() {\n    if [[ -n $1 ]]; then\n        echoContent skyBlue \"\\n进度  $1/${totalProgress} : 生成随机路径\"\n    else\n        echoContent skyBlue \"生成随机路径\"\n    fi\n\n    if [[ -n \"${currentPath}\" && -z \"${lastInstallationConfig}\" ]]; then\n        echo\n        read -r -p \"读取到上次安装记录，是否使用上次安装时的path路径 ？[y/n]:\" historyPathStatus\n        echo\n    elif [[ -n \"${currentPath}\" && -n \"${lastInstallationConfig}\" ]]; then\n        historyPathStatus=\"y\"\n    fi\n\n    if [[ \"${historyPathStatus}\" == \"y\" ]]; then\n        customPath=${currentPath}\n        echoContent green \" ---> 使用成功\\n\"\n    else\n        echoContent yellow \"请输入自定义路径[例: alone]，不需要斜杠，[回车]随机路径\"\n        read -r -p '路径:' customPath\n        if [[ -z \"${customPath}\" ]]; then\n            initRandomPath\n            currentPath=${customPath}\n        else\n            if [[ \"${customPath: -2}\" == \"ws\" ]]; then\n                echo\n                echoContent red \" ---> 自定义path结尾不可用ws结尾，否则无法区分分流路径\"\n                randomPathFunction \"$1\"\n            else\n                currentPath=${customPath}\n            fi\n        fi\n    fi\n    echoContent yellow \"\\n path:${currentPath}\"\n    echoContent skyBlue \"\\n----------------------------\"\n}\n# 随机数\nrandomNum() {\n    if [[ \"${release}\" == \"alpine\" ]]; then\n        local ranNum=\n        ranNum=\"$(shuf -i \"$1\"-\"$2\" -n 1)\"\n        echo \"${ranNum}\"\n    else\n        echo $((RANDOM % $2 + $1))\n    fi\n}\n# Nginx伪装博客\nnginxBlog() {\n    if [[ -n \"$1\" ]]; then\n        echoContent skyBlue \"\\n进度 $1/${totalProgress} : 添加伪装站点\"\n    else\n        echoContent yellow \"\\n开始添加伪装站点\"\n    fi\n\n    if [[ -d \"${nginxStaticPath}\" && -f \"${nginxStaticPath}/check\" ]]; then\n        echo\n        if [[ -z \"${lastInstallationConfig}\" ]]; then\n            read -r -p \"检测到安装伪装站点，是否需要重新安装[y/n]:\" nginxBlogInstallStatus\n        else\n            nginxBlogInstallStatus=\"n\"\n        fi\n\n        if [[ \"${nginxBlogInstallStatus}\" == \"y\" ]]; then\n            rm -rf \"${nginxStaticPath}*\"\n            #  randomNum=$((RANDOM % 6 + 1))\n            randomNum=$(randomNum 1 9)\n            if [[ \"${release}\" == \"alpine\" ]]; then\n                wget -q -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip\"\n            else\n                wget -q \"${wgetShowProgressStatus}\" -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip\"\n            fi\n\n            unzip -o \"${nginxStaticPath}html${randomNum}.zip\" -d \"${nginxStaticPath}\" >/dev/null\n            rm -f \"${nginxStaticPath}html${randomNum}.zip*\"\n            echoContent green \" ---> 添加伪装站点成功\"\n        fi\n    else\n        randomNum=$(randomNum 1 9)\n        #        randomNum=$((RANDOM % 6 + 1))\n        rm -rf \"${nginxStaticPath}*\"\n\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            wget -q -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip\"\n        else\n            wget -q \"${wgetShowProgressStatus}\" -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip\"\n        fi\n\n        unzip -o \"${nginxStaticPath}html${randomNum}.zip\" -d \"${nginxStaticPath}\" >/dev/null\n        rm -f \"${nginxStaticPath}html${randomNum}.zip*\"\n        echoContent green \" ---> 添加伪装站点成功\"\n    fi\n\n}\n\n# 修改http_port_t端口\nupdateSELinuxHTTPPortT() {\n\n    $(find /usr/bin /usr/sbin | grep -w journalctl) -xe >/etc/v2ray-agent/nginx_error.log 2>&1\n\n    if find /usr/bin /usr/sbin | grep -q -w semanage && find /usr/bin /usr/sbin | grep -q -w getenforce && grep -E \"31300|31302\" </etc/v2ray-agent/nginx_error.log | grep -q \"Permission denied\"; then\n        echoContent red \" ---> 检查SELinux端口是否开放\"\n        if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31300; then\n            $(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31300\n            echoContent green \" ---> http_port_t 31300 端口开放成功\"\n        fi\n\n        if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31302; then\n            $(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31302\n            echoContent green \" ---> http_port_t 31302 端口开放成功\"\n        fi\n        handleNginx start\n\n    else\n        exit 0\n    fi\n}\n\n# 操作Nginx\nhandleNginx() {\n\n    if ! echo \"${selectCustomInstallType}\" | grep -qwE \",7,|,8,|,7,8,\" && [[ -z $(pgrep -f \"nginx\") ]] && [[ \"$1\" == \"start\" ]]; then\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            rc-service nginx start 2>/etc/v2ray-agent/nginx_error.log\n        else\n            systemctl start nginx 2>/etc/v2ray-agent/nginx_error.log\n        fi\n\n        sleep 0.5\n\n        if [[ -z $(pgrep -f \"nginx\") ]]; then\n            echoContent red \" ---> Nginx启动失败\"\n            echoContent red \" ---> 请将下方日志反馈给开发者\"\n            nginx\n            if grep -q \"journalctl -xe\" </etc/v2ray-agent/nginx_error.log; then\n                updateSELinuxHTTPPortT\n            fi\n        else\n            echoContent green \" ---> Nginx启动成功\"\n        fi\n\n    elif [[ -n $(pgrep -f \"nginx\") ]] && [[ \"$1\" == \"stop\" ]]; then\n\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            rc-service nginx stop\n        else\n            systemctl stop nginx\n        fi\n        sleep 0.5\n\n        if [[ -z ${btDomain} && -n $(pgrep -f \"nginx\") ]]; then\n            pgrep -f \"nginx\" | xargs kill -9\n        fi\n        echoContent green \" ---> Nginx关闭成功\"\n    fi\n}\n\n# 定时任务更新tls证书\ninstallCronTLS() {\n    if [[ -z \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\n进度 $1/${totalProgress} : 添加定时维护证书\"\n        crontab -l >/etc/v2ray-agent/backup_crontab.cron\n        local historyCrontab\n        historyCrontab=$(sed '/v2ray-agent/d;/acme.sh/d' /etc/v2ray-agent/backup_crontab.cron)\n        echo \"${historyCrontab}\" >/etc/v2ray-agent/backup_crontab.cron\n        echo \"30 1 * * * /bin/bash /etc/v2ray-agent/install.sh RenewTLS >> /etc/v2ray-agent/crontab_tls.log 2>&1\" >>/etc/v2ray-agent/backup_crontab.cron\n        crontab /etc/v2ray-agent/backup_crontab.cron\n        echoContent green \"\\n ---> 添加定时维护证书成功\"\n    fi\n}\n# 定时任务更新geo文件\ninstallCronUpdateGeo() {\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        if crontab -l | grep -q \"UpdateGeo\"; then\n            echoContent red \"\\n ---> 已添加自动更新定时任务，请不要重复添加\"\n            exit 0\n        fi\n        echoContent skyBlue \"\\n进度 1/1 : 添加定时更新geo文件\"\n        crontab -l >/etc/v2ray-agent/backup_crontab.cron\n        echo \"35 1 * * * /bin/bash /etc/v2ray-agent/install.sh UpdateGeo >> /etc/v2ray-agent/crontab_tls.log 2>&1\" >>/etc/v2ray-agent/backup_crontab.cron\n        crontab /etc/v2ray-agent/backup_crontab.cron\n        echoContent green \"\\n ---> 添加定时更新geo文件成功\"\n    fi\n}\n\n# 更新证书\nrenewalTLS() {\n\n    if [[ -n $1 ]]; then\n        echoContent skyBlue \"\\n进度  $1/1 : 更新证书\"\n    fi\n    readAcmeTLS\n    local domain=${currentHost}\n    if [[ -z \"${currentHost}\" && -n \"${tlsDomain}\" ]]; then\n        domain=${tlsDomain}\n    fi\n\n    if [[ -f \"/etc/v2ray-agent/tls/ssl_type\" ]]; then\n        if grep -q \"buypass\" <\"/etc/v2ray-agent/tls/ssl_type\"; then\n            sslRenewalDays=180\n        fi\n    fi\n    if [[ -d \"$HOME/.acme.sh/${domain}_ecc\" && -f \"$HOME/.acme.sh/${domain}_ecc/${domain}.key\" && -f \"$HOME/.acme.sh/${domain}_ecc/${domain}.cer\" ]] || [[ \"${installedDNSAPIStatus}\" == \"true\" ]]; then\n        modifyTime=\n\n        if [[ \"${installedDNSAPIStatus}\" == \"true\" ]]; then\n            modifyTime=$(stat --format=%z \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer\")\n        else\n            modifyTime=$(stat --format=%z \"$HOME/.acme.sh/${domain}_ecc/${domain}.cer\")\n        fi\n\n        modifyTime=$(date +%s -d \"${modifyTime}\")\n        currentTime=$(date +%s)\n        ((stampDiff = currentTime - modifyTime))\n        ((days = stampDiff / 86400))\n        ((remainingDays = sslRenewalDays - days))\n\n        tlsStatus=${remainingDays}\n        if [[ ${remainingDays} -le 0 ]]; then\n            tlsStatus=\"已过期\"\n        fi\n\n        echoContent skyBlue \" ---> 证书检查日期:$(date \"+%F %H:%M:%S\")\"\n        echoContent skyBlue \" ---> 证书生成日期:$(date -d @\"${modifyTime}\" +\"%F %H:%M:%S\")\"\n        echoContent skyBlue \" ---> 证书生成天数:${days}\"\n        echoContent skyBlue \" ---> 证书剩余天数:\"${tlsStatus}\n        echoContent skyBlue \" ---> 证书过期前最后一天自动更新，如更新失败请手动更新\"\n\n        if [[ ${remainingDays} -le 1 ]]; then\n            echoContent yellow \" ---> 重新生成证书\"\n            handleNginx stop\n\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                handleXray stop\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                handleSingBox stop\n            fi\n\n            sudo \"$HOME/.acme.sh/acme.sh\" --cron --home \"$HOME/.acme.sh\"\n            sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"${domain}\" --fullchainpath /etc/v2ray-agent/tls/\"${domain}.crt\" --keypath /etc/v2ray-agent/tls/\"${domain}.key\" --ecc\n            reloadCore\n            handleNginx start\n        else\n            echoContent green \" ---> 证书有效\"\n        fi\n    elif [[ -f \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" && -f \"/etc/v2ray-agent/tls/${tlsDomain}.key\" && -n $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]]; then\n        echoContent yellow \" ---> 检测到使用自定义证书，无法执行renew操作。\"\n    else\n        echoContent red \" ---> 未安装\"\n    fi\n}\n\n# 安装 sing-box\ninstallSingBox() {\n    readInstallType\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 安装sing-box\"\n\n    if [[ ! -f \"/etc/v2ray-agent/sing-box/sing-box\" ]]; then\n\n        version=$(curl -s \"https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | head -1)\n\n        echoContent green \" ---> 最新版本:${version}\"\n\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            wget -c -q -P /etc/v2ray-agent/sing-box/ \"https://github.com/SagerNet/sing-box/releases/download/${version}/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz\"\n        else\n            wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/sing-box/ \"https://github.com/SagerNet/sing-box/releases/download/${version}/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz\"\n        fi\n\n        if [[ ! -f \"/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz\" ]]; then\n            read -r -p \"核心下载失败，请重新尝试安装，是否重新尝试？[y/n]\" downloadStatus\n            if [[ \"${downloadStatus}\" == \"y\" ]]; then\n                installSingBox \"$1\"\n            fi\n        else\n\n            tar zxvf \"/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}.tar.gz\" -C \"/etc/v2ray-agent/sing-box/\" >/dev/null 2>&1\n\n            mv \"/etc/v2ray-agent/sing-box/sing-box-${version/v/}${singBoxCoreCPUVendor}/sing-box\" /etc/v2ray-agent/sing-box/sing-box\n            rm -rf /etc/v2ray-agent/sing-box/sing-box-*\n            chmod 655 /etc/v2ray-agent/sing-box/sing-box\n        fi\n    else\n        echoContent green \" ---> 当前版本:v$(/etc/v2ray-agent/sing-box/sing-box version | grep \"sing-box version\" | awk '{print $3}')\"\n\n        version=$(curl -s \"https://api.github.com/repos/SagerNet/sing-box/releases?per_page=20\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | head -1)\n        echoContent green \" ---> 最新版本:${version}\"\n\n        if [[ -z \"${lastInstallationConfig}\" ]]; then\n            read -r -p \"是否更新、升级？[y/n]:\" reInstallSingBoxStatus\n            if [[ \"${reInstallSingBoxStatus}\" == \"y\" ]]; then\n                rm -f /etc/v2ray-agent/sing-box/sing-box\n                installSingBox \"$1\"\n            fi\n        fi\n    fi\n\n}\n\n# 检查wget showProgress\ncheckWgetShowProgress() {\n    if [[ \"${release}\" != \"alpine\" ]]; then\n        if find /usr/bin /usr/sbin | grep -q \"/wget\" && wget --help | grep -q show-progress; then\n            wgetShowProgressStatus=\"--show-progress\"\n        fi\n    fi\n}\n# 安装xray\ninstallXray() {\n    readInstallType\n    local prereleaseStatus=false\n    if [[ \"$2\" == \"true\" ]]; then\n        prereleaseStatus=true\n    fi\n\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 安装Xray\"\n\n    if [[ ! -f \"/etc/v2ray-agent/xray/xray\" ]]; then\n\n        version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | head -1)\n        echoContent green \" ---> Xray-core版本:${version}\"\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            wget -c -q -P /etc/v2ray-agent/xray/ \"https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip\"\n        else\n            wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip\"\n        fi\n\n        if [[ ! -f \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\" ]]; then\n            read -r -p \"核心下载失败，请重新尝试安装，是否重新尝试？[y/n]\" downloadStatus\n            if [[ \"${downloadStatus}\" == \"y\" ]]; then\n                installXray \"$1\"\n            fi\n        else\n            unzip -o \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\" -d /etc/v2ray-agent/xray >/dev/null\n            rm -rf \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\"\n\n            version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name')\n            echoContent skyBlue \"------------------------Version-------------------------------\"\n            echo \"version:${version}\"\n            rm /etc/v2ray-agent/xray/geo* >/dev/null 2>&1\n\n            if [[ \"${release}\" == \"alpine\" ]]; then\n                wget -c -q -P /etc/v2ray-agent/xray/ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat\"\n                wget -c -q -P /etc/v2ray-agent/xray/ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat\"\n            else\n                wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat\"\n                wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat\"\n            fi\n\n            chmod 655 /etc/v2ray-agent/xray/xray\n        fi\n    else\n        if [[ -z \"${lastInstallationConfig}\" ]]; then\n            echoContent green \" ---> Xray-core版本:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n            read -r -p \"是否更新、升级？[y/n]:\" reInstallXrayStatus\n            if [[ \"${reInstallXrayStatus}\" == \"y\" ]]; then\n                rm -f /etc/v2ray-agent/xray/xray\n                installXray \"$1\" \"$2\"\n            fi\n        fi\n    fi\n}\n\n# xray版本管理\nxrayVersionManageMenu() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : Xray版本管理\"\n    if [[ \"${coreInstallType}\" != \"1\" ]]; then\n        echoContent red \" ---> 没有检测到安装目录，请执行脚本安装内容\"\n        exit 0\n    fi\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.升级Xray-core\"\n    echoContent yellow \"2.升级Xray-core 预览版\"\n    echoContent yellow \"3.回退Xray-core\"\n    echoContent yellow \"4.关闭Xray-core\"\n    echoContent yellow \"5.打开Xray-core\"\n    echoContent yellow \"6.重启Xray-core\"\n    echoContent yellow \"7.更新geosite、geoip\"\n    echoContent yellow \"8.设置自动更新geo文件[每天凌晨更新]\"\n    echoContent yellow \"9.查看日志\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" selectXrayType\n    if [[ \"${selectXrayType}\" == \"1\" ]]; then\n        prereleaseStatus=false\n        updateXray\n    elif [[ \"${selectXrayType}\" == \"2\" ]]; then\n        prereleaseStatus=true\n        updateXray\n    elif [[ \"${selectXrayType}\" == \"3\" ]]; then\n        echoContent yellow \"\\n1.只可以回退最近的五个版本\"\n        echoContent yellow \"2.不保证回退后一定可以正常使用\"\n        echoContent yellow \"3.如果回退的版本不支持当前的config，则会无法连接，谨慎操作\"\n        echoContent skyBlue \"------------------------Version-------------------------------\"\n        curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==false)|.tag_name\" | awk '{print \"\"NR\"\"\":\"$0}'\n        echoContent skyBlue \"--------------------------------------------------------------\"\n        read -r -p \"请输入要回退的版本:\" selectXrayVersionType\n        version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==false)|.tag_name\" | awk '{print \"\"NR\"\"\":\"$0}' | grep \"${selectXrayVersionType}:\" | awk -F \"[:]\" '{print $2}')\n        if [[ -n \"${version}\" ]]; then\n            updateXray \"${version}\"\n        else\n            echoContent red \"\\n ---> 输入有误，请重新输入\"\n            xrayVersionManageMenu 1\n        fi\n    elif [[ \"${selectXrayType}\" == \"4\" ]]; then\n        handleXray stop\n    elif [[ \"${selectXrayType}\" == \"5\" ]]; then\n        handleXray start\n    elif [[ \"${selectXrayType}\" == \"6\" ]]; then\n        reloadCore\n    elif [[ \"${selectXrayType}\" == \"7\" ]]; then\n        updateGeoSite\n    elif [[ \"${selectXrayType}\" == \"8\" ]]; then\n        installCronUpdateGeo\n    elif [[ \"${selectXrayType}\" == \"9\" ]]; then\n        checkLog 1\n    fi\n}\n\n# 更新 geosite\nupdateGeoSite() {\n    echoContent yellow \"\\n来源 https://github.com/Loyalsoldier/v2ray-rules-dat\"\n\n    version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name')\n    echoContent skyBlue \"------------------------Version-------------------------------\"\n    echo \"version:${version}\"\n    rm ${configPath}../geo* >/dev/null\n\n    if [[ \"${release}\" == \"alpine\" ]]; then\n        wget -c -q -P ${configPath}../ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat\"\n        wget -c -q -P ${configPath}../ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat\"\n    else\n        wget -c -q \"${wgetShowProgressStatus}\" -P ${configPath}../ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat\"\n        wget -c -q \"${wgetShowProgressStatus}\" -P ${configPath}../ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat\"\n    fi\n\n    reloadCore\n    echoContent green \" ---> 更新完毕\"\n\n}\n\n# 更新Xray\nupdateXray() {\n    readInstallType\n\n    if [[ -z \"${coreInstallType}\" || \"${coreInstallType}\" != \"1\" ]]; then\n        if [[ -n \"$1\" ]]; then\n            version=$1\n        else\n            version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | head -1)\n        fi\n\n        echoContent green \" ---> Xray-core版本:${version}\"\n\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            wget -c -q -P /etc/v2ray-agent/xray/ \"https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip\"\n        else\n            wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip\"\n        fi\n\n        unzip -o \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\" -d /etc/v2ray-agent/xray >/dev/null\n        rm -rf \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\"\n        chmod 655 /etc/v2ray-agent/xray/xray\n        handleXray stop\n        handleXray start\n    else\n        echoContent green \" ---> 当前版本:v$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n        remoteVersion=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | head -1)\n\n        echoContent green \" ---> 最新版本:${remoteVersion}\"\n\n        if [[ -n \"$1\" ]]; then\n            version=$1\n        else\n            version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=10\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | head -1)\n        fi\n\n        if [[ -n \"$1\" ]]; then\n            read -r -p \"回退版本为${version}，是否继续？[y/n]:\" rollbackXrayStatus\n            if [[ \"${rollbackXrayStatus}\" == \"y\" ]]; then\n                echoContent green \" ---> 当前Xray-core版本:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n\n                handleXray stop\n                rm -f /etc/v2ray-agent/xray/xray\n                updateXray \"${version}\"\n            else\n                echoContent green \" ---> 放弃回退版本\"\n            fi\n        elif [[ \"${version}\" == \"v$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\" ]]; then\n            read -r -p \"当前版本与最新版相同，是否重新安装？[y/n]:\" reInstallXrayStatus\n            if [[ \"${reInstallXrayStatus}\" == \"y\" ]]; then\n                handleXray stop\n                rm -f /etc/v2ray-agent/xray/xray\n                updateXray\n            else\n                echoContent green \" ---> 放弃重新安装\"\n            fi\n        else\n            read -r -p \"最新版本为:${version}，是否更新？[y/n]:\" installXrayStatus\n            if [[ \"${installXrayStatus}\" == \"y\" ]]; then\n                rm /etc/v2ray-agent/xray/xray\n                updateXray\n            else\n                echoContent green \" ---> 放弃更新\"\n            fi\n\n        fi\n    fi\n}\n\n# 验证整个服务是否可用\ncheckGFWStatue() {\n    readInstallType\n    echoContent skyBlue \"\\n进度 $1/${totalProgress} : 验证服务启动状态\"\n    if [[ \"${coreInstallType}\" == \"1\" ]] && [[ -n $(pgrep -f \"xray/xray\") ]]; then\n        echoContent green \" ---> 服务启动成功\"\n    elif [[ \"${coreInstallType}\" == \"2\" ]] && [[ -n $(pgrep -f \"sing-box/sing-box\") ]]; then\n        echoContent green \" ---> 服务启动成功\"\n    else\n        echoContent red \" ---> 服务启动失败，请检查终端是否有日志打印\"\n        exit 0\n    fi\n}\n\n# 安装alpine开机启动\ninstallAlpineStartup() {\n    local serviceName=$1\n    if [[ \"${serviceName}\" == \"sing-box\" ]]; then\n        cat <<EOF >\"/etc/init.d/${serviceName}\"\n#!/sbin/openrc-run\n\ndescription=\"sing-box service\"\ncommand=\"/etc/v2ray-agent/sing-box/sing-box\"\ncommand_args=\"run -c /etc/v2ray-agent/sing-box/conf/config.json\"\ncommand_background=true\npidfile=\"/var/run/sing-box.pid\"\nEOF\n    elif [[ \"${serviceName}\" == \"xray\" ]]; then\n        cat <<EOF >\"/etc/init.d/${serviceName}\"\n#!/sbin/openrc-run\n\ndescription=\"xray service\"\ncommand=\"/etc/v2ray-agent/xray/xray\"\ncommand_args=\"run -confdir /etc/v2ray-agent/xray/conf\"\ncommand_background=true\npidfile=\"/var/run/xray.pid\"\nEOF\n    fi\n\n    chmod +x \"/etc/init.d/${serviceName}\"\n}\n\n# sing-box开机自启\ninstallSingBoxService() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 配置sing-box开机自启\"\n    execStart='/etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json'\n\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") && \"${release}\" != \"alpine\" ]]; then\n        rm -rf /etc/systemd/system/sing-box.service\n        touch /etc/systemd/system/sing-box.service\n        cat <<EOF >/etc/systemd/system/sing-box.service\n[Unit]\nDescription=Sing-Box Service\nDocumentation=https://sing-box.sagernet.org\nAfter=network.target nss-lookup.target\n\n[Service]\nUser=root\nWorkingDirectory=/root\nCapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH\nAmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH\nExecStart=${execStart}\nExecReload=/bin/kill -HUP $MAINPID\nRestart=on-failure\nRestartSec=10\nLimitNPROC=infinity\nLimitNOFILE=infinity\n\n[Install]\nWantedBy=multi-user.target\nEOF\n        bootStartup \"sing-box.service\"\n    elif [[ \"${release}\" == \"alpine\" ]]; then\n        installAlpineStartup \"sing-box\"\n        bootStartup \"sing-box\"\n    fi\n\n    echoContent green \" ---> 配置sing-box开机启动完毕\"\n}\n\n# Xray开机自启\ninstallXrayService() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 配置Xray开机自启\"\n    execStart='/etc/v2ray-agent/xray/xray run -confdir /etc/v2ray-agent/xray/conf'\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]]; then\n        rm -rf /etc/systemd/system/xray.service\n        touch /etc/systemd/system/xray.service\n        cat <<EOF >/etc/systemd/system/xray.service\n[Unit]\nDescription=Xray Service\nDocumentation=https://github.com/xtls\nAfter=network.target nss-lookup.target\n[Service]\nUser=root\nExecStart=${execStart}\nRestart=on-failure\nRestartPreventExitStatus=23\nLimitNPROC=infinity\nLimitNOFILE=infinity\n[Install]\nWantedBy=multi-user.target\nEOF\n        bootStartup \"xray.service\"\n        echoContent green \" ---> 配置Xray开机自启成功\"\n    elif [[ \"${release}\" == \"alpine\" ]]; then\n        installAlpineStartup \"xray\"\n        bootStartup \"xray\"\n    fi\n}\n\n# 操作Hysteria\nhandleHysteria() {\n    # shellcheck disable=SC2010\n    if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q hysteria.service; then\n        if [[ -z $(pgrep -f \"hysteria/hysteria\") ]] && [[ \"$1\" == \"start\" ]]; then\n            systemctl start hysteria.service\n        elif [[ -n $(pgrep -f \"hysteria/hysteria\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop hysteria.service\n        fi\n    fi\n    sleep 0.8\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"hysteria/hysteria\") ]]; then\n            echoContent green \" ---> Hysteria启动成功\"\n        else\n            echoContent red \"Hysteria启动失败\"\n            echoContent red \"请手动执行【/etc/v2ray-agent/hysteria/hysteria --log-level debug -c /etc/v2ray-agent/hysteria/conf/config.json server】，查看错误日志\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"hysteria/hysteria\") ]]; then\n            echoContent green \" ---> Hysteria关闭成功\"\n        else\n            echoContent red \"Hysteria关闭失败\"\n            echoContent red \"请手动执行【ps -ef|grep -v grep|grep hysteria|awk '{print \\$2}'|xargs kill -9】\"\n            exit 0\n        fi\n    fi\n}\n\n# 操作sing-box\nhandleSingBox() {\n    if [[ -f \"/etc/systemd/system/sing-box.service\" ]]; then\n        if [[ -z $(pgrep -f \"sing-box\") ]] && [[ \"$1\" == \"start\" ]]; then\n            singBoxMergeConfig\n            systemctl start sing-box.service\n        elif [[ -n $(pgrep -f \"sing-box\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop sing-box.service\n        fi\n    elif [[ -f \"/etc/init.d/sing-box\" ]]; then\n        if [[ -z $(pgrep -f \"sing-box\") ]] && [[ \"$1\" == \"start\" ]]; then\n            singBoxMergeConfig\n            rc-service sing-box start\n        elif [[ -n $(pgrep -f \"sing-box\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            rc-service sing-box stop\n        fi\n    fi\n    sleep 1\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"sing-box\") ]]; then\n            echoContent green \" ---> sing-box启动成功\"\n        else\n            echoContent red \"sing-box启动失败\"\n            echoContent yellow \"请手动执行【 /etc/v2ray-agent/sing-box/sing-box merge config.json -C /etc/v2ray-agent/sing-box/conf/config/ -D /etc/v2ray-agent/sing-box/conf/ 】，查看错误日志\"\n            echo\n            echoContent yellow \"如上面命令没有错误，请手动执行【 /etc/v2ray-agent/sing-box/sing-box run -c /etc/v2ray-agent/sing-box/conf/config.json 】，查看错误日志\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"sing-box\") ]]; then\n            echoContent green \" ---> sing-box关闭成功\"\n        else\n            echoContent red \" ---> sing-box关闭失败\"\n            echoContent red \"请手动执行【ps -ef|grep -v grep|grep sing-box|awk '{print \\$2}'|xargs kill -9】\"\n            exit 0\n        fi\n    fi\n}\n\n# 操作xray\nhandleXray() {\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]] && [[ -n $(find /etc/systemd/system/ -name \"xray.service\") ]]; then\n        if [[ -z $(pgrep -f \"xray/xray\") ]] && [[ \"$1\" == \"start\" ]]; then\n            systemctl start xray.service\n        elif [[ -n $(pgrep -f \"xray/xray\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop xray.service\n        fi\n    elif [[ -f \"/etc/init.d/xray\" ]]; then\n        if [[ -z $(pgrep -f \"xray/xray\") ]] && [[ \"$1\" == \"start\" ]]; then\n            rc-service xray start\n        elif [[ -n $(pgrep -f \"xray/xray\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            rc-service xray stop\n        fi\n    fi\n\n    sleep 0.8\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"xray/xray\") ]]; then\n            echoContent green \" ---> Xray启动成功\"\n        else\n            echoContent red \"Xray启动失败\"\n            echoContent red \"请手动执行以下的命令后【/etc/v2ray-agent/xray/xray -confdir /etc/v2ray-agent/xray/conf】将错误日志进行反馈\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"xray/xray\") ]]; then\n            echoContent green \" ---> Xray关闭成功\"\n        else\n            echoContent red \"xray关闭失败\"\n            echoContent red \"请手动执行【ps -ef|grep -v grep|grep xray|awk '{print \\$2}'|xargs kill -9】\"\n            exit 0\n        fi\n    fi\n}\n\n# 读取Xray用户数据并初始化\ninitXrayClients() {\n    local type=\",$1,\"\n    local newUUID=$2\n    local newEmail=$3\n    if [[ -n \"${newUUID}\" ]]; then\n        local newUser=\n        newUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"email\\\":\\\"${newEmail}-VLESS_TCP/TLS_Vision\\\"}\"\n        currentClients=$(echo \"${currentClients}\" | jq -r \". +=[${newUser}]\")\n    fi\n    local users=\n    users=[]\n    while read -r user; do\n        uuid=$(echo \"${user}\" | jq -r .id//.uuid)\n        email=$(echo \"${user}\" | jq -r .email//.name | awk -F \"[-]\" '{print $1}')\n        currentUser=\n        if echo \"${type}\" | grep -q \"0\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"email\\\":\\\"${email}-VLESS_TCP/TLS_Vision\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # VLESS WS\n        if echo \"${type}\" | grep -q \",1,\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-VLESS_WS\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # VLESS XHTTP\n        if echo \"${type}\" | grep -q \",12,\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-VLESS_Reality_XHTTP\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # trojan grpc\n        if echo \"${type}\" | grep -q \",2,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-Trojan_gRPC\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # VMess WS\n        if echo \"${type}\" | grep -q \",3,\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-VMess_WS\\\",\\\"alterId\\\": 0}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # trojan tcp\n        if echo \"${type}\" | grep -q \",4,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-trojan_tcp\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # vless grpc\n        if echo \"${type}\" | grep -q \",5,\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-vless_grpc\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # hysteria\n        if echo \"${type}\" | grep -q \",6,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${email}-singbox_hysteria2\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # vless reality vision\n        if echo \"${type}\" | grep -q \",7,\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-vless_reality_vision\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # vless reality grpc\n        if echo \"${type}\" | grep -q \",8,\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-vless_reality_grpc\\\",\\\"flow\\\":\\\"\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # tuic\n        if echo \"${type}\" | grep -q \",9,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"password\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${email}-singbox_tuic\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n    done < <(echo \"${currentClients}\" | jq -c '.[]')\n    echo \"${users}\"\n}\n# 读取singbox用户数据并初始化\ninitSingBoxClients() {\n    local type=\",$1,\"\n    local newUUID=$2\n    local newName=$3\n\n    if [[ -n \"${newUUID}\" ]]; then\n        local newUser=\n        newUser=\"{\\\"uuid\\\":\\\"${newUUID}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"name\\\":\\\"${newName}-VLESS_TCP/TLS_Vision\\\"}\"\n        currentClients=$(echo \"${currentClients}\" | jq -r \". +=[${newUser}]\")\n    fi\n    local users=\n    users=[]\n    while read -r user; do\n        uuid=$(echo \"${user}\" | jq -r .uuid//.id//.password)\n        name=$(echo \"${user}\" | jq -r .name//.email//.username | awk -F \"[-]\" '{print $1}')\n        currentUser=\n        # VLESS Vision\n        if echo \"${type}\" | grep -q \",0,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"name\\\":\\\"${name}-VLESS_TCP/TLS_Vision\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # VLESS WS\n        if echo \"${type}\" | grep -q \",1,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-VLESS_WS\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # VMess ws\n        if echo \"${type}\" | grep -q \",3,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-VMess_WS\\\",\\\"alterId\\\": 0}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # trojan\n        if echo \"${type}\" | grep -q \",4,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-Trojan_TCP\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # VLESS Reality Vision\n        if echo \"${type}\" | grep -q \",7,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"name\\\":\\\"${name}-VLESS_Reality_Vision\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # VLESS Reality gRPC\n        if echo \"${type}\" | grep -q \",8,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-VLESS_Reality_gPRC\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # hysteria2\n        if echo \"${type}\" | grep -q \",6,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-singbox_hysteria2\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # tuic\n        if echo \"${type}\" | grep -q \",9,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"password\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-singbox_tuic\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # naive\n        if echo \"${type}\" | grep -q \",10,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"username\\\":\\\"${name}-singbox_naive\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # VMess HTTPUpgrade\n        if echo \"${type}\" | grep -q \",11,\"; then\n            currentUser=\"{\\\"uuid\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-VMess_HTTPUpgrade\\\",\\\"alterId\\\": 0}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # anytls\n        if echo \"${type}\" | grep -q \",13,\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"name\\\":\\\"${name}-anytls\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        if echo \"${type}\" | grep -q \",20,\"; then\n            currentUser=\"{\\\"username\\\":\\\"${uuid}\\\",\\\"password\\\":\\\"${uuid}\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n    done < <(echo \"${currentClients}\" | jq -c '.[]')\n    echo \"${users}\"\n}\n\n# 初始化hysteria端口\ninitHysteriaPort() {\n    readSingBoxConfig\n    if [[ -n \"${hysteriaPort}\" ]]; then\n        read -r -p \"读取到上次安装时的端口，是否使用上次安装时的端口？[y/n]:\" historyHysteriaPortStatus\n        if [[ \"${historyHysteriaPortStatus}\" == \"y\" ]]; then\n            echoContent yellow \"\\n ---> 端口: ${hysteriaPort}\"\n        else\n            hysteriaPort=\n        fi\n    fi\n\n    if [[ -z \"${hysteriaPort}\" ]]; then\n        echoContent yellow \"请输入Hysteria端口[回车随机10000-30000]，不可与其他服务重复\"\n        read -r -p \"端口:\" hysteriaPort\n        if [[ -z \"${hysteriaPort}\" ]]; then\n            hysteriaPort=$((RANDOM % 20001 + 10000))\n        fi\n    fi\n    if [[ -z ${hysteriaPort} ]]; then\n        echoContent red \" ---> 端口不可为空\"\n        initHysteriaPort \"$2\"\n    elif ((hysteriaPort < 1 || hysteriaPort > 65535)); then\n        echoContent red \" ---> 端口不合法\"\n        initHysteriaPort \"$2\"\n    fi\n    allowPort \"${hysteriaPort}\"\n    allowPort \"${hysteriaPort}\" \"udp\"\n}\n\n# 初始化hysteria网络信息\ninitHysteria2Network() {\n\n    echoContent yellow \"请输入本地带宽峰值的下行速度（默认：100，单位：Mbps）\"\n    read -r -p \"下行速度:\" hysteria2ClientDownloadSpeed\n    if [[ -z \"${hysteria2ClientDownloadSpeed}\" ]]; then\n        hysteria2ClientDownloadSpeed=100\n        echoContent green \"\\n ---> 下行速度: ${hysteria2ClientDownloadSpeed}\\n\"\n    fi\n\n    echoContent yellow \"请输入本地带宽峰值的上行速度（默认：50，单位：Mbps）\"\n    read -r -p \"上行速度:\" hysteria2ClientUploadSpeed\n    if [[ -z \"${hysteria2ClientUploadSpeed}\" ]]; then\n        hysteria2ClientUploadSpeed=50\n        echoContent green \"\\n ---> 上行速度: ${hysteria2ClientUploadSpeed}\\n\"\n    fi\n}\n\n# firewalld设置端口跳跃\naddFirewalldPortHopping() {\n\n    local start=$1\n    local end=$2\n    local targetPort=$3\n    for port in $(seq \"$start\" \"$end\"); do\n        sudo firewall-cmd --permanent --add-forward-port=port=\"${port}\":proto=udp:toport=\"${targetPort}\"\n    done\n    sudo firewall-cmd --reload\n}\n\n# 端口跳跃\naddPortHopping() {\n    local type=$1\n    local targetPort=$2\n    if [[ -n \"${portHoppingStart}\" || -n \"${portHoppingEnd}\" ]]; then\n        echoContent red \" ---> 已添加不可重复添加，可删除后重新添加\"\n        exit 0\n    fi\n    if [[ \"${release}\" == \"centos\" ]]; then\n        if ! systemctl status firewalld 2>/dev/null | grep -q \"active (running)\"; then\n            echoContent red \" ---> 未启动firewalld防火墙，无法设置端口跳跃。\"\n            exit 0\n        fi\n    fi\n\n    echoContent skyBlue \"\\n进度 1/1 : 端口跳跃\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\\n\"\n    echoContent yellow \"仅支持Hysteria2、Tuic\"\n    echoContent yellow \"端口跳跃的起始位置为30000\"\n    echoContent yellow \"端口跳跃的结束位置为40000\"\n    echoContent yellow \"可以在30000-40000范围中选一段\"\n    echoContent yellow \"建议1000个左右\"\n    echoContent yellow \"注意不要和其他的端口跳跃设置范围一样，设置相同会覆盖。\"\n\n    echoContent yellow \"请输入端口跳跃的范围，例如[30000-31000]\"\n\n    read -r -p \"范围:\" portHoppingRange\n    if [[ -z \"${portHoppingRange}\" ]]; then\n        echoContent red \" ---> 范围不可为空\"\n        addPortHopping \"${type}\" \"${targetPort}\"\n    elif echo \"${portHoppingRange}\" | grep -q \"-\"; then\n\n        local portStart=\n        local portEnd=\n        portStart=$(echo \"${portHoppingRange}\" | awk -F '-' '{print $1}')\n        portEnd=$(echo \"${portHoppingRange}\" | awk -F '-' '{print $2}')\n\n        if [[ -z \"${portStart}\" || -z \"${portEnd}\" ]]; then\n            echoContent red \" ---> 范围不合法\"\n            addPortHopping \"${type}\" \"${targetPort}\"\n        elif ((portStart < 30000 || portStart > 40000 || portEnd < 30000 || portEnd > 40000 || portEnd < portStart)); then\n            echoContent red \" ---> 范围不合法\"\n            addPortHopping \"${type}\" \"${targetPort}\"\n        else\n            echoContent green \"\\n端口范围: ${portHoppingRange}\\n\"\n            if [[ \"${release}\" == \"centos\" ]]; then\n                sudo firewall-cmd --permanent --add-masquerade\n                sudo firewall-cmd --reload\n                addFirewalldPortHopping \"${portStart}\" \"${portEnd}\" \"${targetPort}\"\n                if ! sudo firewall-cmd --list-forward-ports | grep -q \"toport=${targetPort}\"; then\n                    echoContent red \" ---> 端口跳跃添加失败\"\n                    exit 0\n                fi\n            else\n                iptables -t nat -A PREROUTING -p udp --dport \"${portStart}:${portEnd}\" -m comment --comment \"mack-a_${type}_portHopping\" -j DNAT --to-destination \":${targetPort}\"\n                sudo netfilter-persistent save\n                if ! iptables-save | grep -q \"mack-a_${type}_portHopping\"; then\n                    echoContent red \" ---> 端口跳跃添加失败\"\n                    exit 0\n                fi\n            fi\n            allowPort \"${portStart}:${portEnd}\" udp\n            echoContent green \" ---> 端口跳跃添加成功\"\n        fi\n    fi\n}\n\n# 读取端口跳跃的配置\nreadPortHopping() {\n    local type=$1\n    local targetPort=$2\n    local portHoppingStart=\n    local portHoppingEnd=\n\n    if [[ \"${release}\" == \"centos\" ]]; then\n        portHoppingStart=$(sudo firewall-cmd --list-forward-ports | grep \"toport=${targetPort}\" | head -1 | cut -d \":\" -f 1 | cut -d \"=\" -f 2)\n        portHoppingEnd=$(sudo firewall-cmd --list-forward-ports | grep \"toport=${targetPort}\" | tail -n 1 | cut -d \":\" -f 1 | cut -d \"=\" -f 2)\n    else\n        if iptables-save | grep -q \"mack-a_${type}_portHopping\"; then\n            local portHopping=\n            portHopping=$(iptables-save | grep \"mack-a_${type}_portHopping\" | cut -d \" \" -f 8)\n\n            portHoppingStart=$(echo \"${portHopping}\" | cut -d \":\" -f 1)\n            portHoppingEnd=$(echo \"${portHopping}\" | cut -d \":\" -f 2)\n        fi\n    fi\n    if [[ \"${type}\" == \"hysteria2\" ]]; then\n        hysteria2PortHoppingStart=\"${portHoppingStart}\"\n        hysteria2PortHoppingEnd=${portHoppingEnd}\n        hysteria2PortHopping=\"${portHoppingStart}-${portHoppingEnd}\"\n    elif [[ \"${type}\" == \"tuic\" ]]; then\n        tuicPortHoppingStart=\"${portHoppingStart}\"\n        tuicPortHoppingEnd=\"${portHoppingEnd}\"\n        #        tuicPortHopping=\"${portHoppingStart}-${portHoppingEnd}\"\n    fi\n}\n# 删除端口跳跃iptables规则\ndeletePortHoppingRules() {\n    local type=$1\n    local start=$2\n    local end=$3\n    local targetPort=$4\n\n    if [[ \"${release}\" == \"centos\" ]]; then\n        for port in $(seq \"${start}\" \"${end}\"); do\n            sudo firewall-cmd --permanent --remove-forward-port=port=\"${port}\":proto=udp:toport=\"${targetPort}\"\n        done\n        sudo firewall-cmd --reload\n    else\n        iptables -t nat -L PREROUTING --line-numbers | grep \"mack-a_${type}_portHopping\" | awk '{print $1}' | while read -r line; do\n            iptables -t nat -D PREROUTING 1\n            sudo netfilter-persistent save\n        done\n    fi\n}\n\n# 端口跳跃菜单\nportHoppingMenu() {\n    local type=$1\n    # 判断iptables是否存在\n    if ! find /usr/bin /usr/sbin | grep -q -w iptables; then\n        echoContent red \" ---> 无法识别iptables工具，无法使用端口跳跃，退出安装\"\n        exit 0\n    fi\n\n    local targetPort=\n    local portHoppingStart=\n    local portHoppingEnd=\n\n    if [[ \"${type}\" == \"hysteria2\" ]]; then\n        readPortHopping \"${type}\" \"${singBoxHysteria2Port}\"\n        targetPort=${singBoxHysteria2Port}\n        portHoppingStart=${hysteria2PortHoppingStart}\n        portHoppingEnd=${hysteria2PortHoppingEnd}\n    elif [[ \"${type}\" == \"tuic\" ]]; then\n        readPortHopping \"${type}\" \"${singBoxTuicPort}\"\n        targetPort=${singBoxTuicPort}\n        portHoppingStart=${tuicPortHoppingStart}\n        portHoppingEnd=${tuicPortHoppingEnd}\n    fi\n\n    echoContent skyBlue \"\\n进度 1/1 : 端口跳跃\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.添加端口跳跃\"\n    echoContent yellow \"2.删除端口跳跃\"\n    echoContent yellow \"3.查看端口跳跃\"\n    read -r -p \"请选择:\" selectPortHoppingStatus\n    if [[ \"${selectPortHoppingStatus}\" == \"1\" ]]; then\n        addPortHopping \"${type}\" \"${targetPort}\"\n    elif [[ \"${selectPortHoppingStatus}\" == \"2\" ]]; then\n        deletePortHoppingRules \"${type}\" \"${portHoppingStart}\" \"${portHoppingEnd}\" \"${targetPort}\"\n        echoContent green \" ---> 删除成功\"\n    elif [[ \"${selectPortHoppingStatus}\" == \"3\" ]]; then\n        if [[ -n \"${portHoppingStart}\" && -n \"${portHoppingEnd}\" ]]; then\n            echoContent green \" ---> 当前端口跳跃范围为: ${portHoppingStart}-${portHoppingEnd}\"\n        else\n            echoContent yellow \" ---> 未设置端口跳跃\"\n        fi\n    else\n        portHoppingMenu\n    fi\n}\n\n# 初始化tuic端口\ninitTuicPort() {\n    readSingBoxConfig\n    if [[ -n \"${tuicPort}\" ]]; then\n        read -r -p \"读取到上次安装时的端口，是否使用上次安装时的端口？[y/n]:\" historyTuicPortStatus\n        if [[ \"${historyTuicPortStatus}\" == \"y\" ]]; then\n            echoContent yellow \"\\n ---> 端口: ${tuicPort}\"\n        else\n            tuicPort=\n        fi\n    fi\n\n    if [[ -z \"${tuicPort}\" ]]; then\n        echoContent yellow \"请输入Tuic端口[回车随机10000-30000]，不可与其他服务重复\"\n        read -r -p \"端口:\" tuicPort\n        if [[ -z \"${tuicPort}\" ]]; then\n            tuicPort=$((RANDOM % 20001 + 10000))\n        fi\n    fi\n    if [[ -z ${tuicPort} ]]; then\n        echoContent red \" ---> 端口不可为空\"\n        initTuicPort \"$2\"\n    elif ((tuicPort < 1 || tuicPort > 65535)); then\n        echoContent red \" ---> 端口不合法\"\n        initTuicPort \"$2\"\n    fi\n    echoContent green \"\\n ---> 端口: ${tuicPort}\"\n    allowPort \"${tuicPort}\"\n    allowPort \"${tuicPort}\" \"udp\"\n}\n\n# 初始化tuic的协议\ninitTuicProtocol() {\n    if [[ -n \"${tuicAlgorithm}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次使用的算法，是否使用 ？[y/n]:\" historyTuicAlgorithm\n        if [[ \"${historyTuicAlgorithm}\" != \"y\" ]]; then\n            tuicAlgorithm=\n        else\n            echoContent yellow \"\\n ---> 算法: ${tuicAlgorithm}\\n\"\n        fi\n    elif [[ -n \"${tuicAlgorithm}\" && -n \"${lastInstallationConfig}\" ]]; then\n        echoContent yellow \"\\n ---> 算法: ${tuicAlgorithm}\\n\"\n    fi\n\n    if [[ -z \"${tuicAlgorithm}\" ]]; then\n\n        echoContent skyBlue \"\\n请选择算法类型\"\n        echoContent red \"==============================================================\"\n        echoContent yellow \"1.bbr(默认)\"\n        echoContent yellow \"2.cubic\"\n        echoContent yellow \"3.new_reno\"\n        echoContent red \"==============================================================\"\n        read -r -p \"请选择:\" selectTuicAlgorithm\n        case ${selectTuicAlgorithm} in\n        1)\n            tuicAlgorithm=\"bbr\"\n            ;;\n        2)\n            tuicAlgorithm=\"cubic\"\n            ;;\n        3)\n            tuicAlgorithm=\"new_reno\"\n            ;;\n        *)\n            tuicAlgorithm=\"bbr\"\n            ;;\n        esac\n        echoContent yellow \"\\n ---> 算法: ${tuicAlgorithm}\\n\"\n    fi\n}\n\n# 初始化tuic配置\n#initTuicConfig() {\n#    echoContent skyBlue \"\\n进度 $1/${totalProgress} : 初始化Tuic配置\"\n#\n#    initTuicPort\n#    initTuicProtocol\n#    cat <<EOF >/etc/v2ray-agent/tuic/conf/config.json\n#{\n#    \"server\": \"[::]:${tuicPort}\",\n#    \"users\": $(initXrayClients 9),\n#    \"certificate\": \"/etc/v2ray-agent/tls/${currentHost}.crt\",\n#    \"private_key\": \"/etc/v2ray-agent/tls/${currentHost}.key\",\n#    \"congestion_control\":\"${tuicAlgorithm}\",\n#    \"alpn\": [\"h3\"],\n#    \"log_level\": \"warn\"\n#}\n#EOF\n#}\n\n# 初始化singbox route配置\ninitSingBoxRouteConfig() {\n    downloadSingBoxGeositeDB\n    local outboundTag=$1\n    if [[ ! -f \"${singBoxConfigPath}${outboundTag}_route.json\" ]]; then\n        cat <<EOF >\"${singBoxConfigPath}${outboundTag}_route.json\"\n{\n    \"route\": {\n        \"geosite\": {\n            \"path\": \"${singBoxConfigPath}geosite.db\"\n        },\n        \"rules\": [\n            {\n                \"domain\": [\n                ],\n                \"geosite\": [\n                ],\n                \"outbound\": \"${outboundTag}\"\n            }\n        ]\n    }\n}\nEOF\n    fi\n}\n# 下载sing-box geosite db\ndownloadSingBoxGeositeDB() {\n    if [[ ! -f \"${singBoxConfigPath}geosite.db\" ]]; then\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            wget -q -P \"${singBoxConfigPath}\" https://github.com/Johnshall/sing-geosite/releases/latest/download/geosite.db\n        else\n            wget -q \"${wgetShowProgressStatus}\" -P \"${singBoxConfigPath}\" https://github.com/Johnshall/sing-geosite/releases/latest/download/geosite.db\n        fi\n\n    fi\n}\n\n# 添加sing-box路由规则\naddSingBoxRouteRule() {\n    local outboundTag=$1\n    # 域名列表\n    local domainList=$2\n    # 路由文件名称\n    local routingName=$3\n    # 读取上次安装内容\n    if [[ -f \"${singBoxConfigPath}${routingName}.json\" ]]; then\n        read -r -p \"读取到上次的配置，是否保留 ？[y/n]:\" historyRouteStatus\n        if [[ \"${historyRouteStatus}\" == \"y\" ]]; then\n            domainList=\"${domainList},$(jq -rc .route.rules[0].rule_set[] \"${singBoxConfigPath}${routingName}.json\" | awk -F \"[_]\" '{print $1}' | paste -sd ',')\"\n            domainList=\"${domainList},$(jq -rc .route.rules[0].domain_regex[] \"${singBoxConfigPath}${routingName}.json\" | awk -F \"[*]\" '{print $2}' | paste -sd ',' | sed 's/\\\\//g')\"\n        fi\n    fi\n    local rules=\n    rules=$(initSingBoxRules \"${domainList}\" \"${routingName}\")\n    # domain精确匹配规则\n    local domainRules=\n    domainRules=$(echo \"${rules}\" | jq .domainRules)\n\n    # ruleSet规则集\n    local ruleSet=\n    ruleSet=$(echo \"${rules}\" | jq .ruleSet)\n\n    # ruleSet规则tag\n    local ruleSetTag=[]\n    if [[ \"$(echo \"${ruleSet}\" | jq '.|length')\" != \"0\" ]]; then\n        ruleSetTag=$(echo \"${ruleSet}\" | jq '.|map(.tag)')\n    fi\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n        cat <<EOF >\"${singBoxConfigPath}${routingName}.json\"\n{\n  \"route\": {\n    \"rules\": [\n      {\n        \"rule_set\":${ruleSetTag},\n        \"domain_regex\":${domainRules},\n        \"outbound\": \"${outboundTag}\"\n      }\n    ],\n    \"rule_set\":${ruleSet}\n  }\n}\nEOF\n        jq 'if .route.rule_set == [] then del(.route.rule_set) else . end' \"${singBoxConfigPath}${routingName}.json\" >\"${singBoxConfigPath}${routingName}_tmp.json\" && mv \"${singBoxConfigPath}${routingName}_tmp.json\" \"${singBoxConfigPath}${routingName}.json\"\n    fi\n\n}\n\n# 移除sing-box route rule\nremoveSingBoxRouteRule() {\n    local outboundTag=$1\n    local delRules\n    if [[ -f \"${singBoxConfigPath}${outboundTag}_route.json\" ]]; then\n        delRules=$(jq -r 'del(.route.rules[]|select(.outbound==\"'\"${outboundTag}\"'\"))' \"${singBoxConfigPath}${outboundTag}_route.json\")\n        echo \"${delRules}\" >\"${singBoxConfigPath}${outboundTag}_route.json\"\n    fi\n}\n\n# 添加sing-box出站\naddSingBoxOutbound() {\n    local tag=$1\n    local type=\"ipv4\"\n    local detour=$2\n    if echo \"${tag}\" | grep -q \"IPv6\"; then\n        type=ipv6\n    fi\n    if [[ -n \"${detour}\" ]]; then\n        cat <<EOF >\"${singBoxConfigPath}${tag}.json\"\n{\n     \"outbounds\": [\n        {\n             \"type\": \"direct\",\n             \"tag\": \"${tag}\",\n             \"detour\": \"${detour}\",\n             \"domain_strategy\": \"${type}_only\"\n        }\n    ]\n}\nEOF\n    elif echo \"${tag}\" | grep -q \"direct\"; then\n\n        cat <<EOF >\"${singBoxConfigPath}${tag}.json\"\n{\n     \"outbounds\": [\n        {\n             \"type\": \"direct\",\n             \"tag\": \"${tag}\"\n        }\n    ]\n}\nEOF\n    elif echo \"${tag}\" | grep -q \"block\"; then\n\n        cat <<EOF >\"${singBoxConfigPath}${tag}.json\"\n{\n     \"outbounds\": [\n        {\n             \"type\": \"block\",\n             \"tag\": \"${tag}\"\n        }\n    ]\n}\nEOF\n    else\n        cat <<EOF >\"${singBoxConfigPath}${tag}.json\"\n{\n     \"outbounds\": [\n        {\n             \"type\": \"direct\",\n             \"tag\": \"${tag}\",\n             \"domain_strategy\": \"${type}_only\"\n        }\n    ]\n}\nEOF\n    fi\n}\n\n# 添加Xray-core 出站\naddXrayOutbound() {\n    local tag=$1\n    local domainStrategy=\n\n    if echo \"${tag}\" | grep -q \"IPv4\"; then\n        domainStrategy=\"ForceIPv4\"\n    elif echo \"${tag}\" | grep -q \"IPv6\"; then\n        domainStrategy=\"ForceIPv6\"\n    fi\n\n    if [[ -n \"${domainStrategy}\" ]]; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n    \"outbounds\":[\n        {\n            \"protocol\":\"freedom\",\n            \"settings\":{\n                \"domainStrategy\":\"${domainStrategy}\"\n            },\n            \"tag\":\"${tag}\"\n        }\n    ]\n}\nEOF\n    fi\n    # direct\n    if echo \"${tag}\" | grep -q \"direct\"; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n    \"outbounds\":[\n        {\n            \"protocol\":\"freedom\",\n            \"settings\": {\n                \"domainStrategy\":\"UseIP\"\n            },\n            \"tag\":\"${tag}\"\n        }\n    ]\n}\nEOF\n    fi\n    # blackhole\n    if echo \"${tag}\" | grep -q \"blackhole\"; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n    \"outbounds\":[\n        {\n            \"protocol\":\"blackhole\",\n            \"tag\":\"${tag}\"\n        }\n    ]\n}\nEOF\n    fi\n    # socks5 outbound\n    if echo \"${tag}\" | grep -q \"socks5\"; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n  \"outbounds\": [\n    {\n      \"protocol\": \"socks\",\n      \"tag\": \"${tag}\",\n      \"settings\": {\n        \"servers\": [\n          {\n            \"address\": \"${socks5RoutingOutboundIP}\",\n            \"port\": ${socks5RoutingOutboundPort},\n            \"users\": [\n              {\n                \"user\": \"${socks5RoutingOutboundUserName}\",\n                \"pass\": \"${socks5RoutingOutboundPassword}\"\n              }\n            ]\n          }\n        ]\n      }\n    }\n  ]\n}\nEOF\n    fi\n    if echo \"${tag}\" | grep -q \"wireguard_out_IPv4\"; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n  \"outbounds\": [\n    {\n      \"protocol\": \"wireguard\",\n      \"settings\": {\n        \"secretKey\": \"${secretKeyWarpReg}\",\n        \"address\": [\n          \"${address}\"\n        ],\n        \"peers\": [\n          {\n            \"publicKey\": \"${publicKeyWarpReg}\",\n            \"allowedIPs\": [\n              \"0.0.0.0/0\",\n              \"::/0\"\n            ],\n            \"endpoint\": \"162.159.192.1:2408\"\n          }\n        ],\n        \"reserved\": ${reservedWarpReg},\n        \"mtu\": 1280\n      },\n      \"tag\": \"${tag}\"\n    }\n  ]\n}\nEOF\n    fi\n    if echo \"${tag}\" | grep -q \"wireguard_out_IPv6\"; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n  \"outbounds\": [\n    {\n      \"protocol\": \"wireguard\",\n      \"settings\": {\n        \"secretKey\": \"${secretKeyWarpReg}\",\n        \"address\": [\n          \"${address}\"\n        ],\n        \"peers\": [\n          {\n            \"publicKey\": \"${publicKeyWarpReg}\",\n            \"allowedIPs\": [\n              \"0.0.0.0/0\",\n              \"::/0\"\n            ],\n            \"endpoint\": \"162.159.192.1:2408\"\n          }\n        ],\n        \"reserved\": ${reservedWarpReg},\n        \"mtu\": 1280\n      },\n      \"tag\": \"${tag}\"\n    }\n  ]\n}\nEOF\n    fi\n    if echo \"${tag}\" | grep -q \"vmess-out\"; then\n        cat <<EOF >\"/etc/v2ray-agent/xray/conf/${tag}.json\"\n{\n  \"outbounds\": [\n    {\n      \"tag\": \"${tag}\",\n      \"protocol\": \"vmess\",\n      \"streamSettings\": {\n        \"network\": \"ws\",\n        \"security\": \"tls\",\n        \"tlsSettings\": {},\n        \"wsSettings\": {\n          \"path\": \"${setVMessWSTLSPath}\"\n        }\n      },\n      \"mux\": {\n        \"enabled\": true,\n        \"concurrency\": 8\n      },\n      \"settings\": {\n        \"vnext\": [\n          {\n            \"address\": \"${setVMessWSTLSAddress}\",\n            \"port\": \"${setVMessWSTLSPort}\",\n            \"users\": [\n              {\n                \"id\": \"${setVMessWSTLSUUID}\",\n                \"security\": \"auto\",\n                \"alterId\": 0\n              }\n            ]\n          }\n        ]\n      }\n    }\n  ]\n}\nEOF\n    fi\n}\n\n# 删除 Xray-core出站\nremoveXrayOutbound() {\n    local tag=$1\n    if [[ -f \"/etc/v2ray-agent/xray/conf/${tag}.json\" ]]; then\n        rm \"/etc/v2ray-agent/xray/conf/${tag}.json\" >/dev/null 2>&1\n    fi\n}\n# 移除sing-box配置\nremoveSingBoxConfig() {\n\n    local tag=$1\n    if [[ -f \"${singBoxConfigPath}${tag}.json\" ]]; then\n        rm \"${singBoxConfigPath}${tag}.json\"\n    fi\n}\n\n# 初始化wireguard出站信息\naddSingBoxWireGuardEndpoints() {\n    local type=$1\n\n    readConfigWarpReg\n\n    cat <<EOF >\"${singBoxConfigPath}wireguard_endpoints_${type}.json\"\n{\n     \"endpoints\": [\n        {\n            \"type\": \"wireguard\",\n            \"tag\": \"wireguard_endpoints_${type}\",\n            \"address\": [\n                \"${address}\"\n            ],\n            \"private_key\": \"${secretKeyWarpReg}\",\n            \"peers\": [\n                {\n                  \"address\": \"162.159.192.1\",\n                  \"port\": 2408,\n                  \"public_key\": \"${publicKeyWarpReg}\",\n                  \"reserved\":${reservedWarpReg},\n                  \"allowed_ips\": [\"0.0.0.0/0\",\"::/0\"]\n                }\n            ]\n        }\n    ]\n}\nEOF\n}\n\n# 初始化 sing-box Hysteria2 配置\ninitSingBoxHysteria2Config() {\n    echoContent skyBlue \"\\n进度 $1/${totalProgress} : 初始化Hysteria2配置\"\n\n    initHysteriaPort\n    initHysteria2Network\n\n    cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/hysteria2.json\n{\n    \"inbounds\": [\n        {\n            \"type\": \"hysteria2\",\n            \"listen\": \"::\",\n            \"listen_port\": ${hysteriaPort},\n            \"users\": $(initXrayClients 6),\n            \"up_mbps\":${hysteria2ClientDownloadSpeed},\n            \"down_mbps\":${hysteria2ClientUploadSpeed},\n            \"tls\": {\n                \"enabled\": true,\n                \"server_name\":\"${currentHost}\",\n                \"alpn\": [\n                    \"h3\"\n                ],\n                \"certificate_path\": \"/etc/v2ray-agent/tls/${currentHost}.crt\",\n                \"key_path\": \"/etc/v2ray-agent/tls/${currentHost}.key\"\n            }\n        }\n    ]\n}\nEOF\n}\n\n# sing-box Tuic安装\nsingBoxTuicInstall() {\n    if ! echo \"${currentInstallProtocolType}\" | grep -qE \",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,\"; then\n        echoContent red \"\\n ---> 由于需要依赖证书，如安装Tuic，请先安装带有TLS标识协议\"\n        exit 0\n    fi\n\n    totalProgress=5\n    installSingBox 1\n    selectCustomInstallType=\",9,\"\n    initSingBoxConfig custom 2 true\n    installSingBoxService 3\n    reloadCore\n    showAccounts 4\n}\n\n# sing-box hy2安装\nsingBoxHysteria2Install() {\n    if ! echo \"${currentInstallProtocolType}\" | grep -qE \",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,\"; then\n        echoContent red \"\\n ---> 由于需要依赖证书，如安装Hysteria2，请先安装带有TLS标识协议\"\n        exit 0\n    fi\n\n    totalProgress=5\n    installSingBox 1\n    selectCustomInstallType=\",6,\"\n    initSingBoxConfig custom 2 true\n    installSingBoxService 3\n    reloadCore\n    showAccounts 4\n}\n\n# 合并config\nsingBoxMergeConfig() {\n    rm /etc/v2ray-agent/sing-box/conf/config.json >/dev/null 2>&1\n    /etc/v2ray-agent/sing-box/sing-box merge config.json -C /etc/v2ray-agent/sing-box/conf/config/ -D /etc/v2ray-agent/sing-box/conf/ >/dev/null 2>&1\n}\n\n# 初始化Xray Trojan XTLS 配置文件\n#initXrayFrontingConfig() {\n#    echoContent red \" ---> Trojan暂不支持 xtls-rprx-vision\"\n#    if [[ -z \"${configPath}\" ]]; then\n#        echoContent red \" ---> 未安装，请使用脚本安装\"\n#        menu\n#        exit 0\n#    fi\n#    if [[ \"${coreInstallType}\" != \"1\" ]]; then\n#        echoContent red \" ---> 未安装可用类型\"\n#    fi\n#    local xtlsType=\n#    if echo ${currentInstallProtocolType} | grep -q trojan; then\n#        xtlsType=VLESS\n#    else\n#        xtlsType=Trojan\n#    fi\n#\n#    echoContent skyBlue \"\\n功能 1/${totalProgress} : 前置切换为${xtlsType}\"\n#    echoContent red \"\\n==============================================================\"\n#    echoContent yellow \"# 注意事项\\n\"\n#    echoContent yellow \"会将前置替换为${xtlsType}\"\n#    echoContent yellow \"如果前置是Trojan，查看账号时则会出现两个Trojan协议的节点，有一个不可用xtls\"\n#    echoContent yellow \"再次执行可切换至上一次的前置\\n\"\n#\n#    echoContent yellow \"1.切换至${xtlsType}\"\n#    echoContent red \"==============================================================\"\n#    read -r -p \"请选择:\" selectType\n#    if [[ \"${selectType}\" == \"1\" ]]; then\n#\n#        if [[ \"${xtlsType}\" == \"Trojan\" ]]; then\n#\n#            local VLESSConfig\n#            VLESSConfig=$(cat ${configPath}${frontingType}.json)\n#            VLESSConfig=${VLESSConfig//\"id\"/\"password\"}\n#            VLESSConfig=${VLESSConfig//VLESSTCP/TrojanTCPXTLS}\n#            VLESSConfig=${VLESSConfig//VLESS/Trojan}\n#            VLESSConfig=${VLESSConfig//\"vless\"/\"trojan\"}\n#            VLESSConfig=${VLESSConfig//\"id\"/\"password\"}\n#\n#            echo \"${VLESSConfig}\" | jq . >${configPath}02_trojan_TCP_inbounds.json\n#            rm ${configPath}${frontingType}.json\n#        elif [[ \"${xtlsType}\" == \"VLESS\" ]]; then\n#\n#            local VLESSConfig\n#            VLESSConfig=$(cat ${configPath}02_trojan_TCP_inbounds.json)\n#            VLESSConfig=${VLESSConfig//\"password\"/\"id\"}\n#            VLESSConfig=${VLESSConfig//TrojanTCPXTLS/VLESSTCP}\n#            VLESSConfig=${VLESSConfig//Trojan/VLESS}\n#            VLESSConfig=${VLESSConfig//\"trojan\"/\"vless\"}\n#            VLESSConfig=${VLESSConfig//\"password\"/\"id\"}\n#\n#            echo \"${VLESSConfig}\" | jq . >${configPath}02_VLESS_TCP_inbounds.json\n#            rm ${configPath}02_trojan_TCP_inbounds.json\n#        fi\n#        reloadCore\n#    fi\n#\n#    exit 0\n#}\n\n# 初始化sing-box端口\ninitSingBoxPort() {\n    local port=$1\n    if [[ -n \"${port}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次使用的端口，是否使用 ？[y/n]:\" historyPort\n        if [[ \"${historyPort}\" != \"y\" ]]; then\n            port=\n        else\n            echo \"${port}\"\n        fi\n    elif [[ -n \"${port}\" && -n \"${lastInstallationConfig}\" ]]; then\n        echo \"${port}\"\n    fi\n    if [[ -z \"${port}\" ]]; then\n        read -r -p '请输入自定义端口[需合法]，端口不可重复，[回车]随机端口:' port\n        if [[ -z \"${port}\" ]]; then\n            port=$((RANDOM % 50001 + 10000))\n        fi\n        if ((port >= 1 && port <= 65535)); then\n            allowPort \"${port}\"\n            allowPort \"${port}\" \"udp\"\n            echo \"${port}\"\n        else\n            echoContent red \" ---> 端口输入错误\"\n            exit 0\n        fi\n    fi\n}\n\n# 初始化Xray 配置文件\ninitXrayConfig() {\n    echoContent skyBlue \"\\n进度 $2/${totalProgress} : 初始化Xray配置\"\n    echo\n    local uuid=\n    local addClientsStatus=\n    if [[ -n \"${currentUUID}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次用户配置，是否使用上次安装的配置 ？[y/n]:\" historyUUIDStatus\n        if [[ \"${historyUUIDStatus}\" == \"y\" ]]; then\n            addClientsStatus=true\n            echoContent green \"\\n ---> 使用成功\"\n        fi\n    elif [[ -n \"${currentUUID}\" && -n \"${lastInstallationConfig}\" ]]; then\n        addClientsStatus=true\n    fi\n\n    if [[ -z \"${addClientsStatus}\" ]]; then\n        echoContent yellow \"请输入自定义UUID[需合法]，[回车]随机UUID\"\n        read -r -p 'UUID:' customUUID\n\n        if [[ -n ${customUUID} ]]; then\n            uuid=${customUUID}\n        else\n            uuid=$(/etc/v2ray-agent/xray/xray uuid)\n        fi\n\n        echoContent yellow \"\\n请输入自定义用户名[需合法]，[回车]随机用户名\"\n        read -r -p '用户名:' customEmail\n        if [[ -z ${customEmail} ]]; then\n            customEmail=\"$(echo \"${uuid}\" | cut -d \"-\" -f 1)-VLESS_TCP/TLS_Vision\"\n        fi\n    fi\n\n    if [[ -z \"${addClientsStatus}\" && -z \"${uuid}\" ]]; then\n        addClientsStatus=\n        echoContent red \"\\n ---> uuid读取错误，随机生成\"\n        uuid=$(/etc/v2ray-agent/xray/xray uuid)\n    fi\n\n    if [[ -n \"${uuid}\" ]]; then\n        currentClients='[{\"id\":\"'${uuid}'\",\"add\":\"'${add}'\",\"flow\":\"xtls-rprx-vision\",\"email\":\"'${customEmail}'\"}]'\n        echoContent green \"\\n ${customEmail}:${uuid}\"\n        echo\n    fi\n\n    # log\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/00_log.json\" ]]; then\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/00_log.json\n{\n  \"log\": {\n    \"error\": \"/etc/v2ray-agent/xray/error.log\",\n    \"loglevel\": \"warning\",\n    \"dnsLog\": false\n  }\n}\nEOF\n    fi\n\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/12_policy.json\" ]]; then\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/12_policy.json\n{\n  \"policy\": {\n      \"levels\": {\n          \"0\": {\n              \"handshake\": $((1 + RANDOM % 4)),\n              \"connIdle\": $((250 + RANDOM % 51))\n          }\n      }\n  }\n}\nEOF\n    fi\n\n    addXrayOutbound \"z_direct_outbound\"\n    # dns\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/11_dns.json\" ]]; then\n        cat <<EOF >/etc/v2ray-agent/xray/conf/11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n          \"localhost\"\n        ]\n  }\n}\nEOF\n    fi\n    # routing\n    cat <<EOF >/etc/v2ray-agent/xray/conf/09_routing.json\n{\n  \"routing\": {\n    \"rules\": [\n      {\n        \"type\": \"field\",\n        \"domain\": [\n          \"domain:gstatic.com\",\n          \"domain:googleapis.com\",\n\t  \"domain:googleapis.cn\"\n        ],\n        \"outboundTag\": \"z_direct_outbound\"\n      }\n    ]\n  }\n}\nEOF\n    # VLESS_TCP_TLS_Vision\n    # 回落nginx\n    local fallbacksList='{\"dest\":31300,\"xver\":1},{\"alpn\":\"h2\",\"dest\":31302,\"xver\":1}'\n\n    # trojan\n    if echo \"${selectCustomInstallType}\" | grep -q \",4,\" || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList='{\"dest\":31296,\"xver\":1},{\"alpn\":\"h2\",\"dest\":31302,\"xver\":1}'\n        cat <<EOF >/etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json\n{\n\"inbounds\":[\n\t{\n\t  \"port\": 31296,\n\t  \"listen\": \"127.0.0.1\",\n\t  \"protocol\": \"trojan\",\n\t  \"tag\":\"trojanTCP\",\n\t  \"settings\": {\n\t\t\"clients\": $(initXrayClients 4),\n\t\t\"fallbacks\":[\n\t\t\t{\n\t\t\t    \"dest\":\"31300\",\n\t\t\t    \"xver\":1\n\t\t\t}\n\t\t]\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"tcp\",\n\t\t\"security\": \"none\",\n\t\t\"tcpSettings\": {\n\t\t\t\"acceptProxyProtocol\": true\n\t\t}\n\t  }\n\t}\n\t]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json >/dev/null 2>&1\n    fi\n\n    # VLESS_WS_TLS\n    if echo \"${selectCustomInstallType}\" | grep -q \",1,\" || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList=${fallbacksList}',{\"path\":\"/'${customPath}'ws\",\"dest\":31297,\"xver\":1}'\n        cat <<EOF >/etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json\n{\n\"inbounds\":[\n    {\n\t  \"port\": 31297,\n\t  \"listen\": \"127.0.0.1\",\n\t  \"protocol\": \"vless\",\n\t  \"tag\":\"VLESSWS\",\n\t  \"settings\": {\n\t\t\"clients\": $(initXrayClients 1),\n\t\t\"decryption\": \"none\"\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"ws\",\n\t\t\"security\": \"none\",\n\t\t\"wsSettings\": {\n\t\t  \"acceptProxyProtocol\": true,\n\t\t  \"path\": \"/${customPath}ws\"\n\t\t}\n\t  }\n\t}\n]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json >/dev/null 2>&1\n    fi\n    # VLESS_Reality_XHTTP_TLS\n    if echo \"${selectCustomInstallType}\" | grep -q \",12,\" || [[ \"$1\" == \"all\" ]]; then\n        initXrayXHTTPort\n        initRealityClientServersName\n        initRealityKey\n        initRealityMldsa65\n        cat <<EOF >/etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json\n{\n\"inbounds\":[\n    {\n\t  \"port\": ${xHTTPort},\n\t  \"listen\": \"0.0.0.0\",\n\t  \"protocol\": \"vless\",\n\t  \"tag\":\"VLESSRealityXHTTP\",\n\t  \"settings\": {\n\t\t\"clients\": $(initXrayClients 12),\n\t\t\"decryption\": \"none\"\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"xhttp\",\n\t\t\"security\": \"reality\",\n\t\t\"realitySettings\": {\n            \"show\": false,\n            \"target\": \"${realityServerName}:${realityDomainPort}\",\n            \"xver\": 0,\n            \"serverNames\": [\n                \"${realityServerName}\"\n            ],\n            \"privateKey\": \"${realityPrivateKey}\",\n            \"publicKey\": \"${realityPublicKey}\",\n            \"maxTimeDiff\": 70000,\n            \"shortIds\": [\n                \"\",\n                \"6ba85179e30d4fc2\"\n            ]\n        },\n        \"xhttpSettings\": {\n            \"host\": \"${realityServerName}\",\n            \"path\": \"/${customPath}xHTTP\",\n            \"mode\": \"auto\"\n        }\n\t  }\n\t}\n]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/xray/conf/12_VLESS_XHTTP_inbounds.json >/dev/null 2>&1\n    fi\n    if echo \"${selectCustomInstallType}\" | grep -q \",3,\" || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList=${fallbacksList}',{\"path\":\"/'${customPath}'vws\",\"dest\":31299,\"xver\":1}'\n        cat <<EOF >/etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"listen\": \"127.0.0.1\",\n          \"port\": 31299,\n          \"protocol\": \"vmess\",\n          \"tag\":\"VMessWS\",\n          \"settings\": {\n            \"clients\": $(initXrayClients 3)\n          },\n          \"streamSettings\": {\n            \"network\": \"ws\",\n            \"security\": \"none\",\n            \"wsSettings\": {\n              \"acceptProxyProtocol\": true,\n              \"path\": \"/${customPath}vws\"\n            }\n          }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json >/dev/null 2>&1\n    fi\n    # VLESS_gRPC\n    #    if echo \"${selectCustomInstallType}\" | grep -q \",5,\" || [[ \"$1\" == \"all\" ]]; then\n    #        cat <<EOF >/etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json\n    #{\n    #    \"inbounds\":[\n    #        {\n    #            \"port\": 31301,\n    #            \"listen\": \"127.0.0.1\",\n    #            \"protocol\": \"vless\",\n    #            \"tag\":\"VLESSGRPC\",\n    #            \"settings\": {\n    #                \"clients\": $(initXrayClients 5),\n    #                \"decryption\": \"none\"\n    #            },\n    #            \"streamSettings\": {\n    #                \"network\": \"grpc\",\n    #                \"grpcSettings\": {\n    #                    \"serviceName\": \"${customPath}grpc\"\n    #                }\n    #            }\n    #        }\n    #    ]\n    #}\n    #EOF\n    #    elif [[ -z \"$3\" ]]; then\n    #        rm /etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json >/dev/null 2>&1\n    #    fi\n\n    # VLESS Vision\n    if echo \"${selectCustomInstallType}\" | grep -q \",0,\" || [[ \"$1\" == \"all\" ]]; then\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"port\": ${port},\n          \"protocol\": \"vless\",\n          \"tag\":\"VLESSTCP\",\n          \"settings\": {\n            \"clients\":$(initXrayClients 0),\n            \"decryption\": \"none\",\n            \"fallbacks\": [\n                ${fallbacksList}\n            ]\n          },\n          \"add\": \"${add}\",\n          \"streamSettings\": {\n            \"network\": \"tcp\",\n            \"security\": \"tls\",\n            \"tlsSettings\": {\n              \"rejectUnknownSni\": true,\n              \"minVersion\": \"1.2\",\n              \"certificates\": [\n                {\n                  \"certificateFile\": \"/etc/v2ray-agent/tls/${domain}.crt\",\n                  \"keyFile\": \"/etc/v2ray-agent/tls/${domain}.key\",\n                  \"ocspStapling\": 3600\n                }\n              ]\n            }\n          }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json >/dev/null 2>&1\n    fi\n\n    # VLESS_TCP/reality\n    if echo \"${selectCustomInstallType}\" | grep -q \",7,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent skyBlue \"\\n===================== 配置VLESS+Reality =====================\\n\"\n\n        initXrayRealityPort\n        initRealityClientServersName\n        initRealityKey\n        initRealityMldsa65\n        cat <<EOF >/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json\n{\n  \"inbounds\": [\n    {\n      \"tag\": \"dokodemo-in-VLESSReality\",\n      \"port\": ${realityPort},\n      \"protocol\": \"dokodemo-door\",\n      \"settings\": {\n        \"address\": \"127.0.0.1\",\n        \"port\": 45987,\n        \"network\": \"tcp\"\n      },\n      \"sniffing\": {\n        \"enabled\": true,\n        \"destOverride\": [\n          \"tls\"\n        ],\n        \"routeOnly\": true\n      }\n    },\n    {\n      \"listen\": \"127.0.0.1\",\n      \"port\": 45987,\n      \"protocol\": \"vless\",\n      \"settings\": {\n        \"clients\": $(initXrayClients 7),\n        \"decryption\": \"none\",\n        \"fallbacks\":[\n        ]\n      },\n      \"streamSettings\": {\n        \"network\": \"tcp\",\n        \"security\": \"reality\",\n        \"realitySettings\": {\n          \"show\": false,\n          \"target\": \"${realityServerName}:${realityDomainPort}\",\n          \"xver\": 0,\n          \"serverNames\": [\n            \"${realityServerName}\"\n          ],\n          \"privateKey\": \"${realityPrivateKey}\",\n          \"publicKey\": \"${realityPublicKey}\",\n          \"mldsa65Seed\": \"${realityMldsa65Seed}\",\n          \"mldsa65Verify\": \"${realityMldsa65Verify}\",\n          \"maxTimeDiff\": 70000,\n          \"shortIds\": [\n            \"\",\n            \"6ba85179e30d4fc2\"\n          ]\n        }\n      },\n      \"sniffing\": {\n        \"enabled\": true,\n        \"destOverride\": [\n          \"http\",\n          \"tls\",\n          \"quic\"\n        ],\n        \"routeOnly\": true\n      }\n    }\n  ],\n  \"routing\": {\n    \"rules\": [\n      {\n        \"inboundTag\": [\n          \"dokodemo-in\"\n        ],\n        \"domain\": [\n          \"${realityServerName}\"\n        ],\n        \"outboundTag\": \"z_direct_outbound\"\n      },\n      {\n        \"inboundTag\": [\n          \"dokodemo-in\"\n        ],\n        \"outboundTag\": \"blackhole_out\"\n      }\n    ]\n  }\n}\nEOF\n        #        cat <<EOF >/etc/v2ray-agent/xray/conf/08_VLESS_vision_gRPC_inbounds.json\n        #{\n        #  \"inbounds\": [\n        #    {\n        #      \"port\": 31305,\n        #      \"listen\": \"127.0.0.1\",\n        #      \"protocol\": \"vless\",\n        #      \"tag\": \"VLESSRealityGRPC\",\n        #      \"settings\": {\n        #        \"clients\": $(initXrayClients 8),\n        #        \"decryption\": \"none\"\n        #      },\n        #      \"streamSettings\": {\n        #            \"network\": \"grpc\",\n        #            \"grpcSettings\": {\n        #                \"serviceName\": \"grpc\",\n        #                \"multiMode\": true\n        #            },\n        #            \"sockopt\": {\n        #                \"acceptProxyProtocol\": true\n        #            }\n        #      }\n        #    }\n        #  ]\n        #}\n        #EOF\n\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1\n        rm /etc/v2ray-agent/xray/conf/08_VLESS_vision_gRPC_inbounds.json >/dev/null 2>&1\n    fi\n    installSniffing\n    if [[ -z \"$3\" ]]; then\n        removeXrayOutbound wireguard_out_IPv4_route\n        removeXrayOutbound wireguard_out_IPv6_route\n        removeXrayOutbound wireguard_outbound\n        removeXrayOutbound IPv4_out\n        removeXrayOutbound IPv6_out\n        removeXrayOutbound socks5_outbound\n        removeXrayOutbound blackhole_out\n        removeXrayOutbound wireguard_out_IPv6\n        removeXrayOutbound wireguard_out_IPv4\n        addXrayOutbound z_direct_outbound\n        addXrayOutbound blackhole_out\n    fi\n}\n\n# 初始化TCP Brutal\ninitTCPBrutal() {\n    echoContent skyBlue \"\\n进度 $2/${totalProgress} : 初始化TCP_Brutal配置\"\n    read -r -p \"是否使用TCP_Brutal？[y/n]:\" tcpBrutalStatus\n    if [[ \"${tcpBrutalStatus}\" == \"y\" ]]; then\n        read -r -p \"请输入本地带宽峰值的下行速度（默认：100，单位：Mbps）:\" tcpBrutalClientDownloadSpeed\n        if [[ -z \"${tcpBrutalClientDownloadSpeed}\" ]]; then\n            tcpBrutalClientDownloadSpeed=100\n        fi\n\n        read -r -p \"请输入本地带宽峰值的上行速度（默认：50，单位：Mbps）:\" tcpBrutalClientUploadSpeed\n        if [[ -z \"${tcpBrutalClientUploadSpeed}\" ]]; then\n            tcpBrutalClientUploadSpeed=50\n        fi\n    fi\n}\n# 初始化sing-box配置文件\ninitSingBoxConfig() {\n    echoContent skyBlue \"\\n进度 $2/${totalProgress} : 初始化sing-box配置\"\n\n    echo\n    local uuid=\n    local addClientsStatus=\n    local sslDomain=\n    if [[ -n \"${domain}\" ]]; then\n        sslDomain=\"${domain}\"\n    elif [[ -n \"${currentHost}\" ]]; then\n        sslDomain=\"${currentHost}\"\n    fi\n    if [[ -n \"${currentUUID}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次用户配置，是否使用上次安装的配置 ？[y/n]:\" historyUUIDStatus\n        if [[ \"${historyUUIDStatus}\" == \"y\" ]]; then\n            addClientsStatus=true\n            echoContent green \"\\n ---> 使用成功\"\n        fi\n    elif [[ -n \"${currentUUID}\" && -n \"${lastInstallationConfig}\" ]]; then\n        addClientsStatus=true\n    fi\n\n    if [[ -z \"${addClientsStatus}\" ]]; then\n        echoContent yellow \"请输入自定义UUID[需合法]，[回车]随机UUID\"\n        read -r -p 'UUID:' customUUID\n\n        if [[ -n ${customUUID} ]]; then\n            uuid=${customUUID}\n        else\n            uuid=$(/etc/v2ray-agent/sing-box/sing-box generate uuid)\n        fi\n\n        echoContent yellow \"\\n请输入自定义用户名[需合法]，[回车]随机用户名\"\n        read -r -p '用户名:' customEmail\n        if [[ -z ${customEmail} ]]; then\n            customEmail=\"$(echo \"${uuid}\" | cut -d \"-\" -f 1)-VLESS_TCP/TLS_Vision\"\n        fi\n    fi\n\n    if [[ -z \"${addClientsStatus}\" && -z \"${uuid}\" ]]; then\n        addClientsStatus=\n        echoContent red \"\\n ---> uuid读取错误，随机生成\"\n        uuid=$(/etc/v2ray-agent/sing-box/sing-box generate uuid)\n    fi\n\n    if [[ -n \"${uuid}\" ]]; then\n        currentClients='[{\"uuid\":\"'${uuid}'\",\"flow\":\"xtls-rprx-vision\",\"name\":\"'${customEmail}'\"}]'\n        echoContent yellow \"\\n ${customEmail}:${uuid}\"\n    fi\n\n    # VLESS Vision\n    if echo \"${selectCustomInstallType}\" | grep -q \",0,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n===================== 配置VLESS+Vision =====================\\n\"\n        echoContent skyBlue \"\\n开始配置VLESS+Vision协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxVLESSVisionPort}\")\n        echoContent green \"\\n ---> VLESS_Vision端口：${result[-1]}\"\n\n        checkDNSIP \"${domain}\"\n        removeNginxDefaultConf\n        handleSingBox stop\n\n        checkPortOpen \"${result[-1]}\" \"${domain}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/02_VLESS_TCP_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"type\": \"vless\",\n          \"listen\":\"::\",\n          \"listen_port\":${result[-1]},\n          \"tag\":\"VLESSTCP\",\n          \"users\":$(initSingBoxClients 0),\n          \"tls\":{\n            \"server_name\": \"${sslDomain}\",\n            \"enabled\": true,\n            \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n            \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n          }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/02_VLESS_TCP_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",1,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n===================== 配置VLESS+WS =====================\\n\"\n        echoContent skyBlue \"\\n开始配置VLESS+WS协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxVLESSWSPort}\")\n        echoContent green \"\\n ---> VLESS_WS端口：${result[-1]}\"\n\n        checkDNSIP \"${domain}\"\n        removeNginxDefaultConf\n        handleSingBox stop\n        randomPathFunction\n        checkPortOpen \"${result[-1]}\" \"${domain}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/03_VLESS_WS_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"type\": \"vless\",\n          \"listen\":\"::\",\n          \"listen_port\":${result[-1]},\n          \"tag\":\"VLESSWS\",\n          \"users\":$(initSingBoxClients 1),\n          \"tls\":{\n            \"server_name\": \"${sslDomain}\",\n            \"enabled\": true,\n            \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n            \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n          },\n          \"transport\": {\n            \"type\": \"ws\",\n            \"path\": \"/${currentPath}ws\",\n            \"max_early_data\": 2048,\n            \"early_data_header_name\": \"Sec-WebSocket-Protocol\"\n          }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/03_VLESS_WS_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",3,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n===================== 配置VMess+ws =====================\\n\"\n        echoContent skyBlue \"\\n开始配置VMess+ws协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxVMessWSPort}\")\n        echoContent green \"\\n ---> VMess_ws端口：${result[-1]}\"\n\n        checkDNSIP \"${domain}\"\n        removeNginxDefaultConf\n        handleSingBox stop\n        randomPathFunction\n        checkPortOpen \"${result[-1]}\" \"${domain}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/05_VMess_WS_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"type\": \"vmess\",\n          \"listen\":\"::\",\n          \"listen_port\":${result[-1]},\n          \"tag\":\"VMessWS\",\n          \"users\":$(initSingBoxClients 3),\n          \"tls\":{\n            \"server_name\": \"${sslDomain}\",\n            \"enabled\": true,\n            \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n            \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n          },\n          \"transport\": {\n            \"type\": \"ws\",\n            \"path\": \"/${currentPath}\",\n            \"max_early_data\": 2048,\n            \"early_data_header_name\": \"Sec-WebSocket-Protocol\"\n          }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/05_VMess_WS_inbounds.json >/dev/null 2>&1\n    fi\n\n    # VLESS_Reality_Vision\n    if echo \"${selectCustomInstallType}\" | grep -q \",7,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n================= 配置VLESS+Reality+Vision =================\\n\"\n        initRealityClientServersName\n        initRealityKey\n        echoContent skyBlue \"\\n开始配置VLESS+Reality+Vision协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxVLESSRealityVisionPort}\")\n        echoContent green \"\\n ---> VLESS_Reality_Vision端口：${result[-1]}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/07_VLESS_vision_reality_inbounds.json\n{\n  \"inbounds\": [\n    {\n      \"type\": \"vless\",\n      \"listen\":\"::\",\n      \"listen_port\":${result[-1]},\n      \"tag\": \"VLESSReality\",\n      \"users\":$(initSingBoxClients 7),\n      \"tls\": {\n        \"enabled\": true,\n        \"server_name\": \"${realityServerName}\",\n        \"reality\": {\n            \"enabled\": true,\n            \"handshake\":{\n                \"server\": \"${realityServerName}\",\n                \"server_port\":${realityDomainPort}\n            },\n            \"private_key\": \"${realityPrivateKey}\",\n            \"short_id\": [\n                \"\",\n                \"6ba85179e30d4fc2\"\n            ]\n        }\n      }\n    }\n  ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",8,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n================== 配置VLESS+Reality+gRPC ==================\\n\"\n        initRealityClientServersName\n        initRealityKey\n        echoContent skyBlue \"\\n开始配置VLESS+Reality+gRPC协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxVLESSRealityGRPCPort}\")\n        echoContent green \"\\n ---> VLESS_Reality_gPRC端口：${result[-1]}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/08_VLESS_vision_gRPC_inbounds.json\n{\n  \"inbounds\": [\n    {\n      \"type\": \"vless\",\n      \"listen\":\"::\",\n      \"listen_port\":${result[-1]},\n      \"users\":$(initSingBoxClients 8),\n      \"tag\": \"VLESSRealityGRPC\",\n      \"tls\": {\n        \"enabled\": true,\n        \"server_name\": \"${realityServerName}\",\n        \"reality\": {\n            \"enabled\": true,\n            \"handshake\":{\n                \"server\":\"${realityServerName}\",\n                \"server_port\":${realityDomainPort}\n            },\n            \"private_key\": \"${realityPrivateKey}\",\n            \"short_id\": [\n                \"\",\n                \"6ba85179e30d4fc2\"\n            ]\n        }\n      },\n      \"transport\": {\n          \"type\": \"grpc\",\n          \"service_name\": \"grpc\"\n      }\n    }\n  ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/08_VLESS_vision_gRPC_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",6,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n================== 配置 Hysteria2 ==================\\n\"\n        echoContent skyBlue \"\\n开始配置Hysteria2协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxHysteria2Port}\")\n        echoContent green \"\\n ---> Hysteria2端口：${result[-1]}\"\n        initHysteria2Network\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json\n{\n    \"inbounds\": [\n        {\n            \"type\": \"hysteria2\",\n            \"listen\": \"::\",\n            \"listen_port\": ${result[-1]},\n            \"users\": $(initSingBoxClients 6),\n            \"up_mbps\":${hysteria2ClientDownloadSpeed},\n            \"down_mbps\":${hysteria2ClientUploadSpeed},\n            \"tls\": {\n                \"enabled\": true,\n                \"server_name\":\"${sslDomain}\",\n                \"alpn\": [\n                    \"h3\"\n                ],\n                \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n                \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n            }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",4,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n================== 配置 Trojan ==================\\n\"\n        echoContent skyBlue \"\\n开始配置Trojan协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxTrojanPort}\")\n        echoContent green \"\\n ---> Trojan端口：${result[-1]}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/04_trojan_TCP_inbounds.json\n{\n    \"inbounds\": [\n        {\n            \"type\": \"trojan\",\n            \"listen\": \"::\",\n            \"listen_port\": ${result[-1]},\n            \"users\": $(initSingBoxClients 4),\n            \"tls\": {\n                \"enabled\": true,\n                \"server_name\":\"${sslDomain}\",\n                \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n                \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n            }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/04_trojan_TCP_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",9,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n==================== 配置 Tuic =====================\\n\"\n        echoContent skyBlue \"\\n开始配置Tuic协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxTuicPort}\")\n        echoContent green \"\\n ---> Tuic端口：${result[-1]}\"\n        initTuicProtocol\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json\n{\n     \"inbounds\": [\n        {\n            \"type\": \"tuic\",\n            \"listen\": \"::\",\n            \"tag\": \"singbox-tuic-in\",\n            \"listen_port\": ${result[-1]},\n            \"users\": $(initSingBoxClients 9),\n            \"congestion_control\": \"${tuicAlgorithm}\",\n            \"tls\": {\n                \"enabled\": true,\n                \"server_name\":\"${sslDomain}\",\n                \"alpn\": [\n                    \"h3\"\n                ],\n                \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n                \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n            }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",10,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n==================== 配置 Naive =====================\\n\"\n        echoContent skyBlue \"\\n开始配置Naive协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxNaivePort}\")\n        echoContent green \"\\n ---> Naive端口：${result[-1]}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/10_naive_inbounds.json\n{\n     \"inbounds\": [\n        {\n            \"type\": \"naive\",\n            \"listen\": \"::\",\n            \"tag\": \"singbox-naive-in\",\n            \"listen_port\": ${result[-1]},\n            \"users\": $(initSingBoxClients 10),\n            \"tls\": {\n                \"enabled\": true,\n                \"server_name\":\"${sslDomain}\",\n                \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n                \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n            }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/10_naive_inbounds.json >/dev/null 2>&1\n    fi\n    if echo \"${selectCustomInstallType}\" | grep -q \",11,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n===================== 配置VMess+HTTPUpgrade =====================\\n\"\n        echoContent skyBlue \"\\n开始配置VMess+HTTPUpgrade协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxVMessHTTPUpgradePort}\")\n        echoContent green \"\\n ---> VMess_HTTPUpgrade端口：${result[-1]}\"\n\n        checkDNSIP \"${domain}\"\n        removeNginxDefaultConf\n        handleSingBox stop\n        randomPathFunction\n        rm -rf \"${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf\" >/dev/null 2>&1\n        checkPortOpen \"${result[-1]}\" \"${domain}\"\n        singBoxNginxConfig \"$1\" \"${result[-1]}\"\n        bootStartup nginx\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/11_VMess_HTTPUpgrade_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"type\": \"vmess\",\n          \"listen\":\"127.0.0.1\",\n          \"listen_port\":31306,\n          \"tag\":\"VMessHTTPUpgrade\",\n          \"users\":$(initSingBoxClients 11),\n          \"transport\": {\n            \"type\": \"httpupgrade\",\n            \"path\": \"/${currentPath}\"\n          }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/11_VMess_HTTPUpgrade_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q \",13,\" || [[ \"$1\" == \"all\" ]]; then\n        echoContent yellow \"\\n================== 配置 AnyTLS ==================\\n\"\n        echoContent skyBlue \"\\n开始配置AnyTLS协议端口\"\n        echo\n        mapfile -t result < <(initSingBoxPort \"${singBoxAnyTLSPort}\")\n        echoContent green \"\\n ---> AnyTLS端口：${result[-1]}\"\n        cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/13_anytls_inbounds.json\n{\n    \"inbounds\": [\n        {\n            \"type\": \"anytls\",\n            \"listen\": \"::\",\n            \"tag\":\"anytls\",\n            \"listen_port\": ${result[-1]},\n            \"users\": $(initSingBoxClients 13),\n            \"tls\": {\n                \"enabled\": true,\n                \"server_name\":\"${sslDomain}\",\n                \"certificate_path\": \"/etc/v2ray-agent/tls/${sslDomain}.crt\",\n                \"key_path\": \"/etc/v2ray-agent/tls/${sslDomain}.key\"\n            }\n        }\n    ]\n}\nEOF\n    elif [[ -z \"$3\" ]]; then\n        rm /etc/v2ray-agent/sing-box/conf/config/13_anytls_inbounds.json >/dev/null 2>&1\n    fi\n\n    if [[ -z \"$3\" ]]; then\n        removeSingBoxConfig wireguard_endpoints_IPv4_route\n        removeSingBoxConfig wireguard_endpoints_IPv6_route\n        removeSingBoxConfig wireguard_endpoints_IPv4\n        removeSingBoxConfig wireguard_endpoints_IPv6\n\n        removeSingBoxConfig IPv4_out\n        removeSingBoxConfig IPv6_out\n        removeSingBoxConfig IPv6_route\n        removeSingBoxConfig block\n        removeSingBoxConfig cn_block_outbound\n        removeSingBoxConfig cn_block_route\n        removeSingBoxConfig 01_direct_outbound\n        removeSingBoxConfig socks5_outbound.json\n        removeSingBoxConfig block_domain_outbound\n        removeSingBoxConfig dns\n    fi\n}\n# 初始化 sing-box订阅配置\ninitSubscribeLocalConfig() {\n    rm -rf /etc/v2ray-agent/subscribe_local/sing-box/*\n}\n# 通用\ndefaultBase64Code() {\n    local type=$1\n    local port=$2\n    local email=$3\n    local id=$4\n    local add=$5\n    local path=$6\n    local user=\n    user=$(echo \"${email}\" | awk -F \"[-]\" '{print $1}')\n    if [[ ! -f \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\" ]]; then\n        echo [] >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n    fi\n    local singBoxSubscribeLocalConfig=\n    if [[ \"${type}\" == \"vlesstcp\" ]]; then\n\n        echoContent yellow \" ---> 通用格式(VLESS+TCP+TLS_Vision)\"\n        echoContent green \"    vless://${id}@${currentHost}:${port}?encryption=none&security=tls&fp=chrome&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\\n\"\n\n        echoContent yellow \" ---> 格式化明文(VLESS+TCP+TLS_Vision)\"\n        echoContent green \"协议类型:VLESS，地址:${currentHost}，端口:${port}，用户ID:${id}，安全:tls，client-fingerprint: chrome，传输方式:tcp，flow:xtls-rprx-vision，账户名:${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${currentHost}:${port}?encryption=none&security=tls&type=tcp&host=${currentHost}&fp=chrome&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: ${currentHost}\n    port: ${port}\n    uuid: ${id}\n    network: tcp\n    tls: true\n    udp: true\n    flow: xtls-rprx-vision\n    client-fingerprint: chrome\nEOF\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"vless\\\",\\\"server\\\":\\\"${currentHost}\\\",\\\"server_port\\\":${port},\\\"uuid\\\":\\\"${id}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"}},\\\"packet_encoding\\\":\\\"xudp\\\"}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 VLESS(VLESS+TCP+TLS_Vision)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${currentHost}%3A${port}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"vmessws\" ]]; then\n        qrCodeBase64Default=$(echo -n \"{\\\"port\\\":${port},\\\"ps\\\":\\\"${email}\\\",\\\"tls\\\":\\\"tls\\\",\\\"id\\\":\\\"${id}\\\",\\\"aid\\\":0,\\\"v\\\":2,\\\"host\\\":\\\"${currentHost}\\\",\\\"type\\\":\\\"none\\\",\\\"path\\\":\\\"${path}\\\",\\\"net\\\":\\\"ws\\\",\\\"add\\\":\\\"${add}\\\",\\\"method\\\":\\\"none\\\",\\\"peer\\\":\\\"${currentHost}\\\",\\\"sni\\\":\\\"${currentHost}\\\"}\" | base64 -w 0)\n        qrCodeBase64Default=\"${qrCodeBase64Default// /}\"\n\n        echoContent yellow \" ---> 通用json(VMess+WS+TLS)\"\n        echoContent green \"    {\\\"port\\\":${port},\\\"ps\\\":\\\"${email}\\\",\\\"tls\\\":\\\"tls\\\",\\\"id\\\":\\\"${id}\\\",\\\"aid\\\":0,\\\"v\\\":2,\\\"host\\\":\\\"${currentHost}\\\",\\\"type\\\":\\\"none\\\",\\\"path\\\":\\\"${path}\\\",\\\"net\\\":\\\"ws\\\",\\\"add\\\":\\\"${add}\\\",\\\"method\\\":\\\"none\\\",\\\"peer\\\":\\\"${currentHost}\\\",\\\"sni\\\":\\\"${currentHost}\\\"}\\n\"\n        echoContent yellow \" ---> 通用vmess(VMess+WS+TLS)链接\"\n        echoContent green \"    vmess://${qrCodeBase64Default}\\n\"\n        echoContent yellow \" ---> 二维码 vmess(VMess+WS+TLS)\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvmess://${qrCodeBase64Default}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vmess\n    server: ${add}\n    port: ${port}\n    uuid: ${id}\n    alterId: 0\n    cipher: none\n    udp: true\n    tls: true\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    network: ws\n    ws-opts:\n      path: ${path}\n      headers:\n        Host: ${currentHost}\nEOF\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"vmess\\\",\\\"server\\\":\\\"${add}\\\",\\\"server_port\\\":${port},\\\"uuid\\\":\\\"${id}\\\",\\\"alter_id\\\":0,\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"}},\\\"packet_encoding\\\":\\\"packetaddr\\\",\\\"transport\\\":{\\\"type\\\":\\\"ws\\\",\\\"path\\\":\\\"${path}\\\",\\\"max_early_data\\\":2048,\\\"early_data_header_name\\\":\\\"Sec-WebSocket-Protocol\\\"}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\\n\"\n\n    elif [[ \"${type}\" == \"vlessws\" ]]; then\n\n        echoContent yellow \" ---> 通用格式(VLESS+WS+TLS)\"\n        echoContent green \"    vless://${id}@${add}:${port}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=${path}#${email}\\n\"\n\n        echoContent yellow \" ---> 格式化明文(VLESS+WS+TLS)\"\n        echoContent green \"    协议类型:VLESS，地址:${add}，伪装域名/SNI:${currentHost}，端口:${port}，client-fingerprint: chrome,用户ID:${id}，安全:tls，传输方式:ws，路径:${path}，账户名:${email}\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${add}:${port}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=${path}#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: ${add}\n    port: ${port}\n    uuid: ${id}\n    udp: true\n    tls: true\n    network: ws\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    ws-opts:\n      path: ${path}\n      headers:\n        Host: ${currentHost}\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"vless\\\",\\\"server\\\":\\\"${add}\\\",\\\"server_port\\\":${port},\\\"uuid\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"}},\\\"multiplex\\\":{\\\"enabled\\\":false,\\\"protocol\\\":\\\"smux\\\",\\\"max_streams\\\":32},\\\"packet_encoding\\\":\\\"xudp\\\",\\\"transport\\\":{\\\"type\\\":\\\"ws\\\",\\\"path\\\":\\\"${path}\\\",\\\"headers\\\":{\\\"Host\\\":\\\"${currentHost}\\\"}}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 VLESS(VLESS+WS+TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dws%26host%3D${currentHost}%26fp%3Dchrome%26sni%3D${currentHost}%26path%3D${path}%23${email}\"\n\n    elif [[ \"${type}\" == \"vlessXHTTP\" ]]; then\n\n        echoContent yellow \" ---> 通用格式(VLESS+reality+XHTTP)\"\n        echoContent green \"    vless://${id}@${add}:${port}?encryption=none&security=reality&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&host=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}\\n\"\n\n        echoContent yellow \" ---> 格式化明文(VLESS+reality+XHTTP)\"\n        echoContent green \"协议类型:VLESS reality，地址:${add}，publicKey:${currentRealityXHTTPPublicKey}，shortId: 6ba85179e30d4fc2,serverNames：${xrayVLESSRealityXHTTPServerName}，端口:${port}，路径：${path}，SNI:${xrayVLESSRealityXHTTPServerName}，伪装域名:${xrayVLESSRealityXHTTPServerName}，用户ID:${id}，传输方式:xhttp，账户名:${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${add}:${port}?encryption=none&security=reality&type=xhttp&sni=${xrayVLESSRealityXHTTPServerName}&fp=chrome&path=${path}&pbk=${currentRealityXHTTPPublicKey}&sid=6ba85179e30d4fc2#${email}\nEOF\n        echoContent yellow \" ---> 二维码 VLESS(VLESS+reality+XHTTP)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dxhttp%26sni%3D${xrayVLESSRealityXHTTPServerName}%26fp%3Dchrome%26path%3D${path}%26host%3D${xrayVLESSRealityXHTTPServerName}%26pbk%3D${currentRealityXHTTPPublicKey}%26sid%3D6ba85179e30d4fc2%23${email}\\n\"\n\n    elif\n        [[ \"${type}\" == \"vlessgrpc\" ]]\n    then\n\n        echoContent yellow \" ---> 通用格式(VLESS+gRPC+TLS)\"\n        echoContent green \"    vless://${id}@${add}:${port}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&fp=chrome&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\\n\"\n\n        echoContent yellow \" ---> 格式化明文(VLESS+gRPC+TLS)\"\n        echoContent green \"    协议类型:VLESS，地址:${add}，伪装域名/SNI:${currentHost}，端口:${port}，用户ID:${id}，安全:tls，传输方式:gRPC，alpn:h2，client-fingerprint: chrome,serviceName:${currentPath}grpc，账户名:${email}\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${add}:${port}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&serviceName=${currentPath}grpc&fp=chrome&alpn=h2&sni=${currentHost}#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: ${add}\n    port: ${port}\n    uuid: ${id}\n    udp: true\n    tls: true\n    network: grpc\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    grpc-opts:\n      grpc-service-name: ${currentPath}grpc\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\": \\\"vless\\\",\\\"server\\\": \\\"${add}\\\",\\\"server_port\\\": ${port},\\\"uuid\\\": \\\"${id}\\\",\\\"tls\\\": {  \\\"enabled\\\": true,  \\\"server_name\\\": \\\"${currentHost}\\\",  \\\"utls\\\": {    \\\"enabled\\\": true,    \\\"fingerprint\\\": \\\"chrome\\\"  }},\\\"packet_encoding\\\": \\\"xudp\\\",\\\"transport\\\": {  \\\"type\\\": \\\"grpc\\\",  \\\"service_name\\\": \\\"${currentPath}grpc\\\"}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 VLESS(VLESS+gRPC+TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${port}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%26fp%3Dchrome%26path%3D${currentPath}grpc%26sni%3D${currentHost}%26alpn%3Dh2%23${email}\"\n\n    elif [[ \"${type}\" == \"trojan\" ]]; then\n        # URLEncode\n        echoContent yellow \" ---> Trojan(TLS)\"\n        echoContent green \"    trojan://${id}@${currentHost}:${port}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\ntrojan://${id}@${currentHost}:${port}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${email}_Trojan\nEOF\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: trojan\n    server: ${currentHost}\n    port: ${port}\n    password: ${id}\n    client-fingerprint: chrome\n    udp: true\n    sni: ${currentHost}\nEOF\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"trojan\\\",\\\"server\\\":\\\"${currentHost}\\\",\\\"server_port\\\":${port},\\\"password\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"alpn\\\":[\\\"http/1.1\\\"],\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"}}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 Trojan(TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentHost}%3a${port}%3fpeer%3d${currentHost}%26fp%3Dchrome%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"trojangrpc\" ]]; then\n        # URLEncode\n\n        echoContent yellow \" ---> Trojan gRPC(TLS)\"\n        echoContent green \"    trojan://${id}@${add}:${port}?encryption=none&peer=${currentHost}&fp=chrome&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\ntrojan://${id}@${add}:${port}?encryption=none&peer=${currentHost}&security=tls&type=grpc&fp=chrome&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    server: ${add}\n    port: ${port}\n    type: trojan\n    password: ${id}\n    network: grpc\n    sni: ${currentHost}\n    udp: true\n    grpc-opts:\n      grpc-service-name: ${currentPath}trojangrpc\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"trojan\\\",\\\"server\\\":\\\"${add}\\\",\\\"server_port\\\":${port},\\\"password\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"insecure\\\":true,\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"}},\\\"transport\\\":{\\\"type\\\":\\\"grpc\\\",\\\"service_name\\\":\\\"${currentPath}trojangrpc\\\",\\\"idle_timeout\\\":\\\"15s\\\",\\\"ping_timeout\\\":\\\"15s\\\",\\\"permit_without_stream\\\":false},\\\"multiplex\\\":{\\\"enabled\\\":false,\\\"protocol\\\":\\\"smux\\\",\\\"max_streams\\\":32}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 Trojan gRPC(TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${add}%3a${port}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"hysteria\" ]]; then\n        echoContent yellow \" ---> Hysteria(TLS)\"\n        local clashMetaPortContent=\"port: ${port}\"\n        local multiPort=\n        local multiPortEncode\n        if echo \"${port}\" | grep -q \"-\"; then\n            clashMetaPortContent=\"ports: ${port}\"\n            multiPort=\"mport=${port}&\"\n            multiPortEncode=\"mport%3D${port}%26\"\n        fi\n\n        echoContent green \"    hysteria2://${id}@${currentHost}:${singBoxHysteria2Port}?${multiPort}peer=${currentHost}&insecure=0&sni=${currentHost}&alpn=h3#${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nhysteria2://${id}@${currentHost}:${singBoxHysteria2Port}?${multiPort}peer=${currentHost}&insecure=0&sni=${currentHost}&alpn=h3#${email}\nEOF\n        echoContent yellow \" ---> v2rayN(hysteria+TLS)\"\n        echo \"{\\\"server\\\": \\\"${currentHost}:${port}\\\",\\\"socks5\\\": { \\\"listen\\\": \\\"127.0.0.1:7798\\\", \\\"timeout\\\": 300},\\\"auth\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"sni\\\":\\\"${currentHost}\\\"}}\" | jq\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: hysteria2\n    server: ${currentHost}\n    ${clashMetaPortContent}\n    password: ${id}\n    alpn:\n        - h3\n    sni: ${currentHost}\n    up: \"${hysteria2ClientUploadSpeed} Mbps\"\n    down: \"${hysteria2ClientDownloadSpeed} Mbps\"\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"hysteria2\\\",\\\"server\\\":\\\"${currentHost}\\\",\\\"server_port\\\":${singBoxHysteria2Port},\\\"up_mbps\\\":${hysteria2ClientUploadSpeed},\\\"down_mbps\\\":${hysteria2ClientDownloadSpeed},\\\"password\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"alpn\\\":[\\\"h3\\\"]}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 Hysteria2(TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria2%3A%2F%2F${id}%40${currentHost}%3A${singBoxHysteria2Port}%3F${multiPortEncode}peer%3D${currentHost}%26insecure%3D0%26sni%3D${currentHost}%26alpn%3Dh3%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"vlessReality\" ]]; then\n        local realityServerName=${xrayVLESSRealityServerName}\n        local publicKey=${currentRealityPublicKey}\n        local realityMldsa65Verify=${currentRealityMldsa65Verify}\n\n        if [[ \"${coreInstallType}\" == \"2\" ]]; then\n            realityServerName=${singBoxVLESSRealityVisionServerName}\n            publicKey=${singBoxVLESSRealityPublicKey}\n        fi\n        echoContent yellow \" ---> 通用格式(VLESS+reality+uTLS+Vision)\"\n        echoContent green \"    vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=tcp&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\\n\"\n\n        echoContent yellow \" ---> 格式化明文(VLESS+reality+uTLS+Vision)\"\n        echoContent green \"协议类型:VLESS reality，地址:$(getPublicIP)，publicKey:${publicKey}，shortId: 6ba85179e30d4fc2，pqv=${realityMldsa65Verify}，serverNames：${realityServerName}，端口:${port}，用户ID:${id}，传输方式:tcp，账户名:${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=tcp&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: $(getPublicIP)\n    port: ${port}\n    uuid: ${id}\n    network: tcp\n    tls: true\n    udp: true\n    flow: xtls-rprx-vision\n    servername: ${realityServerName}\n    reality-opts:\n      public-key: ${publicKey}\n      short-id: 6ba85179e30d4fc2\n    client-fingerprint: chrome\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"vless\\\",\\\"server\\\":\\\"$(getPublicIP)\\\",\\\"server_port\\\":${port},\\\"uuid\\\":\\\"${id}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${realityServerName}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"},\\\"reality\\\":{\\\"enabled\\\":true,\\\"public_key\\\":\\\"${publicKey}\\\",\\\"short_id\\\":\\\"6ba85179e30d4fc2\\\"}},\\\"packet_encoding\\\":\\\"xudp\\\"}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 VLESS(VLESS+reality+uTLS+Vision)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dtcp%26sni%3D${realityServerName}%26fp%3Dchrome%26pbk%3D${publicKey}%26sid%3D6ba85179e30d4fc2%26flow%3Dxtls-rprx-vision%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"vlessRealityGRPC\" ]]; then\n        local realityServerName=${xrayVLESSRealityServerName}\n        local publicKey=${currentRealityPublicKey}\n        local realityMldsa65Verify=${currentRealityMldsa65Verify}\n\n        if [[ \"${coreInstallType}\" == \"2\" ]]; then\n            realityServerName=${singBoxVLESSRealityGRPCServerName}\n            publicKey=${singBoxVLESSRealityPublicKey}\n        fi\n\n        echoContent yellow \" ---> 通用格式(VLESS+reality+uTLS+gRPC)\"\n        # pqv=${realityMldsa65Verify}&\n        echoContent green \"    vless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&type=grpc&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\\n\"\n\n        echoContent yellow \" ---> 格式化明文(VLESS+reality+uTLS+gRPC)\"\n        # pqv=${realityMldsa65Verify}，\n        echoContent green \"协议类型:VLESS reality，serviceName:grpc，地址:$(getPublicIP)，publicKey:${publicKey}，shortId: 6ba85179e30d4fc2，serverNames：${realityServerName}，端口:${port}，用户ID:${id}，传输方式:gRPC，client-fingerprint：chrome，账户名:${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@$(getPublicIP):${port}?encryption=none&security=reality&pqv=${realityMldsa65Verify}&type=grpc&sni=${realityServerName}&fp=chrome&pbk=${publicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: $(getPublicIP)\n    port: ${port}\n    uuid: ${id}\n    network: grpc\n    tls: true\n    udp: true\n    servername: ${realityServerName}\n    reality-opts:\n      public-key: ${publicKey}\n      short-id: 6ba85179e30d4fc2\n    grpc-opts:\n      grpc-service-name: \"grpc\"\n    client-fingerprint: chrome\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"vless\\\",\\\"server\\\":\\\"$(getPublicIP)\\\",\\\"server_port\\\":${port},\\\"uuid\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${realityServerName}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"},\\\"reality\\\":{\\\"enabled\\\":true,\\\"public_key\\\":\\\"${publicKey}\\\",\\\"short_id\\\":\\\"6ba85179e30d4fc2\\\"}},\\\"packet_encoding\\\":\\\"xudp\\\",\\\"transport\\\":{\\\"type\\\":\\\"grpc\\\",\\\"service_name\\\":\\\"grpc\\\"}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 VLESS(VLESS+reality+uTLS+gRPC)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${port}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dgrpc%26sni%3D${realityServerName}%26fp%3Dchrome%26pbk%3D${publicKey}%26sid%3D6ba85179e30d4fc2%26path%3Dgrpc%26serviceName%3Dgrpc%23${email}\\n\"\n    elif [[ \"${type}\" == \"tuic\" ]]; then\n        local tuicUUID=\n        tuicUUID=$(echo \"${id}\" | awk -F \"[_]\" '{print $1}')\n\n        local tuicPassword=\n        tuicPassword=$(echo \"${id}\" | awk -F \"[_]\" '{print $2}')\n\n        if [[ -z \"${email}\" ]]; then\n            echoContent red \" ---> 读取配置失败，请重新安装\"\n            exit 0\n        fi\n\n        echoContent yellow \" ---> 格式化明文(Tuic+TLS)\"\n        echoContent green \"    协议类型:Tuic，地址:${currentHost}，端口：${port}，uuid：${tuicUUID}，password：${tuicPassword}，congestion-controller:${tuicAlgorithm}，alpn: h3，账户名:${email}\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\ntuic://${tuicUUID}:${tuicPassword}@${currentHost}:${port}?congestion_control=${tuicAlgorithm}&alpn=h3&sni=${currentHost}&udp_relay_mode=quic&allow_insecure=0#${email}\nEOF\n        echoContent yellow \" ---> v2rayN(Tuic+TLS)\"\n        echo \"{\\\"relay\\\": {\\\"server\\\": \\\"${currentHost}:${port}\\\",\\\"uuid\\\": \\\"${tuicUUID}\\\",\\\"password\\\": \\\"${tuicPassword}\\\",\\\"ip\\\": \\\"${currentHost}\\\",\\\"congestion_control\\\": \\\"${tuicAlgorithm}\\\",\\\"alpn\\\": [\\\"h3\\\"]},\\\"local\\\": {\\\"server\\\": \\\"127.0.0.1:7798\\\"},\\\"log_level\\\": \\\"warn\\\"}\" | jq\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    server: ${currentHost}\n    type: tuic\n    port: ${port}\n    uuid: ${tuicUUID}\n    password: ${tuicPassword}\n    alpn:\n     - h3\n    congestion-controller: ${tuicAlgorithm}\n    disable-sni: true\n    reduce-rtt: true\n    sni: ${email}\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\": \\\"tuic\\\",\\\"server\\\": \\\"${currentHost}\\\",\\\"server_port\\\": ${port},\\\"uuid\\\": \\\"${tuicUUID}\\\",\\\"password\\\": \\\"${tuicPassword}\\\",\\\"congestion_control\\\": \\\"${tuicAlgorithm}\\\",\\\"tls\\\": {\\\"enabled\\\": true,\\\"server_name\\\": \\\"${currentHost}\\\",\\\"alpn\\\": [\\\"h3\\\"]}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \"\\n ---> 二维码 Tuic\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=tuic%3A%2F%2F${tuicUUID}%3A${tuicPassword}%40${currentHost}%3A${tuicPort}%3Fcongestion_control%3D${tuicAlgorithm}%26alpn%3Dh3%26sni%3D${currentHost}%26udp_relay_mode%3Dquic%26allow_insecure%3D0%23${email}\\n\"\n    elif [[ \"${type}\" == \"naive\" ]]; then\n        echoContent yellow \" ---> Naive(TLS)\"\n\n        echoContent green \"    naive+https://${email}:${id}@${currentHost}:${port}?padding=true#${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nnaive+https://${email}:${id}@${currentHost}:${port}?padding=true#${email}\nEOF\n        echoContent yellow \" ---> 二维码 Naive(TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=naive%2Bhttps%3A%2F%2F${email}%3A${id}%40${currentHost}%3A${port}%3Fpadding%3Dtrue%23${email}\\n\"\n    elif [[ \"${type}\" == \"vmessHTTPUpgrade\" ]]; then\n        qrCodeBase64Default=$(echo -n \"{\\\"port\\\":${port},\\\"ps\\\":\\\"${email}\\\",\\\"tls\\\":\\\"tls\\\",\\\"id\\\":\\\"${id}\\\",\\\"aid\\\":0,\\\"v\\\":2,\\\"host\\\":\\\"${currentHost}\\\",\\\"type\\\":\\\"none\\\",\\\"path\\\":\\\"${path}\\\",\\\"net\\\":\\\"httpupgrade\\\",\\\"add\\\":\\\"${add}\\\",\\\"method\\\":\\\"none\\\",\\\"peer\\\":\\\"${currentHost}\\\",\\\"sni\\\":\\\"${currentHost}\\\"}\" | base64 -w 0)\n        qrCodeBase64Default=\"${qrCodeBase64Default// /}\"\n\n        echoContent yellow \" ---> 通用json(VMess+HTTPUpgrade+TLS)\"\n        echoContent green \"    {\\\"port\\\":${port},\\\"ps\\\":\\\"${email}\\\",\\\"tls\\\":\\\"tls\\\",\\\"id\\\":\\\"${id}\\\",\\\"aid\\\":0,\\\"v\\\":2,\\\"host\\\":\\\"${currentHost}\\\",\\\"type\\\":\\\"none\\\",\\\"path\\\":\\\"${path}\\\",\\\"net\\\":\\\"httpupgrade\\\",\\\"add\\\":\\\"${add}\\\",\\\"method\\\":\\\"none\\\",\\\"peer\\\":\\\"${currentHost}\\\",\\\"sni\\\":\\\"${currentHost}\\\"}\\n\"\n        echoContent yellow \" ---> 通用vmess(VMess+HTTPUpgrade+TLS)链接\"\n        echoContent green \"    vmess://${qrCodeBase64Default}\\n\"\n        echoContent yellow \" ---> 二维码 vmess(VMess+HTTPUpgrade+TLS)\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\n   vmess://${qrCodeBase64Default}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vmess\n    server: ${add}\n    port: ${port}\n    uuid: ${id}\n    alterId: 0\n    cipher: auto\n    udp: true\n    tls: true\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    network: ws\n    ws-opts:\n     path: ${path}\n     headers:\n       Host: ${currentHost}\n     v2ray-http-upgrade: true\nEOF\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"vmess\\\",\\\"server\\\":\\\"${add}\\\",\\\"server_port\\\":${port},\\\"uuid\\\":\\\"${id}\\\",\\\"security\\\":\\\"auto\\\",\\\"alter_id\\\":0,\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\",\\\"utls\\\":{\\\"enabled\\\":true,\\\"fingerprint\\\":\\\"chrome\\\"}},\\\"packet_encoding\\\":\\\"packetaddr\\\",\\\"transport\\\":{\\\"type\\\":\\\"httpupgrade\\\",\\\"path\\\":\\\"${path}\\\"}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\\n\"\n\n    elif [[ \"${type}\" == \"anytls\" ]]; then\n        echoContent yellow \" ---> AnyTLS\"\n\n        echoContent yellow \" ---> 格式化明文(AnyTLS)\"\n        echoContent green \"协议类型:anytls，地址:${currentHost}，端口:${singBoxAnyTLSPort}，用户ID:${id}，传输方式:tcp，账户名:${email}\\n\"\n\n        echoContent green \"    anytls://${id}@${currentHost}:${singBoxAnyTLSPort}?peer=${currentHost}&insecure=0&sni=${currentHost}#${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nanytls://${id}@${currentHost}:${singBoxAnyTLSPort}?peer=${currentHost}&insecure=0&sni=${currentHost}#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: anytls\n    port: ${singBoxAnyTLSPort}\n    server: ${currentHost}\n    password: ${id}\n    client-fingerprint: chrome\n    udp: true\n    sni: ${currentHost}\n    alpn:\n      - h2\n      - http/1.1\nEOF\n\n        singBoxSubscribeLocalConfig=$(jq -r \". += [{\\\"tag\\\":\\\"${email}\\\",\\\"type\\\":\\\"anytls\\\",\\\"server\\\":\\\"${currentHost}\\\",\\\"server_port\\\":${singBoxAnyTLSPort},\\\"password\\\":\\\"${id}\\\",\\\"tls\\\":{\\\"enabled\\\":true,\\\"server_name\\\":\\\"${currentHost}\\\"}}]\" \"/etc/v2ray-agent/subscribe_local/sing-box/${user}\")\n        echo \"${singBoxSubscribeLocalConfig}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${user}\"\n\n        echoContent yellow \" ---> 二维码 AnyTLS\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=anytls%3A%2F%2F${id}%40${currentHost}%3A${singBoxAnyTLSPort}%3Fpeer%3D${currentHost}%26insecure%3D0%26sni%3D${currentHost}%23${email}\\n\"\n    fi\n\n}\n\n# 账号\nshowAccounts() {\n    readInstallType\n    readInstallProtocolType\n    readConfigHostPathUUID\n    readSingBoxConfig\n\n    echo\n    echoContent skyBlue \"\\n进度 $1/${totalProgress} : 账号\"\n\n    initSubscribeLocalConfig\n    # VLESS TCP\n    if echo ${currentInstallProtocolType} | grep -q \",0,\"; then\n\n        echoContent skyBlue \"============================= VLESS TCP TLS_Vision [推荐] ==============================\\n\"\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}02_VLESS_TCP_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n\n            echoContent skyBlue \"\\n ---> 账号:${email}\"\n            echo\n            defaultBase64Code vlesstcp \"${currentDefaultPort}${singBoxVLESSVisionPort}\" \"${email}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\"\n        done\n    fi\n\n    # VLESS WS\n    if echo ${currentInstallProtocolType} | grep -q \",1,\"; then\n        echoContent skyBlue \"\\n================================ VLESS WS TLS [仅CDN推荐] ================================\\n\"\n\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}03_VLESS_WS_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n\n            local vlessWSPort=${currentDefaultPort}\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                vlessWSPort=\"${singBoxVLESSWSPort}\"\n            fi\n            echo\n            local path=\"${currentPath}ws\"\n\n            if [[ ${coreInstallType} == \"1\" ]]; then\n                path=\"/${currentPath}ws\"\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                path=\"${singBoxVLESSWSPath}\"\n            fi\n\n            local count=\n            while read -r line; do\n                echoContent skyBlue \"\\n ---> 账号:${email}${count}\"\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vlessws \"${vlessWSPort}\" \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\" \"${line}\" \"${path}\"\n                    count=$((count + 1))\n                    echo\n                fi\n            done < <(echo \"${currentCDNAddress}\" | tr ',' '\\n')\n        done\n    fi\n    # trojan grpc\n    if echo ${currentInstallProtocolType} | grep -q \",2,\"; then\n        echoContent skyBlue \"\\n================================  Trojan gRPC TLS [仅CDN推荐]  ================================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}04_trojan_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n            local count=\n            while read -r line; do\n                echoContent skyBlue \"\\n ---> 账号:${email}${count}\"\n                echo\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code trojangrpc \"${currentDefaultPort}\" \"${email}${count}\" \"$(echo \"${user}\" | jq -r .password)\" \"${line}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentCDNAddress}\" | tr ',' '\\n')\n\n        done\n    fi\n    # VMess WS\n    if echo ${currentInstallProtocolType} | grep -q \",3,\"; then\n        echoContent skyBlue \"\\n================================ VMess WS TLS [仅CDN推荐]  ================================\\n\"\n        local path=\"${currentPath}vws\"\n        if [[ ${coreInstallType} == \"1\" ]]; then\n            path=\"/${currentPath}vws\"\n        elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n            path=\"${singBoxVMessWSPath}\"\n        fi\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}05_VMess_WS_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n\n            local vmessPort=${currentDefaultPort}\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                vmessPort=\"${singBoxVMessWSPort}\"\n            fi\n\n            local count=\n            while read -r line; do\n                echoContent skyBlue \"\\n ---> 账号:${email}${count}\"\n                echo\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vmessws \"${vmessPort}\" \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\" \"${line}\" \"${path}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentCDNAddress}\" | tr ',' '\\n')\n        done\n    fi\n\n    # trojan tcp\n    if echo ${currentInstallProtocolType} | grep -q \",4,\"; then\n        echoContent skyBlue \"\\n==================================  Trojan TLS [不推荐] ==================================\\n\"\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}04_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n            echoContent skyBlue \"\\n ---> 账号:${email}\"\n\n            defaultBase64Code trojan \"${currentDefaultPort}${singBoxTrojanPort}\" \"${email}\" \"$(echo \"${user}\" | jq -r .password)\"\n        done\n    fi\n    # VLESS grpc\n    if echo ${currentInstallProtocolType} | grep -q \",5,\"; then\n        echoContent skyBlue \"\\n=============================== VLESS gRPC TLS [仅CDN推荐]  ===============================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}06_VLESS_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do\n\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            local count=\n            while read -r line; do\n                echoContent skyBlue \"\\n ---> 账号:${email}${count}\"\n                echo\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vlessgrpc \"${currentDefaultPort}\" \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id)\" \"${line}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentCDNAddress}\" | tr ',' '\\n')\n\n        done\n    fi\n    # hysteria2\n    if echo ${currentInstallProtocolType} | grep -q \",6,\" || [[ -n \"${hysteriaPort}\" ]]; then\n        readPortHopping \"hysteria2\" \"${singBoxHysteria2Port}\"\n        echoContent skyBlue \"\\n================================  Hysteria2 TLS [推荐] ================================\\n\"\n        local path=\"${configPath}\"\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            path=\"${singBoxConfigPath}\"\n        fi\n        local hysteria2DefaultPort=\n        if [[ -n \"${hysteria2PortHoppingStart}\" && -n \"${hysteria2PortHoppingEnd}\" ]]; then\n            hysteria2DefaultPort=\"${hysteria2PortHopping}\"\n        else\n            hysteria2DefaultPort=${singBoxHysteria2Port}\n        fi\n\n        jq -r -c '.inbounds[]|.users[]' \"${path}06_hysteria2_inbounds.json\" | while read -r user; do\n            echoContent skyBlue \"\\n ---> 账号:$(echo \"${user}\" | jq -r .name)\"\n            echo\n            defaultBase64Code hysteria \"${hysteria2DefaultPort}\" \"$(echo \"${user}\" | jq -r .name)\" \"$(echo \"${user}\" | jq -r .password)\"\n        done\n\n    fi\n\n    # VLESS reality vision\n    if echo ${currentInstallProtocolType} | grep -q \",7,\"; then\n        echoContent skyBlue \"============================= VLESS reality_vision [推荐]  ==============================\\n\"\n        jq .inbounds[1].settings.clients//.inbounds[0].users ${configPath}07_VLESS_vision_reality_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n\n            echoContent skyBlue \"\\n ---> 账号:${email}\"\n            echo\n            defaultBase64Code vlessReality \"${xrayVLESSRealityVisionPort}${singBoxVLESSRealityVisionPort}\" \"${email}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\"\n        done\n    fi\n    # VLESS reality gRPC\n    if echo ${currentInstallProtocolType} | grep -q \",8,\"; then\n        echoContent skyBlue \"============================== VLESS reality_gRPC [推荐] ===============================\\n\"\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}08_VLESS_vision_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n\n            echoContent skyBlue \"\\n ---> 账号:${email}\"\n            echo\n            defaultBase64Code vlessRealityGRPC \"${xrayVLESSRealityVisionPort}${singBoxVLESSRealityGRPCPort}\" \"${email}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\"\n        done\n    fi\n    # tuic\n    if echo ${currentInstallProtocolType} | grep -q \",9,\" || [[ -n \"${tuicPort}\" ]]; then\n        echoContent skyBlue \"\\n================================  Tuic TLS [推荐]  ================================\\n\"\n        local path=\"${configPath}\"\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            path=\"${singBoxConfigPath}\"\n        fi\n        jq -r -c '.inbounds[].users[]' \"${path}09_tuic_inbounds.json\" | while read -r user; do\n            echoContent skyBlue \"\\n ---> 账号:$(echo \"${user}\" | jq -r .name)\"\n            echo\n            defaultBase64Code tuic \"${singBoxTuicPort}\" \"$(echo \"${user}\" | jq -r .name)\" \"$(echo \"${user}\" | jq -r .uuid)_$(echo \"${user}\" | jq -r .password)\"\n        done\n\n    fi\n    # naive\n    if echo ${currentInstallProtocolType} | grep -q \",10,\" || [[ -n \"${singBoxNaivePort}\" ]]; then\n        echoContent skyBlue \"\\n================================  naive TLS [推荐，不支持ClashMeta]  ================================\\n\"\n\n        jq -r -c '.inbounds[]|.users[]' \"${configPath}10_naive_inbounds.json\" | while read -r user; do\n            echoContent skyBlue \"\\n ---> 账号:$(echo \"${user}\" | jq -r .username)\"\n            echo\n            defaultBase64Code naive \"${singBoxNaivePort}\" \"$(echo \"${user}\" | jq -r .username)\" \"$(echo \"${user}\" | jq -r .password)\"\n        done\n\n    fi\n    # VMess HTTPUpgrade\n    if echo ${currentInstallProtocolType} | grep -q \",11,\"; then\n        echoContent skyBlue \"\\n================================ VMess HTTPUpgrade TLS [仅CDN推荐]  ================================\\n\"\n        local path=\"${currentPath}vws\"\n        if [[ ${coreInstallType} == \"1\" ]]; then\n            path=\"/${currentPath}vws\"\n        elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n            path=\"${singBoxVMessHTTPUpgradePath}\"\n        fi\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}11_VMess_HTTPUpgrade_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n\n            local vmessHTTPUpgradePort=${currentDefaultPort}\n            if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                vmessHTTPUpgradePort=\"${singBoxVMessHTTPUpgradePort}\"\n            fi\n\n            local count=\n            while read -r line; do\n                echoContent skyBlue \"\\n ---> 账号:${email}${count}\"\n                echo\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vmessHTTPUpgrade \"${vmessHTTPUpgradePort}\" \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\" \"${line}\" \"${path}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentCDNAddress}\" | tr ',' '\\n')\n        done\n    fi\n    # VLESS Reality XHTTP\n    if echo ${currentInstallProtocolType} | grep -q \",12,\"; then\n        echoContent skyBlue \"\\n================================ VLESS Reality XHTTP TLS [仅CDN推荐] ================================\\n\"\n\n        jq .inbounds[0].settings.clients//.inbounds[0].users ${configPath}12_VLESS_XHTTP_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email//.name)\n            echo\n            local path=\"${currentPath}xHTTP\"\n\n            local count=\n            while read -r line; do\n                echoContent skyBlue \"\\n ---> 账号:${email}${count}\"\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vlessXHTTP \"${xrayVLESSRealityXHTTPort}\" \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id//.uuid)\" \"${line}\" \"${path}\"\n                    count=$((count + 1))\n                    echo\n                fi\n            done < <(echo \"${currentCDNAddress}\" | tr ',' '\\n')\n        done\n    fi\n    # AnyTLS\n    if echo ${currentInstallProtocolType} | grep -q \",13,\"; then\n        echoContent skyBlue \"\\n================================  AnyTLS ================================\\n\"\n\n        jq -r -c '.inbounds[]|.users[]' \"${configPath}13_anytls_inbounds.json\" | while read -r user; do\n            echoContent skyBlue \"\\n ---> 账号:$(echo \"${user}\" | jq -r .name)\"\n            echo\n            defaultBase64Code anytls \"${singBoxAnyTLSPort}\" \"$(echo \"${user}\" | jq -r .name)\" \"$(echo \"${user}\" | jq -r .password)\"\n        done\n\n    fi\n}\n# 移除nginx302配置\nremoveNginx302() {\n    local count=\n    grep -n \"return 302\" <\"${nginxConfigPath}alone.conf\" | while read -r line; do\n\n        if ! echo \"${line}\" | grep -q \"request_uri\"; then\n            local removeIndex=\n            removeIndex=$(echo \"${line}\" | awk -F \"[:]\" '{print $1}')\n            removeIndex=$((removeIndex + count))\n            sed -i \"${removeIndex}d\" ${nginxConfigPath}alone.conf\n            count=$((count - 1))\n        fi\n    done\n}\n\n# 检查302是否成功\ncheckNginx302() {\n    local domain302Status=\n    domain302Status=$(curl -s \"https://${currentHost}:${currentPort}\")\n    if echo \"${domain302Status}\" | grep -q \"302\"; then\n        #        local domain302Result=\n        #        domain302Result=$(curl -L -s \"https://${currentHost}:${currentPort}\")\n        #        if [[ -n \"${domain302Result}\" ]]; then\n        echoContent green \" ---> 302重定向设置完毕\"\n        exit 0\n        #        fi\n    fi\n    echoContent red \" ---> 302重定向设置失败，请仔细检查是否和示例相同\"\n    backupNginxConfig restoreBackup\n}\n\n# 备份恢复nginx文件\nbackupNginxConfig() {\n    if [[ \"$1\" == \"backup\" ]]; then\n        cp ${nginxConfigPath}alone.conf /etc/v2ray-agent/alone_backup.conf\n        echoContent green \" ---> nginx配置文件备份成功\"\n    fi\n\n    if [[ \"$1\" == \"restoreBackup\" ]] && [[ -f \"/etc/v2ray-agent/alone_backup.conf\" ]]; then\n        cp /etc/v2ray-agent/alone_backup.conf ${nginxConfigPath}alone.conf\n        echoContent green \" ---> nginx配置文件恢复备份成功\"\n        rm /etc/v2ray-agent/alone_backup.conf\n    fi\n\n}\n# 添加302配置\naddNginx302() {\n\n    local count=1\n    grep -n \"location / {\" <\"${nginxConfigPath}alone.conf\" | while read -r line; do\n        if [[ -n \"${line}\" ]]; then\n            local insertIndex=\n            insertIndex=\"$(echo \"${line}\" | awk -F \"[:]\" '{print $1}')\"\n            insertIndex=$((insertIndex + count))\n            sed \"${insertIndex}i return 302 '$1';\" ${nginxConfigPath}alone.conf >${nginxConfigPath}tmpfile && mv ${nginxConfigPath}tmpfile ${nginxConfigPath}alone.conf\n            count=$((count + 1))\n        else\n            echoContent red \" ---> 302添加失败\"\n            backupNginxConfig restoreBackup\n        fi\n\n    done\n}\n\n# 更新伪装站\nupdateNginxBlog() {\n    if [[ \"${coreInstallType}\" == \"2\" ]]; then\n        echoContent red \"\\n ---> 此功能仅支持Xray-core内核\"\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\n进度 $1/${totalProgress} : 更换伪装站点\"\n\n    if ! echo \"${currentInstallProtocolType}\" | grep -q \",0,\" || [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n ---> 由于环境依赖，请先安装Xray-core的VLESS_TCP_TLS_Vision\"\n        exit 0\n    fi\n    echoContent red \"==============================================================\"\n    echoContent yellow \"# 如需自定义，请手动复制模版文件到 ${nginxStaticPath} \\n\"\n    echoContent yellow \"1.新手引导\"\n    echoContent yellow \"2.游戏网站\"\n    echoContent yellow \"3.个人博客01\"\n    echoContent yellow \"4.企业站\"\n    echoContent yellow \"5.解锁加密的音乐文件模版[https://github.com/ix64/unlock-music]\"\n    echoContent yellow \"6.mikutap[https://github.com/HFIProgramming/mikutap]\"\n    echoContent yellow \"7.企业站02\"\n    echoContent yellow \"8.个人博客02\"\n    echoContent yellow \"9.404自动跳转baidu\"\n    echoContent yellow \"10.302重定向网站\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" selectInstallNginxBlogType\n\n    if [[ \"${selectInstallNginxBlogType}\" == \"10\" ]]; then\n        if [[ \"${coreInstallType}\" == \"2\" ]]; then\n            echoContent red \"\\n ---> 此功能仅支持Xray-core内核，请等待后续更新\"\n            exit 0\n        fi\n        echoContent red \"\\n==============================================================\"\n        echoContent yellow \"重定向的优先级更高，配置302之后如果更改伪装站点，根路由下伪装站点将不起作用\"\n        echoContent yellow \"如想要伪装站点实现作用需删除302重定向配置\\n\"\n        echoContent yellow \"1.添加\"\n        echoContent yellow \"2.删除\"\n        echoContent red \"==============================================================\"\n        read -r -p \"请选择:\" redirectStatus\n\n        if [[ \"${redirectStatus}\" == \"1\" ]]; then\n            backupNginxConfig backup\n            read -r -p \"请输入要重定向的域名,例如 https://www.baidu.com:\" redirectDomain\n            removeNginx302\n            addNginx302 \"${redirectDomain}\"\n            handleNginx stop\n            handleNginx start\n            if [[ -z $(pgrep -f \"nginx\") ]]; then\n                backupNginxConfig restoreBackup\n                handleNginx start\n                exit 0\n            fi\n            checkNginx302\n            exit 0\n        fi\n        if [[ \"${redirectStatus}\" == \"2\" ]]; then\n            removeNginx302\n            echoContent green \" ---> 移除302重定向成功\"\n            exit 0\n        fi\n    fi\n    if [[ \"${selectInstallNginxBlogType}\" =~ ^[1-9]$ ]]; then\n        rm -rf \"${nginxStaticPath}*\"\n\n        if [[ \"${release}\" == \"alpine\" ]]; then\n            wget -q -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip\"\n        else\n            wget -q \"${wgetShowProgressStatus}\" -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip\"\n        fi\n\n        unzip -o \"${nginxStaticPath}html${selectInstallNginxBlogType}.zip\" -d \"${nginxStaticPath}\" >/dev/null\n        rm -f \"${nginxStaticPath}html${selectInstallNginxBlogType}.zip*\"\n        echoContent green \" ---> 更换伪站成功\"\n    else\n        echoContent red \" ---> 选择错误，请重新选择\"\n        updateNginxBlog\n    fi\n}\n\n# 添加新端口\naddCorePort() {\n\n    if [[ \"${coreInstallType}\" == \"2\" ]]; then\n        echoContent red \"\\n ---> 此功能仅支持Xray-core内核\"\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : 添加新端口\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\\n\"\n    echoContent yellow \"支持批量添加\"\n    echoContent yellow \"不影响默认端口的使用\"\n    echoContent yellow \"查看账号时，只会展示默认端口的账号\"\n    echoContent yellow \"不允许有特殊字符，注意逗号的格式\"\n    echoContent yellow \"如已安装hysteria，会同时安装hysteria新端口\"\n    echoContent yellow \"录入示例:2053,2083,2087\\n\"\n\n    echoContent yellow \"1.查看已添加端口\"\n    echoContent yellow \"2.添加端口\"\n    echoContent yellow \"3.删除端口\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" selectNewPortType\n    if [[ \"${selectNewPortType}\" == \"1\" ]]; then\n        find ${configPath} -name \"*dokodemodoor*\" | grep -v \"hysteria\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | awk -F \"[_]\" '{print $4}' | awk -F \"[.]\" '{print \"\"NR\"\"\":\"$1}'\n        exit 0\n    elif [[ \"${selectNewPortType}\" == \"2\" ]]; then\n        read -r -p \"请输入端口号:\" newPort\n        read -r -p \"请输入默认的端口号，同时会更改订阅端口以及节点端口，[回车]默认443:\" defaultPort\n\n        if [[ -n \"${defaultPort}\" ]]; then\n            rm -rf \"$(find ${configPath}* | grep \"default\")\"\n        fi\n\n        if [[ -n \"${newPort}\" ]]; then\n\n            while read -r port; do\n                rm -rf \"$(find ${configPath}* | grep \"${port}\")\"\n\n                local fileName=\n                local hysteriaFileName=\n                if [[ -n \"${defaultPort}\" && \"${port}\" == \"${defaultPort}\" ]]; then\n                    fileName=\"${configPath}02_dokodemodoor_inbounds_${port}_default.json\"\n                else\n                    fileName=\"${configPath}02_dokodemodoor_inbounds_${port}.json\"\n                fi\n\n                if [[ -n ${hysteriaPort} ]]; then\n                    hysteriaFileName=\"${configPath}02_dokodemodoor_inbounds_hysteria_${port}.json\"\n                fi\n\n                # 开放端口\n                allowPort \"${port}\"\n                allowPort \"${port}\" \"udp\"\n\n                local settingsPort=443\n                if [[ -n \"${customPort}\" ]]; then\n                    settingsPort=${customPort}\n                fi\n\n                if [[ -n ${hysteriaFileName} ]]; then\n                    cat <<EOF >\"${hysteriaFileName}\"\n{\n  \"inbounds\": [\n\t{\n\t  \"listen\": \"0.0.0.0\",\n\t  \"port\": ${port},\n\t  \"protocol\": \"dokodemo-door\",\n\t  \"settings\": {\n\t\t\"address\": \"127.0.0.1\",\n\t\t\"port\": ${hysteriaPort},\n\t\t\"network\": \"udp\",\n\t\t\"followRedirect\": false\n\t  },\n\t  \"tag\": \"dokodemo-door-newPort-hysteria-${port}\"\n\t}\n  ]\n}\nEOF\n                fi\n                cat <<EOF >\"${fileName}\"\n{\n  \"inbounds\": [\n\t{\n\t  \"listen\": \"0.0.0.0\",\n\t  \"port\": ${port},\n\t  \"protocol\": \"dokodemo-door\",\n\t  \"settings\": {\n\t\t\"address\": \"127.0.0.1\",\n\t\t\"port\": ${settingsPort},\n\t\t\"network\": \"tcp\",\n\t\t\"followRedirect\": false\n\t  },\n\t  \"tag\": \"dokodemo-door-newPort-${port}\"\n\t}\n  ]\n}\nEOF\n            done < <(echo \"${newPort}\" | tr ',' '\\n')\n\n            echoContent green \" ---> 添加完毕\"\n            reloadCore\n            addCorePort\n        fi\n    elif [[ \"${selectNewPortType}\" == \"3\" ]]; then\n        find ${configPath} -name \"*dokodemodoor*\" | grep -v \"hysteria\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | awk -F \"[_]\" '{print $4}' | awk -F \"[.]\" '{print \"\"NR\"\"\":\"$1}'\n        read -r -p \"请输入要删除的端口编号:\" portIndex\n        local dokoConfig\n        dokoConfig=$(find ${configPath} -name \"*dokodemodoor*\" | grep -v \"hysteria\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | awk -F \"[_]\" '{print $4}' | awk -F \"[.]\" '{print \"\"NR\"\"\":\"$1}' | grep \"${portIndex}:\")\n        if [[ -n \"${dokoConfig}\" ]]; then\n            rm \"${configPath}02_dokodemodoor_inbounds_$(echo \"${dokoConfig}\" | awk -F \"[:]\" '{print $2}').json\"\n            local hysteriaDokodemodoorFilePath=\n\n            hysteriaDokodemodoorFilePath=\"${configPath}02_dokodemodoor_inbounds_hysteria_$(echo \"${dokoConfig}\" | awk -F \"[:]\" '{print $2}').json\"\n            if [[ -f \"${hysteriaDokodemodoorFilePath}\" ]]; then\n                rm \"${hysteriaDokodemodoorFilePath}\"\n            fi\n\n            reloadCore\n            addCorePort\n        else\n            echoContent yellow \"\\n ---> 编号输入错误，请重新选择\"\n            addCorePort\n        fi\n    fi\n}\n\n# 卸载脚本\nunInstall() {\n    read -r -p \"是否确认卸载安装内容？[y/n]:\" unInstallStatus\n    if [[ \"${unInstallStatus}\" != \"y\" ]]; then\n        echoContent green \" ---> 放弃卸载\"\n        menu\n        exit 0\n    fi\n    checkBTPanel\n    echoContent yellow \" ---> 脚本不会删除acme相关配置，删除请手动执行 [rm -rf /root/.acme.sh]\"\n    handleNginx stop\n    if [[ -z $(pgrep -f \"nginx\") ]]; then\n        echoContent green \" ---> 停止Nginx成功\"\n    fi\n    if [[ \"${release}\" == \"alpine\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            handleXray stop\n            rc-update del xray default\n            rm -rf /etc/init.d/xray\n            echoContent green \" ---> 删除Xray开机自启完成\"\n        fi\n        if [[ \"${coreInstallType}\" == \"2\" || -n \"${singBoxConfigPath}\" ]]; then\n            handleSingBox stop\n            rc-update del sing-box default\n            rm -rf /etc/init.d/sing-box\n            echoContent green \" ---> 删除sing-box开机自启完成\"\n        fi\n    else\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            handleXray stop\n            rm -rf /etc/systemd/system/xray.service\n            echoContent green \" ---> 删除Xray开机自启完成\"\n        fi\n        if [[ \"${coreInstallType}\" == \"2\" || -n \"${singBoxConfigPath}\" ]]; then\n            handleSingBox stop\n            rm -rf /etc/systemd/system/sing-box.service\n            echoContent green \" ---> 删除sing-box开机自启完成\"\n        fi\n    fi\n\n    rm -rf /etc/v2ray-agent\n    rm -rf ${nginxConfigPath}alone.conf\n    rm -rf ${nginxConfigPath}checkPortOpen.conf >/dev/null 2>&1\n    rm -rf \"${nginxConfigPath}sing_box_VMess_HTTPUpgrade.conf\" >/dev/null 2>&1\n    rm -rf ${nginxConfigPath}checkPortOpen.conf >/dev/null 2>&1\n\n    unInstallSubscribe\n\n    if [[ -d \"${nginxStaticPath}\" && -f \"${nginxStaticPath}/check\" ]]; then\n        rm -rf \"${nginxStaticPath}\"\n        echoContent green \" ---> 删除伪装网站完成\"\n    fi\n\n    rm -rf /usr/bin/vasma\n    rm -rf /usr/sbin/vasma\n    echoContent green \" ---> 卸载快捷方式完成\"\n    echoContent green \" ---> 卸载v2ray-agent脚本完成\"\n}\n\n# CDN节点管理\nmanageCDN() {\n    echoContent skyBlue \"\\n进度 $1/1 : CDN节点管理\"\n    local setCDNDomain=\n\n    if echo \"${currentInstallProtocolType}\" | grep -qE \",1,|,2,|,3,|,5,|,11,\"; then\n        echoContent red \"==============================================================\"\n        echoContent yellow \"# 注意事项\"\n        echoContent yellow \"\\n教程地址:\"\n        echoContent skyBlue \"https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip\"\n        echoContent red \"\\n如对Cloudflare优化不了解，请不要使用\"\n\n        echoContent yellow \"1.CNAME www.digitalocean.com\"\n        echoContent yellow \"2.CNAME who.int\"\n        echoContent yellow \"3.CNAME blog.hostmonit.com\"\n        echoContent yellow \"4.CNAME www.visa.com.hk\"\n        echoContent yellow \"5.手动输入[可输入多个，比如: 1.1.1.1,1.1.2.2,cloudflare.com 逗号分隔]\"\n        echoContent yellow \"6.移除CDN节点\"\n        echoContent red \"==============================================================\"\n        read -r -p \"请选择:\" selectCDNType\n        case ${selectCDNType} in\n        1)\n            setCDNDomain=\"www.digitalocean.com\"\n            ;;\n        2)\n            setCDNDomain=\"who.int\"\n            ;;\n        3)\n            setCDNDomain=\"blog.hostmonit.com\"\n            ;;\n        4)\n            setCDNDomain=\"www.visa.com.hk\"\n            ;;\n        5)\n            read -r -p \"请输入想要自定义CDN IP或者域名:\" setCDNDomain\n            ;;\n        6)\n            echo >/etc/v2ray-agent/cdn\n            echoContent green \" ---> 移除成功\"\n            exit 0\n            ;;\n        esac\n\n        if [[ -n \"${setCDNDomain}\" ]]; then\n            echo >/etc/v2ray-agent/cdn\n            echo \"${setCDNDomain}\" >\"/etc/v2ray-agent/cdn\"\n            echoContent green \" ---> 修改CDN成功\"\n            subscribe false false\n        else\n            echoContent red \" ---> 不可以为空，请重新输入\"\n            manageCDN 1\n        fi\n    else\n        echoContent yellow \"\\n教程地址:\"\n        echoContent skyBlue \"https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip\\n\"\n        echoContent red \" ---> 未检测到可以使用的协议，仅支持ws、grpc、HTTPUpgrade相关的协议\"\n    fi\n}\n# 自定义uuid\ncustomUUID() {\n    read -r -p \"请输入合法的UUID，[回车]随机UUID:\" currentCustomUUID\n    echo\n    if [[ -z \"${currentCustomUUID}\" ]]; then\n        if [[ \"${selectInstallType}\" == \"1\" || \"${coreInstallType}\" == \"1\" ]]; then\n            currentCustomUUID=$(${ctlPath} uuid)\n        elif [[ \"${selectInstallType}\" == \"2\" || \"${coreInstallType}\" == \"2\" ]]; then\n            currentCustomUUID=$(${ctlPath} generate uuid)\n        fi\n\n        echoContent yellow \"uuid：${currentCustomUUID}\\n\"\n\n    else\n        local checkUUID=\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            checkUUID=$(jq -r --arg currentUUID \"$currentCustomUUID\" \"(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]? | select(.id == \\$currentUUID) | .email\" ${configPath}${frontingType:-$frontingTypeReality}.json)\n        elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n            checkUUID=$(jq -r --arg currentUUID \"$currentCustomUUID\" \".inbounds[0].users[] | select(.uuid == \\$currentUUID) | .name//.username\" ${configPath}${frontingType}.json)\n        fi\n\n        if [[ -n \"${checkUUID}\" ]]; then\n            echoContent red \" ---> UUID不可重复\"\n            exit 0\n        fi\n    fi\n}\n\n# 自定义email\ncustomUserEmail() {\n    read -r -p \"请输入合法的email，[回车]随机email:\" currentCustomEmail\n    echo\n    if [[ -z \"${currentCustomEmail}\" ]]; then\n        currentCustomEmail=\"${currentCustomUUID}\"\n        echoContent yellow \"email: ${currentCustomEmail}\\n\"\n    else\n        local checkEmail=\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            local frontingTypeConfig=\"${frontingType}\"\n            if [[ \"${currentInstallProtocolType}\" == \",7,8,\" ]]; then\n                frontingTypeConfig=\"07_VLESS_vision_reality_inbounds\"\n            fi\n\n            checkEmail=$(jq -r --arg currentEmail \"$currentCustomEmail\" \"(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]? | select(.email == \\$currentEmail) | .email\" ${configPath}${frontingTypeConfig:-$frontingTypeReality}.json)\n        elif\n            [[ \"${coreInstallType}\" == \"2\" ]]\n        then\n            checkEmail=$(jq -r --arg currentEmail \"$currentCustomEmail\" \".inbounds[0].users[] | select(.name == \\$currentEmail) | .name\" ${configPath}${frontingType}.json)\n        fi\n\n        if [[ -n \"${checkEmail}\" ]]; then\n            echoContent red \" ---> email不可重复\"\n            exit 0\n        fi\n    fi\n}\n\n# 添加用户\naddUser() {\n    read -r -p \"请输入要添加的用户数量:\" userNum\n    echo\n    if [[ -z ${userNum} || ${userNum} -le 0 ]]; then\n        echoContent red \" ---> 输入有误，请重新输入\"\n        exit 0\n    fi\n    local userConfig=\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        userConfig=\".inbounds[0].settings.clients\"\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        userConfig=\".inbounds[0].users\"\n    fi\n\n    while [[ ${userNum} -gt 0 ]]; do\n        readConfigHostPathUUID\n        local users=\n        ((userNum--)) || true\n\n        customUUID\n        customUserEmail\n\n        uuid=${currentCustomUUID}\n        email=${currentCustomEmail}\n\n        # VLESS TCP\n        if echo \"${currentInstallProtocolType}\" | grep -q \",0,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 0 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 0 \"${uuid}\" \"${email}\")\n            fi\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}02_VLESS_TCP_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}02_VLESS_TCP_inbounds.json\n        fi\n\n        # VLESS WS\n        if echo \"${currentInstallProtocolType}\" | grep -q \",1,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 1 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 1 \"${uuid}\" \"${email}\")\n            fi\n\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}03_VLESS_WS_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}03_VLESS_WS_inbounds.json\n        fi\n\n        # trojan grpc\n        if echo \"${currentInstallProtocolType}\" | grep -q \",2,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 2 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 2 \"${uuid}\" \"${email}\")\n            fi\n\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}04_trojan_gRPC_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}04_trojan_gRPC_inbounds.json\n        fi\n        # VMess WS\n        if echo \"${currentInstallProtocolType}\" | grep -q \",3,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 3 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 3 \"${uuid}\" \"${email}\")\n            fi\n\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}05_VMess_WS_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}05_VMess_WS_inbounds.json\n        fi\n        # trojan tcp\n        if echo \"${currentInstallProtocolType}\" | grep -q \",4,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 4 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 4 \"${uuid}\" \"${email}\")\n            fi\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}04_trojan_TCP_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}04_trojan_TCP_inbounds.json\n        fi\n\n        # vless grpc\n        if echo \"${currentInstallProtocolType}\" | grep -q \",5,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 5 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 5 \"${uuid}\" \"${email}\")\n            fi\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}06_VLESS_gRPC_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}06_VLESS_gRPC_inbounds.json\n        fi\n\n        # vless reality vision\n        if echo \"${currentInstallProtocolType}\" | grep -q \",7,\"; then\n            local clients=\n            local realityUserConfig=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 7 \"${uuid}\" \"${email}\")\n                realityUserConfig=\".inbounds[1].settings.clients\"\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 7 \"${uuid}\" \"${email}\")\n                realityUserConfig=\".inbounds[0].users\"\n            fi\n            clients=$(jq -r \"${realityUserConfig} = ${clients}\" ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n\n        # vless reality grpc\n        if echo \"${currentInstallProtocolType}\" | grep -q \",8,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 8 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 8 \"${uuid}\" \"${email}\")\n            fi\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}08_VLESS_vision_gRPC_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}08_VLESS_vision_gRPC_inbounds.json\n        fi\n\n        # hysteria2\n        if echo ${currentInstallProtocolType} | grep -q \",6,\"; then\n            local clients=\n\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 6 \"${uuid}\" \"${email}\")\n            elif [[ -n \"${singBoxConfigPath}\" ]]; then\n                clients=$(initSingBoxClients 6 \"${uuid}\" \"${email}\")\n            fi\n\n            clients=$(jq -r \".inbounds[0].users = ${clients}\" \"${singBoxConfigPath}06_hysteria2_inbounds.json\")\n            echo \"${clients}\" | jq . >\"${singBoxConfigPath}06_hysteria2_inbounds.json\"\n        fi\n\n        # tuic\n        if echo ${currentInstallProtocolType} | grep -q \",9,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 9 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 9 \"${uuid}\" \"${email}\")\n            fi\n\n            clients=$(jq -r \".inbounds[0].users = ${clients}\" \"${singBoxConfigPath}09_tuic_inbounds.json\")\n\n            echo \"${clients}\" | jq . >\"${singBoxConfigPath}09_tuic_inbounds.json\"\n        fi\n        # naive\n        if echo ${currentInstallProtocolType} | grep -q \",10,\"; then\n            local clients=\n            clients=$(initSingBoxClients 10 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].users = ${clients}\" \"${singBoxConfigPath}10_naive_inbounds.json\")\n\n            echo \"${clients}\" | jq . >\"${singBoxConfigPath}10_naive_inbounds.json\"\n        fi\n        # VMess WS\n        if echo \"${currentInstallProtocolType}\" | grep -q \",11,\"; then\n            local clients=\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                clients=$(initXrayClients 11 \"${uuid}\" \"${email}\")\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                clients=$(initSingBoxClients 11 \"${uuid}\" \"${email}\")\n            fi\n\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}11_VMess_HTTPUpgrade_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}11_VMess_HTTPUpgrade_inbounds.json\n        fi\n        # anytls\n        if echo \"${currentInstallProtocolType}\" | grep -q \",13,\"; then\n            local clients=\n            clients=$(initSingBoxClients 13 \"${uuid}\" \"${email}\")\n\n            clients=$(jq -r \"${userConfig} = ${clients}\" ${configPath}13_anytls_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}13_anytls_inbounds.json\n        fi\n    done\n    reloadCore\n    echoContent green \" ---> 添加完成\"\n    readNginxSubscribe\n    if [[ -n \"${subscribePort}\" ]]; then\n        subscribe false\n    fi\n    manageAccount 1\n}\n# 移除用户\nremoveUser() {\n\n    local uuid=\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        jq -r -c '(.inbounds[0].settings.clients // .inbounds[1].settings.clients)[]?|.email' ${configPath}${frontingType:-$frontingTypeReality}.json | awk '{print NR\"\"\":\"$0}'\n        read -r -p \"请选择要删除的用户编号[仅支持单个删除]:\" delUserIndex\n        if [[ $(jq -r '(.inbounds[0].settings.clients // .inbounds[1].settings.clients)?|length' ${configPath}${frontingType:-$frontingTypeReality}.json) -lt ${delUserIndex} ]]; then\n            echoContent red \" ---> 选择错误\"\n        else\n            delUserIndex=$((delUserIndex - 1))\n        fi\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        jq -r -c .inbounds[0].users[].name//.inbounds[0].users[].username ${configPath}${frontingType:-$frontingTypeReality}.json | awk '{print NR\"\"\":\"$0}'\n        read -r -p \"请选择要删除的用户编号[仅支持单个删除]:\" delUserIndex\n        if [[ $(jq -r '.inbounds[0].users|length' ${configPath}${frontingType:-$frontingTypeReality}.json) -lt ${delUserIndex} ]]; then\n            echoContent red \" ---> 选择错误\"\n        else\n            delUserIndex=$((delUserIndex - 1))\n        fi\n    fi\n\n    if [[ -n \"${delUserIndex}\" ]]; then\n\n        if echo ${currentInstallProtocolType} | grep -q \",0,\"; then\n            local vlessVision\n            vlessVision=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}02_VLESS_TCP_inbounds.json)\n            echo \"${vlessVision}\" | jq . >${configPath}02_VLESS_TCP_inbounds.json\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",1,\"; then\n            local vlessWSResult\n            vlessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}03_VLESS_WS_inbounds.json)\n            echo \"${vlessWSResult}\" | jq . >${configPath}03_VLESS_WS_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",2,\"; then\n            local trojangRPCUsers\n            trojangRPCUsers=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"')' ${configPath}04_trojan_gRPC_inbounds.json)\n            echo \"${trojangRPCUsers}\" | jq . >${configPath}04_trojan_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",3,\"; then\n            local vmessWSResult\n            vmessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}05_VMess_WS_inbounds.json)\n            echo \"${vmessWSResult}\" | jq . >${configPath}05_VMess_WS_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",5,\"; then\n            local vlessGRPCResult\n            vlessGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}06_VLESS_gRPC_inbounds.json)\n            echo \"${vlessGRPCResult}\" | jq . >${configPath}06_VLESS_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",4,\"; then\n            local trojanTCPResult\n            trojanTCPResult=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}04_trojan_TCP_inbounds.json)\n            echo \"${trojanTCPResult}\" | jq . >${configPath}04_trojan_TCP_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",6,\"; then\n            local hysteriaResult\n            hysteriaResult=$(jq -r 'del(.inbounds[0].users['\"${delUserIndex}\"'])' \"${singBoxConfigPath}06_hysteria2_inbounds.json\")\n            echo \"${hysteriaResult}\" | jq . >\"${singBoxConfigPath}06_hysteria2_inbounds.json\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",7,\"; then\n            local vlessRealityResult\n            vlessRealityResult=$(jq -r 'del(.inbounds[1].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${vlessRealityResult}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",8,\"; then\n            local vlessRealityGRPCResult\n            vlessRealityGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['\"${delUserIndex}\"']//.inbounds[0].users['\"${delUserIndex}\"'])' ${configPath}08_VLESS_vision_gRPC_inbounds.json)\n            echo \"${vlessRealityGRPCResult}\" | jq . >${configPath}08_VLESS_vision_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q \",9,\"; then\n            local tuicResult\n            tuicResult=$(jq -r 'del(.inbounds[0].users['\"${delUserIndex}\"'])' \"${singBoxConfigPath}09_tuic_inbounds.json\")\n            echo \"${tuicResult}\" | jq . >\"${singBoxConfigPath}09_tuic_inbounds.json\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q \",10,\"; then\n            local naiveResult\n            naiveResult=$(jq -r 'del(.inbounds[0].users['\"${delUserIndex}\"'])' \"${singBoxConfigPath}10_naive_inbounds.json\")\n            echo \"${naiveResult}\" | jq . >\"${singBoxConfigPath}10_naive_inbounds.json\"\n        fi\n        # VMess HTTPUpgrade\n        if echo ${currentInstallProtocolType} | grep -q \",11,\"; then\n            local vmessHTTPUpgradeResult\n            vmessHTTPUpgradeResult=$(jq -r 'del(.inbounds[0].users['\"${delUserIndex}\"'])' \"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json\")\n            echo \"${vmessHTTPUpgradeResult}\" | jq . >\"${singBoxConfigPath}11_VMess_HTTPUpgrade_inbounds.json\"\n            echo \"${vmessHTTPUpgradeResult}\" | jq . >${configPath}11_VMess_HTTPUpgrade_inbounds.json\n        fi\n        # AnyTLS\n        if echo ${currentInstallProtocolType} | grep -q \",13,\"; then\n            local anyTLSResult\n            anyTLSResult=$(jq -r 'del(.inbounds[0].users['\"${delUserIndex}\"'])' \"${singBoxConfigPath}13_anytls_inbounds.json\")\n            echo \"${anyTLSResult}\" | jq . >\"${singBoxConfigPath}13_anytls_inbounds.json\"\n        fi\n        reloadCore\n        readNginxSubscribe\n        if [[ -n \"${subscribePort}\" ]]; then\n            subscribe false\n        fi\n    fi\n    manageAccount 1\n}\n# 更新脚本\nupdateV2RayAgent() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 更新v2ray-agent脚本\"\n    rm -rf /etc/v2ray-agent/install.sh\n    if [[ \"${release}\" == \"alpine\" ]]; then\n        wget -c -q -P /etc/v2ray-agent/ -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh\"\n    else\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/ -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh\"\n    fi\n\n    sudo chmod 700 /etc/v2ray-agent/install.sh\n    local version\n    version=$(grep '当前版本：v' \"/etc/v2ray-agent/install.sh\" | awk -F \"[v]\" '{print $2}' | tail -n +2 | head -n 1 | awk -F \"[\\\"]\" '{print $1}')\n\n    echoContent green \"\\n ---> 更新完毕\"\n    echoContent yellow \" ---> 请手动执行[vasma]打开脚本\"\n    echoContent green \" ---> 当前版本：${version}\\n\"\n    echoContent yellow \"如更新不成功，请手动执行下面命令\\n\"\n    echoContent skyBlue \"wget -P /root -N --no-check-certificate https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh && chmod 700 /root/install.sh && /root/install.sh\"\n    echo\n    exit 0\n}\n\n# 防火墙\nhandleFirewall() {\n    if systemctl status ufw 2>/dev/null | grep -q \"active (exited)\" && [[ \"$1\" == \"stop\" ]]; then\n        systemctl stop ufw >/dev/null 2>&1\n        systemctl disable ufw >/dev/null 2>&1\n        echoContent green \" ---> ufw关闭成功\"\n\n    fi\n\n    if systemctl status firewalld 2>/dev/null | grep -q \"active (running)\" && [[ \"$1\" == \"stop\" ]]; then\n        systemctl stop firewalld >/dev/null 2>&1\n        systemctl disable firewalld >/dev/null 2>&1\n        echoContent green \" ---> firewalld关闭成功\"\n    fi\n}\n\n# 安装BBR\nbbrInstall() {\n    echoContent red \"\\n==============================================================\"\n    echoContent green \"BBR、DD脚本用的[ylx2016]的成熟作品，地址[https://github.com/ylx2016/Linux-NetSpeed]，请熟知\"\n    echoContent yellow \"1.安装脚本【推荐原版BBR+FQ】\"\n    echoContent yellow \"2.回退主目录\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" installBBRStatus\n    if [[ \"${installBBRStatus}\" == \"1\" ]]; then\n        wget -O tcpx.sh \"https://github.com/ylx2016/Linux-NetSpeed/raw/master/tcpx.sh\" && chmod +x tcpx.sh && ./tcpx.sh\n    else\n        menu\n    fi\n}\n\n# 查看、检查日志\ncheckLog() {\n    if [[ \"${coreInstallType}\" == \"2\" ]]; then\n        echoContent red \"\\n ---> 此功能仅支持Xray-core内核\"\n        exit 0\n    fi\n    if [[ -z \"${configPath}\" && -z \"${realityStatus}\" ]]; then\n        echoContent red \" ---> 没有检测到安装目录，请执行脚本安装内容\"\n        exit 0\n    fi\n    local realityLogShow=\n    local logStatus=false\n    if grep -q \"access\" ${configPath}00_log.json; then\n        logStatus=true\n    fi\n\n    echoContent skyBlue \"\\n功能 $1/${totalProgress} : 查看日志\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 建议仅调试时打开access日志\\n\"\n\n    if [[ \"${logStatus}\" == \"false\" ]]; then\n        echoContent yellow \"1.打开access日志\"\n    else\n        echoContent yellow \"1.关闭access日志\"\n    fi\n\n    echoContent yellow \"2.监听access日志\"\n    echoContent yellow \"3.监听error日志\"\n    echoContent yellow \"4.查看证书定时任务日志\"\n    echoContent yellow \"5.查看证书安装日志\"\n    echoContent yellow \"6.清空日志\"\n    echoContent red \"==============================================================\"\n\n    read -r -p \"请选择:\" selectAccessLogType\n    local configPathLog=${configPath//conf\\//}\n\n    case ${selectAccessLogType} in\n    1)\n        if [[ \"${logStatus}\" == \"false\" ]]; then\n            realityLogShow=true\n            cat <<EOF >${configPath}00_log.json\n{\n  \"log\": {\n  \t\"access\":\"${configPathLog}access.log\",\n    \"error\": \"${configPathLog}error.log\",\n    \"loglevel\": \"debug\"\n  }\n}\nEOF\n        elif [[ \"${logStatus}\" == \"true\" ]]; then\n            realityLogShow=false\n            cat <<EOF >${configPath}00_log.json\n{\n  \"log\": {\n    \"error\": \"${configPathLog}error.log\",\n    \"loglevel\": \"warning\"\n  }\n}\nEOF\n        fi\n\n        if [[ -n ${realityStatus} ]]; then\n            local vlessVisionRealityInbounds\n            vlessVisionRealityInbounds=$(jq -r \".inbounds[0].streamSettings.realitySettings.show=${realityLogShow}\" ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${vlessVisionRealityInbounds}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n        reloadCore\n        checkLog 1\n        ;;\n    2)\n        tail -f \"${configPathLog}access.log\"\n        ;;\n    3)\n        tail -f \"${configPathLog}error.log\"\n        ;;\n    4)\n        if [[ ! -f \"/etc/v2ray-agent/crontab_tls.log\" ]]; then\n            touch /etc/v2ray-agent/crontab_tls.log\n        fi\n        tail -n 100 /etc/v2ray-agent/crontab_tls.log\n        ;;\n    5)\n        tail -n 100 /etc/v2ray-agent/tls/acme.log\n        ;;\n    6)\n        echo >\"${configPathLog}access.log\"\n        echo >\"${configPathLog}error.log\"\n        ;;\n    esac\n}\n\n# 脚本快捷方式\naliasInstall() {\n\n    if [[ -f \"$HOME/install.sh\" ]] && [[ -d \"/etc/v2ray-agent\" ]] && grep <\"$HOME/install.sh\" -q \"作者:mack-a\"; then\n        mv \"$HOME/install.sh\" /etc/v2ray-agent/install.sh\n        local vasmaType=\n        if [[ -d \"/usr/bin/\" ]]; then\n            if [[ ! -f \"/usr/bin/vasma\" ]]; then\n                ln -s /etc/v2ray-agent/install.sh /usr/bin/vasma\n                chmod 700 /usr/bin/vasma\n                vasmaType=true\n            fi\n\n            rm -rf \"$HOME/install.sh\"\n        elif [[ -d \"/usr/sbin\" ]]; then\n            if [[ ! -f \"/usr/sbin/vasma\" ]]; then\n                ln -s /etc/v2ray-agent/install.sh /usr/sbin/vasma\n                chmod 700 /usr/sbin/vasma\n                vasmaType=true\n            fi\n            rm -rf \"$HOME/install.sh\"\n        fi\n        if [[ \"${vasmaType}\" == \"true\" ]]; then\n            echoContent green \"快捷方式创建成功，可执行[vasma]重新打开脚本\"\n        fi\n    fi\n}\n\n# 检查ipv6、ipv4\ncheckIPv6() {\n    currentIPv6IP=$(curl -s -6 -m 4 http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | cut -d \"=\" -f 2)\n\n    if [[ -z \"${currentIPv6IP}\" ]]; then\n        echoContent red \" ---> 不支持ipv6\"\n        exit 0\n    fi\n}\n\n# ipv6 分流\nipv6Routing() {\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> 未安装，请使用脚本安装\"\n        menu\n        exit 0\n    fi\n\n    checkIPv6\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : IPv6分流\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.查看已分流域名\"\n    echoContent yellow \"2.添加域名\"\n    echoContent yellow \"3.设置IPv6全局\"\n    echoContent yellow \"4.卸载IPv6分流\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" ipv6Status\n    if [[ \"${ipv6Status}\" == \"1\" ]]; then\n        showIPv6Routing\n        exit 0\n    elif [[ \"${ipv6Status}\" == \"2\" ]]; then\n        echoContent red \"==============================================================\"\n        echoContent yellow \"# 注意事项\\n\"\n        echoContent yellow \"# 注意事项\"\n        echoContent yellow \"# 使用教程：https://www.v2ray-agent.com/archives/1683226921000 \\n\"\n\n        read -r -p \"请按照上面示例录入域名:\" domainList\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            addXrayRouting IPv6_out outboundTag \"${domainList}\"\n            addXrayOutbound IPv6_out\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            addSingBoxRouteRule \"IPv6_out\" \"${domainList}\" \"IPv6_route\"\n            addSingBoxOutbound 01_direct_outbound\n            addSingBoxOutbound IPv6_out\n            addSingBoxOutbound IPv4_out\n        fi\n\n        echoContent green \" ---> 添加完毕\"\n\n    elif [[ \"${ipv6Status}\" == \"3\" ]]; then\n\n        echoContent red \"==============================================================\"\n        echoContent yellow \"# 注意事项\\n\"\n        echoContent yellow \"1.会删除所有设置的分流规则\"\n        echoContent yellow \"2.会删除IPv6之外的所有出站规则\\n\"\n        read -r -p \"是否确认设置？[y/n]:\" IPv6OutStatus\n\n        if [[ \"${IPv6OutStatus}\" == \"y\" ]]; then\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                addXrayOutbound IPv6_out\n                removeXrayOutbound IPv4_out\n                removeXrayOutbound z_direct_outbound\n                removeXrayOutbound blackhole_out\n                removeXrayOutbound wireguard_out_IPv4\n                removeXrayOutbound wireguard_out_IPv6\n                removeXrayOutbound socks5_outbound\n\n                rm ${configPath}09_routing.json >/dev/null 2>&1\n            fi\n            if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n                removeSingBoxConfig IPv4_out\n\n                removeSingBoxConfig wireguard_endpoints_IPv4_route\n                removeSingBoxConfig wireguard_endpoints_IPv6_route\n                removeSingBoxConfig wireguard_endpoints_IPv4\n                removeSingBoxConfig wireguard_endpoints_IPv6\n\n                removeSingBoxConfig socks5_02_inbound_route\n\n                removeSingBoxConfig IPv6_route\n\n                removeSingBoxConfig 01_direct_outbound\n\n                addSingBoxOutbound IPv6_out\n\n            fi\n\n            echoContent green \" ---> IPv6全局出站设置完毕\"\n        else\n\n            echoContent green \" ---> 放弃设置\"\n            exit 0\n        fi\n\n    elif [[ \"${ipv6Status}\" == \"4\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            unInstallRouting IPv6_out outboundTag\n\n            removeXrayOutbound IPv6_out\n            addXrayOutbound \"z_direct_outbound\"\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            removeSingBoxConfig IPv6_out\n            removeSingBoxConfig \"IPv6_route\"\n            addSingBoxOutbound \"01_direct_outbound\"\n        fi\n\n        echoContent green \" ---> IPv6分流卸载成功\"\n    else\n        echoContent red \" ---> 选择错误\"\n        exit 0\n    fi\n\n    reloadCore\n}\n\n# ipv6分流规则展示\nshowIPv6Routing() {\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n            echoContent yellow \"Xray-core：\"\n            jq -r -c '.routing.rules[]|select (.outboundTag==\"IPv6_out\")|.domain' ${configPath}09_routing.json | jq -r\n        elif [[ ! -f \"${configPath}09_routing.json\" && -f \"${configPath}IPv6_out.json\" ]]; then\n            echoContent yellow \"Xray-core\"\n            echoContent green \" ---> 已设置IPv6全局分流\"\n        else\n            echoContent yellow \" ---> 未安装IPv6分流\"\n        fi\n\n    fi\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        if [[ -f \"${singBoxConfigPath}IPv6_route.json\" ]]; then\n            echoContent yellow \"sing-box\"\n            jq -r -c '.route.rules[]|select (.outbound==\"IPv6_out\")' \"${singBoxConfigPath}IPv6_route.json\" | jq -r\n        elif [[ ! -f \"${singBoxConfigPath}IPv6_route.json\" && -f \"${singBoxConfigPath}IPv6_out.json\" ]]; then\n            echoContent yellow \"sing-box\"\n            echoContent green \" ---> 已设置IPv6全局分流\"\n        else\n            echoContent yellow \" ---> 未安装IPv6分流\"\n        fi\n    fi\n}\n# bt下载管理\nbtTools() {\n    if [[ \"${coreInstallType}\" == \"2\" ]]; then\n        echoContent red \"\\n ---> 此功能仅支持Xray-core内核，请等待后续更新\"\n        exit 0\n    fi\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> 未安装，请使用脚本安装\"\n        menu\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : bt下载管理\"\n    echoContent red \"\\n==============================================================\"\n\n    if [[ -f ${configPath}09_routing.json ]] && grep -q bittorrent <${configPath}09_routing.json; then\n        echoContent yellow \"当前状态:已禁止下载BT\"\n    else\n        echoContent yellow \"当前状态:允许下载BT\"\n    fi\n\n    echoContent yellow \"1.禁止下载BT\"\n    echoContent yellow \"2.允许下载BT\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" btStatus\n    if [[ \"${btStatus}\" == \"1\" ]]; then\n\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n\n            unInstallRouting blackhole_out outboundTag bittorrent\n\n            routing=$(jq -r '.routing.rules += [{\"type\":\"field\",\"outboundTag\":\"blackhole_out\",\"protocol\":[\"bittorrent\"]}]' ${configPath}09_routing.json)\n\n            echo \"${routing}\" | jq . >${configPath}09_routing.json\n\n        else\n            cat <<EOF >${configPath}09_routing.json\n{\n    \"routing\":{\n        \"domainStrategy\": \"IPOnDemand\",\n        \"rules\": [\n          {\n            \"type\": \"field\",\n            \"outboundTag\": \"blackhole_out\",\n            \"protocol\": [ \"bittorrent\" ]\n          }\n        ]\n  }\n}\nEOF\n        fi\n\n        installSniffing\n        removeXrayOutbound blackhole_out\n        addXrayOutbound blackhole_out\n\n        echoContent green \" ---> 禁止BT下载\"\n\n    elif [[ \"${btStatus}\" == \"2\" ]]; then\n\n        unInstallSniffing\n\n        unInstallRouting blackhole_out outboundTag bittorrent\n\n        echoContent green \" ---> 允许BT下载\"\n    else\n        echoContent red \" ---> 选择错误\"\n        exit 0\n    fi\n\n    reloadCore\n}\n\n# 域名黑名单\nblacklist() {\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> 未安装，请使用脚本安装\"\n        menu\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : 域名黑名单\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.查看已屏蔽域名\"\n    echoContent yellow \"2.添加域名\"\n    echoContent yellow \"3.屏蔽大陆域名\"\n    echoContent yellow \"4.卸载黑名单\"\n    echoContent red \"==============================================================\"\n\n    read -r -p \"请选择:\" blacklistStatus\n    if [[ \"${blacklistStatus}\" == \"1\" ]]; then\n        jq -r -c '.routing.rules[]|select (.outboundTag==\"blackhole_out\")|.domain' ${configPath}09_routing.json | jq -r\n        exit 0\n    elif [[ \"${blacklistStatus}\" == \"2\" ]]; then\n        echoContent red \"==============================================================\"\n        echoContent yellow \"# 注意事项\\n\"\n        echoContent yellow \"1.规则支持预定义域名列表[https://github.com/v2fly/domain-list-community]\"\n        echoContent yellow \"2.规则支持自定义域名\"\n        echoContent yellow \"3.录入示例:speedtest,facebook,cn,example.com\"\n        echoContent yellow \"4.如果域名在预定义域名列表中存在则使用 geosite:xx，如果不存在则默认使用输入的域名\"\n        echoContent yellow \"5.添加规则为增量配置，不会删除之前设置的内容\\n\"\n        read -r -p \"请按照上面示例录入域名:\" domainList\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            addXrayRouting blackhole_out outboundTag \"${domainList}\"\n            addXrayOutbound blackhole_out\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            addSingBoxRouteRule \"block_domain_outbound\" \"${domainList}\" \"block_domain_route\"\n            addSingBoxOutbound \"block_domain_outbound\"\n            addSingBoxOutbound \"01_direct_outbound\"\n        fi\n        echoContent green \" ---> 添加完毕\"\n\n    elif [[ \"${blacklistStatus}\" == \"3\" ]]; then\n\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            unInstallRouting blackhole_out outboundTag\n\n            addXrayRouting blackhole_out outboundTag \"cn\"\n\n            addXrayOutbound blackhole_out\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n            addSingBoxRouteRule \"cn_block_outbound\" \"cn\" \"cn_block_route\"\n\n            addSingBoxRouteRule \"01_direct_outbound\" \"googleapis.com,googleapis.cn,xn--ngstr-lra8j.com,gstatic.com\" \"cn_01_google_play_route\"\n\n            addSingBoxOutbound \"cn_block_outbound\"\n            addSingBoxOutbound \"01_direct_outbound\"\n        fi\n\n        echoContent green \" ---> 屏蔽大陆域名完毕\"\n\n    elif [[ \"${blacklistStatus}\" == \"4\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            unInstallRouting blackhole_out outboundTag\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            removeSingBoxConfig \"cn_block_route\"\n            removeSingBoxConfig \"cn_block_outbound\"\n\n            removeSingBoxConfig \"cn_01_google_play_route\"\n\n            removeSingBoxConfig \"block_domain_route\"\n            removeSingBoxConfig \"block_domain_outbound\"\n        fi\n        echoContent green \" ---> 域名黑名单删除完毕\"\n    else\n        echoContent red \" ---> 选择错误\"\n        exit 0\n    fi\n    reloadCore\n}\n# 添加routing配置\naddXrayRouting() {\n\n    local tag=$1    # warp-socks\n    local type=$2   # outboundTag/inboundTag\n    local domain=$3 # 域名\n\n    if [[ -z \"${tag}\" || -z \"${type}\" || -z \"${domain}\" ]]; then\n        echoContent red \" ---> 参数错误\"\n        exit 0\n    fi\n\n    local routingRule=\n    if [[ ! -f \"${configPath}09_routing.json\" ]]; then\n        cat <<EOF >${configPath}09_routing.json\n{\n    \"routing\":{\n        \"type\": \"field\",\n        \"rules\": [\n            {\n                \"type\": \"field\",\n                \"domain\": [\n                ],\n            \"outboundTag\": \"${tag}\"\n          }\n        ]\n  }\n}\nEOF\n    fi\n    local routingRule=\n    routingRule=$(jq -r \".routing.rules[]|select(.outboundTag==\\\"${tag}\\\" and (.protocol == null))\" ${configPath}09_routing.json)\n\n    if [[ -z \"${routingRule}\" ]]; then\n        routingRule=\"{\\\"type\\\": \\\"field\\\",\\\"domain\\\": [],\\\"outboundTag\\\": \\\"${tag}\\\"}\"\n    fi\n\n    while read -r line; do\n        if echo \"${routingRule}\" | grep -q \"${line}\"; then\n            echoContent yellow \" ---> ${line}已存在，跳过\"\n        else\n            local geositeStatus\n            geositeStatus=$(curl -s \"https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}\" | jq .message)\n\n            if [[ \"${geositeStatus}\" == \"null\" ]]; then\n                routingRule=$(echo \"${routingRule}\" | jq -r '.domain += [\"geosite:'\"${line}\"'\"]')\n            else\n                routingRule=$(echo \"${routingRule}\" | jq -r '.domain += [\"domain:'\"${line}\"'\"]')\n            fi\n        fi\n    done < <(echo \"${domain}\" | tr ',' '\\n')\n\n    unInstallRouting \"${tag}\" \"${type}\"\n    if ! grep -q \"gstatic.com\" ${configPath}09_routing.json && [[ \"${tag}\" == \"blackhole_out\" ]]; then\n        local routing=\n        routing=$(jq -r \".routing.rules += [{\\\"type\\\": \\\"field\\\",\\\"domain\\\": [\\\"gstatic.com\\\"],\\\"outboundTag\\\": \\\"direct\\\"}]\" ${configPath}09_routing.json)\n        echo \"${routing}\" | jq . >${configPath}09_routing.json\n    fi\n\n    routing=$(jq -r \".routing.rules += [${routingRule}]\" ${configPath}09_routing.json)\n    echo \"${routing}\" | jq . >${configPath}09_routing.json\n}\n# 根据tag卸载Routing\nunInstallRouting() {\n    local tag=$1\n    local type=$2\n    local protocol=$3\n\n    if [[ -f \"${configPath}09_routing.json\" ]]; then\n        local routing=\n        if [[ -n \"${protocol}\" ]]; then\n            routing=$(jq -r \"del(.routing.rules[] | select(.${type} == \\\"${tag}\\\" and (.protocol | index(\\\"${protocol}\\\"))))\" ${configPath}09_routing.json)\n            echo \"${routing}\" | jq . >${configPath}09_routing.json\n        else\n            routing=$(jq -r \"del(.routing.rules[] | select(.${type} == \\\"${tag}\\\" and (.protocol == null )))\" ${configPath}09_routing.json)\n            echo \"${routing}\" | jq . >${configPath}09_routing.json\n        fi\n    fi\n}\n\n# 卸载嗅探\nunInstallSniffing() {\n\n    find ${configPath} -name \"*inbounds.json*\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | while read -r inbound; do\n        if grep -q \"destOverride\" <\"${configPath}${inbound}\"; then\n            sniffing=$(jq -r 'del(.inbounds[0].sniffing)' \"${configPath}${inbound}\")\n            echo \"${sniffing}\" | jq . >\"${configPath}${inbound}\"\n        fi\n    done\n\n}\n\n# 安装嗅探\ninstallSniffing() {\n    readInstallType\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        if [[ -f \"${configPath}02_VLESS_TCP_inbounds.json\" ]]; then\n            if ! grep -q \"destOverride\" <\"${configPath}02_VLESS_TCP_inbounds.json\"; then\n                sniffing=$(jq -r '.inbounds[0].sniffing = {\"enabled\":true,\"destOverride\":[\"http\",\"tls\",\"quic\"]}' \"${configPath}02_VLESS_TCP_inbounds.json\")\n                echo \"${sniffing}\" | jq . >\"${configPath}02_VLESS_TCP_inbounds.json\"\n            fi\n        fi\n    fi\n}\n\n# 读取第三方warp配置\nreadConfigWarpReg() {\n    if [[ ! -f \"/etc/v2ray-agent/warp/config\" ]]; then\n        /etc/v2ray-agent/warp/warp-reg >/etc/v2ray-agent/warp/config\n    fi\n\n    secretKeyWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" private_key | awk '{print $2}')\n\n    addressWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" v6 | awk '{print $2}')\n\n    publicKeyWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" public_key | awk '{print $2}')\n\n    reservedWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" reserved | awk -F \"[:]\" '{print $2}')\n\n}\n# 安装warp-reg工具\ninstallWarpReg() {\n    if [[ ! -f \"/etc/v2ray-agent/warp/warp-reg\" ]]; then\n        echo\n        echoContent yellow \"# 注意事项\"\n        echoContent yellow \"# 依赖第三方程序，请熟知其中风险\"\n        echoContent yellow \"# 项目地址：https://github.com/badafans/warp-reg \\n\"\n\n        read -r -p \"warp-reg未安装，是否安装 ？[y/n]:\" installWarpRegStatus\n\n        if [[ \"${installWarpRegStatus}\" == \"y\" ]]; then\n\n            curl -sLo /etc/v2ray-agent/warp/warp-reg \"https://github.com/badafans/warp-reg/releases/download/v1.0/${warpRegCoreCPUVendor}\"\n            chmod 655 /etc/v2ray-agent/warp/warp-reg\n\n        else\n            echoContent yellow \" ---> 放弃安装\"\n            exit 0\n        fi\n    fi\n}\n\n# 展示warp分流域名\nshowWireGuardDomain() {\n    local type=$1\n    # xray\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n            echoContent yellow \"Xray-core\"\n            jq -r -c '.routing.rules[]|select (.outboundTag==\"wireguard_out_'\"${type}\"'\")|.domain' ${configPath}09_routing.json | jq -r\n        elif [[ ! -f \"${configPath}09_routing.json\" && -f \"${configPath}wireguard_out_${type}.json\" ]]; then\n            echoContent yellow \"Xray-core\"\n            echoContent green \" ---> 已设置warp ${type}全局分流\"\n        else\n            echoContent yellow \" ---> 未安装warp ${type}分流\"\n        fi\n    fi\n\n    # sing-box\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        if [[ -f \"${singBoxConfigPath}wireguard_endpoints_${type}_route.json\" ]]; then\n            echoContent yellow \"sing-box\"\n            jq -r -c '.route.rules[]' \"${singBoxConfigPath}wireguard_endpoints_${type}_route.json\" | jq -r\n        elif [[ ! -f \"${singBoxConfigPath}wireguard_endpoints_${type}_route.json\" && -f \"${singBoxConfigPath}wireguard_endpoints_${type}.json\" ]]; then\n            echoContent yellow \"sing-box\"\n            echoContent green \" ---> 已设置warp ${type}全局分流\"\n        else\n            echoContent yellow \" ---> 未安装warp ${type}分流\"\n        fi\n    fi\n\n}\n\n# 添加WireGuard分流\naddWireGuardRoute() {\n    local type=$1\n    local tag=$2\n    local domainList=$3\n    # xray\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        addXrayRouting \"wireguard_out_${type}\" \"${tag}\" \"${domainList}\"\n        addXrayOutbound \"wireguard_out_${type}\"\n    fi\n    # sing-box\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n        # rule\n        addSingBoxRouteRule \"wireguard_endpoints_${type}\" \"${domainList}\" \"wireguard_endpoints_${type}_route\"\n        # addSingBoxOutbound \"wireguard_out_${type}\" \"wireguard_out\"\n        if [[ -n \"${domainList}\" ]]; then\n            addSingBoxOutbound \"01_direct_outbound\"\n        fi\n\n        # outbound\n        addSingBoxWireGuardEndpoints \"${type}\"\n    fi\n}\n\n# 卸载wireGuard\nunInstallWireGuard() {\n    local type=$1\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        if [[ \"${type}\" == \"IPv4\" ]]; then\n            if [[ ! -f \"${configPath}wireguard_out_IPv6.json\" ]]; then\n                rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1\n            fi\n        elif [[ \"${type}\" == \"IPv6\" ]]; then\n            if [[ ! -f \"${configPath}wireguard_out_IPv4.json\" ]]; then\n                rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1\n            fi\n        fi\n    fi\n\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        if [[ ! -f \"${singBoxConfigPath}wireguard_endpoints_IPv6_route.json\" && ! -f \"${singBoxConfigPath}wireguard_endpoints_IPv4_route.json\" ]]; then\n            rm \"${singBoxConfigPath}wireguard_outbound.json\" >/dev/null 2>&1\n            rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1\n        fi\n    fi\n}\n# 移除WireGuard分流\nremoveWireGuardRoute() {\n    local type=$1\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        unInstallRouting wireguard_out_\"${type}\" outboundTag\n\n        removeXrayOutbound \"wireguard_out_${type}\"\n        if [[ ! -f \"${configPath}IPv4_out.json\" ]]; then\n            addXrayOutbound IPv4_out\n        fi\n    fi\n\n    # sing-box\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        removeSingBoxRouteRule \"wireguard_endpoints_${type}\"\n    fi\n\n    unInstallWireGuard \"${type}\"\n}\n# warp分流-第三方IPv4\nwarpRoutingReg() {\n    local type=$2\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : WARP分流[第三方]\"\n    echoContent red \"==============================================================\"\n\n    echoContent yellow \"1.查看已分流域名\"\n    echoContent yellow \"2.添加域名\"\n    echoContent yellow \"3.设置WARP全局\"\n    echoContent yellow \"4.卸载WARP分流\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" warpStatus\n    installWarpReg\n    readConfigWarpReg\n    local address=\n    if [[ ${type} == \"IPv4\" ]]; then\n        address=\"172.16.0.2/32\"\n    elif [[ ${type} == \"IPv6\" ]]; then\n        address=\"${addressWarpReg}/128\"\n    else\n        echoContent red \" ---> IP获取失败，退出安装\"\n    fi\n\n    if [[ \"${warpStatus}\" == \"1\" ]]; then\n        showWireGuardDomain \"${type}\"\n        exit 0\n    elif [[ \"${warpStatus}\" == \"2\" ]]; then\n        echoContent yellow \"# 注意事项\"\n        echoContent yellow \"# 支持sing-box、Xray-core\"\n        echoContent yellow \"# 使用教程：https://www.v2ray-agent.com/archives/1683226921000 \\n\"\n\n        read -r -p \"请按照上面示例录入域名:\" domainList\n        addWireGuardRoute \"${type}\" outboundTag \"${domainList}\"\n        echoContent green \" ---> 添加完毕\"\n\n    elif [[ \"${warpStatus}\" == \"3\" ]]; then\n\n        echoContent red \"==============================================================\"\n        echoContent yellow \"# 注意事项\\n\"\n        echoContent yellow \"1.会删除所有设置的分流规则\"\n        echoContent yellow \"2.会删除除WARP[第三方]之外的所有出站规则\\n\"\n        read -r -p \"是否确认设置？[y/n]:\" warpOutStatus\n\n        if [[ \"${warpOutStatus}\" == \"y\" ]]; then\n            readConfigWarpReg\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                addXrayOutbound \"wireguard_out_${type}\"\n                if [[ \"${type}\" == \"IPv4\" ]]; then\n                    removeXrayOutbound \"wireguard_out_IPv6\"\n                elif [[ \"${type}\" == \"IPv6\" ]]; then\n                    removeXrayOutbound \"wireguard_out_IPv4\"\n                fi\n\n                removeXrayOutbound IPv4_out\n                removeXrayOutbound IPv6_out\n                removeXrayOutbound z_direct_outbound\n                removeXrayOutbound blackhole_out\n                removeXrayOutbound socks5_outbound\n\n                rm ${configPath}09_routing.json >/dev/null 2>&1\n            fi\n\n            if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n                removeSingBoxConfig IPv4_out\n                removeSingBoxConfig IPv6_out\n                removeSingBoxConfig 01_direct_outbound\n\n                # 删除所有分流规则\n                removeSingBoxConfig wireguard_endpoints_IPv4_route\n                removeSingBoxConfig wireguard_endpoints_IPv6_route\n\n                removeSingBoxConfig IPv6_route\n                removeSingBoxConfig socks5_02_inbound_route\n\n                addSingBoxWireGuardEndpoints \"${type}\"\n                addWireGuardRoute \"${type}\" outboundTag \"\"\n                if [[ \"${type}\" == \"IPv4\" ]]; then\n                    removeSingBoxConfig wireguard_endpoints_IPv6\n                else\n                    removeSingBoxConfig wireguard_endpoints_IPv4\n                fi\n\n                # outbound\n                # addSingBoxOutbound \"wireguard_out_${type}\" \"wireguard_out\"\n\n            fi\n\n            echoContent green \" ---> WARP全局出站设置完毕\"\n        else\n            echoContent green \" ---> 放弃设置\"\n            exit 0\n        fi\n\n    elif [[ \"${warpStatus}\" == \"4\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            unInstallRouting \"wireguard_out_${type}\" outboundTag\n\n            removeXrayOutbound \"wireguard_out_${type}\"\n            addXrayOutbound \"z_direct_outbound\"\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            removeSingBoxConfig \"wireguard_endpoints_${type}_route\"\n\n            removeSingBoxConfig \"wireguard_endpoints_${type}\"\n            addSingBoxOutbound \"01_direct_outbound\"\n        fi\n\n        echoContent green \" ---> 卸载WARP ${type}分流完毕\"\n    else\n\n        echoContent red \" ---> 选择错误\"\n        exit 0\n    fi\n    reloadCore\n}\n\n# 分流工具\nroutingToolsMenu() {\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : 分流工具\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\"\n    echoContent yellow \"# 用于服务端的流量分流，可用于解锁ChatGPT、流媒体等相关内容\\n\"\n\n    echoContent yellow \"1.WARP分流【第三方 IPv4】\"\n    echoContent yellow \"2.WARP分流【第三方 IPv6】\"\n    echoContent yellow \"3.IPv6分流\"\n    echoContent yellow \"4.Socks5分流【替换任意门分流】\"\n    echoContent yellow \"5.DNS分流\"\n    #    echoContent yellow \"6.VMess+WS+TLS分流\"\n    echoContent yellow \"7.SNI反向代理分流\"\n\n    read -r -p \"请选择:\" selectType\n\n    case ${selectType} in\n    1)\n        warpRoutingReg 1 IPv4\n        ;;\n    2)\n        warpRoutingReg 1 IPv6\n        ;;\n    3)\n        ipv6Routing 1\n        ;;\n    4)\n        socks5Routing\n        ;;\n    5)\n        dnsRouting 1\n        ;;\n        #    6)\n        #        if [[ -n \"${singBoxConfigPath}\" ]]; then\n        #            echoContent red \"\\n ---> 此功能不支持Hysteria2、Tuic\"\n        #        fi\n        #        vmessWSRouting 1\n        #        ;;\n    7)\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            echoContent red \"\\n ---> 此功能不支持Hysteria2、Tuic\"\n        fi\n        sniRouting 1\n        ;;\n    esac\n\n}\n\n# VMess+WS+TLS 分流\nvmessWSRouting() {\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : VMess+WS+TLS 分流\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\"\n    echoContent yellow \"# 使用教程：https://www.v2ray-agent.com/archives/1683226921000 \\n\"\n\n    echoContent yellow \"1.添加出站\"\n    echoContent yellow \"2.卸载\"\n    read -r -p \"请选择:\" selectType\n\n    case ${selectType} in\n    1)\n        setVMessWSRoutingOutbounds\n        ;;\n    2)\n        removeVMessWSRouting\n        ;;\n    esac\n}\n# Socks5分流\nsocks5Routing() {\n    if [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \" ---> 未安装任意协议，请使用 1.安装 或者 2.任意组合安装 进行安装后使用\"\n        exit 0\n    fi\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : Socks5分流\"\n    echoContent red \"\\n==============================================================\"\n    echoContent red \"# 注意事项\"\n    echoContent yellow \"# 流量明文访问\"\n\n    echoContent yellow \"# 仅限正常网络环境下设备间流量转发，禁止用于代理访问。\"\n    echoContent yellow \"# 使用教程：https://www.v2ray-agent.com/archives/1683226921000#heading-5 \\n\"\n\n    echoContent yellow \"1.Socks5出站\"\n    echoContent yellow \"2.Socks5入站\"\n    echoContent yellow \"3.卸载\"\n    read -r -p \"请选择:\" selectType\n\n    case ${selectType} in\n    1)\n        socks5OutboundRoutingMenu\n        ;;\n    2)\n        socks5InboundRoutingMenu\n        ;;\n    3)\n        removeSocks5Routing\n        ;;\n    esac\n}\n# Socks5入站菜单\nsocks5InboundRoutingMenu() {\n    readInstallType\n    echoContent skyBlue \"\\n功能 1/1 : Socks5入站\"\n    echoContent red \"\\n==============================================================\"\n\n    echoContent yellow \"1.安装Socks5入站\"\n    echoContent yellow \"2.查看分流规则\"\n    echoContent yellow \"3.添加分流规则\"\n    echoContent yellow \"4.查看入站配置\"\n    read -r -p \"请选择:\" selectType\n    case ${selectType} in\n    1)\n        totalProgress=1\n        installSingBox 1\n        installSingBoxService 1\n        setSocks5Inbound\n        setSocks5InboundRouting\n        reloadCore\n        socks5InboundRoutingMenu\n        ;;\n    2)\n        showSingBoxRoutingRules socks5_02_inbound_route\n        socks5InboundRoutingMenu\n        ;;\n    3)\n        setSocks5InboundRouting addRules\n        reloadCore\n        socks5InboundRoutingMenu\n        ;;\n    4)\n        if [[ -f \"${singBoxConfigPath}20_socks5_inbounds.json\" ]]; then\n            echoContent yellow \"\\n ---> 下列内容需要配置到其他机器的出站，请不要进行代理行为\\n\"\n            echoContent green \" 端口：$(jq .inbounds[0].listen_port ${singBoxConfigPath}20_socks5_inbounds.json)\"\n            echoContent green \" 用户名称：$(jq -r .inbounds[0].users[0].username ${singBoxConfigPath}20_socks5_inbounds.json)\"\n            echoContent green \" 用户密码：$(jq -r .inbounds[0].users[0].password ${singBoxConfigPath}20_socks5_inbounds.json)\"\n        else\n            echoContent red \" ---> 未安装相应功能\"\n            socks5InboundRoutingMenu\n        fi\n        ;;\n    esac\n\n}\n\n# Socks5出站菜单\nsocks5OutboundRoutingMenu() {\n    echoContent skyBlue \"\\n功能 1/1 : Socks5出站\"\n    echoContent red \"\\n==============================================================\"\n\n    echoContent yellow \"1.安装Socks5出站\"\n    echoContent yellow \"2.设置Socks5全局转发\"\n    echoContent yellow \"3.查看分流规则\"\n    echoContent yellow \"4.添加分流规则\"\n    read -r -p \"请选择:\" selectType\n    case ${selectType} in\n    1)\n        setSocks5Outbound\n        setSocks5OutboundRouting\n        reloadCore\n        socks5OutboundRoutingMenu\n        ;;\n    2)\n        setSocks5Outbound\n        setSocks5OutboundRoutingAll\n        reloadCore\n        socks5OutboundRoutingMenu\n        ;;\n    3)\n        showSingBoxRoutingRules socks5_01_outbound_route\n        showXrayRoutingRules socks5_outbound\n        socks5OutboundRoutingMenu\n        ;;\n    4)\n        setSocks5OutboundRouting addRules\n        reloadCore\n        socks5OutboundRoutingMenu\n        ;;\n    esac\n\n}\n\n# socks5全局\nsetSocks5OutboundRoutingAll() {\n\n    echoContent red \"==============================================================\"\n    echoContent yellow \"# 注意事项\\n\"\n    echoContent yellow \"1.会删除所有已经设置的分流规则，包括其他分流（warp、IPv6等）\"\n    echoContent yellow \"2.会删除Socks5之外的所有出站规则\\n\"\n    read -r -p \"是否确认设置？[y/n]:\" socksOutStatus\n\n    if [[ \"${socksOutStatus}\" == \"y\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            removeXrayOutbound IPv4_out\n            removeXrayOutbound IPv6_out\n            removeXrayOutbound z_direct_outbound\n            removeXrayOutbound blackhole_out\n            removeXrayOutbound wireguard_out_IPv4\n            removeXrayOutbound wireguard_out_IPv6\n\n            rm ${configPath}09_routing.json >/dev/null 2>&1\n        fi\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n\n            removeSingBoxConfig IPv4_out\n            removeSingBoxConfig IPv6_out\n\n            removeSingBoxConfig wireguard_endpoints_IPv4_route\n            removeSingBoxConfig wireguard_endpoints_IPv6_route\n            removeSingBoxConfig wireguard_endpoints_IPv4\n            removeSingBoxConfig wireguard_endpoints_IPv6\n\n            removeSingBoxConfig socks5_01_outbound_route\n            removeSingBoxConfig 01_direct_outbound\n        fi\n\n        echoContent green \" ---> Socks5全局出站设置完毕\"\n    fi\n}\n# socks5 分流规则\nshowSingBoxRoutingRules() {\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        if [[ -f \"${singBoxConfigPath}$1.json\" ]]; then\n            jq .route.rules \"${singBoxConfigPath}$1.json\"\n        elif [[ \"$1\" == \"socks5_01_outbound_route\" && -f \"${singBoxConfigPath}socks5_outbound.json\" ]]; then\n            echoContent yellow \"已安装 sing-box socks5全局出站分流\"\n            echoContent yellow \"\\n出站分流配置：\"\n            echoContent skyBlue \"$(jq .outbounds[0] ${singBoxConfigPath}socks5_outbound.json)\"\n        elif [[ \"$1\" == \"socks5_02_inbound_route\" && -f \"${singBoxConfigPath}20_socks5_inbounds.json\" ]]; then\n            echoContent yellow \"已安装 sing-box socks5全局入站分流\"\n            echoContent yellow \"\\n出站分流配置：\"\n            echoContent skyBlue \"$(jq .outbounds[0] ${singBoxConfigPath}socks5_outbound.json)\"\n        fi\n    fi\n}\n\n# xray内核分流规则\nshowXrayRoutingRules() {\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n            jq \".routing.rules[]|select(.outboundTag==\\\"$1\\\")\" \"${configPath}09_routing.json\"\n\n            echoContent yellow \"\\n已安装 xray-core socks5全局出站分流\"\n            echoContent yellow \"\\n出站分流配置：\"\n            echoContent skyBlue \"$(jq .outbounds[0].settings.servers[0] ${configPath}socks5_outbound.json)\"\n\n        elif [[ \"$1\" == \"socks5_outbound\" && -f \"${configPath}socks5_outbound.json\" ]]; then\n            echoContent yellow \"\\n已安装 xray-core socks5全局出站分流\"\n            echoContent yellow \"\\n出站分流配置：\"\n            echoContent skyBlue \"$(jq .outbounds[0].settings.servers[0] ${configPath}socks5_outbound.json)\"\n        fi\n    fi\n}\n\n# 卸载Socks5分流\nremoveSocks5Routing() {\n    echoContent skyBlue \"\\n功能 1/1 : 卸载Socks5分流\"\n    echoContent red \"\\n==============================================================\"\n\n    echoContent yellow \"1.卸载Socks5出站\"\n    echoContent yellow \"2.卸载Socks5入站\"\n    echoContent yellow \"3.卸载全部\"\n    read -r -p \"请选择:\" unInstallSocks5RoutingStatus\n    if [[ \"${unInstallSocks5RoutingStatus}\" == \"1\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            removeXrayOutbound socks5_outbound\n            unInstallRouting socks5_outbound outboundTag\n            addXrayOutbound z_direct_outbound\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            removeSingBoxConfig socks5_outbound\n            removeSingBoxConfig socks5_01_outbound_route\n            addSingBoxOutbound 01_direct_outbound\n        fi\n\n    elif [[ \"${unInstallSocks5RoutingStatus}\" == \"2\" ]]; then\n\n        removeSingBoxConfig 20_socks5_inbounds\n        removeSingBoxConfig socks5_02_inbound_route\n\n        handleSingBox stop\n    elif [[ \"${unInstallSocks5RoutingStatus}\" == \"3\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            removeXrayOutbound socks5_outbound\n            unInstallRouting socks5_outbound outboundTag\n            addXrayOutbound z_direct_outbound\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            removeSingBoxConfig socks5_outbound\n            removeSingBoxConfig socks5_01_outbound_route\n            removeSingBoxConfig 20_socks5_inbounds\n            removeSingBoxConfig socks5_02_inbound_route\n            addSingBoxOutbound 01_direct_outbound\n        fi\n\n        handleSingBox stop\n    else\n        echoContent red \" ---> 选择错误\"\n        exit 0\n    fi\n    echoContent green \" ---> 卸载完毕\"\n    reloadCore\n}\n# Socks5入站\nsetSocks5Inbound() {\n\n    echoContent yellow \"\\n==================== 配置 Socks5 入站(解锁机、落地机) =====================\\n\"\n    echoContent skyBlue \"\\n开始配置Socks5协议入站端口\"\n    echo\n    mapfile -t result < <(initSingBoxPort \"${singBoxSocks5Port}\")\n    echoContent green \"\\n ---> 入站Socks5端口：${result[-1]}\"\n    echoContent green \"\\n ---> 此端口需要配置到其他机器出站，请不要进行代理行为\"\n\n    echoContent yellow \"\\n请输入自定义UUID[需合法]，[回车]随机UUID\"\n    read -r -p 'UUID:' socks5RoutingUUID\n    if [[ -z \"${socks5RoutingUUID}\" ]]; then\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            socks5RoutingUUID=$(/etc/v2ray-agent/xray/xray uuid)\n        elif [[ -n \"${singBoxConfigPath}\" ]]; then\n            socks5RoutingUUID=$(/etc/v2ray-agent/sing-box/sing-box generate uuid)\n        fi\n    fi\n    echo\n    echoContent green \"用户名称：${socks5RoutingUUID}\"\n    echoContent green \"用户密码：${socks5RoutingUUID}\"\n\n    echoContent yellow \"\\n请选择分流域名DNS解析类型\"\n    echoContent yellow \"# 注意事项：需要保证vps支持相应的DNS解析\"\n    echoContent yellow \"1.IPv4[回车默认]\"\n    echoContent yellow \"2.IPv6\"\n\n    read -r -p 'IP类型:' socks5InboundDomainStrategyStatus\n    local domainStrategy=\n    if [[ -z \"${socks5InboundDomainStrategyStatus}\" || \"${socks5InboundDomainStrategyStatus}\" == \"1\" ]]; then\n        domainStrategy=\"ipv4_only\"\n    elif [[ \"${socks5InboundDomainStrategyStatus}\" == \"2\" ]]; then\n        domainStrategy=\"ipv6_only\"\n    else\n        echoContent red \" ---> 选择类型错误\"\n        exit 0\n    fi\n    cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/20_socks5_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"type\": \"socks\",\n          \"listen\":\"::\",\n          \"listen_port\":${result[-1]},\n          \"tag\":\"socks5_inbound\",\n          \"users\":[\n            {\n                  \"username\": \"${socks5RoutingUUID}\",\n                  \"password\": \"${socks5RoutingUUID}\"\n            }\n          ],\n          \"domain_strategy\":\"${domainStrategy}\"\n        }\n    ]\n}\nEOF\n\n}\n\n# 初始化sing-box rule配置\ninitSingBoxRules() {\n    local domainRules=[]\n    local ruleSet=[]\n    while read -r line; do\n        local geositeStatus\n        geositeStatus=$(curl -s \"https://api.github.com/repos/SagerNet/sing-geosite/contents/geosite-${line}.srs?ref=rule-set\" | jq .message)\n\n        if [[ \"${geositeStatus}\" == \"null\" ]]; then\n            ruleSet=$(echo \"${ruleSet}\" | jq -r \". += [{\\\"tag\\\":\\\"${line}_$2\\\",\\\"type\\\":\\\"remote\\\",\\\"format\\\":\\\"binary\\\",\\\"url\\\":\\\"https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-${line}.srs\\\",\\\"download_detour\\\":\\\"01_direct_outbound\\\"}]\")\n        else\n            domainRules=$(echo \"${domainRules}\" | jq -r \". += [\\\"^([a-zA-Z0-9_-]+\\\\\\.)*${line//./\\\\\\\\.}\\\"]\")\n        fi\n    done < <(echo \"$1\" | tr ',' '\\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\\n')\n    echo \"{ \\\"domainRules\\\":${domainRules},\\\"ruleSet\\\":${ruleSet}}\"\n}\n\n# socks5 inbound routing规则\nsetSocks5InboundRouting() {\n\n    singBoxConfigPath=/etc/v2ray-agent/sing-box/conf/config/\n\n    if [[ \"$1\" == \"addRules\" && ! -f \"${singBoxConfigPath}socks5_02_inbound_route.json\" && ! -f \"${configPath}09_routing.json\" ]]; then\n        echoContent red \" ---> 请安装入站分流后再添加分流规则\"\n        echoContent red \" ---> 如已选择允许所有网站，请重新安装分流后设置规则\"\n        exit 0\n    fi\n    local socks5InboundRoutingIPs=\n    if [[ \"$1\" == \"addRules\" ]]; then\n        socks5InboundRoutingIPs=$(jq .route.rules[0].source_ip_cidr \"${singBoxConfigPath}socks5_02_inbound_route.json\")\n    else\n        echoContent red \"==============================================================\"\n        echoContent skyBlue \"请输入允许访问的IP地址，多个IP英文逗号隔开。例如:1.1.1.1,2.2.2.2\\n\"\n        read -r -p \"IP:\" socks5InboundRoutingIPs\n\n        if [[ -z \"${socks5InboundRoutingIPs}\" ]]; then\n            echoContent red \" ---> IP不可为空\"\n            exit 0\n        fi\n        socks5InboundRoutingIPs=$(echo \"\\\"${socks5InboundRoutingIPs}\"\\\" | jq -c '.|split(\",\")')\n    fi\n\n    echoContent red \"==============================================================\"\n    echoContent skyBlue \"请输入要分流的域名\\n\"\n    echoContent yellow \"支持Xray-core geosite匹配，支持sing-box1.8+ rule_set匹配\\n\"\n    echoContent yellow \"非增量添加，会替换原有规则\\n\"\n    echoContent yellow \"当输入的规则匹配到geosite或者rule_set后会使用相应的规则\\n\"\n    echoContent yellow \"如无法匹配则，则使用domain精确匹配\\n\"\n\n    read -r -p \"是否允许所有网站？请选择[y/n]:\" socks5InboundRoutingDomainStatus\n    if [[ \"${socks5InboundRoutingDomainStatus}\" == \"y\" ]]; then\n        addSingBoxRouteRule \"01_direct_outbound\" \"\" \"socks5_02_inbound_route\"\n        local route=\n        route=$(jq \".route.rules[0].inbound = [\\\"socks5_inbound\\\"]\" \"${singBoxConfigPath}socks5_02_inbound_route.json\")\n        route=$(echo \"${route}\" | jq \".route.rules[0].source_ip_cidr=${socks5InboundRoutingIPs}\")\n        echo \"${route}\" | jq . >\"${singBoxConfigPath}socks5_02_inbound_route.json\"\n\n        addSingBoxOutbound block\n        addSingBoxOutbound \"01_direct_outbound\"\n    else\n        echoContent yellow \"录入示例:netflix,openai,v2ray-agent.com\\n\"\n        read -r -p \"域名:\" socks5InboundRoutingDomain\n        if [[ -z \"${socks5InboundRoutingDomain}\" ]]; then\n            echoContent red \" ---> 域名不可为空\"\n            exit 0\n        fi\n        addSingBoxRouteRule \"01_direct_outbound\" \"${socks5InboundRoutingDomain}\" \"socks5_02_inbound_route\"\n        local route=\n        route=$(jq \".route.rules[0].inbound = [\\\"socks5_inbound\\\"]\" \"${singBoxConfigPath}socks5_02_inbound_route.json\")\n        route=$(echo \"${route}\" | jq \".route.rules[0].source_ip_cidr=${socks5InboundRoutingIPs}\")\n        echo \"${route}\" | jq . >\"${singBoxConfigPath}socks5_02_inbound_route.json\"\n\n        addSingBoxOutbound block\n        addSingBoxOutbound \"01_direct_outbound\"\n    fi\n\n}\n\n# socks5 出站\nsetSocks5Outbound() {\n\n    echoContent yellow \"\\n==================== 配置 Socks5 出站（转发机、代理机） =====================\\n\"\n    echo\n    read -r -p \"请输入落地机IP地址:\" socks5RoutingOutboundIP\n    if [[ -z \"${socks5RoutingOutboundIP}\" ]]; then\n        echoContent red \" ---> IP不可为空\"\n        exit 0\n    fi\n    echo\n    read -r -p \"请输入落地机端口:\" socks5RoutingOutboundPort\n    if [[ -z \"${socks5RoutingOutboundPort}\" ]]; then\n        echoContent red \" ---> 端口不可为空\"\n        exit 0\n    fi\n    echo\n    read -r -p \"请输入用户名:\" socks5RoutingOutboundUserName\n    if [[ -z \"${socks5RoutingOutboundUserName}\" ]]; then\n        echoContent red \" ---> 用户名不可为空\"\n        exit 0\n    fi\n    echo\n    read -r -p \"请输入用户密码:\" socks5RoutingOutboundPassword\n    if [[ -z \"${socks5RoutingOutboundPassword}\" ]]; then\n        echoContent red \" ---> 用户密码不可为空\"\n        exit 0\n    fi\n    echo\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        cat <<EOF >\"${singBoxConfigPath}socks5_outbound.json\"\n{\n    \"outbounds\":[\n        {\n          \"type\": \"socks\",\n          \"tag\":\"socks5_outbound\",\n          \"server\": \"${socks5RoutingOutboundIP}\",\n          \"server_port\": ${socks5RoutingOutboundPort},\n          \"version\": \"5\",\n          \"username\":\"${socks5RoutingOutboundUserName}\",\n          \"password\":\"${socks5RoutingOutboundPassword}\"\n        }\n    ]\n}\nEOF\n    fi\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        addXrayOutbound socks5_outbound\n    fi\n}\n\n# socks5 outbound routing规则\nsetSocks5OutboundRouting() {\n\n    if [[ \"$1\" == \"addRules\" && ! -f \"${singBoxConfigPath}socks5_01_outbound_route.json\" && ! -f \"${configPath}09_routing.json\" ]]; then\n        echoContent red \" ---> 请安装出站分流后再添加分流规则\"\n        exit 0\n    fi\n\n    echoContent red \"==============================================================\"\n    echoContent skyBlue \"请输入要分流的域名\\n\"\n    echoContent yellow \"支持Xray-core geosite匹配，支持sing-box1.8+ rule_set匹配\\n\"\n    echoContent yellow \"非增量添加，会替换原有规则\\n\"\n    echoContent yellow \"当输入的规则匹配到geosite或者rule_set后会使用相应的规则\\n\"\n    echoContent yellow \"如无法匹配则，则使用domain精确匹配\\n\"\n    echoContent yellow \"录入示例:netflix,openai,v2ray-agent.com\\n\"\n    read -r -p \"域名:\" socks5RoutingOutboundDomain\n    if [[ -z \"${socks5RoutingOutboundDomain}\" ]]; then\n        echoContent red \" ---> IP不可为空\"\n        exit 0\n    fi\n    addSingBoxRouteRule \"socks5_outbound\" \"${socks5RoutingOutboundDomain}\" \"socks5_01_outbound_route\"\n    addSingBoxOutbound \"01_direct_outbound\"\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        unInstallRouting \"socks5_outbound\" \"outboundTag\"\n        local domainRules=[]\n        while read -r line; do\n            if echo \"${routingRule}\" | grep -q \"${line}\"; then\n                echoContent yellow \" ---> ${line}已存在，跳过\"\n            else\n                local geositeStatus\n                geositeStatus=$(curl -s \"https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}\" | jq .message)\n\n                if [[ \"${geositeStatus}\" == \"null\" ]]; then\n                    domainRules=$(echo \"${domainRules}\" | jq -r \". += [\\\"geosite:${line}\\\"]\")\n                else\n                    domainRules=$(echo \"${domainRules}\" | jq -r \". += [\\\"domain:${line}\\\"]\")\n                fi\n            fi\n        done < <(echo \"${socks5RoutingOutboundDomain}\" | tr ',' '\\n')\n        if [[ ! -f \"${configPath}09_routing.json\" ]]; then\n            cat <<EOF >${configPath}09_routing.json\n{\n    \"routing\":{\n        \"rules\": []\n  }\n}\nEOF\n        fi\n        routing=$(jq -r \".routing.rules += [{\\\"type\\\": \\\"field\\\",\\\"domain\\\": ${domainRules},\\\"outboundTag\\\": \\\"socks5_outbound\\\"}]\" ${configPath}09_routing.json)\n        echo \"${routing}\" | jq . >${configPath}09_routing.json\n    fi\n}\n\n# 设置VMess+WS+TLS【仅出站】\nsetVMessWSRoutingOutbounds() {\n    read -r -p \"请输入VMess+WS+TLS的地址:\" setVMessWSTLSAddress\n    echoContent red \"==============================================================\"\n    echoContent yellow \"录入示例:netflix,openai\\n\"\n    read -r -p \"请按照上面示例录入域名:\" domainList\n\n    if [[ -z ${domainList} ]]; then\n        echoContent red \" ---> 域名不可为空\"\n        setVMessWSRoutingOutbounds\n    fi\n\n    if [[ -n \"${setVMessWSTLSAddress}\" ]]; then\n        removeXrayOutbound VMess-out\n\n        echo\n        read -r -p \"请输入VMess+WS+TLS的端口:\" setVMessWSTLSPort\n        echo\n        if [[ -z \"${setVMessWSTLSPort}\" ]]; then\n            echoContent red \" ---> 端口不可为空\"\n        fi\n\n        read -r -p \"请输入VMess+WS+TLS的UUID:\" setVMessWSTLSUUID\n        echo\n        if [[ -z \"${setVMessWSTLSUUID}\" ]]; then\n            echoContent red \" ---> UUID不可为空\"\n        fi\n\n        read -r -p \"请输入VMess+WS+TLS的Path路径:\" setVMessWSTLSPath\n        echo\n        if [[ -z \"${setVMessWSTLSPath}\" ]]; then\n            echoContent red \" ---> 路径不可为空\"\n        elif ! echo \"${setVMessWSTLSPath}\" | grep -q \"/\"; then\n            setVMessWSTLSPath=\"/${setVMessWSTLSPath}\"\n        fi\n        addXrayOutbound \"VMess-out\"\n        addXrayRouting VMess-out outboundTag \"${domainList}\"\n        reloadCore\n        echoContent green \" ---> 添加分流成功\"\n        exit 0\n    fi\n    echoContent red \" ---> 地址不可为空\"\n    setVMessWSRoutingOutbounds\n}\n\n# 移除VMess+WS+TLS分流\nremoveVMessWSRouting() {\n\n    removeXrayOutbound VMess-out\n    unInstallRouting VMess-out outboundTag\n\n    reloadCore\n    echoContent green \" ---> 卸载成功\"\n}\n\n# 重启核心\nreloadCore() {\n    readInstallType\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        handleXray stop\n        handleXray start\n    fi\n    if echo \"${currentInstallProtocolType}\" | grep -q \",20,\" || [[ \"${coreInstallType}\" == \"2\" || -n \"${singBoxConfigPath}\" ]]; then\n        handleSingBox stop\n        handleSingBox start\n    fi\n}\n\n# dns分流\ndnsRouting() {\n\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> 未安装，请使用脚本安装\"\n        menu\n        exit 0\n    fi\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : DNS分流\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\"\n    echoContent yellow \"# 使用教程：https://www.v2ray-agent.com/archives/1683226921000 \\n\"\n\n    echoContent yellow \"1.添加\"\n    echoContent yellow \"2.卸载\"\n    read -r -p \"请选择:\" selectType\n\n    case ${selectType} in\n    1)\n        setUnlockDNS\n        ;;\n    2)\n        removeUnlockDNS\n        ;;\n    esac\n}\n\n# SNI反向代理分流\nsniRouting() {\n\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> 未安装，请使用脚本安装\"\n        menu\n        exit 0\n    fi\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : SNI反向代理分流\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\"\n    echoContent yellow \"# 使用教程：https://www.v2ray-agent.com/archives/1683226921000 \\n\"\n    echoContent yellow \"# sing-box不支持规则集，仅支持指定域名。\\n\"\n\n    echoContent yellow \"1.添加\"\n    echoContent yellow \"2.卸载\"\n    read -r -p \"请选择:\" selectType\n\n    case ${selectType} in\n    1)\n        setUnlockSNI\n        ;;\n    2)\n        removeUnlockSNI\n        ;;\n    esac\n}\n# 设置SNI分流\nsetUnlockSNI() {\n    read -r -p \"请输入分流的SNI IP:\" setSNIP\n    if [[ -n ${setSNIP} ]]; then\n        echoContent red \"==============================================================\"\n\n        if [[ \"${coreInstallType}\" == 1 ]]; then\n            echoContent yellow \"录入示例:netflix,disney,hulu\"\n            read -r -p \"请按照上面示例录入域名:\" xrayDomainList\n            local hosts={}\n            while read -r domain; do\n                hosts=$(echo \"${hosts}\" | jq -r \".\\\"geosite:${domain}\\\"=\\\"${setSNIP}\\\"\")\n            done < <(echo \"${xrayDomainList}\" | tr ',' '\\n')\n            cat <<EOF >${configPath}11_dns.json\n{\n    \"dns\": {\n        \"hosts\":${hosts},\n        \"servers\": [\n            \"8.8.8.8\",\n            \"1.1.1.1\"\n        ]\n    }\n}\nEOF\n        fi\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            echoContent yellow \"录入示例:www.netflix.com,www.google.com\"\n            read -r -p \"请按照上面示例录入域名:\" singboxDomainList\n            addSingBoxDNSConfig \"${setSNIP}\" \"${singboxDomainList}\" \"predefined\"\n        fi\n        echoContent yellow \" ---> SNI反向代理分流成功\"\n        reloadCore\n    else\n        echoContent red \" ---> SNI IP不可为空\"\n    fi\n    exit 0\n}\n\n# 添加xray dns 配置\naddXrayDNSConfig() {\n    local ip=$1\n    local domainList=$2\n    local domains=[]\n    while read -r line; do\n        local geositeStatus\n        geositeStatus=$(curl -s \"https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}\" | jq .message)\n\n        if [[ \"${geositeStatus}\" == \"null\" ]]; then\n            domains=$(echo \"${domains}\" | jq -r '. += [\"geosite:'\"${line}\"'\"]')\n        else\n            domains=$(echo \"${domains}\" | jq -r '. += [\"domain:'\"${line}\"'\"]')\n        fi\n    done < <(echo \"${domainList}\" | tr ',' '\\n')\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        cat <<EOF >${configPath}11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n            {\n                \"address\": \"${ip}\",\n                \"port\": 53,\n                \"domains\": ${domains}\n            },\n        \"localhost\"\n        ]\n    }\n}\nEOF\n    fi\n}\n\n# 添加sing-box dns配置\naddSingBoxDNSConfig() {\n    local ip=$1\n    local domainList=$2\n    local actionType=$3\n\n    local rules=\n    rules=$(initSingBoxRules \"${domainList}\" \"dns\")\n    # domain精确匹配规则\n    local domainRules=\n    domainRules=$(echo \"${rules}\" | jq .domainRules)\n\n    # ruleSet规则集\n    local ruleSet=\n    ruleSet=$(echo \"${rules}\" | jq .ruleSet)\n\n    # ruleSet规则tag\n    local ruleSetTag=[]\n    if [[ \"$(echo \"${ruleSet}\" | jq '.|length')\" != \"0\" ]]; then\n        ruleSetTag=$(echo \"${ruleSet}\" | jq '.|map(.tag)')\n    fi\n    if [[ -n \"${singBoxConfigPath}\" ]]; then\n        if [[ \"${actionType}\" == \"predefined\" ]]; then\n            local predefined={}\n            while read -r line; do\n                predefined=$(echo \"${predefined}\" | jq \".\\\"${line}\\\"=\\\"${ip}\\\"\")\n            done < <(echo \"${domainList}\" | tr ',' '\\n' | grep -v '^$' | sort -n | uniq | paste -sd ',' | tr ',' '\\n')\n\n            cat <<EOF >\"${singBoxConfigPath}dns.json\"\n{\n  \"dns\": {\n    \"servers\": [\n        {\n            \"tag\": \"local\",\n            \"type\": \"local\"\n        },\n        {\n            \"tag\": \"hosts\",\n            \"type\": \"hosts\",\n            \"predefined\": ${predefined}\n        }\n    ],\n    \"rules\": [\n        {\n            \"domain_regex\":${domainRules},\n            \"server\":\"hosts\"\n        }\n    ]\n  }\n}\nEOF\n        else\n            cat <<EOF >\"${singBoxConfigPath}dns.json\"\n{\n  \"dns\": {\n    \"servers\": [\n      {\n        \"tag\": \"local\",\n        \"type\": \"local\"\n      },\n      {\n        \"tag\": \"dnsRouting\",\n        \"type\": \"udp\",\n        \"server\": \"${ip}\"\n      }\n    ],\n    \"rules\": [\n      {\n        \"rule_set\": ${ruleSetTag},\n        \"domain_regex\": ${domainRules},\n        \"server\":\"dnsRouting\"\n      }\n    ]\n  },\n  \"route\":{\n    \"rule_set\":${ruleSet}\n  }\n}\nEOF\n        fi\n    fi\n}\n# 设置dns\nsetUnlockDNS() {\n    read -r -p \"请输入分流的DNS:\" setDNS\n    if [[ -n ${setDNS} ]]; then\n        echoContent red \"==============================================================\"\n        echoContent yellow \"录入示例:netflix,disney,hulu\"\n        read -r -p \"请按照上面示例录入域名:\" domainList\n\n        if [[ \"${coreInstallType}\" == \"1\" ]]; then\n            addXrayDNSConfig \"${setDNS}\" \"${domainList}\"\n        fi\n\n        if [[ -n \"${singBoxConfigPath}\" ]]; then\n            addSingBoxOutbound 01_direct_outbound\n            addSingBoxDNSConfig \"${setDNS}\" \"${domainList}\"\n        fi\n\n        reloadCore\n\n        echoContent yellow \"\\n ---> 如还无法观看可以尝试以下两种方案\"\n        echoContent yellow \" 1.重启vps\"\n        echoContent yellow \" 2.卸载dns解锁后，修改本地的[/etc/resolv.conf]DNS设置并重启vps\\n\"\n    else\n        echoContent red \" ---> dns不可为空\"\n    fi\n    exit 0\n}\n\n# 移除 DNS分流\nremoveUnlockDNS() {\n    if [[ \"${coreInstallType}\" == \"1\" && -f \"${configPath}11_dns.json\" ]]; then\n        cat <<EOF >${configPath}11_dns.json\n{\n\t\"dns\": {\n\t\t\"servers\": [\n\t\t\t\"localhost\"\n\t\t]\n\t}\n}\nEOF\n    fi\n\n    if [[ \"${coreInstallType}\" == \"2\" && -f \"${singBoxConfigPath}dns.json\" ]]; then\n        cat <<EOF >${singBoxConfigPath}dns.json\n{\n    \"dns\": {\n        \"servers\":[\n            {\n                \"type\":\"local\"\n            }\n        ]\n    }\n}\nEOF\n    fi\n\n    reloadCore\n\n    echoContent green \" ---> 卸载成功\"\n\n    exit 0\n}\n\n# 移除SNI分流\nremoveUnlockSNI() {\n    if [[ \"${coreInstallType}\" == 1 ]]; then\n        cat <<EOF >${configPath}11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n            \"localhost\"\n        ]\n    }\n}\nEOF\n    fi\n\n    if [[ \"${coreInstallType}\" == \"2\" && -f \"${singBoxConfigPath}dns.json\" ]]; then\n        cat <<EOF >${singBoxConfigPath}dns.json\n{\n    \"dns\": {\n        \"servers\":[\n            {\n                \"type\":\"local\"\n            }\n        ]\n    }\n}\nEOF\n    fi\n\n    reloadCore\n    echoContent green \" ---> 卸载成功\"\n\n    exit 0\n}\n\n# sing-box 个性化安装\ncustomSingBoxInstall() {\n    echoContent skyBlue \"\\n========================个性化安装============================\"\n    echoContent yellow \"0.VLESS+Vision+TCP\"\n    echoContent yellow \"1.VLESS+TLS+WS[仅CDN推荐]\"\n    echoContent yellow \"3.VMess+TLS+WS[仅CDN推荐]\"\n    echoContent yellow \"4.Trojan+TLS[不推荐]\"\n    echoContent yellow \"6.Hysteria2\"\n    echoContent yellow \"7.VLESS+Reality+Vision\"\n    echoContent yellow \"8.VLESS+Reality+gRPC\"\n    echoContent yellow \"9.Tuic\"\n    echoContent yellow \"10.Naive\"\n    echoContent yellow \"11.VMess+TLS+HTTPUpgrade\"\n    echoContent yellow \"13.anytls\"\n\n    read -r -p \"请选择[多选]，[例如:1,2,3]:\" selectCustomInstallType\n    echoContent skyBlue \"--------------------------------------------------------------\"\n    if echo \"${selectCustomInstallType}\" | grep -q \"，\"; then\n        echoContent red \" ---> 请使用英文逗号分隔\"\n        exit 0\n    fi\n    if [[ \"${selectCustomInstallType}\" != \"10\" ]] && [[ \"${selectCustomInstallType}\" != \"11\" ]] && [[ \"${selectCustomInstallType}\" != \"13\" ]] && ((${#selectCustomInstallType} >= 2)) && ! echo \"${selectCustomInstallType}\" | grep -q \",\"; then\n        echoContent red \" ---> 多选请使用英文逗号分隔\"\n        exit 0\n    fi\n    if [[ \"${selectCustomInstallType: -1}\" != \",\" ]]; then\n        selectCustomInstallType=\"${selectCustomInstallType},\"\n    fi\n    if [[ \"${selectCustomInstallType:0:1}\" != \",\" ]]; then\n        selectCustomInstallType=\",${selectCustomInstallType},\"\n    fi\n\n    if [[ \"${selectCustomInstallType//,/}\" =~ ^[0-9]+$ ]]; then\n        readLastInstallationConfig\n        unInstallSubscribe\n        totalProgress=9\n        installTools 1\n        # 申请tls\n        if echo \"${selectCustomInstallType}\" | grep -q -E \",0,|,1,|,3,|,4,|,6,|,9,|,10,|,11,|,13,\"; then\n            initTLSNginxConfig 2\n            installTLS 3\n            handleNginx stop\n        fi\n\n        installSingBox 4\n        installSingBoxService 5\n        initSingBoxConfig custom 6\n        cleanUp xrayDel\n        installCronTLS 7\n        handleSingBox stop\n        handleSingBox start\n        handleNginx stop\n        handleNginx start\n        # 生成账号\n        checkGFWStatue 8\n        showAccounts 9\n    else\n        echoContent red \" ---> 输入不合法\"\n        customSingBoxInstall\n    fi\n}\n\n# 一键无域名Xray-core Reality\ninstallXrayReality() {\n    selectCustomInstallType=\",7,\"\n    readLastInstallationConfig\n    unInstallSubscribe\n    totalProgress=6\n    installTools 1\n\n    handleNginx stop\n\n    # 安装Xray\n    installXray 2 false\n    installXrayService 3\n    initXrayConfig custom 4\n    cleanUp singBoxDel\n\n    handleXray stop\n    handleXray start\n    # 生成账号\n    checkGFWStatue 5\n    showAccounts 6\n}\n# 一键无域名sing-box Reality\ninstallSingBoxReality() {\n\n    selectCustomInstallType=\",7,\"\n    readLastInstallationConfig\n    unInstallSubscribe\n    totalProgress=6\n    installTools 1\n\n    installSingBox 2\n    installSingBoxService 3\n    initSingBoxConfig custom 4\n    cleanUp xrayDel\n    handleSingBox stop\n    handleSingBox start\n    # 生成账号\n    checkGFWStatue 5\n    showAccounts 6\n}\n# Xray-core个性化安装\ncustomXrayInstall() {\n    echoContent skyBlue \"\\n========================个性化安装============================\"\n    echoContent yellow \"VLESS前置，默认安装0，无域名安装Reality只选择7即可\"\n    echoContent yellow \"0.VLESS+TLS_Vision+TCP[推荐]\"\n    echoContent yellow \"1.VLESS+TLS+WS[仅CDN推荐]\"\n    #    echoContent yellow \"2.Trojan+TLS+gRPC[仅CDN推荐]\"\n    echoContent yellow \"3.VMess+TLS+WS[仅CDN推荐]\"\n    echoContent yellow \"4.Trojan+TLS[不推荐]\"\n    #    echoContent yellow \"5.VLESS+TLS+gRPC[仅CDN推荐]\"\n    echoContent yellow \"7.VLESS+Reality+uTLS+Vision[推荐]\"\n    # echoContent yellow \"8.VLESS+Reality+gRPC\"\n    echoContent yellow \"12.VLESS+Reality+XHTTP+TLS[CDN可用]\"\n    read -r -p \"请选择[多选]，[例如:1,2,3]:\" selectCustomInstallType\n    echoContent skyBlue \"--------------------------------------------------------------\"\n    if echo \"${selectCustomInstallType}\" | grep -q \"，\"; then\n        echoContent red \" ---> 请使用英文逗号分隔\"\n        exit 0\n    fi\n    if [[ \"${selectCustomInstallType}\" != \"12\" ]] && ((${#selectCustomInstallType} >= 2)) && ! echo \"${selectCustomInstallType}\" | grep -q \",\"; then\n        echoContent red \" ---> 多选请使用英文逗号分隔\"\n        exit 0\n    fi\n\n    if [[ \"${selectCustomInstallType}\" == \"7\" ]]; then\n        selectCustomInstallType=\",${selectCustomInstallType},\"\n    else\n        if ! echo \"${selectCustomInstallType}\" | grep -q \"0,\"; then\n            selectCustomInstallType=\",0,${selectCustomInstallType},\"\n        else\n            selectCustomInstallType=\",${selectCustomInstallType},\"\n        fi\n    fi\n\n    if [[ \"${selectCustomInstallType:0:1}\" != \",\" ]]; then\n        selectCustomInstallType=\",${selectCustomInstallType},\"\n    fi\n    if [[ \"${selectCustomInstallType//,/}\" =~ ^[0-7]+$ ]]; then\n        readLastInstallationConfig\n        unInstallSubscribe\n        checkBTPanel\n        check1Panel\n        totalProgress=12\n        installTools 1\n        if [[ -n \"${btDomain}\" ]]; then\n            echoContent skyBlue \"\\n进度  3/${totalProgress} : 检测到宝塔面板/1Panel，跳过申请TLS步骤\"\n            handleXray stop\n            if [[ \"${selectCustomInstallType}\" != \",7,\" ]]; then\n                customPortFunction\n            fi\n        else\n            # 申请tls\n            if [[ \"${selectCustomInstallType}\" != \",7,\" ]]; then\n                initTLSNginxConfig 2\n                handleXray stop\n                installTLS 3\n            else\n                echoContent skyBlue \"\\n进度  2/${totalProgress} : 检测到仅安装Reality，跳过TLS证书步骤\"\n            fi\n        fi\n\n        handleNginx stop\n        # 随机path\n        if echo \"${selectCustomInstallType}\" | grep -qE \",1,|,2,|,3,|,5,|,12,\"; then\n            randomPathFunction 4\n        fi\n        if [[ -n \"${btDomain}\" ]]; then\n            echoContent skyBlue \"\\n进度  6/${totalProgress} : 检测到宝塔面板/1Panel，跳过伪装网站\"\n        else\n            nginxBlog 6\n        fi\n        if [[ \"${selectCustomInstallType}\" != \",7,\" ]]; then\n            updateRedirectNginxConf\n            handleNginx start\n        fi\n\n        # 安装Xray\n        installXray 7 false\n        installXrayService 8\n        initXrayConfig custom 9\n        cleanUp singBoxDel\n        if [[ \"${selectCustomInstallType}\" != \",7,\" ]]; then\n            installCronTLS 10\n        fi\n\n        handleXray stop\n        handleXray start\n        # 生成账号\n        checkGFWStatue 11\n        showAccounts 12\n    else\n        echoContent red \" ---> 输入不合法\"\n        customXrayInstall\n    fi\n}\n\n# 选择核心安装sing-box、xray-core\nselectCoreInstall() {\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : 选择核心安装\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.Xray-core\"\n    echoContent yellow \"2.sing-box\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" selectCoreType\n    case ${selectCoreType} in\n    1)\n        if [[ \"${selectInstallType}\" == \"1\" ]]; then\n            xrayCoreInstall\n        elif [[ \"${selectInstallType}\" == \"2\" ]]; then\n            customXrayInstall\n        elif [[ \"${selectInstallType}\" == \"3\" ]]; then\n            installXrayReality\n        fi\n        ;;\n    2)\n        if [[ \"${selectInstallType}\" == \"1\" ]]; then\n            singBoxInstall\n        elif [[ \"${selectInstallType}\" == \"2\" ]]; then\n            customSingBoxInstall\n        elif [[ \"${selectInstallType}\" == \"3\" ]]; then\n            installSingBoxReality\n        fi\n        ;;\n    *)\n        echoContent red ' ---> 选择错误，重新选择'\n        selectCoreInstall\n        ;;\n    esac\n}\n\n# xray-core 安装\nxrayCoreInstall() {\n    readLastInstallationConfig\n    unInstallSubscribe\n    checkBTPanel\n    check1Panel\n    selectCustomInstallType=\n    totalProgress=12\n    installTools 2\n    if [[ -n \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\n进度  3/${totalProgress} : 检测到宝塔面板/1Panel，跳过申请TLS步骤\"\n        handleXray stop\n        customPortFunction\n    else\n        # 申请tls\n        initTLSNginxConfig 3\n        handleXray stop\n        installTLS 4\n    fi\n\n    handleNginx stop\n    randomPathFunction 5\n\n    # 安装Xray\n    installXray 6 false\n    installXrayService 7\n    initXrayConfig all 8\n    cleanUp singBoxDel\n    installCronTLS 9\n    if [[ -n \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\n进度  11/${totalProgress} : 检测到宝塔面板/1Panel，跳过伪装网站\"\n    else\n        nginxBlog 10\n    fi\n    updateRedirectNginxConf\n    handleXray stop\n    sleep 2\n    handleXray start\n\n    handleNginx start\n    # 生成账号\n    checkGFWStatue 11\n    showAccounts 12\n}\n\n# sing-box 全部安装\nsingBoxInstall() {\n    readLastInstallationConfig\n    unInstallSubscribe\n    checkBTPanel\n    check1Panel\n    selectCustomInstallType=\n    totalProgress=8\n    installTools 2\n\n    if [[ -n \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\n进度  3/${totalProgress} : 检测到宝塔面板/1Panel，跳过申请TLS步骤\"\n        handleXray stop\n        customPortFunction\n    else\n        # 申请tls\n        initTLSNginxConfig 3\n        handleXray stop\n        installTLS 4\n    fi\n\n    handleNginx stop\n\n    installSingBox 5\n    installSingBoxService 6\n    initSingBoxConfig all 7\n\n    cleanUp xrayDel\n    installCronTLS 8\n\n    handleSingBox stop\n    handleSingBox start\n    handleNginx stop\n    handleNginx start\n    # 生成账号\n    showAccounts 9\n}\n\n# 核心管理\ncoreVersionManageMenu() {\n\n    if [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n ---> 没有检测到安装目录，请执行脚本安装内容\"\n        menu\n        exit 0\n    fi\n    echoContent skyBlue \"\\n功能 1/1 : 请选择核心\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.Xray-core\"\n    echoContent yellow \"2.sing-box\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请输入:\" selectCore\n\n    if [[ \"${selectCore}\" == \"1\" ]]; then\n        xrayVersionManageMenu 1\n    elif [[ \"${selectCore}\" == \"2\" ]]; then\n        singBoxVersionManageMenu 1\n    fi\n}\n# 定时任务检查\ncronFunction() {\n    if [[ \"${cronName}\" == \"RenewTLS\" ]]; then\n        renewalTLS\n        exit 0\n    elif [[ \"${cronName}\" == \"UpdateGeo\" ]]; then\n        updateGeoSite >>/etc/v2ray-agent/crontab_updateGeoSite.log\n        echoContent green \" ---> geo更新日期:$(date \"+%F %H:%M:%S\")\" >>/etc/v2ray-agent/crontab_updateGeoSite.log\n        exit 0\n    fi\n}\n# 账号管理\nmanageAccount() {\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : 账号管理\"\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> 未安装\"\n        exit 0\n    fi\n\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 添加单个用户时可自定义email和uuid\"\n    echoContent yellow \"# 如安装了Hysteria或者Tuic，账号会同时添加到相应的类型下面\\n\"\n    echoContent yellow \"1.查看账号\"\n    echoContent yellow \"2.查看订阅\"\n    echoContent yellow \"3.管理其他订阅\"\n    echoContent yellow \"4.添加用户\"\n    echoContent yellow \"5.删除用户\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请输入:\" manageAccountStatus\n    if [[ \"${manageAccountStatus}\" == \"1\" ]]; then\n        showAccounts 1\n    elif [[ \"${manageAccountStatus}\" == \"2\" ]]; then\n        subscribe\n    elif [[ \"${manageAccountStatus}\" == \"3\" ]]; then\n        addSubscribeMenu 1\n    elif [[ \"${manageAccountStatus}\" == \"4\" ]]; then\n        addUser\n    elif [[ \"${manageAccountStatus}\" == \"5\" ]]; then\n        removeUser\n    else\n        echoContent red \" ---> 选择错误\"\n    fi\n}\n\n# 安装订阅\ninstallSubscribe() {\n    readNginxSubscribe\n    local nginxSubscribeListen=\n    local nginxSubscribeSSL=\n    local serverName=\n    local SSLType=\n    local listenIPv6=\n    if [[ -z \"${subscribePort}\" ]]; then\n\n        nginxVersion=$(nginx -v 2>&1)\n\n        if echo \"${nginxVersion}\" | grep -q \"not found\" || [[ -z \"${nginxVersion}\" ]]; then\n            echoContent yellow \"未检测到nginx，无法使用订阅服务\\n\"\n            read -r -p \"是否安装[y/n]？\" installNginxStatus\n            if [[ \"${installNginxStatus}\" == \"y\" ]]; then\n                installNginxTools\n            else\n                echoContent red \" ---> 放弃安装nginx\\n\"\n                exit 0\n            fi\n        fi\n        echoContent yellow \"开始配置订阅，请输入订阅的端口\\n\"\n\n        mapfile -t result < <(initSingBoxPort \"${subscribePort}\")\n        echo\n        echoContent yellow \" ---> 开始配置订阅的伪装站点\\n\"\n        nginxBlog\n        echo\n        local httpSubscribeStatus=\n\n        if ! echo \"${selectCustomInstallType}\" | grep -qE \",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,|,11,|,13,\" && ! echo \"${currentInstallProtocolType}\" | grep -qE \",0,|,1,|,2,|,3,|,4,|,5,|,6,|,9,|,10,|,11,|,13,\" && [[ -z \"${domain}\" ]]; then\n            httpSubscribeStatus=true\n        fi\n\n        if [[ \"${httpSubscribeStatus}\" == \"true\" ]]; then\n\n            echoContent yellow \"未发现tls证书，使用无加密订阅，可能被运营商拦截，请注意风险。\"\n            echo\n            read -r -p \"是否使用http订阅[y/n]？\" addNginxSubscribeStatus\n            echo\n            if [[ \"${addNginxSubscribeStatus}\" != \"y\" ]]; then\n                echoContent yellow \" ---> 退出安装\"\n                exit\n            fi\n        else\n            local subscribeServerName=\n            if [[ -n \"${currentHost}\" ]]; then\n                subscribeServerName=\"${currentHost}\"\n            else\n                subscribeServerName=\"${domain}\"\n            fi\n\n            SSLType=\"ssl\"\n            serverName=\"server_name ${subscribeServerName};\"\n            nginxSubscribeSSL=\"ssl_certificate /etc/v2ray-agent/tls/${subscribeServerName}.crt;ssl_certificate_key /etc/v2ray-agent/tls/${subscribeServerName}.key;\"\n        fi\n        if [[ -n \"$(curl --connect-timeout 2 -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | cut -d \"=\" -f 2)\" ]]; then\n            listenIPv6=\"listen [::]:${result[-1]} ${SSLType};\"\n        fi\n        if echo \"${nginxVersion}\" | grep -q \"1.25\" && [[ $(echo \"${nginxVersion}\" | awk -F \"[.]\" '{print $3}') -gt 0 ]] || [[ $(echo \"${nginxVersion}\" | awk -F \"[.]\" '{print $2}') -gt 25 ]]; then\n            nginxSubscribeListen=\"listen ${result[-1]} ${SSLType} so_keepalive=on;http2 on;${listenIPv6}\"\n        else\n            nginxSubscribeListen=\"listen ${result[-1]} ${SSLType} so_keepalive=on;${listenIPv6}\"\n        fi\n\n        cat <<EOF >${nginxConfigPath}subscribe.conf\nserver {\n    ${nginxSubscribeListen}\n    ${serverName}\n    ${nginxSubscribeSSL}\n    ssl_protocols              TLSv1.2 TLSv1.3;\n    ssl_ciphers                TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;\n    ssl_prefer_server_ciphers  on;\n\n    resolver                   1.1.1.1 valid=60s;\n    resolver_timeout           2s;\n    client_max_body_size 100m;\n    root ${nginxStaticPath};\n    location ~ ^/s/(clashMeta|default|clashMetaProfiles|sing-box|sing-box_profiles)/(.*) {\n        default_type 'text/plain; charset=utf-8';\n        alias /etc/v2ray-agent/subscribe/\\$1/\\$2;\n    }\n    location / {\n    }\n}\nEOF\n        bootStartup nginx\n        handleNginx stop\n        handleNginx start\n    fi\n    if [[ -z $(pgrep -f \"nginx\") ]]; then\n        handleNginx start\n    fi\n}\n# 卸载订阅\nunInstallSubscribe() {\n    rm -rf ${nginxConfigPath}subscribe.conf >/dev/null 2>&1\n}\n\n# 添加订阅\naddSubscribeMenu() {\n    echoContent skyBlue \"\\n===================== 添加其他机器订阅 =======================\"\n    echoContent yellow \"1.添加\"\n    echoContent yellow \"2.移除\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" addSubscribeStatus\n    if [[ \"${addSubscribeStatus}\" == \"1\" ]]; then\n        addOtherSubscribe\n    elif [[ \"${addSubscribeStatus}\" == \"2\" ]]; then\n        if [[ ! -f \"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\" ]]; then\n            echoContent green \" ---> 未安装其他订阅\"\n            exit 0\n        fi\n        grep -v '^$' \"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\" | awk '{print NR\"\"\":\"$0}'\n        read -r -p \"请选择要删除的订阅编号[仅支持单个删除]:\" delSubscribeIndex\n        if [[ -z \"${delSubscribeIndex}\" ]]; then\n            echoContent green \" ---> 不可以为空\"\n            exit 0\n        fi\n\n        sed -i \"$((delSubscribeIndex))d\" \"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\" >/dev/null 2>&1\n\n        echoContent green \" ---> 其他机器订阅删除成功\"\n        subscribe\n    fi\n}\n# 添加其他机器clashMeta订阅\naddOtherSubscribe() {\n    echoContent yellow \"#注意事项:\"\n    echoContent yellow \"请仔细阅读以下文章： https://www.v2ray-agent.com/archives/1681804748677\"\n    echoContent skyBlue \"录入示例：www.v2ray-agent.com:443:vps1\\n\"\n    read -r -p \"请输入域名 端口 机器别名:\" remoteSubscribeUrl\n    if [[ -z \"${remoteSubscribeUrl}\" ]]; then\n        echoContent red \" ---> 不可为空\"\n        addOtherSubscribe\n    elif ! echo \"${remoteSubscribeUrl}\" | grep -q \":\"; then\n        echoContent red \" ---> 规则不合法\"\n    else\n\n        if [[ -f \"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\" ]] && grep -q \"${remoteSubscribeUrl}\" /etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl; then\n            echoContent red \" ---> 此订阅已添加\"\n            exit 0\n        fi\n        echo\n        read -r -p \"是否是HTTP订阅？[y/n]\" httpSubscribeStatus\n        if [[ \"${httpSubscribeStatus}\" == \"y\" ]]; then\n            remoteSubscribeUrl=\"${remoteSubscribeUrl}:http\"\n        fi\n        echo \"${remoteSubscribeUrl}\" >>/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\n        subscribe\n    fi\n}\n# clashMeta配置文件\nclashMetaConfig() {\n    local url=$1\n    local id=$2\n    cat <<EOF >\"/etc/v2ray-agent/subscribe/clashMetaProfiles/${id}\"\nlog-level: debug\nmode: rule\nipv6: true\nmixed-port: 7890\nallow-lan: true\nbind-address: \"*\"\nlan-allowed-ips:\n  - 0.0.0.0/0\n  - ::/0\nfind-process-mode: strict\nexternal-controller: 0.0.0.0:9090\n\ngeox-url:\n  geoip: \"https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat\"\n  geosite: \"https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat\"\n  mmdb: \"https://fastly.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.metadb\"\ngeo-auto-update: true\ngeo-update-interval: 24\n\nexternal-controller-cors:\n  allow-private-network: true\n\nglobal-client-fingerprint: chrome\n\nprofile:\n  store-selected: true\n  store-fake-ip: true\n\nsniffer:\n  enable: true\n  override-destination: false\n  sniff:\n    QUIC:\n      ports: [ 443 ]\n    TLS:\n      ports: [ 443 ]\n    HTTP:\n      ports: [80]\n\n\ndns:\n  enable: true\n  prefer-h3: false\n  listen: 0.0.0.0:1053\n  ipv6: true\n  enhanced-mode: fake-ip\n  fake-ip-range: 198.18.0.1/16\n  fake-ip-filter:\n    - '*.lan'\n    - '*.local'\n    - 'dns.google'\n    - \"localhost.ptlogin2.qq.com\"\n  use-hosts: true\n  nameserver:\n    - https://1.1.1.1/dns-query\n    - https://8.8.8.8/dns-query\n    - 1.1.1.1\n    - 8.8.8.8\n  proxy-server-nameserver:\n    - https://223.5.5.5/dns-query\n    - https://1.12.12.12/dns-query\n  nameserver-policy:\n    \"geosite:cn,private\":\n      - https://doh.pub/dns-query\n      - https://dns.alidns.com/dns-query\n\nproxy-providers:\n  ${subscribeSalt}_provider:\n    type: http\n    path: ./${subscribeSalt}_provider.yaml\n    url: ${url}\n    interval: 3600\n    proxy: DIRECT\n    health-check:\n      enable: true\n      url: https://cp.cloudflare.com/generate_204\n      interval: 300\n\nproxy-groups:\n  - name: 手动切换\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies: null\n  - name: 自动选择\n    type: url-test\n    url: http://www.gstatic.com/generate_204\n    interval: 36000\n    tolerance: 50\n    use:\n      - ${subscribeSalt}_provider\n    proxies: null\n\n  - name: 全球代理\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n\n  - name: 流媒体\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - DIRECT\n  - name: DNS_Proxy\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 自动选择\n      - 手动切换\n      - DIRECT\n\n  - name: Telegram\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n  - name: Google\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - DIRECT\n  - name: YouTube\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n  - name: Netflix\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 手动切换\n      - 自动选择\n  - name: Spotify\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 手动切换\n      - 自动选择\n      - DIRECT\n  - name: HBO\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 手动切换\n      - 自动选择\n  - name: Bing\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n\n\n  - name: OpenAI\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n\n  - name: ClaudeAI\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n\n  - name: Disney\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 手动切换\n      - 自动选择\n  - name: GitHub\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - DIRECT\n\n  - name: 国内媒体\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - DIRECT\n  - name: 本地直连\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - DIRECT\n      - 自动选择\n  - name: 漏网之鱼\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - DIRECT\n      - 手动切换\n      - 自动选择\nrule-providers:\n  lan:\n    type: http\n    behavior: classical\n    interval: 86400\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Lan/Lan.yaml\n    path: ./Rules/lan.yaml\n  reject:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt\n    path: ./ruleset/reject.yaml\n    interval: 86400\n  proxy:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt\n    path: ./ruleset/proxy.yaml\n    interval: 86400\n  direct:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt\n    path: ./ruleset/direct.yaml\n    interval: 86400\n  private:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/private.txt\n    path: ./ruleset/private.yaml\n    interval: 86400\n  gfw:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/gfw.txt\n    path: ./ruleset/gfw.yaml\n    interval: 86400\n  greatfire:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/greatfire.txt\n    path: ./ruleset/greatfire.yaml\n    interval: 86400\n  tld-not-cn:\n    type: http\n    behavior: domain\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/tld-not-cn.txt\n    path: ./ruleset/tld-not-cn.yaml\n    interval: 86400\n  telegramcidr:\n    type: http\n    behavior: ipcidr\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/telegramcidr.txt\n    path: ./ruleset/telegramcidr.yaml\n    interval: 86400\n  applications:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/applications.txt\n    path: ./ruleset/applications.yaml\n    interval: 86400\n  Disney:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Disney/Disney.yaml\n    path: ./ruleset/disney.yaml\n    interval: 86400\n  Netflix:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Netflix/Netflix.yaml\n    path: ./ruleset/netflix.yaml\n    interval: 86400\n  YouTube:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/YouTube/YouTube.yaml\n    path: ./ruleset/youtube.yaml\n    interval: 86400\n  HBO:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/HBO/HBO.yaml\n    path: ./ruleset/hbo.yaml\n    interval: 86400\n  OpenAI:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml\n    path: ./ruleset/openai.yaml\n    interval: 86400\n  ClaudeAI:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Claude/Claude.yaml\n    path: ./ruleset/claudeai.yaml\n    interval: 86400\n  Bing:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Bing/Bing.yaml\n    path: ./ruleset/bing.yaml\n    interval: 86400\n  Google:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Google/Google.yaml\n    path: ./ruleset/google.yaml\n    interval: 86400\n  GitHub:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/GitHub/GitHub.yaml\n    path: ./ruleset/github.yaml\n    interval: 86400\n  Spotify:\n    type: http\n    behavior: classical\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Spotify/Spotify.yaml\n    path: ./ruleset/spotify.yaml\n    interval: 86400\n  ChinaMaxDomain:\n    type: http\n    behavior: domain\n    interval: 86400\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_Domain.yaml\n    path: ./Rules/ChinaMaxDomain.yaml\n  ChinaMaxIPNoIPv6:\n    type: http\n    behavior: ipcidr\n    interval: 86400\n    url: https://gh-proxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_IP_No_IPv6.yaml\n    path: ./Rules/ChinaMaxIPNoIPv6.yaml\nrules:\n  - RULE-SET,YouTube,YouTube,no-resolve\n  - RULE-SET,Google,Google,no-resolve\n  - RULE-SET,GitHub,GitHub\n  - RULE-SET,telegramcidr,Telegram,no-resolve\n  - RULE-SET,Spotify,Spotify,no-resolve\n  - RULE-SET,Netflix,Netflix\n  - RULE-SET,HBO,HBO\n  - RULE-SET,Bing,Bing\n  - RULE-SET,OpenAI,OpenAI\n  - RULE-SET,ClaudeAI,ClaudeAI\n  - RULE-SET,Disney,Disney\n  - RULE-SET,proxy,全球代理\n  - RULE-SET,gfw,全球代理\n  - RULE-SET,applications,本地直连\n  - RULE-SET,ChinaMaxDomain,本地直连\n  - RULE-SET,ChinaMaxIPNoIPv6,本地直连,no-resolve\n  - RULE-SET,lan,本地直连,no-resolve\n  - GEOIP,CN,本地直连\n  - MATCH,漏网之鱼\nEOF\n\n}\n# 随机salt\ninitRandomSalt() {\n    local chars=\"abcdefghijklmnopqrtuxyz\"\n    local initCustomPath=\n    for i in {1..10}; do\n        echo \"${i}\" >/dev/null\n        initCustomPath+=\"${chars:RANDOM%${#chars}:1}\"\n    done\n    echo \"${initCustomPath}\"\n}\n# 订阅\nsubscribe() {\n    readInstallProtocolType\n    installSubscribe\n\n    readNginxSubscribe\n    local renewSalt=$1\n    local showStatus=$2\n    if [[ \"${coreInstallType}\" == \"1\" || \"${coreInstallType}\" == \"2\" ]]; then\n\n        echoContent skyBlue \"-------------------------备注---------------------------------\"\n        echoContent yellow \"# 查看订阅会重新生成本地账号的订阅\"\n        echoContent red \"# 需要手动输入md5加密的salt值，如果不了解使用随机即可\"\n        echoContent yellow \"# 不影响已添加的远程订阅的内容\\n\"\n\n        if [[ -f \"/etc/v2ray-agent/subscribe_local/subscribeSalt\" && -n $(cat \"/etc/v2ray-agent/subscribe_local/subscribeSalt\") ]]; then\n            if [[ -z \"${renewSalt}\" ]]; then\n                read -r -p \"读取到上次安装设置的Salt，是否使用上次生成的Salt ？[y/n]:\" historySaltStatus\n                if [[ \"${historySaltStatus}\" == \"y\" ]]; then\n                    subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt)\n                else\n                    read -r -p \"请输入salt值, [回车]使用随机:\" subscribeSalt\n                fi\n            else\n                subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt)\n            fi\n        else\n            read -r -p \"请输入salt值, [回车]使用随机:\" subscribeSalt\n            showStatus=\n        fi\n\n        if [[ -z \"${subscribeSalt}\" ]]; then\n            subscribeSalt=$(initRandomSalt)\n        fi\n        echoContent yellow \"\\n ---> Salt: ${subscribeSalt}\"\n\n        echo \"${subscribeSalt}\" >/etc/v2ray-agent/subscribe_local/subscribeSalt\n\n        rm -rf /etc/v2ray-agent/subscribe/default/*\n        rm -rf /etc/v2ray-agent/subscribe/clashMeta/*\n        rm -rf /etc/v2ray-agent/subscribe_local/default/*\n        rm -rf /etc/v2ray-agent/subscribe_local/clashMeta/*\n        rm -rf /etc/v2ray-agent/subscribe_local/sing-box/*\n        showAccounts >/dev/null\n        if [[ -n $(ls /etc/v2ray-agent/subscribe_local/default/) ]]; then\n            if [[ -f \"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\" && -n $(cat \"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\") ]]; then\n                if [[ -z \"${renewSalt}\" ]]; then\n                    read -r -p \"读取到其他订阅，是否更新？[y/n]\" updateOtherSubscribeStatus\n                else\n                    updateOtherSubscribeStatus=y\n                fi\n            fi\n            local subscribePortLocal=\"${subscribePort}\"\n            find /etc/v2ray-agent/subscribe_local/default/* | while read -r email; do\n                email=$(echo \"${email}\" | awk -F \"[d][e][f][a][u][l][t][/]\" '{print $2}')\n\n                local emailMd5=\n                emailMd5=$(echo -n \"${email}${subscribeSalt}\"$'\\n' | md5sum | awk '{print $1}')\n\n                cat \"/etc/v2ray-agent/subscribe_local/default/${email}\" >>\"/etc/v2ray-agent/subscribe/default/${emailMd5}\"\n                if [[ \"${updateOtherSubscribeStatus}\" == \"y\" ]]; then\n                    updateRemoteSubscribe \"${emailMd5}\" \"${email}\"\n                fi\n                local base64Result\n                base64Result=$(base64 -w 0 \"/etc/v2ray-agent/subscribe/default/${emailMd5}\")\n                echo \"${base64Result}\" >\"/etc/v2ray-agent/subscribe/default/${emailMd5}\"\n                echoContent yellow \"--------------------------------------------------------------\"\n                local currentDomain=${currentHost}\n\n                if [[ -n \"${currentDefaultPort}\" && \"${currentDefaultPort}\" != \"443\" ]]; then\n                    currentDomain=\"${currentHost}:${currentDefaultPort}\"\n                fi\n                if [[ -n \"${subscribePortLocal}\" ]]; then\n                    if [[ \"${subscribeType}\" == \"http\" ]]; then\n                        currentDomain=\"$(getPublicIP):${subscribePort}\"\n                    else\n                        currentDomain=\"${currentHost}:${subscribePort}\"\n                    fi\n                fi\n                if [[ -z \"${showStatus}\" ]]; then\n                    echoContent skyBlue \"\\n----------默认订阅----------\\n\"\n                    echoContent green \"email:${email}\\n\"\n                    echoContent yellow \"url:${subscribeType}://${currentDomain}/s/default/${emailMd5}\\n\"\n                    echoContent yellow \"在线二维码:https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${subscribeType}://${currentDomain}/s/default/${emailMd5}\\n\"\n                    if [[ \"${release}\" != \"alpine\" ]]; then\n                        echo \"${subscribeType}://${currentDomain}/s/default/${emailMd5}\" | qrencode -s 10 -m 1 -t UTF8\n                    fi\n\n                    # clashMeta\n                    if [[ -f \"/etc/v2ray-agent/subscribe_local/clashMeta/${email}\" ]]; then\n\n                        cat \"/etc/v2ray-agent/subscribe_local/clashMeta/${email}\" >>\"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}\"\n\n                        sed -i '1i\\proxies:' \"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}\"\n\n                        local clashProxyUrl=\"${subscribeType}://${currentDomain}/s/clashMeta/${emailMd5}\"\n                        clashMetaConfig \"${clashProxyUrl}\" \"${emailMd5}\"\n                        echoContent skyBlue \"\\n----------clashMeta订阅----------\\n\"\n                        echoContent yellow \"url:${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}\\n\"\n                        echoContent yellow \"在线二维码:https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}\\n\"\n                        if [[ \"${release}\" != \"alpine\" ]]; then\n                            echo \"${subscribeType}://${currentDomain}/s/clashMetaProfiles/${emailMd5}\" | qrencode -s 10 -m 1 -t UTF8\n                        fi\n\n                    fi\n                    # sing-box\n                    if [[ -f \"/etc/v2ray-agent/subscribe_local/sing-box/${email}\" ]]; then\n                        cp \"/etc/v2ray-agent/subscribe_local/sing-box/${email}\" \"/etc/v2ray-agent/subscribe/sing-box_profiles/${emailMd5}\"\n\n                        echoContent skyBlue \" ---> 下载 sing-box 通用配置文件\"\n                        if [[ \"${release}\" == \"alpine\" ]]; then\n                            wget -O \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\" -q \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/documents/sing-box.json\"\n                        else\n                            wget -O \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\" -q \"${wgetShowProgressStatus}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/documents/sing-box.json\"\n                        fi\n\n                        jq \".outbounds=$(jq \".outbounds|map(if has(\\\"outbounds\\\") then .outbounds += $(jq \".|map(.tag)\" \"/etc/v2ray-agent/subscribe_local/sing-box/${email}\") else . end)\" \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\")\" \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\" >\"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp\" && mv \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp\" \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\"\n                        jq \".outbounds += $(jq '.' \"/etc/v2ray-agent/subscribe_local/sing-box/${email}\")\" \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\" >\"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp\" && mv \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}_tmp\" \"/etc/v2ray-agent/subscribe/sing-box/${emailMd5}\"\n\n                        echoContent skyBlue \"\\n----------sing-box订阅----------\\n\"\n                        echoContent yellow \"url:${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}\\n\"\n                        echoContent yellow \"在线二维码:https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}\\n\"\n                        if [[ \"${release}\" != \"alpine\" ]]; then\n                            echo \"${subscribeType}://${currentDomain}/s/sing-box/${emailMd5}\" | qrencode -s 10 -m 1 -t UTF8\n                        fi\n\n                    fi\n\n                    echoContent skyBlue \"--------------------------------------------------------------\"\n                else\n                    echoContent green \" ---> email:${email}，订阅已更新，请使用客户端重新拉取\"\n                fi\n\n            done\n        fi\n    else\n        echoContent red \" ---> 未安装伪装站点，无法使用订阅服务\"\n    fi\n}\n\n# 更新远程订阅\nupdateRemoteSubscribe() {\n\n    local emailMD5=$1\n    local email=$2\n    while read -r line; do\n        local subscribeType=\n        subscribeType=\"https\"\n\n        local serverAlias=\n        serverAlias=$(echo \"${line}\" | awk -F \"[:]\" '{print $3}')\n\n        local remoteUrl=\n        remoteUrl=$(echo \"${line}\" | awk -F \"[:]\" '{print $1\":\"$2}')\n\n        local subscribeTypeRemote=\n        subscribeTypeRemote=$(echo \"${line}\" | awk -F \"[:]\" '{print $4}')\n\n        if [[ -n \"${subscribeTypeRemote}\" ]]; then\n            subscribeType=\"${subscribeTypeRemote}\"\n        fi\n        local clashMetaProxies=\n\n        clashMetaProxies=$(curl -s \"${subscribeType}://${remoteUrl}/s/clashMeta/${emailMD5}\" | sed '/proxies:/d' | sed \"s/\\\"${email}/\\\"${email}_${serverAlias}/g\")\n\n        if ! echo \"${clashMetaProxies}\" | grep -q \"nginx\" && [[ -n \"${clashMetaProxies}\" ]]; then\n            echo \"${clashMetaProxies}\" >>\"/etc/v2ray-agent/subscribe/clashMeta/${emailMD5}\"\n            echoContent green \" ---> clashMeta订阅 ${remoteUrl}:${email} 更新成功\"\n        else\n            echoContent red \" ---> clashMeta订阅 ${remoteUrl}:${email}不存在\"\n        fi\n\n        local default=\n        default=$(curl -s \"${subscribeType}://${remoteUrl}/s/default/${emailMD5}\")\n\n        if ! echo \"${default}\" | grep -q \"nginx\" && [[ -n \"${default}\" ]]; then\n            default=$(echo \"${default}\" | base64 -d | sed \"s/#${email}/#${email}_${serverAlias}/g\")\n            echo \"${default}\" >>\"/etc/v2ray-agent/subscribe/default/${emailMD5}\"\n\n            echoContent green \" ---> 通用订阅 ${remoteUrl}:${email} 更新成功\"\n        else\n            echoContent red \" ---> 通用订阅 ${remoteUrl}:${email} 不存在\"\n        fi\n\n        local singBoxSubscribe=\n        singBoxSubscribe=$(curl -s \"${subscribeType}://${remoteUrl}/s/sing-box_profiles/${emailMD5}\")\n\n        if ! echo \"${singBoxSubscribe}\" | grep -q \"nginx\" && [[ -n \"${singBoxSubscribe}\" ]]; then\n            singBoxSubscribe=${singBoxSubscribe//tag\\\": \\\"${email}/tag\\\": \\\"${email}_${serverAlias}}\n            singBoxSubscribe=$(jq \". +=${singBoxSubscribe}\" \"/etc/v2ray-agent/subscribe_local/sing-box/${email}\")\n            echo \"${singBoxSubscribe}\" | jq . >\"/etc/v2ray-agent/subscribe_local/sing-box/${email}\"\n\n            echoContent green \" ---> 通用订阅 ${remoteUrl}:${email} 更新成功\"\n        else\n            echoContent red \" ---> 通用订阅 ${remoteUrl}:${email} 不存在\"\n        fi\n\n    done < <(grep -v '^$' <\"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\")\n}\n\n# 切换alpn\nswitchAlpn() {\n    echoContent skyBlue \"\\n功能 1/${totalProgress} : 切换alpn\"\n    if [[ -z ${currentAlpn} ]]; then\n        echoContent red \" ---> 无法读取alpn，请检查是否安装\"\n        exit 0\n    fi\n\n    echoContent red \"\\n==============================================================\"\n    echoContent green \"当前alpn首位为:${currentAlpn}\"\n    echoContent yellow \"  1.当http/1.1首位时，trojan可用，gRPC部分客户端可用【客户端支持手动选择alpn的可用】\"\n    echoContent yellow \"  2.当h2首位时，gRPC可用，trojan部分客户端可用【客户端支持手动选择alpn的可用】\"\n    echoContent yellow \"  3.如客户端不支持手动更换alpn，建议使用此功能更改服务端alpn顺序，来使用相应的协议\"\n    echoContent red \"==============================================================\"\n\n    if [[ \"${currentAlpn}\" == \"http/1.1\" ]]; then\n        echoContent yellow \"1.切换alpn h2 首位\"\n    elif [[ \"${currentAlpn}\" == \"h2\" ]]; then\n        echoContent yellow \"1.切换alpn http/1.1 首位\"\n    else\n        echoContent red '不符合'\n    fi\n\n    echoContent red \"==============================================================\"\n\n    read -r -p \"请选择:\" selectSwitchAlpnType\n    if [[ \"${selectSwitchAlpnType}\" == \"1\" && \"${currentAlpn}\" == \"http/1.1\" ]]; then\n\n        local frontingTypeJSON\n        frontingTypeJSON=$(jq -r \".inbounds[0].streamSettings.tlsSettings.alpn = [\\\"h2\\\",\\\"http/1.1\\\"]\" ${configPath}${frontingType}.json)\n        echo \"${frontingTypeJSON}\" | jq . >${configPath}${frontingType}.json\n\n    elif [[ \"${selectSwitchAlpnType}\" == \"1\" && \"${currentAlpn}\" == \"h2\" ]]; then\n        local frontingTypeJSON\n        frontingTypeJSON=$(jq -r \".inbounds[0].streamSettings.tlsSettings.alpn =[\\\"http/1.1\\\",\\\"h2\\\"]\" ${configPath}${frontingType}.json)\n        echo \"${frontingTypeJSON}\" | jq . >${configPath}${frontingType}.json\n    else\n        echoContent red \" ---> 选择错误\"\n        exit 0\n    fi\n    reloadCore\n}\n\n# 初始化realityKey\ninitRealityKey() {\n    echoContent skyBlue \"\\n生成Reality key\\n\"\n    if [[ -n \"${currentRealityPublicKey}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次安装记录，是否使用上次安装时的PublicKey/PrivateKey ？[y/n]:\" historyKeyStatus\n        if [[ \"${historyKeyStatus}\" == \"y\" ]]; then\n            realityPrivateKey=${currentRealityPrivateKey}\n            realityPublicKey=${currentRealityPublicKey}\n        fi\n    elif [[ -n \"${currentRealityPublicKey}\" && -n \"${lastInstallationConfig}\" ]]; then\n        realityPrivateKey=${currentRealityPrivateKey}\n        realityPublicKey=${currentRealityPublicKey}\n    fi\n    if [[ -z \"${realityPrivateKey}\" ]]; then\n        if [[ \"${selectCoreType}\" == \"2\" || \"${coreInstallType}\" == \"2\" ]]; then\n            realityX25519Key=$(/etc/v2ray-agent/sing-box/sing-box generate reality-keypair)\n            realityPrivateKey=$(echo \"${realityX25519Key}\" | head -1 | awk '{print $2}')\n            realityPublicKey=$(echo \"${realityX25519Key}\" | tail -n 1 | awk '{print $2}')\n            echo \"publicKey:${realityPublicKey}\" >/etc/v2ray-agent/sing-box/conf/config/reality_key\n        else\n            read -r -p \"请输入Private Key[回车自动生成]:\" historyPrivateKey\n            if [[ -n \"${historyPrivateKey}\" ]]; then\n                realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519 -i \"${historyPrivateKey}\")\n            else\n                realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519)\n            fi\n            realityPrivateKey=$(echo \"${realityX25519Key}\" | grep \"PrivateKey\" | awk '{print $2}')\n            realityPublicKey=$(echo \"${realityX25519Key}\" | grep \"Password\" | awk '{print $2}')\n            if [[ -z \"${realityPrivateKey}\" ]]; then\n                echoContent red \"输入的Private Key不合法\"\n                initRealityKey\n            else\n                echoContent green \"\\n privateKey:${realityPrivateKey}\"\n                echoContent green \"\\n publicKey:${realityPublicKey}\"\n            fi\n        fi\n    fi\n}\n# 初始化 mldsa65Seed\ninitRealityMldsa65() {\n    echoContent skyBlue \"\\n生成Reality mldsa65\\n\"\n    if /etc/v2ray-agent/xray/xray tls ping \"${realityServerName}:${realityDomainPort}\" 2>/dev/null | grep -q \"X25519MLKEM768\"; then\n        length=$(/etc/v2ray-agent/xray/xray tls ping \"${realityServerName}:${realityDomainPort}\" | grep \"Certificate chain's total length:\" | awk '{print $5}' | head -1)\n\n        if [ \"$length\" -gt 3500 ]; then\n            if [[ -n \"${currentRealityMldsa65}\" && -z \"${lastInstallationConfig}\" ]]; then\n                read -r -p \"读取到上次安装记录，是否使用上次安装时的Seed/Verify ？[y/n]:\" historyMldsa65Status\n                if [[ \"${historyMldsa65Status}\" == \"y\" ]]; then\n                    realityMldsa65Seed=${currentRealityMldsa65Seed}\n                    realityMldsa65Verify=${currentRealityMldsa65Verify}\n                fi\n            elif [[ -n \"${currentRealityMldsa65Seed}\" && -n \"${lastInstallationConfig}\" ]]; then\n                realityMldsa65Seed=${currentRealityMldsa65Seed}\n                realityMldsa65Verify=${currentRealityMldsa65Verify}\n            fi\n            if [[ -z \"${realityMldsa65Seed}\" ]]; then\n                #        if [[ \"${selectCoreType}\" == \"2\" || \"${coreInstallType}\" == \"2\" ]]; then\n                #            realityX25519Key=$(/etc/v2ray-agent/sing-box/sing-box generate reality-keypair)\n                #            realityPrivateKey=$(echo \"${realityX25519Key}\" | head -1 | awk '{print $2}')\n                #            realityPublicKey=$(echo \"${realityX25519Key}\" | tail -n 1 | awk '{print $2}')\n                #            echo \"publicKey:${realityPublicKey}\" >/etc/v2ray-agent/sing-box/conf/config/reality_key\n                #        else\n                realityMldsa65=$(/etc/v2ray-agent/xray/xray mldsa65)\n                realityMldsa65Seed=$(echo \"${realityMldsa65}\" | head -1 | awk '{print $2}')\n                realityMldsa65Verify=$(echo \"${realityMldsa65}\" | tail -n 1 | awk '{print $2}')\n                #        fi\n            fi\n            #    echoContent green \"\\n Seed:${realityMldsa65Seed}\"\n            #    echoContent green \"\\n Verify:${realityMldsa65Verify}\"\n        else\n            echoContent green \" 目标域名支持X25519MLKEM768，但是证书的长度不足，忽略ML-DSA-65。\"\n        fi\n    else\n        echoContent green \" 目标域名不支持X25519MLKEM768，忽略ML-DSA-65。\"\n    fi\n}\n# 检查reality域名是否符合\ncheckRealityDest() {\n    local traceResult=\n    traceResult=$(curl -s \"https://$(echo \"${realityDestDomain}\" | cut -d ':' -f 1)/cdn-cgi/trace\" | grep \"visit_scheme=https\")\n    if [[ -n \"${traceResult}\" ]]; then\n        echoContent red \"\\n ---> 检测到使用的域名，托管在cloudflare并开启了代理，使用此类型域名可能导致VPS流量被其他人使用[不建议使用]\\n\"\n        read -r -p \"是否继续 ？[y/n]\" setRealityDestStatus\n        if [[ \"${setRealityDestStatus}\" != 'y' ]]; then\n            exit 0\n        fi\n        echoContent yellow \"\\n ---> 忽略风险，继续使用\"\n    fi\n}\n\n# 初始化客户端可用的ServersName\ninitRealityClientServersName() {\n    local realityDestDomainList=\n    if [[ \"${coreInstallType}\" == \"1\" || \"${selectCoreType}\" == \"1\" ]]; then\n        realityDestDomainList=\"gateway.icloud.com,itunes.apple.com,swdist.apple.com,swcdn.apple.com,updates.cdn-apple.com,mensura.cdn-apple.com,osxapps.itunes.apple.com,aod.itunes.apple.com,download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,cdn-dynmedia-1.microsoft.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,lol.secure.dyn.riotcdn.net,www.lovelive-anime.jp,academy.nvidia.com,software.download.prss.microsoft.com,dl.google.com,www.google-analytics.com,www.caltech.edu,www.calstatela.edu,www.suny.edu,www.suffolk.edu,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.java.com,www.oracle.com,www.mysql.com,www.mongodb.com,redis.io,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.umcg.nl,www.fom-international.com,www.u-can.co.jp,github.io\"\n    elif [[ \"${coreInstallType}\" == \"2\" || \"${selectCoreType}\" == \"2\" ]]; then\n        realityDestDomainList=\"gateway.icloud.com,itunes.apple.com,swdist.apple.com,swcdn.apple.com,updates.cdn-apple.com,mensura.cdn-apple.com,osxapps.itunes.apple.com,aod.itunes.apple.com,download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,cdn-dynmedia-1.microsoft.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,lol.secure.dyn.riotcdn.net,www.lovelive-anime.jp,academy.nvidia.com,software.download.prss.microsoft.com,dl.google.com,www.google-analytics.com,www.python.org,vuejs-jp.org,vuejs.org,zh-hk.vuejs.org,react.dev,www.java.com,www.oracle.com,www.mysql.com,www.mongodb.com,cname.vercel-dns.com,vercel-dns.com,www.swift.com,academy.nvidia.com,www.swift.com,www.cisco.com,www.asus.com,www.samsung.com,www.amd.com,www.fom-international.com,github.io\"\n    fi\n    if [[ -n \"${realityServerName}\" && -z \"${lastInstallationConfig}\" ]]; then\n        if echo ${realityDestDomainList} | grep -q \"${realityServerName}\"; then\n            read -r -p \"读取到上次安装设置的Reality域名，是否使用？[y/n]:\" realityServerNameStatus\n            if [[ \"${realityServerNameStatus}\" != \"y\" ]]; then\n                realityServerName=\n                realityDomainPort=\n            fi\n        else\n            realityServerName=\n            realityDomainPort=\n        fi\n    elif [[ -n \"${realityServerName}\" && -z \"${lastInstallationConfig}\" ]]; then\n        realityServerName=\n        realityDomainPort=\n    fi\n\n    if [[ -z \"${realityServerName}\" ]]; then\n        if [[ -n \"${domain}\" ]]; then\n            echo\n            read -r -p \"是否使用 ${domain} 此域名作为Reality目标域名 ？[y/n]:\" realityServerNameCurrentDomainStatus\n            if [[ \"${realityServerNameCurrentDomainStatus}\" == \"y\" ]]; then\n                realityServerName=\"${domain}\"\n                if [[ \"${selectCoreType}\" == \"1\" ]]; then\n                    if [[ -z \"${subscribePort}\" ]]; then\n                        echo\n                        installSubscribe\n                        readNginxSubscribe\n                        realityDomainPort=\"${subscribePort}\"\n                    else\n                        realityDomainPort=\"${subscribePort}\"\n                    fi\n                fi\n                if [[ \"${selectCoreType}\" == \"2\" ]]; then\n                    if [[ -z \"${subscribePort}\" ]]; then\n                        echo\n                        installSubscribe\n                        readNginxSubscribe\n                        realityDomainPort=\"${subscribePort}\"\n                    else\n                        realityDomainPort=\"${subscribePort}\"\n                    fi\n                fi\n            fi\n        fi\n        if [[ -z \"${realityServerName}\" ]]; then\n            realityDomainPort=443\n            echoContent skyBlue \"\\n================ 配置客户端可用的serverNames ===============\\n\"\n            echoContent yellow \"#注意事项\"\n            echoContent green \"Reality目标可用域名列表：https://www.v2ray-agent.com/archives/1689439383686#heading-3\\n\"\n            echoContent yellow \"录入示例:addons.mozilla.org:443\\n\"\n            read -r -p \"请输入目标域名，[回车]随机域名，默认端口443:\" realityServerName\n            if [[ -z \"${realityServerName}\" ]]; then\n                count=$(echo ${realityDestDomainList} | awk -F',' '{print NF}')\n                randomNum=$(randomNum 1 \"${count}\")\n\n                realityServerName=$(echo \"${realityDestDomainList}\" | awk -F ',' -v randomNum=\"$randomNum\" '{print $randomNum}')\n            fi\n            if echo \"${realityServerName}\" | grep -q \":\"; then\n                realityDomainPort=$(echo \"${realityServerName}\" | awk -F \"[:]\" '{print $2}')\n                realityServerName=$(echo \"${realityServerName}\" | awk -F \"[:]\" '{print $1}')\n            fi\n        fi\n    fi\n\n    echoContent yellow \"\\n ---> 客户端可用域名: ${realityServerName}:${realityDomainPort}\\n\"\n}\n# 初始化reality端口\ninitXrayRealityPort() {\n    if [[ -n \"${xrayVLESSRealityPort}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次安装记录，是否使用上次安装时的端口 ？[y/n]:\" historyRealityPortStatus\n        if [[ \"${historyRealityPortStatus}\" == \"y\" ]]; then\n            realityPort=${xrayVLESSRealityPort}\n        fi\n    elif [[ -n \"${xrayVLESSRealityPort}\" && -n \"${lastInstallationConfig}\" ]]; then\n        realityPort=${xrayVLESSRealityPort}\n    fi\n\n    if [[ -z \"${realityPort}\" ]]; then\n        #        if [[ -n \"${port}\" ]]; then\n        #            read -r -p \"是否使用TLS+Vision端口 ？[y/n]:\" realityPortTLSVisionStatus\n        #            if [[ \"${realityPortTLSVisionStatus}\" == \"y\" ]]; then\n        #                realityPort=${port}\n        #            fi\n        #        fi\n        #        if [[ -z \"${realityPort}\" ]]; then\n        echoContent yellow \"请输入端口[回车随机10000-30000]\"\n\n        read -r -p \"端口:\" realityPort\n        if [[ -z \"${realityPort}\" ]]; then\n            realityPort=$((RANDOM % 20001 + 10000))\n        fi\n        #        fi\n        if [[ -n \"${realityPort}\" && \"${xrayVLESSRealityPort}\" == \"${realityPort}\" ]]; then\n            handleXray stop\n        else\n            checkPort \"${realityPort}\"\n        fi\n    fi\n    if [[ -z \"${realityPort}\" ]]; then\n        initXrayRealityPort\n    else\n        allowPort \"${realityPort}\"\n        echoContent yellow \"\\n ---> 端口: ${realityPort}\"\n    fi\n\n}\n# 初始化XHTTP端口\ninitXrayXHTTPort() {\n    if [[ -n \"${xrayVLESSRealityXHTTPort}\" && -z \"${lastInstallationConfig}\" ]]; then\n        read -r -p \"读取到上次安装记录，是否使用上次安装时的端口 ？[y/n]:\" historyXHTTPortStatus\n        if [[ \"${historyXHTTPortStatus}\" == \"y\" ]]; then\n            xHTTPort=${xrayVLESSRealityXHTTPort}\n        fi\n    elif [[ -n \"${xrayVLESSRealityXHTTPort}\" && -n \"${lastInstallationConfig}\" ]]; then\n        xHTTPort=${xrayVLESSRealityXHTTPort}\n    fi\n\n    if [[ -z \"${xHTTPort}\" ]]; then\n\n        echoContent yellow \"请输入端口[回车随机10000-30000]\"\n        read -r -p \"端口:\" xHTTPort\n        if [[ -z \"${xHTTPort}\" ]]; then\n            xHTTPort=$((RANDOM % 20001 + 10000))\n        fi\n        if [[ -n \"${xHTTPort}\" && \"${xrayVLESSRealityXHTTPort}\" == \"${xHTTPort}\" ]]; then\n            handleXray stop\n        else\n            checkPort \"${xHTTPort}\"\n        fi\n    fi\n    if [[ -z \"${xHTTPort}\" ]]; then\n        initXrayXHTTPort\n    else\n        allowPort \"${xHTTPort}\"\n        allowPort \"${xHTTPort}\" \"udp\"\n        echoContent yellow \"\\n ---> 端口: ${xHTTPort}\"\n    fi\n}\n\n# reality管理\nmanageReality() {\n    readInstallProtocolType\n    readConfigHostPathUUID\n    readCustomPort\n    readSingBoxConfig\n\n    if ! echo \"${currentInstallProtocolType}\" | grep -q -E \"7,|8,\" || [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n ---> 请先安装Reality协议，参考教程 https://www.v2ray-agent.com/archives/1680104902581#heading-11\"\n        exit 0\n    fi\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        selectCustomInstallType=\",7,\"\n        initXrayConfig custom 1 true\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        if echo \"${currentInstallProtocolType}\" | grep -q \",7,\"; then\n            selectCustomInstallType=\",7,\"\n        fi\n        if echo \"${currentInstallProtocolType}\" | grep -q \",8,\"; then\n            selectCustomInstallType=\"${selectCustomInstallType},8,\"\n        fi\n        initSingBoxConfig custom 1 true\n    fi\n\n    reloadCore\n    subscribe false\n}\n\n# 安装reality scanner\ninstallRealityScanner() {\n    if [[ ! -f \"/etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64\" ]]; then\n        version=$(curl -s https://api.github.com/repos/XTLS/RealiTLScanner/releases?per_page=1 | jq -r '.[]|.tag_name')\n        wget -c -q -P /etc/v2ray-agent/xray/reality_scan/ \"https://github.com/XTLS/RealiTLScanner/releases/download/${version}/RealiTLScanner-linux-64\"\n        chmod 655 /etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64\n    fi\n}\n# reality scanner\nrealityScanner() {\n    echoContent skyBlue \"\\n进度 1/1 : 扫描Reality域名\"\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"# 注意事项\"\n    echoContent yellow \"扫描完成后，请自行检查扫描网站结果内容是否合规，需个人承担风险\"\n    echoContent red \"某些IDC不允许扫描操作，比如搬瓦工，其中风险请自行承担\\n\"\n    echoContent yellow \"1.扫描IPv4\"\n    echoContent yellow \"2.扫描IPv6\"\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" realityScannerStatus\n    local type=\n    if [[ \"${realityScannerStatus}\" == \"1\" ]]; then\n        type=4\n    elif [[ \"${realityScannerStatus}\" == \"2\" ]]; then\n        type=6\n    fi\n\n    read -r -p \"某些IDC不允许扫描操作，比如搬瓦工，其中风险请自行承担，是否继续？[y/n]:\" scanStatus\n\n    if [[ \"${scanStatus}\" != \"y\" ]]; then\n        exit 0\n    fi\n\n    publicIP=$(getPublicIP \"${type}\")\n    echoContent yellow \"IP:${publicIP}\"\n    if [[ -z \"${publicIP}\" ]]; then\n        echoContent red \" ---> 无法获取IP\"\n        exit 0\n    fi\n\n    read -r -p \"IP是否正确？[y/n]:\" ipStatus\n    if [[ \"${ipStatus}\" == \"y\" ]]; then\n        echoContent yellow \"结果存储在 /etc/v2ray-agent/xray/reality_scan/result.log 文件中\\n\"\n        /etc/v2ray-agent/xray/reality_scan/RealiTLScanner-linux-64 -addr \"${publicIP}\" | tee /etc/v2ray-agent/xray/reality_scan/result.log\n    else\n        echoContent red \" ---> 无法读取正确IP\"\n    fi\n}\n# hysteria管理\nmanageHysteria() {\n    echoContent skyBlue \"\\n进度  1/1 : Hysteria2 管理\"\n    echoContent red \"\\n==============================================================\"\n    local hysteria2Status=\n    if [[ -n \"${singBoxConfigPath}\" ]] && [[ -f \"/etc/v2ray-agent/sing-box/conf/config/06_hysteria2_inbounds.json\" ]]; then\n        echoContent yellow \"依赖第三方sing-box\\n\"\n        echoContent yellow \"1.重新安装\"\n        echoContent yellow \"2.卸载\"\n        echoContent yellow \"3.端口跳跃管理\"\n        hysteria2Status=true\n    else\n        echoContent yellow \"依赖sing-box内核\\n\"\n        echoContent yellow \"1.安装\"\n    fi\n\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" installHysteria2Status\n    if [[ \"${installHysteria2Status}\" == \"1\" ]]; then\n        singBoxHysteria2Install\n    elif [[ \"${installHysteria2Status}\" == \"2\" && \"${hysteria2Status}\" == \"true\" ]]; then\n        unInstallSingBox hysteria2\n    elif [[ \"${installHysteria2Status}\" == \"3\" && \"${hysteria2Status}\" == \"true\" ]]; then\n        portHoppingMenu hysteria2\n    fi\n}\n\n# tuic管理\nmanageTuic() {\n    echoContent skyBlue \"\\n进度  1/1 : Tuic管理\"\n    echoContent red \"\\n==============================================================\"\n    local tuicStatus=\n    if [[ -n \"${singBoxConfigPath}\" ]] && [[ -f \"/etc/v2ray-agent/sing-box/conf/config/09_tuic_inbounds.json\" ]]; then\n        echoContent yellow \"依赖sing-box内核\\n\"\n        echoContent yellow \"1.重新安装\"\n        echoContent yellow \"2.卸载\"\n        echoContent yellow \"3.端口跳跃管理\"\n        tuicStatus=true\n    else\n        echoContent yellow \"依赖sing-box内核\\n\"\n        echoContent yellow \"1.安装\"\n    fi\n\n    echoContent red \"==============================================================\"\n    read -r -p \"请选择:\" installTuicStatus\n    if [[ \"${installTuicStatus}\" == \"1\" ]]; then\n        singBoxTuicInstall\n    elif [[ \"${installTuicStatus}\" == \"2\" && \"${tuicStatus}\" == \"true\" ]]; then\n        unInstallSingBox tuic\n    elif [[ \"${installTuicStatus}\" == \"3\" && \"${tuicStatus}\" == \"true\" ]]; then\n        portHoppingMenu tuic\n    fi\n}\n# sing-box log日志\nsingBoxLog() {\n    cat <<EOF >/etc/v2ray-agent/sing-box/conf/config/log.json\n{\n  \"log\": {\n    \"disabled\": $1,\n    \"level\": \"debug\",\n    \"output\": \"/etc/v2ray-agent/sing-box/conf/box.log\",\n    \"timestamp\": true\n  }\n}\nEOF\n\n    handleSingBox stop\n    handleSingBox start\n}\n\n# sing-box 版本管理\nsingBoxVersionManageMenu() {\n    echoContent skyBlue \"\\n进度  $1/${totalProgress} : sing-box 版本管理\"\n    if [[ -z \"${singBoxConfigPath}\" ]]; then\n        echoContent red \" ---> 没有检测到安装程序，请执行脚本安装内容\"\n        menu\n        exit 0\n    fi\n    echoContent red \"\\n==============================================================\"\n    echoContent yellow \"1.升级 sing-box\"\n    echoContent yellow \"2.关闭 sing-box\"\n    echoContent yellow \"3.打开 sing-box\"\n    echoContent yellow \"4.重启 sing-box\"\n    echoContent yellow \"==============================================================\"\n    local logStatus=\n    if [[ -n \"${singBoxConfigPath}\" && -f \"${singBoxConfigPath}log.json\" && \"$(jq -r .log.disabled \"${singBoxConfigPath}log.json\")\" == \"false\" ]]; then\n        echoContent yellow \"5.关闭日志\"\n        logStatus=true\n    else\n        echoContent yellow \"5.启用日志\"\n        logStatus=false\n    fi\n\n    echoContent yellow \"6.查看日志\"\n    echoContent red \"==============================================================\"\n\n    read -r -p \"请选择:\" selectSingBoxType\n    if [[ ! -f \"${singBoxConfigPath}../box.log\" ]]; then\n        touch \"${singBoxConfigPath}../box.log\" >/dev/null 2>&1\n    fi\n    if [[ \"${selectSingBoxType}\" == \"1\" ]]; then\n        installSingBox 1\n        handleSingBox stop\n        handleSingBox start\n    elif [[ \"${selectSingBoxType}\" == \"2\" ]]; then\n        handleSingBox stop\n    elif [[ \"${selectSingBoxType}\" == \"3\" ]]; then\n        handleSingBox start\n    elif [[ \"${selectSingBoxType}\" == \"4\" ]]; then\n        handleSingBox stop\n        handleSingBox start\n    elif [[ \"${selectSingBoxType}\" == \"5\" ]]; then\n        singBoxLog ${logStatus}\n        if [[ \"${logStatus}\" == \"false\" ]]; then\n            tail -f \"${singBoxConfigPath}../box.log\"\n        fi\n    elif [[ \"${selectSingBoxType}\" == \"6\" ]]; then\n        tail -f \"${singBoxConfigPath}../box.log\"\n    fi\n}\n\n# 主菜单\nmenu() {\n    cd \"$HOME\" || exit\n    echoContent red \"\\n==============================================================\"\n    echoContent green \"作者：mack-a\"\n    echoContent green \"当前版本：v3.5.9\"\n    echoContent green \"Github：https://github.com/mack-a/v2ray-agent\"\n    echoContent green \"描述：八合一共存脚本\\c\"\n    showInstallStatus\n    checkWgetShowProgress\n    echoContent red \"\\n=========================== 推广区============================\"\n    echoContent red \"                                              \"\n    echoContent yellow \"VPS选购攻略\"\n    echoContent green \"https://www.v2ray-agent.com/archives/1679975663984\"\n    echoContent yellow \"年付10美金低价VPS AS4837\"\n    echoContent green \"https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan\"\n    echoContent yellow \"优质常驻套餐DMIT CN2-GIA\"\n    echoContent green \"https://www.v2ray-agent.com/archives/186cee7b-9459-4e57-b9b2-b07a4f36931c\"\n    echoContent yellow \"VPS探针：https://ping.v2ray-agent.com/\"\n    echoContent red \"                                              \"\n    echoContent red \"==============================================================\"\n    if [[ -n \"${coreInstallType}\" ]]; then\n        echoContent yellow \"1.重新安装\"\n    else\n        echoContent yellow \"1.安装\"\n    fi\n\n    echoContent yellow \"2.任意组合安装\"\n    echoContent yellow \"3.一键无域名Reality\"\n    echoContent yellow \"4.Hysteria2管理\"\n    echoContent yellow \"5.REALITY管理\"\n    echoContent yellow \"6.Tuic管理\"\n\n    echoContent skyBlue \"-------------------------工具管理-----------------------------\"\n    echoContent yellow \"7.用户管理\"\n    echoContent yellow \"8.伪装站管理\"\n    echoContent yellow \"9.证书管理\"\n    echoContent yellow \"10.CDN节点管理\"\n    echoContent yellow \"11.分流工具\"\n    echoContent yellow \"12.添加新端口\"\n    echoContent yellow \"13.BT下载管理\"\n    echoContent yellow \"15.域名黑名单\"\n    echoContent skyBlue \"-------------------------版本管理-----------------------------\"\n    echoContent yellow \"16.core管理\"\n    echoContent yellow \"17.更新脚本\"\n    echoContent yellow \"18.安装BBR、DD脚本\"\n    echoContent skyBlue \"-------------------------脚本管理-----------------------------\"\n    echoContent yellow \"20.卸载脚本\"\n    echoContent red \"==============================================================\"\n    mkdirTools\n    aliasInstall\n    read -r -p \"请选择:\" selectInstallType\n    case ${selectInstallType} in\n    1)\n        selectCoreInstall\n        ;;\n    2)\n        selectCoreInstall\n        ;;\n    3)\n        selectCoreInstall\n        ;;\n    4)\n        manageHysteria\n        ;;\n    5)\n        manageReality 1\n        ;;\n    6)\n        manageTuic\n        ;;\n    7)\n        manageAccount 1\n        ;;\n    8)\n        updateNginxBlog 1\n        ;;\n    9)\n        renewalTLS 1\n        ;;\n    10)\n        manageCDN 1\n        ;;\n    11)\n        routingToolsMenu 1\n        ;;\n    12)\n        addCorePort 1\n        ;;\n    13)\n        btTools 1\n        ;;\n    14)\n        switchAlpn 1\n        ;;\n    15)\n        blacklist 1\n        ;;\n    16)\n        coreVersionManageMenu 1\n        ;;\n    17)\n        updateV2RayAgent 1\n        ;;\n    18)\n        bbrInstall\n        ;;\n    20)\n        unInstall 1\n        ;;\n    esac\n}\ncronFunction\nmenu\n"
  },
  {
    "path": "shell/empty_login_history.sh",
    "content": "#!/usr/bin/env bash\n# 清空访问日志\n# wget -P /tmp -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/shell/empty_login_history.sh\" && chmod 700 /tmp/empty_login_history.sh && /tmp/empty_login_history.sh\necho \"清空中\"\necho > /var/log/wtmp\necho > /var/log/btmp\necho > /var/log/lastlog\necho > ~/.bash_history\necho \"清空完毕\"\necho \"删除脚本\"\nrm -rf /tmp/empty_login_history.sh\nhistory -c\necho \"done\"\n"
  },
  {
    "path": "shell/init_tls.sh",
    "content": "#!/usr/bin/env bash\ninstallType='yum -y install'\nremoveType='yum -y remove'\nupgrade=\"yum -y update\"\nechoType='echo -e'\ncp=`which cp`\n# 打印\nechoColor(){\n    case $1 in\n        # 红色\n        \"red\")\n            ${echoType} \"\\033[31m$2 \\033[0m\"\n        ;;\n        # 天蓝色\n        \"skyBlue\")\n            ${echoType} \"\\033[36m$2 \\033[0m\"\n        ;;\n        # 绿色\n        \"green\")\n            ${echoType} \"\\033[32m$2 \\033[0m\"\n        ;;\n        # 白色\n        \"white\")\n            ${echoType} \"\\033[37m$2 \\033[0m\"\n        ;;\n        \"magenta\")\n            ${echoType} \"\\033[31m$2 \\033[0m\"\n        ;;\n        \"skyBlue\")\n            ${echoType} \"\\033[36m$2 \\033[0m\"\n        ;;\n        # 黄色\n        \"yellow\")\n            ${echoType} \"\\033[33m$2 \\033[0m\"\n        ;;\n    esac\n}\n# 选择系统执行工具\ncheckSystem(){\n\n\tif [[ ! -z `find /etc -name \"redhat-release\"` ]] || [[ ! -z `cat /proc/version | grep -i \"centos\" | grep -v grep ` ]] || [[ ! -z `cat /proc/version | grep -i \"red hat\" | grep -v grep ` ]] || [[ ! -z `cat /proc/version | grep -i \"redhat\" | grep -v grep ` ]]\n\tthen\n\t\trelease=\"centos\"\n\t\tinstallType='yum -y install'\n\t\tremoveType='yum -y remove'\n\t\tupgrade=\"yum update -y\"\n\telif [[ ! -z `cat /etc/issue | grep -i \"debian\" | grep -v grep` ]] || [[ ! -z `cat /proc/version | grep -i \"debian\" | grep -v grep` ]]\n    then\n\t\trelease=\"debian\"\n\t\tinstallType='apt -y install'\n\t\tupgrade=\"apt update -y\"\n\t\tremoveType='apt -y autoremove'\n\telif [[ ! -z `cat /etc/issue | grep -i \"ubuntu\" | grep -v grep` ]] || [[ ! -z `cat /proc/version | grep -i \"ubuntu\" | grep -v grep` ]]\n\tthen\n\t\trelease=\"ubuntu\"\n\t\tinstallType='apt -y install'\n\t\tupgrade=\"apt update -y\"\n\t\tremoveType='apt --purge remove'\n    fi\n    if [[ -z ${release} ]]\n    then\n        echoContent red \"本脚本不支持此系统，请将下方日志反馈给开发者\"\n        cat /etc/issue\n        cat /proc/version\n        exit 0;\n    fi\n}\n# 安装工具包\ninstallTools(){\n    echoColor yellow \"更新\"\n    ${upgrade}\n    if [[ -z `find /usr/bin/ -executable -name \"socat\"` ]]\n    then\n        echoColor yellow \"\\nsocat未安装，安装中\\n\"\n        ${installType} socat >/dev/null\n        echoColor green \"socat安装完毕\"\n    fi\n    echoColor yellow \"\\n检测是否安装Nginx\"\n    if [[ -z `find /sbin/ -executable -name 'nginx'` ]]\n    then\n        echoColor yellow \"nginx未安装，安装中\\n\"\n        ${installType} nginx >/dev/null\n        echoColor green \"nginx安装完毕\"\n    else\n        echoColor green \"nginx已安装\\n\"\n    fi\n    echoColor yellow \"检测是否安装acme.sh\"\n    if [[ -z `find ~/.acme.sh/ -name \"acme.sh\"` ]]\n    then\n        echoColor yellow \"\\nacme.sh未安装，安装中\\n\"\n        curl -s https://get.acme.sh | sh >/dev/null\n        echoColor green \"acme.sh安装完毕\\n\"\n    else\n        echoColor green \"acme.sh已安装\\n\"\n    fi\n\n}\n# 恢复配置\nresetNginxConfig(){\n    `cp -Rrf /tmp/mack-a/nginx/nginx.conf /etc/nginx/nginx.conf`\n    rm -rf /etc/nginx/conf.d/5NX2O9XQKP.conf\n    echoColor green \"\\n恢复配置完毕\"\n}\n# 备份\nbakConfig(){\n    mkdir -p /tmp/mack-a/nginx\n    `cp -Rrf /etc/nginx/nginx.conf /tmp/mack-a/nginx/nginx.conf`\n}\n# 安装证书\ninstallTLS(){\n    echoColor yellow \"请输入域名【例:blog.v2ray-agent.com】：\"\n    read domain\n    if [[ -z ${domain} ]]\n    then\n        echoColor red \"域名未填写\\n\"\n        installTLS\n    fi\n    # 备份\n    bakConfig\n    # 替换原始文件中的域名\n    if [[ ! -z `cat /etc/nginx/nginx.conf|grep -v grep|grep \"${domain}\"` ]]\n    then\n        sed -i \"s/${domain}/X655Y0M9UM9/g\"  `grep \"${domain}\" -rl /etc/nginx/nginx.conf`\n    fi\n\n    touch /etc/nginx/conf.d/6GFV1ES52V2.conf\n    echo \"server {listen 80;server_name ${domain};root /usr/share/nginx/html;location ~ /.well-known {allow all;}location /test {return 200 '5NX2O9XQKP';}}\" > /etc/nginx/conf.d/5NX2O9XQKP.conf\n    nginxStatus=1;\n    if [[ ! -z `ps -ef|grep -v grep|grep nginx` ]]\n    then\n        nginxStatus=2;\n        ps -ef|grep -v grep|grep nginx|awk '{print $2}'|xargs kill -9\n        sleep 0.5\n        nginx\n    else\n        nginx\n    fi\n    echoColor yellow \"\\n验证域名以及服务器是否可用\"\n    if [[ ! -z `curl -s ${domain}/test|grep 5NX2O9XQKP` ]]\n    then\n        ps -ef|grep -v grep|grep nginx|awk '{print $2}'|xargs kill -9\n        sleep 0.5\n        echoColor green \"服务可用，生成TLS中，请等待\\n\"\n    else\n        echoColor red \"服务不可用请检测dns配置是否正确\"\n        # 恢复备份\n        resetNginxConfig\n        exit 0;\n    fi\n    sudo ~/.acme.sh/acme.sh --issue -d ${domain} --standalone -k ec-256 >/dev/null\n    ~/.acme.sh/acme.sh --installcert -d ${domain} --fullchainpath /tmp/mack-a/nginx/${domain}.crt --keypath /tmp/mack-a/nginx/${domain}.key --ecc >/dev/null\n    if [[ -z `cat /tmp/mack-a/nginx/${domain}.key` ]]\n    then\n        echoColor red \"证书key生成失败，请重新运行\"\n        resetNginxConfig\n        exit\n    elif [[ -z `cat /tmp/mack-a/nginx/${domain}.crt` ]]\n    then\n        echoColor red \"证书crt生成失败，请重新运行\"\n        resetNginxConfig\n        exit\n    fi\n    echoColor green \"证书生成成功\"\n    echoColor green \"证书目录/tmp/mack-a/nginx\"\n    ls /tmp/mack-a/nginx\n\n    resetNginxConfig\n    if [[ ${nginxStatus} = 2  ]]\n    then\n        nginx\n    fi\n}\n\ninit(){\n    echoColor red \"\\n==============================\"\n    echoColor yellow \"此脚本注意事项\"\n    echoColor green \"   1.会安装依赖所需依赖\"\n    echoColor green \"   2.会把Nginx配置文件备份\"\n    echoColor green \"   3.会安装Nginx、acme.sh，如果已安装则使用已经存在的\"\n    echoColor green \"   4.安装完毕或者安装失败会自动恢复备份，请不要手动关闭脚本\"\n    echoColor green \"   5.执行期间请不要重启机器\"\n    echoColor green \"   6.备份文件和证书文件都在/tmp下面，请注意留存\"\n    echoColor green \"   7.如果多次执行则将上次生成备份和生成的证书强制覆盖\"\n    echoColor green \"   8.证书默认ec-256\"\n    echoColor green \"   9.下个版本会加入通配符证书生成[todo]\"\n    echoColor green \"   10.可以生成多个不同域名的证书[包含子域名]，具体速率请查看[https://letsencrypt.org/zh-cn/docs/rate-limits/]\"\n    echoColor green \"   11.兼容Centos、Ubuntu、Debian\"\n    echoColor green \"   12.Github[https://github.com/mack-a]\"\n    echoColor red \"==============================\"\n    echoColor yellow \"请输入[y]执行脚本，[任意]结束:\"\n    read isExecStatus\n    if [[ ${isExecStatus} = \"y\" ]]\n    then\n        installTools\n        installTLS\n    else\n        echoColor green \"欢迎下次使用\"\n        exit\n    fi\n}\ncheckSystem\ninit\n"
  },
  {
    "path": "shell/install_en.sh",
    "content": "#!/usr/bin/env bash\n# Detection area\n#------------------------------------------------ ----------\n# Check system\nexport LANG=en_US.UTF-8\n\nechoContent() {\n    case $1 in\n    # red\n    \"red\")\n        # shellcheck disable=SC2154\n        ${echoType} \"\\033[31m${printN}$2 \\033[0m\"\n        ;;\n        # sky blue\n    \"skyBlue\")\n        ${echoType} \"\\033[1;36m${printN}$2 \\033[0m\"\n        ;;\n        # green\n    \"green\")\n        ${echoType} \"\\033[32m${printN}$2 \\033[0m\"\n        ;;\n        # White\n    \"white\")\n        ${echoType} \"\\033[37m${printN}$2 \\033[0m\"\n        ;;\n    \"magenta\")\n        ${echoType} \"\\033[31m${printN}$2 \\033[0m\"\n        ;;\n        #yellow\n    \"yellow\")\n        ${echoType} \"\\033[33m${printN}$2 \\033[0m\"\n        ;;\n    esac\n}\n# Check SELinux status\ncheckCentosSELinux() {\n    if [[ -f \"/etc/selinux/config\" ]] && ! grep -q \"SELINUX=disabled\" <\"/etc/selinux/config\"; then\n        echoContent yellow \"# Notes\"\n        echoContent yellow \"It is detected that SELinux is turned on. Please turn it off manually. The tutorial is as follows\"\n        echoContent yellow \"https://www.v2ray-agent.com/archives/1679931532764#heading-8 \"\n        exit 0\n    fi\n}\ncheckSystem() {\n    if [[ -n $(find /etc -name \"redhat-release\") ]] || grep </proc/version -q -i \"centos\"; then\n        mkdir -p /etc/yum.repos.d\n\n        if [[ -f \"/etc/centos-release\" ]]; then\n            centosVersion=$(rpm -q centos-release | awk -F \"[-]\" '{print $3}' | awk -F \"[.]\" '{print $1}')\n\n            if [[ -z \"${centosVersion}\" ]] && grep </etc/centos-release -q -i \"release 8\"; then\n                centosVersion=8\n            fi\n        fi\n\n        release=\"centos\"\n        installType='yum -y install'\n        removeType='yum -y remove'\n        upgrade=\"yum update -y --skip-broken\"\n        checkCentosSELinux\n    elif [[ -f \"/etc/issue\" ]] && grep </etc/issue -q -i \"debian\" || [[ -f \"/proc/version\" ]] && grep </etc/issue -q -i \"debian\" || [[ -f \"/etc/os-release\" ]] && grep </etc/os-release -q -i \"ID=debian\"; then\n        release=\"debian\"\n        installType='apt -y install'\n        upgrade=\"apt update\"\n        updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'\n        removeType='apt -y autoremove'\n\n    elif [[ -f \"/etc/issue\" ]] && grep </etc/issue -q -i \"ubuntu\" || [[ -f \"/proc/version\" ]] && grep </etc/issue -q -i \"ubuntu\"; then\n        release=\"ubuntu\"\n        installType='apt -y install'\n        upgrade=\"apt update\"\n        updateReleaseInfoChange='apt-get --allow-releaseinfo-change update'\n        removeType='apt -y autoremove'\n        if grep </etc/issue -q -i \"16.\"; then\n            release=\n        fi\n    fi\n\n    if [[ -z ${release} ]]; then\n        echoContent red \"\\nThis script does not support this system, please feedback the following log to the developer\\n\"\n        echoContent yellow \"$(cat /etc/issue)\"\n        echoContent yellow \"$(cat /proc/version)\"\n        exit 0\n    fi\n}\n\n# Check CPU provider\ncheckCPUVendor() {\n    if [[ -n $(which uname) ]]; then\n        if [[ \"$(uname)\" == \"Linux\" ]]; then\n            case \"$(uname -m)\" in\n            'amd64' | 'x86_64')\n                xrayCoreCPUVendor=\"Xray-linux-64\"\n                v2rayCoreCPUVendor=\"v2ray-linux-64\"\n                hysteriaCoreCPUVendor=\"hysteria-linux-amd64\"\n                tuicCoreCPUVendor=\"-x86_64-unknown-linux-musl\"\n                warpRegCoreCPUVendor=\"main-linux-amd64\"\n                ;;\n            'armv8' | 'aarch64')\n                cpuVendor=\"arm\"\n                xrayCoreCPUVendor=\"Xray-linux-arm64-v8a\"\n                v2rayCoreCPUVendor=\"v2ray-linux-arm64-v8a\"\n                hysteriaCoreCPUVendor=\"hysteria-linux-arm64\"\n                tuicCoreCPUVendor=\"-aarch64-unknown-linux-musl\"\n                warpRegCoreCPUVendor=\"main-linux-arm64\"\n                ;;\n            *)\n                echo \"This CPU architecture is not supported --->\"\n                exit 1\n                ;;\n            esac\n        fi\n    else\n        echoContent red \"This CPU architecture cannot be recognized, the default is amd64, x86_64--->\"\n        xrayCoreCPUVendor=\"Xray-linux-64\"\n        v2rayCoreCPUVendor=\"v2ray-linux-64\"\n    fi\n}\n\n#Initialize global variables\ninitVar() {\n    installType='yum -y install'\n    removeType='yum -y remove'\n    upgrade=\"yum -y update\"\n    echoType='echo -e'\n\n    #CPU version supported by the core\n    xrayCoreCPUVendor=\"\"\n    v2rayCoreCPUVendor=\"\"\n    hysteriaCoreCPUVendor=\"\"\n    warpRegCoreCPUVendor=\"\"\n    cpuVendor=\"\"\n\n    # domain name\n    domain=\n\n    #Address of CDN node\n    add=\n\n    # Total installation progress\n    totalProgress=1\n\n    #1.xray-core installation\n    #2.v2ray-core installation\n    #3.v2ray-core[xtls] installation\n    coreInstallType=\n\n    # Core installation path\n    # coreInstallPath=\n\n    # v2ctl Path\n    ctlPath=\n    #1.Install all\n    #2.Personalized installation\n    # v2rayAgentInstallType=\n\n    # Current personalized installation method 01234\n    currentInstallProtocolType=\n\n    # The order of the current alpn\n    currentAlpn=\n\n    # Prefix type\n    frontingType=\n\n    # Selected personalized installation method\n    selectCustomInstallType=\n\n    # Path to v2ray-core, xray-core configuration files\n    configPath=\n\n    # xray-core reality state\n    realityStatus=\n\n    # Path to hysteria configuration file\n    hysteriaConfigPath=\n    # interfaceName=\n    # Port hopping\n    portHoppingStart=\n    portHoppingEnd=\n    portHopping=\n\n    # tuic configuration file path\n    tuicConfigPath=\n    tuicAlgorithm=\n    tuicPort=\n\n    # Path to configuration file\n    currentPath=\n\n    #Configuration file host\n    currentHost=\n\n    #The core type selected during installation\n    selectCoreType=\n\n    #Default core version\n    v2rayCoreVersion=\n\n    # Random path\n    customPath=\n\n    # centos version\n    centosVersion=\n\n    #UUID\n    currentUUID=\n\n    #clients\n    currentClients=\n\n    # previousClients\n    previousClients=\n\n    localIP=\n\n    # Scheduled task execution task name RenewTLS-update certificate UpdateGeo-update geo file\n    cronName=$1\n\n    #Number of attempts after tls installation failure\n    installTLSCount=\n\n    #BTPanel status\n    # \tBTPanelStatus=\n    # Pagoda domain name\n    btDomain=\n    # nginx configuration file path\n    nginxConfigPath=/etc/nginx/conf.d/\n    nginxStaticPath=/usr/share/nginx/html/\n\n    # Is it a preview version?\n    prereleaseStatus=false\n\n    # ssl type\n    sslType=\n\n    #sslmail\n    sslEmail=\n\n    # Check the number of days\n    sslRenewalDays=90\n\n    # dns ssl status\n    dnsSSLStatus=\n\n    # dns tls domain\n    dnsTLSDomain=\n\n    # Whether the domain name installs a wildcard certificate through dns\n    installDNSACMEStatus=\n\n    # Custom port\n    customPort=\n\n    #hysteriaport\n    hysteriaPort=\n\n    #hysteriaprotocol\n    hysteriaProtocol=\n\n    #hysteriadelay\n    hysteriaLag=\n\n    # hysteriadownload speed\n    hysteriaClientDownloadSpeed=\n\n    # hysteria uplink speed\n    hysteriaClientUploadSpeed=\n\n    #Reality\n    realityPrivateKey=\n    realityServerNames=\n    realityDestDomain=\n\n    #Port status\n    # isPortOpen=\n    # Wildcard domain name status\n    # wildcardDomainStatus=\n    # Port checked by nginx\n    #nginxIPort=\n\n    # wget show progress\n    wgetShowProgressStatus=\n\n    #warp\n    reservedWarpReg=\n    publicKeyWarpReg=\n    addressWarpReg=\n    secretKeyWarpReg=\n}\n\n# Read tls certificate details\nreadAcmeTLS() {\n    if [[ -n \"${currentHost}\" ]]; then\n        dnsTLSDomain=$(echo \"${currentHost}\" | awk -F \"[.]\" '{print $(NF-1)\".\"$NF}')\n    fi\n    if [[ -d \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc\" && -f \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.key\" && -f \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer\" ]]; then\n        installDNSACMEStatus=true\n    fi\n}\n# Read the default custom port\nreadCustomPort() {\n    if [[ -n \"${configPath}\" && -z \"${realityStatus}\" ]]; then\n        local port=\n        port=$(jq -r .inbounds[0].port \"${configPath}${frontingType}.json\")\n        if [[ \"${port}\" != \"443\" ]]; then\n            customPort=${port}\n        fi\n    fi\n}\n# Detect installation method\nreadInstallType() {\n    coreInstallType=\n    configPath=\n    hysteriaConfigPath=\n\n    #1.Detect the installation directory\n    if [[ -d \"/etc/v2ray-agent\" ]]; then\n        # Detect installation method v2ray-core\n        if [[ -d \"/etc/v2ray-agent/v2ray\" && -f \"/etc/v2ray-agent/v2ray/v2ray\" && -f \"/etc/v2ray-agent/v2ray/v2ctl\" ]]; then\n            if [[ -d \"/etc/v2ray-agent/v2ray/conf\" && -f \"/etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json\" ]]; then\n                configPath=/etc/v2ray-agent/v2ray/conf/\n                if grep </etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json -q '\"security\": \"tls\"'; then\n                    coreInstallType=2\n                    ctlPath=/etc/v2ray-agent/v2ray/v2ctl\n                fi\n            fi\n        fi\n\n        if [[ -d \"/etc/v2ray-agent/xray\" && -f \"/etc/v2ray-agent/xray/xray\" ]]; then\n            # Detect xray-core here\n            if [[ -d \"/etc/v2ray-agent/xray/conf\" ]] && [[ -f \"/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json\" || -f \"/etc/v2ray-agent/xray/conf/02_trojan_TCP_inbounds.json\" || -f \"/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json\" ]]; then\n                #xray-core\n                configPath=/etc/v2ray-agent/xray/conf/\n                ctlPath=/etc/v2ray-agent/xray/xray\n                coreInstallType=1\n                if [[ -f \"${configPath}07_VLESS_vision_reality_inbounds.json\" ]]; then\n                    realityStatus=1\n                fi\n            fi\n        fi\n\n        if [[ -d \"/etc/v2ray-agent/hysteria\" && -f \"/etc/v2ray-agent/hysteria/hysteria\" ]]; then\n            # Detect hysteria here\n            if [[ -d \"/etc/v2ray-agent/hysteria/conf\" ]] && [[ -f \"/etc/v2ray-agent/hysteria/conf/config.json\" ]] && [[ -f \"/etc/v2ray-agent/hysteria/conf/client_network.json\" ]]; then\n                hysteriaConfigPath=/etc/v2ray-agent/hysteria/conf/\n            fi\n        fi\n\n        if [[ -d \"/etc/v2ray-agent/tuic\" && -f \"/etc/v2ray-agent/tuic/tuic\" ]]; then\n            if [[ -d \"/etc/v2ray-agent/tuic/conf\" ]] && [[ -f \"/etc/v2ray-agent/tuic/conf/config.json\" ]]; then\n                tuicConfigPath=/etc/v2ray-agent/tuic/conf/\n            fi\n        fi\n    fi\n}\n\n#Read protocol type\nreadInstallProtocolType() {\n    currentInstallProtocolType=\n    frontingType=\n    while read -r row; do\n        if echo \"${row}\" | grep -q 02_trojan_TCP_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'trojan'\n            frontingType=02_trojan_TCP_inbounds\n        fi\n        if echo \"${row}\" | grep -q VLESS_TCP_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'0'\n            frontingType=02_VLESS_TCP_inbounds\n        fi\n        if echo \"${row}\" | grep -q VLESS_WS_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'1'\n        fi\n        if echo \"${row}\" | grep -q trojan_gRPC_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'2'\n        fi\n        if echo \"${row}\" | grep -q VMess_WS_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'3'\n        fi\n        if echo \"${row}\" | grep -q 04_trojan_TCP_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'4'\n        fi\n        if echo \"${row}\" | grep -q VLESS_gRPC_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'5'\n        fi\n        if echo \"${row}\" | grep -q VLESS_vision_reality_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'7'\n        fi\n        if echo \"${row}\" | grep -q VLESS_reality_fallback_grpc_inbounds; then\n            currentInstallProtocolType=${currentInstallProtocolType}'8'\n        fi\n\n    done < <(find ${configPath} -name \"*inbounds.json\" | awk -F \"[.]\" '{print $1}')\n\n    if [[ -n \"${hysteriaConfigPath}\" ]]; then\n        currentInstallProtocolType=${currentInstallProtocolType}'6'\n    fi\n    if [[ -n \"${tuicConfigPath}\" ]]; then\n        currentInstallProtocolType=${currentInstallProtocolType}'9'\n    fi\n}\n\n# Check whether pagoda is installed\ncheckBTPanel() {\n    if [[ -n $(pgrep -f \"BT-Panel\") ]]; then\n        # Read domain name\n        if [[ -d '/www/server/panel/vhost/cert/' && -n $(find /www/server/panel/vhost/cert/*/fullchain.pem) ]]; then\n            if [[ -z \"${currentHost}\" ]]; then\n                echoContent skyBlue \"\\nRead pagoda configuration\\n\"\n\n                find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F \"[/]\" '{print $7}' | awk '{print NR\"\"\":\"$0}'\n\n                read -r -p \"Please enter the number to select:\" selectBTDomain\n            else\n                selectBTDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F \"[/]\" '{print $7}' | awk '{print NR\"\"\":\"$0}' | grep \"${currentHost}\" | cut -d \":\" -f 1)\n            fi\n\n            if [[ -n \"${selectBTDomain}\" ]]; then\n                btDomain=$(find /www/server/panel/vhost/cert/*/fullchain.pem | awk -F \"[/]\" '{print $7}' | awk '{print NR\"\"\":\"$0}' | grep \"${selectBTDomain}:\" | cut -d \":\" -f 2)\n\n                if [[ -z \"${btDomain}\" ]]; then\n                    echoContent red \" ---> Wrong selection, please select again\"\n                    checkBTPanel\n                else\n                    domain=${btDomain}\n                    if [[ ! -f \"/etc/v2ray-agent/tls/${btDomain}.crt\" && ! -f \"/etc/v2ray-agent/tls/${btDomain}.key\" ]]; then\n                        ln -s \"/www/server/panel/vhost/cert/${btDomain}/fullchain.pem\" \"/etc/v2ray-agent/tls/${btDomain}.crt\"\n                        ln -s \"/www/server/panel/vhost/cert/${btDomain}/privkey.pem\" \"/etc/v2ray-agent/tls/${btDomain}.key\"\n                    fi\n\n                    nginxStaticPath=\"/www/wwwroot/${btDomain}/\"\n                    if [[ -f \"/www/wwwroot/${btDomain}/.user.ini\" ]]; then\n                        chattr -i \"/www/wwwroot/${btDomain}/.user.ini\"\n                    fi\n                    nginxConfigPath=\"/www/server/panel/vhost/nginx/\"\n                fi\n            else\n                echoContent red \" ---> Wrong selection, please select again\"\n                checkBTPanel\n            fi\n        fi\n    fi\n}\n# Read the current alpn order\nreadInstallAlpn() {\n    if [[ -n \"${currentInstallProtocolType}\" && -z \"${realityStatus}\" ]]; then\n        local alpn\n        alpn=$(jq -r .inbounds[0].streamSettings.tlsSettings.alpn[0] ${configPath}${frontingType}.json)\n        if [[ -n ${alpn} ]]; then\n            currentAlpn=${alpn}\n        fi\n    fi\n}\n\n# Check firewall\nallowPort() {\n    local type=$2\n    if [[ -z \"${type}\" ]]; then\n        type=tcp\n    fi\n    # If the firewall is enabled, add the corresponding open port\n    if systemctl status netfilter-persistent 2>/dev/null | grep -q \"active (exited)\"; then\n        local updateFirewalldStatus=\n        if ! iptables -L | grep -q \"$1/${type}(mack-a)\"; then\n            updateFirewalldStatus=true\n            iptables -I INPUT -p ${type} --dport \"$1\" -m comment --comment \"allow $1/${type}(mack-a)\" -j ACCEPT\n        fi\n\n        if echo \"${updateFirewalldStatus}\" | grep -q \"true\"; then\n            netfilter-persistent save\n        fi\n    elif systemctl status ufw 2>/dev/null | grep -q \"active (exited)\"; then\n        if ufw status | grep -q \"Status: active\"; then\n            if ! ufw status | grep -q \"$1/${type}\"; then\n                sudo ufw allow \"$1/${type}\"\n                checkUFWAllowPort \"$1\"\n            fi\n        fi\n\n    elif systemctl status firewalld 2>/dev/null | grep -q \"active (running)\"; then\n        local updateFirewalldStatus=\n        if ! firewall-cmd --list-ports --permanent | grep -qw \"$1/${type}\"; then\n            updateFirewalldStatus=true\n            local firewallPort=$1\n\n            if echo \"${firewallPort}\" | grep \":\"; then\n                firewallPort=$(echo \"${firewallPort}\" | awk -F \":\" '{print $1-$2}')\n            fi\n\n            firewall-cmd --zone=public --add-port=\"${firewallPort}/${type}\" --permanent\n            checkFirewalldAllowPort \"${firewallPort}\"\n        fi\n\n        if echo \"${updateFirewalldStatus}\" | grep -q \"true\"; then\n            firewall-cmd --reload\n        fi\n    fi\n}\n# Get public IP\ngetPublicIP() {\n    local type=4\n    if [[ -n \"$1\" ]]; then\n        type=$1\n    fi\n    if [[ -n \"${currentHost}\" && -n \"${currentRealityServerNames}\" && \"${currentRealityServerNames}\" == \"${currentHost}\" && -z \"$1\" ]]; then\n        echo \"${currentHost}\"\n    else\n        local currentIP=\n        currentIP=$(curl -s \"-${type}\" http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | awk -F \"[=]\" '{print $2}')\n        if [[ -z \"${currentIP}\" && -z \"$1\" ]]; then\n            currentIP=$(curl -s \"-6\" http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | awk -F \"[=]\" '{print $2}')\n        fi\n        echo \"${currentIP}\"\n    fi\n\n}\n\n# Output ufw port open status\ncheckUFWAllowPort() {\n    if ufw status | grep -q \"$1\"; then\n        echoContent green \" ---> $1 port opened successfully\"\n    else\n        echoContent red \" ---> $1 port opening failed\"\n        exit 0\n    fi\n}\n\n# Output firewall-cmd port open status\ncheckFirewalldAllowPort() {\n    if firewall-cmd --list-ports --permanent | grep -q \"$1\"; then\n        echoContent green \" ---> $1 port opened successfully\"\n    else\n        echoContent red \" ---> $1 port opening failed\"\n        exit 0\n    fi\n}\n\n# Read hysteria network environment\nreadHysteriaConfig() {\n    if [[ -n \"${hysteriaConfigPath}\" ]]; then\n        hysteriaLag=$(jq -r .hysteriaLag <\"${hysteriaConfigPath}client_network.json\")\n        hysteriaClientDownloadSpeed=$(jq -r .hysteriaClientDownloadSpeed <\"${hysteriaConfigPath}client_network.json\")\n        hysteriaClientUploadSpeed=$(jq -r .hysteriaClientUploadSpeed <\"${hysteriaConfigPath}client_network.json\")\n        hysteriaPort=$(jq -r .listen <\"${hysteriaConfigPath}config.json\" | awk -F \"[:]\" '{print $2}')\n        hysteriaProtocol=$(jq -r .protocol <\"${hysteriaConfigPath}config.json\")\n    fi\n}\n# Read Tuic configuration\nreadTuicConfig() {\n    if [[ -n \"${tuicConfigPath}\" ]]; then\n        tuicPort=$(jq -r .server <\"${tuicConfigPath}config.json\" | cut -d ':' -f 4)\n        tuicAlgorithm=$(jq -r .congestion_control <\"${tuicConfigPath}config.json\")\n    fi\n}\n# Read xray reality configuration\nreadXrayCoreRealityConfig() {\n    currentRealityServerNames=\n    currentRealityPublicKey=\n    currentRealityPrivateKey=\n    currentRealityPort=\n\n    if [[ -n \"${realityStatus}\" ]]; then\n        currentRealityServerNames=$(jq -r .inbounds[0].streamSettings.realitySettings.serverNames[0] \"${configPath}07_VLESS_vision_reality_inbounds.json\")\n        currentRealityPublicKey=$(jq -r .inbounds[0].streamSettings.realitySettings.publicKey \"${configPath}07_VLESS_vision_reality_inbounds.json\")\n        currentRealityPrivateKey=$(jq -r .inbounds[0].streamSettings.realitySettings.privateKey \"${configPath}07_VLESS_vision_reality_inbounds.json\")\n        currentRealityPort=$(jq -r .inbounds[0].port \"${configPath}07_VLESS_vision_reality_inbounds.json\")\n    fi\n}\n\n# Check the file directory and path\nreadConfigHostPathUUID() {\n    currentPath=\n    currentDefaultPort=\n    currentUUID=\n    currentClients=\n    currentHost=\n    currentPort=\n    currentAdd=\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n\n        # Install\n        if [[ -n \"${frontingType}\" ]]; then\n            currentHost=$(jq -r .inbounds[0].streamSettings.tlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}')\n            currentAdd=$(jq -r .inbounds[0].add ${configPath}${frontingType}.json)\n\n            if [[ \"${currentAdd}\" == \"null\" ]]; then\n                currentAdd=${currentHost}\n            fi\n            currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json)\n\n            local defaultPortFile=\n            defaultPortFile=$(find ${configPath}* | grep \"default\")\n\n            if [[ -n \"${defaultPortFile}\" ]]; then\n                currentDefaultPort=$(echo \"${defaultPortFile}\" | awk -F [_] '{print $4}')\n            else\n                currentDefaultPort=$(jq -r .inbounds[0].port ${configPath}${frontingType}.json)\n            fi\n            currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json)\n            currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}${frontingType}.json)\n        fi\n\n        # reality\n        if [[ -n \"${realityStatus}\" && -z \"${currentClients}\" ]]; then\n            currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}07_VLESS_vision_reality_inbounds.json)\n            currentClients=$(jq -r .inbounds[0].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json)\n\n        fi\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        currentHost=$(jq -r .inbounds[0].streamSettings.tlsSettings.certificates[0].certificateFile ${configPath}${frontingType}.json | awk -F '[t][l][s][/]' '{print $2}' | awk -F '[.][c][r][t]' '{print $1}')\n        currentAdd=$(jq -r .inbounds[0].settings.clients[0].add ${configPath}${frontingType}.json)\n\n        if [[ \"${currentAdd}\" == \"null\" ]]; then\n            currentAdd=${currentHost}\n        fi\n        currentUUID=$(jq -r .inbounds[0].settings.clients[0].id ${configPath}${frontingType}.json)\n        currentPort=$(jq .inbounds[0].port ${configPath}${frontingType}.json)\n    fi\n\n    #Read path\n    if [[ -n \"${configPath}\" && -n \"${frontingType}\" ]]; then\n        local fallback\n        fallback=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.path)' ${configPath}${frontingType}.json | head -1)\n\n        local path\n        path=$(echo \"${fallback}\" | jq -r .path | awk -F \"[/]\" '{print $2}')\n\n        if [[ $(echo \"${fallback}\" | jq -r .dest) == 31297 ]]; then\n            currentPath=$(echo \"${path}\" | awk -F \"[w][s]\" '{print $1}')\n        elif [[ $(echo \"${fallback}\" | jq -r .dest) == 31299 ]]; then\n            currentPath=$(echo \"${path}\" | awk -F \"[v][w][s]\" '{print $1}')\n        fi\n\n        # Try to read alpn h2 Path\n        if [[ -z \"${currentPath}\" ]]; then\n            dest=$(jq -r -c '.inbounds[0].settings.fallbacks[]|select(.alpn)|.dest' ${configPath}${frontingType}.json | head -1)\n            if [[ \"${dest}\" == \"31302\" || \"${dest}\" == \"31304\" ]]; then\n                checkBTPanel\n                if grep -q \"trojangrpc {\" <${nginxConfigPath}alone.conf; then\n                    currentPath=$(grep \"trojangrpc {\" <${nginxConfigPath}alone.conf | awk -F \"[/]\" '{print $2}' | awk -F \"[t][r][o][j][ a][n]\" '{print $1}')\n                elif grep -q \"grpc {\" <${nginxConfigPath}alone.conf; then\n                    currentPath=$(grep \"grpc {\" <${nginxConfigPath}alone.conf | head -1 | awk -F \"[/]\" '{print $2}' | awk -F \"[g][r][p] [c]\" '{print $1}')\n                fi\n            fi\n        fi\n\n    fi\n}\n\n# Status display\nshowInstallStatus() {\n    if [[ -n \"${coreInstallType}\" ]]; then\n        if [[ \"${coreInstallType}\" == 1 ]]; then\n            if [[ -n $(pgrep -f \"xray/xray\") ]]; then\n                echoContent yellow \"\\nCore: Xray-core[Running]\"\n            else\n                echoContent yellow \"\\nCore: Xray-core[not running]\"\n            fi\n\n        elif [[ \"${coreInstallType}\" == 2 || \"${coreInstallType}\" == 3 ]]; then\n            if [[ -n $(pgrep -f \"v2ray/v2ray\") ]]; then\n                echoContent yellow \"\\nCore: v2ray-core[Running]\"\n            else\n                echoContent yellow \"\\nCore: v2ray-core[not running]\"\n            fi\n        fi\n        #Read protocol type\n        readInstallProtocolType\n\n        if [[ -n ${currentInstallProtocolType} ]]; then\n            echoContent yellow \"Installed protocol: \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q 0; then\n            if [[ \"${coreInstallType}\" == 2 ]]; then\n                echoContent yellow \"VLESS+TCP[TLS] \\c\"\n            else\n                echoContent yellow \"VLESS+TCP[TLS_Vision] \\c\"\n            fi\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q trojan; then\n            if [[ \"${coreInstallType}\" == 1 ]]; then\n                echoContent yellow \"Trojan+TCP[TLS_Vision] \\c\"\n            fi\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 1; then\n            echoContent yellow \"VLESS+WS[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 2; then\n            echoContent yellow \"Trojan+gRPC[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 3; then\n            echoContent yellow \"VMess+WS[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 4; then\n            echoContent yellow \"Trojan+TCP[TLS] \\c\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 5; then\n            echoContent yellow \"VLESS+gRPC[TLS] \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q 7; then\n            echoContent yellow \"VLESS+Reality+Vision \\c\"\n        fi\n        if echo ${currentInstallProtocolType} | grep -q 8; then\n            echoContent yellow \"VLESS+Reality+gRPC \\c\"\n        fi\n    fi\n}\n\n# Clean up old residue\ncleanUp() {\n    if [[ \"$1\" == \"v2rayClean\" ]]; then\n        rm -rf \"$(find /etc/v2ray-agent/v2ray/* | grep -E '(config_full.json|conf)')\"\n        handleV2Ray stop >/dev/null\n        rm -f /etc/systemd/system/v2ray.service\n    elif [[ \"$1\" == \"xrayClean\" ]]; then\n        rm -rf \"$(find /etc/v2ray-agent/xray/* | grep -E '(config_full.json|conf)')\"\n        handleXray stop >/dev/null\n        rm -f /etc/systemd/system/xray.service\n\n    elif [[ \"$1\" == \"v2rayDel\" ]]; then\n        rm -rf /etc/v2ray-agent/v2ray/*\n\n    elif [[ \"$1\" == \"xrayDel\" ]]; then\n        rm -rf /etc/v2ray-agent/xray/*\n    fi\n}\ninitVar \"$1\"\ncheckSystem\ncheckCPUVendor\nreadInstallType\nreadInstallProtocolType\nreadConfigHostPathUUID\nreadInstallAlpn\nreadCustomPort\nreadXrayCoreRealityConfig\n#------------------------------------------------ ----------\n\n#Initialize the installation directory\nmkdirTools() {\n    mkdir -p /etc/v2ray-agent/tls\n    mkdir -p /etc/v2ray-agent/subscribe_local/default\n    mkdir -p /etc/v2ray-agent/subscribe_local/clashMeta\n\n    mkdir -p /etc/v2ray-agent/subscribe_remote/default\n    mkdir -p /etc/v2ray-agent/subscribe_remote/clashMeta\n\n    mkdir -p /etc/v2ray-agent/subscribe/default\n    mkdir -p /etc/v2ray-agent/subscribe/clashMetaProfiles\n    mkdir -p /etc/v2ray-agent/subscribe/clashMeta\n\n    mkdir -p /etc/v2ray-agent/v2ray/conf\n    mkdir -p /etc/v2ray-agent/v2ray/tmp\n    mkdir -p /etc/v2ray-agent/xray/conf\n    mkdir -p /etc/v2ray-agent/xray/tmp\n    mkdir -p /etc/v2ray-agent/hysteria/conf\n    mkdir -p /etc/systemd/system/\n    mkdir -p /tmp/v2ray-agent-tls/\n\n    mkdir -p /etc/v2ray-agent/warp\n\n    mkdir -p /etc/v2ray-agent/tuic/conf\n}\n\n# Install toolkit\ninstallTools() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Installation tools\"\n    # Repair individual system problems in ubuntu\n    if [[ \"${release}\" == \"ubuntu\" ]]; then\n        dpkg --configure -a\n    fi\n\n    if [[ -n $(pgrep -f \"apt\") ]]; then\n        pgrep -f apt | xargs kill -9\n    fi\n\n    echoContent green \" ---> Check and install updates [The new machine will be very slow. If there is no response for a long time, please stop it manually and then execute it again]\"\n\n    ${upgrade} >/etc/v2ray-agent/install.log 2>&1\n    if grep <\"/etc/v2ray-agent/install.log\" -q \"changed\"; then\n        ${updateReleaseInfoChange} >/dev/null 2>&1\n    fi\n\n    if [[ \"${release}\" == \"centos\" ]]; then\n        rm -rf /var/run/yum.pid\n        ${installType} epel-release >/dev/null 2>&1\n    fi\n\n    # \t[[ -z `find /usr/bin /usr/sbin |grep -v grep|grep -w curl` ]]\n\n    if ! find /usr/bin /usr/sbin | grep -q -w wget; then\n        echoContent green \" ---> Install wget\"\n        ${installType} wget >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w curl; then\n        echoContent green \" ---> Install curl\"\n        ${installType} curl >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w unzip; then\n        echoContent green \" ---> install unzip\"\n        ${installType} unzip >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w socat; then\n        echoContent green \" ---> Install socat\"\n        ${installType} socat >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w tar; then\n        echoContent green \" ---> Install tar\"\n        ${installType} tar >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w cron; then\n        echoContent green \" ---> install crontabs\"\n        if [[ \"${release}\" == \"ubuntu\" ]] || [[ \"${release}\" == \"debian\" ]]; then\n            ${installType} cron >/dev/null 2>&1\n        else\n            ${installType} crontabs >/dev/null 2>&1\n        fi\n    fi\n    if ! find /usr/bin /usr/sbin | grep -q -w jq; then\n        echoContent green \" ---> Install jq\"\n        ${installType} jq >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w binutils; then\n        echoContent green \" ---> Install binutils\"\n        ${installType} binutils >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w ping6; then\n        echoContent green \" ---> Install ping6\"\n        ${installType} inetutils-ping >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w qrencode; then\n        echoContent green \" ---> Install qrencode\"\n        ${installType} qrencode >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w sudo; then\n        echoContent green \" ---> install sudo\"\n        ${installType} sudo >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w lsb-release; then\n        echoContent green \" ---> install lsb-release\"\n        ${installType} lsb-release >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w lsof; then\n        echoContent green \" ---> Install lsof\"\n        ${installType} lsof >/dev/null 2>&1\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w dig; then\n        echoContent green \" ---> Install dig\"\n        if echo \"${installType} \" | grep -q -w \"apt\"; then\n            ${installType} dnsutils >/dev/null 2>&1\n        elif echo \"${installType} \" | grep -q -w \"yum\"; then\n            ${installType} bind-utils >/dev/null 2>&1\n        fi\n    fi\n\n    # Detect nginx version and provide the option of uninstalling it\n    if [[ \"${selectCustomInstallType}\" == \"7\" ]]; then\n        echoContent green \" ---> Detected services that do not depend on Nginx, skip installation\"\n    else\n        if ! find /usr/bin /usr/sbin | grep -q -w nginx; then\n            echoContent green \" ---> Install nginx\"\n            installNginxTools\n        else\n            nginxVersion=$(nginx -v 2>&1)\n            nginxVersion=$(echo \"${nginxVersion}\" | awk -F \"[n][g][i][n][x][/]\" '{print $2}' | awk -F \"[.]\" '{print $2}')\n            if [[ ${nginxVersion} -lt 14 ]]; then\n                read -r -p \"Read that the current Nginx version does not support gRPC, which will cause the installation to fail. Do you want to uninstall Nginx and reinstall it? [y/n]:\" unInstallNginxStatus\n                if [[ \"${unInstallNginxStatus}\" == \"y\" ]]; then\n                    ${removeType} nginx >/dev/null 2>&1\n                    echoContent yellow \" ---> nginx uninstall completed\"\n                    echoContent green \" ---> Install nginx\"\n                    installNginxTools >/dev/null 2>&1\n                else\n                    exit 0\n                fi\n            fi\n        fi\n    fi\n\n    if ! find /usr/bin /usr/sbin | grep -q -w semanage; then\n        echoContent green \" ---> Install semanage\"\n        ${installType} bash-completion >/dev/null 2>&1\n\n        if [[ \"${centosVersion}\" == \"7\" ]]; then\n            policyCoreUtils=\"policycoreutils-python.x86_64\"\n        elif [[ \"${centosVersion}\" == \"8\" ]]; then\n            policyCoreUtils=\"policycoreutils-python-utils-2.9-9.el8.noarch\"\n        fi\n\n        if [[ -n \"${policyCoreUtils}\" ]]; then\n            ${installType} ${policyCoreUtils} >/dev/null 2>&1\n        fi\n        if [[ -n $(which semanage) ]]; then\n            semanage port -a -t http_port_t -p tcp 31300\n\n        fi\n    fi\n    if [[ \"${selectCustomInstallType}\" == \"7\" ]]; then\n        echoContent green \" ---> Detected services that do not depend on certificates, skip installation\"\n    else\n        if [[ ! -d \"$HOME/.acme.sh\" ]] || [[ -d \"$HOME/.acme.sh\" && -z $(find \"$HOME/.acme.sh/acme.sh\") ]]; then\n            echoContent green \" ---> Install acme.sh\"\n            curl -s https://get.acme.sh | sh >/etc/v2ray-agent/tls/acme.log 2>&1\n\n            if [[ ! -d \"$HOME/.acme.sh\" ]] || [[ -z $(find \"$HOME/.acme.sh/acme.sh\") ]]; then\n                echoContent red \"acme installation failed--->\"\n                tail -n 100 /etc/v2ray-agent/tls/acme.log\n                echoContent yellow \"Error troubleshooting:\"\n                echoContent red \"1.Failed to obtain Github files. Please wait for Github to recover and try again. The recovery progress can be viewed [https://www.githubstatus.com/]\"\n                echoContent red \"2.There is a bug in the acme.sh script, please check [https://github.com/acmesh-official/acme.sh] issues\"\n                echoContent red \"3.For pure IPv6 machines, please set up NAT64.You can execute the following command. If it still does not work after adding the following command, please try to change to another NAT64\"\n                # echoContent skyBlue \" echo -e \\\"nameserver 2001:67c:2b0::4\\\\\\nnameserver 2a00:1098:2c::1\\\" >> /etc/resolv.conf\"\n                echoContent skyBlue \"sed -i \\\"1i\\\\\\nameserver 2001:67c:2b0::4\\\\\\nnameserver 2a00:1098:2c::1\\\" /etc/resolv.conf\"\n                exit 0\n            fi\n        fi\n    fi\n\n}\n\n# Install Nginx\ninstallNginxTools() {\n\n    if [[ \"${release}\" == \"debian\" ]]; then\n        sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1\n        echo \"deb http://nginx.org/packages/mainline/debian $(lsb_release -cs) nginx\" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1\n        echo -e \"Package: *\\nPin: origin nginx.org\\nPin: release o=nginx\\nPin-Priority: 900\\n\" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1\n        curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1\n        # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key\n        sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"ubuntu\" ]]; then\n        sudo apt install gnupg2 ca-certificates lsb-release -y >/dev/null 2>&1\n        echo \"deb http://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx\" | sudo tee /etc/apt/sources.list.d/nginx.list >/dev/null 2>&1\n        echo -e \"Package: *\\nPin: origin nginx.org\\nPin: release o=nginx\\nPin-Priority: 900\\n\" | sudo tee /etc/apt/preferences.d/99nginx >/dev/null 2>&1\n        curl -o /tmp/nginx_signing.key https://nginx.org/keys/nginx_signing.key >/dev/null 2>&1\n        # gpg --dry-run --quiet --import --import-options import-show /tmp/nginx_signing.key\n        sudo mv /tmp/nginx_signing.key /etc/apt/trusted.gpg.d/nginx_signing.asc\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"centos\" ]]; then\n        ${installType} yum-utils >/dev/null 2>&1\n        cat <<EOF >/etc/yum.repos.d/nginx.repo\n[nginx-stable]\nname=nginx stable repo\nbaseurl=http://nginx.org/packages/centos/\\$releasever/\\$basearch/\ngpgcheck=1\nenabled=1\ngpgkey=https://nginx.org/keys/nginx_signing.key\nmodule_hotfixes=true\n\n[nginx-mainline]\nname=nginx mainline repo\nbaseurl=http://nginx.org/packages/mainline/centos/\\$releasever/\\$basearch/\ngpgcheck=1\nenabled=0\ngpgkey=https://nginx.org/keys/nginx_signing.key\nmodule_hotfixes=true\nEOF\n        sudo yum-config-manager --enable nginx-mainline >/dev/null 2>&1\n    fi\n    ${installType} nginx >/dev/null 2>&1\n    systemctl daemon-reload\n    systemctl enable nginx\n}\n\n# Install warp\ninstallWarp() {\n    if [[ \"${cpuVendor}\" == \"arm\" ]]; then\n        echoContent red \" ---> The official WARP client does not support ARM architecture\"\n        exit 0\n    fi\n\n    ${installType} gnupg2 -y >/dev/null 2>&1\n    if [[ \"${release}\" == \"debian\" ]]; then\n        curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1\n        echo \"deb http://pkg.cloudflareclient.com/ $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"ubuntu\" ]]; then\n        curl -s https://pkg.cloudflareclient.com/pubkey.gpg | sudo apt-key add - >/dev/null 2>&1\n        echo \"deb http://pkg.cloudflareclient.com/ focal main\" | sudo tee /etc/apt/sources.list.d/cloudflare-client.list >/dev/null 2>&1\n        sudo apt update >/dev/null 2>&1\n\n    elif [[ \"${release}\" == \"centos\" ]]; then\n        ${installType} yum-utils >/dev/null 2>&1\n        sudo rpm -ivh \"http://pkg.cloudflareclient.com/cloudflare-release-el${centosVersion}.rpm\" >/dev/null 2>&1\n    fi\n\n    echoContent green \" ---> Install WARP\"\n    ${installType} cloudflare-warp >/dev/null 2>&1\n    if [[ -z $(which warp-cli) ]]; then\n        echoContent red \" ---> Failed to install WARP\"\n        exit 0\n    fi\n    systemctl enable warp-svc\n    warp-cli --accept-tos register\n    warp-cli --accept-tos set-mode proxy\n    warp-cli --accept-tos set-proxy-port 31303\n    warp-cli --accept-tos connect\n    warp-cli --accept-tos enable-always-on\n\n    local warpStatus=\n    warpStatus=$(curl -s --socks5 127.0.0.1:31303 https://www.cloudflare.com/cdn-cgi/trace | grep \"warp\" | cut -d \"=\" -f 2)\n\n    if [[ \"${warpStatus}\" == \"on\" ]]; then\n        echoContent green \" ---> WARP started successfully\"\n    fi\n}\n\n# Check the IP of the domain name through dns\ncheckDNSIP() {\n    local domain=$1\n    local dnsIP=\n    local type=4\n    dnsIP=$(dig @1.1.1.1 +time=1 +short \"${domain}\")\n    if [[ -z \"${dnsIP}\" ]]; then\n        dnsIP=$(dig @8.8.8.8 +time=1 +short \"${domain}\")\n    fi\n    if echo \"${dnsIP}\" | grep -q \"timed out\" || [[ -z \"${dnsIP}\" ]]; then\n        echo\n        echoContent red \" ---> Unable to obtain domain name IPv4 address through DNS\"\n        echoContent green \" ---> Try to check the domain name IPv6 address\"\n        dnsIP=$(dig @2606:4700:4700::1111 +time=1 aaaa +short \"${domain}\")\n        type=6\n        if echo \"${dnsIP}\" | grep -q \"network unreachable\" || [[ -z \"${dnsIP}\" ]]; then\n            echoContent red \" ---> Unable to obtain domain name IPv6 address through DNS, exit installation\"\n            exit 0\n        fi\n    fi\n    local publicIP=\n\n    publicIP=$(getPublicIP \"${type}\")\n    if [[ \"${publicIP}\" != \"${dnsIP}\" ]]; then\n        echoContent red \" ---> The domain name resolution IP is inconsistent with the current server IP\\n\"\n        echoContent yellow \" ---> Please check whether the domain name resolution is valid and correct\"\n        echoContent green \" ---> Current VPS IP: ${publicIP}\"\n        echoContent green \" ---> DNS resolution IP: ${dnsIP}\"\n        exit 0\n    else\n        echoContent green \" ---> Domain name IP verification passed\"\n    fi\n}\n# Check the actual open status of the port\ncheckPortOpen() {\n\n    local port=$1\n    local domain=$2\n    local checkPortOpenResult=\n\n    allowPort \"${port}\"\n\n    #Initialize nginx configuration\n    touch ${nginxConfigPath}checkPortOpen.conf\n    cat <<EOF >${nginxConfigPath}checkPortOpen.conf\n    server {\n        listen ${port};\n        listen [::]:${port};\n        server_name ${domain};\n        location /checkPort {\n            return 200 'fjkvymb6len';\n        }\n        location /ip {\n            proxy_set_header Host \\$host;\n            proxy_set_header X-Real-IP \\$remote_addr;\n            proxy_set_header REMOTE-HOST \\$remote_addr;\n            proxy_set_header X-Forwarded-For \\$proxy_add_x_forwarded_for;\n            default_type text/plain;\n            return 200 \\$proxy_add_x_forwarded_for;\n        }\n    }\nEOF\n    handleNginx start\n\n    # Check domain name + port opening\n    checkPortOpenResult=$(curl -s -m 2 \"http://${domain}:${port}/checkPort\")\n    localIP=$(curl -s -m 2 \"http://${domain}:${port}/ip\")\n    rm \"${nginxConfigPath}checkPortOpen.conf\"\n    handleNginx stop\n    if [[ \"${checkPortOpenResult}\" == \"fjkvymb6len\" ]]; then\n        echoContent green \" ---> Detected that ${port} port is open\"\n    else\n        echoContent green \" ---> No open ${port} port detected, exit installation\"\n        if echo \"${checkPortOpenResult}\" | grep -q \"cloudflare\"; then\n            echoContent yellow \" ---> Please close the cloud and wait three minutes to try again\"\n        else\n            if [[ -z \"${checkPortOpenResult}\" ]]; then\n                echoContent red \" ---> Please check if there is a web firewall, such as Oracle and other cloud service providers\"\n                echoContent red \" ---> Check whether you have installed nginx and there are configuration conflicts. You can try DD pure system and try again\"\n            else\n                echoContent red \" ---> Error log: ${checkPortOpenResult}, please submit feedback on this error log through issues\"\n            fi\n        fi\n        exit 0\n    fi\n    checkIP \"${localIP}\"\n}\n\n# Initialize Nginx application certificate configuration\ninitTLSNginxConfig() {\n    handleNginx stop\n    echoContent skyBlue \"\\nProgress $1/${totalProgress}: Initializing Nginx application certificate configuration\"\n    if [[ -n \"${currentHost}\" ]]; then\n        echo\n        read -r -p \"Read the last installation record. Do you want to use the domain name from the last installation? [y/n]:\" historyDomainStatus\n        if [[ \"${historyDomainStatus}\" == \"y\" ]]; then\n            domain=${currentHost}\n            echoContent yellow \"\\n ---> Domain name: ${domain}\"\n        else\n            echo\n            echoContent yellow \"Please enter the domain name to be configured: www.v2ray-agent.com --->\"\n            read -r -p \"domain name:\" domain\n        fi\n    else\n        echo\n        echoContent yellow \"Please enter the domain name to be configured: www.v2ray-agent.com --->\"\n        read -r -p \"domain name:\" domain\n    fi\n\n    if [[ -z ${domain} ]]; then\n        echoContent red \"Domain name cannot be empty--->\"\n        initTLSNginxConfig 3\n    else\n        dnsTLSDomain=$(echo \"${domain}\" | awk -F \"[.]\" '{print $(NF-1)\".\"$NF}')\n        customPortFunction\n        # Change setting\n        handleNginx stop\n        #        touch ${nginxConfigPath}alone.conf\n        #        nginxIPort=80\n        #        if [[ \"${wildcardDomainStatus}\" == \"true\" ]]; then\n        #            nginxIPort=${port}\n        #        fi\n        #\n        #        cat <<EOF >${nginxConfigPath}alone.conf\n        #server {\n        #    listen ${port};\n        #    listen [::]:${port};\n        #    server_name ${domain};\n        #    location /test {\n        #    \treturn 200 'fjkvymb6len';\n        #    }\n        #\tlocation /ip {\n        #\t\tproxy_set_header Host \\$host;\n        #        proxy_set_header X-Real-IP \\$remote_addr;\n        #        proxy_set_header REMOTE-HOST \\$remote_addr;\n        #        proxy_set_header X-Forwarded-For \\$proxy_add_x_forwarded_for;\n        #\t\tdefault_type text/plain;\n        #\t\treturn 200 \\$proxy_add_x_forwarded_for;\n        #\t}\n        #}\n        #EOF\n    fi\n\n    # readAcmeTLS\n    # handleNginx start\n}\n\n# Delete nginx default configuration\nremoveNginxDefaultConf() {\n    if [[ -f ${nginxConfigPath}default.conf ]]; then\n        if [[ \"$(grep -c \"server_name\" <${nginxConfigPath}default.conf)\" == \"1\" ]] && [[ \"$(grep -c \"server_name  localhost;\" <${nginxConfigPath}default.conf)\" == \"1\" ]]; then\n            echoContent green \" ---> Delete Nginx default configuration\"\n            rm -rf ${nginxConfigPath}default.conf\n        fi\n    fi\n}\n# Modify nginx redirection configuration\nupdateRedirectNginxConf() {\n    local redirectDomain=\n    redirectDomain=${domain}:${port}\n\n    cat <<EOF >${nginxConfigPath}alone.conf\nserver {\n    \t\tlisten 127.0.0.1:31300;\n    \t\tserver_name _;\n    \t\treturn 403;\n}\nEOF\n\n    if echo \"${selectCustomInstallType}\" | grep -q 2 && echo \"${selectCustomInstallType}\" | grep -q 5 || [[ -z \"${selectCustomInstallType}\" ]]; then\n        local nginxH2Conf=\n        nginxH2Conf=\"listen 127.0.0.1:31302 http2 so_keepalive=on;\"\n        nginxVersion=$(nginx -v 2>&1)\n\n        if echo \"${nginxVersion}\" | grep -q \"1.25\"; then\n            nginxH2Conf=\"listen 127.0.0.1:31302 so_keepalive=on;http2 on;\"\n        fi\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\t${nginxH2Conf}\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\n\tclient_header_timeout 1071906480m;\n    keepalive_timeout 1071906480m;\n\n\tlocation ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {\n        default_type 'text/plain; charset=utf-8';\n        alias /etc/v2ray-agent/subscribe/\\$1/\\$2;\n    }\n\n    location /${currentPath}grpc {\n    \tif (\\$content_type !~ \"application/grpc\") {\n    \t\treturn 404;\n    \t}\n \t\tclient_max_body_size 0;\n\t\tgrpc_set_header X-Real-IP \\$proxy_add_x_forwarded_for;\n\t\tclient_body_timeout 1071906480m;\n\t\tgrpc_read_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31301;\n\t}\n\n\tlocation /${currentPath}trojangrpc {\n\t\tif (\\$content_type !~ \"application/grpc\") {\n            \t\treturn 404;\n\t\t}\n \t\tclient_max_body_size 0;\n\t\tgrpc_set_header X-Real-IP \\$proxy_add_x_forwarded_for;\n\t\tclient_body_timeout 1071906480m;\n\t\tgrpc_read_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31304;\n\t}\n\tlocation / {\n        \tadd_header Strict-Transport-Security \"max-age=15552000; preload\" always;\n    }\n}\nEOF\n    elif echo \"${selectCustomInstallType}\" | grep -q 5 || [[ -z \"${selectCustomInstallType}\" ]]; then\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\tlisten 127.0.0.1:31302 http2;\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\tlocation ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {\n        default_type 'text/plain; charset=utf-8';\n        alias /etc/v2ray-agent/subscribe/\\$1/\\$2;\n    }\n\tlocation /${currentPath}grpc {\n\t\tclient_max_body_size 0;\n# \t\tkeepalive_time 1071906480m;\n\t\tkeepalive_requests 4294967296;\n\t\tclient_body_timeout 1071906480m;\n \t\tsend_timeout 1071906480m;\n \t\tlingering_close always;\n \t\tgrpc_read_timeout 1071906480m;\n \t\tgrpc_send_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31301;\n\t}\n}\nEOF\n\n    elif echo \"${selectCustomInstallType}\" | grep -q 2 || [[ -z \"${selectCustomInstallType}\" ]]; then\n\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\tlisten 127.0.0.1:31302 http2;\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\tlocation ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {\n        default_type 'text/plain; charset=utf-8';\n        alias /etc/v2ray-agent/subscribe/\\$1/\\$2;\n    }\n\tlocation /${currentPath}trojangrpc {\n\t\tclient_max_body_size 0;\n\t\t# keepalive_time 1071906480m;\n\t\tkeepalive_requests 4294967296;\n\t\tclient_body_timeout 1071906480m;\n \t\tsend_timeout 1071906480m;\n \t\tlingering_close always;\n \t\tgrpc_read_timeout 1071906480m;\n \t\tgrpc_send_timeout 1071906480m;\n\t\tgrpc_pass grpc://127.0.0.1:31301;\n\t}\n}\nEOF\n    else\n\n        cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\tlisten 127.0.0.1:31302 http2;\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\n    location ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {\n            default_type 'text/plain; charset=utf-8';\n            alias /etc/v2ray-agent/subscribe/\\$1/\\$2;\n        }\n\tlocation / {\n\t}\n}\nEOF\n    fi\n\n    cat <<EOF >>${nginxConfigPath}alone.conf\nserver {\n\tlisten 127.0.0.1:31300;\n\tserver_name ${domain};\n\troot ${nginxStaticPath};\n\tlocation ~ ^/s/(clashMeta|default|clashMetaProfiles)/(.*) {\n            default_type 'text/plain; charset=utf-8';\n            alias /etc/v2ray-agent/subscribe/\\$1/\\$2;\n        }\n\tlocation / {\n\t\tadd_header Strict-Transport-Security \"max-age=15552000; preload\" always;\n\t}\n}\nEOF\n    handleNginx stop\n}\n\n# check ip\ncheckIP() {\n    echoContent skyBlue \"\\n ---> Check the domain name ip\"\n    local localIP=$1\n\n    if [[ -z ${localIP} ]] || ! echo \"${localIP}\" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q '\\.' && ! echo \"${localIP}\" | sed '1{s/[^(]*(//;s/).*//;q}' | grep -q ':'; then\n        echoContent red \"\\n ---> The ip of the current domain name was not detected\"\n        echoContent skyBlue \" ---> Please perform the following checks in order\"\n        echoContent yellow \" --->1.Check whether the domain name is written correctly\"\n        echoContent yellow \" --->2.Check whether the domain name dns resolution is correct\"\n        echoContent yellow \" --->3.If the parsing is correct, please wait for the dns to take effect, which is expected to take effect within three minutes\"\n        echoContent yellow \" --->4.If you report Nginx startup problems, please start nginx manually to check the errors. If you cannot handle it yourself, please submit issues\"\n        echo\n        echoContent skyBlue \" ---> If the above settings are correct, please reinstall a pure system and try again\"\n\n        if [[ -n ${localIP} ]]; then\n            echoContent yellow \" ---> Detection of abnormal return value, it is recommended to manually uninstall nginx and re-execute the script\"\n            echoContent red \" ---> Exception result: ${localIP}\"\n        fi\n        exit 0\n    else\n        if echo \"${localIP}\" | awk -F \"[,]\" '{print $2}' | grep -q \".\" || echo \"${localIP}\" | awk -F \"[,]\" '{ print $2}' | grep -q \":\"; then\n            echoContent red \"\\n ---> Multiple IPs were detected, please confirm whether to turn off cloudflare\"\n            echoContent yellow \" ---> Wait three minutes after closing the cloud and try again\"\n            echoContent yellow \" ---> The detected IP is as follows: [${localIP}]\"\n            exit 0\n        fi\n        # echoContent green \" ---> The current domain name ip is: [${localIP}]\"\n        echoContent green \" ---> Check that the current domain name IP is correct\"\n    fi\n}\n# Custom email\ncustomSSLEmail() {\n    if echo \"$1\" | grep -q \"validate email\"; then\n        read -r -p \"Whether to re-enter the email address [y/n]:\" sslEmailStatus\n        if [[ \"${sslEmailStatus}\" == \"y\" ]]; then\n            sed '/ACCOUNT_EMAIL/d' /root/.acme.sh/account.conf >/root/.acme.sh/account.conf_tmp && mv /root/.acme.sh/account.conf_tmp /root/.acme.sh/account.conf\n        else\n            exit 0\n        fi\n    fi\n\n    if [[ -d \"/root/.acme.sh\" && -f \"/root/.acme.sh/account.conf\" ]]; then\n        if ! grep -q \"ACCOUNT_EMAIL\" <\"/root/.acme.sh/account.conf\" && ! echo \"${sslType}\" | grep -q \"letsencrypt\"; then\n            read -r -p \"Please enter your email address:\" sslEmail\n            if echo \"${sslEmail}\" | grep -q \"@\"; then\n                echo \"ACCOUNT_EMAIL='${sslEmail}'\" >>/root/.acme.sh/account.conf\n                echoContent green \" ---> Added successfully\"\n            else\n                echoContent yellow \"Please re-enter the correct email format [Example: username@example.com]\"\n                customSSLEmail\n            fi\n        fi\n    fi\n\n}\n#Select ssl installation type\nswitchSSLType() {\n    if [[ -z \"${sslType}\" ]]; then\n        echoContent red \"\\n==============================================================\"\n        echoContent yellow \"1.letsencrypt[default]\"\n        echoContent yellow \"2.zerossl\"\n        echoContent yellow \"3.buypass[Does not support DNS application]\"\n        echoContent red \"================================================== ===============\"\n        read -r -p \"Please select [Enter] to use the default:\" selectSSLType\n        case ${selectSSLType} in\n        1)\n            sslType=\"letsencrypt\"\n            ;;\n        2)\n            sslType=\"zerossl\"\n            ;;\n        3)\n            sslType=\"buypass\"\n            ;;\n        *)\n            sslType=\"letsencrypt\"\n            ;;\n        esac\n        echo \"${sslType}\" >/etc/v2ray-agent/tls/ssl_type\n\n    fi\n}\n\n#Select acme installation certificate method\nselectAcmeInstallSSL() {\n    local installSSLIPv6=\n\n    if echo \"${localIP}\" | grep -q \":\"; then\n        installSSLIPv6=\"--listen-v6\"\n    fi\n    echo\n    if [[ -n \"${customPort}\" ]]; then\n        if [[ \"${selectSSLType}\" == \"3\" ]]; then\n            echoContent red \" ---> buypass does not support free wildcard certificates\"\n            echo\n            exit\n        fi\n        dnsSSLStatus=true\n    #else\n    # if [[ -z \"${dnsSSLStatus}\" ]]; then\n    # read -r -p \"Whether to use DNS to apply for a certificate? If you do not know how to use DNS to apply for a certificate, please enter n[y/n]:\" installSSLDNStatus\n    #\n    # if [[ ${installSSLDNStatus} == 'y' ]]; then\n    # dnsSSLStatus=true\n    #else\n    #dnsSSLStatus=false\n    #fi\n    # fi\n\n    fi\n    acmeInstallSSL\n\n    readAcmeTLS\n}\n\n# Install SSL certificate\nacmeInstallSSL() {\n    if [[ \"${dnsSSLStatus}\" == \"true\" ]]; then\n\n        sudo \"$HOME/.acme.sh/acme.sh\" --issue -d \"*.${dnsTLSDomain}\" -d \"${dnsTLSDomain}\" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please -k ec-256 --server \"${sslType}\" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n\n        local txtValue=\n        txtValue=$(tail -n 10 /etc/v2ray-agent/tls/acme.log | grep \"TXT value\" | awk -F \"'\" '{print $2}')\n        if [[ -n \"${txtValue}\" ]]; then\n            echoContent green \" ---> Please add DNS TXT record manually\"\n            echoContent yellow \" ---> Please refer to this tutorial for adding method, https://github.com/mack-a/v2ray-agent/blob/master/documents/dns_txt.md\"\n            echoContent yellow \" ---> Just like installing wildcard certificates on multiple machines with the same domain name, please add multiple TXT records. There is no need to modify the previously added TXT records.\"\n            echoContent green \" ---> name: _acme-challenge\"\n            echoContent green \" ---> value: ${txtValue}\"\n            echoContent yellow \" ---> Please wait 1-2 minutes after the addition is completed\"\n            echo\n            read -r -p \"Whether the addition is completed [y/n]:\" addDNSTXTRecordStatus\n            if [[ \"${addDNSTXTRecordStatus}\" == \"y\" ]]; then\n                local txtAnswer=\n                txtAnswer=$(dig @1.1.1.1 +nocmd \"_acme-challenge.${dnsTLSDomain}\" txt +noall +answer | awk -F \"[\\\"]\" '{print $2}')\n                if echo \"${txtAnswer}\" | grep -q \"^${txtValue}\"; then\n                    echoContent green \" ---> TXT record verification passed\"\n                    echoContent green \" ---> Generating certificate\"\n                    if [[ -n \"${installSSLIPv6}\" ]]; then\n                        sudo \"$HOME/.acme.sh/acme.sh\" --renew -d \"*.${dnsTLSDomain}\" -d \"${dnsTLSDomain}\" --yes-I-know-dns-manual-mode-enough-go-ahead-please --ecc --server \"${sslType}\" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n                    else\n                        sudo \"$HOME/.acme.sh/acme.sh\" --renew -d \"*.${dnsTLSDomain}\" -d \"${dnsTLSDomain}\" --yes-I-know-dns-manual-mode-enough-go-ahead-please --ecc --server \"${sslType}\" 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n                    fi\n                else\n                    echoContent red \" ---> Verification failed, please wait 1-2 minutes and try again\"\n                    acmeInstallSSL\n                fi\n            else\n                echoContent red \" ---> Give up\"\n                exit 0\n            fi\n        fi\n    else\n        echoContent green \" ---> Generating certificate\"\n        sudo \"$HOME/.acme.sh/acme.sh\" --issue -d \"${tlsDomain}\" --standalone -k ec-256 --server \"${sslType}\" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null\n    fi\n}\n# Custom port\ncustomPortFunction() {\n    local historyCustomPortStatus=\n    if [[ -n \"${customPort}\" || -n \"${currentPort}\" ]]; then\n        echo\n        read -r -p \"Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:\" historyCustomPortStatus\n        if [[ \"${historyCustomPortStatus}\" == \"y\" ]]; then\n            port=${currentPort}\n            echoContent yellow \"\\n ---> Port: ${port}\"\n        fi\n    fi\n    if [[ -z \"${currentPort}\" ]] || [[ \"${historyCustomPortStatus}\" == \"n\" ]]; then\n        echo\n\n        if [[ -n \"${btDomain}\" ]]; then\n            echoContent yellow \"Please enter the port [cannot be the same as the BT Panel port, press Enter to be random]\"\n            read -r -p \"port:\" port\n            if [[ -z \"${port}\" ]]; then\n                port=$((RANDOM % 20001 + 10000))\n            fi\n        else\n            echo\n            echoContent yellow \"Please enter the port [default: 443], you can customize the port [press Enter to use the default]\"\n            read -r -p \"port:\" port\n            if [[ -z \"${port}\" ]]; then\n                port=443\n            fi\n            if [[ \"${port}\" == \"${currentRealityPort}\" ]]; then\n                handleXray stop\n            fi\n\n        # todo dns api\n        fi\n\n        if [[ -n \"${port}\" ]]; then\n            if ((port >= 1 && port <= 65535)); then\n                allowPort \"${port}\"\n                echoContent yellow \"\\n ---> Port: ${port}\"\n                if [[ -z \"${btDomain}\" ]]; then\n                    checkDNSIP \"${domain}\"\n                    removeNginxDefaultConf\n                    checkPortOpen \"${port}\" \"${domain}\"\n                fi\n            else\n                echoContent red \" ---> Port input error\"\n                exit 0\n            fi\n        else\n            echoContent red \" ---> Port cannot be empty\"\n            exit 0\n        fi\n    fi\n}\n\n# Check whether the port is occupied\ncheckPort() {\n    if [[ -n \"$1\" ]] && lsof -i \"tcp:$1\" | grep -q LISTEN; then\n        echoContent red \"\\n ---> $1 port is occupied, please close it manually and install\\n\"\n        lsof -i \"tcp:$1\" | grep LISTEN\n        exit 0\n    fi\n}\n\n# Install TLS\ninstallTLS() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Apply for TLS certificate\\n\"\n    local tlsDomain=${domain}\n\n    # Install tls\n    if [[ -f \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" && -f \"/etc/v2ray-agent/tls/${tlsDomain}.key\" && -n $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]] || [[ -d \"$HOME/.acme.sh/${tlsDomain}_ecc\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer\" ]]; then\n        echoContent green \" ---> Certificate detected\"\n        # checkTLStatus\n        renewalTLS\n\n        if [[ -z $(find /etc/v2ray-agent/tls/ -name \"${tlsDomain}.crt\") ]] || [[ -z $(find /etc/v2ray-agent/tls/ -name \"${tlsDomain}.key\") ]] || [[ -z $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]]; then\n            sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"${tlsDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" --keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n        else\n            echoContent yellow \" ---> If the certificate has not expired or is customized, please select [n]\\n\"\n            read -r -p \"Reinstall? [y/n]:\" reInstallStatus\n            if [[ \"${reInstallStatus}\" == \"y\" ]]; then\n                rm -rf /etc/v2ray-agent/tls/*\n                installTLS \"$1\"\n            fi\n        fi\n\n    elif [[ -d \"$HOME/.acme.sh\" ]] && [[ ! -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer\" || ! -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key\" ]]; then\n        echoContent green \" ---> Install TLS certificate, need to rely on port 80\"\n        allowPort 80\n        if [[ \"${installDNSACMEStatus}\" != \"true\" ]]; then\n            switchSSLType\n            customSSLEmail\n            selectAcmeInstallSSL\n        #else\n        # echoContent green \" ---> A wildcard certificate has been detected and is being automatically generated\"\n        fi\n        # if [[ \"${installDNSACMEStatus}\" == \"true\" ]]; then\n        # echo\n        # if [[ -d \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc\" && -f \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}. key\" && -f \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer\" ]]; then\n        # sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"*.${dnsTLSDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" -- keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n        # fi\n        #\n        #        el\n        if [[ -d \"$HOME/.acme.sh/${tlsDomain}_ecc\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.key\" && -f \"$HOME/.acme.sh/${tlsDomain}_ecc/${tlsDomain}.cer\" ]]; then\n            sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"${tlsDomain}\" --fullchainpath \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" --keypath \"/etc/v2ray-agent/tls/${tlsDomain}.key\" --ecc >/dev/null\n        fi\n\n        if [[ ! -f \"/etc/v2ray-agent/tls/${tlsDomain}.crt\" || ! -f \"/etc/v2ray-agent/tls/${tlsDomain}.key\" ]] || [[ -z $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.key\") || -z $(cat \"/etc/v2ray-agent/tls/${tlsDomain}.crt\") ]]; then\n            tail -n 10 /etc/v2ray-agent/tls/acme.log\n            if [[ ${installTLSCount} == \"1\" ]]; then\n                echoContent red \" ---> TLS installation failed, please check the acme log\"\n                exit 0\n            fi\n\n            installTLSCount=1\n            echo\n\n            if tail -n 10 /etc/v2ray-agent/tls/acme.log | grep -q \"Could not validate email address as valid\"; then\n                echoContent red \" ---> The email cannot pass SSL vendor verification, please re-enter\"\n                echo\n                customSSLEmail \"validate email\"\n                installTLS \"$1\"\n            else\n                installTLS \"$1\"\n            fi\n        fi\n\n        echoContent green \" ---> TLS generated successfully\"\n    else\n        echoContent yellow \" ---> acme.sh is not installed\"\n        exit 0\n    fi\n}\n\n#Initialize random string\ninitRandomPath() {\n    local chars=\"abcdefghijklmnopqrtuxyz\"\n    local initCustomPath=\n    for i in {1..4}; do\n        echo \"${i}\" >/dev/null\n        initCustomPath+=\"${chars:RANDOM%${#chars}:1}\"\n    done\n    customPath=${initCustomPath}\n}\n\n# Custom/random path\nrandomPathFunction() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Generate random path\"\n\n    if [[ -n \"${currentPath}\" ]]; then\n        echo\n        read -r -p \"Read the last installation record. Do you want to use the path from the last installation? [y/n]:\" historyPathStatus\n        echo\n    fi\n\n    if [[ \"${historyPathStatus}\" == \"y\" ]]; then\n        customPath=${currentPath}\n        echoContent green \" ---> Used successfully\\n\"\n    else\n        echoContent yellow \"Please enter a custom path [eg: alone], no slash required, [Enter] random path\"\n        read -r -p 'path:' customPath\n        if [[ -z \"${customPath}\" ]]; then\n            initRandomPath\n            currentPath=${customPath}\n        else\n            if [[ \"${customPath: -2}\" == \"ws\" ]]; then\n                echo\n                echoContent red \" ---> The custom path cannot end with ws, otherwise the splitting path cannot be distinguished\"\n                randomPathFunction \"$1\"\n            else\n                currentPath=${customPath}\n            fi\n        fi\n    fi\n    echoContent yellow \"\\n path:${currentPath}\"\n    echoContent skyBlue \"\\n----------------------------\"\n}\n# Nginx disguise blog\nnginxBlog() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Add fake site\"\n    if [[ -d \"${nginxStaticPath}\" && -f \"${nginxStaticPath}/check\" ]]; then\n        echo\n        read -r -p \"Detected installation of fake site, do you need to reinstall [y/n]:\" nginxBlogInstallStatus\n        if [[ \"${nginxBlogInstallStatus}\" == \"y\" ]]; then\n            rm -rf \"${nginxStaticPath}\"\n            randomNum=$((RANDOM % 6 + 1))\n            wget -q -P \"${nginxStaticPath}\" https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip >/dev/null\n            unzip -o \"${nginxStaticPath}html${randomNum}.zip\" -d \"${nginxStaticPath}\" >/dev/null\n            rm -f \"${nginxStaticPath}html${randomNum}.zip*\"\n            echoContent green \" ---> Added fake site successfully\"\n        fi\n    else\n        randomNum=$((RANDOM % 6 + 1))\n        rm -rf \"${nginxStaticPath}\"\n        wget -q -P \"${nginxStaticPath}\" https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${randomNum}.zip >/dev/null\n        unzip -o \"${nginxStaticPath}html${randomNum}.zip\" -d \"${nginxStaticPath}\" >/dev/null\n        rm -f \"${nginxStaticPath}html${randomNum}.zip*\"\n        echoContent green \" ---> Added fake site successfully\"\n    fi\n\n}\n\n# Modify http_port_t port\nupdateSELinuxHTTPPortT() {\n\n    $(find /usr/bin /usr/sbin | grep -w journalctl) -xe >/etc/v2ray-agent/nginx_error.log 2>&1\n\n    if find /usr/bin /usr/sbin | grep -q -w semanage && find /usr/bin /usr/sbin | grep -q -w getenforce && grep -E \"31300|31302\" </etc/v2ray-agent/nginx_error.log | grep -q \"Permission denied\"; then\n        echoContent red \" ---> Check if the SELinux port is open\"\n        if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31300; then\n            $(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31300\n            echoContent green \" ---> http_port_t 31300 port opened successfully\"\n        fi\n\n        if ! $(find /usr/bin /usr/sbin | grep -w semanage) port -l | grep http_port | grep -q 31302; then\n            $(find /usr/bin /usr/sbin | grep -w semanage) port -a -t http_port_t -p tcp 31302\n            echoContent green \" ---> http_port_t 31302 port opened successfully\"\n        fi\n        handleNginx start\n\n    else\n        exit 0\n    fi\n}\n\n#Operation Nginx\nhandleNginx() {\n\n    if [[ -z $(pgrep -f \"nginx\") ]] && [[ \"$1\" == \"start\" ]]; then\n        systemctl start nginx 2>/etc/v2ray-agent/nginx_error.log\n\n        sleep 0.5\n\n        if [[ -z $(pgrep -f \"nginx\") ]]; then\n            echoContent red \" ---> Nginx failed to start\"\n            echoContent red \" ---> Please try to install nginx manually and execute the script again\"\n\n            if grep -q \"journalctl -xe\" </etc/v2ray-agent/nginx_error.log; then\n                updateSELinuxHTTPPortT\n            fi\n\n        # exit 0\n        else\n            echoContent green \" ---> Nginx started successfully\"\n        fi\n\n    elif [[ -n $(pgrep -f \"nginx\") ]] && [[ \"$1\" == \"stop\" ]]; then\n        systemctl stop nginx\n        sleep 0.5\n        if [[ -n $(pgrep -f \"nginx\") ]]; then\n            pgrep -f \"nginx\" | xargs kill -9\n        fi\n        echoContent green \" ---> Nginx closed successfully\"\n    fi\n}\n\n# Scheduled task to update tls certificate\ninstallCronTLS() {\n    if [[ -z \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\nProgress$1/${totalProgress}: Add scheduled maintenance certificate\"\n        crontab -l >/etc/v2ray-agent/backup_crontab.cron\n        local historyCrontab\n        historyCrontab=$(sed '/v2ray-agent/d;/acme.sh/d' /etc/v2ray-agent/backup_crontab.cron)\n        echo \"${historyCrontab}\" >/etc/v2ray-agent/backup_crontab.cron\n        echo \"30 1 * * * /bin/bash /etc/v2ray-agent/install.sh RenewTLS >> /etc/v2ray-agent/crontab_tls.log 2>&1\" >>/etc/v2ray-agent/backup_crontab.cron\n        crontab /etc/v2ray-agent/backup_crontab.cron\n        echoContent green \"\\n ---> Add scheduled maintenance certificate successfully\"\n    fi\n}\n# Scheduled tasks update geo files\ninstallCronUpdateGeo() {\n    if [[ -n \"${configPath}\" ]]; then\n        if crontab -l | grep -q \"UpdateGeo\"; then\n            echoContent red \"\\n ---> The automatic update scheduled task has been added, please do not add it repeatedly\"\n            exit 0\n        fi\n        echoContent skyBlue \"\\nProgress 1/1: Add regularly updated geo files\"\n        crontab -l >/etc/v2ray-agent/backup_crontab.cron\n        echo \"35 1 * * * /bin/bash /etc/v2ray-agent/install.sh UpdateGeo >> /etc/v2ray-agent/crontab_tls.log 2>&1\" >>/etc/v2ray-agent/backup_crontab.cron\n        crontab /etc/v2ray-agent/backup_crontab.cron\n        echoContent green \"\\n ---> Adding scheduled update geo file successfully\"\n    fi\n}\n\n# Update certificate\nrenewalTLS() {\n\n    if [[ -n $1 ]]; then\n        echoContent skyBlue \"\\nProgress$1/1: Update certificate\"\n    fi\n    readAcmeTLS\n    local domain=${currentHost}\n    if [[ -z \"${currentHost}\" && -n \"${tlsDomain}\" ]]; then\n        domain=${tlsDomain}\n    fi\n\n    if [[ -f \"/etc/v2ray-agent/tls/ssl_type\" ]]; then\n        if grep -q \"buypass\" <\"/etc/v2ray-agent/tls/ssl_type\"; then\n            sslRenewalDays=180\n        fi\n    fi\n    if [[ -d \"$HOME/.acme.sh/${domain}_ecc\" && -f \"$HOME/.acme.sh/${domain}_ecc/${domain}.key\" && -f \"$HOME/.acme.sh/${domain}_ecc/${domain}.cer\" ]] || [[ \"${installDNSACMEStatus}\" == \"true\" ]]; then\n        modifyTime=\n\n        if [[ \"${installDNSACMEStatus}\" == \"true\" ]]; then\n            modifyTime=$(stat --format=%z \"$HOME/.acme.sh/*.${dnsTLSDomain}_ecc/*.${dnsTLSDomain}.cer\")\n        else\n            modifyTime=$(stat --format=%z \"$HOME/.acme.sh/${domain}_ecc/${domain}.cer\")\n        fi\n\n        modifyTime=$(date +%s -d \"${modifyTime}\")\n        currentTime=$(date +%s)\n        ((stampDiff = currentTime - modifyTime))\n        ((days = stampDiff / 86400))\n        ((remainingDays = sslRenewalDays - days))\n\n        tlsStatus=${remainingDays}\n        if [[ ${remainingDays} -le 0 ]]; then\n            tlsStatus=\"Expired\"\n        fi\n\n        echoContent skyBlue \" ---> Certificate check date:$(date \"+%F %H:%M:%S\")\"\n        echoContent skyBlue \" ---> Certificate generation date: $(date -d @\"${modifyTime}\" +\"%F %H:%M:%S\")\"\n        echoContent skyBlue \" ---> Certificate generation days: ${days}\"\n        echoContent skyBlue \" ---> Number of days remaining on the certificate: \"${tlsStatus}\n        echoContent skyBlue \" ---> The certificate will be automatically updated on the last day before it expires. If the update fails, please update manually\"\n\n        if [[ ${remainingDays} -le 1 ]]; then\n            echoContent yellow \" ---> Regenerate certificate\"\n            handleNginx stop\n\n            if [[ \"${coreInstallType}\" == \"1\" ]]; then\n                handleXray stop\n            elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n                handleV2Ray stop\n            fi\n\n            sudo \"$HOME/.acme.sh/acme.sh\" --cron --home \"$HOME/.acme.sh\"\n            sudo \"$HOME/.acme.sh/acme.sh\" --installcert -d \"${domain}\" --fullchainpath /etc/v2ray-agent/tls/\"${domain}.crt\" --keypath /etc /v2ray-agent/tls/\"${domain}.key\" --ecc\n            reloadCore\n            handleNginx start\n        else\n            echoContent green \" ---> The certificate is valid\"\n        fi\n    else\n        echoContent red \" ---> not installed\"\n    fi\n}\n# Check the status of TLS certificate\ncheckTLStatus() {\n\n    if [[ -d \"$HOME/.acme.sh/${currentHost}_ecc\" ]] && [[ -f \"$HOME/.acme.sh/${currentHost}_ecc/${currentHost}.key\" ]] && [[ -f \"$HOME/.acme.sh/${currentHost}_ecc/${currentHost}.cer\" ]]; then\n        modifyTime=$(stat \"$HOME/.acme.sh/${currentHost}_ecc/${currentHost}.cer\" | sed -n '7,6p' | awk '{print $2\" \"$3\" \"$4\" \"$5}')\n\n        modifyTime=$(date +%s -d \"${modifyTime}\")\n        currentTime=$(date +%s)\n        ((stampDiff = currentTime - modifyTime))\n        ((days = stampDiff / 86400))\n        ((remainingDays = sslRenewalDays - days))\n\n        tlsStatus=${remainingDays}\n        if [[ ${remainingDays} -le 0 ]]; then\n            tlsStatus=\"Expired\"\n        fi\n\n        echoContent skyBlue \" ---> Certificate generation date: $(date -d \"@${modifyTime}\" +\"%F %H:%M:%S\")\"\n        echoContent skyBlue \" ---> Certificate generation days: ${days}\"\n        echoContent skyBlue \" ---> Number of days remaining on the certificate:${tlsStatus}\"\n    fi\n}\n\n#Install V2Ray, specified version\ninstallV2Ray() {\n    readInstallType\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Install V2Ray\"\n\n    if [[ \"${coreInstallType}\" != \"2\" && \"${coreInstallType}\" != \"3\" ]]; then\n        if [[ \"${selectCoreType}\" == \"2\" ]]; then\n\n            version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases?per_page=10 | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -1)\n        else\n            version=${v2rayCoreVersion}\n        fi\n\n        echoContent green \" ---> v2ray-core version:${version}\"\n        # if wget --help | grep -q show-progress; then\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/v2ray/ \"https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip\"\n        #else\n        # wget -c -P /etc/v2ray-agent/v2ray/ \"https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip\" >/dev/ null 2>&1\n        # fi\n\n        unzip -o \"/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip\" -d /etc/v2ray-agent/v2ray >/dev/null\n        rm -rf \"/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip\"\n    else\n        if [[ \"${selectCoreType}\" == \"3\" ]]; then\n            echoContent green \" ---> Lock v2ray-core version to v4.32.1\"\n            rm -f /etc/v2ray-agent/v2ray/v2ray\n            rm -f /etc/v2ray-agent/v2ray/v2ctl\n            installV2Ray \"$1\"\n        else\n            echoContent green \" ---> v2ray-core version:$(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)\"\n            read -r -p \"Update or upgrade? [y/n]:\" reInstallV2RayStatus\n            if [[ \"${reInstallV2RayStatus}\" == \"y\" ]]; then\n                rm -f /etc/v2ray-agent/v2ray/v2ray\n                rm -f /etc/v2ray-agent/v2ray/v2ctl\n                installV2Ray \"$1\"\n            fi\n        fi\n    fi\n}\n\n# Install hysteria\ninstallHysteria() {\n    readInstallType\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Installing Hysteria\"\n\n    if [[ -z \"${hysteriaConfigPath}\" ]]; then\n\n        version=$(curl -s \"https://api.github.com/repos/apernet/hysteria/releases?per_page=10\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\" | grep -v \"app/v2\" | head -1)\n\n        echoContent green \" ---> Hysteria version:${version}\"\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/hysteria/ \"https://github.com/apernet/hysteria/releases/download/${version}/${hysteriaCoreCPUVendor}\"\n        mv \"/etc/v2ray-agent/hysteria/${hysteriaCoreCPUVendor}\" /etc/v2ray-agent/hysteria/hysteria\n        chmod 655 /etc/v2ray-agent/hysteria/hysteria\n    else\n        echoContent green \" ---> Hysteria version:$(/etc/v2ray-agent/hysteria/hysteria --version | awk '{print $3}')\"\n        read -r -p \"Would you like to update or upgrade? [y/n]:\" reInstallHysteriaStatus\n        if [[ \"${reInstallHysteriaStatus}\" == \"y\" ]]; then\n            rm -f /etc/v2ray-agent/hysteria/hysteria\n            installHysteria \"$1\"\n        fi\n    fi\n\n}\n\n# Install tuic\ninstallTuic() {\n    readInstallType\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Install Tuic\"\n\n    if [[ -z \"${tuicConfigPath}\" ]]; then\n\n        version=$(curl -s \"https://api.github.com/repos/EAimTY/tuic/releases?per_page=1\" | jq -r '.[]|select (.prerelease==false)|.tag_name')\n\n        echoContent green \" ---> Tuic version:${version}\"\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/tuic/ \"https://github.com/EAimTY/tuic/releases/download/${version}/${version}${tuicCoreCPUVendor}\"\n        mv \"/etc/v2ray-agent/tuic/${version}${tuicCoreCPUVendor}\" /etc/v2ray-agent/tuic/tuic\n        chmod 655 /etc/v2ray-agent/tuic/tuic\n    else\n        echoContent green \" ---> Tuic version:$(/etc/v2ray-agent/tuic/tuic -v)\"\n        read -r -p \"Would you like to update or upgrade? [y/n]:\" reInstallTuicStatus\n        if [[ \"${reInstallTuicStatus}\" == \"y\" ]]; then\n            rm -f /etc/v2ray-agent/tuic/tuic\n            tuicConfigPath=\n            installTuic \"$1\"\n        fi\n    fi\n\n}\n# Check wget showProgress\ncheckWgetShowProgress() {\n    if find /usr/bin /usr/sbin | grep -q -w wget && wget --help | grep -q show-progress; then\n        wgetShowProgressStatus=\"--show-progress\"\n    fi\n}\n# Install xray\ninstallXray() {\n    readInstallType\n    local prereleaseStatus=false\n    if [[ \"$2\" == \"true\" ]]; then\n        prereleaseStatus=true\n    fi\n\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Install Xray\"\n\n    if [[ \"${coreInstallType}\" != \"1\" ]]; then\n\n        version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1\" | jq -r \".[].tag_name\")\n\n        echoContent green \" ---> Xray-core version:${version}\"\n\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip\"\n        if [[ ! -f \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\" ]]; then\n            echoContent red \" ---> Core download failed, please try installation again\"\n            exit 0\n        fi\n\n        unzip -o \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\" -d /etc/v2ray-agent/xray >/dev/null\n        rm -rf \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\"\n\n        version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name')\n        echoContent skyBlue \"------------------------Version-------------------------------\"\n        echo \"version:${version}\"\n        rm /etc/v2ray-agent/xray/geo* >/dev/null 2>&1\n\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat\"\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat\"\n\n        chmod 655 /etc/v2ray-agent/xray/xray\n    else\n        echoContent green \" ---> Xray-core version:$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n        read -r -p \"Would you like to update or upgrade? [y/n]:\" reInstallXrayStatus\n        if [[ \"${reInstallXrayStatus}\" == \"y\" ]]; then\n            rm -f /etc/v2ray-agent/xray/xray\n            installXray \"$1\" \"$2\"\n        fi\n    fi\n}\n\n# v2ray version management\nv2rayVersionManageMenu() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: V2Ray version management\"\n    if [[ ! -d \"/etc/v2ray-agent/v2ray/\" ]]; then\n        echoContent red \" ---> The installation directory is not detected, please execute the script to install the content\"\n        menu\n        exit 0\n    fi\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.Upgrade v2ray-core\"\n    echoContent yellow \"2.Fallback v2ray-core\"\n    echoContent yellow \"3.Close v2ray-core\"\n    echoContent yellow \"4.Open v2ray-core\"\n    echoContent yellow \"5.Restart v2ray-core\"\n    echoContent yellow \"6.Update geosite, geoip\"\n    echoContent yellow \"7.Set up automatic update of geo files [updated every morning]\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectV2RayType\n    if [[ \"${selectV2RayType}\" == \"1\" ]]; then\n        updateV2Ray\n    elif [[ \"${selectV2RayType}\" == \"2\" ]]; then\n        echoContent yellow \"\\n1.Only the last five versions can be rolled back\"\n        echoContent yellow \"2.There is no guarantee that it will be able to be used normally after the rollback\"\n        echoContent yellow \"3.If the rolled-back version does not support the current config, it will be unable to connect, so operate with caution\"\n        echoContent skyBlue \"------------------------Version-------------------------------\"\n        curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -5 | awk '{print \"\"NR\"\"\":\"$0}'\n\n        echoContent skyBlue \"------------------------------------------------- ---------------\"\n        read -r -p \"Please enter the version to be rolled back:\" selectV2rayVersionType\n        version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -5 | awk '{print \"\"NR\"\"\":\"$0}' | grep \"${selectV2rayVersionType}:\" | awk -F \"[:]\" '{print $2}')\n        if [[ -n \"${version}\" ]]; then\n            updateV2Ray \"${version}\"\n        else\n            echoContent red \"\\n ---> Incorrect input, please re-enter\"\n            v2rayVersionManageMenu 1\n        fi\n    elif [[ \"${selectV2RayType}\" == \"3\" ]]; then\n        handleV2Ray stop\n    elif [[ \"${selectV2RayType}\" == \"4\" ]]; then\n        handleV2Ray start\n    elif [[ \"${selectV2RayType}\" == \"5\" ]]; then\n        reloadCore\n    elif [[ \"${selectXrayType}\" == \"6\" ]]; then\n        updateGeoSite\n    elif [[ \"${selectXrayType}\" == \"7\" ]]; then\n        installCronUpdateGeo\n    fi\n}\n\n# xray version management\nxrayVersionManageMenu() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Xray version management\"\n    if [[ ! -d \"/etc/v2ray-agent/xray/\" ]]; then\n        echoContent red \" ---> The installation directory is not detected, please execute the script to install the content\"\n        menu\n        exit 0\n    fi\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.Upgrade Xray-core\"\n    echoContent yellow \"2.Upgrade Xray-core preview version\"\n    echoContent yellow \"3.Fallback Xray-core\"\n    echoContent yellow \"4.Close Xray-core\"\n    echoContent yellow \"5.Open Xray-core\"\n    echoContent yellow \"6.Restart Xray-core\"\n    echoContent yellow \"7.Update geosite, geoip\"\n    echoContent yellow \"8.Set up automatic update of geo files [updated every morning]\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectXrayType\n    if [[ \"${selectXrayType}\" == \"1\" ]]; then\n        updateXray\n    elif [[ \"${selectXrayType}\" == \"2\" ]]; then\n\n        prereleaseStatus=true\n        updateXray\n\n    elif [[ \"${selectXrayType}\" == \"3\" ]]; then\n        echoContent yellow \"\\n1.Only the last five versions can be rolled back\"\n        echoContent yellow \"2.There is no guarantee that it will be able to be used normally after the rollback\"\n        echoContent yellow \"3.If the rolled-back version does not support the current config, it will be unable to connect, so operate with caution\"\n        echoContent skyBlue \"------------------------Version-------------------------------\"\n        curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==false)|.tag_name\" | awk '{print \"\"NR\"\"\":\"$0}'\n        echoContent skyBlue \"------------------------------------------------- ---------------\"\n        read -r -p \"Please enter the version you want to roll back:\" selectXrayVersionType\n        version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=5\" | jq -r \".[]|select (.prerelease==false)|.tag_name\" | awk '{print \"\"NR\"\"\":\"$0}' | grep \"${selectXrayVersionType}:\" | awk -F \"[:]\" '{print $2}')\n        if [[ -n \"${version}\" ]]; then\n            updateXray \"${version}\"\n        else\n            echoContent red \"\\n ---> Incorrect input, please re-enter\"\n            xrayVersionManageMenu 1\n        fi\n    elif [[ \"${selectXrayType}\" == \"4\" ]]; then\n        handleXray stop\n    elif [[ \"${selectXrayType}\" == \"5\" ]]; then\n        handleXray start\n    elif [[ \"${selectXrayType}\" == \"6\" ]]; then\n        reloadCore\n    elif [[ \"${selectXrayType}\" == \"7\" ]]; then\n        updateGeoSite\n    elif [[ \"${selectXrayType}\" == \"8\" ]]; then\n        installCronUpdateGeo\n    fi\n}\n\n# Update geosite\nupdateGeoSite() {\n    echoContent yellow \"\\nSource https://github.com/Loyalsoldier/v2ray-rules-dat\"\n\n    version=$(curl -s https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases?per_page=1 | jq -r '.[]|.tag_name')\n    echoContent skyBlue \"------------------------Version-------------------------------\"\n    echo \"version:${version}\"\n    rm ${configPath}../geo* >/dev/null\n    wget -c -q \"${wgetShowProgressStatus}\" -P ${configPath}../ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geosite.dat\"\n    wget -c -q \"${wgetShowProgressStatus}\" -P ${configPath}../ \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/download/${version}/geoip.dat\"\n    reloadCore\n    echoContent green \" ---> Update completed\"\n\n}\n# Update V2Ray\nupdateV2Ray() {\n    readInstallType\n    if [[ -z \"${coreInstallType}\" ]]; then\n\n        if [[ -n \"$1\" ]]; then\n            version=$1\n        else\n            version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -1)\n        fi\n        # Use locked version\n        if [[ -n \"${v2rayCoreVersion}\" ]]; then\n            version=${v2rayCoreVersion}\n        fi\n        echoContent green \" ---> v2ray-core version:${version}\"\n        # if wget --help | grep -q show-progress; then\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/v2ray/ \"https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip\"\n        #else\n        # wget -c -P \"/etc/v2ray-agent/v2ray/ https://github.com/v2fly/v2ray-core/releases/download/${version}/${v2rayCoreCPUVendor}.zip\" >/dev/ null 2>&1\n        #fi\n\n        unzip -o \"/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip\" -d /etc/v2ray-agent/v2ray >/dev/null\n        rm -rf \"/etc/v2ray-agent/v2ray/${v2rayCoreCPUVendor}.zip\"\n        handleV2Ray stop\n        handleV2Ray start\n    else\n        echoContent green \" ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)\"\n\n        if [[ -n \"$1\" ]]; then\n            version=$1\n        else\n            version=$(curl -s https://api.github.com/repos/v2fly/v2ray-core/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | grep -v 'v5' | head -1)\n        fi\n\n        if [[ -n \"${v2rayCoreVersion}\" ]]; then\n            version=${v2rayCoreVersion}\n        fi\n        if [[ -n \"$1\" ]]; then\n            read -r -p \"The rollback version is ${version}, do you want to continue? [y/n]:\" rollbackV2RayStatus\n            if [[ \"${rollbackV2RayStatus}\" == \"y\" ]]; then\n                if [[ \"${coreInstallType}\" == \"2\" ]]; then\n                    echoContent green \" ---> Current v2ray-core version: $(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)\"\n                elif [[ \"${coreInstallType}\" == \"1\" ]]; then\n                    echoContent green \" ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n                fi\n\n                handleV2Ray stop\n                rm -f /etc/v2ray-agent/v2ray/v2ray\n                rm -f /etc/v2ray-agent/v2ray/v2ctl\n                updateV2Ray \"${version}\"\n            else\n                echoContent green \" ---> Abandon the rollback version\"\n            fi\n        elif [[ \"${version}\" == \"v$(/etc/v2ray-agent/v2ray/v2ray --version | awk '{print $2}' | head -1)\" ]]; then\n            read -r -p \"The current version is the same as the latest version. Do you want to reinstall? [y/n]:\" reInstallV2RayStatus\n            if [[ \"${reInstallV2RayStatus}\" == \"y\" ]]; then\n                handleV2Ray stop\n                rm -f /etc/v2ray-agent/v2ray/v2ray\n                rm -f /etc/v2ray-agent/v2ray/v2ctl\n                updateV2Ray\n            else\n                echoContent green \" ---> Give up and reinstall\"\n            fi\n        else\n            read -r -p \"The latest version is: ${version}, do you want to update? [y/n]:\" installV2RayStatus\n            if [[ \"${installV2RayStatus}\" == \"y\" ]]; then\n                rm -f /etc/v2ray-agent/v2ray/v2ray\n                rm -f /etc/v2ray-agent/v2ray/v2ctl\n                updateV2Ray\n            else\n                echoContent green \" ---> Abort update\"\n            fi\n\n        fi\n    fi\n}\n\n# Update Xray\nupdateXray() {\n    readInstallType\n    if [[ -z \"${coreInstallType}\" ]]; then\n        if [[ -n \"$1\" ]]; then\n            version=$1\n        else\n            version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1\" | jq -r \".[]|select (.prerelease==${prereleaseStatus})|.tag_name\")\n        fi\n\n        echoContent green \" ---> Xray-core version:${version}\"\n\n        wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/xray/ \"https://github.com/XTLS/Xray-core/releases/download/${version}/${xrayCoreCPUVendor}.zip\"\n\n        unzip -o \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\" -d /etc/v2ray-agent/xray >/dev/null\n        rm -rf \"/etc/v2ray-agent/xray/${xrayCoreCPUVendor}.zip\"\n        chmod 655 /etc/v2ray-agent/xray/xray\n        handleXray stop\n        handleXray start\n    else\n        echoContent green \" ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n\n        if [[ -n \"$1\" ]]; then\n            version=$1\n        else\n            version=$(curl -s \"https://api.github.com/repos/XTLS/Xray-core/releases?per_page=1\" | jq -r \".[].tag_name\")\n        fi\n\n        if [[ -n \"$1\" ]]; then\n            read -r -p \"The rollback version is ${version}, do you want to continue? [y/n]:\" rollbackXrayStatus\n            if [[ \"${rollbackXrayStatus}\" == \"y\" ]]; then\n                echoContent green \" ---> Current Xray-core version: $(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\"\n\n                handleXray stop\n                rm -f /etc/v2ray-agent/xray/xray\n                updateXray \"${version}\"\n            else\n                echoContent green \" ---> Abandon the rollback version\"\n            fi\n        elif [[ \"${version}\" == \"v$(/etc/v2ray-agent/xray/xray --version | awk '{print $2}' | head -1)\" ]]; then\n            read -r -p \"The current version is the same as the latest version. Do you want to reinstall? [y/n]:\" reInstallXrayStatus\n            if [[ \"${reInstallXrayStatus}\" == \"y\" ]]; then\n                handleXray stop\n                rm -f /etc/v2ray-agent/xray/xray\n                rm -f /etc/v2ray-agent/xray/xray\n                updateXray\n            else\n                echoContent green \" ---> Give up and reinstall\"\n            fi\n        else\n            read -r -p \"The latest version is: ${version}, is it updated? [y/n]:\" installXrayStatus\n            if [[ \"${installXrayStatus}\" == \"y\" ]]; then\n                rm -f /etc/v2ray-agent/xray/xray\n                updateXray\n            else\n                echoContent green \" ---> Abort update\"\n            fi\n\n        fi\n    fi\n}\n\n# Verify that the entire service is available\ncheckGFWStatue() {\n    readInstallType\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Verify service startup status\"\n    if [[ \"${coreInstallType}\" == \"1\" ]] && [[ -n $(pgrep -f \"xray/xray\") ]]; then\n        echoContent green \" ---> Service started successfully\"\n    elif [[ \"${coreInstallType}\" == \"2\" ]] && [[ -n $(pgrep -f \"v2ray/v2ray\") ]]; then\n        echoContent green \" ---> Service started successfully\"\n    else\n        echoContent red \" ---> Service startup failed, please check if there are logs printed in the terminal\"\n        exit 0\n    fi\n\n}\n\n# V2Ray starts automatically after booting\ninstallV2RayService() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Configure V2Ray to start automatically at boot\"\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]]; then\n        rm -rf /etc/systemd/system/v2ray.service\n        touch /etc/systemd/system/v2ray.service\n        execStart='/etc/v2ray-agent/v2ray/v2ray -confdir /etc/v2ray-agent/v2ray/conf'\n        cat <<EOF >/etc/systemd/system/v2ray.service\n[Unit]\nDescription=V2Ray - A unified platform for anti-censorship\nDocumentation=https://v2ray.com https://guide.v2fly.org\nAfter=network.target nss-lookup.target\nWants=network-online.target\n\n[Service]\nType=simple\nUser=root\nCapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW\nNoNewPrivileges=yes\nExecStart=${execStart}\nRestart=on-failure\nRestartPreventExitStatus=23\nLimitNPROC=10000\nLimitNOFILE=1000000\n\n[Install]\nWantedBy=multi-user.target\nEOF\n        systemctl daemon-reload\n        systemctl enable v2ray.service\n        echoContent green \" ---> Configure V2Ray to start automatically at boot\"\n    fi\n}\n\n# Install hysteria to start automatically at boot\ninstallHysteriaService() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Configure Hysteria to start automatically at boot\"\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]]; then\n        rm -rf /etc/systemd/system/hysteria.service\n        touch /etc/systemd/system/hysteria.service\n        execStart='/etc/v2ray-agent/hysteria/hysteria --log-level info -c /etc/v2ray-agent/hysteria/conf/config.json server'\n        cat <<EOF >/etc/systemd/system/hysteria.service\n[Unit]\nDescription=Hysteria Service\nDocumentation=https://github.com/apernet\nAfter=network.target nss-lookup.target\n[Service]\nUser=root\nExecStart=${execStart}\nRestart=on-failure\nRestartPreventExitStatus=23\nLimitNPROC=10000\nLimitNOFILE=1000000\n[Install]\nWantedBy=multi-user.target\nEOF\n        systemctl daemon-reload\n        systemctl enable hysteria.service\n        echoContent green \" ---> Configure Hysteria to start automatically at boot\"\n    fi\n}\n# Install Tuic to start automatically at boot\ninstallTuicService() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Configure Tuic to start automatically at boot\"\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]]; then\n        rm -rf /etc/systemd/system/tuic.service\n        touch /etc/systemd/system/tuic.service\n        execStart='/etc/v2ray-agent/tuic/tuic -c /etc/v2ray-agent/tuic/conf/config.json'\n        cat <<EOF >/etc/systemd/system/tuic.service\n[Unit]\nDescription=Tuic Service\nDocumentation=https://github.com/EAimTY\nAfter=network.target nss-lookup.target\n[Service]\nUser=root\nExecStart=${execStart}\nRestart=on-failure\nRestartPreventExitStatus=23\nLimitNPROC=10000\nLimitNOFILE=1000000\n[Install]\nWantedBy=multi-user.target\nEOF\n        systemctl daemon-reload\n        systemctl enable tuic.service\n        echoContent green \" ---> Configuring Tuic to start automatically at boot\"\n    fi\n}\n# Xray starts automatically after booting\ninstallXrayService() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Configure Xray to start automatically at boot\"\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]]; then\n        rm -rf /etc/systemd/system/xray.service\n        touch /etc/systemd/system/xray.service\n        execStart='/etc/v2ray-agent/xray/xray run -confdir /etc/v2ray-agent/xray/conf'\n        cat <<EOF >/etc/systemd/system/xray.service\n[Unit]\nDescription=Xray Service\nDocumentation=https://github.com/xtls\nAfter=network.target nss-lookup.target\n[Service]\nUser=root\nExecStart=${execStart}\nRestart=on-failure\nRestartPreventExitStatus=23\nLimitNPROC=10000\nLimitNOFILE=1000000\n[Install]\nWantedBy=multi-user.target\nEOF\n        systemctl daemon-reload\n        systemctl enable xray.service\n        echoContent green \" ---> Configure Xray to start automatically at boot\"\n    fi\n}\n\n#Operation V2Ray\nhandleV2Ray() {\n    # shellcheck disable=SC2010\n    if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q v2ray.service; then\n        if [[ -z $(pgrep -f \"v2ray/v2ray\") ]] && [[ \"$1\" == \"start\" ]]; then\n            systemctl start v2ray.service\n        elif [[ -n $(pgrep -f \"v2ray/v2ray\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop v2ray.service\n        fi\n    fi\n    sleep 0.8\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"v2ray/v2ray\") ]]; then\n            echoContent green \" ---> V2Ray started successfully\"\n        else\n            echoContent red \"V2Ray failed to start\"\n            echoContent red \"Please manually execute [/etc/v2ray-agent/v2ray/v2ray -confdir /etc/v2ray-agent/v2ray/conf] and check the error log\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"v2ray/v2ray\") ]]; then\n            echoContent green \" ---> V2Ray closed successfully\"\n        else\n            echoContent red \"V2Ray failed to close\"\n            echoContent red \"Please execute manually [ps -ef|grep -v grep|grep v2ray|awk '{print \\$2}'|xargs kill -9]\"\n            exit 0\n        fi\n    fi\n}\n\n# Operation Hysteria\nhandleHysteria() {\n    # shellcheck disable=SC2010\n    if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q hysteria.service; then\n        if [[ -z $(pgrep -f \"hysteria/hysteria\") ]] && [[ \"$1\" == \"start\" ]]; then\n            systemctl start hysteria.service\n        elif [[ -n $(pgrep -f \"hysteria/hysteria\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop hysteria.service\n        fi\n    fi\n    sleep 0.8\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"hysteria/hysteria\") ]]; then\n            echoContent green \" ---> Hysteria started successfully\"\n        else\n            echoContent red \"Hysteria startup failed\"\n            echoContent red \"Please manually execute [/etc/v2ray-agent/hysteria/hysteria --log-level debug -c /etc/v2ray-agent/hysteria/conf/config.json server] to view the error log\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"hysteria/hysteria\") ]]; then\n            echoContent green \" ---> Hysteria closed successfully\"\n        else\n            echoContent red \"Hysteria shutdown failed\"\n            echoContent red \"Please execute manually [ps -ef|grep -v grep|grep hysteria|awk '{print \\$2}'|xargs kill -9]\"\n            exit 0\n        fi\n    fi\n}\n# Operate Tuic\nhandleTuic() {\n    # shellcheck disable=SC2010\n    if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q tuic.service; then\n        if [[ -z $(pgrep -f \"tuic/tuic\") ]] && [[ \"$1\" == \"start\" ]]; then\n            systemctl start tuic.service\n        elif [[ -n $(pgrep -f \"tuic/tuic\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop tuic.service\n        fi\n    fi\n    sleep 0.8\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"tuic/tuic\") ]]; then\n            echoContent green \" ---> Tuic started successfully\"\n        else\n            echoContent red \"Tuic startup failed\"\n            echoContent red \"Please manually execute [/etc/v2ray-agent/tuic/tuic -c /etc/v2ray-agent/tuic/conf/config.json] and check the error log\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"tuic/tuic\") ]]; then\n            echoContent green \" ---> Tuic closed successfully\"\n        else\n            echoContent red \"Tuic failed to close\"\n            echoContent red \"Please execute manually [ps -ef|grep -v grep|grep tuic|awk '{print \\$2}'|xargs kill -9]\"\n            exit 0\n        fi\n    fi\n}\n# Manipulate xray\nhandleXray() {\n    if [[ -n $(find /bin /usr/bin -name \"systemctl\") ]] && [[ -n $(find /etc/systemd/system/ -name \"xray.service\") ]]; then\n        if [[ -z $(pgrep -f \"xray/xray\") ]] && [[ \"$1\" == \"start\" ]]; then\n            systemctl start xray.service\n        elif [[ -n $(pgrep -f \"xray/xray\") ]] && [[ \"$1\" == \"stop\" ]]; then\n            systemctl stop xray.service\n        fi\n    fi\n\n    sleep 0.8\n\n    if [[ \"$1\" == \"start\" ]]; then\n        if [[ -n $(pgrep -f \"xray/xray\") ]]; then\n            echoContent green \" ---> Xray started successfully\"\n        else\n            echoContent red \"Xray startup failed\"\n            echoContent red \"Please manually execute the following command [/etc/v2ray-agent/xray/xray -confdir /etc/v2ray-agent/xray/conf] and feedback the error log\"\n            exit 0\n        fi\n    elif [[ \"$1\" == \"stop\" ]]; then\n        if [[ -z $(pgrep -f \"xray/xray\") ]]; then\n            echoContent green \" ---> Xray closed successfully\"\n        else\n            echoContent red \"xray failed to close\"\n            echoContent red \"Please execute manually [ps -ef|grep -v grep|grep xray|awk '{print \\$2}'|xargs kill -9]\"\n            exit 0\n        fi\n    fi\n}\n\n# Read user data and initialize\ninitXrayClients() {\n    local type=$1\n    local newUUID=$2\n    local newEmail=$3\n    if [[ -n \"${newUUID}\" ]]; then\n        local newUser=\n        newUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"email\\\":\\\"${newEmail}-VLESS_TCP/ TLS_Vision\\\"}\"\n        currentClients=$(echo \"${currentClients}\" | jq -r \". +=[${newUser}]\")\n    fi\n    local users=\n    if [[ \"${type}\" == \"9\" ]]; then\n        users={}\n    else\n        users=[]\n    fi\n\n    while read -r user; do\n        uuid=$(echo \"${user}\" | jq -r .id)\n        email=$(echo \"${user}\" | jq -r .email | awk -F \"[-]\" '{print $1}')\n        currentUser=\n        if echo \"${type}\" | grep -q \"0\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"email\\\":\\\"${email}-VLESS_TCP/TLS_Vision\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        #VLESSWS\n        if echo \"${type}\" | grep -q \"1\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-VLESS_WS\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        #trojan grpc\n        if echo \"${type}\" | grep -q \"2\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-Trojan_gRPC\\\"}\"\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        #VMessWS\n        if echo \"${type}\" | grep -q \"3\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-VMess_WS\\\",\\\"alterId\\\": 0}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        #trojantcp\n        if echo \"${type}\" | grep -q \"4\"; then\n            currentUser=\"{\\\"password\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-trojan_tcp\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # vless grpc\n        if echo \"${type}\" | grep -q \"5\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-vless_grpc\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # hysteria\n        if echo \"${type}\" | grep -q \"6\"; then\n            users=$(echo \"${users}\" | jq -r \". +=[\\\"${uuid}\\\"]\")\n        fi\n\n        # vless reality vision\n        if echo \"${type}\" | grep -q \"7\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-vless_reality_vision\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n\n        # vless reality grpc\n        if echo \"${type}\" | grep -q \"8\"; then\n            currentUser=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}-vless_reality_grpc\\\",\\\"flow\\\":\\\"\\\"}\"\n\n            users=$(echo \"${users}\" | jq -r \". +=[${currentUser}]\")\n        fi\n        # tuic\n        if echo \"${type}\" | grep -q \"9\"; then\n            users=$(echo \"${users}\" | jq -r \".\\\"${uuid}\\\"=\\\"${uuid}\\\"\")\n        fi\n\n    done < <(echo \"${currentClients}\" | jq -c '.[]')\n    echo \"${users}\"\n}\ngetClients() {\n    local path=$1\n\n    local addClientsStatus=$2\n    previousClients=\n\n    if [[ ${addClientsStatus} == \"true\" ]]; then\n        if [[ ! -f \"${path}\" ]]; then\n            echo\n            local protocol\n            protocol=$(echo \"${path}\" | awk -F \"[_]\" '{print $2 $3}')\n            echoContent yellow \"The configuration file last installed for this protocol [${protocol}] was not read, and the first uuid of the configuration file was used\"\n        else\n            previousClients=$(jq -r \".inbounds[0].settings.clients\" \"${path}\")\n        fi\n\n    fi\n}\n\n#Add client configuration\naddClients() {\n\n    local path=$1\n    local addClientsStatus=$2\n    if [[ ${addClientsStatus} == \"true\" && -n \"${previousClients}\" ]]; then\n        config=$(jq -r \".inbounds[0].settings.clients = ${previousClients}\" \"${path}\")\n        echo \"${config}\" | jq . >\"${path}\"\n    fi\n}\n# Add hysteria configuration\naddClientsHysteria() {\n    local path=$1\n    local addClientsStatus=$2\n\n    if [[ ${addClientsStatus} == \"true\" && -n \"${previousClients}\" ]]; then\n        local uuids=\n        uuids=$(echo \"${previousClients}\" | jq -r [.[].id])\n\n        if [[ \"${frontingType}\" == \"02_trojan_TCP_inbounds\" ]]; then\n            uuids=$(echo \"${previousClients}\" | jq -r [.[].password])\n        fi\n        config=$(jq -r \".auth.config = ${uuids}\" \"${path}\")\n        echo \"${config}\" | jq . >\"${path}\"\n    fi\n}\n\n#Initialize hysteria port\ninitHysteriaPort() {\n    readHysteriaConfig\n    if [[ -n \"${hysteriaPort}\" ]]; then\n        read -r -p \"Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:\" historyHysteriaPortStatus\n        if [[ \"${historyHysteriaPortStatus}\" == \"y\" ]]; then\n            echoContent yellow \"\\n ---> Port: ${hysteriaPort}\"\n        else\n            hysteriaPort=\n        fi\n    fi\n\n    if [[ -z \"${hysteriaPort}\" ]]; then\n        echoContent yellow \"Please enter the Hysteria port [enter random 10000-30000], cannot be repeated with other services\"\n        read -r -p \"Port:\" hysteriaPort\n        if [[ -z \"${hysteriaPort}\" ]]; then\n            hysteriaPort=$((RANDOM % 20001 + 10000))\n        fi\n    fi\n    if [[ -z ${hysteriaPort} ]]; then\n        echoContent red \" ---> Port cannot be empty\"\n        initHysteriaPort \"$2\"\n    elif ((hysteriaPort < 1 || hysteriaPort > 65535)); then\n        echoContent red \" ---> The port is illegal\"\n        initHysteriaPort \"$2\"\n    fi\n    allowPort \"${hysteriaPort}\"\n    allowPort \"${hysteriaPort}\" \"udp\"\n}\n\n# Initialize hysteria protocol\ninitHysteriaProtocol() {\n    echoContent skyBlue \"\\nPlease select the protocol type\"\n    echoContent red \"================================================== ===============\"\n    echoContent yellow \"1.udp(QUIC)(default)\"\n    echoContent yellow \"2.faketcp\"\n    echoContent yellow \"3.wechat-video\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectHysteriaProtocol\n    case ${selectHysteriaProtocol} in\n    1)\n        hysteriaProtocol=\"udp\"\n        ;;\n    2)\n        hysteriaProtocol=\"faketcp\"\n        ;;\n    3)\n        hysteriaProtocol=\"wechat-video\"\n        ;;\n    *)\n        hysteriaProtocol=\"udp\"\n        ;;\n    esac\n    echoContent yellow \"\\n ---> Protocol: ${hysteriaProtocol}\\n\"\n}\n\n# Initialize hysteria network information\ninitHysteriaNetwork() {\n\n    echoContent yellow \"Please enter the average delay from local to server, please fill it in according to the actual situation (default: 180, unit: ms)\"\n    read -r -p \"Delay:\" hysteriaLag\n    if [[ -z \"${hysteriaLag}\" ]]; then\n        hysteriaLag=180\n        echoContent yellow \"\\n ---> Delay: ${hysteriaLag}\\n\"\n    fi\n\n    echoContent yellow \"Please enter the local bandwidth peak downstream speed (default: 100, unit: Mbps)\"\n    read -r -p \"Download speed:\" hysteriaClientDownloadSpeed\n    if [[ -z \"${hysteriaClientDownloadSpeed}\" ]]; then\n        hysteriaClientDownloadSpeed=100\n        echoContent yellow \"\\n --->Download speed: ${hysteriaClientDownloadSpeed}\\n\"\n    fi\n\n    echoContent yellow \"Please enter the local bandwidth peak uplink speed (default: 50, unit: Mbps)\"\n    read -r -p \"upload speed:\" hysteriaClientUploadSpeed\n    if [[ -z \"${hysteriaClientUploadSpeed}\" ]]; then\n        hysteriaClientUploadSpeed=50\n        echoContent yellow \"\\n ---> Upload speed: ${hysteriaClientUploadSpeed}\\n\"\n    fi\n\n    cat <<EOF >/etc/v2ray-agent/hysteria/conf/client_network.json\n{\n\t\"hysteriaLag\":\"${hysteriaLag}\",\n\t\"hysteriaClientUploadSpeed\":\"${hysteriaClientUploadSpeed}\",\n\t\"hysteriaClientDownloadSpeed\":\"${hysteriaClientDownloadSpeed}\"\n}\nEOF\n\n}\n\n# hy port jump\nhysteriaPortHopping() {\n    if [[ -n \"${portHoppingStart}\" || -n \"${portHoppingEnd}\" ]]; then\n        echoContent red \" ---> Already added, cannot be added repeatedly, can be deleted and re-added\"\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\nProgress 1/1: Port jump\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\\n\"\n    echoContent yellow \"Only supports UDP\"\n    echoContent yellow \"The starting position of port jumping is 30000\"\n    echoContent yellow \"The end position of port jumping is 60000\"\n    echoContent yellow \"You can choose a segment in the range of 30000-60000\"\n    echoContent yellow \"Recommend about 1000\"\n\n    echoContent yellow \"Please enter the port jumping range, for example [30000-31000]\"\n\n    read -r -p \"Range:\" hysteriaPortHoppingRange\n    if [[ -z \"${hysteriaPortHoppingRange}\" ]]; then\n        echoContent red \" ---> Range cannot be empty\"\n        hysteriaPort Hopping\n    elif echo \"${hysteriaPortHoppingRange}\" | grep -q \"-\"; then\n\n        local portStart=\n        local portEnd=\n        portStart=$(echo \"${hysteriaPortHoppingRange}\" | awk -F '-' '{print $1}')\n        portEnd=$(echo \"${hysteriaPortHoppingRange}\" | awk -F '-' '{print $2}')\n\n        if [[ -z \"${portStart}\" || -z \"${portEnd}\" ]]; then\n            echoContent red \" ---> The range is illegal\"\n            hysteriaPort Hopping\n        elif ((portStart < 30000 || portStart > 60000 || portEnd < 30000 || portEnd > 60000 || portEnd < portStart)); then\n            echoContent red \" ---> The range is illegal\"\n            hysteriaPort Hopping\n        else\n            echoContent green \"\\nPort range: ${hysteriaPortHoppingRange}\\n\"\n            # ip -4 addr show | awk '/inet /{print $NF \":\" $2}' | awk '{print \"\"NR\"\"\":\"$0}'\n            # read -r -p \"Please select the corresponding network card:\" selectInterface\n            # if ! ip -4 addr show | awk '/inet /{print $NF \":\" $2}' | awk '{print \"\"NR\"\"\":\"$0}' | grep -q \"${selectInterface}: \"; then\n            # echoContent red \" ---> Wrong selection\"\n            # hysteriaPortHopping\n            #else\n            iptables -t nat -A PREROUTING -p udp --dport \"${portStart}:${portEnd}\" -m comment --comment \"mack-a_portHopping\" -j DNAT --to-destination :${hysteriaPort}\n\n            if iptables-save | grep -q \"mack-a_portHopping\"; then\n                allowPort \"${portStart}:${portEnd}\" udp\n                echoContent green \" ---> Port hopping added successfully\"\n            else\n                echoContent red \" ---> Failed to add port hopping\"\n            fi\n        # fi\n        fi\n\n    fi\n}\n\n# Read port hopping configuration\nreadHysteriaPortHopping() {\n    if [[ -n \"${hysteriaPort}\" ]]; then\n        #        interfaceName=$(ip -4 addr show | awk '/inet /{print $NF \":\" $2}' | awk '{print \"\"NR\"\"\":\"$0}' | grep \"${selectInterface}:\" | awk -F \"[:]\" '{print $2}')\n        if iptables-save | grep -q \"mack-a_portHopping\"; then\n            portHopping=\n            portHopping=$(iptables-save | grep \"mack-a_portHopping\" | cut -d \" \" -f 8)\n            portHoppingStart=$(echo \"${portHopping}\" | cut -d \":\" -f 1)\n            portHoppingEnd=$(echo \"${portHopping}\" | cut -d \":\" -f 2)\n        fi\n    fi\n}\n\n# Delete hysteria port treaty iptables rules\ndeleteHysteriaPortHoppingRules() {\n    iptables -t nat -L PREROUTING --line-numbers | grep \"mack-a_portHopping\" | awk '{print $1}' | while read -r line; do\n        iptables -t nat -D PREROUTING 1\n    done\n}\n\nhysteriaPortHoppingMenu() {\n    # Determine whether iptables exists\n    if ! find /usr/bin /usr/sbin | grep -q -w iptables; then\n        echoContent red \" ---> Unable to recognize iptables tool, unable to use port jump, exit installation\"\n        exit 0\n    fi\n    readHysteriaConfig\n    readHysteriaPortHopping\n    echoContent skyBlue \"\\nProgress 1/1: Port jump\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.Add port hopping\"\n    echoContent yellow \"2.Delete port hopping\"\n    echoContent yellow \"3.Check port jumping\"\n    read -r -p \"range:\" selectPortHoppingStatus\n    if [[ \"${selectPortHoppingStatus}\" == \"1\" ]]; then\n        hysteriaPort Hopping\n    elif [[ \"${selectPortHoppingStatus}\" == \"2\" ]]; then\n        if [[ -n \"${portHopping}\" ]]; then\n            deleteHysteriaPortHoppingRules\n            echoContent green \" ---> Deletion successful\"\n        fi\n    elif [[ \"${selectPortHoppingStatus}\" == \"3\" ]]; then\n        echoContent green \" ---> The current port hopping range is: ${portHoppingStart}-${portHoppingEnd}\"\n    else\n        hysteriaPortHoppingMenu\n    fi\n}\n#Initialize Hysteria configuration\ninitHysteriaConfig() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Initializing Hysteria configuration\"\n\n    initHysteriaPort\n    initHysteriaProtocol\n    initHysteriaNetwork\n    local uuid=\n    uuid=$(${ctlPath} uuid)\n    getClients \"${configPath}${frontingType}.json\" true\n    cat <<EOF >/etc/v2ray-agent/hysteria/conf/config.json\n{\n\t\"listen\": \":${hysteriaPort}\",\n\t\"protocol\": \"${hysteriaProtocol}\",\n\t\"disable_udp\": false,\n\t\"cert\": \"/etc/v2ray-agent/tls/${currentHost}.crt\",\n\t\"key\": \"/etc/v2ray-agent/tls/${currentHost}.key\",\n\t\"auth\": {\n\t\t\"mode\": \"passwords\",\n\t\t\"config\": []\n\t},\n\t\"socks5_outbound\":{\n\t    \"server\":\"127.0.0.1:31295\",\n\t    \"user\":\"hysteria_socks5_outbound\",\n\t    \"password\":\"${uuid}\"\n\t},\n\t\"alpn\": \"h3\",\n\t\"recv_window_conn\": 15728640,\n\t\"recv_window_client\": 67108864,\n\t\"max_conn_client\": 4096,\n\t\"disable_mtu_discovery\": true,\n\t\"resolve_preference\": \"46\",\n\t\"resolver\": \"https://8.8.8.8:443/dns-query\"\n}\nEOF\n\n    addClientsHysteria \"/etc/v2ray-agent/hysteria/conf/config.json\" true\n\n    # Add socks inbound\n    cat <<EOF >${configPath}/02_socks_inbounds_hysteria.json\n{\n  \"inbounds\": [\n    {\n      \"listen\": \"127.0.0.1\",\n      \"port\": 31295,\n      \"protocol\": \"Socks\",\n      \"tag\": \"socksHysteriaOutbound\",\n      \"settings\": {\n        \"auth\": \"password\",\n        \"accounts\": [\n          {\n            \"user\": \"hysteria_socks5_outbound\",\n            \"pass\": \"${uuid}\"\n          }\n        ],\n        \"udp\": true,\n        \"ip\": \"127.0.0.1\"\n      }\n    }\n  ]\n}\nEOF\n}\n\n#Initialize tuic port\ninitTuicPort() {\n    readTuicConfig\n    if [[ -n \"${tuicPort}\" ]]; then\n        read -r -p \"Read the port from the last installation. Do you want to use the port from the last installation? [y/n]:\" historyTuicPortStatus\n        if [[ \"${historyTuicPortStatus}\" == \"y\" ]]; then\n            echoContent yellow \"\\n ---> Port: ${tuicPort}\"\n        else\n            tuicPort=\n        fi\n    fi\n\n    if [[ -z \"${tuicPort}\" ]]; then\n        echoContent yellow \"Please enter the Tuic port [enter random 10000-30000], cannot be repeated with other services\"\n        read -r -p \"Port:\" tuicPort\n        if [[ -z \"${tuicPort}\" ]]; then\n            tuicPort=$((RANDOM % 20001 + 10000))\n        fi\n    fi\n    if [[ -z ${tuicPort} ]]; then\n        echoContent red \" ---> Port cannot be empty\"\n        initTuicPort \"$2\"\n    elif ((tuicPort < 1 || tuicPort > 65535)); then\n        echoContent red \" ---> The port is illegal\"\n        initTuicPort \"$2\"\n    fi\n    echoContent green \"\\n ---> Port: ${tuicPort}\"\n    allowPort \"${tuicPort}\"\n    allowPort \"${tuicPort}\" \"udp\"\n}\n\n# Initialize tuic protocol\ninitTuicProtocol() {\n    echoContent skyBlue \"\\nPlease select the algorithm type\"\n    echoContent red \"================================================== ===============\"\n    echoContent yellow \"1.bbr(default)\"\n    echoContent yellow \"2.cubic\"\n    echoContent yellow \"3.new_reno\"\n    echoContent red \"================================================== =========== ====\"\n    read -r -p \"Please select:\" selectTuicAlgorithm\n    case ${selectTuicAlgorithm} in\n    1)\n        tuicAlgorithm=\"bbr\"\n        ;;\n    2)\n        tuicAlgorithm=\"cubic\"\n        ;;\n    3)\n        tuicAlgorithm=\"new_reno\"\n        ;;\n    *)\n        tuicAlgorithm=\"bbr\"\n        ;;\n    esac\n    echoContent yellow \"\\n ---> Algorithm: ${tuicAlgorithm}\\n\"\n}\n\n# Initialize tuic configuration\ninitTuicConfig() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Initializing Tuic configuration\"\n\n    initTuicPort\n    initTuicProtocol\n    cat <<EOF >/etc/v2ray-agent/tuic/conf/config.json\n{\n    \"server\": \"[::]:${tuicPort}\",\n    \"users\": $(initXrayClients 9),\n    \"certificate\": \"/etc/v2ray-agent/tls/${currentHost}.crt\",\n    \"private_key\": \"/etc/v2ray-agent/tls/${currentHost}.key\",\n    \"congestion_control\":\"${tuicAlgorithm}\",\n    \"alpn\": [\"h3\"],\n    \"log_level\": \"warn\"\n}\nEOF\n}\n\n# Tuic installation\ntuicCoreInstall() {\n    if ! echo \"${currentInstallProtocolType}\" | grep -q \"0\" || [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n ---> Due to environmental dependencies, if you install Tuic, please install Xray-core's VLESS_TCP_TLS_Vision first\"\n        exit 0\n    fi\n    totalProgress=5\n    installTuic 1\n    initTuicConfig 2\n    installTuicService 3\n    reloadCore\n    showAccounts 4\n}\n\n#Initialize V2Ray configuration file\ninitV2RayConfig() {\n    echoContent skyBlue \"\\nProgress$2/${totalProgress}: Initializing V2Ray configuration\"\n    echo\n\n    read -r -p \"Do you want to customize the UUID? [y/n]:\" customUUIDStatus\n    echo\n    if [[ \"${customUUIDStatus}\" == \"y\" ]]; then\n        read -r -p \"Please enter a valid UUID:\" currentCustomUUID\n        if [[ -n \"${currentCustomUUID}\" ]]; then\n            uuid=${currentCustomUUID}\n        fi\n    fi\n    local addClientsStatus=\n    if [[ -n \"${currentUUID}\" && -z \"${uuid}\" ]]; then\n        read -r -p \"Read the last installation record. Do you want to use the UUID from the last installation? [y/n]:\" historyUUIDStatus\n        if [[ \"${historyUUIDStatus}\" == \"y\" ]]; then\n            uuid=${currentUUID}\n            addClientsStatus=true\n        else\n            uuid=$(/etc/v2ray-agent/v2ray/v2ctl uuid)\n        fi\n    elif [[ -z \"${uuid}\" ]]; then\n        uuid=$(/etc/v2ray-agent/v2ray/v2ctl uuid)\n    fi\n\n    if [[ -z \"${uuid}\" ]]; then\n        addClientsStatus=\n        echoContent red \"\\n ---> uuid reading error, regenerate\"\n        uuid=$(/etc/v2ray-agent/v2ray/v2ctl uuid)\n    fi\n\n    movePreviousConfig\n    # log\n    cat <<EOF >/etc/v2ray-agent/v2ray/conf/00_log.json\n{\n  \"log\": {\n    \"error\": \"/etc/v2ray-agent/v2ray/error.log\",\n    \"loglevel\": \"warning\"\n  }\n}\nEOF\n    # outbounds\n    if [[ -n \"${pingIPv6}\" ]]; then\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/10_ipv6_outbounds.json\n{\n    \"outbounds\": [\n        {\n          \"protocol\": \"freedom\",\n          \"settings\": {},\n          \"tag\": \"direct\"\n        }\n    ]\n}\nEOF\n\n    else\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/10_ipv4_outbounds.json\n{\n    \"outbounds\":[\n        {\n            \"protocol\":\"freedom\",\n            \"settings\":{\n                \"domainStrategy\":\"UseIPv4\"\n            },\n            \"tag\":\"IPv4-out\"\n        },\n        {\n            \"protocol\":\"freedom\",\n            \"settings\":{\n                \"domainStrategy\":\"UseIPv6\"\n            },\n            \"tag\":\"IPv6-out\"\n        },\n        {\n            \"protocol\":\"blackhole\",\n            \"tag\":\"blackhole-out\"\n        }\n    ]\n}\nEOF\n    fi\n\n    # dns\n    cat <<EOF >/etc/v2ray-agent/v2ray/conf/11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n          \"localhost\"\n        ]\n  }\n}\nEOF\n\n    # VLESS_TCP_TLS\n    # Fall back nginx\n    local fallbacksList='{\"dest\":31300,\"xver\":0},{\"alpn\":\"h2\",\"dest\":31302,\"xver\":0}'\n\n    #trojan\n    if echo \"${selectCustomInstallType}\" | grep -q 4 || [[ \"$1\" == \"all\" ]]; then\n\n        fallbacksList='{\"dest\":31296,\"xver\":1},{\"alpn\":\"h2\",\"dest\":31302,\"xver\":0}'\n\n        getClients \"${configPath}../tmp/04_trojan_TCP_inbounds.json\" \"${addClientsStatus}\"\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/04_trojan_TCP_inbounds.json\n{\n\"inbounds\":[\n\t{\n\t  \"port\": 31296,\n\t  \"listen\": \"127.0.0.1\",\n\t  \"protocol\": \"trojan\",\n\t  \"tag\":\"trojanTCP\",\n\t  \"settings\": {\n\t\t\"clients\": [\n\t\t  {\n\t\t\t\"password\": \"${uuid}\",\n\t\t\t\"email\": \"default_Trojan_TCP\"\n\t\t  }\n\t\t],\n\t\t\"fallbacks\":[\n\t\t\t{\"dest\":\"31300\"}\n\t\t]\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"tcp\",\n\t\t\"security\": \"none\",\n\t\t\"tcpSettings\": {\n\t\t\t\"acceptProxyProtocol\": true\n\t\t}\n\t}\n\t}\n\t]\n}\nEOF\n        addClients \"/etc/v2ray-agent/v2ray/conf/04_trojan_TCP_inbounds.json\" \"${addClientsStatus}\"\n    fi\n\n    # VLESS_WS_TLS\n    if echo \"${selectCustomInstallType}\" | grep -q 1 || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList=${fallbacksList}',{\"path\":\"/'${customPath}'ws\",\"dest\":31297,\"xver\":1}'\n        getClients \"${configPath}../tmp/03_VLESS_WS_inbounds.json\" \"${addClientsStatus}\"\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/03_VLESS_WS_inbounds.json\n{\n\"inbounds\":[\n    {\n\t  \"port\": 31297,\n\t  \"listen\": \"127.0.0.1\",\n\t  \"protocol\": \"vless\",\n\t  \"tag\":\"VLESSWS\",\n\t  \"settings\": {\n\t\t\"clients\": [\n\t\t  {\n\t\t\t\"id\": \"${uuid}\",\n\t\t\t\"email\": \"default_VLESS_WS\"\n\t\t  }\n\t\t],\n\t\t\"decryption\": \"none\"\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"ws\",\n\t\t\"security\": \"none\",\n\t\t\"wsSettings\": {\n\t\t  \"acceptProxyProtocol\": true,\n\t\t  \"path\": \"/${customPath}ws\"\n\t\t}\n\t  }\n\t}\n]\n}\nEOF\n        addClients \"/etc/v2ray-agent/v2ray/conf/03_VLESS_WS_inbounds.json\" \"${addClientsStatus}\"\n    fi\n\n    # trojan_grpc\n    if echo \"${selectCustomInstallType}\" | grep -q 2 || [[ \"$1\" == \"all\" ]]; then\n        if ! echo \"${selectCustomInstallType}\" | grep -q 5 && [[ -n ${selectCustomInstallType} ]]; then\n            fallbacksList=${fallbacksList//31302/31304}\n        fi\n        getClients \"${configPath}../tmp/04_trojan_gRPC_inbounds.json\" \"${addClientsStatus}\"\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/04_trojan_gRPC_inbounds.json\n{\n    \"inbounds\": [\n        {\n            \"port\": 31304,\n            \"listen\": \"127.0.0.1\",\n            \"protocol\": \"trojan\",\n            \"tag\": \"trojangRPCTCP\",\n            \"settings\": {\n                \"clients\": [\n                    {\n                        \"password\": \"${uuid}\",\n                        \"email\": \"default_Trojan_gRPC\"\n                    }\n                ],\n                \"fallbacks\": [\n                    {\n                        \"dest\": \"31300\"\n                    }\n                ]\n            },\n            \"streamSettings\": {\n                \"network\": \"grpc\",\n                \"grpcSettings\": {\n                    \"serviceName\": \"${customPath}trojangrpc\"\n                }\n            }\n        }\n    ]\n}\nEOF\n        addClients \"/etc/v2ray-agent/v2ray/conf/04_trojan_gRPC_inbounds.json\" \"${addClientsStatus}\"\n    fi\n\n    # VMess_WS\n    if echo \"${selectCustomInstallType}\" | grep -q 3 || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList=${fallbacksList}',{\"path\":\"/'${customPath}'vws\",\"dest\":31299,\"xver\":1}'\n\n        getClients \"${configPath}../tmp/05_VMess_WS_inbounds.json\" \"${addClientsStatus}\"\n\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/05_VMess_WS_inbounds.json\n{\n\"inbounds\":[\n{\n  \"listen\": \"127.0.0.1\",\n  \"port\": 31299,\n  \"protocol\": \"vmess\",\n  \"tag\":\"VMessWS\",\n  \"settings\": {\n    \"clients\": [\n      {\n        \"id\": \"${uuid}\",\n        \"alterId\": 0,\n        \"add\": \"${add}\",\n        \"email\": \"default_VMess_WS\"\n      }\n    ]\n  },\n  \"streamSettings\": {\n    \"network\": \"ws\",\n    \"security\": \"none\",\n    \"wsSettings\": {\n      \"acceptProxyProtocol\": true,\n      \"path\": \"/${customPath}vws\"\n    }\n  }\n}\n]\n}\nEOF\n        addClients \"/etc/v2ray-agent/v2ray/conf/05_VMess_WS_inbounds.json\" \"${addClientsStatus}\"\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q 5 || [[ \"$1\" == \"all\" ]]; then\n        getClients \"${configPath}../tmp/06_VLESS_gRPC_inbounds.json\" \"${addClientsStatus}\"\n        cat <<EOF >/etc/v2ray-agent/v2ray/conf/06_VLESS_gRPC_inbounds.json\n{\n    \"inbounds\":[\n    {\n        \"port\": 31301,\n        \"listen\": \"127.0.0.1\",\n        \"protocol\": \"vless\",\n        \"tag\":\"VLESSGRPC\",\n        \"settings\": {\n            \"clients\": [\n                {\n                    \"id\": \"${uuid}\",\n                    \"add\": \"${add}\",\n                    \"email\": \"default_VLESS_gRPC\"\n                }\n            ],\n            \"decryption\": \"none\"\n        },\n        \"streamSettings\": {\n            \"network\": \"grpc\",\n            \"grpcSettings\": {\n                \"serviceName\": \"${customPath}grpc\"\n            }\n        }\n    }\n]\n}\nEOF\n        addClients \"/etc/v2ray-agent/v2ray/conf/06_VLESS_gRPC_inbounds.json\" \"${addClientsStatus}\"\n    fi\n\n    # VLESS_TCP\n    getClients \"${configPath}../tmp/02_VLESS_TCP_inbounds.json\" \"${addClientsStatus}\"\n    local defaultPort=443\n    if [[ -n \"${customPort}\" ]]; then\n        defaultPort=${customPort}\n    fi\n\n    cat <<EOF >/etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json\n{\n\"inbounds\":[\n{\n  \"port\": ${defaultPort},\n  \"protocol\": \"vless\",\n  \"tag\":\"VLESSTCP\",\n  \"settings\": {\n    \"clients\": [\n     {\n        \"id\": \"${uuid}\",\n        \"add\":\"${add}\",\n        \"email\": \"default_VLESS_TCP\"\n      }\n    ],\n    \"decryption\": \"none\",\n    \"fallbacks\": [\n        ${fallbacksList}\n    ]\n  },\n  \"streamSettings\": {\n    \"network\": \"tcp\",\n    \"security\": \"tls\",\n    \"tlsSettings\": {\n      \"minVersion\": \"1.2\",\n      \"alpn\": [\n        \"http/1.1\",\n        \"h2\"\n      ],\n      \"certificates\": [\n        {\n          \"certificateFile\": \"/etc/v2ray-agent/tls/${domain}.crt\",\n          \"keyFile\": \"/etc/v2ray-agent/tls/${domain}.key\",\n          \"ocspStapling\": 3600,\n          \"usage\":\"encipherment\"\n        }\n      ]\n    }\n  }\n}\n]\n}\nEOF\n    addClients \"/etc/v2ray-agent/v2ray/conf/02_VLESS_TCP_inbounds.json\" \"${addClientsStatus}\"\n\n}\n\n# Initialize Xray Trojan XTLS configuration file\ninitXrayFrontingConfig() {\n    echoContent red \" ---> Trojan does not currently support xtls-rprx-vision\"\n    exit 0\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> Not installed, please use script to install\"\n        menu\n        exit 0\n    fi\n    if [[ \"${coreInstallType}\" != \"1\" ]]; then\n        echoContent red \" ---> Available types are not installed\"\n    fi\n    local xtlsType=\n    if echo ${currentInstallProtocolType} | grep -q trojan; then\n        xtlsType=VLESS\n    else\n        xtlsType=Trojan\n\n    fi\n\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Switch to ${xtlsType}\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\\n\"\n    echoContent yellow \"will replace the prefix with ${xtlsType}\"\n    echoContent yellow \"If the prefix is Trojan, two Trojan protocol nodes will appear when viewing the account, and one of them is unavailable xtls\"\n    echoContent yellow \"Execute again to switch to the last prefix\\n\"\n\n    echoContent yellow \"1.Switch to ${xtlsType}\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectType\n    if [[ \"${selectType}\" == \"1\" ]]; then\n\n        if [[ \"${xtlsType}\" == \"Trojan\" ]]; then\n\n            local VLESSConfig\n            VLESSConfig=$(cat ${configPath}${frontingType}.json)\n            VLESSConfig=${VLESSConfig//\"id\"/\"password\"}\n            VLESSConfig=${VLESSConfig//VLESSTCP/TrojanTCPXTLS}\n            VLESSConfig=${VLESSConfig//VLESS/Trojan}\n            VLESSConfig=${VLESSConfig//\"vless\"/\"trojan\"}\n            VLESSConfig=${VLESSConfig//\"id\"/\"password\"}\n\n            echo \"${VLESSConfig}\" | jq . >${configPath}02_trojan_TCP_inbounds.json\n            rm ${configPath}${frontingType}.json\n        elif [[ \"${xtlsType}\" == \"VLESS\" ]]; then\n\n            local VLESSConfig\n            VLESSConfig=$(cat ${configPath}02_trojan_TCP_inbounds.json)\n            VLESSConfig=${VLESSConfig//\"password\"/\"id\"}\n            VLESSConfig=${VLESSConfig//TrojanTCPXTLS/VLESSTCP}\n            VLESSConfig=${VLESSConfig//Trojan/VLESS}\n            VLESSConfig=${VLESSConfig//\"trojan\"/\"vless\"}\n            VLESSConfig=${VLESSConfig//\"password\"/\"id\"}\n\n            echo \"${VLESSConfig}\" | jq . >${configPath}02_VLESS_TCP_inbounds.json\n            rm ${configPath}02_trojan_TCP_inbounds.json\n        fi\n        reloadCore\n    fi\n\n    exit 0\n}\n\n# Move the last configuration file to a temporary file\nmovePreviousConfig() {\n\n    if [[ -n \"${configPath}\" ]]; then\n        if [[ -z \"${realityStatus}\" ]]; then\n            rm -rf \"${configPath}../tmp/*\" 2>/dev/null\n            mv ${configPath}[0][2-6]* ${configPath}../tmp/ 2>/dev/null\n        else\n            rm -rf \"${configPath}../tmp/*\"\n            mv ${configPath}[0][7-8]* ${configPath}../tmp/ 2>/dev/null\n            mv ${configPath}[0][2]* ${configPath}../tmp/ 2>/dev/null\n        fi\n\n    fi\n}\n\n#Initialize Xray configuration file\ninitXrayConfig() {\n    echoContent skyBlue \"\\nProgress$2/${totalProgress}: Initializing Xray configuration\"\n    echo\n    local uuid=\n    local addClientsStatus=\n    if [[ -n \"${currentUUID}\" ]]; then\n        read -r -p \"Read the last user configuration. Do you want to use the last installed configuration? [y/n]:\" historyUUIDStatus\n        if [[ \"${historyUUIDStatus}\" == \"y\" ]]; then\n            addClientsStatus=true\n            echoContent green \"\\n ---> Used successfully\"\n        fi\n    fi\n\n    if [[ -z \"${addClientsStatus}\" ]]; then\n        echoContent yellow \"Please enter custom UUID [need to be legal], [Enter] random UUID\"\n        read -r -p 'UUID:' customUUID\n\n        if [[ -n ${customUUID} ]]; then\n            uuid=${customUUID}\n        else\n            uuid=$(/etc/v2ray-agent/xray/xray uuid)\n        fi\n\n    fi\n\n    if [[ -z \"${addClientsStatus}\" && -z \"${uuid}\" ]]; then\n        addClientsStatus=\n        echoContent red \"\\n ---> uuid reading error, randomly generated\"\n        uuid=$(/etc/v2ray-agent/xray/xray uuid)\n    fi\n\n    if [[ -n \"${uuid}\" ]]; then\n        currentClients='[{\"id\":\"'${uuid}'\",\"add\":\"'${add}'\",\"flow\":\"xtls-rprx-vision\",\"email\":\"'${uuid}'-VLESS_TCP/TLS_Vision\"}]'\n        echoContent yellow \"\\n ${uuid}\"\n    fi\n\n    #log\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/00_log.json\" ]]; then\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/00_log.json\n{\n  \"log\": {\n    \"error\": \"/etc/v2ray-agent/xray/error.log\",\n    \"loglevel\": \"warning\"\n  }\n}\nEOF\n    fi\n\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/12_policy.json\" ]]; then\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/12_policy.json\n{\n  \"policy\": {\n      \"levels\": {\n          \"0\": {\n              \"handshake\": $((1 + RANDOM % 4)),\n              \"connIdle\": $((250 + RANDOM % 51))\n          }\n      }\n  }\n}\nEOF\n    fi\n\n    # outbounds\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/10_ipv6_outbounds.json\" ]]; then\n        if [[ -n \"${pingIPv6}\" ]]; then\n            cat <<EOF >/etc/v2ray-agent/xray/conf/10_ipv6_outbounds.json\n{\n    \"outbounds\": [\n        {\n          \"protocol\": \"freedom\",\n          \"settings\": {},\n          \"tag\": \"direct\"\n        }\n    ]\n}\nEOF\n\n        else\n            cat <<EOF >/etc/v2ray-agent/xray/conf/10_ipv4_outbounds.json\n{\n    \"outbounds\":[\n        {\n            \"protocol\":\"freedom\",\n            \"settings\":{\n                \"domainStrategy\":\"UseIPv4\"\n            },\n            \"tag\":\"IPv4-out\"\n        },\n        {\n            \"protocol\":\"freedom\",\n            \"settings\":{\n                \"domainStrategy\":\"UseIPv6\"\n            },\n            \"tag\":\"IPv6-out\"\n        },\n        {\n            \"protocol\":\"freedom\",\n            \"settings\": {},\n            \"tag\":\"direct\"\n        },\n        {\n            \"protocol\":\"blackhole\",\n            \"tag\":\"blackhole-out\"\n        }\n    ]\n}\nEOF\n        fi\n    fi\n\n    # dns\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/11_dns.json\" ]]; then\n        cat <<EOF >/etc/v2ray-agent/xray/conf/11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n          \"localhost\"\n        ]\n  }\n}\nEOF\n    fi\n    # routing\n    if [[ ! -f \"/etc/v2ray-agent/xray/conf/09_routing.json\" ]]; then\n        cat <<EOF >/etc/v2ray-agent/xray/conf/09_routing.json\n{\n  \"routing\": {\n    \"rules\": [\n      {\n        \"type\": \"field\",\n        \"domain\": [\n          \"domain:gstatic.com\",\n          \"domain:googleapis.com\"\n        ],\n        \"outboundTag\": \"direct\"\n      }\n    ]\n  }\n}\nEOF\n    fi\n    # VLESS_TCP_TLS_Vision\n    # Fall back nginx\n    local fallbacksList='{\"dest\":31300,\"xver\":0},{\"alpn\":\"h2\",\"dest\":31302,\"xver\":0}'\n\n    # trojan\n    if echo \"${selectCustomInstallType}\" | grep -q 4 || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList='{\"dest\":31296,\"xver\":1},{\"alpn\":\"h2\",\"dest\":31302,\"xver\":0}'\n        cat <<EOF >/etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json\n{\n\"inbounds\":[\n\t{\n\t  \"port\": 31296,\n\t  \"listen\": \"127.0.0.1\",\n\t  \"protocol\": \"trojan\",\n\t  \"tag\":\"trojanTCP\",\n\t  \"settings\": {\n\t\t\"clients\": $(initXrayClients 4),\n\t\t\"fallbacks\":[\n\t\t\t{\"dest\":\"31300\"}\n\t\t]\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"tcp\",\n\t\t\"security\": \"none\",\n\t\t\"tcpSettings\": {\n\t\t\t\"acceptProxyProtocol\": true\n\t\t}\n\t}\n\t}\n\t]\n}\nEOF\n    else\n        rm /etc/v2ray-agent/xray/conf/04_trojan_TCP_inbounds.json >/dev/null 2>&1\n    fi\n\n    # VLESS_WS_TLS\n    if echo \"${selectCustomInstallType}\" | grep -q 1 || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList=${fallbacksList}',{\"path\":\"/'${customPath}'ws\",\"dest\":31297,\"xver\":1}'\n        cat <<EOF >/etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json\n{\n\"inbounds\":[\n    {\n\t  \"port\": 31297,\n\t  \"listen\": \"127.0.0.1\",\n\t  \"protocol\": \"vless\",\n\t  \"tag\":\"VLESSWS\",\n\t  \"settings\": {\n\t\t\"clients\": $(initXrayClients 1),\n\t\t\"decryption\": \"none\"\n\t  },\n\t  \"streamSettings\": {\n\t\t\"network\": \"ws\",\n\t\t\"security\": \"none\",\n\t\t\"wsSettings\": {\n\t\t  \"acceptProxyProtocol\": true,\n\t\t  \"path\": \"/${customPath}ws\"\n\t\t}\n\t  }\n\t}\n]\n}\nEOF\n    else\n        rm /etc/v2ray-agent/xray/conf/03_VLESS_WS_inbounds.json >/dev/null 2>&1\n    fi\n\n    # trojan_grpc\n    if echo \"${selectCustomInstallType}\" | grep -q 2 || [[ \"$1\" == \"all\" ]]; then\n        if ! echo \"${selectCustomInstallType}\" | grep -q 5 && [[ -n ${selectCustomInstallType} ]]; then\n            fallbacksList=${fallbacksList//31302/31304}\n        fi\n        cat <<EOF >/etc/v2ray-agent/xray/conf/04_trojan_gRPC_inbounds.json\n{\n    \"inbounds\": [\n        {\n            \"port\": 31304,\n            \"listen\": \"127.0.0.1\",\n            \"protocol\": \"trojan\",\n            \"tag\": \"trojangRPCTCP\",\n            \"settings\": {\n                \"clients\": $(initXrayClients 2),\n                \"fallbacks\": [\n                    {\n                        \"dest\": \"31300\"\n                    }\n                ]\n            },\n            \"streamSettings\": {\n                \"network\": \"grpc\",\n                \"grpcSettings\": {\n                    \"serviceName\": \"${customPath}trojangrpc\"\n                }\n            }\n        }\n    ]\n}\nEOF\n    else\n        rm /etc/v2ray-agent/xray/conf/04_trojan_gRPC_inbounds.json >/dev/null 2>&1\n    fi\n\n    # VMess_WS\n    if echo \"${selectCustomInstallType}\" | grep -q 3 || [[ \"$1\" == \"all\" ]]; then\n        fallbacksList=${fallbacksList}',{\"path\":\"/'${customPath}'vws\",\"dest\":31299,\"xver\":1}'\n        cat <<EOF >/etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json\n{\n\"inbounds\":[\n{\n  \"listen\": \"127.0.0.1\",\n  \"port\": 31299,\n  \"protocol\": \"vmess\",\n  \"tag\":\"VMessWS\",\n  \"settings\": {\n    \"clients\": $(initXrayClients 3)\n  },\n  \"streamSettings\": {\n    \"network\": \"ws\",\n    \"security\": \"none\",\n    \"wsSettings\": {\n      \"acceptProxyProtocol\": true,\n      \"path\": \"/${customPath}vws\"\n    }\n  }\n}\n]\n}\nEOF\n    else\n        rm /etc/v2ray-agent/xray/conf/05_VMess_WS_inbounds.json >/dev/null 2>&1\n    fi\n\n    if echo \"${selectCustomInstallType}\" | grep -q 5 || [[ \"$1\" == \"all\" ]]; then\n        cat <<EOF >/etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json\n{\n    \"inbounds\":[\n    {\n        \"port\": 31301,\n        \"listen\": \"127.0.0.1\",\n        \"protocol\": \"vless\",\n        \"tag\":\"VLESSGRPC\",\n        \"settings\": {\n            \"clients\": $(initXrayClients 5),\n            \"decryption\": \"none\"\n        },\n        \"streamSettings\": {\n            \"network\": \"grpc\",\n            \"grpcSettings\": {\n                \"serviceName\": \"${customPath}grpc\"\n            }\n        }\n    }\n]\n}\nEOF\n    else\n        rm /etc/v2ray-agent/xray/conf/06_VLESS_gRPC_inbounds.json >/dev/null 2>&1\n    fi\n    # VLESS Vision\n    if echo \"${selectCustomInstallType}\" | grep -q 0 || [[ \"$1\" == \"all\" ]]; then\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json\n{\n    \"inbounds\":[\n        {\n          \"port\": ${port},\n          \"protocol\": \"vless\",\n          \"tag\":\"VLESSTCP\",\n          \"settings\": {\n            \"clients\":$(initXrayClients 0),\n            \"decryption\": \"none\",\n            \"fallbacks\": [\n                ${fallbacksList}\n            ]\n          },\n          \"add\": \"${add}\",\n          \"streamSettings\": {\n            \"network\": \"tcp\",\n            \"security\": \"tls\",\n            \"tlsSettings\": {\n              \"minVersion\": \"1.2\",\n              \"alpn\": [\n                \"http/1.1\",\n                \"h2\"\n              ],\n              \"certificates\": [\n                {\n                  \"certificateFile\": \"/etc/v2ray-agent/tls/${domain}.crt\",\n                  \"keyFile\": \"/etc/v2ray-agent/tls/${domain}.key\",\n                  \"ocspStapling\": 3600,\n                  \"usage\":\"encipherment\"\n                }\n              ]\n            }\n          }\n        }\n    ]\n}\nEOF\n    else\n        rm /etc/v2ray-agent/xray/conf/02_VLESS_TCP_inbounds.json >/dev/null 2>&1\n    fi\n\n    # VLESS_TCP/reality\n    if echo \"${selectCustomInstallType}\" | grep -q 7 || [[ \"$1\" == \"all\" ]]; then\n        echoContent skyBlue \"\\n===================== Configure VLESS+Reality ==================== =\\n\"\n        initRealityPort\n        initRealityDest\n        initRealityClientServersName\n        initRealityKey\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json\n{\n  \"inbounds\": [\n    {\n      \"port\": ${realityPort},\n      \"protocol\": \"vless\",\n      \"tag\": \"VLESSReality\",\n      \"settings\": {\n        \"clients\": $(initXrayClients 7),\n        \"decryption\": \"none\",\n        \"fallbacks\":[\n            {\n                \"dest\": \"31305\",\n                \"xver\": 1\n            }\n        ]\n      },\n      \"streamSettings\": {\n        \"network\": \"tcp\",\n        \"security\": \"reality\",\n        \"realitySettings\": {\n            \"show\": false,\n            \"dest\": \"${realityDestDomain}\",\n            \"xver\": 0,\n            \"serverNames\": [\n                ${realityServerNames}\n            ],\n            \"privateKey\": \"${realityPrivateKey}\",\n            \"publicKey\": \"${realityPublicKey}\",\n            \"maxTimeDiff\": 70000,\n            \"shortIds\": [\n                \"6ba85179e30d4fc2\"\n            ]\n        }\n      }\n    }\n  ]\n}\nEOF\n\n        cat <<EOF >/etc/v2ray-agent/xray/conf/08_VLESS_reality_fallback_grpc_inbounds.json\n{\n  \"inbounds\": [\n    {\n      \"port\": 31305,\n      \"listen\": \"127.0.0.1\",\n      \"protocol\": \"vless\",\n      \"tag\": \"VLESSRealityGRPC\",\n      \"settings\": {\n        \"clients\": $(initXrayClients 8),\n        \"decryption\": \"none\"\n      },\n      \"streamSettings\": {\n            \"network\": \"grpc\",\n            \"grpcSettings\": {\n                \"serviceName\": \"grpc\",\n                \"multiMode\": true\n            },\n            \"sockopt\": {\n                \"acceptProxyProtocol\": true\n            }\n      }\n    }\n  ]\n}\nEOF\n\n    else\n        rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json >/dev/null 2>&1\n        rm /etc/v2ray-agent/xray/conf/08_VLESS_reality_fallback_grpc_inbounds.json >/dev/null 2>&1\n    fi\n    installSniffing\n}\n#Initialize Xray Reality configuration\n# Custom CDN IP\ncustomCDNIP() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Add cloudflare custom CNAME\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\"\n    echoContent yellow \"\\nTutorial address:\"\n    echoContent skyBlue \"https://www.v2ray-agent.com/archives/cloudflarezi-xuan-ip\"\n    echoContent red \"\\nIf you don't understand Cloudflare optimization, please do not use it\"\n    echoContent yellow \"\\n1.CNAME www.digitalocean.com\"\n    echoContent yellow \"2.CNAME who.int\"\n    echoContent yellow \"3.CNAME blog.hostmonit.com\"\n\n    echoContent skyBlue \"----------------------------\"\n    read -r -p \"Please select [Enter is not used]:\" selectCloudflareType\n    case ${selectCloudflareType} in\n    1)\n        add=\"www.digitalocean.com\"\n        ;;\n    2)\n        add=\"who.int\"\n        ;;\n    3)\n        add=\"blog.hostmonit.com\"\n        ;;\n    *)\n        add=\"${domain}\"\n        echoContent yellow \"\\n ---> Not used\"\n        ;;\n    esac\n}\n# General\ndefaultBase64Code() {\n    local type=$1\n    local email=$2\n    local id=$3\n    local add=$4\n    local user=\n    user=$(echo \"${email}\" | awk -F \"[-]\" '{print $1}')\n    port=${currentDefaultPort}\n\n    if [[ \"${type}\" == \"vlesstcp\" ]]; then\n\n        if [[ \"${coreInstallType}\" == \"1\" ]] && echo \"${currentInstallProtocolType}\" | grep -q 0; then\n            echoContent yellow \" ---> Universal format (VLESS+TCP+TLS_Vision)\"\n            echoContent green \" vless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=tls&fp=chrome&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx- vision#${email}\\n\"\n\n            echoContent yellow \" ---> Formatted plain text (VLESS+TCP+TLS_Vision)\"\n            echoContent green \"Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, client-fingerprint: chrome, transmission method: tcp, flow: xtls-rprx -vision, account name:${email}\\n\"\n            cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=tls&type=tcp&host=${currentHost}&fp=chrome&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\nEOF\n            cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: ${currentHost}\n    port: ${currentDefaultPort}\n    uuid: ${id}\n    network: tcp\n    tls: true\n    udp: true\n    flow: xtls-rprx-vision\n    client-fingerprint: chrome\nEOF\n            echoContent yellow \" ---> QR code VLESS(VLESS+TCP+TLS_Vision)\"\n            echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${currentHost}%3A${currentDefaultPort}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\\n\"\n        elif [[ \"${coreInstallType}\" == 2 ]]; then\n            echoContent yellow \" ---> Universal format (VLESS+TCP+TLS)\"\n            echoContent green \"    vless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&fp=chrome&headerType=none&type=tcp#${email}\\n\"\n\n            echoContent yellow \" ---> Formatted plain text (VLESS+TCP+TLS)\"\n            echoContent green \"Protocol type: VLESS, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, client-fingerprint: chrome, transmission method: tcp, account name: ${email}\\n\"\n\n            cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${currentHost}:${currentDefaultPort}?security=tls&encryption=none&host=${currentHost}&fp=chrome&headerType=none&type=tcp#${email}\nEOF\n            echoContent yellow \" ---> QR code VLESS(VLESS+TCP+TLS)\"\n            echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3a%2f%2f${id}%40${currentHost}%3a${currentDefaultPort}%3fsecurity%3dtls%26encryption%3dnone%26fp%3Dchrome%26host%3d${currentHost}%26headerType%3dnone%26type%3dtcp%23${email}\\n\"\n        fi\n\n    elif [[ \"${type}\" == \"trojanTCPXTLS\" ]]; then\n        echoContent yellow \" ---> Common format (Trojan+TCP+TLS_Vision)\"\n        echoContent green \"    trojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\\n\"\n\n        echoContent yellow \" ---> Formatted plain text (Trojan+TCP+TLS_Vision)\"\n        echoContent green \"Protocol type: Trojan, address: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: xtls, transmission method: tcp, flow: xtls-rprx-vision, account name: ${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\ntrojan://${id}@${currentHost}:${currentDefaultPort}?encryption=none&security=xtls&type=tcp&host=${currentHost}&headerType=none&sni=${currentHost}&flow=xtls-rprx-vision#${email}\nEOF\n        echoContent yellow \" ---> QR code Trojan(Trojan+TCP+TLS_Vision)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3A%2F%2F${id}%40${currentHost}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dxtls%26type%3Dtcp%26${currentHost}%3D${currentHost}%26headerType%3Dnone%26sni%3D${currentHost}%26flow%3Dxtls-rprx-vision%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"vmessws\" ]]; then\n        qrCodeBase64Default=$(echo -n \"{\\\"port\\\":${currentDefaultPort},\\\"ps\\\":\\\"${email}\\\",\\\"tls\\\":\\\"tls\\\",\\\"id\\\":\\\"${id}\\\",\\\"aid\\\":0,\\\"v\\\":2,\\\"host\\\":\\\"${currentHost}\\\",\\\"type\\\":\\\"none\\\",\\\"path\\\":\\\"/${currentPath}vws\\\",\\\"net\\\":\\\"ws\\\",\\\"add\\\":\\\"${add}\\\",\\\"allowInsecure\\\":0,\\\"method\\\":\\\"none\\\",\\\"peer\\\":\\\"${currentHost}\\\",\\\"sni\\\":\\\"${currentHost}\\\"}\" | base64 -w 0)\n        qrCodeBase64Default=\"${qrCodeBase64Default// /}\"\n\n        echoContent yellow \" ---> Universal json(VMess+WS+TLS)\"\n        echoContent green \"    {\\\"port\\\":${currentDefaultPort},\\\"ps\\\":\\\"${email}\\\",\\\"tls\\\":\\\"tls\\\",\\\"id\\\":\\\"${id}\\\",\\\"aid\\\":0,\\\"v\\\":2,\\\"host\\\":\\\"${currentHost}\\\",\\\"type\\\":\\\"none\\\",\\\"path\\\":\\\"/${currentPath}vws\\\",\\\"net\\\":\\\"ws\\\",\\\"add\\\":\\\"${add}\\\",\\\"allowInsecure\\\":0,\\\"method\\\":\\\"none\\\",\\\"peer\\\":\\\"${currentHost}\\\",\\\"sni\\\":\\\"${currentHost}\\\"}\\n\"\n        echoContent yellow \" ---> Universal vmess (VMess+WS+TLS) link\"\n        echoContent green \"    vmess://${qrCodeBase64Default}\\n\"\n        echoContent yellow \" ---> QR code vmess(VMess+WS+TLS)\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvmess://${qrCodeBase64Default}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vmess\n    server: ${add}\n    port: ${currentDefaultPort}\n    uuid: ${id}\n    alterId: 0\n    cipher: none\n    udp: true\n    tls: true\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    network: ws\n    ws-opts:\n      path: /${currentPath}vws\n      headers:\n        Host: ${currentHost}\nEOF\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vmess://${qrCodeBase64Default}\\n\"\n\n    elif [[ \"${type}\" == \"vlessws\" ]]; then\n\n        echoContent yellow \" ---> Universal format (VLESS+WS+TLS)\"\n        echoContent green \" vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=/${currentPath}ws #${email}\\n\"\n\n        echoContent yellow \" ---> Formatted plain text (VLESS+WS+TLS)\"\n        echoContent green \"Protocol type: VLESS, address: ${add}, disguised domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, client-fingerprint: chrome, user ID: ${id}, security: tls, Transmission method: ws, path: /${currentPath}ws, account name: ${email}\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=ws&host=${currentHost}&sni=${currentHost}&fp=chrome&path=/${currentPath}ws#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: ${add}\n    port: ${currentDefaultPort}\n    uuid: ${id}\n    udp: true\n    tls: true\n    network: ws\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    ws-opts:\n      path: /${currentPath}ws\n      headers:\n        Host: ${currentHost}\nEOF\n\n        echoContent yellow \" ---> QR code VLESS(VLESS+WS+TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dws%26host%3D${currentHost}%26fp%3Dchrome%26sni%3D${currentHost}%26path%3D%252f${currentPath}ws%23${email}\"\n\n    elif [[ \"${type}\" == \"vlessgrpc\" ]]; then\n\n        echoContent yellow \" ---> Universal format (VLESS+gRPC+TLS)\"\n        echoContent green \"    vless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&fp=chrome&serviceName=${currentPath}grpc&alpn=h2&sni=${currentHost}#${email}\\n\"\n\n        echoContent yellow \" ---> Formatted plain text (VLESS+gRPC+TLS)\"\n        echoContent green \"Protocol type: VLESS, address: ${add}, disguised domain name/SNI: ${currentHost}, port: ${currentDefaultPort}, user ID: ${id}, security: tls, transmission method: gRPC, alpn :h2, client-fingerprint: chrome, serviceName: ${currentPath}grpc, account name: ${email}\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@${add}:${currentDefaultPort}?encryption=none&security=tls&type=grpc&host=${currentHost}&path=${currentPath}grpc&serviceName=${currentPath}grpc&fp=chrome&alpn=h2&sni=${currentHost}#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: ${add}\n    port: ${currentDefaultPort}\n    uuid: ${id}\n    udp: true\n    tls: true\n    network: grpc\n    client-fingerprint: chrome\n    servername: ${currentHost}\n    grpc-opts:\n      grpc-service-name: ${currentPath}grpc\nEOF\n        echoContent yellow \" ---> QR code VLESS(VLESS+gRPC+TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40${add}%3A${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26type%3Dgrpc%26host%3D${currentHost}%26serviceName%3D${currentPath}grpc%26fp%3Dchrome%26path%3D${currentPath}grpc%26sni%3D${currentHost}%26alpn%3Dh2%23${email}\"\n\n    elif [[ \"${type}\" == \"trojan\" ]]; then\n        # URLEncode\n        echoContent yellow \" ---> Trojan(TLS)\"\n        echoContent green \"    trojan://${id}@${currentHost}:${currentDefaultPort}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${currentHost}_Trojan\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\ntrojan://${id}@${currentHost}:${currentDefaultPort}?peer=${currentHost}&fp=chrome&sni=${currentHost}&alpn=http/1.1#${email}_Trojan\nEOF\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: trojan\n    server: ${currentHost}\n    port: ${currentDefaultPort}\n    password: ${id}\n    client-fingerprint: chrome\n    udp: true\n    sni: ${currentHost}\nEOF\n        echoContent yellow \" ---> QR code Trojan(TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentHost}%3a${port}%3fpeer%3d${currentHost}%26fp%3Dchrome%26sni%3d${currentHost}%26alpn%3Dhttp/1.1%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"trojangrpc\" ]]; then\n        # URLEncode\n\n        echoContent yellow \" ---> Trojan gRPC(TLS)\"\n        echoContent green \"    trojan://${id}@${add}:${currentDefaultPort}?encryption=none&peer=${currentHost}&fp=chrome&security=tls&type=grpc&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\ntrojan://${id}@${add}:${currentDefaultPort}?encryption=none&peer=${currentHost}&security=tls&type=grpc&fp=chrome&sni=${currentHost}&alpn=h2&path=${currentPath}trojangrpc&serviceName=${currentPath}trojangrpc#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    server: ${add}\n    port: ${currentDefaultPort}\n    type: trojan\n    password: ${id}\n    network: grpc\n    sni: ${currentHost}\n    udp: true\n    grpc-opts:\n      grpc-service-name: ${currentPath}trojangrpc\nEOF\n        echoContent yellow \" ---> QR code Trojan gRPC(TLS)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${add}%3a${currentDefaultPort}%3Fencryption%3Dnone%26fp%3Dchrome%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"hysteria\" ]]; then\n        local hysteriaEmail=\n        hysteriaEmail=$(echo \"${email}\" | awk -F \"[-]\" '{print $1}')_hysteria\n        echoContent yellow \" ---> Hysteria(TLS)\"\n        local clashMetaPortTmp=\"port: ${hysteriaPort}\"\n        local v2rayNPortHopping=\n        local mport=\n        if [[ -n \"${portHoppingStart}\" ]]; then\n            mport=\"mport=${portHoppingStart}-${portHoppingEnd}&\"\n            clashMetaPortTmp=\"ports: ${portHoppingStart}-${portHoppingEnd}\"\n            v2rayNPortHopping=\",${portHoppingStart}-${portHoppingEnd}\"\n        fi\n        echoContent green \"    hysteria://${currentHost}:${hysteriaPort}?${mport}protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${hysteriaEmail}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nhysteria://${currentHost}:${hysteriaPort}?${mport}protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${hysteriaEmail}\nEOF\n        echoContent yellow \" ---> v2rayN(hysteria+TLS)\"\n        cat <<EOF >\"/etc/v2ray-agent/hysteria/conf/client.json\"\n{\n  \"server\": \"${currentHost}:${hysteriaPort}${v2rayNPortHopping}\",\n  \"protocol\": \"${hysteriaProtocol}\",\n  \"up_mbps\": ${hysteriaClientUploadSpeed},\n  \"down_mbps\": ${hysteriaClientDownloadSpeed},\n  \"http\": { \"listen\": \"127.0.0.1:10809\", \"timeout\": 300, \"disable_udp\": false },\n  \"socks5\": { \"listen\": \"127.0.0.1:10808\", \"timeout\": 300, \"disable_udp\": false },\n  \"obfs\": \"\",\n  \"auth_str\":\"${id}\",\n  \"alpn\": \"h3\",\n  \"acl\": \"acl/routes.acl\",\n  \"mmdb\": \"acl/Country.mmdb\",\n  \"server_name\": \"${currentHost}\",\n  \"insecure\": false,\n  \"recv_window_conn\": 5767168,\n  \"recv_window\": 23068672,\n  \"disable_mtu_discovery\": true,\n  \"resolver\": \"https://223.5.5.5/dns-query\",\n  \"retry\": 3,\n  \"retry_interval\": 3,\n  \"quit_on_disconnect\": false,\n  \"handshake_timeout\": 15,\n  \"idle_timeout\": 30,\n  \"fast_open\": true,\n  \"hop_interval\": 120\n}\nEOF\n        local v2rayNConf=\n        v2rayNConf=\"$(cat /etc/v2ray-agent/hysteria/conf/client.json)\"\n        echoContent green \"${v2rayNConf}\\n\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${hysteriaEmail}\"\n    type: hysteria\n    server: ${currentHost}\n    ${clashMetaPortTmp}\n    auth_str: ${id}\n    alpn:\n     - h3\n    protocol: ${hysteriaProtocol}\n    up: \"${hysteriaClientUploadSpeed}\"\n    down: \"${hysteriaClientDownloadSpeed}\"\n    sni: ${currentHost}\nEOF\n        echoContent yellow \" ---> QR code Hysteria(TLS)\"\n        if [[ -n \"${mport}\" ]]; then\n            mport=\"mport%3D${portHoppingStart}-${portHoppingEnd}%26\"\n        fi\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria%3A%2F%2F${currentHost}%3A${hysteriaPort}%3F${mport}protocol%3D${hysteriaProtocol}%26auth%3D${id}%26peer%3D${currentHost}%26insecure%3D0%26alpn%3Dh3%26upmbps%3D${hysteriaClientUploadSpeed}%26downmbps%3D${hysteriaClientDownloadSpeed}%23${hysteriaEmail}\\n\"\n    elif [[ \"${type}\" == \"vlessReality\" ]]; then\n        echoContent yellow \" ---> Universal format (VLESS+reality+uTLS+Vision)\"\n        echoContent green \"    vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=tcp&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\\n\"\n\n        echoContent yellow \" ---> Formatted plain text (VLESS+reality+uTLS+Vision)\"\n        echoContent green \"Protocol type: VLESS reality, address: $(getPublicIP), publicKey: ${currentRealityPublicKey}, shortId: 6ba85179e30d4fc2, serverNames: ${currentRealityServerNames}, port: ${currentRealityPort}, user ID: ${id}, transmission Method: tcp, account name: ${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=tcp&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&flow=xtls-rprx-vision#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: $(getPublicIP)\n    port: ${currentRealityPort}\n    uuid: ${id}\n    network: tcp\n    tls: true\n    udp: true\n    flow: xtls-rprx-vision\n    servername: ${currentRealityServerNames}\n    reality-opts:\n      public-key: ${currentRealityPublicKey}\n      short-id: 6ba85179e30d4fc2\n    client-fingerprint: chrome\nEOF\n        echoContent yellow \" ---> QR code VLESS(VLESS+reality+uTLS+Vision)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${currentRealityPort}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dtcp%26sni%3D${currentRealityServerNames}%26fp%3Dchrome%26pbk%3D${currentRealityPublicKey}%26pbk%3D6ba85179e30d4fc2%26flow%3Dxtls-rprx-vision%23${email}\\n\"\n\n    elif [[ \"${type}\" == \"vlessRealityGRPC\" ]]; then\n        echoContent yellow \" ---> Universal format (VLESS+reality+uTLS+gRPC)\"\n        echoContent green \"    vless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=grpc&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\\n\"\n\n        echoContent yellow \" ---> Formatted plain text (VLESS+reality+uTLS+gRPC)\"\n        echoContent green \"Protocol type: VLESS reality, serviceName: grpc, address: $(getPublicIP), publicKey: ${currentRealityPublicKey}, shortId: 6ba85179e30d4fc2, serverNames: ${currentRealityServerNames}, port: ${currentRealityPort}, user ID: ${id}, transmission method: gRPC, client-fingerprint: chrome, account name: ${email}\\n\"\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/default/${user}\"\nvless://${id}@$(getPublicIP):${currentRealityPort}?encryption=none&security=reality&type=grpc&sni=${currentRealityServerNames}&fp=chrome&pbk=${currentRealityPublicKey}&sid=6ba85179e30d4fc2&path=grpc&serviceName=grpc#${email}\nEOF\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${user}\"\n  - name: \"${email}\"\n    type: vless\n    server: $(getPublicIP)\n    port: ${currentRealityPort}\n    uuid: ${id}\n    network: grpc\n    tls: true\n    udp: true\n    servername: ${currentRealityServerNames}\n    reality-opts:\n      public-key: ${currentRealityPublicKey}\n      short-id: 6ba85179e30d4fc2\n    grpc-opts:\n      grpc-service-name: \"grpc\"\n    client-fingerprint: chrome\nEOF\n        echoContent yellow \" ---> QR code VLESS(VLESS+reality+uTLS+gRPC)\"\n        echoContent green \"    https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=vless%3A%2F%2F${id}%40$(getPublicIP)%3A${currentRealityPort}%3Fencryption%3Dnone%26security%3Dreality%26type%3Dgrpc%26sni%3D${currentRealityServerNames}%26fp%3Dchrome%26pbk%3D${currentRealityPublicKey}%26pbk%3D6ba85179e30d4fc2%26path%3Dgrpc%26serviceName%3Dgrpc%23${email}\\n\"\n    elif [[ \"${type}\" == \"tuic\" ]]; then\n\n        if [[ -z \"${email}\" ]]; then\n            echoContent red \" ---> Failed to read configuration, please reinstall\"\n            exit 0\n        fi\n\n        echoContent yellow \" ---> Formatted plain text (Tuic+TLS)\"\n        echoContent green \"Protocol type: Tuic, address: ${currentHost}, port: ${tuicPort}, uuid: ${id}, password: ${id}, congestion-controller:${tuicAlgorithm}, alpn: h3, account Name:${email}_tuic\\n\"\n\n        echoContent yellow \" ---> v2rayN(Tuic+TLS)\"\n        cat <<EOF >\"/etc/v2ray-agent/tuic/conf/v2rayN.json\"\n{\n    \"relay\": {\n        \"server\": \"${currentHost}:${tuicPort}\",\n        \"uuid\": \"${id}\",\n        \"password\": \"${id}\",\n        \"ip\": \"$(getPublicIP)\",\n        \"congestion_control\": \"${tuicAlgorithm}\",\n        \"alpn\": [\"h3\"]\n    },\n    \"local\": {\n        \"server\": \"127.0.0.1:7798\"\n    },\n    \"log_level\": \"warn\"\n}\nEOF\n        local v2rayNConf=\n        v2rayNConf=\"$(cat /etc/v2ray-agent/tuic/conf/v2rayN.json)\"\n        echoContent green \"${v2rayNConf}\"\n\n        cat <<EOF >>\"/etc/v2ray-agent/subscribe_local/clashMeta/${email}\"\n  - name: \"${email}_tuic\"\n    server: ${currentHost}\n    type: tuic\n    port: ${tuicPort}\n    uuid: ${id}\n    password: ${id}\n    alpn:\n     - h3\n    congestion-controller: ${tuicAlgorithm}\n    disable-sni: true\n    reduce-rtt: true\n    fast-open: true\n    heartbeat-interval: 8000\n    request-timeout: 8000\n    max-udp-relay-packet-size: 1500\n    max-open-streams: 100\n    ip-version: dual\n    smux:\n        enabled: false\nEOF\n    fi\n\n}\n\n# account\nshowAccounts() {\n    readInstallType\n    readInstallProtocolType\n    readConfigHostPathUUID\n    readHysteriaConfig\n    readXrayCoreRealityConfig\n    readHysteriaPortHopping\n    readTuicConfig\n    echo\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: account\"\n    local show\n    # VLESS TCP\n    if echo \"${currentInstallProtocolType}\" | grep -q trojan; then\n        echoContent skyBlue \"===================== Trojan TCP TLS_Vision ======================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}02_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            defaultBase64Code trojanTCPXTLS \"${email}\" \"$(echo \"${user}\" | jq -r .password)\"\n        done\n\n    elif echo ${currentInstallProtocolType} | grep -q 0; then\n        show=1\n        echoContent skyBlue \"============================= VLESS TCP TLS_Vision ==============================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}02_VLESS_TCP_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            defaultBase64Code vlesstcp \"${email}\" \"$(echo \"${user}\" | jq -r .id)\"\n        done\n    fi\n\n    # VLESS WS\n    if echo ${currentInstallProtocolType} | grep -q 1; then\n        echoContent skyBlue \"\\n================================ VLESS WS TLS CDN ================================\\n\"\n\n        jq .inbounds[0].settings.clients ${configPath}03_VLESS_WS_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            local path=\"${currentPath}ws\"\n            local count=\n            while read -r line; do\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vlessws \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id)\" \"${line}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentAdd}\" | tr ',' '\\n')\n\n        done\n    fi\n\n    #VLESS grpc\n    if echo ${currentInstallProtocolType} | grep -q 5; then\n        echoContent skyBlue \"\\n=============================== VLESS gRPC TLS CDN ===============================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}06_VLESS_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do\n\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            local count=\n            while read -r line; do\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vlessgrpc \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id)\" \"${line}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentAdd}\" | tr ',' '\\n')\n\n        done\n    fi\n\n    # VMess WS\n    if echo ${currentInstallProtocolType} | grep -q 3; then\n        echoContent skyBlue \"\\n================================ VMess WS TLS CDN ================================\\n\"\n        local path=\"${currentPath}vws\"\n        if [[ ${coreInstallType} == \"1\" ]]; then\n            path=\"${currentPath}vws\"\n        fi\n        jq .inbounds[0].settings.clients ${configPath}05_VMess_WS_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            local count=\n            while read -r line; do\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code vmessws \"${email}${count}\" \"$(echo \"${user}\" | jq -r .id)\" \"${line}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentAdd}\" | tr ',' '\\n')\n        done\n    fi\n\n    #trojantcp\n    if echo ${currentInstallProtocolType} | grep -q 4; then\n        echoContent skyBlue \"\\n==================================  Trojan TLS  ==================================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}04_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n            echoContent skyBlue \"\\n --->Account:${email}\"\n\n            defaultBase64Code trojan \"${email}\" \"$(echo \"${user}\" | jq -r .password)\"\n        done\n    fi\n\n    if echo ${currentInstallProtocolType} | grep -q 2; then\n        echoContent skyBlue \"\\n================================  Trojan gRPC TLS  ================================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}04_trojan_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            local count=\n            while read -r line; do\n                if [[ -n \"${line}\" ]]; then\n                    defaultBase64Code trojangrpc \"${email}${count}\" \"$(echo \"${user}\" | jq -r .password)\" \"${line}\"\n                    count=$((count + 1))\n                fi\n            done < <(echo \"${currentAdd}\" | tr ',' '\\n')\n\n        done\n    fi\n    if echo ${currentInstallProtocolType} | grep -q 6; then\n        echoContent skyBlue \"\\n================================  Hysteria TLS  ================================\\n\"\n        echoContent red \"\\n --->Hysteria speed depends on the local network environment. If it is used by QoS, the experience will be very poor. IDC may also consider it an attack, please use it with caution\"\n\n        jq .auth.config ${hysteriaConfigPath}config.json | jq -r '.[]' | while read -r user; do\n            local defaultUser=\n            local uuidType=\n            uuidType=\".id\"\n\n            if [[ \"${frontingType}\" == \"02_trojan_TCP_inbounds\" ]]; then\n                uuidType=\".password\"\n            fi\n\n            defaultUser=$(jq '.inbounds[0].settings.clients[]|select('${uuidType}'==\"'\"${user}\"'\")' ${configPath}${frontingType}.json)\n            local email=\n            email=$(echo \"${defaultUser}\" | jq -r .email)\n            local hysteriaEmail=\n            hysteriaEmail=$(echo \"${email}\" | awk -F \"[_]\" '{print $1}')_hysteria\n\n            if [[ -n ${defaultUser} ]]; then\n                echoContent skyBlue \"\\n ---> Account:$(echo \"${hysteriaEmail}\" | awk -F \"[-]\" '{print $1\"_hysteria\"}')\"\n                echo\n                defaultBase64Code hysteria \"${hysteriaEmail}\" \"${user}\"\n            fi\n\n        done\n\n    fi\n\n    # VLESS reality vision\n    if echo ${currentInstallProtocolType} | grep -q 7; then\n        show=1\n        echoContent skyBlue \"============================= VLESS reality_vision  ==============================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}07_VLESS_vision_reality_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            defaultBase64Code vlessReality \"${email}\" \"$(echo \"${user}\" | jq -r .id)\"\n        done\n    fi\n\n    # VLESS reality\n    if echo ${currentInstallProtocolType} | grep -q 8; then\n        show=1\n        echoContent skyBlue \"============================== VLESS reality_gRPC  ===============================\\n\"\n        jq .inbounds[0].settings.clients ${configPath}08_VLESS_reality_fallback_grpc_inbounds.json | jq -c '.[]' | while read -r user; do\n            local email=\n            email=$(echo \"${user}\" | jq -r .email)\n\n            echoContent skyBlue \"\\n --->Account:${email}\"\n            echo\n            defaultBase64Code vlessRealityGRPC \"${email}\" \"$(echo \"${user}\" | jq -r .id)\"\n        done\n    fi\n    #tuic\n    if echo ${currentInstallProtocolType} | grep -q 9; then\n        echoContent skyBlue \"\\n================================  Tuic TLS  ================================\\n\"\n        echoContent yellow \"\\n --->Tuic will be warmer and may have a smoother user experience than Hysteria.\"\n\n        jq -r .users[] \"${tuicConfigPath}config.json\" | while read -r id; do\n            local tuicEmail=\n            tuicEmail=$(jq -r '.inbounds[0].settings.clients[]|select(.id==\"'\"${id}\"'\")|.email' ${configPath}${frontingType}. json | awk -F \"[-]\" '{print $1}')\n\n            if [[ -n ${tuicEmail} ]]; then\n                echoContent skyBlue \"\\n --->Account:${tuicEmail}_tuic\"\n                echo\n                defaultBase64Code tuic \"${tuicEmail}\" \"${id}\"\n            fi\n\n        done\n\n    fi\n\n    if [[ -z ${show} ]]; then\n        echoContent red \" ---> not installed\"\n    fi\n}\n# Remove nginx302 configuration\nremoveNginx302() {\n    local count=\n    grep -n \"return 302\" <\"${nginxConfigPath}alone.conf\" | while read -r line; do\n\n        if ! echo \"${line}\" | grep -q \"request_uri\"; then\n            local removeIndex=\n            removeIndex=$(echo \"${line}\" | awk -F \"[:]\" '{print $1}')\n            removeIndex=$((removeIndex + count))\n            sed -i \"${removeIndex}d\" ${nginxConfigPath}alone.conf\n            count=$((count - 1))\n        fi\n    done\n}\n\n# Check if 302 is successful\ncheckNginx302() {\n    local domain302Status=\n    domain302Status=$(curl -s \"https://${currentHost}:${currentPort}\")\n    if echo \"${domain302Status}\" | grep -q \"302\"; then\n        local domain302Result=\n        domain302Result=$(curl -L -s \"https://${currentHost}:${currentPort}\")\n        if [[ -n \"${domain302Result}\" ]]; then\n            echoContent green \" ---> 302 redirection set up successfully\"\n            exit 0\n        fi\n    fi\n    echoContent red \" ---> 302 redirection setting failed, please double check whether it is the same as the example\"\n    backupNginxConfig restoreBackup\n}\n\n# Backup and restore nginx files\nbackupNginxConfig() {\n    if [[ \"$1\" == \"backup\" ]]; then\n        cp ${nginxConfigPath}alone.conf /etc/v2ray-agent/alone_backup.conf\n        echoContent green \" ---> nginx configuration file backup successful\"\n    fi\n\n    if [[ \"$1\" == \"restoreBackup\" ]] && [[ -f \"/etc/v2ray-agent/alone_backup.conf\" ]]; then\n        cp /etc/v2ray-agent/alone_backup.conf ${nginxConfigPath}alone.conf\n        echoContent green \" ---> nginx configuration file restoration backup successful\"\n        rm /etc/v2ray-agent/alone_backup.conf\n    fi\n\n}\n# Add 302 configuration\naddNginx302() {\n    # \tlocal line302Result=\n    # \tline302Result=$(| tail -n 1)\n    local count=1\n    grep -n \"Strict-Transport-Security\" <\"${nginxConfigPath}alone.conf\" | while read -r line; do\n        if [[ -n \"${line}\" ]]; then\n            local insertIndex=\n            insertIndex=\"$(echo \"${line}\" | awk -F \"[:]\" '{print $1}')\"\n            insertIndex=$((insertIndex + count))\n            sed \"${insertIndex}i return 302 '$1';\" ${nginxConfigPath}alone.conf >${nginxConfigPath}tmpfile && mv ${nginxConfigPath}tmpfile ${nginxConfigPath}alone.conf\n            count=$((count + 1))\n        else\n            echoContent red \" ---> 302 Add failed\"\n            backupNginxConfig restoreBackup\n        fi\n\n    done\n}\n\n# Update camouflage station\nupdateNginxBlog() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Change disguise site\"\n\n    if ! echo \"${currentInstallProtocolType}\" | grep -q \"0\" || [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n ---> Due to environmental dependencies, please install Xray-core's VLESS_TCP_TLS_Vision first\"\n        exit 0\n    fi\n    echoContent red \"================================================== =========== ====\"\n    echoContent yellow \"# If you need to customize, please manually copy the template file to ${nginxStaticPath} \\n\"\n    echoContent yellow \"1.Newbie guide\"\n    echoContent yellow \"2.Game website\"\n    echoContent yellow \"3.Personal blog 01\"\n    echoContent yellow \"4.Enterprise Station\"\n    echoContent yellow \"5.Unlock encrypted music file template [https://github.com/ix64/unlock-music]\"\n    echoContent yellow \"6.mikutap[https://github.com/HFIProgramming/mikutap]\"\n    echoContent yellow \"7.Enterprise Station 02\"\n    echoContent yellow \"8.Personal blog 02\"\n    echoContent yellow \"9.404 automatically jumps to baidu\"\n    echoContent yellow \"10.302 redirect website\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectInstallNginxBlogType\n\n    if [[ \"${selectInstallNginxBlogType}\" == \"10\" ]]; then\n        echoContent red \"\\n================================================ =================\"\n        echoContent yellow \"Redirect has a higher priority. If you change the camouflage site after configuring 302, the camouflage site under the root route will not work.\"\n        echoContent yellow \"If you want to disguise the site to achieve the function, you need to delete the 302 redirect configuration\\n\"\n        echoContent yellow \"1.Add\"\n        echoContent yellow \"2.Delete\"\n        echoContent red \"================================================== ===============\"\n        read -r -p \"Please select:\" redirectStatus\n\n        if [[ \"${redirectStatus}\" == \"1\" ]]; then\n            backupNginxConfig backup\n            read -r -p \"Please enter the domain name to be redirected, for example https://www.baidu.com:\" redirectDomain\n            removeNginx302\n            addNginx302 \"${redirectDomain}\"\n            handleNginx stop\n            handleNginx start\n            if [[ -z $(pgrep -f \"nginx\") ]]; then\n                backupNginxConfig restoreBackup\n                handleNginx start\n                exit 0\n            fi\n            checkNginx302\n            exit 0\n        fi\n        if [[ \"${redirectStatus}\" == \"2\" ]]; then\n            removeNginx302\n            echoContent green \" ---> Removed 302 redirect successfully\"\n            exit 0\n        fi\n    fi\n    if [[ \"${selectInstallNginxBlogType}\" =~ ^[1-9]$ ]]; then\n        rm -rf \"${nginxStaticPath}\"\n\n        wget -q -P \"${nginxStaticPath}\" \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/fodder/blog/unable/html${selectInstallNginxBlogType}.zip\" >/dev/null\n\n        unzip -o \"${nginxStaticPath}html${selectInstallNginxBlogType}.zip\" -d \"${nginxStaticPath}\" >/dev/null\n        rm -f \"${nginxStaticPath}html${selectInstallNginxBlogType}.zip*\"\n        echoContent green \" ---> Pseudo site replaced successfully\"\n    else\n        echoContent red \" ---> Wrong selection, please select again\"\n        updateNginxBlog\n    fi\n}\n\n#Add new port\naddCorePort() {\n    readHysteriaConfig\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Add new port\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\\n\"\n    echoContent yellow \"Support batch addition\"\n    echoContent yellow \"Does not affect the use of the default port\"\n    echoContent yellow \"When viewing accounts, only accounts with default ports will be displayed\"\n    echoContent yellow \"No special characters allowed, pay attention to the comma format\"\n    echoContent yellow \"If hysteria is already installed, a new hysteria port will be installed at the same time\"\n    echoContent yellow \"Input example:2053,2083,2087\\n\"\n\n    echoContent yellow \"1.Check the added port\"\n    echoContent yellow \"2.Add port\"\n    echoContent yellow \"3.Delete port\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectNewPortType\n    if [[ \"${selectNewPortType}\" == \"1\" ]]; then\n        find ${configPath} -name \"*dokodemodoor*\" | grep -v \"hysteria\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | awk -F \"[_]\" '{print $4}' | awk -F \"[.]\" '{print \"\"NR\"\"\":\"$1}'\n        exit 0\n    elif [[ \"${selectNewPortType}\" == \"2\" ]]; then\n        read -r -p \"Please enter the port number:\" newPort\n        read -r -p \"Please enter the default port number. The subscription port and node port will be changed at the same time. [Enter] Default 443:\" defaultPort\n\n        if [[ -n \"${defaultPort}\" ]]; then\n            rm -rf \"$(find ${configPath}* | grep \"default\")\"\n        fi\n\n        if [[ -n \"${newPort}\" ]]; then\n\n            while read -r port; do\n                rm -rf \"$(find ${configPath}* | grep \"${port}\")\"\n\n                local fileName=\n                local hysteriaFileName=\n                if [[ -n \"${defaultPort}\" && \"${port}\" == \"${defaultPort}\" ]]; then\n                    fileName=\"${configPath}02_dokodemodoor_inbounds_${port}_default.json\"\n                else\n                    fileName=\"${configPath}02_dokodemodoor_inbounds_${port}.json\"\n                fi\n\n                if [[ -n ${hysteriaPort} ]]; then\n                    hysteriaFileName=\"${configPath}02_dokodemodoor_inbounds_hysteria_${port}.json\"\n                fi\n\n                # open port\n                allowPort \"${port}\"\n                allowPort \"${port}\" \"udp\"\n\n                local settingsPort=443\n                if [[ -n \"${customPort}\" ]]; then\n                    settingsPort=${customPort}\n                fi\n\n                if [[ -n ${hysteriaFileName} ]]; then\n                    cat <<EOF >\"${hysteriaFileName}\"\n{\n  \"inbounds\": [\n\t{\n\t  \"listen\": \"0.0.0.0\",\n\t  \"port\": ${port},\n\t  \"protocol\": \"dokodemo-door\",\n\t  \"settings\": {\n\t\t\"address\": \"127.0.0.1\",\n\t\t\"port\": ${hysteriaPort},\n\t\t\"network\": \"udp\",\n\t\t\"followRedirect\": false\n\t  },\n\t  \"tag\": \"dokodemo-door-newPort-hysteria-${port}\"\n\t}\n  ]\n}\nEOF\n                fi\n                cat <<EOF >\"${fileName}\"\n{\n  \"inbounds\": [\n\t{\n\t  \"listen\": \"0.0.0.0\",\n\t  \"port\": ${port},\n\t  \"protocol\": \"dokodemo-door\",\n\t  \"settings\": {\n\t\t\"address\": \"127.0.0.1\",\n\t\t\"port\": ${settingsPort},\n\t\t\"network\": \"tcp\",\n\t\t\"followRedirect\": false\n\t  },\n\t  \"tag\": \"dokodemo-door-newPort-${port}\"\n\t}\n  ]\n}\nEOF\n            done < <(echo \"${newPort}\" | tr ',' '\\n')\n\n            echoContent green \" ---> Added successfully\"\n            reloadCore\n            addCorePort\n        fi\n    elif [[ \"${selectNewPortType}\" == \"3\" ]]; then\n        find ${configPath} -name \"*dokodemodoor*\" | grep -v \"hysteria\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | awk -F \"[_]\" '{print $4}' | awk -F \"[.]\" '{print \"\"NR\"\"\":\"$1}'\n        read -r -p \"Please enter the port number to be deleted:\" portIndex\n        local dokoConfig\n        dokoConfig=$(find ${configPath} -name \"*dokodemodoor*\" | grep -v \"hysteria\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | awk -F \"[_]\" '{print $4}' | awk -F \"[.]\" '{print \"\"NR\"\"\":\"$1}' | grep \"${portIndex}:\")\n        if [[ -n \"${dokoConfig}\" ]]; then\n            rm \"${configPath}02_dokodemodoor_inbounds_$(echo \"${dokoConfig}\" | awk -F \"[:]\" '{print $2}').json\"\n            local hysteriaDokodemodoorFilePath=\n\n            hysteriaDokodemodoorFilePath=\"${configPath}02_dokodemodoor_inbounds_hysteria_$(echo \"${dokoConfig}\" | awk -F \"[:]\" '{print $2}').json\"\n            if [[ -f \"${hysteriaDokodemodoorFilePath}\" ]]; then\n                rm \"${hysteriaDokodemodoorFilePath}\"\n            fi\n\n            reloadCore\n            addCorePort\n        else\n            echoContent yellow \"\\n ---> The number entered is wrong, please choose again\"\n            addCorePort\n        fi\n    fi\n}\n\n# Uninstall script\nunInstall() {\n    read -r -p \"Are you sure you want to uninstall the installation content? [y/n]:\" unInstallStatus\n    if [[ \"${unInstallStatus}\" != \"y\" ]]; then\n        echoContent green \" ---> Give up uninstalling\"\n        menu\n        exit 0\n    fi\n    echoContent yellow \" ---> The script will not delete acme related configurations. To delete, please execute manually [rm -rf /root/.acme.sh]\"\n    handleNginx stop\n    if [[ -z $(pgrep -f \"nginx\") ]]; then\n        echoContent green \" ---> Stop Nginx successfully\"\n    fi\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        handleXray stop\n        rm -rf /etc/systemd/system/xray.service\n        echoContent green \" ---> Delete Xray and it will start automatically after booting\"\n\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n\n        handleV2Ray stop\n        rm -rf /etc/systemd/system/v2ray.service\n        echoContent green \" ---> Delete V2Ray and it will start automatically after booting\"\n\n    fi\n\n    if [[ -z \"${hysteriaConfigPath}\" ]]; then\n        handleHysteria stop\n        rm -rf /etc/systemd/system/hysteria.service\n        echoContent green \" ---> Delete Hysteria and it will start automatically after booting\"\n    fi\n\n    if [[ -z \"${tuicConfigPath}\" ]]; then\n        handleTuic stop\n        rm -rf /etc/systemd/system/tuic.service\n        echoContent green \" ---> Delete Tuic and start automatically after booting\"\n    fi\n\n    # if [[ -f \"/root/.acme.sh/acme.sh.env\" ]] && grep -q 'acme.sh.env' </root/.bashrc; then\n    # sed -i 's/. \"\\/root\\/.acme.sh\\/acme.sh.env\"//g' \"$(grep '. \"/root/.acme.sh/acme.sh.env \"' -rl /root/.bashrc)\"\n    #fi\n    # rm -rf /root/.acme.sh\n\n    #rm -rf /tmp/v2ray-agent-tls/*\n    # if [[ -d \"/etc/v2ray-agent/tls\" ]] && [[ -n $(find /etc/v2ray-agent/tls/ -name \"*.key\") ]] && [[ -n $(find /etc/v2ray-agent/tls/ -name \"*.crt\") ]]; then\n    # mv /etc/v2ray-agent/tls /tmp/v2ray-agent-tls\n    # if [[ -n $(find /tmp/v2ray-agent-tls -name '*.key') ]]; then\n    # echoContent yellow \" ---> Backup certificate successful, please save it. [/tmp/v2ray-agent-tls]\"\n    #fi\n    #fi\n\n    rm -rf /etc/v2ray-agent\n    rm -rf ${nginxConfigPath}alone.conf\n\n    if [[ -d \"${nginxStaticPath}\" && -f \"${nginxStaticPath}/check\" ]]; then\n        rm -rf \"${nginxStaticPath}\"\n        echoContent green \" ---> Deletion of fake website completed\"\n    fi\n\n    rm -rf /usr/bin/vasma\n    rm -rf /usr/sbin/vasma\n    echoContent green \" ---> Uninstallation of shortcut completed\"\n    echoContent green \" ---> Uninstall v2ray-agent script completed\"\n}\n\n# Modify V2Ray CDN node\nupdateV2RayCDN() {\n\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Modify CDN node\"\n\n    if [[ -n \"${currentAdd}\" ]]; then\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"1.CNAME www.digitalocean.com\"\n        echoContent yellow \"2.CNAME who.int\"\n        echoContent yellow \"3.CNAME blog.hostmonit.com\"\n        echoContent yellow \"4.Manual input [can enter multiple, such as:1.1.1.1,1.1.2.2, cloudflare.com separated by commas]\"\n        echoContent yellow \"5.Remove CDN node\"\n        echoContent red \"================================================== ===============\"\n        read -r -p \"Please select:\" selectCDNType\n        case ${selectCDNType} in\n        1)\n            setDomain=\"www.digitalocean.com\"\n            ;;\n        2)\n            setDomain=\"who.int\"\n            ;;\n        3)\n            setDomain=\"blog.hostmonit.com\"\n            ;;\n        4)\n            read -r -p \"Please enter the CDN IP or domain name you want to customize:\" setDomain\n            ;;\n        5)\n            setDomain=${currentHost}\n            ;;\n        esac\n\n        if [[ -n \"${setDomain}\" ]]; then\n            local cdnAddressResult=\n            cdnAddressResult=$(jq -r \".inbounds[0].add = \\\"${setDomain}\\\" \" ${configPath}${frontingType}.json)\n            echo \"${cdnAddressResult}\" | jq . >${configPath}${frontingType}.json\n\n            echoContent green \" ---> CDN modified successfully\"\n        fi\n    else\n        echoContent red \" ---> Available types are not installed\"\n    fi\n}\n\n# manageUser User management\nmanageUser() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Multi-user management\"\n    echoContent skyBlue \"------------------------------------------------- ------\"\n    echoContent yellow \"1.Add user\"\n    echoContent yellow \"2.Delete user\"\n    echoContent skyBlue \"------------------------------------------------- ------\"\n    read -r -p \"Please select:\" manageUserType\n    if [[ \"${manageUserType}\" == \"1\" ]]; then\n        addUser\n    elif [[ \"${manageUserType}\" == \"2\" ]]; then\n        removeUser\n    else\n        echoContent red \" ---> Wrong selection\"\n    fi\n}\n\n# Custom uuid\ncustomUUID() {\n    read -r -p \"Please enter a legal UUID, [Enter] random UUID:\" currentCustomUUID\n    echo\n    if [[ -z \"${currentCustomUUID}\" ]]; then\n        currentCustomUUID=$(${ctlPath} uuid)\n        echoContent yellow \"uuid：${currentCustomUUID}\\n\"\n\n    else\n        jq -r -c '.inbounds[0].settings.clients[].id' ${configPath}${frontingType}.json | while read -r line; do\n            if [[ \"${line}\" == \"${currentCustomUUID}\" ]]; then\n                echo >/tmp/v2ray-agent\n            fi\n        done\n        if [[ -f \"/tmp/v2ray-agent\" && -n $(cat /tmp/v2ray-agent) ]]; then\n            echoContent red \" ---> UUID cannot be repeated\"\n            rm /tmp/v2ray-agent\n            exit 0\n        fi\n    fi\n}\n\n# Custom email\ncustomUserEmail() {\n    read -r -p \"Please enter a valid email, [Enter] random email:\" currentCustomEmail\n    echo\n    if [[ -z \"${currentCustomEmail}\" ]]; then\n        currentCustomEmail=\"${currentCustomUUID}\"\n        echoContent yellow \"email: ${currentCustomEmail}\\n\"\n    else\n        local defaultConfig=${frontingType}\n\n        if echo \"${currentInstallProtocolType}\" | grep -q \"7\" && [[ -z \"${frontingType}\" ]]; then\n            defaultConfig=\"07_VLESS_vision_reality_inbounds\"\n        fi\n\n        jq -r -c '.inbounds[0].settings.clients[].email' ${configPath}${defaultConfig}.json | while read -r line; do\n            if [[ \"${line}\" == \"${currentCustomEmail}\" ]]; then\n                echo >/tmp/v2ray-agent\n            fi\n        done\n        if [[ -f \"/tmp/v2ray-agent\" && -n $(cat /tmp/v2ray-agent) ]]; then\n            echoContent red \" ---> email cannot be repeated\"\n            rm /tmp/v2ray-agent\n            exit 0\n        fi\n    fi\n    #fi \t_\n}\n\n# Add user\naddUserXray() {\n    readConfigHostPathUUID\n    read -r -p \"Please enter the number of users to add:\" userNum\n    echo\n    if [[ -z ${userNum} || ${userNum} -le 0 ]]; then\n        echoContent red \" ---> Incorrect input, please re-enter\"\n        exit 0\n    fi\n    # Generate user\n    if [[ \"${userNum}\" == \"1\" ]]; then\n        customUUID\n        customUserEmail\n    fi\n\n    while [[ ${userNum} -gt 0 ]]; do\n        local users=\n        ((userNum--)) || true\n\n        if [[ -n \"${currentCustomUUID}\" ]]; then\n            uuid=${currentCustomUUID}\n        else\n            uuid=$(${ctlPath} uuid)\n        fi\n        local email=\n        if [[ -z \"${currentCustomEmail}\" ]]; then\n            email=${uuid}\n        else\n            email=${currentCustomEmail}\n        fi\n\n        # VLESS TCP\n        if echo \"${currentInstallProtocolType}\" | grep -q \"0\"; then\n            local clients=\n            clients=$(initXrayClients 0 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}${frontingType}.json)\n            echo \"${clients}\" | jq . >${configPath}${frontingType}.json\n        fi\n\n        # VLESS WS\n        if echo \"${currentInstallProtocolType}\" | grep -q \"1\"; then\n            local clients=\n            clients=$(initXrayClients 1 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}03_VLESS_WS_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}03_VLESS_WS_inbounds.json\n        fi\n\n        # trojan grpc\n        if echo \"${currentInstallProtocolType}\" | grep -q \"2\"; then\n            local clients=\n            clients=$(initXrayClients 2 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}04_trojan_gRPC_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}04_trojan_gRPC_inbounds.json\n        fi\n        # VMess WS\n        if echo \"${currentInstallProtocolType}\" | grep -q \"3\"; then\n            local clients=\n            clients=$(initXrayClients 3 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}05_VMess_WS_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}05_VMess_WS_inbounds.json\n        fi\n\n        # trojan tcp\n        if echo \"${currentInstallProtocolType}\" | grep -q \"4\"; then\n            local clients=\n            clients=$(initXrayClients 4 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}04_trojan_TCP_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}04_trojan_TCP_inbounds.json\n        fi\n\n        # vless grpc\n        if echo \"${currentInstallProtocolType}\" | grep -q \"5\"; then\n            local clients=\n            clients=$(initXrayClients 5 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}06_VLESS_gRPC_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}06_VLESS_gRPC_inbounds.json\n        fi\n\n        # vless reality vision\n        if echo \"${currentInstallProtocolType}\" | grep -q \"7\"; then\n            local clients=\n            clients=$(initXrayClients 7 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n\n        # vless reality grpc\n        if echo \"${currentInstallProtocolType}\" | grep -q \"8\"; then\n            local clients=\n            clients=$(initXrayClients 8 \"${uuid}\" \"${email}\")\n            clients=$(jq -r \".inbounds[0].settings.clients = ${clients}\" ${configPath}08_VLESS_reality_fallback_grpc_inbounds.json)\n            echo \"${clients}\" | jq . >${configPath}08_VLESS_reality_fallback_grpc_inbounds.json\n        fi\n\n        # hysteria\n        if echo \"${currentInstallProtocolType}\" | grep -q \"6\"; then\n            local clients=\n            clients=$(initXrayClients 6 \"${uuid}\" \"${email}\")\n\n            clients=$(jq -r \".auth.config = ${clients}\" ${hysteriaConfigPath}config.json)\n            echo \"${clients}\" | jq . >${hysteriaConfigPath}config.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 9; then\n            local tuicResult\n\n            tuicResult=$(jq -r \".users.\\\"${uuid}\\\" += \\\"${uuid}\\\"\" \"${tuicConfigPath}config.json\")\n            echo \"${tuicResult}\" | jq . >\"${tuicConfigPath}config.json\"\n        fi\n    done\n\n    reloadCore\n    echoContent green \" ---> Adding completed\"\n    manageAccount 1\n}\n# Add user\naddUser() {\n\n    echoContent yellow \"After adding a new user, you need to check the subscription again\"\n    read -r -p \"Please enter the number of users to add:\" userNum\n    echo\n    if [[ -z ${userNum} || ${userNum} -le 0 ]]; then\n        echoContent red \" ---> Incorrect input, please re-enter\"\n        exit 0\n    fi\n\n    # Generate user\n    if [[ \"${userNum}\" == \"1\" ]]; then\n        customUUID\n        customUserEmail\n    fi\n\n    while [[ ${userNum} -gt 0 ]]; do\n        local users=\n        ((userNum--)) || true\n        if [[ -n \"${currentCustomUUID}\" ]]; then\n            uuid=${currentCustomUUID}\n        else\n            uuid=$(${ctlPath} uuid)\n        fi\n\n        if [[ -n \"${currentCustomEmail}\" ]]; then\n            email=${currentCustomEmail}_${uuid}\n        else\n            email=${currentHost}_${uuid}\n        fi\n\n        #Compatible \twith v2ray-core\n        users=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"flow\\\":\\\"xtls-rprx-vision\\\",\\\"email\\\":\\\"${email}\\\",\\\"alterId\\\":0}\"\n\n        if [[ \"${coreInstallType}\" == \"2\" ]]; then\n            users=\"{\\\"id\\\":\\\"${uuid}\\\",\\\"email\\\":\\\"${email}\\\",\\\"alterId\\\":0}\"\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 0; then\n            local vlessUsers=\"${users//\\,\\\"alterId\\\":0/}\"\n            vlessUsers=\"${users//${email}/${email}_VLESS_TCP}\"\n            local vlessTcpResult\n            vlessTcpResult=$(jq -r \".inbounds[0].settings.clients += [${vlessUsers}]\" ${configPath}${frontingType}.json)\n            echo \"${vlessTcpResult}\" | jq . >${configPath}${frontingType}.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q trojan; then\n            local trojanXTLSUsers=\"${users//\\,\\\"alterId\\\":0/}\"\n            trojanXTLSUsers=\"${trojanXTLSUsers//${email}/${email}_Trojan_TCP}\"\n            trojanXTLSUsers=${trojanXTLSUsers//\"id\"/\"password\"}\n\n            local trojanXTLSResult\n            trojanXTLSResult=$(jq -r \".inbounds[0].settings.clients += [${trojanXTLSUsers}]\" ${configPath}${frontingType}.json)\n            echo \"${trojanXTLSResult}\" | jq . >${configPath}${frontingType}.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 1; then\n            local vlessUsers=\"${users//\\,\\\"alterId\\\":0/}\"\n            vlessUsers=\"${vlessUsers//${email}/${email}_VLESS_TCP}\"\n            vlessUsers=\"${vlessUsers//\\\"flow\\\":\\\"xtls-rprx-vision\\\"\\,/}\"\n            local vlessWsResult\n            vlessWsResult=$(jq -r \".inbounds[0].settings.clients += [${vlessUsers}]\" ${configPath}03_VLESS_WS_inbounds.json)\n            echo \"${vlessWsResult}\" | jq . >${configPath}03_VLESS_WS_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 2; then\n            local trojangRPCUsers=\"${users//\\\"flow\\\":\\\"xtls-rprx-vision\\\"\\,/}\"\n            trojangRPCUsers=\"${trojangRPCUsers//${email}/${email}_Trojan_gRPC}\"\n            trojangRPCUsers=\"${trojangRPCUsers//\\,\\\"alterId\\\":0/}\"\n            trojangRPCUsers=${trojangRPCUsers//\"id\"/\"password\"}\n\n            local trojangRPCResult\n            trojangRPCResult=$(jq -r \".inbounds[0].settings.clients += [${trojangRPCUsers}]\" ${configPath}04_trojan_gRPC_inbounds.json)\n            echo \"${trojangRPCResult}\" | jq . >${configPath}04_trojan_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 3; then\n            local vmessUsers=\"${users//\\\"flow\\\":\\\"xtls-rprx-vision\\\"\\,/}\"\n            vmessUsers=\"${vmessUsers//${email}/${email}_VMess_TCP}\"\n            local vmessWsResult\n            vmessWsResult=$(jq -r \".inbounds[0].settings.clients += [${vmessUsers}]\" ${configPath}05_VMess_WS_inbounds.json)\n            echo \"${vmessWsResult}\" | jq . >${configPath}05_VMess_WS_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 5; then\n            local vlessGRPCUsers=\"${users//\\\"flow\\\":\\\"xtls-rprx-vision\\\"\\,/}\"\n            vlessGRPCUsers=\"${vlessGRPCUsers//\\,\\\"alterId\\\":0/}\"\n            vlessGRPCUsers=\"${vlessGRPCUsers//${email}/${email}_VLESS_gRPC}\"\n            local vlessGRPCResult\n            vlessGRPCResult=$(jq -r \".inbounds[0].settings.clients += [${vlessGRPCUsers}]\" ${configPath}06_VLESS_gRPC_inbounds.json)\n            echo \"${vlessGRPCResult}\" | jq . >${configPath}06_VLESS_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 4; then\n            local trojanUsers=\"${users//\\\"flow\\\":\\\"xtls-rprx-vision\\\"\\,/}\"\n            trojanUsers=\"${trojanUsers//id/password}\"\n            trojanUsers=\"${trojanUsers//\\,\\\"alterId\\\":0/}\"\n            trojanUsers=\"${trojanUsers//${email}/${email}_Trojan_TCP}\"\n\n            local trojanTCPResult\n            trojanTCPResult=$(jq -r \".inbounds[0].settings.clients += [${trojanUsers}]\" ${configPath}04_trojan_TCP_inbounds.json)\n            echo \"${trojanTCPResult}\" | jq . >${configPath}04_trojan_TCP_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 6; then\n            local hysteriaResult\n            hysteriaResult=$(jq -r \".auth.config += [\\\"${uuid}\\\"]\" ${hysteriaConfigPath}config.json)\n            echo \"${hysteriaResult}\" | jq . >${hysteriaConfigPath}config.json\n        fi\n    done\n\n    reloadCore\n    echoContent green \" ---> Adding completed\"\n    manageAccount 1\n}\n\n# Remove user\nremoveUser() {\n    local uuid=\n    if echo ${currentInstallProtocolType} | grep -q 0 || echo ${currentInstallProtocolType} | grep -q trojan; then\n        jq -r -c .inbounds[0].settings.clients[].email ${configPath}${frontingType}.json | awk '{print NR\"\"\":\"$0}'\n        read -r -p \"Please select the user number to delete [only supports single deletion]:\" delUserIndex\n        if [[ $(jq -r '.inbounds[0].settings.clients|length' ${configPath}${frontingType}.json) -lt ${delUserIndex} ]]; then\n            echoContent red \" ---> Wrong selection\"\n        else\n            delUserIndex=$((delUserIndex - 1))\n            local vlessTcpResult\n            uuid=$(jq -r \".inbounds[0].settings.clients[${delUserIndex}].id\" ${configPath}${frontingType}.json)\n            vlessTcpResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}${frontingType}.json)\n            echo \"${vlessTcpResult}\" | jq . >${configPath}${frontingType}.json\n        fi\n    elif [[ -n \"${realityStatus}\" ]]; then\n        jq -r -c .inbounds[0].settings.clients[].email ${configPath}07_VLESS_vision_reality_inbounds.json | awk '{print NR\"\"\":\"$0}'\n        read -r -p \"Please select the user number to delete [only supports single deletion]:\" delUserIndex\n        if [[ $(jq -r '.inbounds[0].settings.clients|length' ${configPath}07_VLESS_vision_reality_inbounds.json) -lt ${delUserIndex} ]]; then\n            echoContent red \" ---> Wrong selection\"\n        else\n            delUserIndex=$((delUserIndex - 1))\n            local vlessRealityResult\n            uuid=$(jq -r \".inbounds[0].settings.clients[${delUserIndex}].id\" ${configPath}${frontingType}.json)\n            vlessRealityResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${vlessRealityResult}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n    fi\n\n    if [[ -n \"${delUserIndex}\" ]]; then\n        if echo ${currentInstallProtocolType} | grep -q 1; then\n            local vlessWSResult\n            vlessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}03_VLESS_WS_inbounds.json)\n            echo \"${vlessWSResult}\" | jq . >${configPath}03_VLESS_WS_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 2; then\n            local trojangRPCUsers\n            trojangRPCUsers=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}04_trojan_gRPC_inbounds.json)\n            echo \"${trojangRPCUsers}\" | jq . >${configPath}04_trojan_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 3; then\n            local vmessWSResult\n            vmessWSResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}05_VMess_WS_inbounds.json)\n            echo \"${vmessWSResult}\" | jq . >${configPath}05_VMess_WS_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 5; then\n            local vlessGRPCResult\n            vlessGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}06_VLESS_gRPC_inbounds.json)\n            echo \"${vlessGRPCResult}\" | jq . >${configPath}06_VLESS_gRPC_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 4; then\n            local trojanTCPResult\n            trojanTCPResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}04_trojan_TCP_inbounds.json)\n            echo \"${trojanTCPResult}\" | jq . >${configPath}04_trojan_TCP_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 6; then\n            local hysteriaResult\n            hysteriaResult=$(jq -r 'del(.auth.config['${delUserIndex}'])' ${hysteriaConfigPath}config.json)\n            echo \"${hysteriaResult}\" | jq . >${hysteriaConfigPath}config.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 7; then\n            local vlessRealityResult\n            vlessRealityResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${vlessRealityResult}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n        if echo ${currentInstallProtocolType} | grep -q 8; then\n            local vlessRealityGRPCResult\n            vlessRealityGRPCResult=$(jq -r 'del(.inbounds[0].settings.clients['${delUserIndex}'])' ${configPath}08_VLESS_reality_fallback_grpc_inbounds.json)\n            echo \"${vlessRealityGRPCResult}\" | jq . >${configPath}08_VLESS_reality_fallback_grpc_inbounds.json\n        fi\n\n        if echo ${currentInstallProtocolType} | grep -q 9; then\n            local tuicResult\n            tuicResult=$(jq -r \"del(.users.\\\"${uuid}\\\")\" \"${tuicConfigPath}config.json\")\n            echo \"${tuicResult}\" | jq . >\"${tuicConfigPath}config.json\"\n        fi\n        reloadCore\n    fi\n    manageAccount 1\n}\n# update script\nupdateV2RayAgent() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Update v2ray-agent script\"\n    rm -rf /etc/v2ray-agent/install.sh\n    # if wget --help | grep -q show-progress; then\n    wget -c -q \"${wgetShowProgressStatus}\" -P /etc/v2ray-agent/ -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh\"\n    #else\n    # wget -c -q -P /etc/v2ray-agent/ -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh\"\n    #fi\n\n    sudo chmod 700 /etc/v2ray-agent/install.sh\n    local version\n    version=$(grep 'Current version: v' \"/etc/v2ray-agent/install.sh\" | awk -F \"[v]\" '{print $2}' | tail -n +2 | head -n 1 | awk -F \"[\\\"]\" '{print $1}')\n\n    echoContent green \"\\n ---> Update completed\"\n    echoContent yellow \" ---> Please manually execute [vasma] to open the script\"\n    echoContent green \" ---> Current version: ${version}\\n\"\n    echoContent yellow \"If the update fails, please manually execute the following command\\n\"\n    echoContent skyBlue \"wget -P /root -N --no-check-certificate https://raw.githubusercontent.com/mack-a/v2ray-agent/master/install.sh && chmod 700 /root/install.sh && /root/install.sh\"\n    echo\n    exit 0\n}\n\n# firewall\nhandleFirewall() {\n    if systemctl status ufw 2>/dev/null | grep -q \"active (exited)\" && [[ \"$1\" == \"stop\" ]]; then\n        systemctl stop ufw >/dev/null 2>&1\n        systemctl disable ufw >/dev/null 2>&1\n        echoContent green \" ---> ufw closed successfully\"\n\n    fi\n\n    if systemctl status firewalld 2>/dev/null | grep -q \"active (running)\" && [[ \"$1\" == \"stop\" ]]; then\n        systemctl stop firewalld >/dev/null 2>&1\n        systemctl disable firewalld >/dev/null 2>&1\n        echoContent green \" ---> firewalld closed successfully\"\n    fi\n}\n\n# Install BBR\nbbrInstall() {\n    echoContent red \"\\n================================================ =================\"\n    echoContent green \"The mature works of [ylx2016] used for BBR and DD scripts, the address [https://github.com/ylx2016/Linux-NetSpeed], please be familiar with it\"\n    echoContent yellow \"1.Installation script [recommended original BBR+FQ]\"\n    echoContent yellow \"2.Return to the home directory\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" installBBRStatus\n    if [[ \"${installBBRStatus}\" == \"1\" ]]; then\n        wget -N --no-check-certificate \"https://raw.githubusercontent.com/ylx2016/Linux-NetSpeed/master/tcp.sh\" && chmod +x tcp.sh && ./tcp.sh\n    else\n        menu\n    fi\n}\n\n# View and check logs\ncheckLog() {\n    if [[ -z \"${configPath}\" && -z \"${realityStatus}\" ]]; then\n        echoContent red \" ---> The installation directory is not detected, please execute the script to install the content\"\n        exit 0\n    fi\n    local realityLogShow=\n    local logStatus=false\n    if grep -q \"access\" ${configPath}00_log.json; then\n        logStatus=true\n    fi\n\n    echoContent skyBlue \"\\nFunction$1/${totalProgress}: View log\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# It is recommended to only open the access log during debugging\\n\"\n\n    if [[ \"${logStatus}\" == \"false\" ]]; then\n        echoContent yellow \"1.Open access log\"\n    else\n        echoContent yellow \"1.Close access log\"\n    fi\n\n    echoContent yellow \"2.Monitor access log\"\n    echoContent yellow \"3.Monitor error log\"\n    echoContent yellow \"4.View certificate scheduled task log\"\n    echoContent yellow \"5.View certificate installation log\"\n    echoContent yellow \"6.Clear the log\"\n    echoContent red \"================================================== ===============\"\n\n    read -r -p \"Please select:\" selectAccessLogType\n    local configPathLog=${configPath//conf\\//}\n\n    case ${selectAccessLogType} in\n    1)\n        if [[ \"${logStatus}\" == \"false\" ]]; then\n            realityLogShow=true\n            cat <<EOF >${configPath}00_log.json\n{\n  \"log\": {\n  \t\"access\":\"${configPathLog}access.log\",\n    \"error\": \"${configPathLog}error.log\",\n    \"loglevel\": \"debug\"\n  }\n}\nEOF\n        elif [[ \"${logStatus}\" == \"true\" ]]; then\n            realityLogShow=false\n            cat <<EOF >${configPath}00_log.json\n{\n  \"log\": {\n    \"error\": \"${configPathLog}error.log\",\n    \"loglevel\": \"warning\"\n  }\n}\nEOF\n        fi\n\n        if [[ -n ${realityStatus} ]]; then\n            local vlessVisionRealityInbounds\n            vlessVisionRealityInbounds=$(jq -r \".inbounds[0].streamSettings.realitySettings.show=${realityLogShow}\" ${configPath}07_VLESS_vision_reality_inbounds.json)\n            echo \"${vlessVisionRealityInbounds}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n        fi\n        reloadCore\n        checkLog 1\n        ;;\n    2)\n        tail -f ${configPathLog}access.log\n        ;;\n    3)\n        tail -f ${configPathLog}error.log\n        ;;\n    4)\n        if [[ ! -f \"/etc/v2ray-agent/crontab_tls.log\" ]]; then\n            touch /etc/v2ray-agent/crontab_tls.log\n        fi\n        tail -n 100 /etc/v2ray-agent/crontab_tls.log\n        ;;\n    5)\n        tail -n 100 /etc/v2ray-agent/tls/acme.log\n        ;;\n    6)\n        echo >${configPathLog}access.log\n        echo >${configPathLog}error.log\n        ;;\n    esac\n}\n\n# Script shortcut\naliasInstall() {\n\n    if [[ -f \"$HOME/install.sh\" ]] && [[ -d \"/etc/v2ray-agent\" ]] && grep <\"$HOME/install.sh\" -q \"作者:mack-a\"; then\n        mv \"$HOME/install.sh\" /etc/v2ray-agent/install.sh\n        local vasmaType=\n        if [[ -d \"/usr/bin/\" ]]; then\n            if [[ ! -f \"/usr/bin/vasma\" ]]; then\n                ln -s /etc/v2ray-agent/install.sh /usr/bin/vasma\n                chmod 700 /usr/bin/vasma\n                vasmaType=true\n            fi\n\n            rm -rf \"$HOME/install.sh\"\n        elif [[ -d \"/usr/sbin\" ]]; then\n            if [[ ! -f \"/usr/sbin/vasma\" ]]; then\n                ln -s /etc/v2ray-agent/install.sh /usr/sbin/vasma\n                chmod 700 /usr/sbin/vasma\n                vasmaType=true\n            fi\n            rm -rf \"$HOME/install.sh\"\n        fi\n        if [[ \"${vasmaType}\" == \"true\" ]]; then\n            echoContent green \"The shortcut is created successfully, you can execute [vasma] to reopen the script\"\n        fi\n    fi\n}\n\n# Check ipv6, ipv4\ncheckIPv6() {\n    currentIPv6IP=$(curl -s -6 http://www.cloudflare.com/cdn-cgi/trace | grep \"ip\" | cut -d \"=\" -f 2)\n\n    if [[ -z \"${currentIPv6IP}\" ]]; then\n        echoContent red \" ---> does not support ipv6\"\n        exit 0\n    fi\n}\n\n# ipv6 offload\nipv6Routing() {\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> Not installed, please use script to install\"\n        menu\n        exit 0\n    fi\n\n    checkIPv6\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: IPv6 offload\"\n    echoContent red \"\\n================================================ ============ =====\"\n    echoContent yellow \"1.View the diverted domain name\"\n    echoContent yellow \"2.Add domain name\"\n    echoContent yellow \"3.Set IPv6 global\"\n    echoContent yellow \"4.Uninstall IPv6 offloading\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" ipv6Status\n    if [[ \"${ipv6Status}\" == \"1\" ]]; then\n\n        jq -r -c '.routing.rules[]|select (.outboundTag==\"IPv6-out\")|.domain' ${configPath}09_routing.json | jq -r\n        exit 0\n    elif [[ \"${ipv6Status}\" == \"2\" ]]; then\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"# Notes\\n\"\n        echoContent yellow \"# Notes\"\n        echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n        addInstallRouting IPv6-out outboundTag \"${domainList}\"\n\n        unInstallOutbounds IPv6-out\n\n        outbounds=$(jq -r '.outbounds += [{\"protocol\":\"freedom\",\"settings\":{\"domainStrategy\":\"UseIPv6\"},\"tag\":\"IPv6-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        echoContent green \" ---> Added successfully\"\n\n    elif [[ \"${ipv6Status}\" == \"3\" ]]; then\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"# Notes\\n\"\n        echoContent yellow \"1.All diversion rules set will be deleted\"\n        echoContent yellow \"2.All outbound rules except IPv6 will be deleted\"\n        read -r -p \"Confirm settings? [y/n]:\" IPv6OutStatus\n\n        if [[ \"${IPv6OutStatus}\" == \"y\" ]]; then\n            cat <<EOF >${configPath}10_ipv4_outbounds.json\n            {\n                \"outbounds\":[\n                    {\n                        \"protocol\":\"freedom\",\n                        \"settings\":{\n                            \"domainStrategy\":\"UseIPv6\"\n                        },\n                        \"tag\":\"IPv6-out\"\n                    }\n                ]\n            }\nEOF\n            rm ${configPath}09_routing.json >/dev/null 2>&1\n            echoContent green \" ---> IPv6 global outbound setting successful\"\n        else\n            echoContent green \" ---> Abandon settings\"\n            exit 0\n        fi\n\n    elif [[ \"${ipv6Status}\" == \"4\" ]]; then\n\n        unInstallRouting IPv6-out outboundTag\n\n        unInstallOutbounds IPv6-out\n\n        if ! grep -q \"IPv4-out\" <\"${configPath}10_ipv4_outbounds.json\"; then\n            outbounds=$(jq -r '.outbounds += [{\"protocol\":\"freedom\",\"settings\": {\"domainStrategy\": \"UseIPv4\"},\"tag\":\"IPv4-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n            echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n        fi\n        echoContent green \" ---> IPv6 offload uninstall successful\"\n    else\n        echoContent red \" ---> Wrong selection\"\n        exit 0\n    fi\n\n    reloadCore\n}\n\n# bt download management\nbtTools() {\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> Not installed, please use script to install\"\n        menu\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: bt download management\"\n    echoContent red \"\\n================================================ =================\"\n\n    if [[ -f ${configPath}09_routing.json ]] && grep -q bittorrent <${configPath}09_routing.json; then\n        echoContent yellow \"Current status: disabled\"\n    else\n        echoContent yellow \"Current status: not disabled\"\n    fi\n\n    echoContent yellow \"1.Disable\"\n    echoContent yellow \"2.Open\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" btStatus\n    if [[ \"${btStatus}\" == \"1\" ]]; then\n\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n\n            unInstallRouting blackhole-out outboundTag\n\n            routing=$(jq -r '.routing.rules += [{\"type\":\"field\",\"outboundTag\":\"blackhole-out\",\"protocol\":[\"bittorrent\"]}]' ${configPath}09_routing.json)\n\n            echo \"${routing}\" | jq . >${configPath}09_routing.json\n\n        else\n            cat <<EOF >${configPath}09_routing.json\n{\n    \"routing\":{\n        \"domainStrategy\": \"IPOnDemand\",\n        \"rules\": [\n          {\n            \"type\": \"field\",\n            \"outboundTag\": \"blackhole-out\",\n            \"protocol\": [ \"bittorrent\" ]\n          }\n        ]\n  }\n}\nEOF\n        fi\n\n        installSniffing\n\n        unInstallOutbounds blackhole-out\n\n        outbounds=$(jq -r '.outbounds += [{\"protocol\":\"blackhole\",\"tag\":\"blackhole-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        echoContent green \" ---> BT download disabled successfully\"\n\n    elif [[ \"${btStatus}\" == \"2\" ]]; then\n\n        unInstallSniffing\n\n        unInstallRouting blackhole-out outboundTag bittorrent\n\n        # \t\tunInstallOutbounds blackhole-out\n\n        echoContent green \" ---> BT download opened successfully\"\n    else\n        echoContent red \" ---> Wrong selection\"\n        exit 0\n    fi\n\n    reloadCore\n}\n\n# Domain name blacklist\nblacklist() {\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> Not installed, please use script to install\"\n        menu\n        exit 0\n    fi\n\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Domain name blacklist\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.View blocked domain names\"\n    echoContent yellow \"2.Add domain name\"\n    echoContent yellow \"3.Block domestic domain names\"\n    echoContent yellow \"4.Delete blacklist\"\n    echoContent red \"================================================== ===============\"\n\n    read -r -p \"Please select:\" blacklistStatus\n    if [[ \"${blacklistStatus}\" == \"1\" ]]; then\n        jq -r -c '.routing.rules[]|select (.outboundTag==\"blackhole-out\")|.domain' ${configPath}09_routing.json | jq -r\n        exit 0\n    elif [[ \"${blacklistStatus}\" == \"2\" ]]; then\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"# Notes\\n\"\n        echoContent yellow \"1.Rules support predefined domain name list [https://github.com/v2fly/domain-list-community]\"\n        echoContent yellow \"2.Rules support custom domain names\"\n        echoContent yellow \"3.Input example: speedtest, facebook, cn, example.com\"\n        echoContent yellow \"4.If the domain name exists in the predefined domain name list, use geosite:xx. If it does not exist, the entered domain name will be used by default.\"\n        echoContent yellow \"5.Add rules as incremental configuration and will not delete previously set content\\n\"\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n            addInstallRouting blackhole-out outboundTag \"${domainList}\"\n        fi\n        unInstallOutbounds blackhole-out\n\n        outbounds=$(jq -r '.outbounds += [{\"protocol\":\"blackhole\",\"tag\":\"blackhole-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        echoContent green \" ---> Added successfully\"\n\n    elif [[ \"${blacklistStatus}\" == \"3\" ]]; then\n        addInstallRouting blackhole-out outboundTag \"cn\"\n\n        unInstallOutbounds blackhole-out\n\n        outbounds=$(jq -r '.outbounds += [{\"protocol\":\"blackhole\",\"tag\":\"blackhole-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        echoContent green \" ---> Domestic domain name blocked successfully\"\n\n    elif [[ \"${blacklistStatus}\" == \"4\" ]]; then\n\n        unInstallRouting blackhole-out outboundTag\n\n        echoContent green \" ---> Domain name blacklist deleted successfully\"\n    else\n        echoContent red \" ---> Wrong selection\"\n        exit 0\n    fi\n    reloadCore\n}\n#Add routing configuration\naddInstallRouting() {\n\n    local tag=$1    # warp-socks\n    local type=$2   # outboundTag/inboundTag\n    local domain=$3 # Domain name\n\n    if [[ -z \"${tag}\" || -z \"${type}\" || -z \"${domain}\" ]]; then\n        echoContent red \" ---> Parameter error\"\n        exit 0\n    fi\n\n    local routingRule=\n    if [[ ! -f \"${configPath}09_routing.json\" ]]; then\n        cat <<EOF >${configPath}09_routing.json\n{\n    \"routing\":{\n        \"type\": \"field\",\n        \"rules\": [\n            {\n                \"type\": \"field\",\n                \"domain\": [\n                ],\n            \"outboundTag\": \"${tag}\"\n          }\n        ]\n  }\n}\nEOF\n    fi\n    local routingRule=\n    routingRule=$(jq -r '.routing.rules[]|select(.outboundTag==\"'\"${tag}\"'\")' ${configPath}09_routing.json)\n    if [[ -z \"${routingRule}\" ]]; then\n        if [[ \"${tag}\" == \"dokodemoDoor-80\" ]]; then\n            routingRule=\"{\\\"type\\\": \\\"field\\\",\\\"port\\\": 80,\\\"domain\\\": [],\\\"outboundTag\\\": \\\"${tag}\\\"}\"\n        elif [[ \"${tag}\" == \"dokodemoDoor-443\" ]]; then\n            routingRule=\"{\\\"type\\\": \\\"field\\\",\\\"port\\\": 443,\\\"domain\\\": [],\\\"outboundTag\\\": \\\"${tag}\\\"}\"\n        else\n            routingRule=\"{\\\"type\\\": \\\"field\\\",\\\"domain\\\": [],\\\"outboundTag\\\": \\\"${tag}\\\"}\"\n        fi\n    fi\n\n    while read -r line; do\n        if echo \"${routingRule}\" | grep -q \"${line}\"; then\n            echoContent yellow \" ---> ${line} already exists, skip\"\n        else\n            local geositeStatus\n            geositeStatus=$(curl -s \"https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}\" | jq .message)\n\n            if [[ \"${geositeStatus}\" == \"null\" ]]; then\n                routingRule=$(echo \"${routingRule}\" | jq -r '.domain += [\"geosite:'\"${line}\"'\"]')\n            else\n                routingRule=$(echo \"${routingRule}\" | jq -r '.domain += [\"domain:'\"${line}\"'\"]')\n            fi\n        fi\n    done < <(echo \"${domain}\" | tr ',' '\\n')\n\n    unInstallRouting \"${tag}\" \"${type}\"\n    if ! grep -q \"gstatic.com\" ${configPath}09_routing.json && [[ \"${tag}\" == \"blackhole-out\" ]]; then\n        local routing=\n        routing=$(jq -r \".routing.rules += [{\\\"type\\\": \\\"field\\\",\\\"domain\\\": [\\\"gstatic.com\\\"],\\\"outboundTag\\\": \\\"direct\\\"}]\" ${configPath}09_routing.json)\n        echo \"${routing}\" | jq . >${configPath}09_routing.json\n    fi\n\n    routing=$(jq -r \".routing.rules += [${routingRule}]\" ${configPath}09_routing.json)\n    echo \"${routing}\" | jq . >${configPath}09_routing.json\n}\n# Uninstall Routing based on tag\nunInstallRouting() {\n    local tag=$1\n    local type=$2\n    local protocol=$3\n\n    if [[ -f \"${configPath}09_routing.json\" ]]; then\n        local routing\n        if grep -q \"${tag}\" ${configPath}09_routing.json && grep -q \"${type}\" ${configPath}09_routing.json; then\n\n            jq -c .routing.rules[] ${configPath}09_routing.json | while read -r line; do\n                local index=$((index + 1))\n                local delStatus=0\n                if [[ \"${type}\" == \"outboundTag\" ]] && echo \"${line}\" | jq .outboundTag | grep -q \"${tag}\"; then\n                    delStatus=1\n                elif [[ \"${type}\" == \"inboundTag\" ]] && echo \"${line}\" | jq .inboundTag | grep -q \"${tag}\"; then\n                    delStatus=1\n                fi\n\n                if [[ -n ${protocol} ]] && echo \"${line}\" | jq .protocol | grep -q \"${protocol}\"; then\n                    delStatus=1\n                elif [[ -z ${protocol} ]] && [[ $(echo \"${line}\" | jq .protocol) != \"null\" ]]; then\n                    delStatus=0\n                fi\n\n                if [[ ${delStatus} == 1 ]]; then\n                    routing=$(jq -r 'del(.routing.rules['$((index - 1))'])' ${configPath}09_routing.json)\n                    echo \"${routing}\" | jq . >${configPath}09_routing.json\n                fi\n            done\n        fi\n    fi\n}\n\n# Uninstall outbound based on tag\nunInstallOutbounds() {\n    local tag=$1\n\n    if grep -q \"${tag}\" ${configPath}10_ipv4_outbounds.json; then\n        local ipv6OutIndex\n        ipv6OutIndex=$(jq .outbounds[].tag ${configPath}10_ipv4_outbounds.json | awk '{print \"\"NR\"\"\":\"$0}' | grep \"${tag}\" | awk -F \"[:]\" '{print $1}' | head -1)\n        if [[ ${ipv6OutIndex} -gt 0 ]]; then\n            routing=$(jq -r 'del(.outbounds['$((ipv6OutIndex - 1))'])' ${configPath}10_ipv4_outbounds.json)\n            echo \"${routing}\" | jq . >${configPath}10_ipv4_outbounds.json\n        fi\n    fi\n\n}\n\n# Uninstall sniffing\nunInstallSniffing() {\n\n    find ${configPath} -name \"*inbounds.json*\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | while read -r inbound; do\n        if grep -q \"destOverride\" <\"${configPath}${inbound}\"; then\n            sniffing=$(jq -r 'del(.inbounds[0].sniffing)' \"${configPath}${inbound}\")\n            echo \"${sniffing}\" | jq . >\"${configPath}${inbound}\"\n        fi\n    done\n\n}\n\n# Install sniffing\ninstallSniffing() {\n    readInstallType\n    find ${configPath} -name \"*inbounds.json*\" | awk -F \"[c][o][n][f][/]\" '{print $2}' | while read -r inbound; do\n        if ! grep -q \"destOverride\" <\"${configPath}${inbound}\"; then\n            sniffing=$(jq -r '.inbounds[0].sniffing = {\"enabled\":true,\"destOverride\":[\"http\",\"tls\"]}' \"${configPath}${inbound}\")\n            echo \"${sniffing}\" | jq . >\"${configPath}${inbound}\"\n        fi\n    done\n}\n\n# warp diversion\nwarpRouting() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: WARP offload\"\n    echoContent red \"==============================================================\"\n    if [[ -z $(which warp-cli) ]]; then\n        echo\n        read -r -p \"WARP is not installed. Do you want to install it? [y/n]:\" installCloudflareWarpStatus\n        if [[ \"${installCloudflareWarpStatus}\" == \"y\" ]]; then\n            installWarp\n        else\n            echoContent yellow \" ---> Abort installation\"\n            exit 0\n        fi\n    fi\n\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.View the diverted domain name\"\n    echoContent yellow \"2.Add domain name\"\n    echoContent yellow \"3.Set WARP global\"\n    echoContent yellow \"4.Uninstall WARP distribution\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" warpStatus\n    if [[ \"${warpStatus}\" == \"1\" ]]; then\n        jq -r -c '.routing.rules[]|select (.outboundTag==\"warp-socks-out\")|.domain' ${configPath}09_routing.json | jq -r\n        exit 0\n    elif [[ \"${warpStatus}\" == \"2\" ]]; then\n        echoContent yellow \"# Notes\"\n        echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n\n        addInstallRouting warp-socks-out outboundTag \"${domainList}\"\n\n        unInstallOutbounds warp-socks-out\n\n        local outbounds\n        outbounds=$(jq -r '.outbounds += [{\"protocol\":\"socks\",\"settings\":{\"servers\":[{\"address\":\"127.0.0.1\",\"port\":31303}]},\"tag\":\"warp-socks-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        echoContent green \" ---> Added successfully\"\n\n    elif [[ \"${warpStatus}\" == \"3\" ]]; then\n\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"# Notes\\n\"\n        echoContent yellow \"1.All diversion rules set will be deleted\"\n        echoContent yellow \"2.All outbound rules except WARP will be deleted\"\n        read -r -p \"Confirm settings? [y/n]:\" warpOutStatus\n\n        if [[ \"${warpOutStatus}\" == \"y\" ]]; then\n            cat <<EOF >${configPath}10_ipv4_outbounds.json\n{\n\"outbounds\":[\n{\n\"protocol\": \"socks\",\n\"settings\": {\n\"servers\": [\n{\n\"address\": \"127.0.0.1\",\n\"port\": 31303\n}\n]\n},\n\"tag\": \"warp-socks-out\"\n}\n]\n}\nEOF\n            rm ${configPath}09_routing.json >/dev/null 2>&1\n            echoContent green \" ---> WARP global outbound setting successful\"\n        else\n            echoContent green \" ---> Abandon settings\"\n            exit 0\n        fi\n\n    elif [[ \"${warpStatus}\" == \"4\" ]]; then\n\n        ${removeType} cloudflare-warp >/dev/null 2>&1\n\n        unInstallRouting warp-socks-out outboundTag\n\n        unInstallOutbounds warp-socks-out\n\n        if ! grep -q \"IPv4-out\" <\"${configPath}10_ipv4_outbounds.json\"; then\n            outbounds=$(jq -r '.outbounds += [{\"protocol\":\"freedom\",\"settings\": {\"domainStrategy\": \"UseIPv4\"},\"tag\":\"IPv4-out\"}]' ${configPath}10_ipv4_outbounds.json)\n\n            echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n        fi\n\n        echoContent green \" ---> WARP offload uninstall successful\"\n    else\n        echoContent red \" ---> Wrong selection\"\n        exit 0\n    fi\n    reloadCore\n}\n\n# Read third-party warp configuration\nreadConfigWarpReg() {\n    if [[ ! -f \"/etc/v2ray-agent/warp/config\" ]]; then\n        /etc/v2ray-agent/warp/warp-reg >/etc/v2ray-agent/warp/config\n    fi\n\n    secretKeyWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" private_key | awk '{print $2}')\n\n    addressWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" v6 | awk '{print $2}')\n\n    publicKeyWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" public_key | awk '{print $2}')\n\n    reservedWarpReg=$(grep <\"/etc/v2ray-agent/warp/config\" reserved | awk -F \"[:]\" '{print $2}')\n\n}\n# warp offload-third-party IPv4\nwarpRoutingReg() {\n    local type=$2\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: WARP offload [third party]\"\n    echoContent red \"================================================== ===============\"\n    if [[ ! -f \"/etc/v2ray-agent/warp/warp-reg\" ]]; then\n        echo\n        echoContent yellow \"# Notes\"\n        echoContent yellow \"# relies on third-party programs, please be aware of the risks\"\n        echoContent yellow \"# Project address: https://github.com/badafans/warp-reg \\n\"\n\n        read -r -p \"warp-reg is not installed, do you want to install it? [y/n]:\" installWarpRegStatus\n\n        if [[ \"${installWarpRegStatus}\" == \"y\" ]]; then\n\n            curl -sLo /etc/v2ray-agent/warp/warp-reg \"https://github.com/badafans/warp-reg/releases/download/v1.0/${warpRegCoreCPUVendor}\"\n            chmod 655 /etc/v2ray-agent/warp/warp-reg\n\n        else\n            echoContent yellow \" ---> Abort installation\"\n            exit 0\n        fi\n    fi\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.View the diverted domain name\"\n    echoContent yellow \"2.Add domain name\"\n    echoContent yellow \"3.Set WARP global\"\n    echoContent yellow \"4.Uninstall WARP distribution\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" warpStatus\n\n    readConfigWarpReg\n    local address=\n    if [[ ${type} == \"IPv4\" ]]; then\n        address=\"172.16.0.2/32\"\n    elif [[ ${type} == \"IPv6\" ]]; then\n        address=\"${addressWarpReg}/128\"\n    else\n        echoContent red \" ---> IP acquisition failed, exit installation\"\n    fi\n\n    if [[ \"${warpStatus}\" == \"1\" ]]; then\n        jq -r -c '.routing.rules[]|select (.outboundTag==\"wireguard-out-'\"${type}\"'\")|.domain' ${configPath}09_routing.json | jq -r\n        exit 0\n    elif [[ \"${warpStatus}\" == \"2\" ]]; then\n        echoContent yellow \"# Notes\"\n        echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n\n        addInstallRouting wireguard-out-\"${type}\" outboundTag \"${domainList}\"\n\n        unInstallOutbounds wireguard-out-\"${type}\"\n\n        local outbounds\n        outbounds=$(jq -r '.outbounds += [{\"protocol\":\"wireguard\",\"settings\":{\"secretKey\":\"'\"${secretKeyWarpReg}\"'\",\"address\":[\"'\"${address}\"'\"],\"peers\":[{\"publicKey\":\"'\"${publicKeyWarpReg}\"'\",\"allowedIPs\":[\"0.0.0.0/0\",\"::/0\"],\"endpoint\":\"162.159.192.1:2408\"}],\"reserved\":'\"${reservedWarpReg}\"',\"mtu\":1280},\"tag\":\"wireguard-out-'\"${type}\"'\"}]' ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        echoContent green \" ---> Added successfully\"\n\n    elif [[ \"${warpStatus}\" == \"3\" ]]; then\n\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"# Notes\\n\"\n        echoContent yellow \"1.All diversion rules set will be deleted\"\n        echoContent yellow \"2.All outbound rules except WARP [third party] will be deleted\"\n        read -r -p \"Confirm the settings? [y/n]:\" warpOutStatus\n\n        if [[ \"${warpOutStatus}\" == \"y\" ]]; then\n            readConfigWarpReg\n\n            cat <<EOF >${configPath}10_ipv4_outbounds.json\n{\n    \"outbounds\":[\n        {\n            \"protocol\": \"wireguard\",\n            \"settings\": {\n                \"secretKey\": \"${secretKeyWarpReg}\",\n                \"address\": [\n                    \"${address}\"\n                ],\n                \"peers\": [\n                    {\n                        \"publicKey\": \"${publicKeyWarpReg}\",\n                        \"allowedIPs\": [\n                            \"0.0.0.0/0\",\n                             \"::/0\"\n                        ],\n                        \"endpoint\": \"162.159.192.1:2408\"\n                    }\n                ],\n                \"reserved\": ${reservedWarpReg},\n                \"mtu\": 1280\n            },\n            \"tag\": \"wireguard-out-${type}\"\n        }\n    ]\n}\nEOF\n            rm ${configPath}09_routing.json >/dev/null 2>&1\n            echoContent green \" ---> WARP global outbound setting successful\"\n        else\n            echoContent green \" ---> Abandon settings\"\n            exit 0\n        fi\n\n    elif [[ \"${warpStatus}\" == \"4\" ]]; then\n\n        unInstallRouting wireguard-out-\"${type}\" outboundTag\n\n        unInstallOutbounds wireguard-out-\"${type}\"\n        if [[ \"${type}\" == \"IPv4\" ]]; then\n            if ! grep -q \"wireguard-out-IPv6\" <${configPath}10_ipv4_outbounds.json; then\n                rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1\n            fi\n        elif [[ \"${type}\" == \"IPv6\" ]]; then\n            if ! grep -q \"wireguard-out-IPv4\" <${configPath}10_ipv4_outbounds.json; then\n                rm -rf /etc/v2ray-agent/warp/config >/dev/null 2>&1\n            fi\n        fi\n\n        if ! grep -q \"IPv4-out\" <\"${configPath}10_ipv4_outbounds.json\"; then\n\n            cat <<EOF >${configPath}10_ipv4_outbounds.json\n            {\n                \"outbounds\":[\n                    {\n                        \"protocol\":\"freedom\",\n                        \"settings\":{\n                            \"domainStrategy\":\"UseIPv4\"\n                        },\n                        \"tag\":\"IPv4-out\"\n                    },\n                    {\n                        \"protocol\":\"freedom\",\n                        \"settings\":{\n                            \"domainStrategy\":\"UseIPv6\"\n                        },\n                        \"tag\":\"IPv6-out\"\n                    },\n                    {\n                        \"protocol\":\"blackhole\",\n                        \"tag\":\"blackhole-out\"\n                    }\n                ]\n            }\nEOF\n        fi\n\n        echoContent green \" ---> WARP offload uninstall successful\"\n    else\n        echoContent red \" ---> Wrong selection\"\n        exit 0\n    fi\n    reloadCore\n}\n\n# Diversion tool\nroutingToolsMenu() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Diversion tool\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.WARP diversion [Third-party IPv4]\"\n    echoContent yellow \"2.WARP diversion [Third-party IPv6]\"\n    echoContent yellow \"3.IPv6 offload\"\n    echoContent yellow \"4.Any door diversion\"\n    echoContent yellow \"5.DNS divert\"\n    echoContent yellow \"6.VMess+WS+TLS offload\"\n    echoContent yellow \"7.SNI reverse proxy offload\"\n\n    read -r -p \"Please select:\" selectType\n\n    case ${selectType} in\n    1)\n        warpRoutingReg 1 IPv4\n        ;;\n    2)\n        warpRoutingReg 1 IPv6\n        ;;\n    3)\n        ipv6Routing 1\n        ;;\n    4)\n        dokodemoDoorRouting 1\n        ;;\n    5)\n        dnsRouting 1\n        ;;\n    6)\n        vmessWSRouting 1\n        ;;\n    7)\n        sniRouting 1\n        ;;\n    esac\n\n}\n#Streaming Toolbox\nstreamingToolbox() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Streaming Media Toolbox\"\n    echoContent red \"\\n================================================ ============ =====\"\n    echoContent yellow \"1.Any door floor machine unlocks streaming media\"\n    echoContent yellow \"2.DNS unlock streaming media\"\n    echoContent yellow \"3.VMess+WS+TLS to unlock streaming media\"\n    read -r -p \"Please select:\" selectType\n\n    case ${selectType} in\n    1)\n        dokodemoDoorRouting\n        ;;\n    2)\n        dnsRouting\n        ;;\n    3)\n        vmessWSRouting\n        ;;\n    esac\n\n}\n\n#Any door unlock streaming\ndokodemoDoorRouting() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: any door diversion\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\"\n    echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n    echoContent yellow \"1.Add outbound\"\n    echoContent yellow \"2.Add inbound\"\n    echoContent yellow \"3.Uninstall\"\n    read -r -p \"Please select:\" selectType\n\n    case ${selectType} in\n    1)\n        setDokodemoDoorRoutingOutbounds\n        ;;\n    2)\n        setDokodemoDoorRoutingInbounds\n        ;;\n    3)\n        removeDokodemoDoorRouting\n        ;;\n    esac\n}\n\n# VMess+WS+TLS offload\nvmessWSRouting() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: VMess+WS+TLS offload\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\"\n    echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n    echoContent yellow \"1.Add outbound\"\n    echoContent yellow \"2.Uninstall\"\n    read -r -p \"Please select:\" selectType\n\n    case ${selectType} in\n    1)\n        setVMessWSRoutingOutbounds\n        ;;\n    2)\n        removeVMessWSRouting\n        ;;\n    esac\n}\n\n# Set VMess+WS+TLS [outbound only]\nsetVMessWSRoutingOutbounds() {\n    read -r -p \"Please enter the address of VMess+WS+TLS:\" setVMessWSTLSAddress\n    echoContent red \"================================================== ===============\"\n    echoContent yellow \"Input example:netflix,openai\\n\"\n    read -r -p \"Please enter the domain name according to the above example:\" domainList\n\n    if [[ -z ${domainList} ]]; then\n        echoContent red \" ---> Domain name cannot be empty\"\n        setVMessWSRoutingOutbounds\n    fi\n\n    if [[ -n \"${setVMessWSTLSAddress}\" ]]; then\n\n        unInstallOutboundsVMess-out\n\n        echo\n        read -r -p \"Please enter the port of VMess+WS+TLS:\" setVMessWSTLSPort\n        echo\n        if [[ -z \"${setVMessWSTLSPort}\" ]]; then\n            echoContent red \" ---> Port cannot be empty\"\n        fi\n\n        read -r -p \"Please enter the UUID of VMess+WS+TLS:\" setVMessWSTLSUUID\n        echo\n        if [[ -z \"${setVMessWSTLSUUID}\" ]]; then\n            echoContent red \" ---> UUID cannot be empty\"\n        fi\n\n        read -r -p \"Please enter the Path of VMess+WS+TLS:\" setVMessWSTLSPath\n        echo\n        if [[ -z \"${setVMessWSTLSPath}\" ]]; then\n            echoContent red \" ---> The path cannot be empty\"\n        elif ! echo \"${setVMessWSTLSPath}\" | grep -q \"/\"; then\n            setVMessWSTLSPath=\"/${setVMessWSTLSPath}\"\n        fi\n\n        outbounds=$(jq -r \".outbounds += [{\\\"tag\\\":\\\"VMess-out\\\",\\\"protocol\\\":\\\"vmess\\\",\\\"streamSettings\\\":{\\\"network\\\":\\\"ws\\\",\\\"security\\\":\\\"tls\\\",\\\"tlsSettings\\\":{\\\"allowInsecure\\\":false},\\\"wsSettings\\\":{\\\"path\\\":\\\"${setVMessWSTLSPath}\\\"}},\\\"mux\\\":{\\\"enabled\\\":true,\\\"concurrency\\\":8},\\\"settings\\\":{\\\"vnext\\\":[{\\\"address\\\":\\\"${setVMessWSTLSAddress}\\\",\\\"port\\\":${setVMessWSTLSPort},\\\"users\\\":[{\\\"id\\\":\\\"${setVMessWSTLSUUID}\\\",\\\"security\\\":\\\"auto\\\",\\\"alterId\\\":0}]}]}}]\" ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        addInstallRouting VMess-out outboundTag \"${domainList}\"\n        reloadCore\n        echoContent green \" ---> Added shunt successfully\"\n        exit 0\n    fi\n    echoContent red \" ---> The address cannot be empty\"\n    setVMessWSRoutingOutbounds\n}\n\n# Set any door diversion [outbound]\nsetDokodemoDoorRoutingOutbounds() {\n    read -r -p \"Please enter the IP of the target vps:\" setIP\n    echoContent red \"==============================================================\"\n    echoContent yellow \"Input example:netflix,openai\\n\"\n    read -r -p \"Please enter the domain name according to the above example:\" domainList\n\n    if [[ -z ${domainList} ]]; then\n        echoContent red \" ---> Domain name cannot be empty\"\n        setDokodemoDoorRoutingOutbounds\n    fi\n\n    if [[ -n \"${setIP}\" ]]; then\n\n        unInstallOutbounds dokodemoDoor-80\n        unInstallOutbounds dokodemoDoor-443\n\n        addInstallRouting dokodemoDoor-80 outboundTag \"${domainList}\"\n        addInstallRouting dokodemoDoor-443 outboundTag \"${domainList}\"\n\n        outbounds=$(jq -r \".outbounds += [{\\\"tag\\\":\\\"dokodemoDoor-80\\\",\\\"protocol\\\":\\\"freedom\\\",\\\"settings\\\":{\\\"domainStrategy\\\":\\\"AsIs\\\",\\\"redirect\\\":\\\"${setIP}:22387\\\"}},{\\\"tag\\\":\\\"dokodemoDoor-443\\\",\\\"protocol\\\":\\\"freedom\\\",\\\"settings\\\":{\\\"domainStrategy\\\":\\\"AsIs\\\",\\\"redirect\\\":\\\"${setIP}:22388\\\"}}]\" ${configPath}10_ipv4_outbounds.json)\n\n        echo \"${outbounds}\" | jq . >${configPath}10_ipv4_outbounds.json\n\n        reloadCore\n        echoContent green \" ---> Add any door to divert successfully\"\n        exit 0\n    fi\n    echoContent red \" ---> ip cannot be empty\"\n}\n\n# Set any door diversion [inbound]\nsetDokodemoDoorRoutingInbounds() {\n\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Add inbound at any door\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"ip entry example:1.1.1.1,1.1.1.2\"\n    echoContent yellow \"The domain name below must be consistent with the outbound vps\"\n    echoContent yellow \"Example of domain name entry: netflix,openai\\n\"\n    read -r -p \"Please enter the IP allowed to access the vps:\" setIPs\n    if [[ -n \"${setIPs}\" ]]; then\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n        allowPort 22387\n        allowPort 22388\n\n        cat <<EOF >${configPath}01_dokodemoDoor_inbounds.json\n{\n  \"inbounds\": [\n    {\n      \"listen\": \"0.0.0.0\",\n      \"port\": 22387,\n      \"protocol\": \"dokodemo-door\",\n      \"settings\": {\n        \"address\": \"0.0.0.0\",\n        \"port\": 80,\n        \"network\": \"tcp\",\n        \"followRedirect\": false\n      },\n      \"sniffing\": {\n        \"enabled\": true,\n        \"destOverride\": [\n          \"http\"\n        ]\n      },\n      \"tag\": \"dokodemoDoor-80\"\n    },\n    {\n      \"listen\": \"0.0.0.0\",\n      \"port\": 22388,\n      \"protocol\": \"dokodemo-door\",\n      \"settings\": {\n        \"address\": \"0.0.0.0\",\n        \"port\": 443,\n        \"network\": \"tcp\",\n        \"followRedirect\": false\n      },\n      \"sniffing\": {\n        \"enabled\": true,\n        \"destOverride\": [\n          \"tls\"\n        ]\n      },\n      \"tag\": \"dokodemoDoor-443\"\n    }\n  ]\n}\nEOF\n        local domains=\n        domains=[]\n        while read -r line; do\n            local geositeStatus\n            geositeStatus=$(curl -s \"https://api.github.com/repos/v2fly/domain-list-community/contents/data/${line}\" | jq .message)\n\n            if [[ \"${geositeStatus}\" == \"null\" ]]; then\n                domains=$(echo \"${domains}\" | jq -r '. += [\"geosite:'\"${line}\"'\"]')\n            else\n                domains=$(echo \"${domains}\" | jq -r '. += [\"domain:'\"${line}\"'\"]')\n            fi\n        done < <(echo \"${domainList}\" | tr ',' '\\n')\n\n        if [[ -f \"${configPath}09_routing.json\" ]]; then\n            unInstallRouting dokodemoDoor-80 inboundTag\n            unInstallRouting dokodemoDoor-443 inboundTag\n\n            local routing\n            routing=$(jq -r \".routing.rules += [{\\\"source\\\":[\\\"${setIPs//,/\\\",\\\"}\\\"],\\\"domains\\\":${domains},\\\"type\\\":\\\"field\\\",\\\"inboundTag\\\":[\\\"dokodemoDoor-80\\\",\\\"dokodemoDoor-443\\\"],\\\"outboundTag\\\":\\\"direct\\\"},{\\\"type\\\":\\\"field\\\",\\\"inboundTag\\\":[\\\"dokodemoDoor-80\\\",\\\"dokodemoDoor-443\\\"],\\\"outboundTag\\\":\\\"blackhole-out\\\"}]\" ${configPath}09_routing.json)\n            echo \"${routing}\" | jq . >${configPath}09_routing.json\n        else\n\n            cat <<EOF >${configPath}09_routing.json\n{\n  \"routing\": {\n    \"rules\": [\n      {\n        \"source\": [\n            \"${setIPs//,/\\\",\\\"}\"\n        ],\n        \"domains\":${domains},\n        \"type\": \"field\",\n        \"inboundTag\": [\n          \"dokodemoDoor-80\",\n          \"dokodemoDoor-443\"\n        ],\n        \"outboundTag\": \"direct\"\n      },\n      {\n        \"type\": \"field\",\n        \"inboundTag\": [\n          \"dokodemoDoor-80\",\n          \"dokodemoDoor-443\"\n        ],\n        \"outboundTag\": \"blackhole-out\"\n      }\n    ]\n  }\n}\nEOF\n\n        fi\n\n        reloadCore\n        echoContent green \" ---> Added landing machine inbound traffic successfully\"\n        exit 0\n    fi\n    echoContent red \" ---> ip cannot be empty\"\n}\n\n# Remove any door shunt\nremoveDokodemoDoorRouting() {\n\n    unInstallOutbounds dokodemoDoor-80\n    unInstallOutbounds dokodemoDoor-443\n\n    unInstallRouting dokodemoDoor-80 inboundTag\n    unInstallRouting dokodemoDoor-443 inboundTag\n\n    unInstallRouting dokodemoDoor-80 outboundTag\n    unInstallRouting dokodemoDoor-443 outboundTag\n\n    rm -rf ${configPath}01_dokodemoDoor_inbounds.json\n\n    reloadCore\n    echoContent green \" ---> Uninstall successful\"\n}\n\n# Remove VMess+WS+TLS shunt\nremoveVMessWSRouting() {\n\n    unInstallOutbounds VMess-out\n\n    unInstallRouting VMess-out outboundTag\n\n    reloadCore\n    echoContent green \" ---> Uninstall successful\"\n}\n\n# Restart core\nreloadCore() {\n    readInstallType\n\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        handleXray stop\n        handleXray start\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        handleV2Ray stop\n        handleV2Ray start\n    fi\n\n    if [[ -n \"${hysteriaConfigPath}\" ]]; then\n        handleHysteria stop\n        handleHysteria start\n    fi\n\n    if [[ -n \"${tuicConfigPath}\" ]]; then\n        handleTuic stop\n        handleTuic start\n    fi\n}\n\n# dns divert\ndnsRouting() {\n\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> Not installed, please use script to install\"\n        menu\n        exit 0\n    fi\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: DNS offloading\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\"\n    echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n    echoContent yellow \"1.Add\"\n    echoContent yellow \"2.Uninstall\"\n    read -r -p \"Please select:\" selectType\n\n    case ${selectType} in\n    1)\n        setUnlockDNS\n        ;;\n    2)\n        removeUnlockDNS\n        ;;\n    esac\n}\n\n# SNI reverse proxy offload\nsniRouting() {\n\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> Not installed, please use script to install\"\n        menu\n        exit 0\n    fi\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: SNI reverse proxy offload\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Notes\"\n    echoContent yellow \"# Tutorial: https://www.v2ray-agent.com/archives/ba-he-yi-jiao-ben-yu-ming-fen-liu-jiao-cheng \\n\"\n\n    echoContent yellow \"1.Add\"\n    echoContent yellow \"2.Uninstall\"\n    read -r -p \"Please select:\" selectType\n\n    case ${selectType} in\n    1)\n        setUnlockSNI\n        ;;\n    2)\n        removeUnlockSNI\n        ;;\n    esac\n}\n# Set up SNI offloading\nsetUnlockSNI() {\n    read -r -p \"Please enter the SNI IP of the offload:\" setSNIP\n    if [[ -n ${setSNIP} ]]; then\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"Input example: netflix, disney, hulu\"\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n\n        if [[ -n \"${domainList}\" ]]; then\n            local hosts={}\n            while read -r domain; do\n                hosts=$(echo \"${hosts}\" | jq -r \".\\\"geosite:${domain}\\\"=\\\"${setSNIP}\\\"\")\n            done < <(echo \"${domainList}\" | tr ',' '\\n')\n            cat <<EOF >${configPath}11_dns.json\n{\n    \"dns\": {\n        \"hosts\":${hosts},\n        \"servers\": [\n            \"8.8.8.8\",\n            \"1.1.1.1\"\n        ]\n    }\n}\nEOF\n            echoContent red \" ---> SNI reverse proxy distribution successful\"\n            reloadCore\n        else\n            echoContent red \" ---> Domain name cannot be empty\"\n        fi\n\n    else\n\n        echoContent red \" ---> SNI IP cannot be empty\"\n    fi\n    exit 0\n}\n# Set dns\nsetUnlockDNS() {\n    read -r -p \"Please enter the diverted DNS:\" setDNS\n    if [[ -n ${setDNS} ]]; then\n        echoContent red \"================================================== ===============\"\n        echoContent yellow \"Input example: netflix, disney, hulu\"\n        echoContent yellow \"Please enter 1 for the default scheme. The default scheme includes the following content\"\n        echoContent yellow \"netflix,bahamut,hulu,hbo,disney,bbc,4chan,fox,abema,dmm,niconico,pixiv,bilibili,viu\"\n        read -r -p \"Please enter the domain name according to the above example:\" domainList\n        if [[ \"${domainList}\" == \"1\" ]]; then\n            cat <<EOF >${configPath}11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n            {\n                \"address\": \"${setDNS}\",\n                \"port\": 53,\n                \"domains\": [\n                    \"geosite:netflix\",\n                    \"geosite:bahamut\",\n                    \"geosite:hulu\",\n                    \"geosite:hbo\",\n                    \"geosite:disney\",\n                    \"geosite:bbc\",\n                    \"geosite:4chan\",\n                    \"geosite:fox\",\n                    \"geosite:abema\",\n                    \"geosite:dmm\",\n                    \"geosite:niconico\",\n                    \"geosite:pixiv\",\n                    \"geosite:bilibili\",\n                    \"geosite:viu\"\n                ]\n            },\n        \"localhost\"\n        ]\n    }\n}\nEOF\n        elif [[ -n \"${domainList}\" ]]; then\n            cat <<EOF >${configPath}11_dns.json\n{\n    \"dns\": {\n        \"servers\": [\n            {\n                \"address\": \"${setDNS}\",\n                \"port\": 53,\n                \"domains\": [\n                    \"geosite:${domainList//,/\\\",\\\"geosite:}\"\n                ]\n            },\n        \"localhost\"\n        ]\n    }\n}\nEOF\n        fi\n\n        reloadCore\n\n        echoContent yellow \"\\n ---> If you still can't watch, you can try the following two solutions\"\n        echoContent yellow \"1.Restart vps\"\n        echoContent yellow \"2.After uninstalling dns unlocking, modify the local [/etc/resolv.conf] DNS settings and restart vps\\n\"\n    else\n        echoContent red \" ---> dns cannot be empty\"\n    fi\n    exit 0\n}\n\n# Remove DNS offloading\nremoveUnlockDNS() {\n    cat <<EOF >${configPath}11_dns.json\n{\n\t\"dns\": {\n\t\t\"servers\": [\n\t\t\t\"localhost\"\n\t\t]\n\t}\n}\nEOF\n    reloadCore\n\n    echoContent green \" ---> Uninstall successful\"\n\n    exit 0\n}\n\n# Remove SNI shunt\nremoveUnlockSNI() {\n    cat <<EOF >${configPath}11_dns.json\n{\n\t\"dns\": {\n\t\t\"servers\": [\n\t\t\t\"localhost\"\n\t\t]\n\t}\n}\nEOF\n    reloadCore\n\n    echoContent green \" ---> Uninstall successful\"\n\n    exit 0\n}\n\n# v2ray-core personalized installation\ncustomV2RayInstall() {\n    echoContent skyBlue \"\\n========================Personalized installation================== ==========\"\n    echoContent yellow \"VLESS is prefixed and 0 is installed by default. If you only need to install 0, just select 0\"\n    echoContent yellow \"0.VLESS+TLS_Vision+TCP\"\n    echoContent yellow \"1.VLESS+TLS+WS[CDN]\"\n    echoContent yellow \"2.Trojan+TLS+gRPC[CDN]\"\n    echoContent yellow \"3.VMess+TLS+WS[CDN]\"\n    echoContent yellow \"4.Trojan+TLS\"\n    echoContent yellow \"5.VLESS+TLS+gRPC[CDN]\"\n    read -r -p \"Please select [multiple selection], [for example: 123]:\" selectCustomInstallType\n    echoContent skyBlue \"------------------------------------------------- ---------------\"\n    if [[ -z ${selectCustomInstallType} ]]; then\n        selectCustomInstallType=0\n    fi\n    if [[ \"${selectCustomInstallType}\" =~ ^[0-5]+$ ]]; then\n        cleanUp xrayClean\n        checkBTPanel\n        totalProgress=17\n        installTools 1\n        # Apply for tls\n        initTLSNginxConfig 2\n        installTLS 3\n        handleNginx stop\n        #random path\n        if echo ${selectCustomInstallType} | grep -q 1 || echo ${selectCustomInstallType} | grep -q 3 || echo ${selectCustomInstallType} | grep -q 4; then\n            randomPathFunction 5\n            customCDNIP 6\n        fi\n        nginxBlog 7\n        updateRedirectNginxConf\n        handleNginx start\n\n        # Install V2Ray\n        installV2Ray 8\n        installV2RayService 9\n        initV2RayConfig custom 10\n        cleanUp xrayDel\n        installCronTLS 14\n        handleV2Ray stop\n        handleV2Ray start\n        # Generate account\n        checkGFWStatue 15\n        showAccounts 16\n    else\n        echoContent red \" ---> Input is illegal\"\n        customV2RayInstall\n    fi\n}\n\n# Xray-core personalized installation\ncustomXrayInstall() {\n    echoContent skyBlue \"\\n========================Personalized installation================== ==========\"\n    echoContent yellow \"VLESS is prefixed and 0 is installed by default. If you only need to install 0, just select 0\"\n    echoContent yellow \"0.VLESS+TLS_Vision+TCP[recommended]\"\n    echoContent yellow \"1.VLESS+TLS+WS[CDN]\"\n    echoContent yellow \"2.Trojan+TLS+gRPC[CDN]\"\n    echoContent yellow \"3.VMess+TLS+WS[CDN]\"\n    echoContent yellow \"4.Trojan+TLS\"\n    echoContent yellow \"5.VLESS+TLS+gRPC[CDN]\"\n    echoContent yellow \"7.VLESS+Reality+uTLS+Vision[recommended]\"\n    # echoContent yellow \"8.VLESS+Reality+gRPC\"\n    read -r -p \"Please select [multiple selection], [for example: 123]:\" selectCustomInstallType\n    echoContent skyBlue \"------------------------------------------------- --------- ------\"\n    if [[ -z ${selectCustomInstallType} ]]; then\n        echoContent red \" ---> cannot be empty\"\n        customXrayInstall\n    elif [[ \"${selectCustomInstallType}\" =~ ^[0-7]+$ ]]; then\n\n        if ! echo \"${selectCustomInstallType}\" | grep -q \"0\"; then\n            selectCustomInstallType=\"0${selectCustomInstallType}\"\n        fi\n        cleanUp v2rayClean\n        checkBTPanel\n        totalProgress=12\n        installTools 1\n        if [[ -n \"${btDomain}\" ]]; then\n            echoContent skyBlue \"\\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS\"\n            handleXray stop\n            customPortFunction\n        else\n            # Apply for tls\n            initTLSNginxConfig 2\n            handleXray stop\n            # handleNginx start\n            installTLS 3\n        fi\n\n        handleNginx stop\n        #random path\n        if echo \"${selectCustomInstallType}\" | grep -q 1 || echo \"${selectCustomInstallType}\" | grep -q 2 || echo \"${selectCustomInstallType}\" | grep -q 3 || echo \"${selectCustomInstallType}\" | grep -q 5; then\n            randomPathFunction 4\n            customCDNIP 5\n        fi\n        if [[ -n \"${btDomain}\" ]]; then\n            echoContent skyBlue \"\\nProgress 6/${totalProgress}: Pagoda panel detected, skipping disguised website\"\n        # echoContent red \"============================================== ================\"\n        # echoContent yellow \"# Notes\"\n        # echoContent yellow \"The static directory under the currently installed website will be cleared. If it has been customized, please select [n]\\n\"\n        # read -r -p \"Please select [y/n]:\" nginxBlogBTStatus\n        # if [[ \"${nginxBlogBTStatus}\" == \"y\" ]]; then\n        #nginxBlog 6\n        #fi\n        else\n            nginxBlog 6\n        fi\n        updateRedirectNginxConf\n        handleNginx start\n\n        # Install Xray\n        installXray 7 false\n        installXrayService 8\n        initXrayConfig custom 9\n        cleanUp v2rayDel\n\n        installCronTLS 10\n        handleXray stop\n        handleXray start\n        # Generate account\n        checkGFWStatue 11\n        showAccounts 12\n    else\n        echoContent red \" ---> Input is illegal\"\n        customXrayInstall\n    fi\n}\n\n# Select core installation---v2ray-core, xray-core\nselectCoreInstall() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Select core installation\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.Xray-core\"\n    echoContent yellow \"2.v2ray-core\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" selectCoreType\n    case ${selectCoreType} in\n    1)\n        if [[ \"${selectInstallType}\" == \"2\" ]]; then\n            customXrayInstall\n        else\n            xrayCoreInstall\n        fi\n        ;;\n    2)\n        v2rayCoreVersion=\n        echoContent red \" ---> Since v2ray does not support many new features, maintenance is now discontinued in order to reduce development costs. It is recommended to use Xray-core, hysteria, and Tuic\"\n        exit 0\n        if [[ \"${selectInstallType}\" == \"2\" ]]; then\n            customV2RayInstall\n        else\n            v2rayCoreInstall\n        fi\n        ;;\n    3)\n        v2rayCoreVersion=v4.32.1\n        if [[ \"${selectInstallType}\" == \"2\" ]]; then\n            customV2RayInstall\n        else\n            v2rayCoreInstall\n        fi\n        ;;\n    *)\n        echoContent red ' ---> Wrong selection, select again'\n        selectCoreInstall\n        ;;\n    esac\n}\n\n# v2ray-core installation\nv2rayCoreInstall() {\n    cleanUp xrayClean\n    checkBTPanel\n    selectCustomInstallType=\n    totalProgress=13\n    installTools 2\n    # Apply for tls\n    initTLSNginxConfig 3\n\n    handleV2Ray stop\n    handleNginx start\n\n    installTLS 4\n    handleNginx stop\n    randomPathFunction 5\n    # Install V2Ray\n    installV2Ray 6\n    installV2RayService 7\n    customCDNIP 8\n    initV2RayConfig all 9\n    cleanUp xrayDel\n    installCronTLS 10\n    nginxBlog 11\n    updateRedirectNginxConf\n    handleV2Ray stop\n    sleep 2\n    handleV2Ray start\n    handleNginx start\n    # Generate account\n    checkGFWStatue 12\n    showAccounts 13\n}\n\n# xray-core installation\nxrayCoreInstall() {\n    cleanUp v2rayClean\n    checkBTPanel\n    selectCustomInstallType=\n    totalProgress=13\n    installTools 2\n    if [[ -n \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\nProgress 3/${totalProgress}: Pagoda panel detected, skip applying for TLS\"\n        handleXray stop\n        customPortFunction\n    else\n        # Apply for tls\n        initTLSNginxConfig 3\n        handleXray stop\n        # handleNginx start\n\n        installTLS 4\n    fi\n\n    handleNginx stop\n    randomPathFunction 5\n    # Install Xray\n    installXray 6 false\n    installXrayService 7\n    customCDNIP 8\n    initXrayConfig all 9\n    cleanUp v2rayDel\n    installCronTLS 10\n    if [[ -n \"${btDomain}\" ]]; then\n        echoContent skyBlue \"\\nProgress 11/${totalProgress}: Pagoda panel detected, skipping disguised website\"\n    # echoContent red \"============================================== ================\"\n    # echoContent yellow \"# Notes\"\n    # echoContent yellow \"The static directory under the currently installed website will be cleared. If it has been customized, please select [n]\\n\"\n    # read -r -p \"Please select [y/n]:\" nginxBlogBTStatus\n    # if [[ \"${nginxBlogBTStatus}\" == \"y\" ]]; then\n    #nginxBlog 11\n    #fi\n    else\n        nginxBlog 11\n    fi\n    updateRedirectNginxConf\n    handleXray stop\n    sleep 2\n    handleXray start\n\n    handleNginx start\n    # Generate account\n    checkGFWStatue 12\n    showAccounts 13\n}\n\n#HysteriaInstallation\nhysteriaCoreInstall() {\n    if ! echo \"${currentInstallProtocolType}\" | grep -q \"0\" || [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n ---> Due to environmental dependencies, if you install hysteria, please install Xray-core's VLESS_TCP_TLS_Vision first\"\n        exit 0\n    fi\n    totalProgress=5\n    installHysteria 1\n    initHysteriaConfig 2\n    installHysteriaService 3\n    reloadCore\n    showAccounts 4\n}\n# Uninstall hysteria\nunInstallHysteriaCore() {\n\n    if [[ -z \"${hysteriaConfigPath}\" ]]; then\n        echoContent red \"\\n ---> not installed\"\n        exit 0\n    fi\n    deleteHysteriaPortHoppingRules\n    handleHysteria stop\n    rm -rf /etc/v2ray-agent/hysteria/*\n    rm ${configPath}02_socks_inbounds_hysteria.json\n    rm -rf /etc/systemd/system/hysteria.service\n    echoContent green \" ---> Uninstall completed\"\n}\n# Uninstall Tuic\nunInstallTuicCore() {\n\n    if [[ -z \"${tuicConfigPath}\" ]]; then\n        echoContent red \"\\n ---> not installed\"\n        exit 0\n    fi\n    handleTuic stop\n    rm -rf /etc/v2ray-agent/tuic/*\n    rm -rf /etc/systemd/system/tuic.service\n    echoContent green \" ---> Uninstall completed\"\n}\nunInstallXrayCoreReality() {\n\n    if [[ -z \"${realityStatus}\" ]]; then\n        echoContent red \"\\n ---> not installed\"\n        exit 0\n    fi\n    echoContent skyBlue \"\\nFunction 1/1: reality uninstall\"\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# Only delete VLESS Reality related configurations, other content will not be deleted.\"\n    echoContent yellow \"# If you need to uninstall other content, please uninstall the script function\"\n    handleXray stop\n    rm /etc/v2ray-agent/xray/conf/07_VLESS_vision_reality_inbounds.json\n    rm /etc/v2ray-agent/xray/conf/08_VLESS_reality_fallback_grpc_inbounds.json\n    echoContent green \" ---> Uninstall completed\"\n}\n\n# Core Management\ncoreVersionManageMenu() {\n\n    if [[ -z \"${coreInstallType}\" ]]; then\n        echoContent red \"\\n >The installation directory is not detected, please execute the script to install the content\"\n        menu\n        exit 0\n    fi\n    if [[ \"${coreInstallType}\" == \"1\" ]]; then\n        xrayVersionManageMenu 1\n    elif [[ \"${coreInstallType}\" == \"2\" ]]; then\n        v2rayCoreVersion=\n        v2rayVersionManageMenu 1\n    fi\n}\n# Scheduled task check\ncronFunction() {\n    if [[ \"${cronName}\" == \"RenewTLS\" ]]; then\n        renewalTLS\n        exit 0\n    elif [[ \"${cronName}\" == \"UpdateGeo\" ]]; then\n        updateGeoSite >>/etc/v2ray-agent/crontab_updateGeoSite.log\n        echoContent green \" ---> geo update date: $(date \"+%F %H:%M:%S\")\" >>/etc/v2ray-agent/crontab_updateGeoSite.log\n        exit 0\n    fi\n}\n#Account management\nmanageAccount() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: Account Management\"\n    if [[ -z \"${configPath}\" ]]; then\n        echoContent red \" ---> not installed\"\n        exit 0\n    fi\n\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"# You can customize email and uuid when adding a single user\"\n    echoContent yellow \"# If Hysteria or Tuic is installed, the account will be added to the corresponding type at the same time\\n\"\n    echoContent yellow \"1.Check account\"\n    echoContent yellow \"2.View subscription\"\n    echoContent yellow \"3.Add subscription\"\n    echoContent yellow \"4.Add user\"\n    echoContent yellow \"5.Delete user\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please enter:\" manageAccountStatus\n    if [[ \"${manageAccountStatus}\" == \"1\" ]]; then\n        showAccounts 1\n    elif [[ \"${manageAccountStatus}\" == \"2\" ]]; then\n        subscribe\n    elif [[ \"${manageAccountStatus}\" == \"3\" ]]; then\n        addSubscribeMenu 1\n    elif [[ \"${manageAccountStatus}\" == \"4\" ]]; then\n        addUserXray\n    elif [[ \"${manageAccountStatus}\" == \"5\" ]]; then\n        removeUser\n    else\n        echoContent red \" ---> Wrong selection\"\n    fi\n}\n\n#Add subscription\naddSubscribeMenu() {\n    echoContent skyBlue \"\\n====================== Add other machine subscriptions==================== ===\"\n    echoContent yellow \"1.Add\"\n    echoContent yellow \"2.Remove\"\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" addSubscribeStatus\n    if [[ \"${addSubscribeStatus}\" == \"1\" ]]; then\n        addOtherSubscribe\n    elif [[ \"${addSubscribeStatus}\" == \"2\" ]]; then\n        rm -rf /etc/v2ray-agent/subscribe_remote/clashMeta/*\n        rm -rf /etc/v2ray-agent/subscribe_remote/default/*\n        echo >/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\n        echoContent green \" ---> Other machine subscriptions were deleted successfully\"\n        subscribe\n    fi\n}\n# Add other machines to clashMeta subscription\naddOtherSubscribe() {\n    echoContent yellow \"#Notes:\"\n    echoContent yellow \"Please read the following article carefully: https://www.v2ray-agent.com/archives/1681804748677\"\n    echoContent skyBlue \"Input example: www.v2ray-agent.com:443:vps1\\n\"\n    read -r -p \"Please enter the domain name, port and machine alias:\" remoteSubscribeUrl\n    if [[ -z \"${remoteSubscribeUrl}\" ]]; then\n        echoContent red \" ---> cannot be empty\"\n        addSubscribe\n    elif ! echo \"${remoteSubscribeUrl}\" | grep -q \":\"; then\n        echoContent red \" ---> Rule is illegal\"\n    else\n        echo \"${remoteSubscribeUrl}\" >>/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\n        local remoteUrl=\n        remoteUrl=$(echo \"${remoteSubscribeUrl}\" | awk -F \"[:]\" '{print $1\":\"$2}')\n\n        local serverAlias=\n        serverAlias=$(echo \"${remoteSubscribeUrl}\" | awk -F \"[:]\" '{print $3}')\n\n        if [[ -n $(ls /etc/v2ray-agent/subscribe/clashMeta/) || -n $(ls /etc/v2ray-agent/subscribe/default/) ]]; then\n            find /etc/v2ray-agent/subscribe_local/default/* | while read -r email; do\n                email=$(echo \"${email}\" | awk -F \"[d][e][f][a][u][l][t][/]\" '{print $2}')\n\n                local emailMd5=\n                emailMd5=$(echo -n \"${email}$(cat \"/etc/v2ray-agent/subscribe_local/subscribeSalt\")\"$'\\n' | md5sum | awk '{print $1}')\n\n                local clashMetaProxies=\n                clashMetaProxies=$(curl -s -4 \"https://${remoteUrl}/s/clashMeta/${emailMd5}\" | sed '/proxies:/d' | sed \"s/${email}/${email}_${serverAlias}/g\")\n\n                local default=\n                default=$(curl -s -4 \"https://${remoteUrl}/s/default/${emailMd5}\" | base64 -d | sed \"s/${email}/${email}_${serverAlias}/g\")\n\n                if echo \"${default}\" | grep -q \"${email}\"; then\n                    echo \"${default}\" >>\"/etc/v2ray-agent/subscribe/default/${emailMd5}\"\n                    echo \"${default}\" >>\"/etc/v2ray-agent/subscribe_remote/default/${email}\"\n\n                    echoContent green \" ---> Universal subscription ${email} added successfully\"\n                else\n                    echoContent red \" ---> Universal subscription ${email} does not exist\"\n                fi\n\n                if echo \"${clashMetaProxies}\" | grep -q \"${email}\"; then\n                    echo \"${clashMetaProxies}\" >>\"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}\"\n                    echo \"${clashMetaProxies}\" >>\"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}\"\n\n                    echoContent green \" ---> clashMeta subscription ${email} added successfully\"\n                else\n                    echoContent red \" ---> clashMeta subscription ${email} does not exist\"\n                fi\n            done\n        else\n            echoContent red \" ---> Please check the subscription first and then add the subscription\"\n        fi\n    fi\n}\n# clashMeta configuration file\nclashMetaConfig() {\n    local url=$1\n    local id=$2\n    cat <<EOF >\"/etc/v2ray-agent/subscribe/clashMetaProfiles/${id}\"\nmixed-port: 7890\nunified-delay: false\ngeodata-mode: true\ntcp-concurrent: false\nfind-process-mode: strict\nglobal-client-fingerprint: chrome\n\nallow-lan: true\nmode: rule\nlog-level: info\nipv6: true\n\nexternal-controller: 127.0.0.1:9090\n\ngeox-url:\n  geoip: \"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat\"\n  geosite: \"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat\"\n  mmdb: \"https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb\"\n\nprofile:\n  store-selected: true\n  store-fake-ip: true\n\nsniffer:\n  enable: false\n  sniff:\n    TLS:\n      ports: [443]\n    HTTP:\n      ports: [80]\n      override-destination: true\n\ntun:\n  enable: true\n  stack: system\n  dns-hijack:\n    - 'any:53'\n  auto-route: true\n  auto-detect-interface: true\n\ndns:\n  enable: true\n  listen: 0.0.0.0:1053\n  ipv6: true\n  enhanced-mode: fake-ip\n  fake-ip-range: 28.0.0.1/8\n  fake-ip-filter:\n    - '*'\n    - '+.lan'\n  default-nameserver:\n    - 223.5.5.5\n  nameserver:\n    - 'tls://8.8.4.4#DNS_Proxy'\n    - 'tls://1.0.0.1#DNS_Proxy'\n  proxy-server-nameserver:\n    - https://dns.alidns.com/dns-query#h3=true\n  nameserver-policy:\n    \"geosite:cn,private\":\n      - 223.5.5.5\n      - 114.114.114.114\n      - https://dns.alidns.com/dns-query#h3=true\n\nproxy-providers:\n  ${subscribeSalt}_provider:\n    type: http\n    path: ./${subscribeSalt}_provider.yaml\n    url: ${url}\n    interval: 3600\n    health-check:\n      enable: false\n      url: http://www.gstatic.com/generate_204\n      interval: 300\n\nproxy-groups:\n  - name: 节点选择\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - 故障转移\n      - 负载均衡\n      - DIRECT\n  - name: 流媒体\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - 故障转移\n      - 负载均衡\n      - DIRECT\n  - name: 手动切换\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies: null\n  - name: 自动选择\n    type: url-test\n    url: http://www.gstatic.com/generate_204\n    interval: 36000\n    tolerance: 50\n    use:\n      - ${subscribeSalt}_provider\n    proxies: null\n  - name: 故障转移\n    type: fallback\n    url: http://www.gstatic.com/generate_204\n    interval: 300\n    tolerance: 50\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 自动选择\n  - name: 负载均衡\n    type: load-balance\n    url: http://www.gstatic.com/generate_204\n    interval: 300\n    tolerance: 50\n    use:\n      - ${subscribeSalt}_provider\n    proxies: null\n  - name: 全球代理\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n  - name: DNS_Proxy\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 自动选择\n      - 节点选择\n      - DIRECT\n\n  - name: Telegram\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n\n  - name: YouTube\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n  - name: Netflix\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 节点选择\n      - 自动选择\n  - name: HBO\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 节点选择\n      - 自动选择\n  - name: Bing\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 节点选择\n      - 自动选择\n  - name: OpenAI\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 节点选择\n      - 自动选择\n  - name: Disney\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 节点选择\n      - 自动选择\n  - name: GitHub\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - DIRECT\n  - name: Spotify\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 流媒体\n      - 手动切换\n      - 自动选择\n      - DIRECT\n  - name: Google\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - 手动切换\n      - 自动选择\n      - DIRECT\n  - name: 国内媒体\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - DIRECT\n  - name: 本地直连\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - DIRECT\n      - 节点选择\n      - 自动选择\n  - name: 漏网之鱼\n    type: select\n    use:\n      - ${subscribeSalt}_provider\n    proxies:\n      - DIRECT\n      - 节点选择\n      - 手动切换\n      - 自动选择\nrule-providers:\n  lan:\n    type: http\n    behavior: classical\n    interval: 86400\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Lan/Lan.yaml\n    path: ./Rules/lan.yaml\n  reject:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt\n    path: ./ruleset/reject.yaml\n    interval: 86400\n  proxy:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt\n    path: ./ruleset/proxy.yaml\n    interval: 86400\n  direct:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt\n    path: ./ruleset/direct.yaml\n    interval: 86400\n  private:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/private.txt\n    path: ./ruleset/private.yaml\n    interval: 86400\n  gfw:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/gfw.txt\n    path: ./ruleset/gfw.yaml\n    interval: 86400\n  greatfire:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/greatfire.txt\n    path: ./ruleset/greatfire.yaml\n    interval: 86400\n  tld-not-cn:\n    type: http\n    behavior: domain\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/tld-not-cn.txt\n    path: ./ruleset/tld-not-cn.yaml\n    interval: 86400\n  telegramcidr:\n    type: http\n    behavior: ipcidr\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/telegramcidr.txt\n    path: ./ruleset/telegramcidr.yaml\n    interval: 86400\n  applications:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/applications.txt\n    path: ./ruleset/applications.yaml\n    interval: 86400\n  Disney:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Disney/Disney.yaml\n    path: ./ruleset/disney.yaml\n    interval: 86400\n  Netflix:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Netflix/Netflix.yaml\n    path: ./ruleset/netflix.yaml\n    interval: 86400\n  YouTube:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/YouTube/YouTube.yaml\n    path: ./ruleset/youtube.yaml\n    interval: 86400\n  HBO:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/HBO/HBO.yaml\n    path: ./ruleset/hbo.yaml\n    interval: 86400\n  OpenAI:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/OpenAI/OpenAI.yaml\n    path: ./ruleset/openai.yaml\n    interval: 86400\n  Bing:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Bing/Bing.yaml\n    path: ./ruleset/bing.yaml\n    interval: 86400\n  Google:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Google/Google.yaml\n    path: ./ruleset/google.yaml\n    interval: 86400\n  GitHub:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/GitHub/GitHub.yaml\n    path: ./ruleset/github.yaml\n    interval: 86400\n  Spotify:\n    type: http\n    behavior: classical\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/Spotify/Spotify.yaml\n    path: ./ruleset/spotify.yaml\n    interval: 86400\n  ChinaMaxDomain:\n    type: http\n    behavior: domain\n    interval: 86400\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_Domain.yaml\n    path: ./Rules/ChinaMaxDomain.yaml\n  ChinaMaxIPNoIPv6:\n    type: http\n    behavior: ipcidr\n    interval: 86400\n    url: https://ghproxy.com/https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/ChinaMax/ChinaMax_IP_No_IPv6.yaml\n    path: ./Rules/ChinaMaxIPNoIPv6.yaml\nrules:\n  - RULE-SET,YouTube,YouTube,no-resolve\n  - RULE-SET,Google,Google,no-resolve\n  - RULE-SET,GitHub,GitHub\n  - RULE-SET,telegramcidr,Telegram,no-resolve\n  - RULE-SET,Spotify,Spotify,no-resolve\n  - RULE-SET,Netflix,Netflix\n  - RULE-SET,HBO,HBO\n  - RULE-SET,Bing,Bing\n  - RULE-SET,OpenAI,OpenAI\n  - RULE-SET,Disney,Disney\n  - RULE-SET,proxy,全球代理\n  - RULE-SET,gfw,全球代理\n  - RULE-SET,applications,本地直连\n  - RULE-SET,ChinaMaxDomain,本地直连\n  - RULE-SET,ChinaMaxIPNoIPv6,本地直连,no-resolve\n  - RULE-SET,lan,本地直连,no-resolve\n  - GEOIP,CN,本地直连\n  - MATCH,漏网之鱼\nEOF\n\n}\n# Random salt\ninitRandomSalt() {\n    local chars=\"abcdefghijklmnopqrtuxyz\"\n    local initCustomPath=\n    for i in {1..10}; do\n        echo \"${i}\" >/dev/null\n        initCustomPath+=\"${chars:RANDOM%${#chars}:1}\"\n    done\n    echo \"${initCustomPath}\"\n}\n# Subscribe\nsubscribe() {\n    readInstallProtocolType\n\n    if echo \"${currentInstallProtocolType}\" | grep -q 0 && [[ -n \"${configPath}\" ]]; then\n\n        echoContent skyBlue \"-------------------------Remarks--------------------- ----------\"\n        echoContent yellow \"# Viewing subscriptions will regenerate local account subscriptions\"\n        echoContent yellow \"# When adding an account or modifying an account, you need to re-check the subscription before the subscription content for external access will be regenerated\"\n        echoContent red \"# You need to manually enter the md5 encrypted salt value. If you don't know, just use random\"\n        echoContent yellow \"# Does not affect the content of added remote subscriptions\\n\"\n\n        if [[ -f \"/etc/v2ray-agent/subscribe_local/subscribeSalt\" && -n $(cat \"/etc/v2ray-agent/subscribe_local/subscribeSalt\") ]]; then\n            read -r -p \"Read the Salt set by the last installation. Do you want to use the Salt generated last time? [y/n]:\" historySaltStatus\n            if [[ \"${historySaltStatus}\" == \"y\" ]]; then\n                subscribeSalt=$(cat /etc/v2ray-agent/subscribe_local/subscribeSalt)\n            else\n                read -r -p \"Please enter the salt value, [Enter] use random:\" subscribeSalt\n            fi\n        else\n            read -r -p \"Please enter the salt value, [Enter] use random:\" subscribeSalt\n        fi\n\n        if [[ -z \"${subscribeSalt}\" ]]; then\n            subscribeSalt=$(initRandomSalt)\n        fi\n        echoContent yellow \"\\n ---> Salt: ${subscribeSalt}\"\n\n        echo \"${subscribeSalt}\" >/etc/v2ray-agent/subscribe_local/subscribeSalt\n\n        rm -rf /etc/v2ray-agent/subscribe/default/*\n        rm -rf /etc/v2ray-agent/subscribe/clashMeta/*\n        rm -rf /etc/v2ray-agent/subscribe_local/default/*\n        rm -rf /etc/v2ray-agent/subscribe_local/clashMeta/*\n        showAccounts >/dev/null\n\n        if [[ -n $(ls /etc/v2ray-agent/subscribe_local/default/) ]]; then\n            find /etc/v2ray-agent/subscribe_local/default/* | while read -r email; do\n                email=$(echo \"${email}\" | awk -F \"[d][e][f][a][u][l][t][/]\" '{print $2}')\n                # md5 encryption\n                local emailMd5=\n                emailMd5=$(echo -n \"${email}${subscribeSalt}\"$'\\n' | md5sum | awk '{print $1}')\n\n                cat \"/etc/v2ray-agent/subscribe_local/default/${email}\" >>\"/etc/v2ray-agent/subscribe/default/${emailMd5}\"\n\n                if [[ -f \"/etc/v2ray-agent/subscribe_remote/default/${email}\" ]]; then\n                    echo >\"/etc/v2ray-agent/subscribe_remote/default/${email}_tmp\"\n                    while read -r remoteUrl; do\n                        updateRemoteSubscribe \"${emailMd5}\" \"${email}\" \"${remoteUrl}\" \"default\"\n                    done < <(grep \"VLESS_TCP/TLS_Vision\" <\"/etc/v2ray-agent/subscribe_remote/default/${email}\" | awk -F \"@\" '{print $2}' | awk -F \"?\" '{print $1}')\n\n                    echo >\"/etc/v2ray-agent/subscribe_remote/default/${email}\"\n                    cat \"/etc/v2ray-agent/subscribe_remote/default/${email}_tmp\" >\"/etc/v2ray-agent/subscribe_remote/default/${email}\"\n                    cat \"/etc/v2ray-agent/subscribe_remote/default/${email}\" >>\"/etc/v2ray-agent/subscribe/default/${emailMd5}\"\n                fi\n\n                local base64Result\n                base64Result=$(base64 -w 0 \"/etc/v2ray-agent/subscribe/default/${emailMd5}\")\n                echo \"${base64Result}\" >\"/etc/v2ray-agent/subscribe/default/${emailMd5}\"\n\n                echoContent yellow \"--------------------------------------------------------------\"\n                local currentDomain=${currentHost}\n\n                if [[ -n \"${currentDefaultPort}\" && \"${currentDefaultPort}\" != \"443\" ]]; then\n                    currentDomain=\"${currentHost}:${currentDefaultPort}\"\n                fi\n                echoContent skyBlue \"\\n----------Default subscription----------\\n\"\n                echoContent green \"email:${email}\\n\"\n                echoContent yellow \"url:https://${currentDomain}/s/default/${emailMd5}\\n\"\n                echoContent yellow \"Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/default/${emailMd5}\\n \"\n                echo \"https://${currentDomain}/s/default/${emailMd5}\" | qrencode -s 10 -m 1 -t UTF8\n\n                #clashMeta\n                if [[ -f \"/etc/v2ray-agent/subscribe_local/clashMeta/${email}\" ]]; then\n\n                    cat \"/etc/v2ray-agent/subscribe_local/clashMeta/${email}\" >>\"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}\"\n\n                    if [[ -f \"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}\" ]]; then\n                        echo >\"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}_tmp\"\n                        while read -r remoteUrl; do\n                            updateRemoteSubscribe \"${emailMd5}\" \"${email}\" \"${remoteUrl}\" \"ClashMeta\"\n                        done < <(grep -A3 \"VLESS_TCP/TLS_Vision\" <\"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}\" | awk '/server:|port:/ {print $2}' | paste -d ':' - -)\n                        echo >\"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}\"\n                        cat \"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}_tmp\" >\"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}\"\n                        cat \"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}\" >>\"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}\"\n                    fi\n\n                    sed -i '1i\\proxies:' \"/etc/v2ray-agent/subscribe/clashMeta/${emailMd5}\"\n\n                    local clashProxyUrl=\"https://${currentDomain}/s/clashMeta/${emailMd5}\"\n                    clashMetaConfig \"${clashProxyUrl}\" \"${emailMd5}\"\n                    echoContent skyBlue \"\\n----------clashMeta subscription----------\\n\"\n                    echoContent yellow \"url:https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\\n\"\n                    echoContent yellow \"Online QR code: https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\\n \"\n                    echo \"https://${currentDomain}/s/clashMetaProfiles/${emailMd5}\" | qrencode -s 10 -m 1 -t UTF8\n                fi\n\n                echoContent skyBlue \"------------------------------------------------- ---------------\"\n            done\n        fi\n    else\n        echoContent red \" ---> The disguise site is not installed and the subscription service cannot be used\"\n    fi\n}\n\n# Update remote subscription\nupdateRemoteSubscribe() {\n    local emailMD5=$1\n    local email=$2\n    local remoteUrl=$3\n    local type=$4\n    local remoteDomain=\n    remoteDomain=$(echo \"${remoteUrl}\" | awk -F \":\" '{print $1}')\n    local serverAlias=\n    serverAlias=$(grep \"${remoteDomain}\" <\"/etc/v2ray-agent/subscribe_remote/remoteSubscribeUrl\" | awk -F \":\" '{print $3}')\n\n    if [[ \"${type}\" == \"ClashMeta\" ]]; then\n        local clashMetaProxies=\n        clashMetaProxies=$(curl -s -4 \"https://${remoteUrl}/s/clashMeta/${emailMD5}\" | sed '/proxies:/d' | sed \"s/${email}/${email}_${serverAlias}/g\")\n        if echo \"${clashMetaProxies}\" | grep -q \"${email}\"; then\n            echo \"${clashMetaProxies}\" >>\"/etc/v2ray-agent/subscribe_remote/clashMeta/${email}_tmp\"\n\n            echoContent green \" ---> clashMeta subscription ${remoteDomain}:${email} updated successfully\"\n        else\n            echoContent red \" ---> clashMeta subscription ${remoteDomain}:${email} does not exist\"\n        fi\n    elif [[ \"${type}\" == \"default\" ]]; then\n        local default=\n        default=$(curl -s -4 \"https://${remoteUrl}/s/default/${emailMD5}\" | base64 -d | sed \"s/${email}/${email}_${serverAlias}/g\")\n        if echo \"${default}\" | grep -q \"${email}\"; then\n            echo \"${default}\" >>\"/etc/v2ray-agent/subscribe_remote/default/${email}_tmp\"\n\n            echoContent green \" ---> Universal subscription ${remoteDomain}:${email} updated successfully\"\n        else\n            echoContent red \" ---> Universal subscription ${remoteDomain}:${email} does not exist\"\n        fi\n    fi\n}\n\n# switch alpn\nswitchAlpn() {\n    echoContent skyBlue \"\\nFunction 1/${totalProgress}: switch alpn\"\n    if [[ -z ${currentAlpn} ]]; then\n        echoContent red \" ---> Unable to read alpn, please check whether it is installed\"\n        exit 0\n    fi\n\n    echoContent red \"\\n================================================ =================\"\n    echoContent green \"The first bit of the current alpn is: ${currentAlpn}\"\n    echoContent yellow \"1.When http/1.1 is the first, trojan is available, and some gRPC clients are available [the client supports manual selection of alpn]\"\n    echoContent yellow \"2.When h2 is the first, gRPC is available, and some trojan clients are available [the client supports manual selection of alpn]\"\n    echoContent yellow \"3.If the client does not support manual alpn replacement, it is recommended to use this function to change the server alpn order to use the corresponding protocol\"\n    echoContent red \"================================================== ===============\"\n\n    if [[ \"${currentAlpn}\" == \"http/1.1\" ]]; then\n        echoContent yellow \"1.Switch alpn h2 first\"\n    elif [[ \"${currentAlpn}\" == \"h2\" ]]; then\n        echoContent yellow \"1.Switch alpn http/1.1 first\"\n    else\n        echoContent red 'does not comply'\n    fi\n\n    echoContent red \"================================================== ===============\"\n\n    read -r -p \"Please select:\" selectSwitchAlpnType\n    if [[ \"${selectSwitchAlpnType}\" == \"1\" && \"${currentAlpn}\" == \"http/1.1\" ]]; then\n\n        local frontingTypeJSON\n        frontingTypeJSON=$(jq -r \".inbounds[0].streamSettings.tlsSettings.alpn = [\\\"h2\\\",\\\"http/1.1\\\"]\" ${configPath}${frontingType}.json)\n        echo \"${frontingTypeJSON}\" | jq . >${configPath}${frontingType}.json\n\n    elif [[ \"${selectSwitchAlpnType}\" == \"1\" && \"${currentAlpn}\" == \"h2\" ]]; then\n        local frontingTypeJSON\n        frontingTypeJSON=$(jq -r \".inbounds[0].streamSettings.tlsSettings.alpn =[\\\"http/1.1\\\",\\\"h2\\\"]\" ${configPath}${frontingType}.json)\n        echo \"${frontingTypeJSON}\" | jq . >${configPath}${frontingType}.json\n    else\n        echoContent red \" ---> Wrong selection\"\n        exit 0\n    fi\n    reloadCore\n}\n\n#Initialize realityKey\ninitRealityKey() {\n    echoContent skyBlue \"\\n========================== Generate key ================= =========\\n\"\n    if [[ -n \"${currentRealityPublicKey}\" ]]; then\n        read -r -p \"Read the last installation record. Do you want to use the PublicKey/PrivateKey from the last installation? [y/n]:\" historyKeyStatus\n        if [[ \"${historyKeyStatus}\" == \"y\" ]]; then\n            realityPrivateKey=${currentRealityPrivateKey}\n            realityPublicKey=${currentRealityPublicKey}\n        fi\n    fi\n    if [[ -z \"${realityPrivateKey}\" ]]; then\n        realityX25519Key=$(/etc/v2ray-agent/xray/xray x25519)\n        realityPrivateKey=$(echo \"${realityX25519Key}\" | head -1 | awk '{print $3}')\n        realityPublicKey=$(echo \"${realityX25519Key}\" | tail -n 1 | awk '{print $3}')\n    fi\n    echoContent green \"\\n privateKey:${realityPrivateKey}\"\n    echoContent green \"\\n publicKey:${realityPublicKey}\"\n}\n# Check whether the reality domain name matches\ncheckRealityDest() {\n    local traceResult=\n    traceResult=$(curl -s \"https://$(echo \"${realityDestDomain}\" | cut -d ':' -f 1)/cdn-cgi/trace\" | grep \"visit_scheme=https\")\n    if [[ -n \"${traceResult}\" ]]; then\n        echoContent red \"\\n ---> The domain name used is detected, hosted on cloudflare and the proxy is enabled. Using this type of domain name may cause VPS traffic to be used by others [not recommended]\\n\"\n        read -r -p \"Continue? [y/n]\" setRealityDestStatus\n        if [[ \"${setRealityDestStatus}\" != 'y' ]]; then\n            exit 0\n        fi\n        echoContent yellow \"\\n --->Ignore the risks and continue using\"\n    fi\n}\n\n#Initialize reality dest\ninitRealityDest() {\n    if [[ -n \"${domain}\" ]]; then\n        realityDestDomain=${domain}:${port}\n    else\n        local realityDestDomainList=\n        realityDestDomainList=\"gateway.icloud.com,itunes.apple.com,swdist.apple.com,swcdn.apple.com,updates.cdn-apple.com,mensura.cdn-apple.com,osxapps.itunes.apple.com,aod.itunes.apple.com,download-installer.cdn.mozilla.net,addons.mozilla.org,s0.awsstatic.com,d1.awsstatic.com,images-na.ssl-images-amazon.com,m.media-amazon.com,player.live-video.net,one-piece.com,lol.secure.dyn.riotcdn.net,www.lovelive-anime.jp,www.nokia.com,auth.riotgames.com,xsso.riotgames.com,csgo.com\"\n\n        echoContent skyBlue \"\\n====== Generate a domain name with fallback configuration , for example : [addons.mozilla.org:443] ======\\n\"\n        echoContent green \"Fallback domain name list: https://www.v2ray-agent.com/archives/1680104902581#heading-8\\n\"\n        read -r -p \"Please enter [Enter] to use random:\" realityDestDomain\n        if [[ -z \"${realityDestDomain}\" ]]; then\n            local randomNum=\n            randomNum=$((RANDOM % 24 + 1))\n            realityDestDomain=$(echo \"${realityDestDomainList}\" | awk -F ',' -v randomNum=\"$randomNum\" '{print $randomNum\":443\"}')\n\n        fi\n        if ! echo \"${realityDestDomain}\" | grep -q \":\"; then\n            echoContent red \"\\n ---> The domain name does not comply with the standard, please re-enter\"\n            initRealityDest\n        else\n            checkRealityDest\n            echoContent yellow \"\\n ---> Fallback domain name: ${realityDestDomain}\"\n        fi\n    fi\n}\n# Initialize the ServersName available to the client\ninitRealityClientServersName() {\n    if [[ -n \"${domain}\" ]]; then\n        realityServerNames=\\\"${domain}\\\"\n    elif [[ -n \"${realityDestDomain}\" ]]; then\n        realityServerNames=$(echo \"${realityDestDomain}\" | cut -d \":\" -f 1)\n\n        realityServerNames=\\\"${realityServerNames//,/\\\",\\\"}\\\"\n    else\n        echoContent skyBlue \"\\n================ Configure serverNames available to the client ================\\n\"\n        echoContent yellow \"#Notes\"\n        echoContent green \"List of serverNames available to the client: https://www.v2ray-agent.com/archives/1680104902581#heading-8\\n\"\n        echoContent yellow \"Input example: addons.mozilla.org\\n\"\n        read -r -p \"Please enter [Enter] to use random:\" realityServerNames\n        if [[ -z \"${realityServerNames}\" ]]; then\n            realityServerNames=\\\"addons.mozilla.org\\\"\n        else\n            realityServerNames=\\\"${realityServerNames//,/\\\",\\\"}\\\"\n        fi\n    fi\n\n    echoContent yellow \"\\n ---> Available client domain names: ${realityServerNames}\\n\"\n}\n#Initialize the reality port\ninitRealityPort() {\n    if [[ -n \"${currentRealityPort}\" ]]; then\n        read -r -p \"Read the last installation record. Do you want to use the port from the last installation? [y/n]:\" historyRealityPortStatus\n        if [[ \"${historyRealityPortStatus}\" == \"y\" ]]; then\n            realityPort=${currentRealityPort}\n        fi\n    fi\n    # todo Read the VLESS_TLS_Vision port and prompt whether to use it. There may be ambiguity here\n    if [[ -z \"${realityPort}\" ]]; then\n        if [[ -n \"${port}\" ]]; then\n            read -r -p \"Do you use TLS+Vision port? [y/n]:\" realityPortTLSVisionStatus\n            if [[ \"${realityPortTLSVisionStatus}\" == \"y\" ]]; then\n                realityPort=${port}\n            fi\n        fi\n        if [[ -z \"${realityPort}\" ]]; then\n            echoContent yellow \"Please enter the port [Enter random 10000-30000]\"\n            read -r -p \"port:\" realityPort\n            if [[ -z \"${realityPort}\" ]]; then\n                realityPort=$((RANDOM % 20001 + 10000))\n            fi\n        fi\n        if [[ -n \"${realityPort}\" && \"${currentRealityPort}\" == \"${realityPort}\" ]]; then\n            handleXray stop\n        else\n            checkPort \"${realityPort}\"\n        # if [[ -n \"${port}\" && \"${port}\" == \"${realityPort}\" ]]; then\n        # echoContent red \"The port cannot be the same as Vision--->\"\n        # echo\n        #realityPort=\n        #fi\n        fi\n    fi\n    if [[ -z \"${realityPort}\" ]]; then\n        initRealityPort\n    else\n        allowPort \"${realityPort}\"\n        echoContent yellow \"\\n ---> Port: ${realityPort}\"\n    fi\n\n}\n#Initialize reality configuration\ninitXrayRealityConfig() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Initializing Xray-core reality configuration\"\n    initRealityPort\n    initRealityKey\n    initRealityDest\n    initRealityClientServersName\n}\n# Modify reality domain name port and other information\nupdateXrayRealityConfig() {\n\n    local realityVisionResult\n    realityVisionResult=$(jq -r \".inbounds[0].port = ${realityPort}\" ${configPath}07_VLESS_vision_reality_inbounds.json)\n    realityVisionResult=$(echo \"${realityVisionResult}\" | jq -r \".inbounds[0].streamSettings.realitySettings.dest = \\\"${realityDestDomain}\\\"\")\n    realityVisionResult=$(echo \"${realityVisionResult}\" | jq -r \".inbounds[0].streamSettings.realitySettings.serverNames = [${realityServerNames}]\")\n    realityVisionResult=$(echo \"${realityVisionResult}\" | jq -r \".inbounds[0].streamSettings.realitySettings.privateKey = \\\"${realityPrivateKey}\\\"\")\n    realityVisionResult=$(echo \"${realityVisionResult}\" | jq -r \".inbounds[0].streamSettings.realitySettings.publicKey = \\\"${realityPublicKey}\\\"\")\n    echo \"${realityVisionResult}\" | jq . >${configPath}07_VLESS_vision_reality_inbounds.json\n    reloadCore\n    echoContent green \" ---> Modification completed\"\n}\n# xray-core Reality installation\nxrayCoreRealityInstall() {\n    totalProgress=13\n    installTools 2\n    # Download core\n    # prereleaseStatus=true\n    #updateXray\n    installXray 3 false\n    # Generate privateKey, configure fallback address, and configure serverNames\n    installXrayService 6\n    # initXrayRealityConfig 5\n    #Initialize configuration\n    initXrayConfig custom 7\n    handleXray stop\n    cleanUp v2rayClean\n    sleep 2\n    # start up\n    handleXray start\n    # Generate account\n    showAccounts 8\n}\n#realitymanagement\nmanageReality() {\n\n    echoContent skyBlue \"\\nProgress 1/1: reality management\"\n    echoContent red \"\\n================================================ =================\"\n\n    if [[ -n \"${realityStatus}\" ]]; then\n        echoContent yellow \"1.Reinstall\"\n        echoContent yellow \"2.Uninstall\"\n        echoContent yellow \"3.Change configuration\"\n    else\n        echoContent yellow \"1.Installation\"\n    fi\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" installRealityStatus\n\n    if [[ \"${installRealityStatus}\" == \"1\" ]]; then\n        selectCustomInstallType=\"7\"\n        xrayCoreRealityInstall\n    elif [[ \"${installRealityStatus}\" == \"2\" ]]; then\n        unInstallXrayCoreReality\n    elif [[ \"${installRealityStatus}\" == \"3\" ]]; then\n        initXrayRealityConfig 1\n        updateXrayRealityConfig\n    fi\n}\n\n# hysteriaadmin\nmanageHysteria() {\n    echoContent skyBlue \"\\nProgress 1/1: Hysteria Management\"\n    echoContent red \"\\n================================================ =================\"\n    local hysteriaStatus=\n    if [[ -n \"${hysteriaConfigPath}\" ]]; then\n        echoContent yellow \"1.Reinstall\"\n        echoContent yellow \"2.Uninstall\"\n        echoContent yellow \"3.Port jump management\"\n        echoContent yellow \"4.core management\"\n        echoContent yellow \"5.View log\"\n        hysteriaStatus=true\n    else\n        echoContent yellow \"1.Installation\"\n    fi\n\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" installHysteriaStatus\n    if [[ \"${installHysteriaStatus}\" == \"1\" ]]; then\n        hysteriaCoreInstall\n    elif [[ \"${installHysteriaStatus}\" == \"2\" && \"${hysteriaStatus}\" == \"true\" ]]; then\n        unInstallHysteriaCore\n    elif [[ \"${installHysteriaStatus}\" == \"3\" && \"${hysteriaStatus}\" == \"true\" ]]; then\n        hysteriaPortHoppingMenu\n    elif [[ \"${installHysteriaStatus}\" == \"4\" && \"${hysteriaStatus}\" == \"true\" ]]; then\n        hysteriaVersionManageMenu 1\n    elif [[ \"${installHysteriaStatus}\" == \"5\" && \"${hysteriaStatus}\" == \"true\" ]]; then\n        journalctl -fu hysteria\n    fi\n}\n\n#tuicadmin\nmanageTuic() {\n    echoContent skyBlue \"\\nProgress 1/1: Tuic Management\"\n    echoContent red \"\\n================================================ =================\"\n    local tuicStatus=\n    if [[ -n \"${tuicConfigPath}\" ]]; then\n        echoContent yellow \"1.Reinstall\"\n        echoContent yellow \"2.Uninstall\"\n        echoContent yellow \"3.core management\"\n        echoContent yellow \"4.View log\"\n        tuicStatus=true\n    else\n        echoContent yellow \"1.Installation\"\n    fi\n\n    echoContent red \"================================================== ===============\"\n    read -r -p \"Please select:\" installTuicStatus\n    if [[ \"${installTuicStatus}\" == \"1\" ]]; then\n        tuicCoreInstall\n    elif [[ \"${installTuicStatus}\" == \"2\" && \"${tuicStatus}\" == \"true\" ]]; then\n        unInstallTuicCore\n    elif [[ \"${installTuicStatus}\" == \"3\" && \"${tuicStatus}\" == \"true\" ]]; then\n        tuicVersionManageMenu 1\n    elif [[ \"${installTuicStatus}\" == \"4\" && \"${tuicStatus}\" == \"true\" ]]; then\n        journalctl -fu tuic\n    fi\n}\n# hysteria version management\nhysteriaVersionManageMenu() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Hysteria version management\"\n    if [[ ! -d \"/etc/v2ray-agent/hysteria/\" ]]; then\n        echoContent red \" ---> The installation directory is not detected, please execute the script to install the content\"\n        menu\n        exit 0\n    fi\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.Upgrade Hysteria\"\n    echoContent yellow \"2.Close Hysteria\"\n    echoContent yellow \"3.Open Hysteria\"\n    echoContent yellow \"4.Restart Hysteria\"\n    echoContent red \"================================================== ===============\"\n\n    read -r -p \"Please select:\" selectHysteriaType\n    if [[ \"${selectHysteriaType}\" == \"1\" ]]; then\n        installHysteria 1\n        handleHysteria start\n    elif [[ \"${selectHysteriaType}\" == \"2\" ]]; then\n        handleHysteria stop\n    elif [[ \"${selectHysteriaType}\" == \"3\" ]]; then\n        handleHysteria start\n    elif [[ \"${selectHysteriaType}\" == \"4\" ]]; then\n        handleHysteria stop\n        handleHysteria start\n    fi\n}\n\n# Tuic version management\ntuicVersionManageMenu() {\n    echoContent skyBlue \"\\nProgress$1/${totalProgress}: Tuic version management\"\n    if [[ ! -d \"/etc/v2ray-agent/tuic/\" ]]; then\n        echoContent red \" ---> The installation directory is not detected, please execute the script to install the content\"\n        menu\n        exit 0\n    fi\n    echoContent red \"\\n================================================ =================\"\n    echoContent yellow \"1.Upgrade Tuic\"\n    echoContent yellow \"2.Close Tuic\"\n    echoContent yellow \"3.Open Tuic\"\n    echoContent yellow \"4.Restart Tuic\"\n    echoContent red \"================================================== ===============\"\n\n    read -r -p \"Please select:\" selectTuicType\n    if [[ \"${selectTuicType}\" == \"1\" ]]; then\n        installTuic 1\n        handleTuic start\n    elif [[ \"${selectTuicType}\" == \"2\" ]]; then\n        handleTuic stop\n    elif [[ \"${selectTuicType}\" == \"3\" ]]; then\n        handleTuic start\n    elif [[ \"${selectTuicType}\" == \"4\" ]]; then\n        handleTuic stop\n        handleTuic start\n    fi\n}\n# main menu\nmenu() {\n    cd \"$HOME\" || exit\n    echoContent red \"\\n================================================ =================\"\n    echoContent green \"Author: mack-a\"\n    echoContent green \"Current version: v2.10.20\"\n    echoContent green \"Github: https://github.com/mack-a/v2ray-agent\"\n    echoContent green \"Description: 8-in-1 coexistence script\\c\"\n    showInstallStatus\n    checkWgetShowProgress\n    echoContent red \"\\n============================ Promotion area================ ============\"\n    echoContent red \" \"\n    echoContent green \"For promotion, please contact TG: @mackaff\\n\"\n    echoContent green \"VPS purchasing guide: https://www.v2ray-agent.com/archives/1679975663984\"\n    echoContent green \"Low-price VPS AS4837 with an annual payment of 10 US dollars: https://www.v2ray-agent.com/archives/racknerdtao-can-zheng-li-nian-fu-10mei-yuan\"\n    echoContent red \"================================================== ===============\"\n    if [[ -n \"${coreInstallType}\" ]]; then\n        echoContent yellow \"1.Reinstall\"\n    else\n        echoContent yellow \"1.Installation\"\n    fi\n\n    echoContent yellow \"2.Install in any combination\"\n    if echo ${currentInstallProtocolType} | grep -q trojan; then\n        echoContent yellow \"3.Switch VLESS[XTLS]\"\n    elif echo ${currentInstallProtocolType} | grep -q 0; then\n        echoContent yellow \"3.Switch Trojan[XTLS]\"\n    fi\n\n    echoContent yellow \"4.Hysteria Management\"\n    echoContent yellow \"5.REALITY Management\"\n    echoContent yellow \"6.Tuic Management\"\n    echoContent skyBlue \"-------------------------Tool Management-------------------- ---------\"\n    echoContent yellow \"7.Account management\"\n    echoContent yellow \"8.Change the camouflage station\"\n    echoContent yellow \"9.Update certificate\"\n    echoContent yellow \"10.Change CDN node\"\n    echoContent yellow \"11.Diversion tool\"\n    echoContent yellow \"12.Add new port\"\n    echoContent yellow \"13.BT download management\"\n    echoContent yellow \"14.Switch alpn\"\n    echoContent yellow \"15.Domain name blacklist\"\n    echoContent skyBlue \"-------------------------Version Management-------------------- ---------\"\n    echoContent yellow \"16.core management\"\n    echoContent yellow \"17.Update script\"\n    echoContent yellow \"18.Install BBR and DD scripts\"\n    echoContent skyBlue \"-------------------------Script Management-------------------- --- ------\"\n    echoContent yellow \"19.View log\"\n    echoContent yellow \"20.Uninstall script\"\n    echoContent red \"================================================== ===============\"\n    mkdirTools\n    aliasInstall\n    read -r -p \"Please select:\" selectInstallType\n    case ${selectInstallType} in\n    1)\n        selectCoreInstall\n        ;;\n    2)\n        selectCoreInstall\n        ;;\n    3)\n        initXrayFrontingConfig 1\n        ;;\n    4)\n        manageHysteria\n        ;;\n    5)\n        manageReality 1\n        ;;\n    6)\n        manageTuic\n        ;;\n    7)\n        manageAccount 1\n        ;;\n    8)\n        updateNginxBlog 1\n        ;;\n    9)\n        renewalTLS 1\n        ;;\n    10)\n        updateV2RayCDN 1\n        ;;\n    11)\n        routingToolsMenu 1\n        ;;\n    12)\n        addCorePort 1\n        ;;\n    13)\n        btTools 1\n        ;;\n    14)\n        switchAlpn 1\n        ;;\n    15)\n        blacklist 1\n        ;;\n    16)\n        coreVersionManageMenu 1\n        ;;\n    17)\n        updateV2RayAgent 1\n        ;;\n    18)\n        bbrInstall\n        ;;\n    19)\n        checkLog 1\n        ;;\n    20)\n        unInstall 1\n        ;;\n    esac\n}\ncronFunction\nmenu\n"
  },
  {
    "path": "shell/send_email.sh",
    "content": "#!/usr/bin/env bash\ntouch /var/local/mail.log\n\ncurrentIP=$(curl -s -4 whatismyip.akamai.com)\nhistoryIP=$(cat /var/local/mail.log)\nif [[ ${currentIP} = ${historyIP} ]];then\n\techo '不发送邮件'\n\techo '不发送邮件' >> /tmp/mail.log\n\texit\nfi\necho ${currentIP}|mail -s ${currentIP} xxx@163.com\necho ${currentIP} > /var/local/mail.log\n"
  },
  {
    "path": "shell/ufw_remove.sh",
    "content": "#!/usr/bin/env bash\n# wget -P /tmp -N --no-check-certificate \"https://raw.githubusercontent.com/mack-a/v2ray-agent/master/shell/ufw_remove.sh\" && chmod 700 /tmp/ufw_remove.sh && /tmp/ufw_remove.sh\nsystemctl stop ufw\nsystemctl disable ufw\niptables -F\niptables -I INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT\niptables -I OUTPUT -o eth0 -d 0.0.0.0/0 -j ACCEPT\n"
  }
]