峯言凬语 O ever youthful O ever weeping~
本无意与众不同,怎奈何口味太重。
首页
平水韵
颜色表
ABOUT
文章分类
友情链接
您正在查看:Nonni 发布的文章

A-10攻击机.jpg

参考 ca110us 的代码,修改了代理和加密部分,使用 CF 的 Worker 脚本自动生成订阅地址,也可后续手动优选 IP。
原 Github 项目地址:

https://github.com/ca110us/epeius

前提
确定有自己的域名托管在 Cloud Flare 中。

部署
1.登录 CloudFlare,点击 Workers/Pages,创建Workers。
2.输入一个喜欢的项目名字,创建项目。
3.部署站点,编辑CODE,贴入下面代码:

// src/worker.js
import { connect } from "cloudflare:sockets";
const proxyIPs = ['cdn.xn--b6gac.eu.org', 'cdn-all.xn--b6gac.eu.org', 'workers.cloudflare.cyou'];

let proxyIP = proxyIPs[Math.floor(Math.random() * proxyIPs.length)];

let sha224Password = 'bd7a2ae56e0de3f72a0655b3f74b355fb4fdad5004149e6aa7ce9026';

const worker_default = {
   /**
    * @param {import("@cloudflare/workers-types").Request} request
    * @param {{UUID: string, PROXYIP: string}} env
    * @param {import("@cloudflare/workers-types").ExecutionContext} ctx
    * @returns {Promise<Response>}
    */
   async fetch(request, env, ctx) {
       try {
           proxyIP = env.PROXYIP || proxyIP;
           const upgradeHeader = request.headers.get("Upgrade");
           if (!upgradeHeader || upgradeHeader !== "websocket") {
               const url = new URL(request.url);
               switch (url.pathname) {
                   case "/link":
                       const host = request.headers.get('Host');
                       return new Response(`trojan://TSI2nice@${host}:443/?type=ws&host=${host}&security=tls`, {
                           status: 200,
                           headers: {
                               "Content-Type": "text/plain;charset=utf-8",
                          }
                      });
                   default:
                       return new Response("404 Not found", { status: 404 });
              }
          } else {
               return await trojanOverWSHandler(request);
          }
      } catch (err) {
           let e = err;
           return new Response(e.toString());
      }
  }
};

async function trojanOverWSHandler(request) {
   const webSocketPair = new WebSocketPair();
   const [client, webSocket] = Object.values(webSocketPair);
   webSocket.accept();
   let address = "";
   let portWithRandomLog = "";
   const log = (info, event) => {
       console.log(`[${address}:${portWithRandomLog}] ${info}`, event || "");
  };
   const earlyDataHeader = request.headers.get("sec-websocket-protocol") || "";
   const readableWebSocketStream = makeReadableWebSocketStream(webSocket, earlyDataHeader, log);
   let remoteSocketWapper = {
       value: null
  };
   let udpStreamWrite = null;
   readableWebSocketStream.pipeTo(new WritableStream({
       async write(chunk, controller) {
           if (udpStreamWrite) {
               return udpStreamWrite(chunk);
          }
           if (remoteSocketWapper.value) {
               const writer = remoteSocketWapper.value.writable.getWriter();
               await writer.write(chunk);
               writer.releaseLock();
               return;
          }
           const {
               hasError,
               message,
               portRemote = 443,
               addressRemote = "",
               rawClientData
          } = await parseTrojanHeader(chunk);
           address = addressRemote;
           portWithRandomLog = `${portRemote}--${Math.random()} tcp`;
           if (hasError) {
               throw new Error(message);
               return;
          }
           handleTCPOutBound(remoteSocketWapper, addressRemote, portRemote, rawClientData, webSocket, log);
      },
       close() {
           log(`readableWebSocketStream is closed`);
      },
       abort(reason) {
           log(`readableWebSocketStream is aborted`, JSON.stringify(reason));
      }
  })).catch((err) => {
       log("readableWebSocketStream pipeTo error", err);
  });
   return new Response(null, {
       status: 101,
       // @ts-ignore
       webSocket: client
  });
}

