自定义 golang 仓库的 module / 库名

如果你写过 golang,那你应该能在导入库时,注意到库名大多都是以 github.com 开头,跟一个链接差不多,复制到浏览器里也能直接访问。但有时也能看到一些与众不同的库名,例如 gopkg.in/yaml.v3 和 go.uber.org/zap 你可以点开上面的两个链接看看,就会发现它们在 pkg.go.dev 中指向的代码仓库都托管在 GitHub,而它们却又不使用 github.com/user/repo 这样的库名,这是怎么做到的呢 大概的流程 golang 对这个实现方法在文档中有一个段落,可见:cmd/go #Remote import paths 来自 GitHub 的仓库 简要的来说,当你在终端里运行 go get 或 go install 命令时,golang 会尝试去解析你传入的库名,如果库名是 github.com/<user>/<repo> 这样,它可以直接识别到这是一个 GitHub 仓库,就会走一套标准的流程,检查它是不是一个 golang 库,且这个库名与代码仓库的 go.mod 文件中定义的 module 名称相符,顺利的话就可以正常下载了 如果不用定义的奇怪库名 你可能会好奇,如果类似 gopkg.in/yaml.v3 这样的库名,而我们知道它的代码仓库托管于 GitHub 中,我们能不能绕过这个奇怪名字,像普通托管在 GitHub 的 golang 项目那样下载它呢? # 这里在加了后缀 /v3 是因为 gopkg.in/yaml.v3 本来就指向 v3 分支 $ go get github.com/go-yaml/yaml/v3 go: downloading github.com/go-yaml/yaml/v3 v3.0.1 go: github.com/go-yaml/yaml/v3@upgrade (v3.0.1) requires github.com/go-yaml/yaml/v3@v3.0.1: parsing go.mod: module declares its path as: gopkg.in/yaml.v3 but was required as: github.com/go-yaml/yaml/v3 显而易见,并不行。通过 go get 或 go install 命令下载某个库时,它的库名必须与 go.mod 文件中定义的 module 名称相同,否则就是下不了 其他自建的版本控制服务 不来自 GitHub 也没关系,golang 也设计有一些回退方法,这时就会根据库名来判断像不像一个 URL,并尝试向这个 URL 发送 HTTP 请求,如果请求的是一个自建的 git 或其他版本控制服务的网页 URL,你的自部署服务大概率会正确的为 golang 提供信息,后续的流程就跟上面差不多了 当然这种情况不多见,更多时候应该是在企业内部的使用场景? 自定义 golang 项目的库名 如果要自定义一个 golang 项目的库名,那我们最少需要一个可以存放 HTML 文件,支持 HTTPS 且可以公开访问的域名。用一些平台提供的二级域名也可以,至于代码仓库托管在哪都可以 首先,你要确定你的库名是什么,它的开头应该是你的域名,然后跟着你的仓库名称,例如下方的演示 我有一个 golang 仓库 https://gitea.trle5.xyz/trle5/tplate 不修改的话,库名就应该是 gitea.trle5.xyz/trle5/tplate 也就是去掉了开头的 https:// 你可以看到,它同时包含了二级域名,用户名和仓库名,这显得它又长又难记 同时还要避免冲突,最后决定的库名就是 trle5.xyz/gopkg/tplate 理论上也可以直接拿一整个二级域名作为库名,就是 tplate.trle5.xyz 这样,但我没试过具体行不行 修改原来的库名 如果你之前跟我一样不知道 golang 库名的命名规范,那你的库名大概就是一个单词,而且 golang 的拓展并没有提供一键重命名库名的方法... 于是,只能先修改 go.mod 文件开头的 module 名称,再看文件的报错逐个替换了 注意:如果你之前发布过 tag 或 release,那你修改库名后,还要推送一个新的 tag 或 release,不然你在使用 go get 或 go install 时,它会默认获取 latest 版本的内容,修改库名后最新的一个 commit 版本并没有包含此次更改,就会出现类似 前面 的错误 创建包含特殊属性的 <meta> 标签 能让 golang 从一个 HTML 页面中识别仓库信息的关键在于其中的 <meta> 标签,golang 不关心这个 HTML 页面里有什么其他内容,只要有对应的信息就行了,像 GitHub 上的 golang 仓库默认都会包含这个标签和对应的属性,下方的仓库 URL 填写你存放代码仓库的网页链接,代码仓库中 go.mod 文件中的 module 名称必须跟你填写的这个库名相同 <meta name="go-import" content="<库名> git <仓库 URL>"> 下面是一个完整的示例,我把它保存为一个名为 tplate.html 的文件,作为资源文件存放到了我的网站里,访问路径就是 trle5.xyz/gopkg/tplate <!doctype html> <html> <head> <meta name="go-import" content="trle5.xyz/gopkg/tplate git https://gitea.trle5.xyz/trle5/tplate.git"> <meta name="go-source" content="trle5.xyz/gopkg/tplate _ https://gitea.trle5.xyz/trle5/tplate/src/branch/custom{/dir} https://gitea.trle5.xyz/trle5/tplate/src/branch/custom{/dir}/{file}#L{line}"> </head> <style>body { color: #c8c8b9; background-color: #14140f; } a {color: #b9d282;}</style> <body> <p>go get trle5.xyz/gopkg/tplate</p> <a href="https://gitea.trle5.xyz/trle5/tplate">https://gitea.trle5.xyz/trle5/tplate</a> </body> </html> 里面其实很多东西都是多余的,这里是参照了 Gitea 的实现而修改的文件还加上了一些信息和链接,你可以编辑好 <meta> 标签,塞到任意一个 HTML 页面的 <head> 标签里都可以 注意:go.mod 文件、<meta> 标签属性 和 对应 URL 的三个库名必须完全相同,即: go.mod 中库名为 example.com/package 浏览器中 example.com/package 可正常访问 example.com/package 页面为 HTML 文档,且其中包含上方的 <meta> 标签 <meta> 标签中的属性已经按照需求正确填写了 之后确保 CDN 缓存之类的不会干扰你的请求,就可以尝试使用新的库名来导入或安装你的项目了

2025/12/3
articleCard.readMore

new tplate

