xray.js 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. const Protocols = {
  2. VMESS: 'vmess',
  3. VLESS: 'vless',
  4. TROJAN: 'trojan',
  5. SHADOWSOCKS: 'shadowsocks',
  6. DOKODEMO: 'dokodemo-door',
  7. MTPROTO: 'mtproto',
  8. SOCKS: 'socks',
  9. HTTP: 'http',
  10. };
  11. const VmessMethods = {
  12. AES_128_GCM: 'aes-128-gcm',
  13. CHACHA20_POLY1305: 'chacha20-poly1305',
  14. AUTO: 'auto',
  15. NONE: 'none',
  16. };
  17. const SSMethods = {
  18. // AES_256_CFB: 'aes-256-cfb',
  19. // AES_128_CFB: 'aes-128-cfb',
  20. // CHACHA20: 'chacha20',
  21. // CHACHA20_IETF: 'chacha20-ietf',
  22. CHACHA20_POLY1305: 'chacha20-poly1305',
  23. AES_256_GCM: 'aes-256-gcm',
  24. AES_128_GCM: 'aes-128-gcm',
  25. };
  26. const RULE_IP = {
  27. PRIVATE: 'geoip:private',
  28. CN: 'geoip:cn',
  29. };
  30. const RULE_DOMAIN = {
  31. ADS: 'geosite:category-ads',
  32. ADS_ALL: 'geosite:category-ads-all',
  33. CN: 'geosite:cn',
  34. GOOGLE: 'geosite:google',
  35. FACEBOOK: 'geosite:facebook',
  36. SPEEDTEST: 'geosite:speedtest',
  37. };
  38. const VLESS_FLOW = {
  39. ORIGIN: "xtls-rprx-origin",
  40. DIRECT: "xtls-rprx-direct",
  41. };
  42. Object.freeze(Protocols);
  43. Object.freeze(VmessMethods);
  44. Object.freeze(SSMethods);
  45. Object.freeze(RULE_IP);
  46. Object.freeze(RULE_DOMAIN);
  47. Object.freeze(VLESS_FLOW);
  48. class XrayCommonClass {
  49. static toJsonArray(arr) {
  50. return arr.map(obj => obj.toJson());
  51. }
  52. static fromJson() {
  53. return new XrayCommonClass();
  54. }
  55. toJson() {
  56. return this;
  57. }
  58. toString(format=true) {
  59. return format ? JSON.stringify(this.toJson(), null, 2) : JSON.stringify(this.toJson());
  60. }
  61. static toHeaders(v2Headers) {
  62. let newHeaders = [];
  63. if (v2Headers) {
  64. Object.keys(v2Headers).forEach(key => {
  65. let values = v2Headers[key];
  66. if (typeof(values) === 'string') {
  67. newHeaders.push({ name: key, value: values });
  68. } else {
  69. for (let i = 0; i < values.length; ++i) {
  70. newHeaders.push({ name: key, value: values[i] });
  71. }
  72. }
  73. });
  74. }
  75. return newHeaders;
  76. }
  77. static toV2Headers(headers, arr=true) {
  78. let v2Headers = {};
  79. for (let i = 0; i < headers.length; ++i) {
  80. let name = headers[i].name;
  81. let value = headers[i].value;
  82. if (ObjectUtil.isEmpty(name) || ObjectUtil.isEmpty(value)) {
  83. continue;
  84. }
  85. if (!(name in v2Headers)) {
  86. v2Headers[name] = arr ? [value] : value;
  87. } else {
  88. if (arr) {
  89. v2Headers[name].push(value);
  90. } else {
  91. v2Headers[name] = value;
  92. }
  93. }
  94. }
  95. return v2Headers;
  96. }
  97. }
  98. class TcpStreamSettings extends XrayCommonClass {
  99. constructor(type='none',
  100. request=new TcpStreamSettings.TcpRequest(),
  101. response=new TcpStreamSettings.TcpResponse(),
  102. ) {
  103. super();
  104. this.type = type;
  105. this.request = request;
  106. this.response = response;
  107. }
  108. static fromJson(json={}) {
  109. let header = json.header;
  110. if (!header) {
  111. header = {};
  112. }
  113. return new TcpStreamSettings(
  114. header.type,
  115. TcpStreamSettings.TcpRequest.fromJson(header.request),
  116. TcpStreamSettings.TcpResponse.fromJson(header.response),
  117. );
  118. }
  119. toJson() {
  120. return {
  121. header: {
  122. type: this.type,
  123. request: this.type === 'http' ? this.request.toJson() : undefined,
  124. response: this.type === 'http' ? this.response.toJson() : undefined,
  125. },
  126. };
  127. }
  128. }
  129. TcpStreamSettings.TcpRequest = class extends XrayCommonClass {
  130. constructor(version='1.1',
  131. method='GET',
  132. path=['/'],
  133. headers=[],
  134. ) {
  135. super();
  136. this.version = version;
  137. this.method = method;
  138. this.path = path.length === 0 ? ['/'] : path;
  139. this.headers = headers;
  140. }
  141. addPath(path) {
  142. this.path.push(path);
  143. }
  144. removePath(index) {
  145. this.path.splice(index, 1);
  146. }
  147. addHeader(name, value) {
  148. this.headers.push({ name: name, value: value });
  149. }
  150. removeHeader(index) {
  151. this.headers.splice(index, 1);
  152. }
  153. static fromJson(json={}) {
  154. return new TcpStreamSettings.TcpRequest(
  155. json.version,
  156. json.method,
  157. json.path,
  158. XrayCommonClass.toHeaders(json.headers),
  159. );
  160. }
  161. toJson() {
  162. return {
  163. method: this.method,
  164. path: ObjectUtil.clone(this.path),
  165. headers: XrayCommonClass.toV2Headers(this.headers),
  166. };
  167. }
  168. };
  169. TcpStreamSettings.TcpResponse = class extends XrayCommonClass {
  170. constructor(version='1.1',
  171. status='200',
  172. reason='OK',
  173. headers=[],
  174. ) {
  175. super();
  176. this.version = version;
  177. this.status = status;
  178. this.reason = reason;
  179. this.headers = headers;
  180. }
  181. addHeader(name, value) {
  182. this.headers.push({ name: name, value: value });
  183. }
  184. removeHeader(index) {
  185. this.headers.splice(index, 1);
  186. }
  187. static fromJson(json={}) {
  188. return new TcpStreamSettings.TcpResponse(
  189. json.version,
  190. json.status,
  191. json.reason,
  192. XrayCommonClass.toHeaders(json.headers),
  193. );
  194. }
  195. toJson() {
  196. return {
  197. version: this.version,
  198. status: this.status,
  199. reason: this.reason,
  200. headers: XrayCommonClass.toV2Headers(this.headers),
  201. };
  202. }
  203. };
  204. class KcpStreamSettings extends XrayCommonClass {
  205. constructor(mtu=1350, tti=20,
  206. uplinkCapacity=5,
  207. downlinkCapacity=20,
  208. congestion=false,
  209. readBufferSize=2,
  210. writeBufferSize=2,
  211. type='none',
  212. seed=RandomUtil.randomSeq(10),
  213. ) {
  214. super();
  215. this.mtu = mtu;
  216. this.tti = tti;
  217. this.upCap = uplinkCapacity;
  218. this.downCap = downlinkCapacity;
  219. this.congestion = congestion;
  220. this.readBuffer = readBufferSize;
  221. this.writeBuffer = writeBufferSize;
  222. this.type = type;
  223. this.seed = seed;
  224. }
  225. static fromJson(json={}) {
  226. return new KcpStreamSettings(
  227. json.mtu,
  228. json.tti,
  229. json.uplinkCapacity,
  230. json.downlinkCapacity,
  231. json.congestion,
  232. json.readBufferSize,
  233. json.writeBufferSize,
  234. ObjectUtil.isEmpty(json.header) ? 'none' : json.header.type,
  235. json.seed,
  236. );
  237. }
  238. toJson() {
  239. return {
  240. mtu: this.mtu,
  241. tti: this.tti,
  242. uplinkCapacity: this.upCap,
  243. downlinkCapacity: this.downCap,
  244. congestion: this.congestion,
  245. readBufferSize: this.readBuffer,
  246. writeBufferSize: this.writeBuffer,
  247. header: {
  248. type: this.type,
  249. },
  250. seed: this.seed,
  251. };
  252. }
  253. }
  254. class WsStreamSettings extends XrayCommonClass {
  255. constructor(path='/', headers=[]) {
  256. super();
  257. this.path = path;
  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 WsStreamSettings(
  268. json.path,
  269. XrayCommonClass.toHeaders(json.headers),
  270. );
  271. }
  272. toJson() {
  273. return {
  274. path: this.path,
  275. headers: XrayCommonClass.toV2Headers(this.headers, false),
  276. };
  277. }
  278. }
  279. class HttpStreamSettings extends XrayCommonClass {
  280. constructor(path='/', host=['']) {
  281. super();
  282. this.path = path;
  283. this.host = host.length === 0 ? [''] : host;
  284. }
  285. addHost(host) {
  286. this.host.push(host);
  287. }
  288. removeHost(index) {
  289. this.host.splice(index, 1);
  290. }
  291. static fromJson(json={}) {
  292. return new HttpStreamSettings(json.path, json.host);
  293. }
  294. toJson() {
  295. let host = [];
  296. for (let i = 0; i < this.host.length; ++i) {
  297. if (!ObjectUtil.isEmpty(this.host[i])) {
  298. host.push(this.host[i]);
  299. }
  300. }
  301. return {
  302. path: this.path,
  303. host: host,
  304. }
  305. }
  306. }
  307. class QuicStreamSettings extends XrayCommonClass {
  308. constructor(security=VmessMethods.NONE,
  309. key='', type='none') {
  310. super();
  311. this.security = security;
  312. this.key = key;
  313. this.type = type;
  314. }
  315. static fromJson(json={}) {
  316. return new QuicStreamSettings(
  317. json.security,
  318. json.key,
  319. json.header ? json.header.type : 'none',
  320. );
  321. }
  322. toJson() {
  323. return {
  324. security: this.security,
  325. key: this.key,
  326. header: {
  327. type: this.type,
  328. }
  329. }
  330. }
  331. }
  332. class TlsStreamSettings extends XrayCommonClass {
  333. constructor(serverName='',
  334. certificates=[new TlsStreamSettings.Cert()]) {
  335. super();
  336. this.server = serverName;
  337. this.certs = certificates;
  338. }
  339. addCert(cert) {
  340. this.certs.push(cert);
  341. }
  342. removeCert(index) {
  343. this.certs.splice(index, 1);
  344. }
  345. static fromJson(json={}) {
  346. let certs;
  347. if (!ObjectUtil.isEmpty(json.certificates)) {
  348. certs = json.certificates.map(cert => TlsStreamSettings.Cert.fromJson(cert));
  349. }
  350. return new TlsStreamSettings(
  351. json.serverName,
  352. certs,
  353. );
  354. }
  355. toJson() {
  356. return {
  357. serverName: this.server,
  358. certificates: TlsStreamSettings.toJsonArray(this.certs),
  359. };
  360. }
  361. }
  362. TlsStreamSettings.Cert = class extends XrayCommonClass {
  363. constructor(useFile=true, certificateFile='', keyFile='', certificate='', key='') {
  364. super();
  365. this.useFile = useFile;
  366. this.certFile = certificateFile;
  367. this.keyFile = keyFile;
  368. this.cert = certificate instanceof Array ? certificate.join('\n') : certificate;
  369. this.key = key instanceof Array ? key.join('\n') : key;
  370. }
  371. static fromJson(json={}) {
  372. if ('certificateFile' in json && 'keyFile' in json) {
  373. return new TlsStreamSettings.Cert(
  374. true,
  375. json.certificateFile,
  376. json.keyFile,
  377. );
  378. } else {
  379. return new TlsStreamSettings.Cert(
  380. false, '', '',
  381. json.certificate.join('\n'),
  382. json.key.join('\n'),
  383. );
  384. }
  385. }
  386. toJson() {
  387. if (this.useFile) {
  388. return {
  389. certificateFile: this.certFile,
  390. keyFile: this.keyFile,
  391. };
  392. } else {
  393. return {
  394. certificate: this.cert.split('\n'),
  395. key: this.key.split('\n'),
  396. };
  397. }
  398. }
  399. };
  400. class StreamSettings extends XrayCommonClass {
  401. constructor(network='tcp',
  402. security='none',
  403. tlsSettings=new TlsStreamSettings(),
  404. tcpSettings=new TcpStreamSettings(),
  405. kcpSettings=new KcpStreamSettings(),
  406. wsSettings=new WsStreamSettings(),
  407. httpSettings=new HttpStreamSettings(),
  408. quicSettings=new QuicStreamSettings(),
  409. ) {
  410. super();
  411. this.network = network;
  412. if (security === "xtls") {
  413. this.security = "tls";
  414. this._is_xtls = true;
  415. } else {
  416. this.security = security;
  417. this._is_xtls = false;
  418. }
  419. this.tls = tlsSettings;
  420. this.tcp = tcpSettings;
  421. this.kcp = kcpSettings;
  422. this.ws = wsSettings;
  423. this.http = httpSettings;
  424. this.quic = quicSettings;
  425. }
  426. get is_xtls() {
  427. return this.security === "tls" && this.network === "tcp" && this._is_xtls;
  428. }
  429. set is_xtls(is_xtls) {
  430. this._is_xtls = is_xtls;
  431. }
  432. static fromJson(json={}) {
  433. let tls;
  434. if (json.security === "xtls") {
  435. tls = TlsStreamSettings.fromJson(json.xtlsSettings);
  436. } else {
  437. tls = TlsStreamSettings.fromJson(json.tlsSettings);
  438. }
  439. return new StreamSettings(
  440. json.network,
  441. json.security,
  442. tls,
  443. TcpStreamSettings.fromJson(json.tcpSettings),
  444. KcpStreamSettings.fromJson(json.kcpSettings),
  445. WsStreamSettings.fromJson(json.wsSettings),
  446. HttpStreamSettings.fromJson(json.httpSettings),
  447. QuicStreamSettings.fromJson(json.quicSettings),
  448. );
  449. }
  450. toJson() {
  451. let network = this.network;
  452. let security = this.security;
  453. if (this.is_xtls) {
  454. security = "xtls";
  455. }
  456. return {
  457. network: network,
  458. security: security,
  459. tlsSettings: this.security === 'tls' && ['tcp', 'ws', 'http', 'quic'].indexOf(network) >= 0 && !this.is_xtls ? this.tls.toJson() : undefined,
  460. xtlsSettings: this.is_xtls ? this.tls.toJson() : undefined,
  461. tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined,
  462. kcpSettings: network === 'kcp' ? this.kcp.toJson() : undefined,
  463. wsSettings: network === 'ws' ? this.ws.toJson() : undefined,
  464. httpSettings: network === 'http' ? this.http.toJson() : undefined,
  465. quicSettings: network === 'quic' ? this.quic.toJson() : undefined,
  466. };
  467. }
  468. }
  469. class Sniffing extends XrayCommonClass {
  470. constructor(enabled=true, destOverride=['http', 'tls']) {
  471. super();
  472. this.enabled = enabled;
  473. this.destOverride = destOverride;
  474. }
  475. static fromJson(json={}) {
  476. let destOverride = ObjectUtil.clone(json.destOverride);
  477. if (!ObjectUtil.isEmpty(destOverride) && !ObjectUtil.isArrEmpty(destOverride)) {
  478. if (ObjectUtil.isEmpty(destOverride[0])) {
  479. destOverride = ['http', 'tls'];
  480. }
  481. }
  482. return new Sniffing(
  483. !!json.enabled,
  484. destOverride,
  485. );
  486. }
  487. }
  488. class Inbound extends XrayCommonClass {
  489. constructor(port=RandomUtil.randomIntRange(10000, 60000),
  490. listen='0.0.0.0',
  491. protocol=Protocols.VMESS,
  492. settings=null,
  493. streamSettings=new StreamSettings(),
  494. tag='',
  495. sniffing=new Sniffing(),
  496. remark='',
  497. enable=true,
  498. ) {
  499. super();
  500. this.port = port;
  501. this.listen = listen;
  502. this.protocol = protocol;
  503. this.settings = ObjectUtil.isEmpty(settings) ? Inbound.Settings.getSettings(protocol) : settings;
  504. this.stream = streamSettings;
  505. this.tag = tag;
  506. this.sniffing = sniffing;
  507. this.remark = remark;
  508. this.enable = enable;
  509. }
  510. reset() {
  511. this.port = RandomUtil.randomIntRange(10000, 60000);
  512. this.listen = '0.0.0.0';
  513. this.protocol = Protocols.VMESS;
  514. this.settings = Inbound.Settings.getSettings(Protocols.VMESS);
  515. this.stream = new StreamSettings();
  516. this.tag = '';
  517. this.sniffing = new Sniffing();
  518. this.remark = '';
  519. this.enable = true;
  520. }
  521. genVmessLink(address='') {
  522. if (this.protocol !== Protocols.VMESS) {
  523. return '';
  524. }
  525. let network = this.stream.network;
  526. let type = 'none';
  527. let host = '';
  528. let path = '';
  529. if (network === 'tcp') {
  530. let tcp = this.stream.tcp;
  531. type = tcp.type;
  532. if (type === 'http') {
  533. let request = tcp.request;
  534. path = request.path.join(',');
  535. let index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
  536. if (index >= 0) {
  537. host = request.headers[index].value;
  538. }
  539. }
  540. } else if (network === 'kcp') {
  541. let kcp = this.stream.kcp;
  542. type = kcp.type;
  543. path = kcp.seed;
  544. } else if (network === 'ws') {
  545. let ws = this.stream.ws;
  546. path = ws.path;
  547. let index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
  548. if (index >= 0) {
  549. host = ws.headers[index].value;
  550. }
  551. } else if (network === 'http') {
  552. network = 'h2';
  553. path = this.stream.http.path;
  554. host = this.stream.http.host.join(',');
  555. } else if (network === 'quic') {
  556. type = this.stream.quic.type;
  557. host = this.stream.quic.security;
  558. path = this.stream.quic.key;
  559. }
  560. if (this.stream.security === 'tls') {
  561. if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
  562. address = this.stream.tls.server;
  563. }
  564. }
  565. let obj = {
  566. v: '2',
  567. ps: this.remark,
  568. add: address,
  569. port: this.port,
  570. id: this.settings.vmesses[0].id,
  571. aid: this.settings.vmesses[0].alterId,
  572. net: network,
  573. type: type,
  574. host: host,
  575. path: path,
  576. tls: this.stream.security,
  577. };
  578. return 'vmess://' + base64(JSON.stringify(obj, null, 2));
  579. }
  580. genVLESSLink(address = '') {
  581. const settings = this.settings;
  582. const uuid = settings.vlesses[0].id;
  583. const port = this.port;
  584. const type = this.stream.network;
  585. const params = new Map();
  586. params.set("type", this.stream.network);
  587. if (this.stream.is_xtls) {
  588. params.set("security", "xtls");
  589. } else {
  590. params.set("security", this.stream.security);
  591. }
  592. switch (type) {
  593. case "tcp":
  594. const tcp = this.stream.tcp;
  595. if (tcp.type === 'http') {
  596. const request = tcp.request;
  597. params.set("path", request.path.join(','));
  598. const index = request.headers.findIndex(header => header.name.toLowerCase() === 'host');
  599. if (index >= 0) {
  600. const host = request.headers[index].value;
  601. params.set("host", host);
  602. }
  603. }
  604. break;
  605. case "kcp":
  606. const kcp = this.stream.kcp;
  607. params.set("headerType", kcp.type);
  608. params.set("seed", kcp.seed);
  609. break;
  610. case "ws":
  611. const ws = this.stream.ws;
  612. params.set("path", ws.path);
  613. const index = ws.headers.findIndex(header => header.name.toLowerCase() === 'host');
  614. if (index >= 0) {
  615. const host = ws.headers[index].value;
  616. params.set("host", host);
  617. }
  618. break;
  619. case "http":
  620. const http = this.stream.http;
  621. params.set("path", http.path);
  622. params.set("host", http.host);
  623. break;
  624. case "quic":
  625. const quic = this.stream.quic;
  626. params.set("quicSecurity", quic.security);
  627. params.set("key", quic.key);
  628. params.set("headerType", quic.type);
  629. break;
  630. }
  631. if (this.stream.security === 'tls') {
  632. if (!ObjectUtil.isEmpty(this.stream.tls.server)) {
  633. address = this.stream.tls.server;
  634. params.set("sni", address);
  635. }
  636. }
  637. if (this.stream.is_xtls) {
  638. params.set("flow", this.settings.vlesses[0].flow);
  639. }
  640. for (const [key, value] of params) {
  641. switch (key) {
  642. case "host":
  643. case "path":
  644. case "seed":
  645. case "key":
  646. case "alpn":
  647. params.set(key, encodeURIComponent(value));
  648. break;
  649. }
  650. }
  651. const link = `vless://${uuid}@${address}:${port}`;
  652. const url = new URL(link);
  653. for (const [key, value] of params) {
  654. url.searchParams.set(key, value)
  655. }
  656. url.hash = encodeURIComponent(this.remark);
  657. return url.toString();
  658. }
  659. genSSLink(address='') {
  660. let settings = this.settings;
  661. const server = this.stream.tls.server;
  662. if (!ObjectUtil.isEmpty(server)) {
  663. address = server;
  664. }
  665. return 'ss://' + safeBase64(settings.method + ':' + settings.password + '@' + address + ':' + this.port)
  666. + '#' + encodeURIComponent(this.remark);
  667. }
  668. genTrojanLink(address='') {
  669. let settings = this.settings;
  670. return `trojan://${settings.clients[0].password}@${address}:${this.port}#${encodeURIComponent(this.remark)}`;
  671. }
  672. genLink(address='') {
  673. switch (this.protocol) {
  674. case Protocols.VMESS: return this.genVmessLink(address);
  675. case Protocols.VLESS: return this.genVLESSLink(address);
  676. case Protocols.SHADOWSOCKS: return this.genSSLink(address);
  677. case Protocols.TROJAN: return this.genTrojanLink(address);
  678. default: return '';
  679. }
  680. }
  681. static fromJson(json={}) {
  682. return new Inbound(
  683. json.port,
  684. json.listen,
  685. json.protocol,
  686. Inbound.Settings.fromJson(json.protocol, json.settings),
  687. StreamSettings.fromJson(json.streamSettings),
  688. json.tag,
  689. Sniffing.fromJson(json.sniffing),
  690. json.remark,
  691. json.enable,
  692. )
  693. }
  694. toJson() {
  695. let streamSettings;
  696. if (this.protocol === Protocols.VMESS
  697. || this.protocol === Protocols.VLESS
  698. || this.protocol === Protocols.TROJAN
  699. || this.protocol === Protocols.SHADOWSOCKS) {
  700. streamSettings = this.stream.toJson();
  701. }
  702. return {
  703. port: this.port,
  704. listen: this.listen,
  705. protocol: this.protocol,
  706. settings: this.settings instanceof XrayCommonClass ? this.settings.toJson() : this.settings,
  707. streamSettings: streamSettings,
  708. tag: this.tag,
  709. sniffing: this.sniffing.toJson(),
  710. remark: this.remark,
  711. enable: this.enable,
  712. };
  713. }
  714. }
  715. Inbound.Settings = class extends XrayCommonClass {
  716. constructor(protocol) {
  717. super();
  718. this.protocol = protocol;
  719. }
  720. static getSettings(protocol) {
  721. switch (protocol) {
  722. case Protocols.VMESS: return new Inbound.VmessSettings(protocol);
  723. case Protocols.VLESS: return new Inbound.VLESSSettings(protocol);
  724. case Protocols.TROJAN: return new Inbound.TrojanSettings(protocol);
  725. case Protocols.SHADOWSOCKS: return new Inbound.ShadowsocksSettings(protocol);
  726. case Protocols.DOKODEMO: return new Inbound.DokodemoSettings(protocol);
  727. case Protocols.MTPROTO: return new Inbound.MtprotoSettings(protocol);
  728. case Protocols.SOCKS: return new Inbound.SocksSettings(protocol);
  729. case Protocols.HTTP: return new Inbound.HttpSettings(protocol);
  730. default: return null;
  731. }
  732. }
  733. static fromJson(protocol, json) {
  734. switch (protocol) {
  735. case Protocols.VMESS: return Inbound.VmessSettings.fromJson(json);
  736. case Protocols.VLESS: return Inbound.VLESSSettings.fromJson(json);
  737. case Protocols.TROJAN: return Inbound.TrojanSettings.fromJson(json);
  738. case Protocols.SHADOWSOCKS: return Inbound.ShadowsocksSettings.fromJson(json);
  739. case Protocols.DOKODEMO: return Inbound.DokodemoSettings.fromJson(json);
  740. case Protocols.MTPROTO: return Inbound.MtprotoSettings.fromJson(json);
  741. case Protocols.SOCKS: return Inbound.SocksSettings.fromJson(json);
  742. case Protocols.HTTP: return Inbound.HttpSettings.fromJson(json);
  743. default: return null;
  744. }
  745. }
  746. toJson() {
  747. return {};
  748. }
  749. };
  750. Inbound.VmessSettings = class extends Inbound.Settings {
  751. constructor(protocol,
  752. vmesses=[new Inbound.VmessSettings.Vmess()],
  753. disableInsecureEncryption=false) {
  754. super(protocol);
  755. this.vmesses = vmesses;
  756. this.disableInsecure = disableInsecureEncryption;
  757. }
  758. indexOfVmessById(id) {
  759. return this.vmesses.findIndex(vmess => vmess.id === id);
  760. }
  761. addVmess(vmess) {
  762. if (this.indexOfVmessById(vmess.id) >= 0) {
  763. return false;
  764. }
  765. this.vmesses.push(vmess);
  766. }
  767. delVmess(vmess) {
  768. const i = this.indexOfVmessById(vmess.id);
  769. if (i >= 0) {
  770. this.vmesses.splice(i, 1);
  771. }
  772. }
  773. static fromJson(json={}) {
  774. return new Inbound.VmessSettings(
  775. Protocols.VMESS,
  776. json.clients.map(client => Inbound.VmessSettings.Vmess.fromJson(client)),
  777. ObjectUtil.isEmpty(json.disableInsecureEncryption) ? false : json.disableInsecureEncryption,
  778. );
  779. }
  780. toJson() {
  781. return {
  782. clients: Inbound.VmessSettings.toJsonArray(this.vmesses),
  783. disableInsecureEncryption: this.disableInsecure,
  784. };
  785. }
  786. };
  787. Inbound.VmessSettings.Vmess = class extends XrayCommonClass {
  788. constructor(id=RandomUtil.randomUUID(), alterId=64) {
  789. super();
  790. this.id = id;
  791. this.alterId = alterId;
  792. }
  793. static fromJson(json={}) {
  794. return new Inbound.VmessSettings.Vmess(
  795. json.id,
  796. json.alterId,
  797. );
  798. }
  799. };
  800. Inbound.VLESSSettings = class extends Inbound.Settings {
  801. constructor(protocol,
  802. vlesses=[new Inbound.VLESSSettings.VLESS()],
  803. decryption='none',
  804. fallbacks=[],) {
  805. super(protocol);
  806. this.vlesses = vlesses;
  807. this.decryption = decryption;
  808. this.fallbacks = fallbacks;
  809. }
  810. addFallback() {
  811. this.fallbacks.push(new Inbound.VLESSSettings.Fallback());
  812. }
  813. delFallback(index) {
  814. this.fallbacks.splice(index, 1);
  815. }
  816. static fromJson(json={}) {
  817. return new Inbound.VLESSSettings(
  818. Protocols.VLESS,
  819. json.clients.map(client => Inbound.VLESSSettings.VLESS.fromJson(client)),
  820. json.decryption,
  821. Inbound.VLESSSettings.Fallback.fromJson(json.fallbacks),
  822. );
  823. }
  824. toJson() {
  825. return {
  826. clients: Inbound.VLESSSettings.toJsonArray(this.vlesses),
  827. decryption: this.decryption,
  828. fallbacks: Inbound.VLESSSettings.toJsonArray(this.fallbacks),
  829. };
  830. }
  831. };
  832. Inbound.VLESSSettings.VLESS = class extends XrayCommonClass {
  833. constructor(id=RandomUtil.randomUUID(), flow=VLESS_FLOW.DIRECT) {
  834. super();
  835. this.id = id;
  836. this.flow = flow;
  837. }
  838. static fromJson(json={}) {
  839. return new Inbound.VLESSSettings.VLESS(
  840. json.id,
  841. json.flow,
  842. );
  843. }
  844. };
  845. Inbound.VLESSSettings.Fallback = class extends XrayCommonClass {
  846. constructor(name="", alpn='', path='', dest='', xver=0) {
  847. super();
  848. this.name = name;
  849. this.alpn = alpn;
  850. this.path = path;
  851. this.dest = dest;
  852. this.xver = xver;
  853. }
  854. toJson() {
  855. let xver = this.xver;
  856. if (!Number.isInteger(xver)) {
  857. xver = 0;
  858. }
  859. return {
  860. name: this.name,
  861. alpn: this.alpn,
  862. path: this.path,
  863. dest: this.dest,
  864. xver: xver,
  865. }
  866. }
  867. static fromJson(json=[]) {
  868. const fallbacks = [];
  869. for (let fallback of json) {
  870. fallbacks.push(new Inbound.VLESSSettings.Fallback(
  871. fallback.name,
  872. fallback.alpn,
  873. fallback.path,
  874. fallback.dest,
  875. fallback.xver,
  876. ))
  877. }
  878. return fallbacks;
  879. }
  880. };
  881. Inbound.TrojanSettings = class extends Inbound.Settings {
  882. constructor(protocol, clients=[new Inbound.TrojanSettings.Client()]) {
  883. super(protocol);
  884. this.clients = clients;
  885. }
  886. toJson() {
  887. return {
  888. clients: Inbound.TrojanSettings.toJsonArray(this.clients),
  889. };
  890. }
  891. static fromJson(json={}) {
  892. const clients = [];
  893. for (const c of json.clients) {
  894. clients.push(Inbound.TrojanSettings.Client.fromJson(c));
  895. }
  896. return new Inbound.TrojanSettings(Protocols.TROJAN, clients);
  897. }
  898. };
  899. Inbound.TrojanSettings.Client = class extends XrayCommonClass {
  900. constructor(password=RandomUtil.randomSeq(10)) {
  901. super();
  902. this.password = password;
  903. }
  904. toJson() {
  905. return {
  906. password: this.password,
  907. };
  908. }
  909. static fromJson(json={}) {
  910. return new Inbound.TrojanSettings.Client(json.password);
  911. }
  912. };
  913. Inbound.ShadowsocksSettings = class extends Inbound.Settings {
  914. constructor(protocol,
  915. method=SSMethods.AES_256_GCM,
  916. password=RandomUtil.randomSeq(10),
  917. network='tcp,udp'
  918. ) {
  919. super(protocol);
  920. this.method = method;
  921. this.password = password;
  922. this.network = network;
  923. }
  924. static fromJson(json={}) {
  925. return new Inbound.ShadowsocksSettings(
  926. Protocols.SHADOWSOCKS,
  927. json.method,
  928. json.password,
  929. json.network,
  930. );
  931. }
  932. toJson() {
  933. return {
  934. method: this.method,
  935. password: this.password,
  936. network: this.network,
  937. };
  938. }
  939. };
  940. Inbound.DokodemoSettings = class extends Inbound.Settings {
  941. constructor(protocol, address, port, network='tcp,udp') {
  942. super(protocol);
  943. this.address = address;
  944. this.port = port;
  945. this.network = network;
  946. }
  947. static fromJson(json={}) {
  948. return new Inbound.DokodemoSettings(
  949. Protocols.DOKODEMO,
  950. json.address,
  951. json.port,
  952. json.network,
  953. );
  954. }
  955. toJson() {
  956. return {
  957. address: this.address,
  958. port: this.port,
  959. network: this.network,
  960. };
  961. }
  962. };
  963. Inbound.MtprotoSettings = class extends Inbound.Settings {
  964. constructor(protocol, users=[new Inbound.MtprotoSettings.MtUser()]) {
  965. super(protocol);
  966. this.users = users;
  967. }
  968. static fromJson(json={}) {
  969. return new Inbound.MtprotoSettings(
  970. Protocols.MTPROTO,
  971. json.users.map(user => Inbound.MtprotoSettings.MtUser.fromJson(user)),
  972. );
  973. }
  974. toJson() {
  975. return {
  976. users: XrayCommonClass.toJsonArray(this.users),
  977. };
  978. }
  979. };
  980. Inbound.MtprotoSettings.MtUser = class extends XrayCommonClass {
  981. constructor(secret=RandomUtil.randomMTSecret()) {
  982. super();
  983. this.secret = secret;
  984. }
  985. static fromJson(json={}) {
  986. return new Inbound.MtprotoSettings.MtUser(json.secret);
  987. }
  988. };
  989. Inbound.SocksSettings = class extends Inbound.Settings {
  990. constructor(protocol, auth='password', accounts=[new Inbound.SocksSettings.SocksAccount()], udp=false, ip='127.0.0.1') {
  991. super(protocol);
  992. this.auth = auth;
  993. this.accounts = accounts;
  994. this.udp = udp;
  995. this.ip = ip;
  996. }
  997. addAccount(account) {
  998. this.accounts.push(account);
  999. }
  1000. delAccount(index) {
  1001. this.accounts.splice(index, 1);
  1002. }
  1003. static fromJson(json={}) {
  1004. let accounts;
  1005. if (json.auth === 'password') {
  1006. accounts = json.accounts.map(
  1007. account => Inbound.SocksSettings.SocksAccount.fromJson(account)
  1008. )
  1009. }
  1010. return new Inbound.SocksSettings(
  1011. Protocols.SOCKS,
  1012. json.auth,
  1013. accounts,
  1014. json.udp,
  1015. json.ip,
  1016. );
  1017. }
  1018. toJson() {
  1019. return {
  1020. auth: this.auth,
  1021. accounts: this.auth === 'password' ? this.accounts.map(account => account.toJson()) : undefined,
  1022. udp: this.udp,
  1023. ip: this.ip,
  1024. };
  1025. }
  1026. };
  1027. Inbound.SocksSettings.SocksAccount = class extends XrayCommonClass {
  1028. constructor(user=RandomUtil.randomSeq(10), pass=RandomUtil.randomSeq(10)) {
  1029. super();
  1030. this.user = user;
  1031. this.pass = pass;
  1032. }
  1033. static fromJson(json={}) {
  1034. return new Inbound.SocksSettings.SocksAccount(json.user, json.pass);
  1035. }
  1036. };
  1037. Inbound.HttpSettings = class extends Inbound.Settings {
  1038. constructor(protocol, accounts=[new Inbound.HttpSettings.HttpAccount()]) {
  1039. super(protocol);
  1040. this.accounts = accounts;
  1041. }
  1042. addAccount(account) {
  1043. this.accounts.push(account);
  1044. }
  1045. delAccount(index) {
  1046. this.accounts.splice(index, 1);
  1047. }
  1048. static fromJson(json={}) {
  1049. return new Inbound.HttpSettings(
  1050. Protocols.HTTP,
  1051. json.accounts.map(account => Inbound.HttpSettings.HttpAccount.fromJson(account)),
  1052. );
  1053. }
  1054. toJson() {
  1055. return {
  1056. accounts: Inbound.HttpSettings.toJsonArray(this.accounts),
  1057. };
  1058. }
  1059. };
  1060. Inbound.HttpSettings.HttpAccount = class extends XrayCommonClass {
  1061. constructor(user=RandomUtil.randomSeq(10), pass=RandomUtil.randomSeq(10)) {
  1062. super();
  1063. this.user = user;
  1064. this.pass = pass;
  1065. }
  1066. static fromJson(json={}) {
  1067. return new Inbound.HttpSettings.HttpAccount(json.user, json.pass);
  1068. }
  1069. };