singbox.sh 262 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981
  1. #!/bin/bash
  2. RED='\033[0;31m'
  3. CYAN='\033[0;36m'
  4. YELLOW='\033[0;33m'
  5. NC='\033[0m'
  6. disable_option=false
  7. enable_ech=false
  8. listen_port=""
  9. override_port=""
  10. ip_v4=""
  11. ip_v6=""
  12. record_content=""
  13. record_type=""
  14. record_name=""
  15. obfs_password=""
  16. domain=""
  17. domain_name=""
  18. up_mbps=""
  19. down_mbps=""
  20. certificate_path=""
  21. private_key_path=""
  22. public_key=""
  23. private_key=""
  24. multiplex_config=""
  25. brutal_config=""
  26. ech_key=()
  27. ech_config=()
  28. user_names=()
  29. user_passwords=()
  30. user_uuids=()
  31. ss_passwords=()
  32. stls_passwords=()
  33. short_ids=()
  34. function check_firewall_configuration() {
  35. local os_name=$(uname -s)
  36. local firewall
  37. if [[ $os_name == "Linux" ]]; then
  38. if command -v ufw >/dev/null 2>&1 && ufw status | grep -q "Status: active"; then
  39. firewall="ufw"
  40. elif command -v ip6tables >/dev/null 2>&1 && ip6tables -S | grep -q "INPUT -j DROP"; then
  41. firewall="ip6tables"
  42. elif command -v iptables >/dev/null 2>&1 && iptables -S | grep -q "INPUT -j DROP"; then
  43. firewall="iptables"
  44. elif systemctl is-active --quiet netfilter-persistent; then
  45. firewall="iptables-persistent"
  46. elif systemctl is-active --quiet iptables.service; then
  47. firewall="iptables-service"
  48. elif command -v firewalld >/dev/null 2>&1 && firewall-cmd --state | grep -q "running"; then
  49. firewall="firewalld"
  50. fi
  51. fi
  52. if [[ -z $firewall ]]; then
  53. echo "No firewall configuration detected or firewall is not enabled, skipping firewall configuration."
  54. return
  55. fi
  56. echo "Checking firewall configuration..."
  57. case $firewall in
  58. ufw)
  59. if ! ufw status | grep -q "Status: active" 2>/dev/null; then
  60. ufw enable > /dev/null 2>&1
  61. fi
  62. if ! ufw status | grep -q " $listen_port" 2>/dev/null; then
  63. ufw allow "$listen_port" > /dev/null 2>&1
  64. fi
  65. if ! ufw status | grep -q " $override_port" 2>/dev/null; then
  66. ufw allow "$override_port" > /dev/null 2>&1
  67. fi
  68. if ! ufw status | grep -q " $fallback_port" 2>/dev/null; then
  69. ufw allow "$fallback_port" > /dev/null 2>&1
  70. fi
  71. if ! ufw status | grep -q " 80" 2>/dev/null; then
  72. ufw allow 80 > /dev/null 2>&1
  73. fi
  74. echo "Firewall configuration has been updated."
  75. ;;
  76. iptables | iptables-persistent | iptables-service)
  77. if ! iptables -C INPUT -p tcp --dport "$listen_port" -j ACCEPT >/dev/null 2>&1; then
  78. iptables -A INPUT -p tcp --dport "$listen_port" -j ACCEPT > /dev/null 2>&1
  79. fi
  80. if ! iptables -C INPUT -p udp --dport "$listen_port" -j ACCEPT >/dev/null 2>&1; then
  81. iptables -A INPUT -p udp --dport "$listen_port" -j ACCEPT > /dev/null 2>&1
  82. fi
  83. if ! iptables -C INPUT -p tcp --dport "$override_port" -j ACCEPT >/dev/null 2>&1; then
  84. iptables -A INPUT -p tcp --dport "$override_port" -j ACCEPT > /dev/null 2>&1
  85. fi
  86. if ! iptables -C INPUT -p udp --dport "$override_port" -j ACCEPT >/dev/null 2>&1; then
  87. iptables -A INPUT -p udp --dport "$override_port" -j ACCEPT > /dev/null 2>&1
  88. fi
  89. if ! iptables -C INPUT -p tcp --dport "$fallback_port" -j ACCEPT >/dev/null 2>&1; then
  90. iptables -A INPUT -p tcp --dport "$fallback_port" -j ACCEPT > /dev/null 2>&1
  91. fi
  92. if ! iptables -C INPUT -p udp --dport "$fallback_port" -j ACCEPT >/dev/null 2>&1; then
  93. iptables -A INPUT -p udp --dport "$fallback_port" -j ACCEPT > /dev/null 2>&1
  94. fi
  95. if ! iptables -C INPUT -p tcp --dport 80 -j ACCEPT >/dev/null 2>&1; then
  96. iptables -A INPUT -p tcp --dport 80 -j ACCEPT > /dev/null 2>&1
  97. fi
  98. if ! iptables -C INPUT -p udp --dport 80 -j ACCEPT >/dev/null 2>&1; then
  99. iptables -A INPUT -p udp --dport 80 -j ACCEPT > /dev/null 2>&1
  100. fi
  101. if ! ip6tables -C INPUT -p tcp --dport "$listen_port" -j ACCEPT >/dev/null 2>&1; then
  102. ip6tables -A INPUT -p tcp --dport "$listen_port" -j ACCEPT > /dev/null 2>&1
  103. fi
  104. if ! ip6tables -C INPUT -p udp --dport "$listen_port" -j ACCEPT >/dev/null 2>&1; then
  105. ip6tables -A INPUT -p udp --dport "$listen_port" -j ACCEPT > /dev/null 2>&1
  106. fi
  107. if ! ip6tables -C INPUT -p tcp --dport "$override_port" -j ACCEPT >/dev/null 2>&1; then
  108. ip6tables -A INPUT -p tcp --dport "$override_port" -j ACCEPT > /dev/null 2>&1
  109. fi
  110. if ! ip6tables -C INPUT -p udp --dport "$override_port" -j ACCEPT >/dev/null 2>&1; then
  111. ip6tables -A INPUT -p udp --dport "$override_port" -j ACCEPT > /dev/null 2>&1
  112. fi
  113. if ! ip6tables -C INPUT -p tcp --dport "$fallback_port" -j ACCEPT >/dev/null 2>&1; then
  114. ip6tables -A INPUT -p tcp --dport "$fallback_port" -j ACCEPT > /dev/null 2>&1
  115. fi
  116. if ! ip6tables -C INPUT -p udp --dport "$fallback_port" -j ACCEPT >/dev/null 2>&1; then
  117. ip6tables -A INPUT -p udp --dport "$fallback_port" -j ACCEPT > /dev/null 2>&1
  118. fi
  119. if ! ip6tables -C INPUT -p tcp --dport 80 -j ACCEPT >/dev/null 2>&1; then
  120. ip6tables -A INPUT -p tcp --dport 80 -j ACCEPT > /dev/null 2>&1
  121. fi
  122. if ! ip6tables -C INPUT -p udp --dport 80 -j ACCEPT >/dev/null 2>&1; then
  123. ip6tables -A INPUT -p udp --dport 80 -j ACCEPT > /dev/null 2>&1
  124. fi
  125. if [[ -e /etc/iptables/rules.v4 ]]; then
  126. iptables-save > /etc/iptables/rules.v4
  127. elif [[ -e /etc/sysconfig/iptables ]]; then
  128. iptables-save > /etc/sysconfig/iptables
  129. fi
  130. if [[ -e /etc/iptables/rules.v6 ]]; then
  131. ip6tables-save > /etc/iptables/rules.v6
  132. elif [[ -e /etc/sysconfig/ip6tables ]]; then
  133. ip6tables-save > /etc/sysconfig/ip6tables
  134. fi
  135. echo "Firewall configuration has been updated."
  136. ;;
  137. firewalld)
  138. if ! firewall-cmd --zone=public --list-ports | grep -q "$listen_port/tcp" 2>/dev/null; then
  139. firewall-cmd --zone=public --add-port="$listen_port/tcp" --permanent > /dev/null 2>&1
  140. fi
  141. if ! firewall-cmd --zone=public --list-ports | grep -q "$listen_port/udp" 2>/dev/null; then
  142. firewall-cmd --zone=public --add-port="$listen_port/udp" --permanent > /dev/null 2>&1
  143. fi
  144. if ! firewall-cmd --zone=public --list-ports | grep -q "$override_port/tcp" 2>/dev/null; then
  145. firewall-cmd --zone=public --add-port="$override_port/tcp" --permanent > /dev/null 2>&1
  146. fi
  147. if ! firewall-cmd --zone=public --list-ports | grep -q "$override_port/udp" 2>/dev/null; then
  148. firewall-cmd --zone=public --add-port="$override_port/udp" --permanent > /dev/null 2>&1
  149. fi
  150. if ! firewall-cmd --zone=public --list-ports | grep -q "$fallback_port/tcp" 2>/dev/null; then
  151. firewall-cmd --zone=public --add-port="$fallback_port/tcp" --permanent > /dev/null 2>&1
  152. fi
  153. if ! firewall-cmd --zone=public --list-ports | grep -q "$fallback_port/udp" 2>/dev/null; then
  154. firewall-cmd --zone=public --add-port="$fallback_port/udp" --permanent > /dev/null 2>&1
  155. fi
  156. if ! firewall-cmd --zone=public --list-ports | grep -q "80/tcp" 2>/dev/null; then
  157. firewall-cmd --zone=public --add-port=80/tcp --permanent > /dev/null 2>&1
  158. fi
  159. if ! firewall-cmd --zone=public --list-ports | grep -q "80/udp" 2>/dev/null; then
  160. firewall-cmd --zone=public --add-port=80/udp --permanent > /dev/null 2>&1
  161. fi
  162. if ! firewall-cmd --zone=public --list-ports | grep -q "$listen_port/tcp" 2>/dev/null; then
  163. firewall-cmd --zone=public --add-port="$listen_port/tcp" --permanent > /dev/null 2>&1
  164. fi
  165. if ! firewall-cmd --zone=public --list-ports | grep -q "$listen_port/udp" 2>/dev/null; then
  166. firewall-cmd --zone=public --add-port="$listen_port/udp" --permanent > /dev/null 2>&1
  167. fi
  168. if ! firewall-cmd --zone=public --list-ports | grep -q "$override_port/tcp" 2>/dev/null; then
  169. firewall-cmd --zone=public --add-port="$override_port/tcp" --permanent > /dev/null 2>&1
  170. fi
  171. if ! firewall-cmd --zone=public --list-ports | grep -q "$override_port/udp" 2>/dev/null; then
  172. firewall-cmd --zone=public --add-port="$override_port/udp" --permanent > /dev/null 2>&1
  173. fi
  174. if ! firewall-cmd --zone=public --list-ports | grep -q "$fallback_port/tcp" 2>/dev/null; then
  175. firewall-cmd --zone=public --add-port="$fallback_port/tcp" --permanent > /dev/null 2>&1
  176. fi
  177. if ! firewall-cmd --zone=public --list-ports | grep -q "$fallback_port/udp" 2>/dev/null; then
  178. firewall-cmd --zone=public --add-port="$fallback_port/udp" --permanent > /dev/null 2>&1
  179. fi
  180. if ! firewall-cmd --zone=public --list-ports | grep -q "80/tcp" 2>/dev/null; then
  181. firewall-cmd --zone=public --add-port=80/tcp --permanent > /dev/null 2>&1
  182. fi
  183. if ! firewall-cmd --zone=public --list-ports | grep -q "80/udp" 2>/dev/null; then
  184. firewall-cmd --zone=public --add-port=80/udp --permanent > /dev/null 2>&1
  185. fi
  186. firewall-cmd --reload
  187. echo "Firewall configuration has been updated."
  188. ;;
  189. esac
  190. }
  191. function create_sing_box_folders() {
  192. local folders=("/usr/local/etc/sing-box" "/etc/ssl/private")
  193. for folder in "${folders[@]}"; do
  194. if [[ ! -d "$folder" ]]; then
  195. mkdir -p "$folder"
  196. [ "$folder" = "/usr/local/etc/sing-box" ] && touch "$folder/config.json"
  197. fi
  198. done
  199. }
  200. function create_juicity_folder() {
  201. local folders=("/usr/local/etc/juicity" "/etc/ssl/private")
  202. for folder in "${folders[@]}"; do
  203. if [[ ! -d "$folder" ]]; then
  204. mkdir -p "$folder"
  205. [ "$folder" = "/usr/local/etc/juicity" ] && touch "$folder/config.json"
  206. fi
  207. done
  208. }
  209. function ensure_clash_yaml() {
  210. local clash_yaml="/usr/local/etc/sing-box/clash.yaml"
  211. if [ ! -e "$clash_yaml" ]; then
  212. touch "$clash_yaml"
  213. fi
  214. }
  215. function check_config_file_existence() {
  216. local config_file="/usr/local/etc/sing-box/config.json"
  217. if [ ! -f "$config_file" ]; then
  218. echo -e "${RED}sing-box 配置文件不存在,请先搭建节点!${NC}"
  219. exit 1
  220. fi
  221. }
  222. function generate_naive_random_filename() {
  223. local dir="/usr/local/etc/sing-box"
  224. local filename=""
  225. while true; do
  226. random_value=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 5 | head -n 1)
  227. filename="naive_client_${random_value}.json"
  228. if [ ! -e "${dir}/${filename}" ]; then
  229. touch "${dir}/${filename}"
  230. naive_client_filename="${dir}/${filename}"
  231. break
  232. fi
  233. done
  234. }
  235. function get_temp_config_file() {
  236. temp_file=$(mktemp)
  237. curl -sSL "https://api.zeroteam.top/warp?format=sing-box" > "$temp_file"
  238. }
  239. function install_sing_box() {
  240. if [[ -f "/usr/local/bin/sing-box" && -f "/usr/local/etc/sing-box/config.json" ]]; then
  241. return 1
  242. else
  243. get_local_ip
  244. configure_dns64
  245. select_sing_box_install_option
  246. configure_sing_box_service
  247. create_sing_box_folders
  248. fi
  249. }
  250. function configure_dns64() {
  251. if [[ -n $ip_v4 ]]; then
  252. return
  253. fi
  254. if [[ -n $ip_v6 ]]; then
  255. echo "Check that the machine is IPv6 single-stack network, configure DNS64..."
  256. sed -i '/^nameserver /s/^/#/' /etc/resolv.conf
  257. echo "nameserver 2001:67c:2b0::4" >> /etc/resolv.conf
  258. echo "nameserver 2001:67c:2b0::6" >> /etc/resolv.conf
  259. echo "DNS64 configuration is complete."
  260. fi
  261. }
  262. function enable_bbr() {
  263. if grep -q "net.core.default_qdisc=fq" /etc/sysctl.conf; then
  264. echo "BBR is already enabled, skipping configuration."
  265. return
  266. fi
  267. while true; do
  268. read -p "是否开启 BBR (Y/N,默认N)? " -i "N" response
  269. response=${response:-"N"}
  270. if [[ $response == "y" || $response == "Y" ]]; then
  271. echo "Enable BBR..."
  272. echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
  273. echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
  274. sysctl -p > /dev/null
  275. echo "BBR has been enabled"
  276. break
  277. elif [[ $response == "n" || $response == "N" ]]; then
  278. echo "BBR will not be enabled."
  279. break
  280. else
  281. echo -e "${RED}无效的输入,请重新输入!${NC}"
  282. fi
  283. done
  284. }
  285. function select_sing_box_install_option() {
  286. while true; do
  287. echo "请选择 sing-box 的安装方式(默认1):"
  288. echo "1). 下载安装 sing-box(Latest 版本)"
  289. echo "2). 下载安装 sing-box(Beta 版本)"
  290. echo "3). 编译安装 sing-box(完整功能版本)"
  291. read -p "请选择 [1-2]: " install_option
  292. install_option="${install_option:-1}"
  293. case $install_option in
  294. 1)
  295. install_latest_sing_box
  296. break
  297. ;;
  298. 2)
  299. install_Pre_release_sing_box
  300. break
  301. ;;
  302. 3)
  303. install_go
  304. compile_install_sing_box
  305. break
  306. ;;
  307. *)
  308. echo -e "${RED}无效的选择,请重新输入!${NC}"
  309. ;;
  310. esac
  311. done
  312. }
  313. function install_go() {
  314. if ! command -v go &> /dev/null; then
  315. echo "Downloading Go..."
  316. local go_arch
  317. case $(uname -m) in
  318. x86_64)
  319. go_arch="amd64"
  320. ;;
  321. i686)
  322. go_arch="386"
  323. ;;
  324. aarch64)
  325. go_arch="arm64"
  326. ;;
  327. armv6l)
  328. go_arch="armv6l"
  329. ;;
  330. *)
  331. echo -e "${RED}不支持的架构: $(uname -m)${NC}"
  332. exit 1
  333. ;;
  334. esac
  335. local go_version
  336. go_version=$(curl -sL "https://golang.org/VERSION?m=text" | grep -o 'go[0-9]\+\.[0-9]\+\.[0-9]\+')
  337. local go_download_url="https://go.dev/dl/$go_version.linux-$go_arch.tar.gz"
  338. wget -qO- "$go_download_url" | tar -xz -C /usr/local
  339. echo 'export PATH=$PATH:/usr/local/go/bin' | tee -a /etc/profile >/dev/null
  340. source /etc/profile
  341. go version
  342. echo "Go has been installed."
  343. else
  344. echo "Go is already installed, skipping installation."
  345. fi
  346. }
  347. function compile_install_sing_box() {
  348. local go_install_command="go install -v -tags \
  349. with_quic,\
  350. with_grpc,\
  351. with_dhcp,\
  352. with_wireguard,\
  353. with_shadowsocksr,\
  354. with_ech,\
  355. with_utls,\
  356. with_reality_server,\
  357. with_acme,\
  358. with_clash_api,\
  359. with_v2ray_api,\
  360. with_gvisor,\
  361. with_lwip \
  362. github.com/sagernet/sing-box/cmd/sing-box@latest"
  363. echo "Compiling and installing sing-box, please wait..."
  364. $go_install_command
  365. if [[ $? -eq 0 ]]; then
  366. mv ~/go/bin/sing-box /usr/local/bin/
  367. chmod +x /usr/local/bin/sing-box
  368. echo "sing-box has been compiled and installed successfully."
  369. else
  370. echo -e "${RED}sing-box compilation and installation failed.${NC}"
  371. exit 1
  372. fi
  373. }
  374. function install_latest_sing_box() {
  375. local arch=$(uname -m)
  376. local url="https://api.github.com/repos/SagerNet/sing-box/releases/latest"
  377. local download_url
  378. case $arch in
  379. x86_64|amd64)
  380. download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-amd64.tar.gz")
  381. ;;
  382. armv7l)
  383. download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-armv7.tar.gz")
  384. ;;
  385. aarch64|arm64)
  386. download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-arm64.tar.gz")
  387. ;;
  388. amd64v3)
  389. download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-amd64v3.tar.gz")
  390. ;;
  391. s390x)
  392. download_url=$(curl -s $url | grep -o "https://github.com[^\"']*linux-s390x.tar.gz")
  393. ;;
  394. *)
  395. echo -e "${RED}不支持的架构:$arch${NC}"
  396. return 1
  397. ;;
  398. esac
  399. if [ -n "$download_url" ]; then
  400. echo "Downloading Sing-Box..."
  401. wget -qO sing-box.tar.gz "$download_url" 2>&1 >/dev/null
  402. tar -xzf sing-box.tar.gz -C /usr/local/bin --strip-components=1
  403. rm sing-box.tar.gz
  404. chmod +x /usr/local/bin/sing-box
  405. echo "Sing-Box installed successfully."
  406. else
  407. echo -e "${RED}Unable to retrieve the download URL for Sing-Box.${NC}"
  408. return 1
  409. fi
  410. }
  411. function install_Pre_release_sing_box() {
  412. local arch=$(uname -m)
  413. local url="https://api.github.com/repos/SagerNet/sing-box/releases"
  414. local download_url
  415. case $arch in
  416. x86_64|amd64)
  417. download_url=$(curl -s "$url" | jq -r '.[] | select(.prerelease == true) | .assets[] | select(.browser_download_url | contains("linux-amd64.tar.gz")) | .browser_download_url' | head -n 1)
  418. ;;
  419. armv7l)
  420. download_url=$(curl -s "$url" | jq -r '.[] | select(.prerelease == true) | .assets[] | select(.browser_download_url | contains("linux-armv7.tar.gz")) | .browser_download_url' | head -n 1)
  421. ;;
  422. aarch64|arm64)
  423. download_url=$(curl -s "$url" | jq -r '.[] | select(.prerelease == true) | .assets[] | select(.browser_download_url | contains("linux-arm64.tar.gz")) | .browser_download_url' | head -n 1)
  424. ;;
  425. amd64v3)
  426. download_url=$(curl -s "$url" | jq -r '.[] | select(.prerelease == true) | .assets[] | select(.browser_download_url | contains("linux-amd64v3.tar.gz")) | .browser_download_url' | head -n 1)
  427. ;;
  428. s390x)
  429. download_url=$(curl -s "$url" | jq -r '.[] | select(.prerelease == true) | .assets[] | select(.browser_download_url | contains("linux-s390x.tar.gz")) | .browser_download_url' | head -n 1)
  430. ;;
  431. *)
  432. echo -e "${RED}不支持的架构:$arch${NC}"
  433. return 1
  434. ;;
  435. esac
  436. if [ -n "$download_url" ]; then
  437. echo "Downloading Sing-Box..."
  438. wget -qO sing-box.tar.gz "$download_url" 2>&1 >/dev/null
  439. tar -xzf sing-box.tar.gz -C /usr/local/bin --strip-components=1
  440. rm sing-box.tar.gz
  441. chmod +x /usr/local/bin/sing-box
  442. echo "Sing-Box installed successfully."
  443. else
  444. echo -e "${RED}Unable to get pre-release download link for Sing-Box.${NC}"
  445. return 1
  446. fi
  447. }
  448. function install_latest_juicity() {
  449. local arch=$(uname -m)
  450. case $arch in
  451. "arm64")
  452. arch_suffix="arm64"
  453. ;;
  454. "armv5")
  455. arch_suffix="armv5"
  456. ;;
  457. "armv6")
  458. arch_suffix="armv6"
  459. ;;
  460. "armv7")
  461. arch_suffix="armv7"
  462. ;;
  463. "mips")
  464. arch_suffix="mips32"
  465. ;;
  466. "mipsel")
  467. arch_suffix="mips32le"
  468. ;;
  469. "mips64")
  470. arch_suffix="mips64"
  471. ;;
  472. "mips64el")
  473. arch_suffix="mips64le"
  474. ;;
  475. "riscv64")
  476. arch_suffix="riscv64"
  477. ;;
  478. "i686")
  479. arch_suffix="x86_32"
  480. ;;
  481. "x86_64")
  482. if [ -n "$(grep avx2 /proc/cpuinfo)" ]; then
  483. arch_suffix="x86_64_v3_avx2"
  484. else
  485. arch_suffix="x86_64_v2_sse"
  486. fi
  487. ;;
  488. *)
  489. echo "Unsupported architecture: $arch"
  490. return 1
  491. ;;
  492. esac
  493. local github_api_url="https://api.github.com/repos/juicity/juicity/releases/latest"
  494. local download_url=$(curl -s "$github_api_url" | grep "browser_download_url.*$arch_suffix.zip\"" | cut -d '"' -f 4)
  495. local temp_dir=$(mktemp -d)
  496. local install_path="/usr/local/bin/juicity-server"
  497. echo "Downloading the latest version of juicity-server..."
  498. wget -P "$temp_dir" "$download_url" >/dev/null 2>&1
  499. unzip "$temp_dir/*.zip" -d "$temp_dir" >/dev/null 2>&1
  500. mv "$temp_dir/juicity-server" "$install_path" >/dev/null 2>&1
  501. chmod +x /usr/local/bin/juicity-server
  502. echo "juicity-server has been downloaded."
  503. rm -rf "$temp_dir"
  504. }
  505. function configure_sing_box_service() {
  506. echo "Configuring sing-box startup service..."
  507. local service_file="/etc/systemd/system/sing-box.service"
  508. if [[ -f $service_file ]]; then
  509. rm "$service_file"
  510. fi
  511. local service_config='[Unit]
  512. Description=sing-box service
  513. Documentation=https://sing-box.sagernet.org
  514. After=network.target nss-lookup.target
  515. [Service]
  516. CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
  517. AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
  518. ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json
  519. ExecReload=/bin/kill -HUP $MAINPID
  520. Restart=on-failure
  521. RestartSec=10s
  522. LimitNOFILE=infinity
  523. [Install]
  524. WantedBy=multi-user.target'
  525. echo "$service_config" >"$service_file"
  526. echo "sing-box startup service has been configured."
  527. }
  528. function configure_juicity_service() {
  529. echo "Configuring juicity startup service..."
  530. local service_file="/etc/systemd/system/juicity.service"
  531. if [[ -f $service_file ]]; then
  532. rm "$service_file"
  533. fi
  534. local service_config='[Unit]
  535. Description=juicity-server Service
  536. Documentation=https://github.com/juicity/juicity
  537. After=network.target nss-lookup.target
  538. [Service]
  539. Type=simple
  540. User=root
  541. Environment=QUIC_GO_ENABLE_GSO=true
  542. ExecStart=/usr/local/bin/juicity-server run -c /usr/local/etc/juicity/config.json --disable-timestamp
  543. Restart=on-failure
  544. LimitNPROC=512
  545. LimitNOFILE=infinity
  546. [Install]
  547. WantedBy=multi-user.target'
  548. echo "$service_config" >"$service_file"
  549. echo "juicity startup service has been configured."
  550. }
  551. function set_listen_port() {
  552. while true; do
  553. read -p "请输入监听端口 (默认443): " new_listen_port
  554. new_listen_port=${new_listen_port:-443}
  555. if [[ $new_listen_port =~ ^[1-9][0-9]{0,4}$ && $new_listen_port -le 65535 ]]; then
  556. check_result=$(netstat -tulpn | grep -E "\b${new_listen_port}\b")
  557. if [ -z "$check_result" ]; then
  558. echo "监听端口:$new_listen_port"
  559. break
  560. else
  561. echo -e "${RED}错误:端口已被占用,请选择其他端口!${NC}" >&2
  562. fi
  563. else
  564. echo -e "${RED}错误:端口范围1-65535,请重新输入!${NC}" >&2
  565. fi
  566. done
  567. listen_port="$new_listen_port"
  568. }
  569. function set_user_name() {
  570. while true; do
  571. read -p "请输入用户名 (默认随机生成): " new_user_name
  572. if [[ -z "$new_user_name" ]]; then
  573. new_user_name=$(sing-box generate rand --base64 6 2>/dev/null || openssl rand -base64 5)
  574. echo "用户名:$new_user_name"
  575. break
  576. elif [[ ! -z "$new_user_name" ]]; then
  577. break
  578. fi
  579. done
  580. user_names+=("$new_user_name")
  581. }
  582. function set_user_password() {
  583. while true; do
  584. read -p "请输入密码(默认随机生成): " new_user_password
  585. if [[ -z "$new_user_password" ]]; then
  586. new_user_password=$(sing-box generate rand --base64 9 2>/dev/null || openssl rand -base64 9)
  587. echo "密码:$new_user_password"
  588. break
  589. elif [[ ! -z "$new_user_password" ]]; then
  590. break
  591. fi
  592. done
  593. user_passwords+=("$new_user_password")
  594. }
  595. function set_ss_password() {
  596. while true; do
  597. read -p "请输入 Shadowsocks 密码(默认随机生成): " ss_user_password
  598. if [[ -z $ss_user_password ]]; then
  599. if [[ $encryption_choice == 1 || $encryption_choice == 2 ]]; then
  600. ss_password=$(sing-box generate rand --base64 32)
  601. echo "Shadowsocks 密码: $ss_password"
  602. else
  603. ss_password=$(sing-box generate rand --base64 16)
  604. echo "Shadowsocks 密码: $ss_password"
  605. fi
  606. ss_passwords+=("$ss_password")
  607. break
  608. elif [[ $encryption_choice == 1 || $encryption_choice == 2 ]] && [[ ${#ss_user_password} -eq 32 ]]; then
  609. ss_password="$ss_user_password"
  610. echo "Shadowsocks 密码: $ss_password"
  611. ss_passwords+=("$ss_password")
  612. break
  613. elif [[ $encryption_choice != 1 && $encryption_choice != 2 ]] && [[ ${#ss_user_password} -eq 16 ]]; then
  614. ss_password="$ss_user_password"
  615. echo "Shadowsocks 密码: $ss_password"
  616. ss_passwords+=("$ss_password")
  617. break
  618. else
  619. echo -e "${RED}错误:密码长度不符合要求,请重新输入!${NC}"
  620. fi
  621. done
  622. }
  623. function set_stls_password() {
  624. while true; do
  625. read -p "请输入 ShadowTLS 密码(默认随机生成): " stls_user_password
  626. if [[ -z $stls_user_password ]]; then
  627. if [[ $encryption_choice == 1 || $encryption_choice == 2 ]]; then
  628. stls_password=$(sing-box generate rand --base64 32)
  629. echo "ShadowTLS 密码: $stls_password"
  630. else
  631. stls_password=$(sing-box generate rand --base64 16)
  632. echo "ShadowTLS 密码: $stls_password"
  633. fi
  634. stls_passwords+=("$stls_password")
  635. break
  636. elif [[ $encryption_choice == 1 || $encryption_choice == 2 ]] && [[ ${#stls_user_password} -eq 32 ]]; then
  637. stls_password="$stls_user_password"
  638. echo "ShadowTLS 密码: $stls_password"
  639. stls_passwords+=("$stls_password")
  640. break
  641. elif [[ $encryption_choice != 1 && $encryption_choice != 2 ]] && [[ ${#stls_user_password} -eq 16 ]]; then
  642. stls_password="$stls_user_password"
  643. echo "ShadowTLS 密码: $stls_password"
  644. stls_passwords+=("$stls_password")
  645. break
  646. else
  647. echo -e "${RED}错误:密码长度不符合要求,请重新输入!${NC}"
  648. fi
  649. done
  650. }
  651. function set_up_speed() {
  652. while true; do
  653. read -p "请输入上行速率 (默认50): " new_up_mbps
  654. new_up_mbps=${new_up_mbps:-50}
  655. if [[ $new_up_mbps =~ ^[0-9]+$ ]]; then
  656. echo "上行速率:$new_up_mbps Mbps"
  657. break
  658. else
  659. echo -e "${RED}错误:请输入数字作为上行速率!${NC}"
  660. fi
  661. done
  662. up_mbps="$new_up_mbps"
  663. }
  664. function set_down_speed() {
  665. while true; do
  666. read -p "请输入下行速率 (默认100): " new_down_mbps
  667. new_down_mbps=${new_down_mbps:-100}
  668. if [[ $new_down_mbps =~ ^[0-9]+$ ]]; then
  669. echo "下行速率:$new_down_mbps Mbps"
  670. break
  671. else
  672. echo -e "${RED}错误:请输入数字作为下行速率!${NC}"
  673. fi
  674. done
  675. down_mbps="$new_down_mbps"
  676. }
  677. function set_uuid() {
  678. while true; do
  679. read -p "请输入UUID(默认随机生成): " new_user_uuid
  680. if [ -z "$new_user_uuid" ]; then
  681. new_user_uuid=$(sing-box generate uuid 2>/dev/null || openssl rand -hex 16 | awk '{print substr($1,1,8) "-" substr($1,9,4) "-" substr($1,13,4) "-" substr($1,17,4) "-" substr($1,21)}')
  682. fi
  683. if [[ $new_user_uuid =~ ^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$ ]]; then
  684. echo "UUID:$new_user_uuid"
  685. break
  686. else
  687. echo -e "${RED}无效的UUID格式,请重新输入!${NC}"
  688. fi
  689. done
  690. user_uuids+=("$new_user_uuid")
  691. }
  692. function set_override_port() {
  693. while true; do
  694. read -p "请输入目标端口 (默认443): " new_override_port
  695. new_override_port=${new_override_port:-443}
  696. if [[ $new_override_port =~ ^[1-9][0-9]{0,4}$ && $new_override_port -le 65535 ]]; then
  697. echo "目标端口: $new_override_port"
  698. break
  699. else
  700. echo -e "${RED}错误:端口范围1-65535,请重新输入!${NC}"
  701. fi
  702. done
  703. override_port="$new_override_port"
  704. }
  705. function generate_unique_tag() {
  706. local config_file="/usr/local/etc/sing-box/config.json"
  707. while true; do
  708. random_tag=$(head /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1)
  709. tag_label="${random_tag}-in"
  710. if ! grep -qE "\"tag\":\\s*\"$tag_label\"(,|$)" "$config_file"; then
  711. break
  712. fi
  713. done
  714. }
  715. function set_override_address() {
  716. while true; do
  717. read -p "请输入目标地址(IP或域名): " target_address
  718. if [[ -z "$target_address" ]]; then
  719. echo -e "${RED}错误:目标地址不能为空!${NC}"
  720. continue
  721. fi
  722. if ( [[ $target_address =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] && [[ $(grep -o '\.' <<< "$target_address" | wc -l) -eq 3 ]] ) || ( [[ $target_address =~ ^[a-fA-F0-9:]+$ ]] && [[ $(grep -o ':' <<< "$target_address" | wc -l) -ge 2 ]] ); then
  723. break
  724. else
  725. resolved_ips=$(host -t A "$target_address" | awk '/has address/ { print $4 }')
  726. if [[ -n "$resolved_ips" ]] && ( [[ "$resolved_ips" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]] || [[ "$resolved_ips" =~ ^[a-fA-F0-9:]+$ ]] ); then
  727. break
  728. else
  729. echo -e "${RED}错误:请输入有效的 IP 地址或域名!${NC}"
  730. fi
  731. fi
  732. done
  733. }
  734. function set_server_name() {
  735. while true; do
  736. read -p "请输入可用的 ServerName 列表 (默认为 nijigen-works.jp): " user_input
  737. if [[ -z "$user_input" ]]; then
  738. server_name="nijigen-works.jp"
  739. echo "ServerName:$server_name"
  740. break
  741. else
  742. server_name="$user_input"
  743. echo "ServerName:$server_name"
  744. echo "Verifying server's TLS version support..."
  745. if command -v openssl >/dev/null 2>&1; then
  746. local openssl_output=$(timeout 10s openssl s_client -connect "$server_name:443" -tls1_3 2>&1)
  747. if [[ $openssl_output == *"TLS_AES_256_GCM_SHA384"* || \
  748. $openssl_output == *"TLS_AES_128_GCM_SHA256"* || \
  749. $openssl_output == *"TLS_CHACHA20_POLY1305_SHA256"* || \
  750. $openssl_output == *"TLS_AES_128_CCM_SHA256"* || \
  751. $openssl_output == *"TLS_AES_128_CCM_8_SHA256"* ]]; then
  752. break
  753. else
  754. echo -e "${RED}该网址不支持 TLS 1.3,请重新输入!${NC}"
  755. fi
  756. else
  757. echo "OpenSSL is not installed, cannot verify TLS support."
  758. break
  759. fi
  760. fi
  761. done
  762. }
  763. function set_target_server() {
  764. while true; do
  765. read -p "请输入目标网站地址(默认为 nijigen-works.jp): " user_input
  766. if [[ -z "$user_input" ]]; then
  767. target_server="nijigen-works.jp"
  768. echo "目标网址:$target_server"
  769. break
  770. else
  771. target_server="$user_input"
  772. echo "目标网址:$target_server"
  773. echo "Verifying server's TLS version support..."
  774. if command -v openssl >/dev/null 2>&1; then
  775. local openssl_output=$(timeout 10s openssl s_client -connect "$target_server:443" -tls1_3 2>&1)
  776. if [[ $openssl_output == *"TLS_AES_256_GCM_SHA384"* || \
  777. $openssl_output == *"TLS_AES_128_GCM_SHA256"* || \
  778. $openssl_output == *"TLS_CHACHA20_POLY1305_SHA256"* || \
  779. $openssl_output == *"TLS_AES_128_CCM_SHA256"* || \
  780. $openssl_output == *"TLS_AES_128_CCM_8_SHA256"* ]]; then
  781. break
  782. else
  783. echo -e "${RED}该目标网站地址不支持 TLS 1.3,请重新输入!${NC}"
  784. fi
  785. else
  786. echo "OpenSSL is not installed, cannot verify TLS support."
  787. break
  788. fi
  789. fi
  790. done
  791. }
  792. function get_local_ip() {
  793. local local_ip_v4
  794. local local_ip_v6
  795. local_ip_v4=$(curl -s4 https://api.myip.com | grep -o '"ip":"[^"]*' | awk -F ':"' '{print $2}')
  796. if [[ -n "$local_ip_v4" ]]; then
  797. ip_v4="$local_ip_v4"
  798. else
  799. local_ip_v4=$(curl -s4 icanhazip.com)
  800. if [[ -n "$local_ip_v4" ]]; then
  801. ip_v4="$local_ip_v4"
  802. fi
  803. fi
  804. local_ip_v6=$(curl -s6 https://api.myip.com | grep -o '"ip":"[^"]*' | awk -F ':"' '{print $2}')
  805. if [[ -n "$local_ip_v6" ]]; then
  806. ip_v6="$local_ip_v6"
  807. else
  808. local_ip_v6=$(curl -s6 icanhazip.com)
  809. if [[ -n "$local_ip_v6" ]]; then
  810. ip_v6="$local_ip_v6"
  811. fi
  812. fi
  813. if [[ -z "$ip_v4" && -z "$ip_v6" ]]; then
  814. echo -e "${RED}无法获取本机IP地址!${NC}"
  815. fi
  816. }
  817. function get_ech_keys() {
  818. local input_file="/etc/ssl/private/ech.tmp"
  819. local output_file="/etc/ssl/private/ech.pem"
  820. sing-box generate ech-keypair [--pq-signature-schemes-enabled] > "$input_file"
  821. IFS=$'\n' read -d '' -ra lines < "$input_file"
  822. exec 3>"$output_file"
  823. in_ech_keys_section=false
  824. in_ech_configs_section=false
  825. for line in "${lines[@]}"; do
  826. if [[ "$line" == *"BEGIN ECH KEYS"* ]]; then
  827. in_ech_keys_section=true
  828. ech_key+=" \"$line\",\n"
  829. elif [[ "$line" == *"END ECH KEYS"* ]]; then
  830. in_ech_keys_section=false
  831. ech_key+=" \"$line\""
  832. elif [[ "$line" == *"BEGIN ECH CONFIGS"* ]]; then
  833. in_ech_configs_section=true
  834. ech_config+=" \"$line\",\n"
  835. elif [[ "$line" == *"END ECH CONFIGS"* ]]; then
  836. in_ech_configs_section=false
  837. ech_config+=" \"$line\""
  838. elif [ "$in_ech_keys_section" = true ]; then
  839. ech_key+=" \"$line\",\n"
  840. elif [ "$in_ech_configs_section" = true ]; then
  841. ech_config+=" \"$line\",\n"
  842. else
  843. echo "\"$line\"," >&3
  844. fi
  845. done
  846. exec 3>&-
  847. rm "$input_file"
  848. }
  849. function get_domain() {
  850. while true; do
  851. read -p "请输入域名(关闭Cloudflare代理): " user_domain
  852. resolved_ipv4=$(dig +short A "$user_domain" 2>/dev/null)
  853. resolved_ipv6=$(dig +short AAAA "$user_domain" 2>/dev/null)
  854. if [[ -z $user_domain ]]; then
  855. echo -e "${RED}错误:域名不能为空,请重新输入!${NC}"
  856. else
  857. if [[ ("$resolved_ipv4" == "$ip_v4" && ! -z "$resolved_ipv4") || ("$resolved_ipv6" == "$ip_v6" && ! -z "$resolved_ipv6") ]]; then
  858. break
  859. else
  860. if [[ -z "$resolved_ipv4" && -n "$ip_v4" ]]; then
  861. resolved_ip_v4=$(ping -4 "$user_domain" -c 1 2>/dev/null | sed '1{s/[^(]*(//;s/).*//;q}')
  862. if [[ ("$resolved_ip_v4" == "$ip_v4" && ! -z "$resolved_ip_v4") ]]; then
  863. break
  864. fi
  865. fi
  866. if [[ -z "$resolved_ipv6" && -n "$ip_v6" ]]; then
  867. resolved_ip_v6=$(ping -6 "$user_domain" -c 1 2>/dev/null | sed '1{s/[^(]*(//;s/).*//;q}')
  868. if [[ ("$resolved_ip_v6" == "$ip_v6" && ! -z "$resolved_ip_v6") ]]; then
  869. break
  870. fi
  871. fi
  872. echo -e "${RED}错误:域名未绑定本机IP,请重新输入!${NC}"
  873. fi
  874. fi
  875. done
  876. domain="$user_domain"
  877. }
  878. function verify_domain() {
  879. new_domain=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_id" \
  880. -H "Authorization: Bearer $api_token" | jq -r '.result.name')
  881. if [[ $new_domain =~ \.(tk|ml|ga|gq|cf)$ ]]; then
  882. echo -e "${RED}您的域名为$new_domain,该域名不支持使用 CloudFlare 的 API 申请证书,请选择其他方式申请证书!${NC}"
  883. domain_supported=false
  884. else
  885. while true; do
  886. read -p "请输入主域名前缀(若为空则使用主域名申请证书,不需要在 CloudFlare 添加 DNS 解析记录): " domain_prefix
  887. if [ -z "$domain_prefix" ]; then
  888. domain="$new_domain"
  889. record_name="$domain_prefix"
  890. break
  891. else
  892. domain="$domain_prefix"."$new_domain"
  893. record_name="$domain_prefix"
  894. break
  895. fi
  896. done
  897. domain_supported=true
  898. fi
  899. }
  900. function set_dns_record() {
  901. if [[ -z "$record_name" ]]; then
  902. name_value="@"
  903. else
  904. name_value="$record_name"
  905. fi
  906. if [[ -n "$ip_v4" ]]; then
  907. record_content=" $ip_v4"
  908. record_type="A"
  909. elif [[ -z "$ip_v4" && -n "$ip_v6" ]]; then
  910. record_content=" $ip_v6"
  911. record_type="AAAA"
  912. fi
  913. curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$CF_Zone_ID/dns_records" \
  914. -H "Authorization: Bearer $CF_Token" \
  915. -H "Content-Type: application/json" \
  916. --data "{\"type\":\"$record_type\",\"name\":\"$name_value\",\"content\":\"$record_content\",\"ttl\":120,\"proxied\":false}" >/dev/null
  917. }
  918. function get_api_token() {
  919. while true; do
  920. read -p "请输入 CloudFlare 的限制性 API 令牌: " api_token
  921. if [[ ! $api_token =~ ^[A-Za-z0-9_-]{40}$ ]]; then
  922. echo -e "${RED}API令牌格式不正确,请重新输入!${NC}"
  923. else
  924. export CF_Token="$api_token"
  925. break
  926. fi
  927. done
  928. }
  929. function get_zone_id() {
  930. while true; do
  931. read -p "请输入 CloudFlare 的区域 ID: " zone_id
  932. if [[ ! $zone_id =~ ^[a-z0-9]{32}$ ]]; then
  933. echo -e "${RED}CloudFlare 的区域 ID 格式不正确,请重新输入!${NC}"
  934. else
  935. export CF_Zone_ID="$zone_id"
  936. break
  937. fi
  938. done
  939. }
  940. function get_api_email() {
  941. while true; do
  942. read -p "请输入 CloudFlare 的登录邮箱: " api_email
  943. if [[ ! $api_email =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$ ]]; then
  944. echo -e "${RED}邮箱格式不正确,请重新输入!${NC}"
  945. else
  946. export CF_Email="$api_email"
  947. break
  948. fi
  949. done
  950. }
  951. function set_fake_domain() {
  952. while true; do
  953. read -p "请输入伪装网址(默认: www.fan-2000.com): " fake_domain
  954. fake_domain=${fake_domain:-"www.fan-2000.com"}
  955. if curl --output /dev/null --silent --head --fail "$fake_domain"; then
  956. echo "伪装网址: $fake_domain"
  957. break
  958. else
  959. echo -e "${RED}伪装网址无效或不可用,请重新输入!${NC}"
  960. fi
  961. done
  962. }
  963. function set_certificate_path() {
  964. while true; do
  965. read -p "请输入 PEM 证书位置: " certificate_path_input
  966. if [[ ! -f "$certificate_path_input" ]]; then
  967. echo -e "${RED}错误:证书文件不存在,请重新输入!${NC}"
  968. continue
  969. fi
  970. certificate_file=$(basename "$certificate_path_input")
  971. allowed_extensions=("crt" "pem")
  972. if [[ ! "${allowed_extensions[@]}" =~ "${certificate_file##*.}" ]]; then
  973. echo -e "${RED}错误:不支持的证书格式,请配置.crt或.pem格式的证书文件!${NC}"
  974. continue
  975. fi
  976. certificate_path="$certificate_path_input"
  977. break
  978. done
  979. }
  980. function set_private_key_path() {
  981. while true; do
  982. read -p "请输入 PEM 私钥位置: " private_key_path_input
  983. if [[ ! -f "$private_key_path_input" ]]; then
  984. echo -e "${RED}错误:私钥文件不存在,请重新输入!${NC}"
  985. continue
  986. fi
  987. private_key_file=$(basename "$private_key_path_input")
  988. allowed_extensions=("key" "pem")
  989. if [[ ! "${allowed_extensions[@]}" =~ "${private_key_file##*.}" ]]; then
  990. echo -e "${RED}错误:不支持的私钥格式,请配置.key或.pem格式的私钥文件!${NC}"
  991. continue
  992. fi
  993. private_key_path="$private_key_path_input"
  994. break
  995. done
  996. }
  997. function apply_certificate() {
  998. certificate_path="/etc/ssl/private/"$domain".crt"
  999. private_key_path="/etc/ssl/private/"$domain".key"
  1000. local has_ipv4=false
  1001. local ca_servers=("letsencrypt" "zerossl")
  1002. local return_to_menu=false
  1003. if [[ -n "$ip_v4" ]]; then
  1004. has_ipv4=true
  1005. fi
  1006. echo "Requesting a certificate..."
  1007. curl -s https://get.acme.sh | sh -s email=example@gmail.com 2>&1 | tail -n 1
  1008. alias acme.sh=~/.acme.sh/acme.sh
  1009. for ca_server in "${ca_servers[@]}"; do
  1010. echo "Requesting a certificate from $ca_server..."
  1011. ~/.acme.sh/acme.sh --set-default-ca --server "$ca_server"
  1012. if $has_ipv4; then
  1013. result=$(~/.acme.sh/acme.sh --issue -d "$domain" --standalone -k ec-256 2>&1)
  1014. else
  1015. result=$(~/.acme.sh/acme.sh --issue -d "$domain" --standalone -k ec-256 --listen-v6 2>&1)
  1016. fi
  1017. if [[ $result == *"force"* ]]; then
  1018. if $has_ipv4; then
  1019. result=$(~/.acme.sh/acme.sh --issue -d "$domain" --standalone -k ec-256 --force 2>&1)
  1020. else
  1021. result=$(~/.acme.sh/acme.sh --issue -d "$domain" --standalone -k ec-256 --listen-v6 --force 2>&1)
  1022. fi
  1023. fi
  1024. if [[ $result == *"log"* || $result == *"debug"* || $result == *"error"* ]]; then
  1025. echo -e "${RED}$result ${NC}"
  1026. continue
  1027. fi
  1028. if [[ $? -eq 0 ]]; then
  1029. echo "Installing the certificate..."
  1030. ~/.acme.sh/acme.sh --install-cert -d "$domain" --ecc --key-file "$private_key_path" --fullchain-file "$certificate_path"
  1031. break
  1032. else
  1033. echo -e "${RED}Failed to obtain a certificate from $ca_server!${NC}"
  1034. return_to_menu=true
  1035. fi
  1036. done
  1037. if [ "$return_to_menu" = true ]; then
  1038. echo -e "${RED}证书申请失败,请使用其它方法申请证书!${NC}"
  1039. return 1
  1040. fi
  1041. }
  1042. function Apply_api_certificate() {
  1043. certificate_path="/etc/ssl/private/"$domain".crt"
  1044. private_key_path="/etc/ssl/private/"$domain".key"
  1045. local has_ipv4=false
  1046. local ca_servers=("letsencrypt" "zerossl")
  1047. if [[ -n "$ip_v4" ]]; then
  1048. has_ipv4=true
  1049. fi
  1050. echo "Requesting a certificate..."
  1051. curl -s https://get.acme.sh | sh -s email=example@gmail.com 2>&1 | tail -n 1
  1052. alias acme.sh=~/.acme.sh/acme.sh
  1053. for ca_server in "${ca_servers[@]}"; do
  1054. echo "Requesting a certificate from $ca_server..."
  1055. ~/.acme.sh/acme.sh --set-default-ca --server "$ca_server"
  1056. if $has_ipv4; then
  1057. result=$(~/.acme.sh/acme.sh --issue --dns dns_cf -d "$domain" -k ec-256 2>&1)
  1058. else
  1059. result=$(~/.acme.sh/acme.sh --issue --dns dns_cf -d "$domain" -k ec-256 --listen-v6 2>&1)
  1060. fi
  1061. if [[ $result == *"log"* || $result == *"debug"* || $result == *"error"* || $result == *"force"* ]]; then
  1062. echo -e "${RED}$result ${NC}"
  1063. return_to_menu=true
  1064. continue
  1065. fi
  1066. if [[ $? -eq 0 ]]; then
  1067. echo "Installing the certificate..."
  1068. ~/.acme.sh/acme.sh --install-cert -d "$domain" --ecc --key-file "$private_key_path" --fullchain-file "$certificate_path"
  1069. break
  1070. else
  1071. echo -e "${RED}Failed to obtain a certificate from $ca_server!${NC}"
  1072. return_to_menu=true
  1073. fi
  1074. done
  1075. if [ "$return_to_menu" = true ]; then
  1076. echo -e "${RED}证书申请失败,请使用其它方法申请证书!${NC}"
  1077. return 1
  1078. fi
  1079. }
  1080. function Reapply_certificates() {
  1081. local tls_info_file="/usr/local/etc/sing-box/tls_info.json"
  1082. local has_ipv4=false
  1083. if [ -n "$ip_v4" ]; then
  1084. has_ipv4=true
  1085. fi
  1086. if ! command -v acme.sh &>/dev/null; then
  1087. curl -s https://get.acme.sh | sh -s email=example@gmail.com
  1088. fi
  1089. alias acme.sh=~/.acme.sh/acme.sh
  1090. echo "Setting CA server to Let's Encrypt..."
  1091. ~/.acme.sh/acme.sh --set-default-ca --server "letsencrypt"
  1092. jq -c '.[]' "$tls_info_file" | while read -r tls_info; do
  1093. server_name=$(echo "$tls_info" | jq -r '.server_name')
  1094. key_path=$(echo "$tls_info" | jq -r '.key_path')
  1095. certificate_path=$(echo "$tls_info" | jq -r '.certificate_path')
  1096. echo "Requesting certificate for $server_name..."
  1097. result=$(
  1098. if $has_ipv4; then
  1099. ~/.acme.sh/acme.sh --issue --dns dns_cf -d "$server_name" -k ec-256 --force
  1100. else
  1101. ~/.acme.sh/acme.sh --issue --dns dns_cf -d "$server_name" -k ec-256 --listen-v6 --force
  1102. fi
  1103. )
  1104. if [[ "$result" =~ "Cert success." ]]; then
  1105. echo "Certificate for $server_name has been applied using Cloudflare DNS verification."
  1106. else
  1107. echo "Cloudflare DNS verification failed for $server_name. Trying standalone verification..."
  1108. result=$(
  1109. if $has_ipv4; then
  1110. ~/.acme.sh/acme.sh --issue -d "$server_name" --standalone --force
  1111. else
  1112. ~/.acme.sh/acme.sh --issue -d "$server_name" --standalone --listen-v6 --force
  1113. fi
  1114. )
  1115. if [[ "$result" =~ "BEGIN CERTIFICATE" && "$result" =~ "END CERTIFICATE" ]]; then
  1116. echo "Certificate for $server_name has been applied using Let's Encrypt CA."
  1117. else
  1118. echo "Failed to obtain certificate for $server_name using standalone verification as well."
  1119. return 1
  1120. fi
  1121. fi
  1122. ~/.acme.sh/acme.sh --install-cert -d "$server_name" --ecc --key-file "$key_path" --fullchain-file "$certificate_path"
  1123. echo "Certificate for $server_name has been installed."
  1124. done
  1125. rm -f "$tls_info_file"
  1126. }
  1127. function generate_private_key() {
  1128. while true; do
  1129. read -p "请输入私钥 (默认随机生成私钥): " local_private_key
  1130. if [[ -z "$local_private_key" ]]; then
  1131. local keypair_output=$(sing-box generate reality-keypair)
  1132. local_private_key=$(echo "$keypair_output" | awk -F: '/PrivateKey/{gsub(/ /, "", $2); print $2}')
  1133. local_public_key=$(echo "$keypair_output" | awk -F: '/PublicKey/{gsub(/ /, "", $2); print $2}')
  1134. echo "private_key:$local_private_key"
  1135. echo "public_key:$local_public_key"
  1136. break
  1137. else
  1138. if [[ "$local_private_key" =~ ^[A-Za-z0-9_\-]{43}$ ]]; then
  1139. read -p "请输入公钥: " local_public_key
  1140. if ! [[ "$local_public_key" =~ ^[A-Za-z0-9_\-]{43}$ ]]; then
  1141. echo -e "${RED}无效的公钥,请重新输入!${NC}"
  1142. else
  1143. break
  1144. fi
  1145. else
  1146. echo -e "${RED}无效的私钥,请重新输入!${NC}"
  1147. fi
  1148. fi
  1149. done
  1150. public_key="$local_public_key"
  1151. private_key="$local_private_key"
  1152. }
  1153. function create_self_signed_cert() {
  1154. while true; do
  1155. read -p "请输入要用于自签名证书的域名(默认为 bing.com): " user_domain
  1156. domain_name=${user_domain:-"bing.com"}
  1157. if curl --output /dev/null --silent --head --fail "$domain_name"; then
  1158. openssl req -x509 -nodes -newkey ec:<(openssl ecparam -name prime256v1) -keyout /etc/ssl/private/$domain_name.key -out /etc/ssl/private/$domain_name.crt -subj "/CN=$domain_name" -days 36500
  1159. chmod 777 /etc/ssl/private/$domain_name.key
  1160. chmod 777 /etc/ssl/private/$domain_name.crt
  1161. break
  1162. else
  1163. echo -e "${RED}无效的域名或域名不可用,请输入有效的域名!${NC}"
  1164. fi
  1165. done
  1166. certificate_path="/etc/ssl/private/$domain_name.crt"
  1167. private_key_path="/etc/ssl/private/$domain_name.key"
  1168. }
  1169. function select_encryption_method() {
  1170. while true; do
  1171. read -p "请选择加密方式(默认1):
  1172. 1). 2022-blake3-chacha20-poly1305
  1173. 2). 2022-blake3-aes-256-gcm
  1174. 3). 2022-blake3-aes-128-gcm
  1175. 4). xchacha20-ietf-poly1305
  1176. 5). chacha20-ietf-poly1305
  1177. 6). aes-256-gcm
  1178. 7). aes-192-gcm
  1179. 8). aes-128-gcm
  1180. 请选择[1-8]: " encryption_choice
  1181. encryption_choice=${encryption_choice:-1}
  1182. case $encryption_choice in
  1183. 1)
  1184. ss_method="2022-blake3-chacha20-poly1305"
  1185. ss_password=$(sing-box generate rand --base64 32)
  1186. shadowtls_password=$(sing-box generate rand --base64 32)
  1187. break
  1188. ;;
  1189. 2)
  1190. ss_method="2022-blake3-aes-256-gcm"
  1191. ss_password=$(sing-box generate rand --base64 32)
  1192. shadowtls_password=$(sing-box generate rand --base64 32)
  1193. break
  1194. ;;
  1195. 3)
  1196. ss_method="2022-blake3-aes-128-gcm"
  1197. ss_password=$(sing-box generate rand --base64 16)
  1198. shadowtls_password=$(sing-box generate rand --base64 16)
  1199. break
  1200. ;;
  1201. 4)
  1202. ss_method="xchacha20-ietf-poly1305"
  1203. ss_password=$(sing-box generate rand --base64 16)
  1204. shadowtls_password=$(sing-box generate rand --base64 16)
  1205. break
  1206. ;;
  1207. 5)
  1208. ss_method="chacha20-ietf-poly1305"
  1209. ss_password=$(sing-box generate rand --base64 16)
  1210. shadowtls_password=$(sing-box generate rand --base64 16)
  1211. break
  1212. ;;
  1213. 6)
  1214. ss_method="aes-256-gcm"
  1215. ss_password=$(sing-box generate rand --base64 16)
  1216. shadowtls_password=$(sing-box generate rand --base64 16)
  1217. break
  1218. ;;
  1219. 7)
  1220. ss_method="aes-192-gcm"
  1221. ss_password=$(sing-box generate rand --base64 16)
  1222. shadowtls_password=$(sing-box generate rand --base64 16)
  1223. break
  1224. ;;
  1225. 8)
  1226. ss_method="aes-128-gcm"
  1227. ss_password=$(sing-box generate rand --base64 16)
  1228. shadowtls_password=$(sing-box generate rand --base64 16)
  1229. break
  1230. ;;
  1231. *)
  1232. echo -e "${RED}错误:无效的选择,请重新输入!${NC}"
  1233. ;;
  1234. esac
  1235. done
  1236. }
  1237. function select_unlocked_items() {
  1238. while true; do
  1239. read -p "请选择要解锁的项目(支持多选):
  1240. 1). ChatGPT
  1241. 2). Netflix
  1242. 3). Disney+
  1243. 4). YouTube
  1244. 请选择[1-4]: " choices
  1245. if [[ "$choices" =~ ^[1234]+$ ]]; then
  1246. selected=($(echo "$choices" | sed 's/./& /g'))
  1247. break
  1248. else
  1249. echo -e "${RED}错误:无效的选择,请重新输入!${NC}"
  1250. fi
  1251. done
  1252. }
  1253. function update_geosite_array() {
  1254. for choice in "${selected[@]}"; do
  1255. case $choice in
  1256. 1)
  1257. geosite+=("\"openai\"")
  1258. ;;
  1259. 2)
  1260. geosite+=("\"netflix\"")
  1261. ;;
  1262. 3)
  1263. geosite+=("\"disney\"")
  1264. ;;
  1265. 4)
  1266. geosite+=("\"youtube\"")
  1267. ;;
  1268. *)
  1269. echo -e "${RED}无效的选择: $choice${NC}"
  1270. ;;
  1271. esac
  1272. done
  1273. }
  1274. function select_outbound() {
  1275. while true; do
  1276. read -p "请选择出站网络 (默认1)
  1277. 1). warp-IPv4
  1278. 2). warp-IPv6
  1279. 请选择[1-2]: " outbound_choice
  1280. case $outbound_choice in
  1281. 1|"")
  1282. outbound="warp-IPv4-out"
  1283. break
  1284. ;;
  1285. 2)
  1286. outbound="warp-IPv6-out"
  1287. break
  1288. ;;
  1289. *)
  1290. echo -e "${RED}错误:无效的选项,请重新输入!${NC}"
  1291. ;;
  1292. esac
  1293. done
  1294. }
  1295. function select_congestion_control() {
  1296. local default_congestion_control="bbr"
  1297. while true; do
  1298. read -p "请选择拥塞控制算法 (默认$default_congestion_control):
  1299. 1). bbr
  1300. 2). cubic
  1301. 3). new_reno
  1302. 请选择[1-3]: " congestion_control
  1303. case $congestion_control in
  1304. 1)
  1305. congestion_control="bbr"
  1306. break
  1307. ;;
  1308. 2)
  1309. congestion_control="cubic"
  1310. break
  1311. ;;
  1312. 3)
  1313. congestion_control="new_reno"
  1314. break
  1315. ;;
  1316. "")
  1317. congestion_control=$default_congestion_control
  1318. break
  1319. ;;
  1320. *)
  1321. echo -e "${RED}错误:无效的选择,请重新输入!${NC}"
  1322. ;;
  1323. esac
  1324. done
  1325. }
  1326. function select_certificate_option() {
  1327. local certificate_option
  1328. local domain_supported=false
  1329. local return_to_menu=false
  1330. while true; do
  1331. read -p "请选择证书来源 (默认1):
  1332. 1). 自签证书
  1333. 2). 监听80端口申请证书(standalone模式)
  1334. 3). cloudflare API 申请证书(DNS API模式)
  1335. 4). 自定义证书路径
  1336. 请选择[1-4]: " certificate_option
  1337. certificate_option=${certificate_option:-1}
  1338. case $certificate_option in
  1339. 1)
  1340. if $disable_option; then
  1341. echo -e "${RED}NaiveProxy节点不支持自签证书,请使用acme申请证书!${NC}"
  1342. continue
  1343. fi
  1344. check_firewall_configuration
  1345. create_self_signed_cert
  1346. break
  1347. ;;
  1348. 2)
  1349. get_local_ip
  1350. get_domain
  1351. check_firewall_configuration
  1352. apply_certificate
  1353. if [ "$return_to_menu" == true ]; then
  1354. return_to_menu=false
  1355. continue
  1356. fi
  1357. break
  1358. ;;
  1359. 3)
  1360. get_local_ip
  1361. get_api_token
  1362. get_zone_id
  1363. get_api_email
  1364. verify_domain
  1365. set_dns_record
  1366. check_firewall_configuration
  1367. if [ "$domain_supported" == "false" ]; then
  1368. continue
  1369. else
  1370. Apply_api_certificate
  1371. if [ "$return_to_menu" == true ]; then
  1372. return_to_menu=false
  1373. continue
  1374. fi
  1375. break
  1376. fi
  1377. ;;
  1378. 4)
  1379. get_local_ip
  1380. get_domain
  1381. check_firewall_configuration
  1382. set_certificate_path
  1383. set_private_key_path
  1384. break
  1385. ;;
  1386. *)
  1387. echo -e "${RED}错误:无效的选择,请重新输入!${NC}"
  1388. ;;
  1389. esac
  1390. done
  1391. }
  1392. function select_vmess_type() {
  1393. while true; do
  1394. read -p "请选择节点类型(默认1):
  1395. 1). VMess+TCP
  1396. 2). VMess+WebSocket
  1397. 3). VMess+gRPC
  1398. 4). VMess+HTTPUpgrade
  1399. 5). VMess+TCP+TLS
  1400. 6). VMess+WebSocket+TLS
  1401. 7). VMess+H2C+TLS
  1402. 8). VMess+gRPC+TLS
  1403. 9). VMess+HTTPUpgrade+TLS
  1404. 请选择 [1-9]: " node_type
  1405. case $node_type in
  1406. "" | 1)
  1407. tls_enabled=false
  1408. break
  1409. ;;
  1410. 2)
  1411. transport_ws=true
  1412. tls_enabled=false
  1413. break
  1414. ;;
  1415. 3)
  1416. transport_grpc=true
  1417. tls_enabled=false
  1418. break
  1419. ;;
  1420. 4)
  1421. transport_httpupgrade=true
  1422. tls_enabled=false
  1423. break
  1424. ;;
  1425. 5)
  1426. tls_enabled=true
  1427. break
  1428. ;;
  1429. 6)
  1430. transport_ws=true
  1431. tls_enabled=true
  1432. break
  1433. ;;
  1434. 7)
  1435. transport_http=true
  1436. tls_enabled=true
  1437. break
  1438. ;;
  1439. 8)
  1440. transport_grpc=true
  1441. tls_enabled=true
  1442. break
  1443. ;;
  1444. 9)
  1445. transport_httpupgrade=true
  1446. tls_enabled=true
  1447. break
  1448. ;;
  1449. *)
  1450. echo -e "${RED}无效的选择,请重新输入!${NC}"
  1451. ;;
  1452. esac
  1453. done
  1454. }
  1455. function select_vless_type() {
  1456. while true; do
  1457. read -p "请选择节点类型 (默认1):
  1458. 1). VLESS+TCP
  1459. 2). VLESS+WebSocket
  1460. 3). VLESS+gRPC
  1461. 4). VLESS+HTTPUpgrade
  1462. 5). VLESS+Vision+REALITY
  1463. 6). VLESS+H2C+REALITY
  1464. 7). VLESS+gRPC+REALITY
  1465. 请选择[1-7]: " flow_option
  1466. case $flow_option in
  1467. "" | 1)
  1468. flow_type=""
  1469. break
  1470. ;;
  1471. 2)
  1472. flow_type=""
  1473. transport_ws=true
  1474. break
  1475. ;;
  1476. 3)
  1477. flow_type=""
  1478. transport_grpc=true
  1479. break
  1480. ;;
  1481. 4)
  1482. flow_type=""
  1483. transport_httpupgrade=true
  1484. break
  1485. ;;
  1486. 5)
  1487. flow_type="xtls-rprx-vision"
  1488. reality_enabled=true
  1489. break
  1490. ;;
  1491. 6)
  1492. flow_type=""
  1493. transport_http=true
  1494. reality_enabled=true
  1495. break
  1496. ;;
  1497. 7)
  1498. flow_type=""
  1499. transport_grpc=true
  1500. reality_enabled=true
  1501. break
  1502. ;;
  1503. *)
  1504. echo -e "${RED}错误的选项,请重新输入!${NC}" >&2
  1505. ;;
  1506. esac
  1507. done
  1508. }
  1509. function select_trojan_type() {
  1510. while true; do
  1511. read -p "请选择节点类型(默认1):
  1512. 1). Trojan+TCP
  1513. 2). Trojan+WebSocket
  1514. 3). Trojan+gRPC
  1515. 4). Trojan+HTTPUpgrade
  1516. 5). Trojan+TCP+TLS
  1517. 6). Trojan+WebSocket+TLS
  1518. 7). Trojan+H2C+TLS
  1519. 8). Trojan+gRPC+TLS
  1520. 9). Trojan+HTTPUpgrade+TLS
  1521. 请选择 [1-9]: " setup_type
  1522. case $setup_type in
  1523. "" | 1)
  1524. tls_enabled=false
  1525. break
  1526. ;;
  1527. 2)
  1528. transport_ws=true
  1529. tls_enabled=false
  1530. break
  1531. ;;
  1532. 3)
  1533. transport_grpc=true
  1534. tls_enabled=false
  1535. break
  1536. ;;
  1537. 4)
  1538. transport_httpupgrade=true
  1539. tls_enabled=false
  1540. break
  1541. ;;
  1542. 5)
  1543. tls_enabled=true
  1544. break
  1545. ;;
  1546. 6)
  1547. transport_ws=true
  1548. tls_enabled=true
  1549. break
  1550. ;;
  1551. 7)
  1552. transport_http=true
  1553. tls_enabled=true
  1554. break
  1555. ;;
  1556. 8)
  1557. transport_grpc=true
  1558. tls_enabled=true
  1559. break
  1560. ;;
  1561. 9)
  1562. transport_httpupgrade=true
  1563. tls_enabled=true
  1564. break
  1565. ;;
  1566. *)
  1567. echo -e "${RED}无效的选择,请重新输入!${NC}"
  1568. ;;
  1569. esac
  1570. done
  1571. }
  1572. function set_short_id() {
  1573. while true; do
  1574. read -p "请输入 Short_Id (用于区分不同的客户端,默认随机生成): " short_id
  1575. if [[ -z "$short_id" ]]; then
  1576. short_id=$(openssl rand -hex 8)
  1577. echo "Short_Id:$short_id"
  1578. break
  1579. elif [[ "$short_id" =~ ^[0-9a-fA-F]{2,16}$ ]]; then
  1580. echo "Short_Id:$short_id"
  1581. break
  1582. else
  1583. echo "错误:请输入两到八位的十六进制字符串!"
  1584. fi
  1585. done
  1586. short_ids+=("$short_id")
  1587. }
  1588. function set_short_ids() {
  1589. while true; do
  1590. set_short_id
  1591. for ((i=0; i<${#short_ids[@]}; i++)); do
  1592. short_id="${short_ids[$i]}"
  1593. done
  1594. read -p "是否继续添加 short id?(Y/N,默认N): " -e choice
  1595. if [[ -z "$choice" ]]; then
  1596. choice="N"
  1597. fi
  1598. if [[ "$choice" == "N" || "$choice" == "n" ]]; then
  1599. short_Ids+="\n \"$short_id\""
  1600. break
  1601. elif [[ "$choice" == "Y" || "$choice" == "y" ]]; then
  1602. short_Ids+="\n \"$short_id\","
  1603. continue
  1604. else
  1605. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1606. fi
  1607. done
  1608. }
  1609. function tuic_multiple_users() {
  1610. while true; do
  1611. set_user_name
  1612. set_user_password
  1613. set_uuid
  1614. for ((i=0; i<${#user_names[@]}; i++)); do
  1615. user_name="${user_names[$i]}"
  1616. user_uuid="${user_uuids[$i]}"
  1617. user_password="${user_passwords[$i]}"
  1618. done
  1619. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1620. if [[ -z "$add_multiple_users" ]]; then
  1621. add_multiple_users="N"
  1622. fi
  1623. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1624. users+="\n {\n \"name\": \"$user_name\",\n \"uuid\": \"$user_uuid\",\n \"password\": \"$user_password\"\n }"
  1625. break
  1626. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1627. users+="\n {\n \"name\": \"$user_name\",\n \"uuid\": \"$user_uuid\",\n \"password\": \"$user_password\"\n },"
  1628. continue
  1629. else
  1630. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1631. fi
  1632. done
  1633. }
  1634. function vmess_multiple_users() {
  1635. while true; do
  1636. set_uuid
  1637. for ((i=0; i<${#user_uuids[@]}; i++)); do
  1638. user_uuid="${user_uuids[$i]}"
  1639. done
  1640. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1641. if [[ -z "$add_multiple_users" ]]; then
  1642. add_multiple_users="N"
  1643. fi
  1644. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1645. users+="\n {\n \"uuid\": \"$user_uuid\",\n \"alterId\": 0\n }"
  1646. break
  1647. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1648. users+="\n {\n \"uuid\": \"$user_uuid\",\n \"alterId\": 0\n },"
  1649. continue
  1650. else
  1651. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1652. fi
  1653. done
  1654. }
  1655. function vless_multiple_users() {
  1656. while true; do
  1657. set_uuid
  1658. for ((i=0; i<${#user_uuids[@]}; i++)); do
  1659. user_uuid="${user_uuids[$i]}"
  1660. done
  1661. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1662. if [[ -z "$add_multiple_users" ]]; then
  1663. add_multiple_users="N"
  1664. fi
  1665. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1666. users+="\n {\n \"uuid\": \"$user_uuid\",\n \"flow\": \"$flow_type\"\n }"
  1667. break
  1668. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1669. users+="\n {\n \"uuid\": \"$user_uuid\",\n \"flow\": \"$flow_type\"\n },"
  1670. continue
  1671. else
  1672. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1673. fi
  1674. done
  1675. }
  1676. function socks_naive_multiple_users() {
  1677. while true; do
  1678. set_user_name
  1679. set_user_password
  1680. for ((i=0; i<${#user_names[@]}; i++)); do
  1681. user_name="${user_names[$i]}"
  1682. user_password="${user_passwords[$i]}"
  1683. done
  1684. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1685. if [[ -z "$add_multiple_users" ]]; then
  1686. add_multiple_users="N"
  1687. fi
  1688. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1689. users+="\n {\n \"username\": \"$user_name\",\n \"password\": \"$user_password\"\n }"
  1690. break
  1691. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1692. users+="\n {\n \"username\": \"$user_name\",\n \"password\": \"$user_password\"\n },"
  1693. continue
  1694. else
  1695. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1696. fi
  1697. done
  1698. }
  1699. function hysteria_multiple_users() {
  1700. while true; do
  1701. set_user_name
  1702. set_user_password
  1703. for ((i=0; i<${#user_names[@]}; i++)); do
  1704. user_name="${user_names[$i]}"
  1705. user_password="${user_passwords[$i]}"
  1706. done
  1707. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1708. if [[ -z "$add_multiple_users" ]]; then
  1709. add_multiple_users="N"
  1710. fi
  1711. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1712. users+="\n {\n \"name\": \"$user_name\",\n \"auth_str\": \"$user_password\"\n }"
  1713. break
  1714. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1715. users+="\n {\n \"name\": \"$user_name\",\n \"auth_str\": \"$user_password\"\n },"
  1716. continue
  1717. else
  1718. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1719. fi
  1720. done
  1721. }
  1722. function hy2_multiple_users() {
  1723. while true; do
  1724. set_user_name
  1725. set_user_password
  1726. for ((i=0; i<${#user_names[@]}; i++)); do
  1727. user_name="${user_names[$i]}"
  1728. user_password="${user_passwords[$i]}"
  1729. done
  1730. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1731. if [[ -z "$add_multiple_users" ]]; then
  1732. add_multiple_users="N"
  1733. fi
  1734. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1735. users+="\n {\n \"name\": \"$user_name\",\n \"password\": \"$user_password\"\n }"
  1736. break
  1737. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1738. users+="\n {\n \"name\": \"$user_name\",\n \"password\": \"$user_password\"\n },"
  1739. continue
  1740. else
  1741. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1742. fi
  1743. done
  1744. }
  1745. function trojan_multiple_users() {
  1746. while true; do
  1747. set_user_password
  1748. for ((i=0; i<${#user_passwords[@]}; i++)); do
  1749. user_password="${user_passwords[$i]}"
  1750. done
  1751. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1752. if [[ -z "$add_multiple_users" ]]; then
  1753. add_multiple_users="N"
  1754. fi
  1755. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1756. users+="\n {\n \"password\": \"$user_password\"\n }"
  1757. break
  1758. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1759. users+="\n {\n \"password\": \"$user_password\"\n },"
  1760. continue
  1761. else
  1762. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1763. fi
  1764. done
  1765. }
  1766. function shadowtls_multiple_users() {
  1767. while true; do
  1768. set_user_name
  1769. set_stls_password
  1770. for ((i=0; i<${#user_names[@]}; i++)); do
  1771. user_name="${user_names[$i]}"
  1772. stls_password="${stls_passwords[$i]}"
  1773. done
  1774. read -p "是否继续添加用户?(Y/N,默认N): " -e add_multiple_users
  1775. if [[ -z "$add_multiple_users" ]]; then
  1776. add_multiple_users="N"
  1777. fi
  1778. if [[ "$add_multiple_users" == "N" || "$add_multiple_users" == "n" ]]; then
  1779. users+="\n {\n \"name\": \"$user_name\",\n \"password\": \"$stls_password\"\n }"
  1780. break
  1781. elif [[ "$add_multiple_users" == "Y" || "$add_multiple_users" == "y" ]]; then
  1782. users+="\n {\n \"name\": \"$user_name\",\n \"password\": \"$stls_password\"\n },"
  1783. continue
  1784. else
  1785. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1786. fi
  1787. done
  1788. }
  1789. function generate_transport_config() {
  1790. if [[ "$transport_ws" = true ]]; then
  1791. read -p "请输入 ws 路径 (默认随机生成): " transport_path_input
  1792. transport_path=${transport_path_input:-/$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8)}
  1793. if [[ ! "$transport_path" =~ ^/ ]]; then
  1794. transport_path="/$transport_path"
  1795. fi
  1796. transport_config="\n \"transport\": {\n \"type\": \"ws\",\n \"path\": \"$transport_path\",\n \"max_early_data\": 2048,\n \"early_data_header_name\": \"Sec-WebSocket-Protocol\"\n },"
  1797. elif [[ "$transport_httpupgrade" = true ]]; then
  1798. transport_path=${transport_path_input:-/$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8)}
  1799. if [[ ! "$transport_path" =~ ^/ ]]; then
  1800. transport_path="/$transport_path"
  1801. fi
  1802. transport_config="\n \"transport\": {\n \"type\": \"httpupgrade\",\n \"path\": \"$transport_path\"\n },"
  1803. elif [[ "$transport_grpc" = true ]]; then
  1804. service_name=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 8)
  1805. transport_config="\n \"transport\": {\n \"type\": \"grpc\",\n \"service_name\": \"$service_name\"\n },"
  1806. elif [[ "$transport_http" = true ]]; then
  1807. transport_config="\n \"transport\": {\n \"type\": \"http\"\n },"
  1808. else
  1809. transport_config=""
  1810. fi
  1811. }
  1812. function generate_tls_config() {
  1813. if [[ "$tls_enabled" = true ]]; then
  1814. set_ech_config
  1815. select_certificate_option
  1816. fi
  1817. if [ -z "$domain_name" ]; then
  1818. if [ -n "$domain" ]; then
  1819. server_name="$domain"
  1820. fi
  1821. else
  1822. server_name="$domain_name"
  1823. fi
  1824. if [[ "$tls_enabled" = true ]]; then
  1825. tls_config=",\n \"tls\": {\n \"enabled\": true,\n \"server_name\": \"$server_name\",\n \"certificate_path\": \"$certificate_path\",\n \"key_path\": \"$private_key_path\"$ech_server_config\n }"
  1826. fi
  1827. }
  1828. function set_ech_config() {
  1829. while true; do
  1830. read -p "是否开启 ECH?(Y/N,默认Y):" enable_ech
  1831. enable_ech="${enable_ech:-Y}"
  1832. if [[ "$enable_ech" == "y" || "$enable_ech" == "Y" ]]; then
  1833. get_ech_keys
  1834. enable_ech=true
  1835. ech_server_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"key\": [\n$ech_key\n ]\n }"
  1836. break
  1837. elif [[ "$enable_ech" == "n" || "$enable_ech" == "N" ]]; then
  1838. enable_ech=false
  1839. ech_server_config=""
  1840. break
  1841. else
  1842. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1843. fi
  1844. done
  1845. }
  1846. function generate_reality_config() {
  1847. if [[ "$reality_enabled" = true ]]; then
  1848. set_server_name
  1849. set_target_server
  1850. generate_private_key
  1851. set_short_ids
  1852. reality_config=",\n \"tls\": {\n \"enabled\": true,\n \"server_name\": \"$server_name\",\n \"reality\": {\n \"enabled\": true,\n \"handshake\": {\n \"server\": \"$target_server\",\n \"server_port\": 443\n },\n \"private_key\": \"$private_key\",\n \"short_id\": [$short_Ids\n ]\n }\n }"
  1853. fi
  1854. }
  1855. function configure_quic_obfuscation() {
  1856. while true; do
  1857. read -p "是否开启QUIC流量混淆(如果你的网络屏蔽了 QUIC 或 HTTP/3 流量,请选择开启)?(Y/N,默认为N): " choice
  1858. choice="${choice:-N}"
  1859. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  1860. read -p "请输入混淆密码(默认随机生成): " new_obfs_password
  1861. if [[ -z "$new_obfs_password" ]]; then
  1862. new_obfs_password=$(sing-box generate rand --base64 9 2>/dev/null || openssl rand -base64 9)
  1863. fi
  1864. obfs_config="\n \"obfs\": {\n \"type\": \"salamander\",\n \"password\": \"$new_obfs_password\"\n },"
  1865. obfs_password="$new_obfs_password"
  1866. echo "混淆密码:$obfs_password"
  1867. break
  1868. elif [[ "$choice" == "n" || "$choice" == "N" ]]; then
  1869. obfs_config=""
  1870. break
  1871. else
  1872. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1873. fi
  1874. done
  1875. }
  1876. function configure_obfuscation() {
  1877. while true; do
  1878. read -p "是否开启 obfs 混淆(用来绕过针对性的 DPI 屏蔽或者 QoS)?(Y/N,默认为N): " choice
  1879. choice="${choice:-N}"
  1880. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  1881. read -p "请输入混淆密码(默认随机生成): " new_obfs_password
  1882. if [[ -z "$new_obfs_password" ]]; then
  1883. new_obfs_password=$(sing-box generate rand --base64 9 2>/dev/null || openssl rand -base64 9)
  1884. fi
  1885. obfs_config="\n \"obfs\": \"$new_obfs_password\","
  1886. obfs_password="$new_obfs_password"
  1887. echo "混淆密码:$obfs_password"
  1888. break
  1889. elif [[ "$choice" == "n" || "$choice" == "N" ]]; then
  1890. obfs_config=""
  1891. break
  1892. else
  1893. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1894. fi
  1895. done
  1896. }
  1897. function configure_multiplex() {
  1898. while true; do
  1899. read -p "是否开启多路复用?(Y/N,默认为Y): " choice
  1900. choice="${choice:-Y}"
  1901. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  1902. configure_brutal
  1903. multiplex_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"padding\": false$brutal_config\n }"
  1904. break
  1905. elif [[ "$choice" == "n" || "$choice" == "N" ]]; then
  1906. multiplex_config=""
  1907. break
  1908. else
  1909. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1910. fi
  1911. done
  1912. }
  1913. function configure_brutal() {
  1914. while true; do
  1915. read -p "是否开启 TCP Brutal?(Y/N,默认为N): " choice
  1916. choice="${choice:-N}"
  1917. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  1918. set_up_speed
  1919. set_down_speed
  1920. brutal_config=",\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $up_mbps,\n \"down_mbps\": $down_mbps\n }"
  1921. break
  1922. elif [[ "$choice" == "n" || "$choice" == "N" ]]; then
  1923. brutal_config=""
  1924. break
  1925. else
  1926. echo -e "${RED}无效的输入,请重新输入!${NC}"
  1927. fi
  1928. done
  1929. }
  1930. function extract_tls_info() {
  1931. local config_file="/usr/local/etc/sing-box/config.json"
  1932. local tls_info_file="/usr/local/etc/sing-box/tls_info.json"
  1933. jq '.inbounds[].tls | select(.server_name and .certificate_path and .key_path) | {server_name: .server_name, certificate_path: .certificate_path, key_path: .key_path}' "$config_file" | jq -s 'unique' > "$tls_info_file"
  1934. }
  1935. function validate_tls_info() {
  1936. local tls_info_file="/usr/local/etc/sing-box/tls_info.json"
  1937. local temp_tls_file="/usr/local/etc/sing-box/temp_tls_info.json"
  1938. server_names=($(jq -r '.[].server_name' "$tls_info_file"))
  1939. for server_name in "${server_names[@]}"; do
  1940. local resolved_ipv4=$(dig +short A "$server_name" 2>/dev/null)
  1941. local resolved_ipv6=$(dig +short AAAA "$server_name" 2>/dev/null)
  1942. if [[ (-n "$resolved_ipv4" && "$resolved_ipv4" == "$ip_v4") || (-n "$resolved_ipv6" && "$resolved_ipv6" == "$ip_v6") ]]; then
  1943. continue
  1944. else
  1945. jq 'map(select(.server_name != "'"$server_name"'"))' "$tls_info_file" > "$temp_tls_file"
  1946. mv "$temp_tls_file" "$tls_info_file"
  1947. fi
  1948. done
  1949. }
  1950. function modify_route_rules() {
  1951. local config_file="/usr/local/etc/sing-box/config.json"
  1952. local temp_config_file="/usr/local/etc/sing-box/temp_config.json"
  1953. if jq -e '.route.rules[] | select(.geosite != null)' "$config_file" >/dev/null; then
  1954. jq '(.route.rules |= [.[] | select(.geosite != null)] + [.[] | select(.geosite == null)])' "$config_file" > "$temp_config_file"
  1955. mv "$temp_config_file" "$config_file"
  1956. fi
  1957. }
  1958. function extract_variables_and_cleanup() {
  1959. server=$(jq -r '.server' "$temp_file")
  1960. server_port=$(jq -r '.server_port' "$temp_file")
  1961. local_address_ipv4=$(jq -r '.local_address[0]' "$temp_file")
  1962. local_address_ipv6=$(jq -r '.local_address[1]' "$temp_file")
  1963. private_key=$(jq -r '.private_key' "$temp_file")
  1964. peer_public_key=$(jq -r '.peer_public_key' "$temp_file")
  1965. reserved=$(jq -c '.reserved' "$temp_file")
  1966. mtu=$(jq -r '.mtu' "$temp_file")
  1967. rm "$temp_file"
  1968. }
  1969. function log_outbound_config() {
  1970. local config_file="/usr/local/etc/sing-box/config.json"
  1971. if ! grep -q '"log": {' "$config_file" || ! grep -q '"route": {' "$config_file" || ! grep -q '"inbounds": \[' "$config_file" || ! grep -q '"outbounds": \[' "$config_file"; then
  1972. echo -e '{\n "log": {\n },\n "route": {\n },\n "inbounds": [\n ],\n "outbounds": [\n ]\n}' > "$config_file"
  1973. sed -i '/"log": {/!b;n;c\ "disabled": true,\n "level": "info",\n "timestamp": true\n },' "$config_file"
  1974. sed -i '/"route": {/!b;n;c\ "rules": [\n ]\n },' "$config_file"
  1975. sed -i '/"outbounds": \[/!b;n;c\ {\n "type": "direct",\n "tag": "direct"\n }\n ]' "$config_file"
  1976. fi
  1977. }
  1978. function modify_format_inbounds_and_outbounds() {
  1979. file_path="/usr/local/etc/sing-box/config.json"
  1980. start_line_inbounds=$(grep -n '"inbounds": \[' "$file_path" | cut -d: -f1)
  1981. start_line_outbounds=$(grep -n '"outbounds": \[' "$file_path" | cut -d: -f1)
  1982. if [ -n "$start_line_inbounds" ]; then
  1983. line_to_modify_inbounds=$((start_line_inbounds - 3))
  1984. if [ "$line_to_modify_inbounds" -ge 1 ]; then
  1985. sed -i "$line_to_modify_inbounds s/,//" "$file_path"
  1986. fi
  1987. fi
  1988. if [ -n "$start_line_outbounds" ]; then
  1989. line_to_modify_outbounds_1=$((start_line_outbounds - 2))
  1990. line_to_modify_outbounds_2=$((start_line_outbounds - 1))
  1991. if [ "$line_to_modify_outbounds_1" -ge 1 ]; then
  1992. sed -i "$line_to_modify_outbounds_1 s/.*/ }/" "$file_path"
  1993. sed -i "$line_to_modify_outbounds_2 s/.*/ ],/" "$file_path"
  1994. fi
  1995. fi
  1996. }
  1997. function generate_http_config() {
  1998. local config_file="/usr/local/etc/sing-box/config.json"
  1999. local cert_path="$certificate_path"
  2000. local key_path="$private_key_path"
  2001. tls_enabled=true
  2002. local tag_label
  2003. generate_unique_tag
  2004. set_listen_port
  2005. socks_naive_multiple_users
  2006. get_local_ip
  2007. generate_tls_config
  2008. local found_rules=0
  2009. local found_inbounds=0
  2010. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" -v tls_config="$tls_config" '
  2011. /"rules": \[/{found_rules=1}
  2012. /"inbounds": \[/{found_inbounds=1}
  2013. {print}
  2014. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2015. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"http\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"set_system_proxy\": false,"; print " \"users\": [" users ""; print " ]" tls_config ""; print " },"; found_inbounds=0}
  2016. ' "$config_file" > "$config_file.tmp"
  2017. mv "$config_file.tmp" "$config_file"
  2018. }
  2019. function generate_Direct_config() {
  2020. local config_file="/usr/local/etc/sing-box/config.json"
  2021. local tag_label
  2022. generate_unique_tag
  2023. local found_rules=0
  2024. local found_inbounds=0
  2025. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v target_address="$target_address" -v override_port="$override_port" '
  2026. /"rules": \[/{found_rules=1}
  2027. /"inbounds": \[/{found_inbounds=1}
  2028. {print}
  2029. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2030. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"direct\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"sniff_timeout\": \"300ms\","; print " \"proxy_protocol\": false,"; print " \"override_address\": \"" target_address "\","; print " \"override_port\": " override_port; print " },"; found_inbounds=0}
  2031. ' "$config_file" > "$config_file.tmp"
  2032. mv "$config_file.tmp" "$config_file"
  2033. }
  2034. function generate_ss_config() {
  2035. local config_file="/usr/local/etc/sing-box/config.json"
  2036. local tag_label
  2037. generate_unique_tag
  2038. configure_multiplex
  2039. local found_rules=0
  2040. local found_inbounds=0
  2041. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v ss_method="$ss_method" -v ss_password="$ss_password" -v multiplex_config="$multiplex_config" '
  2042. /"rules": \[/{found_rules=1}
  2043. /"inbounds": \[/{found_inbounds=1}
  2044. {print}
  2045. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2046. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"shadowsocks\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"method\": \"" ss_method "\","; print " \"password\": \"" ss_password "\"" multiplex_config ""; print " },"; found_inbounds=0}
  2047. ' "$config_file" > "$config_file.tmp"
  2048. mv "$config_file.tmp" "$config_file"
  2049. }
  2050. function generate_vmess_config() {
  2051. local config_file="/usr/local/etc/sing-box/config.json"
  2052. local cert_path="$certificate_path"
  2053. local key_path="$private_key_path"
  2054. local tag_label
  2055. generate_unique_tag
  2056. select_vmess_type
  2057. set_listen_port
  2058. vmess_multiple_users
  2059. generate_transport_config
  2060. if [ "$transport_grpc" != true ] && [ "$transport_http" != true ]; then
  2061. configure_multiplex
  2062. fi
  2063. get_local_ip
  2064. generate_tls_config
  2065. check_firewall_configuration
  2066. local found_rules=0
  2067. local found_inbounds=0
  2068. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" -v transport_config="$transport_config" -v tls_config="$tls_config" -v multiplex_config="$multiplex_config" '
  2069. /"rules": \[/{found_rules=1}
  2070. /"inbounds": \[/{found_inbounds=1}
  2071. {print}
  2072. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2073. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"vmess\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true," transport_config ""; print " \"users\": [" users ""; print " ]" tls_config "" multiplex_config ""; print " },"; found=0}
  2074. ' "$config_file" > "$config_file.tmp"
  2075. mv "$config_file.tmp" "$config_file"
  2076. }
  2077. function generate_socks_config() {
  2078. local config_file="/usr/local/etc/sing-box/config.json"
  2079. local tag_label
  2080. generate_unique_tag
  2081. set_listen_port
  2082. socks_naive_multiple_users
  2083. local found_rules=0
  2084. local found_inbounds=0
  2085. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" '
  2086. /"rules": \[/{found_rules=1}
  2087. /"inbounds": \[/{found_inbounds=1}
  2088. {print}
  2089. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2090. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"socks\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"users\": [" users ""; print " ]"; print " },"; found_inbounds=0}
  2091. ' "$config_file" > "$config_file.tmp"
  2092. mv "$config_file.tmp" "$config_file"
  2093. }
  2094. function generate_naive_config() {
  2095. local config_file="/usr/local/etc/sing-box/config.json"
  2096. disable_option=true
  2097. local tag_label
  2098. generate_unique_tag
  2099. set_listen_port
  2100. socks_naive_multiple_users
  2101. get_local_ip
  2102. select_certificate_option
  2103. local cert_path="$certificate_path"
  2104. local key_path="$private_key_path"
  2105. local found_rules=0
  2106. local found_inbounds=0
  2107. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" -v domain="$domain" -v certificate_path="$certificate_path" -v private_key_path="$private_key_path" '
  2108. /"rules": \[/{found_rules=1}
  2109. /"inbounds": \[/{found_inbounds=1}
  2110. {print}
  2111. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2112. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"naive\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"users\": [" users ""; print " ],"; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" domain "\","; print " \"certificate_path\": \"" certificate_path "\","; print " \"key_path\": \"" private_key_path "\""; print " }"; print " },"; found_inbounds=0}
  2113. ' "$config_file" > "$config_file.tmp"
  2114. mv "$config_file.tmp" "$config_file"
  2115. }
  2116. function generate_tuic_config() {
  2117. local config_file="/usr/local/etc/sing-box/config.json"
  2118. local tag_label
  2119. generate_unique_tag
  2120. set_listen_port
  2121. tuic_multiple_users
  2122. select_congestion_control
  2123. get_local_ip
  2124. set_ech_config
  2125. select_certificate_option
  2126. local cert_path="$certificate_path"
  2127. local key_path="$private_key_path"
  2128. local found_rules=0
  2129. local found_inbounds=0
  2130. local server_name="$domain"
  2131. if [ -z "$domain" ]; then
  2132. server_name="$domain_name"
  2133. fi
  2134. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" -v congestion_control="$congestion_control" -v server_name="$server_name" -v certificate_path="$certificate_path" -v private_key_path="$private_key_path" -v ech_server_config="$ech_server_config" '
  2135. /"rules": \[/{found_rules=1}
  2136. /"inbounds": \[/{found_inbounds=1}
  2137. {print}
  2138. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2139. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"tuic\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"users\": [" users ""; print " ],"; print " \"congestion_control\": \"" congestion_control "\","; print " \"auth_timeout\": \"3s\","; print " \"zero_rtt_handshake\": false,"; print " \"heartbeat\": \"10s\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" server_name "\","; print " \"alpn\": ["; print " \"h3\""; print " ],"; print " \"certificate_path\": \"" certificate_path "\","; print " \"key_path\": \"" private_key_path "\"" ech_server_config ""; print " }"; print " },"; found_inbounds=0}
  2140. ' "$config_file" > "$config_file.tmp"
  2141. mv "$config_file.tmp" "$config_file"
  2142. }
  2143. function generate_Hysteria_config() {
  2144. local config_file="/usr/local/etc/sing-box/config.json"
  2145. local tag_label
  2146. generate_unique_tag
  2147. set_listen_port
  2148. set_up_speed
  2149. set_down_speed
  2150. hysteria_multiple_users
  2151. configure_obfuscation
  2152. get_local_ip
  2153. set_ech_config
  2154. select_certificate_option
  2155. local cert_path="$certificate_path"
  2156. local key_path="$private_key_path"
  2157. local found_rules=0
  2158. local found_inbounds=0
  2159. local server_name="$domain"
  2160. if [ -z "$domain" ]; then
  2161. server_name="$domain_name"
  2162. fi
  2163. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v obfs_config="$obfs_config" -v users="$users" -v server_name="$server_name" -v certificate_path="$certificate_path" -v private_key_path="$private_key_path" -v ech_server_config="$ech_server_config" '
  2164. /"rules": \[/{found_rules=1}
  2165. /"inbounds": \[/{found_inbounds=1}
  2166. {print}
  2167. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2168. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"hysteria\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"up_mbps\": " up_mbps ","; print " \"down_mbps\": " down_mbps ","obfs_config""; print " \"users\": [" users ""; print " ],"; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" server_name "\","; print " \"alpn\": ["; print " \"h3\""; print " ],"; print " \"certificate_path\": \"" certificate_path "\","; print " \"key_path\": \"" private_key_path "\"" ech_server_config ""; print " }"; print " },"; found_inbounds=0}
  2169. ' "$config_file" > "$config_file.tmp"
  2170. mv "$config_file.tmp" "$config_file"
  2171. }
  2172. function generate_shadowtls_config() {
  2173. local config_file="/usr/local/etc/sing-box/config.json"
  2174. local tag_label
  2175. generate_unique_tag
  2176. tag_label1="$tag_label"
  2177. generate_unique_tag
  2178. tag_label2="$tag_label"
  2179. set_listen_port
  2180. select_encryption_method
  2181. shadowtls_multiple_users
  2182. set_ss_password
  2183. set_target_server
  2184. configure_multiplex
  2185. local found_rules=0
  2186. local found_inbounds=0
  2187. awk -v tag_label1="$tag_label1" -v tag_label2="$tag_label2" -v listen_port="$listen_port" -v users="$users" -v target_server="$target_server" -v ss_method="$ss_method" -v ss_password="$ss_password" -v multiplex_config="$multiplex_config" '
  2188. /"rules": \[/{found_rules=1}
  2189. /"inbounds": \[/{found_inbounds=1}
  2190. {print}
  2191. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label1 "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2192. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"shadowtls\","; print " \"tag\": \"" tag_label1 "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"version\": 3,"; print " \"users\": [" users ""; print " ],"; print " \"handshake\": {"; print " \"server\": \"" target_server "\","; print " \"server_port\": 443"; print " },"; print " \"strict_mode\": true,"; print " \"detour\": \"" tag_label2 "\""; print " },"; print " {"; print " \"type\": \"shadowsocks\","; print " \"tag\": \"" tag_label2 "\","; print " \"listen\": \"127.0.0.1\","; print " \"method\": \"" ss_method "\","; print " \"password\": \"" ss_password "\"" multiplex_config ""; print " },"; found=0}
  2193. ' "$config_file" > "$config_file.tmp"
  2194. mv "$config_file.tmp" "$config_file"
  2195. }
  2196. function generate_juicity_config() {
  2197. local config_file="/usr/local/etc/juicity/config.json"
  2198. set_listen_port
  2199. set_uuid
  2200. set_user_password
  2201. select_congestion_control
  2202. get_local_ip
  2203. select_certificate_option
  2204. local cert_path="$certificate_path"
  2205. local key_path="$private_key_path"
  2206. awk -v listen_port="$listen_port" -v user_uuids="$user_uuids" -v user_passwords="$user_passwords" -v certificate_path="$certificate_path" -v private_key_path="$private_key_path" -v congestion_control="$congestion_control" 'BEGIN { print "{"; printf " \"listen\": \":%s\",\n", listen_port; printf " \"users\": {\n"; printf " \"%s\": \"%s\"\n", user_uuids, user_passwords; printf " },\n"; printf " \"certificate\": \"%s\",\n", certificate_path; printf " \"private_key\": \"%s\",\n", private_key_path; printf " \"congestion_control\": \"%s\",\n", congestion_control; printf " \"disable_outbound_udp443\": true,\n"; print " \"log_level\": \"info\""; print "}"}' > "$config_file"
  2207. }
  2208. function generate_vless_config() {
  2209. local config_file="/usr/local/etc/sing-box/config.json"
  2210. local tag_label
  2211. generate_unique_tag
  2212. select_vless_type
  2213. set_listen_port
  2214. vless_multiple_users
  2215. generate_transport_config
  2216. generate_reality_config
  2217. if [[ "$flow_type" != xtls-rprx-vision ]] && [[ "$transport_grpc" != true ]] && [[ "$transport_http" != true ]]; then
  2218. configure_multiplex
  2219. fi
  2220. local found_rules=0
  2221. local found_inbounds=0
  2222. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" -v transport_config="$transport_config" -v reality_config="$reality_config" -v multiplex_config="$multiplex_config" '
  2223. /"rules": \[/{found_rules=1}
  2224. /"inbounds": \[/{found_inbounds=1}
  2225. {print}
  2226. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2227. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"vless\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true," transport_config ""; print " \"users\": [" users ""; print " ]"reality_config"" multiplex_config ""; print " },"; found=0}
  2228. ' "$config_file" > "$config_file.tmp"
  2229. mv "$config_file.tmp" "$config_file"
  2230. }
  2231. function generate_Hy2_config() {
  2232. local config_file="/usr/local/etc/sing-box/config.json"
  2233. local tag_label
  2234. generate_unique_tag
  2235. set_listen_port
  2236. set_up_speed
  2237. set_down_speed
  2238. hy2_multiple_users
  2239. configure_quic_obfuscation
  2240. set_fake_domain
  2241. get_local_ip
  2242. set_ech_config
  2243. select_certificate_option
  2244. local cert_path="$certificate_path"
  2245. local key_path="$private_key_path"
  2246. local found_rules=0
  2247. local found_inbounds=0
  2248. local server_name="$domain"
  2249. if [ -z "$domain" ]; then
  2250. server_name="$domain_name"
  2251. fi
  2252. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v obfs_config="$obfs_config" -v users="$users" -v fake_domain="$fake_domain" -v server_name="$server_name" -v certificate_path="$certificate_path" -v private_key_path="$private_key_path" -v ech_server_config="$ech_server_config" '
  2253. /"rules": \[/{found_rules=1}
  2254. /"inbounds": \[/{found_inbounds=1}
  2255. {print}
  2256. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2257. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"hysteria2\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true,"; print " \"up_mbps\": " up_mbps ","; print " \"down_mbps\": " down_mbps ","obfs_config""; print " \"users\": [" users ""; print " ],"; print " \"ignore_client_bandwidth\": false,"; print " \"masquerade\": \"https://" fake_domain "\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" server_name "\","; print " \"alpn\": ["; print " \"h3\""; print " ],"; print " \"certificate_path\": \"" certificate_path "\","; print " \"key_path\": \"" private_key_path "\"" ech_server_config ""; print " }"; print " },"; found=0}
  2258. ' "$config_file" > "$config_file.tmp"
  2259. mv "$config_file.tmp" "$config_file"
  2260. }
  2261. function generate_trojan_config() {
  2262. local config_file="/usr/local/etc/sing-box/config.json"
  2263. local tag_label
  2264. generate_unique_tag
  2265. select_trojan_type
  2266. set_listen_port
  2267. trojan_multiple_users
  2268. generate_transport_config
  2269. if [ "$transport_grpc" != true ] && [ "$transport_http" != true ]; then
  2270. configure_multiplex
  2271. fi
  2272. get_local_ip
  2273. generate_tls_config
  2274. local cert_path="$certificate_path"
  2275. local key_path="$private_key_path"
  2276. check_firewall_configuration
  2277. local found_rules=0
  2278. local found_inbounds=0
  2279. awk -v tag_label="$tag_label" -v listen_port="$listen_port" -v users="$users" -v transport_config="$transport_config" -v tls_config="$tls_config" -v multiplex_config="$multiplex_config" '
  2280. /"rules": \[/{found_rules=1}
  2281. /"inbounds": \[/{found_inbounds=1}
  2282. {print}
  2283. found_rules && /"rules": \[/{print " {"; print " \"inbound\": [\"" tag_label "\"],"; print " \"outbound\": \"direct\""; print " },"; found_rules=0}
  2284. found_inbounds && /"inbounds": \[/{print " {"; print " \"type\": \"trojan\","; print " \"tag\": \"" tag_label "\","; print " \"listen\": \"::\","; print " \"listen_port\": " listen_port ","; print " \"sniff\": true,"; print " \"sniff_override_destination\": true," transport_config ""; print " \"users\": [" users ""; print " ]" tls_config "" multiplex_config ""; print " },"; found=0}
  2285. ' "$config_file" > "$config_file.tmp"
  2286. mv "$config_file.tmp" "$config_file"
  2287. }
  2288. function update_route_file() {
  2289. local config_file="/usr/local/etc/sing-box/config.json"
  2290. local geosite_list=$(IFS=,; echo "${geosite[*]}")
  2291. local geosite_formatted=$(sed 's/,/,\\n /g' <<< "$geosite_list")
  2292. echo "正在配置 WireGuard..."
  2293. sed -i '/"rules": \[/!b;a\
  2294. {\
  2295. "geosite": [\
  2296. '"$geosite_formatted"'\
  2297. ],\
  2298. "outbound": "'"$1"'"\
  2299. },' "$config_file"
  2300. }
  2301. function update_outbound_file() {
  2302. local config_file="/usr/local/etc/sing-box/config.json"
  2303. awk -v server="$server" -v server_port="$server_port" -v local_address_ipv4="$local_address_ipv4" -v local_address_ipv6="$local_address_ipv6" -v private_key="$private_key" -v peer_public_key="$peer_public_key" -v reserved="$reserved" -v mtu="$mtu" '
  2304. {
  2305. if ($0 ~ /"outbounds": \[/) {
  2306. print $0
  2307. for (i=1; i<=4; i++) {
  2308. getline
  2309. if (i == 4) {
  2310. print "" $0 ","
  2311. } else {
  2312. print $0
  2313. }
  2314. }
  2315. print " {"; print " \"type\": \"direct\","; print " \"tag\": \"warp-IPv4-out\","; print " \"detour\": \"wireguard-out\","; print " \"domain_strategy\": \"ipv4_only\""; print " },"; print " {"; print " \"type\": \"direct\","; print " \"tag\": \"warp-IPv6-out\","; print " \"detour\": \"wireguard-out\","; print " \"domain_strategy\": \"ipv6_only\""; print " },"; print " {"; print " \"type\": \"wireguard\","; print " \"tag\": \"wireguard-out\","; print " \"server\": \"" server "\","; print " \"server_port\": " server_port ","; print " \"system_interface\": false,"; print " \"interface_name\": \"wg0\","; print " \"local_address\": ["; print " \"" local_address_ipv4 "\","; print " \"" local_address_ipv6 "\"" ; print " ],"; print " \"private_key\": \"" private_key "\","; print " \"peer_public_key\": \"" peer_public_key "\","; print " \"reserved\": " reserved ","; print " \"mtu\": " mtu; print " }"
  2316. } else {
  2317. print $0
  2318. }
  2319. }
  2320. ' "$config_file" > "$config_file.tmp"
  2321. mv "$config_file.tmp" "$config_file"
  2322. echo "WireGuard 配置完成。"
  2323. }
  2324. function write_phone_client_file() {
  2325. local dir="/usr/local/etc/sing-box"
  2326. local phone_client="${dir}/phone_client.json"
  2327. if [ ! -s "${phone_client}" ]; then
  2328. awk 'BEGIN { print "{"; print " \"log\": {"; print " \"disabled\": false,"; print " \"level\": \"warn\","; print " \"timestamp\": true"; print " },"; print " \"dns\": {"; print " \"servers\": ["; print " {"; print " \"tag\": \"dns_proxy\","; print " \"address\": \"https://dns.google/dns-query\","; print " \"address_resolver\": \"dns_local\","; print " \"detour\": \"select\""; print " },"; print " {"; print " \"tag\": \"dns_direct\","; print " \"address\": \"https://dns.alidns.com/dns-query\","; print " \"address_resolver\": \"dns_local\","; print " \"detour\": \"direct\""; print " },"; print " {"; print " \"tag\": \"dns_block\","; print " \"address\": \"rcode://success\""; print " },"; print " {"; print " \"tag\": \"dns_fakeip\","; print " \"address\": \"fakeip\""; print " },"; print " {"; print " \"tag\": \"dns_local\","; print " \"address\": \"223.5.5.5\","; print " \"detour\": \"direct\""; print " }"; print " ],"; print " \"rules\": ["; print " {"; print " \"outbound\": \"any\","; print " \"server\": \"dns_local\""; print " },"; print " {"; print " \"geosite\": ["; print " \"category-ads-all\""; print " ],"; print " \"server\": \"dns_block\","; print " \"disable_cache\": true"; print " },"; print " {"; print " \"query_type\": ["; print " \"A\","; print " \"AAAA\""; print " ],"; print " \"server\": \"dns_fakeip\""; print " },"; print " {"; print " \"clash_mode\": \"Direct\","; print " \"server\": \"dns_direct\""; print " },"; print " {"; print " \"clash_mode\": \"Global\","; print " \"server\": \"dns_proxy\""; print " },"; print " {"; print " \"type\": \"logical\","; print " \"mode\": \"and\","; print " \"rules\": ["; print " {"; print " \"geosite\": \"geolocation-!cn\","; print " \"invert\": true"; print " },"; print " {"; print " \"geosite\": ["; print " \"cn\","; print " \"category-companies@cn\""; print " ]"; print " }"; print " ],"; print " \"server\": \"dns_direct\""; print " }"; print " ],"; print " \"final\": \"dns_proxy\","; print " \"strategy\": \"ipv4_only\","; print " \"independent_cache\": true,"; print " \"fakeip\": {"; print " \"enabled\": true,"; print " \"inet4_range\": \"198.18.0.0/15\","; print " \"inet6_range\": \"fc00::/18\""; print " }"; print " },"; print " \"route\": {"; print " \"geoip\": {"; print " \"download_url\": \"https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db\","; print " \"download_detour\": \"select\""; print " },"; print " \"geosite\": {"; print " \"download_url\": \"https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db\","; print " \"download_detour\": \"select\""; print " },"; print " \"rules\": ["; print " {"; print " \"protocol\": \"dns\","; print " \"outbound\": \"dns-out\""; print " },"; print " {"; print " \"geoip\": \"private\","; print " \"outbound\": \"direct\""; print " },"; print " {"; print " \"clash_mode\": \"Direct\","; print " \"outbound\": \"direct\""; print " },"; print " {"; print " \"clash_mode\": \"Global\","; print " \"outbound\": \"select\""; print " },"; print " {"; print " \"type\": \"logical\","; print " \"mode\": \"and\","; print " \"rules\": ["; print " {"; print " \"geosite\": \"geolocation-!cn\","; print " \"invert\": true"; print " },"; print " {"; print " \"geosite\": ["; print " \"cn\","; print " \"category-companies@cn\""; print " ],"; print " \"geoip\": \"cn\""; print " }"; print " ],"; print " \"outbound\": \"direct\""; print " }"; print " ],"; print " \"final\": \"select\","; print " \"auto_detect_interface\": true"; print " },"; print " \"inbounds\": ["; print " {"; print " \"type\": \"tun\","; print " \"tag\": \"tun-in\","; print " \"inet4_address\": \"172.19.0.1/30\","; print " \"inet6_address\": \"fdfe:dcba:9876::1/126\","; print " \"auto_route\": true,"; print " \"strict_route\": true,"; print " \"stack\": \"mixed\","; print " \"sniff\": true,"; print " \"sniff_override_destination\": false"; print " }"; print " ],"; print " \"outbounds\": ["; print " {"; print " \"type\": \"urltest\","; print " \"tag\": \"auto\","; print " \"outbounds\": ["; print " ],"; print " \"url\": \"https://www.gstatic.com/generate_204\","; print " \"interval\": \"1m\","; print " \"tolerance\": 50,"; print " \"interrupt_exist_connections\": false"; print " },"; print " {"; print " \"type\": \"selector\","; print " \"tag\": \"select\","; print " \"outbounds\": ["; print " \"auto\""; print " ],"; print " \"default\": \"auto\","; print " \"interrupt_exist_connections\": false"; print " },"; print " {"; print " \"type\": \"direct\","; print " \"tag\": \"direct\""; print " },"; print " {"; print " \"type\": \"block\","; print " \"tag\": \"block\""; print " },"; print " {"; print " \"type\": \"dns\","; print " \"tag\": \"dns-out\""; print " }"; print " ],"; print " \"experimental\": {"; print " \"clash_api\": {"; print " \"external_controller\": \"127.0.0.1:9090\","; print " \"external_ui\": \"ui\","; print " \"external_ui_download_detour\": \"direct\","; print " \"store_fakeip\": true"; print " }"; print " },"; print " \"ntp\": {"; print " \"enabled\": true,"; print " \"server\": \"time.apple.com\","; print " \"server_port\": 123,"; print " \"interval\": \"30m\","; print " \"detour\": \"direct\""; print " }"; print "}" }' > "${phone_client}"
  2329. fi
  2330. }
  2331. function write_win_client_file() {
  2332. local dir="/usr/local/etc/sing-box"
  2333. local win_client="${dir}/win_client.json"
  2334. if [ ! -s "${win_client}" ]; then
  2335. awk 'BEGIN { print "{"; print " \"log\": {"; print " \"disabled\": false,"; print " \"level\": \"warn\","; print " \"timestamp\": true"; print " },"; print " \"dns\": {"; print " \"servers\": ["; print " {"; print " \"tag\": \"dns_proxy\","; print " \"address\": \"https://dns.google/dns-query\","; print " \"address_resolver\": \"dns_local\","; print " \"detour\": \"select\""; print " },"; print " {"; print " \"tag\": \"dns_direct\","; print " \"address\": \"https://dns.alidns.com/dns-query\","; print " \"address_resolver\": \"dns_local\","; print " \"detour\": \"direct\""; print " },"; print " {"; print " \"tag\": \"dns_block\","; print " \"address\": \"rcode://success\""; print " },"; print " {"; print " \"tag\": \"dns_fakeip\","; print " \"address\": \"fakeip\""; print " },"; print " {"; print " \"tag\": \"dns_local\","; print " \"address\": \"223.5.5.5\","; print " \"detour\": \"direct\""; print " }"; print " ],"; print " \"rules\": ["; print " {"; print " \"outbound\": \"any\","; print " \"server\": \"dns_local\""; print " },"; print " {"; print " \"geosite\": ["; print " \"category-ads-all\""; print " ],"; print " \"server\": \"dns_block\","; print " \"disable_cache\": true"; print " },"; print " {"; print " \"query_type\": ["; print " \"A\","; print " \"AAAA\""; print " ],"; print " \"server\": \"dns_fakeip\""; print " },"; print " {"; print " \"clash_mode\": \"Direct\","; print " \"server\": \"dns_direct\""; print " },"; print " {"; print " \"clash_mode\": \"Global\","; print " \"server\": \"dns_proxy\""; print " },"; print " {"; print " \"type\": \"logical\","; print " \"mode\": \"and\","; print " \"rules\": ["; print " {"; print " \"geosite\": \"geolocation-!cn\","; print " \"invert\": true"; print " },"; print " {"; print " \"geosite\": ["; print " \"cn\","; print " \"category-companies@cn\""; print " ]"; print " }"; print " ],"; print " \"server\": \"dns_direct\""; print " }"; print " ],"; print " \"final\": \"dns_proxy\","; print " \"strategy\": \"ipv4_only\","; print " \"independent_cache\": true,"; print " \"fakeip\": {"; print " \"enabled\": true,"; print " \"inet4_range\": \"198.18.0.0/15\","; print " \"inet6_range\": \"fc00::/18\""; print " }"; print " },"; print " \"route\": {"; print " \"geoip\": {"; print " \"download_url\": \"https://github.com/SagerNet/sing-geoip/releases/latest/download/geoip.db\","; print " \"download_detour\": \"select\""; print " },"; print " \"geosite\": {"; print " \"download_url\": \"https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db\","; print " \"download_detour\": \"select\""; print " },"; print " \"rules\": ["; print " {"; print " \"protocol\": \"dns\","; print " \"outbound\": \"dns-out\""; print " },"; print " {"; print " \"geoip\": \"private\","; print " \"outbound\": \"direct\""; print " },"; print " {"; print " \"clash_mode\": \"Direct\","; print " \"outbound\": \"direct\""; print " },"; print " {"; print " \"clash_mode\": \"Global\","; print " \"outbound\": \"select\""; print " },"; print " {"; print " \"type\": \"logical\","; print " \"mode\": \"and\","; print " \"rules\": ["; print " {"; print " \"geosite\": \"geolocation-!cn\","; print " \"invert\": true"; print " },"; print " {"; print " \"geosite\": ["; print " \"cn\","; print " \"category-companies@cn\""; print " ],"; print " \"geoip\": \"cn\""; print " }"; print " ],"; print " \"outbound\": \"direct\""; print " }"; print " ],"; print " \"final\": \"select\","; print " \"auto_detect_interface\": true"; print " },"; print " \"inbounds\": ["; print " {"; print " \"type\": \"mixed\","; print " \"tag\": \"mixed-in\","; print " \"listen\": \"::\","; print " \"listen_port\": 1080,"; print " \"sniff\": true,"; print " \"set_system_proxy\": false"; print " }"; print " ],"; print " \"outbounds\": ["; print " {"; print " \"type\": \"urltest\","; print " \"tag\": \"auto\","; print " \"outbounds\": ["; print " ],"; print " \"url\": \"https://www.gstatic.com/generate_204\","; print " \"interval\": \"1m\","; print " \"tolerance\": 50,"; print " \"interrupt_exist_connections\": false"; print " },"; print " {"; print " \"type\": \"selector\","; print " \"tag\": \"select\","; print " \"outbounds\": ["; print " \"auto\""; print " ],"; print " \"default\": \"auto\","; print " \"interrupt_exist_connections\": false"; print " },"; print " {"; print " \"type\": \"direct\","; print " \"tag\": \"direct\""; print " },"; print " {"; print " \"type\": \"block\","; print " \"tag\": \"block\""; print " },"; print " {"; print " \"type\": \"dns\","; print " \"tag\": \"dns-out\""; print " }"; print " ],"; print " \"experimental\": {"; print " \"clash_api\": {"; print " \"external_controller\": \"127.0.0.1:9090\","; print " \"external_ui\": \"ui\","; print " \"external_ui_download_detour\": \"direct\","; print " \"store_fakeip\": true"; print " }"; print " },"; print " \"ntp\": {"; print " \"enabled\": true,"; print " \"server\": \"time.apple.com\","; print " \"server_port\": 123,"; print " \"interval\": \"30m\","; print " \"detour\": \"direct\""; print " }"; print "}" }' > "${win_client}"
  2336. fi
  2337. }
  2338. function write_clash_yaml() {
  2339. local dir="/usr/local/etc/sing-box"
  2340. local clash_yaml="${dir}/clash.yaml"
  2341. if [ ! -s "${clash_yaml}" ]; then
  2342. awk 'BEGIN { print "mixed-port: 10801"; print "allow-lan: true"; print "bind-address: \"*\""; print "find-process-mode: strict"; print "mode: rule"; print "geodata-mode: true"; print "geox-url:"; print " geoip: \"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.dat\""; print " geosite: \"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat\""; print " mmdb: \"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country.mmdb\""; print "log-level: info"; print "ipv6: true"; print "global-client-fingerprint: chrome"; print "tun:"; print " enable: true"; print " stack: system"; print " dns-hijack:"; print " - 0.0.0.0:53"; print " auto-detect-interface: true"; print " auto-route: true"; print " mtu: 9000"; print "profile:"; print " store-selected: false"; print " store-fake-ip: true"; print "sniffer:"; print " enable: true"; print " override-destination: false"; print " sniff:"; print " TLS:"; print " ports: [443, 8443]"; print " HTTP:"; print " ports: [80, 8080-8880]"; print " override-destination: true"; print "dns:"; print " enable: true"; print " prefer-h3: true"; print " listen: 0.0.0.0:53"; print " ipv6: true"; print " ipv6-timeout: 300"; print " default-nameserver:"; print " - 223.5.5.5"; print " enhanced-mode: fake-ip"; print " fake-ip-range: 198.18.0.1/16"; print " nameserver:"; print " - https://doh.pub/dns-query"; print " - https://dns.alidns.com/dns-query"; print " fallback:"; print " - https://dns.google/dns-query"; print " - https://1.1.1.1/dns-query"; print " fallback-filter:"; print " geoip: true"; print " geoip-code: CN"; print " geosite:"; print " - gfw"; print " ipcidr:"; print " - 240.0.0.0/4"; print " domain:"; print " - \"+.google.com\""; print " - \"+.facebook.com\""; print " - \"+.youtube.com\""; print " nameserver-policy:"; print " \"geosite:cn,private\":"; print " - https://doh.pub/dns-query"; print " - https://dns.alidns.com/dns-query"; print " \"geosite:category-ads-all\": rcode://success"; print "proxies:"; print "proxy-groups:"; print " - name: Proxy"; print " type: select"; print " proxies:"; print " - auto"; print " - name: auto"; print " type: url-test"; print " proxies:"; print " url: \"https://cp.cloudflare.com/generate_204\""; print " interval: 300"; print "rules:"; print " - GEOSITE,private,DIRECT"; print " - GEOSITE,category-ads-all,REJECT"; print " - GEOSITE,cn,DIRECT"; print " - GEOIP,cn,DIRECT"; print " - MATCH,Proxy"; }' > "${clash_yaml}"
  2343. sed -i'' -e '/^ - "+\.google\.com"/s/"/'\''/g' "${clash_yaml}"
  2344. sed -i'' -e '/^ - "+\.facebook\.com"/s/"/'\''/g' "${clash_yaml}"
  2345. sed -i'' -e '/^ - "+\.youtube\.com"/s/"/'\''/g' "${clash_yaml}"
  2346. fi
  2347. }
  2348. function write_naive_client_file() {
  2349. local naive_client_file="$naive_client_filename"
  2350. awk -v naive_client_file="$naive_client_file" 'BEGIN { print "{"; print " \"listen\": \"socks://127.0.0.1:1080\","; print " \"proxy\": \"https://user_name:user_password@server_name:listen_port\""; print "}" }' > "$naive_client_file"
  2351. }
  2352. function generate_shadowsocks_win_client_config() {
  2353. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2354. local proxy_name
  2355. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  2356. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  2357. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  2358. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  2359. fi
  2360. while true; do
  2361. proxy_name="ss-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2362. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2363. break
  2364. fi
  2365. done
  2366. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v ss_method="$ss_method" -v ss_password="$ss_password" -v multiplex_client_config="$multiplex_client_config" '
  2367. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"shadowsocks\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"method\": \"" ss_method "\", "; print " \"password\": \"" ss_password "\"" multiplex_client_config ""; print " },";}
  2368. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2369. {print}' "$win_client_file" > "$win_client_file.tmp"
  2370. mv "$win_client_file.tmp" "$win_client_file"
  2371. }
  2372. function generate_shadowsocks_phone_client_config() {
  2373. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2374. local proxy_name
  2375. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  2376. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  2377. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  2378. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  2379. fi
  2380. while true; do
  2381. proxy_name="ss-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2382. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2383. break
  2384. fi
  2385. done
  2386. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v ss_method="$ss_method" -v ss_password="$ss_password" -v multiplex_client_config="$multiplex_client_config" '
  2387. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"shadowsocks\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"method\": \"" ss_method "\", "; print " \"password\": \"" ss_password "\"" multiplex_client_config ""; print " },";}
  2388. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2389. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2390. mv "$phone_client_file.tmp" "$phone_client_file"
  2391. }
  2392. function generate_shadowsocks_yaml() {
  2393. local filename="/usr/local/etc/sing-box/clash.yaml"
  2394. local proxy_name
  2395. while true; do
  2396. proxy_name="ss-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2397. if ! grep -q "name: $proxy_name" "$filename"; then
  2398. break
  2399. fi
  2400. done
  2401. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v ss_method="$ss_method" -v ss_password="$ss_password" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: ss"; print " server:", local_ip; print " port:", listen_port; print " cipher:", ss_method; print " password:", "\"" ss_password "\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2402. }
  2403. function generate_juicity_win_client_config() {
  2404. local client_file="/usr/local/etc/juicity/client.json"
  2405. local server_name="$domain"
  2406. local server_value
  2407. local tls_insecure
  2408. if [ -z "$domain" ]; then
  2409. server_name="$domain_name"
  2410. server_value="$local_ip"
  2411. tls_insecure="true"
  2412. else
  2413. server_value="$domain"
  2414. tls_insecure="false"
  2415. fi
  2416. awk -v listen_port="$listen_port" -v server_value="$server_value" -v user_uuids="$user_uuids" -v user_passwords="$user_passwords" -v server_name="$server_name" -v tls_insecure="$tls_insecure" -v congestion_control="$congestion_control" 'BEGIN { print "{"; printf " \"listen\": \":%s\",\n", 1080; printf " \"server\": \"%s:%s\",\n", server_value, listen_port; printf " \"uuid\": \"%s\",\n", user_uuids; printf " \"password\": \"%s\",\n", user_passwords; printf " \"sni\": \"%s\",\n", server_name; printf " \"allow_insecure\": %s,\n", tls_insecure; printf " \"congestion_control\": \"%s\",\n", congestion_control; printf " \"log_level\": \"info\"\n"; print "}"}' > "$client_file"
  2417. echo "客户端配置文件已保存至$client_file,请下载后使用!"
  2418. }
  2419. function generate_tuic_phone_client_config() {
  2420. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2421. local server_name="$domain"
  2422. local proxy_name
  2423. local server_value
  2424. local tls_insecure
  2425. if [ -z "$domain" ]; then
  2426. server_name="$domain_name"
  2427. server_value="$local_ip"
  2428. tls_insecure="true"
  2429. else
  2430. server_value="$domain"
  2431. tls_insecure="false"
  2432. fi
  2433. if [ -n "$ech_config" ]; then
  2434. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2435. fi
  2436. while true; do
  2437. proxy_name="tuic-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2438. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2439. break
  2440. fi
  2441. done
  2442. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v user_password="$user_password" -v congestion_control="$congestion_control" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2443. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"tuic\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\", "; print " \"password\": \"" user_password "\", "; print " \"congestion_control\": \""congestion_control"\","; print " \"udp_relay_mode\": \"native\","; print " \"zero_rtt_handshake\": false,"; print " \"heartbeat\": \"10s\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\", "; print " \"alpn\": ["; print " \"h3\""; print " ]" ech_client_config ""; print " }"; print " },";}
  2444. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2445. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2446. mv "$phone_client_file.tmp" "$phone_client_file"
  2447. }
  2448. function generate_tuic_win_client_config() {
  2449. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2450. local server_name="$domain"
  2451. local proxy_name
  2452. local server_value
  2453. local tls_insecure
  2454. if [ -z "$domain" ]; then
  2455. server_name="$domain_name"
  2456. server_value="$local_ip"
  2457. tls_insecure="true"
  2458. else
  2459. server_value="$domain"
  2460. tls_insecure="false"
  2461. fi
  2462. if [ -n "$ech_config" ]; then
  2463. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2464. fi
  2465. while true; do
  2466. proxy_name="tuic-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2467. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2468. break
  2469. fi
  2470. done
  2471. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v user_password="$user_password" -v congestion_control="$congestion_control" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2472. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"tuic\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\", "; print " \"password\": \"" user_password "\", "; print " \"congestion_control\": \""congestion_control"\","; print " \"udp_relay_mode\": \"native\","; print " \"zero_rtt_handshake\": false,"; print " \"heartbeat\": \"10s\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\", "; print " \"alpn\": ["; print " \"h3\""; print " ]" ech_client_config ""; print " }"; print " },";}
  2473. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2474. {print}' "$win_client_file" > "$win_client_file.tmp"
  2475. mv "$win_client_file.tmp" "$win_client_file"
  2476. }
  2477. function generate_tuic_yaml() {
  2478. local filename="/usr/local/etc/sing-box/clash.yaml"
  2479. local server_name="$domain"
  2480. local proxy_name
  2481. local server_value
  2482. local tls_insecure
  2483. if [ -z "$domain" ]; then
  2484. server_name="$domain_name"
  2485. server_value="$local_ip"
  2486. tls_insecure="true"
  2487. else
  2488. server_value="$domain"
  2489. tls_insecure="false"
  2490. fi
  2491. while true; do
  2492. proxy_name="tuic-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2493. if ! grep -q "name: $proxy_name" "$filename"; then
  2494. break
  2495. fi
  2496. done
  2497. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v user_password="$user_password" -v congestion_control="$congestion_control" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " server:", server_value; print " port:", listen_port; print " type: tuic"; print " uuid:", user_uuid; print " password:", user_password; print " sni:", server_name; print " alpn: [h3]"; print " request-timeout: 8000"; print " udp-relay-mode: native"; print " skip-cert-verify:", tls_insecure; print " congestion-controller:", congestion_control; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2498. }
  2499. function generate_socks_win_client_config() {
  2500. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2501. local proxy_name
  2502. while true; do
  2503. proxy_name="socks-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2504. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2505. break
  2506. fi
  2507. done
  2508. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_name="$user_name" -v user_password="$user_password" '
  2509. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"socks\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"username\": \"" user_name "\", "; print " \"password\": \"" user_password "\" "; print " },";}
  2510. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2511. {print}' "$win_client_file" > "$win_client_file.tmp"
  2512. mv "$win_client_file.tmp" "$win_client_file"
  2513. }
  2514. function generate_socks_phone_client_config() {
  2515. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2516. local proxy_name
  2517. while true; do
  2518. proxy_name="socks-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2519. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2520. break
  2521. fi
  2522. done
  2523. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_name="$user_name" -v user_password="$user_password" '
  2524. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"socks\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"username\": \"" user_name "\", "; print " \"password\": \"" user_password "\" "; print " },";}
  2525. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2526. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2527. mv "$phone_client_file.tmp" "$phone_client_file"
  2528. }
  2529. function generate_socks_yaml() {
  2530. local filename="/usr/local/etc/sing-box/clash.yaml"
  2531. local proxy_name
  2532. while true; do
  2533. proxy_name="socks-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2534. if ! grep -q "name: $proxy_name" "$filename"; then
  2535. break
  2536. fi
  2537. done
  2538. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_name="$user_name" -v user_password="$user_password" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: socks5"; print " server:", local_ip; print " port:", listen_port; print " username:", user_name; print " password:", user_password; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2539. }
  2540. function generate_Hysteria_win_client_config() {
  2541. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2542. local server_name="$domain"
  2543. local proxy_name
  2544. local server_value
  2545. local tls_insecure
  2546. if [ -z "$domain" ]; then
  2547. server_name="$domain_name"
  2548. server_value="$local_ip"
  2549. tls_insecure="true"
  2550. else
  2551. server_value="$domain"
  2552. tls_insecure="false"
  2553. fi
  2554. if [ -n "$obfs_password" ]; then
  2555. obfs_config="\n \"obfs\": \"$obfs_password\","
  2556. fi
  2557. if [ -n "$ech_config" ]; then
  2558. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2559. fi
  2560. while true; do
  2561. proxy_name="Hysteria-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2562. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2563. break
  2564. fi
  2565. done
  2566. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v obfs_config="$obfs_config" -v user_password="$user_password" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2567. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"hysteria\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"up_mbps\": " down_mbps ", "; print " \"down_mbps\": " up_mbps ","obfs_config""; print " \"auth_str\": \""user_password"\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\", "; print " \"alpn\": ["; print " \"h3\""; print " ]" ech_client_config ""; print " }"; print " },";}
  2568. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2569. {print}' "$win_client_file" > "$win_client_file.tmp"
  2570. mv "$win_client_file.tmp" "$win_client_file"
  2571. }
  2572. function generate_Hysteria_phone_client_config() {
  2573. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2574. local server_name="$domain"
  2575. local proxy_name
  2576. local server_value
  2577. local tls_insecure
  2578. if [ -z "$domain" ]; then
  2579. server_name="$domain_name"
  2580. server_value="$local_ip"
  2581. tls_insecure="true"
  2582. else
  2583. server_value="$domain"
  2584. tls_insecure="false"
  2585. fi
  2586. if [ -n "$obfs_password" ]; then
  2587. obfs_config="\n \"obfs\": \"$obfs_password\","
  2588. fi
  2589. if [ -n "$ech_config" ]; then
  2590. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2591. fi
  2592. while true; do
  2593. proxy_name="Hysteria-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2594. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2595. break
  2596. fi
  2597. done
  2598. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v obfs_config="$obfs_config" -v user_password="$user_password" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2599. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"hysteria\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"up_mbps\": " down_mbps ", "; print " \"down_mbps\": " up_mbps ","obfs_config""; print " \"auth_str\": \""user_password"\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\", "; print " \"alpn\": ["; print " \"h3\""; print " ]" ech_client_config ""; print " }"; print " },";}
  2600. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2601. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2602. mv "$phone_client_file.tmp" "$phone_client_file"
  2603. }
  2604. function generate_Hysteria_yaml() {
  2605. local filename="/usr/local/etc/sing-box/clash.yaml"
  2606. local server_name="$domain"
  2607. local proxy_name
  2608. local server_value
  2609. local tls_insecure
  2610. if [ -z "$domain" ]; then
  2611. server_name="$domain_name"
  2612. server_value="$local_ip"
  2613. tls_insecure="true"
  2614. else
  2615. server_value="$domain"
  2616. tls_insecure="false"
  2617. fi
  2618. if [ -n "$obfs_password" ]; then
  2619. obfs_config="
  2620. obfs: $obfs_password"
  2621. fi
  2622. while true; do
  2623. proxy_name="hysteria-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2624. if ! grep -q "name: $proxy_name" "$filename"; then
  2625. break
  2626. fi
  2627. done
  2628. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v user_password="$user_password" -v obfs_config="$obfs_config" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: hysteria"; print " server:", server_value; print " port:", listen_port; print " auth-str:", user_password obfs_config; print " sni:", server_name; print " skip-cert-verify:", tls_insecure; print " alpn:"; print " - h3"; print " protocol: udp"; print " up: \"" down_mbps " Mbps\""; print " down: \"" up_mbps " Mbps\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2629. }
  2630. function generate_vmess_win_client_config() {
  2631. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2632. local proxy_name
  2633. local server_name="$domain"
  2634. local server_value
  2635. local tls_insecure
  2636. if [[ -z "$domain" && -n "$domain_name" ]]; then
  2637. server_name="$domain_name"
  2638. server_value="$local_ip"
  2639. tls_insecure="true"
  2640. elif [[ -z "$domain" && -z "$domain_name" ]]; then
  2641. server_value="$local_ip"
  2642. elif [[ -z "$domain_name" && -n "$domain" ]]; then
  2643. server_name="$domain"
  2644. server_value="$domain"
  2645. tls_insecure="false"
  2646. fi
  2647. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  2648. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  2649. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  2650. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  2651. fi
  2652. if [ -n "$ech_config" ]; then
  2653. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2654. fi
  2655. while true; do
  2656. proxy_name="vmess-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2657. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2658. break
  2659. fi
  2660. done
  2661. if [[ -n "$domain" || -n "$domain_name" ]]; then
  2662. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_config="$transport_config" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" -v multiplex_client_config="$multiplex_client_config" '
  2663. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vmess\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\"," transport_config " "; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\"" ech_client_config ""; print " },"; print " \"security\": \"auto\","; print " \"alter_id\": 0,"; print " \"packet_encoding\": \"xudp\"" multiplex_client_config ""; print " },";}
  2664. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2665. {print}' "$win_client_file" > "$win_client_file.tmp"
  2666. else
  2667. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  2668. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vmess\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\"," transport_config " "; print " \"security\": \"auto\","; print " \"alter_id\": 0,"; print " \"packet_encoding\": \"xudp\"" multiplex_client_config ""; print " },";}
  2669. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2670. {print}' "$win_client_file" > "$win_client_file.tmp"
  2671. fi
  2672. mv "$win_client_file.tmp" "$win_client_file"
  2673. }
  2674. function generate_vmess_phone_client_config() {
  2675. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2676. local proxy_name
  2677. local server_name="$domain"
  2678. local server_value
  2679. local tls_insecure
  2680. if [[ -z "$domain" && -n "$domain_name" ]]; then
  2681. server_name="$domain_name"
  2682. server_value="$local_ip"
  2683. tls_insecure="true"
  2684. elif [[ -z "$domain" && -z "$domain_name" ]]; then
  2685. server_value="$local_ip"
  2686. elif [[ -z "$domain_name" && -n "$domain" ]]; then
  2687. server_name="$domain"
  2688. server_value="$domain"
  2689. tls_insecure="false"
  2690. fi
  2691. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  2692. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  2693. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  2694. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  2695. fi
  2696. if [ -n "$ech_config" ]; then
  2697. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2698. fi
  2699. while true; do
  2700. proxy_name="vmess-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2701. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2702. break
  2703. fi
  2704. done
  2705. if [[ -n "$domain" || -n "$domain_name" ]]; then
  2706. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_config="$transport_config" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" -v multiplex_client_config="$multiplex_client_config" '
  2707. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vmess\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\"," transport_config " "; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\"" ech_client_config ""; print " },"; print " \"security\": \"auto\","; print " \"alter_id\": 0,"; print " \"packet_encoding\": \"xudp\"" multiplex_client_config ""; print " },";}
  2708. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2709. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2710. else
  2711. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  2712. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vmess\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\"," transport_config " "; print " \"security\": \"auto\","; print " \"alter_id\": 0,"; print " \"packet_encoding\": \"xudp\"" multiplex_client_config ""; print " },";}
  2713. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2714. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2715. fi
  2716. mv "$phone_client_file.tmp" "$phone_client_file"
  2717. }
  2718. function generate_vmess_tcp_yaml() {
  2719. local filename="/usr/local/etc/sing-box/clash.yaml"
  2720. local proxy_name
  2721. while true; do
  2722. proxy_name="vmess-tcp-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2723. if ! grep -q "name: $proxy_name" "$filename"; then
  2724. break
  2725. fi
  2726. done
  2727. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vmess"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " alterId: 0"; print " cipher: auto"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2728. }
  2729. function generate_vmess_tcp_tls_yaml() {
  2730. local filename="/usr/local/etc/sing-box/clash.yaml"
  2731. local server_name="$domain"
  2732. local proxy_name
  2733. local server_value
  2734. local tls_insecure
  2735. if [ -z "$domain" ]; then
  2736. server_name="$domain_name"
  2737. server_value="$local_ip"
  2738. tls_insecure="true"
  2739. else
  2740. server_value="$domain"
  2741. tls_insecure="false"
  2742. fi
  2743. while true; do
  2744. proxy_name="vmess-tcp-tls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2745. if ! grep -q "name: $proxy_name" "$filename"; then
  2746. break
  2747. fi
  2748. done
  2749. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vmess"; print " server:", server_value; print " port:", listen_port; print " uuid:", user_uuid; print " alterId: 0"; print " cipher: auto"; print " tls: true"; print " skip-cert-verify:", tls_insecure; print " servername: " server_name; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2750. }
  2751. function generate_vmess_ws_yaml() {
  2752. local filename="/usr/local/etc/sing-box/clash.yaml"
  2753. local proxy_name
  2754. while true; do
  2755. proxy_name="vmess-ws-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2756. if ! grep -q "name: $proxy_name" "$filename"; then
  2757. break
  2758. fi
  2759. done
  2760. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_path="$transport_path" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vmess"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " alterId: 0"; print " cipher: auto"; print " network: ws"; print " ws-opts:"; print " path: " transport_path; print " max-early-data: 2048"; print " early-data-header-name: Sec-WebSocket-Protocol"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2761. }
  2762. function generate_vmess_ws_tls_yaml() {
  2763. local filename="/usr/local/etc/sing-box/clash.yaml"
  2764. local server_name="$domain"
  2765. local proxy_name
  2766. local server_value
  2767. local tls_insecure
  2768. if [ -z "$domain" ]; then
  2769. server_name="$domain_name"
  2770. server_value="$local_ip"
  2771. tls_insecure="true"
  2772. else
  2773. server_value="$domain"
  2774. tls_insecure="false"
  2775. fi
  2776. while true; do
  2777. proxy_name="vmess-ws-tls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2778. if ! grep -q "name: $proxy_name" "$filename"; then
  2779. break
  2780. fi
  2781. done
  2782. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_path="$transport_path" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vmess"; print " server:", server_value; print " port:", listen_port; print " uuid:", user_uuid; print " alterId: 0"; print " cipher: auto"; print " network: ws"; print " tls: true"; print " skip-cert-verify:", tls_insecure; print " servername:", server_name; print " ws-opts:"; print " path: " transport_path; print " max-early-data: 2048"; print " early-data-header-name: Sec-WebSocket-Protocol"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2783. }
  2784. function generate_vmess_grpc_yaml() {
  2785. local filename="/usr/local/etc/sing-box/clash.yaml"
  2786. local proxy_name
  2787. while true; do
  2788. proxy_name="vmess-grpc-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2789. if ! grep -q "name: $proxy_name" "$filename"; then
  2790. break
  2791. fi
  2792. done
  2793. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_service_name="$transport_service_name" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vmess"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " alterId: 0"; print " cipher: auto"; print " network: grpc"; print " grpc-opts:"; print " grpc-service-name:", "\"" transport_service_name "\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2794. }
  2795. function generate_vmess_grpc_tls_yaml() {
  2796. local filename="/usr/local/etc/sing-box/clash.yaml"
  2797. local server_name="$domain"
  2798. local proxy_name
  2799. local server_value
  2800. local tls_insecure
  2801. if [ -z "$domain" ]; then
  2802. server_name="$domain_name"
  2803. server_value="$local_ip"
  2804. tls_insecure="true"
  2805. else
  2806. server_value="$domain"
  2807. tls_insecure="false"
  2808. fi
  2809. while true; do
  2810. proxy_name="vmess-grpc-tls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2811. if ! grep -q "name: $proxy_name" "$filename"; then
  2812. break
  2813. fi
  2814. done
  2815. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_service_name="$transport_service_name" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vmess"; print " server:", server_value; print " port:", listen_port; print " uuid:", user_uuid; print " alterId: 0"; print " cipher: auto"; print " network: grpc"; print " tls: true"; print " skip-cert-verify:", tls_insecure; print " servername:", server_name; print " grpc-opts:"; print " grpc-service-name:", "\"" transport_service_name "\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2816. }
  2817. function generate_http_phone_client_config() {
  2818. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2819. local server_name="$domain"
  2820. local proxy_name
  2821. local server_value
  2822. local tls_insecure
  2823. if [ -z "$domain" ]; then
  2824. server_name="$domain_name"
  2825. server_value="$local_ip"
  2826. tls_insecure="true"
  2827. else
  2828. server_value="$domain"
  2829. tls_insecure="false"
  2830. fi
  2831. if [ -n "$ech_config" ]; then
  2832. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2833. fi
  2834. while true; do
  2835. proxy_name="http-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2836. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2837. break
  2838. fi
  2839. done
  2840. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_name="$user_name" -v user_password="$user_password" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2841. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"http\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"username\": \"" user_name "\", "; print " \"password\": \"" user_password "\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\"" ech_client_config ""; print " }"; print " },";}
  2842. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2843. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2844. mv "$phone_client_file.tmp" "$phone_client_file"
  2845. }
  2846. function generate_http_win_client_config() {
  2847. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2848. local server_name="$domain"
  2849. local proxy_name
  2850. local server_value
  2851. local tls_insecure
  2852. if [ -z "$domain" ]; then
  2853. server_name="$domain_name"
  2854. server_value="$local_ip"
  2855. tls_insecure="true"
  2856. else
  2857. server_value="$domain"
  2858. tls_insecure="false"
  2859. fi
  2860. if [ -n "$ech_config" ]; then
  2861. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2862. fi
  2863. while true; do
  2864. proxy_name="http-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2865. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2866. break
  2867. fi
  2868. done
  2869. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_name="$user_name" -v user_password="$user_password" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2870. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"http\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"username\": \"" user_name "\", "; print " \"password\": \"" user_password "\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\"" ech_client_config ""; print " }"; print " },";}
  2871. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2872. {print}' "$win_client_file" > "$win_client_file.tmp"
  2873. mv "$win_client_file.tmp" "$win_client_file"
  2874. }
  2875. function generate_http_yaml() {
  2876. local filename="/usr/local/etc/sing-box/clash.yaml"
  2877. local server_name="$domain"
  2878. local proxy_name
  2879. local server_value
  2880. local tls_insecure
  2881. if [ -z "$domain" ]; then
  2882. server_name="$domain_name"
  2883. server_value="$local_ip"
  2884. tls_insecure="true"
  2885. else
  2886. server_value="$domain"
  2887. tls_insecure="false"
  2888. fi
  2889. while true; do
  2890. proxy_name="http-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2891. if ! grep -q "name: $proxy_name" "$filename"; then
  2892. break
  2893. fi
  2894. done
  2895. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_name="$user_name" -v user_password="$user_password" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: http"; print " server:", server_value; print " port:", listen_port; print " username:", user_name; print " password:", user_password; print " tls: true"; print " sni:", server_name; print " skip-cert-verify:", tls_insecure; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2896. }
  2897. function generate_Hysteria2_phone_client_config() {
  2898. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  2899. local server_name="$domain"
  2900. local proxy_name
  2901. local server_value
  2902. local tls_insecure
  2903. if [ -z "$domain" ]; then
  2904. server_name="$domain_name"
  2905. server_value="$local_ip"
  2906. tls_insecure="true"
  2907. else
  2908. server_value="$domain"
  2909. tls_insecure="false"
  2910. fi
  2911. if [ -n "$obfs_password" ]; then
  2912. obfs_config="\n \"obfs\": {\n \"type\": \"salamander\",\n \"password\": \"$obfs_password\"\n },"
  2913. fi
  2914. if [ -n "$ech_config" ]; then
  2915. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2916. fi
  2917. while true; do
  2918. proxy_name="Hysteria2-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2919. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  2920. break
  2921. fi
  2922. done
  2923. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v obfs_config="$obfs_config" -v user_password="$user_password" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2924. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"hysteria2\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"up_mbps\": " down_mbps ", "; print " \"down_mbps\": " up_mbps ","obfs_config""; print " \"password\": \"" user_password "\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\", "; print " \"alpn\": ["; print " \"h3\""; print " ]" ech_client_config ""; print " }"; print " },";}
  2925. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2926. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  2927. mv "$phone_client_file.tmp" "$phone_client_file"
  2928. }
  2929. function generate_Hysteria2_win_client_config() {
  2930. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2931. local server_name="$domain"
  2932. local proxy_name
  2933. local server_value
  2934. local tls_insecure
  2935. if [ -z "$domain" ]; then
  2936. server_name="$domain_name"
  2937. server_value="$local_ip"
  2938. tls_insecure="true"
  2939. else
  2940. server_value="$domain"
  2941. tls_insecure="false"
  2942. fi
  2943. if [ -n "$obfs_password" ]; then
  2944. obfs_config="\n \"obfs\": {\n \"type\": \"salamander\",\n \"password\": \"$obfs_password\"\n },"
  2945. fi
  2946. if [ -n "$ech_config" ]; then
  2947. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  2948. fi
  2949. while true; do
  2950. proxy_name="Hysteria2-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2951. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  2952. break
  2953. fi
  2954. done
  2955. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v obfs_config="$obfs_config" -v user_password="$user_password" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" '
  2956. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"hysteria2\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"up_mbps\": " down_mbps ", "; print " \"down_mbps\": " up_mbps ","obfs_config""; print " \"password\": \"" user_password "\","; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\", "; print " \"alpn\": ["; print " \"h3\""; print " ]" ech_client_config ""; print " }"; print " },";}
  2957. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  2958. {print}' "$win_client_file" > "$win_client_file.tmp"
  2959. mv "$win_client_file.tmp" "$win_client_file"
  2960. }
  2961. function generate_Hysteria2_yaml() {
  2962. local filename="/usr/local/etc/sing-box/clash.yaml"
  2963. local server_name="$domain"
  2964. local proxy_name
  2965. local server_value
  2966. local tls_insecure
  2967. if [ -z "$domain" ]; then
  2968. server_name="$domain_name"
  2969. server_value="$local_ip"
  2970. tls_insecure="true"
  2971. else
  2972. server_value="$domain"
  2973. tls_insecure="false"
  2974. fi
  2975. if [ -n "$obfs_password" ]; then
  2976. obfs_config="
  2977. obfs: salamander
  2978. obfs-password: $obfs_password"
  2979. fi
  2980. while true; do
  2981. proxy_name="hysteria2-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2982. if ! grep -q "name: $proxy_name" "$filename"; then
  2983. break
  2984. fi
  2985. done
  2986. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v up_mbps="$up_mbps" -v down_mbps="$down_mbps" -v user_password="$user_password" -v obfs_config="$obfs_config" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: hysteria2"; print " server:", server_value; print " port:", listen_port; print " password:", user_password obfs_config; print " alpn:"; print " - h3"; print " sni:", server_name; print " skip-cert-verify:", tls_insecure; print " up: \"" down_mbps " Mbps\""; print " down: \"" up_mbps " Mbps\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  2987. }
  2988. function generate_vless_win_client_config() {
  2989. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  2990. local proxy_name
  2991. local server_name_in_config=$(jq -r '.inbounds[0].tls.server_name' "$config_file")
  2992. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  2993. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  2994. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  2995. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  2996. fi
  2997. while true; do
  2998. proxy_name="vless-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  2999. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  3000. break
  3001. fi
  3002. done
  3003. if [ "$server_name_in_config" != "null" ]; then
  3004. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v flow_type="$flow_type" -v public_key="$public_key" -v short_id="$short_id" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  3005. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vless\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\", "; print " \"flow\": \"" flow_type "\"," transport_config ""; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" server_name "\", "; print " \"utls\": {"; print " \"enabled\": true,"; print " \"fingerprint\": \"chrome\""; print " },"; print " \"reality\": {"; print " \"enabled\": true,"; print " \"public_key\": \"" public_key "\","; print " \"short_id\": \"" short_id "\""; print " }"; print " }" multiplex_client_config ""; print " },";}
  3006. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3007. {print}' "$win_client_file" > "$win_client_file.tmp"
  3008. else
  3009. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v flow_type="$flow_type" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  3010. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vless\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\"," transport_config ""; print " \"flow\": \"" flow_type "\"" multiplex_client_config ""; print " },";}
  3011. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3012. {print}' "$win_client_file" > "$win_client_file.tmp"
  3013. fi
  3014. mv "$win_client_file.tmp" "$win_client_file"
  3015. }
  3016. function generate_vless_phone_client_config() {
  3017. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3018. local proxy_name
  3019. local server_name_in_config=$(jq -r '.inbounds[0].tls.server_name' "$config_file")
  3020. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  3021. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  3022. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  3023. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  3024. fi
  3025. while true; do
  3026. proxy_name="vless-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3027. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  3028. break
  3029. fi
  3030. done
  3031. if [ "$server_name_in_config" != "null" ]; then
  3032. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v flow_type="$flow_type" -v public_key="$public_key" -v short_id="$short_id" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  3033. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vless\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\", "; print " \"flow\": \"" flow_type "\"," transport_config ""; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" server_name "\", "; print " \"utls\": {"; print " \"enabled\": true,"; print " \"fingerprint\": \"chrome\""; print " },"; print " \"reality\": {"; print " \"enabled\": true,"; print " \"public_key\": \"" public_key "\","; print " \"short_id\": \"" short_id "\""; print " }"; print " }" multiplex_client_config ""; print " },";}
  3034. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3035. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  3036. else
  3037. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v flow_type="$flow_type" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  3038. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"vless\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"uuid\": \"" user_uuid "\"," transport_config ""; print " \"flow\": \"" flow_type "\"" multiplex_client_config ""; print " },";}
  3039. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3040. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  3041. fi
  3042. mv "$phone_client_file.tmp" "$phone_client_file"
  3043. }
  3044. function generate_vless_tcp_yaml() {
  3045. local filename="/usr/local/etc/sing-box/clash.yaml"
  3046. local proxy_name
  3047. while true; do
  3048. proxy_name="vless-tcp-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3049. if ! grep -q "name: $proxy_name" "$filename"; then
  3050. break
  3051. fi
  3052. done
  3053. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vless"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " network: tcp"; print " udp: true"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3054. }
  3055. function generate_vless_ws_yaml() {
  3056. local filename="/usr/local/etc/sing-box/clash.yaml"
  3057. local proxy_name
  3058. while true; do
  3059. proxy_name="vless-ws-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3060. if ! grep -q "name: $proxy_name" "$filename"; then
  3061. break
  3062. fi
  3063. done
  3064. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_path="$transport_path" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vless"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " network: ws"; print " udp: true"; print " ws-opts:"; print " path: " transport_path; print " max-early-data: 2048"; print " early-data-header-name: Sec-WebSocket-Protocol"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3065. }
  3066. function generate_vless_grpc_yaml() {
  3067. local filename="/usr/local/etc/sing-box/clash.yaml"
  3068. local proxy_name
  3069. while true; do
  3070. proxy_name="vless-grpc-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3071. if ! grep -q "name: $proxy_name" "$filename"; then
  3072. break
  3073. fi
  3074. done
  3075. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v transport_service_name="$transport_service_name" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vless"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " network: grpc"; print " udp: true"; print " grpc-opts:"; print " grpc-service-name:", "\"" transport_service_name "\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3076. }
  3077. function generate_vless_reality_vision_yaml() {
  3078. local filename="/usr/local/etc/sing-box/clash.yaml"
  3079. local proxy_name
  3080. while true; do
  3081. proxy_name="vless-reality-vision-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3082. if ! grep -q "name: $proxy_name" "$filename"; then
  3083. break
  3084. fi
  3085. done
  3086. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v public_key="$public_key" -v short_id="$short_id" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vless"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " network: tcp"; print " udp: true"; print " tls: true"; print " flow: xtls-rprx-vision"; print " servername:", server_name; print " reality-opts:"; print " public-key:", public_key; print " short-id:", short_id; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3087. }
  3088. function generate_vless_reality_grpc_yaml() {
  3089. local filename="/usr/local/etc/sing-box/clash.yaml"
  3090. local proxy_name
  3091. while true; do
  3092. proxy_name="vless-reality-grpc-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3093. if ! grep -q "name: $proxy_name" "$filename"; then
  3094. break
  3095. fi
  3096. done
  3097. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v server_name="$server_name" -v listen_port="$listen_port" -v user_uuid="$user_uuid" -v public_key="$public_key" -v short_id="$short_id" -v transport_service_name="$transport_service_name" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: vless"; print " server:", local_ip; print " port:", listen_port; print " uuid:", user_uuid; print " network: grpc"; print " udp: true"; print " tls: true"; print " flow: "; print " servername:", server_name; print " reality-opts:"; print " public-key:", public_key; print " short-id:", short_id; print " grpc-opts:"; print " grpc-service-name:", "\"" transport_service_name "\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3098. }
  3099. function generate_trojan_phone_client_config() {
  3100. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3101. local proxy_name
  3102. local server_name="$domain"
  3103. local server_value
  3104. local tls_insecure
  3105. if [[ -z "$domain" && -n "$domain_name" ]]; then
  3106. server_name="$domain_name"
  3107. server_value="$local_ip"
  3108. tls_insecure="true"
  3109. elif [[ -z "$domain" && -z "$domain_name" ]]; then
  3110. server_value="$local_ip"
  3111. elif [[ -z "$domain_name" && -n "$domain" ]]; then
  3112. server_name="$domain"
  3113. server_value="$domain"
  3114. tls_insecure="false"
  3115. fi
  3116. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  3117. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  3118. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  3119. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  3120. fi
  3121. if [ -n "$ech_config" ]; then
  3122. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  3123. fi
  3124. while true; do
  3125. proxy_name="trojan-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3126. if ! grep -q "name: $proxy_name" "$phone_client_file"; then
  3127. break
  3128. fi
  3129. done
  3130. if [[ -n "$domain" || -n "$domain_name" ]]; then
  3131. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_password="$user_password" -v transport_config="$transport_config" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" -v multiplex_client_config="$multiplex_client_config" '
  3132. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"trojan\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"password\": \"" user_password "\"," transport_config " "; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\"" ech_client_config ""; print " }"multiplex_client_config""; print " },";}
  3133. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3134. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  3135. else
  3136. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_password="$user_password" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  3137. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"trojan\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port "," transport_config " "; print " \"password\": \"" user_password "\""multiplex_client_config""; print " },";}
  3138. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3139. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  3140. fi
  3141. mv "$phone_client_file.tmp" "$phone_client_file"
  3142. }
  3143. function generate_trojan_win_client_config() {
  3144. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3145. local proxy_name
  3146. local server_name="$domain"
  3147. local server_value
  3148. local tls_insecure
  3149. if [[ -z "$domain" && -n "$domain_name" ]]; then
  3150. server_name="$domain_name"
  3151. server_value="$local_ip"
  3152. tls_insecure="true"
  3153. elif [[ -z "$domain" && -z "$domain_name" ]]; then
  3154. server_value="$local_ip"
  3155. elif [[ -z "$domain_name" && -n "$domain" ]]; then
  3156. server_name="$domain"
  3157. server_value="$domain"
  3158. tls_insecure="false"
  3159. fi
  3160. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  3161. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  3162. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  3163. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  3164. fi
  3165. if [ -n "$ech_config" ]; then
  3166. ech_client_config=",\n \"ech\": {\n \"enabled\": true,\n \"pq_signature_schemes_enabled\": true,\n \"dynamic_record_sizing_disabled\": false,\n \"config\": [\n$ech_config\n ]\n }"
  3167. fi
  3168. while true; do
  3169. proxy_name="trojan-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3170. if ! grep -q "name: $proxy_name" "$win_client_file"; then
  3171. break
  3172. fi
  3173. done
  3174. if [[ -n "$domain" || -n "$domain_name" ]]; then
  3175. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_password="$user_password" -v transport_config="$transport_config" -v tls_insecure="$tls_insecure" -v ech_client_config="$ech_client_config" -v multiplex_client_config="$multiplex_client_config" '
  3176. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"trojan\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" server_value "\", "; print " \"server_port\": " listen_port ","; print " \"password\": \"" user_password "\"," transport_config " "; print " \"tls\": {"; print " \"enabled\": true,"; print " \"insecure\": " tls_insecure ","; print " \"server_name\": \"" server_name "\"" ech_client_config ""; print " }"multiplex_client_config""; print " },";}
  3177. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3178. {print}' "$win_client_file" > "$win_client_file.tmp"
  3179. else
  3180. awk -v proxy_name="$proxy_name" -v local_ip="$local_ip" -v listen_port="$listen_port" -v user_password="$user_password" -v transport_config="$transport_config" -v multiplex_client_config="$multiplex_client_config" '
  3181. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"trojan\","; print " \"tag\": \"" proxy_name "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port "," transport_config " "; print " \"password\": \"" user_password "\""multiplex_client_config""; print " },";}
  3182. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3183. {print}' "$win_client_file" > "$win_client_file.tmp"
  3184. fi
  3185. mv "$win_client_file.tmp" "$win_client_file"
  3186. }
  3187. function generate_trojan_tcp_tls_yaml() {
  3188. local filename="/usr/local/etc/sing-box/clash.yaml"
  3189. local server_name="$domain"
  3190. local proxy_name
  3191. local server_value
  3192. local tls_insecure
  3193. if [ -z "$domain" ]; then
  3194. server_name="$domain_name"
  3195. server_value="$local_ip"
  3196. tls_insecure="true"
  3197. else
  3198. server_value="$domain"
  3199. tls_insecure="false"
  3200. fi
  3201. while true; do
  3202. proxy_name="trojan-tcp-tls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3203. if ! grep -q "name: $proxy_name" "$filename"; then
  3204. break
  3205. fi
  3206. done
  3207. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_password="$user_password" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: trojan"; print " server:", server_value; print " port:", listen_port; print " password:", user_password; print " udp: true"; print " sni:", server_name; print " skip-cert-verify:", tls_insecure; print " alpn:"; print " - h2"; print " - http/1.1"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3208. }
  3209. function generate_trojan_ws_tls_yaml() {
  3210. local filename="/usr/local/etc/sing-box/clash.yaml"
  3211. local server_name="$domain"
  3212. local proxy_name
  3213. local server_value
  3214. local tls_insecure
  3215. if [ -z "$domain" ]; then
  3216. server_name="$domain_name"
  3217. server_value="$local_ip"
  3218. tls_insecure="true"
  3219. else
  3220. server_value="$domain"
  3221. tls_insecure="false"
  3222. fi
  3223. while true; do
  3224. proxy_name="trojan-ws-tls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3225. if ! grep -q "name: $proxy_name" "$filename"; then
  3226. break
  3227. fi
  3228. done
  3229. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_password="$user_password" -v transport_path="$transport_path" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: trojan"; print " server:", server_value; print " port:", listen_port; print " password:", "\"" user_password "\""; print " network: ws"; print " sni:", server_name; print " skip-cert-verify:", tls_insecure; print " udp: true"; print " ws-opts:"; print " path:", transport_path; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3230. }
  3231. function generate_trojan_grpc_tls_yaml() {
  3232. local filename="/usr/local/etc/sing-box/clash.yaml"
  3233. local server_name="$domain"
  3234. local proxy_name
  3235. local server_value
  3236. local tls_insecure
  3237. if [ -z "$domain" ]; then
  3238. server_name="$domain_name"
  3239. server_value="$local_ip"
  3240. tls_insecure="true"
  3241. else
  3242. server_value="$domain"
  3243. tls_insecure="false"
  3244. fi
  3245. while true; do
  3246. proxy_name="trojan-grpc-tls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3247. if ! grep -q "name: $proxy_name" "$filename"; then
  3248. break
  3249. fi
  3250. done
  3251. awk -v proxy_name="$proxy_name" -v server_value="$server_value" -v server_name="$server_name" -v listen_port="$listen_port" -v user_password="$user_password" -v transport_service_name="$transport_service_name" -v tls_insecure="$tls_insecure" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: trojan"; print " server:", server_value; print " port:", listen_port; print " password:", "\"" user_password "\""; print " network: grpc"; print " sni:", server_name; print " udp: true"; print " skip-cert-verify:", tls_insecure; print " grpc-opts:"; print " grpc-service-name:", "\"" transport_service_name "\""; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3252. }
  3253. function generate_shadowtls_win_client_config() {
  3254. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3255. local proxy_name
  3256. local shadowtls_out
  3257. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  3258. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  3259. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  3260. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  3261. fi
  3262. while true; do
  3263. proxy_name="shadowtls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3264. shadowtls_out="stl-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3265. if ! grep -q "name: $proxy_name" "$win_client_file" && ! grep -q "name: $shadowtls_out" "$win_client_file" && [ "$proxy_name" != "$shadowtls_out" ]; then
  3266. break
  3267. fi
  3268. done
  3269. awk -v shadowtls_out="$shadowtls_out" -v proxy_name="$proxy_name" -v method="$method" -v ss_password="$ss_password" -v local_ip="$local_ip" -v listen_port="$listen_port" -v stls_password="$stls_password" -v user_input="$user_input" -v multiplex_client_config="$multiplex_client_config" '
  3270. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"shadowsocks\","; print " \"tag\": \"" proxy_name "\","; print " \"method\": \"" method "\", "; print " \"password\": \"" ss_password "\","; print " \"detour\": \"" shadowtls_out "\""multiplex_client_config""; print " },"; print " {"; print " \"type\": \"shadowtls\","; print " \"tag\": \"" shadowtls_out "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"version\": 3, "; print " \"password\": \""stls_password"\", "; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" user_input "\", "; print " \"utls\": {"; print " \"enabled\": true,"; print " \"fingerprint\": \"chrome\" "; print " }"; print " }"; print " },";}
  3271. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3272. {print}' "$win_client_file" > "$win_client_file.tmp"
  3273. mv "$win_client_file.tmp" "$win_client_file"
  3274. }
  3275. function generate_shadowtls_phone_client_config() {
  3276. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3277. local proxy_name
  3278. local shadowtls_out
  3279. if [ -n "$multiplex_config" ] && [ -n "$brutal_config" ]; then
  3280. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false,\n \"brutal\": {\n \"enabled\": true,\n \"up_mbps\": $down_mbps,\n \"down_mbps\": $up_mbps\n }\n }"
  3281. elif [ -n "$multiplex_config" ] && [ -z "$brutal_config" ]; then
  3282. multiplex_client_config=",\n \"multiplex\": {\n \"enabled\": true,\n \"protocol\": \"h2mux\",\n \"max_connections\": 1,\n \"min_streams\": 4,\n \"padding\": false\n }"
  3283. fi
  3284. while true; do
  3285. proxy_name="shadowtls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3286. shadowtls_out="stl-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3287. if ! grep -q "name: $proxy_name" "$phone_client_file" && ! grep -q "name: $shadowtls_out" "$phone_client_file" && [ "$proxy_name" != "$shadowtls_out" ]; then
  3288. break
  3289. fi
  3290. done
  3291. awk -v shadowtls_out="$shadowtls_out" -v proxy_name="$proxy_name" -v method="$method" -v ss_password="$ss_password" -v local_ip="$local_ip" -v listen_port="$listen_port" -v stls_password="$stls_password" -v user_input="$user_input" -v multiplex_client_config="$multiplex_client_config" '
  3292. /^ "outbounds": \[/ {print; getline; print " {"; print " \"type\": \"shadowsocks\","; print " \"tag\": \"" proxy_name "\","; print " \"method\": \"" method "\", "; print " \"password\": \"" ss_password "\","; print " \"detour\": \"" shadowtls_out "\""multiplex_client_config""; print " },"; print " {"; print " \"type\": \"shadowtls\","; print " \"tag\": \"" shadowtls_out "\","; print " \"server\": \"" local_ip "\", "; print " \"server_port\": " listen_port ","; print " \"version\": 3, "; print " \"password\": \""stls_password"\", "; print " \"tls\": {"; print " \"enabled\": true,"; print " \"server_name\": \"" user_input "\", "; print " \"utls\": {"; print " \"enabled\": true,"; print " \"fingerprint\": \"chrome\" "; print " }"; print " }"; print " },";}
  3293. /^ "outbounds": \[/ {print; getline; if ($0 ~ /^ \],$/) {print " \"" proxy_name "\""} else {print " \"" proxy_name "\", "} }
  3294. {print}' "$phone_client_file" > "$phone_client_file.tmp"
  3295. mv "$phone_client_file.tmp" "$phone_client_file"
  3296. }
  3297. function generate_shadowtls_yaml() {
  3298. local filename="/usr/local/etc/sing-box/clash.yaml"
  3299. local proxy_name
  3300. while true; do
  3301. proxy_name="shadowtls-$(head /dev/urandom | tr -dc '0-9' | head -c 4)"
  3302. if ! grep -q "name: $proxy_name" "$filename"; then
  3303. break
  3304. fi
  3305. done
  3306. awk -v proxy_name="$proxy_name" -v method="$method" -v ss_password="$ss_password" -v local_ip="$local_ip" -v listen_port="$listen_port" -v stls_password="$stls_password" -v user_input="$user_input" '/^proxies:$/ {print; print " - name: " proxy_name; print " type: ss"; print " server:", local_ip; print " port:", listen_port; print " cipher:", method; print " password:", "\"" ss_password "\""; print " plugin: shadow-tls"; print " plugin-opts:"; print " host: \"" user_input "\""; print " password:", "\"" stls_password "\""; print " version: 3"; print ""; next} /- name: Proxy/ { print; flag_proxy=1; next } flag_proxy && flag_proxy++ == 3 { print " - " proxy_name } /- name: auto/ { print; flag_auto=1; next } flag_auto && flag_auto++ == 3 { print " - " proxy_name } 1' "$filename" > temp_file && mv temp_file "$filename"
  3307. }
  3308. function generate_naive_win_client_config() {
  3309. local naive_client_file="$naive_client_filename"
  3310. sed -i -e "s,user_name,$user_name," -e "s,user_password,$user_password," -e "s,listen_port,$listen_port," -e "s,server_name,$domain," "$naive_client_file"
  3311. echo "电脑端配置文件已保存至$naive_client_file,请下载后使用!"
  3312. }
  3313. function extract_types_tags() {
  3314. local config_file="/usr/local/etc/sing-box/config.json"
  3315. filtered_tags=()
  3316. types=()
  3317. tags=($(jq -r '.inbounds[] | select(.tag != null) | .tag' "$config_file"))
  3318. detour_tag=$(jq -r '.inbounds[] | select(.type == "shadowtls") | .detour' "$config_file")
  3319. wireguard_type=$(jq -r '.outbounds[] | select(.type == "wireguard" and .tag == "wireguard-out") | .type' "$config_file")
  3320. if [ -z "$tags" ] && [ -z "$wireguard_type" ]; then
  3321. echo "未检测到节点配置,请搭建节点后再使用本选项!"
  3322. exit 0
  3323. fi
  3324. filtered_tags=()
  3325. for tag in "${tags[@]}"; do
  3326. if [ "$tag" != "$detour_tag" ]; then
  3327. filtered_tags+=("$tag")
  3328. fi
  3329. done
  3330. max_length=0
  3331. for tag in "${filtered_tags[@]}"; do
  3332. tag_length=${#tag}
  3333. if ((tag_length > max_length)); then
  3334. max_length=$tag_length
  3335. fi
  3336. done
  3337. for ((i=0; i<${#filtered_tags[@]}; i++)); do
  3338. type=$(jq -r --arg tag "${filtered_tags[$i]}" '.inbounds[] | select(.tag == $tag) | .type' "$config_file")
  3339. types[$i]=$type
  3340. printf "%d).协议类型: %-20s 入站标签: %s\n" "$((i+1))" "$type" "${filtered_tags[$i]}"
  3341. done
  3342. if [ ! -z "$wireguard_type" ]; then
  3343. types[$i]=$wireguard_type
  3344. printf "%d).协议类型: %-20s 出站标签: %s\n" "$((i+1))" "$wireguard_type" "wireguard-out"
  3345. fi
  3346. }
  3347. function delete_choice() {
  3348. local config_file="/usr/local/etc/sing-box/config.json"
  3349. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3350. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3351. local clash_yaml="/usr/local/etc/sing-box/clash.yaml"
  3352. local output_file="/usr/local/etc/sing-box/output.txt"
  3353. local temp_json="/usr/local/etc/sing-box/temp.json"
  3354. local temp_yaml="/usr/local/etc/sing-box/temp.yaml"
  3355. extract_types_tags
  3356. valid_choice=false
  3357. while [ "$valid_choice" == false ]; do
  3358. read -p "请选择要删除的节点配置(输入对应的数字): " choice
  3359. if [[ ! $choice =~ ^[0-9]+$ || $choice -lt 1 || $choice -gt ${#types[@]} ]]; then
  3360. echo -e "${RED}错误:无效的选择,请重新输入!${NC}"
  3361. else
  3362. valid_choice=true
  3363. fi
  3364. done
  3365. selected_tag="${filtered_tags[$choice-1]}"
  3366. selected_type="${types[$choice-1]}"
  3367. listen_port=$(jq -r --arg selected_tag "$selected_tag" '.inbounds[] | select(.tag == $selected_tag) | .listen_port' "$config_file" | awk '{print int($0)}')
  3368. if [ "$selected_type" == "wireguard" ]; then
  3369. jq '.outbounds |= map(select(.tag != "warp-IPv4-out" and .tag != "warp-IPv6-out" and .tag != "wireguard-out"))' "$config_file" > "$temp_json"
  3370. mv "$temp_json" "$config_file"
  3371. jq '.route.rules |= map(select(.outbound != "warp-IPv4-out" and .outbound != "warp-IPv6-out"))' "$config_file" > "$temp_json"
  3372. mv "$temp_json" "$config_file"
  3373. else
  3374. detour_tag=$(jq -r --arg selected_tag "$selected_tag" '.inbounds[] | select(.type == "shadowtls" and .tag == $selected_tag) | .detour' "$config_file")
  3375. jq --arg selected_tag "$selected_tag" --arg detour_tag "$detour_tag" '.inbounds |= map(select(.tag != $selected_tag and .tag != $detour_tag))' "$config_file" > "$temp_json"
  3376. mv "$temp_json" "$config_file"
  3377. jq --arg selected_tag "$selected_tag" '.route.rules |= map(select(.inbound[0] != $selected_tag))' "$config_file" > "$temp_json"
  3378. mv "$temp_json" "$config_file"
  3379. fi
  3380. if [ "$selected_type" != "wireguard" ]; then
  3381. awk -v port="$listen_port" '$0 ~ "监听端口: " port {print; in_block=1; next} in_block && NF == 0 {in_block=0} !in_block' "$output_file" > "$output_file.tmp1"
  3382. mv "$output_file.tmp1" "$output_file"
  3383. awk -v port="$listen_port" '$0 ~ "监听端口: " port {start=NR; next} {lines[NR]=$0} END {for (i=1; i<=NR; i++) if (i < start - 4 || i > start) print lines[i]}' "$output_file" > "$output_file.tmp2"
  3384. mv "$output_file.tmp2" "$output_file"
  3385. sed -i '/./,$!d' "$output_file"
  3386. fi
  3387. if [ -f "$clash_yaml" ]; then
  3388. get_clash_tags=$(awk '/proxies:/ {in_proxies_block=1} in_proxies_block && /- name:/ {name = $3} in_proxies_block && /port:/ {port = $2; print "Name:", name, "Port:", port}' "$clash_yaml" > "$temp_yaml")
  3389. matching_clash_tag=$(grep "Port: $listen_port" "$temp_yaml" | awk '{print $2}')
  3390. fi
  3391. if [ -n "$listen_port" ]; then
  3392. phone_matching_tag=$(jq -r --argjson listen_port "$listen_port" '.outbounds[] | select(.server_port == $listen_port) | .tag' "$phone_client_file")
  3393. win_matching_tag=$(jq -r --argjson listen_port "$listen_port" '.outbounds[] | select(.server_port == $listen_port) | .tag' "$win_client_file")
  3394. fi
  3395. jq --arg tag "$phone_matching_tag" '.outbounds |= map(select(.tag != $tag))' "$phone_client_file" > "$temp_json"
  3396. mv "$temp_json" "$phone_client_file"
  3397. jq --arg tag "$win_matching_tag" '.outbounds |= map(select(.tag != $tag))' "$win_client_file" > "$temp_json"
  3398. mv "$temp_json" "$win_client_file"
  3399. if [ -n "$matching_clash_tag" ] && [ "$selected_type" != "wireguard" ]; then
  3400. sed -i "/^ - name: $matching_clash_tag$/,/^\s*$/d" "$clash_yaml"
  3401. sed -i "/proxy-groups:/,/^\s*$/ {/ - $matching_clash_tag/d}" "$clash_yaml"
  3402. fi
  3403. phone_matching_detour=$(jq -r --arg phone_matching_tag "$phone_matching_tag" '.outbounds[] | select(.detour == $phone_matching_tag) | .detour' "$phone_client_file")
  3404. win_matching_detour=$(jq -r --arg win_matching_tag "$win_matching_tag" '.outbounds[] | select(.detour == $win_matching_tag) | .detour' "$win_client_file")
  3405. phone_matching_detour_tag=$(jq -r --arg phone_matching_detour "$phone_matching_detour" '.outbounds[] | select(.detour == $phone_matching_detour) | .tag' "$phone_client_file")
  3406. win_matching_detour_tag=$(jq -r --arg win_matching_detour "$win_matching_detour" '.outbounds[] | select(.detour == $win_matching_detour) | .tag' "$win_client_file")
  3407. awk -v phone_matching_tag="$phone_matching_tag" '!/^ "outbounds": \[$/,/^\s*]/{if (!($0 ~ "^ * \"" phone_matching_tag "\"")) print; else next; }' "$phone_client_file" > "$phone_client_file.tmp"
  3408. mv "$phone_client_file.tmp" "$phone_client_file"
  3409. awk -v win_matching_tag="$win_matching_tag" '!/^ "outbounds": \[$/,/^\s*]/{if (!($0 ~ "^ * \"" win_matching_tag "\"")) print; else next; }' "$win_client_file" > "$win_client_file.tmp"
  3410. mv "$win_client_file.tmp" "$win_client_file"
  3411. if [ "$phone_matching_tag" == "$phone_matching_detour" ]; then
  3412. jq --arg phone_matching_detour "$phone_matching_detour" '.outbounds |= map(select(.detour != $phone_matching_detour))' "$phone_client_file" > "$temp_json"
  3413. mv "$temp_json" "$phone_client_file"
  3414. awk -v phone_matching_detour_tag="$phone_matching_detour_tag" '!/^ "outbounds": \[$/,/^\s*]/{if (!($0 ~ "^ * \"" phone_matching_detour_tag "\"")) print; else next; }' "$phone_client_file" > "$phone_client_file.tmp"
  3415. mv "$phone_client_file.tmp" "$phone_client_file"
  3416. fi
  3417. if [ "$win_matching_tag" == "$win_matching_detour" ]; then
  3418. jq --arg win_matching_detour "$win_matching_detour" '.outbounds |= map(select(.detour != $win_matching_detour))' "$win_client_file" > "$temp_json"
  3419. mv "$temp_json" "$win_client_file"
  3420. awk -v win_matching_detour_tag="$win_matching_detour_tag" '!/^ "outbounds": \[$/,/^\s*]/{if (!($0 ~ "^ * \"" win_matching_detour_tag "\"")) print; else next; }' "$win_client_file" > "$win_client_file.tmp"
  3421. mv "$win_client_file.tmp" "$win_client_file"
  3422. fi
  3423. awk '{if ($0 ~ /],$/ && p ~ /,$/) sub(/,$/, "", p); if (NR > 1) print p; p = $0;}END{print p;}' "$phone_client_file" > "$phone_client_file.tmp"
  3424. mv "$phone_client_file.tmp" "$phone_client_file"
  3425. awk '{if ($0 ~ /],$/ && p ~ /,$/) sub(/,$/, "", p); if (NR > 1) print p; p = $0;}END{print p;}' "$win_client_file" > "$win_client_file.tmp"
  3426. mv "$win_client_file.tmp" "$win_client_file"
  3427. [ -f "$temp_yaml" ] && rm "$temp_yaml"
  3428. if ! jq -e 'select(.inbounds[] | .listen == "::")' "$config_file" > /dev/null; then
  3429. sed -i 's/"rules": \[\]/"rules": [\n ]/' "$config_file"
  3430. sed -i 's/^ "inbounds": \[\],/ "inbounds": [\n ],/' "$config_file"
  3431. sed -i 's/^ "outbounds": \[\],/ "outbounds": [\n ],/' "$win_client_file"
  3432. sed -i 's/^ "outbounds": \[\],/ "outbounds": [\n ],/' "$phone_client_file"
  3433. fi
  3434. systemctl restart sing-box
  3435. echo "已删除 $selected_type 的配置信息,服务端及客户端配置信息已更新,请下载新的配置文件使用!"
  3436. }
  3437. function display_naive_config_info() {
  3438. local config_file="/usr/local/etc/sing-box/config.json"
  3439. local output_file="/usr/local/etc/sing-box/output.txt"
  3440. local num_users=${#user_names[@]}
  3441. echo -e "${CYAN}NaiveProxy 节点配置信息:${NC}" | tee -a "$output_file"
  3442. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3443. echo "服务器地址: $domain" | tee -a "$output_file"
  3444. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3445. echo "监听端口: $listen_port" | tee -a "$output_file"
  3446. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3447. echo "用 户 名 密 码" | tee -a "$output_file"
  3448. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3449. for ((i=0; i<num_users; i++)); do
  3450. local user_name="${user_names[i]}"
  3451. local user_password="${user_passwords[i]}"
  3452. printf "%-38s %s\n" "$user_name" "$user_password" | tee -a "$output_file"
  3453. done
  3454. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3455. echo "" >> "$output_file"
  3456. echo "配置信息已保存至 $output_file"
  3457. }
  3458. function generate_naive_config_files() {
  3459. local config_file="/usr/local/etc/sing-box/config.json"
  3460. local naive_client_file="$naive_client_filename"
  3461. local num_users=${#user_names[@]}
  3462. for ((i=0; i<num_users; i++)); do
  3463. local user_name="${user_names[i]}"
  3464. local user_password="${user_passwords[i]}"
  3465. generate_naive_random_filename
  3466. write_naive_client_file
  3467. generate_naive_win_client_config "$user_name" "$user_password" "$listen_port" "$domain"
  3468. done
  3469. }
  3470. function display_Direct_config() {
  3471. local config_file="/usr/local/etc/sing-box/config.json"
  3472. local output_file="/usr/local/etc/sing-box/output.txt"
  3473. local override_address=$(jq -r '.inbounds[0].override_address' "$config_file")
  3474. if [[ -n "$ip_v4" ]]; then
  3475. local_ip="$ip_v4"
  3476. elif [[ -n "$ip_v6" ]]; then
  3477. local_ip="$ip_v6"
  3478. fi
  3479. echo -e "${CYAN}Direct 节点配置信息:${NC}" | tee -a "$output_file"
  3480. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3481. echo "中转地址: $local_ip" | tee -a "$output_file"
  3482. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3483. echo "监听端口: $listen_port" | tee -a "$output_file"
  3484. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3485. echo "目标地址: $override_address" | tee -a "$output_file"
  3486. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3487. echo "目标端口: $override_port" | tee -a "$output_file"
  3488. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3489. echo "" >> "$output_file"
  3490. echo "配置信息已保存至 $output_file"
  3491. }
  3492. function display_juicity_config() {
  3493. local config_file="/usr/local/etc/juicity/config.json"
  3494. local output_file="/usr/local/etc/juicity/output.txt"
  3495. local server_address
  3496. local congestion_control=$(jq -r '.congestion_control' "$config_file")
  3497. if [[ -n "$ip_v4" ]]; then
  3498. local_ip="$ip_v4"
  3499. elif [[ -n "$ip_v6" ]]; then
  3500. local_ip="$ip_v6"
  3501. fi
  3502. if [ -z "$domain" ]; then
  3503. server_address="$local_ip"
  3504. else
  3505. server_address="$domain"
  3506. fi
  3507. echo -e "${CYAN}Juicity 节点配置信息:${NC}" | tee -a "$output_file"
  3508. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3509. echo "服务器地址: $server_address" | tee -a "$output_file"
  3510. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3511. echo "监听端口: $listen_port" | tee -a "$output_file"
  3512. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3513. echo "UUID:$user_uuids 密码:$user_passwords " | tee -a "$output_file"
  3514. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3515. echo "拥塞控制算法: $congestion_control" | tee -a "$output_file"
  3516. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3517. echo "" >> "$output_file"
  3518. echo "分享链接:"
  3519. juicity-server generate-sharelink -c "$config_file"
  3520. generate_juicity_win_client_config
  3521. echo "配置信息已保存至 $output_file"
  3522. }
  3523. function display_http_config_info() {
  3524. local config_file="/usr/local/etc/sing-box/config.json"
  3525. local output_file="/usr/local/etc/sing-box/output.txt"
  3526. local num_users=${#user_names[@]}
  3527. local server_address
  3528. if [[ -n "$ip_v4" ]]; then
  3529. local_ip="$ip_v4"
  3530. elif [[ -n "$ip_v6" ]]; then
  3531. local_ip="$ip_v6"
  3532. fi
  3533. if [ -z "$domain" ]; then
  3534. server_address="$local_ip"
  3535. else
  3536. server_address="$domain"
  3537. fi
  3538. echo -e "${CYAN}HTTP 节点配置信息:${NC}" | tee -a "$output_file"
  3539. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3540. echo "服务器地址: $server_address" | tee -a "$output_file"
  3541. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3542. echo "监听端口: $listen_port" | tee -a "$output_file"
  3543. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3544. echo "用 户 名 密 码" | tee -a "$output_file"
  3545. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3546. for ((i=0; i<num_users; i++)); do
  3547. local user_name="${user_names[i]}"
  3548. local user_password="${user_passwords[i]}"
  3549. printf "%-38s %s\n" "$user_name" "$user_password" | tee -a "$output_file"
  3550. done
  3551. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3552. echo "" >> "$output_file"
  3553. echo "配置信息已保存至 $output_file"
  3554. }
  3555. function display_http_config_files() {
  3556. local config_file="/usr/local/etc/sing-box/config.json"
  3557. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3558. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3559. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3560. for ((i=0; i<${#user_passwords[@]}; i++)); do
  3561. user_password="${user_passwords[$i]}"
  3562. if [ "$enable_ech" = true ]; then
  3563. write_phone_client_file
  3564. write_win_client_file
  3565. generate_http_win_client_config "$user_password"
  3566. generate_http_phone_client_config "$user_password"
  3567. else
  3568. write_phone_client_file
  3569. write_win_client_file
  3570. generate_http_win_client_config "$user_password"
  3571. generate_http_phone_client_config "$user_password"
  3572. ensure_clash_yaml
  3573. write_clash_yaml
  3574. generate_http_yaml
  3575. fi
  3576. done
  3577. if [ "$enable_ech" = true ]; then
  3578. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3579. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3580. else
  3581. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3582. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3583. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  3584. fi
  3585. }
  3586. function display_tuic_config_info() {
  3587. local config_file="/usr/local/etc/sing-box/config.json"
  3588. local output_file="/usr/local/etc/sing-box/output.txt"
  3589. local server_address
  3590. local congestion_control=$(jq -r '.inbounds[0].congestion_control' "$config_file")
  3591. local alpn=$(jq -r '.inbounds[0].tls.alpn[0]' "$config_file")
  3592. if [[ -n "$ip_v4" ]]; then
  3593. local_ip="$ip_v4"
  3594. elif [[ -n "$ip_v6" ]]; then
  3595. local_ip="$ip_v6"
  3596. fi
  3597. if [ -z "$domain" ]; then
  3598. server_address="$local_ip"
  3599. else
  3600. server_address="$domain"
  3601. fi
  3602. echo -e "${CYAN}TUIC 节点配置信息:${NC}" | tee -a "$output_file"
  3603. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3604. echo "服务器地址: $server_address" | tee -a "$output_file"
  3605. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3606. echo "监听端口: $listen_port" | tee -a "$output_file"
  3607. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3608. echo "用户密码列表:" | tee -a "$output_file"
  3609. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3610. echo " 用户名 UUID 密码" | tee -a "$output_file"
  3611. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3612. for ((i=0; i<${#user_names[@]}; i++)); do
  3613. user_name="${user_names[$i]}"
  3614. user_uuid="${user_uuids[$i]}"
  3615. user_password="${user_passwords[$i]}"
  3616. printf "%-13s %-42s %s\n" "$user_name" "$user_uuid" "$user_password" | tee -a "$output_file"
  3617. done
  3618. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3619. echo "拥塞控制算法: $congestion_control" | tee -a "$output_file"
  3620. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3621. echo "ALPN: $alpn" | tee -a "$output_file"
  3622. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3623. echo "" >> "$output_file"
  3624. echo "配置信息已保存至 $output_file"
  3625. }
  3626. function display_tuic_config_files() {
  3627. local config_file="/usr/local/etc/sing-box/config.json"
  3628. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3629. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3630. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3631. local congestion_control=$(jq -r '.inbounds[0].congestion_control' "$config_file")
  3632. local alpn=$(jq -r '.inbounds[0].tls.alpn[0]' "$config_file")
  3633. local num_users=${#user_uuids[@]}
  3634. for ((i=0; i<num_users; i++)); do
  3635. local user_uuid="${user_uuids[i]}"
  3636. local user_password="${user_passwords[i]}"
  3637. if [ "$enable_ech" = true ]; then
  3638. write_phone_client_file
  3639. write_win_client_file
  3640. generate_tuic_win_client_config "$user_uuid" "$user_password"
  3641. generate_tuic_phone_client_config "$user_uuid" "$user_password"
  3642. else
  3643. write_phone_client_file
  3644. write_win_client_file
  3645. generate_tuic_win_client_config "$user_uuid" "$user_password"
  3646. generate_tuic_phone_client_config "$user_uuid" "$user_password"
  3647. ensure_clash_yaml
  3648. write_clash_yaml
  3649. generate_tuic_yaml
  3650. fi
  3651. done
  3652. if [ "$enable_ech" = true ]; then
  3653. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3654. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3655. else
  3656. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3657. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3658. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  3659. fi
  3660. }
  3661. function display_Shadowsocks_config_info() {
  3662. local config_file="/usr/local/etc/sing-box/config.json"
  3663. local output_file="/usr/local/etc/sing-box/output.txt"
  3664. local ss_method=$(jq -r '.inbounds[0].method' "$config_file")
  3665. if [[ -n "$ip_v4" ]]; then
  3666. local_ip="$ip_v4"
  3667. elif [[ -n "$ip_v6" ]]; then
  3668. local_ip="$ip_v6"
  3669. fi
  3670. echo -e "${CYAN}Shadowsocks 节点配置信息:${NC}" | tee -a "$output_file"
  3671. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3672. echo "服务器地址: $local_ip" | tee -a "$output_file"
  3673. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3674. echo "监听端口: $listen_port" | tee -a "$output_file"
  3675. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3676. echo "加密方式: $ss_method" | tee -a "$output_file"
  3677. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3678. echo "密码: $ss_passwords" | tee -a "$output_file"
  3679. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3680. echo "" >> "$output_file"
  3681. echo "配置信息已保存至 $output_file"
  3682. }
  3683. function display_Shadowsocks_config_files() {
  3684. local config_file="/usr/local/etc/sing-box/config.json"
  3685. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3686. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3687. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3688. local ss_method=$(jq -r '.inbounds[0].method' "$config_file")
  3689. if [[ -n "$ip_v4" ]]; then
  3690. local_ip="$ip_v4"
  3691. elif [[ -n "$ip_v6" ]]; then
  3692. local_ip="$ip_v6"
  3693. fi
  3694. write_phone_client_file
  3695. write_win_client_file
  3696. generate_shadowsocks_win_client_config
  3697. generate_shadowsocks_phone_client_config
  3698. ensure_clash_yaml
  3699. write_clash_yaml
  3700. generate_shadowsocks_yaml
  3701. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3702. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3703. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  3704. }
  3705. function display_socks_config_info() {
  3706. local config_file="/usr/local/etc/sing-box/config.json"
  3707. local output_file="/usr/local/etc/sing-box/output.txt"
  3708. if [[ -n "$ip_v4" ]]; then
  3709. local_ip="$ip_v4"
  3710. elif [[ -n "$ip_v6" ]]; then
  3711. local_ip="$ip_v6"
  3712. fi
  3713. echo -e "${CYAN}SOCKS 节点配置信息:${NC}" | tee -a "$output_file"
  3714. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3715. echo "服务器地址: $local_ip" | tee -a "$output_file"
  3716. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3717. echo "监听端口: $listen_port" | tee -a "$output_file"
  3718. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3719. echo "用户密码列表:" | tee -a "$output_file"
  3720. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3721. echo "用户名 密码" | tee -a "$output_file"
  3722. for ((i=0; i<${#user_names[@]}; i++)); do
  3723. user_name="${user_names[$i]}"
  3724. user_password="${user_passwords[$i]}"
  3725. printf "%-35s %s\n" "$user_name" "$user_password" | tee -a "$output_file"
  3726. done
  3727. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3728. echo "" >> "$output_file"
  3729. echo "节点配置信息已保存至 $output_file"
  3730. }
  3731. function display_socks_config_files() {
  3732. local config_file="/usr/local/etc/sing-box/config.json"
  3733. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3734. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3735. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3736. local num_users=${#user_names[@]}
  3737. if [[ -n "$ip_v4" ]]; then
  3738. local_ip="$ip_v4"
  3739. elif [[ -n "$ip_v6" ]]; then
  3740. local_ip="$ip_v6"
  3741. fi
  3742. for ((i=0; i<num_users; i++)); do
  3743. local user_name="${user_names[i]}"
  3744. local user_password="${user_passwords[i]}"
  3745. write_phone_client_file
  3746. write_win_client_file
  3747. generate_socks_win_client_config "$user_name" "$user_password"
  3748. generate_socks_phone_client_config "$user_name" "$user_password"
  3749. ensure_clash_yaml
  3750. write_clash_yaml
  3751. generate_socks_yaml
  3752. done
  3753. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3754. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3755. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  3756. }
  3757. function display_Hysteria_config_info() {
  3758. local config_file="/usr/local/etc/sing-box/config.json"
  3759. local output_file="/usr/local/etc/sing-box/output.txt"
  3760. local server_address
  3761. local alpn=$(jq -r '.inbounds[0].tls.alpn[0]' "$config_file")
  3762. if [[ -n "$ip_v4" ]]; then
  3763. local_ip="$ip_v4"
  3764. elif [[ -n "$ip_v6" ]]; then
  3765. local_ip="$ip_v6"
  3766. fi
  3767. if [ -z "$domain" ]; then
  3768. server_address="$local_ip"
  3769. else
  3770. server_address="$domain"
  3771. fi
  3772. echo -e "${CYAN}Hysteria 节点配置信息:${NC}" | tee -a "$output_file"
  3773. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3774. echo "服务器地址:$server_address" | tee -a "$output_file"
  3775. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3776. echo "监听端口:$listen_port" | tee -a "$output_file"
  3777. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3778. echo "上行速度:${up_mbps}Mbps" | tee -a "$output_file"
  3779. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3780. echo "下行速度:${down_mbps}Mbps" | tee -a "$output_file"
  3781. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3782. echo "ALPN:$alpn" | tee -a "$output_file"
  3783. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3784. echo "用户名 密码" | tee -a "$output_file"
  3785. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3786. for ((i=0; i<${#user_names[@]}; i++)); do
  3787. user_name="${user_names[$i]}"
  3788. user_password="${user_passwords[$i]}"
  3789. printf "%-35s %s\n" "$user_name" "$user_password" | tee -a "$output_file"
  3790. done
  3791. if [ -n "$obfs_password" ]; then
  3792. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3793. echo "obfs混淆密码:$obfs_password" | tee -a "$output_file"
  3794. fi
  3795. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3796. echo "" >> "$output_file"
  3797. echo "配置信息已保存至 $output_file"
  3798. }
  3799. function display_Hysteria_config_files() {
  3800. local config_file="/usr/local/etc/sing-box/config.json"
  3801. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3802. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3803. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3804. local alpn=$(jq -r '.inbounds[0].tls.alpn[0]' "$config_file")
  3805. for ((i=0; i<${#user_passwords[@]}; i++)); do
  3806. user_password="${user_passwords[$i]}"
  3807. if [ "$enable_ech" = true ]; then
  3808. write_phone_client_file
  3809. write_win_client_file
  3810. generate_Hysteria_win_client_config "$user_password"
  3811. generate_Hysteria_phone_client_config "$user_password"
  3812. else
  3813. write_phone_client_file
  3814. write_win_client_file
  3815. generate_Hysteria_win_client_config "$user_password"
  3816. generate_Hysteria_phone_client_config "$user_password"
  3817. ensure_clash_yaml
  3818. write_clash_yaml
  3819. generate_Hysteria_yaml
  3820. fi
  3821. done
  3822. if [ "$enable_ech" = true ]; then
  3823. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3824. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3825. else
  3826. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3827. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3828. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  3829. fi
  3830. }
  3831. function display_Hy2_config_info() {
  3832. local config_file="/usr/local/etc/sing-box/config.json"
  3833. local output_file="/usr/local/etc/sing-box/output.txt"
  3834. local server_address
  3835. local alpn=$(jq -r '.inbounds[0].tls.alpn[0]' "$config_file")
  3836. if [[ -n "$ip_v4" ]]; then
  3837. local_ip="$ip_v4"
  3838. elif [[ -n "$ip_v6" ]]; then
  3839. local_ip="$ip_v6"
  3840. fi
  3841. if [ -z "$domain" ]; then
  3842. server_address="$local_ip"
  3843. else
  3844. server_address="$domain"
  3845. fi
  3846. echo -e "${CYAN}Hysteria2 节点配置信息:${NC}" | tee -a "$output_file"
  3847. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3848. echo "服务器地址:$server_address" | tee -a "$output_file"
  3849. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3850. echo "监听端口:$listen_port" | tee -a "$output_file"
  3851. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3852. echo "上行速度:${up_mbps}Mbps" | tee -a "$output_file"
  3853. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3854. echo "下行速度:${down_mbps}Mbps" | tee -a "$output_file"
  3855. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3856. echo "ALPN:$alpn" | tee -a "$output_file"
  3857. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3858. echo "用户名 密码" | tee -a "$output_file"
  3859. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  3860. for ((i=0; i<${#user_names[@]}; i++)); do
  3861. user_name="${user_names[$i]}"
  3862. user_password="${user_passwords[$i]}"
  3863. printf "%-35s %s\n" "$user_name" "$user_password" | tee -a "$output_file"
  3864. done
  3865. if [ -n "$obfs_password" ]; then
  3866. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3867. echo "QUIC 流量混淆器密码:$obfs_password" | tee -a "$output_file"
  3868. fi
  3869. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3870. echo "" >> "$output_file"
  3871. echo "配置信息已保存至 $output_file"
  3872. }
  3873. function display_Hy2_config_files() {
  3874. local config_file="/usr/local/etc/sing-box/config.json"
  3875. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3876. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3877. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3878. local alpn=$(jq -r '.inbounds[0].tls.alpn[0]' "$config_file")
  3879. for ((i=0; i<${#user_passwords[@]}; i++)); do
  3880. user_password="${user_passwords[$i]}"
  3881. if [ "$enable_ech" = true ]; then
  3882. write_phone_client_file
  3883. write_win_client_file
  3884. generate_Hysteria2_win_client_config "$user_password"
  3885. generate_Hysteria2_phone_client_config "$user_password"
  3886. else
  3887. write_phone_client_file
  3888. write_win_client_file
  3889. generate_Hysteria2_win_client_config "$user_password"
  3890. generate_Hysteria2_phone_client_config "$user_password"
  3891. ensure_clash_yaml
  3892. write_clash_yaml
  3893. generate_Hysteria2_yaml
  3894. fi
  3895. done
  3896. if [ "$enable_ech" = true ]; then
  3897. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3898. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3899. else
  3900. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  3901. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  3902. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  3903. fi
  3904. }
  3905. function display_reality_config_info() {
  3906. local config_file="/usr/local/etc/sing-box/config.json"
  3907. local output_file="/usr/local/etc/sing-box/output.txt"
  3908. local flow_type=$(jq -r '.inbounds[0].users[0].flow' "$config_file")
  3909. local transport_type=$(jq -r '.inbounds[0].transport.type' "$config_file")
  3910. local server_name=$(jq -r '.inbounds[0].tls.server_name' "$config_file")
  3911. local target_server=$(jq -r '.inbounds[0].tls.reality.handshake.server' "$config_file")
  3912. local transport_service_name=$(jq -r '.inbounds[0].transport.service_name' "$config_file")
  3913. local lobal_public_key="$public_key"
  3914. if [[ -n "$ip_v4" ]]; then
  3915. local_ip="$ip_v4"
  3916. elif [[ -n "$ip_v6" ]]; then
  3917. local_ip="$ip_v6"
  3918. fi
  3919. if [[ "$flow_type" == "xtls-rprx-vision" ]]; then
  3920. transport_type="tcp"
  3921. fi
  3922. echo -e "${CYAN}VLESS 节点配置信息:${NC}" | tee -a "$output_file"
  3923. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3924. echo "服务器地址: $local_ip" | tee -a "$output_file"
  3925. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3926. echo "监听端口: $listen_port" | tee -a "$output_file"
  3927. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3928. echo "UUID列表:" | tee -a "$output_file"
  3929. for ((i=0; i<${#user_uuids[@]}; i++)); do
  3930. user_uuid="${user_uuids[$i]}"
  3931. echo "$user_uuid"| tee -a "$output_file"
  3932. done
  3933. if [ -n "$flow_type" ]; then
  3934. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3935. echo "流控类型: $flow_type" | tee -a "$output_file"
  3936. fi
  3937. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3938. if [ "$transport_type" != "null" ]; then
  3939. echo "传输协议: $transport_type" | tee -a "$output_file"
  3940. if [ "$transport_type" == "ws" ]; then
  3941. echo "路径: $transport_path" | tee -a "$output_file"
  3942. elif [ "$transport_type" == "httpupgrade" ]; then
  3943. echo "路径: $transport_path" | tee -a "$output_file"
  3944. elif [ "$transport_type" == "grpc" ]; then
  3945. echo "grpc-service-name: $transport_service_name" | tee -a "$output_file"
  3946. fi
  3947. else
  3948. echo "传输协议: tcp" | tee -a "$output_file"
  3949. fi
  3950. if [ -n "$server_name" ] && [ "$server_name" != "null" ]; then
  3951. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3952. echo "ServerName: $server_name" | tee -a "$output_file"
  3953. fi
  3954. if [ -n "$target_server" ] && [ "$target_server" != "null" ]; then
  3955. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3956. echo "目标网站地址: $target_server" | tee -a "$output_file"
  3957. fi
  3958. if [ -n "$short_id" ]; then
  3959. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3960. echo "Short ID:" | tee -a "$output_file"
  3961. for ((i=0; i<${#short_ids[@]}; i++)); do
  3962. short_id="${short_ids[$i]}"
  3963. echo "$short_id" | tee -a "$output_file"
  3964. done
  3965. fi
  3966. if [ -n "$public_key" ]; then
  3967. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  3968. echo "PublicKey: $public_key" | tee -a "$output_file"
  3969. fi
  3970. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  3971. echo "" >> "$output_file"
  3972. echo "配置信息已保存至 $output_file"
  3973. }
  3974. function display_reality_config_files() {
  3975. local config_file="/usr/local/etc/sing-box/config.json"
  3976. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  3977. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  3978. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  3979. local flow_type=$(jq -r '.inbounds[0].users[0].flow' "$config_file")
  3980. local transport_type=$(jq -r '.inbounds[0].transport.type' "$config_file")
  3981. local server_name=$(jq -r '.inbounds[0].tls.server_name' "$config_file")
  3982. local target_server=$(jq -r '.inbounds[0].tls.reality.handshake.server' "$config_file")
  3983. local transport_service_name=$(jq -r '.inbounds[0].transport.service_name' "$config_file")
  3984. local lobal_public_key="$public_key"
  3985. if [[ -n "$ip_v4" ]]; then
  3986. local_ip="$ip_v4"
  3987. elif [[ -n "$ip_v6" ]]; then
  3988. local_ip="$ip_v6"
  3989. fi
  3990. for ((i=0; i<${#user_uuids[@]}; i++)); do
  3991. local user_uuid="${user_uuids[$i]}"
  3992. write_phone_client_file
  3993. write_win_client_file
  3994. if [[ "$server_name" == "null" ]] && [[ "$transport_type" == "null" ]]; then
  3995. ensure_clash_yaml
  3996. write_clash_yaml
  3997. generate_vless_tcp_yaml
  3998. generate_vless_win_client_config
  3999. generate_vless_phone_client_config
  4000. elif [[ "$server_name" == "null" ]] && [[ "$transport_type" == "ws" ]]; then
  4001. ensure_clash_yaml
  4002. write_clash_yaml
  4003. generate_vless_ws_yaml
  4004. generate_vless_win_client_config
  4005. generate_vless_phone_client_config
  4006. elif [[ "$server_name" == "null" ]] && [[ "$transport_type" == "grpc" ]]; then
  4007. ensure_clash_yaml
  4008. write_clash_yaml
  4009. generate_vless_grpc_yaml
  4010. generate_vless_win_client_config
  4011. generate_vless_phone_client_config
  4012. elif [[ "$server_name" == "null" ]] && [[ "$transport_type" == "httpupgrade" ]]; then
  4013. generate_vless_win_client_config
  4014. generate_vless_phone_client_config
  4015. fi
  4016. for ((j=0; j<${#short_ids[@]}; j++)); do
  4017. local short_id="${short_ids[$j]}"
  4018. write_phone_client_file
  4019. write_win_client_file
  4020. if [[ -n "$server_name" ]] && [[ "$server_name" != "null" ]] && [[ "$transport_type" == "null" ]]; then
  4021. ensure_clash_yaml
  4022. write_clash_yaml
  4023. generate_vless_reality_vision_yaml
  4024. generate_vless_win_client_config
  4025. generate_vless_phone_client_config
  4026. elif [[ -n "$server_name" ]] && [[ "$server_name" != "null" ]] && [[ "$transport_type" == "http" ]]; then
  4027. generate_vless_win_client_config
  4028. generate_vless_phone_client_config
  4029. elif [[ -n "$server_name" ]] && [[ "$server_name" != "null" ]] && [[ "$transport_type" == "grpc" ]]; then
  4030. ensure_clash_yaml
  4031. write_clash_yaml
  4032. generate_vless_reality_grpc_yaml
  4033. generate_vless_win_client_config
  4034. generate_vless_phone_client_config
  4035. fi
  4036. done
  4037. done
  4038. if [[ "$transport_type" != "http" && "$transport_type" != "httpupgrade" ]]; then
  4039. echo "Clash配置文件已保存至 $clash_file,请下载使用!"
  4040. fi
  4041. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  4042. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  4043. }
  4044. function display_vmess_config_info() {
  4045. local config_file="/usr/local/etc/sing-box/config.json"
  4046. local output_file="/usr/local/etc/sing-box/output.txt"
  4047. local server_address
  4048. local transport_type=$(jq -r '.inbounds[0].transport.type' "$config_file")
  4049. local transport_path=$(jq -r '.inbounds[0].transport.path' "$config_file")
  4050. local transport_service_name=$(jq -r '.inbounds[0].transport.service_name' "$config_file")
  4051. if [[ -n "$ip_v4" ]]; then
  4052. local_ip="$ip_v4"
  4053. elif [[ -n "$ip_v6" ]]; then
  4054. local_ip="$ip_v6"
  4055. fi
  4056. if [[ -z "$domain" && -n "$domain_name" ]]; then
  4057. server_address="$local_ip"
  4058. elif [[ -z "$domain" && -z "$domain_name" ]]; then
  4059. server_address="$local_ip"
  4060. elif [[ -n "$domain" ]]; then
  4061. server_address="$domain"
  4062. fi
  4063. echo -e "${CYAN}VMess 节点配置信息:${NC}" | tee -a "$output_file"
  4064. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  4065. echo "服务器地址: $server_address" | tee -a "$output_file"
  4066. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4067. echo "监听端口: $listen_port" | tee -a "$output_file"
  4068. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4069. echo "UUID列表:" | tee -a "$output_file"
  4070. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  4071. for ((i=0; i<${#user_uuids[@]}; i++)); do
  4072. user_uuid="${user_uuids[$i]}"
  4073. echo "$user_uuid"| tee -a "$output_file"
  4074. done
  4075. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4076. if [ "$transport_type" != "null" ]; then
  4077. echo "传输协议: $transport_type" | tee -a "$output_file"
  4078. if [ "$transport_type" == "ws" ]; then
  4079. echo "路径: $transport_path" | tee -a "$output_file"
  4080. elif [ "$transport_type" == "httpupgrade" ]; then
  4081. echo "路径: $transport_path" | tee -a "$output_file"
  4082. elif [ "$transport_type" == "grpc" ]; then
  4083. echo "grpc-service-name: $transport_service_name" | tee -a "$output_file"
  4084. fi
  4085. else
  4086. echo "传输协议: tcp" | tee -a "$output_file"
  4087. fi
  4088. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  4089. echo "" >> "$output_file"
  4090. echo "配置信息已保存至 $output_file"
  4091. }
  4092. function display_vmess_config_files() {
  4093. local config_file="/usr/local/etc/sing-box/config.json"
  4094. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  4095. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  4096. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  4097. local transport_type=$(jq -r '.inbounds[0].transport.type' "$config_file")
  4098. local transport_path=$(jq -r '.inbounds[0].transport.path' "$config_file")
  4099. local transport_service_name=$(jq -r '.inbounds[0].transport.service_name' "$config_file")
  4100. local show_clash_message=true
  4101. if [[ -n "$ip_v4" ]]; then
  4102. local_ip="$ip_v4"
  4103. elif [[ -n "$ip_v6" ]]; then
  4104. local_ip="$ip_v6"
  4105. fi
  4106. for ((i=0; i<${#user_uuids[@]}; i++)); do
  4107. user_uuid="${user_uuids[$i]}"
  4108. write_phone_client_file
  4109. write_win_client_file
  4110. generate_vmess_win_client_config
  4111. generate_vmess_phone_client_config
  4112. if [ "$enable_ech" != true ] && [ -z "$domain" ] && [ -z "$domain_name" ] && [ "$transport_type" == "null" ]; then
  4113. ensure_clash_yaml
  4114. write_clash_yaml
  4115. generate_vmess_tcp_yaml
  4116. elif [ "$enable_ech" != true ] && [ -z "$domain" ] && [ -z "$domain_name" ] && [ "$transport_type" == "ws" ]; then
  4117. ensure_clash_yaml
  4118. write_clash_yaml
  4119. generate_vmess_ws_yaml
  4120. elif [ "$enable_ech" != true ] && [ -z "$domain" ] && [ -z "$domain_name" ] && [ "$transport_type" == "grpc" ]; then
  4121. ensure_clash_yaml
  4122. write_clash_yaml
  4123. generate_vmess_grpc_yaml
  4124. elif [ "$enable_ech" != true ] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "null" ]; then
  4125. ensure_clash_yaml
  4126. write_clash_yaml
  4127. generate_vmess_tcp_tls_yaml
  4128. elif [ "$enable_ech" != true ] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "ws" ]; then
  4129. ensure_clash_yaml
  4130. write_clash_yaml
  4131. generate_vmess_ws_tls_yaml
  4132. elif [ "$enable_ech" != true ] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "grpc" ]; then
  4133. ensure_clash_yaml
  4134. write_clash_yaml
  4135. generate_vmess_grpc_tls_yaml
  4136. elif [ "$enable_ech" != true ] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "http" ]; then
  4137. show_clash_message=false
  4138. fi
  4139. done
  4140. if [ "$transport_type" == "http" ] || [ "$transport_type" == "httpupgrade" ] || [ "$enable_ech" = true ]; then
  4141. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  4142. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  4143. else
  4144. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  4145. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  4146. echo "Clash配置文件已保存至 $clash_file,请下载使用!"
  4147. fi
  4148. }
  4149. function display_trojan_config_info() {
  4150. local config_file="/usr/local/etc/sing-box/config.json"
  4151. local output_file="/usr/local/etc/sing-box/output.txt"
  4152. local server_address
  4153. local transport_type=$(jq -r '.inbounds[0].transport.type' "$config_file")
  4154. local transport_path=$(jq -r '.inbounds[0].transport.path' "$config_file")
  4155. local transport_service_name=$(jq -r '.inbounds[0].transport.service_name' "$config_file")
  4156. if [[ -n "$ip_v4" ]]; then
  4157. local_ip="$ip_v4"
  4158. elif [[ -n "$ip_v6" ]]; then
  4159. local_ip="$ip_v6"
  4160. fi
  4161. if [[ -z "$domain" && -n "$domain_name" ]]; then
  4162. server_address="$local_ip"
  4163. elif [[ -z "$domain" && -z "$domain_name" ]]; then
  4164. server_address="$local_ip"
  4165. elif [[ -n "$domain" ]]; then
  4166. server_address="$domain"
  4167. fi
  4168. echo -e "${CYAN}Trojan 节点配置信息:${NC}" | tee -a "$output_file"
  4169. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  4170. echo "服务器地址: $server_address" | tee -a "$output_file"
  4171. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4172. echo "监听端口: $listen_port" | tee -a "$output_file"
  4173. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4174. echo "密码列表:" | tee -a "$output_file"
  4175. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  4176. for ((i = 0; i < ${#user_passwords[@]}; i++)); do
  4177. user_password="${user_passwords[i]}"
  4178. echo "$user_password"| tee -a "$output_file"
  4179. done
  4180. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4181. if [ "$transport_type" != "null" ]; then
  4182. echo "传输协议: $transport_type" | tee -a "$output_file"
  4183. if [ "$transport_type" == "ws" ]; then
  4184. echo "路径: $transport_path" | tee -a "$output_file"
  4185. elif [ "$transport_type" == "httpupgrade" ]; then
  4186. echo "路径: $transport_path" | tee -a "$output_file"
  4187. elif [ "$transport_type" == "grpc" ]; then
  4188. echo "grpc-service-name: $transport_service_name" | tee -a "$output_file"
  4189. fi
  4190. else
  4191. echo "传输协议: tcp" | tee -a "$output_file"
  4192. fi
  4193. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  4194. echo "" >> "$output_file"
  4195. echo "配置信息已保存至 $output_file"
  4196. }
  4197. function display_trojan_config_files() {
  4198. local config_file="/usr/local/etc/sing-box/config.json"
  4199. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  4200. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  4201. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  4202. local transport_type=$(jq -r '.inbounds[0].transport.type' "$config_file")
  4203. local transport_path=$(jq -r '.inbounds[0].transport.path' "$config_file")
  4204. local transport_service_name=$(jq -r '.inbounds[0].transport.service_name' "$config_file")
  4205. if [[ -n "$ip_v4" ]]; then
  4206. local_ip="$ip_v4"
  4207. elif [[ -n "$ip_v6" ]]; then
  4208. local_ip="$ip_v6"
  4209. fi
  4210. for ((i = 0; i < ${#user_passwords[@]}; i++)); do
  4211. user_password="${user_passwords[i]}"
  4212. write_phone_client_file
  4213. write_win_client_file
  4214. generate_trojan_win_client_config
  4215. generate_trojan_phone_client_config
  4216. if [[ "$enable_ech" != true ]] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "null" ]; then
  4217. ensure_clash_yaml
  4218. write_clash_yaml
  4219. generate_trojan_tcp_tls_yaml
  4220. elif [[ "$enable_ech" != true ]] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "ws" ]; then
  4221. ensure_clash_yaml
  4222. write_clash_yaml
  4223. generate_trojan_ws_tls_yaml
  4224. elif [[ "$enable_ech" != true ]] && [[ -n "$domain" || -n "$domain_name" ]] && [ "$transport_type" == "grpc" ]; then
  4225. ensure_clash_yaml
  4226. write_clash_yaml
  4227. generate_trojan_grpc_tls_yaml
  4228. fi
  4229. done
  4230. if [[ "$enable_ech" != true ]] && [[ -n "$domain" || -n "$domain_name" ]] && [[ "$transport_type" != "http" || "$transport_type" != "httpupgrade" ]]; then
  4231. echo "Clash配置文件已保存至 $clash_file,请下载使用!"
  4232. fi
  4233. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  4234. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  4235. }
  4236. function display_shadowtls_config_info() {
  4237. local config_file="/usr/local/etc/sing-box/config.json"
  4238. local output_file="/usr/local/etc/sing-box/output.txt"
  4239. local user_input=$(jq -r '.inbounds[0].handshake.server' "$config_file")
  4240. local method=$(jq -r '.inbounds[1].method' "$config_file")
  4241. if [[ -n "$ip_v4" ]]; then
  4242. local_ip="$ip_v4"
  4243. elif [[ -n "$ip_v6" ]]; then
  4244. local_ip="$ip_v6"
  4245. fi
  4246. echo -e "${CYAN}ShadowTLS 节点配置信息:${NC}" | tee -a "$output_file"
  4247. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  4248. echo "服务器地址: $local_ip" | tee -a "$output_file"
  4249. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4250. echo "监听端口: $listen_port" | tee -a "$output_file"
  4251. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4252. echo "加密方式: $method" | tee -a "$output_file"
  4253. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4254. echo "ShadowTLS用户名 ShadowTLS密码" | tee -a "$output_file"
  4255. echo "------------------------------------------------------------------------------" | tee -a "$output_file"
  4256. for ((i = 0; i < ${#stls_passwords[@]}; i++)); do
  4257. local stls_password="${stls_passwords[i]}"
  4258. printf "%-25s %s\n" "$user_name" "$stls_password" | tee -a "$output_file"
  4259. done
  4260. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4261. echo "Shadowsocks 密码: $ss_passwords" | tee -a "$output_file"
  4262. echo -e "${CYAN}------------------------------------------------------------------------------${NC}" | tee -a "$output_file"
  4263. echo "握手服务器地址: $user_input" | tee -a "$output_file"
  4264. echo -e "${CYAN}==============================================================================${NC}" | tee -a "$output_file"
  4265. echo "" >> "$output_file"
  4266. echo "配置信息已保存至 $output_file"
  4267. }
  4268. function display_shadowtls_config_files() {
  4269. local config_file="/usr/local/etc/sing-box/config.json"
  4270. local clash_file="/usr/local/etc/sing-box/clash.yaml"
  4271. local phone_client_file="/usr/local/etc/sing-box/phone_client.json"
  4272. local win_client_file="/usr/local/etc/sing-box/win_client.json"
  4273. local user_input=$(jq -r '.inbounds[0].handshake.server' "$config_file")
  4274. local method=$(jq -r '.inbounds[1].method' "$config_file")
  4275. for ((i = 0; i < ${#stls_passwords[@]}; i++)); do
  4276. local stls_password="${stls_passwords[i]}"
  4277. write_phone_client_file
  4278. write_win_client_file
  4279. generate_shadowtls_win_client_config "$stls_password"
  4280. generate_shadowtls_phone_client_config "$stls_password"
  4281. ensure_clash_yaml
  4282. write_clash_yaml
  4283. generate_shadowtls_yaml
  4284. done
  4285. echo "手机端配置文件已保存至$phone_client_file,请下载后使用!"
  4286. echo "电脑端配置文件已保存至$win_client_file,请下载后使用!"
  4287. echo "Clash配置文件已保存至 $clash_file ,请下载使用!"
  4288. }
  4289. function view_saved_config() {
  4290. local config_paths=(
  4291. "/usr/local/etc/sing-box/output.txt"
  4292. "/usr/local/etc/juicity/output.txt"
  4293. )
  4294. local found=false
  4295. for path in "${config_paths[@]}"; do
  4296. if [[ -f "$path" ]]; then
  4297. echo "配置信息文件 ($path):"
  4298. cat "$path"
  4299. found=true
  4300. fi
  4301. done
  4302. if [[ "$found" == false ]]; then
  4303. echo "未找到保存的配置信息文件!"
  4304. fi
  4305. }
  4306. function check_and_restart_services() {
  4307. if [ -f "/etc/systemd/system/sing-box.service" ]; then
  4308. systemctl restart sing-box.service
  4309. systemctl status --no-pager sing-box.service
  4310. fi
  4311. if [ -f "/etc/systemd/system/juicity.service" ]; then
  4312. systemctl restart juicity.service
  4313. systemctl status --no-pager juicity.service
  4314. fi
  4315. }
  4316. function uninstall_sing_box() {
  4317. echo "开始卸载 sing-box..."
  4318. systemctl stop sing-box
  4319. systemctl disable sing-box
  4320. rm -rf /usr/local/bin/sing-box
  4321. rm -rf /usr/local/etc/sing-box
  4322. rm -rf /etc/systemd/system/sing-box.service
  4323. systemctl daemon-reload
  4324. echo "sing-box 卸载完成。"
  4325. }
  4326. function uninstall_juicity() {
  4327. echo "开始卸载 juicity..."
  4328. systemctl stop juicity.service
  4329. systemctl disable juicity.service
  4330. rm -rf /etc/systemd/system/juicity.service
  4331. rm -rf /usr/local/etc/juicity
  4332. rm -rf /usr/local/bin/juicity-server
  4333. echo "juicity 卸载完成。"
  4334. }
  4335. function update_proxy_tool() {
  4336. if [ -e /usr/local/bin/juicity-server ]; then
  4337. install_latest_juicity
  4338. fi
  4339. if [ -e /usr/local/bin/sing-box ]; then
  4340. select_sing_box_install_option
  4341. fi
  4342. }
  4343. function uninstall() {
  4344. local uninstall_sing_box=false
  4345. local uninstall_juicity=false
  4346. if [[ -f "/etc/systemd/system/sing-box.service" ]] || [[ -f "/usr/local/bin/sing-box" ]] || [[ -d "/usr/local/etc/sing-box/" ]]; then
  4347. uninstall_sing_box=true
  4348. fi
  4349. if [[ -f "/etc/systemd/system/juicity.service" ]] || [[ -f "/usr/local/bin/juicity-server" ]] || [[ -d "/usr/local/etc/juicity/" ]]; then
  4350. uninstall_juicity=true
  4351. fi
  4352. if [[ "$uninstall_sing_box" == true ]]; then
  4353. uninstall_sing_box
  4354. fi
  4355. if [[ "$uninstall_juicity" == true ]]; then
  4356. uninstall_juicity
  4357. fi
  4358. }
  4359. function check_wireguard_config() {
  4360. local config_file="/usr/local/etc/sing-box/config.json"
  4361. if grep -q "wireguard" "$config_file"; then
  4362. echo -e "${RED}Warp 已安装,请勿重复安装!${NC}"
  4363. exit 1
  4364. fi
  4365. }
  4366. function Update_Script() {
  4367. wget -O /root/singbox.sh https://raw.githubusercontent.com/qiuxiuya/qiuxiuya/main/VPS/singbox.sh
  4368. chmod +x /root/singbox.sh
  4369. }
  4370. function add_cron_job() {
  4371. if command -v crontab > /dev/null && crontab -l | grep -q "singbox.sh"; then
  4372. echo "Cron job already exists."
  4373. else
  4374. (crontab -l 2>/dev/null ; echo "0 2 * * 1 /bin/bash /root/singbox.sh >> /usr/local/etc/certificate.log 2>&1") | crontab -
  4375. echo "Cron job added successfully."
  4376. fi
  4377. }
  4378. function juicity_install() {
  4379. configure_dns64
  4380. enable_bbr
  4381. create_juicity_folder
  4382. install_latest_juicity
  4383. get_local_ip
  4384. generate_juicity_config
  4385. add_cron_job
  4386. configure_juicity_service
  4387. systemctl daemon-reload
  4388. systemctl enable juicity.service
  4389. systemctl start juicity.service
  4390. systemctl restart juicity.service
  4391. display_juicity_config
  4392. }
  4393. function Direct_install() {
  4394. install_sing_box
  4395. enable_bbr
  4396. log_outbound_config
  4397. set_listen_port
  4398. set_override_address
  4399. set_override_port
  4400. generate_Direct_config
  4401. modify_format_inbounds_and_outbounds
  4402. modify_route_rules
  4403. check_firewall_configuration
  4404. systemctl daemon-reload
  4405. systemctl enable sing-box
  4406. systemctl start sing-box
  4407. systemctl restart sing-box
  4408. get_local_ip
  4409. display_Direct_config
  4410. }
  4411. function Shadowsocks_install() {
  4412. install_sing_box
  4413. enable_bbr
  4414. log_outbound_config
  4415. set_listen_port
  4416. select_encryption_method
  4417. set_ss_password
  4418. generate_ss_config
  4419. modify_format_inbounds_and_outbounds
  4420. modify_route_rules
  4421. check_firewall_configuration
  4422. systemctl daemon-reload
  4423. systemctl enable sing-box
  4424. systemctl start sing-box
  4425. systemctl restart sing-box
  4426. get_local_ip
  4427. display_Shadowsocks_config_info
  4428. display_Shadowsocks_config_files
  4429. }
  4430. function socks_install() {
  4431. install_sing_box
  4432. enable_bbr
  4433. log_outbound_config
  4434. generate_socks_config
  4435. modify_format_inbounds_and_outbounds
  4436. modify_route_rules
  4437. check_firewall_configuration
  4438. systemctl daemon-reload
  4439. systemctl enable sing-box
  4440. systemctl start sing-box
  4441. systemctl restart sing-box
  4442. get_local_ip
  4443. display_socks_config_info
  4444. display_socks_config_files
  4445. }
  4446. function NaiveProxy_install() {
  4447. install_sing_box
  4448. enable_bbr
  4449. log_outbound_config
  4450. generate_naive_config
  4451. add_cron_job
  4452. modify_format_inbounds_and_outbounds
  4453. modify_route_rules
  4454. systemctl daemon-reload
  4455. systemctl enable sing-box
  4456. systemctl start sing-box
  4457. systemctl restart sing-box
  4458. display_naive_config_info
  4459. generate_naive_config_files
  4460. }
  4461. function http_install() {
  4462. install_sing_box
  4463. enable_bbr
  4464. log_outbound_config
  4465. generate_http_config
  4466. add_cron_job
  4467. modify_format_inbounds_and_outbounds
  4468. modify_route_rules
  4469. systemctl daemon-reload
  4470. systemctl enable sing-box
  4471. systemctl start sing-box
  4472. systemctl restart sing-box
  4473. display_http_config_info
  4474. display_http_config_files
  4475. }
  4476. function tuic_install() {
  4477. install_sing_box
  4478. enable_bbr
  4479. log_outbound_config
  4480. generate_tuic_config
  4481. add_cron_job
  4482. modify_format_inbounds_and_outbounds
  4483. modify_route_rules
  4484. systemctl daemon-reload
  4485. systemctl enable sing-box
  4486. systemctl start sing-box
  4487. systemctl restart sing-box
  4488. get_local_ip
  4489. display_tuic_config_info
  4490. display_tuic_config_files
  4491. }
  4492. function Hysteria_install() {
  4493. install_sing_box
  4494. enable_bbr
  4495. log_outbound_config
  4496. generate_Hysteria_config
  4497. add_cron_job
  4498. modify_format_inbounds_and_outbounds
  4499. modify_route_rules
  4500. systemctl daemon-reload
  4501. systemctl enable sing-box
  4502. systemctl start sing-box
  4503. systemctl restart sing-box
  4504. display_Hysteria_config_info
  4505. display_Hysteria_config_files
  4506. }
  4507. function shadowtls_install() {
  4508. install_sing_box
  4509. enable_bbr
  4510. log_outbound_config
  4511. generate_shadowtls_config
  4512. modify_format_inbounds_and_outbounds
  4513. modify_route_rules
  4514. check_firewall_configuration
  4515. systemctl daemon-reload
  4516. systemctl enable sing-box
  4517. systemctl start sing-box
  4518. systemctl restart sing-box
  4519. get_local_ip
  4520. display_shadowtls_config_info
  4521. display_shadowtls_config_files
  4522. }
  4523. function reality_install() {
  4524. install_sing_box
  4525. enable_bbr
  4526. log_outbound_config
  4527. generate_vless_config
  4528. modify_format_inbounds_and_outbounds
  4529. modify_route_rules
  4530. check_firewall_configuration
  4531. systemctl daemon-reload
  4532. systemctl enable sing-box
  4533. systemctl start sing-box
  4534. systemctl restart sing-box
  4535. get_local_ip
  4536. display_reality_config_info
  4537. display_reality_config_files
  4538. }
  4539. function Hysteria2_install() {
  4540. install_sing_box
  4541. enable_bbr
  4542. log_outbound_config
  4543. generate_Hy2_config
  4544. add_cron_job
  4545. modify_format_inbounds_and_outbounds
  4546. modify_route_rules
  4547. systemctl daemon-reload
  4548. systemctl enable sing-box
  4549. systemctl start sing-box
  4550. systemctl restart sing-box
  4551. display_Hy2_config_info
  4552. display_Hy2_config_files
  4553. }
  4554. function trojan_install() {
  4555. install_sing_box
  4556. enable_bbr
  4557. log_outbound_config
  4558. generate_trojan_config
  4559. add_cron_job
  4560. modify_format_inbounds_and_outbounds
  4561. modify_route_rules
  4562. systemctl daemon-reload
  4563. systemctl enable sing-box
  4564. systemctl start sing-box
  4565. systemctl restart sing-box
  4566. display_trojan_config_info
  4567. display_trojan_config_files
  4568. }
  4569. function vmess_install() {
  4570. install_sing_box
  4571. enable_bbr
  4572. log_outbound_config
  4573. get_local_ip
  4574. generate_vmess_config
  4575. add_cron_job
  4576. modify_format_inbounds_and_outbounds
  4577. modify_route_rules
  4578. systemctl daemon-reload
  4579. systemctl enable sing-box
  4580. systemctl start sing-box
  4581. systemctl restart sing-box
  4582. display_vmess_config_info
  4583. display_vmess_config_files
  4584. }
  4585. function wireguard_install() {
  4586. check_wireguard_config
  4587. check_config_file_existence
  4588. select_unlocked_items
  4589. geosite=()
  4590. update_geosite_array
  4591. select_outbound
  4592. update_route_file "$outbound"
  4593. get_temp_config_file
  4594. extract_variables_and_cleanup
  4595. update_outbound_file
  4596. systemctl restart sing-box
  4597. }
  4598. function Update_certificate() {
  4599. get_local_ip
  4600. extract_tls_info
  4601. validate_tls_info
  4602. Reapply_certificates
  4603. }
  4604. function main_menu() {
  4605. echo "╔════════════════════════════════════════════════════════════════════════╗"
  4606. echo -e "║ ${CYAN}作者${NC}: Mr. xiao ║"
  4607. echo -e "║ ${CYAN} Version:1.2 原作者已删库( ║"
  4608. echo "╠════════════════════════════════════════════════════════════════════════╣"
  4609. echo "║ 请选择要执行的操作: ║"
  4610. echo -e "║${CYAN} [1]${NC} SOCKS ${CYAN} [2]${NC} Direct ║"
  4611. echo -e "║${CYAN} [3]${NC} HTTP ${CYAN} [4]${NC} VMess ║"
  4612. echo -e "║${CYAN} [5]${NC} VLESS ${CYAN} [6]${NC} TUIC ║"
  4613. echo -e "║${CYAN} [7]${NC} Juicity ${CYAN} [8]${NC} Trojan ║"
  4614. echo -e "║${CYAN} [9]${NC} Hysteria ${CYAN} [10]${NC} Hysteria2 ║"
  4615. echo -e "║${CYAN} [11]${NC} ShadowTLS ${CYAN} [12]${NC} NaiveProxy ║"
  4616. echo -e "║${CYAN} [13]${NC} Shadowsocks ${CYAN} [14]${NC} WireGuard ║"
  4617. echo -e "║${CYAN} [15]${NC} 查看节点信息 ${CYAN} [16]${NC} 更新内核 ║"
  4618. echo -e "║${CYAN} [17]${NC} 更新脚本 ${CYAN} [18]${NC} 更新证书 ║"
  4619. echo -e "║${CYAN} [19]${NC} 重启服务 ${CYAN} [20]${NC} 节点管理 ║"
  4620. echo -e "║${CYAN} [21]${NC} 卸载 ${CYAN} [0]${NC} 退出 ║"
  4621. echo "╚════════════════════════════════════════════════════════════════════════╝"
  4622. local choice
  4623. read -p "请选择 [0-21]: " choice
  4624. case $choice in
  4625. 1)
  4626. socks_install
  4627. exit 0
  4628. ;;
  4629. 2)
  4630. Direct_install
  4631. exit 0
  4632. ;;
  4633. 3)
  4634. http_install
  4635. exit 0
  4636. ;;
  4637. 4)
  4638. vmess_install
  4639. exit 0
  4640. ;;
  4641. 5)
  4642. reality_install
  4643. exit 0
  4644. ;;
  4645. 6)
  4646. tuic_install
  4647. exit 0
  4648. ;;
  4649. 7)
  4650. juicity_install
  4651. exit 0
  4652. ;;
  4653. 8)
  4654. trojan_install
  4655. exit 0
  4656. ;;
  4657. 9)
  4658. Hysteria_install
  4659. exit 0
  4660. ;;
  4661. 10)
  4662. Hysteria2_install
  4663. exit 0
  4664. ;;
  4665. 11)
  4666. shadowtls_install
  4667. exit 0
  4668. ;;
  4669. 12)
  4670. NaiveProxy_install
  4671. exit 0
  4672. ;;
  4673. 13)
  4674. Shadowsocks_install
  4675. exit 0
  4676. ;;
  4677. 14)
  4678. wireguard_install
  4679. exit 0
  4680. ;;
  4681. 15)
  4682. view_saved_config
  4683. exit 0
  4684. ;;
  4685. 16)
  4686. update_proxy_tool
  4687. exit 0
  4688. ;;
  4689. 17)
  4690. Update_Script
  4691. exit 0
  4692. ;;
  4693. 18)
  4694. Update_certificate
  4695. ;;
  4696. 19)
  4697. check_and_restart_services
  4698. exit 0
  4699. ;;
  4700. 20)
  4701. delete_choice
  4702. exit 0
  4703. ;;
  4704. 21)
  4705. uninstall
  4706. exit 0
  4707. ;;
  4708. 0)
  4709. echo "感谢使用 Mr. xiao 安装脚本!再见!"
  4710. exit 0
  4711. ;;
  4712. *)
  4713. echo -e "${RED}无效的选择,请重新输入。${NC}"
  4714. main_menu
  4715. ;;
  4716. esac
  4717. }
  4718. function run_option() {
  4719. case "$1" in
  4720. "18")
  4721. Update_certificate
  4722. exit 0
  4723. ;;
  4724. esac
  4725. }
  4726. if [ $# -eq 0 ]; then
  4727. main_menu
  4728. else
  4729. run_option "$1"
  4730. fi
  4731. main_menu