起因 我的 Pixelbook Go 的 Linux 虚拟机在某一天再次(是的,很多次)炸掉了,于是我开始将更多的开发工作挪到台式机上。但是呢,我的台式机配置依然还是 8 GB 内存。 是的,我那台 8 GB 内存的台式机已经没法跑起 Urara 模板了,在构建时会因为内存不够而失败 但这并不是我这么久没有更新的原因 时间间隔太久,我也忘了是什麽时候了,我觉得 @kwaa 写的 lume_theme_shiraha 很合我的胃口,MD3 自适应配色加上样式,非常的喜欢 后面因为对 Pixelbook Go 的逐步厌恶,我反倒去买了台只有 8 GB 内存的笔记本(ThinkPad X1 Carbon Gen 4),它给我的印象还不错,至少比前面那台能干的活多... 本来我想在这里放一个 Pixelbook Go 的链接,因为我真的喜欢它的设计,但是 Google 似乎把它从商店里下架了 但是呢... 我发现在跑 lume_theme_shiraha 时,deno 依然是得吃掉 4 GB 的内存,这是 JavaScript 的原罪吗... 现在 我于是想写一个尽量不用到 JavaScript 的博客生成模板(至少在构建时不能用),同时它还需要支持我的一些奇怪想法,于是就写,如果你能看到这个文章,那我就是在写,或许已经写好一大半了 我打算先支持一下完整的 Markdown 文章解析,再考虑其他的附加东西,最后替换掉正在使用的 Urara 博客,当然还有一大堆事情要做 ⚠ 注意:此项目不遵循任何网页设计规范,您可能会遇到以下各种情况 主容器不遵循 768px 最大宽度 可能并不适合人类观看的配色 乱用字重和行高 前期 我选了 go 语言来写这个东西,毕竟我就会两门语言,要是用 C 写的话那就不知道要写多久了(说实话也很久没写了) 其次就是我在使用 Gitea 时发现,它用到了一种叫 .tmpl 的文件,只要去仓库里把对应目录下的 .tmpl 拖到对应的目录,再修改其中的内容,就可以直接更改网页的布局,不需要构建甚至重启 还是要的,但可以做,感觉非常的神奇 但我上手了几次后,发现它的逻辑确实是有一点难懂的,如果去看 Gitea 的模板的话,它也不是按照引用 template 来嵌套组合网页的,而是从头到尾拼出来的,也就是 header + 某些组件 + 实际内容 + footer 这种类似字符串拼接的做法,其中 header 和 footer 的标签并不是完全闭合的,当案例去看很误导人怎么用 而且 .tmpl 没有静态检查拓展,语法之类的就问 GPT 去吧 文章解析器 一开始我只使用了 lute 作为 Markdown 解析器,然后我发现它似乎没有什么好的方法可以在将 Markdown 解析成 HTML 的过程中将类或者 ID 选择器加到 HTML 标签中,于是开始邪恶的将 YAML 作为文章源文件(对的,现在还留着,现在这篇文章就是用 YAML 写的 放弃了) 但我尝试写了一会后,发现这样跟手搓 HTML 似乎没什么区别,过了一阵子又改回来了。但样式的问题解决了,CSS 的类型选择器 也不是不能用,而且不用往 HTML 标签里单独塞东西感觉还不错 期间搬了自己几篇文章试试效果,就是不知道为什么不能解析 Markdown 的 Front Matter 部分。没有什么想法,于是跑回去写 bot,由于配置文件我也用的是 YAML,结果越看越眼熟... 这个 Front Matter 部分怎么长得跟 YAML 有点像,而且 Front Matter 前后的 --- 符号似乎也是 YAML 的单文件分隔符,询问神奇的 ChatGPT 后,得到了肯定的答复,于是简单写个解析器区分 YAML 和 Markdown 部分单独解析,文章信息就好了 代码高亮 本来是不打算做代码高亮的,原因很简单,我写不出来 但是呢,lute 支持代码高亮,虽然中途发现样式似乎有奇怪的问题,但后面改了一下,效果还不错,但配色跟我的主题看上去不是很好,现在还没有改的打算 Spoiler / 遮罩 由于 lute 好像不支持 Markdown 的 Spoiler 语法(即 || 遮罩内容 ||),而我之前又有在部分文章中使用到了这个语法。找了一圈 HTML 中也没有对应的标签实现 当然你能在这个文章中看到这个语法,就代表我用了一些奇怪的实现方式 因为我把 <mark> 标签夺舍成 Spoiler 语法了,实际上就是 ==遮罩内容== 这可能会导致在一些 RSS 订阅的阅读器中降低一些阅读体验,因为没找到什么好方法,而且在手机上,必须得长按选中才能看到实际的内容 文章目录和章节 lute 好像没有方法在渲染 Markdown 后拿到一些章节数据,不过还是提供了章节标题锚点的功能,见章节标题右边那个小图标 改了一下,靠 JavaScript 实现了类似 lume_theme_shiraha 的标题链接锚点效果,本来也想写到标题前面,但是因为我设定的 body 填充范围小了些,放到外面在移动端上不是很方便,就顺着放到右边了 一开始是靠作为 lute 标题链接锚点的伪元素实现的,但这样其实还是会留着 svg 元素,标题多了浪费流量,后面问了问 GPT 才给出一个用 JavaScript 代码自动查找元素并添加子元素的方法,但这也导致了如果禁用 JavaScript 那就没法显示出这个按钮 也因为这个,所以文章目录不是很好写,或许可以写一些正则表达式,逐行匹配 heading 标签来尝试生成目录,这个缓一缓也没什么问题了... 我还想设计成每个段落都像代码编辑器里那样可以折叠显示,这样相对来说可能方便些?不过感觉很难做 样式 由于 前面说到 lume_theme_shiraha 很合我的胃口,就打算照着样子做一个(不过就不是最新版那个样子了),还有部分设计借鉴了 Urara,非常感谢 kwaa 当然前者是有 MD3 按图片取色的,这个我尝试从网上找一个 MD3 取色的 go 语言库,完全没找到于是放弃,就固定两个配色就好了... 个人偏好 期间还掺杂了个人偏好的样式,例如我觉得全屏看网页时 768px 的主容器宽度未必显得两侧太空了,于是在窗口大小大于 1536px 时,主容器宽度会拓展到 1024px。也不至于出现 21:9 的屏幕读一行字需要头从左往右转的情况 由于没有使用 css 库之类的,样式全都是自己写的,还可以把样式全部写进 HTML 的 <head> 标签里,这样只需要按 Ctrl + S 就能按照原样保存的网页 不过文章里有引用网络资源的话就还不行,或许能想个办法在构建静态网页时把引用的网络资源都一起扔进 HTML 里。但这样可能会因为重复加载相同的样式和资源而消耗多余的流量甚至拖慢加载速度,这个就之后再说了 按需样式加载 好像前端那些样式库之类的东西,都会根据使用到的样式来按需构建样式表文件,而我思考了一下,好像做起来很难,但每个页面都加载用到的全部样式又比较浪费流量,思考了一段时间后我选择了另一个方法 把全部的样式文件,看哪些组件会用到哪些样式,将其分别存放到对应文件夹中,在构建时存储到变量中,当调用这个组件时,自动在组件前附加样式 本来还想把样式都丢在 <head> 标签里,但是在 .tmpl 模板中进行操作时无法更改外部的值,好在测试都正常,就暂时用吧 文章列表 想到之前使用 Urara 时会将题图放到文章列表中,于是自己试了试也做一个,发现效果很难看,甚至想过要不还是不显示图片了 后面又乱折腾了一阵,最后是作为文章列表项目的背景图像显示的,并叠加了一个背景色到透明的渐变来模拟遮罩效果,在深色模式下观感可能还可以,但浅色模式下可能就不太行了 而且图片的显示区域是由设定文章描述高度来撑开的,想不到什么办法了... 通过 PageSpeed Insights 测试了一下,这个题图实现方式还有个应该应用 fetchpriority="high" 的建议,但我这个是 <div> 标签的 background 样式,添加属性也没效果,就暂时先这样了 文章分类和标签 在之前使用 Urara 的时候是有从其他仓库里拿过一个 sections 插件(见 Interstellar750/hexo_s/urara 的 README 部分),可以以某个分类来显示其下的文章,这个代码在我的 Urara 库中还有保留,但是 @jiwaszki 似乎转向使用 hugo 来搭建博客,原来的代码就不得而知了... 好在这个写起来也不算太难,其实仔细想想跟 tag 也没差多少,就是分类只能指定一个,而标签能指定多个,最终都是靠标签或分类来索引符合条件的文章而已 由于它们很像,索引过程也都是用的文章列表模板,我把它们都放到同一个页面去了,然后再遍历生成 HTML,分类的的 URI 就是 host/category/<分类名>,标签就是 host/category/_<标签名> (前面多一个下划线) 在分类展示页里,分类以 grid 的形式显示在前面,显示分类名、最后发布的文章时间和其下的文章数量。后面部分就留给标签,如果有某个标签包含多个文章,也会显示计数 不过相比 Urara 就不能按分类 + 标签逐个筛选了,只能一个个看 网页交互 RSS 订阅 / Sitemap 数据 一开始我觉得 HTML 也是一种 XML 嘛,就直接当做 .tmpl 文件,进行一个模版的写,但是由于开头的 <?xml version='1.0' encoding='utf-8'?> 不是一个正常的 HTML 标签,就会导致被转义掉,就算用 template.HTML() 套住也不行,它在执行模板时就被转义了,没法被正常识别成 XML 文件 中途想了各种奇怪方法来解决这个问题,最后在写文章的时候突发奇想: 既然就开头那一行有问题,那我先把它去掉,执行完模板后再把开头作为字符串把它拼起来不就好了 于是现在就只需要在使用时填一下 "atom" 参数就好了,舒服 途中还看了看 Atom 和 RSS 的区别,我一开始还以为 RSS 是 Atom 的升级,没想到是反着来的 后面顺带把 sitemap 也做了 链接预览 在写了一半发出去让群友们不得不品鉴时,发现好像没有链接预览,试了试几个博客链接,最后发现是 <meta> 标签的问题 途中看了各种网站,最后的结论大概是得加 <meta property="og:description" content="描述"> 这种标签,但是总感觉不太对劲,我在 MDN 甚至都没看到 meta 标签有 property 这个属性... 还尝试过为文章生成链接预览图片,但尝试了一会后发现设计出来的图相当难看... 暂时搁置了 评论系统 好在我使用 Urara 时并没有添加太多的评论系统,只用到了 Giscus 和 Webmention,这让我的迁移过程变得比较轻松 Giscus 本来就提供 JavaScript 代码的使用方式,而 Webmention 显示嘛,用 kwaa 写的 seia 就好了 提交 Webmention 链接的话,去了解了一下 API 端点,请 ChatGPT 写了一份代码,就好了

2025/11/20
articleCard.readMore

为 Chrome OS 设置代理

