inbound.js 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197
  1. const Protocols = {
  2. VMESS: 'vmess',
  3. VLESS: 'vless',
  4. TROJAN: 'trojan',
  5. SHADOWSOCKS: 'shadowsocks',
  6. WIREGUARD: 'wireguard',
  7. HYSTERIA: 'hysteria',
  8. MIXED: 'mixed',
  9. HTTP: 'http',
  10. TUNNEL: 'tunnel',
  11. TUN: 'tun',
  12. };
  13. const SSMethods = {
  14. CHACHA20_POLY1305: 'chacha20-poly1305',
  15. CHACHA20_IETF_POLY1305: 'chacha20-ietf-poly1305',
  16. XCHACHA20_IETF_POLY1305: 'xchacha20-ietf-poly1305',
  17. BLAKE3_AES_128_GCM: '2022-blake3-aes-128-gcm',
  18. BLAKE3_AES_256_GCM: '2022-blake3-aes-256-gcm',
  19. BLAKE3_CHACHA20_POLY1305: '2022-blake3-chacha20-poly1305',
  20. };
  21. const TLS_FLOW_CONTROL = {
  22. VISION: "xtls-rprx-vision",
  23. VISION_UDP443: "xtls-rprx-vision-udp443",
  24. };
  25. const TLS_VERSION_OPTION = {
  26. TLS10: "1.0",
  27. TLS11: "1.1",
  28. TLS12: "1.2",
  29. TLS13: "1.3",
  30. };
  31. const TLS_CIPHER_OPTION = {
  32. AES_128_GCM: "TLS_AES_128_GCM_SHA256",
  33. AES_256_GCM: "TLS_AES_256_GCM_SHA384",
  34. CHACHA20_POLY1305: "TLS_CHACHA20_POLY1305_SHA256",
  35. ECDHE_ECDSA_AES_128_CBC: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
  36. ECDHE_ECDSA_AES_256_CBC: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
  37. ECDHE_RSA_AES_128_CBC: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
  38. ECDHE_RSA_AES_256_CBC: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
  39. ECDHE_ECDSA_AES_128_GCM: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
  40. ECDHE_ECDSA_AES_256_GCM: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
  41. ECDHE_RSA_AES_128_GCM: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
  42. ECDHE_RSA_AES_256_GCM: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
  43. ECDHE_ECDSA_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
  44. ECDHE_RSA_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
  45. };
  46. const UTLS_FINGERPRINT = {
  47. UTLS_CHROME: "chrome",
  48. UTLS_FIREFOX: "firefox",
  49. UTLS_SAFARI: "safari",
  50. UTLS_IOS: "ios",
  51. UTLS_android: "android",
  52. UTLS_EDGE: "edge",
  53. UTLS_360: "360",
  54. UTLS_QQ: "qq",
  55. UTLS_RANDOM: "random",
  56. UTLS_RANDOMIZED: "randomized",
  57. UTLS_RONDOMIZEDNOALPN: "randomizednoalpn",
  58. UTLS_UNSAFE: "unsafe",
  59. };
  60. const ALPN_OPTION = {
  61. H3: "h3",
  62. H2: "h2",
  63. HTTP1: "http/1.1",
  64. };
  65. const SNIFFING_OPTION = {
  66. HTTP: "http",
  67. TLS: "tls",
  68. QUIC: "quic",
  69. FAKEDNS: "fakedns"
  70. };
  71. const USAGE_OPTION = {
  72. ENCIPHERMENT: "encipherment",
  73. VERIFY: "verify",
  74. ISSUE: "issue",
  75. };
  76. const DOMAIN_STRATEGY_OPTION = {
  77. AS_IS: "AsIs",
  78. USE_IP: "UseIP",
  79. USE_IPV6V4: "UseIPv6v4",
  80. USE_IPV6: "UseIPv6",
  81. USE_IPV4V6: "UseIPv4v6",
  82. USE_IPV4: "UseIPv4",
  83. FORCE_IP: "ForceIP",
  84. FORCE_IPV6V4: "ForceIPv6v4",
  85. FORCE_IPV6: "ForceIPv6",
  86. FORCE_IPV4V6: "ForceIPv4v6",
  87. FORCE_IPV4: "ForceIPv4",
  88. };
  89. const TCP_CONGESTION_OPTION = {
  90. BBR: "bbr",
  91. CUBIC: "cubic",
  92. RENO: "reno",
  93. };
  94. const USERS_SECURITY = {
  95. AES_128_GCM: "aes-128-gcm",
  96. CHACHA20_POLY1305: "chacha20-poly1305",
  97. AUTO: "auto",
  98. NONE: "none",
  99. ZERO: "zero",
  100. };
  101. const MODE_OPTION = {
  102. AUTO: "auto",
  103. PACKET_UP: "packet-up",
  104. STREAM_UP: "stream-up",
  105. STREAM_ONE: "stream-one",
  106. };
  107. Object.freeze(Protocols);
  108. Object.freeze(SSMethods);
  109. Object.freeze(TLS_FLOW_CONTROL);
  110. Object.freeze(TLS_VERSION_OPTION);
  111. Object.freeze(TLS_CIPHER_OPTION);
  112. Object.freeze(UTLS_FINGERPRINT);
  113. Object.freeze(ALPN_OPTION);
  114. Object.freeze(SNIFFING_OPTION);
  115. Object.freeze(USAGE_OPTION);
  116. Object.freeze(DOMAIN_STRATEGY_OPTION);
  117. Object.freeze(TCP_CONGESTION_OPTION);
  118. Object.freeze(USERS_SECURITY);
  119. Object.freeze(MODE_OPTION);
  120. class XrayCommonClass {
  121. static toJsonArray(arr) {
  122. return arr.map(obj => obj.toJson());
  123. }
  124. static fromJson() {
  125. return new XrayCommonClass();
  126. }
  127. toJson() {
  128. return this;
  129. }
  130. toString(format = true) {
  131. return format ? JSON.stringify(this.toJson(), null, 2) : JSON.stringify(this.toJson());
  132. }
  133. static toHeaders(v2Headers) {
  134. let newHeaders = [];
  135. if (v2Headers) {
  136. Object.keys(v2Headers).forEach(key => {
  137. let values = v2Headers[key];
  138. if (typeof (values) === 'string') {
  139. newHeaders.push({ name: key, value: values });
  140. } else {
  141. for (let i = 0; i < values.length; ++i) {
  142. newHeaders.push({ name: key, value: values[i] });
  143. }
  144. }
  145. });
  146. }
  147. return newHeaders;
  148. }
  149. static toV2Headers(headers, arr = true) {
  150. let v2Headers = {};
  151. for (let i = 0; i < headers.length; ++i) {
  152. let name = headers[i].name;
  153. let value = headers[i].value;
  154. if (ObjectUtil.isEmpty(name) || ObjectUtil.isEmpty(value)) {
  155. continue;
  156. }
  157. if (!(name in v2Headers)) {
  158. v2Headers[name] = arr ? [value] : value;
  159. } else {
  160. if (arr) {
  161. v2Headers[name].push(value);
  162. } else {
  163. v2Headers[name] = value;
  164. }
  165. }
  166. }
  167. return v2Headers;
  168. }
  169. }
  170. class TcpStreamSettings extends XrayCommonClass {
  171. constructor(
  172. acceptProxyProtocol = false,
  173. type = 'none',
  174. request = new TcpStreamSettings.TcpRequest(),
  175. response = new TcpStreamSettings.TcpResponse(),
  176. ) {
  177. super();
  178. this.acceptProxyProtocol = acceptProxyProtocol;
  179. this.type = type;
  180. this.request = request;
  181. this.response = response;
  182. }
  183. static fromJson(json = {}) {
  184. let header = json.header;
  185. if (!header) {
  186. header = {};
  187. }
  188. return new TcpStreamSettings(json.acceptProxyProtocol,
  189. header.type,
  190. TcpStreamSettings.TcpRequest.fromJson(header.request),
  191. TcpStreamSettings.TcpResponse.fromJson(header.response),
  192. );
  193. }
  194. toJson() {
  195. return {
  196. acceptProxyProtocol: this.acceptProxyProtocol,
  197. header: {
  198. type: this.type,
  199. request: this.type === 'http' ? this.request.toJson() : undefined,
  200. response: this.type === 'http' ? this.response.toJson() : undefined,
  201. },
  202. };
  203. }
  204. }
  205. TcpStreamSettings.TcpRequest = class extends XrayCommonClass {
  206. constructor(
  207. version = '1.1',
  208. method = 'GET',
  209. path = ['/'],
  210. headers = [],
  211. ) {
  212. super();
  213. this.version = version;
  214. this.method = method;
  215. this.path = path.length === 0 ? ['/'] : path;
  216. this.headers = headers;
  217. }
  218. addPath(path) {
  219. this.path.push(path);
  220. }
  221. removePath(index) {
  222. this.path.splice(index, 1);
  223. }
  224. addHeader(name, value) {
  225. this.headers.push({ name: name, value: value });
  226. }
  227. removeHeader(index) {
  228. this.headers.splice(index, 1);
  229. }
  230. static fromJson(json = {}) {
  231. return new TcpStreamSettings.TcpRequest(
  232. json.version,
  233. json.method,
  234. json.path,
  235. XrayCommonClass.toHeaders(json.headers),
  236. );
  237. }
  238. toJson() {
  239. return {
  240. version: this.version,
  241. method: this.method,
  242. path: ObjectUtil.clone(this.path),
  243. headers: XrayCommonClass.toV2Headers(this.headers),
  244. };
  245. }
  246. };
  247. TcpStreamSettings.TcpResponse = class extends XrayCommonClass {
  248. constructor(
  249. version = '1.1',
  250. status = '200',
  251. reason = 'OK',
  252. headers = [],
  253. ) {
  254. super();
  255. this.version = version;
  256. this.status = status;
  257. this.reason = reason;
  258. this.headers = headers;
  259. }
  260. addHeader(name, value) {
  261. this.headers.push({ name: name, value: value });
  262. }
  263. removeHeader(index) {
  264. this.headers.splice(index, 1);
  265. }
  266. static fromJson(json = {}) {
  267. return new TcpStreamSettings.TcpResponse(
  268. json.version,
  269. json.status,
  270. json.reason,
  271. XrayCommonClass.toHeaders(json.headers),
  272. );
  273. }
  274. toJson() {
  275. return {
  276. version: this.version,
  277. status: this.status,
  278. reason: this.reason,
  279. headers: XrayCommonClass.toV2Headers(this.headers),
  280. };
  281. }
  282. };
  283. class KcpStreamSettings extends XrayCommonClass {
  284. constructor(
  285. mtu = 1350,
  286. tti = 20,
  287. uplinkCapacity = 5,
  288. downlinkCapacity = 20,
  289. cwndMultiplier = 1,
  290. maxSendingWindow = 2097152,
  291. ) {
  292. super();
  293. this.mtu = mtu;
  294. this.tti = tti;
  295. this.upCap = uplinkCapacity;
  296. this.downCap = downlinkCapacity;
  297. this.cwndMultiplier = cwndMultiplier;
  298. this.maxSendingWindow = maxSendingWindow;
  299. }
  300. static fromJson(json = {}) {
  301. return new KcpStreamSettings(
  302. json.mtu,
  303. json.tti,
  304. json.uplinkCapacity,
  305. json.downlinkCapacity,
  306. json.cwndMultiplier,
  307. json.maxSendingWindow,
  308. );
  309. }
  310. toJson() {
  311. return {
  312. mtu: this.mtu,
  313. tti: this.tti,
  314. uplinkCapacity: this.upCap,
  315. downlinkCapacity: this.downCap,
  316. cwndMultiplier: this.cwndMultiplier,
  317. maxSendingWindow: this.maxSendingWindow,
  318. };
  319. }
  320. }
  321. class WsStreamSettings extends XrayCommonClass {
  322. constructor(
  323. acceptProxyProtocol = false,
  324. path = '/',
  325. host = '',
  326. headers = [],
  327. heartbeatPeriod = 0,
  328. ) {
  329. super();
  330. this.acceptProxyProtocol = acceptProxyProtocol;
  331. this.path = path;
  332. this.host = host;
  333. this.headers = headers;
  334. this.heartbeatPeriod = heartbeatPeriod;
  335. }
  336. addHeader(name, value) {
  337. this.headers.push({ name: name, value: value });
  338. }
  339. removeHeader(index) {
  340. this.headers.splice(index, 1);
  341. }
  342. static fromJson(json = {}) {
  343. return new WsStreamSettings(
  344. json.acceptProxyProtocol,
  345. json.path,
  346. json.host,
  347. XrayCommonClass.toHeaders(json.headers),
  348. json.heartbeatPeriod,
  349. );
  350. }
  351. toJson() {
  352. return {
  353. acceptProxyProtocol: this.acceptProxyProtocol,
  354. path: this.path,
  355. host: this.host,
  356. headers: XrayCommonClass.toV2Headers(this.headers, false),
  357. heartbeatPeriod: this.heartbeatPeriod,
  358. };
  359. }
  360. }
  361. class GrpcStreamSettings extends XrayCommonClass {
  362. constructor(
  363. serviceName = "",
  364. authority = "",
  365. multiMode = false,
  366. ) {
  367. super();
  368. this.serviceName = serviceName;
  369. this.authority = authority;
  370. this.multiMode = multiMode;
  371. }
  372. static fromJson(json = {}) {
  373. return new GrpcStreamSettings(
  374. json.serviceName,
  375. json.authority,
  376. json.multiMode
  377. );
  378. }
  379. toJson() {
  380. return {
  381. serviceName: this.serviceName,
  382. authority: this.authority,
  383. multiMode: this.multiMode,
  384. }
  385. }
  386. }
  387. class HTTPUpgradeStreamSettings extends XrayCommonClass {
  388. constructor(
  389. acceptProxyProtocol = false,
  390. path = '/',
  391. host = '',
  392. headers = []
  393. ) {
  394. super();
  395. this.acceptProxyProtocol = acceptProxyProtocol;
  396. this.path = path;
  397. this.host = host;
  398. this.headers = headers;
  399. }
  400. addHeader(name, value) {
  401. this.headers.push({ name: name, value: value });
  402. }
  403. removeHeader(index) {
  404. this.headers.splice(index, 1);
  405. }
  406. static fromJson(json = {}) {
  407. return new HTTPUpgradeStreamSettings(
  408. json.acceptProxyProtocol,
  409. json.path,
  410. json.host,
  411. XrayCommonClass.toHeaders(json.headers),
  412. );
  413. }
  414. toJson() {
  415. return {
  416. acceptProxyProtocol: this.acceptProxyProtocol,
  417. path: this.path,
  418. host: this.host,
  419. headers: XrayCommonClass.toV2Headers(this.headers, false),
  420. };
  421. }
  422. }
  423. class xHTTPStreamSettings extends XrayCommonClass {
  424. constructor(
  425. path = '/',
  426. host = '',
  427. headers = [],
  428. scMaxBufferedPosts = 30,
  429. scMaxEachPostBytes = "1000000",
  430. scStreamUpServerSecs = "20-80",
  431. noSSEHeader = false,
  432. xPaddingBytes = "100-1000",
  433. mode = MODE_OPTION.AUTO,
  434. xPaddingObfsMode = false,
  435. xPaddingKey = '',
  436. xPaddingHeader = '',
  437. xPaddingPlacement = '',
  438. xPaddingMethod = '',
  439. uplinkHTTPMethod = '',
  440. sessionPlacement = '',
  441. sessionKey = '',
  442. seqPlacement = '',
  443. seqKey = '',
  444. uplinkDataPlacement = '',
  445. uplinkDataKey = '',
  446. uplinkChunkSize = 0,
  447. ) {
  448. super();
  449. this.path = path;
  450. this.host = host;
  451. this.headers = headers;
  452. this.scMaxBufferedPosts = scMaxBufferedPosts;
  453. this.scMaxEachPostBytes = scMaxEachPostBytes;
  454. this.scStreamUpServerSecs = scStreamUpServerSecs;
  455. this.noSSEHeader = noSSEHeader;
  456. this.xPaddingBytes = xPaddingBytes;
  457. this.mode = mode;
  458. this.xPaddingObfsMode = xPaddingObfsMode;
  459. this.xPaddingKey = xPaddingKey;
  460. this.xPaddingHeader = xPaddingHeader;
  461. this.xPaddingPlacement = xPaddingPlacement;
  462. this.xPaddingMethod = xPaddingMethod;
  463. this.uplinkHTTPMethod = uplinkHTTPMethod;
  464. this.sessionPlacement = sessionPlacement;
  465. this.sessionKey = sessionKey;
  466. this.seqPlacement = seqPlacement;
  467. this.seqKey = seqKey;
  468. this.uplinkDataPlacement = uplinkDataPlacement;
  469. this.uplinkDataKey = uplinkDataKey;
  470. this.uplinkChunkSize = uplinkChunkSize;
  471. }
  472. addHeader(name, value) {
  473. this.headers.push({ name: name, value: value });
  474. }
  475. removeHeader(index) {
  476. this.headers.splice(index, 1);
  477. }
  478. static fromJson(json = {}) {
  479. return new xHTTPStreamSettings(
  480. json.path,
  481. json.host,
  482. XrayCommonClass.toHeaders(json.headers),
  483. json.scMaxBufferedPosts,
  484. json.scMaxEachPostBytes,
  485. json.scStreamUpServerSecs,
  486. json.noSSEHeader,
  487. json.xPaddingBytes,
  488. json.mode,
  489. json.xPaddingObfsMode,
  490. json.xPaddingKey,
  491. json.xPaddingHeader,
  492. json.xPaddingPlacement,
  493. json.xPaddingMethod,
  494. json.uplinkHTTPMethod,
  495. json.sessionPlacement,
  496. json.sessionKey,
  497. json.seqPlacement,
  498. json.seqKey,
  499. json.uplinkDataPlacement,
  500. json.uplinkDataKey,
  501. json.uplinkChunkSize,
  502. );
  503. }
  504. toJson() {
  505. return {
  506. path: this.path,
  507. host: this.host,
  508. headers: XrayCommonClass.toV2Headers(this.headers, false),
  509. scMaxBufferedPosts: this.scMaxBufferedPosts,
  510. scMaxEachPostBytes: this.scMaxEachPostBytes,
  511. scStreamUpServerSecs: this.scStreamUpServerSecs,
  512. noSSEHeader: this.noSSEHeader,
  513. xPaddingBytes: this.xPaddingBytes,
  514. mode: this.mode,
  515. xPaddingObfsMode: this.xPaddingObfsMode,
  516. xPaddingKey: this.xPaddingKey,
  517. xPaddingHeader: this.xPaddingHeader,
  518. xPaddingPlacement: this.xPaddingPlacement,
  519. xPaddingMethod: this.xPaddingMethod,
  520. uplinkHTTPMethod: this.uplinkHTTPMethod,
  521. sessionPlacement: this.sessionPlacement,
  522. sessionKey: this.sessionKey,
  523. seqPlacement: this.seqPlacement,
  524. seqKey: this.seqKey,
  525. uplinkDataPlacement: this.uplinkDataPlacement,
  526. uplinkDataKey: this.uplinkDataKey,
  527. uplinkChunkSize: this.uplinkChunkSize,
  528. };
  529. }
  530. }
  531. class HysteriaStreamSettings extends XrayCommonClass {
  532. constructor(
  533. protocol,
  534. version = 2,
  535. auth = '',
  536. udpIdleTimeout = 60,
  537. masquerade,
  538. ) {
  539. super(protocol);
  540. this.version = version;
  541. this.auth = auth;
  542. this.udpIdleTimeout = udpIdleTimeout;
  543. this.masquerade = masquerade;
  544. }
  545. static fromJson(json = {}) {
  546. return new HysteriaStreamSettings(
  547. json.protocol,
  548. json.version ?? 2,
  549. json.auth ?? '',
  550. json.udpIdleTimeout ?? 60,
  551. json.masquerade ? HysteriaMasquerade.fromJson(json.masquerade) : undefined,
  552. );
  553. }
  554. toJson() {
  555. return {
  556. protocol: this.protocol,
  557. version: this.version,
  558. auth: this.auth,
  559. udpIdleTimeout: this.udpIdleTimeout,
  560. masquerade: this.masqueradeSwitch ? this.masquerade.toJson() : undefined,
  561. };
  562. }
  563. get masqueradeSwitch() {
  564. return this.masquerade != undefined;
  565. }
  566. set masqueradeSwitch(value) {
  567. this.masquerade = value ? new HysteriaMasquerade() : undefined;
  568. }
  569. };
  570. class HysteriaMasquerade extends XrayCommonClass {
  571. constructor(
  572. type = 'proxy',
  573. dir = '',
  574. url = '',
  575. rewriteHost = false,
  576. insecure = false,
  577. content = '',
  578. headers = [],
  579. statusCode = 0,
  580. ) {
  581. super();
  582. this.type = type;
  583. this.dir = dir;
  584. this.url = url;
  585. this.rewriteHost = rewriteHost;
  586. this.insecure = insecure;
  587. this.content = content;
  588. this.headers = headers;
  589. this.statusCode = statusCode;
  590. }
  591. addHeader(name, value) {
  592. this.headers.push({ name: name, value: value });
  593. }
  594. removeHeader(index) {
  595. this.headers.splice(index, 1);
  596. }
  597. static fromJson(json = {}) {
  598. return new HysteriaMasquerade(
  599. json.type,
  600. json.dir,
  601. json.url,
  602. json.rewriteHost,
  603. json.insecure,
  604. json.content,
  605. XrayCommonClass.toHeaders(json.headers),
  606. json.statusCode,
  607. );
  608. }
  609. toJson() {
  610. return {
  611. type: this.type,
  612. dir: this.dir,
  613. url: this.url,
  614. rewriteHost: this.rewriteHost,
  615. insecure: this.insecure,
  616. content: this.content,
  617. headers: XrayCommonClass.toV2Headers(this.headers, false),
  618. statusCode: this.statusCode,
  619. };
  620. }
  621. };
  622. class TlsStreamSettings extends XrayCommonClass {
  623. constructor(
  624. serverName = '',
  625. minVersion = TLS_VERSION_OPTION.TLS12,
  626. maxVersion = TLS_VERSION_OPTION.TLS13,
  627. cipherSuites = '',
  628. rejectUnknownSni = false,
  629. disableSystemRoot = false,
  630. enableSessionResumption = false,
  631. certificates = [new TlsStreamSettings.Cert()],
  632. alpn = [ALPN_OPTION.H2, ALPN_OPTION.HTTP1],
  633. echServerKeys = '',
  634. settings = new TlsStreamSettings.Settings()
  635. ) {
  636. super();
  637. this.sni = serverName;
  638. this.minVersion = minVersion;
  639. this.maxVersion = maxVersion;
  640. this.cipherSuites = cipherSuites;
  641. this.rejectUnknownSni = rejectUnknownSni;
  642. this.disableSystemRoot = disableSystemRoot;
  643. this.enableSessionResumption = enableSessionResumption;
  644. this.certs = certificates;
  645. this.alpn = alpn;
  646. this.echServerKeys = echServerKeys;
  647. this.settings = settings;
  648. }
  649. addCert() {
  650. this.certs.push(new TlsStreamSettings.Cert());
  651. }
  652. removeCert(index) {
  653. this.certs.splice(index, 1);
  654. }
  655. static fromJson(json = {}) {
  656. let certs;
  657. let settings;
  658. if (!ObjectUtil.isEmpty(json.certificates)) {
  659. certs = json.certificates.map(cert => TlsStreamSettings.Cert.fromJson(cert));
  660. }
  661. if (!ObjectUtil.isEmpty(json.settings)) {
  662. settings = new TlsStreamSettings.Settings(json.settings.fingerprint, json.settings.echConfigList);
  663. }
  664. return new TlsStreamSettings(
  665. json.serverName,
  666. json.minVersion,
  667. json.maxVersion,
  668. json.cipherSuites,
  669. json.rejectUnknownSni,
  670. json.disableSystemRoot,
  671. json.enableSessionResumption,
  672. certs,
  673. json.alpn,
  674. json.echServerKeys,
  675. settings,
  676. );
  677. }
  678. toJson() {
  679. return {
  680. serverName: this.sni,
  681. minVersion: this.minVersion,
  682. maxVersion: this.maxVersion,
  683. cipherSuites: this.cipherSuites,
  684. rejectUnknownSni: this.rejectUnknownSni,
  685. disableSystemRoot: this.disableSystemRoot,
  686. enableSessionResumption: this.enableSessionResumption,
  687. certificates: TlsStreamSettings.toJsonArray(this.certs),
  688. alpn: this.alpn,
  689. echServerKeys: this.echServerKeys,
  690. settings: this.settings,
  691. };
  692. }
  693. }
  694. TlsStreamSettings.Cert = class extends XrayCommonClass {
  695. constructor(
  696. useFile = true,
  697. certificateFile = '',
  698. keyFile = '',
  699. certificate = '',
  700. key = '',
  701. oneTimeLoading = false,
  702. usage = USAGE_OPTION.ENCIPHERMENT,
  703. buildChain = false,
  704. ) {
  705. super();
  706. this.useFile = useFile;
  707. this.certFile = certificateFile;
  708. this.keyFile = keyFile;
  709. this.cert = Array.isArray(certificate) ? certificate.join('\n') : certificate;
  710. this.key = Array.isArray(key) ? key.join('\n') : key;
  711. this.oneTimeLoading = oneTimeLoading;
  712. this.usage = usage;
  713. this.buildChain = buildChain
  714. }
  715. static fromJson(json = {}) {
  716. if ('certificateFile' in json && 'keyFile' in json) {
  717. return new TlsStreamSettings.Cert(
  718. true,
  719. json.certificateFile,
  720. json.keyFile, '', '',
  721. json.oneTimeLoading,
  722. json.usage,
  723. json.buildChain,
  724. );
  725. } else {
  726. return new TlsStreamSettings.Cert(
  727. false, '', '',
  728. json.certificate.join('\n'),
  729. json.key.join('\n'),
  730. json.oneTimeLoading,
  731. json.usage,
  732. json.buildChain,
  733. );
  734. }
  735. }
  736. toJson() {
  737. if (this.useFile) {
  738. return {
  739. certificateFile: this.certFile,
  740. keyFile: this.keyFile,
  741. oneTimeLoading: this.oneTimeLoading,
  742. usage: this.usage,
  743. buildChain: this.buildChain,
  744. };
  745. } else {
  746. return {
  747. certificate: this.cert.split('\n'),
  748. key: this.key.split('\n'),
  749. oneTimeLoading: this.oneTimeLoading,
  750. usage: this.usage,
  751. buildChain: this.buildChain,
  752. };
  753. }
  754. }
  755. };
  756. TlsStreamSettings.Settings = class extends XrayCommonClass {
  757. constructor(
  758. fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
  759. echConfigList = '',
  760. ) {
  761. super();
  762. this.fingerprint = fingerprint;
  763. this.echConfigList = echConfigList;
  764. }
  765. static fromJson(json = {}) {
  766. return new TlsStreamSettings.Settings(
  767. json.fingerprint,
  768. json.echConfigList,
  769. );
  770. }
  771. toJson() {
  772. return {
  773. fingerprint: this.fingerprint,
  774. echConfigList: this.echConfigList
  775. };
  776. }
  777. };
  778. class RealityStreamSettings extends XrayCommonClass {
  779. constructor(
  780. show = false,
  781. xver = 0,
  782. target = '',
  783. serverNames = '',
  784. privateKey = '',
  785. minClientVer = '',
  786. maxClientVer = '',
  787. maxTimediff = 0,
  788. shortIds = RandomUtil.randomShortIds(),
  789. mldsa65Seed = '',
  790. settings = new RealityStreamSettings.Settings()
  791. ) {
  792. super();
  793. // If target/serverNames are not provided, use random values
  794. if (!target && !serverNames) {
  795. const randomTarget = typeof getRandomRealityTarget !== 'undefined'
  796. ? getRandomRealityTarget()
  797. : { target: 'www.amazon.com:443', sni: 'www.amazon.com,amazon.com' };
  798. target = randomTarget.target;
  799. serverNames = randomTarget.sni;
  800. }
  801. this.show = show;
  802. this.xver = xver;
  803. this.target = target;
  804. this.serverNames = Array.isArray(serverNames) ? serverNames.join(",") : serverNames;
  805. this.privateKey = privateKey;
  806. this.minClientVer = minClientVer;
  807. this.maxClientVer = maxClientVer;
  808. this.maxTimediff = maxTimediff;
  809. this.shortIds = Array.isArray(shortIds) ? shortIds.join(",") : shortIds;
  810. this.mldsa65Seed = mldsa65Seed;
  811. this.settings = settings;
  812. }
  813. static fromJson(json = {}) {
  814. let settings;
  815. if (!ObjectUtil.isEmpty(json.settings)) {
  816. settings = new RealityStreamSettings.Settings(
  817. json.settings.publicKey,
  818. json.settings.fingerprint,
  819. json.settings.serverName,
  820. json.settings.spiderX,
  821. json.settings.mldsa65Verify,
  822. );
  823. }
  824. return new RealityStreamSettings(
  825. json.show,
  826. json.xver,
  827. json.target,
  828. json.serverNames,
  829. json.privateKey,
  830. json.minClientVer,
  831. json.maxClientVer,
  832. json.maxTimediff,
  833. json.shortIds,
  834. json.mldsa65Seed,
  835. settings,
  836. );
  837. }
  838. toJson() {
  839. return {
  840. show: this.show,
  841. xver: this.xver,
  842. target: this.target,
  843. serverNames: this.serverNames.split(","),
  844. privateKey: this.privateKey,
  845. minClientVer: this.minClientVer,
  846. maxClientVer: this.maxClientVer,
  847. maxTimediff: this.maxTimediff,
  848. shortIds: this.shortIds.split(","),
  849. mldsa65Seed: this.mldsa65Seed,
  850. settings: this.settings,
  851. };
  852. }
  853. }
  854. RealityStreamSettings.Settings = class extends XrayCommonClass {
  855. constructor(
  856. publicKey = '',
  857. fingerprint = UTLS_FINGERPRINT.UTLS_CHROME,
  858. serverName = '',
  859. spiderX = '/',
  860. mldsa65Verify = ''
  861. ) {
  862. super();
  863. this.publicKey = publicKey;
  864. this.fingerprint = fingerprint;
  865. this.serverName = serverName;
  866. this.spiderX = spiderX;
  867. this.mldsa65Verify = mldsa65Verify;
  868. }
  869. static fromJson(json = {}) {
  870. return new RealityStreamSettings.Settings(
  871. json.publicKey,
  872. json.fingerprint,
  873. json.serverName,
  874. json.spiderX,
  875. json.mldsa65Verify
  876. );
  877. }
  878. toJson() {
  879. return {
  880. publicKey: this.publicKey,
  881. fingerprint: this.fingerprint,
  882. serverName: this.serverName,
  883. spiderX: this.spiderX,
  884. mldsa65Verify: this.mldsa65Verify
  885. };
  886. }
  887. };
  888. class SockoptStreamSettings extends XrayCommonClass {
  889. constructor(
  890. acceptProxyProtocol = false,
  891. tcpFastOpen = false,
  892. mark = 0,
  893. tproxy = "off",
  894. tcpMptcp = false,
  895. penetrate = false,
  896. domainStrategy = DOMAIN_STRATEGY_OPTION.USE_IP,
  897. tcpMaxSeg = 1440,
  898. dialerProxy = "",
  899. tcpKeepAliveInterval = 0,
  900. tcpKeepAliveIdle = 300,
  901. tcpUserTimeout = 10000,
  902. tcpcongestion = TCP_CONGESTION_OPTION.BBR,
  903. V6Only = false,
  904. tcpWindowClamp = 600,
  905. interfaceName = "",
  906. trustedXForwardedFor = [],
  907. ) {
  908. super();
  909. this.acceptProxyProtocol = acceptProxyProtocol;
  910. this.tcpFastOpen = tcpFastOpen;
  911. this.mark = mark;
  912. this.tproxy = tproxy;
  913. this.tcpMptcp = tcpMptcp;
  914. this.penetrate = penetrate;
  915. this.domainStrategy = domainStrategy;
  916. this.tcpMaxSeg = tcpMaxSeg;
  917. this.dialerProxy = dialerProxy;
  918. this.tcpKeepAliveInterval = tcpKeepAliveInterval;
  919. this.tcpKeepAliveIdle = tcpKeepAliveIdle;
  920. this.tcpUserTimeout = tcpUserTimeout;
  921. this.tcpcongestion = tcpcongestion;
  922. this.V6Only = V6Only;
  923. this.tcpWindowClamp = tcpWindowClamp;
  924. this.interfaceName = interfaceName;
  925. this.trustedXForwardedFor = trustedXForwardedFor;
  926. }
  927. static fromJson(json = {}) {
  928. if (Object.keys(json).length === 0) return undefined;
  929. return new SockoptStreamSettings(
  930. json.acceptProxyProtocol,
  931. json.tcpFastOpen,
  932. json.mark,
  933. json.tproxy,
  934. json.tcpMptcp,
  935. json.penetrate,
  936. json.domainStrategy,
  937. json.tcpMaxSeg,
  938. json.dialerProxy,
  939. json.tcpKeepAliveInterval,
  940. json.tcpKeepAliveIdle,
  941. json.tcpUserTimeout,
  942. json.tcpcongestion,
  943. json.V6Only,
  944. json.tcpWindowClamp,
  945. json.interface,
  946. json.trustedXForwardedFor || [],
  947. );
  948. }
  949. toJson() {
  950. const result = {
  951. acceptProxyProtocol: this.acceptProxyProtocol,
  952. tcpFastOpen: this.tcpFastOpen,
  953. mark: this.mark,
  954. tproxy: this.tproxy,
  955. tcpMptcp: this.tcpMptcp,
  956. penetrate: this.penetrate,
  957. domainStrategy: this.domainStrategy,
  958. tcpMaxSeg: this.tcpMaxSeg,
  959. dialerProxy: this.dialerProxy,
  960. tcpKeepAliveInterval: this.tcpKeepAliveInterval,
  961. tcpKeepAliveIdle: this.tcpKeepAliveIdle,
  962. tcpUserTimeout: this.tcpUserTimeout,
  963. tcpcongestion: this.tcpcongestion,
  964. V6Only: this.V6Only,
  965. tcpWindowClamp: this.tcpWindowClamp,
  966. interface: this.interfaceName,
  967. };
  968. if (this.trustedXForwardedFor && this.trustedXForwardedFor.length > 0) {
  969. result.trustedXForwardedFor = this.trustedXForwardedFor;
  970. }
  971. return result;
  972. }
  973. }
  974. class UdpMask extends XrayCommonClass {
  975. constructor(type = 'salamander', settings = {}) {
  976. super();
  977. this.type = type;
  978. this.settings = this._getDefaultSettings(type, settings);
  979. }
  980. _getDefaultSettings(type, settings = {}) {
  981. switch (type) {
  982. case 'salamander':
  983. case 'mkcp-aes128gcm':
  984. return { password: settings.password || '' };
  985. case 'header-dns':
  986. return { domain: settings.domain || '' };
  987. case 'xdns':
  988. return { domains: Array.isArray(settings.domains) ? settings.domains : [] };
  989. case 'xicmp':
  990. return { ip: settings.ip || '', id: settings.id ?? 0 };
  991. case 'mkcp-original':
  992. case 'header-dtls':
  993. case 'header-srtp':
  994. case 'header-utp':
  995. case 'header-wechat':
  996. case 'header-wireguard':
  997. return {};
  998. case 'header-custom':
  999. return {
  1000. client: Array.isArray(settings.client) ? settings.client : [],
  1001. server: Array.isArray(settings.server) ? settings.server : [],
  1002. };
  1003. case 'noise':
  1004. return {
  1005. reset: settings.reset ?? 0,
  1006. noise: Array.isArray(settings.noise) ? settings.noise : [],
  1007. };
  1008. default:
  1009. return settings;
  1010. }
  1011. }
  1012. static fromJson(json = {}) {
  1013. return new UdpMask(
  1014. json.type || 'salamander',
  1015. json.settings || {}
  1016. );
  1017. }
  1018. toJson() {
  1019. const cleanItem = item => {
  1020. const out = { ...item };
  1021. if (out.type === 'array') {
  1022. delete out.packet;
  1023. } else {
  1024. delete out.rand;
  1025. delete out.randRange;
  1026. }
  1027. return out;
  1028. };
  1029. let settings = this.settings;
  1030. if (this.type === 'noise' && settings && Array.isArray(settings.noise)) {
  1031. settings = { ...settings, noise: settings.noise.map(cleanItem) };
  1032. } else if (this.type === 'header-custom' && settings) {
  1033. settings = {
  1034. ...settings,
  1035. client: Array.isArray(settings.client) ? settings.client.map(cleanItem) : settings.client,
  1036. server: Array.isArray(settings.server) ? settings.server.map(cleanItem) : settings.server,
  1037. };
  1038. }
  1039. return {
  1040. type: this.type,
  1041. settings: (settings && Object.keys(settings).length > 0) ? settings : undefined
  1042. };
  1043. }
  1044. }
  1045. class TcpMask extends XrayCommonClass {
  1046. constructor(type = 'fragment', settings = {}) {
  1047. super();
  1048. this.type = type;
  1049. this.settings = this._getDefaultSettings(type, settings);
  1050. }
  1051. _getDefaultSettings(type, settings = {}) {
  1052. switch (type) {
  1053. case 'fragment':
  1054. return {
  1055. packets: settings.packets ?? 'tlshello',
  1056. length: settings.length ?? '',
  1057. delay: settings.delay ?? '',
  1058. maxSplit: settings.maxSplit ?? '',
  1059. };
  1060. case 'sudoku':
  1061. return {
  1062. password: settings.password ?? '',
  1063. ascii: settings.ascii ?? '',
  1064. customTable: settings.customTable ?? '',
  1065. customTables: Array.isArray(settings.customTables) ? settings.customTables : [],
  1066. paddingMin: settings.paddingMin ?? 0,
  1067. paddingMax: settings.paddingMax ?? 0,
  1068. };
  1069. case 'header-custom':
  1070. return {
  1071. clients: Array.isArray(settings.clients) ? settings.clients : [],
  1072. servers: Array.isArray(settings.servers) ? settings.servers : [],
  1073. };
  1074. default:
  1075. return settings;
  1076. }
  1077. }
  1078. static fromJson(json = {}) {
  1079. return new TcpMask(
  1080. json.type || 'fragment',
  1081. json.settings || {}
  1082. );
  1083. }
  1084. toJson() {
  1085. const cleanItem = item => {
  1086. const out = { ...item };
  1087. if (out.type === 'array') {
  1088. delete out.packet;
  1089. } else {
  1090. delete out.rand;
  1091. delete out.randRange;
  1092. }
  1093. return out;
  1094. };
  1095. let settings = this.settings;
  1096. if (this.type === 'header-custom' && settings) {
  1097. const cleanGroup = group => Array.isArray(group) ? group.map(cleanItem) : group;
  1098. settings = {
  1099. ...settings,
  1100. clients: Array.isArray(settings.clients) ? settings.clients.map(cleanGroup) : settings.clients,
  1101. servers: Array.isArray(settings.servers) ? settings.servers.map(cleanGroup) : settings.servers,
  1102. };
  1103. }
  1104. return {
  1105. type: this.type,
  1106. settings: (settings && Object.keys(settings).length > 0) ? settings : undefined
  1107. };
  1108. }
  1109. }
  1110. class QuicParams extends XrayCommonClass {
  1111. constructor(
  1112. congestion = 'bbr',
  1113. debug = false,
  1114. brutalUp = 65537,
  1115. brutalDown = 65537,
  1116. udpHop = undefined,
  1117. initStreamReceiveWindow = 8388608,
  1118. maxStreamReceiveWindow = 8388608,
  1119. initConnectionReceiveWindow = 20971520,
  1120. maxConnectionReceiveWindow = 20971520,
  1121. maxIdleTimeout = 30,
  1122. keepAlivePeriod = 5,
  1123. disablePathMTUDiscovery = false,
  1124. maxIncomingStreams = 1024,
  1125. ) {
  1126. super();
  1127. this.congestion = congestion;
  1128. this.debug = debug;
  1129. this.brutalUp = brutalUp;
  1130. this.brutalDown = brutalDown;
  1131. this.udpHop = udpHop;
  1132. this.initStreamReceiveWindow = initStreamReceiveWindow;
  1133. this.maxStreamReceiveWindow = maxStreamReceiveWindow;
  1134. this.initConnectionReceiveWindow = initConnectionReceiveWindow;
  1135. this.maxConnectionReceiveWindow = maxConnectionReceiveWindow;
  1136. this.maxIdleTimeout = maxIdleTimeout;
  1137. this.keepAlivePeriod = keepAlivePeriod;
  1138. this.disablePathMTUDiscovery = disablePathMTUDiscovery;
  1139. this.maxIncomingStreams = maxIncomingStreams;
  1140. }
  1141. get hasUdpHop() {
  1142. return this.udpHop != null;
  1143. }
  1144. set hasUdpHop(value) {
  1145. this.udpHop = value ? (this.udpHop || { ports: '20000-50000', interval: '5-10' }) : undefined;
  1146. }
  1147. static fromJson(json = {}) {
  1148. if (!json || Object.keys(json).length === 0) return undefined;
  1149. return new QuicParams(
  1150. json.congestion,
  1151. json.debug,
  1152. json.brutalUp,
  1153. json.brutalDown,
  1154. json.udpHop ? { ports: json.udpHop.ports, interval: json.udpHop.interval } : undefined,
  1155. json.initStreamReceiveWindow,
  1156. json.maxStreamReceiveWindow,
  1157. json.initConnectionReceiveWindow,
  1158. json.maxConnectionReceiveWindow,
  1159. json.maxIdleTimeout,
  1160. json.keepAlivePeriod,
  1161. json.disablePathMTUDiscovery,
  1162. json.maxIncomingStreams,
  1163. );
  1164. }
  1165. toJson() {
  1166. const result = { congestion: this.congestion };
  1167. if (this.debug) result.debug = this.debug;
  1168. if (['brutal', 'force-brutal'].includes(this.congestion)) {
  1169. if (this.brutalUp) result.brutalUp = this.brutalUp;
  1170. if (this.brutalDown) result.brutalDown = this.brutalDown;
  1171. }
  1172. if (this.udpHop) result.udpHop = { ports: this.udpHop.ports, interval: this.udpHop.interval };
  1173. if (this.initStreamReceiveWindow > 0) result.initStreamReceiveWindow = this.initStreamReceiveWindow;
  1174. if (this.maxStreamReceiveWindow > 0) result.maxStreamReceiveWindow = this.maxStreamReceiveWindow;
  1175. if (this.initConnectionReceiveWindow > 0) result.initConnectionReceiveWindow = this.initConnectionReceiveWindow;
  1176. if (this.maxConnectionReceiveWindow > 0) result.maxConnectionReceiveWindow = this.maxConnectionReceiveWindow;
  1177. if (this.maxIdleTimeout !== 30 && this.maxIdleTimeout > 0) result.maxIdleTimeout = this.maxIdleTimeout;
  1178. if (this.keepAlivePeriod > 0) result.keepAlivePeriod = this.keepAlivePeriod;
  1179. if (this.disablePathMTUDiscovery) result.disablePathMTUDiscovery = this.disablePathMTUDiscovery;
  1180. if (this.maxIncomingStreams > 0) result.maxIncomingStreams = this.maxIncomingStreams;
  1181. return result;
  1182. }
  1183. }
  1184. class FinalMaskStreamSettings extends XrayCommonClass {
  1185. constructor(tcp = [], udp = [], quicParams = undefined) {
  1186. super();
  1187. this.tcp = Array.isArray(tcp) ? tcp.map(t => t instanceof TcpMask ? t : new TcpMask(t.type, t.settings)) : [];
  1188. this.udp = Array.isArray(udp) ? udp.map(u => new UdpMask(u.type, u.settings)) : [new UdpMask(udp.type, udp.settings)];
  1189. this.quicParams = quicParams instanceof QuicParams ? quicParams : (quicParams ? QuicParams.fromJson(quicParams) : undefined);
  1190. }
  1191. get enableQuicParams() {
  1192. return this.quicParams != null;
  1193. }
  1194. set enableQuicParams(value) {
  1195. this.quicParams = value ? (this.quicParams || new QuicParams()) : undefined;
  1196. }
  1197. static fromJson(json = {}) {
  1198. return new FinalMaskStreamSettings(
  1199. json.tcp || [],
  1200. json.udp || [],
  1201. json.quicParams ? QuicParams.fromJson(json.quicParams) : undefined,
  1202. );
  1203. }
  1204. toJson() {
  1205. const result = {};
  1206. if (this.tcp && this.tcp.length > 0) {
  1207. result.tcp = this.tcp.map(t => t.toJson());
  1208. }
  1209. if (this.udp && this.udp.length > 0) {
  1210. result.udp = this.udp.map(udp => udp.toJson());
  1211. }
  1212. if (this.quicParams) {
  1213. result.quicParams = this.quicParams.toJson();
  1214. }
  1215. return result;
  1216. }
  1217. }
  1218. class StreamSettings extends XrayCommonClass {
  1219. constructor(network = 'tcp',
  1220. security = 'none',
  1221. externalProxy = [],
  1222. tlsSettings = new TlsStreamSettings(),
  1223. realitySettings = new RealityStreamSettings(),
  1224. tcpSettings = new TcpStreamSettings(),
  1225. kcpSettings = new KcpStreamSettings(),
  1226. wsSettings = new WsStreamSettings(),
  1227. grpcSettings = new GrpcStreamSettings(),
  1228. httpupgradeSettings = new HTTPUpgradeStreamSettings(),
  1229. xhttpSettings = new xHTTPStreamSettings(),
  1230. hysteriaSettings = new HysteriaStreamSettings(),
  1231. finalmask = new FinalMaskStreamSettings(),
  1232. sockopt = undefined,
  1233. ) {
  1234. super();
  1235. this.network = network;
  1236. this.security = security;
  1237. this.externalProxy = externalProxy;
  1238. this.tls = tlsSettings;
  1239. this.reality = realitySettings;
  1240. this.tcp = tcpSettings;
  1241. this.kcp = kcpSettings;
  1242. this.ws = wsSettings;
  1243. this.grpc = grpcSettings;
  1244. this.httpupgrade = httpupgradeSettings;
  1245. this.xhttp = xhttpSettings;
  1246. this.hysteria = hysteriaSettings;
  1247. this.finalmask = finalmask;
  1248. this.sockopt = sockopt;
  1249. }
  1250. addTcpMask(type = 'fragment') {
  1251. this.finalmask.tcp.push(new TcpMask(type));
  1252. }
  1253. delTcpMask(index) {
  1254. if (this.finalmask.tcp) {
  1255. this.finalmask.tcp.splice(index, 1);
  1256. }
  1257. }
  1258. addUdpMask(type = 'salamander') {
  1259. this.finalmask.udp.push(new UdpMask(type));
  1260. }
  1261. delUdpMask(index) {
  1262. if (this.finalmask.udp) {
  1263. this.finalmask.udp.splice(index, 1);
  1264. }
  1265. }
  1266. get hasFinalMask() {
  1267. const hasTcp = this.finalmask.tcp && this.finalmask.tcp.length > 0;
  1268. const hasUdp = this.finalmask.udp && this.finalmask.udp.length > 0;
  1269. const hasQuicParams = this.finalmask.quicParams != null;
  1270. return hasTcp || hasUdp || hasQuicParams;
  1271. }
  1272. get isTls() {
  1273. return this.security === "tls";
  1274. }
  1275. set isTls(isTls) {
  1276. if (isTls) {
  1277. this.security = 'tls';
  1278. } else {
  1279. this.security = 'none';
  1280. }
  1281. }
  1282. //for Reality
  1283. get isReality() {
  1284. return this.security === "reality";
  1285. }
  1286. set isReality(isReality) {
  1287. if (isReality) {
  1288. this.security = 'reality';
  1289. } else {
  1290. this.security = 'none';
  1291. }
  1292. }
  1293. get sockoptSwitch() {
  1294. return this.sockopt != undefined;
  1295. }
  1296. set sockoptSwitch(value) {
  1297. this.sockopt = value ? new SockoptStreamSettings() : undefined;
  1298. }
  1299. static fromJson(json = {}) {
  1300. return new StreamSettings(
  1301. json.network,
  1302. json.security,
  1303. json.externalProxy,
  1304. TlsStreamSettings.fromJson(json.tlsSettings),
  1305. RealityStreamSettings.fromJson(json.realitySettings),
  1306. TcpStreamSettings.fromJson(json.tcpSettings),
  1307. KcpStreamSettings.fromJson(json.kcpSettings),
  1308. WsStreamSettings.fromJson(json.wsSettings),
  1309. GrpcStreamSettings.fromJson(json.grpcSettings),
  1310. HTTPUpgradeStreamSettings.fromJson(json.httpupgradeSettings),
  1311. xHTTPStreamSettings.fromJson(json.xhttpSettings),
  1312. HysteriaStreamSettings.fromJson(json.hysteriaSettings),
  1313. FinalMaskStreamSettings.fromJson(json.finalmask),
  1314. SockoptStreamSettings.fromJson(json.sockopt),
  1315. );
  1316. }
  1317. toJson() {
  1318. const network = this.network;
  1319. return {
  1320. network: network,
  1321. security: this.security,
  1322. externalProxy: this.externalProxy,
  1323. tlsSettings: this.isTls ? this.tls.toJson() : undefined,
  1324. realitySettings: this.isReality ? this.reality.toJson() : undefined,
  1325. tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
  1326. kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
  1327. wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
  1328. grpcSettings: network === 'grpc' ? this.grpc.toJson() : undefined,
  1329. httpupgradeSettings: network === 'httpupgrade' ? this.httpupgrade.toJson() : undefined,
  1330. xhttpSettings: network === 'xhttp' ? this.xhttp.toJson() : undefined,
  1331. hysteriaSettings: network === 'hysteria' ? this.hysteria.toJson() : undefined,
  1332. finalmask: this.hasFinalMask ? this.finalmask.toJson() : undefined,
  1333. sockopt: this.sockopt != undefined ? this.sockopt.toJson() : undefined,
  1334. };
  1335. }
  1336. }
  1337. class Sniffing extends XrayCommonClass {
  1338. constructor(
  1339. enabled = false,
  1340. destOverride = ['http', 'tls', 'quic', 'fakedns'],
  1341. metadataOnly = false,
  1342. routeOnly = false,
  1343. ipsExcluded = [],
  1344. domainsExcluded = []) {
  1345. super();
  1346. this.enabled = enabled;
  1347. this.destOverride = Array.isArray(destOverride) && destOverride.length > 0 ? destOverride : ['http', 'tls', 'quic', 'fakedns'];
  1348. this.metadataOnly = metadataOnly;
  1349. this.routeOnly = routeOnly;
  1350. this.ipsExcluded = Array.isArray(ipsExcluded) ? ipsExcluded : [];
  1351. this.domainsExcluded = Array.isArray(domainsExcluded) ? domainsExcluded : [];
  1352. }
  1353. static fromJson(json = {}) {
  1354. let destOverride = ObjectUtil.clone(json.destOverride);
  1355. if (ObjectUtil.isEmpty(destOverride) || ObjectUtil.isArrEmpty(destOverride) || ObjectUtil.isEmpty(destOverride[0])) {
  1356. destOverride = ['http', 'tls', 'quic', 'fakedns'];
  1357. }
  1358. return new Sniffing(
  1359. !!json.enabled,
  1360. destOverride,
  1361. json.metadataOnly,
  1362. json.routeOnly,
  1363. json.ipsExcluded || [],
  1364. json.domainsExcluded || [],
  1365. );
  1366. }
  1367. toJson() {
  1368. return {
  1369. enabled: this.enabled,
  1370. destOverride: this.destOverride,
  1371. metadataOnly: this.metadataOnly,
  1372. routeOnly: this.routeOnly,
  1373. ipsExcluded: this.ipsExcluded.length > 0 ? this.ipsExcluded : undefined,
  1374. domainsExcluded: this.domainsExcluded.length > 0 ? this.domainsExcluded : undefined,
  1375. };
  1376. }
  1377. }
  1378. class Inbound extends XrayCommonClass {
  1379. constructor(
  1380. port = RandomUtil.randomInteger(10000, 60000),
  1381. listen = '',
  1382. protocol = Protocols.VLESS,
  1383. settings = null,
  1384. streamSettings = new StreamSettings(),
  1385. tag = '',
  1386. sniffing = new Sniffing(),
  1387. clientStats = '',
  1388. ) {
  1389. super();
  1390. this.port = port;
  1391. this.listen = listen;
  1392. this._protocol = protocol;
  1393. this.settings = ObjectUtil.isEmpty(settings) ? Inbound.Settings.getSettings(protocol) : settings;
  1394. this.stream = streamSettings;
  1395. this.tag = tag;
  1396. this.sniffing = sniffing;
  1397. this.clientStats = clientStats;
  1398. }
  1399. getClientStats() {
  1400. return this.clientStats;
  1401. }
  1402. // Copy the xPadding* settings into the query-string of a vless/trojan/ss
  1403. // link. Without this, the admin's custom xPaddingBytes range and (in
  1404. // obfs mode) the custom xPaddingKey / xPaddingHeader / placement /
  1405. // method never reach the client — the client keeps xray / sing-box's
  1406. // internal defaults and the server rejects every handshake with
  1407. // `invalid padding (...) length: 0`.
  1408. //
  1409. // Two encodings are emitted so each client family can pick at least
  1410. // one up:
  1411. // - x_padding_bytes=<range> flat, for sing-box-family clients
  1412. // - extra=<url-encoded-json> full blob, for xray-core clients
  1413. //
  1414. // Fields are only included when they actually have a value, so a
  1415. // default inbound yields the same URL it did before this helper.
  1416. static applyXhttpPaddingToParams(xhttp, params) {
  1417. if (!xhttp) return;
  1418. if (typeof xhttp.xPaddingBytes === 'string' && xhttp.xPaddingBytes.length > 0) {
  1419. params.set("x_padding_bytes", xhttp.xPaddingBytes);
  1420. }
  1421. const extra = {};
  1422. if (typeof xhttp.xPaddingBytes === 'string' && xhttp.xPaddingBytes.length > 0) {
  1423. extra.xPaddingBytes = xhttp.xPaddingBytes;
  1424. }
  1425. if (xhttp.xPaddingObfsMode === true) {
  1426. extra.xPaddingObfsMode = true;
  1427. ["xPaddingKey", "xPaddingHeader", "xPaddingPlacement", "xPaddingMethod"].forEach(k => {
  1428. if (typeof xhttp[k] === 'string' && xhttp[k].length > 0) {
  1429. extra[k] = xhttp[k];
  1430. }
  1431. });
  1432. }
  1433. if (Object.keys(extra).length > 0) {
  1434. params.set("extra", JSON.stringify(extra));
  1435. }
  1436. }
  1437. // VMess variant: VMess links are a base64-encoded JSON object, so we
  1438. // copy the padding fields directly into the JSON instead of building
  1439. // a query string.
  1440. static applyXhttpPaddingToObj(xhttp, obj) {
  1441. if (!xhttp || !obj) return;
  1442. if (typeof xhttp.xPaddingBytes === 'string' && xhttp.xPaddingBytes.length > 0) {
  1443. obj.x_padding_bytes = xhttp.xPaddingBytes;
  1444. }
  1445. if (xhttp.xPaddingObfsMode === true) {
  1446. obj.xPaddingObfsMode = true;
  1447. ["xPaddingKey", "xPaddingHeader", "xPaddingPlacement", "xPaddingMethod"].forEach(k => {
  1448. if (typeof xhttp[k] === 'string' && xhttp[k].length > 0) {
  1449. obj[k] = xhttp[k];
  1450. }
  1451. });
  1452. }
  1453. }
  1454. static hasShareableFinalMaskValue(value) {
  1455. if (value == null) {
  1456. return false;
  1457. }
  1458. if (Array.isArray(value)) {
  1459. return value.some(item => Inbound.hasShareableFinalMaskValue(item));
  1460. }
  1461. if (typeof value === 'object') {
  1462. return Object.values(value).some(item => Inbound.hasShareableFinalMaskValue(item));
  1463. }
  1464. if (typeof value === 'string') {
  1465. return value.length > 0;
  1466. }
  1467. return true;
  1468. }
  1469. static serializeFinalMask(finalmask) {
  1470. if (!finalmask) {
  1471. return '';
  1472. }
  1473. const value = typeof finalmask.toJson === 'function' ? finalmask.toJson() : finalmask;
  1474. return Inbound.hasShareableFinalMaskValue(value) ? JSON.stringify(value) : '';
  1475. }
  1476. // Export finalmask with the same compact JSON payload shape that
  1477. // v2rayN-compatible share links use: fm=<json>.
  1478. static applyFinalMaskToParams(finalmask, params) {
  1479. if (!params) return;
  1480. const payload = Inbound.serializeFinalMask(finalmask);
  1481. if (payload.length > 0) {
  1482. params.set("fm", payload);
  1483. }
  1484. }
  1485. // VMess links are a base64 JSON object, so keep the same fm payload
  1486. // under a flat property instead of a URL query string.
  1487. static applyFinalMaskToObj(finalmask, obj) {
  1488. if (!obj) return;
  1489. const payload = Inbound.serializeFinalMask(finalmask);
  1490. if (payload.length > 0) {
  1491. obj.fm = payload;
  1492. }
  1493. }
  1494. get clients() {
  1495. switch (this.protocol) {
  1496. case Protocols.VMESS: return this.settings.vmesses;
  1497. case Protocols.VLESS: return this.settings.vlesses;
  1498. case Protocols.TROJAN: return this.settings.trojans;
  1499. case Protocols.SHADOWSOCKS: return this.isSSMultiUser ? this.settings.shadowsockses : null;
  1500. case Protocols.HYSTERIA: return this.settings.hysterias;
  1501. default: return null;
  1502. }
  1503. }
  1504. get protocol() {
  1505. return this._protocol;
  1506. }
  1507. set protocol(protocol) {
  1508. this._protocol = protocol;
  1509. this.settings = Inbound.Settings.getSettings(protocol);
  1510. this.stream = new StreamSettings();
  1511. if (protocol === Protocols.TROJAN) {
  1512. this.tls = false;
  1513. }
  1514. if (protocol === Protocols.HYSTERIA) {
  1515. this.stream.network = 'hysteria';
  1516. this.stream.security = 'tls';
  1517. // Hysteria runs over QUIC and must not inherit TCP TLS ALPN defaults.
  1518. this.stream.tls.alpn = [ALPN_OPTION.H3];
  1519. }
  1520. }
  1521. get network() {
  1522. return this.stream.network;
  1523. }
  1524. set network(network) {
  1525. this.stream.network = network;
  1526. }
  1527. get isTcp() {
  1528. return this.network === "tcp";
  1529. }
  1530. get isWs() {
  1531. return this.network === "ws";
  1532. }
  1533. get isKcp() {
  1534. return this.network === "kcp";
  1535. }
  1536. get isGrpc() {
  1537. return this.network === "grpc";
  1538. }
  1539. get isHttpupgrade() {
  1540. return this.network === "httpupgrade";
  1541. }
  1542. get isXHTTP() {
  1543. return this.network === "xhttp";
  1544. }
  1545. // Shadowsocks
  1546. get method() {
  1547. switch (this.protocol) {
  1548. case Protocols.SHADOWSOCKS:
  1549. return this.settings.method;
  1550. default:
  1551. return "";
  1552. }
  1553. }
  1554. get isSSMultiUser() {
  1555. return this.method != SSMethods.BLAKE3_CHACHA20_POLY1305;
  1556. }
  1557. get isSS2022() {
  1558. return this.method.substring(0, 4) === "2022";
  1559. }
  1560. get serverName() {
  1561. if (this.stream.isTls) return this.stream.tls.sni;
  1562. if (this.stream.isReality) return this.stream.reality.serverNames;
  1563. return "";
  1564. }
  1565. getHeader(obj, name) {
  1566. for (const header of obj.headers) {
  1567. if (header.name.toLowerCase() === name.toLowerCase()) {
  1568. return header.value;
  1569. }
  1570. }
  1571. return "";
  1572. }
  1573. get host() {
  1574. if (this.isTcp) {
  1575. return this.getHeader(this.stream.tcp.request, 'host');
  1576. } else if (this.isWs) {
  1577. return this.stream.ws.host?.length > 0 ? this.stream.ws.host : this.getHeader(this.stream.ws, 'host');
  1578. } else if (this.isHttpupgrade) {
  1579. return this.stream.httpupgrade.host?.length > 0 ? this.stream.httpupgrade.host : this.getHeader(this.stream.httpupgrade, 'host');
  1580. } else if (this.isXHTTP) {
  1581. return this.stream.xhttp.host?.length > 0 ? this.stream.xhttp.host : this.getHeader(this.stream.xhttp, 'host');
  1582. }
  1583. return null;
  1584. }
  1585. get path() {
  1586. if (this.isTcp) {
  1587. return this.stream.tcp.request.path[0];
  1588. } else if (this.isWs) {
  1589. return this.stream.ws.path;
  1590. } else if (this.isHttpupgrade) {
  1591. return this.stream.httpupgrade.path;
  1592. } else if (this.isXHTTP) {
  1593. return this.stream.xhttp.path;
  1594. }
  1595. return null;
  1596. }
  1597. get serviceName() {
  1598. return this.stream.grpc.serviceName;
  1599. }
  1600. isExpiry(index) {
  1601. let exp = this.clients[index].expiryTime;
  1602. return exp > 0 ? exp < new Date().getTime() : false;
  1603. }
  1604. canEnableTls() {
  1605. if (this.protocol === Protocols.HYSTERIA) return true;
  1606. if (![Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS].includes(this.protocol)) return false;
  1607. return ["tcp", "ws", "http", "grpc", "httpupgrade", "xhttp"].includes(this.network);
  1608. }
  1609. //this is used for xtls-rprx-vision
  1610. canEnableTlsFlow() {
  1611. if (((this.stream.security === 'tls') || (this.stream.security === 'reality')) && (this.network === "tcp")) {
  1612. return this.protocol === Protocols.VLESS;
  1613. }
  1614. return false;
  1615. }
  1616. // Vision seed applies only when the XTLS Vision (TCP/TLS) flow is selected.
  1617. // Excludes the UDP variant per spec.
  1618. canEnableVisionSeed() {
  1619. if (!this.canEnableTlsFlow()) return false;
  1620. const clients = this.settings?.vlesses;
  1621. if (!Array.isArray(clients)) return false;
  1622. return clients.some(c => c?.flow === TLS_FLOW_CONTROL.VISION);
  1623. }
  1624. canEnableReality() {
  1625. if (![Protocols.VLESS, Protocols.TROJAN].includes(this.protocol)) return false;
  1626. return ["tcp", "http", "grpc", "xhttp"].includes(this.network);
  1627. }
  1628. canEnableStream() {
  1629. return [Protocols.VMESS, Protocols.VLESS, Protocols.TROJAN, Protocols.SHADOWSOCKS, Protocols.HYSTERIA].includes(this.protocol);
  1630. }
  1631. reset() {
  1632. this.port = RandomUtil.randomInteger(10000, 60000);
  1633. this.listen = '';
  1634. this.protocol = Protocols.VMESS;
  1635. this.settings = Inbound.Settings.getSettings(Protocols.VMESS);
  1636. this.stream = new StreamSettings();
  1637. this.tag = '';
  1638. this.sniffing = new Sniffing();
  1639. }
  1640. genVmessLink(address = '', port = this.port, forceTls, remark = '', clientId, security) {
  1641. if (this.protocol !== Protocols.VMESS) {
  1642. return '';
  1643. }
  1644. const tls = forceTls == 'same' ? this.stream.security : forceTls;
  1645. let obj = {
  1646. v: '2',
  1647. ps: remark,
  1648. add: address,
  1649. port: port,
  1650. id: clientId,
  1651. scy: security,
  1652. net: this.stream.network,
  1653. tls: tls,
  1654. };
  1655. const network = this.stream.network;
  1656. if (network === 'tcp') {
  1657. const tcp = this.stream.tcp;
  1658. obj.type = tcp.type;
  1659. if (tcp.type === 'http') {
  1660. const request = tcp.request;
  1661. obj.path = request.path.join(',');
  1662. const host = this.getHeader(request, 'host');
  1663. if (host) obj.host = host;
  1664. }
  1665. } else if (network === 'kcp') {
  1666. const kcp = this.stream.kcp;
  1667. obj.mtu = kcp.mtu;
  1668. obj.tti = kcp.tti;
  1669. } else if (network === 'ws') {
  1670. const ws = this.stream.ws;
  1671. obj.path = ws.path;
  1672. obj.host = ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host');
  1673. } else if (network === 'grpc') {
  1674. obj.path = this.stream.grpc.serviceName;
  1675. obj.authority = this.stream.grpc.authority;
  1676. if (this.stream.grpc.multiMode) {
  1677. obj.type = 'multi'
  1678. }
  1679. } else if (network === 'httpupgrade') {
  1680. const httpupgrade = this.stream.httpupgrade;
  1681. obj.path = httpupgrade.path;
  1682. obj.host = httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host');
  1683. } else if (network === 'xhttp') {
  1684. const xhttp = this.stream.xhttp;
  1685. obj.path = xhttp.path;
  1686. obj.host = xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host');
  1687. obj.type = xhttp.mode;
  1688. Inbound.applyXhttpPaddingToObj(xhttp, obj);
  1689. }
  1690. Inbound.applyFinalMaskToObj(this.stream.finalmask, obj);
  1691. if (tls === 'tls') {
  1692. if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
  1693. obj.sni = this.stream.tls.sni;
  1694. }
  1695. if (!ObjectUtil.isEmpty(this.stream.tls.settings.fingerprint)) {
  1696. obj.fp = this.stream.tls.settings.fingerprint;
  1697. }
  1698. if (this.stream.tls.alpn.length > 0) {
  1699. obj.alpn = this.stream.tls.alpn.join(',');
  1700. }
  1701. }
  1702. return 'vmess://' + Base64.encode(JSON.stringify(obj, null, 2));
  1703. }
  1704. genVLESSLink(address = '', port = this.port, forceTls, remark = '', clientId, flow) {
  1705. const uuid = clientId;
  1706. const type = this.stream.network;
  1707. const security = forceTls == 'same' ? this.stream.security : forceTls;
  1708. const params = new Map();
  1709. params.set("type", this.stream.network);
  1710. params.set("encryption", this.settings.encryption);
  1711. switch (type) {
  1712. case "tcp":
  1713. const tcp = this.stream.tcp;
  1714. if (tcp.type === 'http') {
  1715. const request = tcp.request;
  1716. params.set("path", request.path.join(','));
  1717. const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
  1718. if (index >= 0) {
  1719. const host = request.headers[index].value;
  1720. params.set("host", host);
  1721. }
  1722. params.set("headerType", 'http');
  1723. }
  1724. break;
  1725. case "kcp":
  1726. const kcp = this.stream.kcp;
  1727. params.set("mtu", kcp.mtu);
  1728. params.set("tti", kcp.tti);
  1729. break;
  1730. case "ws":
  1731. const ws = this.stream.ws;
  1732. params.set("path", ws.path);
  1733. params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'));
  1734. break;
  1735. case "grpc":
  1736. const grpc = this.stream.grpc;
  1737. params.set("serviceName", grpc.serviceName);
  1738. params.set("authority", grpc.authority);
  1739. if (grpc.multiMode) {
  1740. params.set("mode", "multi");
  1741. }
  1742. break;
  1743. case "httpupgrade":
  1744. const httpupgrade = this.stream.httpupgrade;
  1745. params.set("path", httpupgrade.path);
  1746. params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
  1747. break;
  1748. case "xhttp":
  1749. const xhttp = this.stream.xhttp;
  1750. params.set("path", xhttp.path);
  1751. params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
  1752. params.set("mode", xhttp.mode);
  1753. Inbound.applyXhttpPaddingToParams(xhttp, params);
  1754. break;
  1755. }
  1756. Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
  1757. if (security === 'tls') {
  1758. params.set("security", "tls");
  1759. if (this.stream.isTls) {
  1760. params.set("fp", this.stream.tls.settings.fingerprint);
  1761. params.set("alpn", this.stream.tls.alpn);
  1762. if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
  1763. params.set("sni", this.stream.tls.sni);
  1764. }
  1765. if (this.stream.tls.settings.echConfigList?.length > 0) {
  1766. params.set("ech", this.stream.tls.settings.echConfigList);
  1767. }
  1768. if (type == "tcp" && !ObjectUtil.isEmpty(flow)) {
  1769. params.set("flow", flow);
  1770. }
  1771. }
  1772. }
  1773. else if (security === 'reality') {
  1774. params.set("security", "reality");
  1775. params.set("pbk", this.stream.reality.settings.publicKey);
  1776. params.set("fp", this.stream.reality.settings.fingerprint);
  1777. if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) {
  1778. params.set("sni", this.stream.reality.serverNames.split(",")[0]);
  1779. }
  1780. if (this.stream.reality.shortIds.length > 0) {
  1781. params.set("sid", this.stream.reality.shortIds.split(",")[0]);
  1782. }
  1783. if (!ObjectUtil.isEmpty(this.stream.reality.settings.spiderX)) {
  1784. params.set("spx", this.stream.reality.settings.spiderX);
  1785. }
  1786. if (!ObjectUtil.isEmpty(this.stream.reality.settings.mldsa65Verify)) {
  1787. params.set("pqv", this.stream.reality.settings.mldsa65Verify);
  1788. }
  1789. if (type == 'tcp' && !ObjectUtil.isEmpty(flow)) {
  1790. params.set("flow", flow);
  1791. }
  1792. }
  1793. else {
  1794. params.set("security", "none");
  1795. }
  1796. const link = `vless://${uuid}@${address}:${port}`;
  1797. const url = new URL(link);
  1798. for (const [key, value] of params) {
  1799. url.searchParams.set(key, value)
  1800. }
  1801. url.hash = encodeURIComponent(remark);
  1802. return url.toString();
  1803. }
  1804. genSSLink(address = '', port = this.port, forceTls, remark = '', clientPassword) {
  1805. let settings = this.settings;
  1806. const type = this.stream.network;
  1807. const security = forceTls == 'same' ? this.stream.security : forceTls;
  1808. const params = new Map();
  1809. params.set("type", this.stream.network);
  1810. switch (type) {
  1811. case "tcp":
  1812. const tcp = this.stream.tcp;
  1813. if (tcp.type === 'http') {
  1814. const request = tcp.request;
  1815. params.set("path", request.path.join(','));
  1816. const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
  1817. if (index >= 0) {
  1818. const host = request.headers[index].value;
  1819. params.set("host", host);
  1820. }
  1821. params.set("headerType", 'http');
  1822. }
  1823. break;
  1824. case "kcp":
  1825. const kcp = this.stream.kcp;
  1826. params.set("mtu", kcp.mtu);
  1827. params.set("tti", kcp.tti);
  1828. break;
  1829. case "ws":
  1830. const ws = this.stream.ws;
  1831. params.set("path", ws.path);
  1832. params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'));
  1833. break;
  1834. case "grpc":
  1835. const grpc = this.stream.grpc;
  1836. params.set("serviceName", grpc.serviceName);
  1837. params.set("authority", grpc.authority);
  1838. if (grpc.multiMode) {
  1839. params.set("mode", "multi");
  1840. }
  1841. break;
  1842. case "httpupgrade":
  1843. const httpupgrade = this.stream.httpupgrade;
  1844. params.set("path", httpupgrade.path);
  1845. params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
  1846. break;
  1847. case "xhttp":
  1848. const xhttp = this.stream.xhttp;
  1849. params.set("path", xhttp.path);
  1850. params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
  1851. params.set("mode", xhttp.mode);
  1852. Inbound.applyXhttpPaddingToParams(xhttp, params);
  1853. break;
  1854. }
  1855. Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
  1856. if (security === 'tls') {
  1857. params.set("security", "tls");
  1858. if (this.stream.isTls) {
  1859. params.set("fp", this.stream.tls.settings.fingerprint);
  1860. params.set("alpn", this.stream.tls.alpn);
  1861. if (this.stream.tls.settings.echConfigList?.length > 0) {
  1862. params.set("ech", this.stream.tls.settings.echConfigList);
  1863. }
  1864. if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
  1865. params.set("sni", this.stream.tls.sni);
  1866. }
  1867. }
  1868. }
  1869. let password = new Array();
  1870. if (this.isSS2022) password.push(settings.password);
  1871. if (this.isSSMultiUser) password.push(clientPassword);
  1872. let link = `ss://${Base64.encode(`${settings.method}:${password.join(':')}`, true)}@${address}:${port}`;
  1873. const url = new URL(link);
  1874. for (const [key, value] of params) {
  1875. url.searchParams.set(key, value)
  1876. }
  1877. url.hash = encodeURIComponent(remark);
  1878. return url.toString();
  1879. }
  1880. genTrojanLink(address = '', port = this.port, forceTls, remark = '', clientPassword) {
  1881. const security = forceTls == 'same' ? this.stream.security : forceTls;
  1882. const type = this.stream.network;
  1883. const params = new Map();
  1884. params.set("type", this.stream.network);
  1885. switch (type) {
  1886. case "tcp":
  1887. const tcp = this.stream.tcp;
  1888. if (tcp.type === 'http') {
  1889. const request = tcp.request;
  1890. params.set("path", request.path.join(','));
  1891. const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
  1892. if (index >= 0) {
  1893. const host = request.headers[index].value;
  1894. params.set("host", host);
  1895. }
  1896. params.set("headerType", 'http');
  1897. }
  1898. break;
  1899. case "kcp":
  1900. const kcp = this.stream.kcp;
  1901. params.set("mtu", kcp.mtu);
  1902. params.set("tti", kcp.tti);
  1903. break;
  1904. case "ws":
  1905. const ws = this.stream.ws;
  1906. params.set("path", ws.path);
  1907. params.set("host", ws.host?.length > 0 ? ws.host : this.getHeader(ws, 'host'));
  1908. break;
  1909. case "grpc":
  1910. const grpc = this.stream.grpc;
  1911. params.set("serviceName", grpc.serviceName);
  1912. params.set("authority", grpc.authority);
  1913. if (grpc.multiMode) {
  1914. params.set("mode", "multi");
  1915. }
  1916. break;
  1917. case "httpupgrade":
  1918. const httpupgrade = this.stream.httpupgrade;
  1919. params.set("path", httpupgrade.path);
  1920. params.set("host", httpupgrade.host?.length > 0 ? httpupgrade.host : this.getHeader(httpupgrade, 'host'));
  1921. break;
  1922. case "xhttp":
  1923. const xhttp = this.stream.xhttp;
  1924. params.set("path", xhttp.path);
  1925. params.set("host", xhttp.host?.length > 0 ? xhttp.host : this.getHeader(xhttp, 'host'));
  1926. params.set("mode", xhttp.mode);
  1927. Inbound.applyXhttpPaddingToParams(xhttp, params);
  1928. break;
  1929. }
  1930. Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
  1931. if (security === 'tls') {
  1932. params.set("security", "tls");
  1933. if (this.stream.isTls) {
  1934. params.set("fp", this.stream.tls.settings.fingerprint);
  1935. params.set("alpn", this.stream.tls.alpn);
  1936. if (this.stream.tls.settings.echConfigList?.length > 0) {
  1937. params.set("ech", this.stream.tls.settings.echConfigList);
  1938. }
  1939. if (!ObjectUtil.isEmpty(this.stream.tls.sni)) {
  1940. params.set("sni", this.stream.tls.sni);
  1941. }
  1942. }
  1943. }
  1944. else if (security === 'reality') {
  1945. params.set("security", "reality");
  1946. params.set("pbk", this.stream.reality.settings.publicKey);
  1947. params.set("fp", this.stream.reality.settings.fingerprint);
  1948. if (!ObjectUtil.isArrEmpty(this.stream.reality.serverNames)) {
  1949. params.set("sni", this.stream.reality.serverNames.split(",")[0]);
  1950. }
  1951. if (this.stream.reality.shortIds.length > 0) {
  1952. params.set("sid", this.stream.reality.shortIds.split(",")[0]);
  1953. }
  1954. if (!ObjectUtil.isEmpty(this.stream.reality.settings.spiderX)) {
  1955. params.set("spx", this.stream.reality.settings.spiderX);
  1956. }
  1957. if (!ObjectUtil.isEmpty(this.stream.reality.settings.mldsa65Verify)) {
  1958. params.set("pqv", this.stream.reality.settings.mldsa65Verify);
  1959. }
  1960. }
  1961. else {
  1962. params.set("security", "none");
  1963. }
  1964. const link = `trojan://${clientPassword}@${address}:${port}`;
  1965. const url = new URL(link);
  1966. for (const [key, value] of params) {
  1967. url.searchParams.set(key, value)
  1968. }
  1969. url.hash = encodeURIComponent(remark);
  1970. return url.toString();
  1971. }
  1972. genHysteriaLink(address = '', port = this.port, remark = '', clientAuth) {
  1973. const protocol = this.settings.version == 2 ? "hysteria2" : "hysteria";
  1974. const link = `${protocol}://${clientAuth}@${address}:${port}`;
  1975. const params = new Map();
  1976. params.set("security", "tls");
  1977. if (this.stream.tls.settings.fingerprint?.length > 0) params.set("fp", this.stream.tls.settings.fingerprint);
  1978. if (this.stream.tls.alpn?.length > 0) params.set("alpn", this.stream.tls.alpn);
  1979. if (this.stream.tls.settings.allowInsecure) params.set("insecure", "1");
  1980. if (this.stream.tls.settings.echConfigList?.length > 0) params.set("ech", this.stream.tls.settings.echConfigList);
  1981. if (this.stream.tls.sni?.length > 0) params.set("sni", this.stream.tls.sni);
  1982. const udpMasks = this.stream?.finalmask?.udp;
  1983. if (Array.isArray(udpMasks)) {
  1984. const salamanderMask = udpMasks.find(mask => mask?.type === 'salamander');
  1985. const obfsPassword = salamanderMask?.settings?.password;
  1986. if (typeof obfsPassword === 'string' && obfsPassword.length > 0) {
  1987. params.set("obfs", "salamander");
  1988. params.set("obfs-password", obfsPassword);
  1989. }
  1990. }
  1991. Inbound.applyFinalMaskToParams(this.stream.finalmask, params);
  1992. const url = new URL(link);
  1993. for (const [key, value] of params) {
  1994. url.searchParams.set(key, value);
  1995. }
  1996. url.hash = encodeURIComponent(remark);
  1997. return url.toString();
  1998. }
  1999. getWireguardTxt(address, port, remark, peerId) {
  2000. let txt = `[Interface]\n`
  2001. txt += `PrivateKey = ${this.settings.peers[peerId].privateKey}\n`
  2002. txt += `Address = ${this.settings.peers[peerId].allowedIPs[0]}\n`
  2003. txt += `DNS = 1.1.1.1, 1.0.0.1\n`
  2004. if (this.settings.mtu) {
  2005. txt += `MTU = ${this.settings.mtu}\n`
  2006. }
  2007. txt += `\n# ${remark}\n`
  2008. txt += `[Peer]\n`
  2009. txt += `PublicKey = ${this.settings.pubKey}\n`
  2010. txt += `AllowedIPs = 0.0.0.0/0, ::/0\n`
  2011. txt += `Endpoint = ${address}:${port}`
  2012. if (this.settings.peers[peerId].psk) {
  2013. txt += `\nPresharedKey = ${this.settings.peers[peerId].psk}`
  2014. }
  2015. if (this.settings.peers[peerId].keepAlive) {
  2016. txt += `\nPersistentKeepalive = ${this.settings.peers[peerId].keepAlive}\n`
  2017. }
  2018. return txt;
  2019. }
  2020. getWireguardLink(address, port, remark, peerId) {
  2021. const peer = this.settings?.peers?.[peerId];
  2022. if (!peer) return '';
  2023. const link = `wireguard://${address}:${port}`;
  2024. const url = new URL(link);
  2025. url.username = peer.privateKey || '';
  2026. if (this.settings?.pubKey) {
  2027. url.searchParams.set("publickey", this.settings.pubKey);
  2028. }
  2029. if (Array.isArray(peer.allowedIPs) && peer.allowedIPs.length > 0 && peer.allowedIPs[0]) {
  2030. url.searchParams.set("address", peer.allowedIPs[0]);
  2031. }
  2032. if (this.settings?.mtu) {
  2033. url.searchParams.set("mtu", this.settings.mtu);
  2034. }
  2035. url.hash = encodeURIComponent(remark);
  2036. return url.toString();
  2037. }
  2038. genWireguardLinks(remark = '', remarkModel = '-ieo') {
  2039. const addr = !ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0" ? this.listen : location.hostname;
  2040. const separationChar = remarkModel.charAt(0);
  2041. let links = [];
  2042. this.settings.peers.forEach((p, index) => {
  2043. links.push(this.getWireguardLink(addr, this.port, remark + separationChar + (index + 1), index));
  2044. });
  2045. return links.join('\r\n');
  2046. }
  2047. genWireguardConfigs(remark = '', remarkModel = '-ieo') {
  2048. const addr = !ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0" ? this.listen : location.hostname;
  2049. const separationChar = remarkModel.charAt(0);
  2050. let links = [];
  2051. this.settings.peers.forEach((p, index) => {
  2052. links.push(this.getWireguardTxt(addr, this.port, remark + separationChar + (index + 1), index));
  2053. });
  2054. return links.join('\r\n');
  2055. }
  2056. genLink(address = '', port = this.port, forceTls = 'same', remark = '', client) {
  2057. switch (this.protocol) {
  2058. case Protocols.VMESS:
  2059. return this.genVmessLink(address, port, forceTls, remark, client.id, client.security);
  2060. case Protocols.VLESS:
  2061. return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow);
  2062. case Protocols.SHADOWSOCKS:
  2063. return this.genSSLink(address, port, forceTls, remark, this.isSSMultiUser ? client.password : '');
  2064. case Protocols.TROJAN:
  2065. return this.genTrojanLink(address, port, forceTls, remark, client.password);
  2066. case Protocols.HYSTERIA:
  2067. return this.genHysteriaLink(address, port, remark, client.auth.length > 0 ? client.auth : this.stream.hysteria.auth);
  2068. default: return '';
  2069. }
  2070. }
  2071. genAllLinks(remark = '', remarkModel = '-ieo', client) {
  2072. let result = [];
  2073. let email = client ? client.email : '';
  2074. let addr = !ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0" ? this.listen : location.hostname;
  2075. let port = this.port;
  2076. const separationChar = remarkModel.charAt(0);
  2077. const orderChars = remarkModel.slice(1);
  2078. let orders = {
  2079. 'i': remark,
  2080. 'e': email,
  2081. 'o': '',
  2082. };
  2083. if (ObjectUtil.isArrEmpty(this.stream.externalProxy)) {
  2084. let r = orderChars.split('').map(char => orders[char]).filter(x => x.length > 0).join(separationChar);
  2085. result.push({
  2086. remark: r,
  2087. link: this.genLink(addr, port, 'same', r, client)
  2088. });
  2089. } else {
  2090. this.stream.externalProxy.forEach((ep) => {
  2091. orders['o'] = ep.remark;
  2092. let r = orderChars.split('').map(char => orders[char]).filter(x => x.length > 0).join(separationChar);
  2093. result.push({
  2094. remark: r,
  2095. link: this.genLink(ep.dest, ep.port, ep.forceTls, r, client)
  2096. });
  2097. });
  2098. }
  2099. return result;
  2100. }
  2101. genInboundLinks(remark = '', remarkModel = '-ieo') {
  2102. let addr = !ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0" ? this.listen : location.hostname;
  2103. if (this.clients) {
  2104. let links = [];
  2105. this.clients.forEach((client) => {
  2106. this.genAllLinks(remark, remarkModel, client).forEach(l => {
  2107. links.push(l.link);
  2108. })
  2109. });
  2110. return links.join('\r\n');
  2111. } else {
  2112. if (this.protocol == Protocols.SHADOWSOCKS && !this.isSSMultiUser) return this.genSSLink(addr, this.port, 'same', remark);
  2113. if (this.protocol == Protocols.WIREGUARD) {
  2114. return this.genWireguardConfigs(remark, remarkModel);
  2115. }
  2116. return '';
  2117. }
  2118. }
  2119. static fromJson(json = {}) {
  2120. return new Inbound(
  2121. json.port,
  2122. json.listen,
  2123. json.protocol,
  2124. Inbound.Settings.fromJson(json.protocol, json.settings),
  2125. StreamSettings.fromJson(json.streamSettings),
  2126. json.tag,
  2127. Sniffing.fromJson(json.sniffing),
  2128. json.clientStats
  2129. )
  2130. }
  2131. toJson() {
  2132. let streamSettings;
  2133. if (this.canEnableStream() || this.stream?.sockopt) {
  2134. streamSettings = this.stream.toJson();
  2135. }
  2136. return {
  2137. port: this.port,
  2138. listen: this.listen,
  2139. protocol: this.protocol,
  2140. settings: this.settings instanceof XrayCommonClass ? this.settings.toJson() : this.settings,
  2141. streamSettings: streamSettings,
  2142. tag: this.tag,
  2143. sniffing: this.sniffing.toJson(),
  2144. clientStats: this.clientStats
  2145. };
  2146. }
  2147. }
  2148. Inbound.Settings = class extends XrayCommonClass {
  2149. constructor(protocol) {
  2150. super();
  2151. this.protocol = protocol;
  2152. }
  2153. static getSettings(protocol) {
  2154. switch (protocol) {
  2155. case Protocols.VMESS: return new Inbound.VmessSettings(protocol);
  2156. case Protocols.VLESS: return new Inbound.VLESSSettings(protocol);
  2157. case Protocols.TROJAN: return new Inbound.TrojanSettings(protocol);
  2158. case Protocols.SHADOWSOCKS: return new Inbound.ShadowsocksSettings(protocol);
  2159. case Protocols.TUNNEL: return new Inbound.TunnelSettings(protocol);
  2160. case Protocols.MIXED: return new Inbound.MixedSettings(protocol);
  2161. case Protocols.HTTP: return new Inbound.HttpSettings(protocol);
  2162. case Protocols.WIREGUARD: return new Inbound.WireguardSettings(protocol);
  2163. case Protocols.TUN: return new Inbound.TunSettings(protocol);
  2164. case Protocols.HYSTERIA: return new Inbound.HysteriaSettings(protocol);
  2165. default: return null;
  2166. }
  2167. }
  2168. static fromJson(protocol, json) {
  2169. switch (protocol) {
  2170. case Protocols.VMESS: return Inbound.VmessSettings.fromJson(json);
  2171. case Protocols.VLESS: return Inbound.VLESSSettings.fromJson(json);
  2172. case Protocols.TROJAN: return Inbound.TrojanSettings.fromJson(json);
  2173. case Protocols.SHADOWSOCKS: return Inbound.ShadowsocksSettings.fromJson(json);
  2174. case Protocols.TUNNEL: return Inbound.TunnelSettings.fromJson(json);
  2175. case Protocols.MIXED: return Inbound.MixedSettings.fromJson(json);
  2176. case Protocols.HTTP: return Inbound.HttpSettings.fromJson(json);
  2177. case Protocols.WIREGUARD: return Inbound.WireguardSettings.fromJson(json);
  2178. case Protocols.TUN: return Inbound.TunSettings.fromJson(json);
  2179. case Protocols.HYSTERIA: return Inbound.HysteriaSettings.fromJson(json);
  2180. default: return null;
  2181. }
  2182. }
  2183. toJson() {
  2184. return {};
  2185. }
  2186. };
  2187. /** Shared user-quota fields and UI helpers for multi-user protocol clients. */
  2188. Inbound.ClientBase = class extends XrayCommonClass {
  2189. constructor(
  2190. email = RandomUtil.randomLowerAndNum(8),
  2191. limitIp = 0,
  2192. totalGB = 0,
  2193. expiryTime = 0,
  2194. enable = true,
  2195. tgId = '',
  2196. subId = RandomUtil.randomLowerAndNum(16),
  2197. comment = '',
  2198. reset = 0,
  2199. created_at = undefined,
  2200. updated_at = undefined,
  2201. ) {
  2202. super();
  2203. this.email = email;
  2204. this.limitIp = limitIp;
  2205. this.totalGB = totalGB;
  2206. this.expiryTime = expiryTime;
  2207. this.enable = enable;
  2208. this.tgId = tgId;
  2209. this.subId = subId;
  2210. this.comment = comment;
  2211. this.reset = reset;
  2212. this.created_at = created_at;
  2213. this.updated_at = updated_at;
  2214. }
  2215. static commonArgsFromJson(json = {}) {
  2216. return [
  2217. json.email,
  2218. json.limitIp,
  2219. json.totalGB,
  2220. json.expiryTime,
  2221. json.enable,
  2222. json.tgId,
  2223. json.subId,
  2224. json.comment,
  2225. json.reset,
  2226. json.created_at,
  2227. json.updated_at,
  2228. ];
  2229. }
  2230. _clientBaseToJson() {
  2231. return {
  2232. email: this.email,
  2233. limitIp: this.limitIp,
  2234. totalGB: this.totalGB,
  2235. expiryTime: this.expiryTime,
  2236. enable: this.enable,
  2237. tgId: this.tgId,
  2238. subId: this.subId,
  2239. comment: this.comment,
  2240. reset: this.reset,
  2241. created_at: this.created_at,
  2242. updated_at: this.updated_at,
  2243. };
  2244. }
  2245. get _expiryTime() {
  2246. if (this.expiryTime === 0 || this.expiryTime === '') {
  2247. return null;
  2248. }
  2249. if (this.expiryTime < 0) {
  2250. return this.expiryTime / -86400000;
  2251. }
  2252. return moment(this.expiryTime);
  2253. }
  2254. set _expiryTime(t) {
  2255. if (t == null || t === '') {
  2256. this.expiryTime = 0;
  2257. } else {
  2258. this.expiryTime = t.valueOf();
  2259. }
  2260. }
  2261. get _totalGB() {
  2262. return NumberFormatter.toFixed(this.totalGB / SizeFormatter.ONE_GB, 2);
  2263. }
  2264. set _totalGB(gb) {
  2265. this.totalGB = NumberFormatter.toFixed(gb * SizeFormatter.ONE_GB, 0);
  2266. }
  2267. };
  2268. Inbound.VmessSettings = class extends Inbound.Settings {
  2269. constructor(protocol,
  2270. vmesses = [new Inbound.VmessSettings.VMESS()]) {
  2271. super(protocol);
  2272. this.vmesses = vmesses;
  2273. }
  2274. indexOfVmessById(id) {
  2275. return this.vmesses.findIndex(VMESS => VMESS.id === id);
  2276. }
  2277. addVmess(VMESS) {
  2278. if (this.indexOfVmessById(VMESS.id) >= 0) {
  2279. return false;
  2280. }
  2281. this.vmesses.push(VMESS);
  2282. }
  2283. delVmess(VMESS) {
  2284. const i = this.indexOfVmessById(VMESS.id);
  2285. if (i >= 0) {
  2286. this.vmesses.splice(i, 1);
  2287. }
  2288. }
  2289. static fromJson(json = {}) {
  2290. return new Inbound.VmessSettings(
  2291. Protocols.VMESS,
  2292. (json.clients || []).map(client => Inbound.VmessSettings.VMESS.fromJson(client)),
  2293. );
  2294. }
  2295. toJson() {
  2296. return {
  2297. clients: Inbound.VmessSettings.toJsonArray(this.vmesses),
  2298. };
  2299. }
  2300. };
  2301. Inbound.VmessSettings.VMESS = class extends Inbound.ClientBase {
  2302. constructor(
  2303. id = RandomUtil.randomUUID(),
  2304. security = USERS_SECURITY.AUTO,
  2305. email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
  2306. ) {
  2307. super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
  2308. this.id = id;
  2309. this.security = security;
  2310. }
  2311. static fromJson(json = {}) {
  2312. return new Inbound.VmessSettings.VMESS(
  2313. json.id,
  2314. json.security,
  2315. ...Inbound.ClientBase.commonArgsFromJson(json),
  2316. );
  2317. }
  2318. toJson() {
  2319. return {
  2320. id: this.id,
  2321. security: this.security,
  2322. ...this._clientBaseToJson(),
  2323. };
  2324. }
  2325. };
  2326. Inbound.VLESSSettings = class extends Inbound.Settings {
  2327. constructor(
  2328. protocol,
  2329. vlesses = [new Inbound.VLESSSettings.VLESS()],
  2330. decryption = "none",
  2331. encryption = "none",
  2332. fallbacks = [],
  2333. testseed = [],
  2334. ) {
  2335. super(protocol);
  2336. this.vlesses = vlesses;
  2337. this.decryption = decryption;
  2338. this.encryption = encryption;
  2339. this.fallbacks = fallbacks;
  2340. this.testseed = testseed;
  2341. }
  2342. addFallback() {
  2343. this.fallbacks.push(new Inbound.VLESSSettings.Fallback());
  2344. }
  2345. delFallback(index) {
  2346. this.fallbacks.splice(index, 1);
  2347. }
  2348. // Empty array means "use server defaults" (won't be sent).
  2349. // Anything else must be exactly 4 positive integers.
  2350. static isValidTestseed(arr) {
  2351. if (!Array.isArray(arr) || arr.length === 0) return true;
  2352. if (arr.length !== 4) return false;
  2353. return arr.every(v => Number.isInteger(v) && v > 0);
  2354. }
  2355. static fromJson(json = {}) {
  2356. // Preserve a saved testseed only if it's a valid 4-positive-int array; otherwise leave empty
  2357. // so toJson omits it and the form falls back to placeholder defaults.
  2358. const saved = json.testseed;
  2359. const testseed = (Array.isArray(saved)
  2360. && saved.length === 4
  2361. && saved.every(v => Number.isInteger(v) && v > 0))
  2362. ? saved
  2363. : [];
  2364. const obj = new Inbound.VLESSSettings(
  2365. Protocols.VLESS,
  2366. (json.clients || []).map(client => Inbound.VLESSSettings.VLESS.fromJson(client)),
  2367. json.decryption,
  2368. json.encryption,
  2369. Inbound.VLESSSettings.Fallback.fromJson(json.fallbacks || []),
  2370. testseed,
  2371. );
  2372. return obj;
  2373. }
  2374. toJson() {
  2375. const json = {
  2376. clients: Inbound.VLESSSettings.toJsonArray(this.vlesses),
  2377. };
  2378. if (this.decryption) {
  2379. json.decryption = this.decryption;
  2380. }
  2381. if (this.encryption) {
  2382. json.encryption = this.encryption;
  2383. }
  2384. if (this.fallbacks && this.fallbacks.length > 0) {
  2385. json.fallbacks = Inbound.VLESSSettings.toJsonArray(this.fallbacks);
  2386. }
  2387. // testseed is only meaningful for the exact xtls-rprx-vision flow, and only when
  2388. // the user supplied a complete 4-positive-int array. Otherwise omit and let the
  2389. // backend fall back to its safe defaults.
  2390. const hasVisionFlow = this.vlesses && this.vlesses.some(v => v.flow === TLS_FLOW_CONTROL.VISION);
  2391. if (hasVisionFlow
  2392. && Array.isArray(this.testseed)
  2393. && this.testseed.length === 4
  2394. && this.testseed.every(v => Number.isInteger(v) && v > 0)) {
  2395. json.testseed = this.testseed;
  2396. }
  2397. return json;
  2398. }
  2399. };
  2400. Inbound.VLESSSettings.VLESS = class extends Inbound.ClientBase {
  2401. constructor(
  2402. id = RandomUtil.randomUUID(),
  2403. flow = '',
  2404. reverseTag = '',
  2405. reverseSniffing = new Sniffing(),
  2406. email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
  2407. ) {
  2408. super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
  2409. this.id = id;
  2410. this.flow = flow;
  2411. this.reverseTag = reverseTag;
  2412. this.reverseSniffing = reverseSniffing;
  2413. }
  2414. static fromJson(json = {}) {
  2415. return new Inbound.VLESSSettings.VLESS(
  2416. json.id,
  2417. json.flow,
  2418. json.reverse?.tag ?? '',
  2419. Sniffing.fromJson(json.reverse?.sniffing || {}),
  2420. ...Inbound.ClientBase.commonArgsFromJson(json),
  2421. );
  2422. }
  2423. toJson() {
  2424. const json = {
  2425. id: this.id,
  2426. flow: this.flow,
  2427. ...this._clientBaseToJson(),
  2428. };
  2429. if (this.reverseTag) {
  2430. json.reverse = {
  2431. tag: this.reverseTag,
  2432. };
  2433. }
  2434. return json;
  2435. }
  2436. };
  2437. Inbound.VLESSSettings.Fallback = class extends XrayCommonClass {
  2438. constructor(name = "", alpn = '', path = '', dest = '', xver = 0) {
  2439. super();
  2440. this.name = name;
  2441. this.alpn = alpn;
  2442. this.path = path;
  2443. this.dest = dest;
  2444. this.xver = xver;
  2445. }
  2446. toJson() {
  2447. let xver = this.xver;
  2448. if (!Number.isInteger(xver)) {
  2449. xver = 0;
  2450. }
  2451. return {
  2452. name: this.name,
  2453. alpn: this.alpn,
  2454. path: this.path,
  2455. dest: this.dest,
  2456. xver: xver,
  2457. }
  2458. }
  2459. static fromJson(json = []) {
  2460. const fallbacks = [];
  2461. for (let fallback of json) {
  2462. fallbacks.push(new Inbound.VLESSSettings.Fallback(
  2463. fallback.name,
  2464. fallback.alpn,
  2465. fallback.path,
  2466. fallback.dest,
  2467. fallback.xver,
  2468. ))
  2469. }
  2470. return fallbacks;
  2471. }
  2472. };
  2473. Inbound.TrojanSettings = class extends Inbound.Settings {
  2474. constructor(protocol,
  2475. trojans = [new Inbound.TrojanSettings.Trojan()],
  2476. fallbacks = [],) {
  2477. super(protocol);
  2478. this.trojans = trojans;
  2479. this.fallbacks = fallbacks;
  2480. }
  2481. addFallback() {
  2482. this.fallbacks.push(new Inbound.TrojanSettings.Fallback());
  2483. }
  2484. delFallback(index) {
  2485. this.fallbacks.splice(index, 1);
  2486. }
  2487. static fromJson(json = {}) {
  2488. return new Inbound.TrojanSettings(
  2489. Protocols.TROJAN,
  2490. (json.clients || []).map(client => Inbound.TrojanSettings.Trojan.fromJson(client)),
  2491. Inbound.TrojanSettings.Fallback.fromJson(json.fallbacks),);
  2492. }
  2493. toJson() {
  2494. return {
  2495. clients: Inbound.TrojanSettings.toJsonArray(this.trojans),
  2496. fallbacks: Inbound.TrojanSettings.toJsonArray(this.fallbacks)
  2497. };
  2498. }
  2499. };
  2500. Inbound.TrojanSettings.Trojan = class extends Inbound.ClientBase {
  2501. constructor(
  2502. password = RandomUtil.randomSeq(10),
  2503. email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
  2504. ) {
  2505. super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
  2506. this.password = password;
  2507. }
  2508. toJson() {
  2509. return {
  2510. password: this.password,
  2511. ...this._clientBaseToJson(),
  2512. };
  2513. }
  2514. static fromJson(json = {}) {
  2515. return new Inbound.TrojanSettings.Trojan(
  2516. json.password,
  2517. ...Inbound.ClientBase.commonArgsFromJson(json),
  2518. );
  2519. }
  2520. };
  2521. Inbound.TrojanSettings.Fallback = class extends XrayCommonClass {
  2522. constructor(name = "", alpn = '', path = '', dest = '', xver = 0) {
  2523. super();
  2524. this.name = name;
  2525. this.alpn = alpn;
  2526. this.path = path;
  2527. this.dest = dest;
  2528. this.xver = xver;
  2529. }
  2530. toJson() {
  2531. let xver = this.xver;
  2532. if (!Number.isInteger(xver)) {
  2533. xver = 0;
  2534. }
  2535. return {
  2536. name: this.name,
  2537. alpn: this.alpn,
  2538. path: this.path,
  2539. dest: this.dest,
  2540. xver: xver,
  2541. }
  2542. }
  2543. static fromJson(json = []) {
  2544. const fallbacks = [];
  2545. for (let fallback of json) {
  2546. fallbacks.push(new Inbound.TrojanSettings.Fallback(
  2547. fallback.name,
  2548. fallback.alpn,
  2549. fallback.path,
  2550. fallback.dest,
  2551. fallback.xver,
  2552. ))
  2553. }
  2554. return fallbacks;
  2555. }
  2556. };
  2557. Inbound.ShadowsocksSettings = class extends Inbound.Settings {
  2558. constructor(protocol,
  2559. method = SSMethods.BLAKE3_AES_256_GCM,
  2560. password = RandomUtil.randomShadowsocksPassword(),
  2561. network = 'tcp,udp',
  2562. shadowsockses = [new Inbound.ShadowsocksSettings.Shadowsocks()],
  2563. ivCheck = false,
  2564. ) {
  2565. super(protocol);
  2566. this.method = method;
  2567. this.password = password;
  2568. this.network = network;
  2569. this.shadowsockses = shadowsockses;
  2570. this.ivCheck = ivCheck;
  2571. }
  2572. static fromJson(json = {}) {
  2573. return new Inbound.ShadowsocksSettings(
  2574. Protocols.SHADOWSOCKS,
  2575. json.method,
  2576. json.password,
  2577. json.network,
  2578. (json.clients || []).map(client => Inbound.ShadowsocksSettings.Shadowsocks.fromJson(client)),
  2579. json.ivCheck,
  2580. );
  2581. }
  2582. toJson() {
  2583. return {
  2584. method: this.method,
  2585. password: this.password,
  2586. network: this.network,
  2587. clients: Inbound.ShadowsocksSettings.toJsonArray(this.shadowsockses),
  2588. ivCheck: this.ivCheck,
  2589. };
  2590. }
  2591. };
  2592. Inbound.ShadowsocksSettings.Shadowsocks = class extends Inbound.ClientBase {
  2593. constructor(
  2594. method = '',
  2595. password = RandomUtil.randomShadowsocksPassword(),
  2596. email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
  2597. ) {
  2598. super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
  2599. this.method = method;
  2600. this.password = password;
  2601. }
  2602. toJson() {
  2603. return {
  2604. method: this.method,
  2605. password: this.password,
  2606. ...this._clientBaseToJson(),
  2607. };
  2608. }
  2609. static fromJson(json = {}) {
  2610. return new Inbound.ShadowsocksSettings.Shadowsocks(
  2611. json.method,
  2612. json.password,
  2613. ...Inbound.ClientBase.commonArgsFromJson(json),
  2614. );
  2615. }
  2616. };
  2617. Inbound.HysteriaSettings = class extends Inbound.Settings {
  2618. constructor(protocol, version = 2, hysterias = [new Inbound.HysteriaSettings.Hysteria()]) {
  2619. super(protocol);
  2620. this.version = version;
  2621. this.hysterias = hysterias;
  2622. }
  2623. static fromJson(json = {}) {
  2624. return new Inbound.HysteriaSettings(
  2625. Protocols.HYSTERIA,
  2626. json.version ?? 2,
  2627. (json.clients || []).map(client => Inbound.HysteriaSettings.Hysteria.fromJson(client)),
  2628. );
  2629. }
  2630. toJson() {
  2631. return {
  2632. version: this.version,
  2633. clients: Inbound.HysteriaSettings.toJsonArray(this.hysterias),
  2634. };
  2635. }
  2636. };
  2637. Inbound.HysteriaSettings.Hysteria = class extends Inbound.ClientBase {
  2638. constructor(
  2639. auth = RandomUtil.randomSeq(10),
  2640. email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at,
  2641. ) {
  2642. super(email, limitIp, totalGB, expiryTime, enable, tgId, subId, comment, reset, created_at, updated_at);
  2643. this.auth = auth;
  2644. }
  2645. toJson() {
  2646. return {
  2647. auth: this.auth,
  2648. ...this._clientBaseToJson(),
  2649. };
  2650. }
  2651. static fromJson(json = {}) {
  2652. return new Inbound.HysteriaSettings.Hysteria(
  2653. json.auth,
  2654. ...Inbound.ClientBase.commonArgsFromJson(json),
  2655. );
  2656. }
  2657. };
  2658. Inbound.TunnelSettings = class extends Inbound.Settings {
  2659. constructor(
  2660. protocol,
  2661. address,
  2662. port,
  2663. portMap = [],
  2664. network = 'tcp,udp',
  2665. followRedirect = false
  2666. ) {
  2667. super(protocol);
  2668. this.address = address;
  2669. this.port = port;
  2670. this.portMap = portMap;
  2671. this.network = network;
  2672. this.followRedirect = followRedirect;
  2673. }
  2674. static fromJson(json = {}) {
  2675. return new Inbound.TunnelSettings(
  2676. Protocols.TUNNEL,
  2677. json.address,
  2678. json.port,
  2679. XrayCommonClass.toHeaders(json.portMap),
  2680. json.network,
  2681. json.followRedirect,
  2682. );
  2683. }
  2684. toJson() {
  2685. return {
  2686. address: this.address,
  2687. port: this.port,
  2688. portMap: XrayCommonClass.toV2Headers(this.portMap, false),
  2689. network: this.network,
  2690. followRedirect: this.followRedirect,
  2691. };
  2692. }
  2693. };
  2694. Inbound.MixedSettings = class extends Inbound.Settings {
  2695. constructor(protocol, auth = 'password', accounts = [new Inbound.MixedSettings.SocksAccount()], udp = false, ip = '127.0.0.1') {
  2696. super(protocol);
  2697. this.auth = auth;
  2698. this.accounts = accounts;
  2699. this.udp = udp;
  2700. this.ip = ip;
  2701. }
  2702. addAccount(account) {
  2703. this.accounts.push(account);
  2704. }
  2705. delAccount(index) {
  2706. this.accounts.splice(index, 1);
  2707. }
  2708. static fromJson(json = {}) {
  2709. let accounts;
  2710. if (json.auth === 'password') {
  2711. accounts = json.accounts.map(
  2712. account => Inbound.MixedSettings.SocksAccount.fromJson(account)
  2713. )
  2714. }
  2715. return new Inbound.MixedSettings(
  2716. Protocols.MIXED,
  2717. json.auth,
  2718. accounts,
  2719. json.udp,
  2720. json.ip,
  2721. );
  2722. }
  2723. toJson() {
  2724. return {
  2725. auth: this.auth,
  2726. accounts: this.auth === 'password' ? this.accounts.map(account => account.toJson()) : undefined,
  2727. udp: this.udp,
  2728. ip: this.ip,
  2729. };
  2730. }
  2731. };
  2732. Inbound.MixedSettings.SocksAccount = class extends XrayCommonClass {
  2733. constructor(user = RandomUtil.randomSeq(10), pass = RandomUtil.randomSeq(10)) {
  2734. super();
  2735. this.user = user;
  2736. this.pass = pass;
  2737. }
  2738. static fromJson(json = {}) {
  2739. return new Inbound.MixedSettings.SocksAccount(json.user, json.pass);
  2740. }
  2741. };
  2742. Inbound.HttpSettings = class extends Inbound.Settings {
  2743. constructor(
  2744. protocol,
  2745. accounts = [new Inbound.HttpSettings.HttpAccount()],
  2746. allowTransparent = false,
  2747. ) {
  2748. super(protocol);
  2749. this.accounts = accounts;
  2750. this.allowTransparent = allowTransparent;
  2751. }
  2752. addAccount(account) {
  2753. this.accounts.push(account);
  2754. }
  2755. delAccount(index) {
  2756. this.accounts.splice(index, 1);
  2757. }
  2758. static fromJson(json = {}) {
  2759. return new Inbound.HttpSettings(
  2760. Protocols.HTTP,
  2761. json.accounts.map(account => Inbound.HttpSettings.HttpAccount.fromJson(account)),
  2762. json.allowTransparent,
  2763. );
  2764. }
  2765. toJson() {
  2766. return {
  2767. accounts: Inbound.HttpSettings.toJsonArray(this.accounts),
  2768. allowTransparent: this.allowTransparent,
  2769. };
  2770. }
  2771. };
  2772. Inbound.HttpSettings.HttpAccount = class extends XrayCommonClass {
  2773. constructor(user = RandomUtil.randomSeq(10), pass = RandomUtil.randomSeq(10)) {
  2774. super();
  2775. this.user = user;
  2776. this.pass = pass;
  2777. }
  2778. static fromJson(json = {}) {
  2779. return new Inbound.HttpSettings.HttpAccount(json.user, json.pass);
  2780. }
  2781. };
  2782. Inbound.WireguardSettings = class extends XrayCommonClass {
  2783. constructor(
  2784. protocol,
  2785. mtu = 1420,
  2786. secretKey = Wireguard.generateKeypair().privateKey,
  2787. peers = [new Inbound.WireguardSettings.Peer()],
  2788. noKernelTun = false
  2789. ) {
  2790. super(protocol);
  2791. this.mtu = mtu;
  2792. this.secretKey = secretKey;
  2793. this.pubKey = secretKey.length > 0 ? Wireguard.generateKeypair(secretKey).publicKey : '';
  2794. this.peers = peers;
  2795. this.noKernelTun = noKernelTun;
  2796. }
  2797. addPeer() {
  2798. this.peers.push(new Inbound.WireguardSettings.Peer(null, null, '', ['10.0.0.' + (this.peers.length + 2)]));
  2799. }
  2800. delPeer(index) {
  2801. this.peers.splice(index, 1);
  2802. }
  2803. static fromJson(json = {}) {
  2804. return new Inbound.WireguardSettings(
  2805. Protocols.WIREGUARD,
  2806. json.mtu,
  2807. json.secretKey,
  2808. json.peers.map(peer => Inbound.WireguardSettings.Peer.fromJson(peer)),
  2809. json.noKernelTun,
  2810. );
  2811. }
  2812. toJson() {
  2813. return {
  2814. mtu: this.mtu ?? undefined,
  2815. secretKey: this.secretKey,
  2816. peers: Inbound.WireguardSettings.Peer.toJsonArray(this.peers),
  2817. noKernelTun: this.noKernelTun,
  2818. };
  2819. }
  2820. };
  2821. Inbound.WireguardSettings.Peer = class extends XrayCommonClass {
  2822. constructor(privateKey, publicKey, psk = '', allowedIPs = ['10.0.0.2/32'], keepAlive = 0) {
  2823. super();
  2824. this.privateKey = privateKey
  2825. this.publicKey = publicKey;
  2826. if (!this.publicKey) {
  2827. [this.publicKey, this.privateKey] = Object.values(Wireguard.generateKeypair())
  2828. }
  2829. this.psk = psk;
  2830. allowedIPs.forEach((a, index) => {
  2831. if (a.length > 0 && !a.includes('/')) allowedIPs[index] += '/32';
  2832. })
  2833. this.allowedIPs = allowedIPs;
  2834. this.keepAlive = keepAlive;
  2835. }
  2836. static fromJson(json = {}) {
  2837. return new Inbound.WireguardSettings.Peer(
  2838. json.privateKey,
  2839. json.publicKey,
  2840. json.preSharedKey,
  2841. json.allowedIPs,
  2842. json.keepAlive
  2843. );
  2844. }
  2845. toJson() {
  2846. this.allowedIPs.forEach((a, index) => {
  2847. if (a.length > 0 && !a.includes('/')) this.allowedIPs[index] += '/32';
  2848. });
  2849. return {
  2850. privateKey: this.privateKey,
  2851. publicKey: this.publicKey,
  2852. preSharedKey: this.psk.length > 0 ? this.psk : undefined,
  2853. allowedIPs: this.allowedIPs,
  2854. keepAlive: this.keepAlive ?? undefined,
  2855. };
  2856. }
  2857. };
  2858. Inbound.TunSettings = class extends Inbound.Settings {
  2859. constructor(
  2860. protocol,
  2861. name = 'xray0',
  2862. mtu = [1500, 1280],
  2863. gateway = [],
  2864. dns = [],
  2865. userLevel = 0,
  2866. autoSystemRoutingTable = [],
  2867. autoOutboundsInterface = 'auto'
  2868. ) {
  2869. super(protocol);
  2870. this.name = name;
  2871. this.mtu = this._normalizeMtu(mtu);
  2872. this.gateway = Array.isArray(gateway) ? gateway : [];
  2873. this.dns = Array.isArray(dns) ? dns : [];
  2874. this.userLevel = userLevel;
  2875. this.autoSystemRoutingTable = Array.isArray(autoSystemRoutingTable) ? autoSystemRoutingTable : [];
  2876. this.autoOutboundsInterface = autoOutboundsInterface;
  2877. }
  2878. _normalizeMtu(mtu) {
  2879. if (!Array.isArray(mtu)) {
  2880. const single = Number(mtu) || 1500;
  2881. return [single, single];
  2882. }
  2883. if (mtu.length === 0) {
  2884. return [1500, 1280];
  2885. }
  2886. if (mtu.length === 1) {
  2887. const single = Number(mtu[0]) || 1500;
  2888. return [single, single];
  2889. }
  2890. return [Number(mtu[0]) || 1500, Number(mtu[1]) || 1280];
  2891. }
  2892. static fromJson(json = {}) {
  2893. return new Inbound.TunSettings(
  2894. Protocols.TUN,
  2895. json.name ?? 'xray0',
  2896. json.mtu ?? json.MTU ?? [1500, 1280],
  2897. json.gateway ?? json.Gateway ?? [],
  2898. json.dns ?? json.DNS ?? [],
  2899. json.userLevel ?? 0,
  2900. json.autoSystemRoutingTable ?? [],
  2901. Object.prototype.hasOwnProperty.call(json, 'autoOutboundsInterface') ? json.autoOutboundsInterface : 'auto'
  2902. );
  2903. }
  2904. toJson() {
  2905. return {
  2906. name: this.name || 'xray0',
  2907. mtu: this._normalizeMtu(this.mtu),
  2908. gateway: this.gateway,
  2909. dns: this.dns,
  2910. userLevel: this.userLevel || 0,
  2911. autoSystemRoutingTable: this.autoSystemRoutingTable,
  2912. autoOutboundsInterface: this.autoOutboundsInterface,
  2913. };
  2914. }
  2915. };