├── .gitignore ├── .env.example ├── wrangler.toml ├── package.json ├── docs └── DEPLOYMENT.md ├── README.md └── _worker.js /.gitignore: -------------------------------------------------------------------------------- 1 | ``` 2 | # Dependencies 3 | node_modules/ 4 | 5 | # Environment variables 6 | .env 7 | .dev.vars 8 | 9 | # Build output 10 | dist/ 11 | .wrangler/ 12 | 13 | # Logs 14 | *.log 15 | npm-debug.log* 16 | 17 | # OS 18 | .DS_Store 19 | Thumbs.db 20 | 21 | # IDE 22 | .vscode/ 23 | .idea/ 24 | *.swp 25 | *.swo 26 | ``` 27 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ```bash 2 | # 复制此文件为 .env 或 .dev.vars 用于本地开发 3 | # 生产环境请在 Cloudflare Dashboard 中设置环境变量 4 | 5 | # 必需的环境变量 6 | SUBSCRIPTION_URL=https://your-subscription-link.com 7 | PROXY_URL=https://your-snip-domain.com 8 | 9 | # 可选的环境变量 10 | TELEGRAM_URL=https://t.me/yourgroup 11 | BUTTON_TEXT_1=订阅链接(点击复制) 12 | BUTTON_TEXT_2=加入群组 13 | ``` 14 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | ```toml 2 | name = "subscription-checker" 3 | main = "worker.js" 4 | compatibility_date = "2024-01-01" 5 | 6 | # 环境变量在部署时通过 Cloudflare Dashboard 设置 7 | # 不要在此文件中包含敏感信息 8 | 9 | # 本地开发时的环境变量示例(使用 .dev.vars 文件) 10 | # SUBSCRIPTION_URL = "https://your-subscription-link.com" 11 | # PROXY_URL = "https://your-snip-domain.com" 12 | # TELEGRAM_URL = "https://t.me/yourgroup" 13 | # BUTTON_TEXT_1 = "订阅链接" 14 | # BUTTON_TEXT_2 = "加入群组" 15 | ``` 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subscription-checker", 3 | "version": "1.0.0", 4 | "description": "Cloudflare Worker - 订阅链接检测系统", 5 | "main": "worker.js", 6 | "scripts": { 7 | "dev": "wrangler dev", 8 | "deploy": "wrangler deploy" 9 | }, 10 | "keywords": [ 11 | "cloudflare", 12 | "worker", 13 | "subscription", 14 | "checker" 15 | ], 16 | "author": "", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "wrangler": "^3.0.0" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /docs/DEPLOYMENT.md: -------------------------------------------------------------------------------- 1 | ```markdown 2 | # 详细部署指南 3 | 4 | ## Cloudflare Workers 部署 5 | 6 | ### 步骤 1:准备工作 7 | 8 | 1. 注册 [Cloudflare 账号](https://dash.cloudflare.com/sign-up) 9 | 2. 安装 Node.js(版本 16 或更高) 10 | 11 | ### 步骤 2:使用 Dashboard 部署(最简单) 12 | 13 | 1. 登录 Cloudflare Dashboard 14 | 2. 进入 "Workers & Pages" 15 | 3. 点击 "创建应用程序" 16 | 4. 选择 "创建 Worker" 17 | 5. 给 Worker 命名(例如:subscription-checker) 18 | 6. 将 `worker.js` 的完整代码复制粘贴到编辑器 19 | 7. 点击 "保存并部署" 20 | 21 | ### 步骤 3:配置环境变量 22 | 23 | 1. 在 Worker 页面点击 "设置" 24 | 2. 找到 "环境变量" 25 | 3. 添加以下变量: 26 | 27 | **必需变量:** 28 | - `SUBSCRIPTION_URL`: 你的订阅链接 29 | - `PROXY_URL`: 你的SNIP反代链接 30 | 31 | **可选变量:** 32 | - `TELEGRAM_URL`: 群组链接 33 | - `BUTTON_TEXT_1`: 第一个按钮文字 34 | - `BUTTON_TEXT_2`: 第二个按钮文字 35 | 36 | 4. 点击 "保存" 37 | 38 | ### 步骤 4:绑定自定义域名(可选) 39 | 40 | 1. 在 Worker 设置中找到 "触发器" 41 | 2. 点击 "添加自定义域" 42 | 3. 输入你的域名(需要域名已托管在 Cloudflare) 43 | 4. 等待 SSL 证书自动配置 44 | 45 | ## Cloudflare Pages 部署 46 | 47 | ### 步骤 1:准备 GitHub 仓库 48 | 49 | 1. Fork 本项目或创建新仓库 50 | 2. 将所有文件推送到 GitHub 51 | 52 | ### 步骤 2:连接到 Pages 53 | 54 | 1. 登录 Cloudflare Dashboard 55 | 2. 进入 "Workers & Pages" 56 | 3. 点击 "创建应用程序" 57 | 4. 选择 "Pages" → "连接到 Git" 58 | 5. 授权 Cloudflare 访问你的 GitHub 59 | 6. 选择你的仓库 60 | 61 | ### 步骤 3:配置构建 62 | 63 | - **项目名称**:自定义名称 64 | - **生产分支**:main 或 master 65 | - **构建命令**:留空 66 | - **构建输出目录**:留空 67 | - **根目录**:/ 68 | 69 | ### 步骤 4:添加环境变量 70 | 71 | 在 "环境变量" 部分添加: 72 | - `SUBSCRIPTION_URL` 73 | - `PROXY_URL` 74 | - `TELEGRAM_URL`(可选) 75 | - `BUTTON_TEXT_1`(可选) 76 | - `BUTTON_TEXT_2`(可选) 77 | 78 | ### 步骤 5:部署 79 | 80 | 点击 "保存并部署",等待部署完成。 81 | 82 | ## 使用 Wrangler CLI 部署 83 | 84 | ### 安装 Wrangler 85 | 86 | ```bash 87 | npm install -g wrangler 88 | ``` 89 | 90 | ### 登录 Cloudflare 91 | 92 | ```bash 93 | wrangler login 94 | ``` 95 | 96 | ### 部署 97 | 98 | ```bash 99 | wrangler deploy 100 | ``` 101 | 102 | ### 设置环境变量 103 | 104 | ```bash 105 | wrangler secret put SUBSCRIPTION_URL 106 | wrangler secret put PROXY_URL 107 | ``` 108 | 109 | ## 验证部署 110 | 111 | 1. 访问你的 Worker 或 Pages 域名 112 | 2. 检查页面是否正常加载 113 | 3. 检查状态指示器是否显示正确 114 | 4. 测试订阅链接复制功能 115 | 116 | ## 故障排除 117 | 118 | ### 问题:环境变量未生效 119 | 120 | **解决方案**: 121 | - 确认环境变量已正确添加 122 | - 重新部署 Worker 123 | - 检查变量名是否正确(区分大小写) 124 | 125 | ### 问题:API 返回 403 错误 126 | 127 | **解决方案**: 128 | - 这是 Referer 检查导致的 129 | - 确保从正确的域名访问 130 | - 不要直接访问 API 端点 131 | 132 | ### 问题:链接检测失败 133 | 134 | **解决方案**: 135 | - 检查环境变量中的链接是否正确 136 | - 确认链接可以访问 137 | - 查看浏览器控制台的错误信息 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🚀 Hello Snippets - 2 | 3 | **双模式功能 支持你的snip反代检测 支持你的公益订阅链接** 4 | 5 | 6 | 7 | **【你可以把它作为你的snip反代检测域名是否失效 支持手动写入公益订阅链接进行分享】** 8 | 9 | **此项目为snip反代检测域名是否失效为制作 【主要】** 10 | 11 | **也可以作为你的公益订阅分享站 【次要】** 12 | 13 | **双模式完美支持 【更新完成 完美支持worker部署 支持Pages GitHub 部署】** 14 | 15 | **特别声明:此项目不支持pages上传部署! 【取消上传部署的方式禁上传】** 16 | 17 | **一个snip反代域名检测+公益订阅链接分享,具有自动链接状态检测功能。** 18 | 19 | **✅ 完美支持 Cloudflare Workers** 20 | **✅ 完美支持 Cloudflare Pages** 21 | 22 | image 23 | 24 | 25 | 26 | 27 | 28 | --- 29 | 30 | ## 📞 支持 31 | 32 | - **Telegram群组**: https://t.me/zyssadmin 33 | - **telegram作者**:https://t.me/ym94203 34 | - **Cloudflare Docs支持**: https://developers.cloudflare.com/ 35 | 36 | --- 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ⚠️ **免责声明** 46 | 本免责声明适用于 GitHub 上的 “snippet-FD-GY” 项目 【非新项目】 47 | 48 | 用途 49 | 本项目仅供教育、研究和安全测试目的而设计和开发。旨在为安全研究人员、学术界人士及技术爱好者提供一个探索和实践网络通信技术的工具。 50 | 51 | 合法性 52 | 在下载和使用本项目代码时,必须遵守使用者所适用的法律和规定。使用者有责任确保其行为符合所在地区的法律框架、规章制度及其他相关规定。 53 | 54 | 免责 55 | 作为本项目的 作者【非首次开发】,我 LH 强调本项目仅应用于合法、道德和教育目的。 56 | 作者不认可、不支持亦不鼓励任何形式的非法使用。如果发现本项目被用于任何非法或不道德的活动,作者将对此强烈谴责。 57 | 作者对任何人或组织利用本项目代码从事的任何非法活动不承担责任。使用本项目代码所产生的任何后果,均由使用者自行承担。 58 | 作者不对使用本项目代码可能引起的任何直接或间接损害负责。 59 | 为避免任何意外后果或法律风险,使用者应在使用本项目代码后的 24 小时内删除代码。 60 | 通过使用本项目代码,使用者即表示理解并同意本免责声明的所有条款。如使用者不同意这些条款,应立即停止使用本项目。 61 | 62 | 作者保留随时更新本免责声明的权利,且不另行通知。最新版本的免责声明将发布在本项目的 GitHub 页面上。 63 | 64 | ------------------------------------------------------------------------ 65 | 66 | ## ✨ 特性 67 | 68 | - 🔐 **完全加密** - 所有敏感链接通过环境变量管理,不出现在代码中 69 | - 🛡️ **防盗用保护** - API 端点具有 Referer 检查 70 | - 📊 **实时检测** - 自动检测订阅链接和代理链接的可用性 71 | - 📋 **一键复制** - 点击按钮即可复制订阅链接 72 | - 🎨 **现代设计** - 响应式界面,支持移动设备 73 | - ⚡ **高性能** - 基于 Cloudflare Workers,全球加速 74 | 75 | ------------------------------------------------------------------------ 76 | 77 | 78 | ------------------------------------------------------------------------ 79 | 80 | **环境变量重要设置** 81 | 82 | 83 | | 变量名 | 说明 | 示例 | 84 | |--------|------|------| 85 | | `SUBSCRIPTION_URL` | 订阅链接 | `https://your-subscription-link.com` | 86 | | `PROXY_URL` | SNIP反代链接 | `https://your-snip-domain.com` | 87 | 88 | ### 可选变量 89 | 90 | | 变量名 | 说明 | 默认值 | 91 | |--------|------|--------| 92 | | `TELEGRAM_URL` | 群组/个人链接 | `#` | 93 | | `BUTTON_TEXT_1` | 第一个按钮文字 | `可以修改你需要显示的内容` | 94 | | `BUTTON_TEXT_2` | 第二个按钮文字 | `可以修改你需要显示的内容` | 95 | 96 | 97 | ------------------------------------------------------------------------ 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ## 🚀 快速开始 106 | 107 | --- **worker部署**(小白最优选择) 108 | 部署 CF Worker: 109 | 110 | 登录你的cloudflare 111 | 找到计算和AI里的Workers 和 Pages: 112 | 选择从 Hello World! 开始: 113 | 114 | image 115 | 116 | 117 | 输入任意的work名称之后点击部署即可 118 | 119 | image 120 | 121 | 122 | 然后在cloudflare的Workers 和 Pages里面 找到你部署好的work项目 以我的项目为例: 点击编辑代码 123 | 124 | image 125 | 126 | 127 | 将 worker.js 的内容粘贴到 Worker 编辑器中并完成部署 128 | 129 | image 130 | 131 | **到这里worker部署就结束了** 132 | 133 | 134 | ------------------------------------------------------------------------ 135 | 136 | 137 | 138 | 139 | ---------------------------------------------------------- 140 | ### 方法二:Cloudflare Pages 部署 141 | 142 | 1. **Fork 本项目到你的 GitHub** 143 | 144 | 2. **连接到 Cloudflare Pages** 145 | - 登录 Cloudflare Dashboard 146 | - 进入 Pages 147 | - 点击 "创建项目" 148 | - 连接你的 GitHub 仓库 149 | - 选择本项目 150 | 151 | 3. **配置构建设置** 152 | - 构建命令:留空 153 | - 构建输出目录:留空 154 | - 根目录:/ 155 | 156 | 4. **添加环境变量** 157 | 在 Pages 项目的 **设置 → 环境变量** 中添加 158 | 159 | 5. **部署** 160 | - 点击 "保存并部署" 161 | 162 | ## 🔧 环境变量配置 163 | 164 | ### 必需变量 165 | 166 | | 变量名 | 说明 | 示例 | 167 | |--------|------|------| 168 | | `SUBSCRIPTION_URL` | 订阅链接 | `https://your-subscription-link.com` | 169 | | `PROXY_URL` | SNIP反代链接 | `https://your-snip-domain.com` | 170 | 171 | ### 可选变量 172 | 173 | | 变量名 | 说明 | 默认值 | 174 | |--------|------|--------| 175 | | `TELEGRAM_URL` | 群组/个人链接 | `#` | 176 | | `BUTTON_TEXT_1` | 第一个按钮文字 | `可以修改你需要显示的内容` | 177 | | `BUTTON_TEXT_2` | 第二个按钮文字 | `可以修改你需要显示的内容` | 178 | 179 | ## 📖 本地开发 180 | 181 | 1. **创建 .dev.vars 文件** 182 | bash 183 | cp .env.example .dev.vars 184 | 185 | 186 | 2. **编辑 .dev.vars 文件,填入你的配置** 187 | 188 | 3. **启动开发服务器** 189 | bash 190 | npm run dev 191 | 192 | 193 | 4. **访问 http://localhost:8787** 194 | 195 | ## 🔒 安全特性 196 | 197 | - ✅ 所有敏感链接通过环境变量加密存储 198 | - ✅ API 端点具有 Referer 验证 199 | - ✅ 前端代码中不包含任何硬编码链接 200 | - ✅ 防止爬虫抓取和 API 盗用 201 | 202 | ## 📝 API 端点 203 | 204 | - `GET /` - 主页面 205 | - `GET /api/get-subscription` - 获取订阅链接(需要 Referer 验证) 206 | - `GET /api/get-proxy` - 获取代理链接(需要 Referer 验证) 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | --- 219 | 220 | ## ✅ 验证清单 221 | 222 | 部署完成后,请检查以下项目: 223 | 224 | - ✅ Worker/Pages 可以正常访问 225 | - ✅ 页面样式显示正常 226 | - ✅ 状态指示器显示"检测中"后变为"正常"或"失效" 227 | - ✅ 点击订阅按钮可以复制链接 228 | - ✅ 点击群组按钮可以跳转 229 | - ✅ 浏览器控制台没有错误 230 | - ✅ F12 查看源代码,确认没有硬编码的链接 231 | 232 | --- 233 | 234 | ## 🔐 安全性确认 235 | 236 | worker.js 文件中: 237 | - ✅ 没有任何 https:// 链接硬编码 238 | - ✅ 所有链接通过 env 参数获取 239 | - ✅ API 端点有 Referer 检查 240 | - ✅ 环境变量未配置时返回错误 241 | - ✅ 完全符合加密要求 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | ## 🤝 贡献 251 | 252 | 欢迎提交 Issue 和 Pull Request! 253 | 254 | ## 📄 许可证 255 | 256 | MIT License 257 | 258 | ## 🙏 鸣谢 259 | 260 | - [Cloudflare Workers](https://workers.cloudflare.com/) 261 | - [Cloudflare Pages](https://pages.cloudflare.com/) 262 | ``` 263 | -------------------------------------------------------------------------------- /_worker.js: -------------------------------------------------------------------------------- 1 | // Cloudflare Pages Functions 入口文件 2 | // Pages 不支持 import 语法,需要直接包含所有代码 3 | 4 | export default { 5 | async fetch(request, env) { 6 | const url = new URL(request.url); 7 | 8 | // API端点:获取订阅链接 9 | if (url.pathname === '/api/get-subscription') { 10 | return handleGetSubscription(request, env); 11 | } 12 | 13 | // API端点:获取SNIP反代链接 14 | if (url.pathname === '/api/get-proxy') { 15 | return handleGetProxy(request, env); 16 | } 17 | 18 | // 主页面 19 | return new Response(getHTML(env), { 20 | headers: { 21 | 'Content-Type': 'text/html; charset=utf-8', 22 | }, 23 | }); 24 | }, 25 | }; 26 | 27 | // 处理订阅链接请求 28 | function handleGetSubscription(request, env) { 29 | const referer = request.headers.get('Referer'); 30 | const origin = new URL(request.url).origin; 31 | 32 | if (!referer || !referer.startsWith(origin)) { 33 | return new Response(JSON.stringify({ error: 'Unauthorized' }), { 34 | status: 403, 35 | headers: { 'Content-Type': 'application/json' }, 36 | }); 37 | } 38 | 39 | const subscriptionUrl = env.SUBSCRIPTION_URL; 40 | 41 | if (!subscriptionUrl) { 42 | return new Response(JSON.stringify({ error: 'SUBSCRIPTION_URL not configured' }), { 43 | status: 500, 44 | headers: { 'Content-Type': 'application/json' }, 45 | }); 46 | } 47 | 48 | return new Response(JSON.stringify({ url: subscriptionUrl }), { 49 | headers: { 'Content-Type': 'application/json' }, 50 | }); 51 | } 52 | 53 | // 处理SNIP反代链接请求 54 | function handleGetProxy(request, env) { 55 | const referer = request.headers.get('Referer'); 56 | const origin = new URL(request.url).origin; 57 | 58 | if (!referer || !referer.startsWith(origin)) { 59 | return new Response(JSON.stringify({ error: 'Unauthorized' }), { 60 | status: 403, 61 | headers: { 'Content-Type': 'application/json' }, 62 | }); 63 | } 64 | 65 | const proxyUrl = env.PROXY_URL; 66 | 67 | if (!proxyUrl) { 68 | return new Response(JSON.stringify({ error: 'PROXY_URL not configured' }), { 69 | status: 500, 70 | headers: { 'Content-Type': 'application/json' }, 71 | }); 72 | } 73 | 74 | return new Response(JSON.stringify({ url: proxyUrl }), { 75 | headers: { 'Content-Type': 'application/json' }, 76 | }); 77 | } 78 | 79 | // HTML页面生成函数 80 | function getHTML(env) { 81 | const telegramUrl = env.TELEGRAM_URL || '#'; 82 | const buttonText1 = env.BUTTON_TEXT_1 || '复制订阅链接'; 83 | const buttonText2 = env.BUTTON_TEXT_2 || '加入 Telegram 群组'; 84 | 85 | return ` 86 | 87 | 88 | 89 | 90 | Hello Snippets! 91 | 267 | 268 | 269 |
270 |
271 | 272 | 273 | 274 |
275 | 276 |

Hello Snippets!

277 | 278 |
279 |
280 | 正在检测代理功能... 281 |
282 | 283 |
284 | 正在检测公益订阅... 285 |
286 |
287 | 288 |

289 | 正在检测服务状态,请稍候... 290 |

291 | 292 | 293 | 294 | 295 | 296 | ${buttonText1} 297 | 298 | 299 | 300 | 301 | 302 | 303 | ${buttonText2} 304 | 305 | 306 | 309 |
310 | 311 | 442 | 443 | `; 444 | } 445 | --------------------------------------------------------------------------------