⚠ 文章未完成 Chrome OS 因为安全原因逐步隔离了用户空间和 crosh 终端 这导致了原本固定映射至用户下载文件夹的 /home/chronos/Downloads 目录已经消失了 于是现在找不到一个稳定的目录可以直接将 sing-box 的二进制文件转移到 crosh 中的 /usr/local/bin/ 目录中(可能有,但我心灰意冷懒得找了) 而如果在 crosh 中直接使用 curl 从 GitHub 上下载文件,大概率会因为 DNS 污染等原因下载失败,没有一个好用的办法... 想要在 Chrome OS 上简单方便的代理设备的流量,那就只能在 Android 环境下安装软件,再由系统设定好的本机通道自动在 Chrome、Android 与 Linux 虚拟机之间共享,好处自然是方便且稳定,代价嘛... 点击来帮助 Chrome OS 夺回属于它的内存 在某一天调式程序时,我发现请求的 API 似乎迟迟没有响应,想着是不是节点出问题了?当我尝试打开 Android 上的代理软件时,我意识到并不是网络问题,而是这个 Android 虚拟机,在只跑了一个代理软件的情况下,卡死了... 保存代码进度再重启设备后,Android 虚拟机正常了,继续写代码调程序,但那天晚上我意识到,我似乎启用这个 Android 虚拟机,为的只是跑一个代理软件?于是在第二天我备份好 Android 虚拟机中的必要数据后就把它删掉了。然后我在诊断程序里看到设备的空闲内存从日常的 2GB 变为了... 12GB 剩下的就不多说了,现在 Chrome OS 夺回了属于它的内存,只需要解决网络代理问题就可以了 如果你的网络情况还不能在脱离了 Android 环境中的代理软件下访问网络,那请先不要着急删掉它 删掉了 Android 容器后,就得考虑选择替代的代理方式了,目前大概有四类设置代理的方式,在下方表格中按配置难易度从低到高排序,还有能代理到的范围和优缺点 代理类型 Chrome crostini crosh 优点 缺点 Wi-Fi 代理 ✅ ❌ ❌ 简单方便,可连本机或其他设备 代理范围过小,Linux 虚拟机吃不上,每个 Wi-Fi 都需要单独配置 WireGuard ✅ ✅ ✅ 代理范围广,有系统 UI 控件可快捷切换 需要进入 crosh 添加配置,协议因素有速度劣势 Tun ✅ ✅ ✅ 代理范围广 需要在 crosh 中配置代理软件,可能还会有些奇怪问题 TProxy ✅ ❌ ✅ 暂时想不到 代理范围一般,Linux 虚拟机会直接没网(不只是没代理) 非侵入式(不修改 Chrome OS) 我们有两种不需要安装任何软件就能添加代理的方式,它们就是 Chrome OS 自带的 WireGuard 和比较差劲的 Wi-Fi 代理 1. WireGuard 通过 WireGuard 设置代理可以覆盖到浏览器、Linux 虚拟机和 crosh,还有系统 UI 控件,方便又好用。 但是系统自带的图形化 WireGuard 配置添加工具有 bug,必须要在 crosh 中通过命令来添加配置,这代表你必须要清除所有数据,开启开发者模式后才能添加 WireGuard 配置 似乎并不需要,请手动试试能不能通过下方的快捷键打开 crosh,如果可以的话就不需要 此教程来自 ChromeOS Flex: Can’t save Wireguard config (FIX) – Tech Blog (Web Archive link) 由于 Cloudflare 的 Warp 现在被 ban 的厉害,比较推荐自建服务端 首先确保你已经为你的 Chrome OS 设备启用了开发者模式,之后按 Ctrl + Alt + T 来打开 crosh,再逐行运行以下命令,注意根据你的 WireGuard 配置替换掉对应的内容: wireguard new <名称> wireguard set <名称> local-ip 10.8.0.9 wireguard set <名称> private-key # 运行这行命令后粘贴密钥,回车保存 wireguard set <名称> peer <公钥> preshared-key # 同上,但如果没有预共享密钥则不用运行此行 wireguard set <名称> peer <公钥> allowed-ips 0.0.0.0/0 wireguard set <名称> peer <公钥> endpoint <端点 IP:端口> wireguard set <名称> peer <公钥> persistent-keepalive 0 wireguard show # 查看添加完成的配置 添加完配置后,你应该会得到类似以下的输出: name: wireguard-profile local ip: 10.8.0.9 public key: iJbPYu1dCc1VVU7o6OS5uWhnni9iXCi1nuGkwdsIPn0= private key: (hidden) name servers: 8.8.8.8, 8.8.4.4 peer: QiTfo+u2brfoTh5BHQKbU/Rt/OJ7MAQMO0+pMEYNxRg= preshared key: (hidden or not set) endpoint: 127.1:5300 allowed ips: 0.0.0.0/0 persistent keepalive: 0 其中的 public key、peer 以及 endpoint 可能会与上方显示的不同,因为这几个参数取决于你的 WireGuard 配置,然后你就可以到设置的网络板块里启用刚刚添加的配置,试试能不能正常代理流量了 2. Wi-Fi 代理 Wi-Fi 代理更适合只用浏览器上网的用户,因为代理不到 Linux 虚拟机,可以应急用用,长期使用还是推荐选择其他方式 Wi-Fi 代理配置方法不算难,只需要在设置中依次点击 网络 > Wi-Fi,找到目前已连接的 Wi-Fi 名称并点击它就可以查看网络详情信息,再点击最下方的 代理 选项,把连接选项改为 手动配置代理,就可以配置 Wi-Fi 代理了 接下来就是填入 HTTP/S 或 SOCKS 代理主机的 IP 以及端口了,如果你的代理软件支持在一个端口上使用多个协议,还可以把 对所有协议使用同一代理 打开,那样只需要填一个主机的 IP 和端口就足够了,至于下面的 不要对以下主机和域使用代理设置 直接留空,如果你知道这方面的知识,就看你想怎么来了,填完信息记得点击保存 只要你填入的 IP 和端口正确,且对应的设备上运行着负责代理流量的服务,那么这个时候 Wi-Fi 代理就已经生效了,去测试一下吧 侵入式(在 Chrome OS 中安装代理软件) 如果要像 Linux 发行版那样在 Chrome OS 里安装代理软件,那么首先你得给你的 Chrome OS 设备启用开发者模式 注意不是修改 设置 > 关于系统 > 版本 里的开发者版本 具体怎么启用开发者模式我这里就不写了,只讲启用开发者模式后如何将代理软件安装到 Chrome OS 中 如果你选择安装侵入式的代理软件,你就可以选择多种方式来将 Chrome OS 连接到代理,这里首要推荐的是支持 Tun 模式的 sing-box sing-box 折腾了许久,在 Chrome OS 中似乎只有 sing-box 能使用 Tun 模式来代理设备的全部流量,根本原因大概有两个: 似乎 Chrome OS 的系统网络栈不支持执行 L3 到 L4 转换,只有在 sing-box 入站(inbounds) 配置中将 Tun 的 stack 参数手动设定为 gVisor 才可以正常转发流量 同时需要将 sing-box 路由(route) 配置中的 default_interface 参数设定为 wlan0,这个值对应的是给机器提供网络的网卡设备,我的 Pixelbook Go 没有网线接口,我也没有能插网线的拓展坞,没法测试连接网线后是否需要修改。有能力的话请自己到 crosh 里运行 ifconfig 命令判断是否要修改 下方是一份针对 Chrome OS 的 sing-box 配置,配置好了 Tun TProxy 和 HTTP 代理入站,Yacd Web UI 控制台,DNS 和去广告规则集,使用时请手动替换掉出站(outbounds) 中的示例节点: 点击查看配置 { "log": { "level": "info", "timestamp": false }, "experimental": { "clash_api": { "default_mode": "rule", "external_controller": "127.0.0.1:9090", "external_ui": "ui", "secret": "", "external_ui_download_detour": "", "external_ui_download_url": "https://github.com/MetaCubeX/Yacd-meta/archive/gh-pages.zip" }, "cache_file": { "enabled": true, "store_fakeip": false } }, "dns": { "servers": [ { "tag": "proxyDns", "detour": "proxy", "address": "https://1.1.1.1/dns-query" }, { "tag": "localDns", "detour": "direct", "address": "tls://120.53.53.53" }, { "tag": "block", "address": "rcode://success" } ], "rules": [ { "rule_set": "geosite-category-ads-all", "server": "block" }, { "outbound": "any", "server": "localDns", "disable_cache": true }, { "clash_mode": "direct", "server": "localDns" }, { "clash_mode": "global", "server": "proxyDns" } ], "strategy": "prefer_ipv4" }, "inbounds": [ { "type": "tun", "stack": "gvisor", "auto_route": true, "strict_route": true, "domain_strategy": "prefer_ipv4", "mtu": 9000, "inet4_address": "172.114.0.1/30", "inet6_address": "2001::1/64", "sniff": true, "sniff_override_destination": true, "inet4_route_exclude_address": [ "0.0.0.0/8", "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.168.0.0/16", "224.0.0.0/4", "240.0.0.0/4" ] }, { "type": "tproxy", "tag": "TPROXY-IN", "listen": "0.0.0.0", "listen_port": 7895, "sniff": true, "sniff_override_destination": true }, { "type": "mixed", "listen": "127.0.0.1", "listen_port": 2080, "sniff": true, "users": [] } ], "outbounds": [ { "tag":"proxy", "type":"selector", "outbounds":[ "auto", "direct", "outbound_hy2" ] }, { "tag":"auto", "type":"urltest", "url": "http://www.gstatic.com/generate_204", "interval": "10m", "tolerance": 50, "outbounds":[ "outbound_hy2" ] }, { "type": "hysteria2", "tag": "outbound_hy2", "server": "114.51.4.191", "server_port": 9810, "password": "example_password", "tls": { "enabled": true, "server_name": "exmaple.com", "insecure": true } }, { "type": "direct", "tag": "direct" }, { "type": "dns", "tag": "dns-out" }, { "type": "block", "tag": "block" } ], "route": { "default_interface": "wlan0", "final": "proxy", "rules": [ { "protocol": "dns", "outbound": "dns-out" }, { "rule_set": "geosite-category-ads-all", "outbound": "block" }, { "clash_mode": "direct", "outbound": "direct" }, { "clash_mode": "global", "outbound": "proxy" }, { "domain": [ "clash.razord.top", "yacd.metacubex.one", "yacd.haishan.me", "d.metacubex.one" ], "outbound": "direct" } ], "rule_set": [ { "tag": "geosite-category-ads-all", "type": "remote", "format": "binary", "download_detour": "direct", "url": "https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/sing/geo/geosite/category-ads-all.srs" } ] } } 配置文件有了,你可以决定是否要继续操作,接下来的步骤如果操作不当可能会炸掉你的系统 首先判断一下你的 Chrome OS 设备的架构,按 Ctrl + Alt + T 打开 crosh,使用 uname -m 命令来查看硬件架构: crosh> uname -m x86_64 由于我的 Pixelbook Go 使用的是英特尔(Intel) 的处理器,所以这里显示的是 x86_64,如果是 AMD(超威半导体) 的处理器,那应该也是 x86_64,也有可能是 amd64 如果你的 Chromebook 使用了高通(Qualcomm) 或者联发科(MediaTek) 的处理器,那可能会显示 arm64 或者 aarch64 接着前往 SagerNet/sing-box 的最新发布页面,根据你的设备架构来拿到最新的 sing-box 的下载链接 如果设备架构是 x86_64 或 amd64,那就选 sing-box-<版本号>-linux-amd64.tar.gz 如果设备架构是 aarch64 或 arm64,那就选 sing-box-<版本号>-linux-arm64.tar.gz 建议打开网站后按 Ctrl + F 进行搜索,先搜 linux-,然后根据你的设备架构接着输入 amd64 或 arm64,最后唯一高亮的那个就是你需要的,右键那一行字,再点击复制链接地址 注意是点击 复制链接地址,不是 复制,否则你复制到的链接地址是错误的 接下来按下按 Ctrl + Alt + T 打开 crosh,逐行输入以下命令并回车,将其作为一个命令脚本保存到文件中 shell cd /tmp # 这篇文章完成时,最新的版本是 1.11.7 echo 'curl "https://github.com/SagerNet/sing-box/releases/download/v1.11.7/sing-box-1.11.7-linux-amd64.tar.gz" > sing-box.tar.gz' > download_sing-box.sh sh download_sing-box.sh && tar xzf sing-box.tar.gz &&

