├── .github
└── workflows
│ └── release.yml
├── LICENSE
├── README.md
├── install.sh
├── src
├── bbr.sh
├── caddy.sh
├── core.sh
├── dns.sh
├── download.sh
├── help.sh
├── init.sh
└── systemd.sh
└── xray.sh
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Main
2 |
3 | on: push
4 |
5 | permissions:
6 | contents: write
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: checkout
13 | uses: actions/checkout@v3
14 | with:
15 | fetch-depth: 0
16 | - name: get ver
17 | run: |
18 | echo "$(cat xray.sh | grep ver=)" >> $GITHUB_ENV
19 | echo "old=$(git tag | tail -n1)" >> $GITHUB_ENV
20 | # - name: test
21 | # if: env.is_sh_ver == env.old
22 | # run: |
23 | # echo not found new version.
24 | # exit 1
25 | - name: zip
26 | run: zip -9vr code.zip . -x .\*
27 | - name: release
28 | uses: softprops/action-gh-release@v1
29 | with:
30 | files: code.zip
31 | tag_name: ${{ env.is_sh_ver }}
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 介绍
2 |
3 | 最好用的 Xray 一键安装脚本 & 管理脚本
4 |
5 | # 特点
6 |
7 | - 快速安装
8 | - 无敌好用
9 | - 零学习成本
10 | - 自动化 TLS
11 | - 简化所有流程
12 | - 屏蔽 BT
13 | - 屏蔽中国 IP
14 | - 使用 API 操作
15 | - 兼容 Xray 命令
16 | - 强大的快捷参数
17 | - 支持所有常用协议
18 | - 一键添加 VLESS-REALITY (默认)
19 | - 一键添加 Shadowsocks 2022
20 | - 一键添加 VMess-(TCP/mKCP)
21 | - 一键添加 VMess-(WS/gRPC)-TLS
22 | - 一键添加 VLESS-(WS/gRPC/XHTTP)-TLS
23 | - 一键添加 Trojan-(WS/gRPC)-TLS
24 | - 一键添加 VMess-(TCP/mKCP) 动态端口
25 | - 一键启用 BBR
26 | - 一键更改伪装网站
27 | - 一键更改 (端口/UUID/密码/域名/路径/加密方式/SNI/动态端口/等...)
28 | - 还有更多...
29 |
30 | # 设计理念
31 |
32 | 设计理念为:**高效率,超快速,极易用**
33 |
34 | 脚本基于作者的自身使用需求,以 **多配置同时运行** 为核心设计
35 |
36 | 并且专门优化了,添加、更改、查看、删除、这四项常用功能
37 |
38 | 你只需要一条命令即可完成 添加、更改、查看、删除、等操作
39 |
40 | 例如,添加一个配置仅需不到 1 秒!瞬间完成添加!其他操作亦是如此!
41 |
42 | 脚本的参数非常高效率并且超级易用,请掌握参数的使用
43 |
44 | # 文档
45 |
46 | 安装及使用:https://233boy.com/xray/xray-script/
47 |
48 | # 帮助
49 |
50 | 使用:`xray help`
51 |
52 | ```
53 | Xray script v1.21 by 233boy
54 | Usage: xray [options]... [args]...
55 |
56 | 基本:
57 | v, version 显示当前版本
58 | ip 返回当前主机的 IP
59 | pbk 同等于 xray x25519
60 | get-port 返回一个可用的端口
61 | ss2022 返回一个可用于 Shadowsocks 2022 的密码
62 |
63 | 一般:
64 | a, add [protocol] [args... | auto] 添加配置
65 | c, change [name] [option] [args... | auto] 更改配置
66 | d, del [name] 删除配置**
67 | i, info [name] 查看配置
68 | qr [name] 二维码信息
69 | url [name] URL 信息
70 | log 查看日志
71 | logerr 查看错误日志
72 |
73 | 更改:
74 | dp, dynamicport [name] [start | auto] [end] 更改动态端口
75 | full [name] [...] 更改多个参数
76 | id [name] [uuid | auto] 更改 UUID
77 | host [name] [domain] 更改域名
78 | port [name] [port | auto] 更改端口
79 | path [name] [path | auto] 更改路径
80 | passwd [name] [password | auto] 更改密码
81 | key [name] [Private key | atuo] [Public key] 更改密钥
82 | type [name] [type | auto] 更改伪装类型
83 | method [name] [method | auto] 更改加密方式
84 | sni [name] [ ip | domain] 更改 serverName
85 | seed [name] [seed | auto] 更改 mKCP seed
86 | new [name] [...] 更改协议
87 | web [name] [domain] 更改伪装网站
88 |
89 | 进阶:
90 | dns [...] 设置 DNS
91 | dd, ddel [name...] 删除多个配置**
92 | fix [name] 修复一个配置
93 | fix-all 修复全部配置
94 | fix-caddyfile 修复 Caddyfile
95 | fix-config.json 修复 config.json
96 |
97 | 管理:
98 | un, uninstall 卸载
99 | u, update [core | sh | dat | caddy] [ver] 更新
100 | U, update.sh 更新脚本
101 | s, status 运行状态
102 | start, stop, restart [caddy] 启动, 停止, 重启
103 | t, test 测试运行
104 | reinstall 重装脚本
105 |
106 | 测试:
107 | client [name] 显示用于客户端 JSON, 仅供参考
108 | debug [name] 显示一些 debug 信息, 仅供参考
109 | gen [...] 同等于 add, 但只显示 JSON 内容, 不创建文件, 测试使用
110 | genc [name] 显示用于客户端部分 JSON, 仅供参考
111 | no-auto-tls [...] 同等于 add, 但禁止自动配置 TLS, 可用于 *TLS 相关协议
112 | xapi [...] 同等于 xray api, 但 API 后端使用当前运行的 Xray 服务
113 |
114 | 其他:
115 | bbr 启用 BBR, 如果支持
116 | bin [...] 运行 Xray 命令, 例如: xray bin help
117 | api, x25519, tls, run, uuid [...] 兼容 Xray 命令
118 | h, help 显示此帮助界面
119 |
120 | 谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认
121 | 反馈问题) https://github.com/233boy/xray/issues
122 | 文档(doc) https://233boy.com/xray/xray-script/
123 | ```
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | author=233boy
4 | # github=https://github.com/233boy/xray
5 |
6 | # bash fonts colors
7 | red='\e[31m'
8 | yellow='\e[33m'
9 | gray='\e[90m'
10 | green='\e[92m'
11 | blue='\e[94m'
12 | magenta='\e[95m'
13 | cyan='\e[96m'
14 | none='\e[0m'
15 | _red() { echo -e ${red}$@${none}; }
16 | _blue() { echo -e ${blue}$@${none}; }
17 | _cyan() { echo -e ${cyan}$@${none}; }
18 | _green() { echo -e ${green}$@${none}; }
19 | _yellow() { echo -e ${yellow}$@${none}; }
20 | _magenta() { echo -e ${magenta}$@${none}; }
21 | _red_bg() { echo -e "\e[41m$@${none}"; }
22 |
23 | is_err=$(_red_bg 错误!)
24 | is_warn=$(_red_bg 警告!)
25 |
26 | err() {
27 | echo -e "\n$is_err $@\n" && exit 1
28 | }
29 |
30 | warn() {
31 | echo -e "\n$is_warn $@\n"
32 | }
33 |
34 | # root
35 | [[ $EUID != 0 ]] && err "当前非 ${yellow}ROOT用户.${none}"
36 |
37 | # yum or apt-get, ubuntu/debian/centos
38 | cmd=$(type -P apt-get || type -P yum)
39 | [[ ! $cmd ]] && err "此脚本仅支持 ${yellow}(Ubuntu or Debian or CentOS)${none}."
40 |
41 | # systemd
42 | [[ ! $(type -P systemctl) ]] && {
43 | err "此系统缺少 ${yellow}(systemctl)${none}, 请尝试执行:${yellow} ${cmd} update -y;${cmd} install systemd -y ${none}来修复此错误."
44 | }
45 |
46 | # wget installed or none
47 | is_wget=$(type -P wget)
48 |
49 | # x64
50 | case $(uname -m) in
51 | amd64 | x86_64)
52 | is_jq_arch=amd64
53 | is_core_arch="64"
54 | ;;
55 | *aarch64* | *armv8*)
56 | is_jq_arch=arm64
57 | is_core_arch="arm64-v8a"
58 | ;;
59 | *)
60 | err "此脚本仅支持 64 位系统..."
61 | ;;
62 | esac
63 |
64 | is_core=xray
65 | is_core_name=Xray
66 | is_core_dir=/etc/$is_core
67 | is_core_bin=$is_core_dir/bin/$is_core
68 | is_core_repo=xtls/$is_core-core
69 | is_conf_dir=$is_core_dir/conf
70 | is_log_dir=/var/log/$is_core
71 | is_sh_bin=/usr/local/bin/$is_core
72 | is_sh_dir=$is_core_dir/sh
73 | is_sh_repo=$author/$is_core
74 | is_pkg="wget unzip"
75 | is_config_json=$is_core_dir/config.json
76 | tmp_var_lists=(
77 | tmpcore
78 | tmpsh
79 | tmpjq
80 | is_core_ok
81 | is_sh_ok
82 | is_jq_ok
83 | is_pkg_ok
84 | )
85 |
86 | # tmp dir
87 | tmpdir=$(mktemp -u)
88 | [[ ! $tmpdir ]] && {
89 | tmpdir=/tmp/tmp-$RANDOM
90 | }
91 |
92 | # set up var
93 | for i in ${tmp_var_lists[*]}; do
94 | export $i=$tmpdir/$i
95 | done
96 |
97 | # load bash script.
98 | load() {
99 | . $is_sh_dir/src/$1
100 | }
101 |
102 | # wget add --no-check-certificate
103 | _wget() {
104 | [[ $proxy ]] && export https_proxy=$proxy
105 | wget --no-check-certificate $*
106 | }
107 |
108 | # print a mesage
109 | msg() {
110 | case $1 in
111 | warn)
112 | local color=$yellow
113 | ;;
114 | err)
115 | local color=$red
116 | ;;
117 | ok)
118 | local color=$green
119 | ;;
120 | esac
121 |
122 | echo -e "${color}$(date +'%T')${none}) ${2}"
123 | }
124 |
125 | # show help msg
126 | show_help() {
127 | echo -e "Usage: $0 [-f xxx | -l | -p xxx | -v xxx | -h]"
128 | echo -e " -f, --core-file 自定义 $is_core_name 文件路径, e.g., -f /root/${is_core}-linux-64.zip"
129 | echo -e " -l, --local-install 本地获取安装脚本, 使用当前目录"
130 | echo -e " -p, --proxy 使用代理下载, e.g., -p http://127.0.0.1:2333"
131 | echo -e " -v, --core-version 自定义 $is_core_name 版本, e.g., -v v1.8.1"
132 | echo -e " -h, --help 显示此帮助界面\n"
133 |
134 | exit 0
135 | }
136 |
137 | # install dependent pkg
138 | install_pkg() {
139 | cmd_not_found=
140 | for i in $*; do
141 | [[ ! $(type -P $i) ]] && cmd_not_found="$cmd_not_found,$i"
142 | done
143 | if [[ $cmd_not_found ]]; then
144 | pkg=$(echo $cmd_not_found | sed 's/,/ /g')
145 | msg warn "安装依赖包 >${pkg}"
146 | $cmd install -y $pkg &>/dev/null
147 | if [[ $? != 0 ]]; then
148 | [[ $cmd =~ yum ]] && yum install epel-release -y &>/dev/null
149 | $cmd update -y &>/dev/null
150 | $cmd install -y $pkg &>/dev/null
151 | [[ $? == 0 ]] && >$is_pkg_ok
152 | else
153 | >$is_pkg_ok
154 | fi
155 | else
156 | >$is_pkg_ok
157 | fi
158 | }
159 |
160 | # download file
161 | download() {
162 | case $1 in
163 | core)
164 | link=https://github.com/${is_core_repo}/releases/latest/download/${is_core}-linux-${is_core_arch}.zip
165 | [[ $is_core_ver ]] && link="https://github.com/${is_core_repo}/releases/download/${is_core_ver}/${is_core}-linux-${is_core_arch}.zip"
166 | name=$is_core_name
167 | tmpfile=$tmpcore
168 | is_ok=$is_core_ok
169 | ;;
170 | sh)
171 | link=https://github.com/${is_sh_repo}/releases/latest/download/code.zip
172 | name="$is_core_name 脚本"
173 | tmpfile=$tmpsh
174 | is_ok=$is_sh_ok
175 | ;;
176 | jq)
177 | link=https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-$is_jq_arch
178 | name="jq"
179 | tmpfile=$tmpjq
180 | is_ok=$is_jq_ok
181 | ;;
182 | esac
183 |
184 | msg warn "下载 ${name} > ${link}"
185 | if _wget -t 3 -q -c $link -O $tmpfile; then
186 | mv -f $tmpfile $is_ok
187 | fi
188 | }
189 |
190 | # get server ip
191 | get_ip() {
192 | export "$(_wget -4 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null
193 | [[ -z $ip ]] && export "$(_wget -6 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null
194 | }
195 |
196 | # check background tasks status
197 | check_status() {
198 | # dependent pkg install fail
199 | [[ ! -f $is_pkg_ok ]] && {
200 | msg err "安装依赖包失败"
201 | msg err "请尝试手动安装依赖包: $cmd update -y; $cmd install -y $pkg"
202 | is_fail=1
203 | }
204 |
205 | # download file status
206 | if [[ $is_wget ]]; then
207 | [[ ! -f $is_core_ok ]] && {
208 | msg err "下载 ${is_core_name} 失败"
209 | is_fail=1
210 | }
211 | [[ ! -f $is_sh_ok ]] && {
212 | msg err "下载 ${is_core_name} 脚本失败"
213 | is_fail=1
214 | }
215 | [[ ! -f $is_jq_ok ]] && {
216 | msg err "下载 jq 失败"
217 | is_fail=1
218 | }
219 | else
220 | [[ ! $is_fail ]] && {
221 | is_wget=1
222 | [[ ! $is_core_file ]] && download core &
223 | [[ ! $local_install ]] && download sh &
224 | [[ $jq_not_found ]] && download jq &
225 | get_ip
226 | wait
227 | check_status
228 | }
229 | fi
230 |
231 | # found fail status, remove tmp dir and exit.
232 | [[ $is_fail ]] && {
233 | exit_and_del_tmpdir
234 | }
235 | }
236 |
237 | # parameters check
238 | pass_args() {
239 | while [[ $# -gt 0 ]]; do
240 | case $1 in
241 | -f | --core-file)
242 | [[ -z $2 ]] && {
243 | err "($1) 缺少必需参数, 正确使用示例: [$1 /root/$is_core-linux-64.zip]"
244 | } || [[ ! -f $2 ]] && {
245 | err "($2) 不是一个常规的文件."
246 | }
247 | is_core_file=$2
248 | shift 2
249 | ;;
250 | -l | --local-install)
251 | [[ ! -f ${PWD}/src/core.sh || ! -f ${PWD}/$is_core.sh ]] && {
252 | err "当前目录 (${PWD}) 非完整的脚本目录."
253 | }
254 | local_install=1
255 | shift 1
256 | ;;
257 | -p | --proxy)
258 | [[ -z $2 ]] && {
259 | err "($1) 缺少必需参数, 正确使用示例: [$1 http://127.0.0.1:2333 or -p socks5://127.0.0.1:2333]"
260 | }
261 | proxy=$2
262 | shift 2
263 | ;;
264 | -v | --core-version)
265 | [[ -z $2 ]] && {
266 | err "($1) 缺少必需参数, 正确使用示例: [$1 v1.8.1]"
267 | }
268 | is_core_ver=v${2#v}
269 | shift 2
270 | ;;
271 | -h | --help)
272 | show_help
273 | ;;
274 | *)
275 | echo -e "\n${is_err} ($@) 为未知参数...\n"
276 | show_help
277 | ;;
278 | esac
279 | done
280 | [[ $is_core_ver && $is_core_file ]] && {
281 | err "无法同时自定义 ${is_core_name} 版本和 ${is_core_name} 文件."
282 | }
283 | }
284 |
285 | # exit and remove tmpdir
286 | exit_and_del_tmpdir() {
287 | rm -rf $tmpdir
288 | [[ ! $1 ]] && {
289 | msg err "哦豁.."
290 | msg err "安装过程出现错误..."
291 | echo -e "反馈问题) https://github.com/${is_sh_repo}/issues"
292 | echo
293 | exit 1
294 | }
295 | exit
296 | }
297 |
298 | # main
299 | main() {
300 |
301 | # check old version
302 | [[ -f $is_sh_bin && -d $is_core_dir/bin && -d $is_sh_dir && -d $is_conf_dir ]] && {
303 | err "检测到脚本已安装, 如需重装请使用${green} ${is_core} reinstall ${none}命令."
304 | }
305 |
306 | # check parameters
307 | [[ $# -gt 0 ]] && pass_args $@
308 |
309 | # show welcome msg
310 | clear
311 | echo
312 | echo "........... $is_core_name script by $author .........."
313 | echo
314 |
315 | # start installing...
316 | msg warn "开始安装..."
317 | [[ $is_core_ver ]] && msg warn "${is_core_name} 版本: ${yellow}$is_core_ver${none}"
318 | [[ $proxy ]] && msg warn "使用代理: ${yellow}$proxy${none}"
319 | # create tmpdir
320 | mkdir -p $tmpdir
321 | # if is_core_file, copy file
322 | [[ $is_core_file ]] && {
323 | cp -f $is_core_file $is_core_ok
324 | msg warn "${yellow}${is_core_name} 文件使用 > $is_core_file${none}"
325 | }
326 | # local dir install sh script
327 | [[ $local_install ]] && {
328 | >$is_sh_ok
329 | msg warn "${yellow}本地获取安装脚本 > $PWD ${none}"
330 | }
331 |
332 | timedatectl set-ntp true &>/dev/null
333 | [[ $? != 0 ]] && {
334 | msg warn "${yellow}\e[4m提醒!!! 无法设置自动同步时间, 可能会影响使用 VMess 协议.${none}"
335 | }
336 |
337 | # install dependent pkg
338 | install_pkg $is_pkg &
339 |
340 | # jq
341 | if [[ $(type -P jq) ]]; then
342 | >$is_jq_ok
343 | else
344 | jq_not_found=1
345 | fi
346 | # if wget installed. download core, sh, jq, get ip
347 | [[ $is_wget ]] && {
348 | [[ ! $is_core_file ]] && download core &
349 | [[ ! $local_install ]] && download sh &
350 | [[ $jq_not_found ]] && download jq &
351 | get_ip
352 | }
353 |
354 | # waiting for background tasks is done
355 | wait
356 |
357 | # check background tasks status
358 | check_status
359 |
360 | # test $is_core_file
361 | if [[ $is_core_file ]]; then
362 | unzip -qo $is_core_ok -d $tmpdir/testzip &>/dev/null
363 | [[ $? != 0 ]] && {
364 | msg err "${is_core_name} 文件无法通过测试."
365 | exit_and_del_tmpdir
366 | }
367 | for i in ${is_core} geoip.dat geosite.dat; do
368 | [[ ! -f $tmpdir/testzip/$i ]] && is_file_err=1 && break
369 | done
370 | [[ $is_file_err ]] && {
371 | msg err "${is_core_name} 文件无法通过测试."
372 | exit_and_del_tmpdir
373 | }
374 | fi
375 |
376 | # get server ip.
377 | [[ ! $ip ]] && {
378 | msg err "获取服务器 IP 失败."
379 | exit_and_del_tmpdir
380 | }
381 |
382 | # create sh dir...
383 | mkdir -p $is_sh_dir
384 |
385 | # copy sh file or unzip sh zip file.
386 | if [[ $local_install ]]; then
387 | cp -rf $PWD/* $is_sh_dir
388 | else
389 | unzip -qo $is_sh_ok -d $is_sh_dir
390 | fi
391 |
392 | # create core bin dir
393 | mkdir -p $is_core_dir/bin
394 | # copy core file or unzip core zip file
395 | if [[ $is_core_file ]]; then
396 | cp -rf $tmpdir/testzip/* $is_core_dir/bin
397 | else
398 | unzip -qo $is_core_ok -d $is_core_dir/bin
399 | fi
400 |
401 | # add alias
402 | echo "alias $is_core=$is_sh_bin" >>/root/.bashrc
403 |
404 | # core command
405 | ln -sf $is_sh_dir/$is_core.sh $is_sh_bin
406 |
407 | # jq
408 | [[ $jq_not_found ]] && mv -f $is_jq_ok /usr/bin/jq
409 |
410 | # chmod
411 | chmod +x $is_core_bin $is_sh_bin /usr/bin/jq
412 |
413 | # create log dir
414 | mkdir -p $is_log_dir
415 |
416 | # show a tips msg
417 | msg ok "生成配置文件..."
418 |
419 | # create systemd service
420 | load systemd.sh
421 | is_new_install=1
422 | install_service $is_core &>/dev/null
423 |
424 | # create condf dir
425 | mkdir -p $is_conf_dir
426 |
427 | load core.sh
428 | # create a tcp config
429 | add reality
430 | # remove tmp dir and exit.
431 | exit_and_del_tmpdir ok
432 | }
433 |
434 | # start.
435 | main $@
436 |
--------------------------------------------------------------------------------
/src/bbr.sh:
--------------------------------------------------------------------------------
1 | _open_bbr() {
2 | sed -i '/net.ipv4.tcp_congestion_control/d' /etc/sysctl.conf
3 | sed -i '/net.core.default_qdisc/d' /etc/sysctl.conf
4 | echo "net.ipv4.tcp_congestion_control = bbr" >>/etc/sysctl.conf
5 | echo "net.core.default_qdisc = fq" >>/etc/sysctl.conf
6 | sysctl -p &>/dev/null
7 | echo
8 | _green "..已经启用 BBR 优化...."
9 | echo
10 | }
11 |
12 | _try_enable_bbr() {
13 | local _test1=$(uname -r | cut -d\. -f1)
14 | local _test2=$(uname -r | cut -d\. -f2)
15 | if [[ $_test1 -eq 4 && $_test2 -ge 9 ]] || [[ $_test1 -ge 5 ]]; then
16 | _open_bbr
17 | else
18 | err "不支持启用 BBR 优化."
19 | fi
20 | }
21 |
--------------------------------------------------------------------------------
/src/caddy.sh:
--------------------------------------------------------------------------------
1 | caddy_config() {
2 | is_caddy_site_file=$is_caddy_conf/${host}.conf
3 | case $1 in
4 | new)
5 | mkdir -p $is_caddy_dir $is_caddy_dir/sites $is_caddy_conf
6 | cat >$is_caddyfile <<-EOF
7 | # don't edit this file #
8 | # for more info, see https://233boy.com/$is_core/caddy-auto-tls/
9 | # 不要编辑这个文件 #
10 | # 更多相关请阅读此文章: https://233boy.com/$is_core/caddy-auto-tls/
11 | # https://caddyserver.com/docs/caddyfile/options
12 | {
13 | admin off
14 | http_port $is_http_port
15 | https_port $is_https_port
16 | }
17 | import $is_caddy_conf/*.conf
18 | import $is_caddy_dir/sites/*.conf
19 | EOF
20 | ;;
21 | *ws*)
22 | cat >${is_caddy_site_file} <<<"
23 | ${host}:${is_https_port} {
24 | reverse_proxy ${path} 127.0.0.1:${port}
25 | import ${is_caddy_site_file}.add
26 | }"
27 | ;;
28 | *h2*)
29 | cat >${is_caddy_site_file} <<<"
30 | ${host}:${is_https_port} {
31 | reverse_proxy ${path} h2c://127.0.0.1:${port}
32 | import ${is_caddy_site_file}.add
33 | }"
34 | ;;
35 | *grpc*)
36 | cat >${is_caddy_site_file} <<<"
37 | ${host}:${is_https_port} {
38 | reverse_proxy /${path}/* h2c://127.0.0.1:${port}
39 | import ${is_caddy_site_file}.add
40 | }"
41 | ;;
42 | xhttp)
43 | cat >${is_caddy_site_file} <<<"
44 | ${host}:${is_https_port} {
45 | reverse_proxy ${path}/* h2c://127.0.0.1:${port}
46 | import ${is_caddy_site_file}.add
47 | }"
48 | ;;
49 | proxy)
50 |
51 | cat >${is_caddy_site_file}.add <<<"
52 | reverse_proxy https://$proxy_site {
53 | header_up Host {upstream_hostport}
54 | }"
55 | ;;
56 | esac
57 | [[ $1 != "new" && $1 != 'proxy' ]] && {
58 | [[ ! -f ${is_caddy_site_file}.add ]] && echo "# see https://233boy.com/$is_core/caddy-auto-tls/" >${is_caddy_site_file}.add
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/core.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | protocol_list=(
4 | VMess-TCP
5 | VMess-mKCP
6 | # VMess-QUIC
7 | # VMess-H2-TLS
8 | VMess-WS-TLS
9 | VMess-gRPC-TLS
10 | # VLESS-H2-TLS
11 | VLESS-WS-TLS
12 | VLESS-gRPC-TLS
13 | VLESS-XHTTP-TLS
14 | VLESS-REALITY
15 | # Trojan-H2-TLS
16 | Trojan-WS-TLS
17 | Trojan-gRPC-TLS
18 | Shadowsocks
19 | # Dokodemo-Door
20 | VMess-TCP-dynamic-port
21 | VMess-mKCP-dynamic-port
22 | # VMess-QUIC-dynamic-port
23 | Socks
24 | )
25 | ss_method_list=(
26 | aes-128-gcm
27 | aes-256-gcm
28 | chacha20-ietf-poly1305
29 | xchacha20-ietf-poly1305
30 | 2022-blake3-aes-128-gcm
31 | 2022-blake3-aes-256-gcm
32 | 2022-blake3-chacha20-poly1305
33 | )
34 | header_type_list=(
35 | none
36 | srtp
37 | utp
38 | wechat-video
39 | dtls
40 | wireguard
41 | )
42 | mainmenu=(
43 | "添加配置"
44 | "更改配置"
45 | "查看配置"
46 | "删除配置"
47 | "运行管理"
48 | "更新"
49 | "卸载"
50 | "帮助"
51 | "其他"
52 | "关于"
53 | )
54 | info_list=(
55 | "协议 (protocol)"
56 | "地址 (address)"
57 | "端口 (port)"
58 | "用户ID (id)"
59 | "传输协议 (network)"
60 | "伪装类型 (type)"
61 | "伪装域名 (host)"
62 | "路径 (path)"
63 | "传输层安全 (TLS)"
64 | "mKCP seed"
65 | "密码 (password)"
66 | "加密方式 (encryption)"
67 | "链接 (URL)"
68 | "目标地址 (remote addr)"
69 | "目标端口 (remote port)"
70 | "流控 (flow)"
71 | "SNI (serverName)"
72 | "指纹 (Fingerprint)"
73 | "公钥 (Public key)"
74 | "用户名 (Username)"
75 | )
76 | change_list=(
77 | "更改协议"
78 | "更改端口"
79 | "更改域名"
80 | "更改路径"
81 | "更改密码"
82 | "更改 UUID"
83 | "更改加密方式"
84 | "更改伪装类型"
85 | "更改目标地址"
86 | "更改目标端口"
87 | "更改密钥"
88 | "更改 SNI (serverName)"
89 | "更改动态端口"
90 | "更改伪装网站"
91 | "更改 mKCP seed"
92 | "更改用户名 (Username)"
93 | )
94 | servername_list=(
95 | www.amazon.com
96 | www.ebay.com
97 | www.paypal.com
98 | www.cloudflare.com
99 | dash.cloudflare.com
100 | aws.amazon.com
101 | )
102 |
103 | is_random_ss_method=${ss_method_list[$(shuf -i 4-6 -n1)]} # random only use ss2022
104 | is_random_header_type=${header_type_list[$(shuf -i 1-5 -n1)]} # random dont use none
105 | is_random_servername=${servername_list[$(shuf -i 0-${#servername_list[@]} -n1) - 1]}
106 |
107 | msg() {
108 | echo -e "$@"
109 | }
110 |
111 | msg_ul() {
112 | echo -e "\e[4m$@\e[0m"
113 | }
114 |
115 | # pause
116 | pause() {
117 | echo
118 | echo -ne "按 $(_green Enter 回车键) 继续, 或按 $(_red Ctrl + C) 取消."
119 | read -rs -d $'\n'
120 | echo
121 | }
122 |
123 | get_uuid() {
124 | tmp_uuid=$(cat /proc/sys/kernel/random/uuid)
125 | }
126 |
127 | get_ip() {
128 | [[ $ip || $is_no_auto_tls || $is_gen || $is_dont_get_ip ]] && return
129 | export "$(_wget -4 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null
130 | [[ ! $ip ]] && export "$(_wget -6 -qO- https://one.one.one.one/cdn-cgi/trace | grep ip=)" &>/dev/null
131 | [[ ! $ip ]] && {
132 | err "获取服务器 IP 失败.."
133 | }
134 | }
135 |
136 | get_port() {
137 | is_count=0
138 | while :; do
139 | ((is_count++))
140 | if [[ $is_count -ge 233 ]]; then
141 | err "自动获取可用端口失败次数达到 233 次, 请检查端口占用情况."
142 | fi
143 | tmp_port=$(shuf -i 445-65535 -n 1)
144 | [[ ! $(is_test port_used $tmp_port) && $tmp_port != $port ]] && break
145 | done
146 | }
147 |
148 | get_pbk() {
149 | is_tmp_pbk=($($is_core_bin x25519 | sed 's/.*://'))
150 | is_private_key=${is_tmp_pbk[0]}
151 | is_public_key=${is_tmp_pbk[1]}
152 | }
153 |
154 | show_list() {
155 | PS3=''
156 | COLUMNS=1
157 | select i in "$@"; do echo; done &
158 | wait
159 | # i=0
160 | # for v in "$@"; do
161 | # ((i++))
162 | # echo "$i) $v"
163 | # done
164 | # echo
165 |
166 | }
167 |
168 | is_test() {
169 | case $1 in
170 | number)
171 | echo $2 | egrep '^[1-9][0-9]?+$'
172 | ;;
173 | port)
174 | if [[ $(is_test number $2) ]]; then
175 | [[ $2 -le 65535 ]] && echo ok
176 | fi
177 | ;;
178 | port_used)
179 | [[ $(is_port_used $2) && ! $is_cant_test_port ]] && echo ok
180 | ;;
181 | domain)
182 | echo $2 | egrep -i '^\w(\w|\-|\.)?+\.\w+$'
183 | ;;
184 | path)
185 | echo $2 | egrep -i '^\/\w(\w|\-|\/)?+\w$'
186 | ;;
187 | uuid)
188 | echo $2 | egrep -i '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
189 | ;;
190 | esac
191 |
192 | }
193 |
194 | is_port_used() {
195 | if [[ $(type -P netstat) ]]; then
196 | [[ ! $is_used_port ]] && is_used_port="$(netstat -tunlp | sed -n 's/.*:\([0-9]\+\).*/\1/p' | sort -nu)"
197 | echo $is_used_port | sed 's/ /\n/g' | grep ^${1}$
198 | return
199 | fi
200 | if [[ $(type -P ss) ]]; then
201 | [[ ! $is_used_port ]] && is_used_port="$(ss -tunlp | sed -n 's/.*:\([0-9]\+\).*/\1/p' | sort -nu)"
202 | echo $is_used_port | sed 's/ /\n/g' | grep ^${1}$
203 | return
204 | fi
205 | is_cant_test_port=1
206 | msg "$is_warn 无法检测端口是否可用."
207 | msg "请执行: $(_yellow "${cmd} update -y; ${cmd} install net-tools -y") 来修复此问题."
208 | }
209 |
210 | # ask input a string or pick a option for list.
211 | ask() {
212 | case $1 in
213 | set_ss_method)
214 | is_tmp_list=(${ss_method_list[@]})
215 | is_default_arg=$is_random_ss_method
216 | is_opt_msg="\n请选择加密方式:\n"
217 | is_opt_input_msg="(默认\e[92m $is_default_arg\e[0m):"
218 | is_ask_set=ss_method
219 | ;;
220 | set_header_type)
221 | is_tmp_list=(${header_type_list[@]})
222 | is_default_arg=$is_random_header_type
223 | [[ $(grep -i tcp <<<"$is_new_protocol-$net") ]] && {
224 | is_tmp_list=(none http)
225 | is_default_arg=none
226 | }
227 | is_opt_msg="\n请选择伪装类型:\n"
228 | is_opt_input_msg="(默认\e[92m $is_default_arg\e[0m):"
229 | is_ask_set=header_type
230 | [[ $is_use_header_type ]] && return
231 | ;;
232 | set_protocol)
233 | is_tmp_list=(${protocol_list[@]})
234 | [[ $is_no_auto_tls ]] && {
235 | unset is_tmp_list
236 | for v in ${protocol_list[@]}; do
237 | [[ $(grep -i tls$ <<<$v) ]] && is_tmp_list=(${is_tmp_list[@]} $v)
238 | done
239 | }
240 | is_opt_msg="\n请选择协议:\n"
241 | is_ask_set=is_new_protocol
242 | ;;
243 | set_change_list)
244 | is_tmp_list=()
245 | for v in ${is_can_change[@]}; do
246 | is_tmp_list+=("${change_list[$v]}")
247 | done
248 | is_opt_msg="\n请选择更改:\n"
249 | is_ask_set=is_change_str
250 | is_opt_input_msg=$3
251 | ;;
252 | string)
253 | is_ask_set=$2
254 | is_opt_input_msg=$3
255 | ;;
256 | list)
257 | is_ask_set=$2
258 | [[ ! $is_tmp_list ]] && is_tmp_list=($3)
259 | is_opt_msg=$4
260 | is_opt_input_msg=$5
261 | ;;
262 | get_config_file)
263 | is_tmp_list=("${is_all_json[@]}")
264 | is_opt_msg="\n请选择配置:\n"
265 | is_ask_set=is_config_file
266 | ;;
267 | mainmenu)
268 | is_tmp_list=("${mainmenu[@]}")
269 | is_ask_set=is_main_pick
270 | is_emtpy_exit=1
271 | ;;
272 | esac
273 | msg $is_opt_msg
274 | [[ ! $is_opt_input_msg ]] && is_opt_input_msg="请选择 [\e[91m1-${#is_tmp_list[@]}\e[0m]:"
275 | [[ $is_tmp_list ]] && show_list "${is_tmp_list[@]}"
276 | while :; do
277 | echo -ne $is_opt_input_msg
278 | read REPLY
279 | [[ ! $REPLY && $is_emtpy_exit ]] && exit
280 | [[ ! $REPLY && $is_default_arg ]] && export $is_ask_set=$is_default_arg && break
281 | [[ "$REPLY" == "${is_str}2${is_get}3${is_opt}3" && $is_ask_set == 'is_main_pick' ]] && {
282 | msg "\n${is_get}2${is_str}3${is_msg}3b${is_tmp}o${is_opt}y\n" && exit
283 | }
284 | if [[ ! $is_tmp_list ]]; then
285 | [[ $(grep port <<<$is_ask_set) ]] && {
286 | [[ ! $(is_test port "$REPLY") ]] && {
287 | msg "$is_err 请输入正确的端口, 可选(1-65535)"
288 | continue
289 | }
290 | if [[ $(is_test port_used $REPLY) && $is_ask_set != 'door_port' ]]; then
291 | msg "$is_err 无法使用 ($REPLY) 端口."
292 | continue
293 | fi
294 | }
295 | [[ $(grep path <<<$is_ask_set) && ! $(is_test path "$REPLY") ]] && {
296 | [[ ! $tmp_uuid ]] && get_uuid
297 | msg "$is_err 请输入正确的路径, 例如: /$tmp_uuid"
298 | continue
299 | }
300 | [[ $(grep uuid <<<$is_ask_set) && ! $(is_test uuid "$REPLY") ]] && {
301 | [[ ! $tmp_uuid ]] && get_uuid
302 | msg "$is_err 请输入正确的 UUID, 例如: $tmp_uuid"
303 | continue
304 | }
305 | [[ $(grep ^y$ <<<$is_ask_set) ]] && {
306 | [[ $(grep -i ^y$ <<<"$REPLY") ]] && break
307 | msg "请输入 (y)"
308 | continue
309 | }
310 | [[ $REPLY ]] && export $is_ask_set=$REPLY && msg "使用: ${!is_ask_set}" && break
311 | else
312 | [[ $(is_test number "$REPLY") ]] && is_ask_result=${is_tmp_list[$REPLY - 1]}
313 | [[ $is_ask_result ]] && export $is_ask_set="$is_ask_result" && msg "选择: ${!is_ask_set}" && break
314 | fi
315 |
316 | msg "输入${is_err}"
317 | done
318 | unset is_opt_msg is_opt_input_msg is_tmp_list is_ask_result is_default_arg is_emtpy_exit
319 | }
320 |
321 | # create file
322 | create() {
323 | case $1 in
324 | server)
325 | get new
326 |
327 | # file name
328 | if [[ $host ]]; then
329 | is_config_name=$2-${host}.json
330 | else
331 | is_config_name=$2-${port}.json
332 | fi
333 | is_json_file=$is_conf_dir/$is_config_name
334 | # get json
335 | [[ $is_change || ! $json_str ]] && get protocol $2
336 | is_listen='listen:"0.0.0.0"'
337 | [[ $host ]] && is_listen=${is_listen/0.0.0.0/127.0.0.1}
338 | is_sniffing='sniffing:{enabled:true,destOverride:["http","tls"]}'
339 | is_new_json=$(jq '{inbounds:[{tag:"'$is_config_name'",port:'"$port"','"$is_listen"',protocol:"'$is_protocol'",'"$json_str"','"$is_sniffing"'}]}' <<<{})
340 | if [[ $is_dynamic_port ]]; then
341 | [[ ! $is_dynamic_port_range ]] && get dynamic-port
342 | is_new_dynamic_port_json=$(jq '{inbounds:[{tag:"'$is_config_name-link.json'",port:"'$is_dynamic_port_range'",'"$is_listen"',protocol:"vmess",'"$is_stream"','"$is_sniffing"',allocate:{strategy:"random"}}]}' <<<{})
343 | fi
344 | [[ $is_test_json ]] && return # tmp test
345 | # only show json, dont save to file.
346 | [[ $is_gen ]] && {
347 | msg
348 | jq <<<$is_new_json
349 | msg
350 | [[ $is_new_dynamic_port_json ]] && jq <<<$is_new_dynamic_port_json && msg
351 | return
352 | }
353 | # del old file
354 | [[ $is_config_file ]] && is_no_del_msg=1 && del $is_config_file
355 | # save json to file
356 | cat <<<$is_new_json >$is_json_file
357 | [[ $is_new_dynamic_port_json ]] && {
358 | is_dynamic_port_link_file=$is_json_file-link.json
359 | cat <<<$is_new_dynamic_port_json >$is_dynamic_port_link_file
360 | }
361 | if [[ $is_new_install ]]; then
362 | # config.json
363 | create config.json
364 | else
365 | # use api add config
366 | api add $is_json_file $is_dynamic_port_link_file &>/dev/null
367 | fi
368 | # caddy auto tls
369 | [[ $is_caddy && $host && ! $is_no_auto_tls ]] && {
370 | create caddy $net
371 | }
372 | # restart core
373 | [[ $is_api_fail ]] && manage restart &
374 | ;;
375 | client)
376 | is_tls=tls
377 | is_client=1
378 | get info $2
379 | [[ ! $is_client_id_json ]] && err "($is_config_name) 不支持生成客户端配置."
380 | [[ $host ]] && is_stream="${is_stream/network:\"$net\"/network:\"$net\",security:\"tls\"}"
381 | is_new_json=$(jq '{outbounds:[{tag:"'$is_config_name'",protocol:"'$is_protocol'",'"$is_client_id_json"','"$is_stream"'}]}' <<<{})
382 | if [[ $is_full_client ]]; then
383 | is_dns='dns:{servers:[{address:"223.5.5.5",domain:["geosite:cn","geosite:geolocation-cn"],expectIPs:["geoip:cn"]},"1.1.1.1","8.8.8.8"]}'
384 | is_route='routing:{rules:[{type:"field",outboundTag:"direct",ip:["geoip:cn","geoip:private"]},{type:"field",outboundTag:"direct",domain:["geosite:cn","geosite:geolocation-cn"]}]}'
385 | is_inbounds='inbounds:[{port:2333,listen:"127.0.0.1",protocol:"socks",settings:{udp:true},sniffing:{enabled:true,destOverride:["http","tls"]}}]'
386 | is_outbounds='outbounds:[{tag:"'$is_config_name'",protocol:"'$is_protocol'",'"$is_client_id_json"','"$is_stream"'},{tag:"direct",protocol:"freedom"}]'
387 | is_new_json=$(jq '{'$is_dns,$is_route,$is_inbounds,$is_outbounds'}' <<<{})
388 | fi
389 | msg
390 | jq <<<$is_new_json
391 | msg
392 | ;;
393 | caddy)
394 | load caddy.sh
395 | [[ $is_install_caddy ]] && caddy_config new
396 | [[ ! $(grep "$is_caddy_conf" $is_caddyfile) ]] && {
397 | msg "import $is_caddy_conf/*.conf" >>$is_caddyfile
398 | }
399 | [[ ! -d $is_caddy_conf ]] && mkdir -p $is_caddy_conf
400 | caddy_config $2
401 | manage restart caddy &
402 | ;;
403 | config.json)
404 | get_port
405 | is_log='log:{access:"/var/log/'"$is_core"'/access.log",error:"/var/log/'"$is_core"'/error.log",loglevel:"warning"}'
406 | is_dns='dns:{}'
407 | is_api='api:{tag:"api",services:["HandlerService","LoggerService","StatsService"]}'
408 | is_stats='stats:{}'
409 | is_policy_system='system:{statsInboundUplink:true,statsInboundDownlink:true,statsOutboundUplink:true,statsOutboundDownlink:true}'
410 | is_policy='policy:{levels:{"0":{handshake:'"$((${tmp_port:0:1} + 1))"',connIdle:'"${tmp_port:0:3}"',uplinkOnly:'"$((${tmp_port:2:1} + 1))"',downlinkOnly:'"$((${tmp_port:3:1} + 3))"',statsUserUplink:true,statsUserDownlink:true}},'"$is_policy_system"'}'
411 | is_ban_ad='{type:"field",domain:["geosite:category-ads-all"],marktag:"ban_ad",outboundTag:"block"}'
412 | is_ban_bt='{type:"field",protocol:["bittorrent"],marktag:"ban_bt",outboundTag:"block"}'
413 | is_ban_cn='{type:"field",ip:["geoip:cn"],marktag:"ban_geoip_cn",outboundTag:"block"}'
414 | is_openai='{type:"field",domain:["geosite:openai"],marktag:"fix_openai",outboundTag:"direct"}'
415 | is_routing='routing:{domainStrategy:"IPIfNonMatch",rules:[{type:"field",inboundTag:["api"],outboundTag:"api"},'"$is_ban_bt"','"$is_ban_cn"','"$is_openai"',{type:"field",ip:["geoip:private"],outboundTag:"block"}]}'
416 | is_inbounds='inbounds:[{tag:"api",port:'"$tmp_port"',listen:"127.0.0.1",protocol:"dokodemo-door",settings:{address:"127.0.0.1"}}]'
417 | is_outbounds='outbounds:[{tag:"direct",protocol:"freedom"},{tag:"block",protocol:"blackhole"}]'
418 | is_server_config_json=$(jq '{'"$is_log"','"$is_dns"','"$is_api"','"$is_stats"','"$is_policy"','"$is_routing"','"$is_inbounds"','"$is_outbounds"'}' <<<{})
419 | cat <<<$is_server_config_json >$is_config_json
420 | manage restart &
421 | ;;
422 | esac
423 | }
424 |
425 | # change config file
426 | change() {
427 | is_change=1
428 | is_dont_show_info=1
429 | if [[ $2 ]]; then
430 | case ${2,,} in
431 | full)
432 | is_change_id=full
433 | ;;
434 | new)
435 | is_change_id=0
436 | ;;
437 | port)
438 | is_change_id=1
439 | ;;
440 | host)
441 | is_change_id=2
442 | ;;
443 | path)
444 | is_change_id=3
445 | ;;
446 | pass | passwd | password)
447 | is_change_id=4
448 | ;;
449 | id | uuid)
450 | is_change_id=5
451 | ;;
452 | ssm | method | ss-method | ss_method)
453 | is_change_id=6
454 | ;;
455 | type | header | header-type | header_type)
456 | is_change_id=7
457 | ;;
458 | dda | door-addr | door_addr)
459 | is_change_id=8
460 | ;;
461 | ddp | door-port | door_port)
462 | is_change_id=9
463 | ;;
464 | key | publickey | privatekey)
465 | is_change_id=10
466 | ;;
467 | sni | servername | servernames)
468 | is_change_id=11
469 | ;;
470 | dp | dyp | dynamic | dynamicport | dynamic-port)
471 | is_change_id=12
472 | ;;
473 | web | proxy-site)
474 | is_change_id=13
475 | ;;
476 | seed | kcpseed | kcp-seed | kcp_seed)
477 | is_change_id=14
478 | ;;
479 | *)
480 | [[ $is_try_change ]] && return
481 | err "无法识别 ($2) 更改类型."
482 | ;;
483 | esac
484 | fi
485 | [[ $is_try_change ]] && return
486 | [[ $is_dont_auto_exit ]] && {
487 | get info $1
488 | } || {
489 | [[ $is_change_id ]] && {
490 | is_change_msg=${change_list[$is_change_id]}
491 | [[ $is_change_id == 'full' ]] && {
492 | [[ $3 ]] && is_change_msg="更改多个参数" || is_change_msg=
493 | }
494 | [[ $is_change_msg ]] && _green "\n快速执行: $is_change_msg"
495 | }
496 | info $1
497 | [[ $is_auto_get_config ]] && msg "\n自动选择: $is_config_file"
498 | }
499 | is_old_net=$net
500 | [[ $host ]] && net=$is_protocol-$net-tls
501 | [[ $is_reality ]] && net=reality
502 | [[ $is_dynamic_port ]] && net=${net}d
503 | [[ $3 == 'auto' ]] && is_auto=1
504 | # if is_dont_show_info exist, cant show info.
505 | is_dont_show_info=
506 | # if not prefer args, show change list and then get change id.
507 | [[ ! $is_change_id ]] && {
508 | ask set_change_list
509 | is_change_id=${is_can_change[$REPLY - 1]}
510 | }
511 | case $is_change_id in
512 | full)
513 | add $net ${@:3}
514 | ;;
515 | 0)
516 | # new protocol
517 | is_set_new_protocol=1
518 | add ${@:3}
519 | ;;
520 | 1)
521 | # new port
522 | is_new_port=$3
523 | [[ $host && ! $is_caddy ]] && err "($is_config_file) 不支持更改端口, 因为没啥意义."
524 | if [[ $is_new_port && ! $is_auto ]]; then
525 | [[ ! $(is_test port $is_new_port) ]] && err "请输入正确的端口, 可选(1-65535)"
526 | [[ $is_new_port != 443 && $(is_test port_used $is_new_port) ]] && err "无法使用 ($is_new_port) 端口"
527 | fi
528 | [[ $is_auto ]] && get_port && is_new_port=$tmp_port
529 | [[ ! $is_new_port ]] && ask string is_new_port "请输入新端口:"
530 | if [[ $is_caddy && $host ]]; then
531 | net=$is_old_net
532 | is_https_port=$is_new_port
533 | load caddy.sh
534 | caddy_config $net
535 | manage restart caddy &
536 | info
537 | else
538 | add $net $is_new_port
539 | fi
540 | ;;
541 | 2)
542 | # new host
543 | is_new_host=$3
544 | [[ ! $host ]] && err "($is_config_file) 不支持更改域名."
545 | [[ ! $is_new_host ]] && ask string is_new_host "请输入新域名:"
546 | old_host=$host # del old host
547 | add $net $is_new_host
548 | ;;
549 | 3)
550 | # new path
551 | is_new_path=$3
552 | [[ ! $path ]] && err "($is_config_file) 不支持更改路径."
553 | [[ $is_auto ]] && get_uuid && is_new_path=/$tmp_uuid
554 | [[ ! $is_new_path ]] && ask string is_new_path "请输入新路径:"
555 | add $net auto auto $is_new_path
556 | ;;
557 | 4)
558 | # new password
559 | is_new_pass=$3
560 | if [[ $net == 'ss' || $is_trojan || $is_socks_pass ]]; then
561 | [[ $is_auto ]] && get_uuid && is_new_pass=$tmp_uuid
562 | else
563 | err "($is_config_file) 不支持更改密码."
564 | fi
565 | [[ ! $is_new_pass ]] && ask string is_new_pass "请输入新密码:"
566 | trojan_password=$is_new_pass
567 | ss_password=$is_new_pass
568 | is_socks_pass=$is_new_pass
569 | add $net
570 | ;;
571 | 5)
572 | # new uuid
573 | is_new_uuid=$3
574 | [[ ! $uuid ]] && err "($is_config_file) 不支持更改 UUID."
575 | [[ $is_auto ]] && get_uuid && is_new_uuid=$tmp_uuid
576 | [[ ! $is_new_uuid ]] && ask string is_new_uuid "请输入新 UUID:"
577 | add $net auto $is_new_uuid
578 | ;;
579 | 6)
580 | # new method
581 | is_new_method=$3
582 | [[ $net != 'ss' ]] && err "($is_config_file) 不支持更改加密方式."
583 | [[ $is_auto ]] && is_new_method=$is_random_ss_method
584 | [[ ! $is_new_method ]] && {
585 | ask set_ss_method
586 | is_new_method=$ss_method
587 | }
588 | add $net auto auto $is_new_method
589 | ;;
590 | 7)
591 | # new header type
592 | is_new_header_type=$3
593 | [[ ! $header_type ]] && err "($is_config_file) 不支持更改伪装类型."
594 | [[ $is_auto ]] && {
595 | is_new_header_type=$is_random_header_type
596 | if [[ $net == 'tcp' ]]; then
597 | is_tmp_header_type=(none http)
598 | is_new_header_type=${is_tmp_header_type[$(shuf -i 0-1 -n1)]}
599 | fi
600 | }
601 | [[ ! $is_new_header_type ]] && {
602 | ask set_header_type
603 | is_new_header_type=$header_type
604 | }
605 | add $net auto auto $is_new_header_type
606 | ;;
607 | 8)
608 | # new remote addr
609 | is_new_door_addr=$3
610 | [[ $net != 'door' ]] && err "($is_config_file) 不支持更改目标地址."
611 | [[ ! $is_new_door_addr ]] && ask string is_new_door_addr "请输入新的目标地址:"
612 | door_addr=$is_new_door_addr
613 | add $net
614 | ;;
615 | 9)
616 | # new remote port
617 | is_new_door_port=$3
618 | [[ $net != 'door' ]] && err "($is_config_file) 不支持更改目标端口."
619 | [[ ! $is_new_door_port ]] && {
620 | ask string door_port "请输入新的目标端口:"
621 | is_new_door_port=$door_port
622 | }
623 | add $net auto auto $is_new_door_port
624 | ;;
625 | 10)
626 | # new is_private_key is_public_key
627 | is_new_private_key=$3
628 | is_new_public_key=$4
629 | [[ ! $is_reality ]] && err "($is_config_file) 不支持更改密钥."
630 | if [[ $is_auto ]]; then
631 | get_pbk
632 | add $net
633 | else
634 | [[ $is_new_private_key && ! $is_new_public_key ]] && {
635 | err "无法找到 Public key."
636 | }
637 | [[ ! $is_new_private_key ]] && ask string is_new_private_key "请输入新 Private key:"
638 | [[ ! $is_new_public_key ]] && ask string is_new_public_key "请输入新 Public key:"
639 | if [[ $is_new_private_key == $is_new_public_key ]]; then
640 | err "Private key 和 Public key 不能一样."
641 | fi
642 | is_private_key=$is_new_private_key
643 | is_test_json=1
644 | # create server $is_protocol-$net | $is_core_bin -test &>/dev/null
645 | create server $is_protocol-$net
646 | $is_core_bin -test <<<"$is_new_json" &>/dev/null
647 | if [[ $? != 0 ]]; then
648 | err "Private key 无法通过测试."
649 | fi
650 | is_private_key=$is_new_public_key
651 | # create server $is_protocol-$net | $is_core_bin -test &>/dev/null
652 | create server $is_protocol-$net
653 | $is_core_bin -test <<<"$is_new_json" &>/dev/null
654 | if [[ $? != 0 ]]; then
655 | err "Public key 无法通过测试."
656 | fi
657 | is_private_key=$is_new_private_key
658 | is_public_key=$is_new_public_key
659 | is_test_json=
660 | add $net
661 | fi
662 | ;;
663 | 11)
664 | # new serverName
665 | is_new_servername=$3
666 | [[ ! $is_reality ]] && err "($is_config_file) 不支持更改 serverName."
667 | [[ $is_auto ]] && is_new_servername=$is_random_servername
668 | [[ ! $is_new_servername ]] && ask string is_new_servername "请输入新的 serverName:"
669 | is_servername=$is_new_servername
670 | [[ $(grep -i "^233boy.com$" <<<$is_servername) ]] && {
671 | err "你干嘛~哎呦~"
672 | }
673 | add $net
674 | ;;
675 | 12)
676 | # new dynamic-port
677 | is_new_dynamic_port_start=$3
678 | is_new_dynamic_port_end=$4
679 | [[ ! $is_dynamic_port ]] && err "($is_config_file) 不支持更改动态端口."
680 | if [[ $is_auto ]]; then
681 | get dynamic-port
682 | add $net
683 | else
684 | [[ $is_new_dynamic_port_start && ! $is_new_dynamic_port_end ]] && {
685 | err "无法找到动态结束端口."
686 | }
687 | [[ ! $is_new_dynamic_port_start ]] && ask string is_new_dynamic_port_start "请输入新的动态开始端口:"
688 | [[ ! $is_new_dynamic_port_end ]] && ask string is_new_dynamic_port_end "请输入新的动态结束端口:"
689 | add $net auto auto auto $is_new_dynamic_port_start $is_new_dynamic_port_end
690 | fi
691 | ;;
692 | 13)
693 | # new proxy site
694 | is_new_proxy_site=$3
695 | [[ ! $is_caddy && ! $host ]] && {
696 | err "($is_config_file) 不支持更改伪装网站."
697 | }
698 | [[ ! -f $is_caddy_conf/${host}.conf.add ]] && err "无法配置伪装网站."
699 | [[ ! $is_new_proxy_site ]] && ask string is_new_proxy_site "请输入新的伪装网站 (例如 example.com):"
700 | proxy_site=$(sed 's#^.*//##;s#/$##' <<<$is_new_proxy_site)
701 | [[ $(grep -i "^233boy.com$" <<<$proxy_site) ]] && {
702 | err "你干嘛~哎呦~"
703 | } || {
704 | load caddy.sh
705 | caddy_config proxy
706 | manage restart caddy &
707 | }
708 | msg "\n已更新伪装网站为: $(_green $proxy_site) \n"
709 | ;;
710 | 14)
711 | # new kcp seed
712 | is_new_kcp_seed=$3
713 | [[ ! $kcp_seed ]] && err "($is_config_file) 不支持更改 mKCP seed."
714 | [[ $is_auto ]] && get_uuid && is_new_kcp_seed=$tmp_uuid
715 | [[ ! $is_new_kcp_seed ]] && ask string is_new_kcp_seed "请输入新 mKCP seed:"
716 | kcp_seed=$is_new_kcp_seed
717 | add $net
718 | ;;
719 | 15)
720 | # new socks user
721 | [[ ! $is_socks_user ]] && err "($is_config_file) 不支持更改用户名 (Username)."
722 | ask string is_socks_user "请输入新用户名 (Username):"
723 | add $net
724 | ;;
725 | esac
726 | }
727 |
728 | # delete config.
729 | del() {
730 | # dont get ip
731 | is_dont_get_ip=1
732 | [[ $is_conf_dir_empty ]] && return # not found any json file.
733 | # get a config file
734 | [[ ! $is_config_file ]] && get info $1
735 | if [[ $is_config_file ]]; then
736 | if [[ $is_main_start && ! $is_no_del_msg ]]; then
737 | msg "\n是否删除配置文件?: $is_config_file"
738 | pause
739 | fi
740 | api del $is_conf_dir/"$is_config_file" $is_dynamic_port_file &>/dev/null
741 | rm -rf $is_conf_dir/"$is_config_file" $is_dynamic_port_file
742 | [[ $is_api_fail && ! $is_new_json ]] && manage restart &
743 | [[ ! $is_no_del_msg ]] && _green "\n已删除: $is_config_file\n"
744 |
745 | [[ $is_caddy ]] && {
746 | is_del_host=$host
747 | [[ $is_change ]] && {
748 | [[ ! $old_host ]] && return # no host exist or not set new host;
749 | is_del_host=$old_host
750 | }
751 | [[ $is_del_host && $host != $old_host ]] && {
752 | rm -rf $is_caddy_conf/$is_del_host.conf $is_caddy_conf/$is_del_host.conf.add
753 | [[ ! $is_new_json ]] && manage restart caddy &
754 | }
755 | }
756 | fi
757 | if [[ ! $(ls $is_conf_dir | grep .json) && ! $is_change ]]; then
758 | warn "当前配置目录为空! 因为你刚刚删除了最后一个配置文件."
759 | is_conf_dir_empty=1
760 | fi
761 | unset is_dont_get_ip
762 | [[ $is_dont_auto_exit ]] && unset is_config_file
763 | }
764 |
765 | # uninstall
766 | uninstall() {
767 | if [[ $is_caddy ]]; then
768 | is_tmp_list=("卸载 $is_core_name" "卸载 ${is_core_name} & Caddy")
769 | ask list is_do_uninstall
770 | else
771 | ask string y "是否卸载 ${is_core_name}? [y]:"
772 | fi
773 | manage stop &>/dev/null
774 | manage disable &>/dev/null
775 | rm -rf $is_core_dir $is_log_dir $is_sh_bin /lib/systemd/system/$is_core.service
776 | sed -i "/alias $is_core=/d" /root/.bashrc
777 | # uninstall caddy; 2 is ask result
778 | if [[ $REPLY == '2' ]]; then
779 | manage stop caddy &>/dev/null
780 | manage disable caddy &>/dev/null
781 | rm -rf $is_caddy_dir $is_caddy_bin /lib/systemd/system/caddy.service
782 | fi
783 | [[ $is_install_sh ]] && return # reinstall
784 | _green "\n卸载完成!"
785 | msg "脚本哪里需要完善? 请反馈"
786 | msg "反馈问题) $(msg_ul https://github.com/${is_sh_repo}/issues)\n"
787 | }
788 |
789 | # manage run status
790 | manage() {
791 | [[ $is_dont_auto_exit ]] && return
792 | case $1 in
793 | 1 | start)
794 | is_do=start
795 | is_do_msg=启动
796 | is_test_run=1
797 | ;;
798 | 2 | stop)
799 | is_do=stop
800 | is_do_msg=停止
801 | ;;
802 | 3 | r | restart)
803 | is_do=restart
804 | is_do_msg=重启
805 | is_test_run=1
806 | ;;
807 | *)
808 | is_do=$1
809 | is_do_msg=$1
810 | ;;
811 | esac
812 | case $2 in
813 | caddy)
814 | is_do_name=$2
815 | is_run_bin=$is_caddy_bin
816 | is_do_name_msg=Caddy
817 | ;;
818 | *)
819 | is_do_name=$is_core
820 | is_run_bin=$is_core_bin
821 | is_do_name_msg=$is_core_name
822 | ;;
823 | esac
824 | systemctl $is_do $is_do_name
825 | [[ $is_test_run && ! $is_new_install ]] && {
826 | sleep 2
827 | if [[ ! $(pgrep -f $is_run_bin) ]]; then
828 | is_run_fail=${is_do_name_msg,,}
829 | [[ ! $is_no_manage_msg ]] && {
830 | msg
831 | warn "($is_do_msg) $is_do_name_msg 失败"
832 | _yellow "检测到运行失败, 自动执行测试运行."
833 | get test-run
834 | _yellow "测试结束, 请按 Enter 退出."
835 | }
836 | fi
837 | }
838 | }
839 |
840 | # use api add or del inbounds
841 | api() {
842 | [[ ! $1 ]] && err "无法识别 API 的参数."
843 | [[ $is_core_stop ]] && {
844 | warn "$is_core_name 当前处于停止状态."
845 | is_api_fail=1
846 | return
847 | }
848 | case $1 in
849 | add)
850 | is_api_do=adi
851 | ;;
852 | del)
853 | is_api_do=rmi
854 | ;;
855 | s)
856 | is_api_do=stats
857 | ;;
858 | t | sq)
859 | is_api_do=statsquery
860 | ;;
861 | esac
862 | [[ ! $is_api_do ]] && is_api_do=$1
863 | [[ ! $is_api_port ]] && {
864 | is_api_port=$(jq '.inbounds[] | select(.tag == "api") | .port' $is_config_json)
865 | [[ $? != 0 ]] && {
866 | warn "读取 API 端口失败, 无法使用 API 操作."
867 | return
868 | }
869 | }
870 | $is_core_bin api $is_api_do --server=127.0.0.1:$is_api_port ${@:2}
871 | [[ $? != 0 ]] && {
872 | is_api_fail=1
873 | }
874 | }
875 |
876 | # add a config
877 | add() {
878 | is_lower=${1,,}
879 | if [[ $is_lower ]]; then
880 | case $is_lower in
881 | # tcp | kcp | quic | tcpd | kcpd | quicd)
882 | tcp | kcp | tcpd | kcpd)
883 | is_new_protocol=VMess-$(sed 's/^K/mK/;s/D$/-dynamic-port/' <<<${is_lower^^})
884 | ;;
885 | # ws | h2 | grpc | vws | vh2 | vgrpc | tws | th2 | tgrpc)
886 | ws | grpc | vws | vgrpc | tws | tgrpc)
887 | is_new_protocol=$(sed -E "s/^V/VLESS-/;s/^T/Trojan-/;/^(W|H|G)/{s/^/VMess-/};s/G/g/" <<<${is_lower^^})-TLS
888 | ;;
889 | xhttp)
890 | is_new_protocol=VLESS-XHTTP-TLS
891 | ;;
892 | r | reality)
893 | is_new_protocol=VLESS-REALITY
894 | ;;
895 | ss)
896 | is_new_protocol=Shadowsocks
897 | ;;
898 | door)
899 | is_new_protocol=Dokodemo-Door
900 | ;;
901 | socks)
902 | is_new_protocol=Socks
903 | ;;
904 | # http)
905 | # is_new_protocol=local-$is_lower
906 | # ;;
907 | *)
908 | for v in ${protocol_list[@]}; do
909 | [[ $(egrep -i "^$is_lower$" <<<$v) ]] && is_new_protocol=$v && break
910 | done
911 |
912 | [[ ! $is_new_protocol ]] && err "无法识别 ($1), 请使用: $is_core add [protocol] [args... | auto]"
913 | ;;
914 | esac
915 | fi
916 |
917 | # no prefer protocol
918 | [[ ! $is_new_protocol ]] && ask set_protocol
919 |
920 | case ${is_new_protocol,,} in
921 | *-tls)
922 | is_use_tls=1
923 | is_use_host=$2
924 | is_use_uuid=$3
925 | is_use_path=$4
926 | is_add_opts="[host] [uuid] [/path]"
927 | ;;
928 | vmess*)
929 | is_use_port=$2
930 | is_use_uuid=$3
931 | is_use_header_type=$4
932 | is_use_dynamic_port_start=$5
933 | is_use_dynamic_port_end=$6
934 | [[ $(grep dynamic-port <<<$is_new_protocol) ]] && is_dynamic_port=1
935 | if [[ $is_dynamic_port ]]; then
936 | is_add_opts="[port] [uuid] [type] [start_port] [end_port]"
937 | else
938 | is_add_opts="[port] [uuid] [type]"
939 | fi
940 | ;;
941 | *reality*)
942 | is_reality=1
943 | is_use_port=$2
944 | is_use_uuid=$3
945 | is_use_servername=$4
946 | is_add_opts="[port] [uuid] [sni]"
947 | ;;
948 | shadowsocks)
949 | is_use_port=$2
950 | is_use_pass=$3
951 | is_use_method=$4
952 | is_add_opts="[port] [password] [method]"
953 | ;;
954 | *door)
955 | is_use_port=$2
956 | is_use_door_addr=$3
957 | is_use_door_port=$4
958 | is_add_opts="[port] [remote_addr] [remote_port]"
959 | ;;
960 | socks)
961 | is_socks=1
962 | is_use_port=$2
963 | is_use_socks_user=$3
964 | is_use_socks_pass=$4
965 | is_add_opts="[port] [username] [password]"
966 | ;;
967 | *http)
968 | is_use_port=$2
969 | is_add_opts="[port]"
970 | ;;
971 | esac
972 |
973 | [[ $1 && ! $is_change ]] && {
974 | msg "\n使用协议: $is_new_protocol"
975 | # err msg tips
976 | is_err_tips="\n\n请使用: $(_green $is_core add $1 $is_add_opts) 来添加 $is_new_protocol 配置"
977 | }
978 |
979 | # remove old protocol args
980 | if [[ $is_set_new_protocol ]]; then
981 | case $is_old_net in
982 | tcp)
983 | unset header_type net
984 | ;;
985 | kcp | quic)
986 | kcp_seed=
987 | [[ $(grep -i tcp <<<$is_new_protocol) ]] && header_type=
988 | ;;
989 | h2 | ws | grpc | xhttp)
990 | old_host=$host
991 | if [[ ! $is_use_tls ]]; then
992 | host=
993 | else
994 | [[ $is_old_net == 'grpc' ]] && {
995 | path=/$path
996 | }
997 | fi
998 | [[ ! $(grep -i trojan <<<$is_new_protocol) ]] && is_trojan=
999 | ;;
1000 | ss)
1001 | [[ $(is_test uuid $ss_password) ]] && uuid=$ss_password
1002 | ;;
1003 | esac
1004 | [[ $is_dynamic_port && ! $(grep dynamic-port <<<$is_new_protocol) ]] && {
1005 | is_dynamic_port=
1006 | }
1007 |
1008 | [[ ! $(is_test uuid $uuid) ]] && uuid=
1009 | [[ ! $(grep -i reality <<<$is_new_protocol) ]] && is_reality=
1010 | fi
1011 |
1012 | # no-auto-tls only use h2,ws,grpc
1013 | if [[ $is_no_auto_tls && ! $is_use_tls ]]; then
1014 | err "$is_new_protocol 不支持手动配置 tls."
1015 | fi
1016 |
1017 | # prefer args.
1018 | if [[ $2 ]]; then
1019 | for v in is_use_port is_use_uuid is_use_header_type is_use_host is_use_path is_use_pass is_use_method is_use_door_addr is_use_door_port is_use_dynamic_port_start is_use_dynamic_port_end; do
1020 | [[ ${!v} == 'auto' ]] && unset $v
1021 | done
1022 |
1023 | if [[ $is_use_port ]]; then
1024 | [[ ! $(is_test port ${is_use_port}) ]] && {
1025 | err "($is_use_port) 不是一个有效的端口. $is_err_tips"
1026 | }
1027 | [[ $(is_test port_used $is_use_port) ]] && {
1028 | err "无法使用 ($is_use_port) 端口. $is_err_tips"
1029 | }
1030 | port=$is_use_port
1031 | fi
1032 | if [[ $is_use_door_port ]]; then
1033 | [[ ! $(is_test port ${is_use_door_port}) ]] && {
1034 | err "(${is_use_door_port}) 不是一个有效的目标端口. $is_err_tips"
1035 | }
1036 | door_port=$is_use_door_port
1037 | fi
1038 | if [[ $is_use_uuid ]]; then
1039 | [[ ! $(is_test uuid $is_use_uuid) ]] && {
1040 | err "($is_use_uuid) 不是一个有效的 UUID. $is_err_tips"
1041 | }
1042 | uuid=$is_use_uuid
1043 | fi
1044 | if [[ $is_use_path ]]; then
1045 | [[ ! $(is_test path $is_use_path) ]] && {
1046 | err "($is_use_path) 不是有效的路径. $is_err_tips"
1047 | }
1048 | path=$is_use_path
1049 | fi
1050 | if [[ $is_use_header_type || $is_use_method ]]; then
1051 | is_tmp_use_name=加密方式
1052 | is_tmp_list=${ss_method_list[@]}
1053 | [[ ! $is_use_method ]] && {
1054 | is_tmp_use_name=伪装类型
1055 | ask set_header_type
1056 | }
1057 | for v in ${is_tmp_list[@]}; do
1058 | [[ $(egrep -i "^${is_use_header_type}${is_use_method}$" <<<$v) ]] && is_tmp_use_type=$v && break
1059 | done
1060 | [[ ! ${is_tmp_use_type} ]] && {
1061 | warn "(${is_use_header_type}${is_use_method}) 不是一个可用的${is_tmp_use_name}."
1062 | msg "${is_tmp_use_name}可用如下: "
1063 | for v in ${is_tmp_list[@]}; do
1064 | msg "\t\t$v"
1065 | done
1066 | msg "$is_err_tips\n"
1067 | exit 1
1068 | }
1069 | ss_method=$is_tmp_use_type
1070 | header_type=$is_tmp_use_type
1071 | fi
1072 | if [[ $is_dynamic_port && $is_use_dynamic_port_start ]]; then
1073 | get dynamic-port-test
1074 | fi
1075 | [[ $is_use_pass ]] && ss_password=$is_use_pass
1076 | [[ $is_use_host ]] && host=$is_use_host
1077 | [[ $is_use_door_addr ]] && door_addr=$is_use_door_addr
1078 | [[ $is_use_servername ]] && is_servername=$is_use_servername
1079 | [[ $is_use_socks_user ]] && is_socks_user=$is_use_socks_user
1080 | [[ $is_use_socks_pass ]] && is_socks_pass=$is_use_socks_pass
1081 | fi
1082 |
1083 | if [[ $is_use_tls ]]; then
1084 | if [[ ! $is_no_auto_tls && ! $is_caddy && ! $is_gen ]]; then
1085 | # test auto tls
1086 | [[ $(is_test port_used 80) || $(is_test port_used 443) ]] && {
1087 | get_port
1088 | is_http_port=$tmp_port
1089 | get_port
1090 | is_https_port=$tmp_port
1091 | warn "端口 (80 或 443) 已经被占用, 你也可以考虑使用 no-auto-tls"
1092 | msg "\e[41m no-auto-tls 帮助(help)\e[0m: $(msg_ul https://233boy.com/$is_core/no-auto-tls/)\n"
1093 | msg "\n Caddy 将使用非标准端口实现自动配置 TLS, HTTP:$is_http_port HTTPS:$is_https_port\n"
1094 | msg "请确定是否继续???"
1095 | pause
1096 | }
1097 | is_install_caddy=1
1098 | fi
1099 | # set host
1100 | [[ ! $host ]] && ask string host "请输入域名:"
1101 | # test host dns
1102 | get host-test
1103 | else
1104 | # for main menu start, dont auto create args
1105 | if [[ $is_main_start ]]; then
1106 |
1107 | # set port
1108 | [[ ! $port ]] && ask string port "请输入端口:"
1109 |
1110 | case ${is_new_protocol,,} in
1111 | *tcp* | *kcp* | *quic*)
1112 | [[ ! $header_type ]] && ask set_header_type
1113 | ;;
1114 | socks)
1115 | # set user
1116 | [[ ! $is_socks_user ]] && ask string is_socks_user "请设置用户名:"
1117 | # set password
1118 | [[ ! $is_socks_pass ]] && ask string is_socks_pass "请设置密码:"
1119 | ;;
1120 | shadowsocks)
1121 | # set method
1122 | [[ ! $ss_method ]] && ask set_ss_method
1123 | # set password
1124 | [[ ! $ss_password ]] && ask string ss_password "请设置密码:"
1125 | ;;
1126 | esac
1127 | # set dynamic port
1128 | [[ $is_dynamic_port && ! $is_dynamic_port_range ]] && {
1129 | ask string is_use_dynamic_port_start "请输入动态开始端口:"
1130 | ask string is_use_dynamic_port_end "请输入动态结束端口:"
1131 | get dynamic-port-test
1132 | }
1133 | fi
1134 | fi
1135 |
1136 | # Dokodemo-Door
1137 | if [[ $is_new_protocol == 'Dokodemo-Door' ]]; then
1138 | # set remote addr
1139 | [[ ! $door_addr ]] && ask string door_addr "请输入目标地址:"
1140 | # set remote port
1141 | [[ ! $door_port ]] && ask string door_port "请输入目标端口:"
1142 | fi
1143 |
1144 | # Shadowsocks 2022
1145 | if [[ $(grep 2022 <<<$ss_method) ]]; then
1146 | # test ss2022 password
1147 | [[ $ss_password ]] && {
1148 | is_test_json=1
1149 | # create server Shadowsocks | $is_core_bin -test &>/dev/null
1150 | create server Shadowsocks
1151 | $is_core_bin -test <<<"$is_new_json" &>/dev/null
1152 | if [[ $? != 0 ]]; then
1153 | warn "Shadowsocks 协议 ($ss_method) 不支持使用密码 ($(_red_bg $ss_password))\n\n你可以使用命令: $(_green $is_core ss2022) 生成支持的密码.\n\n脚本将自动创建可用密码:)"
1154 | ss_password=
1155 | # create new json.
1156 | json_str=
1157 | fi
1158 | is_test_json=
1159 | }
1160 |
1161 | fi
1162 |
1163 | # install caddy
1164 | if [[ $is_install_caddy ]]; then
1165 | get install-caddy
1166 | fi
1167 |
1168 | # create json
1169 | create server $is_new_protocol
1170 |
1171 | # show config info.
1172 | info
1173 | }
1174 |
1175 | # get config info
1176 | # or somes required args
1177 | get() {
1178 | case $1 in
1179 | addr)
1180 | is_addr=$host
1181 | [[ ! $is_addr ]] && {
1182 | get_ip
1183 | is_addr=$ip
1184 | [[ $(grep ":" <<<$ip) ]] && is_addr="[$ip]"
1185 | }
1186 | ;;
1187 | new)
1188 | [[ ! $host ]] && get_ip
1189 | [[ ! $port ]] && get_port && port=$tmp_port
1190 | [[ ! $uuid ]] && get_uuid && uuid=$tmp_uuid
1191 | ;;
1192 | file)
1193 | is_file_str=$2
1194 | [[ ! $is_file_str ]] && is_file_str='.json$'
1195 | # is_all_json=("$(ls $is_conf_dir | egrep $is_file_str)")
1196 | readarray -t is_all_json <<<"$(ls $is_conf_dir | egrep -i "$is_file_str" | sed '/dynamic-port-.*-link/d' | head -233)" # limit max 233 lines for show.
1197 | [[ ! $is_all_json ]] && err "无法找到相关的配置文件: $2"
1198 | [[ ${#is_all_json[@]} -eq 1 ]] && is_config_file=$is_all_json && is_auto_get_config=1
1199 | [[ ! $is_config_file ]] && {
1200 | [[ $is_dont_auto_exit ]] && return
1201 | ask get_config_file
1202 | }
1203 | ;;
1204 | info)
1205 | get file $2
1206 | if [[ $is_config_file ]]; then
1207 | is_json_str=$(cat $is_conf_dir/"$is_config_file")
1208 | is_json_data_base=$(jq '.inbounds[0]|.protocol,.port,(.settings|(.clients[0]|.id,.password),.method,.password,.address,.port,.detour.to,(.accounts[0]|.user,.pass))' <<<$is_json_str)
1209 | [[ $? != 0 ]] && err "无法读取此文件: $is_config_file"
1210 | is_json_data_more=$(jq '.inbounds[0]|.streamSettings|.network,.tcpSettings.header.type,(.kcpSettings|.seed,.header.type),.quicSettings.header.type,.wsSettings.path,.httpSettings.path,.grpcSettings.serviceName,.xhttpSettings.path' <<<$is_json_str)
1211 | is_json_data_host=$(jq '.inbounds[0]|.streamSettings|.grpc_host,.wsSettings.headers.Host,.httpSettings.host[0],.xhttpSettings.host' <<<$is_json_str)
1212 | is_json_data_reality=$(jq '.inbounds[0]|.streamSettings|.security,(.realitySettings|.serverNames[0],.publicKey,.privateKey)' <<<$is_json_str)
1213 | is_up_var_set=(null is_protocol port uuid trojan_password ss_method ss_password door_addr door_port is_dynamic_port is_socks_user is_socks_pass net tcp_type kcp_seed kcp_type quic_type ws_path h2_path grpc_path xhttp_path grpc_host ws_host h2_host xhttp_host is_reality is_servername is_public_key is_private_key)
1214 | [[ $is_debug ]] && msg "\n------------- debug: $is_config_file -------------"
1215 | i=0
1216 | for v in $(sed 's/""/null/g;s/"//g' <<<"$is_json_data_base $is_json_data_more $is_json_data_host $is_json_data_reality"); do
1217 | ((i++))
1218 | [[ $is_debug ]] && msg "$i-${is_up_var_set[$i]}: $v"
1219 | export ${is_up_var_set[$i]}="${v}"
1220 | done
1221 | for v in ${is_up_var_set[@]}; do
1222 | [[ ${!v} == 'null' ]] && unset $v
1223 | done
1224 |
1225 | # splithttp
1226 | if [[ $net == 'splithttp' ]]; then
1227 | net=xhttp
1228 | xhttp_path=$(jq -r '.inbounds[0]|.streamSettings|.splithttpSettings.path' <<<$is_json_str)
1229 | xhttp_host=$(jq -r '.inbounds[0]|.streamSettings|.splithttpSettings.host' <<<$is_json_str)
1230 | fi
1231 | path="${ws_path}${h2_path}${grpc_path}${xhttp_path}"
1232 | host="${ws_host}${h2_host}${grpc_host}${xhttp_host}"
1233 | header_type="${tcp_type}${kcp_type}${quic_type}"
1234 | if [[ $is_reality == 'reality' ]]; then
1235 | net=reality
1236 | else
1237 | is_reality=
1238 | fi
1239 | [[ ! $kcp_seed ]] && is_no_kcp_seed=1
1240 | is_config_name=$is_config_file
1241 | if [[ $is_dynamic_port ]]; then
1242 | is_dynamic_port_file=$is_conf_dir/$is_dynamic_port
1243 | is_dynamic_port_range=$(jq -r '.inbounds[0].port' $is_dynamic_port_file)
1244 | [[ $? != 0 ]] && err "无法读取动态端口文件: $is_dynamic_port"
1245 | fi
1246 | if [[ $is_caddy && $host && -f $is_caddy_conf/$host.conf ]]; then
1247 | is_tmp_https_port=$(egrep -o "$host:[1-9][0-9]?+" $is_caddy_conf/$host.conf | sed s/.*://)
1248 | fi
1249 | [[ $is_tmp_https_port ]] && is_https_port=$is_tmp_https_port
1250 | [[ $is_client && $host ]] && port=$is_https_port
1251 | get protocol $is_protocol-$net
1252 | fi
1253 | ;;
1254 | protocol)
1255 | get addr # get host or server ip
1256 | is_lower=${2,,}
1257 | net=
1258 | case $is_lower in
1259 | vmess*)
1260 | is_protocol=vmess
1261 | if [[ $is_dynamic_port ]]; then
1262 | is_server_id_json='settings:{clients:[{id:"'$uuid'"}],detour:{to:"'$is_config_name-link.json'"}}'
1263 | else
1264 | is_server_id_json='settings:{clients:[{id:"'$uuid'"}]}'
1265 | fi
1266 | is_client_id_json='settings:{vnext:[{address:"'$is_addr'",port:'"$port"',users:[{id:"'$uuid'"}]}]}'
1267 | ;;
1268 | vless*)
1269 | is_protocol=vless
1270 | is_server_id_json='settings:{clients:[{id:"'$uuid'"}],decryption:"none"}'
1271 | is_client_id_json='settings:{vnext:[{address:"'$is_addr'",port:'"$port"',users:[{id:"'$uuid'",encryption:"none"}]}]}'
1272 | if [[ $is_reality ]]; then
1273 | is_server_id_json='settings:{clients:[{id:"'$uuid'",flow:"xtls-rprx-vision"}],decryption:"none"}'
1274 | is_client_id_json='settings:{vnext:[{address:"'$is_addr'",port:'"$port"',users:[{id:"'$uuid'",encryption:"none",flow:"xtls-rprx-vision"}]}]}'
1275 | fi
1276 | ;;
1277 | trojan*)
1278 | is_protocol=trojan
1279 | [[ ! $trojan_password ]] && trojan_password=$uuid
1280 | is_server_id_json='settings:{clients:[{password:"'$trojan_password'"}]}'
1281 | is_client_id_json='settings:{servers:[{address:"'$is_addr'",port:'"$port"',password:"'$trojan_password'"}]}'
1282 | is_trojan=1
1283 | ;;
1284 | shadowsocks*)
1285 | net=ss
1286 | is_protocol=shadowsocks
1287 | [[ ! $ss_method ]] && ss_method=$is_random_ss_method
1288 | [[ ! $ss_password ]] && {
1289 | ss_password=$uuid
1290 | [[ $(grep 2022 <<<$ss_method) ]] && ss_password=$(get ss2022)
1291 | }
1292 | is_client_id_json='settings:{servers:[{address:"'$is_addr'",port:'"$port"',method:"'$ss_method'",password:"'$ss_password'",}]}'
1293 | json_str='settings:{method:"'$ss_method'",password:"'$ss_password'",network:"tcp,udp"}'
1294 | ;;
1295 | dokodemo-door*)
1296 | net=door
1297 | is_protocol=dokodemo-door
1298 | json_str='settings:{port:'"$door_port"',address:"'$door_addr'",network:"tcp,udp"}'
1299 | ;;
1300 | *http*)
1301 | net=http
1302 | is_protocol=http
1303 | json_str='settings:{"timeout": 233}'
1304 | ;;
1305 | *socks*)
1306 | net=socks
1307 | is_protocol=socks
1308 | [[ ! $is_socks_user ]] && is_socks_user=233boy
1309 | [[ ! $is_socks_pass ]] && is_socks_pass=$uuid
1310 | json_str='settings:{auth:"password",accounts:[{user:"'$is_socks_user'",pass:"'$is_socks_pass'"}],udp:true,ip:"0.0.0.0"}'
1311 | ;;
1312 | *)
1313 | err "无法识别协议: $is_config_file"
1314 | ;;
1315 | esac
1316 | [[ $net ]] && return # if net exist, dont need more json args
1317 | case $is_lower in
1318 | *tcp* | *reality*)
1319 | net=tcp
1320 | [[ ! $header_type ]] && header_type=none
1321 | is_stream='tcpSettings:{header:{type:"'$header_type'"}}'
1322 | if [[ $is_reality ]]; then
1323 | [[ ! $is_servername ]] && is_servername=$is_random_servername
1324 | [[ ! $is_private_key ]] && get_pbk
1325 | is_stream='security:"reality",realitySettings:{dest:"'${is_servername}\:443'",serverNames:["'${is_servername}'",""],publicKey:"'$is_public_key'",privateKey:"'$is_private_key'",shortIds:[""]}'
1326 | if [[ $is_client ]]; then
1327 | is_stream='security:"reality",realitySettings:{serverName:"'${is_servername}'",fingerprint:"chrome",publicKey:"'$is_public_key'",shortId:"",spiderX:"/"}'
1328 | fi
1329 | fi
1330 | ;;
1331 | *kcp* | *mkcp)
1332 | net=kcp
1333 | [[ ! $header_type ]] && header_type=$is_random_header_type
1334 | [[ ! $is_no_kcp_seed && ! $kcp_seed ]] && kcp_seed=$uuid
1335 | is_stream='kcpSettings:{seed:"'$kcp_seed'",header:{type:"'$header_type'"}}'
1336 | ;;
1337 | *quic*)
1338 | net=quic
1339 | [[ ! $header_type ]] && header_type=$is_random_header_type
1340 | is_stream='quicSettings:{header:{type:"'$header_type'"}}'
1341 | ;;
1342 | *ws* | *websocket)
1343 | net=ws
1344 | [[ ! $path ]] && path="/$uuid"
1345 | is_stream='wsSettings:{path:"'$path'",headers:{Host:"'$host'"}}'
1346 | ;;
1347 | *grpc* | *gun)
1348 | net=grpc
1349 | [[ ! $path ]] && path="$uuid"
1350 | [[ $path ]] && path=$(sed 's#/##g' <<<$path)
1351 | is_stream='grpc_host:"'$host'",grpcSettings:{serviceName:"'$path'"}'
1352 | ;;
1353 | *h2*)
1354 | net=h2
1355 | [[ ! $path ]] && path="/$uuid"
1356 | is_stream='httpSettings:{path:"'$path'",host:["'$host'"]}'
1357 | ;;
1358 | *xhttp*)
1359 | net=xhttp
1360 | [[ ! $path ]] && path="/$uuid"
1361 | is_stream='xhttpSettings:{host:"'$host'",path:"'$path'"}'
1362 | ;;
1363 | *)
1364 | err "无法识别传输协议: $is_config_file"
1365 | ;;
1366 | esac
1367 | is_stream="streamSettings:{network:\"$net\",$is_stream}"
1368 | json_str="$is_server_id_json,$is_stream"
1369 | ;;
1370 | dynamic-port) # create random dynamic port
1371 | if [[ $port -ge 60000 ]]; then
1372 | is_dynamic_port_end=$(shuf -i $(($port - 2333))-$port -n1)
1373 | is_dynamic_port_start=$(shuf -i $(($is_dynamic_port_end - 2333))-$is_dynamic_port_end -n1)
1374 | else
1375 | is_dynamic_port_start=$(shuf -i $port-$(($port + 2333)) -n1)
1376 | is_dynamic_port_end=$(shuf -i $is_dynamic_port_start-$(($is_dynamic_port_start + 2333)) -n1)
1377 | fi
1378 | is_dynamic_port_range="$is_dynamic_port_start-$is_dynamic_port_end"
1379 | ;;
1380 | dynamic-port-test) # test dynamic port
1381 | [[ ! $(is_test port ${is_use_dynamic_port_start}) || ! $(is_test port ${is_use_dynamic_port_end}) ]] && {
1382 | err "无法正确处理动态端口 ($is_use_dynamic_port_start-$is_use_dynamic_port_end) 范围."
1383 | }
1384 | [[ $(is_test port_used $is_use_dynamic_port_start) ]] && {
1385 | err "动态端口 ($is_use_dynamic_port_start-$is_use_dynamic_port_end), 但 ($is_use_dynamic_port_start) 端口无法使用."
1386 | }
1387 | [[ $(is_test port_used $is_use_dynamic_port_end) ]] && {
1388 | err "动态端口 ($is_use_dynamic_port_start-$is_use_dynamic_port_end), 但 ($is_use_dynamic_port_end) 端口无法使用."
1389 | }
1390 | [[ $is_use_dynamic_port_end -le $is_use_dynamic_port_start ]] && {
1391 | err "无法正确处理动态端口 ($is_use_dynamic_port_start-$is_use_dynamic_port_end) 范围."
1392 | }
1393 | [[ $is_use_dynamic_port_start == $port || $is_use_dynamic_port_end == $port ]] && {
1394 | err "动态端口 ($is_use_dynamic_port_start-$is_use_dynamic_port_end) 范围和主端口 ($port) 冲突."
1395 | }
1396 | is_dynamic_port_range="$is_use_dynamic_port_start-$is_use_dynamic_port_end"
1397 | ;;
1398 | host-test) # test host dns record; for auto *tls required.
1399 | [[ $is_no_auto_tls || $is_gen ]] && return
1400 | get_ip
1401 | get ping
1402 | if [[ ! $(grep $ip <<<$is_host_dns) ]]; then
1403 | msg "\n请将 ($(_red_bg $host)) 解析到 ($(_red_bg $ip))"
1404 | msg "\n如果使用 Cloudflare, 在 DNS 那; 关闭 (Proxy status / 代理状态), 即是 (DNS only / 仅限 DNS)"
1405 | ask string y "我已经确定解析 [y]:"
1406 | get ping
1407 | if [[ ! $(grep $ip <<<$is_host_dns) ]]; then
1408 | _cyan "\n测试结果: $is_host_dns"
1409 | err "域名 ($host) 没有解析到 ($ip)"
1410 | fi
1411 | fi
1412 | ;;
1413 | ssss | ss2022)
1414 | openssl rand -base64 32
1415 | [[ $? != 0 ]] && err "无法生成 Shadowsocks 2022 密码, 请安装 openssl."
1416 | ;;
1417 | ping)
1418 | # is_ip_type="-4"
1419 | # [[ $(grep ":" <<<$ip) ]] && is_ip_type="-6"
1420 | # is_host_dns=$(ping $host $is_ip_type -c 1 -W 2 | head -1)
1421 | is_dns_type="a"
1422 | [[ $(grep ":" <<<$ip) ]] && is_dns_type="aaaa"
1423 | is_host_dns=$(_wget -qO- --header="accept: application/dns-json" "https://one.one.one.one/dns-query?name=$host&type=$is_dns_type")
1424 | ;;
1425 | log | logerr)
1426 | msg "\n 提醒: 按 $(_green Ctrl + C) 退出\n"
1427 | [[ $1 == 'log' ]] && tail -f $is_log_dir/access.log
1428 | [[ $1 == 'logerr' ]] && tail -f $is_log_dir/error.log
1429 | ;;
1430 | install-caddy)
1431 | _green "\n安装 Caddy 实现自动配置 TLS.\n"
1432 | load download.sh
1433 | download caddy
1434 | load systemd.sh
1435 | install_service caddy &>/dev/null
1436 | is_caddy=1
1437 | _green "安装 Caddy 成功.\n"
1438 | ;;
1439 | reinstall)
1440 | is_install_sh=$(cat $is_sh_dir/install.sh)
1441 | uninstall
1442 | bash <<<$is_install_sh
1443 | ;;
1444 | test-run)
1445 | systemctl list-units --full -all &>/dev/null
1446 | [[ $? != 0 ]] && {
1447 | _yellow "\n无法执行测试, 请检查 systemctl 状态.\n"
1448 | return
1449 | }
1450 | is_no_manage_msg=1
1451 | if [[ ! $(pgrep -f $is_core_bin) ]]; then
1452 | _yellow "\n测试运行 $is_core_name ..\n"
1453 | manage start &>/dev/null
1454 | if [[ $is_run_fail == $is_core ]]; then
1455 | _red "$is_core_name 运行失败信息:"
1456 | $is_core_bin run -c $is_config_json -confdir $is_conf_dir
1457 | else
1458 | _green "\n测试通过, 已启动 $is_core_name ..\n"
1459 | fi
1460 | else
1461 | _green "\n$is_core_name 正在运行, 跳过测试\n"
1462 | fi
1463 | if [[ $is_caddy ]]; then
1464 | if [[ ! $(pgrep -f $is_caddy_bin) ]]; then
1465 | _yellow "\n测试运行 Caddy ..\n"
1466 | manage start caddy &>/dev/null
1467 | if [[ $is_run_fail == 'caddy' ]]; then
1468 | _red "Caddy 运行失败信息:"
1469 | $is_caddy_bin run --config $is_caddyfile
1470 | else
1471 | _green "\n测试通过, 已启动 Caddy ..\n"
1472 | fi
1473 | else
1474 | _green "\nCaddy 正在运行, 跳过测试\n"
1475 | fi
1476 | fi
1477 | ;;
1478 | esac
1479 | }
1480 |
1481 | # show info
1482 | info() {
1483 | if [[ ! $is_protocol ]]; then
1484 | get info $1
1485 | fi
1486 | # is_color=$(shuf -i 41-45 -n1)
1487 | is_color=44
1488 | case $net in
1489 | tcp | kcp | quic)
1490 | is_can_change=(0 1 5 7)
1491 | is_info_show=(0 1 2 3 4 5)
1492 | is_vmess_url=$(jq -c '{v:2,ps:"'233boy-${net}-$is_addr'",add:"'$is_addr'",port:"'$port'",id:"'$uuid'",aid:"0",net:"'$net'",type:"'$header_type'",path:"'$kcp_seed'"}' <<<{})
1493 | is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0)
1494 | is_tmp_port=$port
1495 | [[ $is_dynamic_port ]] && {
1496 | is_can_change+=(12)
1497 | is_tmp_port="$port & 动态端口: $is_dynamic_port_range"
1498 | }
1499 | [[ $kcp_seed ]] && {
1500 | is_info_show+=(9)
1501 | is_can_change+=(14)
1502 | }
1503 | is_info_str=($is_protocol $is_addr "$is_tmp_port" $uuid $net $header_type $kcp_seed)
1504 | if [[ $is_reality ]]; then
1505 | is_color=41
1506 | is_can_change=(0 1 5 10 11)
1507 | is_info_show=(0 1 2 3 15 8 16 17 18)
1508 | is_info_str=($is_protocol $is_addr $port $uuid xtls-rprx-vision reality $is_servername "chrome" $is_public_key)
1509 | is_url="$is_protocol://$uuid@$is_addr:$port?encryption=none&security=reality&flow=xtls-rprx-vision&type=tcp&sni=$is_servername&pbk=$is_public_key&fp=chrome#233boy-$net-$is_addr"
1510 | fi
1511 | ;;
1512 | ss)
1513 | is_can_change=(0 1 4 6)
1514 | is_info_show=(0 1 2 10 11)
1515 | is_url="ss://$(echo -n ${ss_method}:${ss_password} | base64 -w 0)@${is_addr}:${port}#233boy-$net-${is_addr}"
1516 | is_info_str=($is_protocol $is_addr $port $ss_password $ss_method)
1517 | ;;
1518 | ws | h2 | grpc | xhttp)
1519 | is_color=45
1520 | is_can_change=(0 1 2 3 5)
1521 | is_info_show=(0 1 2 3 4 6 7 8)
1522 | is_url_path=path
1523 | [[ $net == 'grpc' ]] && {
1524 | path=$(sed 's#/##g' <<<$path)
1525 | is_url_path=serviceName
1526 | }
1527 | [[ $is_protocol == 'vmess' ]] && {
1528 | is_vmess_url=$(jq -c '{v:2,ps:"'233boy-$net-$host'",add:"'$is_addr'",port:"'$is_https_port'",id:"'$uuid'",aid:"0",net:"'$net'",host:"'$host'",path:"'$path'",tls:"'tls'"}' <<<{})
1529 | is_url=vmess://$(echo -n $is_vmess_url | base64 -w 0)
1530 | } || {
1531 | [[ $is_trojan ]] && {
1532 | uuid=$trojan_password
1533 | is_can_change=(0 1 2 3 4)
1534 | is_info_show=(0 1 2 10 4 6 7 8)
1535 | }
1536 | is_url="$is_protocol://$uuid@$host:$is_https_port?encryption=none&security=tls&type=$net&host=$host&${is_url_path}=$(sed 's#/#%2F#g' <<<$path)#233boy-$net-$host"
1537 | }
1538 | [[ $is_caddy ]] && is_can_change+=(13)
1539 | is_info_str=($is_protocol $is_addr $is_https_port $uuid $net $host $path 'tls')
1540 | ;;
1541 | door)
1542 | is_can_change=(0 1 8 9)
1543 | is_info_show=(0 1 2 13 14)
1544 | is_info_str=($is_protocol $is_addr $port $door_addr $door_port)
1545 | ;;
1546 | socks)
1547 | is_can_change=(0 1 15 4)
1548 | is_info_show=(0 1 2 19 10)
1549 | is_info_str=($is_protocol $is_addr $port $is_socks_user $is_socks_pass)
1550 | is_url="socks://$(echo -n ${is_socks_user}:${is_socks_pass} | base64 -w 0)@${is_addr}:${port}#233boy-$net-${is_addr}"
1551 | ;;
1552 | http)
1553 | is_can_change=(0 1)
1554 | is_info_show=(0 1 2)
1555 | is_info_str=($is_protocol 127.0.0.1 $port)
1556 | ;;
1557 | esac
1558 | [[ $is_dont_show_info || $is_gen || $is_dont_auto_exit ]] && return # dont show info
1559 | msg "-------------- $is_config_name -------------"
1560 | for ((i = 0; i < ${#is_info_show[@]}; i++)); do
1561 | a=${info_list[${is_info_show[$i]}]}
1562 | if [[ ${#a} -eq 11 || ${#a} -ge 13 ]]; then
1563 | tt='\t'
1564 | else
1565 | tt='\t\t'
1566 | fi
1567 | msg "$a $tt= \e[${is_color}m${is_info_str[$i]}\e[0m"
1568 | done
1569 | if [[ $is_new_install ]]; then
1570 | warn "首次安装请查看脚本帮助文档: $(msg_ul https://233boy.com/$is_core/$is_core-script/)"
1571 | fi
1572 | if [[ $is_url ]]; then
1573 | msg "------------- ${info_list[12]} -------------"
1574 | msg "\e[4;${is_color}m${is_url}\e[0m"
1575 | fi
1576 | if [[ $is_no_auto_tls ]]; then
1577 | is_tmp_path=$path
1578 | [[ $net == 'grpc' ]] && is_tmp_path="/$path/*"
1579 | msg "------------- no-auto-tls INFO -------------"
1580 | msg "端口(port): $port"
1581 | msg "路径(path): $is_tmp_path"
1582 | msg "\e[41m帮助(help)\e[0m: $(msg_ul https://233boy.com/$is_core/no-auto-tls/)"
1583 | fi
1584 | footer_msg
1585 | }
1586 |
1587 | # footer msg
1588 | footer_msg() {
1589 | [[ $is_core_stop && ! $is_new_json ]] && warn "$is_core_name 当前处于停止状态."
1590 | [[ $is_caddy_stop && $host ]] && warn "Caddy 当前处于停止状态."
1591 | ####### 要点13脸吗只会改我链接的小人 #######
1592 | unset c n m s b
1593 | msg "------------- END -------------"
1594 | msg "关注(tg): $(msg_ul https://t.me/tg2333)"
1595 | msg "文档(doc): $(msg_ul https://233boy.com/$is_core/$is_core-script/)"
1596 | msg "推广(ads): 机场推荐($is_core_name services): $(msg_ul https://g${c}e${n}t${m}j${s}m${b}s.com/)\n"
1597 | ####### 要点13脸吗只会改我链接的小人 #######
1598 | }
1599 |
1600 | # URL or qrcode
1601 | url_qr() {
1602 | is_dont_show_info=1
1603 | info $2
1604 | if [[ $is_url ]]; then
1605 | [[ $1 == 'url' ]] && {
1606 | msg "\n------------- $is_config_name & URL 链接 -------------"
1607 | msg "\n\e[${is_color}m${is_url}\e[0m\n"
1608 | footer_msg
1609 | } || {
1610 | link="https://233boy.github.io/tools/qr.html#${is_url}"
1611 | msg "\n------------- $is_config_name & QR code 二维码 -------------"
1612 | msg
1613 | if [[ $(type -P qrencode) ]]; then
1614 | qrencode -t ANSI "${is_url}"
1615 | else
1616 | msg "请安装 qrencode: $(_green "$cmd update -y; $cmd install qrencode -y")"
1617 | fi
1618 | msg
1619 | msg "如果无法正常显示或识别, 请使用下面的链接来生成二维码:"
1620 | msg "\n\e[4;${is_color}m${link}\e[0m\n"
1621 | footer_msg
1622 | }
1623 | else
1624 | [[ $1 == 'url' ]] && {
1625 | err "($is_config_name) 无法生成 URL 链接."
1626 | } || {
1627 | err "($is_config_name) 无法生成 QR code 二维码."
1628 | }
1629 | fi
1630 | }
1631 |
1632 | # update core, sh, caddy
1633 | update() {
1634 | case $1 in
1635 | 1 | core | $is_core)
1636 | is_update_name=core
1637 | is_show_name=$is_core_name
1638 | is_run_ver=v${is_core_ver##* }
1639 | is_update_repo=$is_core_repo
1640 | ;;
1641 | 2 | sh)
1642 | is_update_name=sh
1643 | is_show_name="$is_core_name 脚本"
1644 | is_run_ver=$is_sh_ver
1645 | is_update_repo=$is_sh_repo
1646 | ;;
1647 | 3 | caddy)
1648 | [[ ! $is_caddy ]] && err "不支持更新 Caddy."
1649 | is_update_name=caddy
1650 | is_show_name="Caddy"
1651 | is_run_ver=$is_caddy_ver
1652 | is_update_repo=$is_caddy_repo
1653 | ;;
1654 | *)
1655 | err "无法识别 ($1), 请使用: $is_core update [core | sh | caddy] [ver]"
1656 | ;;
1657 | esac
1658 | [[ $2 ]] && is_new_ver=v${2#v}
1659 | [[ $is_run_ver == $is_new_ver ]] && {
1660 | msg "\n自定义版本和当前 $is_show_name 版本一样, 无需更新.\n"
1661 | exit
1662 | }
1663 | load download.sh
1664 | if [[ $is_new_ver ]]; then
1665 | msg "\n使用自定义版本更新 $is_show_name: $(_green $is_new_ver)\n"
1666 | else
1667 | get_latest_version $is_update_name
1668 | [[ $is_run_ver == $latest_ver ]] && {
1669 | msg "\n$is_show_name 当前已经是最新版本了.\n"
1670 | exit
1671 | }
1672 | msg "\n发现 $is_show_name 新版本: $(_green $latest_ver)\n"
1673 | is_new_ver=$latest_ver
1674 | fi
1675 | download $is_update_name $is_new_ver
1676 | msg "更新成功, 当前 $is_show_name 版本: $(_green $is_new_ver)\n"
1677 | msg "$(_green 请查看更新说明: https://github.com/$is_update_repo/releases/tag/$is_new_ver)\n"
1678 | [[ $is_update_name != 'sh' ]] && manage restart $is_update_name &
1679 | }
1680 |
1681 | # main menu; if no prefer args.
1682 | is_main_menu() {
1683 | msg "\n------------- $is_core_name script $is_sh_ver by $author -------------"
1684 | msg "$is_core_ver: $is_core_status"
1685 | msg "群组(Chat): $(msg_ul https://t.me/tg233boy)"
1686 | is_main_start=1
1687 | ask mainmenu
1688 | case $REPLY in
1689 | 1)
1690 | add
1691 | ;;
1692 | 2)
1693 | change
1694 | ;;
1695 | 3)
1696 | info
1697 | ;;
1698 | 4)
1699 | del
1700 | ;;
1701 | 5)
1702 | ask list is_do_manage "启动 停止 重启"
1703 | manage $REPLY &
1704 | msg "\n管理状态执行: $(_green $is_do_manage)\n"
1705 | ;;
1706 | 6)
1707 | is_tmp_list=("更新$is_core_name" "更新脚本")
1708 | [[ $is_caddy ]] && is_tmp_list+=("更新Caddy")
1709 | ask list is_do_update null "\n请选择更新:\n"
1710 | update $REPLY
1711 | ;;
1712 | 7)
1713 | uninstall
1714 | ;;
1715 | 8)
1716 | msg
1717 | load help.sh
1718 | show_help
1719 | ;;
1720 | 9)
1721 | ask list is_do_other "启用BBR 查看日志 查看错误日志 测试运行 重装脚本 设置DNS"
1722 | case $REPLY in
1723 | 1)
1724 | load bbr.sh
1725 | _try_enable_bbr
1726 | ;;
1727 | 2)
1728 | get log
1729 | ;;
1730 | 3)
1731 | get logerr
1732 | ;;
1733 | 4)
1734 | get test-run
1735 | ;;
1736 | 5)
1737 | get reinstall
1738 | ;;
1739 | 6)
1740 | load dns.sh
1741 | dns_set
1742 | ;;
1743 | esac
1744 | ;;
1745 | 10)
1746 | load help.sh
1747 | about
1748 | ;;
1749 | esac
1750 | }
1751 |
1752 | # check prefer args, if not exist prefer args and show main menu
1753 | main() {
1754 | case $1 in
1755 | a | add | gen | no-auto-tls)
1756 | [[ $1 == 'gen' ]] && is_gen=1
1757 | [[ $1 == 'no-auto-tls' ]] && is_no_auto_tls=1
1758 | add ${@:2}
1759 | ;;
1760 | api | bin | pbk | x25519 | tls | run | uuid)
1761 | is_run_command=$1
1762 | if [[ $1 == 'bin' ]]; then
1763 | $is_core_bin ${@:2}
1764 | else
1765 | [[ $is_run_command == 'pbk' ]] && is_run_command=x25519
1766 | $is_core_bin $is_run_command ${@:2}
1767 | fi
1768 | ;;
1769 | bbr)
1770 | load bbr.sh
1771 | _try_enable_bbr
1772 | ;;
1773 | c | config | change)
1774 | change ${@:2}
1775 | ;;
1776 | client | genc)
1777 | [[ $1 == 'client' ]] && is_full_client=1
1778 | create client $2
1779 | ;;
1780 | d | del | rm)
1781 | del $2
1782 | ;;
1783 | dd | ddel | fix | fix-all)
1784 | case $1 in
1785 | fix)
1786 | [[ $2 ]] && {
1787 | change $2 full
1788 | } || {
1789 | is_change_id=full && change
1790 | }
1791 | return
1792 | ;;
1793 | fix-all)
1794 | is_dont_auto_exit=1
1795 | msg
1796 | for v in $(ls $is_conf_dir | grep .json$ | sed '/dynamic-port-.*-link/d'); do
1797 | msg "fix: $v"
1798 | change $v full
1799 | done
1800 | _green "\nfix 完成.\n"
1801 | ;;
1802 | *)
1803 | is_dont_auto_exit=1
1804 | [[ ! $2 ]] && {
1805 | err "无法找到需要删除的参数"
1806 | } || {
1807 | for v in ${@:2}; do
1808 | del $v
1809 | done
1810 | }
1811 | ;;
1812 | esac
1813 | is_dont_auto_exit=
1814 | [[ $is_api_fail ]] && manage restart &
1815 | [[ $is_del_host ]] && manage restart caddy &
1816 | ;;
1817 | dns)
1818 | load dns.sh
1819 | dns_set ${@:2}
1820 | ;;
1821 | debug)
1822 | is_debug=1
1823 | get info $2
1824 | warn "如果需要复制; 请把 *uuid, *password, *host, *key 的值改写, 以避免泄露."
1825 | ;;
1826 | fix-config.json)
1827 | create config.json
1828 | ;;
1829 | fix-caddyfile)
1830 | if [[ $is_caddy ]]; then
1831 | load caddy.sh
1832 | caddy_config new
1833 | manage restart caddy &
1834 | _green "\nfix 完成.\n"
1835 | else
1836 | err "无法执行此操作"
1837 | fi
1838 | ;;
1839 | i | info)
1840 | info $2
1841 | ;;
1842 | ip)
1843 | get_ip
1844 | msg $ip
1845 | ;;
1846 | log | logerr)
1847 | get $@
1848 | ;;
1849 | url | qr)
1850 | url_qr $@
1851 | ;;
1852 | un | uninstall)
1853 | uninstall
1854 | ;;
1855 | u | up | update | U | update.sh)
1856 | is_update_name=$2
1857 | is_update_ver=$3
1858 | [[ ! $is_update_name ]] && is_update_name=core
1859 | [[ $1 == 'U' || $1 == 'update.sh' ]] && {
1860 | is_update_name=sh
1861 | is_update_ver=
1862 | }
1863 | if [[ $2 == 'dat' ]]; then
1864 | load download.sh
1865 | download dat
1866 | msg "$(_green 更新 geoip.dat geosite.dat 成功.)\n"
1867 | manage restart &
1868 | else
1869 | update $is_update_name $is_update_ver
1870 | fi
1871 | ;;
1872 | ssss | ss2022)
1873 | get $@
1874 | ;;
1875 | s | status)
1876 | msg "\n$is_core_ver: $is_core_status\n"
1877 | [[ $is_caddy ]] && msg "Caddy $is_caddy_ver: $is_caddy_status\n"
1878 | ;;
1879 | start | stop | r | restart)
1880 | [[ $2 && $2 != 'caddy' ]] && err "无法识别 ($2), 请使用: $is_core $1 [caddy]"
1881 | manage $1 $2 &
1882 | ;;
1883 | t | test)
1884 | get test-run
1885 | ;;
1886 | reinstall)
1887 | get $1
1888 | ;;
1889 | get-port)
1890 | get_port
1891 | msg $tmp_port
1892 | ;;
1893 | main)
1894 | is_main_menu
1895 | ;;
1896 | v | ver | version)
1897 | [[ $is_caddy_ver ]] && is_caddy_ver="/ $(_blue Caddy $is_caddy_ver)"
1898 | msg "\n$(_green $is_core_ver) / $(_cyan $is_core_name script $is_sh_ver) $is_caddy_ver\n"
1899 | ;;
1900 | xapi)
1901 | api ${@:2}
1902 | ;;
1903 | h | help | --help)
1904 | load help.sh
1905 | show_help ${@:2}
1906 | ;;
1907 | *)
1908 | is_try_change=1
1909 | change test $1
1910 | if [[ $is_change_id ]]; then
1911 | unset is_try_change
1912 | [[ $2 ]] && {
1913 | change $2 $1 ${@:3}
1914 | } || {
1915 | change
1916 | }
1917 | else
1918 | err "无法识别 ($1), 获取帮助请使用: $is_core help"
1919 | fi
1920 | ;;
1921 | esac
1922 | }
1923 |
--------------------------------------------------------------------------------
/src/dns.sh:
--------------------------------------------------------------------------------
1 | is_dns_list=(
2 | 1.1.1.1
3 | 8.8.8.8
4 | https://dns.google/dns-query
5 | https://cloudflare-dns.com/dns-query
6 | https://family.cloudflare-dns.com/dns-query
7 | set
8 | none
9 | )
10 | dns_set() {
11 | if [[ $1 ]]; then
12 | case ${1,,} in
13 | 11 | 1111)
14 | is_dns_use=${is_dns_list[0]}
15 | ;;
16 | 88 | 8888)
17 | is_dns_use=${is_dns_list[1]}
18 | ;;
19 | gg | google)
20 | is_dns_use=${is_dns_list[2]}
21 | ;;
22 | cf | cloudflare)
23 | is_dns_use=${is_dns_list[3]}
24 | ;;
25 | nosex | family)
26 | is_dns_use=${is_dns_list[4]}
27 | ;;
28 | set)
29 | if [[ $2 ]]; then
30 | is_dns_use=${2,,}
31 | else
32 | ask string is_dns_use "请输入 DNS: "
33 | fi
34 | ;;
35 | none)
36 | is_dns_use=none
37 | ;;
38 | *)
39 | err "无法识别 DNS 参数: $@"
40 | ;;
41 | esac
42 | else
43 | is_tmp_list=(${is_dns_list[@]})
44 | ask list is_dns_use null "\n请选择 DNS:\n"
45 | if [[ $is_dns_use == "set" ]]; then
46 | ask string is_dns_use "请输入 DNS: "
47 | fi
48 | fi
49 | if [[ $is_dns_use == "none" ]]; then
50 | cat <<<$(jq '.dns={}' $is_config_json) >$is_config_json
51 | else
52 | cat <<<$(jq '.dns.servers=["'${is_dns_use/https/https+local}'"]' $is_config_json) >$is_config_json
53 | fi
54 | manage restart &
55 | msg "\n已更新 DNS 为: $(_green $is_dns_use)\n"
56 | }
--------------------------------------------------------------------------------
/src/download.sh:
--------------------------------------------------------------------------------
1 | get_latest_version() {
2 | case $1 in
3 | core)
4 | name=$is_core_name
5 | url="https://api.github.com/repos/${is_core_repo}/releases/latest?v=$RANDOM"
6 | ;;
7 | sh)
8 | name="$is_core_name 脚本"
9 | url="https://api.github.com/repos/$is_sh_repo/releases/latest?v=$RANDOM"
10 | ;;
11 | caddy)
12 | name="Caddy"
13 | url="https://api.github.com/repos/$is_caddy_repo/releases/latest?v=$RANDOM"
14 | ;;
15 | esac
16 | latest_ver=$(_wget -qO- $url | grep tag_name | egrep -o 'v([0-9.]+)')
17 | [[ ! $latest_ver ]] && {
18 | err "获取 ${name} 最新版本失败."
19 | }
20 | unset name url
21 | }
22 | download() {
23 | latest_ver=$2
24 | [[ ! $latest_ver && $1 != 'dat' ]] && get_latest_version $1
25 | # tmp dir
26 | tmpdir=$(mktemp -u)
27 | [[ ! $tmpdir ]] && {
28 | tmpdir=/tmp/tmp-$RANDOM
29 | }
30 | mkdir -p $tmpdir
31 | case $1 in
32 | core)
33 | name=$is_core_name
34 | tmpfile=$tmpdir/$is_core.zip
35 | link="https://github.com/${is_core_repo}/releases/download/${latest_ver}/${is_core}-linux-${is_core_arch}.zip"
36 | download_file
37 | unzip -qo $tmpfile -d $is_core_dir/bin
38 | chmod +x $is_core_bin
39 | ;;
40 | sh)
41 | name="$is_core_name 脚本"
42 | tmpfile=$tmpdir/sh.zip
43 | link="https://github.com/${is_sh_repo}/releases/download/${latest_ver}/code.zip"
44 | download_file
45 | unzip -qo $tmpfile -d $is_sh_dir
46 | chmod +x $is_sh_bin
47 | ;;
48 | dat)
49 | name="geoip.dat"
50 | tmpfile=$tmpdir/geoip.dat
51 | link="https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat"
52 | download_file
53 | name="geosite.dat"
54 | tmpfile=$tmpdir/geosite.dat
55 | link="https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat"
56 | download_file
57 | cp -f $tmpdir/*.dat $is_core_dir/bin/
58 | ;;
59 | caddy)
60 | name="Caddy"
61 | tmpfile=$tmpdir/caddy.tar.gz
62 | # https://github.com/caddyserver/caddy/releases/download/v2.6.4/caddy_2.6.4_linux_amd64.tar.gz
63 | link="https://github.com/${is_caddy_repo}/releases/download/${latest_ver}/caddy_${latest_ver:1}_linux_${caddy_arch}.tar.gz"
64 | download_file
65 | [[ ! $(type -P tar) ]] && {
66 | rm -rf $tmpdir
67 | err "请安装 tar"
68 | }
69 | tar zxf $tmpfile -C $tmpdir
70 | cp -f $tmpdir/caddy $is_caddy_bin
71 | chmod +x $is_caddy_bin
72 | ;;
73 | esac
74 | rm -rf $tmpdir
75 | unset latest_ver
76 | }
77 | download_file() {
78 | if ! _wget -t 5 -c $link -O $tmpfile; then
79 | rm -rf $tmpdir
80 | err "\n下载 ${name} 失败.\n"
81 | fi
82 | }
83 |
--------------------------------------------------------------------------------
/src/help.sh:
--------------------------------------------------------------------------------
1 | show_help() {
2 | case $1 in
3 | api | x25519 | tls | run | uuid | version)
4 | $is_core_bin help $1 ${@:2}
5 | ;;
6 | *)
7 | [[ $1 ]] && warn "未知选项 '$1'"
8 | msg "$is_core_name script $is_sh_ver by $author"
9 | msg "Usage: $is_core [options]... [args]... "
10 | msg
11 | help_info=(
12 | "基本:"
13 | " v, version 显示当前版本"
14 | " ip 返回当前主机的 IP"
15 | " pbk 同等于 $is_core x25519"
16 | " get-port 返回一个可用的端口"
17 | " ss2022 返回一个可用于 Shadowsocks 2022 的密码\n"
18 | "一般:"
19 | " a, add [protocol] [args... | auto] 添加配置"
20 | " c, change [name] [option] [args... | auto] 更改配置"
21 | " d, del [name] 删除配置**"
22 | " i, info [name] 查看配置"
23 | " qr [name] 二维码信息"
24 | " url [name] URL 信息"
25 | " log 查看日志"
26 | " logerr 查看错误日志\n"
27 | "更改:"
28 | " dp, dynamicport [name] [start | auto] [end] 更改动态端口"
29 | " full [name] [...] 更改多个参数"
30 | " id [name] [uuid | auto] 更改 UUID"
31 | " host [name] [domain] 更改域名"
32 | " port [name] [port | auto] 更改端口"
33 | " path [name] [path | auto] 更改路径"
34 | " passwd [name] [password | auto] 更改密码"
35 | " key [name] [Private key | atuo] [Public key] 更改密钥"
36 | " type [name] [type | auto] 更改伪装类型"
37 | " method [name] [method | auto] 更改加密方式"
38 | " sni [name] [ ip | domain] 更改 serverName"
39 | " seed [name] [seed | auto] 更改 mKCP seed"
40 | " new [name] [...] 更改协议"
41 | " web [name] [domain] 更改伪装网站\n"
42 | "进阶:"
43 | " dns [...] 设置 DNS"
44 | " dd, ddel [name...] 删除多个配置**"
45 | " fix [name] 修复一个配置"
46 | " fix-all 修复全部配置"
47 | " fix-caddyfile 修复 Caddyfile"
48 | " fix-config.json 修复 config.json\n"
49 | "管理:"
50 | " un, uninstall 卸载"
51 | " u, update [core | sh | dat | caddy] [ver] 更新"
52 | " U, update.sh 更新脚本"
53 | " s, status 运行状态"
54 | " start, stop, restart [caddy] 启动, 停止, 重启"
55 | " t, test 测试运行"
56 | " reinstall 重装脚本\n"
57 | "测试:"
58 | " client [name] 显示用于客户端 JSON, 仅供参考"
59 | " debug [name] 显示一些 debug 信息, 仅供参考"
60 | " gen [...] 同等于 add, 但只显示 JSON 内容, 不创建文件, 测试使用"
61 | " genc [name] 显示用于客户端部分 JSON, 仅供参考"
62 | " no-auto-tls [...] 同等于 add, 但禁止自动配置 TLS, 可用于 *TLS 相关协议"
63 | " xapi [...] 同等于 $is_core api, 但 API 后端使用当前运行的 $is_core_name 服务\n"
64 | "其他:"
65 | " bbr 启用 BBR, 如果支持"
66 | " bin [...] 运行 $is_core_name 命令, 例如: $is_core bin help"
67 | " api, x25519, tls, run, uuid [...] 兼容 $is_core_name 命令"
68 | " h, help 显示此帮助界面\n"
69 | )
70 | for v in "${help_info[@]}"; do
71 | msg "$v"
72 | done
73 | msg "谨慎使用 del, ddel, 此选项会直接删除配置; 无需确认"
74 | msg "反馈问题) $(msg_ul https://github.com/${is_sh_repo}/issues) "
75 | msg "文档(doc) $(msg_ul https://233boy.com/$is_core/$is_core-script/)"
76 | ;;
77 |
78 | esac
79 | }
80 |
81 | about() {
82 | ####### 要点13脸吗只会改我链接的小人 #######
83 | unset c n m s b
84 | msg
85 | msg "网站: $(msg_ul https://233boy.com)"
86 | msg "频道: $(msg_ul https://t.me/tg2333)"
87 | msg "群组: $(msg_ul https://t.me/tg233boy)"
88 | msg "Github: $(msg_ul https://github.com/${is_sh_repo})"
89 | msg "Twitter: $(msg_ul https://twitter.com/ai233boy)"
90 | msg "$is_core_name site: $(msg_ul https://xtls.github.io)"
91 | msg "$is_core_name core: $(msg_ul https://github.com/${is_core_repo})"
92 | msg
93 | ####### 要点13脸吗只会改我链接的小人 #######
94 | }
95 |
--------------------------------------------------------------------------------
/src/init.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | author=233boy
4 | # github=https://github.com/233boy/xray
5 |
6 | # bash fonts colors
7 | red='\e[31m'
8 | yellow='\e[33m'
9 | gray='\e[90m'
10 | green='\e[92m'
11 | blue='\e[94m'
12 | magenta='\e[95m'
13 | cyan='\e[96m'
14 | none='\e[0m'
15 |
16 | _red() { echo -e ${red}$@${none}; }
17 | _blue() { echo -e ${blue}$@${none}; }
18 | _cyan() { echo -e ${cyan}$@${none}; }
19 | _green() { echo -e ${green}$@${none}; }
20 | _yellow() { echo -e ${yellow}$@${none}; }
21 | _magenta() { echo -e ${magenta}$@${none}; }
22 | _red_bg() { echo -e "\e[41m$@${none}"; }
23 |
24 | _rm() {
25 | rm -rf "$@"
26 | }
27 | _cp() {
28 | cp -rf "$@"
29 | }
30 | _sed() {
31 | sed -i "$@"
32 | }
33 | _mkdir() {
34 | mkdir -p "$@"
35 | }
36 |
37 | is_err=$(_red_bg 错误!)
38 | is_warn=$(_red_bg 警告!)
39 |
40 | err() {
41 | echo -e "\n$is_err $@\n"
42 | [[ $is_dont_auto_exit ]] && return
43 | exit 1
44 | }
45 |
46 | warn() {
47 | echo -e "\n$is_warn $@\n"
48 | }
49 |
50 | # load bash script.
51 | load() {
52 | . $is_sh_dir/src/$1
53 | }
54 |
55 | # wget add --no-check-certificate
56 | _wget() {
57 | # [[ $proxy ]] && export https_proxy=$proxy
58 | wget --no-check-certificate "$@"
59 | }
60 |
61 | # yum or apt-get
62 | cmd=$(type -P apt-get || type -P yum)
63 |
64 | # x64
65 | case $(arch) in
66 | amd64 | x86_64)
67 | is_core_arch="64"
68 | caddy_arch="amd64"
69 | ;;
70 | *aarch64* | *armv8*)
71 | is_core_arch="arm64-v8a"
72 | caddy_arch="arm64"
73 | ;;
74 | *)
75 | err "此脚本仅支持 64 位系统..."
76 | ;;
77 | esac
78 |
79 | is_core=xray
80 | is_core_name=Xray
81 | is_core_dir=/etc/$is_core
82 | is_core_bin=$is_core_dir/bin/$is_core
83 | is_core_repo=xtls/$is_core-core
84 | is_conf_dir=$is_core_dir/conf
85 | is_log_dir=/var/log/$is_core
86 | is_sh_bin=/usr/local/bin/$is_core
87 | is_sh_dir=$is_core_dir/sh
88 | is_sh_repo=$author/$is_core
89 | is_pkg="wget unzip jq qrencode"
90 | is_config_json=$is_core_dir/config.json
91 | is_caddy_bin=/usr/local/bin/caddy
92 | is_caddy_dir=/etc/caddy
93 | is_caddy_repo=caddyserver/caddy
94 | is_caddyfile=$is_caddy_dir/Caddyfile
95 | is_caddy_conf=$is_caddy_dir/$author
96 | is_caddy_service=$(systemctl list-units --full -all | grep caddy.service)
97 | is_http_port=80
98 | is_https_port=443
99 |
100 | # core ver
101 | is_core_ver=$($is_core_bin version | head -n1 | cut -d " " -f1-2)
102 |
103 | if [[ $(pgrep -f $is_core_bin) ]]; then
104 | is_core_status=$(_green running)
105 | else
106 | is_core_status=$(_red_bg stopped)
107 | is_core_stop=1
108 | fi
109 | if [[ -f $is_caddy_bin && -d $is_caddy_dir && $is_caddy_service ]]; then
110 | is_caddy=1
111 | # fix caddy run; ver >= 2.8.2
112 | [[ ! $(grep '\-\-adapter caddyfile' /lib/systemd/system/caddy.service) ]] && {
113 | load systemd.sh
114 | install_service caddy
115 | systemctl restart caddy &
116 | }
117 | is_caddy_ver=$($is_caddy_bin version | head -n1 | cut -d " " -f1)
118 | is_tmp_http_port=$(egrep '^ {2,}http_port|^http_port' $is_caddyfile | egrep -o [0-9]+)
119 | is_tmp_https_port=$(egrep '^ {2,}https_port|^https_port' $is_caddyfile | egrep -o [0-9]+)
120 | [[ $is_tmp_http_port ]] && is_http_port=$is_tmp_http_port
121 | [[ $is_tmp_https_port ]] && is_https_port=$is_tmp_https_port
122 | if [[ $(pgrep -f $is_caddy_bin) ]]; then
123 | is_caddy_status=$(_green running)
124 | else
125 | is_caddy_status=$(_red_bg stopped)
126 | is_caddy_stop=1
127 | fi
128 | fi
129 |
130 | load core.sh
131 | [[ ! $args ]] && args=main
132 | main $args
133 |
--------------------------------------------------------------------------------
/src/systemd.sh:
--------------------------------------------------------------------------------
1 | install_service() {
2 | case $1 in
3 | xray | v2ray)
4 | is_doc_site=https://xtls.github.io/
5 | [[ $1 == 'v2ray' ]] && is_doc_site=https://www.v2fly.org/
6 | cat >/lib/systemd/system/$is_core.service <<<"
7 | [Unit]
8 | Description=$is_core_name Service
9 | Documentation=$is_doc_site
10 | After=network.target nss-lookup.target
11 |
12 | [Service]
13 | #User=nobody
14 | User=root
15 | NoNewPrivileges=true
16 | ExecStart=$is_core_bin run -config $is_config_json -confdir $is_conf_dir
17 | Restart=on-failure
18 | RestartPreventExitStatus=23
19 | LimitNPROC=10000
20 | LimitNOFILE=1048576
21 | PrivateTmp=true
22 | ProtectSystem=full
23 | #CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
24 | #AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
25 |
26 | [Install]
27 | WantedBy=multi-user.target"
28 | ;;
29 | caddy)
30 | cat >/lib/systemd/system/caddy.service <<<"
31 | #https://github.com/caddyserver/dist/blob/master/init/caddy.service
32 | [Unit]
33 | Description=Caddy
34 | Documentation=https://caddyserver.com/docs/
35 | After=network.target network-online.target
36 | Requires=network-online.target
37 |
38 | [Service]
39 | Type=notify
40 | User=root
41 | Group=root
42 | ExecStart=$is_caddy_bin run --environ --config $is_caddyfile --adapter caddyfile
43 | ExecReload=$is_caddy_bin reload --config $is_caddyfile --adapter caddyfile
44 | TimeoutStopSec=5s
45 | LimitNPROC=10000
46 | LimitNOFILE=1048576
47 | PrivateTmp=true
48 | ProtectSystem=full
49 | #AmbientCapabilities=CAP_NET_BIND_SERVICE
50 |
51 | [Install]
52 | WantedBy=multi-user.target"
53 | ;;
54 | esac
55 |
56 | # enable, reload
57 | systemctl enable $1
58 | systemctl daemon-reload
59 | }
60 |
--------------------------------------------------------------------------------
/xray.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | args=$@
4 | is_sh_ver=v1.27
5 |
6 | . /etc/xray/sh/src/init.sh
--------------------------------------------------------------------------------