WWW.YOUINFO.SITE
标签聚合 备注

/tag/备注

LinuxDo 最新话题 · 2026-05-12 12:37:05+08:00 · tech

内网穿透与远程访问常用方案 一、公网直连类 方式 特点 是否需要公网IP 备注 IPv6 直连 无需任何工具,直接用 IPv6 地址 需要家里公网IPv6 现在很多家庭宽带已有 IPv6,值得优先尝试。速度和稳定性极佳 纯 IPv4 端口转发 传统路由器 DMZ 或端口映射 需要家里公网IPv4 最原始方式 二、虚拟局域网 / VPN 类 这类方案会把所有设备组成一个加密的虚拟局域网,像在同一个局域网里一样访问。安全性高,支持任意协议(RDP、SSH、HTTP、数据库等)。 工具 难度 特点 是否需要公网IP Tailscale(商业,有免费额度) 极低 几乎零配置、速度快、跨平台优秀 不需要 EasyTier(自建) 低 高性能 P2P 组网、去中心化、轻量、NAT 穿透强 不需要(可选公共节点) WireGuard(自建) 低 性能最强、轻量、现代协议 需要服务器公网IPv4 Headscale(自建) 中 Tailscale 的开源自托管版 需要服务器公网IPv4 ZeroTier(商业,有免费额度) 低 简单易用、支持自定义网段 不需要 OpenVPN(自建) 中 老牌、兼容性好 需要服务器公网IPv4 三、内网穿透类 这类工具通过公网服务器做中转,把内网端口映射出去,支持 TCP/UDP,可用于 RDP、SSH、Web、数据库等任意服务。 工具 类型 难度 特点 是否需要公网IP frp(自建) 自建 中 灵活、支持 TCP/UDP/HTTP/HTTPS 需要服务器公网IPv4 SakuraFrp(公共服务) 公共服务 低 frp 的公共服务版,免费额度较高 不需要 花生壳(商业服务) 商业服务 极低 稳定、合规、有技术支持、安全功能多 不需要 ngrok(公共/自建) 公共/自建 低 官方支持好,但免费版有限制 不需要 NPS(自建) 自建 中 类似 frp,Web 管理界面更友好 需要服务器公网IPv 4 四、仅 Web 服务 工具 难度 特点 是否需要公网IP 适合场景 Cloudflare Tunnel(商业,有免费额度) 低 免费、自动 HTTPS + CDN 不需要 Web 服务首选 五、专用远程桌面工具 工具 类型 是否需要公网IP 连接原理 RDP(原生) 直连协议 需要直连 直连 VNC 直连协议 需要直连 直连 RustDesk(自建中继 / 公共服务) 自建 / 公共 不需要(自建中继需服务器) 中继 + P2P 向日葵(商业服务) 商业服务 不需要 云中继 ToDesk(商业服务) 商业服务 不需要 云中继 AnyDesk(商业服务) 商业服务 不需要 云中继 TeamViewer(商业服务) 商业服务 不需要 云中继 UU远程(商业服务) 商业服务 不需要 云中继 大家认为哪种方案比较好呢?从速度(能否跑满宽带)和稳定性两方面考虑 11 个帖子 - 8 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-10 20:33:26+08:00 · tech