2024/8/6
articleCard.readMore

在 Chrome OS 的用户终端 (crosh) 中使用 sudo 权限

首先按 Ctrl + Alt + F2 打开 VT-2 终端,输入 chronos 用户进行登录,默认无密码 # 分别创建 ed25519 和 rsa 类型的密钥,两个都要用到 # 会询问一些信息,可以全部回车 ssh-keygen -t ed25519 ssh-keygen -t rsa # 将密钥复制到 sshd 服务器需要的目录 sudo mkdir -p /mnt/stateful_partition/etc/ssh/ sudo cp ~/.ssh/id_ed25519 /mnt/stateful_partition/etc/ssh/ssh_host_ed25519_key sudo cp ~/.ssh/id_rsa /mnt/stateful_partition/etc/ssh/ssh_host_rsa_key # 允许上方的公钥建立 ssh 连接 cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 接下来,往 ~/.bashrc 中预设几个命令,好让使用的过程更方便: echo "alias vt2port=\"sudo /usr/sbin/sshd -p 6969\"" >> ~/.bashrc echo "alias vt2connect=\"ssh 127.1 -p 6969\"" >> ~/.bashrc # 使命令生效 source ~/.bashrc 到这里具体的配置就完成了,在 VT-2 中输入 vt2port 后,会自动开启 sshd 服务器,之后你就可以按 Ctrl + D 注销 VT-2 了,除非你重启 Chrome OS 或手动杀掉它,否则它都会一直运行 然后按 Ctrl + Alt + F1 回到 Chrome OS 中,再按 Ctrl + Alt + T 打开 crosh 后,输入 shell 进入终端再输入 vt2connect,会询问你要不要信任主机,确认后就可以方便的在 crosh 中使用 sudo 命令了 以后每次重新启动之后,开启 sshd 服务器需要的步骤就是: 进入 VT-2 登录 chronos 用户 输入 vt2port 开启 sshd 服务器 注销 VT-2 返回 Chrome OS 需要在 crosh 中使用 sudo 权限的步骤: 打开 crosh > 输入 shell 进入终端 输入 vt2connect 连接到 sshd 服务器 运行任何需要 sudo 的命令 参考链接:oddbyte/howto-use-sudo-in-crosh

2024/6/20
articleCard.readMore

在没有管理员权限的情况下更新 Windows 的系统时间

有些机房的老电脑的 BIOS 电池早就没了电,还拿不到管理员权限来更改时间,通过更改策略组来给予其他用户更改时间的权限就可以调整到正确的时间了 首先按下 Win + R 键进入运行窗口,在弹出的窗口里输入下方内容来进入 本地策略组编辑器: gpedit.msc 然后根据路径找到对应的策略文件夹: 计算机配置 ↳ Windows 设置 ↳ 安全设置 ↳ 本地策略 ↳ 用户权限分配 > 更改系统时间 双击策略名称后,会弹出来它的属性,点击中下方的 添加用户或组(U)...,再点击下方的 高级(A)...,继续点击右侧的 立即查找(N) 按钮,就会在窗口下方显示现有的用户和组,选择要添加的用户或组点击保存即可。图标显示一个人的是用户,显示两个人的就是用户组 考虑在机房可能并不能重启,若遇到这种情况,可以考虑添加其他普通用户或来宾用户,并给予修改时间的权限,再通过开始菜单切换到对应的用户来修改时间 如果你使用的设备登录的是没有添加用户权限的用户嘛,那就给当前用户添加权限,保存后注销当前用户再登录,检查一下能不能修改时间。我自己试了试似乎不行,祝你好运吧

2023/4/27
articleCard.readMore

隐藏站点的源服务器 IP

