@@ -66,28 +66,79 @@ export default {
6666 async fetch ( request , env , _ctx ) {
6767 try {
6868 const { UUID , PROXYIP , SOCKS5 , SOCKS5_RELAY } = env ;
69- userID = UUID || userID ;
70- socks5Address = SOCKS5 || socks5Address ;
71- socks5Relay = SOCKS5_RELAY || socks5Relay ;
69+ const url = new URL ( request . url ) ;
70+
71+ // 为当前请求创建配置副本,避免修改全局变量
72+ const requestConfig = {
73+ userID : UUID || userID ,
74+ socks5Address : SOCKS5 || socks5Address ,
75+ socks5Relay : SOCKS5_RELAY === 'true' || socks5Relay ,
76+ proxyIP : null ,
77+ proxyPort : null ,
78+ enableSocks : false ,
79+ parsedSocks5Address : { }
80+ } ;
81+
82+ // 获取正常URL参数
83+ let urlPROXYIP = url . searchParams . get ( 'proxyip' ) ;
84+ let urlSOCKS5 = url . searchParams . get ( 'socks5' ) ;
85+ let urlSOCKS5_RELAY = url . searchParams . get ( 'socks5_relay' ) ;
86+
87+ // 检查编码在路径中的参数
88+ if ( ! urlPROXYIP && ! urlSOCKS5 && ! urlSOCKS5_RELAY ) {
89+ const encodedParams = parseEncodedQueryParams ( url . pathname ) ;
90+ urlPROXYIP = urlPROXYIP || encodedParams . proxyip ;
91+ urlSOCKS5 = urlSOCKS5 || encodedParams . socks5 ;
92+ urlSOCKS5_RELAY = urlSOCKS5_RELAY || encodedParams . socks5_relay ;
93+ }
94+
95+ // 验证proxyip格式
96+ if ( urlPROXYIP ) {
97+ // 验证格式: domain:port 或 ip:port
98+ const proxyPattern = / ^ ( [ 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 { 1 , 3 } \. \d { 1 , 3 } \. \d { 1 , 3 } \. \d { 1 , 3 } | \[ [ 0 - 9 a - f A - F : ] + \] ) : \d { 1 , 5 } $ / ;
99+ if ( ! proxyPattern . test ( urlPROXYIP ) ) {
100+ console . warn ( '无效的proxyip格式:' , urlPROXYIP ) ;
101+ urlPROXYIP = null ;
102+ }
103+ }
104+
105+ // 验证socks5格式
106+ if ( urlSOCKS5 ) {
107+ // 基本验证 - 可以根据实际格式要求调整
108+ const socks5Pattern = / ^ ( ( [ ^ : @ ] + : [ ^ : @ ] + @ ) ? [ 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 { 1 , 3 } \. \d { 1 , 3 } \. \d { 1 , 3 } \. \d { 1 , 3 } ) : \d { 1 , 5 } $ / ;
109+ if ( ! socks5Pattern . test ( urlSOCKS5 ) ) {
110+ console . warn ( '无效的socks5格式:' , urlSOCKS5 ) ;
111+ urlSOCKS5 = null ;
112+ }
113+ }
114+
115+ // 应用URL参数到当前请求的配置
116+ requestConfig . socks5Address = urlSOCKS5 || requestConfig . socks5Address ;
117+ requestConfig . socks5Relay = urlSOCKS5_RELAY === 'true' || requestConfig . socks5Relay ;
118+
119+ // 记录参数值,用于调试
120+ console . log ( '配置参数:' , requestConfig . userID , requestConfig . socks5Address , requestConfig . socks5Relay , urlPROXYIP ) ;
121+
122+ // Handle proxy configuration for the current request
123+ const proxyConfig = handleProxyConfig ( urlPROXYIP || PROXYIP ) ;
124+ requestConfig . proxyIP = proxyConfig . ip ;
125+ requestConfig . proxyPort = proxyConfig . port ;
72126
73- // Handle proxy configuration
74- const proxyConfig = handleProxyConfig ( PROXYIP ) ;
75- proxyIP = proxyConfig . ip ;
76- proxyPort = proxyConfig . port ;
127+ // 记录最终使用的代理设置
128+ console . log ( '使用代理:' , requestConfig . proxyIP , requestConfig . proxyPort ) ;
77129
78- if ( socks5Address ) {
130+ if ( requestConfig . socks5Address ) {
79131 try {
80- const selectedSocks5 = selectRandomAddress ( socks5Address ) ;
81- parsedSocks5Address = socks5AddressParser ( selectedSocks5 ) ;
82- enableSocks = true ;
132+ const selectedSocks5 = selectRandomAddress ( requestConfig . socks5Address ) ;
133+ requestConfig . parsedSocks5Address = socks5AddressParser ( selectedSocks5 ) ;
134+ requestConfig . enableSocks = true ;
83135 } catch ( err ) {
84136 console . log ( err . toString ( ) ) ;
85- enableSocks = false ;
137+ requestConfig . enableSocks = false ;
86138 }
87139 }
88140
89- const userIDs = userID . includes ( ',' ) ? userID . split ( ',' ) . map ( id => id . trim ( ) ) : [ userID ] ;
90- const url = new URL ( request . url ) ;
141+ const userIDs = requestConfig . userID . includes ( ',' ) ? requestConfig . userID . split ( ',' ) . map ( id => id . trim ( ) ) : [ requestConfig . userID ] ;
91142 const host = request . headers . get ( 'Host' ) ;
92143 const requestedPath = url . pathname . substring ( 1 ) ; // Remove leading slash
93144 const matchingUserID = userIDs . length === 1 ?
@@ -110,7 +161,7 @@ export default {
110161 if ( matchingUserID ) {
111162 if ( url . pathname === `/${ matchingUserID } ` || url . pathname === `/sub/${ matchingUserID } ` ) {
112163 const isSubscription = url . pathname . startsWith ( '/sub/' ) ;
113- const proxyAddresses = PROXYIP ? PROXYIP . split ( ',' ) . map ( addr => addr . trim ( ) ) : proxyIP ;
164+ const proxyAddresses = PROXYIP ? PROXYIP . split ( ',' ) . map ( addr => addr . trim ( ) ) : requestConfig . proxyIP ;
114165 const content = isSubscription ?
115166 GenSub ( matchingUserID , host , proxyAddresses ) :
116167 getConfig ( matchingUserID , host , proxyAddresses ) ;
@@ -129,7 +180,7 @@ export default {
129180 }
130181 return handleDefaultPath ( url , request ) ;
131182 } else {
132- return await ProtocolOverWSHandler ( request ) ;
183+ return await ProtocolOverWSHandler ( request , requestConfig ) ;
133184 }
134185 } catch ( err ) {
135186 return new Response ( err . toString ( ) ) ;
@@ -395,9 +446,22 @@ async function handleDefaultPath(url, request) {
395446/**
396447 * Handles protocol over WebSocket requests by creating a WebSocket pair, accepting the WebSocket connection, and processing the protocol header.
397448 * @param {import("@cloudflare/workers-types").Request } request - The incoming request object
449+ * @param {Object } config - The configuration for this request
398450 * @returns {Promise<Response> } WebSocket response
399451 */
400- async function ProtocolOverWSHandler ( request ) {
452+ async function ProtocolOverWSHandler ( request , config = null ) {
453+ // 如果没有传入配置,使用全局配置
454+ if ( ! config ) {
455+ config = {
456+ userID,
457+ socks5Address,
458+ socks5Relay,
459+ proxyIP,
460+ proxyPort,
461+ enableSocks,
462+ parsedSocks5Address
463+ } ;
464+ }
401465
402466 /** @type {import("@cloudflare/workers-types").WebSocket[] } */
403467 // @ts -ignore
@@ -443,7 +507,7 @@ async function ProtocolOverWSHandler(request) {
443507 rawDataIndex,
444508 ProtocolVersion = new Uint8Array ( [ 0 , 0 ] ) ,
445509 isUDP,
446- } = ProcessProtocolHeader ( chunk , userID ) ;
510+ } = ProcessProtocolHeader ( chunk , config . userID ) ;
447511 address = addressRemote ;
448512 portWithRandomLog = `${ portRemote } --${ Math . random ( ) } ${ isUDP ? 'udp ' : 'tcp '
449513 } `;
@@ -467,7 +531,7 @@ async function ProtocolOverWSHandler(request) {
467531 if ( isDns ) {
468532 return handleDNSQuery ( rawClientData , webSocket , ProtocolResponseHeader , log ) ;
469533 }
470- HandleTCPOutBound ( remoteSocketWapper , addressType , addressRemote , portRemote , rawClientData , webSocket , ProtocolResponseHeader , log ) ;
534+ HandleTCPOutBound ( remoteSocketWapper , addressType , addressRemote , portRemote , rawClientData , webSocket , ProtocolResponseHeader , log , config ) ;
471535 } ,
472536 close ( ) {
473537 log ( `readableWebSocketStream is close` ) ;
@@ -497,15 +561,29 @@ async function ProtocolOverWSHandler(request) {
497561 * @param {WebSocket } webSocket - WebSocket connection
498562 * @param {Uint8Array } protocolResponseHeader - Protocol response header
499563 * @param {Function } log - Logging function
564+ * @param {Object } config - The configuration for this request
500565 */
501- async function HandleTCPOutBound ( remoteSocket , addressType , addressRemote , portRemote , rawClientData , webSocket , protocolResponseHeader , log , ) {
566+ async function HandleTCPOutBound ( remoteSocket , addressType , addressRemote , portRemote , rawClientData , webSocket , protocolResponseHeader , log , config = null ) {
567+ // 如果没有传入配置,使用全局配置
568+ if ( ! config ) {
569+ config = {
570+ userID,
571+ socks5Address,
572+ socks5Relay,
573+ proxyIP,
574+ proxyPort,
575+ enableSocks,
576+ parsedSocks5Address
577+ } ;
578+ }
579+
502580 async function connectAndWrite ( address , port , socks = false ) {
503581 /** @type {import("@cloudflare/workers-types").Socket } */
504582 let tcpSocket ;
505- if ( socks5Relay ) {
506- tcpSocket = await socks5Connect ( addressType , address , port , log )
583+ if ( config . socks5Relay ) {
584+ tcpSocket = await socks5Connect ( addressType , address , port , log , config . parsedSocks5Address )
507585 } else {
508- tcpSocket = socks ? await socks5Connect ( addressType , address , port , log )
586+ tcpSocket = socks ? await socks5Connect ( addressType , address , port , log , config . parsedSocks5Address )
509587 : connect ( {
510588 hostname : address ,
511589 port : port ,
@@ -521,10 +599,11 @@ async function HandleTCPOutBound(remoteSocket, addressType, addressRemote, portR
521599
522600 // if the cf connect tcp socket have no incoming data, we retry to redirect ip
523601 async function retry ( ) {
524- if ( enableSocks ) {
602+ let tcpSocket ;
603+ if ( config . enableSocks ) {
525604 tcpSocket = await connectAndWrite ( addressRemote , portRemote , true ) ;
526605 } else {
527- tcpSocket = await connectAndWrite ( proxyIP || addressRemote , proxyPort || portRemote , false ) ;
606+ tcpSocket = await connectAndWrite ( config . proxyIP || addressRemote , config . proxyPort || portRemote , false ) ;
528607 }
529608 // no matter retry success or not, close websocket
530609 tcpSocket . closed . catch ( error => {
@@ -871,10 +950,13 @@ async function handleDNSQuery(udpChunk, webSocket, protocolResponseHeader, log)
871950 * @param {string } addressRemote - Remote address
872951 * @param {number } portRemote - Remote port
873952 * @param {Function } log - Logging function
953+ * @param {Object } parsedSocks5Addr - Parsed SOCKS5 address information
874954 * @returns {Promise<Socket> } Connected socket
875955 */
876- async function socks5Connect ( addressType , addressRemote , portRemote , log ) {
877- const { username, password, hostname, port } = parsedSocks5Address ;
956+ async function socks5Connect ( addressType , addressRemote , portRemote , log , parsedSocks5Addr = null ) {
957+ // 如果没有传入解析的SOCKS5地址,使用全局的
958+ const { username, password, hostname, port } = parsedSocks5Addr || parsedSocks5Address ;
959+
878960 // Connect to the SOCKS server
879961 const socket = connect ( {
880962 hostname,
@@ -1237,9 +1319,9 @@ function getConfig(userIDs, hostName, proxyIP) {
12371319 <h3>Best IP Configuration</h3>
12381320 <div class="input-group mb-3">
12391321 <select class="form-select" id="proxySelect" onchange="updateProxyConfig()">
1240- ${ typeof proxyIP === 'string' ?
1241- `<option value="${ proxyIP } ">${ proxyIP } </option>` :
1242- Array . from ( proxyIP ) . map ( proxy => `<option value="${ proxy } ">${ proxy } </option>` ) . join ( '' ) }
1322+ ${ typeof proxyIP === 'string' ?
1323+ `<option value="${ proxyIP } ">${ proxyIP } </option>` :
1324+ Array . from ( proxyIP ) . map ( proxy => `<option value="${ proxy } ">${ proxy } </option>` ) . join ( '' ) }
12431325 </select>
12441326 </div>
12451327 <br>
@@ -1407,3 +1489,25 @@ function selectRandomAddress(addresses) {
14071489 addresses ;
14081490 return addressArray [ Math . floor ( Math . random ( ) * addressArray . length ) ] ;
14091491}
1492+
1493+ /**
1494+ * 合并路径查询参数解析为通用函数
1495+ * @param {string } pathname - URL路径
1496+ * @returns {Object } 解析的参数对象
1497+ */
1498+ function parseEncodedQueryParams ( pathname ) {
1499+ const params = { } ;
1500+ if ( pathname . includes ( '%3F' ) ) {
1501+ const encodedParamsMatch = pathname . match ( / % 3 F ( .+ ) $ / ) ;
1502+ if ( encodedParamsMatch ) {
1503+ const encodedParams = encodedParamsMatch [ 1 ] ;
1504+ const paramPairs = encodedParams . split ( '&' ) ;
1505+
1506+ for ( const pair of paramPairs ) {
1507+ const [ key , value ] = pair . split ( '=' ) ;
1508+ if ( value ) params [ key ] = decodeURIComponent ( value ) ;
1509+ }
1510+ }
1511+ }
1512+ return params ;
1513+ }
0 commit comments