async function parseTrojanHeader(buffer) {
   if (buffer.byteLength < 56) {
       return {
           hasError: true,
           message: "invalid data"
      };
  }
   let crLfIndex = 56;
   if (new Uint8Array(buffer.slice(56, 57))[0] !== 0x0d || new Uint8Array(buffer.slice(57, 58))[0] !== 0x0a) {
       return {
           hasError: true,
           message: "invalid header format (missing CR LF)"
      };
  }
   const password = new TextDecoder().decode(buffer.slice(0, crLfIndex));
   if (password !== sha224Password) {
       return {
           hasError: true,
           message: "invalid password"
      };
  }

   const socks5DataBuffer = buffer.slice(crLfIndex + 2);
   if (socks5DataBuffer.byteLength < 6) {
       return {
           hasError: true,
           message: "invalid SOCKS5 request data"
      };
  }

   const view = new DataView(socks5DataBuffer);
   const cmd = view.getUint8(0);
   if (cmd !== 1) {
       return {
           hasError: true,
           message: "unsupported command, only TCP (CONNECT) is allowed"
      };
  }

   const atype = view.getUint8(1);
   // 0x01: IPv4 address
   // 0x03: Domain name
   // 0x04: IPv6 address
   let addressLength = 0;
   let addressIndex = 2;
   let address = "";
   switch (atype) {
       case 1:
           addressLength = 4;
           address = new Uint8Array(
             socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
          ).join(".");
           break;
       case 3:
           addressLength = new Uint8Array(
             socks5DataBuffer.slice(addressIndex, addressIndex + 1)
          )[0];
           addressIndex += 1;
           address = new TextDecoder().decode(
             socks5DataBuffer.slice(addressIndex, addressIndex + addressLength)
          );
           break;
       case 4:
           addressLength = 16;
           const dataView = new DataView(socks5DataBuffer.slice(addressIndex, addressIndex + addressLength));
           const ipv6 = [];
           for (let i = 0; i < 8; i++) {
               ipv6.push(dataView.getUint16(i * 2).toString(16));
          }
           address = ipv6.join(":");
           break;
       default:
           return {
               hasError: true,
               message: `invalid addressType is ${atype}`
          };
  }

   if (!address) {
       return {
           hasError: true,
           message: `address is empty, addressType is ${atype}`
      };
  }

   const portIndex = addressIndex + addressLength;
   const portBuffer = socks5DataBuffer.slice(portIndex, portIndex + 2);
   const portRemote = new DataView(portBuffer).getUint16(0);
   return {
       hasError: false,
       addressRemote: address,
       portRemote,
       rawClientData: socks5DataBuffer.slice(portIndex + 4)
  };
}

async function handleTCPOutBound(remoteSocket, addressRemote, portRemote, rawClientData, webSocket, log) {
   async function connectAndWrite(address, port) {
       const tcpSocket2 = connect({
           hostname: address,
           port
      });
       remoteSocket.value = tcpSocket2;
       log(`connected to ${address}:${port}`);
       const writer = tcpSocket2.writable.getWriter();
       await writer.write(rawClientData);
       writer.releaseLock();
       return tcpSocket2;
  }
   async function retry() {
       const tcpSocket2 = await connectAndWrite(proxyIP || addressRemote, portRemote);
       tcpSocket2.closed.catch((error) => {
           console.log("retry tcpSocket closed error", error);
      }).finally(() => {
           safeCloseWebSocket(webSocket);
      });
       remoteSocketToWS(tcpSocket2, webSocket, null, log);
  }
   const tcpSocket = await connectAndWrite(addressRemote, portRemote);
   remoteSocketToWS(tcpSocket, webSocket, retry, log);
}

function makeReadableWebSocketStream(webSocketServer, earlyDataHeader, log) {
   let readableStreamCancel = false;
   const stream = new ReadableStream({
       start(controller) {
           webSocketServer.addEventListener("message", (event) => {
               if (readableStreamCancel) {
                   return;
              }
               const message = event.data;
               controller.enqueue(message);
          });
           webSocketServer.addEventListener("close", () => {
               safeCloseWebSocket(webSocketServer);
               if (readableStreamCancel) {
                   return;
              }
               controller.close();
          });
           webSocketServer.addEventListener("error", (err) => {
               log("webSocketServer error");
               controller.error(err);
          });
           const { earlyData, error } = base64ToArrayBuffer(earlyDataHeader);
           if (error) {
               controller.error(error);
          } else if (earlyData) {
               controller.enqueue(earlyData);
          }
      },
       pull(controller) {},
       cancel(reason) {
           if (readableStreamCancel) {
               return;
          }
           log(`readableStream was canceled, due to ${reason}`);
           readableStreamCancel = true;
           safeCloseWebSocket(webSocketServer);
      }
  });
   return stream;
}

async function remoteSocketToWS(remoteSocket, webSocket, retry, log) {
   let hasIncomingData = false;
   await remoteSocket.readable.pipeTo(
       new WritableStream({
           start() {},
           /**
            *
            * @param {Uint8Array} chunk
            * @param {*} controller
            */
           async write(chunk, controller) {
               hasIncomingData = true;
               if (webSocket.readyState !== WS_READY_STATE_OPEN) {
                   controller.error(
                       "webSocket connection is not open"
                  );
              }
               webSocket.send(chunk);
          },
           close() {
               log(`remoteSocket.readable is closed, hasIncomingData: ${hasIncomingData}`);
          },
           abort(reason) {
               console.error("remoteSocket.readable abort", reason);
          }
      })
  ).catch((error) => {
       console.error(
           `remoteSocketToWS error:`,
           error.stack || error
      );
       safeCloseWebSocket(webSocket);
  });
   if (hasIncomingData === false && retry) {
       log(`retry`);
       retry();
  }
}