从不开 CDN,域名 DNS 直接解析到 IP,再到服务器被打到空路由后的总结 为什么要隐藏源服务器 IP 首先我们要看看浏览器访问一个站点时,这个请求会如何到达源服务器: 浏览器获得用户输入的域名,首先向 DNS 服务器发送查询请求 DNS 服务器收到了请求,解析到了域名对应的 IP,返回给浏览器 浏览器得知了源服务器的 IP 地址,接着继续向源服务器发送请求 DNS 的作用就不多说了,简单来看就是放域名进去,就可以吐出域名对应的 IP 这个过程中,浏览器就已经知道源服务器的 IP 了,怎么知道的呢?当然是 DNS 告诉它的 但 DNS 是怎么知道源服务器的 IP 呢?不是什么魔法,是站点主人自己告诉 DNS 的,不然没了 DNS,想访问站点只能记一串 IP,很不方便 现在我看某个人不爽,想把他的网站做掉 当然我不提倡任何网络攻击,这里只是做一个例子 上面我们知道了请求是如何到达源站的,最简单的方法,就是一秒给他发几千个请求甚至更多,就能起效果。于是立刻手搓了一段代码,一秒发五千个请求,这个叫分布式拒绝服务(DDoS)攻击 由于服务器的配置并不是很高,处理不来我们发送的这么多请求,一段时候后,服务器的主人发现了不对劲,赶紧把 DNS 解析删除了,打算等我们不打他之后再重新添加 DNS 解析,让网站恢复访问 此时,虽然 DNS 解析被删除了,但服主在被打之前在 DNS 里设置的 IP 已经被我们请求过了,我们早已知道了源站 IP。于是我们乘胜追击,把发送请求的域名换成 IP,接着打: 在我们的不懈努力下,服务器的占用爆满,服主只能关机跑路 就算服主重新开机,迎接他的依然是 100% 占用,跑不掉 到这里我们已经知道 DNS 与 IP 公开绑定的后果了,就算站点不能通过域名访问了,只要服务器不关机,那还是能通过 IP 访问的,不做些什么,站点就只能停了 所以,我们要在确保通过域名可以正常访问的情况下,保证源服务器的 IP 不被泄露 有哪些办法可以隐藏源服务器 IP? 我们先代入到前面的攻击事件中服主的视角,看看有什么方法可恢复站点访问,还能让他打不到我们 换 IP 一台机器想要作为站点的服务器,大部分情况下都需要被分配一个可被外部访问的 IP 地址,但它是可以更换的,可能会需要一些成本 更换了 IP 后,我们可以的服务器就可以开机了,因为攻击者并不知道我们服务器新的 IP 是多少,在不设定 DNS 解析的情况下,服务器是暂时安全了。但如果再次把域名解析到新的 IP,那他还是跟前面一样,只需要访问一次就能知道我们的新 IP,服务器就会继续挨打 我们也可以更换 IP 的同时更换一个域名,不过这样可能会损失之前积累的用户。如果你将更换域名的消息告诉了之前的用户,而攻击者潜伏在用户之中,那么你的服务器可能会再次遭殃 若网站之前有被搜索引擎收录,更换后的新域名再次被收录,那攻击者可以通过搜索引擎得知更换后的域名,DNS 再返回对应的 IP,那服务器同样会遭殃 上高防 / 升级服务器 只要你的配置够高,他就没法把你的服务器干掉线,只是看你的钱包能不能受得住。DDoS 的攻击和防御成本并不是一个量级的,一般的小站点可没有这个资金去买高防,升级服务器的性价比也很低,这是一个很糟糕的解决办法 使用 CDN 本文章的主角,能让 DNS 解析不会给出你的源站 IP,同时还能保证域名可以正常访问,它是怎么运作的呢? CDN 翻译过来就是内容分发网络,在 DNS 层面,它可以将 DNS 解析出来的 IP 从你的源站 IP 换为来自 CDN 的 IP,避免 DNS 直接暴露源站 IP DNS 解析出来不是源站 IP,那怎么获取我的站点内容呢? 按照流程,在 前面 所说的 DNS 解析出 IP 进行返回的过程中,使用 CDN 后,解析出来的 IP 是来自 CDN 的。接下来的请求部分,用户会从向源站 IP 发送请求变为向 CDN 的 IP 发送请求,这里 CDN 需要负责接受请求,然后再向源服务器发送请求,过程如下: # 没有使用 CDN 的请求 用户发送请求 > 源服务器收到请求 源服务器发送响应 > 用户收到响应 # 使用了 CDN 的请求 用户发送请求 > CDN 收到请求 CDN 转发请求 > 源服务器收到请求 源服务器发送响应 > CDN 收到响应 CDN 转发响应 > 用户收到响应 可以看到,开启 CDN 比不开启 CDN,用户每个请求都会先到达 CDN,再由 CDN 转发到源服务器,源服务器处理完得到响应之后,再发送给 CDN,CDN 再将回应发送给用户 看上去多了两个步骤,麻烦了不少,但我们需要的隐藏源站 IP 功能不是实现了? 不过要注意,CDN 很多时候只能转发 HTTP/S 请求,例如你本来用你的域名直接解析到 IP,使用 git 克隆仓库时可以使用域名替换服务器 IP,但开启 CDN 后,就不能这样了,你可能需要找一些其他方法 还没完 我们选择了最实用的 CDN 方法来隐藏了源站 IP,但还有一些需要注意的事情 如果你在没开 CDN 之前就被打了,只开 CDN 是不行的,你还需要同步更换 IP。CDN 只是阻断了通过 DNS 获取源站 IP 的方法,但你的 IP 早就在开 CDN 前泄露了,此时攻击者不会和你走流程,直接对着 IP 继续打,服务器还是得遭殃 我没有开过 CDN,但我也并没有被打过,看了文章我现在感觉有必要开一个 CDN,还来得及吗? 避免源服务器暴露站点特征 截止到这里,防止 DNS 泄露源站 IP 的方法其实已经解决了,不过为了安全,我们还是要配置一下源服务器上的反向代理,避免网上那些扫 IP 的服务暴露了我们在 CDN 后的源服务器 IP 排查暴露的端口 首先,我们要检查一下直接访问服务器 IP 能获得什么,请按照下面的列表排查一下自己服务器: 在浏览器中通过 IP:80 或 IP:443 能否直接访问到你的 HTTP/S 服务 如果你有其他非标准端口的服务,使用 IP:端口 是否能直接访问 如果你有部署 docker 或其他容器类服务,请检查容器的端口映射是否暴露在了公网 (可选)去 Censys 搜搜你的 IP 中有哪些被记录的端口和服务 暴露的 80/443 标准端口 如果你的 HTTP/S 服务能够通过 80/443 端口访问,那说明你的服务就直接暴露出来了,就算攻击者因为 CDN 中继保护还不知道你的 IP,但 80/443 是标准的 HTTP/S 端口,最简单的 IP 扫描也不会放过这两个端口,只要被扫到,基本就会暴露对应的数据 你可能会好奇,不是开了 CDN 吗?但 CDN 也是通过 80/443 端口才能转发服务器与客户端之间的请求,CDN 能访问到的数据,通过 IP 访问也可以,而直接通过 IP 访问则会绕过 CDN。如果一个 IP 访问后显示的网页数据和某个域名一样,那不用猜,这个 IP 就是域名后面对应的源服务器 IP,这时你的源服务器 IP 也就暴露了 还有上面说到的 Censys,有些人可能觉得我去上面搜自己的 IP 不就是主动暴露自己吗,确实有这个风险,但你可以去搜一下你的域名,有时候你的 DNS 解析或是服务器设置的证书中的域名也可能会在上面暴露 IP 与域名的关系 暴露的非标准端口 第二则是非标准端口的服务,其实也像上面一样,没什么安全性。大一点的扫描类服务为了数据库够大、相比同行更有竞争性,基本都会把每个 IP 能扫的端口都扫一遍,设定非标准端口并没有太大作用 暴露的容器端口 最后是容器中的端口映射,一般容器与主机的端口映射是可以修改的,很多容器自部署服务为了避免端口冲突,并不会将服务端口设为 80/443,而是 3000、5000 这种四位数的端口。为了让 IP 或域名可以不加端口直接访问,需要在服务器上设定反向代理,在收到请求时,根据传入的域名,决定转发请求到哪个容器中处理 设置得当时,通过域名访问站点,不管源服务器上有多少个容器,反向代理都可以帮你正确的转发请求到对应的容器,而用户与 CDN 发送的请求始终都是通过标准的 80/443 HTTP/S 端口,这可以让我们无需为每个相同的 HTTP/S 服务单独设置一个端口,避免了暴露多个端口的问题 不过,你有按照我说的步骤去排查 docker 容器端口映射了吗?如果发现你的 docker 容器也可以使用 IP:端口 直接访问,那你就要注意一下 docker 的端口映射方式了 docker 中容器的端口映射有两种方式:暴露至公网与仅在本机暴露,下面假设容器内的端口为 2340,映射到主机的端口为 1230: // 暴露至公网 // docker run 启动 docker run -p 1230:2340 <容器镜像> // docker compose 配置 ports: - 1230:2340 // 仅在本机暴露 // docker run 启动 docker run -p 127.0.0.1:1230:2340 <容器镜像> // docker compose 配置 ports: - 127.0.0.1:1230:2340 相比之下就是在 1230:2340 前多加了一段 127.0.0.1:,可能有点难看懂,这时它实际也是分为两段,127.0.0.1:1230 为主机的部分,2340 依然为容器端口,这里我们主要是限定了这个端口只允许在 127.0.0.1 访问,而 127.0.0.1 同时也对应了 localhost,就仅为本机使用 修改容器配置后,重启一下容器,再运行 docker ps 看看 PORTS 是不是由 0.0.0.0:1230->2340/tcp 变成了 127.0.0.1:1230->2340/tcp。这个时候,就无法通过 IP:1230 的方式访问到 docker 中的容器了 还有什么要注意的吗?当然,现在通过 IP 的 80/443 端口依然可以访问到服务器上的服务,跟 前面 说的一样,只要通过 IP 访问依然能得到与通过域名访问一样的数据,那还是能猜到这两者的关联,所以我们要完全切断 IP 与域名的联系,不留任何可以被关联的数据 当然肯定不是让你直接关机跑路 禁止直接通过 IP 访问 看上去很玄乎?虽然前面也提到了 CDN 能访问到的数据,通过 IP 访问也可以,但也有方法,让 CDN 可以正常转发,而直接访问 IP 不返回任何数据 此段部分内容来自 NGINX 配置避免 IP 访问时证书暴露域名 - ZingLix Blog 文章,在此感谢 ZingLix 假设我们使用的反向代理软件为 Nginx,我们原本的配置如下,其中假设自己的域名为 example.com: # 此段作用为转发 HTTP 请求至 HTTPS server { listen 80 default_server; return 301 https://$host$request_uri; } server { listen 443 http2 ssl; server_name example.com; ssl_certificate <SSL 证书公钥文件>; ssl_certificate_key <SSL 证书私钥文件>; # 忽略了一些配置 location / { proxy_pass http://localhost:3000; # 忽略了一些配置 } } 一份很普通的 nginx 配置,除了转发 HTTP 请求到 HTTPS 外,还有一段配置,作用是收到包含 example.com 域名的请求时,将请求转发到本地的 3000 端口进行处理。解析好 DNS 或同时加上 CDN,你都可以通过 example.com 域名来访问到服务器上的 3000 端口对应的服务 不过,如果你通过浏览器直接访问 IP,不管使用 http:// 还是 https:// 前缀,最后都是访问到了 443 端口,因为第一端的转发请求起了作用。而下一步就是请求 443 端口了,第二段配置的 listen 443 意思就是监听 443 端口,那么这个请求自然就传到第二段配置设定的 3000 端口对应的服务里去了,这就造成了使用 IP 能直接访问到服务器上的服务,我们可不希望这样 添加配置拒绝直接通过 IP 访问时的请求 那怎么办?我们可以在第一段后面添加一段监听 443 端口的配置,返回 403 或者 404?你可以现在试一下: # 此处作用为转发 HTTP 请求至 HTTPS server { listen 80 default_server; return 301 https://$host$request_uri; } server { listen 443 ssl default_server; return 403; } # 忽略了第三段配置 然后你会不出所料的得到类似 no "ssl_certificate" is defined for the "listen ... ssl" 的错误,简单来说就是,想要监听 443 端口,你必须要设定一个 SSL 证书,当然这个证书是否有效并不重要,只要是个证书就可以 但在添加证书前,我们先看看证书里有哪些内容(来自 什么是 SSL 证书? | Cloudflare): 针对其颁发证书的域名 证书颁发给哪一个人、组织或设备 证书由哪一证书颁发机构颁发 证书颁发机构的数字签名 关联的子域 证书的颁发日期 证书的到期日期 公钥(私钥为保密状态) 看到了吗,第一行中就有关于域名的信息,这可不行,在这个配置里加 SSL 证书也会泄露我们的域名,怎么办呢? 也有办法,只要我们给一个不包含我们域名信息的 SSL 证书就可以了,毕竟 nginx 并不会检验证书的有效性,于是我们使用 openssl 生成一个私钥和证书: # 请在 Linux 下运行,生成后的证书将生成在运行代码时的目录 # 在运行第二行时,会询问你证书的信息,可以随便填写也可以直接全部回车 openssl genpkey -algorithm RSA -out private.key openssl req -new -key private.key -out cert.csr openssl x509 -req -in cert.csr -signkey private.key -out certificate.crt 运行以上命令后,目录下会多出来三个文件,分别是 private.key、cert.csr 和 certificate.crt,将其添加到前面的配置里: # 忽略了第一段配置 server { listen 443 ssl default_server; ssl_certificate <文件目录>/certificate.crt; ssl_certificate_key <文件目录>/private.key; return 403; } # 忽略了第三段配置 此时再去直接访问 IP,你就会得到证书无效的错误,当然你也可以在页面上找一找,一般会有高级选项允许继续访问,就会得到 403 或 404 的错误,看你是如何设置的 不过我们是为了防止证书暴露信息,所以这是无法访问也是在我们的预期中的。点击浏览器地址栏旁边的信息按钮,这个按钮一般会显示成一个小锁或是类似设置的图标,就能看到证书无效的提示,点击查看详细信息就在弹出的窗口里可以看到里面的证书信息,这些信息就是你在前面生成证书时填写的信息 到这里,已经很难将你的源站与域名联系起来了,只要你使用 openssl 生成的证书中没有明晃晃写上你的域名,那想通过特征找到源站对应的域名,就等于大海捞针了 如果你的 Nginx 版本高于 1.19.4,你还可以使用新功能:拒绝握手 设定直接通过 IP 访问时拒绝握手 注意:这个功能和上一个方法作用类似,你只需要选择其中的一个来设置。相对而言,拒绝握手能提供更少的信息,效果更佳 这个功能需要 Nginx 版本高于 1.19.4,你可以在终端运行一下 nginx -v 检查一下是否可以使用该新功能。当然你也可以去升级 Nginx,如果无法升级或其他原因不想升级,上面的方法也足够安全了 拒绝握手的方法配置起来很简单,与上面的方法类似,只需在正常配置前添加一个监听 443 端口的服务即可,可以不指定 SSL 证书: # 此处作用为转发 HTTP 请求至 HTTPS server { listen 80 default_server; return 301 https://$host$request_uri; } server { listen 443 ssl default_server; # 当配置中开启拒绝握手时,不需要添加 SSL 证书与私钥 ssl_reject_handshake on; } # 忽略了第三段配置 保存配置并重启 nginx 服务后,再去浏览器里访问 IP,就可以看到已经无法通过 IP 访问到站点了,而且页面信息里也没有证书信息,可谓非常的干净 第二段配置中的 ssl_reject_handshake on 就是关键所在,只要一段配置中启用了这个功能,那么走这个通道的请求都会被拒绝握手,不会提供任何信息,所以注意不要往正常的服务配置里启用这个功能 我们安全了?暂时的 直到这里,我们开启了 CDN、关闭了暴露的端口、禁止 IP 访问以及配置了证书避免泄露我们的域名,不过还有一个方式能访问到服务,那就是我们的域名 为什么配置了怎么多,IP 都不能访问到网站了,而通过域名还可以?下面有两行命令,你可以试一试: curl -v -k https://<你的源站 IP> curl -v -k https://<你的源站所绑定的域名> 第一行是直接通过 IP 请求内容,第二行相同,但走的是域名来请求内容,可能还会经过 CDN。看着我们是配置成功了,IP 会无法访问,域名访问一切正常,不过,如果你试试下面这行命令呢? curl -v -k https://<你的源站所绑定的域名> --resolve <你的源站所绑定的域名>:443:<你的源站 IP> 看似能正常从域名获取网页内容?没错,不过我可要告诉你,这里请求的其实是 IP,而不是你的域名,是不会经过 CDN 的。但我们配置了禁止 IP 访问,为什么还是能获取到站点内容呢? 依然有办法可以通过 IP 访问 先看看这行命令有哪些参数,下面的域名将被替换为 example.com,IP 被替换为 333.333.333.333,CDN 的 IP 被替换为 444.444.444.444: curl \ -v \ # 输出请求时的整个过程 -k \ # 请求时跳过 SSL 检测(不会因为证书原因导致请求失败) https://example.com \ # 要请求的域名 --resolve \ # 将某个域名强制解析到某个 IP(替代 DNS 的作用) example.com:443:333.333.333.333 # 要强制指定的数据 这么看,这行命令的作用就是:在请求时输出全部日志并跳过 SSL 检测,跳过正常的 DNS 环节,直接将域名解析到指定的 IP 地址,再向强制解析后的域名发送请求,运行后的输出类似这样: $ curl -v -k https://example.com --resolve example.com:443:333.333.333.333 * Added example.com:443:333.333.333.333 to DNS cache * Hostname example.com was found in DNS cache * Trying 333.333.333.333:443... * Connected to example.com (333.333.333.333) port 443 (#0) # 忽略后续信息 而正常通过域名访问的输出呢? $ curl -v -k https://example.com * Trying 444.444.444.444:443... * Connected to example.com (444.444.444.444) port 443 (#0) # 忽略后续信息 可以看到,如果指定了 --resolve example.com:443:333.333.333.333 参数,在请求时会将 example.com 直接解析到 333.333.333.333,之后请求会直接冲着源服务器去,服务器再返回站点数据,我们的服务器可能就会再次沦陷了 怎么办呢?说实话,如果攻击者到了这种拿着域名一个个试试 IP 能不能通过请求的时候,我们就只能限制哪些 IP 可以直接访问服务器了 限制哪些 IP 可以直接访问源服务器 想要限制哪些 IP 可以访问我们的源服务器,我们总不能手动将用户的 IP 地址添加到防火墙白名单,家庭宽带很多时候并不会有固定 IP,每次用户 IP 变动时,你都需要实时将用户的 IP 添加到防火墙白名单,这相当的麻烦,而且你总不能在用户的设备上安装软件实时检测 IP 变化,这个解决方法很不现实 但如果我们使用的是 CDN,那解决方法就很方便了,由于 CDN 会负责转发用户的请求,使用 CDN 后用户与源服务器的请求始终是由 CDN 负责的,服务器日志中只会有来自 CDN IP 的请求,我们只需要使用防火墙拒绝其他 IP 的连接请求,仅允许来自 CDN IP 的请求即可 不过,你需要提前查询一下你使用的 CDN 供应商是否能提供 CDN 全部 IP 的列表,不然下方的两个方法都不适用你的情况 下面部分内容来自 屏蔽 Censys 扫描器, 及设置仅允许 Cloudflare 回源 - Zikin 的独立博客 文章,同样在此感谢 Zikin 我们有两种方式可以对设置仅允许哪些 IP 与源服务器建立连接: 方法 1: 使用 Nginx 的 allow / deny 字段 (不推荐) 由于这是一个不被推荐的方法,我并不会写出具体的操作流程,如果你还是想看看如何配置,你可以去 屏蔽 Censys 扫描器, 及设置仅允许 Cloudflare 回源 - Zikin 的独立博客 文章查看操作步骤 这个方法是可以不向被限制的 IP 发送原本的网页数据,但在搭配了上面添加的 nginx 拒绝握手特性时,会出现一个自欺欺骗人的情况。我们先保留之前的拒绝握手设置,再往普通配置里添加 deny 字段拒绝所有 IP 的连接请求: # 此处作用为转发 HTTP 请求至 HTTPS server { listen 80 default_server; return 301 https://$host$request_uri; } server { listen 443 ssl default_server; ssl_reject_handshake on; } server { listen 443 http2 ssl; server_name example.com; ssl_certificate <SSL 证书公钥文件>; ssl_certificate_key <SSL 证书私钥文件>; # 忽略了一些配置 # 方便测试,这里我们将拒绝来自所有 IP 的连接请求,使用时,你需要改为仅允许来自你 CDN 供应商的 IP deny all; location / { proxy_pass http://localhost:3000; # 忽略了一些配置 } } 我们再使用 curl 发送请求,域名被替换为 example.com,源站 IP 依然为 333.333.333.333: 我们先试试直接请求 IP $ curl -v -k https://333.333.333.333 * Trying 333.333.333.333:443... * Connected to 333.333.333.333 (333.333.333.333) port 443 (#0) * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS alert, unrecognized name (624): * OpenSSL: error:0A000458:SSL routines::tlsv1 unrecognized name * Closing connection 0 curl: (35) OpenSSL: error:0A000458:SSL routines::tlsv1 unrecognized name 与预期相同,服务器拒绝了我们发送的握手请求,也没有提供证书,接下来我们试试强制将域名解析到源站的 IP 地址: $ curl -v -k https://example.com --resolve example.com:443:333.333.333.333 * Added example.com:443:333.333.333.333 to DNS cache * Hostname example.com was found in DNS cache * Trying 333.333.333.333:443... * Connected to example.com (333.333.333.333) port 443 (#0) * ALPN: offers h2,http/1.1 # 忽略了部分 TLS 握手内容 * ALPN: server accepted h2 * Server certificate: # 忽略了服务器证书内容 # 忽略了请求信息 > GET / HTTP/2 > Host: example.com > user-agent: curl > accept: */* > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * old SSL session ID is stale, removing < HTTP/2 403 < server: nginx < content-type: text/html < content-length: 153 < <html> <head><title>403 Forbidden</title></head> <body> <center><h1>403 Forbidden</h1></center> <hr><center>nginx</center> </body> </html> * Connection #0 to host example.com left intact 可以看到,curl 成功与源服务器握手,并输出了来自 nginx 的回应,虽然最后输出的是 403 Forbidden(无权访问) 的回应,也没有输出原本的网页信息。看上去 IP 白名单起效果了,但它并没有达到我们想要的效果,此时我们再试试将一个不存在的域名解析到源站的 IP 地址: $ curl -v -k https://noexistdomian --resolve noexistdomian:443:333.333.333.333 * Added noexistdomian:443:333.333.333.333 to DNS cache * Hostname noexistdomian was found in DNS cache * Trying 333.333.333.333:443... * Connected to noexistdomian (333.333.333.333) port 443 (#0) * ALPN: offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS alert, unrecognized name (624): * OpenSSL: error:0A000458:SSL routines::tlsv1 unrecognized name * Closing connection 0 curl: (35) OpenSSL: error:0A000458:SSL routines::tlsv1 unrecognized name 从最后的输出可以看出,这个不存在的域名,触发了我们的拒绝握手配置 如果向源服务器发送请求时传递的域名正确,则可成功握手,否则将返回拒绝握手的 tlsv1 unrecognized name 错误 这代表当攻击者使用域名对我们的服务器进行扫描时,直接请求 IP 或附加的是错误的域名,那么你的服务器会正常的拒绝握手。但如果请求的是正确的域名,服务器接收了请求、完成了握手,然后返回了 403 Forbidden(无权访问) 有什么问题呢?将视角换为攻击者就好理解了:我直接请求 IP 你拒绝我的握手,用其他域名请求你也拒绝握手,但我用 example.com 你通过了握手再给我返回 403?那这个 IP 绝对跟 example.com 这个域名有关系 后面的就不用我说了吧,可以等着换下一个 IP 了 方法 2: 使用系统防火墙 在这里,我们使用基于 iptables 易用接口的 ufw 设定防火墙规则,此处部分内容同样来自 屏蔽 Censys 扫描器, 及设置仅允许 Cloudflare 回源 - Zikin 的独立博客 文章 我们照样先试试被防火墙封禁后,直接请求 IP 与携带域名请求会怎么样,先设置防火墙: sudo ufw allow OpenSSH # 设定防火墙允许 ssh,否则可能就连不上服务器了 sudo ufw default deny # 将默认入站连接设定为拒绝 注意!如果你需要通过 ssh 才能连接到服务器,请务必按照上面的方法允许 ssh 请求,否则你可能会再也无法连接到你的服务器 此时,我们已经设定好了防火墙配置,允许 ssh 连接,并拒绝所有入站请求,接下来我们就可以通过 ufw 开启防火墙了: sudo ufw enable # 启用防火墙 sudo ufw status verbose # 查看防火墙状态以及规则 # 此时的输出应如下所示 Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), deny (routed) New profiles: skip To Action From -- ------ ---- 22/tcp (OpenSSH) ALLOW IN Anywhere 22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6) 这时候再去试试请求服务器,你会发现不管是单独请求 IP 还是携带域名请求都无法获取到内容了,可能会提示无法连接或者迟迟没有完成请求,因为这个时候请求到达防火墙的时候直接被拒绝了,没有返回任何信息 不过这个时候再去浏览器访问域名,你会发现域名也进不去了,因为上面的规则阻止了所有 IP 的入站请求,CDN 的 IP 也同样被阻止了,所以我们还需要设定规则允许来自 CDN IP 的连接 与用户多变的 IP 不同,CDN 的 IP 一般是固定的,我们只需要将 CDN 供应商提供的 CDN IP 列表添加到防火墙白名单即可 我使用的 CDN 来自 Cloudflare,如果你使用的是其他 CDN 提供商,请手动查找对应的 IP 范围列表,按照 前面 的需求,Cloudflare 是提供全部 IP 的列表的,可见 IP 范围 | Cloudflare,我们只需要将列出的 IP 范围添加到防火墙白名单,通过域名访问的请求即可恢复正常: sudo ufw allow from 173.245.48.0/20 sudo ufw allow from 103.21.244.0/22 # 省略后面一条条加的过程 测试的时候我觉得很麻烦,于是我写了一个 shell 脚本,发布在 GitHub Gists 上,可以一键获取 Cloudflare CDN 的所有 IP 范围列表并添加到防火墙白名单,你可以使用它来一键添加: curl -L https://gist.githubusercontent.com/Interstellar750/1803cdefcaa91940e87a3d27fe78f17b/raw/add_cf_ips.sh | sudo bash # 如果你想从防火墙白名单中移除 Cloudflare 的 IP,执行下面这行 # 运行后会在运行时的目录留下来一个 add_cf_ips.sh 文件,你可能需要手动删除它 curl -L https://gist.githubusercontent.com/Interstellar750/1803cdefcaa91940e87a3d27fe78f17b/raw/add_cf_ips.sh > add_cf_ips.sh && sudo bash add_cf_ips.sh --remove 对了,在添加完防火墙规则后,你可能需要运行一下 sudo ufw reload 加载修改后的规则以生效,之后再去浏览器使用域名访问,就可以正常访问了。使用 curl 请求 IP 或携带域名请求 IP,都不会返回站点信息,我们就完成了对源服务器的保护 最后的一些琐事 如果设定了防火墙白名单,那么上面 nginx 的拒绝握手配置其实也可有可无了,非 CDN 的 IP 根本无法触发到这个拒绝握手的规则,最坏的情况只能是攻击者用 CDN 的 IP 去扫服务器请求,如果真有这种情况,可以考虑换一个 CDN 提供商了 在想到防火墙添加 Cloudflare CDN 的 IP 白名单时,我还在考虑如果攻击者连上 warp 之后扫服务器怎么办,我就去查了查 warp 的 IP 段,跟 CDN 并不在一个段。这下除非去机房一台机一台机的拔网线,不然基本就不可能找得到我 IP 了 文章末尾感谢: Cloudflare Vercel 本文提到文章的两位作者 某个服务器提供商 不知名的攻击者 从 23 年 7 月开始将我服务器打到空路由,在我建立防护后顶着 Cloudflare 一直给我刷了估计有 30m 请求。同时给我 Vercel 的免费 100 GB 套餐超额刷至 1.2TB,让我被迫学习网络安全知识

