@@ -8,13 +8,14 @@ export default {
88 const url = new URL ( request . url ) ;
99 const UA = request . headers . get ( 'User-Agent' ) || 'null' ;
1010 const upgradeHeader = request . headers . get ( 'Upgrade' ) ;
11- const 管理员密码 = env . ADMIN || env . admin || env . PASSWORD || env . password || env . pswd || env . TOKEN || env . KEY ;
11+ const 管理员密码 = env . ADMIN || env . admin || env . PASSWORD || env . password || env . pswd || env . TOKEN || env . KEY || env . UUID || env . uuid ;
1212 const 加密秘钥 = env . KEY || '勿动此默认密钥,有需求请自行通过添加变量KEY进行修改' ;
1313 const userIDMD5 = await MD5MD5 ( 管理员密码 + 加密秘钥 ) ;
1414 const uuidRegex = / ^ [ 0 - 9 a - f A - F ] { 8 } - [ 0 - 9 a - f A - F ] { 4 } - 4 [ 0 - 9 a - f A - F ] { 3 } - [ 8 9 a b A B ] [ 0 - 9 a - f A - F ] { 3 } - [ 0 - 9 a - f A - F ] { 12 } $ / ;
1515 const envUUID = env . UUID || env . uuid ;
1616 const userID = ( envUUID && uuidRegex . test ( envUUID ) ) ? envUUID . toLowerCase ( ) : [ userIDMD5 . slice ( 0 , 8 ) , userIDMD5 . slice ( 8 , 12 ) , '4' + userIDMD5 . slice ( 13 , 16 ) , '8' + userIDMD5 . slice ( 17 , 20 ) , userIDMD5 . slice ( 20 ) ] . join ( '-' ) ;
17- const host = env . HOST ? env . HOST . toLowerCase ( ) . replace ( / ^ h t t p s ? : \/ \/ / , '' ) . split ( '/' ) [ 0 ] . split ( ':' ) [ 0 ] : url . hostname ;
17+ const hosts = env . HOST ? ( await 整理成数组 ( env . HOST ) ) . map ( h => h . toLowerCase ( ) . replace ( / ^ h t t p s ? : \/ \/ / , '' ) . split ( '/' ) [ 0 ] . split ( ':' ) [ 0 ] ) : [ url . hostname ] ;
18+ const host = hosts [ 0 ] ;
1819 if ( env . PROXYIP ) {
1920 const proxyIPs = await 整理成数组 ( env . PROXYIP ) ;
2021 反代IP = proxyIPs [ Math . floor ( Math . random ( ) * proxyIPs . length ) ] ;
@@ -229,53 +230,68 @@ export default {
229230 if ( 订阅类型 === 'mixed' ) {
230231 const 节点路径 = config_JSON . 启用0RTT ? config_JSON . PATH + '?ed=2560' : config_JSON . PATH ;
231232 const TLS分片参数 = config_JSON . TLS分片 == 'Shadowrocket' ? `&fragment=${ encodeURIComponent ( '1,40-60,30-50,tlshello' ) } ` : config_JSON . TLS分片 == 'Happ' ? `&fragment=${ encodeURIComponent ( '3,1,tlshello' ) } ` : '' ;
232- const 完整优选列表 = config_JSON . 优选订阅生成 . 本地IP库 . 随机IP ? ( await 生成随机IP ( request , config_JSON . 优选订阅生成 . 本地IP库 . 随机数量 , config_JSON . 优选订阅生成 . 本地IP库 . 指定端口 ) ) [ 0 ] : await env . KV . get ( 'ADD.txt' ) ? await 整理成数组 ( await env . KV . get ( 'ADD.txt' ) ) : ( await 生成随机IP ( request , config_JSON . 优选订阅生成 . 本地IP库 . 随机数量 , config_JSON . 优选订阅生成 . 本地IP库 . 指定端口 ) ) [ 0 ] ;
233- const 优选API = [ ] , 优选IP = [ ] , 其他节点 = [ ] ;
234- for ( const 元素 of 完整优选列表 ) {
235- if ( 元素 . toLowerCase ( ) . startsWith ( 'https://' ) ) 优选API . push ( 元素 ) ;
236- else if ( 元素 . toLowerCase ( ) . includes ( '://' ) ) 其他节点 . push ( 元素 ) ;
237- else 优选IP . push ( 元素 ) ;
238- }
239- const 其他节点LINK = 其他节点 . join ( '\n' ) + '\n' ;
233+ let 完整优选IP = [ ] , 其他节点LINK = '' ;
234+
240235 if ( ! url . searchParams . has ( 'sub' ) && config_JSON . 优选订阅生成 . local ) { // 本地生成订阅
236+ const 完整优选列表 = config_JSON . 优选订阅生成 . 本地IP库 . 随机IP ? ( await 生成随机IP ( request , config_JSON . 优选订阅生成 . 本地IP库 . 随机数量 , config_JSON . 优选订阅生成 . 本地IP库 . 指定端口 ) ) [ 0 ] : await env . KV . get ( 'ADD.txt' ) ? await 整理成数组 ( await env . KV . get ( 'ADD.txt' ) ) : ( await 生成随机IP ( request , config_JSON . 优选订阅生成 . 本地IP库 . 随机数量 , config_JSON . 优选订阅生成 . 本地IP库 . 指定端口 ) ) [ 0 ] ;
237+ const 优选API = [ ] , 优选IP = [ ] , 其他节点 = [ ] ;
238+ for ( const 元素 of 完整优选列表 ) {
239+ if ( 元素 . toLowerCase ( ) . startsWith ( 'https://' ) ) 优选API . push ( 元素 ) ;
240+ else if ( 元素 . toLowerCase ( ) . includes ( '://' ) ) 其他节点 . push ( 元素 ) ;
241+ else 优选IP . push ( 元素 ) ;
242+ }
243+ 其他节点LINK = 其他节点 . join ( '\n' ) + '\n' ;
241244 const 优选API的IP = await 请求优选API ( 优选API ) ;
242- const 完整优选IP = [ ...new Set ( 优选IP . concat ( 优选API的IP ) ) ] ;
243- 订阅内容 = 完整优选IP . map ( 原始地址 => {
244- // 统一正则: 匹配 域名/IPv4/IPv6地址 + 可选端口 + 可选备注
245- // 示例:
246- // - 域名: hj.xmm1993.top:2096#备注 或 example.com
247- // - IPv4: 166.0.188.128:443#Los Angeles 或 166.0.188.128
248- // - IPv6: [2606:4700::]:443#CMCC 或 [2606:4700::]
249- const regex = / ^ ( \[ [ \d a - f A - F : ] + \] | [ \d . ] + | [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 - ] * [ a - z A - Z 0 - 9 ] ) ? (?: \. [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 - ] * [ a - z A - Z 0 - 9 ] ) ? ) * ) (?: : ( \d + ) ) ? (?: # ( .+ ) ) ? $ / ;
250- const match = 原始地址 . match ( regex ) ;
251-
252- let 节点地址 , 节点端口 = "443" , 节点备注 ;
253-
254- if ( match ) {
255- 节点地址 = match [ 1 ] ; // IP地址或域名(可能带方括号)
256- 节点端口 = match [ 2 ] || "443" ; // 端口,默认443
257- 节点备注 = match [ 3 ] || 节点地址 ; // 备注,默认为地址本身
258- } else {
259- // 不规范的格式,跳过处理返回null
260- console . warn ( `[订阅内容] 不规范的IP格式已忽略: ${ 原始地址 } ` ) ;
261- return null ;
262- }
263- const 节点HOST = 随机替换通配符 ( host ) ;
264- return `${ 协议类型 } ://${ config_JSON . UUID } @${ 节点地址 } :${ 节点端口 } ?security=tls&type=${ config_JSON . 传输协议 } &host=${ 节点HOST } &sni=${ 节点HOST } &path=${ encodeURIComponent ( config_JSON . 随机路径 ? 随机路径 ( ) + 节点路径 : 节点路径 ) + TLS分片参数 } &encryption=none${ config_JSON . 跳过证书验证 ? '&allowInsecure=1' : '' } #${ encodeURIComponent ( 节点备注 ) } ` ;
265- } ) . filter ( item => item !== null ) . join ( '\n' ) ;
266- 订阅内容 = btoa ( 其他节点LINK + 订阅内容 ) ;
245+ 完整优选IP = [ ...new Set ( 优选IP . concat ( 优选API的IP ) ) ] ;
267246 } else { // 优选订阅生成器
268247 let 优选订阅生成器HOST = url . searchParams . get ( 'sub' ) || config_JSON . 优选订阅生成 . SUB ;
269248 优选订阅生成器HOST = 优选订阅生成器HOST && ! / ^ h t t p s ? : \/ \/ / i. test ( 优选订阅生成器HOST ) ? `https://${ 优选订阅生成器HOST } ` : 优选订阅生成器HOST ;
270- const 优选订阅生成器URL = `${ 优选订阅生成器HOST } /sub?host=example.com&${ 协议类型 === ( 'v' + 'le' + 'ss' ) ? ' uuid' : 'pw' } =00000000-0000-4000-8000-000000000000&path= ${ encodeURIComponent ( config_JSON . 随机路径 ? 随机路径 ( ) + 节点路径 : 节点路径 ) + TLS分片参数 } &type= ${ config_JSON . 传输协议 } ` ;
249+ const 优选订阅生成器URL = `${ 优选订阅生成器HOST } /sub?host=example.com&uuid=00000000-0000-4000-8000-000000000000` ;
271250 try {
272251 const response = await fetch ( 优选订阅生成器URL , { headers : { 'User-Agent' : 'v2rayN/edge' + 'tunnel (https://github.com/cmliu/edge' + 'tunnel)' } } ) ;
273- if ( response . ok ) 订阅内容 = btoa ( 其他节点LINK + atob ( await response . text ( ) ) ) ;
274- else return new Response ( '优选订阅生成器异常:' + response . statusText , { status : response . status } ) ;
252+ if ( ! response . ok ) return new Response ( '优选订阅生成器异常:' + response . statusText , { status : response . status } ) ;
253+ const 优选订阅生成器返回订阅内容 = atob ( await response . text ( ) ) ;
254+ const 订阅行列表 = 优选订阅生成器返回订阅内容 . includes ( '\r\n' ) ? 优选订阅生成器返回订阅内容 . split ( '\r\n' ) : 优选订阅生成器返回订阅内容 . split ( '\n' ) ;
255+ for ( const 行内容 of 订阅行列表 ) {
256+ if ( ! 行内容 . trim ( ) ) continue ; // 跳过空行
257+ if ( 行内容 . includes ( '00000000-0000-4000-8000-000000000000' ) && 行内容 . includes ( 'example.com' ) ) { // 这是优选IP行,提取 域名:端口#备注
258+ const 地址匹配 = 行内容 . match ( / : \/ \/ [ ^ @ ] + @ ( [ ^ ? ] + ) / ) ;
259+ if ( 地址匹配 ) {
260+ let 地址端口 = 地址匹配 [ 1 ] , 备注 = '' ; // 域名:端口 或 IP:端口
261+ const 备注匹配 = 行内容 . match ( / # ( .+ ) $ / ) ;
262+ if ( 备注匹配 ) 备注 = '#' + decodeURIComponent ( 备注匹配 [ 1 ] ) ;
263+ 完整优选IP . push ( 地址端口 + 备注 ) ;
264+ }
265+ } else 其他节点LINK += 行内容 + '\n' ;
266+ }
275267 } catch ( error ) {
276268 return new Response ( '优选订阅生成器异常:' + error . message , { status : 403 } ) ;
277269 }
278270 }
271+
272+ 订阅内容 = 完整优选IP . map ( 原始地址 => {
273+ // 统一正则: 匹配 域名/IPv4/IPv6地址 + 可选端口 + 可选备注
274+ // 示例:
275+ // - 域名: hj.xmm1993.top:2096#备注 或 example.com
276+ // - IPv4: 166.0.188.128:443#Los Angeles 或 166.0.188.128
277+ // - IPv6: [2606:4700::]:443#CMCC 或 [2606:4700::]
278+ const regex = / ^ ( \[ [ \d a - f A - F : ] + \] | [ \d . ] + | [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 - ] * [ a - z A - Z 0 - 9 ] ) ? (?: \. [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 - ] * [ a - z A - Z 0 - 9 ] ) ? ) * ) (?: : ( \d + ) ) ? (?: # ( .+ ) ) ? $ / ;
279+ const match = 原始地址 . match ( regex ) ;
280+
281+ let 节点地址 , 节点端口 = "443" , 节点备注 ;
282+
283+ if ( match ) {
284+ 节点地址 = match [ 1 ] ; // IP地址或域名(可能带方括号)
285+ 节点端口 = match [ 2 ] || "443" ; // 端口,默认443
286+ 节点备注 = match [ 3 ] || 节点地址 ; // 备注,默认为地址本身
287+ } else {
288+ // 不规范的格式,跳过处理返回null
289+ console . warn ( `[订阅内容] 不规范的IP格式已忽略: ${ 原始地址 } ` ) ;
290+ return null ;
291+ }
292+
293+ return `${ 协议类型 } ://00000000-0000-4000-8000-000000000000@${ 节点地址 } :${ 节点端口 } ?security=tls&type=${ config_JSON . 传输协议 } &host=example.com&sni=example.com&path=${ encodeURIComponent ( config_JSON . 随机路径 ? 随机路径 ( ) + 节点路径 : 节点路径 ) + TLS分片参数 } &encryption=none${ config_JSON . 跳过证书验证 ? '&allowInsecure=1' : '' } #${ encodeURIComponent ( 节点备注 ) } ` ;
294+ } ) . filter ( item => item !== null ) . join ( '\n' ) ;
279295 } else { // 订阅转换
280296 const 订阅转换URL = `${ config_JSON . 订阅转换配置 . SUBAPI } /sub?target=${ 订阅类型 } &url=${ encodeURIComponent ( url . protocol + '//' + url . host + '/sub?target=mixed&token=' + 订阅TOKEN + ( url . searchParams . has ( 'sub' ) && url . searchParams . get ( 'sub' ) != '' ? `&sub=${ url . searchParams . get ( 'sub' ) } ` : '' ) ) } &config=${ encodeURIComponent ( config_JSON . 订阅转换配置 . SUBCONFIG ) } &emoji=${ config_JSON . 订阅转换配置 . SUBEMOJI } &scv=${ config_JSON . 跳过证书验证 } ` ;
281297 try {
@@ -288,10 +304,11 @@ export default {
288304 return new Response ( '订阅转换后端异常:' + error . message , { status : 403 } ) ;
289305 }
290306 }
291- if ( 订阅类型 === 'mixed' ) {
292- 订阅内容 = 批量替换域名 ( atob ( 订阅内容 ) . replace ( / 0 0 0 0 0 0 0 0 - 0 0 0 0 - 4 0 0 0 - 8 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 / g, config_JSON . UUID ) , host ) ;
293- if ( ! ua . includes ( 'mozilla' ) ) 订阅内容 = btoa ( 订阅内容 ) ;
294- } else 订阅内容 = 批量替换域名 ( 订阅内容 . replace ( / 0 0 0 0 0 0 0 0 - 0 0 0 0 - 4 0 0 0 - 8 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 / g, config_JSON . UUID ) , host ) ;
307+
308+ if ( ! ua . includes ( 'subconverter' ) ) 订阅内容 = 批量替换域名 ( 订阅内容 . replace ( / 0 0 0 0 0 0 0 0 - 0 0 0 0 - 4 0 0 0 - 8 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 / g, config_JSON . UUID ) , config_JSON . HOSTS )
309+
310+ if ( ! ua . includes ( 'mozilla' ) && 订阅类型 === 'mixed' ) 订阅内容 = btoa ( 订阅内容 ) ;
311+
295312 if ( 订阅类型 === 'singbox' ) {
296313 订阅内容 = JSON . stringify ( JSON . parse ( 订阅内容 ) , null , 2 ) ;
297314 responseHeaders [ "content-type" ] = 'application/json; charset=utf-8' ;
@@ -502,7 +519,8 @@ async function forwardataTCP(host, portNum, rawData, ws, respHeader, remoteConnW
502519 connectStreams ( newSocket , ws , respHeader , null ) ;
503520 }
504521
505- if ( 启用SOCKS5反代 && 启用SOCKS5全局反代 ) {
522+ const 验证SOCKS5白名单 = ( addr ) => SOCKS5白名单 . some ( p => new RegExp ( `^${ p . replace ( / \* / g, '.*' ) } $` , 'i' ) . test ( addr ) ) ;
523+ if ( 启用SOCKS5反代 && ( 启用SOCKS5全局反代 || 验证SOCKS5白名单 ( host ) ) ) {
506524 try {
507525 await connecttoPry ( ) ;
508526 } catch ( err ) {
@@ -831,21 +849,23 @@ function 随机替换通配符(h) {
831849 } ) ;
832850}
833851
834- function 批量替换域名 ( 内容 , host , 每组数量 = 2 ) {
852+ function 批量替换域名 ( 内容 , hosts , 每组数量 = 2 ) {
835853 let count = 0 , currentRandomHost = null ;
836854 return 内容 . replace ( / e x a m p l e \. c o m / g, ( ) => {
837- if ( count % 每组数量 === 0 ) currentRandomHost = 随机替换通配符 ( host ) ;
855+ if ( count % 每组数量 === 0 ) currentRandomHost = 随机替换通配符 ( hosts [ Math . floor ( Math . random ( ) * hosts . length ) ] ) ;
838856 count ++ ;
839857 return currentRandomHost ;
840858 } ) ;
841859}
842860
843861async function 读取config_JSON ( env , hostname , userID , path , 重置配置 = false ) {
844- const host = 随机替换通配符 ( hostname ) ;
862+ //const host = 随机替换通配符(hostname);
863+ const host = hostname ;
845864 const 初始化开始时间 = performance . now ( ) ;
846865 const 默认配置JSON = {
847866 TIME : new Date ( ) . toISOString ( ) ,
848867 HOST : host ,
868+ HOSTS : [ hostname ] ,
849869 UUID : userID ,
850870 协议类型 : "v" + "le" + "ss" ,
851871 传输协议 : "ws" ,
@@ -912,6 +932,8 @@ async function 读取config_JSON(env, hostname, userID, path, 重置配置 = fal
912932 }
913933
914934 config_JSON . HOST = host ;
935+ if ( ! config_JSON . HOSTS ) config_JSON . HOSTS = [ hostname ] ;
936+ if ( env . HOST ) config_JSON . HOSTS = ( await 整理成数组 ( env . HOST ) ) . map ( h => h . toLowerCase ( ) . replace ( / ^ h t t p s ? : \/ \/ / , '' ) . split ( '/' ) [ 0 ] . split ( ':' ) [ 0 ] ) ;
915937 config_JSON . UUID = userID ;
916938 config_JSON . PATH = path ? ( path . startsWith ( '/' ) ? path : '/' + path ) : ( config_JSON . 反代 . SOCKS5 . 启用 ? ( '/' + config_JSON . 反代 . SOCKS5 . 启用 + ( config_JSON . 反代 . SOCKS5 . 全局 ? '://' : '=' ) + config_JSON . 反代 . SOCKS5 . 账号 ) : ( config_JSON . 反代 . PROXYIP === 'auto' ? '/' : `/proxyip=${ config_JSON . 反代 . PROXYIP } ` ) ) ;
917939 const TLS分片参数 = config_JSON . TLS分片 == 'Shadowrocket' ? `&fragment=${ encodeURIComponent ( '1,40-60,30-50,tlshello' ) } ` : config_JSON . TLS分片 == 'Happ' ? `&fragment=${ encodeURIComponent ( '3,1,tlshello' ) } ` : '' ;
0 commit comments