function base64ToArrayBuffer(base64Str) {
   if (!base64Str) {
       return { error: null };
  }
   try {
       base64Str = base64Str.replace(/-/g, "+").replace(/_/g, "/");
       const decode = atob(base64Str);
       const arryBuffer = Uint8Array.from(decode, (c) => c.charCodeAt(0));
       return { earlyData: arryBuffer.buffer, error: null };
  } catch (error) {
       return { error };
  }
}

let WS_READY_STATE_OPEN = 1;
let WS_READY_STATE_CLOSING = 2;

function safeCloseWebSocket(socket) {
   try {
       if (socket.readyState === WS_READY_STATE_OPEN || socket.readyState === WS_READY_STATE_CLOSING) {
           socket.close();
      }
  } catch (error) {
       console.error("safeCloseWebSocket error", error);
  }
}
export {
   worker_default as
   default
};
//# sourceMappingURL=worker.js.map

4.密码部分默认是TSI2nice,也可自行修改,SHA224 加密运算工具:

https://tools.nonni.cn/hash.html

5.修改后点击部署,然后进入项目,在 Setting 的 Triggers 中设置一个自定义域名。
6.地址栏输入链接查看节点订阅信息地址:

https://自定义域名/link

AX6000.jpg
1.在 KoolCenter 固件中心下载对应型号的梅林改版固件:

https://fw.koolcenter.com

2.电脑连接路由器,点击左边的『系统管理』,选择『固件升级』- 点击上传,更新固件为梅林改版固件,进度条100%路由器会自行重启。
3.登录路由器,进行双清,手动配置路由器,完成后登录路由器,在『系统管理』–『系统设置』内勾选:Format JFFS partition at next boot 和 Enable JFFS custom scripts and configs, 点击『应用本页面设置』,成功后重启路由器,再次登录后出现『软件中心』。
4.下载安装科学插件,点击『软件中心』,软件中心版本,『进入设置』,点击『更新』保持当前版本与在线版本一致。点击 『手动安装』,选择已下载好的 MerlinClash插件文件。
merlinclash 插件使用文档与插件下载地址:

https://mcreadme.gitbook.io/mc
https://t.me/merlinclashfile

科学上网插件下载地址:

https://github.com/hq450/fancyss

守望先锋屁股高清壁纸.jpg

使用 CM 修改的 Worker 脚本自动生成自适应订阅,SUB CLASH 和 SURGE 订阅地址,自动优选 IP。
Github 项目地址:
https://github.com/cmliu/edgetunnel

部署
1.登录 CloudFlare,点击 Workers 和 Pages,Pages ,直接上传创建 – 上传资产。
2.输入一个喜欢的项目名字,创建项目。
3.下载 worker.zip,然后在上传资产页面点击从计算机中选择 – 上传压缩文件,部署站点,继续处理项目。
cf-free-node.png
4.在 UUID 生成工具网站 https://nonni.cn/uuid 生成一个 UUID。
5.在项目页面点设置 – 环境变量 – 添加变量,变量名称为 UUID ,变量值为刚才生成的那个 UUID ,点击保存。
cf-free-node-uuid.png
6.在项目页面点部署,创建新部署,再次上传刚才上传过的 worker.zip 文件,保存并部署。
7.点击部署中的域名链接访问站点,如果有内容出现,就证明部署成功了。
8.查看节点信息地址: https://域名链接/UUID
9.(可选项)如果有在 Cloudflare 中有域名托管,也可以在自定义域中设置自定义域。

showgirl.png

问题:
login Ubuntu 显示 There is 1 zombie process.

解决:

ps axo stat,ppid,pid,comm | grep -w defunct
sudo kill -9 <ppid>

cloudgirl.jpeg

20年的微软 VScode 用户,在 Windows 一直很方便,在 Macbook 上,要使用 cquery 插件,但是作者停止更新超过五年了,连 GitHub 上的仓库都关了,没了 repo,Apple Silicon 编译不了 cquery。
解决方法是使用 cquery 的一个个人开发的分支 ccls,现在有了一个更加稳定的官方项目,llvm 官方团队的 clangd,基于 Clang C++ Compiler,默认集成到了 llvm 项目中,安装 llvm 后即可使用。
1.安装 llvm。
$ brew install llvm
2.打开 VScode,搜索"clangd"安装 clangd 插件。
3.关闭 VScode 中 C/C++ 插件的智能提示功能。
"C_Cpp.intelliSenseEngine": "Disabled",
4.为工程生成 compile_commands.json 文件,clangd 需要它来分析依赖关系。
使用 CMake 编译时,需要添加参数
$ cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=YES
或在 CMakeLists.txt 里,指定生成
set(CMAKE_EXPORT_COMPILE_COMMANDS YES)
生成的 compile_commands.json 文件可能在 build 目录下,这时需要在项目主目录里创建一个该文件的软链
ln -s build/compile_commands.json .
重启 vscode,或者 CMD+Shift+P 输入 Reload Window