2024/4/5
articleCard.readMore

域名变动

个人站点的域名将迎来一些变动,位于 trle5.dev 域名下的全部站点,其绑定的域名将被迁移到 trle5.xyz 域名下 站点迁移后使用的域名: 服务 先前域名 新域名 备注 Hubert's Gitea trle5.dev gitea.trle5.xyz Hubert's Alist alist.trle5.dev alist.trle5.xyz Cloudflare tunnle git.trle5.dev git.trle5.xyz 日程 从此文章发布起,当您访问任何一个使用 trle5.dev 域名或子域名的站点时,您都能在网页顶部看到一个提示,并有一个超链接将您引导到这个页面 在 4 月 1 日前,您依然可以照常通过旧域名访问 trle5.dev 下的全部站点,但我不保证功能是否依然正常 4 月 1 日后,位于 trle5.dev 域名及其子域名的站点将被 301 重定向至新域名,直到 6 月 4 日域名到期 DNS 停止解析 trle5.dev 域名过期后,可能会购入重新使用,如果域名被重新注册,您应该能在网页顶部再此看到一个链接到此页面的提示,文中应该也更新了域名的使用信息

2024/2/16
articleCard.readMore

为旧 iOS 设备下载适用的旧版软件

需要的东西: 任意区 iCloud 账号 能安装最新版软件的 iOS 设备 上一条需求听上去有点扯,都有另一个设备能装最新版了那还为什么装旧版软件。这另一个设备主要作只用是入库,即让软件出现在应用商店的“已购项目”中,如果实在没有也可以找朋友帮忙 在旧设备和新设备的应用商店中登录同一个 iCloud 账号 在新设备中搜索想在旧设备上安装的软件,安装对应软件,只要过了验证后,出现应用下载进度条,就可以取消了 打开旧设备的应用商店,找到“已购项目”页面,不出意料你能在里面找到刚刚的那个软件,点击安装,会提示“该软件不兼容此 iOS,是否下载兼容的最后一个版本”,选择“是”即可 注意事项 此方法只能下载软件兼容旧版 iOS 系统的最新一个版本 如果你要下载的软件从发布起就要求很高的 iOS 版本(例如 ChatGPT 最低要求 iOS 16.1),这种情况应用商店根本没有符合旧系统的旧版应用下载,那也是没办法的 如果 iOS 系统版本高于或等于目前软件适配的最高系统版本,就没法通过此方法安装旧版软件 例如 iOS 12 在今年发布,目前某个软件的系统要求如下 1.0 版本需要 iOS 9+ 2.0 版本需要 iOS 10+ 3.0 版本需要 iOS 11+ 3.5 版本需要 iOS 11+ 4.0 版本需要 iOS 12+ 现在软件版本号已经是 4.0,最低要求 iOS 12 使用 iOS 9 的设备去安装该软件时,应用商店会询问你是否安装兼容该系统的的最后一个版本,选择是后,应用商店会给你安装 1.0 版本的软件。同理,使用 iOS 10 的设备会安装 2.0 版本 但使用 iOS 11 来安装时,虽然 3.0 和 3.5 都兼容 iOS 11,但应用商店只会安装 3.5 版本,因为这是兼容 iOS 11 的最新一个版本,想安装 3.0 版本就只能找其他办法了 如果使用 iOS 12+ 的设备来安装这个软件,不管你是搜索直接安装,还是在“已购项目”中安装,下载到的永远都是最新的 4.0 版本 下载后的旧版软件能正常安装不代表能正常使用,因为服务器可能会对旧版本进行禁止登录或其他限制使用的行为,这样就没有其他办法了