本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容: 我的帖子已经打上 开源推广 标签: 是 我的开源项目完整开源,无未开源部分: 是 我的开源项目已链接认可 LINUX DO 社区: 是 我帖子内的项目介绍,AI生成、润色内容部分已截图发出: 是 以上选择我承诺是永久有效的,接受社区和佬友监督: 是 以下为项目介绍正文内容,AI生成、润色内容已使用截图方式发出 痛点:linux下习惯使用终端,并且喜欢使用轻量开源小工具,并且我英文白痴。尽管简单分了大类但还是存在一个工具放久了都不知道是干啥的东西了。 因此搞了一个小工具,仿照 ls 的作用,为文件/文件夹自定义备注 使用 rust 编写,轻、快。Mac、linux都可以使用(win 没试过,不过win基本很少人会习惯用shell,更多还是文件管理器) 默认轻量模式,同时具有TUI,可在终端里快速看 README、代码、压缩包和项目卡片 TUI内置帮助文档,支持模糊搜索(直接拼音也能搜索) tui也存在模糊匹配(过滤)功能 常用目录有收藏功能,可快速跳转 对于存在如 README 等标准介绍文档的项目可自动识别并备注 同时简单写了一个 skill 专门给它(只是给命令,人工review一下还是好的) 简单截点图。具体可以查看帮助文档探索,基本 tui 中都有对应的命令提示,还是以轻量模式为主,tui 是同事吐槽“看看人家”后增加的补强功能 (点击了解更多详细信息) 项目链接: github.com GitHub - 803S/lsz: 一个给 文件/文件夹 添加注释和快速预览的现代化文件浏览工具 一个给 文件/文件夹 添加注释和快速预览的现代化文件浏览工具 github.com GitHub - 803S/project-insight-lsz: 专为lsz服务的skills 专为lsz服务的skills 2 个帖子 - 2 位参与者 阅读完整话题

linux.do · 2026-04-27 09:50:08+08:00 · tech

