e8QuhVq=e+%W?|9z|&0(P0r|On$uWg!`{S2NxTdxoz6vEbRK<}+$cXuK zO~`cbkl|@~03o`XZ_6E{HMyE#kacQ(N8rwjFlbscjv~G?4yAo|UOnPW+~ePB>bLiA zoGs8AW1(L3(+(=Brzd*cU;8HsnYgP!7wKp!h8Lx$E}mbx)JYYmEI$A?wyN 40zrn46=HX?%%Zp(~5Y=cW}_a{2G|O6tV(Dq_m+v3LBn zA~N4$7X{*S1y*RS;YmEb6Z4^N;E9%USH1;c0T7|ASZUiC9b1oAR8!f~MY9e??Au zL5XOgkNer#BJwu_Dky^*t2$wq)AeF9U+)HCB}4zZ6X*ro|LDSX|2OL1JF2NKi1)>U zAQn&r6s3s@QbYwrS|T7_LFt61A_5|y^d3bJ1OX8VN{dpY6X`7hMUYOUOG_a18bV7T zA$dFg?z{J`x7NM?U;bg4l_mR}v(L=zna_OZe=6UI6rcOwiRd(f2NgWFfbT9qKdO0t zwAugMvuID>i)|`t_Gc_5{`<+!ew<#rZeMw7ZlklpR_=EKSH^|Q qS{}xl{@8?c7>&S0#7V!w)-&a2~q!k z^xh^dm`!ed-nK?M+<;G&tThljo-iwcTScIx@*K-Q=_rtxA)RV(o2~M+UmS!Qz7!8| zc}(F9Z0-h#earS8IP@2oqcNw6yu7??HcVEdBT1$TP%I |N0m`+lb@*mcCRRUk>?|KS>r#9BKzaV@rb_Vf`z(eHN$zTA?^fSAw)M-(epR6 zoF4XJ;?|=_1b?ieg!wmS(T`WkVq(AA!78u;Zi2vcBkmEX)0>-e^f)4eXZbHUebLd^ zmqavHQrK?Y_yt;&f7O{dRr>XY!0Q%nz%_cRR+&mh8S{TnCJ}Dei_;xZu!?q8Q6nRx z# Ec2&djQU*TIX42D zCi$3OHGj8XpQ*J|2wb*#(7j5+x2y~49_!P(Vx)3{?Qw5B((y>t7tMcL&|J`HNfLcy zqx4YSlwv4kO{F37L-^{4gSEw#j*o$OQ}&OO4X&d%sK9MECfKKc_~=)u%Re^r?SU!W zrLt)F^XdP0Z6(u36($5S2kj)X{>ZkD4D>f&Gt<@4d45dd-F@LOuI5)4>H+Gg6LeoE z=$IkFocJGIQNnUyT$g|nBuq_RB&kO}0-gT _B%4U8|4 zNm7=NfN%!~%2xcp6STO29*htt1YJ$fzA_`Q5x}>*!z}4Eckv`pm=6f3p*W%%=(S8y zCVmCC tS^wVlge@ohle}gtxac$ zDvx&0_OW;m*70GVIJ^eUNvLbqG>cQ5lYx zca6#}e>&Uth)({S*BmVsJmH9-J2dFDo!(8%hHv?&JAZ~6OgzDsx&6+4=#w#JRU?F^ z{(T#$^+wWJwayAgE{?~3jMiH*y}j7sit*gebZ{SjG@PPfwf*LpPr$fR$KfDDgRajG zZPF>D!^Zwtm-QoEQZBtsDt)(m61c1I)Yv;+RU-Mf{K%Vm;YU_BcfI3vhwFSS2RlE{ z1>1#HkBIBOo%5dqm`D|9;Hq`}E=-p-e?PIoi@gGFQ^jHKOQ}^hh_9>5%gf+2ExIgu z1_=#dxB%SYWCgQm3%HPxwfy_c5H^ar@zk71d*HO$m>}@t#fw1zqNFUSRtu;G^a} MNC6#wyAi9CUt6ymM>*SJ2S-D|tfCsd#w90MkHc?Ff zY4253lcR&>qr~e7Oz>!pv)1c29evlK5hFY26swVnlFrKs8&aYi+P~*d_|WX&C9;P} zla{P4fqx7OEt`$-H^~ZVS}01Odr4Vd-YeGd>Rs?Wv~B%EEWw%06lk3p-ng)?cj@s} zhY--%bmPGf7QRnTJsIKPBo@q+D@(G}^*JwPQ`_&LZ-%lRS8eI~bWOB0#5rtg%CZa` zLCnB=ypcY0vz{qVq`JYwCo|zIxXyVRqbN(12omAjs3miY7k_~_I z?<(wHthG3me*UeDzsK<={|^@9rQZx*JWATsQPp?b&6OmPX&nh(h8f6!&JThv58ArY zOJ%j=vpCWtB_s&wF-kKwH qu4}{gCeT%(2YVnj?7d9a3s9 WH6TzgLV(479P z;aQuZoCostUXd|AV4R!UBE6^II|r>wK$1(su2 (RYL-80H6e zpK*tmS-<(oN*aWw@aRQ (i!DKuFWPra*O)&%3Un(e>5DtkVic86Qc%hB*# zO|V|@o 67A)C(wYPCc=49*I7bGK`|FFgHx+?2SI`1d4_Y_4hMAjYRn_r(?9Xiq} z!@g`>Eht8+vUYd;;K5j(#zpLmIgUk~gZtGdP@c}|(+*T=Ci+!z@+n0?J#m x%-(~iq7O2?tO5e8@HjO62HU52lou}Rj{gk zIfikaj_)#(>>y;-H$a=NRi5kPw%XdwRghuSx=ruV7V>V SsIL}}vPl{P+q#Oq-0ENTzwNKhLzCRzAdq{BbEg?NwR{8sT%k{Fm(w^%( zWQWC3cMGG; tpdCY#2)rYA#(jO<+86{%BFMS*wIC3-z5kl^5q+#c;v0aZPou8}H{=L^pbsFvMc9;DQAHp$gfy%d0`za8+@z zBUXjdWJu}DV)BI!V$|(c**%X3Qm;4F>?}OW#H34Xk0sHOivC8paP&qRX-_<9=jYCo zn$1@=aK{C8wWJv1Xg;giYN8D}v}spf+H>*o(9G+lM2ouoI 6Orro)a&{T2NZE zjs|
7&=F( octCswu6p@UZen%v|Iu;lY373$S{*PO`{`g`9W{yN`rV1t?b zQ~2ZV9AUrMn;orRH0OUMNQ#wN5)gOOvnIT??&Ii$a_>5eGy~@GxXi5h-IK(e4)XGF z-`=lLw13&sSzg;!b NxRD3Gwjy$&c9GtVkH@Y?&LNzfmIkREJsw{6uR_eZ_^ zeQ)APq1k;yP-t36>n+18qgs%hEqcE^d+IWNG-29MG`yaaGgK5Sm2~Y K^P?D!bSG2a%X9BBE>+ysoh3jJ28#WFg!cj~+{HbBjQbgQQ}k)ty@h>5%2_{x z+>c(!?vGgfy1BmdXm3GXaTWZv)YjHEu9E(2_^f9(|3ktj?tIn9mVG&vv!94k^i_C` zRA@&yFgi7b0_3c{&ELn|gc1bZ=fe`6+)KqAKTox2Ci$7G#V#phDf?gcUxHG@(zXPz z8mpeD|J0<>??iHVc`(PvPqFHu(`1moEB?1~eFO6B7i^%`Hza7~3YjZ59~@ImFN~|` z6!K)7?bx1{r>Cc+dR>B!H`Q(blFFVb #4j zGmm&L?_TUHwDo<;m;TEDWwA;e(G*b*zjNZYYVZV$FGTiDU n%}7jDiczHZ|8sA&wFuit_OKZ1ltm6~pLW5!}!Eo+7IqTT4}*$u=vF zEq6;BSM?3(!;&v}_ZPSwHtneWeTcu(V0*>6g}$Rb^kX_fen#6J&Uhq-3+xln-{r&k zw2!a+{(jR_#TWfHRaAQnlh#|D=ulErEL3|%{%EoI?fb?jPsTj}CyDm0h&jterpnIV zh@?sGM0y{~Tlnl}$Mr&OCKRxzBY&XjnvP)4vM@Lzmx1yOj~`x-|B$g;-?td=)v=uq z{DS|2@Nc&-rXy^39j+ |Xo0UKrNyO9=%a&J0$1gO=)GrIT*?EQtPKyV&7#Py& zZlAe-*J0Vu?R{DBm`E6$(a ^W>8_Lb<&_amUf1V62lA9DV`|(Eshf+kH FI4ooEr-h=gac=^%XR^ojVpW@f0_n6=aF_HpoaCuC}W4qfX{WiUe zyC30?*l5GmwQvunSbt+Z!}|Q`f{`*E3#}>HM=K|F>T-{5IW+kR2cD-F!-qdNdBVBh z?{d30@a_a%yRJ2hb7c3EYZbh?J!EG&B4%^GN=^{q$u Wv7R*`B)-w3>3y+V@kb@62(J1+&dc)0#rx1}{j}2QJOqx;iufpj+E{LqUs4uFBq6 zUc|lyoht3YSIC3rT>cZo?;_=wC~M~;TB%FI+n}oEgE|m<(T_K??q~LY9<~`|vJ3Xi z#)QkK*ReqDb}Yj1i~L83?$P3tbo *oJ8K+X1Eg}=)(NoU?PK!SWONlDzAcmfm&)9WZdTu#PzA?C634k!qK7PmbX4c z?)xZyhWkAGp<5 !VE}wJ9Eb@{m$kx!(&fJ#{mrt?3&IT0sn^)$y%oX+e2_W80%m9qsJZ(5kE| z=PlyfDy)B4Jv0Aw) Fgv0K6lr%{%6#jf^W2pA<*9_AFwCES7o! cX4n9e5^ zI@SeJu#1dB2UWa+(_ZKU8mGSd-go2>-k>rTI@+cDIitvN$cZgR;>rh9gM`wYs_kO~ zG;gIc*mt4WIoLX$(Wl3mO2NyTqI3Cgr|ln>Iku*E#I 6|v~$`)(<_gCg2vqQJvC7B?u~!B$t61SuOcW>5@$`X zWZ`!4J#)R-=_UHJGif8H0q34WtfRP~pl;1jFsJc)aD1u41r$iL)1ji$(p?&8t!(+) zVl@O){}n*8w0i!a`!|QK?I{ D5tSEqrz zqv43#ZH7jUhh$oG)srrM&gIF$iy|vS{ G{e+KdRsKOsRKtsWsGH?*UR zWZ1w?yf-Kq3vC(me$+&j3-aC-K1y|RUgOM9J)9|B(LJvAY0=dZgN&*CXjNQ6kQUqS z+2#@o`}Egzy@E4%-HxHkPtcbaLOUO@8 dnsVR+xZTZrL}+11u302!{ehzALJg|pHTN9CW*@kO?*Y+4 z>A3+lH7A;kB<)hEu*uI|8lBq8ZatYDu?ASVf`N!Qx? zoQ?Bw%_>)+rE76kg<>J3joo5-BE+}xv`}ztB`LGWukTx{e68=gOOyHgu#6+4+0Ab# ziizq$&TG3{xPh-9ltb>U2^@bHMwyBC-x}Z`shu{&P>~4b3_`F8txI!=mt7->=+@)n z7wO*Dd0kmEw7xRB-=!;MbMP(o;5sz@{^h2es*rw3I}h#SMYNhO)K0+uAD_WCL3sx; zyLsS$o6|vII7z0zpd#edvi!g`9}#6&wnDh_Ld~!IHqeMSTK!@Q{lNo35Q&EzLk_c( zSguq?pCrgQhWSx+Xvv9-mZcvsfl>wL=13XAH!-OXQGU)- zb*zNKR_cPjDzeJt8AM{2$A0!E_ix<4*OTEZ@mdDw=O$t+LZ%=?jGez?HuB}zy|;+( zyl$A7TygrTn0V8rg{8;Q#5ua=ljhc@U@3L8d NIY}KHBZ0i}7*cZo1O3o?9 ziu *iBHm Y<#Rbt_&Bz8~yg~) }chZuGcE zn3FWLw=>PfNP?FEK{PH@d+6p9PQRTR*lO+x!PbmPU6J~30mL}Uag$#VoG!Mfx!}L- zGDPa7WF;wus~gfAL3B)I rg%eAhF5F zRG`VYEuKFWFKvP%$<(-Wi(h4mwgn&pYOkcq%()2ofM3e;{T{Z#3t3z!@>h?w55i9A zGRaHDn#1j{v1UkpoU;2c3Cb9hWW9Z4!TF)uO0+H7r>Nl&rhY#8AP4E^9NZ|9L1ZW? zHZfN486vjP^_S-h9@nc#jyAZfCMDIkbQwbvKdg-I@t-j)e|Kk`UA?^V`OTQj{9uA= zlih|;Pt6X@;$EM$Trx@+mB-)0SXY)j>I=We;%?DWx(ngPXwe{~CM-g*;Fxa?q z=zIT1uZqN7?Q );Vzwgm zZ!YH_-c X7~^ub1|mH z$8EE?@aToNTtY#W$x2`359%d+2>n9AWaC0Id9GMYc&1b+!2`Iqdqat^f|P=On!2Pl zB{L44GgvF?w@M9$R5iS*_0?4N)_aY;S@c2x8CVpX(!WcFJ&7|2DZbz*v`gD?L|WWx zpKD?xo8}m|&NVUiID5E=Ewfz}A4iL~RtB%92Q-?y4XMWr93vTBo$C{xwsp<(9e=za zEmYAT=w3l1f1}jUERzlCE$t!@KLb|A^9#14BMX(bufJtI<_zjKS{h$DB7#`{duHJd z2OU!ONUL=N_jw+ryxnl3%f|e>q07CF>qs{~m3lX>M#({o`-;JRhafpnu%@c-o!u*$ z5$&?qgVGzcrj6a}x~o1J=R__A8!fXUxBD#}4Ec8w%~~R#2xUhI4UFJQ8i _9DQ1DGP4mMzwu3MM3ggN zr%YWddx~eSoIk`g=xlXMGF1m&9;C>Av)RR*iuMVQ`<`mc!vg!N;`3D{G1Z0P7Q_Fh z|4cm8^{H30+g;YyK=*to4vVsx^9 |tkkt2$;;)Zg6oRUHK*HFR%PMQHO^kD?u(~@ z-&n_P6v(`uBEr Hn$T+Ux9))H^@hs?vGK5GCzoODk zZ3Z{f1@cAp1b9aHuOebywgTZY&>*2b;!lQhkGzDBC3{?6nJzL|#rybe^LioW#+ %>zWbOO*Ms+z KS;LgwVT!J;jmM$-(z(ehx#tb2=)xn#$?XWYDo*|-s2DXBAY*)MZert>Sl z;~Z|G6nr;b)L4|Rv0+Bq^)O9#Y5VzOhQtF@q|vhlQ)J>o+PNzfh{-yt;!u9Z55BYg zoBTX)u;Gmbp;f%meUaYJHWs)iA+yy|xqY|NSSPQrH>cbPNPImzb|7j0|JT&~@XtKa z*NB}<-y=LocC>r_fvB%(e6BRWE7s(m3a-?{W#{`0mL^UYsSaz*+n3z^9+&khdn_mh zRl#L7!(x3Wj3Rl285?RvHiU`TVikRsE!0)sM{dSd gN_~oD`pZ4z68p zvVOwC@_Yw|k?dN8HvEXv>xOJD;HC3t^&Qy4_1!=}$2Lf0!xROoS+0C|8bQg(I4|@T zU+!#7%M0_#Q%6IvAf^2`OE;mr#(o+@BwLk<=oeauzGPvUC>>mhk>6f?=Q-MI^ys7GA#de_{o}XN&;Vi{Q##1P@+17dh0&8t==ekO_D*+f7V>Y~ W{Z$pk#Lu zF0(O*t&*vy5JIb%^-82W5KFD}UaHw@Y*G4P_MqsE%*HyJFUP&~epwZ(t8$E1W{*?3 zKCW_DQpl}@jZM0g&DPop$dI=%@D$6wS|yHn0N!oiI>R8I8wq#b_05zp0jP}YH#wH- z`KRXy7lBYIv)sy5O6*EgR`{Btz6Hvw21+4clha)QFJ@a0uTM-&8qJVyac%7^y79dI z(Ak^bqW|OXj)yV~1ZUvA$d2poyMc!pn#jDD zEYB~enntpLNk}X#d_p3E%-=5$s{Qwguo@R(AM+C(F0kLiDqD@CbAlgNu(mhD{4`Nt zzhNtasXlfOt^#D1ev0`$;X@*Hj%%(Xa%W|q+@U?}= )}S8u9~CE~PK&nD-l}8N14O=HGvQ`2+#Q1zNJn z!slc}MSp>W`(psyMnk=A&w*#k90)RLqZR^moB< 07dA`7SPLY&m8K*oYVr4zRFL5 zDM^hCP^i4|u<;-h`H&J5%jw;*7)h!G5W)=rQqGtB{ScxG68^{vrXq8IR8~uOiUL*; z K(*D;2^WY4wx1=4&)}Zu%_NZs=gFK?_f+$ zezD}v&Q5(xaW}Jy&_gbMdPubxbTTvBtbyDGT{n&utp8>7D=v6=u3MxX;NO@9a>(u; zvpFAhPq{O<4bs>W9qZEM4}eCdqQO#ccE{zpe917$CdulYtgOFa_{d|Rww}eTP{W}i zv}(Z0whF>&FQ7sNU%vbRBOnA&C;!;X@d&G`j&}?wd(A%pccbFxYc{G&k9foWO7V|N z*MQt&IkQX;{({v)t?9TUU~5BcRO4);i>aVj76xd@%%QHXuC3z{phc2e{_=+Fh($}R zz}`k5)m&2zNK1oxE^at~F354_Gr4j}oyL< %-^ z9L}sIbX6!eR7^}PaN@Y#YYBF_2-|^!IT=)-Kv2~id}<6xGfzLX@v^~~W6VAS7P-Qy z=lm{Cez*9KkkumUcsNj#(sVxn*7(ojs+%Y@xty}xM+Q@mRGdrdfSkmzHogI Jske z-}z$JB`L_*{r=0rCc8LbMr9J?vU|3G)&i9nfKRsNasfM2aCys5`dJPcY;dSqEhqDy z{qqD(x%V>*!Q2H>1m+$3;jcH99y5AC0G`OP03OK3k1;Te$qFb%BaQuQv{EW`aPLJl zf|_har}!_Uo{m<7VG7jk=Mp*QX9E6S{?hC3eU7%-XDArL^8?H>;v&yS{^dgT_^P^r zfm4aA8-Qv33qbbC2Fa!Z`$?};1bgU_t`c`JQVUGwx;YC*9OM|1$zO(Yu@8YHMPfG` zG`Vm8(cs*fSN&&Qe$2cC8yCo~zX7zz1=tnA-W%@Vy{SU+%Opn&8dVR_+`FLWIs@oU z%6&Hh=)ie52_#b1F_r;w8@q|@C}t^MVz#Yo*Ymss6TUQs98h}CBF(jb0=|FNbH+Z; z#Ljb6bM7fWL4K$K5C~$@-*bxA`ag@*Hb9~+n2sl}R%a#zs)q9L#^0IGx< zWv-TaPC*F+x3^vD8Gb)8ZYf7A#oqkQ5Zb$Fq__qrA!7c60W?Z7=Xlb2Xz~%(+0y`; zS6#W`DN$wqJqE?{e(|79kqSy8)ItIepLoSaQ=OL=w}>#=&j9L|&12NZ{KMvsS}LkH zwri6&g!F&f4jffN-2haN-kdkw+auRrBkkP(T*p=Z7eo1L$;gm@7TaKE61>_Q&+P`R zePi-nTy7?gBHuRF@unMp4+gU9K}}Yf3$R;;1N$5^*6H8%fHYg(Kn)jO@k=S~@8x}_ zisQis-sA5ZYr2t(n7NsmYbTled*Xvg(-iuT-X?$BAllQF^bK!V(V)Uy!Nl_a@=bos z4_Hnf{6Dy_|0}+d>K%#g>Z$-UQ~m;yuMoHgx|jNBoiECDtoj;#O|y*Y-GDYf7+5Do z@3+*~*Jm~f{Ny-tL|R4$3(#b*=3sZ`t$3bY@FG%1My3iNw=gCi1>nsJrji5@^LMbS zeD=0sNzoEG4&RfhGK*doV91Jtqhkv)|Mos|n;5bjXlS$`Yn?6`q&k7NfGQe|Mlp7D zT^XsMrvV;sOiy3G$Pt?kbm-BPx_|M(6?^&PB&K4>I6y$RK@-pjV4 $+N8j$s`w(1VL|3U2BvKr*tEbu7!v?V0uL)jUsGffEaPy- zo*+R}loY439_j1Gyfl`R8Zqi bEY$CHg!G~K>J3RAN1?1x(rGY F*M%!3`)zY D|2imlhlYK&55_Z)zZ9 z3*x6f?anP*2yIOx1q>qFyq3><8WL0uoLD!wH{7aMb_>DW#7PtpKyPGh6##R3xKL3C z!*@aN3&=S$Z_C8GX(ktACdn=!(p)?y=fwC`VToJY^F6=#Z#;7X(j=uVf`OfaL2GK9 z#M0-J>UA64%03g&MaXHq4;np4bgntcuddN?#+Rs(?{dHI0CiTwCoF!e(7H9D3_ z=Ap8G-~jl?M6G-U&q0Fz0?`abrm#s7m<@wFagS%5Tu)t%e&gIz0bKOdP@lc;%E-(s z7*QLGGT=xvZ&AA$5e(*x_yA3N3NTV|TzbIbWtWliychxHL2QBS7htP;=H3GooErF^ zDft2`cbaS<;v4W!fuJ}*CUWhx1 j1jiCM z3RD0IBdOg_0B0RM;HTr+DE~pIHxjcS-G~;?g>3%OfQ(21Ke2i5>>Cqr3Gt?gS2k+4 zo{i*{QNEf7Jk0)&S1LYN>O(6UpFeBSoa;`*@C#=>VD6DXo|jr1Jk`uVR29YXiaCDe zbv (5yY6FX!qOPe%8 zmd|_gKXd~j?PjIch`n~F{8Jhj(&zVm=*6DNpP~6`rzVx<3+&F*Fo&&-TLp7RJ0=S< zdOgA^eXQd^cL**dVLU|h$MDL>tiwsod~}PutoL+-3W17tfL~HF$fQo1d*6CiLjyx% zFz40#jx&43-~s{6?w~mMH^4(~Ej1f$z3y&_ZCWaG2AFRrhPi23lFInQ{kkri`@KuU z3+jv3XRs)R&?tIya$?pZMxJPSp!-Mtt2rRYx#uNfJ15sz^fLec^Kh5Fqr^-up+mdx z^#)x|668yZs7 ?pML+<6MEzf;H^2eA*4vid?$c)SO->Wrv7CE#xptzs8G@YYh!zA|=b3s9?BgI(o z-mf1jfS*G~2 t_|ly^Ouwy^E%ccZQN%ith&&H5H%ql>U9Gwn+HgSpqORhs^J{4v3c& zqgHU`8Firrp}~53QE^gG0A(_V3+?RjR8DEsYc*_*+>Yx}c~QhGBov}yX=w?GvrRiH z664Y0dpyjOZW@AG%1^b~*!oqo8Ssubz7G+&sPadAM}EkfJ6JmZ_8-Swo(1{q%$A~2 zpsjRTAa7_3grYOd=+RjCMw81ms5EbGH>-EyyuWEUS8RPjrur)zqG`dr %ve6jt7aoYI>@&T@ybzWv zGQe4i#K2ra{BIiB@~}SZl8GC~+LZHH-GoE3T$*G)<%|Xts(b2WFYu3ZcFb!?IG`3u zB*}$>W!1_J;dG_bazfC;levqvBEg3^nsWje`6l=LF FANG)%%2PF>i=RjmcyZ3|4u8nLT?suA>-pGsXttx8vroxagyWzm$hL2Do`^{ zw?+Gv%q=D7zKFB~Cl>d_8}`4CT2(*)8sY!Hz6X*k1Mcm8?E~#Y?ZX4W?KL>}T>=5d zr+?wZzn7OqJ}amwwFqq^FmRkSq8tpy$uUp!|6K~pgw$n6Nq0$Kq;7=<4dfx70ckrk zBcqe>|1Ko;;>@!d*O^t>JfBE>jb{!9bk>q0{slTe6pe6Zs}S!0aa~EL|E~) dXS zJIhO_r@@oH>u-ig%+6^M@^NTuDN@N?^yE|bS9@jY>`a@Km6R+i{S{G&uD(gXQ}NN^ zv4y{_Ep76t q;f!idvsJNQBsobWim{%H%m`2Uibv3x5Sz%A#^s=3wEiORW~GbYs zr6rx(_xeT`M+0@Ry@2veog+Ta+pP=~QVE8pc@uqcMH5qJdPYBEy-H}Gg__4QpOmH( z?Q1f%E!v805IqDDNnGtk`W1Rjc2&^dC|;R-ubbqp62zW0QLm*thp@FIMNHE*v$Z%4 zUqp*jJn9{MmQK@1AGPUP9ihmdc#GfMuA$hSgs3T=W8g0F|GP`sRI=5sXpB^WBcEhP zd+9nYNK#+7q_n?ZIIO6uKhUj&(3MgoC5_3*Hs#p*Y@=kM)#8I-Ov<_Y6YE{uh8S%g zc4zrj5nDla`tBa^=PRL~9FMC{H(f)heu-n)QU+A?UHp*Q(2-WF_PawCur%fKRYGn~ zXX50^_g&f;6RP_E3fm9M+5V=U(2(*SYyE;TtGRpHet~mbNTucNm*l<04n)uF{f?CN z%Iq U9_$J=7C3bTtW$T%*zRSo}{>_4n` uUC!2UFqdaeej?u~n7_fQu5^K&Oh<_GOW)9G47r%?Z|P>Io+)c~ORQxw z1a5jZEc8JNY1-cGDkGY^rMnDW)nc^{rB92}`9kSWHgKPuYEXvkIA6(*`9Fhr<92B{ znVdq} +^U_w*f-8V&qRapbrNhpD*Nj~PkkH!Uef<5Eo5JY)?6D9Vu3{If zkpo+y_kwdA%H3x7K|k)?aqM6`_URnxG+M&BIq)l@?v;mN;!Yw@5%9@Q!!jy-H75>Q zC;B8k!#}-fbpr<53sha+T^U!FOiZ0KOnLTMK!}V#!YBPb_5QESIl@frnTNx{fw$cq zIR&2iC*Zg7eJO+F`0dVBf!AbzOg40^bsgv5;h}wOg9>Uaj~0pm-6zHB3E7CBL0?V~ zbzS@@oLhe;?6-@Q?`Es;Z9~-;ZtE8$KauWd-=FWzLQ2gb&8@oE%%zF17Z7B+oW6@m zOKGj|akmCy73MA{j{NFCPfK3kg}@0<1hbl;;Qn->O9Hm``P w?S)nc*s|_L3 >BmDqC4D<{g}rW6l(Q`!`s$yRI5+EO35Q|o zUe7HoI`mp%y$ )}d(X)uP3iH#f0}4; 7XWQR@B4j;2VYh}_;iPXdW;Yo}^j)m69&a#Dn_bM
1jBT&I_t-O~8)w#A1_x?(lS6)c9BQ!6+fYl~ zm* T} z+JB9j+*$(+f!|7UYwDUu**hOssWRih4mdn^9Vl*kXg_!lcGe;*`|h q8Km5vn%A8H{+`jFzWGlNnYuSAUv6R}Y77<0sb&@uEO?eqP`nLG zE@}9zk#i0BY>YV|NEd&1%!!}~ltsHY{CNGZq0mv375!ZqG9UQ)5Pzoea)*5cV@=uh zE}J3JPaHF<$<#VHDfX>Nx!P`5<5-bXb18R=#N+Lw`+bLwBN*{|bNC~nqgDuyQ8?Ss zX?{gsxvoGg`~JY2C+z~JBWK>3M!KI2n^Qt$)-3qfsIi=V{MoQ_D}Ij_=cozeYBVBZ zhV^{h;sT#Uql;(nN?~R+1b0RE-R!-tq+*-*O!cFzM{f35fGZb^5PJw+^t!6>7it92 z@aqlYiozrHpn>SD8Eoo9%e?@rfT L)DD3GK7H5bqlY#M?nmt%!)VT z>FbRd6Ut{61WwHGhzzsBg%%$imONwf;)`(F;1{zsf$>FwbCVz0phA2E`A6xvWi?4$ zsbYYT_vr;?spIL&CWsHuEHSk(SXy1^67GrR9 Z2XWji$54ae>1@Fiao-wA`S! jPsJTSr<+c 90d^)#zewmH z;n-3zB%p1uh~&GaxCJ?n%k-q>wWd;J!zsc+j^)miqBK?z7yK+dV@4TBf}k*0*|#N- z<`0Gfb&I?Mz0w(Pxu7`&A1=b#aTou-Z?M(B_r-#dAQ=xpvMI0e=>o @XeXR8ekzDmBfuHz9dc(tBPdb^R@?spwZkb1D^UqR5{{jf+95I);Px2} z3Z`;d3h+OAmCr~G&HZ(B=NeJltqq5t @7a3Ao{-&bPZ{s(2PU!cnTSYbN96B7%ruP?o zpT1_|Sz_*=$CYlkFCalJ5`im>PkIM@i9K&+!t&SG=rUp7&8r<}1jAN@t7i_j7_Fk~ z+vEL;*3$!q?n2`5`tv-`r(mRfo=GUHUn|U{-uwVmx!+S}pB79v3(lzJGE- zJ!t!7y&Bix; ?xNk671G5f zk+9_=&6whph7Ypg*1uuSUd|CxxE^q4E*c?~f9_7v`6eiynJgeJo)V|cT1nD&mvmB~ z_})+!^8p?7Y#nuMN6-d+{)^Gl@W5P+BSgTGMJDS{aXw2|+Yrr5`kmRygAWs@1OG}% z$8^4hcIgDs%P-sV7VoUWE*OYF3LmwGkQ6&O(!sR081uhUs$ABnyBosn3YDAMDSrAj zJ48r8I*#_WwPeCttF9#|=Vh+2oJ&t_sLc79O<1{s%i)iX4%Gamd~tEu_aDllkF;xm zV+lUXNeLk4agcPWG%vbXnN-F0itStBa6FvvFiBH01V}LQ1zr2~oOAc1vioK@IU|WI z5rYa{I$pN?YEODc2!2$Z_Hurw>@X=GeUqMp_j? 9qP;ZJx0%zchVB-{Jb60_)*H-4;sD>=n0<8u7z zW>f>agT)`B?%%VsF3fNaEbAYs3b^dG{30e}H`so lB+4$mS%+y|1c7x4`+9wWP-Laz^z@+dSIAz^Z`%NAi5)ZH z^=7<;R=;U)>R{Hx$D^_pyqr5a9_!xl^ _2NpA?g2aYyX9-if+-}wBl J-RrtiB{}w0Ur(Se#!!GYKK4NP zLz~g4^AD{O_qD-yFp0}=y}ag?H-!b?Pz<4Ot#h;f8ZDU|C-ILD>TU6N4Sqa)7s+lO zWUj3~@_Gy1t0qbq-V4+e%E9VlEo;e56-F+2|5+|Z95ldDQ=E~>xlFNx6HQq{gzU-< zszkriO(eqoVwx0OCzcL6?fd!NIgwsIQYFi*IsLOJB2L}`ob&p8Y?E8kNXK;Lhs(MS z(<8A`Wqk>1&!alu4n}SB7Y+D0;cgUG0Y!<>7W{-&{esV?HCL`4r@(qk-Z>Rf_6M*B z22?+nP2~b}-;QTPzxiHvIPFBroJ`ue?Ski2m1WO>rP&nxjMn-qI+}s;@i-Fdw@T?z zyV+GfHYACy;jFTj?B^h5XCrXcu?@Djx+QguptN#2vub9~?TpB>HEu^`6eAX}^`+ zmf|qSW({}CE`1ZWPj%*7gMUt_nHTnqe5aldaeJU&Ufp&;-M2*LG5o43{rN?XN{+mX zqm^v +r0XlxT+~i0PH56DnwI0%G0^i)PXZKK)Ft=LwEkpl{#)Mo?JQD8t9ne+Y1t} z$gisjvH@YJnlC4Ux>gM9ckxAQbvltlj%hu+Cy3>Lcwfy7E7nIoXp3Djv$by4L7U}p zh6V*p1t7L3_7FXlrhi~su(hg8X&QkM3lcE~OnR@>91%43E01jk!MSt(#mHH@Nsy#c z; On-N0vd@V9R=tQrMb$~Kb9U$94S~lXViSbcFUY5 8Eam)UK2Zu^Cuicd_f)1+qHB1G$g)D=t`j^CIK5Ag!ToDJ0^yattCq+k5 z{(Bt1V3u}Ee7Ol~M@~FV^ywkze_6I7sgAW874KyxuA+9SrY$;yvWDhL-!wUmiPgC4 zg6@`iO?dM;&e)4~WIp|(;3Nlf;NaYt7-O#i9i_IO)39WP)vSs*vfsB`A4{cef3!l8 z8|p%b%P_s_iCjG{Y((fr+YJPNkc=~DKN+)Rdii8sm-U4v=%O+2W=$3w`M!6=>XZxX z!MlBOa$>dvT#g%La8~{=rVmWkUh&MkYxPq4?ZM$2aj+*K-7s8(Nvd}AS>U1xj;&I{ z9LilBnhVS=ExA5i7j${(9J2_6P3?-oxV{+?(LaBcYH3NP9dT=Mv*eY8kC@=ytqbZ4 z?0>ROn$L`YL*(ZD0MnzXX7}S~FxPrK-W;tgTs34vO(D%ny*u9aNt#p83#Fpk!CU^} zEd*1^;4G``jTzP*gzT<7QV11Kp)@b#XIw4d!Rz}Fqo6!9nH@!fCFQlgRK4|*yQ0mo z0UMWnx8sI}uvB#W*X6$@6W+L|;9#0s{lL=y@ywQRYC+-nWns?1W}{+;)#Dya)DGpd zYAvjO`z ?_1#SAw 8I7!5JR>>n4s zSG-V@3a$1P1wXOydi=W^U3)p-UO1)K4+{KA4F)M!SthHu%p(oEce&sHs#Qa`hS4NV zrf@A9Tl5@fElCNA<>@p|SrT33upBYFyRXoTL2s94501y%V>LsnqIzcZLSN>2EN9Hb zhmR7RPsuZ;KHF9X!_;ndB1vCo3{Jc52-VL~lg*XV;@z69ZcxRGuyCaDHFK3%NJ3+_ zX#>K~76uLJT(C<~68-QYs5_tyhe=F^KusY{LgszGUzZ9zvwK6me-cN`|DWp4EUc+> z3&W>cr`j5*Ac|n5wiN}$36wF46)PyH2#6r4XbWTzMaDp4K?MiI2~ZFMDk6p?ObJRD z1qDG2G6fQnfT*b?AwVDrWZ385iaveL>BYG@7tM9@WdD2r!`f@T>-!x1{4CR4-UsgB z(4}$Wxe@l~gz+||2`qGmKJAJa%AUJFg9K?eLR`-|iHn-d_?0ibnJJ8Zl_kHT)ozKK zN(17G{r^M$_@DZfSNJ3W9c?h3E}p+7+V_cS7oadxjBJjA29NUi`1rp`PR9lZ7r=zp zBH*a <$-zFo|R_B^ixAkk K gqQ)zC!S3Etu0ZyJCK({IT-#3AR8`01JXmvsV4os&@ED?ZkhYG*}MZ&L#&K`fY_ zz^_w1>DpB`qsG7E3AKT^Zkt-V)Uud}E$h+d)g4vsu74(HK3^#io(lOiKOfh=@=ii* z8v~T51mJTF*j5NM)nP#`T4;2KMTZ|5Y-0puv={(8R7#Yp{pE)Wbs*-P__k&0%F+%) z{ONvYvLGx=Q_#B}Asbax`58_Rq)4XwM!&u5JOYV} Z+hw`FLdC$;4zMoAogy zW#gg32N%ygyJWxx#Z@dI*Um+nHwf}8BuCFG1r9|G+RoV9Rd&!yuGS-i!o7|0mFM-| zO>Pud52GakmL1F8r*DZEEVtxZ_gic0aE}LO!?LMZeq}G92adtiD(`g1ZkT^@PAHub z4wSXZo~8AP9FN!#JcaeD21iH2eg}E+ltb*RpIp sw`s@CCo zPAX~U8akO 5asf(b356Xu;TJMsTGc#E #Q?0@amq1jSH%*-0w{VM28RFf7$T^E2qGw<-JA7=TVv0K4NjR)gc&qL7Y4 zfcj|sU 6pzSCtmI>fuaRYh`w+BBoZ;_!k3iusJN;=Eq&mJ8qLtS zgEjHPk<9hbN_6Lm1kLIwu>-HWrwF0oc($hFgCML<8x6~R>YrK6!iCf{6FiC6cw?O* zHQG&P3%Iv@RGNbsL?m=Dq z2Cm0CNR_aoqmb_ed!b7 zGW<|Mz8JO_0!XJX;Bhc83DaNu6+#944r&1V*HTXeOf&3R1bby6ePHMjNZ13dDd)?J zj{p>i0UI=1V|w~oWE&} I-@9M=%DNrb6Y15WD4DT-cJ<9hK06W{o@>Zb(b zv&x0{-n)uZTGM(XMOQfS6ODzcv&M2xVH`ucr=sgaakut$L>{CaIg?y%%BLlCM~_=` zODwyzBTf65+6$hH7<@_Gcs)zLYozCdH?sHy+h{_UaL7(OvA=wJ- Es7u^f0lf* zz215}p-K*Q`2- gUDoC`Z1Uf00 zp<+LG#SBvQM4Ll0=V+B|58mfp3M@$_td#~}U<{}@+OBFyJU%>iXuyYD59EbK@^)9t zUN8(aq!ywiVD(SvfWQ?X!!{NAciwjcbWN~L3$(zh?rnJ|9|)=$Uij)71nB8lw`!M( zISY(}VB#ZO%IDE&-xC~8+&vp*m0AnA>U4X`wc|}#>%l~l#ZL|`e8kfy@s-UYt5bY} z(#x^{xd~5_>~f)xlEjFolTPT-_MZcEq=*#r(xn_q$!=A9p_hU#x2y|KKVgFtP;7>B z37s$Fti|;X4Aqv5s@%5e9jAr; yfR2h;3>B`0qQO#C}-mR7urc`lkMz_%zbuZvOh1R1Uhj((5@p9&cFe ze*c=1h~P*wOq+JdFL-a(3MLGEM0J@KRx7x}Qu-^cs#u>9OMa@<#lO=y$X_-XGcdA~ zh|w5aawm &F@%x zZ}Qzq!>qh^{5fJOM-;RAhWD@DTfBE_KtL5Dh?OO$4~cBX7kkb*D;r&C(ty^VtYI9) zk<4w5QD$Su_J$`{K+>2?Vn)6 )H0+G`f&m-Q<%m*>KKFmchvjKePb z>k53(MtL%9I1j8(u+#P#Jn`^hUJ1rkcs)V_S!PR2{vK*c6i)#Thb!lmK;OJKXKMn; zfly*-jb=B=z&(nKD+Qe5WM3p@AMKh3AfWgqHO(@BRs0z?9v(+IL-QQ=oRy t&z9bxo>=f2*5|{E9ENdAF 8Sic_ znMWE{=+OEDRJZAAdVYcR*?P=kjY|zxev1Z)ZMmATitn-+jfUd~f7kFiA5^b5iJ5#t z*aEZ8g`dKk8Fok$|J`*5>JF`t7>-f_JqjTGr^1#*-&)W^(gjPSBRIf4ZNlLl{d*12 zpNu;VTbIFIN>lWwDp>Bu7UADGv6$jQ^Ay7k4X`?GK)}{R3gp_uXGpLN_{1=e3(lu^ zDIPY}!!%u$GFoL7Y_OsMy-_Uy=c2*SQic^57 d|inqrBuUp+|p@3{vaEtHp2aF<81&Ip8%xYZX5qo(?v9P}J zPaz=pH3y6Tu&=CswF)CrjKmE55LL{!&5T&*RGAT9>D);)P!n1M&EnSCS=cI=bKK6J zq}bAA8A7VSis*k&Qq10)Lkoc-jlF{)){eC3+LYN)SkRYv>Gvc=W_(!e;uNgV@ILGG zcUgA4$*^DpvxY|NS&EKUPZaOT26|XDCict8Zvq-C`_^nva=-a`bNtT`&N+$Zv!a1i z@p (UeWC6$lF@vU?cV~ zkU*UQLD)oG`Stb=qBZCM2Jz>auswc$7$BbZ^<>A!)Ys&r1H0~x>|6A 7!q!e}8{D@okf?rGfY1ysRLgk0jSs4t=e> zI{Ut0ax96*52k3W=Q3B*YT7g2*Fpu8r|_62Yc8QE<}3f{@n`Gl>-&HUws_F>V`ZZ& zYgMtQT`A_pgKvFf^60HgtiF+&{1;O7e|jZOg67XO-MTY(T@fD+&UbEi`-SRsIR4)= Ct>(f2 literal 0 HcmV?d00001 diff --git a/install.sh b/install.sh index 4ac523e..d3705f4 100644 --- a/install.sh +++ b/install.sh @@ -83,12 +83,12 @@ checkCPUVendor() { 'amd64' | 'x86_64') xrayCoreCPUVendor="Xray-linux-64" v2rayCoreCPUVendor="v2ray-linux-64" - # hysteriaCoreCPUVendor="hysteria-linux-amd64" + hysteriaCoreCPUVendor="hysteria-linux-amd64" ;; 'armv8' | 'aarch64') xrayCoreCPUVendor="Xray-linux-arm64-v8a" v2rayCoreCPUVendor="v2ray-linux-arm64-v8a" - # hysteriaCoreCPUVendor="hysteria-linux-arm64" + hysteriaCoreCPUVendor="hysteria-linux-arm64" ;; *) echo " 不支持此CPU架构--->" @@ -113,7 +113,7 @@ initVar() { # 核心支持的cpu版本 xrayCoreCPUVendor="" v2rayCoreCPUVendor="" - # hysteriaCoreCPUVendor="" + hysteriaCoreCPUVendor="" # 域名 domain= @@ -153,6 +153,9 @@ initVar() { # v2ray-core、xray-core配置文件的路径 configPath= + # hysteria 配置文件的路径 + hysteriaConfigPath= + # 配置文件的path currentPath= @@ -214,6 +217,22 @@ initVar() { # 自定义端口 customPort= + + # hysteria端口 + hysteriaPort= + + # hysteria协议 + hysteriaProtocol= + + # hysteria延迟 + hysteriaLag= + + # hysteria下行速度 + hysteriaClientDownloadSpeed= + + # hysteria上行速度 + hysteriaClientUploadSpeed= + } # 读取tls证书详情 @@ -239,6 +258,7 @@ readCustomPort() { readInstallType() { coreInstallType= configPath= + hysteriaConfigPath= # 1.检测安装目录 if [[ -d "/etc/v2ray-agent" ]]; then @@ -267,6 +287,14 @@ readInstallType() { coreInstallType=1 fi fi + + if [[ -d "/etc/v2ray-agent/hysteria" && -f "/etc/v2ray-agent/hysteria/hysteria" ]]; then + # 这里检测 hysteria + if [[ -d "/etc/v2ray-agent/hysteria/conf" ]] && [[ -f "/etc/v2ray-agent/hysteria/conf/config.json" ]] && [[ -f "/etc/v2ray-agent/hysteria/conf/client_network.json" ]]; then + hysteriaConfigPath=/etc/v2ray-agent/hysteria/conf/ + fi + fi + fi } @@ -299,6 +327,10 @@ readInstallProtocolType() { currentInstallProtocolType=${currentInstallProtocolType}'5' fi done < <(find ${configPath} -name "*inbounds.json" | awk -F "[.]" '{print $1}') + + if [[ -n "${hysteriaConfigPath}" ]]; then + currentInstallProtocolType=${currentInstallProtocolType}'6' + fi } # 检查是否安装宝塔 @@ -390,6 +422,17 @@ checkFirewalldAllowPort() { exit 0 fi } + +# 读取hysteria网络环境 +readHysteriaConfig() { + if [[ -n "${hysteriaConfigPath}" ]]; then + hysteriaLag=$(jq -r .hysteriaLag <"${hysteriaConfigPath}client_network.json") + hysteriaClientDownloadSpeed=$(jq -r .hysteriaClientDownloadSpeed <"${hysteriaConfigPath}client_network.json") + hysteriaClientUploadSpeed=$(jq -r .hysteriaClientUploadSpeed <"${hysteriaConfigPath}client_network.json") + hysteriaPort=$(jq -r .listen <"${hysteriaConfigPath}config.json" | awk -F "[:]" '{print $2}') + hysteriaProtocol=$(jq -r .protocol <"${hysteriaConfigPath}config.json") + fi +} # 检查文件目录以及path路径 readConfigHostPathUUID() { currentPath= @@ -563,7 +606,7 @@ mkdirTools() { mkdir -p /etc/v2ray-agent/xray/conf mkdir -p /etc/v2ray-agent/xray/tmp mkdir -p /etc/v2ray-agent/trojan - # mkdir -p /etc/v2ray-agent/hysteria/conf + mkdir -p /etc/v2ray-agent/hysteria/conf mkdir -p /etc/systemd/system/ mkdir -p /tmp/v2ray-agent-tls/ } @@ -1036,8 +1079,10 @@ checkIP() { echoContent yellow " ---> 2.检查域名dns解析是否正确" echoContent yellow " ---> 3.如解析正确,请等待dns生效,预计三分钟内生效" echoContent yellow " ---> 4.如报Nginx启动问题,请手动启动nginx查看错误,如自己无法处理请提issues" + echoContent yellow " ---> 5.错误日志:${localIP}" echo echoContent skyBlue " ---> 如以上设置都正确,请重新安装纯净系统后再次尝试" + if [[ -n ${localIP} ]]; then echoContent yellow " ---> 检测返回值异常,建议手动卸载nginx后重新执行脚本" fi @@ -1126,7 +1171,9 @@ switchSSLType() { fi } -acmeInstallSSL() { + +# 选择acme安装证书方式 +selectAcmeInstallSSL() { local installSSLIPv6= if echo "${localIP}" | grep -q ":"; then installSSLIPv6="--listen-v6" @@ -1145,7 +1192,13 @@ acmeInstallSSL() { dnsSSLStatus=true fi fi + acmeInstallSSL + readAcmeTLS +} + +# 安装SSL证书 +acmeInstallSSL() { if [[ "${dnsSSLStatus}" == "true" ]]; then sudo "$HOME/.acme.sh/acme.sh" --issue -d "*.${dnsTLSDomain}" --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please --standalone -k ec-256 --server "${sslType}" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null @@ -1154,6 +1207,7 @@ acmeInstallSSL() { txtValue=$(tail -n 10 /etc/v2ray-agent/tls/acme.log | grep "TXT value" | awk -F "'" '{print $2}') if [[ -n "${txtValue}" ]]; then echoContent green " ---> 请手动添加DNS TXT记录" + echoContent yellow " ---> 添加方法请参考此教程,https://github.com/mack-a/v2ray-agent/blob/master/documents/dns_txt.md" echoContent green " ---> name:_acme-challenge" echoContent green " ---> value:${txtValue}" echoContent yellow " ---> 添加完成后等请等待1-2分钟" @@ -1168,7 +1222,7 @@ acmeInstallSSL() { sudo "$HOME/.acme.sh/acme.sh" --renew -d "*.${dnsTLSDomain}" --yes-I-know-dns-manual-mode-enough-go-ahead-please --ecc --server "${sslType}" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null else echoContent red " ---> 验证失败,请等待1-2分钟后重新尝试" - exit 0 + acmeInstallSSL fi else echoContent red " ---> 放弃" @@ -1179,7 +1233,6 @@ acmeInstallSSL() { echoContent green " ---> 生成证书中" sudo "$HOME/.acme.sh/acme.sh" --issue -d "${tlsDomain}" --standalone -k ec-256 --server "${sslType}" ${installSSLIPv6} 2>&1 | tee -a /etc/v2ray-agent/tls/acme.log >/dev/null fi - readAcmeTLS } # 自定义端口 customPortFunction() { @@ -1194,7 +1247,7 @@ customPortFunction() { if [[ "${historyCustomPortStatus}" == "n" || -z "${customPort}" ]]; then echo - echoContent yellow "请输入自定义端口[例: 2083],自定义端口后只允许使用DNS申请证书,[回车]使用443" + echoContent yellow "请输入端口[默认: 443],如自定义端口,只允许使用DNS申请证书[回车使用默认]" read -r -p "端口:" customPort if [[ -n "${customPort}" ]]; then if ((customPort >= 1 && customPort <= 65535)); then @@ -1246,7 +1299,7 @@ installTLS() { if [[ "${installDNSACMEStatus}" != "true" ]]; then switchSSLType customSSLEmail - acmeInstallSSL + selectAcmeInstallSSL else echoContent green " ---> 检测到已安装通配符证书,自动生成中" fi @@ -1548,6 +1601,33 @@ installV2Ray() { fi } +# 安装 hysteria +installHysteria() { + readInstallType + echoContent skyBlue "\n进度 $1/${totalProgress} : 安装Hysteria" + + if [[ -z "${hysteriaConfigPath}" ]]; then + + version=$(curl -s https://api.github.com/repos/HyNetwork/hysteria/releases | jq -r '.[]|select (.prerelease==false)|.tag_name' | head -1) + + echoContent green " ---> Hysteria版本:${version}" + if wget --help | grep -q show-progress; then + wget -c -q --show-progress -P /etc/v2ray-agent/hysteria/ "https://github.com/HyNetwork/hysteria/releases/download/${version}/${hysteriaCoreCPUVendor}" + else + wget -c -P /etc/v2ray-agent/hysteria/ "https://github.com/HyNetwork/hysteria/releases/download/${version}/${hysteriaCoreCPUVendor}" >/dev/null 2>&1 + fi + mv "/etc/v2ray-agent/hysteria/${hysteriaCoreCPUVendor}" /etc/v2ray-agent/hysteria/hysteria + chmod 655 /etc/v2ray-agent/hysteria/hysteria + else + echoContent green " ---> Hysteria版本:$(/etc/v2ray-agent/hysteria/hysteria --version | awk '{print $3}')" + read -r -p "是否更新、升级?[y/n]:" reInstallHysteriaStatus + if [[ "${reInstallHysteriaStatus}" == "y" ]]; then + rm -f /etc/v2ray-agent/hysteria/hysteria + installHysteria "$1" + fi + fi + +} # 安装xray installXray() { readInstallType @@ -1861,6 +1941,39 @@ EOF fi } +# 安装hysteria开机自启 +installHysteriaService() { + echoContent skyBlue "\n进度 $1/${totalProgress} : 配置Hysteria开机自启" + if [[ -n $(find /bin /usr/bin -name "systemctl") ]]; then + rm -rf /etc/systemd/system/hysteria.service + touch /etc/systemd/system/hysteria.service + execStart='/etc/v2ray-agent/hysteria/hysteria --log-level info -c /etc/v2ray-agent/hysteria/conf/config.json server' + cat < /etc/systemd/system/hysteria.service + [Unit] + Description=Hysteria Service + Documentation=https://github.com/HyNetwork/hysteria/wiki + After=network.target nss-lookup.target + Wants=network-online.target + + [Service] + Type=simple + User=root + CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_NET_RAW + NoNewPrivileges=yes + ExecStart=${execStart} + Restart=on-failure + RestartPreventExitStatus=23 + LimitNPROC=10000 + LimitNOFILE=1000000 + + [Install] + WantedBy=multi-user.target +EOF + systemctl daemon-reload + systemctl enable hysteria.service + echoContent green " ---> 配置Hysteria开机自启成功" + fi +} # Xray开机自启 installXrayService() { echoContent skyBlue "\n进度 $1/${totalProgress} : 配置Xray开机自启" @@ -1925,6 +2038,37 @@ handleV2Ray() { fi fi } + +# 操作Hysteria +handleHysteria() { + # shellcheck disable=SC2010 + if find /bin /usr/bin | grep -q systemctl && ls /etc/systemd/system/ | grep -q hysteria.service; then + if [[ -z $(pgrep -f "hysteria/hysteria") ]] && [[ "$1" == "start" ]]; then + systemctl start hysteria.service + elif [[ -n $(pgrep -f "hysteria/hysteria") ]] && [[ "$1" == "stop" ]]; then + systemctl stop hysteria.service + fi + fi + sleep 0.8 + + if [[ "$1" == "start" ]]; then + if [[ -n $(pgrep -f "hysteria/hysteria") ]]; then + echoContent green " ---> Hysteria启动成功" + else + echoContent red "Hysteria启动失败" + echoContent red "请手动执行【/etc/v2ray-agent/hysteria/hysteria --log-level debug -c /etc/v2ray-agent/hysteria/conf/config.json server】,查看错误日志" + exit 0 + fi + elif [[ "$1" == "stop" ]]; then + if [[ -z $(pgrep -f "hysteria/hysteria") ]]; then + echoContent green " ---> Hysteria关闭成功" + else + echoContent red "Hysteria关闭失败" + echoContent red "请手动执行【ps -ef|grep -v grep|grep hysteria|awk '{print \$2}'|xargs kill -9】" + exit 0 + fi + fi +} # 操作xray handleXray() { if [[ -n $(find /bin /usr/bin -name "systemctl") ]] && [[ -n $(find /etc/systemd/system/ -name "xray.service") ]]; then @@ -1983,10 +2127,121 @@ addClients() { echo "${config}" | jq . >"${path}" fi } +# 添加hysteria配置 +addClientsHysteria() { + local path=$1 + local addClientsStatus=$2 + if [[ ${addClientsStatus} == "true" && -n "${previousClients}" ]]; then + local uuids= + uuids=$(echo "${previousClients}" | jq -r [.[].id]) + config=$(jq -r ".auth.config = ${uuids}" "${path}") + echo "${config}" | jq . >"${path}" + fi +} + +# 初始化hysteria端口 +initHysteriaPort() { + echoContent yellow "请输入Hysteria端口[例: 10000],不可与其他服务重复" + read -r -p "端口:" hysteriaPort + if [[ -z ${hysteriaPort} ]]; then + echoContent red "\n ---> 端口不可为空" + initHysteriaPort "$2" + elif ((customPort >= 1 && customPort <= 65535)); then + echoContent red "\n ---> 端口不合法" + initHysteriaPort "$2" + fi + allowPort "${hysteriaPort}" +} + +# 初始化hysteria的协议 +initHysteriaProtocol() { + echoContent skyBlue "\n请选择协议类型" + echoContent red "==============================================================" + echoContent yellow "1.udp(QUIC)(默认)" + echoContent yellow "2.faketcp" + echoContent yellow "3.wechat-video" + echoContent red "==============================================================" + read -r -p "请选择:" selectHysteriaProtocol + case ${selectHysteriaProtocol} in + 1) + hysteriaProtocol="udp" + ;; + 2) + hysteriaProtocol="faketcp" + ;; + 3) + hysteriaProtocol="wechat-video" + ;; + *) + hysteriaProtocol="udp" + ;; + esac +} + +# 初始化hysteria网络信息 +initHysteriaNetwork() { + + echoContent yellow "请输入本地到服务器的平均延迟,请按照真实情况填写(默认:180,单位:ms)" + read -r -p "延迟:" hysteriaLag + if [[ -z "${hysteriaLag}" ]]; then + hysteriaLag=180 + fi + + echoContent yellow "请输入本地带宽峰值的下行速度(默认:100,单位:Mbps)" + read -r -p "延迟:" hysteriaClientDownloadSpeed + if [[ -z "${hysteriaClientDownloadSpeed}" ]]; then + hysteriaClientDownloadSpeed=100 + fi + + echoContent yellow "请输入本地带宽峰值的上行速度(默认:50,单位:Mbps)" + read -r -p "延迟:" hysteriaClientUploadSpeed + if [[ -z "${hysteriaClientUploadSpeed}" ]]; then + hysteriaClientUploadSpeed=50 + fi + + cat < /etc/v2ray-agent/hysteria/conf/client_network.json +{ + "hysteriaLag":"${hysteriaLag}", + "hysteriaClientUploadSpeed":"${hysteriaClientUploadSpeed}", + "hysteriaClientDownloadSpeed":"${hysteriaClientDownloadSpeed}" +} +EOF + +} # 初始化Hysteria配置 initHysteriaConfig() { - echoContent skyBlue "\n进度 $2/${totalProgress} : 初始化Hysteria配置" + echoContent skyBlue "\n进度 $1/${totalProgress} : 初始化Hysteria配置" + + initHysteriaPort + initHysteriaProtocol + initHysteriaNetwork + + getClients "${configPath}/02_VLESS_TCP_inbounds.json" true + cat < /etc/v2ray-agent/hysteria/conf/config.json +{ + "listen": ":${hysteriaPort}", + "protocol": "udp", + "disable_udp": false, + "cert": "/etc/v2ray-agent/tls/${currentHost}.crt", + "key": "/etc/v2ray-agent/tls/${currentHost}.key", + "auth": { + "mode": "passwords", + "config": [] + }, + "up_mbps":${hysteriaClientUploadSpeed}, + "down_mbps":${hysteriaClientDownloadSpeed}, + "alpn": "h3", + "recv_window_conn": 15728640, + "recv_window_client": 67108864, + "max_conn_client": 4096, + "disable_mtu_discovery": true, + "resolve_preference": "46", + "resolver": "https://8.8.8.8:443/dns-query" +} +EOF + + addClientsHysteria "/etc/v2ray-agent/hysteria/conf/config.json" true } # 初始化V2Ray 配置文件 @@ -2105,7 +2360,7 @@ EOF "clients": [ { "password": "${uuid}", - "email": "${domain}_trojan_tcp" + "email": "${domain}_${uuid}" } ], "fallbacks":[ @@ -2142,7 +2397,7 @@ EOF "clients": [ { "id": "${uuid}", - "email": "${domain}_VLESS_WS" + "email": "${domain}_${uuid}" } ], "decryption": "none" @@ -2180,7 +2435,7 @@ EOF "clients": [ { "password": "${uuid}", - "email": "${domain}_trojan_gRPC" + "email": "${domain}_${uuid}" } ], "fallbacks": [ @@ -2222,7 +2477,7 @@ EOF "id": "${uuid}", "alterId": 0, "add": "${add}", - "email": "${domain}_vmess_ws" + "email": "${domain}_${uuid}" } ] }, @@ -2256,7 +2511,7 @@ EOF { "id": "${uuid}", "add": "${add}", - "email": "${domain}_VLESS_gRPC" + "email": "${domain}_${uuid}" } ], "decryption": "none" @@ -2518,7 +2773,7 @@ EOF "clients": [ { "password": "${uuid}", - "email": "${domain}_trojan_tcp" + "email": "${domain}_${uuid}" } ], "fallbacks":[ @@ -2555,7 +2810,7 @@ EOF "clients": [ { "id": "${uuid}", - "email": "${domain}_VLESS_WS" + "email": "${domain}_${uuid}" } ], "decryption": "none" @@ -2593,7 +2848,7 @@ EOF "clients": [ { "password": "${uuid}", - "email": "${domain}_trojan_gRPC" + "email": "${domain}_${uuid}" } ], "fallbacks": [ @@ -2633,7 +2888,7 @@ EOF "id": "${uuid}", "alterId": 0, "add": "${add}", - "email": "${domain}_vmess_ws" + "email": "${domain}_${uuid}" } ] }, @@ -2667,7 +2922,7 @@ EOF { "id": "${uuid}", "add": "${add}", - "email": "${domain}_VLESS_gRPC" + "email": "${domain}_${uuid}" } ], "decryption": "none" @@ -2705,7 +2960,7 @@ EOF "id": "${uuid}", "add":"${add}", "flow":"xtls-rprx-direct", - "email": "${domain}_VLESS_XTLS/TLS-direct_TCP" + "email": "${domain}_${uuid}" } ], "decryption": "none", @@ -2963,6 +3218,15 @@ trojan://${id}@${currentAdd}:${currentDefaultPort}?encryption=none&peer=${curren EOF echoContent yellow " ---> 二维码 Trojan gRPC(TLS)" echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=trojan%3a%2f%2f${id}%40${currentAdd}%3a${currentDefaultPort}%3Fencryption%3Dnone%26security%3Dtls%26peer%3d${currentHost}%26type%3Dgrpc%26sni%3d${currentHost}%26path%3D${currentPath}trojangrpc%26alpn%3Dh2%26serviceName%3D${currentPath}trojangrpc%23${email}\n" + + elif [[ "${type}" == "hysteria" ]]; then + echoContent yellow " ---> Hysteria(TLS)" + echoContent green " hysteria://${currentHost}:${hysteriaPort}?protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${email}\n" + cat < >"/etc/v2ray-agent/subscribe_tmp/${subAccount}" +hysteria://${currentHost}:${hysteriaPort}?protocol=${hysteriaProtocol}&auth=${id}&peer=${currentHost}&insecure=0&alpn=h3&upmbps=${hysteriaClientUploadSpeed}&downmbps=${hysteriaClientDownloadSpeed}#${email} +EOF + echoContent yellow " ---> 二维码 Hysteria(TLS)" + echoContent green " https://api.qrserver.com/v1/create-qr-code/?size=400x400&data=hysteria%3A%2F%2F${currentHost}%3A${hysteriaPort}%3Fprotocol%3D${hysteriaProtocol}%26auth%3D${id}%26peer%3D${currentHost}%26insecure%3D0%26alpn%3Dh3%26upmbps%3D${hysteriaClientUploadSpeed}%26downmbps%3D${hysteriaClientDownloadSpeed}%23${email}\n" fi } @@ -2972,6 +3236,7 @@ showAccounts() { readInstallType readInstallProtocolType readConfigHostPathUUID + readHysteriaConfig echoContent skyBlue "\n进度 $1/${totalProgress} : 账号" local show # VLESS TCP @@ -2980,16 +3245,21 @@ showAccounts() { if echo "${currentInstallProtocolType}" | grep -q trojan; then echoContent skyBlue "===================== Trojan TCP TLS/XTLS-direct/XTLS-splice ======================\n" jq .inbounds[0].settings.clients ${configPath}02_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" - defaultBase64Code trojanTCPXTLS "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .password)" + local email= + email=$(echo "${user}" | jq -r .email) + echoContent skyBlue "\n ---> 账号:${email}" + defaultBase64Code trojanTCPXTLS "${email}" "$(echo "${user}" | jq -r .password)" done else echoContent skyBlue "===================== VLESS TCP TLS/XTLS-direct/XTLS-splice ======================\n" jq .inbounds[0].settings.clients ${configPath}02_VLESS_TCP_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" + local email= + email=$(echo "${user}" | jq -r .email) + + echoContent skyBlue "\n ---> 账号:${email}" echo - defaultBase64Code vlesstcp "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .id)" + defaultBase64Code vlesstcp "${email}" "$(echo "${user}" | jq -r .id)" done fi @@ -2998,14 +3268,17 @@ showAccounts() { echoContent skyBlue "\n================================ VLESS WS TLS CDN ================================\n" jq .inbounds[0].settings.clients ${configPath}03_VLESS_WS_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" + local email= + email=$(echo "${user}" | jq -r .email) + + echoContent skyBlue "\n ---> 账号:${email}" echo local path="${currentPath}ws" # if [[ ${coreInstallType} == "1" ]]; then # echoContent yellow "Xray的0-RTT path后面会有,不兼容以v2ray为核心的客户端,请手动删除后使用\n" # path="${currentPath}ws" # fi - defaultBase64Code vlessws "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .id)" + defaultBase64Code vlessws "${email}" "$(echo "${user}" | jq -r .id)" done fi @@ -3017,9 +3290,12 @@ showAccounts() { path="${currentPath}vws" fi jq .inbounds[0].settings.clients ${configPath}05_VMess_WS_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" + local email= + email=$(echo "${user}" | jq -r .email) + + echoContent skyBlue "\n ---> 账号:${email}" echo - defaultBase64Code vmessws "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .id)" + defaultBase64Code vmessws "${email}" "$(echo "${user}" | jq -r .id)" done fi @@ -3030,9 +3306,13 @@ showAccounts() { # local serviceName # serviceName=$(jq -r .inbounds[0].streamSettings.grpcSettings.serviceName ${configPath}06_VLESS_gRPC_inbounds.json) jq .inbounds[0].settings.clients ${configPath}06_VLESS_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" + + local email= + email=$(echo "${user}" | jq -r .email) + + echoContent skyBlue "\n ---> 账号:${email}" echo - defaultBase64Code vlessgrpc "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .id)" + defaultBase64Code vlessgrpc "${email}" "$(echo "${user}" | jq -r .id)" done fi fi @@ -3041,23 +3321,44 @@ showAccounts() { if echo ${currentInstallProtocolType} | grep -q 4; then echoContent skyBlue "\n================================== Trojan TLS ==================================\n" jq .inbounds[0].settings.clients ${configPath}04_trojan_TCP_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" + local email= + email=$(echo "${user}" | jq -r .email) + echoContent skyBlue "\n ---> 账号:${email}" - defaultBase64Code trojan "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .password)" + defaultBase64Code trojan "${email}" "$(echo "${user}" | jq -r .password)" done fi if echo ${currentInstallProtocolType} | grep -q 2; then echoContent skyBlue "\n================================ Trojan gRPC TLS ================================\n" echoContent red "\n --->gRPC处于测试阶段,可能对你使用的客户端不兼容,如不能使用请忽略" - # local serviceName= - # serviceName=$(jq -r .inbounds[0].streamSettings.grpcSettings.serviceName ${configPath}04_trojan_gRPC_inbounds.json) jq .inbounds[0].settings.clients ${configPath}04_trojan_gRPC_inbounds.json | jq -c '.[]' | while read -r user; do - echoContent skyBlue "\n ---> 账号:$(echo "${user}" | jq -r .email)" + local email= + email=$(echo "${user}" | jq -r .email) + + echoContent skyBlue "\n ---> 账号:${email}" echo - defaultBase64Code trojangrpc "$(echo "${user}" | jq -r .email)" "$(echo "${user}" | jq -r .password)" + defaultBase64Code trojangrpc "${email}" "$(echo "${user}" | jq -r .password)" done fi + if echo ${currentInstallProtocolType} | grep -q 6; then + echoContent skyBlue "\n================================ Hysteria TLS ================================\n" + echoContent red "\n --->Hysteria速度依赖与本地的网络环境,如果被QoS使用体验会非常差。IDC也有可能认为是攻击,请谨慎使用" + jq .auth.config ${hysteriaConfigPath}config.json | jq -r '.[]' | while read -r user; do + local vlessUser= + vlessUser=$(jq '.inbounds[0].settings.clients[]|select(.id=="'"${user}"'")' ${configPath}02_VLESS_TCP_inbounds.json) + local email= + email=$(echo "${vlessUser}" | jq -r .email) + + if [[ -n ${vlessUser} ]]; then + echoContent skyBlue "\n ---> 账号:${email}" + echo + defaultBase64Code hysteria "${email}" "${user}" + fi + + done + + fi if [[ -z ${show} ]]; then echoContent red " ---> 未安装" @@ -3065,9 +3366,6 @@ showAccounts() { } # 移除nginx302配置 removeNginx302() { - # 查找到302那行并删除 - # local line302Result= - # line302Result=$(grep -n "return 302" 删除Hysteria开机自启完成" + fi + if [[ -f "/root/.acme.sh/acme.sh.env" ]] && grep -q 'acme.sh.env' 卸载v2ray-agent脚本完成" } +#updateGeoSite + # 修改V2Ray CDN节点 updateV2RayCDN() { @@ -3548,6 +3854,12 @@ addUser() { trojanTCPResult=$(jq -r ".inbounds[0].settings.clients += [${trojanUsers}]" ${configPath}04_trojan_TCP_inbounds.json) echo "${trojanTCPResult}" | jq . >${configPath}04_trojan_TCP_inbounds.json fi + + if echo ${currentInstallProtocolType} | grep -q 6; then + local hysteriaResult + hysteriaResult=$(jq -r ".auth.config += [\"${uuid}\"]" ${hysteriaConfigPath}config.json) + echo "${hysteriaResult}" | jq . >${hysteriaConfigPath}config.json + fi done reloadCore @@ -3601,6 +3913,12 @@ removeUser() { echo "${trojanTCPResult}" | jq . >${configPath}04_trojan_TCP_inbounds.json fi + if echo ${currentInstallProtocolType} | grep -q 6; then + local hysteriaResult + hysteriaResult=$(jq -r 'del(.auth.config['${delUserIndex}'])' ${hysteriaConfigPath}config.json) + echo "${hysteriaResult}" | jq . >${hysteriaConfigPath}config.json + fi + reloadCore fi manageAccount 1 @@ -4539,6 +4857,11 @@ reloadCore() { handleV2Ray stop handleV2Ray start fi + + if [[ -n "${hysteriaConfigPath}" ]]; then + handleHysteria stop + handleHysteria start + fi } # dns解锁Netflix @@ -4869,6 +5192,32 @@ xrayCoreInstall() { checkGFWStatue 12 showAccounts 13 } +# Hysteria安装 +hysteriaCoreInstall() { + if [[ -z "${coreInstallType}" ]]; then + echoContent red "\n ---> 由于环境依赖,如安装hysteria,请先安装Xray/V2ray" + menu + exit 0 + fi + totalProgress=5 + installHysteria 1 + initHysteriaConfig 2 + installHysteriaService 3 + handleHysteria start + showAccounts 5 +} +# 卸载 hysteria +unInstallHysteriaCore() { + + if [[ -z "${hysteriaConfigPath}" ]]; then + echoContent red "\n ---> 未安装" + exit 0 + fi + handleHysteria stop + rm -rf /etc/v2ray-agent/hysteria/* + rm -rf /etc/systemd/system/hysteria.service + echoContent green " ---> 卸载完成" +} # 核心管理 coreVersionManageMenu() { @@ -4900,7 +5249,8 @@ cronRenewTLS() { manageAccount() { echoContent skyBlue "\n功能 1/${totalProgress} : 账号管理" echoContent red "\n==============================================================" - echoContent yellow "# 每次删除、添加账号后,需要重新查看订阅生成订阅\n" + echoContent yellow "# 每次删除、添加账号后,需要重新查看订阅生成订阅" + echoContent yellow "# 如安装了Hysteria,账号会同时添加到Hysteria\n" echoContent yellow "1.查看账号" echoContent yellow "2.查看订阅" echoContent yellow "3.添加用户" @@ -4999,12 +5349,31 @@ switchAlpn() { fi reloadCore } + +# hysteria管理 +manageHysteria() { + echoContent skyBlue "\n进度 1/1 : Hysteria管理" + echoContent red "\n==============================================================" + echoContent yellow "1.安装" + echoContent yellow "2.卸载" + echoContent yellow "3.更新core" + echoContent red "==============================================================" + read -r -p "请选择:" installHysteriaStatus + if [[ "${installHysteriaStatus}" == "1" ]]; then + hysteriaCoreInstall + elif [[ "${installHysteriaStatus}" == "2" ]]; then + unInstallHysteriaCore + elif [[ "${installHysteriaStatus}" == "3" ]]; then + installHysteria 1 + handleHysteria start + fi +} # 主菜单 menu() { cd "$HOME" || exit echoContent red "\n==============================================================" echoContent green "作者:mack-a" - echoContent green "当前版本:v2.6.5" + echoContent green "当前版本:v2.6.6" echoContent green "Github:https://github.com/mack-a/v2ray-agent" echoContent green "描述:八合一共存脚本\c" showInstallStatus @@ -5027,25 +5396,26 @@ menu() { echoContent yellow "3.切换Trojan[XTLS]" fi + echoContent yellow "4.Hysteria管理" echoContent skyBlue "-------------------------工具管理-----------------------------" - echoContent yellow "4.账号管理" - echoContent yellow "5.更换伪装站" - echoContent yellow "6.更新证书" - echoContent yellow "7.更换CDN节点" - echoContent yellow "8.IPv6分流" - echoContent yellow "9.WARP分流" - echoContent yellow "10.流媒体工具" - echoContent yellow "11.添加新端口" - echoContent yellow "12.BT下载管理" - echoContent yellow "13.切换alpn" - echoContent yellow "14.域名黑名单" + echoContent yellow "5.账号管理" + echoContent yellow "6.更换伪装站" + echoContent yellow "7.更新证书" + echoContent yellow "8.更换CDN节点" + echoContent yellow "9.IPv6分流" + echoContent yellow "10.WARP分流" + echoContent yellow "11.流媒体工具" + echoContent yellow "12.添加新端口" + echoContent yellow "13.BT下载管理" + echoContent yellow "14.切换alpn" + echoContent yellow "15.域名黑名单" echoContent skyBlue "-------------------------版本管理-----------------------------" - echoContent yellow "15.core管理" - echoContent yellow "16.更新脚本" - echoContent yellow "17.安装BBR、DD脚本" + echoContent yellow "16.core管理" + echoContent yellow "17.更新脚本" + echoContent yellow "18.安装BBR、DD脚本" echoContent skyBlue "-------------------------脚本管理-----------------------------" - echoContent yellow "18.查看日志" - echoContent yellow "19.卸载脚本" + echoContent yellow "19.查看日志" + echoContent yellow "20.卸载脚本" echoContent red "==============================================================" mkdirTools aliasInstall @@ -5061,51 +5431,54 @@ menu() { initXrayFrontingConfig 1 ;; 4) - manageAccount 1 + manageHysteria ;; 5) - updateNginxBlog 1 + manageAccount 1 ;; 6) - renewalTLS 1 + updateNginxBlog 1 ;; 7) - updateV2RayCDN 1 + renewalTLS 1 ;; 8) - ipv6Routing 1 + updateV2RayCDN 1 ;; 9) - warpRouting 1 + ipv6Routing 1 ;; 10) - streamingToolbox 1 + warpRouting 1 ;; 11) - addCorePort 1 + streamingToolbox 1 ;; 12) - btTools 1 + addCorePort 1 ;; 13) - switchAlpn 1 + btTools 1 ;; 14) - blacklist 1 + switchAlpn 1 ;; 15) - coreVersionManageMenu 1 + blacklist 1 ;; 16) - updateV2RayAgent 1 + coreVersionManageMenu 1 ;; 17) - bbrInstall + updateV2RayAgent 1 ;; 18) - checkLog 1 + bbrInstall ;; 19) + checkLog 1 + ;; + 20) unInstall 1 ;; esac