2024/1/9
articleCard.readMore

隐私声明

本站源代码存放在 GitHub 仓库,博客托管在 Cloudflare Pages 平台,域名 DNS 解析由 Cloudflare 提供,我可得知的数据如下: GitHub 仓库 stars / watching / fork 的用户列表 Discussions 的讨论内容(包括 Giscus) Pull Request 请求信息 Cloudflare / Cloudflare Pages 平台 流量分析 Cloudflare 为域名托管者提供了免费的流量分析,最长可以记录 30 天的数据,借此,我可以得知的数据如下: 此功能为使用 Cloudflare 域名托管服务时默认开启的功能,您可能无法通过任何方式绕过这部分的数据收集 Web 流量 请求(最长 30 天,最短 24 小时,精确到请求数) 请求总数 已缓存的请求 未缓存的请求 带宽(最长 30 天,最短 24 小时,精确到 KB) 总带宽 已缓存的带宽 未缓存的带宽 唯一访问者(精确到人数) 总计(最长 30 天,最短 24 小时) 上限(最长 1 天,最短 1 小时) 下限(最长 1 天,最短 1 小时) Web 流量请求 访客流量靠前的国家或地区(精确到流量数,最长 30 天,最短 24 小时) 统计信息(上个月) 已节省的字节数(精确到 KB) 已提供的 SSL 请求数(精确到次数) 已阻止的攻击数(精确到次数) Web Analytics Cloudflare Web Analytics 是一个基于 JavaScript 代码的分析工具,最长可以记录 180 天的数据 您可以尝试使用一些工具来屏蔽 https://static.cloudflareinsights.com/beacon.min.js JavaScript 代码来绕过此部分的数据收集。您也可以选择对于本站点(trle5.xyz)屏蔽 JavaScript 代码,但这可能会导致一些功能将无法使用 在控制台中,可以按最长 30 天,最短 1 分钟的时间间隔来查看数据,同时还可以使用 国家/地区 主机 路径 引用方 设备类型 浏览器 操作系统 站点 排除自动程序 来作为筛选条件,借此,我可以得知的数据如下: 高级指标 页面加载时间(精确到毫秒) 访问量(精确到次数) 页面浏览量(精确到次数) 核心网络指标(Core Web Vitals)见下方 核心网络指标(Core Web Vitals) 最大内容绘制(LCP)(精确到次数) 与下一个画图交互(INP)(精确到次数) 累计布局偏移(CLS)(精确到次数) 以上三个指标数据,均可按照 URL 浏览器 操作系统 国家/地区 元素 类别来排序 在控制台中还提供了调式视图,在调式视图中可以查看被记为 差 和 需要改进 元素的详情信息,其中也可查看到一些数据: 最大内容绘制(LCP) Object 和 页面 主机 路径 指标延迟 LCP - P50 LCP - P75 LCP - P90 LCP - P99 DOM 元素 与下一个画图交互(INP) 页面 主机 路径 指标 INP - P50 INP - P75 INP - P90 INP - P99 DOM 元素 累计布局偏移(CLS) 页面 主机 路径 指标 CLS - P50 CLS - P75 CLS - P90 CLS - P99 DOM 元素 布局偏移 上一个 当前 关于统计数据 统计数据中绝大部分可展示的数据已列举于上方,但此列表可能依然会有遗漏,若有其他需要了解的数据请前往对应平台中查看相应文档 您在本站的浏览统计数据可能会被公开展示,点此查看公开展示时的类似形式 与他人展示 你看看我这篇文章竟然有这么多人看:(附上页面浏览数据) 演示流量消耗: 压缩了图片大小后,我博客每个月只需要不到 1GB 流量:(附上流量消耗统计) 浏览器类型 访问我博客用的浏览器七八成都是 Chrome:(附上浏览器类型统计)

