ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

使用 CloudFlare Worker 免费部署 jsproxy 在线代理节点:cf-worker 方案实操与源码解析

使用 CloudFlare Worker 免费部署 jsproxy 在线代理节点:cf-worker 方案实操与源码解析 后端网络通信【免费下载链接】jsproxyAn online proxy based on ServiceWorker项目地址https://gitcode.com/gh_mirrors/js/jsproxy点击查看免费下载本文围绕 jsproxy 仓库中的cf-worker模块展开先按 cf-worker/README.md 的步骤在 CloudFlare 上免费部署一套无需自有服务器的在线代理节点再逐段剖析 cf-worker/index.js 的路由分发、请求头还原、CORS 转义与 YouTube 视频重定向修复等核心实现并对照 nginx 侧的 api.conf 与 OpenResty 脚本说明两条代理链路如何保持协议一致。读完你可以独立完成一个零服务器成本的代理节点部署并理解它与服务端 nginx 版在接口协议上的对应关系。一、CloudFlare Worker 简介CloudFlare Worker是 CloudFlare 提供的边缘计算服务。开发者可通过 JavaScript 对 CDN 进行编程从而灵活处理 HTTP 请求使得很多任务可以在 CDN 上完成而无需自己的服务器参与。对 jsproxy 而言这正是它无服务器版cfworker 节点的载体把代理逻辑压缩进一个单文件 Worker 脚本直接跑在 CloudFlare 的边缘节点上。仓库根目录 README 的更新日志README.md中2019-06-22 发布的cfworker 无服务器版即指本模块并建议长期使用演示服务的读者迁移到该版本。jsproxy 的整体架构是前端 ServiceWorker 后端纯转发浏览器中的 ServiceWorker 拦截并改写页面请求把目标 URL 打包进Referer请求头、以/http/目标URL的形式打到代理节点节点nginx 版或 cf-worker 版只负责转发流量并改写 HTTP 头。cf-worker 就是这条链路中可完全托管在 CDN 上的节点实现。二、部署步骤部署入口是 CloudFlare 官方的 Workers 控制台workers.cloudflare.com可从 CloudFlare 官网进入。操作流程如下注册并登录 CloudFlare 账号点击Start building为自己的 Worker 取一个子域名选择Create a Worker创建新 Worker把本仓库 cf-worker/index.js 的全部内容复制到控制台左侧的代码框点击Save and deploy完成部署。部署成功后右侧应显示 Worker 的首页。收藏地址栏中的https://xxxx.子域名.workers.dev形式的访问地址以后可直接访问。部署后的可用端点Worker 的路由逻辑集中在 fetchHandler 中与仓库 test/works.txt内容为ok的命名相呼应部署后可验证以下路径路径行为源码依据/works返回文本it works用于连通性自检cf-worker/index.js#L78-L79/http/...HTTP(S) 代理主接口见后文解析cf-worker/index.js#L69-L71/http返回请更新 cfworker 到最新版本!作为版本探测接口cf-worker/index.js#L73-L75/ws返回not support400WebSocket 代理尚未实现cf-worker/index.js#L76-L77其他路径作为静态资源从ASSET_URL反向代理cf-worker/index.js#L80-L83另外所有以http:协议的请求会被 301 重定向到https:并附带strict-transport-security头见 cf-worker/index.js#L61-L67因此实际使用时统一走 HTTPS。三、计费与扩容回到控制台的overview页面可以查看用量。关键计费事实以 cf-worker/README.md 为准免费版每天 10 万次免费请求对个人使用通常足够扩容方式一注册多个 Worker多个免费子域名在前端conf.js中配置多线路负载均衡把流量摊到多个节点扩容方式二升级到 $5/月 的高级版本每月可用 1000 万次请求超出部分 $0.5/百万次请求。多节点方案在 changelogs/v0.1.0.md 中有配套的权重设计前端conf.js的node_map节点 id 与节点主机与node_default默认节点之外v0.1.0 为每条线路增加了权重配置命中比例 当前值 / 总值。演示案例中 cfworker 节点即采用1 个收费版 多个免费版的组合——由于免费版有访问频率限制通过更低权重减少其负载。也就是说用多个免费 Worker 堆量的策略是官方文档明确支持的用法。四、修改配置ASSET_URL 与自定义 conf.jsWorker 脚本顶部的常量直接决定前端资源从哪里加载// cf-worker/index.js const ASSET_URL https://etherdream.github.io/jsproxy const JS_VER 10 const MAX_RETRY 1ASSET_URL默认情况下Worker 首页所需的静态资源404.html、sw.js、conf.js等对应 nginx 版部署中的 www 目录内容从https://etherdream.github.io/jsproxy反向代理。修改这个常量指向自己的静态资源站如自己的 GitHub Pages即可使用自定义的conf.js——也就是配置自己的node_map节点列表、node_default默认节点与线路权重。Worker 对非代理路径的处理就是一行return fetch(ASSET_URL path)cf-worker/index.js#L82因此ASSET_URL站点必须能正常提供这些静态文件。JS_VER当前脚本版本号值为 10会随响应头--ver下发给前端用于前端判断代理端是否为最新版本/http端点的请更新 cfworker提示即服务于这个探测机制。MAX_RETRY内容长度校验失败时的最大重试次数后文详述。需要注意的是v0.1.0 起后端代理与 cfworker 的接口做过调整以修复缓存失效问题详见 changelogs/v0.1.0.md服务端与 cfworker 的版本需配套不要混用旧接口。五、源码解析一次 /http/ 请求的完整链路cf-worker/index.js全文约 290 行从源码结构看可分为入口分发、请求头还原、代理转发、响应头改写四层。5.1 入口与全局错误处理addEventListener(fetch, e { const ret fetchHandler(e) .catch(err makeRes(cfworker error:\n err.stack, 502)) e.respondWith(ret) })所有请求统一进入 fetchHandler任何未捕获异常都以 502 返回错误栈便于排查。makeRes辅助函数cf-worker/index.js#L26-L30会给每个响应补上--ver版本头与access-control-allow-origin: *。5.2 防循环依赖与 CORS preflighthttpHandler 开头有两道检查if (reqHdrRaw.has(x-jsproxy)) { return Response.error() }请求头中一旦带有x-jsproxy说明流量来自 jsproxy 节点自身nginx 版在转发前会注入proxy_set_header x-jsproxy 1见 api.conf#L51此时直接返回错误防止 A→B 两个 jsproxy 节点互相代理形成环路。这与 nginx 版/http/location 中CIRCULAR_DEPENDENCY的检查逻辑一一对应api.conf#L48-L50。其次是 OPTIONS 预检请求的处理当方法为OPTIONS且携带access-control-request-headers时直接用 PREFLIGHT_INIT 返回 204允许全部常用方法与max-age: 172800020 天的预检缓存与 api.conf 中 /preflight 端点 的行为一致。5.3 请求头还原为什么参数藏在 Referer 里这是整个代理协议最核心的设计。浏览器 fetch 对非简单请求头会触发 CORS preflight而 preflight 的max-age是按 URL 记忆缓存的jsproxy 每次请求的 URL/http/目标URL几乎都不同预检缓存形同虚设。因此 v0.1.0 之后的方案是把绝大部分请求头字段打包进Referer的 query 部分因为Referer属于 CORS 安全头不会触发 preflight。Worker 侧的解析代码cf-worker/index.js#L114-L143const refer reqHdrNew.get(referer) const query refer.substr(refer.indexOf(?) 1) if (!query) { return makeRes(missing params, 403) } const param new URLSearchParams(query) for (const [k, v] of Object.entries(param)) { if (k.substr(0, 2) --) { // 系统信息 switch (k.substr(2)) { case aceh: acehOld true break case raw-info: [rawSvr, rawLen, rawEtag] v.split(|) break } } else { // 还原 HTTP 请求头 if (v) { reqHdrNew.set(k, v) } else { reqHdrNew.delete(k) } } } if (!param.has(referer)) { reqHdrNew.delete(referer) }规则可以概括为query 中--前缀的键是系统参数--aceh标记前端浏览器不支持access-control-expose-headers: *通配符、需要回退到逐字段列表模式--raw-info携带原始地址|长度|etag三段信息用于节点切换时的内容校验其余键是待还原的原始请求头有值则set空值则delete前端借此表达原始请求没有该头若参数里没有referer键说明原始请求不带 referer把代理请求自带的 referer 删掉。这段逻辑与 nginx 版的 lua/http-dec-req-hdr.lua 大致相同cf-worker/index.js#L112 的注释即指向它只是 Worker 版只实现了--aceh与--raw-info两个系统参数nginx 版还多解析--ver、--type、--mode、--level节点切换等级。URL 还原处有一个针对 CloudFlare Worker 平台行为的修正cf-worker/index.js#L145-L150cfworker 会把路径中的//合并成/导致https://变成https:/所以用replace(/^(https?):\//, $1://)把协议后的斜杠补回来解析失败则返回invalid proxy url403。5.4 转发与响应头改写proxy 以redirect: manual发起真实请求不跟随重定向并只对POST透传请求体。响应处理包含三块逻辑1敏感头转义。四个对浏览器 CORS 语义有特殊意义的响应头会被改名为--前缀的版本再下发防止被浏览器直接执行if (k access-control-allow-origin || k access-control-expose-headers || k location || k set-cookie ) { resHdrNew.set(-- k, v) ... resHdrNew.delete(k) }nginx 版由 lua/http-enc-res-hdr.lua#L116-L148 完成同样的转义且额外处理了重复头多个Set-Cookie会被编码为1-set-cookie、2-set-cookie……。前端 ServiceWorker 读到--前缀的头后还原为真实值从而在浏览器内重建目标站点的响应。2--aceh回退模式。当请求带--aceh时脚本会把所有非简单响应头cache-control、content-type等六个浏览器默认可读的除外逐一追加进access-control-expose-headers列表并额外设置--t: 1作为浏览器是否支持*通配的探测标记——前端能否读到这个不属于 expose 列表的--t头即判定是否支持通配。这与 lua/http-enc-res-hdr.lua#L21-L28 的注释逻辑完全对应。3内容长度校验与 YouTube 视频修复。若请求携带--raw-info中的期望长度rawLen脚本会比对实际content-lengthif (badLen) { if (retryTimes MAX_RETRY) { urlObj await parseYtVideoRedir(urlObj, newLen, res) if (urlObj) { return proxy(urlObj, reqInit, acehOld, rawLen, retryTimes 1) } } return makeRes(res.body, 400, { --error: bad len: ${newLen}, except: ${rawLen}, ... }) }长度不一致时parseYtVideoRedir 会尝试一个特定修复仅当 URL 是 YouTube 视频流host 以.googlevideo.com结尾且路径以/videoplayback开头见 isYtUrl且响应体小于 2KB 时把响应体当作一个新的跳转 URL 解析并重试一次MAX_RETRY 1。这可以推断是针对 YouTubevideoplayback接口偶发二次重定向、导致缓存长度不匹配的问题做的兜底。校验失败则返回 400错误信息通过--error头下发配合 api.conf 中 error 端点的 expose 配置 思路一致。4状态码转义。与 nginx 版 lua/http-enc-res-hdr.lua#L42-L52 相同的处理真实状态码写入--s头非 200 时而对外状态码保留原始值用于控制台调试例如 404 会显示红色但 301/302/303/307/308 会统一10变成 311/312/313/317/318——按 CORS 标准 fetch 不允许跟随这类重定向转义后前端可以自行处理cf-worker/index.js#L242-L249。最后脚本还会删除content-security-policy、content-security-policy-report-only、clear-site-data三个头避免目标站点的 CSP 干扰代理页面。六、与 nginx 服务端链路的对照同一套协议在仓库中有两份实现对照关系如下职责cf-worker 实现nginx 实现代理入口/http/前缀分支cf-worker/index.js#L69-L71location /http/api.conf#L43-L74防循环依赖检测x-jsproxy头返回Response.error()重写为/error?msgCIRCULAR_DEPENDENCYapi.conf#L48-L50请求头还原httpHandlerlua/http-dec-req-hdr.lua多解析--ver/--type/--mode/--level响应头编码proxylua/http-enc-res-hdr.lua lua/http-body-hash.lua缓存无依赖 CloudFlare 边缘缓存proxy_cache my_cacheapi.conf#L61WebSocket未实现/ws返回 400已实现api.conf#L77-L83 lua/ws-dec-req-hdr.lua外链白名单未实现allowed-sites.conf限制可调用站点api.conf#L44-L47从源码结构看Worker 版可以视为 nginx 版的协议子集它保留了 v0.1.0 新接口的全部关键要素/http/目标URL路径式 URL、Referer 打包参数、--前缀转义头、--s状态码、30X 转义但去掉了节点切换nodeSwitched在 lua/http-enc-res-hdr.lua#L110-L113 中也仅处于注释测试状态、缓存与白名单能力。七、当前局限cf-worker/README.md 明确列出了三个已知问题与源码相互印证WebSocket 代理尚未实现/ws路径直接返回not supportcf-worker/index.js#L76-L77。CloudFlare Worker 的 fetch 事件模型本身也不支持长连接透传这类站点需要回退到 nginx 节点api.conf#L77-L83。外链限制尚未实现nginx 版可通过 allowed-sites.conf 限定可调用代理的github.io站点Worker 版对所有来源一视同仁access-control-allow-origin恒为*因此公开部署的 Worker 节点应视为不对外提供服务的私有加速节点流量风险由节点主自担。未充分测试作者自述以后再完善生产环境使用前建议先用/works端点和真实站点做充分验证。八、小结cf-worker 方案把 jsproxy 的节点侧压缩成了单个可托管文件约百行的部署流程换来一个每天 10 万请求免费额度的 HTTPS 代理节点ASSET_URL一个常量即可切换前端配置来源实现自定义conf.js与多线路负载均衡。其核心工程价值在于展示了如何用Referer 参数打包 --前缀头转义 状态码转义这一套协议在不触发 CORS preflight、不执行远端敏感响应头的前提下让浏览器里的 ServiceWorker 完整接管目标站点的请求与响应语义。由于 WebSocket 与外链白名单暂未实现对完整功能有要求的场景仍应选择 nginx 服务端部署参考 docs/setup.md。赞分享后端网络通信【免费下载链接】jsproxyAn online proxy based on ServiceWorker项目地址https://gitcode.com/gh_mirrors/js/jsproxy点击查看免费下载相关推荐jsproxy 部署与运维实战用 nginx Service Worker 构建低开销在线代理jsproxy 部署与运维实战用 nginx Service Worker 构建低开销在线代理 本文基于 jsproxy 仓库根目录 README.md后端网络通信tg-ws-proxy 免费免域名代理指南Cloudflare Worker 部署与 --cfproxy-worker-domain 接入tg ws proxy 免费免域名代理指南Cloudflare Worker 部署与 cfproxy worker domain 接入 导读 本文讲解 tgtg-ws-proxy 部署 Cloudflare Worker 免费代理从零搭建 WebSocket 中转端tg ws proxy 部署 Cloudflare Worker 免费代理从零搭建 WebSocket 中转端 本文档基于 tg ws proxy 官方文档上一篇Ripple Node.js 适配器 ripple-ts/adapter-node用 Web Request/Response 标准 API 编写 Node 服务器下一篇Bottlerocket灾备方案跨区域实例复制与数据备份创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表