/** 可口可乐吧 签到 - 青龙多账号版 环境变量: WXID: 备注#wxid,多账号用 & 或 换行 分隔 示例: 账号1#wxid_xxxxxxxx&账号2#wxid_yyyyyyyy 功能: 微信 code → Bearer token(带缓存) 查询签到状态 执行每日签到 查询积分 cron: 30 8 * * * const: disabled = false */ const axios = require(‘axios’); const fs = require(‘fs’); const path = require(‘path’); /* ==================== 常量配置 ==================== */ const APPID = ‘wxa5811e0426a94686’; const BASE_URL = ‘ https://member-api.icoke.cn ’; const UA = ‘Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.59(0x18003b2e) NetType/4G Language/zh_CN’; const REFERER = https://servicewechat.com/${APPID}/499/page-frame.html ; const SCRIPT_DIR = path.dirname(__filename); const CACHE_FILE = path.join(SCRIPT_DIR, ‘可口可乐签到_cache.txt’); /* ==================== 环境变量 ==================== */ const WECHAT_SERVER = process.env.WECHAT_SERVER; const WXID_ENV = process.env.WXID; if (!WECHAT_SERVER || !WXID_ENV) { console.log(‘ 请设置 WECHAT_SERVER 和 WXID 环境变量’); process.exit(1); } const wxidList = WXID_ENV.split(/[\n&]/).map(i => i.trim()).filter(i => i && i.includes(‘#’)); if (!wxidList.length) { console.log(‘ WXID 格式错误,请使用 备注#wxid 格式’); process.exit(1); } /* ==================== 缓存管理 ==================== */ function loadTokenCache() { const cacheMap = {}; try { if (fs.existsSync(CACHE_FILE)) { fs.readFileSync(CACHE_FILE, ‘utf8’).split(/\n/).filter(Boolean).forEach(line => { const idx = line.indexOf(‘#’); if (idx > 0) { const remark = line.substring(0, idx); const token = line.substring(idx + 1); cacheMap[remark] = token; } }); } } catch (e) {} return cacheMap; } function saveTokenCache(cacheMap) { try { const content = Object.entries(cacheMap).map(([r, t]) => ${r}#${t} ).join(‘\n’); fs.writeFileSync(CACHE_FILE, content || ‘ #cache ’, { encoding: ‘utf8’, flag: ‘w’ }); } catch (e) {} } /* ==================== 微信 code 换 token ==================== */ async function getCode(wxid) { try { const url = ${WECHAT_SERVER}/api/v1/wx/app/get/code ; const res = await axios.post(url, { wxid, appid: APPID }, { timeout: 10000 }); const code = res.data?.Data?.code; if (!code) { console.log(‘ getCode 响应:’, JSON.stringify(res.data)); return null; } return code; } catch (e) { console.log(‘ getCode 异常:’, e.message); return null; } } async function codeToToken(code) { try { const url = ${BASE_URL}/api/sp-portal/store/icoke/wechat/loginNoCache/${code} ; const headers = { ‘Host’: ‘ member-api.icoke.cn ’, ‘content-type’: ‘application/json’, ‘Accept’: ‘application/json, text/plain, / ’, ‘Accept-Encoding’: ‘gzip,compress,br,deflate’, ‘User-Agent’: UA, ‘Referer’: REFERER, }; const res = await axios.get(url, { headers, timeout: 10000 }); const body = res.data; // 实际抓包确认:token 在响应体的 jwtString 字段 if (body && body.jwtString) { return body.jwtString; } console.log(‘ codeToToken 响应:’, JSON.stringify(body).substring(0, 300)); return null; } catch (e) { console.log(‘ codeToToken 异常:’, e.message); return null; } } async function getValidToken(remark, wxid, force = false) { const m = loadTokenCache(); if (force) delete m[remark]; if (m[remark]) { console.log(‘ 使用缓存 token’); return m[remark]; } console.log(‘ 获取微信 code…’); const code = await getCode(wxid); if (!code) return null; console.log( ✅ code: ${code.substring(0, 10)}... ); const token = await codeToToken(code); if (!token) return null; m[remark] = token; saveTokenCache(m); console.log(‘ token 已缓存’); return token; } /* ==================== 判断 token 失效 ==================== */ function isTokenInvalid(data) { if (!data) return false; const msg = (data.message || data.msg || ‘’).toLowerCase(); return msg.includes(‘未登录’) || msg.includes(‘token’) || msg.includes(‘登录’) || data.code === ‘401’ || data.code === 401 || data.status === 401 || data.httpStatus === 401; } /* ==================== 公共请求头 ==================== */ function getHeaders(token) { return { ‘Host’: ‘ member-api.icoke.cn ’, ‘Authorization’: token, ‘content-type’: ‘application/json’, ‘Accept’: ‘application/json, text/plain, / ’, ‘Accept-Encoding’: ‘gzip,compress,br,deflate’, ‘User-Agent’: UA, ‘Referer’: REFERER, }; } /* ==================== API 请求封装 ==================== */ async function apiGet(path, token, params) { try { const res = await axios.get( ${BASE_URL}${path} , { headers: getHeaders(token), params, timeout: 15000, }); return res.data; } catch (e) { console.log( ❌ GET ${path} 异常: , e.message); return null; } } async function apiPost(path, token, data) { try { const res = await axios.post( ${BASE_URL}${path} , data, { headers: getHeaders(token), timeout: 15000, }); return res.data; } catch (e) { console.log( ❌ POST ${path} 异常: , e.message); return null; } } /* ==================== 业务接口 ==================== */ async function getSignOutline(token) { const res = await apiGet(‘/api/icoke-sign/icoke/mini/sign/main/getSignOutline’, token); if (!res) return null; if (isTokenInvalid(res)) return { needRefresh: true }; const today = new Date(); const y = today.getFullYear(), m = today.getMonth() + 1, d = today.getDate(); const list = res.data || ; const todayRecord = list.find(r => r.year === y && r.month === m && r.day === d); return { signed: !!(todayRecord && todayRecord.exist), totalDays: list.filter(r => r.exist).length, point: todayRecord?.point || 0, data: list, raw: res, }; } async function doSign(token) { const res = await apiGet(‘/api/icoke-sign/icoke/mini/sign/main/sign’, token); if (!res) return { success: false, msg: ‘请求失败’ }; if (isTokenInvalid(res)) return { needRefresh: true }; if (res.success === true || res.isSuccess === true) { return { success: true, point: res.point || 0, msg: res.message || ‘签到成功’, }; } const msg = res.message || res.msg || JSON.stringify(res); if (msg.includes(‘已签’) || msg.includes(‘重复’) || msg.includes(‘already’)) { return { success: false, alreadySigned: true, msg }; } return { success: false, msg }; } /** 查询积分 */ async function getPoints(token) { const res = await apiGet(‘/api/icoke-customer/icoke/mini/customer/main/points’, token); if (!res) return null; return { point: res.point || 0, experiencePoints: res.experiencePoints || 0, frozenPoint: res.frozenPoint || 0, }; } /** 查询用户基本信息 */ async function getUserInfo(token) { const res = await apiGet(‘/api/icoke-customer/icoke/mini/customer/main/base/info’, token); if (!res) return null; return { name: res.name || ‘未知’, mobile: res.mobile || ‘’, grade: res.grade || ‘’, }; } /* ==================== 工具函数 ==================== */ function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } /* ==================== 单账号执行 ==================== */ async function runSingleAccount(accountStr, index) { const sepIdx = accountStr.indexOf(‘#’); if (sepIdx <= 0) { console.log( ❌ 第${index}个账号格式错误,应为 备注#wxid ); return; } const remark = accountStr.substring(0, sepIdx); const wxid = accountStr.substring(sepIdx + 1).trim(); console.log( \n==================================== ); console.log( 🚀 【可口可乐】${remark}(第${index}个) ); console.log( ==================================== ); // 获取 token let token = await getValidToken(remark, wxid); if (!token) { console.log(‘ 获取 token 失败,跳过’); return; } // 查询签到状态 let outline = await getSignOutline(token); if (outline?.needRefresh) { console.log(‘ token 失效,重新获取…’); token = await getValidToken(remark, wxid, true); if (!token) { console.log(‘ 重新获取 token 失败’); return; } outline = await getSignOutline(token); } if (outline) { if (outline.signed) { console.log( 📅 签到状态:✅ 今日已签到 | 本月已签 ${outline.totalDays} 天 ); } else { console.log( 📅 签到状态:❌ 今日未签到 | 本月已签 ${outline.totalDays} 天 ); } } // 执行签到 let signResult = await doSign(token); if (signResult?.needRefresh) { console.log(‘ token 失效,重新获取…’); token = await getValidToken(remark, wxid, true); if (!token) { console.log(‘ 重新获取 token 失败’); return; } signResult = await doSign(token); } if (signResult?.success) { console.log( ✅ 签到成功!获得积分:${signResult.point} ); } else if (signResult?.alreadySigned) { console.log( ℹ️ 今日已签到:${signResult.msg} ); } else { console.log( ⚠️ 签到结果:${signResult?.msg || '未知'} ); } await sleep(1000); // 查询积分 const pts = await getPoints(token); if (pts) { console.log( 💰 当前积分:${pts.point} | 经验值:${pts.experiencePoints} | 冻结:${pts.frozenPoint} ); } // 查询用户信息 const userInfo = await getUserInfo(token); if (userInfo) { console.log( 👤 会员:${userInfo.name} | 手机:${userInfo.mobile} ); } console.log( ✨ ${remark} 执行完成\n ); } /* ==================== 主函数 ==================== */ !(async () => { console.log( 📢 可口可乐吧签到 - 共检测到 ${wxidList.length} 个账号 ); for (let i = 0; i < wxidList.length; i++) { await runSingleAccount(wxidList[i], i + 1); if (i < wxidList.length - 1) await sleep(2000); } console.log(‘ 全部账号执行完毕!’); })(); 4 个帖子 - 4 位参与者 阅读完整话题

linux.do · 2026-04-26 12:54:50+08:00 · tech

备注:我是使用ether(国人无法KYC) 我是请我海外哥们帮我验的,所以不要问我KYC方法 建议:无痕浏览器去注册 有条件的可以使用 指纹浏览器配PROXY 1.同一个手机号码可以申请好几个PAYPAL 2.我使用ether申请了三张虚拟卡 3.三个账号都绑定1张虚拟卡 4.支付地区选法国,就可以使用PAYPAL付款了 没啥技术,对了同一张卡可以删除 7天后再去绑定另一个新的PAYPAL 你也可以绑GOOGLE PAY、APPLE PAY PAYPAL似乎是认帐号的,不是认卡 所以换个账号 一个月后再薅不会被封号(同一张卡) 4 个帖子 - 3 位参与者 阅读完整话题