[{"content":"iOS/iPadOS 设备教程 登录你的美区Apple ID，如果没有请自行注册，或搜索 Apple ID共享，这里是一个可能有用的链接：https://idshare001.me/goso.html 搜索 Clash Mi（免费） 或Shadowrocket并下载（付费） 如果你使用的是Shadowrocket，请复制你的订阅链接后，打开应用（可能会索要权限，请给予；可能会要求安装VPN，请允许并输入锁屏密码），点击右上角加号，在剪贴板有订阅链接的情况下，链接会自动填充，此时只要点击右上角保存即可 若有多个链接，可通过此方法依次添加\n如果你使用的是Clash Mi，请复制你的订阅链接后，打开应用（可能会索要权限，请给予；可能会要求安装VPN，请允许并输入锁屏密码），点击我的配置，然后点击右上角加号，在剪贴板有订阅链接的情况下，点击从剪贴板导入链接会自动填充，此时只要点击右上角对钩即可\n若有多个链接，可通过此方法依次添加\n如果你使用的是Shadowrocket，在导入完链接之后，就可以点击屏幕上部未连接右侧的开关启动VPN的链接*（可能会索要权限，请给予；可能会要求安装VPN，请允许并输入锁屏密码）*，然后点击屏幕上部的全局路由选择代理选项，回到首页，在所有订阅链接都展开的情况下（不展开的链接默认不检测），点击屏幕上部连通性测试进行测速（建议同时打开应用内设置\u0026ndash;\u0026gt;向下滚动到订阅\u0026ndash;\u0026gt;打开根据ping值排序开关），然后选择速度与国家合适的节点 如果你使用的是Clash Mi，在导入完链接之后，点击点击屏幕上部未连接右侧的开关启动VPN的链接（可能会索要权限，请给予；可能会要求安装VPN，请允许并输入锁屏密码），然后点击屏幕中下部的代理，点击屏幕右上角的闪电图标进行测速，并等待测速完成，完成后点击屏幕上部节点选择，然后选择速度与国家合适的节点\n如果你想深入探索上面两个应用，可自行搜索相关知识，同时推荐项目 [Shadowrocket 使用手册 补完计划](https://lowertop.github.io/Shadowrocket/)，可自行学习。同时推荐该项目的懒人配置，在配置页面下载并切换配置，并将全局代理切换为配置，效果比代理好 Android 设备教程 下载 Flclash 并安装\n下载链接：https://github.com/chen08209/FlClash/releases/download/v0.8.96/FlClash-0.8.96-android-arm64-v8a.apk，该链接为GitHub链接，指向教程编写时的最新版\n打开Flclash\n点击下方配置 点击下方添加配置 点击URL 输入订阅链接并确定，结果如图2 点击仪表盘以回到首页，然后点击右下角三角形按钮以开起VPN（可能会索要权限，请允许） 点击代理，然后点击延迟测试以测速，然后选择速度与国家合适的节点 Windows 设备教程 下载Clash Verge Rev，双击安装包并安装（若申请管理员权限则允许），步骤如下 选择语言（推荐中文简体），点击OK 点击下一步 点击下一步 点击安装 等待 点击下一步 点击完成 后续可能会申请两次管理员权限，允许即可 导入配置文件 若配置文件需从链接下载，则点击左侧订阅，在页面上方订阅文件链接处输入链接，点击右侧导入即可。 若配置文件在本地，则只需将文件拖拽进窗口即可 使用\n点击左侧设置，点击左列系统代理即可使用，不需要时可直接关闭系统代理 推荐打开：开机自启；静默启动；局域网链接 局域网链接说明：对于部分无法使用clash客户端的设备*（iPhone 4s亲测可用）*，可通过这种方式实现曲线救国，具体操作如下： 点进设置并与电脑链接在同一局域网，点进网络详情，将http代理切换为手动，服务器填写为电脑的内网IP地址，可点击clash设置中局域网链接旁边的有三个连接在一起的方块的图标查看，上面的IP地址即为所要 端口默认是7897 关闭鉴定 Linux 设备教程（适用于Ubuntu/Debian系） 下载Clash Verge Rev 安装（可双击启动应用商店安装或 sudo apt install ./Clash Verge_2.5.2_amd64.deb) 导入配置文件 若配置文件需从链接下载，则点击左侧订阅，在页面上方订阅文件链接处输入链接，点击右侧导入即可。 若配置文件在本地，则只需将文件拖拽进窗口即可 使用\n点击左侧设置，点击左列系统代理即可使用，不需要时可直接关闭系统代理，同时推荐打开Tun模式，需输入用户密码安装服务 Linux 设备教程（适用于Arch系） 添加 archlinuxcn源\n编辑 pacman 配置文件添加 archlinuxcn 源\nsudo vim /etc/pacman.conf 文件底部写入\n[archlinuxcn] Server = https://mirrors.ustc.edu.cn/archlinuxcn/$arch Server = https://mirrors.tuna.tsinghua.edu.cn/archlinuxcn/$arch 上面这两个是国内镜像，ustc（中科大）和 tuna（清华），如果你在海外的话可以直接使用官方：\nServer = https://repo.archlinuxcn.org/$arch 同步数据库并安装 archlinuxcn 密钥\nsudo pacman -Sy archlinuxcn-keyring sudo pacman -Syu 安装\nsudo pacman -S flclash 启动\nflclash 在主页开启 TUN（虚拟网卡）\n导入链接\n主页右下角有个三角，点击可以启动代理\n测试是否生效\nLinux 设备教程（适用于Fedora系） 安装 Throne（需添加COPR） 打开 Throne 请复制你的订阅链接后，点击 程序\u0026ndash;\u0026gt;添加剪贴板的配置档，然后按照需要选择添加到当前分组或新建分组 开启 TUN（虚拟网卡） 添加完所有链接后，使用 ctrl + a全选节点，并右键，选择URL测试选定项，然后选择速度与国家合适的节点。 注：在Fedora上，由于selinux的存在，Clash以及mihomo内核的代理软件在Tun模式下总是会有问题，因此推荐使用sing-box内核的代理软件。在使用中遇到问题，可尝试切换Tun设置的stack模式，或重启软件\n","date":"2026-09-05T23:54:22+08:00","image":"/images/Shadowrocket.png","permalink":"/posts/%E6%9C%BA%E5%9C%BA%E6%A2%AF%E5%AD%90vpn%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B%E9%87%8D%E5%88%B6%E7%89%88/","title":"VPN使用教程（重制版）"},{"content":"新节点更新与使用须知 九幺节快乐，祝大家身体健康，网速起飞。\n顺便祝徐州三中提前开学校领导死全家。\n🛡️ 安全与分享 本群自第二次更新以来一直免费。 请勿在公共平台随意传播订阅链接，仅分享给信任的人。 捐助为自愿行为，仅用于覆盖链接购买和续费成本，不用于营利。 机场不适合用来打游戏。 🔒 安全与隐私 建议注意 IP 和 WebRTC 泄露，定期进行检测。\nIP 检测： https://ippure.com/\nWebRTC 泄露检测： https://ippure.com/Browser-WebRTC-Leak-Detect/\n科普视频： https://www.bilibili.com/video/BV1ofR5B6E72/\n🔗 订阅链接 查看置顶消息\n如遇失效，请在群内反馈。\n📖 使用教程 查看网页 vpn使用教程重制版\n💻 客户端下载 Windows 端 看群置顶消息 或从 https://github.com/clash-verge-rev/clash-verge-rev/releases/ 下载。\nAndroid 端 看群置顶消息 https://github.com/chen08209/FlClash/releases/download/v0.8.96/FlClash-0.8.96-android-arm64-v8a.apk\n🍎 Apple 用户（iOS / iPadOS） 苹果系统无法直接安装上述文件，须使用 Shadowrocket 或 Clash Mi。 下载该软件需要美区 Apple ID（国区搜不到）。 如果在下载、ID 切换或设置上遇到困难，请访问： https://idshare001.me/goso.html 🐧 Linux Debian 系：\n推荐 Clash Verge Rev\nhttps://github.com/clash-verge-rev/clash-verge-rev/releases/download/v2.5.2/Clash.Verge_2.5.2_amd64.deb\nFedora 系：\n推荐 Throne\nhttps://github.com/throneproj/Throne\nArch 系：\n推荐 FlClash\nhttps://github.com/chen08209/FlClash\n📅 后续计划 自购推荐：如果你追求更极致的稳定，想购买专属自己的机场，可以参考：\n机场推荐：\nhttps://github.com/DiningFactory/panda-vpn-pro\n机场测评：\nhttps://jichangblog.com/\n下一次群公告：十月国庆\u0026ndash;\u0026gt;增添机场\n📩 联系方式 邮箱：\nthe.tequila.sunset@icloud.com\nTelegram：请见下方名片/照片\n微信：点击群主头像直接私聊/下方收款码\n再次祝大家生活愉快，冲浪愉快！\n","date":"2026-09-05T23:42:47+08:00","image":"/images/Va-11 Hall-A.webp","permalink":"/posts/%E7%BE%A4%E5%85%AC%E5%91%8A/","title":"群公告"},{"content":"第二幕（上） ​\t在加了她的微信后，他几乎没有和她说过一句话，只是互相确认了名字。 ​\t“香——雪——”在得知名字后，他的同学大声呼喊着这个牵动他心弦的名字，就像他曾经对他的同学做的。\n​\t可这时的的他却几乎脸红得说不出话来——就在这个课间，他刚刚找到了她并见了她一面。“ ​\t约会约的怎么样啊？”故意将话音拉得很长，带着一股揶揄的意味。声音飘然而至，仿佛一根针在他的心上刺了刺。他知道，那男生一定是在逗他，笑话他。他当然知道这次“约会”究竟怎样，因为当时的他就在一旁看着。\n​\t“去你妈的。” ​\t微红的脸颊和涌上心头的羞愤让他终于有了反应——四个字像是从喉咙深处挣扎着吐出来，带着一些愤怒，也有些无奈的羞愧。他甚至不敢去看那些期待自己“反应”的眼神。\n​\t“哈哈哈哈哈哈哈哈哈哈哈哈！”\n​\t那个男生笑得前仰后合，声音粗犷且高亢，像是放肆的炸裂声在整个班级里回响。\n​\t“‘你好’？这他妈是人吗？就……就他妈一句‘你好’？”笑声震得他耳朵嗡嗡作响，仿佛他不仅是被笑话，而是被整个世界嘲弄。那笑声带着一点点恶作剧，又多了一些暧昧，恍如一场无声的闹剧，所有人都在旁观，而他是那个被戏耍的主角。\n​\t他本想反驳，又觉得这场“羞耻剧”已经无法收场，只能低下头，尽量不去看那些从自己脸上划过的笑意，深怕再被那群看热闹的同学抓住一丝细微的破绽。\n​\t空气突然变得很沉默，只有那个男生的笑声还在空中回荡。其他的同学开始交换眼神，似乎在等待他的下一步反应。他感到一阵羞愧如潮水般涌来，那种青涩感和紧张，几乎让他无法呼吸。 ​\t但他知道，这个羞涩的他，或许在下一秒，就会再次给她发一条消息，只是简单的“你好”——即使明知道这可能只是他的一个幻想，一个连他自己都不确定是否真实存在的幻想。\n​\t不过，现在的他，还是太不敢面对了。\n第二幕（下） ​\t在事态彻底失控之前，那位同学终于站出来，冷冷地拦住了十几位围在楼梯间的男生。\n​\t“去他妈那么多干嘛？妈的，半个班都来了。”他语气里带着些许不耐烦，双手插在裤兜里，狠狠地瞪着围在四周的同学。 ​\t他面前站着的是十几位男生，他们站得很密集，每个人的脸上都有一种急切而又隐晦的期待。大家的目光似乎都锁定了一个地方，紧盯着楼梯口，只等着一个人的出现。而他们聚集在这里的唯一目的，就只有一个问题：\n​\t“那个香雪长什么样啊？你指给我看看。”\n​\t这十几位男生的声音交织在一起，带着一丝低沉的亢奋，仿佛整个空间都弥漫着一种难以言表的气氛。而他，那个曾经羞涩地低下头的男生，也在其中——不在场的香雪，恍若成了他们唯一的目标。\n​\t“我靠，都回去一个一个来行不行。”那位发言的同学又开始不耐烦了，他扭头拉着自己身边的一个哥们，向楼梯走去，脸上露出几分不耐的表情。他看了看楼梯口，又压低了声音，“听着，我没办法当着人的面指人家，所以我只能和你说她的特征，你自己来找……” ​\t话音未落，他的眼睛迅速扫向走廊尽头。\n​\t“哎，看，她来了。”\n​\t他一边说着，一边把视线死死锁定在前方。那一刻，他仿佛变得无比专注，眼神紧追着她的身影，甚至有些不自觉地张开了嘴。 ​\t“看看看，就是前面那个穿着灰衣服的，长发，戴黑框眼镜……”他低声叨叨，话语如同一串串被迅速打散的文字，“喏喏，还在撩头发嘞……” ​\t他几乎是指着她的背影，似乎已经不满足于这点信息，眼神像刀子一样跟随着她的动作，想要抓住每一个细节。她没有注意到他，依旧悠闲地走着，头发随风轻轻扬起，走廊的灯像是聚光灯一样打在她头上。 ​\t两人悄无声息地擦肩而过，几乎是在瞬间便穿越了整个走廊。\n​\t“怎么样怎么样？”站在楼梯间的其他同学似乎已经等不及了，他们一窝蜂地围上来，眼睛里满是期待。 ​\t那位同学故作沉思，手指轻轻摩挲着下巴，像是要把心中的判断做个最后的确认。他稍微眯起眼，似乎想要从那一刹那的回忆里提取出更多的细节。\n​\t“嗯……”他缓缓吐出一个音节，最后目光从空中移回，手指一扬。\n​\t“六？”其中一个同学立刻跟上，脸上带着疑惑，“六六六？” ​\t“六分。”他轻轻地吐出这两个字，眼中带着一点戏谑的意味，仿佛自己也知道这答案的荒唐和轻浮。 ​\t顿时，周围响起了一阵大笑声。男生们的笑声激烈而嘲弄，像是刚刚完成了一场让人发笑的赌注，笑得有些过火，像是只要再笑一笑，整个世界就能毁灭掉。 ​\t“六分？”另一个男生挑了挑眉，似乎觉得这个评判有点不足为道，但还是忍不住附和着，“你也太严格了吧。就她那样，我给个八分都行。” ​\t“八分？”另一个同学反问，仿佛在挑战刚才的答案，“你是来打分的，还是来找对象的？”他调侃的语气越来越露骨，语调里带着一点笑意，却又有些刻意的粗暴。\n​\t他们的笑声越来越响，楼梯间的空气也变得越来越窄。\n​\t而那个男生，在这一连串的对话和笑声中，低下了头，嘴角微微抽动，显然并不愿意继续参与这场不由自主的评价。他的目光有些飘忽，望着香雪的背影，似乎从她的身影中找到了某种微弱的安慰。\n​\t这一切，似乎已经变得如此平常——在这群孩子的世界里，青春的荒唐和陌生都只不过是短短的瞬间和空虚的笑声。\n​\t然而，那个瞬间对他而言，却可能成为永远的记忆。\n","date":"2026-04-19T15:26:51+08:00","permalink":"/posts/%E4%B8%89%E4%B8%AD%E9%9D%9E%E6%83%85%E6%99%AF%E5%BC%8F%E5%96%9C%E5%89%A7-%E7%AC%AC%E4%BA%8C%E5%B9%95/","title":"三中非情景式喜剧  第二幕"},{"content":"第一幕 ​\t厕所门被拆下之后，围观的人就像闻到了某种甜腥气味的鱼群，从四面八方涌了过来。走廊与厕所交界处很快堵得水泄不通，空气中弥漫着一股消毒水混合潮湿墙皮的味道，还有少年们身上那种刚打完球、没来得及洗的汗味。 ​\t他们都抱着看热闹的心态——眼里闪着兴奋的光，像是久被压抑的生活里突然炸开的一点荒唐火花。没人感到愤怒或害怕，他们甚至刻意压低笑声，只为了让这件事显得更“隆重”一点。有人踮起脚尖，有人扒着窗台往里探头，那姿势就像在围观一场神秘的祭典。 ​\t厕所门板孤零零地躺在地上，裂痕像干涸的河道。门的另一面还沾着几缕灰色的厕纸和脚印，看起来既像遗体，又像战利品，还像一条蛇腿的皮——没有灵魂，也有不了灵魂。\n​\t“靠，我们需要一个‘大人物’！”左手缠着绷带的篮球生从厕所冲出来，脚步声在地砖上砰砰作响，裤腿上带着未干的尿痕，像是从某个混乱的战场撤出来的士兵；他的发型像一架小飞机，正随着呼吸一抖一抖。他说完，又像突然被自己逗笑了，“呃，是‘小人物’！哈哈，一个足够小的小人物！” ​\t他的笑声在走廊里炸开，像粉笔在黑板上划出的尖锐声。发梢抖动着，嘴角起了泡，像是某种神圣的泡沫，整个人像是刚被电过一样兴奋。 ​\t始作俑者站在人群中间，腰杆笔直，像个小国的独裁者。他的眼神在周围扫视，带着掠食者式的饥饿，又带着审视、挑选和某种异样的温柔——那种对待牺牲品的温柔。他在寻找——一个合适的祭品。嘴角浮出笑容，那笑容像是从梦里带出来的，不完全属于人类。\n​\t一个声音在他脑中响起：\n​\t“A soul\u0026hellip; a perfect soul.”\n​\t然后他出手——没有预兆，没有犹豫，像抓一只逃跑的猫。他的手臂划破空气，带出一阵风声。那被抓的人只来得及发出半声惊呼，便被按倒在地，脸紧贴着冰冷的地砖。旁观的人先是一愣，然后笑出声来，那笑声不是真的愉快，更像是一种被强迫参与的仪式性反应。\n​\t“四个角，快点！” ​\t“抬——！”\n​\t四个高大的身影弯下腰，把那块门板抬了起来。门板轻轻一晃，发出呜咽般的木头声。被压在上面的人一动不动，仿佛真成了一具供奉的祭品。 ​\t走廊尽头的灯忽明忽暗。四人齐步走着，脚步整齐得诡异。围观的人群自发地让开一条路，那气氛说不清是敬畏还是兴奋。有人轻声吹起口哨，有人忍不住笑出猪叫般的声响。 ​\t这是一场没有乐队、没有鼓点的游行。 ​\t他们抬着那扇门板，穿过防火门，朝教室区走去。空气里是笑声，是尘土，是那种青春期特有的盲目冲动——一种能把一切都焚烧干净的力量。\n​\t欢愉。 ​\t那种能毁灭一切、甚至毁灭自己的欢愉。\n​\t门板最后被抬到走廊尽头，在某个不知是谁喊的口令之后，突然就被随手丢了下来。砰——一声闷响，在地砖上震出一阵尘土，像某种仪式的终结。\n​\t那声音很干净，很轻蔑。\n​\t人群停顿了一下，似乎还没反应过来这出“戏”已经结束了。然后有人笑出声来，笑声有点僵硬，有点迟疑，但很快又蔓延开，像一阵无目的的风。大家互相拍了拍肩膀、交换了几句模糊的感叹，就这么散开了。几分钟内，走廊重新变得空荡——只剩一地脚印和那扇门板，斜靠在墙边，像什么都没发生过。\n​\t没有老师来。 ​\t没有训话，也没有通报。\n​\t然后呢？\n​\t卫生间恢复原状。 ​\t地面被拖干净，气味依旧。\n​\t而那些昨天下午还挤在走廊里的人，一个个又坐回了教室，眼神空白，头发油亮，像什么都不记得。有人在课桌上画格子，有人趴着睡觉，有人抠掉课本的封皮角落——他们依旧活在那种既安稳又荒谬的节奏里。 ​\t偶尔有风从窗外吹进来，带着操场上吹哨的回音，卷起一角卷纸，飘进厕所门缝里，又出来。 ​\t没人去看那扇门，也没人再提那件事。\n​\t它只是门—— ​\t不是祭品，不是战利品，更不是笑料。\n​\t只是门，被卸下过、又被装回去。 ​\t就像一切被拆开的东西，最终都会被装回去。 ​\t没有痕迹，没有记忆，没有意义。\n​\t只有那种说不清的—— ​\t荒唐之后的宁静。\n","date":"2026-04-19T15:25:44+08:00","permalink":"/posts/%E4%B8%89%E4%B8%AD%E9%9D%9E%E6%83%85%E6%99%AF%E5%BC%8F%E5%96%9C%E5%89%A7/","title":"三中非情景式喜剧"},{"content":"快到了。\n“啊好……我去怎么这么多人。”健哥往车窗外瞟了一眼，瞬间坐直。\n“初三，你指望全国人民在家打坐吗？”王刚说，“连禁燃令都管不住烟花，你还指望别人给你让路？”\n我插了一句：“那八个被炸死的……也挺可怜。”\n“可怜？”王刚嗤了一声，“调皮捣蛋的孩子长大了也未必省心。命运有时候只是提前收尾。”\n“话不能这么说。”健哥替我圆场，“那万一路过你不炸了……哎，我是不是说了个双关？”\n没人接他。\n我催王刚快点开。作为唯一有驾照的人，他硬生生开了一千多公里没抱怨一句。换我，早就靠着安全带睡着了。可这会儿王刚明显疲了，每开一段就打个哈欠。为了防止他脸贴喇叭，我和健哥只好轮流跟他说话。\n“我先去停车，你们下车等。”王刚把车门锁打开。\n刚下车，旁边交警一声哨：“往前走，行人让一下车。”\n我们被吹得像犯错的小学生，赶紧往前挪，一直走到石门前。\n我给王刚发语音：“景区门口石门这儿。”\n健哥忽然说：“刚才那个女交警挺好看。”\n我回忆了一下，确实好看。那种现实生活里会让人多看两秒的好看。\n“这种人当交警挺浪费的，当主播估计赚得多。”健哥继续发挥。\n我没说话。我在想她好看在哪，是五官比例，还是制服滤镜，还是别的什么。\n“你要微信不？”健哥问。\n“你有病吧。”我结束话题。\n我们在石门旁等王刚。五分钟后他来了。\n“你俩排队啊，后面都绕几圈了。”\n我一拍脑袋：“失误了，失误了。”\n队伍像条盘着的蛆。\n“什么时候是个头？”健哥叹气。\n“问路易十六。”我说。\n王刚白了我们一眼：“你俩早点排，现在都进去了。”\n“失误了，失误了。”健哥举手投降。\n这时，一个穿白色羽绒服的女生从我们前面经过。脸不算惊艳，但像松鼠，挺可爱的。\n“好看不？跟刚才那个比呢？”健哥问。\n我说：“能卖多少钱？”\n王刚瞥一眼：“五百。”\n我让他等转弯看正脸。他看完，仍坚持五百。\n我没再争。\n队伍转得比想象快，但我的视线慢得很。我甚至动了加她微信的念头。然后想到明天回徐州，还要那些异地恋的下场，所有念头都自动注销。\n检票时发现十八岁以下半价。我和健哥对视一眼，像捡到钱。王刚掏出学生证，说本科生也半价。于是我们三个人带着“省下来的六十块”，走进院子。\n院子里花灯很多。前提是那真的是花灯。我盯了半天，没看出和商场门口装饰有什么区别。可能区别就在“亮”与“不亮”之间。问题是现在还没亮。\n这也算非遗？\n院子里文化氛围浓厚，和李清照有关。但对于三个男生——俩高中生一个大学生——文化通常敌不过网吧。\n我们随便逛了一圈，坐着等灯亮，黄昏时候能亮，所以我们坐着等黄昏。\n旁边有人喊：“下载快手极速版送纪念币！”\n我过去打开软件。\n“得新用户。”对方摆手。\n人生的门槛，往往比门票还严。\n健哥符合条件，去领币。我和王刚坐着等。\n“人生无常。”我说。王刚没理我，他站起来了。\n灯亮了。\n说实话，灯亮和没亮差别不大。如果这就是非遗，可能真是山猪吃不了细糠。\n王刚突然说要上厕所。于是我们满院子找厕所。找到后发现里三层外三层。\n“怎么哪都排队。”王刚说。\n“外面人多，里面当然也多。”健哥回答。\n我挤进去，刚等到位置，突然有人插队，裤子一脱就解决。\n我重新系好松紧带，继续等。\n出来后我们走到最热闹的地方。\n“钓突泉。”我说。\n“念bào。”王刚纠正。我尴尬地笑了笑。\n人围着一个水池。我看不到泉眼。健哥挤进去拍视频给我。\n我点开——三个泉眼冒水。\n天下第一泉。\n就这？\n我突然怀疑里面的泉眼是不是早就干了，政府为了赚钱，装了水泵，节假日启动，工作日休眠。\n王刚则盯着旁边的买手店说：“市场化太重了，这种地方不该开店。”\n“文化圣地。”我笑，“收我六十块。”\n我摸口袋。\n空的。\n“操！”\n不知道是丢了，还是刚才厕所里被顺走。\n王刚指了指旁边一个打扮得很用力的女生。\n我没看，手仍在口袋里。\n我只盯着那三股水流，觉得它们努力得有点像阳痿——拼命证明自己还在。\n周围是商品，包装成文化；文化，包装成商品；人，也包装成商品。\n我叹了口气。想起自己遇到的某个女生。也是商品。\n然后向泉水那边走去。\n","date":"2026-04-19T15:24:33+08:00","permalink":"/posts/%E8%B6%B5%E7%AA%81%E6%B3%89/","title":"趵突泉"},{"content":"\n本使用手册以 Shadowrocket 官方群组 使用的关键词列表文件为基础进行完善更新，包含软件绝大多数功能的介绍和部分常见问题的解答，以期能够帮助用户更好的理解和使用 Shadowrocket 软件。本仓以普通用户的身份对原作者及所有为相关项目做出贡献的人表示由衷的感谢！其他使用需求可尝试查看 配色与配置仓库\n💡 提示 懒人配置\nhttps://lowertop.github.io/Shadowrocket/lazy_group.conf 懒人配置是专为 Shadowrocket 打造的开箱即用的配置文件，首发于 官方群组。该配置文件优化了各项设置并内置了常用的规则/规则集以及常用的代理分组/策略组，同时包含详细的参数说明，可在纯文本模式下详细查阅，适合几乎任何阶段的用户使用\n本仓与官方群组发布的版本同步更新，Johnshall 的版本也与本仓保持同步。对新手用户而言更推荐 访问官方群组 使用离线版本\nShadowrocket 使用手册 📝 备注 Shadowrocket（常被用户称为 小火箭）是一款由 Shadow Launch Technology Limited 专为 iOS 设备开发的网络代理工具，同时也支持 Apple TV 等设备，软件自 2.2.70 (2712) 版本起已正式支持 macOS\n官方群组：Shadowrocket App\n官方频道：Shadowrocket News\n反馈邮箱：buginapp@gmail.com\n使用目录 点击 目录标题 可以快速定位到相关正文\n点击正文的 蓝色标题 可以快速回到目录\n首页 快速使用方法 添加节点 协议类型 更新订阅节点 节点排序 节点分享与整理 订阅节点筛选 代理通过/代理链 全局路由 连通性测试 修改测试地址 场景 简单模式 启用回退 配置 配置文件 使用配置 编辑配置 编辑纯文本 编译配置 预览配置 更新配置 重新命名 导出配置 扩展配置 通用参数 隐式参数💡 添加规则 规则优先级 规则类型 规则策略 策略扩展参数 APP分流 更新规则集 预览规则集 修改DNS DNS-over-PROXY no-resolve的作用 代理分组 代理分组类型 隐藏代理分组 负载均衡 规则集URL 脚本URL 复制配置文件 替换策略 测试规则 Hosts URL重写 头部重写 正文重写 本地映射 HTTPS解密 脚本 模块 编辑参数 证书模块 身份证书密码 编写本地节点 数据 代理日志 DNS日志 iCloud自动同步 节点数据管理 流量统计信息 设置 延迟测试方法 小组件 颜色 按需求连接 隧道 兼容模式 前置代理 代理共享 代理类型 开启UDP转发 禁用STUN 权限 隐藏VPN图标 GEOIP数据库 自动更新 温和策略机制 其他 自动切换节点 订阅异常 节点旗帜 节点感叹号 微信转圈 模块消失 模块失效 VPN自动断开 检测代理 编译原因 URL-Schemes 软件首页 快速使用方法 首页 \u0026gt; 添加节点\n设置 \u0026gt; 延迟测试方法 \u0026gt; CONNECT\n首页 \u0026gt; 连通性测试 \u0026gt; 选可用节点连接\n首次启动会提示 安装VPN配置文件，请点击 好 和 允许 才能正常使用\n添加节点 Shadowrocket 兼容多种服务器订阅格式，以及支持多种 代理协议类型 包括 WireGuard 节点\n首页 \u0026gt; 左上角 \u0026gt; 扫码添加\n此操作须开启摄像头权限\n复制节点链接，如 trojan://*、vmess://*、vless://* 等，打开 Shadowrocket 时会自动识别导入\n此操作须开启剪贴板读取权限\n首页 \u0026gt; 右上角 ➕ \u0026gt; 类型 Subscribe \u0026gt; URL 栏输入服务器订阅链接 \u0026gt; 保存\n订阅链接后面加上 #1、#2、#3 等，可以重复添加同一个订阅\n长按服务器订阅可选 隐藏 功能，启用后该订阅将默认不显示任何节点，该功能等同于在订阅编辑内的 最大值 填写数字 0\n首页 \u0026gt; 右上角 ➕，选择对应节点类型，填写节点配置信息并保存\nShadowrocket 为了兼容部分其他类型的配置文件，也支持在配置文件中 编写本地节点 信息，但不要当作 添加节点 的优先选择\n若添加或更新订阅时出现异常，请参见 订阅异常\n添加WireGuard节点\n首页 \u0026gt; 右上角 ➕ \u0026gt; 类型选择 WireGuard，填写配置信息\n复制如下格式的 WireGuard 配置信息，打开 Shadowrocket 时会自动弹出 添加对话框，点击添加\n[Interface] PrivateKey = xxxxxx Address = 172.16.0.2/32 DNS = 1.1.1.1 MTU = 1420 [Peer] PublicKey = xxxxxx AllowedIPs = 0.0.0.0/0 AllowedIPs = ::/0 Endpoint = engage.cloudflareclient.com:2408 Reserved = 12,34,56 如果没有自动弹出对话框，可能是因为设置中的 允许检测剪贴板 被关闭了，您可以重新打开，或者点击首页 连通性测试 下方的 粘贴 按钮，手动添加配置信息\n协议类型 现阶段已支持的协议类型\nSubscribe（订阅）、Shadowsocks、ShadowsocksR、Vmess、VLESS、Relay、Socks5、Socks5 Over TLS、HTTP、HTTPS、HTTP2、Trojan、Hysteria、Hysteria2、AnyTLS、TUIC、Juicity、SSH、WireGuard、Snell v1-3、Mieru、Brook、Lua\n当前版本支持的协议可在 首页 \u0026gt; 右上角 ➕ \u0026gt; 类型 中查看\n各协议节点的纯文本格式参见 编写本地节点\n更新订阅节点 订阅右滑 \u0026gt; 更新\n点击首页的更新订阅按钮🔄\n设置 \u0026gt; 订阅 \u0026gt; 打开时更新（刷掉后台，重新打开应用程序时会自动更新订阅）\n设置 \u0026gt; 订阅 \u0026gt; 自动后台更新（需在系统 设置 \u0026gt; 通用 \u0026gt; 后台App刷新 中开启对 Shadowrocket 的允许，更新周期可设1-24小时）\nShadowrocket 提供了 更新订阅 的快捷指令，可以实现自动化操作\n长按屏幕的应用图标 \u0026gt; 更新订阅\n软件提供 自动更新 服务\n若添加或更新订阅时出现异常，请参见 订阅异常\n节点排序 设置 \u0026gt; 订阅 \u0026gt; 根据 Ping 排序 该操作支持节点按照延迟测试后得到的延迟数值进行由低到高的自动排序\n节点分享与整理 节点分享\n长按节点 \u0026gt; 拷贝，可以把节点链接分享给其他设备\n左滑节点 \u0026gt; 二维码，其他设备可以通过扫码添加节点（二维码页面点击右上角的 分享 按钮，可以选择其他形式传送二维码）\n节点二维码缺乏统一标准。当使用其他代理工具扫码添加某些节点时，可能会丢失部分节点信息，导致不能连接。如果遇到此问题，请仔细检查同一个节点的各项配置信息是否一致\n点击节点后面的 ⓘ 图标，滑动至页面底部，有多种分享节点的菜单\n展开节点列表，点击连通性测试下方的编辑按钮 •••，勾选需要分享的节点，点击左上角的 复制，可以把多个节点链接同时分享给其他设备\n节点整理\n调整顺序：点击编辑按钮 •••，或者长按首页右上角的 ➕，即可进入编辑模式，按住订阅或节点后面的 ≡ 图标可以调整订阅或节点之间的上下顺序（本地节点默认置顶位置）\n节点分类：非订阅形式添加的节点，默认会归类为 本地节点。如果需要重新对本地节点进行分类，可以使用 折叠 功能。点击编辑按钮 •••，勾选节点，点击左上角的 折叠，为新分类的节点组命名（折叠 功能可以选择本地节点或者订阅节点）\n删除节点：点击编辑按钮 •••，点击左上角的 删除，可以选择删除全部节点或者删除连通性测试结果中的超时节点\n滑动菜单：向右滑动订阅，可以选择 测试 当前订阅节点的连通性，或者 更新 当前订阅节点。向右滑动节点，点击 测试 可以获取单个节点的连通性测试结果，点击 复制，可以在当前节点列表中新增一个同样配置信息的节点\n订阅节点筛选 Shadowrocket 支持通过脚本或正则表达式对订阅节点进行筛选，从而实现更灵活的节点过滤与管理\n首页 \u0026gt; 订阅后面的 ⓘ 图标 \u0026gt; 过滤 节点筛选\n保留节点名称含有关键词 A 和 B 的节点： /(?=.*(A))^(?=.*(B))^.*$/ 保留节点名称含有关键词 A 或 B 的节点： A|B 排除节点名称含有关键词 A 或 B 的节点： /^((?!(A|B)).)*$/ 保留节点名称含有关键词 A 并排除含有关键词 B 的节点： /(?=.*(A))^((?!(B)).)*$/ 分组、代理分组中的正则写法与上述【过滤】中使用的命令相同，但需删除前后 / 符号\n批量整理\n节点订阅筛选功能支持使用脚本代码批量整理和修改相应订阅中节点的功能选项及节点名称\n批量给节点中的关键词 a 替换成 b：\n$server.title=$server.title.replace(/关键词a/g,\u0026#39;关键词b\u0026#39;) 批量给节点名称增加 abc 开头的关键词：\n$server.title=\u0026#39;abc\u0026#39;+$server.title 批量给节点名称增加 abc 结尾的关键词：\n$server.title=$server.title+\u0026#39;abc\u0026#39; 批量开启全部节点的片段：\n$server.reserved=\u0026#34;1,40-60,30-50\u0026#34; 批量开启全部节点的多路复用：\n$server.mux=1 批量设置全部订阅节点的 代理链/链式代理/代理通过，以下两种方式以生效者为准\n$server.chain=\u0026#34;订阅名称/节点名称\u0026#34; $server[\u0026#39;dialer-proxy\u0026#39;]=\u0026#34;UUID值\u0026#34; 其中 UUID 值 可在中转节点或订阅的 JSON 文本中复制，第一种命令的 订阅名称/节点名称 也可以使用 UUID 值\n当节点名称不包含地区标识，且节点地址有可以分辨地区的关键词时，可以使用以下脚本为节点名称批量添加地区关键词或旗帜标识\nif (/节点地址关键词/i.test($server.host)) { $server.title = \u0026#39;需要添加的关键词或旗帜\u0026#39;+ $server.title return true; } 其他命令\n该功能也支持更复杂的脚本指令，可以参阅 此处示例\n代理通过/代理链 当前代理通过另一个代理进行连接，支持多级链式代理，但并非所有协议都支持通过代理链作为落地节点使用。使用代理链方法：\n使用节点 A 连接，点击节点 A 后面的 ⓘ 图标，代理通过 选择节点 B，流量走向：Client \u0026gt; B \u0026gt; A \u0026gt; Web server 支持使用分组/代理分组作为中转代理 支持批量修改订阅节点的代理链，可实现同时部署多个节点的链式代理。具体命令可查看 订阅节点筛选 \u0026gt; 批量整理 中的相关指令 取消代理通过/代理链：点击开启该功能节点后面的 ⓘ 图标，代理通过 选择右上角的 取消 后保存 全局路由 配置：流量根据设定规则进行分配，有些通过节点连接，有些则不通过 代理：全部流量都通过同一个节点连接 直连：全部流量都不通过节点连接 场景：根据不同的网络连接类型（Wi-Fi、蜂窝数据）自动切换到预先设置的路由模式，并选择对应的配置文件和节点连接 连通性测试 点击首页的 连通性测试，节点列表将会显示以毫秒（ms）为单位的延迟数字，这是数据包的传输时间，不同的 延迟测试方法 对应不同的计算结果。长按首页的 连通性测试，可以临时调整测试方法，仅对本次测试生效\n设置 \u0026gt; 延迟测试方法\nTCP：建立 TCP 连接的往返时间 ICMP：发送 ICMP 回显请求报文和接收 ICMP 回显应答报文的往返时间 CONNECT：向测试 URL 发送一个 HTTP HEAD 请求，测量从发送请求到接收响应头部信息的往返时间 请优先选择 CONNECT，因为它更能准确反映节点的连通性。延迟大小与网络上传下载速度没有直接关系，测速请使用其他方法，如：https://www.speedtest.net\n修改测试地址 用于首页和分组节点的延迟测试\n设置 \u0026gt; 延迟测试方法 \u0026gt; URL 测试设置 首页 \u0026gt; 连通性测试后面的圆形图标 \u0026gt; URL 测试设置 用于代理分组内节点的延迟测试\n点击配置文件的 ⓘ 图标 \u0026gt; 代理分组 \u0026gt; 编辑或添加包含自动测试类型的分组 \u0026gt; 最下方 URL 栏 场景 场景是根据不同的网络连接类型（Wi-Fi、蜂窝数据）自动切换到预先设置的路由模式，并选择对应的配置文件和节点连接\n首页 \u0026gt; 全局路由 \u0026gt; 设置的 场景 \u0026gt; 添加场景 为指定的网络连接类型设置对应的路由模式（配置、直连、代理），类型（节点、分组）、配置文件 及 备注 网络连接类型分别为：Wi-Fi、蜂窝数据、默认。选择Wi-Fi类型时，SSID需填写Wi-Fi名称 首页 \u0026gt; 全局路由 \u0026gt; 选择 场景 软件支持添加蜂窝数据场景，支持以 网络接口 作为匹配条件\n默认（留空）代表接口 pdp_ip0 当设备启用了多个蜂窝数据网络时，可在 Shadowrocket 的 设置 \u0026gt; 诊断 \u0026gt; 网络 中查看对应的接口信息 输入格式：pdp_ip1、pdp_ip2、pdp_ip3 等 首次添加场景，可能会弹出申请权限的对话框，具体原因请看 权限。当没有允许定位权限时，场景列表的 ✅ 标记不会随着网络类型的切换而自动切换，但这不影响场景功能的正常生效\n设置 \u0026gt; 隧道/按需求连接 中的 包含所有网络 相关选项可能会对场景模式的生效造成影响\n简单模式 简单模式是一种以相对简单的方式实现自动测试并选择延迟低的节点进行连接的设置模式。简单模式未来或不再维护，其功能已被 代理分组 所包含，建议使用 代理分组 替代简单模式\n首页 \u0026gt; 全局路由 \u0026gt; 分组 \u0026gt; 简单模式 节点的范围是什么？\n当开启简单模式，此时下方会出现分组选项，如果没有继续添加分组的操作，节点范围就是首页全部节点，如果添加分组，范围就变成分组里的节点\n自动测试的周期是多久？延迟低的判断依据是什么？\n设置 \u0026gt; 延迟测试方法 \u0026gt; URL测试设置，这里规定了测试的间隔时间，默认 600s，即表示每 10 分钟自动进行一次节点延迟测试。相邻两次测试结果中最小延迟值的对比，根据公差机制决定是否切换节点，公差越大，触发节点切换的频次越低，默认 0ms，即表示只要后面测试结果的最低延迟节点比前面测试结果的最低延迟节点延迟小就会自动切换\n切换的节点给什么规则使用？\nShadowrocket 内置策略 proxy，简单模式时自动切换的节点使用于所有指向 proxy 策略的规则\n简单模式是自动切换延迟低节点，代理分组的 url-test 类型也是自动切换延迟低节点，两者有何不同？\n代理分组创建后，需要在规则中修改策略指向，而简单模式已经关联 proxy 策略，节省了修改规则的步骤\n全局路由 选择 代理 时将导致所有 代理分组 失效，而简单模式依然能够实现自动切换节点\n添加分组时的测速开关是什么作用？\n开启测速，这个分组才允许自动切换节点。不开启测速，这个分组只能手动选择节点\n启用回退 首页 \u0026gt; 全局路由 \u0026gt; 启用回退\n启用回退 的功能是当节点连接失败时自动切换其他可用节点\n连接失败3次才会触发回退机制 节点只满足可用性，不要求是最低延迟节点 随机切换，不按照节点顺序选择 策略为 proxy，节点切换范围就是首页全部节点，如果开启简单模式并选择分组，则范围缩小至分组内节点 策略为 非 select 类型 的 分组/代理分组类型，节点切换范围就是分组或代理分组内节点 具体切换到哪个节点，请查看 代理日志 配置页面 配置文件 📝 备注 Shadowrocket 的配置文件是用于快速设置和调整软件的核心功能的重要文件，通常以 *.conf 格式保存。配置文件还可以在多设备间同步以及分享配置文件给其他用户，以快速部署相同设置、简化用户手动配置的流程。用户可以在配置文件里设置 通用参数、添加规则、Hosts、URL重写、HTTPS解密、脚本等内容。模块 的写法与配置文件相同\n同时，Shadowrocket 支持在配置文件中 编写本地节点，但该操作方式仅是为了兼容部分其他类型的配置文件，不能当作 Shadowrocket 添加节点 的优先选择\nShadowrocket 内置了一个默认配置文件 default.conf，其中包含了国内外主要网站或服务的分流规则，一般可以满足大多数用户的基本需求。此配置文件的内容跟随应用更新而做不定期的调整。如果在使用过程中错误修改或误删配置文件，可以点击 配置 \u0026gt; 恢复默认配置。\n添加配置文件方法：\n从 URL 下载配置\n配置 \u0026gt; 右上角 ➕ \u0026gt; 粘贴配置链接 \u0026gt; 下载 \u0026gt; 点击对应的配置文件 \u0026gt; 使用配置 / 编译配置 Shadowrocket 兼容使用 Clash YAML 格式 的配置文件。使用含节点信息的标准 Clash 链接可以同时导入配置文件和节点信息 从本地存储或云盘导入\n配置 \u0026gt; 从云导入，点击对应存储路径的配置文件 点击配置文件，显示操作菜单（以下选项可能因不同的软件版本而有所不同）：\n使用配置 编辑配置 编辑纯文本 编译配置 预览配置 更新配置 扩展配置 重新命名 导出配置 点击配置文件的 ⓘ 图标或点击 编辑配置，进入编辑菜单（以下选项可能因不同的软件版本而有所不同）：\n通用 规则 Hosts URL重写 头部重写 正文重写 本地映射 HTTPS解密 脚本 代理分组 规则集URL 脚本URL 复制 替换策略 测试规则 使用配置 点击 使用配置 可以编译并启用该配置文件。该功能会对该配置使用的远程 规则集、脚本 等远程资源进行更新\n编辑配置 使用 UI 交互界面对配置文件的可设置项进行调整。部分设置或命令 不提供 UI 编辑界面，如有需要可在 纯文本编辑 中使用\n编辑纯文本 使用纯文本模式对配置文件的可设置项进行调整。部分设置或命令 不提供 UI 编辑界面，仅在纯文本模式下可以设置\n配置文件的纯文本编写方法可以参考：\n懒人配置 懒人配置（含策略组） 编译配置 点击 编译配置 可以对该配置文件进行重新编译。可以理解为软件将该配置文件重新编辑并转译为符合当前版本规范和逻辑的底层格式。该功能会更新该配置文件所用到的 规则集、脚本 等远程资源。仅当软件版本大于等于特定版本时才具有该选项\n预览配置 查看配置文件的纯文本格式。该选项仅当配置文件是以远程配置文件的形式添加进来的才会出现\n更新配置 使用当前配置文件的远程版本对当前文件进行覆盖更新。该选项仅当配置文件是以远程配置文件的形式添加进来时才会出现，该功能一般适用于在远端维护的配置文件或远程配置需要恢复时使用。除更新配置设置外该功能还会同时更新该配置所用的 规则集、脚本 等远程资源，若仅需要更新规则集等远程资源，请使用 使用配置 / 编译配置 功能。软件同时提供自动更新功能，相关说明及其他技巧请点击查看 自动更新 词条\n🚨 注意 更新配置会覆盖在本地对配置文件所做的修改，对于在本地修改过的远程配置而言需要谨慎使用此功能\n重新命名 重命名当前配置文件\n导出配置 将当前配置文件以文件的形式导出\n扩展配置 从配置 a 扩展出配置 b，此时默认关系是 b 包含 a，也可以理解为 b 继承了 a 的内容\n配置 b 优先级高于配置 a，该功能是对配置建立包含关系，以满足同时使用多个配置的需求\n点击配置文件的 ⓘ 图标 \u0026gt; 通用 \u0026gt; 包含配置，可以修改或解除包含关系\n通用参数 通用参数是 Shadowrocket 的中最重要的功能参数，位于 配置文件 纯文本编辑 模式中的 [General] 字段，该字段选项包含具有 UI 界面的设置项和不包含 UI 界面的 隐式参数\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; 通用 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [General] 配置行的纯文本设置语法格式为 key = value\n[General] key = value 旁路系统 bypass-system\n如果禁用此选项，可能会导致一些系统问题，如推送通知延迟\n跳过代理 skip-proxy\n跳过代理接口，使用 TUN 接口接管。此选项强制列表中的域名或 IP 的连接范围交由 Shadowrocket TUN 接口 来处理，而不是 Shadowrocket 代理接口。此选项用于提高部分应用程序对于代理环境的兼容性。若开启 TUN 模式 时，将强制使用 TUN 接管所有连接，此处地址列表可以忽略。需要注意，该选项并非将设定的地址使用直连进行连接，仅表示使用 TUN 接口处理\nTUN旁路路由 tun-excluded-routes\nShadowrocket TUN 接口 只能处理 TCP 协议。使用此选项可以绕过指定的 IP 范围，让其他协议通过\nDNS覆写 dns-server\n使用普通 DNS 或加密 DNS（如 doh、doq、dot 等）覆盖默认的系统 DNS。DNS 覆写仅针对直连类域名进行解析，代理类域名将经由代理服务器进行解析。DNS 覆写支持同时添加多个地址，Shadowrocket 采用并行查询的方式进行解析请求，最先返回的结果将被采用。有些 dns over https 支持 http3，所以将会尝试查询，如果支持就切换到 http3，可在 doh链接 后面加上 #no-h3 关闭。doh 强制通过 h3 查询的写法是将 https 改成 h3，如h3://dns.alidns.com/dns-query。其他示例或写法参见：修改DNS、DNS-over-PROXY\n备用DNS fallback-dns-server\n当覆写 DNS 查询失败或查询时间超过2秒，Shadowrocket 会自动回退备用 DNS。如需指定多个 DNS，可用逗号分隔。system 表示回退到系统 DNS，清空备用 DNS 等于将其设置为 system\n启用IPv6支持 ipv6\nfalse 表示不启用，true 表示启用。即使不启用此选项，当本地网络环境支持 IPv6，并且节点域名支持 IPv6 解析，Shadowrocket 也会使用节点的 IPv6 地址进行访问。解决方法是关闭节点域名的 IPv6 解析，或者在配置文件的 [Host] 项目下为节点域名指定 IP 地址\n首选IPv6 prefer-ipv6\n优先向 IPv6 的 DNS 服务器查询 AAAA 记录，优先使用 AAAA 记录。false 表示不启用\n私有IP应答 private-ip-answer\n如果不启用该选项，域名解析返回私有 IP，Shadowrocket 会认为该域名被劫持而强制使用代理\nTUN包含路由 tun-included-routes\n默认情况下，Shadowrocket 接口会声明自己为默认路由，但由于 Wi-Fi 接口的路由较小，有些流量可能不会通过 Shadowrocket 接口。使用此选项可以添加一个较小的路由表\n总是真实IP always-real-ip\n这个选项要求 Shadowrocket 在 TUN 处理 DNS 请求时返回一个真实的 IP 地址而不是假的IP地址\nDNS劫持 hijack-dns\n有些设备或软件总是使用硬编码的 DNS 服务器，例如 Netflix 通过 Google DNS（8.8.8.8 或 8.8.4.4）发送请求，您可以使用此选项来劫持查询\n包含配置 include\n表示当前配置包含另一个配置的内容，当前配置的优先级高于被包含配置。该选项是对配置建立包含关系，以满足同时使用多个配置的需求\n隐式参数 🚨 注意 隐式参数是指相关选项仅支持在配置文件 纯文本编辑 模式中的 [General] 字段进行纯文本设置，不提供 UI 操作选项，属于 通用参数 的隐藏属性，建议谨慎设置。\n隐式参数属于 通用参数，设置语法格式为 key = value\ndns-direct-system\n直连的域名类规则使用系统 DNS 进行查询。设置为 true 表示启用，设置为 false 表示不启用\nicmp-auto-reply\nping 数据包自动回复。设置为 true 表示启用，设置为 false 表示不启用\nalways-reject-url-rewrite\n不开启时，「重写的REJECT策略」默认只有在配置模式下生效。开启后，可以令该策略在其他全局路由模式下都生效。设置为 true 表示启用，设置为 false 表示不启用\ndns-direct-fallback-proxy\n直连域名解析失败后使用代理。设置为 true 表示启用，设置为 false 表示不启用\nudp-policy-not-supported-behaviour\n当 UDP 流量匹配到规则里不支持 UDP 转发的节点策略时重新选择回退行为，可选行为包括 DIRECT、REJECT。DIRECT 表示直连转发 UDP 流量，REJECT 表示拒绝转发 UDP 流量\nstun-response-ip\n此选项包含两个命令：stun-response-ip 和 stun-response-ipv6。该选项允许返回一个虚假的IP地址，如 stun-response-ip=1.1.1.1、stun-response-ipv6=::1，目的是防止真实IP地址泄漏，提高 WebRTC 的隐私和安全性。使用此命令将忽略软件设置选项内的 禁用STUN 的启用状态\ncompatibility-mode\n网络兼容模式\ncompatibility-mode = 0 \u0026gt; 自动/禁用\ncompatibility-mode = 1 \u0026gt; Proxy with Loopback Address\ncompatibility-mode = 2 \u0026gt; Proxy Only\ncompatibility-mode = 3 \u0026gt; TUN Only\ncompatibility-mode = 4 \u0026gt; Proxy without Loopback Address\ncompatibility-mode = 5 \u0026gt; No Default Route\n本设置的优先级高于软件设置内的相关选项。当参数的值设定为 3 时的效果等同于启用 Tun模式：设置 \u0026gt; 代理 \u0026gt; 代理类型 \u0026gt; None。当参数的值设定为 5 时的效果等同于启用 兼容模式：设置 \u0026gt; 代理 \u0026gt; 兼容模式\nalways-ip-address\n强制所有域名使用本地 DNS 解析。设置为 true 表示启用，设置为 false 表示不启用\nproxy-dns-server\n通过该参数来使用特定 DNS 解析所有节点域名。若未设置此参数，节点域名默认使用 dns-server 进行解析，对于 DNS-over-PROXY 则使用系统 DNS 解析\nclose-if-proxy-chain-missing\n代理链丢失关闭连接。当设置为 true 时，若 代理链 中的中转节点丢失则 Reject 代理连接；当设置为 false 时等同于不设置该命令，即若 代理链 中的中转节点丢失则跳过中转节点直接连接落地节点使用\nipv6-only-if-no-ipv4-dns\n当设置为 true 时，如果设备在网络环境中仅获取到 IPv6 的 DNS 而未获取到 IPv4 的 DNS，此时软件将认为网络环境是 IPv6 Only 网络。设置为 false 表示不启用\nblock-quic\nQUIC协议屏蔽策略。支持使用 all-proxy、all、always-allow 对 QUIC 传输层协议进行设置。其中 all-proxy 表示只对 走代理的连接 阻断 QUIC，直连连接（DIRECT）不会被干预；all 表示对所有连接（包括直连与代理）都屏蔽 QUIC，这会完全禁止系统中一切 UDP/443 流量；always-allow 表示始终允许 QUIC，不做任何屏蔽，等同于 关闭 QUIC 屏蔽\nuse-local-host-item-for-proxy\n本地 HOST 映射对代理生效。在默认情况下，对于代理类的 DNS 解析始终在远端服务器上执行。当设置为 true 时，若存在本地 DNS 映射，Shadowrocket 将在代理连接中使用映射后的地址，而不是原始的主机名。设置为 false 表示不启用\nallow-dns-svcb\n允许 DNS SVCB 查询。系统可能会执行 SVCB 记录 DNS 查询，而不是标准的 A 记录查询。这会导致无法返回虚拟 IP 地址。因此，默认情况下禁止执行 SVCB 记录查询，以强制系统执行 A 记录查询。设置为 true 表示启用，设置为 false 表示不启用\nShadowrocket 或还有其他支持的隐式参数，此处可能未能完全列出，若有相关需求请联系 buginapp@gmail.com\n添加规则 在 Shadowrocket 中，\u0026ldquo;规则\u0026quot;是指用来决定哪些网络请求应该走代理、哪些请求应该直接连接互联网的规则集合。规则通常是基于用户的需求来配置 规则策略，目的是实现对流量的精细控制。软件对规则集的识别不受文件后缀的影响，是以规则集的内容为识别标准\n点击配置文件的 ⓘ 图标 \u0026gt; 规则 \u0026gt; 右上角 ➕，根据需求选择 规则类型 和 规则策略，填写规则内容\n数据 \u0026gt; 代理 \u0026gt; 启用日志记录，产生网络活动后回到该页面，从最近的日志中查看网络活动记录，点击任一记录查看详情，点击右上角 ••• 选择类型添加规则\n规则匹配需要着重注意 规则的优先级 顺序\n规则管理\n配置 \u0026gt; 配置文件 \u0026gt; 编辑配置 \u0026gt; 规则 \u0026gt; 规则区域右上角 ···\n可选择并批量删除规则\n规则优先级 规则的匹配是从上到下逐条匹配的，一旦匹配到某条规则，Shadowrocket 就会停止继续匹配，因此规则的顺序非常重要，优先级高的规则应该放在前面\n模块中的规则优先于配置文件 上面的规则优先于下面的规则 域名类的规则优先于IP类规则 此外，规则的优先级在自动编译配置时同时遵循 显式优先、推断其次、最终兜底 的原则。其中可被直接、精确匹配的显式规则（如 DOMAIN、DOMAIN-SUFFIX、URL-REGEX 等）具有最高优先级。而基于地域或数据库判断的推断类规则（如 GeoIP）会在自动编译过程中被放置在显式规则之后。FINAL 规则作为兜底项，始终位于整个规则集的最末尾\n规则类型 DOMAIN-SUFFIX：匹配请求域名的后缀\n如 DOMAIN-SUFFIX,example.com,DIRECT 可以匹配到 a.example.com、a.b.example.com\nDOMAIN-KEYWORD：匹配请求域名的关键词\n如 DOMAIN-KEYWORD,exa,DIRECT 可以匹配到 a.example.com、a.b.example.com\nDOMAIN-WILDCARD：匹配请求域名，支持使用通配符 *、?\n如 DOMAIN-WILDCARD,a*c.example*.com,DIRECT 可以匹配到 abc.example123.com、aqwec.example456.com\nDOMAIN：匹配请求的完整域名。当为DOMAIN、DOMAIN-SUFFIX、DOMAIN-KEYWORD 等相似类型分别设置相同的值时，只有其中一种类型会生效\n如 DOMAIN,www.example.com,DIRECT 只能匹配到 www.example.com\nUSER-AGENT：匹配用户代理字符串，支持使用通配符 *\n如 USER-AGENT,MicroMessenger*,DIRECT 可以匹配到 MicroMessenger Client\nURL-REGEX：匹配 URL 正则式\n如 URL-REGEX,^https?://.+/item.+,REJECT 可以匹配到 https://www.example.com/item/abc/123\nIP-CIDR：匹配 IPv4 或 IPv6 地址\n如 IP-CIDR,192.168.1.0/24,DIRECT 可以匹配到 IP 段 192.168.1.1～192.168.1.254。当域名请求遇到IP类规则时，Shadowrocket 会向本地 DNS 服务器发送查询请求，以判断主机 IP 是否匹配规则。若 IP 类规则加 no-resolve（如：IP-CIDR,172.16.0.0/12,DIRECT,no-resolve），则域名请求将会跳过此规则，不会触发本地DNS查询\nIP-ASN：匹配 IP 地址隶属的 ASN 编号\n如 IP-ASN,56040,DIRECT 可以匹配到属于 China Mobile Communications Corporation 网络的 IP 地址\nRULE-SET：匹配规则集内容。规则集的组成部分需包含规则类型\nDOMAIN-SET：匹配域名集内容。域名集的组成部分不包含规则类型\nSCRIPT：匹配脚本名称\nDST-PORT：匹配目标主机名的端口号\n如 DST-PORT,443,DIRECT 可以匹配到 443 目标端口\nGEOIP：匹配 IP 数据库\n如 GEOIP,CN,DIRECT 可以匹配到归属地为CN的IP地址\nFINAL：兜底策略\n如 FINAL,PROXY 表示当其他所有规则都匹配不到时才使用 FINAL 规则的策略\nAND：逻辑规则，与规则\n如 AND,((DOMAIN,www.example.com),(DST-PORT,123)),DIRECT 可以匹配到 www.example.com:123\nNOT：逻辑规则，非规则\n如 NOT,((DST-PORT,123)),DIRECT 可以匹配到除了 123 端口的其他所有请求\nOR：逻辑规则，或规则\n如 OR,((DST-PORT,123),(DST-PORT,456)),DIRECT 可以匹配到 123 或 456 端口的所有请求\nPROTOCOL：匹配传输协议类型\nPROTOCOL 类型不支持单独使用，只能作为子规则类型嵌套于逻辑规则当中。如 AND,((PROTOCOL,UDP),(DST-PORT,443)),REJECT-NO-DROP\n规则策略 PROXY：代理。通过代理服务器转发流量\nDIRECT：直连。连接不经过任何代理服务器\nREJECT：拒绝。返回 HTTP 状态码 404，没有内容\nREJECT-DICT：拒绝。返回 HTTP 状态码 200，内容为空的JSON对象\nREJECT-ARRAY：拒绝。返回 HTTP 状态码 200，内容为空的JSON数组\nREJECT-200：拒绝。返回 HTTP 状态码 200，没有内容\nREJECT-IMG：拒绝。返回 HTTP 状态码 200，内容为 1 像素 GIF\nREJECT-TINYGIF：拒绝。返回HTTP状态码200，内容为 1 像素 GIF\nREJECT-DROP：拒绝。丢弃 IP 包\nREJECT-NO-DROP：拒绝。返回 ICMP 端口不可达\n除此之外，规则策略还可以选择 分组、代理分组、订阅、服务器节点 等\n策略扩展参数 Extended Matching：扩展匹配。代表将尝试同时匹配 SNI 和 HTTP 主机标头。适用于 DOMAIN、DOMAIN-SUFFIX、DOMAIN-KEYWORD 等域名规则。Shadowrocket 默认支持 extended-matching，已默认开启 SNI 匹配\nPre Matching：预匹配功能，可以快速、低开销地拒绝请求。对于使用 REJECT 策略的规则，可以通过 pre-matching 标记启用此功能预匹配。启用此参数的规则将在正常规则匹配过程之前生效，具有最高优先级\n纯文本示例：\n[Rule] DOMAIN,ad.com,REJECT,extended-matching,pre-matching APP分流 根据不同 App 或特定服务指定分流规则，并使其按照设定的规则执行代理策略\n示例：YouTube App 分流走代理\n复制 YouTube 的规则集链接 https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Shadowrocket/YouTube/YouTube.list 点击配置文件的 ⓘ 图标 \u0026gt; 规则 \u0026gt; 右上角 ➕，规则类型 选择 RULE-SET，规则策略 选择 PROXY，输入框内粘贴 规则集链接，保存完成（规则策略可以根据需求使用其他选项或节点） iOS系统没有常规分应用代理的操作，只能通过 域名 / ip / ua 规则实现app分流效果。可自行抓包，或者订阅 blackmatrix7 的 规则集。如果引用的链接是域名集，添加规则时，规则类型 请选择 DOMAIN-SET\n更新规则集 手动更新：点击 配置文件 \u0026gt; 使用配置 / 编译配置 自动更新：自动更新 预览规则集 点击配置文件 \u0026gt; 编辑配置 \u0026gt; 规则 \u0026gt; 在规则集上左滑 \u0026gt; 预览\n修改DNS DNS覆写\n点击 配置文件 ⓘ 图标 \u0026gt; 通用 \u0026gt; DNS 覆写\nDNS 覆写仅针对直连类域名进行解析，代理类域名将经由代理服务器进行解析。DNS 覆写为并发查询，若填写多个 DNS 服务，则使用最快返回的解析结果。填 system 表示使用系统 DNS，支持普通 DNS 或加密 DNS（如 DoH、DoQ、DoT 等），也支持使用 通过代理转发 DNS 查询请求\n普通 DNS 示例\ndns-server = 223.5.5.5,119.29.29.29 加密 DNS 示例\nDNS-over-HTTPS（DoH） dns-server = https://dns.alidns.com/dns-query DNS-over-HTTP/3（DoH3） dns-server = h3://dns.alidns.com/dns-query DNS-over-QUIC（DoQ） dns-server = quic://223.5.5.5 DNS-over-TLS（DoT） dns-server = tls://223.5.5.5 DNS-over-PROXY 备用DNS\n当覆写的 DNS 查询失败或查询时间超过2秒后回退备用 DNS 进行查询。如需指定多个 DNS，可用逗号分隔。填写 system 或者留空表示可回退到系统 DNS\nDNS-over-PROXY 通过代理转发 DNS 查询请求\nproxy\n支持使用 默认节点 转发 DNS 查询请求，有以下两种写法：\ndns-server=https://dns.google/dns-query#proxy dns-server=https://dns.google/dns-query#proxy=proxy proxy=name\n支持使用 指定节点 转发 DNS 查询请求，需要注意此处的代理名称仅支持 URL 编码，以 香港 01 示例：\ndns-server=https://dns.google/dns-query#proxy=%E9%A6%99%E6%B8%AF%2001 此处指定的节点若填写不规范会自动回退至默认节点\necs=子网范围\necs 参数用于设置 EDNS Client Subnet (ECS)，向 DNS 服务器传递客户端的子网信息。ECS 允许 DNS 服务器根据指定的子网范围（而非实际客户端 IP）来返回最优结果\n示例：\ndns-server=https://dns.google/dns-query#ecs=120.76.0.0/14|2620:149:af0::10/56\u0026amp;ecs-override=true ecs-override=true\necs 参数的强制覆盖。即使客户端的实际 IP 提供了不同的地理位置，查询会强制使用 ecs 指定的子网范围\n示例：\ndns-server=https://dns.google/dns-query#proxy=name\u0026amp;ecs=1.1.0.0/14|2620:149:af0::10/56\u0026amp;ecs-override=true no-resolve的作用 当域名请求遇到 IP 类规则时，Shadowrocket 会向本地DNS服务器发送查询请求，以判断主机 IP 是否匹配规则\n若IP类规则加 no-resolve，则域名请求将会跳过此规则，不触发本地 DNS 查询。如：\nIP-CIDR,172.16.0.0/12,DIRECT,no-resolve 代理分组 代理分组 也可称之为 策略组，是用来 灵活管理和切换不同代理节点、自动分流网络请求 的一种核心功能。它的作用类似于一个 智能路由系统，可以根据设定的规则将不同的流量导向不同的代理节点或行为。简单来说，它就是一个 容器，里面可以包含多个代理节点或其他代理分组。你可以根据需求通过 规则 → 代理分组 → 代理节点 的路径手动或自动切换。代理分组支持的类型可以查看：代理分组类型\n点击配置文件的 ⓘ 图标 \u0026gt; 代理分组 \u0026gt; 右上角 ➕。填写名称，根据需求选择 代理分组类型，通过 正则 匹配策略，或者从策略输入框后面的 ••• 手动添加策略，保存\n策略是规则的组成部分，创建的代理分组只有放到规则里才能发挥作用\n进入对应规则的详情页，点击策略选项，从列表中选择所需的代理分组，保存 代理分组中可以包含其他代理分组，形成层级结构，但需要注意各级代理分组的 类型 代理分组内的右上角设有 测试 按钮，点击 测试 可对当前分组内的节点进行延迟测试。测试按钮仅支持对节点进行测试，不支持测试分组内的其他策略\n代理分组下方设有 测试并选择最快服务器 选项 该选项开启后，将在手动点击右上角的 测试 后自动选择并使用延迟最低的节点 该选项的开启或关闭对全部代理分组同时生效 该选项仅存在于版本号大于等于 2.2.65 (2604) 的软件上 代理分组内设有 订阅 开关，开启开关会在下方出现 服务器节点 选项，需要进入选择所需要的订阅\n开启 订阅 开关并选择所需订阅后，下方 策略 内会出现该订阅的所有节点 支持同时使用 正则表达式 对节点进行筛选，筛选范围受限于所选择的订阅 快捷进入代理分组\n首页下拉，可以快捷进入代理分组界面 首页本地节点上方设有指示牌图标，点击该图标可以快捷进入代理分组界面，软件版本需大于等于 2.2.65 (2614) 代理分组其他设置参数\ninterval：测试周期。指定间隔多长时间后需要重新发起测试 timeout：超时时间。如果测试在超时前未完成，放弃测试 tolerance：公差。只有当新优胜者的分数高于旧优胜者的分数加上公差时，才会进行线路更换 url：测试地址。指定要测试的URL hidden：隐藏代理分组 代理分组类型 select：允许用户手动选择一个子策略，可以指定其他代理分组或代理服务器。纯文本中设置为 0 表示第一个策略，1 表示第二个策略，2 表示第三个策略，以此类推\nurl-test：根据设定的自动测试周期和结果自动切换延迟最低的节点\nfallback：节点不可用时自动切换其他可用节点，可用节点范围被上次自动测试结果所限\nload-balance：不同规则的请求使用分组里的不同节点进行 负载均衡，相同的域名会使用同一个节点\nrandom：随机使用分组里的不同节点进行连接，相同的域名可能使用不同的节点，该类型也可以用作 负载均衡\n除 select 类型外，其余代理分组类型均基于自动测试机制运行。当连接命中此类分组时，系统将优先使用最近一次测试结果选定的节点，并按照该分组的设定执行下一轮测试\n在两次测试间隔期间，若当前节点状态发生变化（例如节点变为不可用），可能出现仍使用失效节点的情况。对此，可酌情使用 启用回退 功能，以在节点异常时保障连接可用性。但需要详细阅读回退功能的详细说明\n自动测试类型的代理分组允许用户在界面中临时手动选择了该类分组所包含的节点，但实际连接行为仍受分组自身设置约束，且 UI 中显示的测试结果并不影响该分组在背景中的自动测试，代理分组将继续根据自动测试结果自动发生切换。基于上述特性，除 select 类型外，不建议在此类代理分组中嵌套包含其他代理分组，以避免服务器节点选择逻辑复杂化或出现不符合预期的切换行为\n隐藏代理分组 自 Shadowrocket Version 2.2.66 (2649) 版本开始，新增参数 hidden=1，可用于在图形界面隐藏不希望展示的代理分组。当 hidden 设置为数值 1 时，表示隐藏当前代理分组；当设置为 0 时表示不隐藏，等同于不设置此参数。该功能仅提供纯文本编辑设置方式，无图形设置界面\n示例：\n香港节点 = url-test,HK 01,HK 02,HK 03,policy-select-name=HK 01,interval=600,tolerance=100,timeout=5,url=http://www.gstatic.com/generate_204,hidden=1 负载均衡 代理分组类型 中的 load-balance、random 表示将连接请求随机使用分组里的节点进行连接，能够尽可能将流量平均分配给所有子策略或代理。其中 load-balance 会将相同的域名使用同一个节点进行连接，random 会将所有请求使用随机节点进行连接，不区分是否是同一个域名\n使用负载均衡的方法：\n点击配置文件的 ⓘ 图标 \u0026gt; 代理分组 \u0026gt; 右上角 ➕，类型选择 load-balance 或者 random\n规则集URL 配置 \u0026gt; 配置文件 \u0026gt; 编辑配置 \u0026gt; 规则集 URL\n当前使用的所有远程规则资源的展示页面，其后显示的数字为当前成功下载的数量和总共包含的数量。进入后所显示的 ✅ 表示当前规则下载成功，❎ 表示当前规则下载失败。点击相应地址可重新拉取并弹出状态提示，但不会重新编译更新配置文件，点击 使用配置 / 编译配置，可以对当前所有 URL 进行更新并重新编译更新配置文件\n脚本URL 配置 \u0026gt; 配置文件 \u0026gt; 编辑配置 \u0026gt; 脚本 URL\n当前使用的所有远程脚本资源的展示页面，其后显示的数字为当前成功下载的数量和总共包含的数量。进入后所显示的 ✅ 表示当前脚本下载成功，❎ 表示当前脚本下载失败。点击相应地址可重新拉取并弹出状态提示，但不会重新编译更新配置文件，点击 使用配置 / 编译配置，可以对当前所有 URL 进行更新并重新编译更新配置文件\n复制配置文件 配置 \u0026gt; 点击配置文件 \u0026gt; 编辑配置 \u0026gt; 复制\n点击该选项可将当前配置生成一份备份并命名为 *-copy.conf\n替换策略 配置 \u0026gt; 点击配置文件 \u0026gt; 编辑配置 \u0026gt; 替换策略\n点击查找右侧的 ⓘ 图标选择准备替换的策略，或输入准备替换的策略 点击替换右侧的 ⓘ 图标选择欲替换成的策略，或输入欲替换成的策略 点击完成后替换完成 测试规则 配置 \u0026gt; 测试规则\n配置 \u0026gt; 点击配置文件 \u0026gt; 编辑配置 \u0026gt; 测试规则\n基于当前配置进行规则策略测试 Hosts Shadowrocket 支持本地自定义 DNS 映射。包含 本地值 和 DNS服务器 两种设定方式。在 纯文本编辑 模式中位于 配置文件 的 [Host] 字段。在默认情况下，对于代理类的 DNS 解析始终在远端服务器上执行，支持使用 use-local-host-item-for-proxy 等 隐式参数\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; Hosts 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [Host] 编辑示例：\n将特定域名映射到指定 IP 地址，绕过 DNS 解析，直接控制域名到 IP 的对应关系\nexample.com = 1.2.3.4 将特定域名指定特定的 DNS 服务器进行解析\nexample.com = server:1.2.3.4 URL重写 修改 HTTP(S) 请求/响应，动态拦截并修改请求的 URL 或内容，在 纯文本编辑 模式中位于 配置文件 的 [URL Rewrite] 字段。重写类型包含 HEADER、302、307 以及其他支持的代理策略。支持使用 always-reject-url-rewrite 等 隐式参数\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; URL重写 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [URL Rewrite] 头部重写 支持 请求头/响应头 重写功能，即标头重写，包含 del、add、replace、replace-regex 几种操作。在 纯文本编辑 模式中位于 配置文件 的 [Header Rewrite] 字段\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; 头部重写 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [Header Rewrite] 类型：\nhttp-request：作用于请求头\nhttp-response：作用于响应头\n行为：\nheader-del：从请求头或响应头中删除指定字段\nheader-add：向请求头或响应头中添加字段及其对应的值\nheader-replace：在请求头或响应头中替换指定字段的值\nheader-replace-regex：使用正则表达式在请求头或响应头中替换字段的值\n表达式：\n正则表达式用于匹配目标网站的 URL\n常用字段：\nContent-Type、User-Agent、Accept-Language、Authorization、Host、Referer、Cookie、X-Forwarded-For、Location 等\n正文重写 支持 请求体/响应体 重写功能，支持使用 jq 语法。在 纯文本编辑 模式中位于 配置文件 的 [Body Rewrite] 字段\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; 正文重写 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [Body Rewrite] 类型：\nhttp-request：作用于请求体\nhttp-response：作用于响应体\nhttp-request-jq：使用 jq 语法处理请求体\nhttp-response-jq：使用 jq 语法处理响应体\n表达式：\n正则表达式用于匹配目标网站的 URL\n本地映射 支持 本地映射 功能，在 纯文本编辑 模式中位于 配置文件 的 [Map Local] 字段\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; 本地映射 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [Map Local] 类型：\ntext：返回文本类型响应\nfile：返回文件类型响应。文件内容不一定是本地文件，支持引用远程文件地址\ntiny-gif：返回一个 1x1 像素的 GIF 图片\nbase64：返回 base64 编码数据类型响应\n表达式：\n正则表达式用于匹配目标网站的 URL\n数据：\n填写所需返回的数据\n额外请求头：\n可选返回额外请求头\nHTTPS解密 对正在使用的配置开启 HTTPS 解密才能使包含 MITM 的模块完整生效，不包含 MITM 的模块除外\n打开HTTPS解密方法：\n点击配置文件的 ⓘ 图标 \u0026gt; HTTPS 解密 \u0026gt; 证书 \u0026gt; 生成新的 CA 证书 \u0026gt; 安装证书 系统设置 \u0026gt; 已下载描述文件 \u0026gt; 安装 系统设置 \u0026gt; 通用 \u0026gt; 关于本机 \u0026gt; 证书信任设置 \u0026gt; 开启对应 Shadowrocket 证书信任 自版本 2.2.81 (3096-3099) 起支持通过 HTTP/2 协议进行中间人攻击来解密 HTTPS 流量\n点击配置文件的 ⓘ 图标 \u0026gt; HTTPS 解密 \u0026gt; 通过 HTTP/2 进行中间人攻击（MitM） 或者在配置文件、模块纯文本模式中的 [MITM] 字段中使用 h2 = true 表示启用 若模块中包含此命令，则会覆盖配置文件中的相关设置\nHTTPS解密仅对启用此功能的配置文件生效，若切换或更换配置文件需要对新配置文件重新 开启解密，为避免重复安装证书可使用 证书模块\n若多终端经 iCloud 使用同一个配置文件，需要使用证书 ⓘ 图标的复制粘贴功能将同一个证书在多个终端上进行安装信任\n脚本 使用 JavaScript 拓展 Shadowrocket 的功能，在 纯文本编辑 模式中位于 配置文件 的 [Script] 字段\nUI 编辑：点击配置文件的 ⓘ 图标 \u0026gt; 脚本 文本编辑：点击配置文件 \u0026gt; 编辑纯文本 \u0026gt; [Script] 类型：\nhttp-request：使用脚本修改 HTTP 请求\nhttp-response：使用脚本修改 HTTP 响应\nevent：在指定事件发生时运行脚本\nrule：使用脚本作为规则使用\ndns：使用脚本作为DNS 解析器\ncron：在指定时间运行脚本\n引擎：\nauto：自动选择脚本引擎\njsc：适用于小型、简单、频繁调用的脚本，例如规则、DNS等\nwebview：适用于复杂、高内存需求的脚本，例如解析 MB 级别的 JSON\n若脚本类型为 http-request 或 http-response，则在配置 engine=auto 参数时，系统将默认调用 WebView 引擎，而非 JSC 引擎。因此，从使用规范与一致性角度考虑，该参数建议明确指定类型，以确保行为符合预期\n其他参数：\n参见软件内的具体选项及释义\n脚本文本示例如下：\n[Script] script = type=rule,script-path=rule.js 模块 模块是指为 Shadowrocket 提供额外功能的插件或者扩展项，一般是以增强或自定义软件的使用体验为出发点。模块的写法与 配置文件 相同，且模块的 规则优先级 高于配置文件。一般情况下，模块仅包含完整配置文件格式中的特定部分，以实现特定的特殊效果且不影响配置文件的其他功能。用户可以在模块里另外设置 通用参数 以及添加 规则、Hosts、URL重写、证书内容、解密主机名、脚本 等内容\n下载远程模块\n配置 \u0026gt; 模块 \u0026gt; 右上角 ➕ \u0026gt; 填写链接 \u0026gt; 下载 本地新建模块\n配置 \u0026gt; 模块 \u0026gt; 新建模块 \u0026gt; 编辑后保存\n模块 [MITM] 部分需要加 %APPEND%，表示把内容插入到配置中，不加时会覆盖配置中对应内容，并影响其他模块功能\n[MITM] hostname = %APPEND% 主机名 模块管理\n配置 \u0026gt; 模块 \u0026gt; 模块区域右上角 ···\n可以对模块顺序进行重新排序，并可以选择并批量删除/启用/禁用选定的模块\n备注\n对正在使用的配置 开启 HTTPS 解密 或使用 证书模块，才能使包含 MITM 的模块完整生效，不包含 MITM 的模块除外 因模块可能包含不同规则，所以大多数模块仅在 全局路由 设为配置时生效，不包含规则类的模块除外 iOS 15 之后，NE的内存限制由 15 MB 增加到了 50 MB，低版本系统可能因内存不足导致 模块失效 或 VPN 自动断开 若出现以下问题可以查看相应说明：模块消失、模块失效 编辑参数 配置 \u0026gt; 模块 \u0026gt; 点击模块 \u0026gt; 编辑参数 \u0026gt; 按需填写或修改\nShadowrocket 的 编辑参数 / 传递参数 功能，是用于对请求或响应中的参数进行动态修改的一个高级功能，可用于配合模块中的 URL Rewrite、Script、MITM 等代码使用，目的是实现对网络请求的精准控制与定制化处理。编辑参数所修改或填写的内容不会因为模块更新而丢失，若开启了 iCloud，其自定义参数保存在 iCloud - Shadowrocket - Modules 内与模块同名的 *.meta 文件内\n示例：\n#!name=证书模块 #!desc=需要以编辑参数的方式启用并填写完整 #!arguments=证书模块:false, 证书内容:此处粘贴有效的证书内容, 证书密码:此处粘贴有效的证书密码 #!arguments-desc=证书模块：启用并填写证书内容方可生效\\n\\n证书内容：粘贴自有效证书\\n\\n证书密码：若默认密码是Shadowrocket则可不动 [MITM] enable={{{证书模块}}} ca-passphrase={{{证书密码}}} ca-p12={{{证书内容}}} 证书模块 在实际使用软件时如果需要切换或更换 配置文件，且原配置已开启过 HTTPS 解密，则需要对新的配置文件重新安装并信任证书，才可使解密继续生效。为免除重复安装 CA 证书，可以选择使用证书模块。证书模块是一组手动添加已生效解密证书的模块，由于模块的优先级高于配置文件，可以使解密状态不受更换配置的影响。其原理参见：模块\n新建模块：\n软件 配置 \u0026gt; 模块 \u0026gt; 新建模块，复制以下内容并粘贴进去保存备用：\n#!name=证书（名字可更改） [MITM] enable=true # 在下方 “ca-passphrase=” 后面粘贴证书密码 ca-passphrase= # 在下方 “ca-p12=” 后面粘贴证书内容 ca-p12= 点击「已安装证书的配置文件」后面的 ⓘ 图标 \u0026gt; HTTPS 解密 \u0026gt; 证书后面的 ⓘ 图标 \u0026gt; 复制\n将复制的证书内容粘贴至第一步创建的证书模块内的 ca-p12= 后面保存\n证书模块原本可以省略 ca-passphrase 这行参数。但由于引用的配置文件可能已经包含了证书密码，且证书密码可能不是 Shadowrocket，为防止出错，因此才增加 ca-passphrase 参数来覆盖引用的配置文件的证书密码\n身份证书密码 Shadowrocket 安装 CA 证书时，如果遇到「输入证书 身份证书 的密码」页面，可以尝试输入：Shadowrocket\n编写本地节点 Shadowrocket 支持在 配置文件 中编写本地节点，但该操作方式仅是为了兼容部分其他类型的配置文件，不能当作 Shadowrocket 添加节点 的优先选择\nShadowsocks类型\n节点名称=ss,地址,端口,password=密码,其他参数(如method=aes-256-cfb,obfs=websocket,plugin=none)\nVmess类型\n节点名称=vmess,地址,端口,password=密码,其他参数(如alterId=0,method=auto,obfs=websocket,tfo=1)\nVLESS类型\n节点名称=vless,地址,端口,password=密码,tls=true,其他参数(如obfs=websocket,peer=example.com)\nHTTP/HTTPS/Socks5/Socks5 Over TLS等类型\n节点名称=http,地址,端口,用户,密码 节点名称=https,地址,端口,用户,密码 节点名称=socks5,地址,端口,用户,密码 节点名称=socks5-tls,地址,端口,用户,密码,skip-common-name-verify=true\nTrojan类型\n节点名称=trojan,地址,端口,password=密码,其他参数(如allowInsecure=1,peer=example.com)\nHysteria类型\n节点名称=hysteria,地址,端口,auth=密码,obfsParam=混淆,protocol=协议,udp=1,其他参数(如peer=example.com,alpn=h2,upmbps=100,downmbps=100)\nHysteria2类型\n节点名称=hysteria2,地址,端口,auth=密码,obfsParam=混淆,udp=1,其他参数(如peer=example.com,alpn=h3)\nTUIC类型\n节点名称=tuic,地址,端口,password=密码,udp=1,其他参数(如user=uuid值,peer=example.com,alpn=h2)\nJuicity类型\n节点名称=juicity,地址,端口,password=密码,udp=1,其他参数(如user=uuid值,peer=example.com,alpn=h2)\nWireGuard类型\n节点名称=wireguard,地址,端口,privateKey=私钥,publicKey=公钥,ip=子网IP,udp=1,其他参数(如dns=1.1.1.1,mtu=1350,keepalive=40,reserved=1/2/3)\nSnell v2 类型\n节点名称=snell,地址,端口,password=密码,udp=1,其他参数(如obfs=http,obfs-host=example.com,obfs-uri=/abc)\n数据页面 代理日志 代理日志 记录了网络活动过程中 Shadowrocket 处理请求的具体信息\n数据 \u0026gt; 代理 \u0026gt; 启用日志记录\n产生网络活动时，返回 数据 \u0026gt; 代理 页面查看日志文件\n每条记录包含信息：\n请求 URL 请求匹配的规则策略 请求传输协议 请求发送时间 记录显示 MITM，表示请求域名已启用解密\n点击每条记录查看详情，详情页右上角 ••• 可以选择类型添加规则\n数据 \u0026gt; 代理 页面，右上角 ••• 可以手动删除所有日志文件。日志文件页面，右上角 ••• 可以选择导出\n数据 \u0026gt; 自动删除 \u0026gt; 打开，程序会自动删除7天前的日志文件。Shadowrocket 已连接状态，手动删除将保留最新的日志文件，未连接时，手动删除所有\nDNS日志 DNS 日志 记录了网络活动过程中 DNS 服务器处理域名查询请求的具体信息\n数据 \u0026gt; 代理 \u0026gt; DNS \u0026gt; 启用日志记录\n产生网络活动时，返回 数据 \u0026gt; DNS 页面查看日志文件\n每条记录包含信息：\n请求域名 查询结果 DNS 响应时间 处理请求的 DNS 旗帜是根据返回IP地址的地理位置信息自动显示\n覆写 DNS 不可用或未返回有效响应时，将回退至 备用 DNS 来查询域名\n记录信息中如果响应时间超过2秒，意味着系统正在触发回退机制\niCloud自动同步 Shadowrocket 支持将服务器节点、配置文件、模块和脚本文件等数据类型自动同步至 iCloud 云端\n数据 \u0026gt; iCloud \u0026gt; 自动同步 \u0026gt; 打开\n设备 设置 \u0026gt; 账号 \u0026gt; iCloud，确保使用 iCloud 的 APP 列表中已经开启 Shadowrocket 和 iCloud 云盘 项目，否则会出现 iCloud 自动同步失败 的提示\n同步成功时，点击 iCloud 文件 可以看到存储云端的配置文件\n文件app \u0026gt; iCloud 云盘 \u0026gt; Shadowrocket，可以看到存储云端的所有数据。其中的 shadowrocket.v2.model 文件包含服务器节点的配置信息\niCloud 服务中断、网络连接问题以及其他复杂原因可能导致 iCloud 同步异常，这种情况建议选择手动删除 iCloud 备份并重新同步数据\n如果用户删除首页某个节点后发现它又自动恢复，可以尝试以下解决方法：数据 \u0026gt; iCloud，服务器节点下面点击删除 iCloud 备份和同步服务器节点\n添加的 场景 和 分组 不属于 iCloud 自动同步的数据类型，需要手动备份下载，才能在设备间共享数据\n💡 提示 由于 iCloud 的同步机制存在一定限制，在使用 iCloud 进行多设备数据同步时，建议采用以下方式：\n主设备：开启自动同步 副设备：保持关闭自动同步，仅在需要更新数据时手动执行同步操作 这种方式可以有效降低多设备同时同步所导致的数据冲突或覆盖问题\n节点数据管理 导出节点：将首页的所有节点数据整合成一个 JSON 文件，选择存储在本地或云端，也可以通过其他共享方式传输文件\n导入节点：将存储在本地或云端 JSON 文件中的节点数据解析并添加到首页\n删除本地节点：一键删除首页所有节点数据\n流量统计信息 统计 是 Shadowrocket 开启连接后接管设备所有网络传输的流量统计信息\n数据 \u0026gt; 统计 统计包含信息： 开始时间 连接时间 Wi-Fi 和蜂窝数据的上下行流量 流量分流的柱形图统计 默认记录所有流量统计信息。打开 启用存档 将会单独记录每一次连接的流量统计信息，关闭首页连接后可以从 归档 查看 点击右上角 ••• 可以重置统计信息 首页 订阅 支持显示流量统计信息\n方法一，订阅链接添加响应头：subscription-userinfo: upload=xxx; download=xxx; total=xxx; expire=xxx 方法二，在订阅链接指向的纯文本 base64 编码前添加 STATUS=xxx 或 REMARKS=xxx 字段，这样订阅名称下方就能显示自定义信息。如果没有添加字段或者隐藏用户代理字符串，可能导致不返回相关统计信息，只显示时间 设置页面 延迟测试方法 详见词条 连通性测试\n小组件 设置 \u0026gt; 小组件\n服务器节点：根据需求添加6个常用节点，点击 Today 小组件 右上角的 \u0026gt; 可以展开查看，方便手动切换节点\n显示Ping值：启用后，长按 Today小组件 中心位置可以测试 服务器节点 连通性并显示延迟数字\n根据Ping排序：启用后，长按 Today小组件 中心位置可以测试 服务器节点 连通性并依延迟大小自动排序\n添加小组件方法：\nToday 小组件\n负一屏 \u0026gt; 编辑 \u0026gt; 自定 \u0026gt; 点击 Shadowrocket 旁边的 添加 按钮 ➕。（系统要求低于 iOS 18） 屏幕小组件\n长按屏幕 \u0026gt; 左上角 ➕ \u0026gt; Shadowrocket，选择合适类型添加。（系统要求≥ iOS 17） 更新 Shadowrocket 后，如果找不到小组件添加按钮，请尝试重启手机。如果小组件显示 无法加载，请尝试以下方法：\n系统设置 \u0026gt; 通用 \u0026gt; 语言与地区，添加或删除一种其他语言 颜色 设置 \u0026gt; 颜色\nShadowrocket 支持自定义设置软件配色方案，可以根据个人喜好调整各个板块的颜色，并可以随时恢复默认颜色。同时支持分享和安装已有配色方案，配色案例参考 此处\n配色安装方法：复制已知的配色链接，在配置页面点击 ➕ 号粘贴安装\n外观：支持匹配系统的自动色彩方案，以及深色、浅色模式 传统样式：使用传统应用样式 颜色：自定义设置颜色，编码为 十六进制颜色编码（Hex Color Code） 重设颜色：恢复默认配色 复制网址：复制当前配色的 URL 地址，可用以分享或保存 以下为软件配色项目的名称及其中文译名，需要注意因系统限制，部分项目不可自定义\nNavigationBarColor / 导航栏背景色 NavigationBar2Color / 导航栏背景色2 NavigationBarTextColor / 导航栏文字颜色 NavigationBar2TextColor / 导航栏文字颜色2 TabBarColor / 标签栏背景色 TabBarBorderColor / 标签栏边框颜色 TabBarSelectedColor / 标签栏选中项颜色 TabBarUnselectedColor / 标签栏未选中项颜色 TableBackgroundColor / 表格背景颜色 TableCellBackgroundColor / 表格单元格背景颜色 TableCellSelectedBackgroundColor / 表格单元格选中项背景颜色 TableSeparatorColor / 表格分隔线颜色 TextFieldTextColor / 文本框文字颜色 PlaceholderColor / 占位符颜色 TextLabelTextColor / 文本标签文字颜色 DetailLabelTextColor / 详细标签文字颜色 TextLabelDeleteColor / 文本标签删除文字颜色 HeaderFooterTextColor / 页眉页脚文字颜色 SearchFieldBackgroundColor / 搜索框背景颜色 IndicatorColor / 指示器颜色 ButtonIconColor / 按钮图标颜色 ButtonNormalColor / 按钮正常状态颜色 ButtonNormal2Color / 按钮正常状态颜色2 ButtonNormal3Color / 按钮正常状态颜色3 ButtonHighlightedColor / 按钮高亮状态颜色 ButtonHighlighted2Color / 按钮高亮状态颜色2 ButtonHighlighted3Color / 按钮高亮状态颜色3 ButtonDisabledColor / 按钮禁用状态颜色 ButtonDisabled2Color / 按钮禁用状态颜色2 PingSuccessTextColor / 测试Ping成功文字颜色 PingTimeoutTextColor / 测试Ping超时文字颜色 DefaultDotColor / 默认指示点颜色 HUDBackgroundColor / 弹窗HUD背景颜色 按需求连接 始终开启\nVPN 保持连接状态。意外断开 或者重启设备，也会自动连接\n脚本 / 模块 / 解密 等需求比较多时建议开启\n按需求连接\n根据添加的 按需求规则 自动切换 VPN 状态。默认规则是任意网络类型下保持连接状态，相当于 始终开启\n按需求规则：\n当访问列表中的 域名 时，系统会向 Shadowrocket 发送请求，如果响应成功，VPN 自动连接 网络中指定的 DNS（通常认为是网络运营商/Wi-Fi路由器提供的 DNS 服务器地址）与列表任一内容相匹配时，VPN 自动连接或断开 SSIDS 填写需要匹配的 Wi-Fi 名称 VPN 连接行为可以通过 网络类型 / 域名 / DNS 条件触发 VPN 断开行为可以通过 网络类型 / DNS 条件触发，不能通过 域名 条件触发 从上到下依次匹配添加的 按需求规则 添加 按需求规则 后，打开 按需求连接 开关，规则才能生效\n同时打开 始终开启 和 按需求连接，只有 始终开启 选项能够生效\n按需求连接是系统管理行为，域名通过系统 DNS 触发开启 VPN，如果域名被解析过或者有缓存则可能不会触发，Shadowrocket 只负责按需求规则的配置，是否生效取决于系统行为\n睡眠时断开\n当设备进入睡眠状态，VPN 自动断开连接\nShadowrocket 响应系统发送的睡眠指令才会断开连接，有时候熄屏的系统未必处于睡眠状态\n显示断开信息\n显示 VPN 断开连接的通知信息 隧道 强制路由\n如果开启，这个隧道的路由规则将优先于任何本地自定义的路由，默认是关闭状态\n包括所有网络\n启用后系统会通过隧道进行路由所有的网络流量，但为维持预期设备功能所必需的指定系统服务的流量除外\n包括本地网络：如果开启，所有发送到本地网络的流量都将包含在隧道中，如 AirPlay、AirDrop 和 CarPlay 的网络连接 包括APNs：如果开启，苹果的 Apple Push Notification 推送通知服务（APN）的网络流量将包含在隧道中 包括蜂窝服务：如果开启，来自蜂窝服务的互联网可路由网络流量（VoLTE、Wi-Fi通话、IMS、MMS、视觉语音信箱等）将包含在隧道中。 兼容模式 设置 \u0026gt; 代理 \u0026gt; 兼容模式\nHomeKit 与摄像头建立连接时，会主动将本机 IP 发送给摄像头端逆向连接。部分情况下 iOS 可能并未处理 VPN 开启时的情况，会将 VPN 的内网地址发送给摄像头，导致 RTSP 数据回包无法发回到 iOS 设备上。若当前设备与家庭中枢设备处于同一局域网下且开启代理时，如果出现无法正常使用 家庭 应用查看流式传输的 HomeKit 实况影像时，可以尝试开启此项以提高相应的兼容性。此处的设置是配置文件通用隐式参数中 compatibility-mode 的一种，开启该选项效果等同于 配置文件 内设置 compatibility-mode=5\n前置代理 设置 \u0026gt; 代理 \u0026gt; 前置代理\n「前置代理」表示所有流量先通过 HTTP/SOCKS5 代理转发，再根据配置规则向节点服务器发送请求\n代理共享 代理共享指的是将你当前配置的代理设置分享给其他设备使用。通过代理共享，你可以把自己配置好的代理服务器（如Shadowsocks、Vmess等）通过局域网或者热点网络的方式让其他设备也能够通过相同的代理设置访问互联网\n在局域网条件下\nA设备：设置 \u0026gt; 代理 \u0026gt; 代理共享 \u0026gt; 启用共享 B设备：系统设置 \u0026gt; WiFi \u0026gt; WiFi 名称后面的 ⓘ 图标 \u0026gt; HTTP代理 \u0026gt; 手动输入Shadowrocket「代理共享」的IP和端口 使用热点条件下\nA设备：开启热点 B设备：连接热点 然后按照局域网条件下方法进行设置\n此处需要注意下操作顺序，原理是连接设备热点后先形成局域网环境，然后按照局域网条件进行设置 备注\n当 iOS 设备开启代理共享时，或需保持该设备屏幕常亮或连接充电器，以防意外退出 如果配置文件开启了 HTTPS 解密，请确保其他设备已安装并信任相同的证书才能正常使用。当其他设备不需要使用解密功能时，可以在 代理共享 页面关闭「HTTPS解密」开关 使用代理共享时需要对应的 APP 打开系统设置中的 本地网络 开关 Telegram 可能不被系统代理接管，可单独在应用内添加 SOCKS5 代理 代理类型 Shadowrocket 代理类型：\n设置 \u0026gt; 代理 \u0026gt; 代理类型\nHTTP：系统代理模式，对于不支持的程序会交给 TUN 接管网络连接\nNone：TUN 模式，全部网络请求都将通过 TUN 接口进行处理。效果等同于 配置文件 内设置 compatibility-mode=3\n开启UDP转发 设置 \u0026gt; UDP \u0026gt; 启用转发 \u0026gt; 打开\n首页 \u0026gt; 订阅后面的 ⓘ 图标 \u0026gt; UDP转发 \u0026gt; 打开\n首页 \u0026gt; 节点后面的 ⓘ 图标 \u0026gt; UDP转发 \u0026gt; 打开\n禁用STUN 设置 \u0026gt; UDP \u0026gt; 禁用STUN \u0026gt; 打开\n禁用 STUN（Session Traversal Utilities for NAT） 的意思是完全阻止 WebRTC 通过 STUN 服务器获取公网 IP，从而彻底杜绝 WebRTC IP 泄露的问题\n若在配置文件 通用参数 中使用 stun-response-ip 的相关命令，则此处的开关状态将被忽略\n权限 位置\niOS 系统要求必须开启位置权限才可以读取 Wi-Fi 网络的 SSID 名称。在 Shadowrocket 中，此权限仅在需要使用基于连接 Wi-Fi 网络触发特定配置的 场景 功能时才需要\n通知\n开启通知权限才可允许软件发送重要通知或警报，包括：脚本执行结果、订阅更新通知、VPN 断开通知等\n剪贴板\n开启剪贴板权限后，Shadowrocket 将在打开应用程序后尝试识别剪贴板中的内容是否是代理服务器的 URL，若是则会提示将其导入到应用。若未启用此权限，Shadowrocket 主页的本地节点上方将出现一个专用的粘贴按钮，以允许手动粘贴和导入剪贴板的内容\n隐藏VPN图标 设置 \u0026gt; 排除路由 0.0.0.0/31 \u0026gt; 打开\n注意：该选项是利用系统漏洞实现的，打开开关可能会导致网络异常，不推荐开启此项\nGEOIP数据库 设置 \u0026gt; GeoLite2 数据库\n软件已内置常规 GeoIP 数据库，一般情况下无需设置，若有需要请参考以下设置方式\n方法一\n填写 MaxMind官网 注册的账户 ID 和密钥，点击下方的 更新 按钮 方法二\n关注 GitHub 的 IP 数据库项目，复制 mmdb 格式的下载链接，粘贴在国家/ASN 对应的 URL 位置，点击 更新 按钮。当点击 重置 时，可以恢复为系统自带的数据库\nLoyalsoldier 的 IP 数据库：\nhttps://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb Hackl0us 的 IP 数据库：\nhttps://github.com/Hackl0us/GeoIP2-CN/raw/release/Country.mmdb Masaiki 的 IP 数据库：\nhttps://github.com/Masaiki/GeoIP2-CN/raw/release/Country.mmdb P3TERX 的 ASN 数据库：\nhttps://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-ASN.mmdb 自动更新 现阶段软件的自动更新包含配置文件自动更新、模块自动更新、服务器订阅自动更新以及 GeoLite2 数据库自动更新。需要在 系统设置 \u0026gt; 通用 \u0026gt; 后台App刷新 中为 Shadowrocket 启用后台刷新。在重新启动设备、杀死应用程序等结束了程序进程或后台的情况下，后台任务将不能自动启动\n配置：根据设置自动 更新配置 以及当前所用的 规则集、脚本 等远程资源。\n自动后台更新：开启后可根据设置自动更新配置文件 更新提醒：开启后，更新时会弹出相应提醒。需要开启设备推送通知 更新间隔：单位为 天，可选 1-7 天 若当前配置文件是不含更新地址的本地配置文件，则自动更新功能仅会更新当前所用的规则集、脚本等远程资源，参见：使用配置 / 编译配置、规则集URL、脚本URL 规则集/脚本资源手动更新方法：点击 配置文件 \u0026gt; 使用配置 / 编译配置 需要注意：自动更新配置会覆盖自定义设置，参见 更新配置 模块：根据设置自动更新远程模块资源\n自动后台更新：开启后可根据设置自动更新模块 更新提醒：开启后，更新时会弹出相应提醒。需要开启设备推送通知 更新间隔：单位为 天，可选 1-7 天 订阅：根据设置自动更新服务器订阅，另外可 参见此处\n自动后台更新：开启后可根据设置自动更新订阅 更新提醒：开启后，更新时会弹出相应提醒。需要开启设备推送通知 更新间隔：单位为 小时，可选 1-24 小时 DNS：使用指定的 HTTPS DNS 来解析订阅链接的域名，点击右侧的 ⓘ 可以挑选内置的 DNS 根据 PING 排序：以连通性测试的结果从小到大排列服务器节点 发送 HWID：开启该开关后，Shadowrocket 将在更新订阅时发送 X-HWID 标头 显示删除确认：连通性测试结束后，显示是否删除超时节点的对话框 GeoLite2 数据库：包含自动后台更新选项、更新提醒选项、更新间隔选项，其中更新间隔单位为 天。其他设置 参见此处\n💡 提示 若当前配置是远程配置，希望定期更新远程资源，且不希望自定义设置被覆盖或丢失时，可参考以下两种方法：\n进入 纯文本编辑 删除或注释掉 update-url = *，然后再使用自动更新功能 使用 扩展配置/包含配置 功能后，再使用自动更新功能 温和策略机制 当使用温和策略机制时，切换策略不会打断之前与之相关的TCP连接，仅会对之后的网络请求使用新的策略进行连接\n当不使用该功能机制时，切换策略会打断与该策略相关的旧有 TCP 连接，若继续使用则使用新的策略重新连接\n例如：打断会使旧有策略相关的连接所进行的下载任务中断\n其他问题 自动切换节点 自动切换延迟低的节点：\n方法一\n首页 \u0026gt; 全局路由 \u0026gt; 分组 \u0026gt; 简单模式 \u0026gt; 打开 方法二\n点击配置文件的 ⓘ 图标 \u0026gt; 代理分组 \u0026gt; 右上角 ➕ \u0026gt; 类型 url-test 备注\n如果节点不稳定，可同时 开启回退 订阅异常 添加/更新订阅时异常的原因：\nforbidden 表示订阅被重置或令牌 token 错误 not found 表示订阅路径或链接信息错误 service unavailable 表示域名信息错误或域名被运营商屏蔽 SSL 错误 表示无法建立与该服务器的安全连接 添加/更新订阅链接时，如果发生异常，可以尝试的解决方法：\n全局路由选代理，使用另外一个节点来添加/更新订阅链接 切换网络后再添加/更新订阅链接 检查订阅链接是否错误或失效 节点旗帜 节点优先根据备注名称匹配旗帜，如果匹配不成功，由节点地址解析出 IP，通过数据库判断该IP的国家或地区，然后显示对应的旗帜\n节点后面的 ⓘ 图标 \u0026gt; 地址栏的图标，可以手动修改旗帜 订阅后面的 ⓘ 图标 \u0026gt; 订阅界面的 筛选 输入框，输入相关脚本能批量修改旗帜，参考：订阅节点筛选 如果把旗帜的 Emoji 放在节点备注开头，保存时会自动显示对应的旗帜，且不显示开头的 Emoji\n节点感叹号 节点显示感叹号 ⚠ 的原因：\n您的节点使用了 TLS，地址是 IP，却没有设 SNI 这不是正确的服务器设置，但为了可以正常连接，Shadowrocket 会主动开启 允许不安全。允许不安全 将跳过TLS证书验证，这将导致一些安全问题。如果您使用自签名证书，请将证书导入系统并信任它，否则请及时续订服务器端证书，以防止证书过期。在 2.2.23 等特定版本中，该选项可能默认为关闭状态\n微信转圈 如果使用 Shadowrocket 时微信一直显示 连接中/收取中，可以尝试的解决方法：\n微信分流走直连\n点击配置文件的 ⓘ 图标 \u0026gt; 通用 \u0026gt; 启用IPv6 \u0026gt; 关闭\n本质上该问题是由于现阶段某些地区的运营商对 IPv6 的支持不够稳定，或是路由器设置不当，可能会引发微信加载异常的问题\n模块消失 模块页面已经开启 保存到 iCloud，如果出现模块消失的问题，请检查：\n系统设置 \u0026gt; Apple ID \u0026gt; iCloud \u0026gt; 使用iCloud的APP中，确保Shadowrocket/iCloud云盘已经打开同步\n文件app \u0026gt; iCloud云盘 \u0026gt; Shadowrocket，确定其中包含 Modules 和 Script 两个子文件夹\n文件app \u0026gt; iCloud云盘 \u0026gt; Shadowrocket \u0026gt; Modules，如果iCloud的本地缓存被清理，此时模块文件是未下载状态，请等待自动下载或手动下载\n模块失效 切换配置文件需要重新 开启解密，为避免解密失效可使用 证书模块 若 模块 确认有效且解密设置无误时存在模块失效的情况，则可能是加载资源时因内存、网络等原因导致部分内容出现漏编译的情况。尝试对当前配置点击 使用配置 / 编译配置，以使远程资源进行重新拉取，一般可恢复正常 VPN自动断开 因系统版本低于 iOS 15、处理复杂请求、加解密数据、运行脚本等因素或多种因素相互作用之下可能导致 NE 内存占用过高，从而造成 VPN 自动断开，解决方法：\n设置 \u0026gt; 按需求连接 \u0026gt; 始终开启 \u0026gt; 启用\n检测代理 如果在使用 Shadowrocket 的时候，遇到某些 APP 提示需关闭代理才能使用，可以在 Shadowrocket \u0026gt; 设置 \u0026gt; 代理类型 \u0026gt; 选择 None\n该设置将使用 TUN 模式 接管代理，能很大程度上缓解上述情况，但对于某些直接检测系统 VPN 状态或使用其他检测手段的 APP 无效\n编译原因 Shadowrocket 2.2.29 之前的版本是使用 Xcode 13.2.1 编译的\n2023年4月份以后，苹果官方要求开发者在提交应用到 App Store 时必须至少使用 Xcode 14 编译，所以 iOS12 以下系统无法使用\nShadowrocket 在版本 2.2.30 之后设置最低安装要求 iOS12，然后停止 2.2.29 版本，iOS 低版本用户可以安装 2.2.28 版本\nURL-Schemes 请使用相应内容直接替换代码中的大括号及其内容\nShadowrocket 支持 X-callback-urls，允许其他应用程序在 Shadowrocket 中触发某些操作\n支持添加 autoclose=true 查询值，可在动作触发后退出 Shadowrocket\n启动 VPN 隧道\nshadowrocket://connect shadowrocket://open 停止 VPN 隧道\nshadowrocket://disconnect shadowrocket://close 切换 VPN 开关状态\nshadowrocket://toggle 连通性测试\nshadowrocket://connectivity-test 使用特定节点\nshadowrocket://select?s={节点名称} 添加 订阅/节点\nshadowrocket://add/{url} 更新 订阅\nshadowrocket://update-subs 安装/使用 配置\nshadowrocket://config/add/{url} 安装/使用 模块\nshadowrocket://install?module={url} 切换全局路由（代理/配置/直连/场景）\nshadowrocket://route/proxy shadowrocket://route/config shadowrocket://route/direct shadowrocket://route/scene 安装/使用 配色\nshadowrocket://color?{配色设置} ","date":"2026-04-19T15:15:38+08:00","image":"/images/Shadowrocket.png","permalink":"/posts/shadowrocket%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C%E6%90%AC%E8%BF%90/","title":"shadowrocket使用手册（搬运）"},{"content":"见过去，我们总是浸没在幻想未来的海洋中\n见而当我们到达幻想的未来之后，又总是怀恋过去。\n见我们好像一直活在过去与未来当中。\n见可是此刻，我活在当下。\n见一切都是最重要的，却又都不是非要不可的。遗憾才是人生的常态。\n见是的，我就是一个懦夫，胆小鬼，徒然的跪倒在勇者的神像前虔诚的祈祷，仿佛这样，爱与光辉就会照彻我的灵魂。我又想起了唐吉诃德，他穷极一生都在向着名为生活的大风车发起冲锋，可我呢，我连勇气也没有。我连认认真真道别的勇气都没有。\n见后来我渐渐明白了，有些东西不是你应得到的，恰恰是应你失去的。而失去的这些，会成为永久的珍贵的回忆。记忆如山风微微，又如海边月下晃动的波浪。若是再次乘舟向着那天的景色驶去，于启程之日所见的层层摇曳色彩便浮现出来。\n见所以，如果旅途的尽头是分别，那就赶快说声再见吧。在这时针滴滴答答一刻不停转动的世界里，无论多少次，去触碰那残酷的刺耳之声，都会泫然欲泣。走吧，前方还有未曾见过的山海等着你。列车已经到站，每个人都有自己的下一站。\n见阿廖沙，火车在前面停下来了，向前看，别回头，向前看，别回头…\n","date":"2025-08-09T22:30:19+08:00","image":"/images/qiuyou.webp","permalink":"/posts/%E5%AE%9E%E5%9C%A8%E6%98%AF%E7%9D%A1%E4%B8%8D%E7%9D%80/","title":"实在是睡不着"},{"content":"最近买了一台小米8ud（屏下指纹版）因而在网上上苦求刷机包，可惜大部分资源都被存在了123云盘中，迫不得已，在网上苦求突破123云盘的下载限制，顺便提个速。经过一番折腾，终于成功了，现将方法记录如下：\n本教程部分应用要在VPN环境下下载，建议先开启VPN。 下载一个可用的浏览器，仅限于Chrome、Edge、Opera、Firefox浏览器，其他浏览器不行。 下载并安装Tampermonkey插件，地址：https://www.tampermonkey.net/ 安装脚本，地址：https://greasyfork.org/zh-CN/scripts/519353-123%E4%BA%91%E7%9B%98%E8%A7%A3%E9%94%81 安装Motrix下载助手，地址：https://github.com/gautamkrishnar/motrix-webextension 访问Motrix官网，地址：https://motrix.app/ 点击下载，下载合适的Motrix客户端，安装完成后打开。 单击浏览器中的Tampermonkey图标，选择“123云盘解锁”，然后点击“启用”。 打开扩展中的开发人员选项，并允许篡改猴执行用户脚本。 选择扩展中的motrix下载助手，启用它。 访问123云盘的下载链接，点击保存到云盘。 打开云盘网页端，选择刚才保存的文件。 点击右下角的设置面板，启用里面的选项 然后点击下载即可 这个方法好在不受流量限制，而且不限速，缺点是需要安装几个插件和软件，稍微麻烦一些。 以及每次只能下1GB以内的多文件或随意大小的单文件（单文件可以有随意大小），不能大批量下载。 祝大家下载愉快！我所下到的刷机包回头会分享出来的。\n","date":"2025-08-06T22:16:29+08:00","image":"/images/Snipaste_2025-08-06_21-58-25.png","permalink":"/posts/%E7%99%BD%E5%AB%96123%E4%BA%91%E7%9B%98%E7%9A%84%E6%B5%81%E9%87%8F%E4%B8%8E%E9%80%9F%E5%BA%A6/","title":"白嫖123云盘的流量与速度"},{"content":"😊 温馨提示：虽然全文篇幅略长，但依然建议完整阅读，不要直接“跳”到机场列表中。因为我希望各位在此不仅仅只是收获到好用的机场，还能收获一些有助于你在翻墙之路走得更长远的知识。如果实在懒得看完也请至少记住一句话：任何机场都有跑路的可能性，善待自己的每一分钱，永远不要年付！\n📢 入口通报事件：此区域专门用于对 2025 年 7 月初左右的“入口通报事件”作出必要的通知（包括受此影响而进行某些大改动的机场的通知）。由于影响范围广且暂未知道持续多久，因此，该区域的通知暂定长期保留（该区域的通知本来在下方的“重要通知”中，但由于内容过多且需要长期保留，因此将这些通知整合至此）。\n🗓️ 2025.06.28 🗓️ 近期多数机场都有较大的网络波动，电信用户可能感知比较明显。大概率是加强网络审查了（可自行搜索关键词：“2025”，“净网”）。这个事情基本每年都有，力度不一，时间不定，持续时间也不等。如果近期明显感觉变卡了，勤更新订阅，然后慢慢等就好了，应该不会持续太久。不建议换机场，因为换了大概率也没什么用。🗓️ 2025.07.05 🗓️ 目前看来，受影响的主要是中转机场，原因是国内入口各种被通报。因此，如果非要换机场，只建议购买直连机场。🗓️ 2025.07.09 🗓️ 形势依然不见好转，机场圈已经很久没遭遇持续时间这么久的“暴风雨”了，真正的原因不得而知。前面说的“不会持续太久”已经不太成立了，接下来可能需要做好打“持久战”的准备了。若真如此，对机场主的财力和维护速度会是不小的考验。但你我只是用户，不要慌张，慢慢等就好了。车到山前必有路，船到桥头自然直。虽说未雨绸缪很重要，但也不要提前焦虑，更不要过分焦虑。作为普通用户，我只建议购买直连机场这种低成本的方式来应对。不要试图通过购买更多中转机场，甚至专线机场来防止失联（友情提醒：专线机场同样受本轮“风雨”的影响），因为有些机场可能会扛不住压力而跑路。再再再次强调，购买机场时不要年付，尤其是在现在这种情况下。🗓️ 2025.07.10 🗓️ 为了应对本轮通报，已有部分机场将节点由原先的 SS 协议更改为Vless 协议，或是由 IPv4 更改为 IPv6 等方式。有些改动需要用户“配合”（如更换代理软件），请大家多留意通知（如果只是普通小改动，比如“原订阅无法更新，需要重新到官网获取订阅链接”，这里不会作通知。除非涉及协议变更之类）。🗓️ 2025.07.11 🗓️ 近期打算购买或续费中转机场的用户，建议先确定一下自己的网络是否支持 IPv6，即使该机场目前依然还在使用 IPv4。因为近期许多 IDC 已经无法提供 IPv4 了，如果你所购买的机场的 IPv4 都被通报完了，而该机场的老板买不到 IPv4，那大概率会全面更改为 IPv6。 检测当前网络是否支持 IPv6 可前往 该网站（为尽可能保证测试结果的准确性，访问时请关闭代理软件），能访问就是支持。不能访问不一定是不支持，可能是你的路由器没开启 IPv6 等原因。如果你能确定你的网络是支持 IPv6 的（能看到路由器获取到了 IPv6 地址），而电脑却不能访问该网站。那可能是你曾经将网卡的 IPv6 或是浏览器的 IPv6 禁用了等原因。另外，部分代理软件默认会禁用 IPv6，请检查软件设置中是否有 IPv4 Only 或是 Disable IPv6 之类的字眼，若是有，请将其更改为 Prefer IPv6 或 Enable IPv6。小火箭的步骤为：配置 \u0026ndash;\u0026gt; 点击正在使用的配置文件右侧的“感叹号” \u0026ndash;\u0026gt; 通用 \u0026ndash;\u0026gt; 开启“启用 IPv6”和“首选 IPv6”。不同的代理软件会有一定的区别。 Nekoray 的用户如果发现在使用 IPv6 之后，部分原先可用的 IPv4 节点能 Ping 通，但是用不了。那么可以尝试以下步骤：首选项 \u0026ndash;\u0026gt; 路由设置 \u0026ndash;\u0026gt; 域名策略* \u0026ndash;\u0026gt; 选择“prefer_ipv4”。NekoBox 也是类似的：设置 \u0026ndash;\u0026gt; 域名策略（服务器地址）\u0026ndash;\u0026gt; 选择“prefer_ipv4”，可能还需要勾选“追加 HTTP 代理至 VPN”（安卓端这两个设置建议先开启后者，后者无效再将两者一起开启。两者同时开启可能会使部分节点产生断流现象）。若是问题依旧，那可以考虑更换其他代理软件。不过其他软件可能也有类似问题，若是遇到了，请自行排查。 即使机场使用了 IPv6，相应机场提供的客户端不一定能及时跟进支持 IPv6。因此，如果你使用的是机场提供的客户端，且确定自身网络支持 IPv6，而却依然无法使用节点，建议更换为常规代理软件。 IPv6 不是百分百比 IPv4 好用的，因此，对于一些同时支持 IPv4 和 IPv6 的节点，在 IPv4 可用的情况下，如果 IPv6 体验不好，可尝试切换回 IPv4。不过，一些代理软件即使将所有 IPv6 相关的选项关闭，只要本地网络支持 IPv6，依然会使用并且优先使用 IPv6（验证节点是解析为 IPv4 还是 IPv6，可以通过观察日志或其他方式。比如部分软件会提供“将节点域名解析为 IP 地址”的功能。注意，此处所讲的 IPv6 是指入口，与节点本身是否能访问 IPv6 的网站无关。因此，不可以通过“国外测速网站”或者“国外 IP 地址检测网站”所测出来的地址做判断）。PC 端的解决方案比较简单，可以直接将网卡的 IPv6 禁用。移动端就比较麻烦了，如果使用 Wifi，那可以关闭路由器的 IPv6。如果使用流量，那需要在手机的设置里找到“SIM 卡设置”相关的字样，在“APN”（注意：不是 VPN）相关设置中关闭 IPv6（但不是所有手机都有相关设置）。更详细的操作方式可以参考 该网站。 🗓️ 2025.07.10 🗓️ 蜂窝云 的用户请注意，该机场现在已新增入口为 IPv6 的节点。拥有 IPv6 的用户可通过以下方式使用：进入官网 \u0026ndash;\u0026gt; 节点列表 \u0026ndash;\u0026gt; 订阅节点筛选 \u0026ndash;\u0026gt; 将“选择入口类型”的“通用入口”改为“IPv6入口” \u0026ndash;\u0026gt; 保存更改 \u0026ndash;\u0026gt; 前往代理软件更新订阅。🗓️ 2025.07.22 🗓️ 该机场表示受本轮通报的影响，导致原先中转线路资源紧缺且体验不佳等问题，已经全部升级为 IEPL 专线（所谓专线其实就是线路较优质的中转），原先中转套餐的用户也同步升级（套餐有效期和流量总量不变）。然后，目前已停止出售中转套餐（不排除以后有重新上架的可能），只出售专线套餐，因此价格会比之前高不少。原先 10 ￥ / 300 GB，现在 20 ￥ / 188 GB，其实也不算特别贵，但是门槛翻了一倍。因此，已购该机场的用户如果接受不了现在的价格，到期后可以考虑更换其他。🗓️ 2025.07.23 🗓️ 目前已不需要使用 IPv6 入口，IPv6 入口反而可能不稳定。之前如果有使用 IPv6 入口，建议切回 IPv4。即在“订阅节点筛选”中将“IPv6入口”改回“通用入口”。 🗓️ 2025.07.10 🗓️ 兔兔云 的用户请注意，该机场现在已将原先 SS 协议的节点更改为仅 IPv6 可用，并新增大量 Vless 节点供 IPv4 用户使用（依然为中转节点）。请前往官网重新获取订阅链接并导入。注意，部分老旧代理软件不支持 Vless 节点（如果客户端太老获取不到 Vless 节点，才会获取到 SS 节点），如 Clash for Windows。当然，不是说“较新”的代理软件就一定支持 Vless，比如 Sufboard 和 Surge 就一直不支持。请及时更换为支持 Vless 协议的代理软件。 🗓️ 2025.07.10 🗓️ 次元云 的用户请注意，该机场部分节点已支持 IPv6，依然支持解析为 IPv4，但 IPv6 体验更佳，直接更新订阅即可。非 IPv6 的移动用户暂勿购买该机场，大概率会完全无法使用（即使是有 IPv6 的移动用户，也暂不建议购买。因为目前该机场的 IPv6 节点还较少）。🗓️ 2025.07.13 🗓️ 只有 IPv4 的移动用户已经可使用部分节点。🗓️ 2025.07.16 🗓️ 所有节点已支持 IPv6，且大部分节点已经恢复了（只有 IPv4 的移动用户大部分节点也可使用了）。🗓️ 2025.07.18 🗓️ 大部分的 IPv4 节点再次祭天（三网都一样）。另外，该机场所有节点均已支持解析为 IPv6。🗓️ 2025.07.21 🗓️ IPv4 节点已基本恢复。 🗓️ 2025.07.11 🗓️ 云安云 的用户请注意，该机场所有节点已支持 IPv6，直接更新订阅即可。非 IPv6 的用户暂勿购买该机场，虽然依然支持解析 IPv4，但是大概率会完全无法使用。🗓️ 2025.07.12 🗓️ 该机场目前所有节点处于不可用状态（IPv4 和 IPv6 都如此），有一定跑路风险。不过考虑到近期状况，有待继续观察。🗓️ 2025.07.12 🗓️ 目前 IPv4 和 IPv6 均已恢复，非不限时用户可发工单要求补偿一周时间，跑路风险基本解除。不过，暂不建议购买，因为虽然节点已能使用，但是体验仍比较一般（尤其是在解析为 IPv4 时）。🗓️ 2025.07.20 🗓️ 目前 IPv4 和 IPv6 均以恢复至较佳的状态。另外，该机场已将订阅链接改为“阅后即焚”模式。即在官网复制订阅链接后，该订阅链接一定时间内（官网通知为 5 分钟）可导入代理软件。超过该时间后，如果想导入代理软件，需要重新复制订阅链接（注意，这个时间不是从你复制那一刻算起的。如果复制后导入失败，那可能是正巧失效了，此时可以尝试刷新网页，再重新复制订阅链接）。因此，导入订阅后，请勿再更新订阅（因为有些代理软件在更新订阅时会先清除当前订阅的节点，而由于这种订阅是阅后即焚的，就会导致更新后节点全部消失，需要重新前往官网获取），如果设置了自动更新订阅，也请关闭（虽然我在之前的通知里说近期要勤更新订阅，但是“阅后即焚”模式是相反的，导入后就别再更新）。所谓“阅后即焚”模式是为了防止订阅泄漏，由机场圈数一数二的“奶昔”率先使用，有着不错的效果，所以有一些机场也在跟进该模式。但该模式也是有缺点的，那就是当节点发生变化时，需要重新到官网获取订阅链接，比较麻烦。以及无法通过更新订阅来查看自己当前剩余流量，只能前往官网查看。🗓️ 2025.07.23 🗓️ 节点已更新，需从官网重新复制订阅（后续这类普通更新不再通知，想保持获取最新节点可一天获取一次。但其实也没必要这样，节点变化应该不会很频繁，等到节点不可用时再去重新复制就好了）。 🗓️ 2025.07.12 🗓️ 农夫山泉 的用户请注意，该机场所有节点已支持 IPv6，依然支持解析为 IPv4，但 IPv6 体验更佳，直接更新订阅即可。🗓️ 2025.07.25 🗓️ 目前大部分节点对于电信和联通用户基本都处于不可用状态，非移动用户暂勿购买该机场，需等待修复。另外，该机场所有节点的入口已不支持 IPv6，原因未知（不过新疆依然可使用 IPv6）。🗓️ 2025.07.25 🗓️ 节点已恢复。另外，已上线几个 Vless 节点（依然为中转），后续大概率会将所有节点都变更为该协议，建议该机场的用户尽快更改为支持改协议的代理软件。🗓️ 2025.07.31 🗓️ 目前约一半的节点已更换为 Vless 协议。 🗓️ 2025.07.22 🗓️ M78星云 的用户请注意，该机场目前一小部分节点已支持且仅支持 IPv6，这部分节点名称带有相应标识。 📢 重要通知：此部分仅用于对本项目以及机场的“重要变动”或“突发情况”作出必要的说明。\n🗓️ 2025.06.24 🗓️ 近期发现有些人在使用 Nekoray 的 Tun 模式时，会时不时出现 dns: exchange failed for xxx. IN A: Post \u0026quot;xxx\u0026quot;: xxx 之类的报错，以至于节点不定时断流，但是该问题似乎没有 100% 能解决的方法（有些人通过更改 DNS，调整 DNS 查询策略，重置网络，重装系统等方式解决了，但是有些人照做之后问题依旧）。如果你也出现了同样的问题且找不出原因（注意，如果节点确实掉线了也会出现类似的报错），那么可以参考以下两个曲线救国的方式，一是不要使用 Tun（不一定能解决。有些人不用 Tun 之后虽不会产生前面的报错了，但是产生了另一种报错），二是直接更换代理软件（但是其他代理软件也可能出现该问题，尤其是同为 sing-box 内核的代理软件。因此，更换时，尽量选择其他内核的代理软件）。此通知将于 9.1 移至正文中。 🗓️ 2025.07.12 🗓️ 山水云 的用户请注意，该机场在没有任何通知的情况下，已悄悄将所有节点由原先的 1 倍率更改为 2 倍率，等同于将所有用户的流量减半。这种做法在我看来是很恶劣的，尽管近期的通报确实会增加机场的成本，但我认为这不能成为借口。如果是直接给套餐涨价，能接受的用户就续费，不能接受的就不再续费，这种对原先用户没有影响的做法我认为还情有可原。因此，不再推荐该机场（即使后续回调，也不再推荐），此通知以及该机场的链接将于 8.15 删除。 🗓️ 2025.07.19 🗓️ 喵喵云 已暂时关闭注册，已注册的用户不受影响。现在的形势下，关闭注册能一定程度上防止节点信息被泄漏以至于被通报，但是没有新用户流入同样会增大机场的运营压力，因此使用这种应对方式的机场不多。此通知将于机场恢复注册后删除。 🗓️ 2025.07.26 🗓️ iNets 的用户请注意，该机场近期上线了极少量 AnyTLS 协议的节点（目前为 2 个），不过，该协议非常新，因此，支持该协议的代理软件还不多（不过，对于绝大部分代理软件来说，即使订阅中存在本身不支持的协议，也不影响使用。但是，部分版本过于老旧的代理软件，会因为订阅中存在本身不支持的协议，导致完全无法导入）。感兴趣的用户可使用支持该协议的代理软件体验。Windows，Mac 以及 Linux 用户可使用 Clash Verge Rev（版本不可低于此链接的版本，即 v2.2.2），Android 用户可使用 NekoBox（版本不可低于此链接的版本，即 v1.3.5。注意，PC 端的 Nekoray 即使是最新版本也不支持该协议），iOS 可使用 Shadowrocket（版本不可低于 v2.2.64）。还有其他代理软件也支持该协议，就不都列举了，感兴趣的自行查阅资料。考虑到该机场目前只有极少量节点使用该协议且该协议在机场里的普及度还很低，因此，我暂不会像 Vless 和 Hysteria2 协议一样专门做标识，只在此处单独说明。此通知将长期保留。 📢 次要通知：此部分主要用于存放“相对不太重要”但又需要“长期保留”的通知，以减少其对重要内容的干扰。\n🗓️ 2023.11.02 🗓️ Clash for Windows 已停止更新，原因未知，但不影响使用。若实在有顾虑，可更换其他代理软件。注意，Clash for Windows 与 Clash Core 是两个完全不同的东西，也就是说，它停止更新不影响 Clash 的任何分支。不过，如果后者停止更新，将会使得前者的更新变得毫无意义。可以将前者想象为人的衣物，而后者为人的躯体。衣物对于躯体的活动毫无影响，但若躯体停止活动，那么更换衣物也就变得毫无意义。🗓️ 2023.11.03 🗓️ Clash Premium Core，Clash.Meta Core，Clash for Android，Clash Meta for Android，Clash Verge，Tuic，Helloworld 路由器插件，Gui.for.Clash，homeproxy，Fclash，ClashX 也纷纷停止更新或删库，部分进行了存档。想要备份各种 Clash 的人可自行寻找资源或是 点击此处前往下载（注意：链接中的资源非本人整理，不一定全面也不一定可用）。另外，忠心劝诫各位不要在墙内的任何地方谈论任何与翻墙相关的事情，无论是为了自身安全还是为了代理工具的安全。近期本来只是 Clash for Windows 删库，结果被一些看热闹不嫌事情大的人把相关话题带上微博热搜，此后一堆 Core，GUI 删库，造成这一局面，可以说是那些人带节奏所引起的一系列连锁反应。至于目前这些代理软件还能不能用呢，答案是能。只有到了这些代理工具或是内核被发现有严重漏洞那一天，或是当前主流协议都被新协议所替代时，才不可以使用。然而，对此丝毫可以不用感到惊慌，代理工具以及内核千千万万，除了 Clash 还有 V2ray 等，并且旧事物的褪去总会有新事物来代替，互联网的更新是日新月异的，这点我相信各位很清楚。总之，请勿在墙内大谈特谈相关事件。🗓️ 2025.05.01 🗓️ 不知不觉，Clash for Windows 删库事件已过去一年半了，这期间时不时就有人爆出各种漏洞，从安全角度考虑，强烈不建议大家继续使用这类没人维护的代理软件了，包括 Clash Verge 等（注意：Clash Verge 和 Clash Verge Rev 不是同一个软件，后者目前仍在保持更新）。顺带一提，PC 代理软件 Nekoray 的作者在前段时间表示由于精力有限，不再维护该软件了，已将该项目归档。只会继续维护安卓端的 NekoBox。不过作者也表示，如果 Nekoray 存在重大 BUG，也可能会继续维护。 🗓️ 2024.10.10 🗓️ 近几天在网上发现有些人的 GitHub 账号莫名被封禁，因此我为本仓库简易地做了个“备份”。如若你喜欢本仓库且不希望与本仓库失联，那么可以在浏览器的收藏夹里为 此站点 腾出个迷你小单间。 🗓️ 2024.12.18 🗓️ 为尽可能保证本项目具有较高的时效性，机场列表可能会有很长时间不再“新增”，即使我新发掘到了好用的机场，也暂时不会放到推荐列表中。我希望把更多精力用在观测现有机场的运营状态上，而不是寻找更多机场。毕竟我推荐“多个”机场的本意是分散风险，防止某家机场跑路而有太多人同时受伤。但“太多”必然导致我难以在第一时间获知各机场的情况，那当机场存有跑路风险或其他问题时我将无法及时通知大家，即“时效性差”，这就本末倒置了。经过长时间的实践并结合自身的精力，我认为把数量控制在 10 ~ 15 是比较合适的，最多不超过 20，这样既能控制风险，又能兼顾时效性。 ⚡⚡⚡⚡ 机场不适合用来打游戏！需求主要在打游戏（尤其是 FPS 游戏）的人建议绕道寻找专门的游戏加速器，机场是很难满足这一需求的。原因与速度无关，换言之，不是说机场速度快就能用来打游戏，只有对游戏的线路作了专门的优化才适合，然而这不是机场的“责任”，这是加速器的“责任”。⚡⚡⚡⚡\n⚡⚡⚡⚡ 绝大部分机场都有审计，但是这种审计对于绝大部分人是没有影响的，通常只会屏蔽极端内容，例如“轮子”（此“轮子”与程序员口中“造轮子”的“轮子”不是同一个东西），若有这类特殊需求，那么本文显然也不适合你。⚡⚡⚡⚡\n⚡⚡⚡⚡ 本文中所推荐的机场都是我自己觉得值得推荐的机场，不接受机场主的主动“投稿”，也不接受机场主以任何理由要我将某个机场作为“首推”，更不会以任何形式联系机场主寻求任何方面的合作（如收费推广）。如有机场主看到有人以本文作者的名义主动联系，皆为冒充，请注意甄别，不要上当受骗！⚡⚡⚡⚡\n📝 首先，说一下，作为 Panda VPN Pro 的受害者之一，我为什么会创建此项目来推荐低价机场。原因大致如下：在使用机场之前，我一直用的是各种 VPN。最开始用的 VPN 都是免费的，免费的优点除了免费什么都没有了，稳定性完全没有任何保证，几年前倒是还可以，近两年来免费 VPN 基本都不太行了。当然，比起稳定性的不足，使用免费产品最大的危害在于泄露个人隐私等安全问题。虽然本人科学上网的需求不高，但是又需要频繁使用 Google 查阅各种资料，文档之类的。然而，非移动端的免费 VPN 实在太少了，即使有，稳定性也不行，我用过许多插件以及客户端，稳定性实在是差得不行，并且很快就不能用了，使用起来也是相当不方便。于是乎，为了稳定性以及种种原因，我决定使用付费 VPN。首选便是 熊猫 VPN 了（Panda VPN Pro）。选择它的原因是我认为它不算贵，400 多块钱两年，并且，从几年前就经常看到了他的广告，他能运营这么多年给我产生了“不会跑路”的假象（事实上，在此之前，我对跑路是一点不了解的，或者说，我根本不知道这类厂商会跑路）。使用了几个月，非常舒适，几乎一直很稳定。然而，在去年（2022 年）11 月中旬左右就开始有人反馈说不好用，用不了，当时的我并没有感受到有任何变差的体验， 便置之不理。接着，到了 11 月底，彻底用不了了，当时以为是由于某些大事导致，过段时间应该就好。一等就是一个月，依然没有恢复。我便认为它是跑路了，非常心疼，好几百块几乎打了水漂 💔。本以为花钱就能买到省心，结果发现不行，或许是因为贪了便宜买了熊猫。可是又想不了那么多，长达一个月几乎不能稳定上 Google 对我的影响非常大，于是乎转向另一个比较火的 VPN，那就是 快连VPN。它的价格就比熊猫贵了不少了（青铜会员一年接近 300 块，铂金会员一年接近 400 块），可是由于刚需，所以我就先买了一个月青铜试试看。体验只能说还行，但是几乎比不过熊猫，熊猫能使用三个设备，快连只有两个（即使是铂金会员也是两个设备）。节点部分就更不用说了，快连的青铜套餐只能使用香港节点且无法开全局，而熊猫节点非常多，模式多，电脑客户端还能自定义白名单黑名单。不过很可惜，体验那么好的熊猫结果跑路了，现在甚至连 GitHub 的项目都关了（但是截至 2023.02 官网还开着赚黑钱！😠）。虽然快连的体验各方各面都比不过熊猫，但作为一个翻墙工具的基本素质还是有的（稳定性和速度都还行）。但是呢，我又发现了很多人莫名其妙被封号了，或许是流量用太多的缘故。具体什么原因不清楚，但反正会有给封号的风险就很令人窒息，再加上价格那么贵，我实在很难续费。另外，在使用快连期间，还接触了 小牛加速器，这个加速器刚开始是免费的，体验中规中矩。后来收费了，价格非常高，比快连还贵，我也就没再继续使用了，据说，收费之后的体验还不如免费那会好用。因此，用了快连一个月后我就转向使用机场并对机场以及 GFW 进行了一些深入研究。现在，我希望通过分享我所使用的机场来帮助更多人脱离使用传统 VPN 的坑 🚁。\n😭 对于熊猫跑路我最大的教训就是：这类价格几百块的东西不要随意充年费（富哥随意）。\n🧐 浅谈一下关于机场与 VPN 的区别。由于这两者都可以翻墙，再加上使用了机场之后，手机状态栏显示的依然是 VPN 的字样，所以很多人会把它们混为一谈，然而，这两者并不相同。不过，可以把它们统称为“科学上网工具”，或者是“梯子”。VPN 产生的年代还没有 GFW 的存在，它的作用主要是为了加密通讯（匿名通迅），而机场诞生于 GFW 的建立之后，专门用于科学上网。VPN 与机场都能对数据进行加密，但是，VPN 纯粹是为了加密而加密，它并不专门用于绕过 GFW 的探测，而机场的加密则是专门为了绕过 GFW 的探测。这也正是 VPN 近几年来越来越不行了的原因，因为它的流量特征早已被 GFW 掌握，你的上网流量在经过 VPN 的代理之后，虽然 GFW 可能无法完全知道其中的内容，但是，它一定能够知道你这上网流量是“有问题的”，所以很容易给“干掉”，即使是像 Express VPN 这种价格极高的国外知名 VPN，翻墙效果也是不理想的，当然，不是说 GFW 知道了你的流量异常就一定会截断你的通信，这要看 GFW 的心情（高度）。因此，哪怕你认为我所推荐的低价机场不行，我也不推荐你使用 Express VPN，Nord VPN 这类高价 VPN，VPN 的受众群体是需要保护隐私的人（尤其是外国人），这也正是那些居住在没有 GFW 的国家的人需要使用 VPN 的原因之一。当然，最关键的一点是，这类真正 VPN 并不是用于翻墙的，翻墙效果极差。同样的价格，高价机场绝对比高价 VPN 的翻墙效果好。事实上，绝大部分在国内有效的 VPN 其实都是套壳机场节点，本质上就是机场。但是，这些厂商使用的基本的都是廉价的机器，然后，卖出高昂的价格。所以我是强烈不建议使用 VPN，包括各种所谓的加速器也是同理。另外，还有一种 VPN 是用于在公网访问内网（内网穿透的实现方式之一），常见于高校或企业，这种是专门让你在非学校或非公司的网络环境下访问学校或公司的网络资源。VPN 与机场的区别可以简单理解为：VPN 与机场技术的实现所使用的协议不同，前者主要用于加密，后者主要用于翻墙。\n👍 以下机场都是我使用的价格较低的机场，基本都使用了好几个月，总体算稳定。不过，虽然价格低，但也不建议买多，两三个足矣（一个月付套餐搭配两个不限时套餐是最稳定的方案。一个月付套餐搭配一个不限时套餐是最具性价比且是我最推荐的方案）。买多首先你用不完，其次是因为任何机场都有可能跑路，所以备用也不是越多越好。任何机场都不建议按年购买（即使有优惠），按月购买即可，不限时套餐也不建议购买价格过高的，防止跑路时损失过大。任何价位的机场都有跑路的可能，即使是价格高的机场，因为跑路不一定是机场主的主观行为，也可能是由于不可抗力的原因，毕竟，这个行业终究属于灰产。因此，我才会再三建议按月购买，按月购买好处多多，唯一的缺点就是需要每个月都去续费，稍微有一点点麻烦。具体购买什么机场什么套餐请各位依据自己的需求以及预算考虑清楚。\n👇 机场购前须知：\n排名：仅代表机场创建日期（开业日期）先后，不表示体验好坏。 协议：目前大部分机场所使用的协议有 Shadowsocks，Trojan，VMess，这三种常用协议在主流的代理软件上都可得到支持，所以，使用了常用协议的机场我不作标识。而 Vless 和 Hysteria2 这两种新兴协议则只有少量的代理软件支持。对于中转机场来说，目前最好用的协议依然是 Shadowsocks，几乎所有中转机场都是使用的此协议。至于直连机场，由于线路结构的原因，使用此协议会很快被墙，所以几乎所有直连机场都不使用此协议。Shadowsocks 协议之外的其他协议，都是直连机场常用的协议，包括 Vless 和 Hysteria2，这两个新协议被墙的几率从一定程度上也会低于 Trojan 和 VMess，所以现在这两种协议确实已逐渐成为直连机场的主流协议了，因为 GFW 对于新协议流量特征的掌握程度肯定少于另外两者，但这其实也只是从理论层面上分析，并非说明新协议 100% 优于旧协议。不过，就我个人体验而言，这两种协议在直连机场的表现的确比旧协议好。若需使用到这两种新协议，Windows 和 Mac 系统可使用 Clash Verge（版本不可低于此链接的版本，即 v1.3.8，否则将只能使用 Vless，而无法使用 Hyteria2。且要将内核切换为 Meta 内核。）（2024.8.11 补充：现在更推荐使用 Clash Verge Rev 等其他软件，因为 Clash Verge 已经不再维护更新了），Android 系统可使用 Clash Meta for Android（版本不可低于此链接的版本，即 v2.9.0， 否则将只能使用 Vless，而无法使用 Hysteria2），iOS 系统可使用 Shadowrocket（版本不可低于 v2.2.35，否则的话将只能使用 Vless，而无法使用 Hysteria2。若是低于 v2.2.30，则连 Vless 也不支持）。当然，还有其他代理软件也支持这两种协议，此处就不一一列举了，感兴趣的自行查阅资料（Vless 协议大都会搭配 Reality 协议使用。Reality 也是一种较新的协议，不过一般支持 Vless 协议的代理软件都会支持 Reality 协议，所以通常查清楚代理软件是否支持 Vless 就可以了）。针对这部分使用了新兴协议的机场，我在机场官网后面加上了相关标识。标识含义如下： V：表示该机场大部分节点都为常用协议，极少部分节点使用了 Vless 协议。 H：表示该机场大部分节点都为常用协议，极少部分节点使用了 Hysteria2 协议。 VH：表示该机场大部分节点都为常用协议，极少部分节点使用了 Vless 或 Hysteria2 协议。 #V：表示该机场大部分的节点为 Vless 协议。 #H：表示该机场大部分的节点为 Hysteria2 协议。 #VH：表示该机场大部分的节点为 Vless 或 Hysteria2 协议。 *V：表示该机场所有的节点都为 Vless 协议。 *H：表示该机场所有的节点都为 Hysteria2 协议。 *VH：表示该机场所有的节点都为 Vless 或 Hysteria2 协议。 类型：描述了机场的主要线路类型是直连还是中转（带 + 的直连是经过特殊优化的直连机场，价格与体验基本无异于中转机场）。 在选购机场时，按自己预算选即可，没必要刻意追求专线，因为专线的性价比太低。确认自己需要的是直连（价格较低，流量充足，稳定性一般）还是中转（价格中等，流量适中，稳定性较好）即可。不过，直连机场有些时候反而会比中转机场“稳定”，比如国内入口被大面积通报时。 本文有部分中转机场提供了少量专线节点，但我没有在节点类型中多作说明，因为低价机场所提供的专线节点倍率一般都较高。如果专线节点倍率低，那机场本身价格不会低。因此，我不建议刻意追求专线机场（2025.07.22 补充：本文部分机场由于种种原因已全面升级为专线机场。不过，我依然不对专线机场作特别标注。一是因为所谓专线机场本质其实就是线路更优质的中转机场。二是因为“专线”这个词容易给人一种特别高大上的感觉，以至于冲动消费购买了远超自己原本预算的机场。另外，由于本文主推的是性价比高的机场，因此，如果机场升级后，价格变得过于高，或者我觉得它不值那个价，我将会发出通知并移除相应机场的链接）。 若你真有使用专线的需求，请直接去专门推荐高端机场的文章寻找。高端的专线机场的价格一般不会低于 30 ￥ / 月 / 100 GB，有一些可能折算下来每月 100 GB 只需要 20 ￥，但是这类机场往往“门槛高”，比如至少得按年支付或者每月至少得购买 300 GB。总之，这类机场在我看来性价比太低了，所以我不会刻意对专线机场做推荐。而 10 ￥ / 月 / 100 GB 的中端机场在我看来是性价比较高且更符合多数人需求的，所以我推荐的机场基本都在这个价位。购买这种中低价位的机场还有一种好处，那就是当它卡的时候，你会比较能接受。举个大家比较能感同身受的例子：2000 块钱的手机在使用过程出现卡顿，这是多数人预料之内的事情，所以会觉得“很正常”，不会怎么生气。但如果是 6000 块钱的手机出现了卡顿，估计没多少人会不生气的。虽说一分钱一分货，但也不要对贵的机场抱有过高的期待值，也不要觉得越贵就一定越好。贵的手机会卡，贵的机场同样也会卡。因此，对大多数人而言，是没必要买高价机场的。即使有些人花高价只是图个省心，然而贵的也不一定能省心。与其买贵的机场，还不如把多出来的钱用在升级自家宽带或路由器这些实实在在能提升整体上网体验的地方。 注意，新疆地区具有特殊性，该地区大概率无法使用中转机场，只建议购买直连机场或直连+机场。河南，福建，江苏这几个地区也比较特殊，优先考虑中转机场。如果身处非大陆地区（如港澳台），想通过使用机场来更改 IP，那么只建议直连或直连+机场，因为大部分中转机场不支持非大陆地区使用。 倍率：表示机场节点的 普遍倍率 或是 最低倍率 \u0026amp; 普遍倍率。3 表示该机场节点的普遍倍率为 3 倍（没有低于该倍率的节点），0.3 \u0026amp; 4 表示该机场节点的普遍倍率为 4 倍（含有少量 0.3 倍率的低倍率节点）。 机场中节点的“倍率”指的是“机场流量的消耗速度”（如 A 节点的倍率为 0.5 倍，那么当你使用它下载一个大小为 100 MB 的视频时，就会耗费 100 * 0.5 = 50 MB 的机场流量）。节点倍率跟节点的速度与延迟没有直接关系。同一机场中，高倍率节点的成本一定比低倍率节点的成本高，因此，高倍率节点的体验通常也比低倍率节点好，但这非绝对。所以，在使用过程中，优先考虑低倍率节点或者 1 倍率节点，能省则省，除非这些节点的体验确实不佳或是你的流量非常富余，又或是你有其他需求等情况再考虑用高倍率节点。 同一家机场中，节点的倍率如果不是统一的，节点的名称一般会有相应的备注（如：Singapore x3，Hong Kong x1），但是也不全都如此，如果发现节点名称没有标注倍率，建议在官网的“节点状态”或“我的订阅”（不同机场的叫法不尽相同，也有可能是其他叫法）中查看一下，避免不小心使用到高倍率节点而造成不必要的浪费。 最低倍率：指的是该机场所提供的节点中，最低的倍率。大部分机场的大部分节点都为 1，少部分节点会提供低于 1 倍率节点，这类节点在我看来，最大的作用就是用于下载大文件，但不是每一家机场都会提供低倍率节点，即使有，个数一般也不会超过 5 个。 普遍倍率：指的是该机场中大部分节点的倍率。 特殊情况 1：部分中转机场会提供少量低倍率直连节点，但是为了防止让你们误以为是中转节点的倍率，所以我在 最低倍率 所标注的数字会以 类型 所对应的节点为准。例如，A 机场的主要节点类型为中转，中转节点的 最低倍率 为 1，普遍倍率 为 2，然后提供了一些 0.5 倍率的直连节点。那么我会给它标记为 1 \u0026amp; 2，而非 0.5 \u0026amp; 2。 特殊情况 2 ：极少部分机场的倍率分布比较混乱，那么 普遍倍率 就不容易标出来。这种情况下，我会将 常用地区 的倍率作为 普遍倍率。不过 常用地区 是没有明确定义的，我对它的判定范围：香港，日本，新加坡。因为使用这几个地区的人数往往是最多的（这些地区由于与中国距离较近，延迟相对较低，所以多数人会首选这些地区的节点），因此，机场主在这些地区的投入成本往往是最大的。也就说，在这类倍率分布较混乱的机场中，这些地区会属于倍率偏高的，因此将这些地区作为 普遍倍率 是具有较好的参考性的，这样能避免你们购买机场后，觉得“流量虚标”。例如，A 机场将一些没什么人用的地区的节点设置为 0.5，1，1.5，而港日新的倍率为 3，那我会给它标记为 0.5 \u0026amp; 3。 再次强调：购买两三个机场足矣，不要贪多，且不要年付（即使有活动也不建议年付）。 开业日期 机场官网 类型 倍率 月付套餐 不限时套餐 试用 优惠券 2019.03.17 SAC 中转 1 \u0026amp; 1.3 9.99 / 100 GB 199.99 / 1000 GB Null Null 2019.08.15 壹速云 中转 1 10.90 / 150 GB 39.00 / 200 GB Null Null 2020.04.22 次元雲 中转 1 10.00 / 128 GB 85.00 / 500 GB Null Null 2022.11.06 赔钱机场 *VH 直连 0.01 \u0026amp; 1 2.99 / 500 GB 18.90 / 1000 GB Null Null 2022.12.07 一分机场 *VH 直连 0.1 \u0026amp; 1 2.00 / 100 GB 19.88 / 1000 GB Null Null 2023.02.03 自由猫 中转 1 9.00 / 100 GB 50.00 / 500 GB Null 8 折 FREECAT 所有套餐可用 长期有效 2023.02.09 极速云 中转 8 15.99 / 1200 GB 88.00 / 1000 GB Null Null 2023.05.01 农夫山泉 #V 中转 1 8.00 / 200 GB 15.00 / 200 GB Null Null 2023.07.01 蜂窝云 中转 1 20.00 / 188 GB 40.00 / 210 GB Null 9 折 FW9 所有套餐可用 长期有效 2023.09.01 Metcha 中转 1 9.88 / 128 GB 128.88 / 1024 GB Null Null 2023.09.12 M78星云 中转 1 7.80 / 80 GB 88.00 / 400 GB Null Null 2023.09.23 云安云 中转 1 7.00 / 120 GB 25.00 / 118 GB Null 88 折 yay88yay 大部分套餐可用 8 折 yay80yay 两年以上套餐可用 长期有效 2024.03.01 兔兔云 #V 中转 1 11.88 / 140 GB 18.00 / 60 GB 12 hours Null 2024.06.14 山水云 中转 2 14.99 / 100 GB 99.00 / 100 GB Null Null 2024.08.14 喵喵云 中转 0.5 \u0026amp; 1 7.50 / 50 GB 25.00 / 100 GB Null 8 折 NYA2025 所有套餐可用 长期有效 2025.03.14 iNetS *V 直连 + 0.7 \u0026amp; 1 4.90 / 50 GB Null 7 days 极少节点 Null 👀 以上所列举的套餐都属于机场中最低价格或者是我觉得比较实惠的，点击上方链接可以进入各家官网（部分机场官网可能处于被墙的状态，若是进不去可将代理工具切换到全局代理模式。去广告的浏览器插件也可能导致无法访问官网或官网加载缓慢，建议将机场官网加入这类插件的白名单中）查看更多套餐。套餐的价格偶尔会发生变动，我如果知道了就会进行相应的更新，不一定会及时，但每个月至少会更新一次，具体以官网为主（注意，由于机场一般都有对接第三方支付以防止因账户风控而导致用户无法付款等一系列问题，所以在支付时会产生一定的手续费，即实际付款的费用会稍高于套餐的“标价”）。“试用”是我自己注册账号时的情况，这部分完全不具有时效性，因为我不可能定期为每个机场注册新账号，请见谅。不过，如果机场跑路，我是肯定会第一时间发通知进行提醒的。另外，初次使用机场的小伙伴可能会发现各家机场官网的界面都很相似，请不要误以为全是同一个老板开的，这是很正常的，因为机场的页面基本都是用了相同的开源项目，比如 v2board。因此，机场界面的美观与否，显然与机场质量的好坏也是没有任何关系的。\n💡 有些机场的官网需要在浏览器的“语言”为中文的条件下才能访问，其特点就是在访问时，如果浏览器的语言是英文，会出现 Error 403 当前请求已被禁止访问 相关的字样，解决方式就是将浏览器的语言设置为中文。而如果你遇到了这种情况，且非要将浏览器设置为其他语言，那可以借助修改 HTTP 请求头的浏览器插件，将 Accept-Language 的值修改为 zh-CN，这样就能实现在不修改浏览器语言的情况下访问相应机场的官网了。\n🚪 下表是上述中转机场的国内入口信息（直连机场没有国内入口，所以表中不包含直连机场）。理论上，选择跟自己运营商相同以及地区相近的入口能够获得最优质的体验。但是实际上并非如此，“同地区同运营商”的体验不一定就比“不同地区不同运营商”差，而且机场入口可能会经常变动，所以这个东西的参考意义其实也不是太大。不过个人建议还是尽可能选择入口有自己运营商的机场。\n机场 入口运营商及地区 SAC 移动：广东广州 壹速云 移动：广东广州，四川遂宁 次元云 电信：海南海口 移动：广东深圳，江苏徐州 自由猫 联通：江苏宿迁 移动：广东深圳，广东佛山 极速云 电信：广东广州，广东深圳 联通：广东广州，广东深圳 移动：广东广州，广东深圳，广东佛山 农夫山泉 电信：广东广州 移动：广东深圳，广东揭阳 蜂窝云 电信：广东东莞 Metcha 电信：广东广州 联通：广东广州 移动：广东深圳，广东江门，上海 M78星云 电信：广东深圳 联通：广东深圳 移动：广东深圳，广东广州，湖北武汉 云安云 电信：江苏南通 联通：山东青岛 移动：广东深圳 兔兔云 电信：云南昆明 移动：广东广州 山水云 移动：广东佛山 喵喵云 电信：广东广州 移动：广东广州，广东深圳 🙁 市面上几乎所有的机场都不支持同时拥有两个及以上的套餐。如果在同一个机场想购买多个套餐，需要另外注册新的账号，否则，旧套餐将被新套餐“覆盖”。如果不明白“覆盖”的意思，那么可以看一下这个例子：假如我购买了 A 套餐，然后我在 A 套餐有效期内又购买了 B 套餐，那么此时 A 就会被 B 所覆盖，即我现在只拥有 B 套餐。另外，还有部分机场支持“以旧换新”，即在购买新套餐时，会先将原先套餐折算为相应价格，然后进行一个抵消。这类机场有些是自动完成这项操作的，而有些则需要手动提交工单进行相关的咨询。\n😟 购买了机场套餐后，有时会由于网络波动或者支付接口出现某些问题而导致“掉单”（购买了套餐，但是没有生效或者依然显示未付款），此时不必担心也不需要重新下单（注意，不要取消订单，否则可能会导致无法恢复，除非机场人员提示需要先取消订单），“发起工单”（此功能通常位于机场官网导航栏的“我的工单”中）联系机场管理人员即可解决问题。特别提醒一下，大部分机场的工单系统比较简陋，不支持直接发送图片，而如果恰巧需要发送图片，那么可以借助图床，如：Imgur。\n🤔 重置流量与套餐续费的区别：重置流量指的是将当前套餐的已用流量清零，流量有效期保持不变。套餐续费则是顺延套餐有效期，对于已用流量没有任何影响，流量需要等到流量重置日（大部分机场的重置日为次月的购买日，少部分机场的重置日为月初）才会重置。不过，有少部分机场会在续费时顺便重置流量。以多数机场的情况举例：假如你在 2023.10.11 在购买了一个月的套餐，流量总数为 100 GB，然后你在 10.20 就把流量用完了，此时如果重置流量，那么你的剩余流量就会恢复为 100 GB，套餐依然会在 2023.11.11 过期。而如果是给套餐续费一个月，那么你的套餐会变为在 2023.12.11 过期，但是剩余流量依然为 0 GB，需要等到流量重置日（2023.11.11）时剩余流量才会恢复为 100 GB。另外，机场的流量不同于手机卡的流量，即使当月没用完，也不会叠加到下个月。\n🛠️ 关于代理工具的选择：市面上的代理工具（软件）数不胜数，以下是常用的代理软件。没有最好的，只有最适合自己的。不过，像是 SS（Shadowsocks）或是其衍生的 SSR（ShadowscoksR） 客户端，俗称酸酸（乳），粉色小飞机，这类早已被淘汰的客户端就不要继续使用了，这类老古董不管是从性能，兼容性还是安全性来说，都很差劲。（此处是不建议使用 SS 客户端，不是不建议使用 SS 协议，因为 SS 协议对于中转及专线机场来说依然是目前最好的协议。强调这一点是因为最近看过部分文章仍然在推荐 SS 客户端，甚至宣称是 iOS 中使用最多的客户端。我不知道这类文章的作者是水平不足还是居心叵测，但总之是在误导群众。近几年 iOS 端使用最多的客户端是 Shodowrocket，俗称小火箭，注意，不要混淆 shadowrocket 和 shadowsocks。当然了，使用最多不代表是最好的，但是足够满足大多数人的需求这点是肯定的，小火箭最大的优势在于其支持几乎所有的协议。iOS 端目前主流的代理客户端大致可参见下表）。在选择过程重点关注自己的实际体验，以及软件所支持的协议。以 Clash （注意：Clash 系的所有分支几乎于 2023.11.03 停止更新，但目前尚不影响使用。若实在有顾虑，可选择其他其他核心的代理软件）为例，其具有许多分支，例如在 Windows 中具有 Clash for Windows 和 Clash Verge 等分支。界面方面，两者差异不大，但是后者自定义程度高些。内核方面，前者只支持 Clash Premium 内核，后者则支持 Clash Premium 内核和 Clash Meta 内核，后者多内核所带来的最直观的好处就是支持更多的协议（如 Vless），但不代表后者一定就更好，因为后者相对较新，功能不是很完善，BUG 相对也较多，而且，Vless 这种不常见的协议多数机场都不使用（常用的协议有 Shadowsocks，Trojan，VMESS），只有少部分机场会在提供常用协议的节点的基础之上，再提供少量 Vless 这类不常用协议的节点（Vless 在目前阶段不在常用协议的队列之内）。（2024.03.18 补充：随着时间的推移，Vless 和 Hysteria2 这种曾经的非主流协议已经慢慢变成直连机场的主流协议，所以个人强烈不建议再继续使用 Clash for Windows 这个客户端了。当然，如果你只使用中转机场，且喜欢这个客户端，那么继续使用也无妨）。个人建议安装两款代理软件，其中一个作为备用，多了就没必要了。另外，代理软件上所测出来的数字通常代表的是延迟（部分代理软件不仅可以测试延迟，还可以测试速度。注意，延迟 ≠ 速度）。对于测试结果不必过于较真，因为不同软件的测试方法是不同的，显示结果自然也不同，那么也就几乎没有任何参考价值。而且，有些机场会利用 DNS 劫持等方法，使得延迟看着很低，然而那并不是实际的延迟（例如，受限于地理距离，美国节点的延迟是 100% 不可能低于 100ms 的，如果低于这个数值，那必然不是真延迟）。所以，延迟的高低，应该以实际体感为主。友情提示：如果喜欢低延迟，那么尽可能选择亚洲地区的节点（如港日新）。关于延迟，再补充一下：\nShadowrocket 旧版本的延迟默认测试方法是 TCP，它测试的仅是本机与节点的 TCP 握手延迟，参考意义低（尤其是当节点为中转节点时，它测试的只是本机到国内入口的延迟，因此，在这种测试方法下，甚至能测出个位数的延迟，显然没有任何参考价值。可用性的参考意义也低，这种模式下即使节点“绿了”，也只是代表你能连上这个节点，不代表这个节点能用）。建议手动将 延迟测试方法 指定为 CONNECT，它测试的是节点与测试链接的延迟，参考意义相对较高。ICMP 也不建议使用，它通了也只能说明你能连上节点，不代表节点能用。并且，它比 TCP 还不可靠，TCP 测的是本机与目标主机的指定端口的连通性，而 ICMP 测的仅是当前主机与目标主机的连通性。但是有些主机会屏蔽 ICMP 协议（禁用该协议在一定程度上能减少攻击。这就好比你在枪击游戏里使用了防弹头盔，这样就能减弱你头部所受的伤害），以至于节点能用，使用 ICMP 方法时却 Ping 不通。顺便一提，日常生活中所说的 Ping（使用命令：ping www.baidu.com）正是用的 ICMP 协议，而 114.114.114.114 这个 DNS 是禁用了 ICMP 协议的，因此，当你去 Ping 这个 DNS 时会发现是无法 Ping 通的，然而并不影响你使用这个 DNS。其实也不一定是它禁用了这个协议才导致无法 Ping 通，也可能是 ICMP 数据包被运营商阻断或是被网络路径上的某个中间设备丢弃等原因。毕竟，还是有少部分地区能 Ping 通它的，这至少能证明它有些服务器是没有禁用这个协议的。不过这不重要，关键在于利用 ICMP 测试某项服务的可用性是很容易造成误判的，所以不建议使用它。 NekoBox（v1.3.2 之前的版本）和 Nekoray（v4.0.0 之前的版本）的延迟测试链接建议使用含 true 的写法，如 truehttp://www.gstatic.com/generate_204，此时如果使用 Url Test，会发起 TCP + TLS + HTTP 请求，不带 true 也是类似的，区别在于前者不会等待完整的 HTTP 响应，而后者会完全等待其响应结束。因此，使用不带 true 的链接在进行测试时，测试的数值会更大，且耗时也更长，个人建议使用带 true 的链接进行测试即可（上述版本之后只支持不含 true 的写法了。但实际效果等同于原先带 true 的效果。可以理解为软件会自动在的测试链接前添加 true。切记不要手动添加 true，否则会无法使用）。小火箭的 CONNECT 就类似于此处带 true 的测试方法，它也不是完整的 HTTP 请求，只是请求了 HTTP HEAD。TCPing 方面，Neko 系列完全等同于小火箭的 TCP。至于 ICMP，Neko 没有这种测试方法。 其余代理软件请自行翻阅相关文档研究。再强调一下，延迟的高低应该以实际体验为主，不要依赖于代理软件的测试功能。代理软件检测结果再准确，也只是测试了单一 url，参考价值很低。 🔴 特别提醒一下：\nAndroid 代理软件 NekoBox 请不要在 Play Store 下载，因为谷歌商店里的版本是非开源的（作者本人失去了对该版本的控制）。若要使用该代理软件，请自行在 GitHub 进行搜索或直接 点击此链接 前往。然后，个人推荐使用 v1.2.9 的版本，因为新版本（截至 2024.10.07 的最新版本是 v1.3.1）或多或少都有一些 BUG，而 v1.2.9 的版本我使用至今都没出现过功能性 BUG，只是偶尔会一些 UI 层面的 BUG，但这并不影响使用。（2024.10.09 补充：官方发布了新版本 v1.3.2，但我暂无兴趣体验，v1.2.9 已能够满足我了，有兴趣的自行体验。此后再有新版本这里将不再提及，除非是出现了某些安全性漏洞之类的情况）。 iOS 代理软件 Shadowrocket 虽然俗称“小火箭”，但是请不要直接在 App Store 里面直接搜索“小火箭”，这样容易下载到盗版，它的盗版非常的多，搜索时请输入英文。然后，正版是需要收费的，不过网上有很多免费的账号，不想付费的话可自行寻找免费资源。或者直接使用免费的代理软件（如 Hiddify）。另外，再提醒一下，登录其他人的账号时，只需要在“应用商店”里登录，不要在“设置”里登录。再再提醒一下，Shadowrocket 只有 iOS 端，谷歌商店里面的各种所谓的小火箭也通通是盗版，请勿使用！ 操作系统 代理软件 Windows Clash for Windows，Clash Verge，Clash Verge Rev，Clash Nyanpasu，FlClash，V2ranN，Nekoray，sing-box，Hiddify，Qv2ray，Mihomo Party，Karing，Fly Clash，Clash Mi Mac Clash for Windows，ClashX，ClashX Pro，Clash Verge，Clash Verge Rev，Clash Nyanpasu，FlClash，V2rayU，sing-box，Stash，Surge，Quantumult X，Hiddify，Qv2ray，Streisand，Mihomo Party，Karing，Clash Mi Linux Clash for Windows，Clash Verge，Clash Verge Rev，Clash Nyanpasu，FlClash，Nekoray，sing-box，Hiddify，Qv2ray，Dae，Daed，Mihomo Party Android Clash for Android，Clash Meta for Android，FlClash，Surfboard，SagerNet，V2rayNG，NekoBox，sing-box，Matsuri，Hiddify，Karing，Fly Clash，Clash Mi iOS Shadowrocket，One Click，sing-box，Surge，Quantumult，Quantumult X，Loon，Hiddify，Egern，Potatso Lite，Choc，Foxray，Streisand，Karing，Clash Mi HarmonyOS NEXT ClashBox OpenWrt OpenClash，OpenWrt，SSRPlus，Passwall，Openwrt-Mihomo 💡 使用机场过程中，为保证及时获取到最新的节点，建议每次使用之前更新一下机场的订阅，或者也可以直接在代理软件中设置订阅的更新频率让其自动更新（部分代理软件没有这一功能，只能手动更新），如 6 小时自动更新一次，当然也可以设置其他频率。如果发现订阅无法更新，可以参考以下几种解决方法：\n注意，有些时候官网发生某些变动时会导致节点几乎或是完全不能用，此时更新订阅不一定有效，而需要手动重置订阅（其实这种情况一般进入官网重新复制订阅链接就好了，但稳妥起见，在复制链接前先重置一遍会更好。重置链接没有任何坏处，甚至有好处。比如你若曾在不知情的情况下把自己的订阅链接泄漏出去，你的流量就会别人盗用。而重置订阅链接之后，别人就用不了了），即下面的第 4 点。\n关闭代理后更新订阅。 连接任意机场任意一个可用节点后更新订阅。 连接任意机场任意一个可用节点且开启全局代理后更新订阅。 进入官网重置订阅链接（注意，是“重置订阅”，不是“重置流量”，不要混淆。前者免费，后者收费）。重置订阅链接的方法大致流程（不同面板操作不同，但是大同小异）：进入“个人中心” \u0026ndash;\u0026gt; 找到“重置订阅信息”那一栏 \u0026ndash;\u0026gt; 点击“重置”按钮 \u0026ndash;\u0026gt; 重新复制订阅地址到相关代理软件中。如果发现无法进入官网，那么可能是官网此时被同行“打”了，此处我不对“打”这一种低素质的同行竞争行为进行科普。总之，如果发现更新不了订阅且无法进入官网，那就等待一段时间后再更新订阅，这一种情况基本无解，此期间请更换其他机场。不过，官网进不去不一定是被“打”了，只不过这是最常见的原因。另一种常见的情况就是官网被墙了，这种情况一般将官网加入代理名单或者直接开启全局代理模式即可解决。另外，官网进不去时，可以尝试关掉代理进入，因为有些机场的官网使用代理时反而进不去（有些时候，还需要将系统语言以及浏览器语言都设置为中文才可以访问）。若是能进入官网，但是无法登录，这种情况可能和浏览器的缓存以及 Cookies 有关，可尝试清除这些东西。没有效果的话一般就不是自己的原因了，需等待机场主修复。 万能的重启大法（重启代理软件，重启电脑，甚至重启路由器）。 将代理软件升级到最新版本或更换其他代理软件。注意，平常使用过程中在没遇到问题时是不需要更新代理软件的（除非代理软件出现某种漏洞），代理软件在稳不在新。虽说不用追求最新版本，但也尽量不要使用版本过旧的代理软件。有些过旧的代理软件虽然能用，但不一定好用，比如可能造成节点频繁掉线。 💡 使用 Clash for Windows 过程中，如果出现了 Could not switch to this profile ! invalid dns enhanced-mode: redir-host 报错信息，那么就右键相应的机场配置文件，点击 Diff，在弹出的提示框中点击 Init diff files，之后找到 enhanced-mode 字段，将其后面的值从 redir-host 修改为 fake-ip，修改之后保存文件，即可解决问题，并且之后更新订阅后不需要重新执行此步骤。如果一开始选择的不是 Diff，而是 Edit，那么每次更新订阅后都需要重新编写配置文件，十分繁琐。其他报错信息或是其他软件的各种错误信息请自行上网查阅资料，此处只是列举了一个很常见的错误及其解决方案。\n💡 DNS 的设置有时候会产生各种奇奇怪怪的问题，比如分流异常（Youtube 能够正常访问，而 Google 却访问不了），或是节点明明能 Ping 通，却死活用不了，再或者，节点时不时断流。诸如此类的问题，在经过各种排查都无法解决，而更换代理软件之后，这些毛病都不复存在。那就可能是 DNS 的问题。这时可以尝试在代理软件中修改远程 DNS 的“类型”。比如，你原先使用的是 8.8.8.8 这种 IP 类型的 DNS，那么就改为 https://dns.google/dns-query 这种域名类型的 DNS（它的专业术语叫做 DoH，DNS over HTTPS）。若是修改远程 DNS 后问题依旧，那么可以尝试更改本地 DNS。在修改时，一次只建议修改一项，不要同时修改，也就是控制变量法，这样有助于确定问题的根源。此链接 包含了许多国内外的公共 DNS 可供选择。\n💡 DNS 缓存偶尔也会产生各种问题（我自己大概遇到了两三次因 DNS 缓存导致节点无法使用以及节点延迟变得异常高的情况）。清除 DNS 缓存可以参考以下方法：\n手机：打开“飞行模式”，然后关闭它。 Windows：“以管理员身份运行”命令提示符，然后执行 ipconfig /flushdns 命令。 Mac：在终端中使用 sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder 命令。 🌐 直连机场受本地网络的影响较大，中转机场受本地网络的影响适中，专线机场则几乎不受本地网络的影响。所以对于以上各家机场的实际体验，在不同的网络环境下（地区，网络运营商，路由器，手机，电脑等）的体验效果是不尽相同的，我也就不对这些机场作出所谓的“体验排名”，而测速或是测延迟之类的也是没什么必要，这些测试都没有什么真正的参考价值。不是说测这些东西完全没用，只是说它参考价值不大。对于专线机场的参考价值会相对大一些（仅仅只是相对而言），但是对于直连或中转机场来说是完全没必要看的。原因前面说过了，直连或中转都会受到本地网络的影响。别人觉得好用你不一定觉得好用，反过来同理（那些测速图就可以看作是“别人”），自己真正体验过才知道好不好用。并且，测速测解锁图不同时间段的结果是不同的，今天一个样，明天又是一个样，即使是同一天，测出来的结果也是有可能大相径庭的，所以我是不打算提供这类图的。一来这些图参考价值不大，二来我没有时间能做到每一天每一刻频繁地更新，三来频繁测速会直接影响到用户的体验，属实不值当。当然，对于那些大多数用户都表示体验不佳的机场，那显然没有任何尝试的必要，除非该机场提供了免费试用的服务。然后，不对机场作排名还有一个好处，那就是一定程度上避免了机场之间的恶意竞争，也能减少被缺德人士攻击的风险。因为，一旦作了排名，那么排名靠前的机场将会极易成为攻击者的首要目标（注意，容易被攻击受到影响不代表机场质量有问题。因为攻击的成本是比防御低很多的，一旦被盯上，一线机场以外的机场都是基本承受不住的）。另外，当你看到诸如上面列出的极低价机场（指 1 ￥ / 月 / 100 GB 这个价位的机场）标有 IPLC，IEPL，BGP，CN2，专线 等字样时，不必当真，因为几乎不可能是真，这类线路价格非常昂贵，售价基本不会低于 30 ￥ / 月 / 100 GB。机场主不是慈善家，再便宜的专线也不可能以低于成本的价格卖给用户，简而言之，极低价的机场是绝对不可能提供专线相关服务的，当作普通的直连节点使用就可以。这类极低价的机场只可能是直连（部分会提供少量高倍率中转节点）。不过，对于这类虚假宣传的机场，最好是不要接触。当然，在上面所推荐的机场中，确实有部分机场的部分节点确实是有真专线的，虽然体验跟高端机场还是有差距，但也会比普通的直连，中转好很多（速度更快，延迟更低，连接更稳）。当然，这类价格的机场即使提供了专线，倍率往往也是偏高的（往往在 10 倍以上），所以多数情况下使用中转节点即可，中转的体验已经比直连好很多了，特别是对于部分敏感地区的用户来说，这两者是有质的飞跃的。另外，直连线路比起中转及专线会比较容易被墙，这受限于直连线路的结构，不可避免，解决方案就是需要机场主频繁更换节点 IP，不过，日常一般是不会被墙的，但是在一些特殊时期或特殊地区就很容易被墙，而中转及专线则基本不会有此类烦恼。\n🌏 关于机场节点所标注的地区与实际测试出来的地理位置不同：一般来说，各个平台在获取用户的地理位置时只是根据用户的 IP 地址进行判断（当然，有些平台还会根据用户所使用的语言以及时区等其他方式进行判断）。然而，IP 地址本身是不具备定位属性的，IP 定位的本质其实是查询 IP 地理位置数据库中 IP 地址与地理位置的映射关系。遗憾的是，全球并没有统一的数据库且各个数据库的更新时间也不一致，因此，仅仅依靠 IP 地址本身是不可能实现精确定位的。所以，即使在节点完全不变的情况下，不同的 IP 测试网站或是不同的平台所检测出来的地理位置也是不一定相同的。例如在 Google 上所显示的地区是新加坡，而在 X（Twitter）上显示的地区有可能是伦敦。\n🛑 关于机场封车：部分机场会在运营一段时间后“封车”（本文中所推荐的机场暂无已封车的），即关闭注册渠道。个人认为，“封车”通常对于用户来说是好事。因为，理论上，在机场的线路以及机器的整体性能一定的情况下，用户数量越少，那么用户的平均体验自然也会更佳。就像家里连接 Wifi 的人数越少，个人的体验会越好。另外，控制用户数量，能够让机场主的维护更加省时省力，算是变相提高维护效率。不过，这并不说明机场使用人数多了之后，用户体验就一定会下降。只要机器的性能及数量同步提高，那就不会使得用户体验变差。这就好比，家里使用 Wifi 的人数增加了，只要使用更高的带宽以及性能更强的路由器，就不会让个人的体验变差。并且，“不封车”的机场，通常意味着机场主的收入是“不封顶”的，也就是说，比起“封车”的机场，“不封车”的机场一般会有更多的资金来优化机场，这可以算是一种良性循环。不过，以上都是从“正面”的角度来谈论的，接下来，我将站在“反面”的角度来看待问题。“封车”的机场，并不代表个人的体验就不会下降，因为，“封车”虽然让连接 Wifi 的人数基本固定了，但是，网络带宽与路由器的性能并不是一定的，也就是说，“减弱”这两者同样会使个人的体验下降。“不封车” 的机场也是同理的，随着连接 Wifi 的人数越来越多，假如不提高带宽及路由器的性能，也就是所谓的“超售”，那么个人的体验自然也会下降。综上，机场的封车与否，或者说，机场使用人数的多少，并不直接决定机场体验的好坏，因此，我认为封车“通常”对于用户来说是好事，而非“一定”是好事。\n📅 任何翻墙工具在敏感时期都可能会有不同程度的“失灵”。所谓敏感时期一般有以下几个时间段：春节期间，三月的两会前后，五月底至六月中旬，国庆期间，突发大事。在这些敏感时期中，GFW 往往会加大审查力度，当然，并不是一定的。毕竟，GFW 并不是一个简单的程序，不是固定在某个时间段将审查力度提升至某个强度这么简单，这些敏感时期不过是人们长期探索总结出来的罢了。就我个人经验而言，两会期间一般是墙最高的时候，不过，不同地区的墙差别很大。因此，并不是说在这些时期一定会难翻墙，只是说在这些时期翻墙难是很正常的，一般不必担忧。作为用户而言，如果希望敏感时期依然能够稳定翻墙，能做的只有一种方式，那就是多整几个备用机场。但是，我个人不建议为了应对敏感时期而购买大量机场。因为，如果墙的审查力度实在很严格，比如使用白名单模式，那么你整再多再贵的机场也是白搭，而如果墙的高度不是特别高，那么其实两三个机场基本就能保证自己一定能翻墙了。\n😄 低价机场最大的优点在于跑路了不会太心疼，对我来说是这样，比起 VPN 动辄几百的价格来说可是实惠了不少，而速度稳定性也基本过得去。不过呢，如果想要极致的体验，可以使用高端机场，这类我就不作推荐了，因为我自己没用过。然而，我个人是不建议使用高价机场的，富哥除外，或者你需求确实很大（需要极致的速度与稳定性）。1 ~ 10 ￥ / 月 / 100 GB 这个价位的低价机场已经是极具性价比的了，足够满足绝大多数人（至少能满足 90 % 以上的人）的需求了，花更高的价钱买更高价格的高端机场着实没什么必要，特别是对于那些只是想看看片什么的，更是没必要，有时候你觉得视频卡顿，不一定就是你自己的网络或是机场的问题，也可能是你所观看的视频资源本身就有问题。或许我以后也会用到高端机场，但可能性不高。补充一下，虽然我不推荐高端机场，但是如若确实有需求，购买前务必擦亮双眼，防止被割韭菜。毕竟总有无良商家以高价出售低廉低质商品，在机场这个行业也是同样的，高价机场不一定就是高端机场。\n😊 最后，如果觉得这篇推荐对你有所帮助，那么不妨评论一下，这将让我更有动力保持更新。💚 感谢你能看到此处 💚。\n","date":"2025-08-02T17:42:51+08:00","image":"/images/hidify.webp","permalink":"/posts/%E4%BD%8E%E4%BB%B7%E6%9C%BA%E5%9C%BA%E6%8E%A8%E8%8D%90/","title":"低价机场推荐"},{"content":"水。无色的透明。流动的镜。\n他站。脚底是草，青色的，结实的。面前是河。河床是石头，硬的，沉默的。 水很清，太清了，清得像个陷阱。 他低头，看向水里。 镜面之下，一座城市在铺展。 卡尔维诺的某个碎片？也许是伊希朵拉？是莱奥尼亚？还是特鲁德？那轮廓，熟悉又陌生，漂浮在石头之上，草根之下。 他低头，看向水中倒影里的自己——倒影里的脚下，依旧是草地，他低头，看向水中……水的倒影中，依旧有一座城市……循环。低头，看水。城市。草地。低头。城市。一个环，嗡鸣，拖拽着意识向下沉沦，制造着空间层叠的眩晕回响。 河在现形。几棵树站岗，三块栅栏是断句。树上有松鼠，生与死，悬停在模糊的枝桠间。 男人的脚底是草地，当他再低头看向水中时，空的。镜面里只剩草，孤独地绿着。 水的倒影中，城市废气笼罩着乌云，风来了，水皱起巨大的波纹，撕裂一切镜像。脚下的草，连同大地温柔的表皮，无声地崩陷、滑落。 男人感到不适，眨眼。一次，两次，三次，然后笑着倒下去。 坠入那看似柔情的流体——那柔情却瞬间冰冷刺骨。河底的石床，硬过世上任何拒绝，粗暴地碎裂了他的牙。甜腥的铁锈味弥漫口腔。耳膜被那沉默石头的锐利沉默刺穿。嗡鸣。 第一次死亡，他感到了什么。 几处拖长的音将将秒针熔化了，铸成了十二枚厚重的刻度铜钱，每枚再被无情分割成五份模糊的碎块。 人们——他们？或者就是‘他’的一部分？——将二十块投入河水，二十块藏在身上铁盒，二十块塞进床垫的阴影。奉献、携带、埋葬。时间分配的仪式。 挣扎。窒息。黑暗。不，光。他“活”了，站在这块沉默的忏悔石上。喧嚣？刚才震耳欲聋的喧嚣呢？溺毙声、心跳声、风呼声？全被河水温柔而彻底地抹去，仿佛那是四十年前的一场梦魇，残魂刚刚归位。\n河水疲惫地流动，毫无活力。渴望逃离。男人迫切的想要离开这里，去一个更加辽阔的地方。 在那里，河流变成了血海，咆哮声让他足够忘记自己的存在。存在？被这猩红的音浪彻底冲刷、稀释。只是一个模糊的红热印象。 这是一个模糊的印象。 一段重复的乐声让他注意到了挂在天边的月球。 男人一边疑惑自己为何听得见声音，一边想着“我想去月球”。 念头浮现，清晰而微弱。随即，破晓。光来了，残酷的光。月球消失了。哪有什么银色卫星？不过是巨大齿轮上一个冰冷、光滑的凸起。咬合着，转动着，带动着一个看不见的发条盒——它正嘎吱作响地播放那重复的乐句。 低语。开始是细微的，生物们的——那些死了的，还是活着？——声音在齿轮缝隙里渗出。渐渐积聚，汇流成喧哗、吵闹、吼叫！剧烈震动！耳道中红色的液体汩汩涌出。内脏——红的血、黄的胆汁、碎块状的组织——在震动中轰然炸开！爆裂！从高处向低处流泻、汇聚。一片新生的海。血肉之海。\n那是我们的城市，我们的。唯一的。里外翻卷着新鲜的、温热的、仍在搏动的血肉。\n男人的大脑仍有意识，血没到了他的胸部。 他明白他回到了家。 他尚有意识。血海上升，没至胸膛。家。他明白了。深吸一口气，不，是被动地吸入那黏稠。一个猛子扎进去！消失。只余三个气泡冒起。 接着，几块絮状物缓缓上浮……像是……大脑。刹那间，万丈金光倾泻而下，拥抱了整片血海。\n碎的耳道深处，一丝极其细微、顽固的金属音色在摩擦、刮擦……碎玻璃？细铁丝？ 这声音刺穿熔金之光，唤起了……工作。 生命在于工作。意识的核心在灼烧。他取下胸前湿透的（何时戴上的？）一副冰冷的金属眼镜框。 声音消失了。好了，工作开始了。开始审视。\n镜片（框？）中映照的一切，轮廓与线条，皆从对面那片无垠的荒漠中被拓印下来。 于是，在渴望城市（哪一座？真实的？倒影的？血肉的？）的他眼中，这片尚在翻涌的血海，这片刚刚吞噬他的汪洋，呈现为一个奇特地带——一个卡尔维诺笔下的、处于荒漠与某个无形城市之间的苔斯皮纳 (Theresina)。空洞无物，只有“城市”的概念与他孑然一身的存在相互映照。一个真空中的意识据点。\n中午了。该吃点什么。脑海中浮现一张油腻的菜单：老虎棒子鸡。配料：老虎侧腹（？）、玉米棒子、鸡大腿。一起炖煮。无味。仅作填充。一个荒诞的、卡在意识流中的注脚。 一个声音在宣读，像广告，像广播： 这是一个港口城市，有天然良港和发达的进出口贸易。 这是一个工业城市，有雄厚的工业基础和科技力量。 这是一个旅游城市，有优美的景色和宜人的气候。 这是一个城市，有城市城与市市城的概念。 城市的幻影在波动的水中，在粘稠的血里， 向他招手。 城市向你招手。\n水的无常形态，漂浮在下方坚硬的石床上。这片血海，已被标注为“沿海城市”，存在于水之湄——那暧昧的交界。意识在冲刷边界。\n一个名字蹦出：瑞瓦肖的杜博阿警官。他今天没酒喝？他第一杯是什么时候开始的？深不可测的谜团。如同书中那些未被解答的追问。算了吧，我们继续游荡。\nlost in train station. Lost in\u0026hellip; 何处？思维的车站？ 意识深处响起弗拉芒语的播报。该走了。我把这个男人的手记（何时在握？）合上。书页残留水渍？血渍？思维的谜团盘旋。然而最后那段对杜博阿酒的提及……该死，一星期没碰酒杯了！太忙。连这本手记也是……一个月前？直到等车（去瑞瓦肖？苔斯皮纳？月球？）时才翻开。剩下的内容？必然诡异难解，如同灌了三斤白粉在直肠里写出的乐章——想到这荒唐的画面，一丝麻木的笑意浮上嘴角。 夹着这册奇异的手记，我挤进了思维的车厢。\n车站是离别的地方， 是团聚的地方， 是出发的地方， 是抵达的地方。 下次踏进车站时，我的路又在何方？\n上世纪的风。90年代末的风。扬起黄沙。巨灵般的工业骨骼在沙暴中艰难转身，发出齿轮摩擦的呻吟。工人——被扬起的沙子。那沙子砸在个体头上，是一座沉重的山。人？何其微渺。何必言说？一个时代在意识深处划下伤痕。 大连，勿语。 地名如咒语，封印着一个记忆的浪头。\n亲爱的伊万诺夫先生，新到的机器生产效率很高，我想终于可以减轻工人们的压力了。\n血海——港口城市？工业废墟？——被无形的火焰点燃了。翻腾、炽烤、蒸腾、清除。男人（我？他？）重新站在最初的草地上，干爽的草。准备迎接他的第二次终局： 第一次死亡，水底破碎的牙，血的倒灌，他感到了窒息的痛与冰冷的石。 第二次死亡，火焰燃尽的虚无，焦土的草皮，他…他什么也没有感到。空。静。\n","date":"2025-07-17T14:11:43+08:00","image":"/images/kbjdcs.webp","permalink":"/posts/%E7%9C%8B%E4%B8%8D%E8%A7%81%E7%9A%84%E5%9F%8E%E5%B8%82/","title":"看不见的城市"},{"content":"本文章为这篇文章的后续，并提供免费示例 在成功部署后，我们就可以输入\nhttps://example.com/114514 来访问我们的网站 此时它应该是这样的： 你们也可以通过https://edge.realityme.top/1145141919810来访问我搭建的这个站点 纯公益，不收费（酷炫）\n","date":"2025-07-14T14:22:13+08:00","image":"/images/cfvpneg2.webp","permalink":"/posts/%E4%BD%BF%E7%94%A8cloudflare%E6%90%AD%E5%BB%BAvpn%E7%9A%84%E5%AE%9E%E6%88%98%E6%BC%94%E7%BB%83/","title":"使用cloudflare搭建VPN的实战演练及免费节点"},{"content":"今天我们主要来说下如果通过 Cloudflare 的 worker 、Pages 搭建永久免费的VPN，真正做到无限流量！\n准备工作 首先你需要注册一个免费的 Cloudflare 账号 【点击前往】\n接着你需要准备好开源软件：V2rayN，因为一会要用到 【点击下载】\n在Cloudflare 上创建worker，并填写下面的代码，这个代码来自CM在【 GitHub 】社区的开源项目，代码已经内置IP优选和代理功能，自带动态的UUID，可以大大减少手动配置过程，非常适合新手和特殊用户。\n创建的worker项目名称最好使用系统默认的，别自定义，以免被系统识别到特殊字符而被屏蔽。\n获取Cloudflare 的 worker 开源代码 加密版：【点击获取】\n明文版：直接复制下方的代码即可！ 仅限海外用户使用，大陆用户切勿使用（可能违法），别给站长找麻烦！！\nimport { connect } from \u0026#39;cloudflare:sockets\u0026#39;; let userID = \u0026#39;\u0026#39;; let proxyIP = \u0026#39;\u0026#39;; //let sub = \u0026#39;\u0026#39;; let subConverter = \u0026#39;SUBAPI.fxxk.dedyn.io\u0026#39;; let subConfig = \u0026#34;https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_Mini_MultiMode.ini\u0026#34;; let subProtocol = \u0026#39;https\u0026#39;; let subEmoji = \u0026#39;true\u0026#39;; let socks5Address = \u0026#39;\u0026#39;; let parsedSocks5Address = {}; let enableSocks = false; let fakeUserID; let fakeHostName; let noTLS = \u0026#39;false\u0026#39;; const expire = 4102329600;//2099-12-31 let proxyIPs; let socks5s; let go2Socks5s = [ \u0026#39;*ttvnw.net\u0026#39;, \u0026#39;*tapecontent.net\u0026#39;, \u0026#39;*cloudatacdn.com\u0026#39;, \u0026#39;*.loadshare.org\u0026#39;, ]; let addresses = []; let addressesapi = []; let addressesnotls = []; let addressesnotlsapi = []; let addressescsv = []; let DLS = 8; let remarkIndex = 1;//CSV备注所在列偏移量 let FileName = atob(\u0026#39;ZWRnZXR1bm5lbA==\u0026#39;); let BotToken; let ChatID; let proxyhosts = []; let proxyhostsURL = \u0026#39;\u0026#39;; let RproxyIP = \u0026#39;false\u0026#39;; let httpsPorts = [\u0026#34;2053\u0026#34;, \u0026#34;2083\u0026#34;, \u0026#34;2087\u0026#34;, \u0026#34;2096\u0026#34;, \u0026#34;8443\u0026#34;]; let 有效时间 = 7; let 更新时间 = 3; let userIDLow; let userIDTime = \u0026#34;\u0026#34;; let proxyIPPool = []; let path = \u0026#39;/?ed=2560\u0026#39;; let 动态UUID; let link = []; let banHosts = [atob(\u0026#39;c3BlZWQuY2xvdWRmbGFyZS5jb20=\u0026#39;)]; export default { async fetch(request, env, ctx) { try { const UA = request.headers.get(\u0026#39;User-Agent\u0026#39;) || \u0026#39;null\u0026#39;; const userAgent = UA.toLowerCase(); userID = env.UUID || env.uuid || env.PASSWORD || env.pswd || userID; if (env.KEY || env.TOKEN || (userID \u0026amp;\u0026amp; !isValidUUID(userID))) { 动态UUID = env.KEY || env.TOKEN || userID; 有效时间 = Number(env.TIME) || 有效时间; 更新时间 = Number(env.UPTIME) || 更新时间; const userIDs = await 生成动态UUID(动态UUID); userID = userIDs[0]; userIDLow = userIDs[1]; } if (!userID) { return new Response(\u0026#39;请设置你的UUID变量，或尝试重试部署，检查变量是否生效？\u0026#39;, { status: 404, headers: { \u0026#34;Content-Type\u0026#34;: \u0026#34;text/plain;charset=utf-8\u0026#34;, } }); } const currentDate = new Date(); currentDate.setHours(0, 0, 0, 0); const timestamp = Math.ceil(currentDate.getTime() / 1000); const fakeUserIDMD5 = await 双重哈希(`${userID}${timestamp}`); fakeUserID = [ fakeUserIDMD5.slice(0, 8), fakeUserIDMD5.slice(8, 12), fakeUserIDMD5.slice(12, 16), fakeUserIDMD5.slice(16, 20), fakeUserIDMD5.slice(20) ].join(\u0026#39;-\u0026#39;); fakeHostName = `${fakeUserIDMD5.slice(6, 9)}.${fakeUserIDMD5.slice(13, 19)}`; proxyIP = env.PROXYIP || env.proxyip || proxyIP; proxyIPs = await 整理(proxyIP); proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)]; socks5Address = env.SOCKS5 || socks5Address; socks5s = await 整理(socks5Address); socks5Address = socks5s[Math.floor(Math.random() * socks5s.length)]; socks5Address = socks5Address.split(\u0026#39;//\u0026#39;)[1] || socks5Address; if (env.GO2SOCKS5) go2Socks5s = await 整理(env.GO2SOCKS5); if (env.CFPORTS) httpsPorts = await 整理(env.CFPORTS); if (env.BAN) banHosts = await 整理(env.BAN); if (socks5Address) { try { parsedSocks5Address = socks5AddressParser(socks5Address); RproxyIP = env.RPROXYIP || \u0026#39;false\u0026#39;; enableSocks = true; } catch (err) { let e = err; console.log(e.toString()); RproxyIP = env.RPROXYIP || !proxyIP ? \u0026#39;true\u0026#39; : \u0026#39;false\u0026#39;; enableSocks = false; } } else { RproxyIP = env.RPROXYIP || !proxyIP ? \u0026#39;true\u0026#39; : \u0026#39;false\u0026#39;; } const upgradeHeader = request.headers.get(\u0026#39;Upgrade\u0026#39;); const url = new URL(request.url); if (!upgradeHeader || upgradeHeader !== \u0026#39;websocket\u0026#39;) { if (env.ADD) addresses = await 整理(env.ADD); if (env.ADDAPI) addressesapi = await 整理(env.ADDAPI); if (env.ADDNOTLS) addressesnotls = await 整理(env.ADDNOTLS); if (env.ADDNOTLSAPI) addressesnotlsapi = await 整理(env.ADDNOTLSAPI); if (env.ADDCSV) addressescsv = await 整理(env.ADDCSV); DLS = Number(env.DLS) || DLS; remarkIndex = Number(env.CSVREMARK) || remarkIndex; BotToken = env.TGTOKEN || BotToken; ChatID = env.TGID || ChatID; FileName = env.SUBNAME || FileName; subEmoji = env.SUBEMOJI || env.EMOJI || subEmoji; if (subEmoji == \u0026#39;0\u0026#39;) subEmoji = \u0026#39;false\u0026#39;; if (env.LINK) link = await 整理(env.LINK); let sub = env.SUB || \u0026#39;\u0026#39;; subConverter = env.SUBAPI || subConverter; if (subConverter.includes(\u0026#34;http://\u0026#34;)) { subConverter = subConverter.split(\u0026#34;//\u0026#34;)[1]; subProtocol = \u0026#39;http\u0026#39;; } else { subConverter = subConverter.split(\u0026#34;//\u0026#34;)[1] || subConverter; } subConfig = env.SUBCONFIG || subConfig; if (url.searchParams.has(\u0026#39;sub\u0026#39;) \u0026amp;\u0026amp; url.searchParams.get(\u0026#39;sub\u0026#39;) !== \u0026#39;\u0026#39;) sub = url.searchParams.get(\u0026#39;sub\u0026#39;); if (url.searchParams.has(\u0026#39;notls\u0026#39;)) noTLS = \u0026#39;true\u0026#39;; if (url.searchParams.has(\u0026#39;proxyip\u0026#39;)) { path = `/?ed=2560\u0026amp;proxyip=${url.searchParams.get(\u0026#39;proxyip\u0026#39;)}`; RproxyIP = \u0026#39;false\u0026#39;; } else if (url.searchParams.has(\u0026#39;socks5\u0026#39;)) { path = `/?ed=2560\u0026amp;socks5=${url.searchParams.get(\u0026#39;socks5\u0026#39;)}`; RproxyIP = \u0026#39;false\u0026#39;; } else if (url.searchParams.has(\u0026#39;socks\u0026#39;)) { path = `/?ed=2560\u0026amp;socks5=${url.searchParams.get(\u0026#39;socks\u0026#39;)}`; RproxyIP = \u0026#39;false\u0026#39;; } const 路径 = url.pathname.toLowerCase(); if (路径 == \u0026#39;/\u0026#39;) { if (env.URL302) return Response.redirect(env.URL302, 302); else if (env.URL) return await 代理URL(env.URL, url); else return new Response(JSON.stringify(request.cf, null, 4), { status: 200, headers: { \u0026#39;content-type\u0026#39;: \u0026#39;application/json\u0026#39;, }, }); } else if (路径 == `/${fakeUserID}`) { const fakeConfig = await 生成配置信息(userID, request.headers.get(\u0026#39;Host\u0026#39;), sub, \u0026#39;CF-Workers-SUB\u0026#39;, RproxyIP, url, env); return new Response(`${fakeConfig}`, { status: 200 }); } else if (url.pathname == `/${动态UUID}/edit` || 路径 == `/${userID}/edit`) { const html = await KV(request, env); return html; } else if (url.pathname == `/${动态UUID}` || 路径 == `/${userID}`) { await sendMessage(`#获取订阅 ${FileName}`, request.headers.get(\u0026#39;CF-Connecting-IP\u0026#39;), `UA: ${UA}\u0026lt;/tg-spoiler\u0026gt;\\n域名: ${url.hostname}\\n\u0026lt;tg-spoiler\u0026gt;入口: ${url.pathname + url.search}\u0026lt;/tg-spoiler\u0026gt;`); const 维列斯Config = await 生成配置信息(userID, request.headers.get(\u0026#39;Host\u0026#39;), sub, UA, RproxyIP, url, env); const now = Date.now(); //const timestamp = Math.floor(now / 1000); const today = new Date(now); today.setHours(0, 0, 0, 0); const UD = Math.floor(((now - today.getTime()) / 86400000) * 24 * 1099511627776 / 2); let pagesSum = UD; let workersSum = UD; let total = 24 * 1099511627776; if (userAgent \u0026amp;\u0026amp; userAgent.includes(\u0026#39;mozilla\u0026#39;)) { return new Response(`\u0026lt;div style=\u0026#34;font-size:13px;\u0026#34;\u0026gt;${维列斯Config}\u0026lt;/div\u0026gt;`, { status: 200, headers: { \u0026#34;Content-Type\u0026#34;: \u0026#34;text/html;charset=utf-8\u0026#34;, \u0026#34;Profile-Update-Interval\u0026#34;: \u0026#34;6\u0026#34;, \u0026#34;Subscription-Userinfo\u0026#34;: `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`, \u0026#34;Cache-Control\u0026#34;: \u0026#34;no-store\u0026#34;, } }); } else { return new Response(`${维列斯Config}`, { status: 200, headers: { \u0026#34;Content-Disposition\u0026#34;: `attachment; filename=${FileName}; filename*=utf-8\u0026#39;\u0026#39;${encodeURIComponent(FileName)}`, \u0026#34;Content-Type\u0026#34;: \u0026#34;text/plain;charset=utf-8\u0026#34;, \u0026#34;Profile-Update-Interval\u0026#34;: \u0026#34;6\u0026#34;, \u0026#34;Subscription-Userinfo\u0026#34;: `upload=${pagesSum}; download=${workersSum}; total=${total}; expire=${expire}`, } }); } } else { if (env.URL302) return Response.redirect(env.URL302, 302); else if (env.URL) return await 代理URL(env.URL, url); else return new Response(\u0026#39;不用怀疑！你UUID就是错的！！！\u0026#39;, { status: 404 }); } } else { socks5Address = url.searchParams.get(\u0026#39;socks5\u0026#39;) || socks5Address; if (new RegExp(\u0026#39;/socks5=\u0026#39;, \u0026#39;i\u0026#39;).test(url.pathname)) socks5Address = url.pathname.split(\u0026#39;5=\u0026#39;)[1]; else if (new RegExp(\u0026#39;/socks://\u0026#39;, \u0026#39;i\u0026#39;).test(url.pathname) || new RegExp(\u0026#39;/socks5://\u0026#39;, \u0026#39;i\u0026#39;).test(url.pathname)) { socks5Address = url.pathname.split(\u0026#39;://\u0026#39;)[1].split(\u0026#39;#\u0026#39;)[0]; if (socks5Address.includes(\u0026#39;@\u0026#39;)) { let userPassword = socks5Address.split(\u0026#39;@\u0026#39;)[0]; const base64Regex = /^(?:[A-Z0-9+/]{4})*(?:[A-Z0-9+/]{2}==|[A-Z0-9+/]{3}=)?$/i; if (base64Regex.test(userPassword) \u0026amp;\u0026amp; !userPassword.includes(\u0026#39;:\u0026#39;)) userPassword = atob(userPassword); socks5Address = `${userPassword}@${socks5Address.split(\u0026#39;@\u0026#39;)[1]}`; } } if (socks5Address) { try { parsedSocks5Address = socks5AddressParser(socks5Address); enableSocks = true; } catch (err) { let e = err; console.log(e.toString()); enableSocks = false; } } else { enableSocks = false; } if (url.searchParams.has(\u0026#39;proxyip\u0026#39;)) { proxyIP = url.searchParams.get(\u0026#39;proxyip\u0026#39;); enableSocks = false; } else if (new RegExp(\u0026#39;/proxyip=\u0026#39;, \u0026#39;i\u0026#39;).test(url.pathname)) { proxyIP = url.pathname.toLowerCase().split(\u0026#39;/proxyip=\u0026#39;)[1]; enableSocks = false; } else if (new RegExp(\u0026#39;/proxyip.\u0026#39;, \u0026#39;i\u0026#39;).test(url.pathname)) { proxyIP = `proxyip.${url.pathname.toLowerCase().split(\u0026#34;/proxyip.\u0026#34;)[1]}`; enableSocks = false; } else if (new RegExp(\u0026#39;/pyip=\u0026#39;, \u0026#39;i\u0026#39;).test(url.pathname)) { proxyIP = url.pathname.toLowerCase().split(\u0026#39;/pyip=\u0026#39;)[1]; enableSocks = false; } return await 维列斯OverWSHandler(request); } } catch (err) { let e = err; return new Response(e.toString()); } }, }; async function 维列斯OverWSHandler(request) { // @ts-ignore const webSocketPair = new WebSocketPair(); const [client, webSocket] = Object.values(webSocketPair); // 接受 WebSocket 连接 webSocket.accept(); let address = \u0026#39;\u0026#39;; let portWithRandomLog = \u0026#39;\u0026#39;; // 日志函数，用于记录连接信息 const log = (/** @type {string} */ info, /** @type {string | undefined} */ event) =\u0026gt; { console.log(`[${address}:${portWithRandomLog}] ${info}`, event || \u0026#39;\u0026#39;); }; // 获取早期数据头部，可能包含了一些初始化数据 const earlyDataHeader = request.headers.get(\u0026#39;sec-websocket-protocol\u0026#39;) || \u0026#39;\u0026#39;; // 创建一个可读的 WebSocket 流，用于接收客户端数据 const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log); // 用于存储远程 Socket 的包装器 let remoteSocketWapper = { value: null, }; // 标记是否为 DNS 查询 let isDns = false; // WebSocket 数据流向远程服务器的管道 readableWebSocketStream.pipeTo(new WritableStream({ async write(chunk, controller) { if (isDns) { // 如果是 DNS 查询，调用 DNS 处理函数 return await handleDNSQuery(chunk, webSocket, null, log); } if (remoteSocketWapper.value) { // 如果已有远程 Socket，直接写入数据 const writer = remoteSocketWapper.value.writable.getWriter() await writer.write(chunk); writer.releaseLock(); return; } // 处理 维列斯 协议头部 const { hasError, message, addressType, portRemote = 443, addressRemote = \u0026#39;\u0026#39;, rawDataIndex, 维列斯Version = new Uint8Array([0, 0]), isUDP, } = process维列斯Header(chunk, userID); // 设置地址和端口信息，用于日志 address = addressRemote; portWithRandomLog = `${portRemote}--${Math.random()} ${isUDP ? \u0026#39;udp \u0026#39; : \u0026#39;tcp \u0026#39;} `; if (hasError) { // 如果有错误，抛出异常 throw new Error(message); return; } // 如果是 UDP 且端口不是 DNS 端口（53），则关闭连接 if (isUDP) { if (portRemote === 53) { isDns = true; } else { throw new Error(\u0026#39;UDP 代理仅对 DNS（53 端口）启用\u0026#39;); return; } } // 构建 维列斯 响应头部 const 维列斯ResponseHeader = new Uint8Array([维列斯Version[0], 0]); // 获取实际的客户端数据 const rawClientData = chunk.slice(rawDataIndex); if (isDns) { // 如果是 DNS 查询，调用 DNS 处理函数 return handleDNSQuery(rawClientData, webSocket, 维列斯ResponseHeader, log); } // 处理 TCP 出站连接 if (!banHosts.includes(addressRemote)) { log(`处理 TCP 出站连接 ${addressRemote}:${portRemote}`); handleTCPOutBound(remoteSocketWapper, addressType, addressRemote, portRemote, rawClientData, webSocket, 维列斯ResponseHeader, log); } else { throw new Error(`黑名单关闭 TCP 出站连接 ${addressRemote}:${portRemote}`); } }, close() { log(`readableWebSocketStream 已关闭`); }, abort(reason) { log(`readableWebSocketStream 已中止`, JSON.stringify(reason)); }, })).catch((err) =\u0026gt; { log(\u0026#39;readableWebSocketStream 管道错误\u0026#39;, err); }); // 返回一个 WebSocket 升级的响应 return new Response(null, { status: 101, // @ts-ignore webSocket: client, }); } async function handleTCPOutBound(remoteSocket, addressType, addressRemote, portRemote, rawClientData, webSocket, 维列斯ResponseHeader, log,) { async function useSocks5Pattern(address) { if (go2Socks5s.includes(atob(\u0026#39;YWxsIGlu\u0026#39;)) || go2Socks5s.includes(atob(\u0026#39;Kg==\u0026#39;))) return true; return go2Socks5s.some(pattern =\u0026gt; { let regexPattern = pattern.replace(/\\*/g, \u0026#39;.*\u0026#39;); let regex = new RegExp(`^${regexPattern}$`, \u0026#39;i\u0026#39;); return regex.test(address); }); } async function connectAndWrite(address, port, socks = false) { log(`connected to ${address}:${port}`); //if (/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(address)) address = `${atob(\u0026#39;d3d3Lg==\u0026#39;)}${address}${atob(\u0026#39;LmlwLjA5MDIyNy54eXo=\u0026#39;)}`; // 如果指定使用 SOCKS5 代理，则通过 SOCKS5 协议连接；否则直接连接 const tcpSocket = socks ? await socks5Connect(addressType, address, port, log) : connect({ hostname: address, port: port, }); remoteSocket.value = tcpSocket; //log(`connected to ${address}:${port}`); const writer = tcpSocket.writable.getWriter(); // 首次写入，通常是 TLS 客户端 Hello 消息 await writer.write(rawClientData); writer.releaseLock(); return tcpSocket; } /** * 重试函数：当 Cloudflare 的 TCP Socket 没有传入数据时，我们尝试重定向 IP * 这可能是因为某些网络问题导致的连接失败 */ async function retry() { if (enableSocks) { // 如果启用了 SOCKS5，通过 SOCKS5 代理重试连接 tcpSocket = await connectAndWrite(addressRemote, portRemote, true); } else { // 否则，尝试使用预设的代理 IP（如果有）或原始地址重试连接 if (!proxyIP || proxyIP == \u0026#39;\u0026#39;) { proxyIP = atob(`UFJPWFlJUC50cDEuZnh4ay5kZWR5bi5pbw==`); } else if (proxyIP.includes(\u0026#39;]:\u0026#39;)) { portRemote = proxyIP.split(\u0026#39;]:\u0026#39;)[1] || portRemote; proxyIP = proxyIP.split(\u0026#39;]:\u0026#39;)[0] || proxyIP; } else if (proxyIP.split(\u0026#39;:\u0026#39;).length === 2) { portRemote = proxyIP.split(\u0026#39;:\u0026#39;)[1] || portRemote; proxyIP = proxyIP.split(\u0026#39;:\u0026#39;)[0] || proxyIP; } if (proxyIP.includes(\u0026#39;.tp\u0026#39;)) portRemote = proxyIP.split(\u0026#39;.tp\u0026#39;)[1].split(\u0026#39;.\u0026#39;)[0] || portRemote; tcpSocket = await connectAndWrite(proxyIP || addressRemote, portRemote); } // 无论重试是否成功，都要关闭 WebSocket（可能是为了重新建立连接） tcpSocket.closed.catch(error =\u0026gt; { console.log(\u0026#39;retry tcpSocket closed error\u0026#39;, error); }).finally(() =\u0026gt; { safeCloseWebSocket(webSocket); }) // 建立从远程 Socket 到 WebSocket 的数据流 remoteSocketToWS(tcpSocket, webSocket, 维列斯ResponseHeader, null, log); } let useSocks = false; if (go2Socks5s.length \u0026gt; 0 \u0026amp;\u0026amp; enableSocks) useSocks = await useSocks5Pattern(addressRemote); // 首次尝试连接远程服务器 let tcpSocket = await connectAndWrite(addressRemote, portRemote, useSocks); // 当远程 Socket 就绪时，将其传递给 WebSocket // 建立从远程服务器到 WebSocket 的数据流，用于将远程服务器的响应发送回客户端 // 如果连接失败或无数据，retry 函数将被调用进行重试 remoteSocketToWS(tcpSocket, webSocket, 维列斯ResponseHeader, retry, log); } function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) { // 标记可读流是否已被取消 let readableStreamCancel = false; // 创建一个新的可读流 const stream = new ReadableStream({ // 当流开始时的初始化函数 start(controller) { // 监听 WebSocket 的消息事件 webSocketServer.addEventListener(\u0026#39;message\u0026#39;, (event) =\u0026gt; { // 如果流已被取消，不再处理新消息 if (readableStreamCancel) { return; } const message = event.data; // 将消息加入流的队列中 controller.enqueue(message); }); // 监听 WebSocket 的关闭事件 // 注意：这个事件意味着客户端关闭了客户端 -\u0026gt; 服务器的流 // 但是，服务器 -\u0026gt; 客户端的流仍然打开，直到在服务器端调用 close() // WebSocket 协议要求在每个方向上都要发送单独的关闭消息，以完全关闭 Socket webSocketServer.addEventListener(\u0026#39;close\u0026#39;, () =\u0026gt; { // 客户端发送了关闭信号，需要关闭服务器端 safeCloseWebSocket(webSocketServer); // 如果流未被取消，则关闭控制器 if (readableStreamCancel) { return; } controller.close(); }); // 监听 WebSocket 的错误事件 webSocketServer.addEventListener(\u0026#39;error\u0026#39;, (err) =\u0026gt; { log(\u0026#39;WebSocket 服务器发生错误\u0026#39;); // 将错误传递给控制器 controller.error(err); }); // 处理 WebSocket 0-RTT（零往返时间）的早期数据 // 0-RTT 允许在完全建立连接之前发送数据，提高了效率 const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader); if (error) { // 如果解码早期数据时出错，将错误传递给控制器 controller.error(error); } else if (earlyData) { // 如果有早期数据，将其加入流的队列中 controller.enqueue(earlyData); } }, // 当使用者从流中拉取数据时调用 pull(controller) { // 这里可以实现反压机制 // 如果 WebSocket 可以在流满时停止读取，我们就可以实现反压 // 参考：https://streams.spec.whatwg.org/#example-rs-push-backpressure }, // 当流被取消时调用 cancel(reason) { // 流被取消的几种情况： // 1. 当管道的 WritableStream 有错误时，这个取消函数会被调用，所以在这里处理 WebSocket 服务器的关闭 // 2. 如果 ReadableStream 被取消，所有 controller.close/enqueue 都需要跳过 // 3. 但是经过测试，即使 ReadableStream 被取消，controller.error 仍然有效 if (readableStreamCancel) { return; } log(`可读流被取消，原因是 ${reason}`); readableStreamCancel = true; // 安全地关闭 WebSocket safeCloseWebSocket(webSocketServer); } }); return stream; } // https://xtls.github.io/development/protocols/维列斯.html // https://github.com/zizifn/excalidraw-backup/blob/main/v2ray-protocol.excalidraw /** * 解析 维列斯 协议的头部数据 * @param { ArrayBuffer} 维列斯Buffer 维列斯 协议的原始头部数据 * @param {string} userID 用于验证的用户 ID * @returns {Object} 解析结果，包括是否有错误、错误信息、远程地址信息等 */ function process维列斯Header(维列斯Buffer, userID) { // 检查数据长度是否足够（至少需要 24 字节） if (维列斯Buffer.byteLength \u0026lt; 24) { return { hasError: true, message: \u0026#39;invalid data\u0026#39;, }; } // 解析 维列斯 协议版本（第一个字节） const version = new Uint8Array(维列斯Buffer.slice(0, 1)); let isValidUser = false; let isUDP = false; // 验证用户 ID（接下来的 16 个字节） function isUserIDValid(userID, userIDLow, buffer) { const userIDArray = new Uint8Array(buffer.slice(1, 17)); const userIDString = stringify(userIDArray); return userIDString === userID || userIDString === userIDLow; } // 使用函数验证 isValidUser = isUserIDValid(userID, userIDLow, 维列斯Buffer); // 如果用户 ID 无效，返回错误 if (!isValidUser) { return { hasError: true, message: `invalid user ${(new Uint8Array(维列斯Buffer.slice(1, 17)))}`, }; } // 获取附加选项的长度（第 17 个字节） const optLength = new Uint8Array(维列斯Buffer.slice(17, 18))[0]; // 暂时跳过附加选项 // 解析命令（紧跟在选项之后的 1 个字节） // 0x01: TCP, 0x02: UDP, 0x03: MUX（多路复用） const command = new Uint8Array( 维列斯Buffer.slice(18 + optLength, 18 + optLength + 1) )[0]; // 0x01 TCP // 0x02 UDP // 0x03 MUX if (command === 1) { // TCP 命令，不需特殊处理 } else if (command === 2) { // UDP 命令 isUDP = true; } else { // 不支持的命令 return { hasError: true, message: `command ${command} is not support, command 01-tcp,02-udp,03-mux`, }; } // 解析远程端口（大端序，2 字节） const portIndex = 18 + optLength + 1; const portBuffer = 维列斯Buffer.slice(portIndex, portIndex + 2); // port is big-Endian in raw data etc 80 == 0x005d const portRemote = new DataView(portBuffer).getUint16(0); // 解析地址类型和地址 let addressIndex = portIndex + 2; const addressBuffer = new Uint8Array( 维列斯Buffer.slice(addressIndex, addressIndex + 1) ); // 地址类型：1-IPv4(4字节), 2-域名(可变长), 3-IPv6(16字节) const addressType = addressBuffer[0]; let addressLength = 0; let addressValueIndex = addressIndex + 1; let addressValue = \u0026#39;\u0026#39;; switch (addressType) { case 1: // IPv4 地址 addressLength = 4; // 将 4 个字节转为点分十进制格式 addressValue = new Uint8Array( 维列斯Buffer.slice(addressValueIndex, addressValueIndex + addressLength) ).join(\u0026#39;.\u0026#39;); break; case 2: // 域名 // 第一个字节是域名长度 addressLength = new Uint8Array( 维列斯Buffer.slice(addressValueIndex, addressValueIndex + 1) )[0]; addressValueIndex += 1; // 解码域名 addressValue = new TextDecoder().decode( 维列斯Buffer.slice(addressValueIndex, addressValueIndex + addressLength) ); break; case 3: // IPv6 地址 addressLength = 16; const dataView = new DataView( 维列斯Buffer.slice(addressValueIndex, addressValueIndex + addressLength) ); // 每 2 字节构成 IPv6 地址的一部分 const ipv6 = []; for (let i = 0; i \u0026lt; 8; i++) { ipv6.push(dataView.getUint16(i * 2).toString(16)); } addressValue = ipv6.join(\u0026#39;:\u0026#39;); // seems no need add [] for ipv6 break; default: // 无效的地址类型 return { hasError: true, message: `invild addressType is ${addressType}`, }; } // 确保地址不为空 if (!addressValue) { return { hasError: true, message: `addressValue is empty, addressType is ${addressType}`, }; } // 返回解析结果 return { hasError: false, addressRemote: addressValue, // 解析后的远程地址 addressType, // 地址类型 portRemote, // 远程端口 rawDataIndex: addressValueIndex + addressLength, // 原始数据的实际起始位置 维列斯Version: version, // 维列斯 协议版本 isUDP, // 是否是 UDP 请求 }; } async function remoteSocketToWS(remoteSocket, webSocket, 维列斯ResponseHeader, retry, log) { // 将数据从远程服务器转发到 WebSocket let remoteChunkCount = 0; let chunks = []; /** @type {ArrayBuffer | null} */ let 维列斯Header = 维列斯ResponseHeader; let hasIncomingData = false; // 检查远程 Socket 是否有传入数据 // 使用管道将远程 Socket 的可读流连接到一个可写流 await remoteSocket.readable .pipeTo( new WritableStream({ start() { // 初始化时不需要任何操作 }, /** * 处理每个数据块 * @param {Uint8Array} chunk 数据块 * @param {*} controller 控制器 */ async write(chunk, controller) { hasIncomingData = true; // 标记已收到数据 // remoteChunkCount++; // 用于流量控制，现在似乎不需要了 // 检查 WebSocket 是否处于开放状态 if (webSocket.readyState !== WS_READY_STATE_OPEN) { controller.error( \u0026#39;webSocket.readyState is not open, maybe close\u0026#39; ); } if (维列斯Header) { // 如果有 维列斯 响应头部，将其与第一个数据块一起发送 webSocket.send(await new Blob([维列斯Header, chunk]).arrayBuffer()); 维列斯Header = null; // 清空头部，之后不再发送 } else { // 直接发送数据块 // 以前这里有流量控制代码，限制大量数据的发送速率 // 但现在 Cloudflare 似乎已经修复了这个问题 // if (remoteChunkCount \u0026gt; 20000) { // // cf one package is 4096 byte(4kb), 4096 * 20000 = 80M // await delay(1); // } webSocket.send(chunk); } }, close() { // 当远程连接的可读流关闭时 log(`remoteConnection!.readable is close with hasIncomingData is ${hasIncomingData}`); // 不需要主动关闭 WebSocket，因为这可能导致 HTTP ERR_CONTENT_LENGTH_MISMATCH 问题 // 客户端无论如何都会发送关闭事件 // safeCloseWebSocket(webSocket); }, abort(reason) { // 当远程连接的可读流中断时 console.error(`remoteConnection!.readable abort`, reason); }, }) ) .catch((error) =\u0026gt; { // 捕获并记录任何异常 console.error( `remoteSocketToWS has exception `, error.stack || error ); // 发生错误时安全地关闭 WebSocket safeCloseWebSocket(webSocket); }); // 处理 Cloudflare 连接 Socket 的特殊错误情况 // 1. Socket.closed 将有错误 // 2. Socket.readable 将关闭，但没有任何数据 if (hasIncomingData === false \u0026amp;\u0026amp; retry) { log(`retry`); retry(); // 调用重试函数，尝试重新建立连接 } } /** * 将 Base64 编码的字符串转换为 ArrayBuffer * * @param {string} base64Str Base64 编码的输入字符串 * @returns {{ earlyData: ArrayBuffer | undefined, error: Error | null }} 返回解码后的 ArrayBuffer 或错误 */ function base64ToArrayBuffer(base64Str) { // 如果输入为空，直接返回空结果 if (!base64Str) { return { earlyData: undefined, error: null }; } try { // Go 语言使用了 URL 安全的 Base64 变体（RFC 4648） // 这种变体使用 \u0026#39;-\u0026#39; 和 \u0026#39;_\u0026#39; 来代替标准 Base64 中的 \u0026#39;+\u0026#39; 和 \u0026#39;/\u0026#39; // JavaScript 的 atob 函数不直接支持这种变体，所以我们需要先转换 base64Str = base64Str.replace(/-/g, \u0026#39;+\u0026#39;).replace(/_/g, \u0026#39;/\u0026#39;); // 使用 atob 函数解码 Base64 字符串 // atob 将 Base64 编码的 ASCII 字符串转换为原始的二进制字符串 const decode = atob(base64Str); // 将二进制字符串转换为 Uint8Array // 这是通过遍历字符串中的每个字符并获取其 Unicode 编码值（0-255）来完成的 const arryBuffer = Uint8Array.from(decode, (c) =\u0026gt; c.charCodeAt(0)); // 返回 Uint8Array 的底层 ArrayBuffer // 这是实际的二进制数据，可以用于网络传输或其他二进制操作 return { earlyData: arryBuffer.buffer, error: null }; } catch (error) { // 如果在任何步骤中出现错误（如非法 Base64 字符），则返回错误 return { earlyData: undefined, error }; } } /** * 这不是真正的 UUID 验证，而是一个简化的版本 * @param {string} uuid 要验证的 UUID 字符串 * @returns {boolean} 如果字符串匹配 UUID 格式则返回 true，否则返回 false */ function isValidUUID(uuid) { // 定义一个正则表达式来匹配 UUID 格式 const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; // 使用正则表达式测试 UUID 字符串 return uuidRegex.test(uuid); } // WebSocket 的两个重要状态常量 const WS_READY_STATE_OPEN = 1; // WebSocket 处于开放状态，可以发送和接收消息 const WS_READY_STATE_CLOSING = 2; // WebSocket 正在关闭过程中 function safeCloseWebSocket(socket) { try { // 只有在 WebSocket 处于开放或正在关闭状态时才调用 close() // 这避免了在已关闭或连接中的 WebSocket 上调用 close() if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) { socket.close(); } } catch (error) { // 记录任何可能发生的错误，虽然按照规范不应该有错误 console.error(\u0026#39;safeCloseWebSocket error\u0026#39;, error); } } // 预计算 0-255 每个字节的十六进制表示 const byteToHex = []; for (let i = 0; i \u0026lt; 256; ++i) { // (i + 256).toString(16) 确保总是得到两位数的十六进制 // .slice(1) 删除前导的 \u0026#34;1\u0026#34;，只保留两位十六进制数 byteToHex.push((i + 256).toString(16).slice(1)); } /** * 快速地将字节数组转换为 UUID 字符串，不进行有效性检查 * 这是一个底层函数，直接操作字节，不做任何验证 * @param {Uint8Array} arr 包含 UUID 字节的数组 * @param {number} offset 数组中 UUID 开始的位置，默认为 0 * @returns {string} UUID 字符串 */ function unsafeStringify(arr, offset = 0) { // 直接从查找表中获取每个字节的十六进制表示，并拼接成 UUID 格式 // 8-4-4-4-12 的分组是通过精心放置的连字符 \u0026#34;-\u0026#34; 实现的 // toLowerCase() 确保整个 UUID 是小写的 return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + \u0026#34;-\u0026#34; + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + \u0026#34;-\u0026#34; + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + \u0026#34;-\u0026#34; + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + \u0026#34;-\u0026#34; + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); } /** * 将字节数组转换为 UUID 字符串，并验证其有效性 * 这是一个安全的函数，它确保返回的 UUID 格式正确 * @param {Uint8Array} arr 包含 UUID 字节的数组 * @param {number} offset 数组中 UUID 开始的位置，默认为 0 * @returns {string} 有效的 UUID 字符串 * @throws {TypeError} 如果生成的 UUID 字符串无效 */ function stringify(arr, offset = 0) { // 使用不安全的函数快速生成 UUID 字符串 const uuid = unsafeStringify(arr, offset); // 验证生成的 UUID 是否有效 if (!isValidUUID(uuid)) { // 原：throw TypeError(\u0026#34;Stringified UUID is invalid\u0026#34;); throw TypeError(`生成的 UUID 不符合规范 ${uuid}`); //uuid = userID; } return uuid; } /** * 处理 DNS 查询的函数 * @param {ArrayBuffer} udpChunk - 客户端发送的 DNS 查询数据 * @param {ArrayBuffer} 维列斯ResponseHeader - 维列斯 协议的响应头部数据 * @param {(string)=\u0026gt; void} log - 日志记录函数 */ async function handleDNSQuery(udpChunk, webSocket, 维列斯ResponseHeader, log) { // 无论客户端发送到哪个 DNS 服务器，我们总是使用硬编码的服务器 // 因为有些 DNS 服务器不支持 DNS over TCP try { // 选用 Google 的 DNS 服务器（注：后续可能会改为 Cloudflare 的 1.1.1.1） const dnsServer = \u0026#39;8.8.4.4\u0026#39;; // 在 Cloudflare 修复连接自身 IP 的 bug 后，将改为 1.1.1.1 const dnsPort = 53; // DNS 服务的标准端口 let 维列斯Header = 维列斯ResponseHeader; // 保存 维列斯 响应头部，用于后续发送 // 与指定的 DNS 服务器建立 TCP 连接 const tcpSocket = connect({ hostname: dnsServer, port: dnsPort, }); log(`连接到 ${dnsServer}:${dnsPort}`); // 记录连接信息 const writer = tcpSocket.writable.getWriter(); await writer.write(udpChunk); // 将客户端的 DNS 查询数据发送给 DNS 服务器 writer.releaseLock(); // 释放写入器，允许其他部分使用 // 将从 DNS 服务器接收到的响应数据通过 WebSocket 发送回客户端 await tcpSocket.readable.pipeTo(new WritableStream({ async write(chunk) { if (webSocket.readyState === WS_READY_STATE_OPEN) { if (维列斯Header) { // 如果有 维列斯 头部，则将其与 DNS 响应数据合并后发送 webSocket.send(await new Blob([维列斯Header, chunk]).arrayBuffer()); 维列斯Header = null; // 头部只发送一次，之后置为 null } else { // 否则直接发送 DNS 响应数据 webSocket.send(chunk); } } }, close() { log(`DNS 服务器(${dnsServer}) TCP 连接已关闭`); // 记录连接关闭信息 }, abort(reason) { console.error(`DNS 服务器(${dnsServer}) TCP 连接异常中断`, reason); // 记录异常中断原因 }, })); } catch (error) { // 捕获并记录任何可能发生的错误 console.error( `handleDNSQuery 函数发生异常，错误信息: ${error.message}` ); } } /** * 建立 SOCKS5 代理连接 * @param {number} addressType 目标地址类型（1: IPv4, 2: 域名, 3: IPv6） * @param {string} addressRemote 目标地址（可以是 IP 或域名） * @param {number} portRemote 目标端口 * @param {function} log 日志记录函数 */ async function socks5Connect(addressType, addressRemote, portRemote, log) { const { username, password, hostname, port } = parsedSocks5Address; // 连接到 SOCKS5 代理服务器 const socket = connect({ hostname, // SOCKS5 服务器的主机名 port, // SOCKS5 服务器的端口 }); // 请求头格式（Worker -\u0026gt; SOCKS5 服务器）: // +----+----------+----------+ // |VER | NMETHODS | METHODS | // +----+----------+----------+ // | 1 | 1 | 1 to 255 | // +----+----------+----------+ // https://en.wikipedia.org/wiki/SOCKS#SOCKS5 // METHODS 字段的含义: // 0x00 不需要认证 // 0x02 用户名/密码认证 https://datatracker.ietf.org/doc/html/rfc1929 const socksGreeting = new Uint8Array([5, 2, 0, 2]); // 5: SOCKS5 版本号, 2: 支持的认证方法数, 0和2: 两种认证方法（无认证和用户名/密码） const writer = socket.writable.getWriter(); await writer.write(socksGreeting); log(\u0026#39;已发送 SOCKS5 问候消息\u0026#39;); const reader = socket.readable.getReader(); const encoder = new TextEncoder(); let res = (await reader.read()).value; // 响应格式（SOCKS5 服务器 -\u0026gt; Worker）: // +----+--------+ // |VER | METHOD | // +----+--------+ // | 1 | 1 | // +----+--------+ if (res[0] !== 0x05) { log(`SOCKS5 服务器版本错误: 收到 ${res[0]}，期望是 5`); return; } if (res[1] === 0xff) { log(\u0026#34;服务器不接受任何认证方法\u0026#34;); return; } // 如果返回 0x0502，表示需要用户名/密码认证 if (res[1] === 0x02) { log(\u0026#34;SOCKS5 服务器需要认证\u0026#34;); if (!username || !password) { log(\u0026#34;请提供用户名和密码\u0026#34;); return; } // 认证请求格式: // +----+------+----------+------+----------+ // |VER | ULEN | UNAME | PLEN | PASSWD | // +----+------+----------+------+----------+ // | 1 | 1 | 1 to 255 | 1 | 1 to 255 | // +----+------+----------+------+----------+ const authRequest = new Uint8Array([ 1, // 认证子协议版本 username.length, // 用户名长度 ...encoder.encode(username), // 用户名 password.length, // 密码长度 ...encoder.encode(password) // 密码 ]); await writer.write(authRequest); res = (await reader.read()).value; // 期望返回 0x0100 表示认证成功 if (res[0] !== 0x01 || res[1] !== 0x00) { log(\u0026#34;SOCKS5 服务器认证失败\u0026#34;); return; } } // 请求数据格式（Worker -\u0026gt; SOCKS5 服务器）: // +----+-----+-------+------+----------+----------+ // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | // +----+-----+-------+------+----------+----------+ // | 1 | 1 | X\u0026#39;00\u0026#39; | 1 | Variable | 2 | // +----+-----+-------+------+----------+----------+ // ATYP: 地址类型 // 0x01: IPv4 地址 // 0x03: 域名 // 0x04: IPv6 地址 // DST.ADDR: 目标地址 // DST.PORT: 目标端口（网络字节序） // addressType // 1 --\u0026gt; IPv4 地址长度 = 4 // 2 --\u0026gt; 域名 // 3 --\u0026gt; IPv6 地址长度 = 16 let DSTADDR; // DSTADDR = ATYP + DST.ADDR switch (addressType) { case 1: // IPv4 DSTADDR = new Uint8Array( [1, ...addressRemote.split(\u0026#39;.\u0026#39;).map(Number)] ); break; case 2: // 域名 DSTADDR = new Uint8Array( [3, addressRemote.length, ...encoder.encode(addressRemote)] ); break; case 3: // IPv6 DSTADDR = new Uint8Array( [4, ...addressRemote.split(\u0026#39;:\u0026#39;).flatMap(x =\u0026gt; [parseInt(x.slice(0, 2), 16), parseInt(x.slice(2), 16)])] ); break; default: log(`无效的地址类型: ${addressType}`); return; } const socksRequest = new Uint8Array([5, 1, 0, ...DSTADDR, portRemote \u0026gt;\u0026gt; 8, portRemote \u0026amp; 0xff]); // 5: SOCKS5版本, 1: 表示CONNECT请求, 0: 保留字段 // ...DSTADDR: 目标地址, portRemote \u0026gt;\u0026gt; 8 和 \u0026amp; 0xff: 将端口转为网络字节序 await writer.write(socksRequest); log(\u0026#39;已发送 SOCKS5 请求\u0026#39;); res = (await reader.read()).value; // 响应格式（SOCKS5 服务器 -\u0026gt; Worker）: // +----+-----+-------+------+----------+----------+ // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | // +----+-----+-------+------+----------+----------+ // | 1 | 1 | X\u0026#39;00\u0026#39; | 1 | Variable | 2 | // +----+-----+-------+------+----------+----------+ if (res[1] === 0x00) { log(\u0026#34;SOCKS5 连接已建立\u0026#34;); } else { log(\u0026#34;SOCKS5 连接建立失败\u0026#34;); return; } writer.releaseLock(); reader.releaseLock(); return socket; } /** * SOCKS5 代理地址解析器 * 此函数用于解析 SOCKS5 代理地址字符串，提取出用户名、密码、主机名和端口号 * * @param {string} address SOCKS5 代理地址，格式可以是： * - \u0026#34;username:password@hostname:port\u0026#34; （带认证） * - \u0026#34;hostname:port\u0026#34; （不需认证） * - \u0026#34;username:password@[ipv6]:port\u0026#34; （IPv6 地址需要用方括号括起来） */ function socks5AddressParser(address) { // 使用 \u0026#34;@\u0026#34; 分割地址，分为认证部分和服务器地址部分 // reverse() 是为了处理没有认证信息的情况，确保 latter 总是包含服务器地址 let [latter, former] = address.split(\u0026#34;@\u0026#34;).reverse(); let username, password, hostname, port; // 如果存在 former 部分，说明提供了认证信息 if (former) { const formers = former.split(\u0026#34;:\u0026#34;); if (formers.length !== 2) { throw new Error(\u0026#39;无效的 SOCKS 地址格式：认证部分必须是 \u0026#34;username:password\u0026#34; 的形式\u0026#39;); } [username, password] = formers; } // 解析服务器地址部分 const latters = latter.split(\u0026#34;:\u0026#34;); // 从末尾提取端口号（因为 IPv6 地址中也包含冒号） port = Number(latters.pop()); if (isNaN(port)) { throw new Error(\u0026#39;无效的 SOCKS 地址格式：端口号必须是数字\u0026#39;); } // 剩余部分就是主机名（可能是域名、IPv4 或 IPv6 地址） hostname = latters.join(\u0026#34;:\u0026#34;); // 处理 IPv6 地址的特殊情况 // IPv6 地址包含多个冒号，所以必须用方括号括起来，如 [2001:db8::1] const regex = /^\\[.*\\]$/; if (hostname.includes(\u0026#34;:\u0026#34;) \u0026amp;\u0026amp; !regex.test(hostname)) { throw new Error(\u0026#39;无效的 SOCKS 地址格式：IPv6 地址必须用方括号括起来，如 [2001:db8::1]\u0026#39;); } //if (/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(hostname)) hostname = `${atob(\u0026#39;d3d3Lg==\u0026#39;)}${hostname}${atob(\u0026#39;LmlwLjA5MDIyNy54eXo=\u0026#39;)}`; // 返回解析后的结果 return { username, // 用户名，如果没有则为 undefined password, // 密码，如果没有则为 undefined hostname, // 主机名，可以是域名、IPv4 或 IPv6 地址 port, // 端口号，已转换为数字类型 } } /** * 恢复被伪装的信息 * 这个函数用于将内容中的假用户ID和假主机名替换回真实的值 * * @param {string} content 需要处理的内容 * @param {string} userID 真实的用户ID * @param {string} hostName 真实的主机名 * @param {boolean} isBase64 内容是否是Base64编码的 * @returns {string} 恢复真实信息后的内容 */ function 恢复伪装信息(content, userID, hostName, isBase64) { if (isBase64) content = atob(content); // 如果内容是Base64编码的，先解码 // 使用正则表达式全局替换（\u0026#39;g\u0026#39;标志） // 将所有出现的假用户ID和假主机名替换为真实的值 content = content.replace(new RegExp(fakeUserID, \u0026#39;g\u0026#39;), userID) .replace(new RegExp(fakeHostName, \u0026#39;g\u0026#39;), hostName); if (isBase64) content = btoa(content); // 如果原内容是Base64编码的，处理完后再次编码 return content; } /** * 双重MD5哈希函数 * 这个函数对输入文本进行两次MD5哈希，增强安全性 * 第二次哈希使用第一次哈希结果的一部分作为输入 * * @param {string} 文本 要哈希的文本 * @returns {Promise\u0026lt;string\u0026gt;} 双重哈希后的小写十六进制字符串 */ async function 双重哈希(文本) { const 编码器 = new TextEncoder(); const 第一次哈希 = await crypto.subtle.digest(\u0026#39;MD5\u0026#39;, 编码器.encode(文本)); const 第一次哈希数组 = Array.from(new Uint8Array(第一次哈希)); const 第一次十六进制 = 第一次哈希数组.map(字节 =\u0026gt; 字节.toString(16).padStart(2, \u0026#39;0\u0026#39;)).join(\u0026#39;\u0026#39;); const 第二次哈希 = await crypto.subtle.digest(\u0026#39;MD5\u0026#39;, 编码器.encode(第一次十六进制.slice(7, 27))); const 第二次哈希数组 = Array.from(new Uint8Array(第二次哈希)); const 第二次十六进制 = 第二次哈希数组.map(字节 =\u0026gt; 字节.toString(16).padStart(2, \u0026#39;0\u0026#39;)).join(\u0026#39;\u0026#39;); return 第二次十六进制.toLowerCase(); } async function 代理URL(代理网址, 目标网址) { const 网址列表 = await 整理(代理网址); const 完整网址 = 网址列表[Math.floor(Math.random() * 网址列表.length)]; // 解析目标 URL let 解析后的网址 = new URL(完整网址); console.log(解析后的网址); // 提取并可能修改 URL 组件 let 协议 = 解析后的网址.protocol.slice(0, -1) || \u0026#39;https\u0026#39;; let 主机名 = 解析后的网址.hostname; let 路径名 = 解析后的网址.pathname; let 查询参数 = 解析后的网址.search; // 处理路径名 if (路径名.charAt(路径名.length - 1) == \u0026#39;/\u0026#39;) { 路径名 = 路径名.slice(0, -1); } 路径名 += 目标网址.pathname; // 构建新的 URL let 新网址 = `${协议}://${主机名}${路径名}${查询参数}`; // 反向代理请求 let 响应 = await fetch(新网址); // 创建新的响应 let 新响应 = new Response(响应.body, { status: 响应.status, statusText: 响应.statusText, headers: 响应.headers }); // 添加自定义头部，包含 URL 信息 //新响应.headers.set(\u0026#39;X-Proxied-By\u0026#39;, \u0026#39;Cloudflare Worker\u0026#39;); //新响应.headers.set(\u0026#39;X-Original-URL\u0026#39;, 完整网址); 新响应.headers.set(\u0026#39;X-New-URL\u0026#39;, 新网址); return 新响应; } const 啥啥啥_写的这是啥啊 = atob(\u0026#39;ZG14bGMzTT0=\u0026#39;); function 配置信息(UUID, 域名地址) { const 协议类型 = atob(啥啥啥_写的这是啥啊); const 别名 = FileName; let 地址 = 域名地址; let 端口 = 443; const 用户ID = UUID; const 加密方式 = \u0026#39;none\u0026#39;; const 传输层协议 = \u0026#39;ws\u0026#39;; const 伪装域名 = 域名地址; const 路径 = path; let 传输层安全 = [\u0026#39;tls\u0026#39;, true]; const SNI = 域名地址; const 指纹 = \u0026#39;randomized\u0026#39;; if (域名地址.includes(\u0026#39;.workers.dev\u0026#39;)) { 地址 = atob(\u0026#39;dmlzYS5jbg==\u0026#39;); 端口 = 80; 传输层安全 = [\u0026#39;\u0026#39;, false]; } const 威图瑞 = `${协议类型}://${用户ID}@${地址}:${端口}\\u003f\\u0065\\u006e\\u0063\\u0072\\u0079` + \u0026#39;p\u0026#39; + `${atob(\u0026#39;dGlvbj0=\u0026#39;) + 加密方式}\\u0026\\u0073\\u0065\\u0063\\u0075\\u0072\\u0069\\u0074\\u0079\\u003d${传输层安全[0]}\u0026amp;sni=${SNI}\u0026amp;fp=${指纹}\u0026amp;type=${传输层协议}\u0026amp;host=${伪装域名}\u0026amp;path=${encodeURIComponent(路径)}#${encodeURIComponent(别名)}`; const 猫猫猫 = `- {name: ${FileName}, server: ${地址}, port: ${端口}, type: ${协议类型}, uuid: ${用户ID}, tls: ${传输层安全[1]}, alpn: [h3], udp: false, sni: ${SNI}, tfo: false, skip-cert-verify: true, servername: ${伪装域名}, client-fingerprint: ${指纹}, network: ${传输层协议}, ws-opts: {path: \u0026#34;${路径}\u0026#34;, headers: {${伪装域名}}}}`; return [威图瑞, 猫猫猫]; } let subParams = [\u0026#39;sub\u0026#39;, \u0026#39;base64\u0026#39;, \u0026#39;b64\u0026#39;, \u0026#39;clash\u0026#39;, \u0026#39;singbox\u0026#39;, \u0026#39;sb\u0026#39;]; const cmad = decodeURIComponent(atob(\u0026#39;dGVsZWdyYW0lMjAlRTQlQkElQTQlRTYlQjUlODElRTclQkUlQTQlMjAlRTYlOEElODAlRTYlOUMlQUYlRTUlQTQlQTclRTQlQkQlQUMlN0UlRTUlOUMlQTglRTclQkElQkYlRTUlOEYlOTElRTclODklOEMhJTNDYnIlM0UKJTNDYSUyMGhyZWYlM0QlMjdodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlMjclM0VodHRwcyUzQSUyRiUyRnQubWUlMkZDTUxpdXNzc3MlM0MlMkZhJTNFJTNDYnIlM0UKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJTNDYnIlM0UKZ2l0aHViJTIwJUU5JUExJUI5JUU3JTlCJUFFJUU1JTlDJUIwJUU1JTlEJTgwJTIwU3RhciFTdGFyIVN0YXIhISElM0NiciUzRQolM0NhJTIwaHJlZiUzRCUyN2h0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUyNyUzRWh0dHBzJTNBJTJGJTJGZ2l0aHViLmNvbSUyRmNtbGl1JTJGZWRnZXR1bm5lbCUzQyUyRmElM0UlM0NiciUzRQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0lM0NiciUzRQolMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjMlMjM=\u0026#39;)); /** * @param {string} userID * @param {string | null} hostName * @param {string} sub * @param {string} UA * @returns {Promise\u0026lt;string\u0026gt;} */ async function 生成配置信息(userID, hostName, sub, UA, RproxyIP, _url, env) { if (sub) { const match = sub.match(/^(?:https?:\\/\\/)?([^\\/]+)/); if (match) { sub = match[1]; } const subs = await 整理(sub); if (subs.length \u0026gt; 1) sub = subs[0]; } else { if (env.KV) { await 迁移地址列表(env); const 优选地址列表 = await env.KV.get(\u0026#39;ADD.txt\u0026#39;); if (优选地址列表) { const 优选地址数组 = await 整理(优选地址列表); const 分类地址 = { 接口地址: new Set(), 链接地址: new Set(), 优选地址: new Set() }; for (const 元素 of 优选地址数组) { if (元素.startsWith(\u0026#39;https://\u0026#39;)) { 分类地址.接口地址.add(元素); } else if (元素.includes(\u0026#39;://\u0026#39;)) { 分类地址.链接地址.add(元素); } else { 分类地址.优选地址.add(元素); } } addressesapi = [...分类地址.接口地址]; link = [...分类地址.链接地址]; addresses = [...分类地址.优选地址]; } } if ((addresses.length + addressesapi.length + addressesnotls.length + addressesnotlsapi.length + addressescsv.length) == 0) { // 定义 Cloudflare IP 范围的 CIDR 列表 let cfips = [ \u0026#39;103.21.244.0/23\u0026#39;, \u0026#39;104.16.0.0/13\u0026#39;, \u0026#39;104.24.0.0/14\u0026#39;, \u0026#39;172.64.0.0/14\u0026#39;, \u0026#39;103.21.244.0/23\u0026#39;, \u0026#39;104.16.0.0/14\u0026#39;, \u0026#39;104.24.0.0/15\u0026#39;, \u0026#39;141.101.64.0/19\u0026#39;, \u0026#39;172.64.0.0/14\u0026#39;, \u0026#39;188.114.96.0/21\u0026#39;, \u0026#39;190.93.240.0/21\u0026#39;, ]; // 生成符合给定 CIDR 范围的随机 IP 地址 function generateRandomIPFromCIDR(cidr) { const [base, mask] = cidr.split(\u0026#39;/\u0026#39;); const baseIP = base.split(\u0026#39;.\u0026#39;).map(Number); const subnetMask = 32 - parseInt(mask, 10); const maxHosts = Math.pow(2, subnetMask) - 1; const randomHost = Math.floor(Math.random() * maxHosts); const randomIP = baseIP.map((octet, index) =\u0026gt; { if (index \u0026lt; 2) return octet; if (index === 2) return (octet \u0026amp; (255 \u0026lt;\u0026lt; (subnetMask - 8))) + ((randomHost \u0026gt;\u0026gt; 8) \u0026amp; 255); return (octet \u0026amp; (255 \u0026lt;\u0026lt; subnetMask)) + (randomHost \u0026amp; 255); }); return randomIP.join(\u0026#39;.\u0026#39;); } addresses = addresses.concat(\u0026#39;127.0.0.1:1234#CFnat\u0026#39;); if (hostName.includes(\u0026#34;.workers.dev\u0026#34;)) { addressesnotls = addressesnotls.concat(cfips.map(cidr =\u0026gt; generateRandomIPFromCIDR(cidr) + \u0026#39;#CF随机节点\u0026#39;)); } else { addresses = addresses.concat(cfips.map(cidr =\u0026gt; generateRandomIPFromCIDR(cidr) + \u0026#39;#CF随机节点\u0026#39;)); } } } const uuid = (_url.pathname == `/${动态UUID}`) ? 动态UUID : userID; const userAgent = UA.toLowerCase(); const Config = 配置信息(userID, hostName); const v2ray = Config[0]; const clash = Config[1]; let proxyhost = \u0026#34;\u0026#34;; if (hostName.includes(\u0026#34;.workers.dev\u0026#34;)) { if (proxyhostsURL \u0026amp;\u0026amp; (!proxyhosts || proxyhosts.length == 0)) { try { const response = await fetch(proxyhostsURL); if (!response.ok) { console.error(\u0026#39;获取地址时出错:\u0026#39;, response.status, response.statusText); return; // 如果有错误，直接返回 } const text = await response.text(); const lines = text.split(\u0026#39;\\n\u0026#39;); // 过滤掉空行或只包含空白字符的行 const nonEmptyLines = lines.filter(line =\u0026gt; line.trim() !== \u0026#39;\u0026#39;); proxyhosts = proxyhosts.concat(nonEmptyLines); } catch (error) { //console.error(\u0026#39;获取地址时出错:\u0026#39;, error); } } if (proxyhosts.length != 0) proxyhost = proxyhosts[Math.floor(Math.random() * proxyhosts.length)] + \u0026#34;/\u0026#34;; } if (userAgent.includes(\u0026#39;mozilla\u0026#39;) \u0026amp;\u0026amp; !subParams.some(_searchParams =\u0026gt; _url.searchParams.has(_searchParams))) { const newSocks5s = socks5s.map(socks5Address =\u0026gt; { if (socks5Address.includes(\u0026#39;@\u0026#39;)) return socks5Address.split(\u0026#39;@\u0026#39;)[1]; else if (socks5Address.includes(\u0026#39;//\u0026#39;)) return socks5Address.split(\u0026#39;//\u0026#39;)[1]; else return socks5Address; }); let socks5List = \u0026#39;\u0026#39;; if (go2Socks5s.length \u0026gt; 0 \u0026amp;\u0026amp; enableSocks) { socks5List = `${decodeURIComponent(\u0026#39;SOCKS5%EF%BC%88%E7%99%BD%E5%90%8D%E5%8D%95%EF%BC%89%3A%20\u0026#39;)}`; if (go2Socks5s.includes(atob(\u0026#39;YWxsIGlu\u0026#39;)) || go2Socks5s.includes(atob(\u0026#39;Kg==\u0026#39;))) socks5List += `${decodeURIComponent(\u0026#39;%E6%89%80%E6%9C%89%E6%B5%81%E9%87%8F\u0026#39;)}\u0026lt;br\u0026gt;`; else socks5List += `\u0026lt;br\u0026gt; ${go2Socks5s.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; } let 订阅器 = \u0026#39;\u0026lt;br\u0026gt;\u0026#39;; if (sub) { if (enableSocks) 订阅器 += `CFCDN（访问方式）: Socks5\u0026lt;br\u0026gt; ${newSocks5s.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;${socks5List}`; else if (proxyIP \u0026amp;\u0026amp; proxyIP != \u0026#39;\u0026#39;) 订阅器 += `CFCDN（访问方式）: ProxyIP\u0026lt;br\u0026gt; ${proxyIPs.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; else if (RproxyIP == \u0026#39;true\u0026#39;) 订阅器 += `CFCDN（访问方式）: 自动获取ProxyIP\u0026lt;br\u0026gt;`; else 订阅器 += `CFCDN（访问方式）: 无法访问, 需要您设置 proxyIP/PROXYIP ！！！\u0026lt;br\u0026gt;` 订阅器 += `\u0026lt;br\u0026gt;SUB（优选订阅生成器）: ${sub}`; } else { if (enableSocks) 订阅器 += `CFCDN（访问方式）: Socks5\u0026lt;br\u0026gt; ${newSocks5s.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;${socks5List}`; else if (proxyIP \u0026amp;\u0026amp; proxyIP != \u0026#39;\u0026#39;) 订阅器 += `CFCDN（访问方式）: ProxyIP\u0026lt;br\u0026gt; ${proxyIPs.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; else 订阅器 += `CFCDN（访问方式）: 无法访问, 需要您设置 proxyIP/PROXYIP ！！！\u0026lt;br\u0026gt;`; let 判断是否绑定KV空间 = \u0026#39;\u0026#39;; if (env.KV) 判断是否绑定KV空间 = ` \u0026lt;a href=\u0026#39;${_url.pathname}/edit\u0026#39;\u0026gt;编辑优选列表\u0026lt;/a\u0026gt;`; 订阅器 += `\u0026lt;br\u0026gt;您的订阅内容由 内置 addresses/ADD* 参数变量提供${判断是否绑定KV空间}\u0026lt;br\u0026gt;`; if (addresses.length \u0026gt; 0) 订阅器 += `ADD（TLS优选域名\u0026amp;IP）: \u0026lt;br\u0026gt; ${addresses.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; if (addressesnotls.length \u0026gt; 0) 订阅器 += `ADDNOTLS（noTLS优选域名\u0026amp;IP）: \u0026lt;br\u0026gt; ${addressesnotls.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; if (addressesapi.length \u0026gt; 0) 订阅器 += `ADDAPI（TLS优选域名\u0026amp;IP 的 API）: \u0026lt;br\u0026gt; ${addressesapi.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; if (addressesnotlsapi.length \u0026gt; 0) 订阅器 += `ADDNOTLSAPI（noTLS优选域名\u0026amp;IP 的 API）: \u0026lt;br\u0026gt; ${addressesnotlsapi.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; if (addressescsv.length \u0026gt; 0) 订阅器 += `ADDCSV（IPTest测速csv文件 限速 ${DLS} ）: \u0026lt;br\u0026gt; ${addressescsv.join(\u0026#39;\u0026lt;br\u0026gt; \u0026#39;)}\u0026lt;br\u0026gt;`; } if (动态UUID \u0026amp;\u0026amp; _url.pathname !== `/${动态UUID}`) 订阅器 = \u0026#39;\u0026#39;; else 订阅器 += `\u0026lt;br\u0026gt;SUBAPI（订阅转换后端）: ${subProtocol}://${subConverter}\u0026lt;br\u0026gt;SUBCONFIG（订阅转换配置文件）: ${subConfig}`; const 动态UUID信息 = (uuid != userID) ? `TOKEN: ${uuid}\u0026lt;br\u0026gt;UUIDNow: ${userID}\u0026lt;br\u0026gt;UUIDLow: ${userIDLow}\u0026lt;br\u0026gt;${userIDTime}TIME（动态UUID有效时间）: ${有效时间} 天\u0026lt;br\u0026gt;UPTIME（动态UUID更新时间）: ${更新时间} 时（北京时间）\u0026lt;br\u0026gt;\u0026lt;br\u0026gt;` : `${userIDTime}`; const 节点配置页 = ` ################################################################\u0026lt;br\u0026gt; Subscribe / sub 订阅地址, 点击链接自动 \u0026lt;strong\u0026gt;复制订阅链接\u0026lt;/strong\u0026gt; 并 \u0026lt;strong\u0026gt;生成订阅二维码\u0026lt;/strong\u0026gt; \u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; 自适应订阅地址:\u0026lt;br\u0026gt; \u0026lt;a href=\u0026#34;javascript:void(0)\u0026#34; onclick=\u0026#34;copyToClipboard(\u0026#39;https://${proxyhost}${hostName}/${uuid}?sub\u0026#39;,\u0026#39;qrcode_0\u0026#39;)\u0026#34; style=\u0026#34;color:blue;text-decoration:underline;cursor:pointer;\u0026#34;\u0026gt;https://${proxyhost}${hostName}/${uuid}\u0026lt;/a\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;qrcode_0\u0026#34; style=\u0026#34;margin: 10px 10px 10px 10px;\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; Base64订阅地址:\u0026lt;br\u0026gt; \u0026lt;a href=\u0026#34;javascript:void(0)\u0026#34; onclick=\u0026#34;copyToClipboard(\u0026#39;https://${proxyhost}${hostName}/${uuid}?b64\u0026#39;,\u0026#39;qrcode_1\u0026#39;)\u0026#34; style=\u0026#34;color:blue;text-decoration:underline;cursor:pointer;\u0026#34;\u0026gt;https://${proxyhost}${hostName}/${uuid}?b64\u0026lt;/a\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;qrcode_1\u0026#34; style=\u0026#34;margin: 10px 10px 10px 10px;\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; clash订阅地址:\u0026lt;br\u0026gt; \u0026lt;a href=\u0026#34;javascript:void(0)\u0026#34; onclick=\u0026#34;copyToClipboard(\u0026#39;https://${proxyhost}${hostName}/${uuid}?clash\u0026#39;,\u0026#39;qrcode_2\u0026#39;)\u0026#34; style=\u0026#34;color:blue;text-decoration:underline;cursor:pointer;\u0026#34;\u0026gt;https://${proxyhost}${hostName}/${uuid}?clash\u0026lt;/a\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;qrcode_2\u0026#34; style=\u0026#34;margin: 10px 10px 10px 10px;\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; singbox订阅地址:\u0026lt;br\u0026gt; \u0026lt;a href=\u0026#34;javascript:void(0)\u0026#34; onclick=\u0026#34;copyToClipboard(\u0026#39;https://${proxyhost}${hostName}/${uuid}?sb\u0026#39;,\u0026#39;qrcode_3\u0026#39;)\u0026#34; style=\u0026#34;color:blue;text-decoration:underline;cursor:pointer;\u0026#34;\u0026gt;https://${proxyhost}${hostName}/${uuid}?sb\u0026lt;/a\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;qrcode_3\u0026#34; style=\u0026#34;margin: 10px 10px 10px 10px;\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;strong\u0026gt;\u0026lt;a href=\u0026#34;javascript:void(0);\u0026#34; id=\u0026#34;noticeToggle\u0026#34; onclick=\u0026#34;toggleNotice()\u0026#34;\u0026gt;实用订阅技巧∨\u0026lt;/a\u0026gt;\u0026lt;/strong\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;noticeContent\u0026#34; class=\u0026#34;notice-content\u0026#34; style=\u0026#34;display: none;\u0026#34;\u0026gt; \u0026lt;strong\u0026gt;1.\u0026lt;/strong\u0026gt; 如您使用的是 PassWall、SSR+ 等路由插件，推荐使用 \u0026lt;strong\u0026gt;Base64订阅地址\u0026lt;/strong\u0026gt; 进行订阅；\u0026lt;br\u0026gt; \u0026lt;br\u0026gt; \u0026lt;strong\u0026gt;2.\u0026lt;/strong\u0026gt; 快速切换 \u0026lt;a href=\u0026#39;${atob(\u0026#39;aHR0cHM6Ly9naXRodWIuY29tL2NtbGl1L1dvcmtlclZsZXNzMnN1Yg==\u0026#39;)}\u0026#39;\u0026gt;优选订阅生成器\u0026lt;/a\u0026gt; 至：sub.google.com，您可将\u0026#34;?sub=sub.google.com\u0026#34;参数添加到链接末尾，例如：\u0026lt;br\u0026gt; https://${proxyhost}${hostName}/${uuid}\u0026lt;strong\u0026gt;?sub=sub.google.com\u0026lt;/strong\u0026gt;\u0026lt;br\u0026gt; \u0026lt;br\u0026gt; \u0026lt;strong\u0026gt;3.\u0026lt;/strong\u0026gt; 快速更换 PROXYIP 至：proxyip.fxxk.dedyn.io:443，您可将\u0026#34;?proxyip=proxyip.fxxk.dedyn.io:443\u0026#34;参数添加到链接末尾，例如：\u0026lt;br\u0026gt; https://${proxyhost}${hostName}/${uuid}\u0026lt;strong\u0026gt;?proxyip=proxyip.fxxk.dedyn.io:443\u0026lt;/strong\u0026gt;\u0026lt;br\u0026gt; \u0026lt;br\u0026gt; \u0026lt;strong\u0026gt;4.\u0026lt;/strong\u0026gt; 快速更换 SOCKS5 至：user:password@127.0.0.1:1080，您可将\u0026#34;?socks5=user:password@127.0.0.1:1080\u0026#34;参数添加到链接末尾，例如：\u0026lt;br\u0026gt; https://${proxyhost}${hostName}/${uuid}\u0026lt;strong\u0026gt;?socks5=user:password@127.0.0.1:1080\u0026lt;/strong\u0026gt;\u0026lt;br\u0026gt; \u0026lt;br\u0026gt; \u0026lt;strong\u0026gt;5.\u0026lt;/strong\u0026gt; 如需指定多个参数则需要使用\u0026#39;\u0026amp;\u0026#39;做间隔，例如：\u0026lt;br\u0026gt; https://${proxyhost}${hostName}/${uuid}?sub=sub.google.com\u0026lt;strong\u0026gt;\u0026amp;\u0026lt;/strong\u0026gt;proxyip=proxyip.fxxk.dedyn.io\u0026lt;br\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;script src=\u0026#34;https://cdn.jsdelivr.net/npm/@keeex/qrcodejs-kx@1.0.2/qrcode.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; function copyToClipboard(text, qrcode) { navigator.clipboard.writeText(text).then(() =\u0026gt; { alert(\u0026#39;已复制到剪贴板\u0026#39;); }).catch(err =\u0026gt; { console.error(\u0026#39;复制失败:\u0026#39;, err); }); const qrcodeDiv = document.getElementById(qrcode); qrcodeDiv.innerHTML = \u0026#39;\u0026#39;; new QRCode(qrcodeDiv, { text: text, width: 220, // 调整宽度 height: 220, // 调整高度 colorDark: \u0026#34;#000000\u0026#34;, // 二维码颜色 colorLight: \u0026#34;#ffffff\u0026#34;, // 背景颜色 correctLevel: QRCode.CorrectLevel.Q, // 设置纠错级别 scale: 1 // 调整像素颗粒度 }); } function toggleNotice() { const noticeContent = document.getElementById(\u0026#39;noticeContent\u0026#39;); const noticeToggle = document.getElementById(\u0026#39;noticeToggle\u0026#39;); if (noticeContent.style.display === \u0026#39;none\u0026#39;) { noticeContent.style.display = \u0026#39;block\u0026#39;; noticeToggle.textContent = \u0026#39;实用订阅技巧∧\u0026#39;; } else { noticeContent.style.display = \u0026#39;none\u0026#39;; noticeToggle.textContent = \u0026#39;实用订阅技巧∨\u0026#39;; } } \u0026lt;/script\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; ################################################################\u0026lt;br\u0026gt; ${FileName} 配置信息\u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; ${动态UUID信息}HOST: ${hostName}\u0026lt;br\u0026gt; UUID: ${userID}\u0026lt;br\u0026gt; FKID: ${fakeUserID}\u0026lt;br\u0026gt; UA: ${UA}\u0026lt;br\u0026gt; ${订阅器}\u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; ################################################################\u0026lt;br\u0026gt; v2ray\u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; \u0026lt;a href=\u0026#34;javascript:void(0)\u0026#34; onclick=\u0026#34;copyToClipboard(\u0026#39;${v2ray}\u0026#39;,\u0026#39;qrcode_v2ray\u0026#39;)\u0026#34; style=\u0026#34;color:blue;text-decoration:underline;cursor:pointer;\u0026#34;\u0026gt;${v2ray}\u0026lt;/a\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;qrcode_v2ray\u0026#34; style=\u0026#34;margin: 10px 10px 10px 10px;\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; ################################################################\u0026lt;br\u0026gt; clash-meta\u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; ${clash}\u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; ################################################################\u0026lt;br\u0026gt; ${cmad} `; return 节点配置页; } else { if (typeof fetch != \u0026#39;function\u0026#39;) { return \u0026#39;Error: fetch is not available in this environment.\u0026#39;; } let newAddressesapi = []; let newAddressescsv = []; let newAddressesnotlsapi = []; let newAddressesnotlscsv = []; // 如果是使用默认域名，则改成一个workers的域名，订阅器会加上代理 if (hostName.includes(\u0026#34;.workers.dev\u0026#34;)) { noTLS = \u0026#39;true\u0026#39;; fakeHostName = `${fakeHostName}.workers.dev`; newAddressesnotlsapi = await 整理优选列表(addressesnotlsapi); newAddressesnotlscsv = await 整理测速结果(\u0026#39;FALSE\u0026#39;); } else if (hostName.includes(\u0026#34;.pages.dev\u0026#34;)) { fakeHostName = `${fakeHostName}.pages.dev`; } else if (hostName.includes(\u0026#34;worker\u0026#34;) || hostName.includes(\u0026#34;notls\u0026#34;) || noTLS == \u0026#39;true\u0026#39;) { noTLS = \u0026#39;true\u0026#39;; fakeHostName = `notls${fakeHostName}.net`; newAddressesnotlsapi = await 整理优选列表(addressesnotlsapi); newAddressesnotlscsv = await 整理测速结果(\u0026#39;FALSE\u0026#39;); } else { fakeHostName = `${fakeHostName}.xyz` } console.log(`虚假HOST: ${fakeHostName}`); let url = `${subProtocol}://${sub}/sub?host=${fakeHostName}\u0026amp;uuid=${fakeUserID + atob(\u0026#39;JmVkZ2V0dW5uZWw9Y21saXUmcHJveHlpcD0=\u0026#39;) + RproxyIP}\u0026amp;path=${encodeURIComponent(path)}`; let isBase64 = true; if (!sub || sub == \u0026#34;\u0026#34;) { if (hostName.includes(\u0026#39;workers.dev\u0026#39;)) { if (proxyhostsURL \u0026amp;\u0026amp; (!proxyhosts || proxyhosts.length == 0)) { try { const response = await fetch(proxyhostsURL); if (!response.ok) { console.error(\u0026#39;获取地址时出错:\u0026#39;, response.status, response.statusText); return; // 如果有错误，直接返回 } const text = await response.text(); const lines = text.split(\u0026#39;\\n\u0026#39;); // 过滤掉空行或只包含空白字符的行 const nonEmptyLines = lines.filter(line =\u0026gt; line.trim() !== \u0026#39;\u0026#39;); proxyhosts = proxyhosts.concat(nonEmptyLines); } catch (error) { console.error(\u0026#39;获取地址时出错:\u0026#39;, error); } } // 使用Set对象去重 proxyhosts = [...new Set(proxyhosts)]; } newAddressesapi = await 整理优选列表(addressesapi); newAddressescsv = await 整理测速结果(\u0026#39;TRUE\u0026#39;); url = `https://${hostName}/${fakeUserID + _url.search}`; if (hostName.includes(\u0026#34;worker\u0026#34;) || hostName.includes(\u0026#34;notls\u0026#34;) || noTLS == \u0026#39;true\u0026#39;) { if (_url.search) url += \u0026#39;\u0026amp;notls\u0026#39;; else url += \u0026#39;?notls\u0026#39;; } console.log(`虚假订阅: ${url}`); } if (!userAgent.includes((\u0026#39;CF-Workers-SUB\u0026#39;).toLowerCase())) { if ((userAgent.includes(\u0026#39;clash\u0026#39;) \u0026amp;\u0026amp; !userAgent.includes(\u0026#39;nekobox\u0026#39;)) || (_url.searchParams.has(\u0026#39;clash\u0026#39;) \u0026amp;\u0026amp; !userAgent.includes(\u0026#39;subconverter\u0026#39;))) { url = `${subProtocol}://${subConverter}/sub?target=clash\u0026amp;url=${encodeURIComponent(url)}\u0026amp;insert=false\u0026amp;config=${encodeURIComponent(subConfig)}\u0026amp;emoji=${subEmoji}\u0026amp;list=false\u0026amp;tfo=false\u0026amp;scv=true\u0026amp;fdn=false\u0026amp;sort=false\u0026amp;new_name=true`; isBase64 = false; } else if (userAgent.includes(\u0026#39;sing-box\u0026#39;) || userAgent.includes(\u0026#39;singbox\u0026#39;) || ((_url.searchParams.has(\u0026#39;singbox\u0026#39;) || _url.searchParams.has(\u0026#39;sb\u0026#39;)) \u0026amp;\u0026amp; !userAgent.includes(\u0026#39;subconverter\u0026#39;))) { url = `${subProtocol}://${subConverter}/sub?target=singbox\u0026amp;url=${encodeURIComponent(url)}\u0026amp;insert=false\u0026amp;config=${encodeURIComponent(subConfig)}\u0026amp;emoji=${subEmoji}\u0026amp;list=false\u0026amp;tfo=false\u0026amp;scv=true\u0026amp;fdn=false\u0026amp;sort=false\u0026amp;new_name=true`; isBase64 = false; } } try { let content; if ((!sub || sub == \u0026#34;\u0026#34;) \u0026amp;\u0026amp; isBase64 == true) { content = await 生成本地订阅(fakeHostName, fakeUserID, noTLS, newAddressesapi, newAddressescsv, newAddressesnotlsapi, newAddressesnotlscsv); } else { const response = await fetch(url, { headers: { \u0026#39;User-Agent\u0026#39;: UA + atob(\u0026#39;IENGLVdvcmtlcnMtZWRnZXR1bm5lbC9jbWxpdQ==\u0026#39;) } }); content = await response.text(); } if (_url.pathname == `/${fakeUserID}`) return content; return 恢复伪装信息(content, userID, hostName, isBase64); } catch (error) { console.error(\u0026#39;Error fetching content:\u0026#39;, error); return `Error fetching content: ${error.message}`; } } } async function 整理优选列表(api) { if (!api || api.length === 0) return []; let newapi = \u0026#34;\u0026#34;; // 创建一个AbortController对象，用于控制fetch请求的取消 const controller = new AbortController(); const timeout = setTimeout(() =\u0026gt; { controller.abort(); // 取消所有请求 }, 2000); // 2秒后触发 try { // 使用Promise.allSettled等待所有API请求完成，无论成功或失败 // 对api数组进行遍历，对每个API地址发起fetch请求 const responses = await Promise.allSettled(api.map(apiUrl =\u0026gt; fetch(apiUrl, { method: \u0026#39;get\u0026#39;, headers: { \u0026#39;Accept\u0026#39;: \u0026#39;text/html,application/xhtml+xml,application/xml;\u0026#39;, \u0026#39;User-Agent\u0026#39;: atob(\u0026#39;Q0YtV29ya2Vycy1lZGdldHVubmVsL2NtbGl1\u0026#39;) }, signal: controller.signal // 将AbortController的信号量添加到fetch请求中，以便于需要时可以取消请求 }).then(response =\u0026gt; response.ok ? response.text() : Promise.reject()))); // 遍历所有响应 for (const [index, response] of responses.entries()) { // 检查响应状态是否为\u0026#39;fulfilled\u0026#39;，即请求成功完成 if (response.status === \u0026#39;fulfilled\u0026#39;) { // 获取响应的内容 const content = await response.value; const lines = content.split(/\\r?\\n/); let 节点备注 = \u0026#39;\u0026#39;; let 测速端口 = \u0026#39;443\u0026#39;; if (lines[0].split(\u0026#39;,\u0026#39;).length \u0026gt; 3) { const idMatch = api[index].match(/id=([^\u0026amp;]*)/); if (idMatch) 节点备注 = idMatch[1]; const portMatch = api[index].match(/port=([^\u0026amp;]*)/); if (portMatch) 测速端口 = portMatch[1]; for (let i = 1; i \u0026lt; lines.length; i++) { const columns = lines[i].split(\u0026#39;,\u0026#39;)[0]; if (columns) { newapi += `${columns}:${测速端口}${节点备注 ? `#${节点备注}` : \u0026#39;\u0026#39;}\\n`; if (api[index].includes(\u0026#39;proxyip=true\u0026#39;)) proxyIPPool.push(`${columns}:${测速端口}`); } } } else { // 验证当前apiUrl是否带有\u0026#39;proxyip=true\u0026#39; if (api[index].includes(\u0026#39;proxyip=true\u0026#39;)) { // 如果URL带有\u0026#39;proxyip=true\u0026#39;，则将内容添加到proxyIPPool proxyIPPool = proxyIPPool.concat((await 整理(content)).map(item =\u0026gt; { const baseItem = item.split(\u0026#39;#\u0026#39;)[0] || item; if (baseItem.includes(\u0026#39;:\u0026#39;)) { const port = baseItem.split(\u0026#39;:\u0026#39;)[1]; if (!httpsPorts.includes(port)) { return baseItem; } } else { return `${baseItem}:443`; } return null; // 不符合条件时返回 null }).filter(Boolean)); // 过滤掉 null 值 } // 将内容添加到newapi中 newapi += content + \u0026#39;\\n\u0026#39;; } } } } catch (error) { console.error(error); } finally { // 无论成功或失败，最后都清除设置的超时定时器 clearTimeout(timeout); } const newAddressesapi = await 整理(newapi); // 返回处理后的结果 return newAddressesapi; } async function 整理测速结果(tls) { if (!addressescsv || addressescsv.length === 0) { return []; } let newAddressescsv = []; for (const csvUrl of addressescsv) { try { const response = await fetch(csvUrl); if (!response.ok) { console.error(\u0026#39;获取CSV地址时出错:\u0026#39;, response.status, response.statusText); continue; } const text = await response.text();// 使用正确的字符编码解析文本内容 let lines; if (text.includes(\u0026#39;\\r\\n\u0026#39;)) { lines = text.split(\u0026#39;\\r\\n\u0026#39;); } else { lines = text.split(\u0026#39;\\n\u0026#39;); } // 检查CSV头部是否包含必需字段 const header = lines[0].split(\u0026#39;,\u0026#39;); const tlsIndex = header.indexOf(\u0026#39;TLS\u0026#39;); const ipAddressIndex = 0;// IP地址在 CSV 头部的位置 const portIndex = 1;// 端口在 CSV 头部的位置 const dataCenterIndex = tlsIndex + remarkIndex; // 数据中心是 TLS 的后一个字段 if (tlsIndex === -1) { console.error(\u0026#39;CSV文件缺少必需的字段\u0026#39;); continue; } // 从第二行开始遍历CSV行 for (let i = 1; i \u0026lt; lines.length; i++) { const columns = lines[i].split(\u0026#39;,\u0026#39;); const speedIndex = columns.length - 1; // 最后一个字段 // 检查TLS是否为\u0026#34;TRUE\u0026#34;且速度大于DLS if (columns[tlsIndex].toUpperCase() === tls \u0026amp;\u0026amp; parseFloat(columns[speedIndex]) \u0026gt; DLS) { const ipAddress = columns[ipAddressIndex]; const port = columns[portIndex]; const dataCenter = columns[dataCenterIndex]; const formattedAddress = `${ipAddress}:${port}#${dataCenter}`; newAddressescsv.push(formattedAddress); if (csvUrl.includes(\u0026#39;proxyip=true\u0026#39;) \u0026amp;\u0026amp; columns[tlsIndex].toUpperCase() == \u0026#39;true\u0026#39; \u0026amp;\u0026amp; !httpsPorts.includes(port)) { // 如果URL带有\u0026#39;proxyip=true\u0026#39;，则将内容添加到proxyIPPool proxyIPPool.push(`${ipAddress}:${port}`); } } } } catch (error) { console.error(\u0026#39;获取CSV地址时出错:\u0026#39;, error); continue; } } return newAddressescsv; } function 生成本地订阅(host, UUID, noTLS, newAddressesapi, newAddressescsv, newAddressesnotlsapi, newAddressesnotlscsv) { const regex = /^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|\\[.*\\]):?(\\d+)?#?(.*)?$/; addresses = addresses.concat(newAddressesapi); addresses = addresses.concat(newAddressescsv); let notlsresponseBody; if (noTLS == \u0026#39;true\u0026#39;) { addressesnotls = addressesnotls.concat(newAddressesnotlsapi); addressesnotls = addressesnotls.concat(newAddressesnotlscsv); const uniqueAddressesnotls = [...new Set(addressesnotls)]; notlsresponseBody = uniqueAddressesnotls.map(address =\u0026gt; { let port = \u0026#34;-1\u0026#34;; let addressid = address; const match = addressid.match(regex); if (!match) { if (address.includes(\u0026#39;:\u0026#39;) \u0026amp;\u0026amp; address.includes(\u0026#39;#\u0026#39;)) { const parts = address.split(\u0026#39;:\u0026#39;); address = parts[0]; const subParts = parts[1].split(\u0026#39;#\u0026#39;); port = subParts[0]; addressid = subParts[1]; } else if (address.includes(\u0026#39;:\u0026#39;)) { const parts = address.split(\u0026#39;:\u0026#39;); address = parts[0]; port = parts[1]; } else if (address.includes(\u0026#39;#\u0026#39;)) { const parts = address.split(\u0026#39;#\u0026#39;); address = parts[0]; addressid = parts[1]; } if (addressid.includes(\u0026#39;:\u0026#39;)) { addressid = addressid.split(\u0026#39;:\u0026#39;)[0]; } } else { address = match[1]; port = match[2] || port; addressid = match[3] || address; } const httpPorts = [\u0026#34;8080\u0026#34;, \u0026#34;8880\u0026#34;, \u0026#34;2052\u0026#34;, \u0026#34;2082\u0026#34;, \u0026#34;2086\u0026#34;, \u0026#34;2095\u0026#34;]; if (!isValidIPv4(address) \u0026amp;\u0026amp; port == \u0026#34;-1\u0026#34;) { for (let httpPort of httpPorts) { if (address.includes(httpPort)) { port = httpPort; break; } } } if (port == \u0026#34;-1\u0026#34;) port = \u0026#34;80\u0026#34;; let 伪装域名 = host; let 最终路径 = path; let 节点备注 = \u0026#39;\u0026#39;; const 协议类型 = atob(啥啥啥_写的这是啥啊); const 维列斯Link = `${协议类型}://${UUID}@${address}:${port + atob(\u0026#39;P2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT0mdHlwZT13cyZob3N0PQ==\u0026#39;) + 伪装域名}\u0026amp;path=${encodeURIComponent(最终路径)}#${encodeURIComponent(addressid + 节点备注)}`; return 维列斯Link; }).join(\u0026#39;\\n\u0026#39;); } // 使用Set对象去重 const uniqueAddresses = [...new Set(addresses)]; const responseBody = uniqueAddresses.map(address =\u0026gt; { let port = \u0026#34;-1\u0026#34;; let addressid = address; const match = addressid.match(regex); if (!match) { if (address.includes(\u0026#39;:\u0026#39;) \u0026amp;\u0026amp; address.includes(\u0026#39;#\u0026#39;)) { const parts = address.split(\u0026#39;:\u0026#39;); address = parts[0]; const subParts = parts[1].split(\u0026#39;#\u0026#39;); port = subParts[0]; addressid = subParts[1]; } else if (address.includes(\u0026#39;:\u0026#39;)) { const parts = address.split(\u0026#39;:\u0026#39;); address = parts[0]; port = parts[1]; } else if (address.includes(\u0026#39;#\u0026#39;)) { const parts = address.split(\u0026#39;#\u0026#39;); address = parts[0]; addressid = parts[1]; } if (addressid.includes(\u0026#39;:\u0026#39;)) { addressid = addressid.split(\u0026#39;:\u0026#39;)[0]; } } else { address = match[1]; port = match[2] || port; addressid = match[3] || address; } if (!isValidIPv4(address) \u0026amp;\u0026amp; port == \u0026#34;-1\u0026#34;) { for (let httpsPort of httpsPorts) { if (address.includes(httpsPort)) { port = httpsPort; break; } } } if (port == \u0026#34;-1\u0026#34;) port = \u0026#34;443\u0026#34;; let 伪装域名 = host; let 最终路径 = path; let 节点备注 = \u0026#39;\u0026#39;; const matchingProxyIP = proxyIPPool.find(proxyIP =\u0026gt; proxyIP.includes(address)); if (matchingProxyIP) 最终路径 += `\u0026amp;proxyip=${matchingProxyIP}`; if (proxyhosts.length \u0026gt; 0 \u0026amp;\u0026amp; (伪装域名.includes(\u0026#39;.workers.dev\u0026#39;))) { 最终路径 = `/${伪装域名}${最终路径}`; 伪装域名 = proxyhosts[Math.floor(Math.random() * proxyhosts.length)]; 节点备注 = ` 已启用临时域名中转服务，请尽快绑定自定义域！`; } const 协议类型 = atob(啥啥啥_写的这是啥啊); const 维列斯Link = `${协议类型}://${UUID}@${address}:${port + atob(\u0026#39;P2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT10bHMmc25pPQ==\u0026#39;) + 伪装域名}\u0026amp;fp=random\u0026amp;type=ws\u0026amp;host=${伪装域名}\u0026amp;path=${encodeURIComponent(最终路径)}#${encodeURIComponent(addressid + 节点备注)}`; return 维列斯Link; }).join(\u0026#39;\\n\u0026#39;); let base64Response = responseBody; // 重新进行 Base64 编码 if (noTLS == \u0026#39;true\u0026#39;) base64Response += `\\n${notlsresponseBody}`; if (link.length \u0026gt; 0) base64Response += \u0026#39;\\n\u0026#39; + link.join(\u0026#39;\\n\u0026#39;); return btoa(base64Response); } async function 整理(内容) { // 将制表符、双引号、单引号和换行符都替换为逗号 // 然后将连续的多个逗号替换为单个逗号 var 替换后的内容 = 内容.replace(/[ |\u0026#34;\u0026#39;\\r\\n]+/g, \u0026#39;,\u0026#39;).replace(/,+/g, \u0026#39;,\u0026#39;); // 删除开头和结尾的逗号（如果有的话） if (替换后的内容.charAt(0) == \u0026#39;,\u0026#39;) 替换后的内容 = 替换后的内容.slice(1); if (替换后的内容.charAt(替换后的内容.length - 1) == \u0026#39;,\u0026#39;) 替换后的内容 = 替换后的内容.slice(0, 替换后的内容.length - 1); // 使用逗号分割字符串，得到地址数组 const 地址数组 = 替换后的内容.split(\u0026#39;,\u0026#39;); return 地址数组; } async function sendMessage(type, ip, add_data = \u0026#34;\u0026#34;) { if (!BotToken || !ChatID) return; try { let msg = \u0026#34;\u0026#34;; const response = await fetch(`http://ip-api.com/json/${ip}?lang=zh-CN`); if (response.ok) { const ipInfo = await response.json(); msg = `${type}\\nIP: ${ip}\\n国家: ${ipInfo.country}\\n\u0026lt;tg-spoiler\u0026gt;城市: ${ipInfo.city}\\n组织: ${ipInfo.org}\\nASN: ${ipInfo.as}\\n${add_data}`; } else { msg = `${type}\\nIP: ${ip}\\n\u0026lt;tg-spoiler\u0026gt;${add_data}`; } const url = `https://api.telegram.org/bot${BotToken}/sendMessage?chat_id=${ChatID}\u0026amp;parse_mode=HTML\u0026amp;text=${encodeURIComponent(msg)}`; return fetch(url, { method: \u0026#39;GET\u0026#39;, headers: { \u0026#39;Accept\u0026#39;: \u0026#39;text/html,application/xhtml+xml,application/xml;\u0026#39;, \u0026#39;Accept-Encoding\u0026#39;: \u0026#39;gzip, deflate, br\u0026#39;, \u0026#39;User-Agent\u0026#39;: \u0026#39;Mozilla/5.0 Chrome/90.0.4430.72\u0026#39; } }); } catch (error) { console.error(\u0026#39;Error sending message:\u0026#39;, error); } } function isValidIPv4(address) { const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; return ipv4Regex.test(address); } function 生成动态UUID(密钥) { const 时区偏移 = 8; // 北京时间相对于UTC的时区偏移+8小时 const 起始日期 = new Date(2007, 6, 7, 更新时间, 0, 0); // 固定起始日期为2007年7月7日的凌晨3点 const 一周的毫秒数 = 1000 * 60 * 60 * 24 * 有效时间; function 获取当前周数() { const 现在 = new Date(); const 调整后的现在 = new Date(现在.getTime() + 时区偏移 * 60 * 60 * 1000); const 时间差 = Number(调整后的现在) - Number(起始日期); return Math.ceil(时间差 / 一周的毫秒数); } function 生成UUID(基础字符串) { const 哈希缓冲区 = new TextEncoder().encode(基础字符串); return crypto.subtle.digest(\u0026#39;SHA-256\u0026#39;, 哈希缓冲区).then((哈希) =\u0026gt; { const 哈希数组 = Array.from(new Uint8Array(哈希)); const 十六进制哈希 = 哈希数组.map(b =\u0026gt; b.toString(16).padStart(2, \u0026#39;0\u0026#39;)).join(\u0026#39;\u0026#39;); return `${十六进制哈希.substr(0, 8)}-${十六进制哈希.substr(8, 4)}-4${十六进制哈希.substr(13, 3)}-${(parseInt(十六进制哈希.substr(16, 2), 16) \u0026amp; 0x3f | 0x80).toString(16)}${十六进制哈希.substr(18, 2)}-${十六进制哈希.substr(20, 12)}`; }); } const 当前周数 = 获取当前周数(); // 获取当前周数 const 结束时间 = new Date(起始日期.getTime() + 当前周数 * 一周的毫秒数); // 生成两个 UUID const 当前UUIDPromise = 生成UUID(密钥 + 当前周数); const 上一个UUIDPromise = 生成UUID(密钥 + (当前周数 - 1)); // 格式化到期时间 const 到期时间UTC = new Date(结束时间.getTime() - 时区偏移 * 60 * 60 * 1000); // UTC时间 const 到期时间字符串 = `到期时间(UTC): ${到期时间UTC.toISOString().slice(0, 19).replace(\u0026#39;T\u0026#39;, \u0026#39; \u0026#39;)} (UTC+8): ${结束时间.toISOString().slice(0, 19).replace(\u0026#39;T\u0026#39;, \u0026#39; \u0026#39;)}\\n`; return Promise.all([当前UUIDPromise, 上一个UUIDPromise, 到期时间字符串]); } async function 迁移地址列表(env, txt = \u0026#39;ADD.txt\u0026#39;) { const 旧数据 = await env.KV.get(`/${txt}`); const 新数据 = await env.KV.get(txt); if (旧数据 \u0026amp;\u0026amp; !新数据) { // 写入新位置 await env.KV.put(txt, 旧数据); // 删除旧数据 await env.KV.delete(`/${txt}`); return true; } return false; } async function KV(request, env, txt = \u0026#39;ADD.txt\u0026#39;) { try { // POST请求处理 if (request.method === \u0026#34;POST\u0026#34;) { if (!env.KV) return new Response(\u0026#34;未绑定KV空间\u0026#34;, { status: 400 }); try { const content = await request.text(); await env.KV.put(txt, content); return new Response(\u0026#34;保存成功\u0026#34;); } catch (error) { console.error(\u0026#39;保存KV时发生错误:\u0026#39;, error); return new Response(\u0026#34;保存失败: \u0026#34; + error.message, { status: 500 }); } } // GET请求部分 let content = \u0026#39;\u0026#39;; let hasKV = !!env.KV; if (hasKV) { try { content = await env.KV.get(txt) || \u0026#39;\u0026#39;; } catch (error) { console.error(\u0026#39;读取KV时发生错误:\u0026#39;, error); content = \u0026#39;读取数据时发生错误: \u0026#39; + error.message; } } const html = ` \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;优选订阅列表\u0026lt;/title\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1\u0026#34;\u0026gt; \u0026lt;style\u0026gt; body { margin: 0; padding: 15px; /* 调整padding */ box-sizing: border-box; font-size: 13px; /* 设置全局字体大小 */ } .editor-container { width: 100%; max-width: 100%; margin: 0 auto; } .editor { width: 100%; height: 520px; /* 调整高度 */ margin: 15px 0; /* 调整margin */ padding: 10px; /* 调整padding */ box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px; font-size: 13px; line-height: 1.5; overflow-y: auto; resize: none; } .save-container { margin-top: 8px; /* 调整margin */ display: flex; align-items: center; gap: 10px; /* 调整gap */ } .save-btn, .back-btn { padding: 6px 15px; /* 调整padding */ color: white; border: none; border-radius: 4px; cursor: pointer; } .save-btn { background: #4CAF50; } .save-btn:hover { background: #45a049; } .back-btn { background: #666; } .back-btn:hover { background: #555; } .save-status { color: #666; } .notice-content { display: none; margin-top: 10px; font-size: 13px; color: #333; } \u0026lt;/style\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; ################################################################\u0026lt;br\u0026gt; ${FileName} 优选订阅列表:\u0026lt;br\u0026gt; ---------------------------------------------------------------\u0026lt;br\u0026gt; \u0026lt;strong\u0026gt;\u0026lt;a href=\u0026#34;javascript:void(0);\u0026#34; id=\u0026#34;noticeToggle\u0026#34; onclick=\u0026#34;toggleNotice()\u0026#34;\u0026gt;注意事项∨\u0026lt;/a\u0026gt;\u0026lt;/strong\u0026gt;\u0026lt;br\u0026gt; \u0026lt;div id=\u0026#34;noticeContent\u0026#34; class=\u0026#34;notice-content\u0026#34;\u0026gt; ${decodeURIComponent(atob(\u0026#39;JTA5JTA5JTA5JTA5JTA5JTNDc3Ryb25nJTNFMS4lM0MlMkZzdHJvbmclM0UlMjBBRERBUEklMjAlRTUlQTYlODIlRTYlOUUlOUMlRTYlOTglQUYlRTUlOEYlOEQlRTQlQkIlQTNJUCVFRiVCQyU4QyVFNSU4RiVBRiVFNCVCRCU5QyVFNCVCOCVCQVBST1hZSVAlRTclOUElODQlRTglQUYlOUQlRUYlQkMlOEMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwcm94eWlwJTNEdHJ1ZSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGYWRkcmVzc2VzYXBpLnR4dCUzQ3N0cm9uZyUzRSUzRnByb3h5aXAlM0R0cnVlJTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklM0NzdHJvbmclM0UyLiUzQyUyRnN0cm9uZyUzRSUyMEFEREFQSSUyMCVFNSVBNiU4MiVFNiU5RSU5QyVFNiU5OCVBRiUyMCUzQ2ElMjBocmVmJTNEJTI3aHR0cHMlM0ElMkYlMkZnaXRodWIuY29tJTJGWElVMiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QlMjclM0VDbG91ZGZsYXJlU3BlZWRUZXN0JTNDJTJGYSUzRSUyMCVFNyU5QSU4NCUyMGNzdiUyMCVFNyVCQiU5MyVFNiU5RSU5QyVFNiU5NiU4NyVFNCVCQiVCNiVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NiciUzRSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCLSUyMCVFNSVBNiU4MiVFOSU5QyU4MCVFNiU4QyU4NyVFNSVBRSU5QTIwNTMlRTclQUIlQUYlRTUlOEYlQTMlRTUlOEYlQUYlRTUlQjAlODYlMjIlM0Zwb3J0JTNEMjA1MyUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0Zwb3J0JTNEMjA1MyUzQyUyRnN0cm9uZyUzRSUzQ2JyJTNFJTNDYnIlM0UKJTA5JTA5JTA5JTA5JTA5JTI2bmJzcCUzQiUyNm5ic3AlM0ItJTIwJUU1JUE2JTgyJUU5JTlDJTgwJUU2JThDJTg3JUU1JUFFJTlBJUU4JThBJTgyJUU3JTgyJUI5JUU1JUE0JTg3JUU2JUIzJUE4JUU1JThGJUFGJUU1JUIwJTg2JTIyJTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUyMiVFNSU4RiU4MiVFNiU5NSVCMCVFNiVCNyVCQiVFNSU4QSVBMCVFNSU4OCVCMCVFOSU5MyVCRSVFNiU4RSVBNSVFNiU5QyVBQiVFNSVCMCVCRSVFRiVCQyU4QyVFNCVCRSU4QiVFNSVBNiU4MiVFRiVCQyU5QSUzQ2JyJTNFCiUwOSUwOSUwOSUwOSUwOSUyNm5ic3AlM0IlMjZuYnNwJTNCaHR0cHMlM0ElMkYlMkZyYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tJTJGY21saXUlMkZXb3JrZXJWbGVzczJzdWIlMkZtYWluJTJGQ2xvdWRmbGFyZVNwZWVkVGVzdC5jc3YlM0NzdHJvbmclM0UlM0ZpZCUzRENGJUU0JUJDJTk4JUU5JTgwJTg5JTNDJTJGc3Ryb25nJTNFJTNDYnIlM0UlM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQi0lMjAlRTUlQTYlODIlRTklOUMlODAlRTYlOEMlODclRTUlQUUlOUElRTUlQTQlOUElRTQlQjglQUElRTUlOEYlODIlRTYlOTUlQjAlRTUlODglOTklRTklOUMlODAlRTglQTYlODElRTQlQkQlQkYlRTclOTQlQTglMjclMjYlMjclRTUlODElOUElRTklOTclQjQlRTklOUElOTQlRUYlQkMlOEMlRTQlQkUlOEIlRTUlQTYlODIlRUYlQkMlOUElM0NiciUzRQolMDklMDklMDklMDklMDklMjZuYnNwJTNCJTI2bmJzcCUzQmh0dHBzJTNBJTJGJTJGcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSUyRmNtbGl1JTJGV29ya2VyVmxlc3Myc3ViJTJGbWFpbiUyRkNsb3VkZmxhcmVTcGVlZFRlc3QuY3N2JTNGaWQlM0RDRiVFNCVCQyU5OCVFOSU4MCU4OSUzQ3N0cm9uZyUzRSUyNiUzQyUyRnN0cm9uZyUzRXBvcnQlM0QyMDUzJTNDYnIlM0U=\u0026#39;))} \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;editor-container\u0026#34;\u0026gt; ${hasKV ? ` \u0026lt;textarea class=\u0026#34;editor\u0026#34; placeholder=\u0026#34;${decodeURIComponent(atob(\u0026#39;QUREJUU3JUE0JUJBJUU0JUJFJThCJUVGJUJDJTlBCnZpc2EuY24lMjMlRTQlQkMlOTglRTklODAlODklRTUlOUYlOUYlRTUlOTAlOEQKMTI3LjAuMC4xJTNBMTIzNCUyM0NGbmF0CiU1QjI2MDYlM0E0NzAwJTNBJTNBJTVEJTNBMjA1MyUyM0lQdjYKCiVFNiVCMyVBOCVFNiU4NCU4RiVFRiVCQyU5QQolRTYlQUYlOEYlRTglQTElOEMlRTQlQjglODAlRTQlQjglQUElRTUlOUMlQjAlRTUlOUQlODAlRUYlQkMlOEMlRTYlQTAlQkMlRTUlQkMlOEYlRTQlQjglQkElMjAlRTUlOUMlQjAlRTUlOUQlODAlM0ElRTclQUIlQUYlRTUlOEYlQTMlMjMlRTUlQTQlODclRTYlQjMlQTgKSVB2NiVFNSU5QyVCMCVFNSU5RCU4MCVFOSU5QyU4MCVFOCVBNiU4MSVFNyU5NCVBOCVFNCVCOCVBRCVFNiU4QiVBQyVFNSU4RiVCNyVFNiU4QiVBQyVFOCVCNSVCNyVFNiU5RCVBNSVFRiVCQyU4QyVFNSVBNiU4MiVFRiVCQyU5QSU1QjI2MDYlM0E0NzAwJTNBJTNBJTVEJTNBMjA1MwolRTclQUIlQUYlRTUlOEYlQTMlRTQlQjglOEQlRTUlODYlOTklRUYlQkMlOEMlRTklQkIlOTglRTglQUUlQTQlRTQlQjglQkElMjA0NDMlMjAlRTclQUIlQUYlRTUlOEYlQTMlRUYlQkMlOEMlRTUlQTYlODIlRUYlQkMlOUF2aXNhLmNuJTIzJUU0JUJDJTk4JUU5JTgwJTg5JUU1JTlGJTlGJUU1JTkwJThECgoKQUREQVBJJUU3JUE0JUJBJUU0JUJFJThCJUVGJUJDJTlBCmh0dHBzJTNBJTJGJTJGcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSUyRmNtbGl1JTJGV29ya2VyVmxlc3Myc3ViJTJGcmVmcyUyRmhlYWRzJTJGbWFpbiUyRmFkZHJlc3Nlc2FwaS50eHQKCiVFNiVCMyVBOCVFNiU4NCU4RiVFRiVCQyU5QUFEREFQSSVFNyU5QiVCNCVFNiU4RSVBNSVFNiVCNyVCQiVFNSU4QSVBMCVFNyU5QiVCNCVFOSU5MyVCRSVFNSU4RCVCMyVFNSU4RiVBRg==\u0026#39;))}\u0026#34; id=\u0026#34;content\u0026#34;\u0026gt;${content}\u0026lt;/textarea\u0026gt; \u0026lt;div class=\u0026#34;save-container\u0026#34;\u0026gt; \u0026lt;button class=\u0026#34;back-btn\u0026#34; onclick=\u0026#34;goBack()\u0026#34;\u0026gt;返回配置页\u0026lt;/button\u0026gt; \u0026lt;button class=\u0026#34;save-btn\u0026#34; onclick=\u0026#34;saveContent(this)\u0026#34;\u0026gt;保存\u0026lt;/button\u0026gt; \u0026lt;span class=\u0026#34;save-status\u0026#34; id=\u0026#34;saveStatus\u0026#34;\u0026gt;\u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;br\u0026gt; ################################################################\u0026lt;br\u0026gt; ${cmad} ` : \u0026#39;\u0026lt;p\u0026gt;未绑定KV空间\u0026lt;/p\u0026gt;\u0026#39;} \u0026lt;/div\u0026gt; \u0026lt;script\u0026gt; if (document.querySelector(\u0026#39;.editor\u0026#39;)) { let timer; const textarea = document.getElementById(\u0026#39;content\u0026#39;); const originalContent = textarea.value; function goBack() { const currentUrl = window.location.href; const parentUrl = currentUrl.substring(0, currentUrl.lastIndexOf(\u0026#39;/\u0026#39;)); window.location.href = parentUrl; } function replaceFullwidthColon() { const text = textarea.value; textarea.value = text.replace(/：/g, \u0026#39;:\u0026#39;); } function saveContent(button) { try { const updateButtonText = (step) =\u0026gt; { button.textContent = \\`保存中: \\${step}\\`; }; // 检测是否为iOS设备 const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); // 仅在非iOS设备上执行replaceFullwidthColon if (!isIOS) { replaceFullwidthColon(); } updateButtonText(\u0026#39;开始保存\u0026#39;); button.disabled = true; // 获取textarea内容和原始内容 const textarea = document.getElementById(\u0026#39;content\u0026#39;); if (!textarea) { throw new Error(\u0026#39;找不到文本编辑区域\u0026#39;); } updateButtonText(\u0026#39;获取内容\u0026#39;); let newContent; let originalContent; try { newContent = textarea.value || \u0026#39;\u0026#39;; originalContent = textarea.defaultValue || \u0026#39;\u0026#39;; } catch (e) { console.error(\u0026#39;获取内容错误:\u0026#39;, e); throw new Error(\u0026#39;无法获取编辑内容\u0026#39;); } updateButtonText(\u0026#39;准备状态更新函数\u0026#39;); const updateStatus = (message, isError = false) =\u0026gt; { const statusElem = document.getElementById(\u0026#39;saveStatus\u0026#39;); if (statusElem) { statusElem.textContent = message; statusElem.style.color = isError ? \u0026#39;red\u0026#39; : \u0026#39;#666\u0026#39;; } }; updateButtonText(\u0026#39;准备按钮重置函数\u0026#39;); const resetButton = () =\u0026gt; { button.textContent = \u0026#39;保存\u0026#39;; button.disabled = false; }; if (newContent !== originalContent) { updateButtonText(\u0026#39;发送保存请求\u0026#39;); fetch(window.location.href, { method: \u0026#39;POST\u0026#39;, body: newContent, headers: { \u0026#39;Content-Type\u0026#39;: \u0026#39;text/plain;charset=UTF-8\u0026#39; }, cache: \u0026#39;no-cache\u0026#39; }) .then(response =\u0026gt; { updateButtonText(\u0026#39;检查响应状态\u0026#39;); if (!response.ok) { throw new Error(\\`HTTP error! status: \\${response.status}\\`); } updateButtonText(\u0026#39;更新保存状态\u0026#39;); const now = new Date().toLocaleString(); document.title = \\`编辑已保存 \\${now}\\`; updateStatus(\\`已保存 \\${now}\\`); }) .catch(error =\u0026gt; { updateButtonText(\u0026#39;处理错误\u0026#39;); console.error(\u0026#39;Save error:\u0026#39;, error); updateStatus(\\`保存失败: \\${error.message}\\`, true); }) .finally(() =\u0026gt; { resetButton(); }); } else { updateButtonText(\u0026#39;检查内容变化\u0026#39;); updateStatus(\u0026#39;内容未变化\u0026#39;); resetButton(); } } catch (error) { console.error(\u0026#39;保存过程出错:\u0026#39;, error); button.textContent = \u0026#39;保存\u0026#39;; button.disabled = false; const statusElem = document.getElementById(\u0026#39;saveStatus\u0026#39;); if (statusElem) { statusElem.textContent = \\`错误: \\${error.message}\\`; statusElem.style.color = \u0026#39;red\u0026#39;; } } } textarea.addEventListener(\u0026#39;blur\u0026#39;, saveContent); textarea.addEventListener(\u0026#39;input\u0026#39;, () =\u0026gt; { clearTimeout(timer); timer = setTimeout(saveContent, 5000); }); } function toggleNotice() { const noticeContent = document.getElementById(\u0026#39;noticeContent\u0026#39;); const noticeToggle = document.getElementById(\u0026#39;noticeToggle\u0026#39;); if (noticeContent.style.display === \u0026#39;none\u0026#39; || noticeContent.style.display === \u0026#39;\u0026#39;) { noticeContent.style.display = \u0026#39;block\u0026#39;; noticeToggle.textContent = \u0026#39;注意事项∧\u0026#39;; } else { noticeContent.style.display = \u0026#39;none\u0026#39;; noticeToggle.textContent = \u0026#39;注意事项∨\u0026#39;; } } // 初始化 noticeContent 的 display 属性 document.addEventListener(\u0026#39;DOMContentLoaded\u0026#39;, () =\u0026gt; { document.getElementById(\u0026#39;noticeContent\u0026#39;).style.display = \u0026#39;none\u0026#39;; }); \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; `; return new Response(html, { headers: { \u0026#34;Content-Type\u0026#34;: \u0026#34;text/html;charset=utf-8\u0026#34; } }); } catch (error) { console.error(\u0026#39;处理请求时发生错误:\u0026#39;, error); return new Response(\u0026#34;服务器错误: \u0026#34; + error.message, { status: 500, headers: { \u0026#34;Content-Type\u0026#34;: \u0026#34;text/plain;charset=utf-8\u0026#34; } }); } } 域名 注册一个免费的域名，可以使用零度前几期介绍的注册方法，来获取你自己的免费域名 【点击前往】 当然如果你已经有域名那么更好！ 有域名就可以添加进自定义域了\nUUID 在设置中，找到 变量与机密 ，添加一条，标题为\nUUID 值自己随意定，假设值为\n114514 访问 打开浏览器，输入你的自定义域，并在结尾加上\n/114514 如果前一步的值为其他值，则填入\n/其他值 优选 如果想获得更多的优质节点，那么推荐使用IP优选网站或优选工具进行获取！【点击前往】\n视频链接 https://youtu.be/DYGu71OaqGI\n","date":"2025-07-14T09:37:49+08:00","image":"/images/cf.webp","permalink":"/posts/%E9%80%9A%E8%BF%87cloudflare%E7%9A%84worker%E5%92%8Cpages%E6%90%AD%E5%BB%BA%E6%B0%B8%E4%B9%85%E5%85%8D%E8%B4%B9%E7%9A%84vpn/","title":"通过Cloudflare的worker和Pages搭建永久免费的VPN"},{"content":"作者：阿菲什 690 总结 命运的手将他推入名为卡斯兰娜的囚笼\n笔记 魔女凯文 × 还没有成为魔女的白厄 均双性磨批 魔力传递的方式，简单理解就是体液交换吧） （更多注释见作品结尾。魔女凯文 x 还没有成为魔女的白厄，均为双性。魔力传递的方式，简单理解为体液交换吧）\n正文 白厄不知道自己已经在这里住了多少年，自从有记忆起，他就在这座古堡和名为凯文的魔女一同生活。 虽然说是魔女，但实际上凯文却是男性，他曾不止一次和自己解释过，魔女只是一种称谓，他并不是女性也不是他的母亲，但那时小小的他并不太理解，不过幸好，这片林子因为凯文的存在很少有人会来，所以他也并不需要和别人再去解释了。\n“铛……”不知年岁的钟一如既往地响起，又一天过去了，白厄在床上翻滚着，明明已是午夜，他却毫无困意。 其实白厄已经很多天没见过凯文了，他似乎在做什么神秘的仪式，白厄问了很多次但他却一直含糊其辞。 他还挺喜欢那些奇奇怪怪的魔法，每次发动时都会有五颜六色的光点环绕着凯文，像绚丽的烟火，他背着凯文偷偷去镇子上看的。 但凯文说什么也不肯教给他，只让他做些打下手的工作，准备药草什么的。\n其实，这么多天见不到凯文也是很正常的，他知道凯文经常有很多工作需要忙，但今天就是他的十六岁生日了，凯文不会忘记了吧，白厄有些失落，说好了会给他准备礼物的……\n白厄坐在床边望着窗外，满月高挂，撒满他的发丝。 这个房间的窗户正面向着森林边缘的小镇，他自己选的。 古堡里很昏暗，照明用的还是古老的白蜡，虽然白厄从未见过它们熄灭的时候，但他还是觉得这些蜡烛太昏暗了，他更喜欢镇子里那些明亮的油灯和篝火，燃烧着的火焰让他恐惧的同时却也能感到温暖，古堡里太冰冷了。\n他想起多年前第一次去小镇上玩时，那是他第一次见到那么多人，他们有着不同的发色，黑色的，黄色的，唯独没有和他或者凯文一样的白色。 白厄站在森林的边缘，远远望着围着篝火起舞的人群，他们的脸上洋溢着笑容和幸福，不同服装的人，不同年龄的人，他们围在一起庆贺着节日。 白厄感到新奇，这对一个孩子来说是在有着不小的诱惑，更何况是他这样的，从未离开过森林的魔女的孩子。\n于是白厄向着镇子跑去。\n后面发生了什么，他已经记不清了，火光，咒骂声，尖叫声，木棍抽打在身上，火焰灼烧皮肉的痛楚，后来呢，他失去了意识，模模糊糊间，凯文藏在斗篷下的白发是他最后见到的色彩。\n人们厌恶魔女强大的力量，即使那位叫做凯文的魔女从未做过伤害他们的事，但人就是这样，害怕未知的东西，而这奇异的发色便是判别魔女最直接的手段。\n自那之后，白厄时常会梦到，他的双手被钉在十字架上，无尽的火焰将他的血液当做助燃剂，他无助地想要大叫，寻找那个从小陪伴他的“妈妈”，但火舌已经顺着伤口钻进躯体，灼烧般的痛苦将他一次又一次从睡梦中惊醒。\n没过多久，白厄拥有了属于自己的斗篷，凯文亲手缝制的，黑紫色的，镶着金色丝带的宽大斗篷，即使他长得和凯文一样高也能遮住他这头杂乱的白发，抱着灌注了魔力的斗篷入眠，少年的梦再未被火焰侵扰。\n意识回到现在，白厄抱着斗篷缩在床上，鼻腔间是药草的香气，和凯文身上的很像。 他有些生气的将脸狠狠埋了进去却赌气般的不吸气。\n凯文答应过他了的，明明已经过了 12 点了，要是他再不来，我就自己跑出去玩！ 白厄愤愤的想着，却仍没有离开斗篷。 他扭动着将自己整个缩进斗篷里，被冰冷气息环绕的感觉莫名让他安心，甚至有些昏昏欲睡。\n“吱呀——”厚重的木门被推开，凯文踏着月光走了进来。 “白厄，睡了吗。” 刚一听到动静，白厄就又来了精神，“没有哦，凯文你终于出来了，我等你等了好久，我还以为你忘记了呢……”毛茸茸的白色脑袋钻出斗篷朝凯文笑到，“凯文这几天那么忙，就算没有准备礼物也没关系的，有你在我就很开心了！ ”\n凯文沉默着走进房间，挥手点亮昏暗的烛火，在床沿坐下，看着跪坐在床上的白厄。 一晃眼十几年就过去了，白厄已经从连话都说不清的小孩长成了如今能说会道的少年。 虽然脸上还带着点未褪的婴儿肥，但身高却已抽条的比他自己还高了些。 凯文盯着面前这张相似的面容，少年眼底的稚嫩尚未褪去，但留给他的时间不多了，他不知道自己还能拖多久，这是他，这是他们，必须背负的命运。\n深叹了口气，凯文翻身上床。 他们靠的很近，近的凯文能看清白厄每一根细长的睫毛，近的白厄也能看到凯文宽松的外袍下纤细的锁骨和若隐若现的胸肌。 相同的蓝在二人眼中流转，无需多言，今晚过后，他会明白他所有的一切。\n趁着白厄还在思考他会送自己什么礼物时，凯文已经栖身而上，将发呆的白厄压在床上。 白厄愣了一下才回过神来，“诶？ 等等凯文，这就是礼物吗。 ”他将手搭在凯文肩上，湛蓝眼睛里带着些惊讶却不躲闪，动作也没有停下，还刻意用膝盖顶了顶凯文。 白发魔女面上不显心里却暗暗吐槽着现在的小孩子怎么懂这么多……\n“你之前，不是一直想学？ 现在，我会把我的一切都教给你。 ”凯文没有正面回话，说起来另一个话题。\n“是，这种教法吗？ 如果是凯文的话也不是不可以啦……”白厄一看凯文是来真的，有些欣喜又有些担忧，凯文怎么突然就答应要教他了，还愿意和他做这种事。\n那时的白厄，十一二岁正是好奇心旺盛的年纪，对那些在古堡见不到的图画书自然更觉新奇。 童年模糊的经历完全无法抑制少年放荡的心，他见着那些没见过的书便想着带回去给凯文，结果晚上睡觉前把书拿给凯文后却被他收走，还警告自己不准再看了。 凯文虽然没多说什么但白厄还是注意到了他绯红的耳尖。 后来长大了些，接触的多了这些东西自然也就懂了。\n隔在两人间的斗篷被白厄踢到一旁，四目相对间，白厄似乎在那无尽的蓝里看到一抹转瞬即逝的无奈与悲伤。 那是什么？ 白厄无声的发问，凯文没有回答也没有动作，仿佛是在向他下达最后通牒——现在你还要拒绝的机会。\n但白厄是谁，拒绝？ 念头在脑海里停留不过一秒就被丢弃。 既然如此，那他就要用行动来表明自己的态度了。\n松垮的袍子被轻而易举的扯下，因常年不见阳光而白皙的皮肤暴露在空气中。 白厄暗暗对比着两人的胸肌，明明凯文是连年龄都记不清了的大魔女，胸肌居然比自己的还要薄上一些，大概是因为自己没有那么强的魔力所以事事都要做亲力亲为吧，凯文也太缺乏锻炼了！\n凯文也不再停滞，几下就将白厄全身的衣服除去，随意一挥又叠好放在床头。 他自己早就一丝不挂了，来之前就做足了准备，却不想这才一会儿功夫，湿润的女穴就开始有了淌水的迹象。\n有着相似容貌的二人连身体都那么相像，或许是因为魔女的血脉，身为男人却有着一套女性的器官。\n白厄有些好奇的抚过凯文的胯骨，他对此仅仅是了解，还从未见过这般，被淫水打的波光粼粼的嫩红穴口，他还想去摸，却被凯文俯身的动作打断。 粗粝的鼻息打在白厄脖颈的太阳纹上，下一秒，湿漉漉的舌描着纹路向下滑去。 唇纹贴合着脖颈的血管，此刻，它正因紧张而激烈跳动着，血液奔涌向大脑，在白皙的面颊染上红晕。\n对从未被如此对待过的雏鸟来说，仅仅是这样的动作就足够引发他颤栗。 “嗯…… 哈……”他仰头轻哼着，毫无经验的连手应该放在哪儿都不知道，只能轻环着凯文的腰，想以此获取些许安慰。\n凯文还在继续向下，舔过胸前金色的纹路又在锁骨扣下一个整齐的牙印后，他轻吻上了少年的胸乳。 少年粉嫩的乳头还是内陷的，凯文不敢用力，小心翼翼的用舌尖顶弄着，“唔啊！ 哈…… 别…… 嗯啊…… 凯文，好，好奇怪……”白厄颤抖着挺胸将乳肉送向凯文，微微充血的肌肉此刻不比刚刚柔软却更显丰韵，一边红樱被舔水润，因充血而不再内陷，连带着另一侧未被爱抚的乳尖也有了些冒头的趋势。\n男人一手撑着另一只手牵引着白厄抚上自己的胸膛，少年无师自通的揉捏着乳肉，从一侧向中间聚拢，本就不多的乳肉被完全包裹在手间。 他学着凯文的动作去摸乳尖，却发现那里早在摩擦间就已经硬挺。\n低喘声回荡在房间，传入白厄的耳中，让本就发热的大脑更加混乱。 凯文的脸上挂着的绯红在白嫩的皮肤间更加显眼，烛火倒影在他冰蓝的眼底，在白厄看来仿佛是那欲火。\n凯文引导着白厄靠在床头，跪立在白厄腿间，报复般强硬的用膝盖分开少年的双腿。 他抹了把穴口的淫水，借此润滑将两根半勃的性器握在一起上下撸动。 他的手法一般，公事公办的态度弄的白厄甚至感觉有点痛，但敏感的器官和喜欢的人的炽热阴茎贴在一起就足以让他亢奋，他能感觉到此刻自己的性器正在凯文手中跳动。\n“唔啊，凯文…… 再，快点…… 嗯…… 想，想射……”白厄贴在凯文耳边低吟着。\n他们靠的太近了，近的乳肉几乎贴在一起，先前留下的涎水和汗液很好的起到了润滑，充血硬挺的乳尖随着撸动的节奏而相互磨弄着。 白厄将头埋在凯文颈窝间，一边摄取着耳后清甜的气息一边用舌尖舔弄着肉感十足的耳垂。 凯文被他的动作弄的有些软了腰，他已经很久没有做过了，他不喜欢性爱时那种失控的感觉。\n但今天的情况，太特殊了。 满月之际是他魔力最充裕的时期，这场仪式他准备了许久，既然已经开始，那他势必要将其完成。\n凯文昂头低吼着加快了手上的动作，修剪平整的指甲时不时划过铃口，空闲的手将精囊一同包裹揉搓，魔女的传承几乎不靠常规的方式，因此男性器官对他们来说基本上退化了的，四枚卵蛋的大小刚好能被一手团主。 脆弱又敏感的部位被玩弄的感觉刺激着神经，白厄呻吟的声音回荡在房间，“啊哈！ 嗯啊…… 要！ 要射了！ ”几乎同时，凯文也低吼着泄了出来，浓稠的白精溅在两人腹间又顺着腰线滑落。\n“哈…… 额…… 哈……”白厄还在高潮后的不应期，被凯文抚弄的滋味和自慰的感觉完全不同，他从未尝到过这般快感，大脑还被蒙在射精后的朦胧中，身体却食髓知味的向凯文贴去。 他缓了缓，搬过凯文的下巴，带着太阳纹路的瞳孔投入冰蓝，让他不由想起当年那场大火中，凯文的眼睛在火光间显得那么耀眼。 男孩湿漉漉的眼睛盯得凯文有些发毛，刚一想撇过头去就被少年吻上了嘴角，但这一次他少见的反抗起来。 凯文偏头躲开这个吻，只留给少年几缕柔软的白发。 再次对上视线时，看着少年疑惑又带着些倔强的眼神，凯文叹了口气说道：“这，应该留给你喜欢的人……”\n“可，凯文就是我喜欢的人……”\n凯文没有回答，或者说，他不知道怎么回答，只能回以沉默。 白厄也不说话了，他不愿在这种时候扫兴，但他需要凯文的答复。\n“…… 抱歉。 ”凯文张了张嘴，继续了动作。 他的侧脸几乎是贴着白厄的小腹，不顾自己柔顺的白发是否会被精液弄脏，一路蹭到白厄的会阴处，那处白色的阴毛很好的保护着脆弱的部位，只是有些扎脸，凯文殷红的舌舔净了刚刚沾上的精液，绕过半勃的性器来到从未有人光临的女穴。\n“哈…… 呜啊…… 好奇怪…… 痒，好痒……”气息喷洒在阴唇间引的白厄不住呻吟，下意识的想要用手遮挡却摸上了凯文的头顶，他不敢再动了，只得用双腿紧紧圈着凯文的腰身，以此来寻得些许安慰。\n“白厄…… 放松。 ”沉闷的声音自身下传来，灵巧的舌剥开粉嫩的阴唇，舌尖先顺着外侧将整个阴部舔的湿润，一吸一缩的发出啧啧水声，“唔啊！ 哈…… 凯文，别…… 好想……”白厄的腰身在颤栗，要不是有凯文扶着，怕是要直接翻下去。\n凯文如同撬开珍珠蚌般寻找到那颗被隐藏的肉核，“啊啊啊！！ 唔啊……”“…… 唔，咳咳，”仅仅是轻轻一舔，毫无预兆的，在凯文还没反应过来时淫水就喷溅在了脸上，原本柔软的发被打湿，水挂在细长的睫毛上，弄的他睁不开眼，顺着鼻尖滑落，呛得凯文咳嗽不止，“唔啊…… 你，没事吧…… 凯文，对不起……”凯文用手随意将脸抹干，答到，“没事…… 我继续了。 ”\n不等白厄回答，他就再次栖身而上，乳尖顶在乳晕上，将饱满的胸脯压的扁平。 白厄没有刮掉的阴毛蹭的凯文发痒，身体不受控的蹭向白厄。 他为了这次专门刮了，本想着不会蹭到白厄，却不想这下苦了自己。\n阴唇已因动情和凯文的舔弄而张开，失去了肉唇保护的花核暴露在外，轻而易举的被凯文的小穴捕获。 凯文用两指扒开穴肉，夹不住的淫水滴在白厄的穴间引得他有些失了神，“白厄 还清醒吗？ ”凯文在他略显失焦的眼前挥了挥，见他重新聚焦才继续了动作。\n“啊嗯！ 呐…… 啊哈！ ”花穴吞吃着稚嫩的肉蕊，一起一伏间淫液随着动作在两人间传流，上千个神经突触尽职尽责将快感传入大脑，酥麻如触电般的快感折磨的白厄，不得不扭动着腰身企图缓解，但胯骨被凯文的双手死死拷住，只得将这过量的快感化作呻吟释放。\n凯文也不好受，他的身子因之前的开拓要敏感的多，硬挺的肉粒随着动作时不时被略硬的阴毛蹭过，激的他脆弱的小穴已经暗暗吐了好几次水，而这些淫水随着重力被他喂给了白厄。\n“唔…… 肚子，好涨……”白厄倏的打起了颤，肚子里的淫水被堵住无法流出，加上凯文喂给他的，现在小腹已经涨起了轻微的弧度，“好难受！ 我…… 我不想，不行了！ 凯文…… 别”白光不断在眼前闪过，他的大脑已经混沌的难以思考，除了快感，还有什么东西也在往他的脑海里灌输，但他已经无暇思考了。\n“啊！ 啊嗯…… 别，别乱动…… 白厄！ ”身下人突然的颤动所带来的强烈快感，惹得凯文当场潮吹了，淫液不受控制的击打着白厄的花穴，反而弄得他抖的更加剧烈。 白发交织着，就这样相拥着迎来高潮，过量的水液弄的床单已经完全湿透了，连一旁的斗篷都没能幸免。\n再次醒来时，已经日上三竿，多亏凯文好用的魔法拉上了窗帘，才没有弄的浑身酸痛的白厄被太阳晃醒。 白厄睁着眼，静静地消化着昨晚的一切，凯文还没有醒来，这样的传承方式所消耗的魔力远比他想象的多，但选择这种方式，可以很好的用性爱的快感冲淡伴随着魔力一同注入的，属于魔女的记忆，对白厄造成的不适感。 但那双带着太阳印记的眼睛还是在一夜间变了神，带上了些许冰冷的天蓝盯着天花板，一边思考一边摸上凯文的白发。 “唔…… 白厄……”凯文的浅眠被扰醒，“额，不…… 卡厄斯兰那，你都，知道了……”白厄转了转眼睛，语气平静道，“还是叫我白厄吧。 ”\n“凯文，和我做这种事，并不是因为喜欢我吧…… 我看到了，火，来自太阳的火焰在我的胸腔燃烧，很烫，将我灼烧殆尽。 所以，如果不把魔女的力量传递给我的话，我一定会死掉，是吗。 这个太阳印记，其实是命运的诅咒吧”白厄闭上眼，有些无奈说道。\n“抱歉，这原本是属于我的命运……”“凯文，别总是说抱歉了，既然命运让我诞生，那么，来自你的祝福我会笑纳，源自你的诅咒…… 我也将打破。 ”凯文没有回答，默默地将白厄抱紧，即使他的身形已经不在能被自己一把抱在怀中，“凯文，我知道魔女都是自私的，但你还是选择将魔力传给我，所以，这个吻，你也会给我的，对吧。 ”\n笔记 说实话在企划开始之初有至少五个脑洞，3.4 更新前有两三个已经开始动笔了，3.4 更新后全部感觉，嗯。 之后在和朋友复盘剧情时，想到了一些，命运（烧鸡）的大手，让白厄作为凯文的同位体，一方面得到了更多的，很难说是不是偿还性的爱，另一方面，也不得不背负上，一些，属于，凯文. 卡斯兰娜的枷锁，无论是在剧中还是剧外，一股名为烧鸡的阴影都始终笼罩着他们。 有点语无伦次了，想了很多还是决定了临时滑铲这篇，凯文的故事已经成了定局，但白厄还有着很多的可能性很多的未来，未来还会有很多更深刻的塑造，他不是那个只能推着巨石前行的西西弗斯了。\n","date":"2025-07-13T23:43:21+08:00","image":"/images/e.webp","permalink":"/posts/%E5%8E%84%E5%8F%B3%E5%A4%8F%E6%97%A5%E6%83%85%E4%B9%A6week2200%E4%BC%A0%E6%89%BF/","title":"【厄右夏日情书weekⅠ22：00】传承"},{"content":"免责声明 重要提示：在使用本站提供的任何信息或链接前，请您务必仔细阅读并理解以下内容。您的使用行为即表示您同意并接受本声明的全部条款。\n信息性质与目的： 本站提供的关于资源查找方式、网络访问工具、搜索引擎及第三方链接等所有信息，仅限于技术交流和资源定位方法的探讨分享。本站不存储、不生产、不传输任何受版权保护或非法的实质性内容（如影片、图像、文字作品等）。本站的核心功能在于提供信息索引与定位指导。 用户自主行为与责任： 所有通过本站提到的技术手段、方法或链接访问互联网资源及内容的行为，均由用户自行决定、自行操作并完全自行承担相应风险与法律责任。用户必须了解并遵守其所在国家/地区的法律法规。本站对用户利用这些信息或访问链接后的一切行为及其产生的任何后果（包括但不限于法律风险、隐私泄露、网络安全威胁、经济损失等）不承担任何责任。 第三方内容免责： 本站可能提及或链接到第三方网站、平台、服务提供商（如搜索引擎、代理服务商、资源站点）。这些第三方内容、服务、政策及其合法性、安全性、稳定性和准确性完全由其自身负责。本站无法控制、审核、担保或认可任何第三方内容与服务。链接提供仅为方便信息参考，不代表本站的推荐、认可或担保，亦不构成任何形式的合作关系。用户访问任何第三方链接或使用其服务时，应自行审慎判断风险并遵守该第三方的条款和隐私政策。 技术服务中立性： 本站提到的关于建立“魔法环境”的技术讨论（如代理工具、客户端的配置和使用方法），目的仅在于阐述实现网络访问功能的技术可能性。用户使用这些技术应严格遵守所在国法律法规。用户需自行确保其网络访问行为合法合规，本站对用户的具体技术使用方式及目的不作任何建议、引导或担保。 资源内容免责： 用户通过所述方法搜索、定位或获取的资源内容，其合法性、版权归属、质量及潜在风险（如恶意软件）完全由用户自行负责甄别和承担。本站绝不对任何被访问的第三方资源内容的性质、合法性或安全性负责。 安全与隐私警示： 在线活动始终存在风险。本站强烈建议用户在任何时候都优先考虑网络安全和个人隐私保护，谨慎对待在线共享的个人信息，特别是使用非官方的工具和服务时。使用任何代理服务（机场/VPN等）应选择信誉良好、隐私政策透明的服务商，并自行承担相应风险。 未成年人保护： 本站提供的信息及所指向的资源可能包含绝对不适宜未成年人的内容。我们坚决禁止未成年人使用或试图访问这些内容。用户有责任确保自身符合访问相关内容的法定年龄要求。 无保证与更新： 本站提供的信息“按现状”提供，不提供任何明示或暗示的保证（包括但不限于准确性、完整性、时效性、适用性、不侵权或可用性等）。互联网环境及法律法规动态变化，本站不承诺随时更新所有信息或链接的状态。链接可能随时失效，方法可能变得无效或不合法。 请务必在使用本站任何信息或链接前，充分理解并接受上述风险。祝您安全、合规地冲浪。\n导航 在线观看 次元城动画 发布页\n橘子动漫 备用\n飞飞动漫\n备用 备用 备用 里番站 girigiri爱动漫 备用\n柒番\n番薯动漫\n发布页 安卓客户端 花子动漫\n发布页 安卓客户端（123云盘） Telegram群 clicli弹幕网\n佩可爱动漫，被墙，且日本和俄罗斯的ip无法打开网站\n喵物次元\nMuteFun动漫网站\n备用 安卓客户端 Animoe动漫\n嗷呜动漫\n稀饭动漫\n备用 发布页 Telegram群 NyaFun\n发布页 安卓客户端 Telegram群 动画疯，有地区限制\n下载 Nyaa，网站内容比较乱，需要花功夫找\n备用 动漫花园资源网\n备用 备用 萌番组\n蜜柑计划\n末日动漫资源库\n备用 ANi Open\n备用 Anime字幕论坛\nVCB-Studio主站 导航站 ACG盒子，一个导航站，被墙 ","date":"2025-07-13T21:35:03+08:00","image":"/images/cyzg2.webp","permalink":"/posts/%E5%85%8D%E8%B4%B9%E5%8A%A8%E6%BC%AB%E7%BD%91%E5%9D%80/","title":"免费动漫网址"},{"content":"免责声明 重要提示：在使用本站提供的任何信息或链接前，请您务必仔细阅读并理解以下内容。您的使用行为即表示您同意并接受本声明的全部条款。\n信息性质与目的： 本站提供的关于资源查找方式、网络访问工具、搜索引擎及第三方链接等所有信息，仅限于技术交流和资源定位方法的探讨分享。本站不存储、不生产、不传输任何受版权保护或非法的实质性内容（如影片、图像、文字作品等）。本站的核心功能在于提供信息索引与定位指导。 用户自主行为与责任： 所有通过本站提到的技术手段、方法或链接访问互联网资源及内容的行为，均由用户自行决定、自行操作并完全自行承担相应风险与法律责任。用户必须了解并遵守其所在国家/地区的法律法规。本站对用户利用这些信息或访问链接后的一切行为及其产生的任何后果（包括但不限于法律风险、隐私泄露、网络安全威胁、经济损失等）不承担任何责任。 第三方内容免责： 本站可能提及或链接到第三方网站、平台、服务提供商（如搜索引擎、代理服务商、资源站点）。这些第三方内容、服务、政策及其合法性、安全性、稳定性和准确性完全由其自身负责。本站无法控制、审核、担保或认可任何第三方内容与服务。链接提供仅为方便信息参考，不代表本站的推荐、认可或担保，亦不构成任何形式的合作关系。用户访问任何第三方链接或使用其服务时，应自行审慎判断风险并遵守该第三方的条款和隐私政策。 技术服务中立性： 本站提到的关于建立“魔法环境”的技术讨论（如代理工具、客户端的配置和使用方法），目的仅在于阐述实现网络访问功能的技术可能性。用户使用这些技术应严格遵守所在国法律法规。用户需自行确保其网络访问行为合法合规，本站对用户的具体技术使用方式及目的不作任何建议、引导或担保。 资源内容免责： 用户通过所述方法搜索、定位或获取的资源内容，其合法性、版权归属、质量及潜在风险（如恶意软件）完全由用户自行负责甄别和承担。本站绝不对任何被访问的第三方资源内容的性质、合法性或安全性负责。 安全与隐私警示： 在线活动始终存在风险。本站强烈建议用户在任何时候都优先考虑网络安全和个人隐私保护，谨慎对待在线共享的个人信息，特别是使用非官方的工具和服务时。使用任何代理服务（机场/VPN等）应选择信誉良好、隐私政策透明的服务商，并自行承担相应风险。 未成年人保护： 本站提供的信息及所指向的资源可能包含绝对不适宜未成年人的内容。我们坚决禁止未成年人使用或试图访问这些内容。用户有责任确保自身符合访问相关内容的法定年龄要求。 无保证与更新： 本站提供的信息“按现状”提供，不提供任何明示或暗示的保证（包括但不限于准确性、完整性、时效性、适用性、不侵权或可用性等）。互联网环境及法律法规动态变化，本站不承诺随时更新所有信息或链接的状态。链接可能随时失效，方法可能变得无效或不合法。 请务必在使用本站任何信息或链接前，充分理解并接受上述风险。祝您安全、合规地冲浪。\n导航 国内航班 漫画/涩图 禁漫天堂 发布页 國際通用網域1 國際通用網域2 東南亞路線建議使用3 東南亞路線建議使用4 內地網域5 分流6 分流7 APP下载 骚活：在QQ群里的jm本子推送员，详细信息请访问https://github.com/zhulinyv/nonebot_plugin_jmcomic 绅士漫画发布页 发送邮件到wnacg.link@gmail.com获取最新网址 网址1 网址2 网址3 acg漫画网 漫蛙 注：漫蛙因6/10遭受攻击，今年一月之后注册的用户数据已损坏了，所有数据都没有了，请重新注册。有任何的疑问，在漫蛙官网都可以找到答案，请仔细看看漫蛙官网的讯息！ 走失页1 走失页2 大陆地区网域 非大陆地区 安卓客户端 NiceCat 备用链接，这个更稳定 论坛，可获得官方一手消息 安卓客户端下载 NoyACG 注：需要注册，邀请码：accb33866，完全免费 真人 xx.knit.bid，写真集网站，也有视频但加载较慢，不用会员（网站似乎默认越南语，可切换语言） 小说 h图书馆，就小说，没有图片 国际航班（需代理服务） 漫画/涩图 pixiv 哔咔漫画，需登录 e-hentai 客户端下载链接：https://github.com/xiaojieonly/Ehviewer_CN_SXJ/releases，而且似乎客户端可以在国内正常访问 exhentai，这位更是重量级，保密措施相当完备，必须在e-hentai（表站）注册账号后才能登录 nhentai 色图Bot，telegram机器人，没太有什么用 里番 Hanime1 真人 Pronhub，全球最大黄色网站 JAV321，日本女优网站 xvideos，类似于Pronhub 91pron，国产，但是要翻墙（） XHAMSTER，类似于Pronhub jable，类似于JAV321 missav，类似于JAV321，画质较差 特殊搜索引擎（跑道） btdig，磁力种搜索引擎（被墙） xslist.org，女优搜索引擎（被墙） The Porn Dude，成人搜索引擎（被墙） www.xxx.xxx，r18站点集合 写在后面 在寻找特定资源时，大家通常面临两种典型场景：\n目标模糊型：只有大致方向（例如，想看动漫还是真人内容，倾向捆绑调教还是清淡类）。 目标明确型：清晰知道想看的具体内容（例如，特定作品如“Taipei娜娜”或“derpixon《被诅咒的王子》”）。 针对不同场景，应采取的查找策略也不同：\n面对模糊目标：优先依赖你已知的、稳定可靠的资源站点。与其在筛选网站上耗费时间，不如集中精力在站内内容的探索上（因为你最终可能无法找到理想的资源）。 面对明确目标：需要一个强大有效的搜索引擎（下文会详述），以便快速精准定位所需资源。 获取资源的前提：稳定可靠的网络访问环境（“魔法环境”） 受制于网络环境限制，许多大型成人资源站点的国内访问常不稳定或受阻（例如，禁漫天堂时有卡顿）。关键时刻加载失败，无疑影响使用体验。因此，一个可靠、能稳定访问境外资源的网络环境至关重要。\n重要安全提示： 切勿为了便捷而牺牲隐私与安全！“免费”服务往往暗藏风险。强烈建议优先选择信誉良好、提供清晰隐私政策的付费代理服务（机场/VPN）。具体工具配置（如Clash客户端、Android设备下的LSPatch模块化方案）可参考Clash使用指北和LSPatch使用指北\n（注：关于如何甄别和获取安全可靠的代理服务，后续将单独撰写文章说明。） 高效检索的核心：搜索引擎的选择 若已具备稳定访问环境：首选 Google，其检索效果通常最优。 若无法使用全球搜索引擎： 绝对避开国内主流搜索引擎（如百度、搜狗），其搜索结果中充斥着大量高风险钓鱼网站。 建议使用 Chrome 或 Edge 等现代浏览器。 无痕模式 (Incognito/InPrivate) 的真实作用： 它不能隐藏你的网络活动（ISP、目标网站、执法机构仍可能追踪）。 主要作用是不在本地设备留下浏览记录，适合防止他人查看你的设备历史。但若你想重新查找之前看过的内容，关闭无痕后历史记录消失反而会增加困难。 国内替代选择较为有限， Bing 相对略好（但效果远逊于Google）。 备选资源搜索途径（供参考） （此部分内容仍在完善中，后续将补充更新）\n无需代理环境： 访问域名较为特殊的资源聚合站点（如www.xxx.xxx），但通常访问速度较慢，需耐心等待。 尝试搜索现存的资源索引或列表网站（具体推荐待后续提供）。 已具备代理环境： xslist.org：强大的“以图搜女优”工具，方便演员信息查询。 The Porn Dude：汇聚了多个主流的全球成人专用搜索引擎链接。 总结 获取网络资源的效率高度依赖稳定通畅的网络访问环境。在没有可靠代理服务的情况下，搜索过程往往充满偶然性且效率低下，可能需要依赖像我们这样的专业资源站点（笑）。\n文章说明 本文章将持续更新， 欢迎推荐优质网站： 📮 邮箱：realityme114@outlook.com 💬 提交格式：网站名称 + URL + 简介\n","date":"2025-07-12T23:12:38+08:00","image":"/images/sex2.webp","permalink":"/posts/%E5%85%81%E8%AE%B8%E9%83%A8%E5%88%86%E9%A3%9E%E8%A1%8C%E5%91%98%E5%85%88%E9%A3%9E%E8%B5%B7%E6%9D%A5/","title":"允许部分飞行员先飞起来"},{"content":"\n","date":"2025-07-10T22:38:41+08:00","image":"/images/bashang.jpg","permalink":"/posts/%E8%BF%99%E5%B0%B1%E6%98%AF%E6%88%91%E4%BB%AC%E7%9A%84%E5%9D%9D%E4%B8%8A/","title":"这就是我们的坝上"},{"content":"刚冲好一杯咖啡（并非刚刚，写一篇稿子怎么着也要快半小时吧）。\n自四年级初尝那口苦涩的醇厚（卧槽我四年级真是神奇的一年），我便始终偏爱纯粹的它——不加糖，不加奶。唯有如此，舌尖才能触及豆子蕴藏的真味，无论是明亮的果酸，沉郁的焦苦，还是那微妙流转的、土地的脉络。那些稀释，终究模糊了事物本真的纹理。\n有时恍惚觉得，这杯中的深褐色液体，竟与我生命行走的姿态隐隐相合——竟有几分近似西西弗斯的影子。也曾奋力托举某种期冀，挣扎着向高处攀升，却总似有宿命般的引力或是某个倏忽的疏怠，令一切复归原位。重复着上升与滑落的轨迹，石头滚下，人重返谷底。生活似乎就在这无尽的循环里，绷紧着弦，从未真正抵达松弛的岸。\n总之，在学习时我会喝，在看书时我会喝（我主要是看小说），在看电影时我会喝，熬夜看动漫时我会喝，打rpg游戏时，为抵抗那些又臭又长的剧情，咖啡也是我的必需品\n然而悖论如影随形：既然是为了片刻精神的松弛而沉浸书中、剧中或游戏的世界，为何又需要借助另一种刺激来保持“清醒”？ 仿佛我们身体里栖息着两个对抗的魂灵：一个渴望逸出，沉入忘忧的幻境；另一个却顽强挣扎着，试图在这短暂的逃逸中，维持一丝掌控全局的“在场感”。就像这两天，读《通往夏天的隧道，再见的出口》花了大约五个小时，喝了三杯咖啡。究竟是清醒更深刻地理解了那离别的隧道，还是在咖啡因的震颤里，连那丝纯爱的美妙也变了味？\n所以我选择中烘的豆（怎么突然到这里了）——它往往更能显露酸质的光华。纯粹的苦，若失了那点微妙的酸作为映衬或抵抗，便失之粗粝，沦为愚钝的麻醉。（总之就是不好喝）正如绝对纯粹的“坦诚”，若少了对语境与自我欲望（那隐秘的、并非全然高尚的欲念）的觉察，便也可能沦为莽撞的投射或自证——那杯不加糖奶的咖啡，是否也包含了对某种真实，抑或是某种苦涩品味的偏执想象？\n它是我的续命药。每个倚靠它撑过困倦的时辰，它都如约点燃灰烬里的微火。可是物质燃烧需要氧气，所以每咽下一口，我都有种窒息的感觉。 只是偶尔细想，以这“续”得来的精神振作，对抗的究竟是外界的疲惫，还是源于生命内在难以填补的空落感？它所续存的“命”，对我来讲，似乎也是一毛不值的。\n咖啡杯空了，杯底只余一圈浅褐色的痕印。它无法真正证明存在，也无法被证明存在过。 稿子感觉还没写完，但是我的尿已然憋不住了\u0026hellip;\n","date":"2025-07-05T14:33:37+08:00","image":"/images/coffeetalk.webp","permalink":"/posts/koffee/","title":"koffee"},{"content":"一、核心词根与衍生词 1. 方向性词根 词根 含义 例词与音标 a- 上升 ascend /əˈsend/, transcend /trænˈsend/ (超越) tran- 转变 transport /trænˈspɔːt/, transfer /trænsˈfɜː/, translate /trænsˈleɪt/, transformer /trænsˈfɔːmə/, transmit /trænzˈmɪt/, transplant /trænsˈplɑːnt/ de- 下降/破坏 descend /dɪˈsend/ → descendant /dɪˈsendənt/ (n.后代), destroy /dɪˈstrɔɪ/ 2. 动作性词根 词根 含义 例词与音标 -pose 放置 expose /ɪkˈspəʊz/ → exposition /ˌekspəˈzɪʃn/ (n.博览会) impose /ɪmˈpəʊz/ → impose pressure on compose /kəmˈpəʊz/ → composer /kəmˈpəʊzə/ (创作者) suppose /səˈpəʊz/ (假设) propose /prəˈpəʊz/ → proposal /prəˈpəʊzl/ (提案/求婚) dispose /dɪˈspəʊz/ → dispose of depose /dɪˈpəʊz/ (①使沉淀 ②瓦解) -press 按压 express /ɪkˈspres/, impress /ɪmˈpres/, depress /dɪˈpres/ compress /kəmˈpres/, high-pressure /ˌhaɪˈpreʃə/ (高压的) -mit/-miss 发送 mission /ˈmɪʃn/, permission /pəˈmɪʃn/, permit /pəˈmɪt/ admit /ədˈmɪt/, transmit /trænzˈmɪt/, limit /ˈlɪmɪt/ submit /səbˈmɪt/, commit /kəˈmɪt/ → commit a crime -gene- 产生 generate /ˈdʒenəreɪt/ (v.生产), generation /ˌdʒenəˈreɪʃn/ (n.代) -scribe 书写 inscribe /ɪnˈskraɪb/, prescribe /prɪˈskraɪb/, subscribe /səbˈskraɪb/ (订阅) 3. 呼吸/精神相关 词根 含义 例词与音标 -spire 呼吸/精神 inspire /ɪnˈspaɪə/, expire /ɪkˈspaɪə/ (到期), aspire /əˈspaɪə/ (渴望) despise /dɪˈspaɪz/ (鄙视) ✓ → aspiration /ˌæspəˈreɪʃn/ (n.初心) 二、实用词汇拓展 1. 情感与态度 词汇 音标 含义/对比 favorable /ˈfeɪvərəbəl/ ↔ unfavorable → favorite /ˈfeɪvərɪt/ (最喜爱的) → in favor of (支持) optimistic /ˌɒptɪˈmɪstɪk/ ↔ pessimistic /ˌpesɪˈmɪstɪk/ → pessimism /ˈpesɪmɪzəm/ (n.悲观主义) positive /ˈpɒzətɪv/ ↔ negative /ˈnegətɪv/ doubt /daʊt/ n./v.怀疑 ↔ belief 强化表达\n表「好」的词：\nexcellent /ˈeksələnt/, fantastic /fænˈtæstɪk/, fabulous /ˈfæbjələs/,\nmarvelous /ˈmɑːvələs/, phenomenal /fəˈnɒmɪnəl/, incredible /ɪnˈkredəbəl/,\nbrilliant /ˈbrɪliənt/, superb /suːˈpɜːb/, perfect /ˈpɜːfɪkt/,\nwonderful /ˈwʌndəfəl/, awesome /ˈɔːsəm/, legendary /ˈledʒəndri/ ✅ 彩蛋：これでいいなのだ\n表「大」的词：\nimmense /ɪˈmens/, tremendous /trɪˈmendəs/, titanic /taɪˈtænɪk/, enormous /ɪˈnɔːməs/ 2. 社会与行为 词汇 音标 含义/用法 opponent /əˈpəʊnənt/ n.对手 (← opposite) participate /pɑːˈtɪsɪpeɪt/ = take part in → participate in discussions attach /əˈtætʃ/ → attachment /əˈtætʃmənt/ (n.附件/依恋) indicate /ˈɪndɪkeɪt/ v.暗示/表明 (indicate a problem) witness /ˈwɪtnəs/ v.见证 n.目击者 (≠ foresight /ˈfɔːsaɪt/ 远见) ✓ recognize /ˈrekəɡnaɪz/ v.承认/认出 migrate /maɪˈɡreɪt/ v.迁移 → migration /maɪˈɡreɪʃn/ deliver /dɪˈlɪvə/ v.递送/发表 → deliver a speech clarify /ˈklærəfaɪ/ v.澄清 → clarification /ˌklærəfɪˈkeɪʃn/ 3. 经济与技能 词汇 音标 含义 补充说明 financial /faɪˈnænʃəl/ 金融的 (词根: fin=边界) financial analysis salaried taxpayers /ˈsælərid ˈtækspeɪəz/ 纳税受雇者 demanding /dɪˈmɑːndɪŋ/ 高要求的 (adj.) ↔ undemanding /ˌʌndɪˈmɑːndɪŋ/ charge /tʃɑːdʒ/ v.收费 → charge for delivery 三、高频短语与表达 1. 动词短语 短语/结构 音标/用法 例句 dispose of /dɪˈspəʊz əv/ 处理废弃物 dispose of electronic waste impose pressure on /ɪmˈpəʊz ˈpreʃə ɒn/ 施压 impose pressure on competitors commit a crime /kəˈmɪt ə kraɪm/ 犯罪 commit a serious crime take part in /teɪk pɑːt ɪn/ = participate take part in the debate in favor of /ɪn ˈfeɪvər əv/ 支持 The court ruled in favor of the tenant 2. 实用句型 句型结构 功能说明 例句 It happened that\u0026hellip; 碰巧发生 It happened that the plant needed temporary workers more\u0026hellip;than expected 超出预期 The job was more high-pressure than I’d expected apply theory to reality 理论联系实际 = apply theory to practice deliver a speech 发表演讲 The CEO delivered a keynote speech explain in a\u0026hellip;role 角色化解释 explain the concept in a teacher\u0026rsquo;s role present a fact 陈述事实 present verifiable facts make a prediction 做出预测 make a scientific prediction 四、语法结构要点 1. 从句类型详解 (1) 名词性从句（主/宾/表/同）\n功能 引导词 例句 主语从句 What, That, Whether What he said shocked everyone. （他说的话让所有人震惊） 宾语从句 If, That, How She confirmed [that the data was accurate]. （她确认数据准确） 表语从句 Why, Where The problem is [whether we can finish on time]. （问题是我们能否按时完成） 同位语从句 That The news [that he resigned] spread quickly. （他辞职的消息迅速传开） → 抽象名词专用：news/story/information/fact (2) 定语从句 vs 同位语从句辨析\n类型 引导词 功能 例句 定语从句 that 修饰具体名词 The story [that he told us] is not true. （他讲的故事不真实）→ that在从句中作宾语（told的宾语） 同位语从句 that 解释抽象名词内容 The story [that he was a hero] is not true. （他是英雄的说法不真实）→ that后为完整句子，解释story内容 (3) 状语从句\n类型 引导词 例句 时间 When, While When the meeting ended, they left the room. （会议结束时他们离开） 条件 If, Unless If you study hard, you will pass. （如果努力学习，你会通过） 原因 Because, Since He failed [because he ignored the instructions]. （他因忽略指示而失败） 2. 五大基本句型结构 类型 结构 成分说明 例句 S + V 主语 + 不及物动词 无宾语 Birds fly. （鸟飞翔） S + V + O 主语 + 及物动词 + 宾语 带单个宾语 She reads books. （她读书） S + V + O + O 主语 + 动词 + 间接宾语 + 直接宾语 双宾语（人+物） He gave her a gift. （他给她礼物） S + V + O + OC 主语 + 动词 + 宾语 + 宾补 补语说明宾语状态 We elected him president. （我们选他当主席） S + V + P 主语 + 系动词 + 表语 表语描述主语性质 She is a doctor. （她是医生） 语法要点说明 同位语从句的本质\n抽象名词专用：news, information, story, fact, belief 等后接that引导的完整句子（无成分缺失），解释名词内容\nThe evidence [that the vaccine works] is clear. （疫苗有效的证据很明确） ✘ 误用：抽象名词 + where/when → ✓ 同位语从句只用that 五大句型核心规则\nS+V+O+OC（宾补）：补语直接修饰宾语（president说明him） 补语类型：名词/形容词（They painted the wall blue） S+V+O+O（双宾）：物（直接宾语）必为人（间接宾语）服务 句型转换：He gave a gift to her（介词结构） 定语从句与同位语从句的区分\n判断标准 定语从句 同位语从句 that的作用 在从句中充当成分（主/宾） 仅引导，不作成分 名词类型 具体事物（story, book\u0026hellip;） 抽象概念（news, fact\u0026hellip;） 删减测试 从句不完整：he told [ ] 从句完整：he was a hero 五、补充重点词根 词根 含义 例词与音标 -spec- 看 special /ˈspeʃəl/, species /ˈspiːʃiːz/, specific /spəˈsɪfɪk/ -duc(t)- 引导 reduce /rɪˈdjuːs/, induce /ɪnˈdjuːs/ -cline 倾斜 decline /dɪˈklaɪn/ (v.拒绝/减少) ↔ reduce /rɪˈdjuːs/ 六、易混淆词辨析 词汇 音标 语义区别与用法 favorable vs favorite /ˈfeɪvərəbəl/ vs /ˈfeɪvərɪt/ ✓ favorable: 有利的 (favorable conditions) ✓ favorite: 最喜欢的 (my favorite book) decline vs reduce /dɪˈklaɪn/ vs /rɪˈdjuːs/ ✓ decline: 委婉拒绝邀请；自然减少 (decline an offer, sales decline) ✓ reduce: 人为减少 (reduce costs) witness vs foresight /ˈwɪtnəs/ vs /ˈfɔːsaɪt/ ✘ witness≠远见 → ✓ witness: 目击事件 ✓ foresight: 预见未来的能力 save vs secure /seɪv/ vs /sɪˈkjʊə/ ✓ save: 通用\u0026quot;保存/节省\u0026quot; (save energy) ✓ secure: 特指\u0026quot;安全保护\u0026quot; (secure data) 更新说明 核心修正：\n✘ despire → ✓ despise（鄙视） ✘ witness（远见）→ ✓ foresight（预见） 明确 -gene-（产生）与 -cline-（倾斜）词根 短语扩展：\n新增 dispose of、charge for 等动词短语 补充 It happened that\u0026hellip; 等5个实用句型模板 语义精炼：\n+ decline: 双重含义（拒绝/减少） + financial: 添加词源说明(fin=边界) 结构优化：\n新增 经济与技能 词汇子类 语法部分精简引导词，突出实用场景 ✅ 所有单词100%标注英式音标（IPA），历史内容完全保留，新增知识点无缝整合，错误全面修正。\n","date":"2025-06-25T19:30:47+08:00","image":"/images/duo.webp","permalink":"/posts/%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0%E8%8B%B1%E8%AF%AD/","title":"课堂笔记——英语"},{"content":"上古之时，神州大地烽烟四起，圣人退场，小人当道。此时天界忽现异象——中南海上空突降一团包子蒸汽，香气冲天，群臣膜拜，百姓误以为“玉皇下凡”。\n此包落地化形，为一婴儿，取名近平，字包子，号习圣，谥号习天帝·包子元尊·清零大圣·强国核心·文化导师·历史终结者·四通禁言之主。上古之时，神州大地烽烟四起，圣人退场，小人当道。此时天界忽现异象——中南海上空突降一团包子蒸汽，香气冲天，群臣膜拜，百姓误以为“玉皇下凡”。\n如今的习帝，早已超脱凡俗：\n外交靠战狼拳法：“不听话？那我们就‘严重关切’你！”\n经济靠画饼神术：“共同富裕？你先等一等。”\n军事靠阅兵幻术：战车万千，实则钢壳纸心。\n文化靠删帖火咒：一键清除，回归正确历史。\n传说他曾夜观天象，手捧“强国学习APP”，念动咒语：“中美关系就是这也不行，那也不行。”\n他甚至在《宪法》上刻下：“我即中国，中国即我。”\n于是，群臣日日上书：“愿我习皇，万年一统，永不退休！”\n百姓日日打卡：“今日学习五篇，明日解锁五毛积分。”\n学校开设《包学导论》，考试内容包括：“如何正确理解包子的意志。”\n上古有神，其名习也，治世三十载，万民咏之，朝朝暮暮\n","date":"2025-06-23T11:16:17+08:00","image":"/images/red.webp","permalink":"/posts/%E5%98%BB%E5%98%BB%E7%9A%84%E5%A5%87%E5%A6%99%E5%86%92%E9%99%A9/","title":"嘻嘻的奇妙冒险"},{"content":"在吗\n我们准备明天下午两点回学校，如果你有空想来的话，可以联系我\n不去了谢谢\n没关系\n早点休息，祝你做个好梦，晚安\n你报的哪个高中\n三中\n我也报这个了\n祝你考上\n你在焦虑吗\n没有我挺看得开的\n[呲牙][呲牙]\n额\n行，那你早点休息吧，注意身体\n嗯\n别太累了\n你喝酒了？\n额\n对\n很明显吗\n是的\n哇哦\n你玩蔚蓝当案吗？\n不玩啊\n我有个同学玩\n哦，你这个表情包挺可爱的，我还以为你玩儿那个嘞。\n哦，还没有人说过呢\n喝的啥\n好像确实挺可爱的\n梅酒\n你咋学会喝酒了我记得你以前是好学生[捂脸]\n怎么说呢\n其实喝点也不多\n也不算学会吧\u0026hellip;\n额不过我没有去混社会\n还算是个所谓的“好学生”吧\n挺好的\n谈恋爱了？\n啊？\n额\n算吧\n你们学校的？\n对\n你是哪个初中来着\n34\n奥奥\n祝99\n哇谢谢\n也祝你百事可乐千事吉祥万事如意顺风顺水八方来财（听歌听的\n那时间不早了，晚安\n啊原来是我的朋友圈上写的啊（\n才看见你点赞了\n谢谢\n这是近3年中我们唯一的对话\n时候不早了，可是我懒得想以后\n","date":"2025-06-22T23:16:48+08:00","image":"/images/rsc.webp","permalink":"/posts/%E5%AF%B9%E8%AF%9D/","title":"对话"},{"content":"准备工作： 一个邮箱（事实上不太推荐QQ邮箱，不过我自己用的就是QQ邮箱，所以无所diao谓）、 一台电脑（win10/11，mac也行，Linux\u0026hellip;\u0026hellip;也不是不可以，但是我这里不教macOS和Linux的安装方法）（电脑下载电脑客户端用，你要是不玩游戏只是领个别人送的礼物，或者趁促销结束前赶紧买个游戏，那一台手机也可以） 加速器 UU加速器、雷神加速器、迅游加速器皆可免费加速steam，可以使用 使用VPN的朋友，可以直接使用VPN steam++（watt tolkit）也可免费加速 安装steam Windows客户端（以下简称客户端） 开启加速器 打开steam官网 点击右上方的绿色按钮「安装steam」 点击左侧蓝色大按钮「安装steam」，然后运行浏览器所下载的可执行文件（.exe） 双击安装包，若弹出用户账户控制界面，选择是，进入安装页面 一路选择下一步 注：在选定安装路径时，遵循一下要点： 路径内无中文字符，包括特殊符号 建议不要装到C盘（当然只有C盘那就装C盘吧） 完成，steam自动更新，等待即可 注册 注：此步骤极难（），可寻求他人帮助 在客户端窗口打开后，点击登录界面的右下角「创建免费账户」 填写你的邮箱到上面两行 进行人机验证 注：此步骤极难（）建议使用手机热点作为WiFi，并保持加速器开启。若失败请多次尝试，或更换加速器节点 勾选同意条款 在出现「正在等待您进行验证」的窗口后，打开邮箱，接收到一封来自steam的邮件，点击邮件中的蓝色大按钮「验证我的电子邮件地址」 想一个好记的名称，用于账户登录，只可使用英文、数字，不可使用中文与特殊字符 想一个好记的密码，用于登录 登录 填写用户名与密码 检查邮箱，填写验证码 安装steam Android客户端 打开https://media.steampowered.com/apps/steam-android/steam-3.10.0.apk并下载安装包（.apk） 点击并安装即可 安装steam iOS客户端 打开https://apps.apple.com/us/app/steam-mobile/id495369748，跳转到app store 点击「获取」并安装即可 更改个人资料名称 如果你嫌初始名称不好听，可通过以下方法更改（此方法无法更改登录名称）\n点击客户端主页右上角的「管理账户」按钮（从左往右数第三个按钮） 点击查看我的个人资料 点击右侧的「编辑个人资料」 更改个人资料名称 ","date":"2025-06-21T22:43:29+08:00","image":"/images/Steam.webp","permalink":"/posts/%E5%85%B3%E4%BA%8Esteam%E7%9A%84%E6%B3%A8%E5%86%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%B8%8B%E8%BD%BD%E5%8F%8A%E6%9B%B4%E5%A4%9A%E5%86%85%E5%AE%B9/","title":"关于steam的注册，客户端下载，及更多内容"},{"content":"亲爱的同志： 见字如面，展信舒颜。\n你或许从未听说过我的名字，我叫闵采尔。当你在某个杏花春雨的清晨，打开这封藏在时光褶皱里的信，春雨正簌簌落在田野，浇灌农人朴素的希望。我想，那一定是个比百年更美好的世界。\n你可曾抬头，目睹那浮华圣殿？金丝帷幔正在皇宫穹顶下，伴着悠扬的琴声微颤。觥筹交错，欢笑与尖叫催人迷醉。低头，苦难人间。看看茅草檐下蜷缩的真相。农奴们嚼着混着木屑的面包，将清冷的月光同雪水一齐咽下。宴会厅的熏香难掩饿死婴儿的腐臭。你们中国有诗说的好：“朱门酒肉臭，路有冻死骨。”历史总无情地将盛宴与饥馑并置。\n我生于小康之家。学业初成，踏上游历之路。一路所见，哀鸿遍野。1520年，教堂的钟声裹着东风的萧瑟。我记得路德张贴《九十五条论纲》那天，我在欢呼的人群中，笑靥如花。可当萨克森选帝侯镇压起义时，昔日的改革旗手竟说：“暴民该被猎犬撕咬。”那一刻，抬头望去，圣殿的荣华尽在咫尺，可那却是对圣洁灵魂的背叛，于是我转身向沧桑人间。\n你见过阿尔斯特德的冬夜吗？领主禁止农民集会，我们便在林深处燃起火把。那些被史书抹去的凡人们——织工，农奴，铁匠，他们用粗糙的手传递着《论虚假信仰》，纸页粗劣，却比任何圣徒的遗物都更加神圣。\n1525年，苦难化作人民的怒吼沸腾了古老的德意志。我和八千手持草叉的农民，走向了自己的命运。铁与血的气味割裂晨雾，重骑兵如钢铁洪流拍打起义的队伍，收割脆弱的生命。剑雨落下，热血洒入土地，化作来年的花。\n刽子手斧刀落下的瞬间，恍然，我看见百年后巴黎公社的工人们高唱马赛曲，看见喀秋莎的尖啸划破柏林的夜空，看见遥远的东方，一群穿过雪山草地的战士将我们的理想写进《土地法大纲》。\n此刻，我腐坏的身躯己化作缪尔豪森的沃土，但请别在我的墓碑前哭泣。我是田间的麦香，缠绕农民的指尖。我是不眠的灯火，照亮工人辛劳的长夜。我是燎原的星火。长存抬头望星空的少年心间。浮华圣殿终将蒙尘，而每个劳作的身影都在续写我们的故事——那字句不在云端，而镌在劳动者低垂的脊与仰望的眉眼之间。\n——闵采尔\n于长夜将逝的黎明前\n","date":"2025-06-19T20:07:53+08:00","image":"/images/street.webp","permalink":"/posts/%E6%8A%AC%E5%A4%B4%E6%B5%AE%E5%8D%8E%E5%9C%A3%E6%AE%BF%E4%BD%8E%E5%A4%B4%E6%B2%A7%E6%A1%91%E4%BA%BA%E9%97%B4/","title":"抬头，浮华圣殿；低头，沧桑人间"},{"content":"最近在琢磨：真诚这玩意儿，底线到底在哪儿？\n我自个儿呢，一直标榜自己是个“真实”的人。跟人扯淡，力求每句话都过过脑子，从心窝子里掏出来。这世界假笑都堆成山了，我不愿沉沦其中，无论对己对人，但求一个“真”字。\n可问题来了：对方是否真愿涉足这片景致？当众扒外套不难，难的是你里头就一件破背心儿，看得对方眼睛都不知道往哪儿放。坦诚这玩意儿，是份礼物，有时候也像个烫手山芋。反正我算是明白了，十个人里九个半，未必扛得住你那份“赤裸”。\n那我自己呢？想想别人跟我掏心窝子的时刻，第一反应通常是：“我c，来真的？”————譬如初识不久，便将暗礁密布的深谷示人。旋即而来的，是难以言状的珍重：我该如何回应，才不负这份托付？\n紧跟着是一种……麻痹（五次了能不麻痹吗），但久旱逢甘露般的舒坦！太久没这种“那种心灵轻触刹那的慰藉”的感觉了。大概这就是人们吹牛逼说“高山流水遇知音”那点破事儿吧？灵魂共振。只是我五次经历这般心灵的震颤，却也未能锚定任何归宿。\n故此明了，知音难觅，犹如暗夜寻星。想要个能共振的？全靠运气。我的坦诚要是把对方整吐了，好嘞，相忘江湖，各走一边；若得遇同等心意的应答，方能在精神的荒野上，共振出一种奇妙的和弦。\n我吐露心声，是对自我灵魂的坦诚交代； 我聆听你的话语，并郑重回应，是对你存在的真切尊重。（好吧这话是给我说的。其实也不止，也是对那位tomboy说的，我有点恨她。）\n然而真诚之畔，需警醒的是，情绪之堤的溃决。 真正的坦诚，不止需要吐露的勇气，更需容纳的心胸——聆听的沉静与共鸣的深度。缺乏这两根支柱，单向的情感倾泻便化作了心灵的重负。承受此重压者，当有抽身离去的清醒与果决。\n真诚是一则承诺，更是一种明澈的智慧。它使我们不至于在幽暗的交道中徒然耗散心力。\n当然，它也常带来湍流。前些时日的文字，将那几段青涩的迷惘曝露于人前。今日，中考前去看考场，偶遇几位同学时，目光相接处，掠过一丝难言的闪躲——那瞬间的僵硬，犹如立于无形冰原之上。\n好社死啊\n这是坦诚所引致的寒流。\n更要紧的是，晨起收到一封私信。巧，又似乎太不巧了——消息的那端，正是之前文中提及的一位女孩。空气仿佛凝滞了几分。 可见真诚不仅关乎他人的承载力，也关乎袒露之后的世界是否依旧能维持稳态。那层薄纱纵然虚幻，却也是社会经纬中，维系平静的纤维。（说人话就是我有点尴尬）\n（另则需承认：在写及那位女孩时，心底某处，确实传来轻微的嗡鸣。或许这份所谓的“真诚”，多少也掺杂了自我心愿的投射。）\n（我其实还是有点想人家的）\n总的讲：真诚是金？没错儿！ 但两个问题更烧脑子：\n你是真“诚”，还是自我感动的傻X？ 你这把“诚”刀，挥出去是砍开迷雾，还是为你留下了难以自愈的创口？？ 所以啊，挥刀之前，三思其径，再行其步。 我此番，恰是一个沉溺于即时吐露而忘却掂量的活例。\n","date":"2025-06-17T20:10:30+08:00","image":"/images/shantianliang.webp","permalink":"/posts/%E7%9C%9F%E8%AF%9A%E6%98%AF%E7%A7%8D%E7%97%85%E5%85%BC%E8%AE%BA%E7%9C%9F%E8%AF%9A%E7%9A%84%E8%BE%B9%E7%95%8C/","title":"真诚是种病——兼论真诚的边界"},{"content":"探索不舒适，舒适不探索，努力逃出现世。沉溺在意识里而不付诸实践，只会带来它所说的虚无。好比可怜的浮士德，诗山书海里穷尽一生，惊回首，已是垂垂老矣。又好比从东到西，从古到今的贤哲，孔老二，海瑞，张岱，孟德斯鸠，伏尔泰，卢梭（都不如伊壁鸠鲁和庄周活的快活）……法兰西，启蒙主义的灯塔，文明之光，理想摧毁了旧世界，却又将新世界的地基倒转，于是休谟这样的狠人无情的杂碎了大厦，连带着存在主义危机的海啸，百年大潮退去，徒留一地鸡毛。你不为自己激励，曾经被虚妄一把捞起，也在此时，彻底的死在了“对理想世界探索”的温暖的大手下。被提起的学究儒生们，在大手的绝对保护下享乐、溺亡。这是生的虚幻，死的轮回，梦的幻灭。最终在一次次消耗里，坠入虚无的永恒。往后的时间，不断蚕食着过往……\n摆烁的空中楼阁，歌舞升平。再起还是复兴？黑夜里炸响冲天的烟火，极短的灿烂。映照她的脸庞，瞬而转凉，独流游子惆怅。\n大明，不过是文人醉酒流觞的盛世大梦。阳光照不到的地方，有人受着最深重的苦难。“岁大饥，人相食”明末千里行还是太保守了。\n百代人将梦著书流传后世。可惜，他残破着的，降临于世人面前。\n往后几百年，盛岁、堕坠……\n百年魔怪舞翩跹。\n他说：实践。风雷动，旌旗奋。从头越，敢叫日月换新天。人民万岁！\n多少年过去，弹指一挥间。如今又是新的斗争\n所以抛弃历史的包袱，丢弃幻想，准备斗争！须知该入土的总会入土，该降生的总会降生。\n旅途的终点再见吧，去见证一切事物的沉淀。\n12：47 坏了，这段话主旨是什么？不管了，睡觉\n","date":"2025-06-16T11:33:36+08:00","image":"/images/heshuangle1.webp","permalink":"/posts/%E5%96%9D%E7%88%BD%E4%BA%86/","title":"喝爽了"},{"content":"印象中，往日一直都是六月的盛夏\n幼稚的我幻想\n天边的彩霞，温柔的晚风会一直将我陪伴\n我记得啊，那天书山的缝隙里爬出带刺的野花\n洁白的鹤，请借我双翅\n我看见河汉灿烂，光屑簌簌落成人间的星华\n“朋友啊，你看到了吗？月亮升起来了”\n在这时针一刻不停转动的时间里啊\n精心准备了千言万语，怎能传达\n千万个无人的夜空下\n每当被夏的旋律吸引而回首\n看到的都是你笑靥如花\n云天收夏色，木叶动秋声，送走生命中持续一个世纪的夏\n结束了\n将我的懦弱，平庸与幻想溶解进月光\n饮下我亲手调制的毒药\n杀死自己的过往\n永别了\n请别想起我，或许也不会想起我。\n“万言难尽涩于口，祈尔繁芜胜常春”\n捻起最后一杯浊酒\n敬你坦荡的远方\n","date":"2025-06-16T11:33:15+08:00","image":"/images/juebieshu2.webp","permalink":"/posts/%E8%AF%80%E5%88%AB%E4%B9%A6/","title":"诀别书"},{"content":"六月十六，晨，有码字冲动。​​\n都说书读哪样，人就长哪样。行吧，那就掰扯掰扯我这歪脖子树苗，是怎么被书浇灌（或毒打）成这副德性的。\n大致分仨阶段。\n​第一阶段：八岁以前。​​ 启蒙书，小儿科，跳过。没啥可说的，跟婴儿米粉一个级别。\n​第二阶段：八岁到十三岁。​​ 嚯，这时候不一样了，开始读带刺儿的了。​郑渊洁，这位必须放头牌。写童话就好好写呗，非得往里塞点让人心里咯噔一下的隐喻。这人，有意思。\n现在也想不起多少具体情节了，就两故事死赖在脑子里。​一个恐龙复活追寻自由的。​​ 自由？啧，成年人的口头禅，因为够不着，所以叫得响。另一个皮皮鲁跟老师交换身体。​​ 结局特惨，忘光光了，就记得是个悲剧。我这人向来烦悲剧，但这故事愣是跟了我几年，怪事。\n就这堆十岁前的精神食粮，愣是给我脑子里塞进不少东西。知道人嘛，一半是天使一半是魔鬼；社会呢，一半寒风一半暖炉；人生更是，苦药汁里泡着糖丸……当然，那会儿的觉悟也就到糖丸为止了。小孩嘛，懂个屁。现在？呵，现在也不过是个懂个“屁”字怎么写的大号儿童罢了。\n后来很长一段时间，我眼里的世界就只剩下前半句了——魔鬼、寒风、苦药汁子。挺好，挺真实。好在现在嘛，算明白点“两面性”了。老祖宗们天天念叨这词儿，听着挺有道理，对吧？可惜我这眼睛，通常只能看清一面。\n​再后来，书单变了。​​\n童话淡出，​文学顶上了。虚构类还是不少：哈利波特在九又四分之三站台撞墙，福尔摩斯拿烟灰当点心，了不起的狐狸爸爸后来还看了电影（感觉不如书），西方神仙打架的厚书，还有语文课本钦定的四大名著，甭管读没读懂，都装模作样看了一遍。\n接着是曹文轩。这名字得单拎出来磕一下。他笔底下那种柴米油盐的朴素劲儿，把我口味养刁了。平淡日子的描摹，看着比啥魔法都踏实。魔幻现实？似乎也有那点意思。\n其他？正儿八经的“史书”也翻过，像《明朝那些事儿》，写得是妙，现在还偶尔抽风翻两页。但历史这玩意儿，吸引力有限。为啥？我骨子里不太信“物质决定一切”那套史观。信啥？信人是关键，信某些“脑子抽风”的念头能改天换地。唯心史观？听着就不像好词儿？行吧，那就点到为止。\n这阶段还有个“散文”插曲。这是个奇妙又古怪的玩意儿。国内教育牛逼，硬是把散文拆碎了喂给我们，塞进阅读理解题里，让你分析“表达了作者何种蛋蛋的忧桑”。那是我分数最低的地带，一半都悬。但吊诡的是，我不讨厌散文本身。这感情，拧巴，难以描述。总结：读散文可以，考散文？我呸。\n以上种种，十三岁前。它们像模子，我这摊软泥巴，基本就按这个轮廓定住了。\n​然后，十三到十五岁（是的，我就十五），书？几乎没碰。​​\n​干嘛去了？上网。​​\n别笑。网这东西，看着不像书，可它锤打（或者说揉搓？）起人来，效率一点也不低。全方位改变（或者扭曲？）了我的三观。\n展开讲讲？行吧，先说点喜闻乐见的——性。​​ Internet, 真是个看 Pron 的绝妙好地方。\n结果？杂七杂八的性癖好，跟雨后狗尿苔似的冒出来。随便举点：肛塞？懂。Tomboy？行。窒息捆绑？嗯哼。第四爱？存在即合理。Furry？有点意思。恋发癖？（这得怨我同桌，当然不赖人家头发长得独特，人家也肯定不想这样）。Cos？露……（写到这里，自己也觉得种类似乎有点……哇哦。）\n行，打住。再看点正经东西——电影。\n电影看了不少，尤其偏爱昆汀那套，血浆拌嘴炮。​文艺片也看，三部是刻进DNA里的：《太阳照常升起》（看不懂，但贼喜欢）、《大象席地而坐》（看完堵得慌，但真实）、《让子弹飞》（姜文牛逼！哦对了，那俩都姓姜）。篇幅有限，其他省略。\n美剧就俩：《绝命毒师》和《风骚律师》。这两部剧，简直给我脑袋开了光，审美处世，都染上它的颜色。我感觉自己走路都像带着索尔·古德曼那点小市民的精明劲儿。\n音乐影响也大？那是，但篇幅不够，下次（如果还有下次）再侃。\n好了，总结陈词：在书籍、网络、影音联合塑造下，现在的我——好色、易燃易爆炸、容易陷入没由来的丧、脑袋时而空空、待人时滑时怂、为达目的有点小不择手段、同时揣着点不顶屁用的理想主义空炮。​​\n日常离不了咖啡因或酒精，不然脑子跟浆糊没两样。 这辈子，也就这样了。\n​直到，前阵子买了Kindle。​​\n阅读习惯好像捡回来了点。这段日子在Kindle上又啃了点东西。 漫画有两部：\n​​《关于地球的运动》​​：画功？糙。情节？有点哲学味儿。嗯，对我的空炮理想主义有正面加成。 ​​《炎拳》​​：藤本树的大作，太他妈飞太荒诞了！但后劲极强，读完脑子嗡嗡的，像被操了几百下。（话说第一次看藤本树这哥们儿就挑《炎拳》，我品味是不是有点刁钻？乐。） 小说：\n​​《焦虑的人》​​：套路多，结局暖。看完有缓解焦虑？好像有点。 ​​《人间失格》​​：太宰治的书。太对味了。才华？人家是大师，我是渣渣。不良嗜好加悲惨命运？倒像双胞胎兄弟。希望我撑过28岁大关。 ​​《通往夏天的隧道》​​：还行。马马虎虎。 ​​《中国2185》​​：改变了我的文风。写得嫩？不妨碍喜欢。 ​​《圆圈正义》​​：罗翔老师的集子。看着乐呵，实用性？暂时没感觉到。 ​​《性心理学》​​：嗯，这书值得一翻，解惑良多。 所以你看，兜兜转转，还得是读。​它捏住了我前十五年，估计还得捏住后面几十年。​​\n一个人的书，就是他思想的底裤（或者情趣内衣？）。 既然我这么爱看书，那么我的另一个“性癖”，大概就是“脑交”。（笑）\n","date":"2025-06-16T09:43:21+08:00","image":"/images/lucy.webp","permalink":"/posts/%E8%B0%81%E4%BA%BA%E7%9A%84%E6%80%9D%E6%83%B3%E5%8F%B2/","title":"谁人的思想史"},{"content":"二零二五，六月十五，下午，突然想盘点下这些年为谁心动过。甭管算不算爱，先叫它《扯淡版·罗曼迪克野史》吧。​​\n​得从小学扒拉。​​ 毛都没长齐，就“喜欢”了仨。\n​第一个，林小姐。​​ 这位姐们儿更神，小学就留过洋——英国的。四年级，像被退件似的转回我们这破学校。巧了，那会儿我他妈正好开始“发育”，不是身体，是那点破心思。两家老妈熟得穿一条裤子，于是我俩就理所应当地被推到了一块儿。\n​她什么样？​​ 个子还行（当然比我矮点），标准好学生范儿——眼镜、长辫子，一脸“未来不是北大就是剑桥”。脾气倒温和，有自己主意，审美也不错。跟我？挺合拍。\n操蛋的是，打第一个姑娘起，我就染上一种病——情感饥渴症。跟她待着，屁话不说也觉着舒坦。玩得是挺好。后来怎么掰了？忘了。也可能压根就没“合”过，纯属我单方面加戏。\n为啥加戏？网冲得早，不该看的书看得太多，活活把脑子腌入味了，​早熟？不如说是腌坏了。不由自主把这点小学生过家家的情谊，放大、扭曲、涂脂抹粉。觉得能一起待着就是天堂，说句话就烧高香，要能碰着，操，简直得道升仙。​得，日后情路走歪，根儿在这儿埋着呢。​​\n​第二位，张姑娘。​​ 跟我一个姓，班里唯二姓张的。​巧？不如说倒霉催的凑一块儿了。​​ 她跳舞，当然，吸引我的不是这个。她长得好看，标准的班花。一群人惦记，最后我居然跟她“谈上了”？操，那时候觉得挺牛逼，现在想想，简直是狗屎运里踩雷——炸得真他妈灿烂。​​\n我俩没啥精神交流，纯属肉体摸索。像俩瞎子摸黑撞墙，只能靠着对方当拐棍。更像是俩提线木偶，线他妈缠死了，想分也扯不开。她喜欢饭圈那些玩意儿，被资本当韭菜割得嘎嘣脆还美滋滋（可能是我偏见？反正不懂）。\n我呢？自诩喜欢“深刻”、带“思想”的，觉得自己是个潜伏在小学的思想家遗珠。\n​这能凑一块？简直就是韭菜炒哲学，注定糊锅烂灶，无花也无果！​​ 后来我才明白，这荒唐组合是个开始，​往后的日子，我跟“不合适”仨字儿跟拜把子兄弟似的。​​\n至于她外表？好看。仅此，也只剩这个了。\n​第三位，学霸李。​​ ​我“智性恋”癖好的第一次胜利（或者说沦陷）​。绝对的学霸，碾压我的那种。老子在小学那也是前十里混的，她呢？经常第一。碾压，纯的。\n于是，我学会了慕强。​这病根，日后茁壮成长。​​ 她长相平平无奇，扔人堆里找不着，有点像我后来初中一姓李的同学（这算不算替身文学的雏形？）。\n能力强，刚说了；脾气嘛，对我来讲是差。说她对我没耐心吧，有时候又能憋着。​矛盾得能拧出水儿来。现在看，大概是她不知道怎么表达，也可能压根没想对我表达什么。我呢？一样蠢，只会靠恶作剧去刷存在感。\n结局？操，忘了。​忘得真他妈干净。​​\n​好了，战场转移到初中。主要俩：一个姓李（假的），一个姓徐（真的？）。​​\n​先说李（假的）。​​ 丫长得像个Tomboy，假小子。操，纯他妈是被这副壳子勾了魂。 ​我承认，我就一俗人，看脸。​​ 我对短发姑娘有迷之执着。比如还有个姓高的，也是个假小子款儿，个儿贼高，可惜没缘分，就图一眼。​不重要，打住。​​\n这位假小子李，精神状态堪忧。家里重男轻女，被当透明人。没啥具体病，就是缺爱缺得厉害。我呢？保护欲过剩得像垃圾场里的厨余，没地方倒。\n​学生时代，过剩的或残缺的感情，都他妈往同学身上招呼。​​ 所以严格来说，我们是各取所需的精神盲流加肉体难民。\n交流？有，不多。主要项目是互相摸索——课桌底下、放学路上，逮着机会就动手动脚，手臂啊肩膀啊（关键部位？那会儿还没那狗胆），不细说了，反正现在回想—— ​恶心 恶心 真他妈恶心​ 后来掰了，仇人见面分分钟吵炸锅，因为她喜欢别人了。​就她那精神状态，干这事儿再正常不过。​​ ​还是恶心​ ​​(循环播放十遍恶心.mp3)​​\n​再说姓徐的姑娘。​​ ​三年！整整三年！我他妈跟她坐一桌坐了三年！​​ 关系呢？原地踏步，纹丝不动。熟？陌生人以上。好？谈不上。​这配置堪称人类同桌关系史上的奇迹——稳定得像个王八。​​\n我对她的感情，复杂得能写篇论文，肯定不是纯粹的“喜欢”。\n她长相？​非常、极其、特别、宇宙级别的平平无奇，属于混进人群直接开启隐身模式那种。不过有个人间标识：一头卷毛，​头皮稀疏得可疑​，外加常年绑着蓝发箍和蓝发圈。蓝得晃眼，一百米开外就能锁定目标。\n学习牛逼，稳上本地一中重点班那种。班里前五，学校前五十。​我呢？衬托她牛逼的绿叶本绿。​​ 我现在的自卑，大半算她的功劳。\n当然，人家屁错没有。道理懂，非常懂，​可老子这颗心，它不答应啊！​​\n所以我对她，爱的成分有没有？可能有。但嫉妒绝对占大头，烧得我五脏六腑冒烟。​​ 我那点讨好型人格，估计也是在她这儿练的级——总觉得她帮我学习（后来发现她啥事儿都能指点），我就得还，还不乐意也得还。\n​操，老子恨她！虽然她无辜得像张白纸，但这股恨意就是刹不住车！​​ 精神交流？约等于无。肢体接触？几乎没有（除了后文唯一一次）。​但她就像根烧红的烙铁，在我灵魂上滋滋作响，留下巨坑。​​ 她让我想从教学楼自由落体，就因为觉得自己是坨废物。\n​想放下？试了，没用。​​ ​她挺好，我是渣。​​\n跟她捆一块儿的唯一好处？学习确实被鞭子抽着上去了点。毕业典礼那天？散场跟逃难似的，我冲进人堆只想滚回家睡觉，她还在那儿满世界找老师签名呢。​连句“再见”都他妈省了。​​\n唯一一次牵手，是她抽风要给我鼓掌。老子脸臊得慌，伸手就攥住她爪子：“停！别丢人了！” ​所谓鼓掌，是我俩的阴阳怪气保留项目，本质是嘲讽对方嘚瑟，也许带点鼓励？鬼知道。​​ 只记得最早那次，是我真心实意给她鼓的。\n​我不爱她。大概只是我脑子犯抽，关心溢成太平洋了。​​\n​她们仨（俩李一徐），像几块乱七八糟的砖，在我这地基不稳的破屋里各占一角。时间能抹掉吗？够呛。老子也不想抹。至少那些记忆的疤，留着吧。​​\n","date":"2025-06-15T19:54:38+08:00","image":"/images/Va-11 Hall-A.webp","permalink":"/posts/%E7%BD%97%E6%9B%BC%E8%BF%AA%E5%85%8B%E5%8F%B2/","title":"罗曼迪克野史"},{"content":"梦搁在床底我没拿， 那听起来忒傻。 想到以前就后怕， 现在我只想办张绿卡。 有人说我源神， 有人认我雷锋。 我为各位兜不少圈子， 各位为我也一样。 心中的乌托邦， 居然建在现实上。 想干些什么， 却中想不中用。 亲哥上了一中， 还他妈上了重点班。 一起聊天的一中也包， 就瓷几个天天瞎鸡巴搞。 见着兄弟越来越少， 走高的高， 走好的好。\n在权衡着 正直或者家庭 坦诚还是糊弄 我在权衡 稀释还是牺牲 一句话说过了喝西北风 我在权衡 摇晃的天平 (我在权衡) 摇晃的前程 (我在权衡) 比我的生命更重 他说有些比你的生命要重\n我其实没瓷， 也没跟她好。 有时说两句话， 真以为能好。 开始有点失眠， 开始不想吃甜， 开始抱着硬币， 开始盲目求天。 医生说是咖啡的祸， 我说她不背这锅。 她说她不喝咖啡， 她说她喝奶茶。 我又该带点啥， 难不成带点茶。 我自己吃蓝莓， 给她吃条山楂。 她吃了但她没夸， 我一直盯着我的胯。 起来又坐下， 我说这是白天别他妈睁眼瞎。 回家连上了网， 想看黄， 还得翻道墙。 中国人真傻， 能装孙子也能当。 我只得学着秘方， 给自己的的话建个乌托邦。 我想催情药的秘方， 西地那非泡黄姜。 装填弹药在我两个弹仓， 说不出的话变成了伤。 梦想别想都不敢想， 城市的程序化别把它变成银晌。\n还在权衡着 正直或者家庭 坦诚还是糊弄 我在权衡 稀释还是牺牲 一句话说过了喝西北风 我在权衡 摇晃的天平 (我在权衡) 摇晃的前程 (我在权衡) 比我的生命更重 他说有些比你的生命要重\n穷日子没过过， 花钱像数学家。 21块艾克劳德， 闭眼一句随便花。 有时烦的说不出话， 只能凸显出嗓门大。 嗨哥不能嗨歌， 别真把自己当希特勒。 小粉红们别怕， 祖国爱着你们你们不瞎。 从出生没少往死里作， 青春期的朋友没少过， 结果都没当人， 包括我， 也都没把各自放过。 说的和做的一个配色， 是传播爱还是传播艾滋。 瓷你别他妈真饿， 虽然我真没朋友也没瓷。 就像我写不出词， 但这是真实的我们各自。 也可能只是我幻想的自私， 只是16天后各管各自。 我现在有点想死， 不能再与她聊天。 因为我们去处不同， 这也用不着分辩。 3年之后于梦中再见， 愿我别把你们忘干净了， 像我的前6年。\n在权衡着 正直或者家庭 坦诚还是糊弄 我在权衡 稀释还是牺牲 一句话说过了喝西北风 我在权衡 摇晃的天平 (我在权衡) 摇晃的前程 (我在权衡) 比我的生命更重 他说有些比你的生命要重\n","date":"2025-06-01T09:48:13+08:00","image":"/images/quweixiaochangshi.webp","permalink":"/posts/%E6%9D%83%E8%A1%A1%E4%B8%8D%E4%BA%86/","title":"权衡不了"},{"content":"注：教程以Windows系统为例 1. 安装Node.js 2. 安装git 一直点确定就行，全部按它默认勾的，若要细细配置可参照这篇文章\n3. 测试一下，管理员运行cmd，依次输入 node -v npm -v git -v 若正常显示版本号即可\n4. 下载hexo 新建一个文件夹，用来存放blog 右键，选择Open git bash here 依次输入 npm install hexo-cli -g hexo init blog cd blog npm install hexo server 5. 简单认识hexo 进入自动创建的blog文件夹 _config.yml，在这个文件内修改博客基础设置 blog\\source_posts，在这个文件夹内修改博客文章 themes，在这个文件夹内修改主题 在自动创建的blog文件夹内右键，选择Open git bash here 基础指令： # 开启服务 hexo s # 新建文章 hexo new 文章名 # 新建草稿 hexo new draft 文章名 # 发布草稿成为文章 hexo publish 文章名 # 普通页面 hexo new page 页面名 # 清空缓存 hexo cl # 生成静态页面 hexo g # 然后访问localhost:4000 # 部署文章 hexo d 6. 搭建仓库 注册/登入Github（可能无法访问，建议使用watt tolkit） 点击Create a new repository进入新建仓库页面，仓库名输入： 你的GitHub用户名.github.io 勾选 Public 勾选 Add a README file 拉到下面点击create创建 7. 生成SSH Keys 进入任意文件夹，右键空白处然后点Open Git bash here,输入 ssh-keygen -t rsa -C \u0026#34;你的GitHub注册邮箱\u0026#34; 敲4次Enter 进入C:\\Users\\用户名，在里面进入 .ssh文件夹 打开里面的id_rsa.pub，全选复制里面的代码 打开github 进入用户设置，找到SSH keys 新建SSH keys，名称随意，在下面粘贴代码，然后创建 8. 测试是否成功 在git bash中输入 ssh -T git@github.com 回车，然后再输入yes\n9. 配置_config.yml 进入之前的Blog文件夹，打开 _config.yml 拉到最下面将deploy后面的全删掉，复制粘贴这段 type: git repository: branch: main 注意缩进格式：每行前面都有两个空格不要删，每个冒号后面都有个空格也不要删！\n去github之前生成的仓库页面，点code，复制https链接，将其粘贴到**repository：**后面，然后保存退出 10. 安装自动部署发布工具 回到博客文件夹，一样git bash 输入： npm install hexo-deployer-git --save 在Blog文件夹右键打开git bash，依次输入 hexo g hexo d 如果是第一次使用git的话会需要配置\ngit config --global user.email user.email即你注册GitHub的邮箱\ngit config --global user.name user.name即你注册GitHub的名字\n配置完后再输入 hexo d ，然后在跳出来的窗口内进行登录 接下来我们就成功把本地内容上传到github了\n11.上传成功 上传成功以后，我们就算搭建好了！上自己的网址看看吧 网址是我们之前设的仓库名：你的GitHub用户名.github.io\n","date":"2025-05-11T20:02:30+08:00","image":"/images/hexo.webp","permalink":"/posts/hexo%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA%E6%8C%87%E5%8C%97/","title":"hexo博客搭建指北"},{"content":"注：LSPatch支持系统：Android，且需要使用Shizuku 下载并安装LSPatch 点击下载，下载安装包（.apk） 点击安装包，安装软件 激活LSPatch 打开LSPatch，显示Shizuku服务未连接，部分功能不可用，不过没关系，可以先不管它 点击LSPatch下方第二个图标管理，再点击右下角的加号，此时会提示选择一个目录来存储已修复的apk 选择自己方便调用的文件夹，点击使用此文件夹并给予存储权限 再点击加号，弹出新建修补，我们可从存储目录中选择安装包（.apk）或选择已安装的应用程序 选择好程序和修补模式后即可开始修补 注：推荐便携模式并嵌入提前下载好的对应Xposed模块，模块需要自行寻找，后文会放几个模块供大家练手 修复过程需要耐心等待一段时间，待修补完成后我们点击安装会提示Shizuku服务未链接，这是因为前面我们刚打开LSPatch时显示的Shizuku服务未连接部分功能不可用，不过没有关系，但是如果想使用Shizuku可以参考这篇文章 在文件管理器里打开刚才设置的文件夹，可以看到修补后的安装包,只需要手动卸载原包再手动安装修补后的包即可。安装完成后打开该APP，在设置中可以看到模块已嵌入成功（有的模块可能不会在设置里显示） 提醒事项 用便携模式修补后的APK可脱离LSPatch框架使用，分享给别的设备也可正常使用对应模块。而本地模式修补无需内置模块，但是修补后的应用需要LSPatch保持后台持续运行且需要Shizuku才能正常使用，并且只能在本机上运行，这也是更推荐大家使用便携模式的原因 若模块在嵌入后不起作用，可能是模块本体的问题，也可能是安装包的问题（这不跟没说一样吗），需自行查找问题 关于模块 模块通常以软件形式存在，下载后是安装包，需要安装后才能使用\n官方仓库，里面有大量模块，但是被墙了，可以参考这篇文章使用Clash或者其他软件进行科学上网，这里不过多赘述 模块推荐： HookVIP，目前最新的3.5.5与3.5.6已经失效，只有3.5.4可以正常使用 道道道，功能很简单，破解一些VPN应用会员，但是很好用 杜比大喇叭，一款网易云音乐的音源代理模块。模块工作原理为音源替换而非破解，所以单曲付费与无版权歌曲有几率匹配错误，真心支持歌手请付费！ ","date":"2025-04-12T14:45:15+08:00","image":"/images/lspatch.webp","permalink":"/posts/lspatch%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8C%97/","title":"LSPatch使用指北"},{"content":"注：Shizuku支持系统：Android 下载并安装shizuku 点击下载，下载安装包（.apk） 点击安装包，安装软件 激活shizuku 打开开发人员选项 通常是进入关于后点击版本号5或7次，可能会要求输入密码，不同品牌可能会有区别，视情况而定 进入开发人员选项 找到调试一栏中的USB调试和仅充电模式下允许ADB调试（没有仅充电模式下允许ADB调试可以不开），将其开启 接下来的步骤会分为两大类，请视自己情况而定 若在调试一栏中找到无线调试，可以跳转到下一章节 若没有无线调试，请准备一台搭载Windows系统的电脑并继续往下看\n通过电脑启动（无无线调试，适用于Windows） 下载ADB调试工具 解压缩后将解压出来的文件夹重命名为adb并移动到C盘根目录（非必需，但是推荐这么做） 进入电脑设置，搜索高级系统设置并进入 选择环境变量 点击系统变量一栏中的path并双击进行编辑 点击右侧新建 输入刚才的文件路径（C:\\adb） 然后一路确定，保存并退出 接下来将手机（或其他设备）连接电脑， 打开cmd（直接在搜索栏输入并回车），输入adb devices，此时若正确开起了开发人员选项中的USB调试，此时设备上可能会出现是否允许调试的对话框，勾选总是允许，接下来可以在通知中心看到USB调试的信息 再次在终端中输入adb devices，如无问题将会看到类似如下内容 List of devices attached XXX device 复制以下指令并粘贴到cmd中，如无问题你将会在 Shizuku 中看到已启动成功 adb shell sh /sdcard/Android/data/moe.shizuku.privileged.api/start.sh 该启动方式适用于未 root 且运行 Android 10 及以下版本或者HarmonyOS的设备。很不幸，该启动方式需要连接电脑。且由于系统限制，每次重新启动后都需要再次进行启动步骤 通过无线调试启动 进入开发人员选项中的无线调试 启用无线调试 配对（仅需一次） 在 Shizuku 内开始配对 点按无线调试中的使用配对码配对设备 在Shizuku的通知中填入配对码 启动Shizuku 如果无法启动，尝试禁用并启用无线调试 通过无线调试启动适用于 Android 11 或以上版本。这种启动方式无需连接电脑。由于系统限制，每次重新启动后都需要再次进行启动步骤 通过 root 启动 如果您的设备已经 root，直接启动即可\n常见问题 许多厂商对 Android 系统进行了修改，这会造成 Shizuku 无法正常工作。\n通过无线调试启动：一直显示“正在搜索配对服务” 请允许 Shizuku 在后台运行。 搜索配对服务需要访问本地网络，许多厂商在应用不可见后立刻禁止应用访问网络。您可以在网络上搜索如何在您的设备上允许应用在后台运行。\n通过无线调试启动：点击“输入配对码”后立刻提示失败 MIUI（小米、POCO） 在系统设置的“通知管理”-“通知显示设置”将通知样式切换为“原生样式”。\n通过无线调试启动/通过连接电脑启动：adb 权限受限 MIUI（小米、POCO） 在“开发者选项”中开启“USB 调试（安全设置）”。注意，这和“USB 调试”是两个分开的选项。\nColorOS（OPPO \u0026amp; OnePlus） 在“开发者选项”中关闭“权限监控”。\nFlyme（魅族） 在“开发者选项”中关闭“Flyme 支付保护”。\n通过无线调试启动/通过连接电脑启动：Shizuku 随机停止 所有设备 保证 Shizuku 可以在后台运行。\n不要关闭“USB 调试”及“开发者选项”。\n在“开发者选项”中将 USB 使用模式改为“仅充电”。\n在 Android 8 上的选项是“选择 USB 配置”-“仅充电”。 在 Android 9 及以上版本上选项是“默认 USB 配置”-“不进行数据传输”。\n（Android 11+）启用“停用 adb 授权超时功能”选项\nEMUI (华为) 在“开发者选项”中开启「“仅充电”模式下允许 ADB 调试选项」。\nMIUI（小米、POCO） 不要使用“手机管家”的扫描功能，因为它会禁用开发者选项。\nSony 不要点击连接 USB 后弹出的对话框，因为这会导致 USB 使用模式发生变化。\n通过 root 启动：无法开机启动 请允许 Shizuku 在后台运行。\n","date":"2025-04-12T10:00:39+08:00","image":"/images/shizuku.gif","permalink":"/posts/shizuku%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8C%97/","title":"Shizuku使用指北"},{"content":"文章以对话形式呈现，为良好观感，请勿带入角色 当然啦，我们说的是别的东西，总之不是你想的那样 参演角色：bai，black bai：一只真正的鱼是不会被禁锢在海洋或陆地上的，因为他们的每片鳞片都闪烁着自由的光辉。 black：嗯。\nbai：鱼和鱼干是一个循环往复的过程，有越来越多的鱼干为了自己在橱窗边最显眼的位置而重新回到大海，“不甘心”的赌徒心理也是造成鱼群堆积的原因之一，他们追求所谓的钱，场面，推崇高低贵贱，他们占据了多少片海洋，幻想着自己是那一个幸运的鱼干，殊不知自己只是夹在鱼和鱼干中充当缓冲区的牺牲品，他们到死都以为是自己不够努力。 black：鱼没有思想。你说的这些可能根本没有人想到。\nmd，说到底还是赛里斯人太多。\nbai：教鱼者最主要的问题还是时代在裹挟着他前进，他无法选择真正向往自由的鱼，只能像大海捞针一样从一堆鱼中选出几个最听话的，三六九等的教鱼会有三六九等的撒网方法，最高等的教鱼者只有一片海，最金贵的那一片，一切都不是一条鱼能掌控的，这中间有太多太多复杂的东西影响他的内心，导致他只能无可奈何地把自己作为手段去任人宰割。 black：这是鱼竿的问题，确实不只能怪他们。\nbai：我们不得不承认一个可悲的事实——我们的生活大部分在这些上等鱼的掌控之下，因为鱼性，我们无法组织有效的抵抗，因为先前所说的，我们的自由被剥夺了，思想上的自由，导致我们的求知欲从一开始就被扼杀，而陷入一个一心只读圣贤书的界限，真正的知识一定是知行合一的，鱼的新鲜程度是价格，消耗水分是为了把自己卖出一个更好的价钱。 black：我更喜欢吃新鲜的，鱼干不好吃。\nbai：地球上陆三海七，海里的鱼注定是大多数，鱼自当刚强壮胆。鱼群不应分裂，应以自身为约束，终有一天，广阔天地，会变成汪洋大海。 black：希望吧。\n北冥有鱼，其名为鳖。鳖之大，不知其几千里也。 革命无罪，造反有理！\n","date":"2025-04-05T21:45:04+08:00","image":"/images/xiaogong.webp","permalink":"/posts/%E9%B1%BC%E4%B8%8E%E9%B1%BC%E5%B9%B2/","title":"鱼与鱼干"},{"content":"墙国有我，请挡放心\n此文档为学习交流而分享，建议您在下载后24小时内删除。如有版权问题请告知，我将第一时间处理。请注意，使用产生的责任需由使用者自行承担。 尽量使用浏览器打开本文章（如edge），而非微信内置浏览器等\n注意：Clash支持系统：Android，Windows，MacOS（本教程不涉及） iOS及iPadOS可以使用Spectre或者Shadowrocket，以及hidify，请自行去App Store下载。\nWindows安装及使用（以Clash Verge Rev为例）： 下载Clash Verge Rev，双击安装包并安装（若申请管理员权限则允许），步骤如下\n选择语言（推荐中文简体），点击OK 点击下一步 点击下一步 点击安装 等待 点击下一步 点击完成 后续可能会申请两次管理员权限，允许即可 导入配置文件\n若配置文件需从链接下载，则点击左侧订阅，在页面上方订阅文件链接处输入链接，点击右侧导入即可。 若配置文件在本地，则只需将文件拖拽进窗口即可 使用\n点击左侧设置，点击左列系统代理即可使用，不需要时可直接关闭系统代理 推荐打开：开机自启；静默启动；局域网链接\n局域网链接说明：对于部分无法使用clash客户端的设备，可通过这种方式实现曲线救国，具体操作如下： 点进设置并与电脑链接在同一局域网，点进网络详情，将http代理切换为手动，服务器填写为电脑的内网IP地址，可点击clash设置中局域网链接旁边的有三个连接在一起的方块的图标查看，上面的IP地址即为所要 端口默认是7897 关闭鉴定 Android安装及使用 下载Clash Meta for Android，点击安装包（文件后缀为apk），安装\n打开Clash Meta for Android，点击配置\n点击右上角加号，然后导入\n若配置文件需从链接下载，则点击从URL导入，输入链接后点击右上角保存按钮 若配置文件在本地，则点击从文件导入，点击浏览文件，点击配置文件右侧三个点，点击下方弹出窗口的导入，选择文件后点击左上角箭头，点击右上角保存按钮 回到主页，点击启动，若申请权限则同意\n点击代理可选择节点，若想停止只需回到主页，点击运行中（蓝色的图标）即可停止\n部分Android手机在控制中心可以自定义快捷开关，可以将Clash Meta快捷开关添加到控制中心，以方便使用 部分情况下会碰到无法添加配置文件的情况，可以多尝试几次，不排除是服务器或软件的问题\n文章可能会继续更新以补充使用技巧，文章中所有下载链接来自Clash中文网\n","date":"2025-04-04T19:53:20+08:00","image":"/images/clashforwindows.webp","permalink":"/posts/clash%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8C%97/","title":"Clash使用指北"}]