├── README.md └── _worker.js /README.md: -------------------------------------------------------------------------------- 1 | # Workers-Vless 2 | 3 | 轻量级版本,对抗2.0 4 | 5 | - 群聊: [HeroCore](https://t.me/HeroCore) 6 | - 频道: [HeroMsg](https://t.me/HeroMsg) 7 | 8 | 9 | ## Update history 10 | - **20250527**:添加 NAT64。 11 | - **20240417**:修复了报错问题(错误代码:1101)。 12 | -------------------------------------------------------------------------------- /_worker.js: -------------------------------------------------------------------------------- 1 | // VLESS代理服务器 - 支持IPv4地址NAT64回落和负载均衡 2 | import { 3 | connect 4 | } from 'cloudflare:sockets'; 5 | 6 | export default { 7 | async fetch(req, env, ctx) { 8 | try { 9 | // 环境变量配置 10 | const UUID = env.UUID || '4ba0eec8-25e1-4ab3-b188-fd8a70b53984'; 11 | const NAT64P = env.NAT64P || '2602:fc59:b0:64::,2001:67c:2960:6464::'; 12 | 13 | // WebSocket代理处理 14 | if (req.headers.get('Upgrade')?.toLowerCase() === 'websocket') { 15 | const [client, ws] = Object.values(new WebSocketPair()); 16 | ws.accept(); 17 | 18 | const early = req.headers.get('sec-websocket-protocol') || ''; 19 | let remote = null, 20 | udp = null, 21 | dns = false; 22 | 23 | // WebSocket数据流处理 24 | new ReadableStream({ 25 | start(ctrl) { 26 | ws.addEventListener('message', e => ctrl.enqueue(e.data)); 27 | ws.addEventListener('close', () => ctrl.close()); 28 | ws.addEventListener('error', err => ctrl.error(err)); 29 | 30 | // 处理早期数据 31 | if (early) { 32 | try { 33 | const decoded = atob(early.replace(/-/g, '+').replace(/_/g, '/')); 34 | ctrl.enqueue(Uint8Array.from(decoded, c => c.charCodeAt(0)).buffer); 35 | } catch (e) {} 36 | } 37 | } 38 | }).pipeTo(new WritableStream({ 39 | async write(data) { 40 | // DNS UDP数据转发 41 | if (dns && udp) return udp(data); 42 | 43 | // TCP数据转发 44 | if (remote) { 45 | const w = remote.writable.getWriter(); 46 | await w.write(data); 47 | w.releaseLock(); 48 | return; 49 | } 50 | 51 | // VLESS协议头解析 52 | if (data.byteLength < 24) throw new Error('协议头长度不足'); 53 | 54 | const view = new DataView(data); 55 | const ver = new Uint8Array(data.slice(0, 1)); 56 | 57 | // UUID验证 58 | const bytes = new Uint8Array(data.slice(1, 17)); 59 | const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join( 60 | ''); 61 | const id = 62 | `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`; 63 | if (id !== UUID) throw new Error('UUID验证失败'); 64 | 65 | const optLen = view.getUint8(17); 66 | const cmd = view.getUint8(18 + optLen); 67 | const isUdp = cmd === 2; 68 | if (cmd !== 1 && cmd !== 2) throw new Error('不支持的命令类型'); 69 | 70 | let pos = 19 + optLen; 71 | const port = view.getUint16(pos); 72 | pos += 2; 73 | 74 | // 地址解析 75 | const type = view.getUint8(pos++); 76 | let addr = ''; 77 | 78 | if (type === 1) { 79 | // IPv4 80 | addr = Array.from(new Uint8Array(data.slice(pos, pos + 4))).join('.'); 81 | pos += 4; 82 | } else if (type === 2) { 83 | // 域名 84 | const len = view.getUint8(pos++); 85 | addr = new TextDecoder().decode(data.slice(pos, pos + len)); 86 | pos += len; 87 | } else if (type === 3) { 88 | // IPv6 89 | const parts = []; 90 | for (let i = 0; i < 8; i++) { 91 | parts.push(view.getUint16(pos).toString(16).padStart(4, '0')); 92 | pos += 2; 93 | } 94 | addr = parts.join(':').replace(/(^|:)0+(\w)/g, '$1$2'); 95 | } else { 96 | throw new Error('不支持的地址类型'); 97 | } 98 | 99 | const header = new Uint8Array([ver[0], 0]); 100 | const payload = data.slice(pos); 101 | 102 | // UDP DNS处理 103 | if (isUdp) { 104 | if (port !== 53) throw new Error('UDP仅支持DNS'); 105 | dns = true; 106 | 107 | let sent = false; 108 | const t = new TransformStream({ 109 | transform(chunk, ctrl) { 110 | for (let i = 0; i < chunk.byteLength;) { 111 | const len = new DataView(chunk.slice(i, i + 2)) 112 | .getUint16(0); 113 | ctrl.enqueue(new Uint8Array(chunk.slice(i + 2, i + 114 | 2 + len))); 115 | i += 2 + len; 116 | } 117 | } 118 | }); 119 | 120 | t.readable.pipeTo(new WritableStream({ 121 | async write(query) { 122 | const resp = await fetch( 123 | 'https://1.1.1.1/dns-query', { 124 | method: 'POST', 125 | headers: { 126 | 'content-type': 'application/dns-message' 127 | }, 128 | body: query 129 | }); 130 | 131 | const result = await resp.arrayBuffer(); 132 | const len = result.byteLength; 133 | const lenBuf = new Uint8Array([len >> 8, len & 134 | 0xff 135 | ]); 136 | 137 | if (ws.readyState === 1) { 138 | const buf = sent ? 139 | await new Blob([lenBuf, result]) 140 | .arrayBuffer() : 141 | await new Blob([header, lenBuf, result]) 142 | .arrayBuffer(); 143 | ws.send(buf); 144 | sent = true; 145 | } 146 | } 147 | })); 148 | 149 | udp = chunk => t.writable.getWriter().write(chunk); 150 | return udp(payload); 151 | } 152 | 153 | // TCP连接处理 154 | const conn = async (host, p) => { 155 | const sock = await connect({ 156 | hostname: host, 157 | port: p 158 | }); 159 | remote = sock; 160 | const w = sock.writable.getWriter(); 161 | await w.write(payload); 162 | w.releaseLock(); 163 | return sock; 164 | }; 165 | 166 | // NAT64地址转换 167 | const nat64 = async (address) => { 168 | let ipv4; 169 | 170 | if (/^(\d{1,3}\.){3}\d{1,3}$/.test(address)) { 171 | ipv4 = address; 172 | } else { 173 | const resp = await fetch( 174 | `https://1.1.1.1/dns-query?name=${address}&type=A`, { 175 | headers: { 176 | 'Accept': 'application/dns-json' 177 | } 178 | }); 179 | const json = await resp.json(); 180 | const record = json.Answer?.find(r => r.type === 1); 181 | if (!record) throw new Error('DNS解析失败'); 182 | ipv4 = record.data; 183 | } 184 | 185 | const parts = ipv4.split('.'); 186 | const hex = parts.map(p => parseInt(p).toString(16).padStart(2, 187 | '0')); 188 | const ipv4Hex = `${hex[0]}${hex[1]}:${hex[2]}${hex[3]}`; 189 | 190 | const prefixes = NAT64P.split(',').map(p => p.trim()).filter( 191 | p => p); 192 | const prefix = prefixes[Math.floor(Math.random() * prefixes 193 | .length)]; 194 | 195 | return `[${prefix}${ipv4Hex}]`; 196 | }; 197 | 198 | // 数据转发管道 199 | const pipe = (sock, retry = null) => { 200 | let sent = false, 201 | hasData = false; 202 | 203 | sock.readable.pipeTo(new WritableStream({ 204 | write(chunk) { 205 | hasData = true; 206 | if (ws.readyState === 1) { 207 | if (!sent) { 208 | const buf = new Uint8Array(header 209 | .length + chunk.byteLength); 210 | buf.set(header, 0); 211 | buf.set(new Uint8Array(chunk), header 212 | .length); 213 | ws.send(buf.buffer); 214 | sent = true; 215 | } else { 216 | ws.send(chunk); 217 | } 218 | } 219 | }, 220 | close() { 221 | if (!hasData && retry) return retry(); 222 | if (ws.readyState === 1) ws.close(1000); 223 | } 224 | })).catch(() => { 225 | try { 226 | sock?.close(); 227 | } catch (e) {} 228 | if (ws.readyState === 1) ws.close(1011); 229 | }); 230 | }; 231 | 232 | // 连接尝试 - 直连失败后NAT64回退 233 | try { 234 | const sock = await conn(addr, port); 235 | pipe(sock, async () => { 236 | try { 237 | const ipv6 = await nat64(addr); 238 | const retry = await conn(ipv6, port); 239 | pipe(retry); 240 | } catch (e) { 241 | ws.close(1011); 242 | } 243 | }); 244 | } catch (e) { 245 | try { 246 | const ipv6 = await nat64(addr); 247 | const retrySock = await conn(ipv6, port); 248 | pipe(retrySock); 249 | } catch (natErr) { 250 | ws.close(1011); 251 | } 252 | } 253 | }, 254 | close() { 255 | try { 256 | remote?.close(); 257 | } catch (e) {} 258 | } 259 | })).catch(() => { 260 | try { 261 | remote?.close(); 262 | } catch (e) {} 263 | ws.close(1011); 264 | }); 265 | 266 | return new Response(null, { 267 | status: 101, 268 | webSocket: client 269 | }); 270 | } 271 | 272 | // HTTP反向代理 273 | const url = new URL(req.url); 274 | url.hostname = 'example.com'; 275 | 276 | return fetch(new Request(url.toString(), { 277 | method: req.method, 278 | headers: req.headers, 279 | body: req.body 280 | })); 281 | 282 | } catch (err) { 283 | return new Response(`服务器错误: ${err.message}`, { 284 | status: 500 285 | }); 286 | } 287 | } 288 | }; 289 | --------------------------------------------------------------------------------