-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy path_worker.js
More file actions
4 lines (4 loc) · 13.1 KB
/
_worker.js
File metadata and controls
4 lines (4 loc) · 13.1 KB
1
2
3
4
// Time is: 2026-02-24T00:01:01.404Z
import{connect as N}from"cloudflare:sockets";var W=null,H=e=>atob(e),j="https://nirevil.github.io/zizifn/",G={userID:"bb813507-8ed8-40c0-9b64-3eba878349a2",proxyIPs:["nima.nscl.ir:443"],scamalytics:{username:"nimasecure999",apiKey:"ce75d58f98849753077a270e6013a036d6f4a6c562fd74c960960ae7a7087b40",baseUrl:"https://api12.scamalytics.com/v3/"},socks5:{enabled:!1,relayMode:!1,address:""},fromEnv(e){let t=e.PROXYIP||this.proxyIPs[Math.floor(Math.random()*this.proxyIPs.length)],[a,r="443"]=t.split(":");return{userID:e.UUID||this.userID,proxyIP:a,proxyPort:r,proxyAddress:t,scamalytics:{username:e.SCAMALYTICS_USERNAME||this.scamalytics.username,apiKey:e.SCAMALYTICS_API_KEY||this.scamalytics.apiKey,baseUrl:e.SCAMALYTICS_BASEURL||this.scamalytics.baseUrl},socks5:{enabled:!!e.SOCKS5,relayMode:e.SOCKS5_RELAY==="true"||this.socks5.relayMode,address:e.SOCKS5||this.socks5.address}}}};async function M(e,t={},a=4e3){let r=new AbortController,n=setTimeout(()=>r.abort(),a);try{return await fetch(e,{...t,signal:r.signal})}finally{clearTimeout(n)}}var g={ED_PARAMS:{ed:2560,eh:"Sec-WebSocket-Protocol"},AT_SYMBOL:"@",VLESS_PROTOCOL:H("dmxlc3M="),WS_READY_STATE_OPEN:1,WS_READY_STATE_CLOSING:2};function $(e=28,t=""){let a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",r="";for(let n=0;n<e;n++)r+=a.charAt(Math.floor(Math.random()*a.length));return`/${r}${t?`?${t}`:""}`}var z={xray:{tls:{path:()=>$(12,"ed=2048"),security:"tls",fp:"chrome",alpn:"http/1.1",extra:{}},tcp:{path:()=>$(12,"ed=2560"),security:"none",fp:"chrome",extra:{}}},sb:{tls:{path:()=>$(18),security:"tls",fp:"chrome",alpn:"http/1.1",extra:g.ED_PARAMS},tcp:{path:()=>$(18),security:"none",fp:"chrome",extra:g.ED_PARAMS}}};function F(e,t){return`${e}-${t.toUpperCase()}`}function X({userID:e,address:t,port:a,host:r,path:n,security:c,sni:s,fp:o,alpn:i,extra:d={},name:h}){let u=new URLSearchParams({type:H("d3M="),host:r,path:n});c&&(u.set("security",c),c==="tls"&&u.set("allowInsecure","1")),s&&u.set("sni",s),o&&u.set("fp",o),i&&u.set("alpn",i);for(let[l,p]of Object.entries(d))u.set(l,p);return`${g.VLESS_PROTOCOL}://${e}@${t}:${a}?${u.toString()}#${encodeURIComponent(h)}`}function x({core:e,proto:t,userID:a,hostName:r,address:n,port:c,tag:s}){let o=z[e][t];return X({userID:a,address:n,port:c,host:r,path:o.path(),security:o.security,sni:o.security==="tls"?r:void 0,fp:o.fp,alpn:o.alpn,extra:o.extra,name:F(s,t)})}var I=e=>e[Math.floor(Math.random()*e.length)];async function K(e,t,a,r,n){let s=new URL(e.url).searchParams.get("name"),o={total_TB:380,base_GB:42e3,daily_growth_GB:250,expire_date:"2028-4-20"},i=[r,"creativecommons.org","2027.victoriacross.ir","www.speedtest.net","sky.rethinkdns.com","chat.openai.com","cfip.xxxxxxxx.tk","go.inmobi.com","singapore.com","www.visa.com","www.wto.org","chatgpt.com","yakamoz.nscl.ir","nodejs.org","zzula.ir","csgo.com","fbi.gov"],d=[443,8443,2053,2083,2087,2096],h=[80,8080,8880,2052,2082,2086,2095],u=[],l=r.endsWith(".pages.dev");i.forEach((S,E)=>{u.push(x({core:t,proto:"tls",userID:a,hostName:r,address:S,port:I(d),tag:`Domain${E+1}`})),l||u.push(x({core:t,proto:"tcp",userID:a,hostName:r,address:S,port:I(h),tag:`Domain${E+1}`}))});try{let S=caches.default,E=new Request("https://cf-ip-cache.local"),P=await S.match(E);if(!P){let U=await M("https://raw.githubusercontent.com/NiREvil/vless/refs/heads/main/Cloudflare-IPs.json",{},4e3);U.ok&&(P=new Response(await U.text(),{headers:{"Cache-Control":"public, max-age=86400"}}),n.waitUntil(S.put(E,P.clone())))}if(P){let U=await P.json();[...U.ipv4||[],...U.ipv6||[]].slice(0,20).map(_=>_.ip).forEach((_,v)=>{let B=_.includes(":")?`[${_}]`:_;u.push(x({core:t,proto:"tls",userID:a,hostName:r,address:B,port:I(d),tag:`IP${v+1}`})),l||u.push(x({core:t,proto:"tcp",userID:a,hostName:r,address:B,port:I(h),tag:`IP${v+1}`}))})}}catch(S){console.error("Cached IP fetch failed",S)}let p=1024*1024*1024,f=1024*p,y=o.total_TB*f,m=o.base_GB*p,b=new Date,R=(b.getHours()+b.getMinutes()/60)/24*(o.daily_growth_GB*p),L=m+R/2,C=m+R/2,k=Math.floor(new Date(o.expire_date).getTime()/1e3),A={"Content-Type":"text/plain;charset=utf-8","Profile-Update-Interval":"6","Subscription-Userinfo":`upload=${Math.round(C)}; download=${Math.round(L)}; total=${y}; expire=${k}`};return s&&(A["Profile-Title"]=s),new Response(btoa(u.join(`
`)),{headers:A})}async function J(e,t){let a=new WebSocketPair,[r,n]=Object.values(a);n.accept();let c="",s="",o=null,i=(l,p)=>{console.log(`[${c}:${s}] ${l}`,p||"")},d=e.headers.get("Sec-WebSocket-Protocol")||"",h=Z(n,d,i),u={value:null};return h.pipeTo(new WritableStream({async write(l,p){if(o)return o.write(l);if(u.value){let A=u.value.writable.getWriter();await A.write(l),A.releaseLock();return}let{hasError:f,message:y,addressType:m,portRemote:b=443,addressRemote:T="",rawDataIndex:R,ProtocolVersion:L=new Uint8Array([0,0]),isUDP:C}=ee(l,t.userID);if(c=T,s=`${b}--${Math.random()} ${C?"udp":"tcp"} `,f)throw new Error(y);let k=new Uint8Array([L[0],0]),O=l.slice(R);if(C){if(b===53)o=(await ne(n,k,i)).write,o(O);else throw new Error("UDP proxy is only enabled for DNS (port 53)");return}Q(u,m,T,b,O,n,k,i,t)},close(){i("readableWebSocketStream closed")},abort(l){i("readableWebSocketStream aborted",l)}})).catch(l=>{console.error("Pipeline failed:",l.stack||l)}),new Response(null,{status:101,webSocket:r})}function q(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}async function Q(e,t,a,r,n,c,s,o,i){async function d(l,p,f=!1){let y;i.socks5Relay?y=await Y(t,l,p,o,i.parsedSocks5Address):y=f?await Y(t,l,p,o,i.parsedSocks5Address):N({hostname:l,port:p}),e.value=y,o(`connected to ${l}:${p}`);let m=y.writable.getWriter();return await m.write(n),m.releaseLock(),y}async function h(){let l=i.enableSocks?await d(a,r,!0):await d(i.proxyIP||a,i.proxyPort||r,!1);l.closed.catch(p=>console.log("retry tcpSocket closed error",p)).finally(()=>D(c)),V(l,c,s,null,o)}let u=await d(a,r);V(u,c,s,h,o)}function Z(e,t,a){return new ReadableStream({start(r){e.addEventListener("message",s=>r.enqueue(s.data)),e.addEventListener("close",()=>{D(e),r.close()}),e.addEventListener("error",s=>{a("webSocketServer has error"),r.error(s)});let{earlyData:n,error:c}=te(t);c?r.error(c):n&&r.enqueue(n)},pull(r){},cancel(r){a(`ReadableStream was canceled, due to ${r}`),D(e)}})}function ee(e,t){if(e.byteLength<24)return{hasError:!0,message:"invalid data"};let a=new DataView(e),r=a.getUint8(0),n=ae(new Uint8Array(e.slice(1,17))),c=t.split(",").map(y=>y.trim());if(!n)return{hasError:!0,message:"invalid uuid format"};if(!c.some(y=>n===y))return{hasError:!0,message:"invalid user"};let o=a.getUint8(17),i=a.getUint8(18+o);if(i!==1&&i!==2)return{hasError:!0,message:`command ${i} is not supported`};let d=18+o+1,h=a.getUint16(d),u=a.getUint8(d+2),l,p,f;switch(u){case 1:p=4,f=d+3,l=new Uint8Array(e.slice(f,f+p)).join(".");break;case 2:p=a.getUint8(d+3),f=d+4,l=new TextDecoder().decode(e.slice(f,f+p));break;case 3:p=16,f=d+3,l=Array.from({length:8},(y,m)=>a.getUint16(f+m*2).toString(16)).join(":");break;default:return{hasError:!0,message:`invalid addressType: ${u}`}}return l?{hasError:!1,addressRemote:l,addressType:u,portRemote:h,rawDataIndex:f+p,ProtocolVersion:new Uint8Array([r]),isUDP:i===2}:{hasError:!0,message:`addressValue is empty, addressType is ${u}`}}async function V(e,t,a,r,n){let c=!1;try{await e.readable.pipeTo(new WritableStream({async write(s){if(t.readyState!==g.WS_READY_STATE_OPEN)throw new Error("WebSocket is not open");c=!0;let o=a?await new Blob([a,s]).arrayBuffer():s;t.send(o),a=null},close(){n("Remote connection readable closed.")},abort(s){console.error("Remote connection readable aborted:",s)}}))}catch(s){console.error("RemoteSocketToWS error:",s.stack||s),D(t)}!c&&r&&(n("No incoming data, retrying"),await r())}function te(e){if(!e)return{earlyData:null,error:null};try{let t=atob(e.replace(/-/g,"+").replace(/_/g,"/")),a=new ArrayBuffer(t.length),r=new Uint8Array(a);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n);return{earlyData:a,error:null}}catch(t){return{earlyData:null,error:t}}}function D(e){try{(e.readyState===g.WS_READY_STATE_OPEN||e.readyState===g.WS_READY_STATE_CLOSING)&&e.close()}catch(t){console.error("safeCloseWebSocket error:",t)}}var w=Array.from({length:256},(e,t)=>(t+256).toString(16).slice(1));function re(e,t=0){return(w[e[t]]+w[e[t+1]]+w[e[t+2]]+w[e[t+3]]+"-"+w[e[t+4]]+w[e[t+5]]+"-"+w[e[t+6]]+w[e[t+7]]+"-"+w[e[t+8]]+w[e[t+9]]+"-"+w[e[t+10]]+w[e[t+11]]+w[e[t+12]]+w[e[t+13]]+w[e[t+14]]+w[e[t+15]]).toLowerCase()}function ae(e,t=0){let a=re(e,t);return q(a)?a:""}async function ne(e,t,a){let r=!1,n=new TransformStream({transform(s,o){for(let i=0;i<s.byteLength;){let d=s.slice(i,i+2),h=new DataView(d).getUint16(0),u=new Uint8Array(s.slice(i+2,i+2+h));i=i+2+h,o.enqueue(u)}}});n.readable.pipeTo(new WritableStream({async write(s){try{let i=await(await M("https://1.1.1.1/dns-query",{method:"POST",headers:{"content-type":"application/dns-message"},body:s},3e3)).arrayBuffer(),d=i.byteLength,h=new Uint8Array([d>>8&255,d&255]);e.readyState===g.WS_READY_STATE_OPEN&&(r?e.send(await new Blob([h,i]).arrayBuffer()):(e.send(await new Blob([t,h,i]).arrayBuffer()),r=!0))}catch(o){a("DNS query error: "+o)}}})).catch(s=>a("DNS stream error: "+s));let c=n.writable.getWriter();return{write:s=>c.write(s)}}async function Y(e,t,a,r,n){let{username:c,password:s,hostname:o,port:i}=n,d=N({hostname:o,port:i}),h=d.writable.getWriter(),u=d.readable.getReader(),l=new TextEncoder;await h.write(new Uint8Array([5,2,0,2]));let p=(await u.read()).value;if(p[0]!==5||p[1]===255)throw new Error("SOCKS5 server connection failed.");if(p[1]===2){if(!c||!s)throw new Error("SOCKS5 auth credentials not provided.");let m=new Uint8Array([1,c.length,...l.encode(c),s.length,...l.encode(s)]);if(await h.write(m),p=(await u.read()).value,p[0]!==1||p[1]!==0)throw new Error("SOCKS5 authentication failed.")}let f;switch(e){case 1:f=new Uint8Array([1,...t.split(".").map(Number)]);break;case 2:f=new Uint8Array([3,t.length,...l.encode(t)]);break;case 3:f=new Uint8Array([4,...t.split(":").flatMap(m=>[parseInt(m.slice(0,2),16),parseInt(m.slice(2),16)])]);break;default:throw new Error(`Invalid addressType for SOCKS5: ${e}`)}let y=new Uint8Array([5,1,0,...f,a>>8,a&255]);if(await h.write(y),p=(await u.read()).value,p[1]!==0)throw new Error("Failed to open SOCKS5 connection.");return h.releaseLock(),u.releaseLock(),d}function se(e){try{let[t,a]=e.includes("@")?e.split("@"):[null,e],[r,n]=a.split(":"),c=parseInt(n,10);if(!r||isNaN(c))throw new Error;let s,o;if(t&&([s,o]=t.split(":"),!s))throw new Error;return{username:s,password:o,hostname:r,port:c}}catch{throw new Error("Invalid SOCKS5 address format.")}}async function oe(e,t){let r=new URL(e.url).searchParams.get("ip");if(!r)return new Response(JSON.stringify({error:"Missing IP"}),{status:400,headers:{"Content-Type":"application/json"}});let{username:n,apiKey:c,baseUrl:s}=t.scamalytics;if(!n||!c)return new Response(JSON.stringify({error:"Scamalytics API not configured"}),{status:500,headers:{"Content-Type":"application/json"}});let o=`${s}${n}/?key=${c}&ip=${r}`,i=new Headers({"Content-Type":"application/json","Access-Control-Allow-Origin":"*"});try{let h=await(await fetch(o)).json();return new Response(JSON.stringify(h),{headers:i})}catch(d){return new Response(JSON.stringify({error:d.toString()}),{status:500,headers:i})}}async function ie(e,t,a){let r=x({core:"xray",proto:"tls",userID:e,hostName:t,address:t,port:443,tag:`${t}-Xray`}),n=x({core:"sb",proto:"tls",userID:e,hostName:t,address:t,port:443,tag:`${t}-Singbox`}),c=encodeURIComponent("INDEX"),s=`https://${t}/xray/${e}?name=${c}`,o=`https://${t}/sb/${e}?name=${c}`;try{let i=await M(j);if(!i.ok)throw new Error(`Failed to load HTML from GitHub Pages: ${i.status}`);let d=await i.text();return d=d.replace(/{{PROXY_ADDRESS}}/g,a).replace(/{{CONFIG_DREAM}}/g,r).replace(/{{CONFIG_FREEDOM}}/g,n).replace(/{{URL_HIDDIFY}}/g,`hiddify://install-config?url=${encodeURIComponent(s)}`).replace(/{{URL_V2RAYNG}}/g,`v2rayng://install-config?url=${encodeURIComponent(s)}#${c}`).replace(/{{URL_CLASH}}/g,`clash://install-config?url=${encodeURIComponent(`https://revil-sub.pages.dev/sub/clash-meta?url=${o}`)}`).replace(/{{URL_EXCLAVE}}/g,`sn://subscription?url=${encodeURIComponent(o)}&name=${c}`),new Response(d,{headers:{"Content-Type":"text/html; charset=utf-8"}})}catch(i){return new Response(`Error rendering panel: ${i.message}`,{status:500,headers:{"Content-Type":"text/plain"}})}}var de={async fetch(e,t,a){try{let r=G.fromEnv(t),n=new URL(e.url),c=e.headers.get("Upgrade");if(c&&c.toLowerCase()==="websocket"){r.socks5.enabled&&!W&&(W=se(r.socks5.address));let s={userID:r.userID,proxyIP:r.proxyIP,proxyPort:r.proxyPort,socks5Address:r.socks5.address,socks5Relay:r.socks5.relayMode,enableSocks:r.socks5.enabled,parsedSocks5Address:r.socks5.enabled?W:{}};return J(e,s)}return n.pathname==="/scamalytics-lookup"?oe(e,r):n.pathname.startsWith(`/xray/${r.userID}`)?K(e,"xray",r.userID,n.hostname,a):n.pathname.startsWith(`/sb/${r.userID}`)?K(e,"sb",r.userID,n.hostname,a):n.pathname.startsWith(`/${r.userID}`)?ie(r.userID,n.hostname,r.proxyAddress):new Response("UUID not found. Please set the UUID environment variable in the Cloudflare dashboard.",{status:404})}catch(r){return new Response(`Worker Logic Error: ${r.message}
${r.stack}`,{status:500,headers:{"Content-Type":"text/plain"}})}}};export{de as default};