2025/10/24
articleCard.readMore

待办事项

嗨,你好! 顾名思义,这是一个待办清单,我会把我的博客更新计划和完成进度记录在这里,不过也不是全部列在这里的事情都会完成,有时候会遭受到不可抗力的影响 博客相关 文章更新 还没有想法... 需要修改 / 补充的文章 还没有想法... 其他 Link Preview 时的图片 搓了一些,但难看到自己都不想看...

2025/10/24
articleCard.readMore

建站历程

想了想以后这个页面似乎会长长长,就单独放个页面了 以后也得想个办法整理一下这个页面 建站初期 & hexo & chic 2022/01/24 初次建立 GitHub Pages 来作为服务器 (其实并不是第一次,前前后后试了好几次,因为碰到了好多 bug) 2022/01/29 白嫖域名 Freenom 上申请了 12 个月的免费域名 trle5.tk ,但由于不会设置 DNS 解析,依然用着 GitHub Pages 的默认域名 2022/02/26 迁移后端 Sailfish OS 因为未知问题操作很卡,把 hexo 后端备份出来迁移到了 s10e 上,使用 Termux 来继续运维 2022/02/27 设置 DNS 解析 GoDaddy ,成功用上了自定义域名 2022/03/08 购入新域名 reg.ru 购买了一年的 trle5.xyz 域名,用于存放文件,本站可能有一些图片文件会储存在里面 2022/03/14 更换 DNS 解析 Freenom 提供的 DNS 解析 2022/03/15 更换存文件的地方 trle5.xyz 迁移到 t5d.trle5.tk 2022/05/07 换 Chic 主题 Siricee 制作的 Chic 主题 2022/05/08 建立镜像站 Vercel 建立了博客镜像站,使用域名 trle5.xyz ,DNS 解析由 Cloudflare 提供 2022/06/01 重新配置主题 2022/07/19 修正文章 懒 ,由于之前的丢数据问题,Cloudflare 账号也登不上了,找回有点麻烦 2022/09/11 成功找回 Cloudflare 帐号 trle5.xyz 站点会随时更新,就是代表上面可能会有一些没写完的文章和新东西,文章写完后再推送至 trle5.tk,于 6 月 4 日在 Porkbun 白嫖的 trle5.dev 域名还没打算好用来干嘛,两个付费域名以我现在的经济能力压力有点大 切换至 Urara 2022/10/23 切换到 Urara 后端 Dejavu's Blog 频道看见 Urara 直到今天才完全成功切换到这个后端,配置其实不算太难,我完全没有 svelte 的基础,但看着原文件和 Urara 作者 藍+85CD 的博客改也勉强可以了,后面估计我还得改不少东西 2022/11/02 小修小补 2022/11/13 移除了加都没加的东西 从 8 号开始搞到现在,搞好了一个朋友页面,但很奇怪在本地运行一切正常,部署到 Vercel 上就无法运行,用之前的部署方式会出现 404 问题,于是现在只能删掉了 😭 修好咯,不过目前有个鼠标放到文章日期上时修改时间会与创建时间叠在一起,看看 kwaa 大佬什么时候修 顺便说一句,trle5.dev 域名借给朋友拿去搭博客了 2022/11/19 同步与开源 这个 议题发了一个 comment,今天中午问题就修复了,要在这里说一句非常感谢大佬们,自己没学过前端也就只能提个议题或报告一下问题了,修复问题这种问题很可惜帮不上忙 😥 推完这次更新后我的整个博客的源码就开源啦,至于之前为什么不放出来,第一个原因是可以用之前的 blog 项目直接部署,但换到 Urara 后端之后这样就不行了,除非点击任意链接后网页链接都会自动加上 .html 后缀,不然就会出错,没那个技术力的我就只能弃用之前的方法了,第二个就是当时有巨多问题,自己修也不知道怎么修 2022/12/01 开通 Giscus #47 这个议题好像说会有 bug 导致登不上 Giscus,但我自己试了试没问题,有点奇怪 修了,但似乎只修了 Giscus 的登录问题,sitemap 还是没法使用 一周年 2023/01/24 续费域名 freenom 上注册的免费域名 trle5.tk,不出意料的免费续费了一年,虽然目前已经闲置很久了 博客目前主要用的 trle5.xyz 打算在今天转移到 Blacknight,本来是打算转到 Cloudflare,但架不住 5 欧元一年 的续费/转移价格,便宜 但是被限制付款了,发个工单问问客服,不行那就高价转到 Cloudflare 至于 trle5.dev 最便宜还是 $10 以上,但过期时间在六月,再等等吧 2023/03/02 购入服务器 RackNerd 买了个服务器,折腾两天后搭好了一个能用的 memos,分配的二级域名为 memos.trle5.xyz 还有一个 SSL 证书时不时抽风的 Gitea 服务则是为了操作方便把 trle5.dev 拿来用,原来朋友的博客就给他安排了个二级域名:blog.trle5.dev,但他好像打算把博客重构了 2023/07 被 DDoS 新的博客后端 2025/08 计划开始 .tmpl 文件的一些简单原理后,打算想写一个新的博客生成工具,虽然计划暂搁了一会,但还是在九月中期继续折腾,设计大部分仿照着 lume_theme_shiraha 做,小部分设计参考之前使用的 Urara 2025/10 接近可用状态 new tplate 文章

2025/10/24
articleCard.readMore

关于我

大家好啊,我是 Hubert,今天来点大家想看的东西啊 会些什么 Go 语言 现在写了几个小项目,自我认为还可以 C 语言 说实话已经很久没写过了 Linux 没什么变化,会些日常用的命令就足够了 兴趣爱好 日常消遣方式是在 Telegram 上聊天与刷频道,其次就是玩游戏 有时会画点画画,但还没到入门的阶段 联系方式 依然是没有国内的交流平台,不是很喜欢用,有联系需求就发邮件吧 Telegram: @trle5 / @include011 Matrix: @trle5:matrix.org 不怎么活跃,但应该能收到消息 Email: 01@trle5.xyz 用的 Cloudflare 转发到 Gmail Twitter: @interstellar750 不是很喜欢发推文 Fediverse: trle5@hyp3r.link 在 kwaa 大佬的实例上注册的,也是不怎么喜欢发文 GitHub: @interstellar750 (好像并不能联系到人...) Gitea: @trle5 自己在 VPS 上用 docker 跑了个 Gitea,已经运行三年了 GPG 公钥 AAC3 7641 0634 FF86 sec rsa4096/AAC376410634FF86 2023-01-01 [SC] (签名 证明) 7456 A0AB 47EC E8BE 1AD0 89D9 AAC3 7641 0634 FF86 uid [ultimate] Hubert Chen <01@trle5.xyz> ssb rsa4096/B716CE1EAA7B8F00 2023-01-01 [E] (加密) ssb rsa4096/B4ED58260C725C91 2023-01-06 [A] (认证) ssb rsa4096/2935B4DE0D6F7720 2023-01-06 [SE] (签名 加密) 8A2A 227E 222D CCDB sec# ed25519/8A2A227E222DCCDB 2023-01-18 [C] (证明) F154 5A09 2296 673A 0C43 6BE0 8A2A 227E 222D CCDB uid [ultimate] Hubert Chen <01@trle5.xyz> ssb> ed25519/74D8BCE883FDDEE2 2023-01-19 [S] (签名) ssb> cv25519/FA47AF4129AA0BB1 2023-01-19 [E] (加密) ssb> ed25519/7043720D3C7D7718 2023-01-19 [A] (认证) 当你需要确认屏幕前的人为“我”时,你不需要任何理由即可向我索要以上方 GPG 密钥进行签名的消息,收到签名的消息时请务必验证消息的时效性,同时请确保验证消息中包含双方的信息以及需要的操作内容 若验证失败或以任何方式拒绝或推脱签名请求,请不要信任此时“我”的任何请求! 获取公钥文件: GitHub | Hubert's Gitea | Hubert's Box 目前主要用来给 Commit 签名的密钥为 2935 B4DE 0D6F 7720,暂未对其他 GPG 公钥进行证明 游戏平台 Steam: interstellar Xbox: interstellar771 Ubisoft: interstellar750 Minecraft ID: trle5 EA ID: trle5 音乐 Spotify: Hubert Chen 网易云音乐: trle5 不是很常用 目前主要是用 Spotify,喜欢听的音乐类型比较杂 设备 移动设备 iPhone 12 A14 / 4GB / 128GB iPhone SE 2 A13 / 3GB / 64GB iPad mini 5 A12 / 3GB / 64GB Apple Watch S5 44mm / 32GB 硬件 i5-4460 / HD 4600 & Tesla P4 / 8GB DDR3 / 240GB SATA SSD x 3 Orange Pi Zero2 H616 / 1GB DDR3 / 64GB Micro SD Xbox Series S 1TB 操作系统 Windows LTSC 2021 (21H2) Debian bullseye | kernel 5.10.0 服务器用 iOS 15.6 (iPhone 12) 17.7 (iPhone SE 2) iPad OS 17.3.1 (iPad mini 5) 关于本站 想想也是得在这个页面写一点关于本站的信息 博客后端 建立初期使用 Hexo,使用过 Chic 主题,很长一段时间在使用 Urara 模板,现在用的是自己写的 tplate 评论系统 目前支持基于 GitHub Discussions 的 Giscus 以及基于 webmention.io 的 Webmention,由于我换成了自己的博客模板,显示信息的部分就交给 kwaa 开发的 seia 插件了

2025/12/18
articleCard.readMore