利用Cloudflare Worker部署VLESS翻墙代理的代码学习:Zizifn's edgetunnel repo

代码在Github上的链接:edgetunnel/src/worker-vless.js at main · zizifn/edgetunnel (github.com)

丢给ChatGPT他的解释这段代码的用途:

这段代码是一个 Cloudflare Worker,它是用於处理 WebSocket 请求的。让我们来逐一解释代码中的不同部分:

  1. 开头注解:
  2. import@ts-ignore
  3. UUID 验证与设定:
  4. export default
  5. fetch 函式:
  6. vlessOverWSHandler 函式:
  7. 其他辅助函式:

总体来说,这个代码看起来是一个 WebSocket 的代理伺服器,可以在 Cloudflare Worker 环境中运行。它处理进来的 HTTP 请求,并在需要时建立 WebSocket 连接,将数据转发到後端伺服器或其他服务器上。根据需要,它还支援对 DNS 的 UDP 请求进行转发。

摘要节点

ProxyIP的作用?

当我们查看代码时,可以发现 proxyIP 是一个空字串,它被定义在代码的开头:

let proxyIP = '';

在後续代码中,proxyIP 的值会被设定为 env.PROXYIP 或保持不变,取决於是否存在 env.PROXYIP

proxyIP = env.PROXYIP || proxyIP;

这里,env 是一个代表环境变数的物件。根据代码中的注释,它是在 fetch 函式的参数中传入的:

async fetch(request, env, ctx) { ... }

因此,env 应该是一个包含了一些环境设定的物件。env.PROXYIP 似乎是这个物件中的一个属性,用於指定代理 IP。

总的来说,proxyIP 这个变数的作用是用来存储代理伺服器的 IP 地址。如果在 env 中提供了 PROXYIP,则会将该值赋给 proxyIP,否则 proxyIP 的值保持不变。使用 proxyIP 变数可以方便地在後续代码中引用代理 IP,以便在需要时使用。

vlessOverWSHandler 这个function是的运作原理

vlessOverWSHandler 函式是用於处理 WebSocket 升级後的数据交换。它处理了从客户端传递过来的 WebSocket 资料,并根据数据的不同进行相应的处理。

让我们逐步解释 vlessOverWSHandler 函式的运作:

开始处理:接收 WebSocket 资料:数据处理:UDP 数据处理:

回应数据:

WebSocket 关闭处理:

总体来说,vlessOverWSHandler 函式在 WebSocket 升级後负责处理数据传输。根据数据内容,它可能建立 TCP 或 UDP 连接,然後进行数据的转发。如果收到 DNS 的 UDP 请求,它会将该请求发送到 1.1.1.1 DNS 服务器进行解析,然後将解析结果返回给 WebSocket 客户端。

如果 vlessOverWSHandler 接收到的是 TCP 数据,它会进行以下处理:

  1. 解析 VLESS 协议头部:
    首先,它会解析收到的 TCP 数据中的 VLESS 协议头部,以了解目标地址和端口等信息。
  2. 创建 TCP 连接:
    接下来,vlessOverWSHandler 会根据 VLESS 协议头部中的目标地址和端口信息,建立一个新的 TCP 连接。它会向目标地址和端口发送数据,将接收到的 TCP 数据转发到该 TCP 连接。
  3. 转发数据:
    一旦新的 TCP 连接建立完成,vlessOverWSHandler 会将接收到的 TCP 数据转发到该连接中,这样数据就能够正确地发送到目标服务器。
  4. WebSocket 关闭处理:
    在整个处理过程中,vlessOverWSHandler 函式会监听 WebSocket 的状态变化,特别是关闭事件。如果 WebSocket 关闭,则相应地处理数据流程,确保正确地关闭数据传输。

总的来说,如果 vlessOverWSHandler 接收到的是 TCP 数据,它会根据 VLESS 协议头部中的目标地址和端口信息,建立一个新的 TCP 连接,然後将接收到的 TCP 数据转发到该连接中,最终将数据正确地发送到目标服务器。这样,它能够处理 WebSocket 传输中的 TCP 数据流量。

handleTCPOutBound 的运作原理

handleTCPOutBound 函数的作用是处理出站(Outbound)TCP连接,即建立到目标服务器的TCP连接并转发数据。

函数的工作原理如下:

函数参数:

建立远程连接:

转发数据:

监听远程 Socket 数据:

WebSocket 关闭处理:

总体而言,handleTCPOutBound 函数的工作原理是建立到目标服务器的远程 TCP 连接,然后将客户端发送的原始数据转发到目标服务器,再将目标服务器的响应数据转发回客户端。这样,它能够处理 WebSocket 传输中的 TCP 数据流量。

handleTCPOutBound 函数中,转发数据和监听远程 Socket 数据是通过以下几个部分的代码实现的:

  1. 转发数据:
    handleTCPOutBound 函数的 write 方法中,将客户端发送的原始数据 rawClientData 转发到已建立的远程 TCP 连接 tcpSocket 中。具体实现代码如下:
   async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log) {      // ... 其他代码 ...      // 转发数据到远程 Socket      const writer = tcpSocket.writable.getWriter();      await writer.write(rawClientData);      writer.releaseLock();      // ... 其他代码 ...   }
  1. 监听远程 Socket 数据:
    handleTCPOutBound 函数中,通过 tcpSocket.readablepipeTo 方法来监听远程 Socket 的数据流,并将收到的数据转发到 WebSocket 连接中,从而将目标服务器的响应数据返回给客户端。具体实现代码如下:
   async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, vlessResponseHeader, log) {      // ... 其他代码 ...      // 监听远程 Socket 数据,并将数据转发到 WebSocket 连接中      remoteSocket.readable.pipeTo(new WritableStream({         async write(chunk, controller) {            if (webSocket.readyState !== WS_READY_STATE_OPEN) {               controller.error('webSocket.readyState is not open, maybe close');            }            webSocket.send(chunk);         },         close() {            log(`remoteConnection!.readable is close with hasIncomingData is ${hasIncomingData}`);            // safeCloseWebSocket(webSocket); // no need server close websocket first for some case will cause HTTP ERR_CONTENT_LENGTH_MISMATCH issue, client will send close event anyway.         },         abort(reason) {            console.error(`remoteConnection!.readable abort`, reason);         },      })).catch((error) => {         console.error(`remoteSocketToWS has exception`, error.stack || error);         safeCloseWebSocket(webSocket);      });      // ... 其他代码 ...   }

在这两个部分中,handleTCPOutBound 函数分别将数据从客户端转发到远程 Socket(目标服务器)以及从远程 Socket 转发到 WebSocket 连接,实现了数据的转发和监听功能。这样,数据能够在客户端、目标服务器和 WebSocket 之间传递,实现了 TCP 数据的传输和响应。

makeReadableWebSocketStream 是干什麽的?

makeReadableWebSocketStream 是一个函数,它的作用是创建一个可读的 WebSocket 流(ReadableStream)。

在 WebSocket 中,可以通过 addEventListener 监听 message 事件来接收来自客户端的数据。然而,message 事件在接收到数据后只会触发一次,无法实现数据流的持续传输。makeReadableWebSocketStream 函数的目的是将 WebSocket 的数据流封装为一个可读流,以便能够通过流式数据传输的方式处理客户端的数据,并且在客户端发送更多数据时,能够持续触发数据传输。

函数的实现原理如下:

  1. 创建可读流:
    函数首先通过 new ReadableStream() 创建一个可读流对象 stream
  2. 注册事件监听器:
    在可读流的 start 回调函数中,函数会通过 addEventListener 监听 WebSocket 的 message 事件。一旦接收到客户端发送的数据,该事件会触发并将数据添加到可读流中。
  3. 数据传输:
    在可读流的 transform 回调函数中,函数会将接收到的 WebSocket 数据转换为可读流的数据,并通过 controller.enqueue 方法将数据添加到可读流中。这样,在 WebSocket 有新数据到来时,transform 回调函数会被调用,从而触发数据传输。
  4. WebSocket 关闭处理:
    函数还会监听 WebSocket 的状态变化,特别是关闭事件。一旦 WebSocket 关闭,cancel 回调函数会被调用,函数会相应地关闭数据传输。

通过这种方式,makeReadableWebSocketStream 函数实现了将 WebSocket 的数据流封装为可读流的功能,使得可以通过流式传输的方式处理客户端的数据,从而能够持续地接收客户端的数据并作出相应的处理。

processVlessHeader 是干什麽的?

processVlessHeader 是一个函数,它的作用是解析 VLESS 协议的头部信息。

在 VLESS 协议中,数据流的开头包含了一些特定的字段,用于标识数据的类型和其他相关信息。processVlessHeader 函数接收一个 ArrayBuffer 参数 vlessBuffer,该参数是从客户端发送的数据流中提取的 VLESS 协议头部信息。函数会解析该头部信息,提取出其中的字段,以便后续对数据进行处理。

具体来说,processVlessHeader 函数的工作原理如下:

  1. 解析数据类型和用户验证:
    函数首先从 vlessBuffer 中解析出数据类型(TCP 或 UDP)以及用户验证信息(UUID)。这里需要注意的是,VLESS 头部信息的前 17 个字节包含了 UUID,用于验证用户身份。如果解析出的 UUID 与预设的 userID 不匹配,说明该用户不合法。
  2. 解析其他信息:
    接下来,函数会解析其他的 VLESS 头部信息,包括可选字段的长度和字段值。目前,函数只关心数据类型为 UDP 时的处理,因为数据类型为 TCP 或 MUX 时不需要做特殊处理。
  3. 提取目标服务器地址和端口:
    当数据类型为 UDP 时,函数会提取出目标服务器的地址(IPv4 或 IPv6)和端口号,以便后续转发 UDP 数据包。
  4. 返回解析结果:
    最后,函数会返回一个包含解析结果的对象。如果解析过程中出现错误或数据格式不合法,函数会在返回的对象中标记出错信息。如果解析成功,返回的对象包含了目标服务器的地址、端口号以及其他相关信息,用于后续的数据转发和处理。

总体而言,processVlessHeader 函数在 VLESS 协议的数据流中提取出相关的信息,以便后续根据这些信息来进行数据的处理和转发。这个函数在整个 VLESS 协议的实现中起到了关键的作用。

remoteSocketToWS 是干什麽的?

remoteSocketToWS 是一个函数,它的作用是将来自远程服务器的数据流转发到 WebSocket 客户端。

在 VLESS 协议中,数据流是从远程服务器返回给本地客户端的。而本地客户端与服务器之间是通过 WebSocket 连接通信的。remoteSocketToWS 函数负责将远程服务器返回的数据流转发到 WebSocket 客户端,以便客户端能够接收到实时的数据并做相应的处理。

函数的实现原理如下:

  1. 数据转发:
    函数通过 remoteSocketreadable 属性来获取可读流,这个可读流是从远程服务器读取数据的。然后,通过 pipeTo 方法将远程服务器的数据流与 WebSocket 的数据流相连接,实现数据的转发。
  2. WebSocket 传输:
    在转发数据的过程中,函数会检查 WebSocket 的状态,只有在 WebSocket 连接处于打开状态(WS_READY_STATE_OPEN)时,才会将数据发送给客户端。
  3. 关闭处理:
    函数会监听 remoteSocket 的关闭事件,当远程服务器的连接关闭时,会执行相应的关闭处理,并调用 safeCloseWebSocket 函数关闭 WebSocket 连接,避免出现异常。

总体来说,remoteSocketToWS 函数是 VLESS 协议中数据转发的关键部分,它负责将远程服务器返回的数据转发给 WebSocket 客户端,实现了客户端与服务器之间的实时数据传输。

remoteSocketToWS 函数并没有在转发数据时添加 VLESS 协议的头部信息。实际上,该函数是用于处理 UDP 数据的转发,而 VLESS 协议的头部信息是在客户端发起 WebSocket 请求时添加的。

在 VLESS 协议中,客户端在发起 WebSocket 连接时会携带特定的查询参数或者在 WebSocket 握手时发送特定的数据来表明使用 VLESS 协议。服务器在收到客户端的请求后,会根据请求中携带的信息来识别并处理 VLESS 协议的数据。

因此,在 remoteSocketToWS 函数中并没有添加 VLESS 协议的头部信息,而是在 WebSocket 握手阶段或客户端发起请求时添加的。该函数只负责将远程服务器返回的数据转发给 WebSocket 客户端,并不处理具体的协议头部信息。

https://chat.openai.com/share/75559006-a870-4d1f-9516-51c1f9487cf5

Leave a Reply

Your email address will not be published. Required fields are marked *