<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>夏沫花火zzz🌙 (Muska_Ami)のLife</title>
  
  <subtitle>Muska_Ami 的小站</subtitle>
  <link href="https://blog.amaicat.work/atom.xml" rel="self"/>
  
  <link href="https://blog.amaicat.work/"/>
  <updated>2026-07-15T16:23:36.622Z</updated>
  <id>https://blog.amaicat.work/</id>
  
  <author>
    <name>夏沫花火zzz🌙 (Muska_Ami)</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>阿里云 ESA 使用体验</title>
    <link href="https://blog.amaicat.work/2025/08/06/a-li-yun-esa-shi-yong-ti-yan/"/>
    <id>https://blog.amaicat.work/2025/08/06/a-li-yun-esa-shi-yong-ti-yan/</id>
    <published>2025-08-06T05:21:18.000Z</published>
    <updated>2026-07-15T16:23:36.622Z</updated>
    
    <content type="html"><![CDATA[<p>阿里云 ESA 很早就开始用了，之前一直在找稳定的和 Cloudflare 类似的国内 CDN，刚好阿里云 DCDN 升级，用国内版效果还不错。<br>速度也挺快的，这是我主站的测试图，源站在海外访问也很快。</p><p><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2025/08/06/689357abef142.webp" alt="测速"></p><p>现在搞活动还能免费领，链接：<a class="link"   href="http://s.tb.cn/e6.0DENEf" >http://s.tb.cn/e6.0DENEf <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;阿里云 ESA 很早就开始用了，之前一直在找稳定的和 Cloudflare 类似的国内 CDN，刚好阿里云 DCDN 升级，用国内版效果还不错。&lt;br&gt;速度也挺快的，这是我主站的测试图，源站在海外访问也很快。&lt;/p&gt;
&lt;p&gt;&lt;img loading=&quot;lazy&quot; src=&quot;</summary>
      
    
    
    
    
    <category term="阿里云" scheme="https://blog.amaicat.work/tags/%E9%98%BF%E9%87%8C%E4%BA%91/"/>
    
    <category term="CDN" scheme="https://blog.amaicat.work/tags/CDN/"/>
    
  </entry>
  
  <entry>
    <title>LoCyanFrp 3 更新日志</title>
    <link href="https://blog.amaicat.work/2025/07/05/locyanfrp-3-geng-xin-ri-zhi/"/>
    <id>https://blog.amaicat.work/2025/07/05/locyanfrp-3-geng-xin-ri-zhi/</id>
    <published>2025-07-05T07:21:57.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<p>本次更新，我们重构了整个前后端，故花费了较长的时间，感谢各位的耐心等待。</p><h2 id="项目架构更新"><a href="#项目架构更新" class="headerlink" title="项目架构更新"></a>项目架构更新</h2><p>第三代乐青映射的技术栈为：</p><ul><li>前端<ul><li>Nuxt.js</li><li>Vue.js</li></ul></li><li>后端<ul><li>Spring Boot</li><li>Spring Cloud</li></ul></li></ul><h3 id="网页面板"><a href="#网页面板" class="headerlink" title="网页面板"></a>网页面板</h3><ul><li>使用 Nuxt.js 框架进行了重写</li><li>从 CSR 切换到了 SSG，加载面板更快，性能更好</li><li>经过重新设计的 UI&#x2F;UX，带来更方便的操作，更人性化的体验</li><li>彻底移除了 Axios，使用 ofetch 作为网络请求库</li></ul><h3 id="后端"><a href="#后端" class="headerlink" title="后端"></a>后端</h3><ul><li>完全重写，并规范了命名空间</li><li>几乎全部使用 Kotlin，增加开发效率，并减少空指针导致可能的异常</li><li>使用 Gradle Version Catalog 进行依赖管理，减少可能的依赖问题</li><li>引入了 Spring Cloud Eureka 微服务架构，为集群化部署进行了适配</li><li>对后端进行了模块化</li></ul><h3 id="数据库"><a href="#数据库" class="headerlink" title="数据库"></a>数据库</h3><ul><li>从 MySQL 更换为了 PostgreSQL + TimescaleDB</li><li>对数据库结构进行了完全的重新设计，完全抛弃 Sakura Panel 的数据库格式</li></ul><h2 id="软件更新"><a href="#软件更新" class="headerlink" title="软件更新"></a>软件更新</h2><ul><li>将 Frp 从 0.51.3 版本更新到了 0.62.1 版本</li><li>将 Controller 移植到了非 Linux 客户端</li></ul><h2 id="其他更新"><a href="#其他更新" class="headerlink" title="其他更新"></a>其他更新</h2><ul><li>支持了港澳台证件进行身份认证</li><li>对用户组功能进行了重新设计</li><li>暂时移除了没有任何用的联机功能，后续会重新加入</li><li>加入了 TOML、YAML、JSON 配置的支持，移除了 INI 配置</li><li>引入了 Umami 统计</li></ul><h2 id="计划中（未完成更新）"><a href="#计划中（未完成更新）" class="headerlink" title="计划中（未完成更新）"></a>计划中（未完成更新）</h2><ul><li>通行密钥登录</li><li>HTTP2HTTPS 自动配置</li></ul><p>更多未列出事项，可以在 GitHub Issue Tracker 查看。</p><p><a class="link"   href="https://github.com/LoCyan-Team/LoCyanFrpFrontend/issues/1" >LoCyanFrpFrontend#1 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本次更新，我们重构了整个前后端，故花费了较长的时间，感谢各位的耐心等待。&lt;/p&gt;
&lt;h2 id=&quot;项目架构更新&quot;&gt;&lt;a href=&quot;#项目架构更新&quot; class=&quot;headerlink&quot; title=&quot;项目架构更新&quot;&gt;&lt;/a&gt;项目架构更新&lt;/h2&gt;&lt;p&gt;第三代乐青映射的技术</summary>
      
    
    
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/tags/LoCyanFrp/"/>
    
  </entry>
  
  <entry>
    <title>在 Windows 环境为 rEFInd 配置安全启动</title>
    <link href="https://blog.amaicat.work/2025/06/22/zai-windows-huan-jing-wei-refind-pei-zhi-an-quan-qi-dong/"/>
    <id>https://blog.amaicat.work/2025/06/22/zai-windows-huan-jing-wei-refind-pei-zhi-an-quan-qi-dong/</id>
    <published>2025-06-22T12:20:49.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><ol><li>下载微软签名的 <code>PreLoader.efi</code> <code>HashTool.efi</code> <a class="link"   href="https://blog.hansenpartnership.com/linux-foundation-secure-boot-system-released/" >https://blog.hansenpartnership.com/linux-foundation-secure-boot-system-released/ <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></li><li>准备一个可以读写 EFI 分区的软件（此处为 DiskGenius）</li><li>确认你的磁盘格式支持安全启动</li><li>一点耐心</li></ol><h2 id="操作步骤"><a href="#操作步骤" class="headerlink" title="操作步骤"></a>操作步骤</h2><h3 id="将-PreLoader-和-HashTool-复制到-rEFInd-可启动项的目录"><a href="#将-PreLoader-和-HashTool-复制到-rEFInd-可启动项的目录" class="headerlink" title="将 PreLoader 和 HashTool 复制到 rEFInd 可启动项的目录"></a>将 PreLoader 和 HashTool 复制到 rEFInd 可启动项的目录</h3><p>根据你实际放置的位置来，我的是 <code>\EFI\refind</code>，将这两个文件拷到里面即可。</p><p><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2025/06/23/6858674a75107.webp" alt="效果"></p><h3 id="复制-rEFInd-的可启动项文件"><a href="#复制-rEFInd-的可启动项文件" class="headerlink" title="复制 rEFInd 的可启动项文件"></a>复制 rEFInd 的可启动项文件</h3><p>复制一份 rEFInd 的可启动项文件，比如我的是 <code>refind_x64.efi</code>，复制成 <code>loader.efi</code>。</p><p><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2025/06/23/685867a356642.webp" alt="效果"></p><h3 id="添加-UEFI-BIOS-启动项"><a href="#添加-UEFI-BIOS-启动项" class="headerlink" title="添加 UEFI BIOS 启动项"></a>添加 UEFI BIOS 启动项</h3><p>DiskGenius 菜单栏，<code>工具</code> -&gt; <code>设置UEFI BIOS启动项</code> 添加一个新的启动项，路径为刚才复制过去的 <code>PreLoader.efi</code>。<br>将启动项移动到最顶上（第一个启动的），保存。</p><p><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2025/06/23/68586819c57a3.webp" alt="效果"></p><h3 id="重启设备，进入-BIOS-设置"><a href="#重启设备，进入-BIOS-设置" class="headerlink" title="重启设备，进入 BIOS 设置"></a>重启设备，进入 BIOS 设置</h3><p>进入你的主板 BIOS 设置，如果你不知道怎么按键盘进入那在上一步勾上下面 <code>下次启动时直接进入UEFI BIOS设置界面（仅一次）</code>，然后点击 <code>立即重启</code>。</p><p>在 安全（Security）设置找到 安全启动（Secure Boot）设置，改为 开启（Enabled）。<br>在最后一个选项卡保存并重启（Save &amp; Reset(有的是 Save &amp; Restart)）。</p><h3 id="使用-HashTool-导入-Hash"><a href="#使用-HashTool-导入-Hash" class="headerlink" title="使用 HashTool 导入 Hash"></a>使用 HashTool 导入 Hash</h3><p>这个时候你应该会看到一个蓝色的屏幕，并显示如下：</p><div class="highlight-container" data-rel="TEXT"><figure class="iseeu highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">┌──────────────────────────────────────────────────────────────────────────────┐</span><br><span class="line">│                            Failed to start loader                            │</span><br><span class="line">│                                                                              │</span><br><span class="line">│          It should be called loader.efi (in the current directory)           │</span><br><span class="line">│                     Please enrol its hash and try again                      │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                I will now execute HashTool for you to do this                │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                     ┌────┐                                   │</span><br><span class="line">│                                     │ OK │                                   │</span><br><span class="line">│                                     └────┘                                   │  </span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">└──────────────────────────────────────────────────────────────────────────────┘</span><br></pre></td></tr></table></figure></div><p>此时按回车，显示如下：</p><div class="highlight-container" data-rel="TEXT"><figure class="iseeu highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">┌──────────────────────────────────────────────────────────────────────────────┐</span><br><span class="line">│                                Select Binary                                 │</span><br><span class="line">│                                                                              │</span><br><span class="line">│               The Selected Binary will have its hash Enrolled                │</span><br><span class="line">│            This means it will Subsequently Boot with no prompting            │</span><br><span class="line">│    Remember to make sure it is a genuine binary before Enroling its hash     │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                            ┌─────────────────────┐                           │</span><br><span class="line">│                            │     Enroll Hash     │                           │</span><br><span class="line">│                            │ Reboot to UEFI Menu │                           │</span><br><span class="line">│                            │    Reboot System    │                           │</span><br><span class="line">│                            │        Exit         │                           │</span><br><span class="line">│                            └─────────────────────┘                           │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">└──────────────────────────────────────────────────────────────────────────────┘</span><br></pre></td></tr></table></figure></div><p>使用键盘上的上下按键，切换到 <code>Enroll Hash</code>，回车。<br>此时应该显示为：</p><div class="highlight-container" data-rel="TEXT"><figure class="iseeu highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">┌──────────────────────────────────────────────────────────────────────────────┐</span><br><span class="line">│                                Select Binary                                 │</span><br><span class="line">│                                                                              │</span><br><span class="line">│               The Selected Binary will have its hash Enrolled                │</span><br><span class="line">│            This means it will Subsequently Boot with no prompting            │</span><br><span class="line">│    Remember to make sure it is a genuine binary before Enroling its hash     │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                ┌──────────────┐                              │</span><br><span class="line">│                                │     EFI/     │                              │</span><br><span class="line">│                                │    (More)    │                              │</span><br><span class="line">│                                └──────────────┘                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">└──────────────────────────────────────────────────────────────────────────────┘</span><br></pre></td></tr></table></figure></div><p>选择你要导入的启动项，我们这里要选择导入我们刚刚复制的 <code>loader.efi</code>，使用上下按键和回车来操作确认。<br>如果选择了文件应该会显示：</p><div class="highlight-container" data-rel="TEXT"><figure class="iseeu highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">┌──────────────────────────────────────────────────────────────────────────────┐</span><br><span class="line">│                      Enroll this hash into MOK database?                     │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                         File: \EFI\rEFInd\loader.efi                         │</span><br><span class="line">│     Hash: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX   │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                     ┌─────┐                                  │</span><br><span class="line">│                                     │ No  │                                  │</span><br><span class="line">│                                     │ Yes │                                  │</span><br><span class="line">│                                     └─────┘                                  │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">│                                                                              │</span><br><span class="line">└──────────────────────────────────────────────────────────────────────────────┘</span><br></pre></td></tr></table></figure></div><p>选择 Yes，回车。<br>等待导入完毕后，还要同样的操作导入其他 rEFInd 下引导的可启动项，然后重启电脑，你应该就可以正常进入了。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;准备工作&quot;&gt;&lt;a href=&quot;#准备工作&quot; class=&quot;headerlink&quot; title=&quot;准备工作&quot;&gt;&lt;/a&gt;准备工作&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;下载微软签名的 &lt;code&gt;PreLoader.efi&lt;/code&gt; &lt;code&gt;HashTool.efi&lt;/c</summary>
      
    
    
    
    
    <category term="Windows" scheme="https://blog.amaicat.work/tags/Windows/"/>
    
    <category term="rEFInd" scheme="https://blog.amaicat.work/tags/rEFInd/"/>
    
    <category term="Secure Boot" scheme="https://blog.amaicat.work/tags/Secure-Boot/"/>
    
  </entry>
  
  <entry>
    <title>战地风云 2042 解决“我们注意到您的计算机目前处于离线状态。您需要连接网络以使用EA账户在本机上激活游戏。”提示</title>
    <link href="https://blog.amaicat.work/2025/06/22/zhan-di-feng-yun-2042-jie-jue-wo-men-zhu-yi-dao-nin-de-ji-suan-ji-mu-qian-chu-yu-chi-xian-zhuang-tai-nin-xu-yao-lian-jie-wang-luo-yi-shi-yong-ea-zhang-hu-zai-ben-ji-shang-ji-huo-you-xi-ti-shi/"/>
    <id>https://blog.amaicat.work/2025/06/22/zhan-di-feng-yun-2042-jie-jue-wo-men-zhu-yi-dao-nin-de-ji-suan-ji-mu-qian-chu-yu-chi-xian-zhuang-tai-nin-xu-yao-lian-jie-wang-luo-yi-shi-yong-ea-zhang-hu-zai-ben-ji-shang-ji-huo-you-xi-ti-shi/</id>
    <published>2025-06-22T11:54:16.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<p>折腾了一天的解决方案，搜索引擎搜了半天然后在战地 2042 论坛查了一圈，结合自己尝试总结出来的方案。</p><h2 id="排查网络"><a href="#排查网络" class="headerlink" title="排查网络"></a>排查网络</h2><p>首先你要先确认一下你的设备网络是不是有问题，能不能正常连 EA 服务器，不行开个代理或者加速器。<br>看 EA App 是否在线就行。</p><h2 id="重置系统代理"><a href="#重置系统代理" class="headerlink" title="重置系统代理"></a>重置系统代理</h2><p><code>网络和 Internet</code> -&gt; <code>代理设置</code> 看一下是不是有系统代理，有的话清除一下。</p><h2 id="关掉-VPN-软件"><a href="#关掉-VPN-软件" class="headerlink" title="关掉 VPN 软件"></a>关掉 VPN 软件</h2><p>如果你安装了 VPN 软件，先尝试关掉，能否正常启动。</p><h2 id="关掉杀毒软件"><a href="#关掉杀毒软件" class="headerlink" title="关掉杀毒软件"></a>关掉杀毒软件</h2><p>有的杀毒软件会导致这个问题，关掉尝试能不能启动。</p><h2 id="重置网络适配器"><a href="#重置网络适配器" class="headerlink" title="重置网络适配器"></a>重置网络适配器</h2><p><code>网络和 Internet</code> -&gt; <code>高级网络设置</code> -&gt; <code>网络重置</code> 重置一下网络适配器。</p><h3 id="同时重置各种网络配置服务的方法"><a href="#同时重置各种网络配置服务的方法" class="headerlink" title="同时重置各种网络配置服务的方法"></a>同时重置各种网络配置服务的方法</h3><p>如果重置网络适配器没用，可以试试以管理员权限运行 cmd，然后运行下面的这些命令重置其他网络服务：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">netsh winsock reset</span><br><span class="line">netsh int ip reset</span><br><span class="line">netsh advfirewall reset</span><br><span class="line">netsh winhttp reset proxy</span><br><span class="line">ipconfig /release</span><br><span class="line">ipconfig /flushdns</span><br></pre></td></tr></table></figure></div><p>执行过后需要重启电脑。</p><p>如果上面的方法执行之后游戏连反作弊那个加载屏幕也没弹出来先去把 EA App 卸载了，然后重新安装，如果你和我一样是 Steam 买的卸载后在游戏上右键，<code>属性</code> -&gt; <code>已安装文件</code> 校验游戏文件完整性，然后重新开游戏安装。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;折腾了一天的解决方案，搜索引擎搜了半天然后在战地 2042 论坛查了一圈，结合自己尝试总结出来的方案。&lt;/p&gt;
&lt;h2 id=&quot;排查网络&quot;&gt;&lt;a href=&quot;#排查网络&quot; class=&quot;headerlink&quot; title=&quot;排查网络&quot;&gt;&lt;/a&gt;排查网络&lt;/h2&gt;&lt;p&gt;首先你</summary>
      
    
    
    
    
    <category term="游戏" scheme="https://blog.amaicat.work/tags/%E6%B8%B8%E6%88%8F/"/>
    
    <category term="BF2042" scheme="https://blog.amaicat.work/tags/BF2042/"/>
    
  </entry>
  
  <entry>
    <title>Spring WebSocket 与 Spring Cloud Gateway 同时使用踩坑及修复</title>
    <link href="https://blog.amaicat.work/2025/06/14/spring-websocket-yu-spring-cloud-gateway-tong-shi-shi-yong-cai-keng-ji-xiu-fu/"/>
    <id>https://blog.amaicat.work/2025/06/14/spring-websocket-yu-spring-cloud-gateway-tong-shi-shi-yong-cai-keng-ji-xiu-fu/</id>
    <published>2025-06-14T05:57:47.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<h2 id="未配置协议导致只转发-HTTP"><a href="#未配置协议导致只转发-HTTP" class="headerlink" title="未配置协议导致只转发 HTTP"></a>未配置协议导致只转发 HTTP</h2><p>解决方法是把协议从 <code>lb://</code> 改为 <code>lb:ws(s)://</code></p><div class="highlight-container" data-rel="YAML"><figure class="iseeu highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">server:</span></span><br><span class="line">        <span class="attr">webflux:</span></span><br><span class="line">          <span class="attr">routes:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">api-service</span></span><br><span class="line">              <span class="attr">uri:</span> <span class="string">lb:ws://API</span> <span class="comment"># &lt;-- Here</span></span><br><span class="line">              <span class="attr">predicates:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">Path=/default/**</span></span><br><span class="line">              <span class="attr">filters:</span></span><br><span class="line">                <span class="bullet">-</span> <span class="string">StripPrefix=1</span></span><br></pre></td></tr></table></figure></div><h2 id="class-org-apache-catalina-connector-ResponseFacade-cannot-be-cast-to-class-reactor-netty-http-server-HttpServerResponse-org-apache-catalina-connector-ResponseFacade-and-reactor-netty-http-server-HttpServerResponse-are-in-unnamed-module-of-loader-‘app’"><a href="#class-org-apache-catalina-connector-ResponseFacade-cannot-be-cast-to-class-reactor-netty-http-server-HttpServerResponse-org-apache-catalina-connector-ResponseFacade-and-reactor-netty-http-server-HttpServerResponse-are-in-unnamed-module-of-loader-‘app’" class="headerlink" title="class org.apache.catalina.connector.ResponseFacade cannot be cast to class reactor.netty.http.server.HttpServerResponse (org.apache.catalina.connector.ResponseFacade and reactor.netty.http.server.HttpServerResponse are in unnamed module of loader ‘app’)"></a>class org.apache.catalina.connector.ResponseFacade cannot be cast to class reactor.netty.http.server.HttpServerResponse (org.apache.catalina.connector.ResponseFacade and reactor.netty.http.server.HttpServerResponse are in unnamed module of loader ‘app’)</h2><p>参见 <a class="link"   href="https://github.com/spring-cloud/spring-cloud-gateway/issues/2039" >spring-cloud&#x2F;spring-cloud-gateway#2039 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p><p>依赖冲突，我这里是 <code>spring-boot-starter-web</code> 引入了 Tomcat Embed Core 导致 Gateway 使用 Tomcat 而不是 Netty，解决方案是排除依赖项：</p><div class="highlight-container" data-rel="KTS"><figure class="iseeu highlight kts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">dependencies &#123;</span><br><span class="line">    implementation(rootProject.libs.spring.boot.starter.web) &#123;</span><br><span class="line">        exclude(group = <span class="string">&quot;org.apache.tomcat.embed&quot;</span>, module = <span class="string">&quot;tomcat-embed-core&quot;</span>) <span class="comment">// &lt;-- Here</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><blockquote><p>可以使用命令</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./gradlew &lt;项目&gt;:dependencies --configuration runtimeClasspath &gt; dependencies_runtime.txt</span><br></pre></td></tr></table></figure></div><p>输出运行时依赖关系，查找是哪个依赖引入了 Tomcat Embed Core</p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;未配置协议导致只转发-HTTP&quot;&gt;&lt;a href=&quot;#未配置协议导致只转发-HTTP&quot; class=&quot;headerlink&quot; title=&quot;未配置协议导致只转发 HTTP&quot;&gt;&lt;/a&gt;未配置协议导致只转发 HTTP&lt;/h2&gt;&lt;p&gt;解决方法是把协议从 &lt;code&gt;lb</summary>
      
    
    
    
    
    <category term="Spring Cloud" scheme="https://blog.amaicat.work/tags/Spring-Cloud/"/>
    
  </entry>
  
  <entry>
    <title>有关 LoCyanFrp 未来的发展方向和技术变迁的一点说明</title>
    <link href="https://blog.amaicat.work/2025/03/26/you-guan-locyanfrp-wei-lai-de-fa-zhan-fang-xiang-he-ji-zhu-bian-qian-de-yi-dian-shuo-ming/"/>
    <id>https://blog.amaicat.work/2025/03/26/you-guan-locyanfrp-wei-lai-de-fa-zhan-fang-xiang-he-ji-zhu-bian-qian-de-yi-dian-shuo-ming/</id>
    <published>2025-03-26T09:30:11.000Z</published>
    <updated>2026-07-15T16:23:36.622Z</updated>
    
    <content type="html"><![CDATA[<h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>我是 LoCyanFrp 的现任站长，夏沫花火zzz🌙。<br>过去的两年间，LoCyanFrp 完成了大量的升级，正式发布了第二版，并得到了广大领域用户的青睐。</p><p>我们一直牢记我们的初衷，秉承着一颗做公益的心，维护着 LoCyanFrp。三年间，LoCyanFrp 一直保持着全公益的运营模式。<br>在这片文章里，我想谈谈我对 LoCyanFrp 接下来的规划，以及进行一部分答疑。</p><h2 id="现状"><a href="#现状" class="headerlink" title="现状"></a>现状</h2><p>LoCyanFrp 从 2022 年 4 月起，一直运营至今。如你所见的，我们一直是全公益的运营模式。<br>尽管期间我们遇到了一些难点，但是我们没有放弃，没有选择跑路，也没有选择改变为商业运营模式。</p><p>迄今为止，我们已经成为业内第四大的 Frp 内网穿透服务（按服务用户量计数）。我们拥有将近 30k 的用户，用户创建过 104k 以上的隧道，每个月传输 TB 级别的数据，与官网宣传的保守统计不同，我们实经传输数据量可能超过 100 TB。<br>在三年来，我们为用户提供了尽可能稳定，低成本的流量穿透服务。</p><h2 id="稳定的背后"><a href="#稳定的背后" class="headerlink" title="稳定的背后"></a>稳定的背后</h2><p>海量的数据传输，意味着对服务的可靠性的依赖。我们拥有着上万的用户，我们是如何保障我们的服务的呢？请听我道来。</p><p>首先，我们基于 Frp，由于 Go 语言有着在 IO 上的一些优势，使得我们的服务能够拥有优异的包转发性能，能够为用户带来高效的流量穿透。当然，也有其他语言在网络传输上具备先天优势，不过我们最开始是基于现成方案制作的，所以一直沿用至今。<br>其次，我们通过使用 Spring 框架自研后端，借助 JVM 和 Spring 的性能和调度优势，我们的后端每天处理超过 600k 的请求量，也丝毫不显逊色。<br>通过结合两者，我们实现了一套高效的系统，为用户提供更好的体验。</p><p>然而，光有性能是不够的。</p><p>或许用过同类产品的用户可能遇到过这种尴尬情况：由于主控服务器挂了或者维护，导致节点服务无法获取数据，从而无法正常使用服务或启动节点服务器。<br>我们的节点服务则不同，在设计上便可离线运行，即使主控服务器离线，也能维护现有状态运转或启动。通过这样的设计，即使我们对主控服务器进行维护，也不会影响节点端的运作。</p><p>另外的，为了保障我们的服务不受渗透攻击、拒绝服务攻击（DDoS）、泛洪攻击的影响，我们对全部业务采用容器化部署方式，且具备完善的 WAF 规则，可拦截大部分恶意流量，并且我们使用了 高防服务器 + 安全加速 的组合，有效防护 DDoS 和 CC 等常见攻击手段，并实现了全球的高速访问。我们在后端上也做了严格的权限控制，并在近年接入了人机验证、行为检测等技术，且实现了 OAuth 2.0 以精细化对权限的控制并进一步控制 API 访问，有效保护用户的账户数据。</p><p>感谢这些服务商，它们为我们的服务提供了高速稳定的服务（不分先后）：</p><ul><li>阿里云</li><li>括彩智能 CDN</li><li>木韩网络</li><li>火山引擎</li><li>百度智能云</li><li>Cloudflare</li><li>湖南裕米云数据科技有限公司</li><li>武汉新软科技有限公司</li></ul><p>感谢这些产品为我们提供了高效的服务器管理和解决方案：</p><ul><li>1Panel</li><li>JumpServer</li></ul><h2 id="LoCyanFrp，还会有下一代吗"><a href="#LoCyanFrp，还会有下一代吗" class="headerlink" title="LoCyanFrp，还会有下一代吗"></a>LoCyanFrp，还会有下一代吗</h2><p>LoCyanFrp 目前看来是一个很完善的平台，它拥有自研的前后端面板和节点控制程序，并具备强大的服务能力。<br>但事情并不会这么简单，我们还有很多没完成的事情要做。在不久的将来，我们会一一实现我们的 TODO，真正做一个用户友好的、功能健全的穿透平台。所以，先不要着急，在下一步我们并不打算推出 LoCyanFrp 3，因为这是极其不负责任的——我们还有很多的事情要做，还有很多能够做的更好的地方，既然如此，又为何着急心切推出一个全新的大版本？</p><p>或许 LoCyanFrp 会有下一代，但不是现在，也不是不久后。</p><h2 id="关于技术栈的选择"><a href="#关于技术栈的选择" class="headerlink" title="关于技术栈的选择"></a>关于技术栈的选择</h2><p>或许有一些开发者会好奇，为什么我们会选择 Spring，而不是 Gin，明明 Frp 本身就是 Go 写的，同样的技术栈不是更好维护吗？<br>事情并没有看起来这么简单。</p><p>首先我们先来谈谈，为什么选择了 Spring。</p><p>如你所见，Spring 是一个老牌的框架，你别看它老，正因为老，经过了无数使用者的考验，我们才选择了 Spring。我可以直接举一个例子：淘宝。淘宝的后端最初是 PHP 写的，但最后还是转向了 Spring。与 PHP 比，Spring 具备更完善的 REST API 实现，更高效的处理方式和更完善的生态链。不只是淘宝，阿里系的大部分产品都使用了 Spring。</p><p>另外的，Spring 具备有一套完整的分层，如控制层、服务层等，在每一层开发无需关心其他层的实现，这是选择 Spring 的理由之一。<br>以及，Java 在学习难度和上手难度上，对新手是比较友好的，无需很深入的理解，就能够写出一套完整的服务。我们的原站长刚开始编写第二代 LCF 后端时并不会 Java，他也能写的有模有样的。</p><p>Spring AOP 为我们提供了一个相对于中间件更强大的剖面系统，可以让我们根据需求打造不同的功能。</p><p>基于如上还有很多其他考量，我们选择了 Spring 而不是其他技术栈。</p><p>接下来，让我们谈谈其他技术栈。</p><h3 id="为什么不是-Go-的-Gin？"><a href="#为什么不是-Go-的-Gin？" class="headerlink" title="为什么不是 Go 的 Gin？"></a>为什么不是 Go 的 Gin？</h3><p>Gin 固然是一个优秀的框架，但经过考量我们最终没有选择 Gin。</p><p>首先，Go 与大多数语言不同，它的错误处理有些独特。对于习惯了 <code>try...catch</code> 的我来说，转换到 Go 语言的错误处理思路非常不友好。以及 Go 脆弱的稳定性：我只是不小心写错了非常小的一个逻辑，你却让我的服务整个“panic”，造成整个程序的崩溃，进而导致整个服务体系崩溃，这很明显有违我们保障服务稳定性的初衷。尽管 Gin 提供了统一的错误处理机制，但你如何保证其他部分一定不会 panic？<br>其次的，我们开发组里面对 Go 的了解程度并不深。老实说，我以前完全没有接触过 Go，对语法一概不知，也没有任何实操经验。而我做过一些 Java &#x2F; Kotlin 的开发，对于选择一个毫无把握的语言和框架作为服务基础，我是做不到的。当然我们的友商也有在使用 Go + Gin 的方案，不是说不好，而是不适合我们。</p><p>以及，我真的很不喜欢 Go 的 public 和 private 机制和命名法。</p><h3 id="那，其他的呢"><a href="#那，其他的呢" class="headerlink" title="那，其他的呢"></a>那，其他的呢</h3><p>有人和我们提过其他语言，最多的当属 Rust 了吧。</p><p>我倒要好好说一说为什么不使用 Rust。</p><p>Rust 凭借自身的优势和各种其他因素，似乎受到很多开发者的追捧。<br>但我并不喜欢这门语言。我没有写过 C&#x2F;C++ 这类较为低级的语言，主要还是写一些中级和高级语言，Rust 的语法对我来说非常不友好。<br>另外的，Rust 自开发组一直到社区的高傲的态度，实在无法令我接受。或许 Rust 是一门好的语言，抑或是高效的语言，但我无法认同它——我遇到过不少的开发者，无脑的吹捧 Rust，并一踩一捧的贬低其他语言，或是故意引战。<br>况且，Rust 给我的感觉，并不是一门稳定或者具备有企业级能力的语言，至少现在不是。如果你直接和我提起 Rust，我想不到一个完善的 Web 框架的名字，但 Java 和 Go 我起码能想到一个或两个。哪怕是 Node.js，我也能想到 Express 亦或是 Koa 这些框架。基于这个原因，Rust 成功的被 pass 掉了。<br>我们可能会用 Rust 做启动器，但不会用，至少现在不不会它来做后端。</p><p>上面提到了 Node.js，如果你问我为什么不用，那我会和你说，我们有部分开发成员代码习惯并不好，写 JS 的话后续因为动态类型绝对会炸。什么？你和我说 TypeScript？如果你很喜欢做类型体操，那我也不反对，但是我不想要在我的代码里包含如此多的毫无意义的类型定义。如果你不使用类型检查器，那 TS 的类型功能也完全是个摆设。如果你和我说那 Java 不也要声明类型，那我会和你说：拜托，请你自己去写一下 Java 和 TypeScript，你就知道 TS 的类型系统有多令人恼火了。</p><p>关于语言和框架的讨论到此为止，点到即可，我也不想引战，只是单纯发表我的观点。</p><h2 id="未来的一些规划"><a href="#未来的一些规划" class="headerlink" title="未来的一些规划"></a>未来的一些规划</h2><p>在未来，我们会逐步实现这些功能：</p><ul><li>WebAuthn 无密码登录</li><li>违规使用审计与计费</li><li>节点详细统计数据界面</li><li>捐赠节点可视数据面板</li><li>定制节点管理面板</li><li>Eda 功能的增强</li></ul><p>是的，我们打算对违规使用进行计费，不按要求使用，我们为什么一定要给你免费提供服务呢？<br>可能还会有更多功能，敬请期待。</p><p>马上就是 LoCyanFrp 的生日了，基于各种因素，我写下了这篇博文。这些看法也不一定全对，欢迎你在评论区评论，纠错或提供建议。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;引言&quot;&gt;&lt;a href=&quot;#引言&quot; class=&quot;headerlink&quot; title=&quot;引言&quot;&gt;&lt;/a&gt;引言&lt;/h2&gt;&lt;p&gt;我是 LoCyanFrp 的现任站长，夏沫花火zzz🌙。&lt;br&gt;过去的两年间，LoCyanFrp 完成了大量的升级，正式发布了第二版，并得</summary>
      
    
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/categories/LoCyanFrp/"/>
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/tags/LoCyanFrp/"/>
    
  </entry>
  
  <entry>
    <title>ADB 修改参数修复网络正常但 Android 设备提示网络连接受限问题</title>
    <link href="https://blog.amaicat.work/2025/02/10/adb-xiu-gai-can-shu-xiu-fu-wang-luo-zheng-chang-dan-android-she-bei-ti-shi-wang-luo-lian-jie-shou-xian-wen-ti/"/>
    <id>https://blog.amaicat.work/2025/02/10/adb-xiu-gai-can-shu-xiu-fu-wang-luo-zheng-chang-dan-android-she-bei-ti-shi-wang-luo-lian-jie-shou-xian-wen-ti/</id>
    <published>2025-02-10T09:08:44.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<p>最近我的 Pixel 在连接国内网络的时候会出现这个问题，大概率是三网又把测试服务器地址 ban 了，以下是解决方案。</p><h2 id="获取-ADB"><a href="#获取-ADB" class="headerlink" title="获取 ADB"></a>获取 ADB</h2><p>首先需要获取 ADB，可以参考 AOSP 的文档下载配置</p><p><a class="link"   href="https://source.android.google.cn/docs/setup/build/adb?hl=zh-cn" >https://source.android.google.cn/docs/setup/build/adb?hl=zh-cn <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p><h2 id="修改测试服务器地址"><a href="#修改测试服务器地址" class="headerlink" title="修改测试服务器地址"></a>修改测试服务器地址</h2><p>首先删除原来的</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">adb shell settings delete global captive_portal_https_url</span><br><span class="line">adb shell settings delete global captive_portal_http_url</span><br></pre></td></tr></table></figure></div><p>然后重新添加</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">adb shell settings put global captive_portal_https_url https://g.cn/generate_204</span><br><span class="line">adb shell settings put global captive_portal_http_url http://g.cn/generate_204</span><br></pre></td></tr></table></figure></div><blockquote><p>如果 Google 中国的服务器你也无法访问，可以尝试其他厂商的地址:</p><ul><li>connectivitycheck.platform.hicloud.com&#x2F;generate_204</li><li>connect.rom.miui.com&#x2F;generate_204</li><li>wifi.vivo.com.cn&#x2F;generate_204</li></ul><p>或者你也可以自建一个，只要地址返回 204 No Content 即可。</p></blockquote><p>修改完需要重新联网一下，不行就重启一下手机。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;最近我的 Pixel 在连接国内网络的时候会出现这个问题，大概率是三网又把测试服务器地址 ban 了，以下是解决方案。&lt;/p&gt;
&lt;h2 id=&quot;获取-ADB&quot;&gt;&lt;a href=&quot;#获取-ADB&quot; class=&quot;headerlink&quot; title=&quot;获取 ADB&quot;&gt;&lt;/a&gt;获</summary>
      
    
    
    
    
    <category term="Android" scheme="https://blog.amaicat.work/tags/Android/"/>
    
  </entry>
  
  <entry>
    <title>我与 LoCyanFrp -（二）重构与升级</title>
    <link href="https://blog.amaicat.work/2024/12/04/wo-yu-locyanfrp-er-chong-gou-yu-sheng-ji/"/>
    <id>https://blog.amaicat.work/2024/12/04/wo-yu-locyanfrp-er-chong-gou-yu-sheng-ji/</id>
    <published>2024-12-03T21:16:48.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<p>本文主要从我自己的视角谈一谈 LoCyanFrp 的重构和技术相关变化。</p><h2 id="早期技术"><a href="#早期技术" class="headerlink" title="早期技术"></a>早期技术</h2><h3 id="SakuraPanel"><a href="#SakuraPanel" class="headerlink" title="SakuraPanel"></a>SakuraPanel</h3><p>最开始的时候，LoCyanFrp 使用的是 <a class="link"   href="https://github.com/ZeroDream-CN/SakuraPanel" >SakuraPanel <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a><br>这一个没什么特别好提的，大多数内网穿透除去自研方案基本都是 SakuraPanel 起手</p><h4 id="我对于-SakuraPanel-的些许看法"><a href="#我对于-SakuraPanel-的些许看法" class="headerlink" title="我对于 SakuraPanel 的些许看法"></a>我对于 SakuraPanel 的些许看法</h4><p>SakuraPanel 本身实现了一套齐全的公共 Frp 方案，但是在实际接触之后，我认为改进空间很大。<br>主要有以下这些我不是很满意的：</p><ul><li>前后端不分离，代码混在一起</li><li>数据库表格混乱，包括数据列命名并不是很规范，以及数据类型混乱，隧道远程端口居然是 varchar 类型，有用户 ID，但是却用用户名查找用户等等…</li><li>二改并不好实现平滑的前端页面切换效果，不够现代化</li><li>UI 风格略显老旧</li><li>代码并不是很好，许多回调地狱和 if 嵌套，可读性不佳</li><li>虽然 PHP 并不慢，但是我不喜欢这种前后端写在一起的，不好区分职能</li></ul><h3 id="前端升级"><a href="#前端升级" class="headerlink" title="前端升级"></a>前端升级</h3><p>我们的前端先行一步进行了升级，不过这个阶段后端还是围绕 SakuraPanel 原本去实现的。<br>我们前端改用 Vue 3 + NaiveUI，初步实现前后端分离，这个阶段后端使用的是 ThinkPHP 框架。<br>整体布局是 @Daiyangcheng 写的，当时我还没有正式成为乐青团队的一员，不过给前端布局提供了一些设计思路。</p><blockquote><p>PS: @Daiyangcheng 主要是写后端的，但是因为那会我们的前端都没有空，结果当时他从 0 开始手搓 Vue 3 写的，CSS 啥的都不会，有一些布局怪难看的，我就吐槽了一下，顺便给了点思路和样式。<br>如果你细心的话，你甚至可以发现我们前端里面有各种吐槽的注释（</p></blockquote><p>那会其实还有和莱云合作，不过后面估计因为各种事情不了了之了，由于那会我还不是团队成员，具体的我也不清楚。</p><h4 id="一点个人吐槽：你这前端保熟吗？？！"><a href="#一点个人吐槽：你这前端保熟吗？？！" class="headerlink" title="一点个人吐槽：你这前端保熟吗？？！"></a>一点个人吐槽：你这前端保熟吗？？！</h4><p>新面板确实挺简洁现代化的，但是它的代码可不一定了——一个原本写后端的从 0 起手写的，要写好确实挺有难度（<br>由于我的强迫症，那会面板有好多细节让我觉得超级不满意，太难受了，干脆之间 fork 改。<br>不改还好吧，一改人差点傻了，第一次见三种变量命名法混一起的，还有各种奇葩嵌套，看完高血压那种（<br>没办法，看着真不爽，只能硬着头皮改了（反正我是为了自己看的爽一定要改，当时完全没想到别的用户体验xd）<br>一改就是整个面板重构，改完之后整个面板终于算是基本符合自己的感觉了</p><h3 id="后端技术的演变"><a href="#后端技术的演变" class="headerlink" title="后端技术的演变"></a>后端技术的演变</h3><h4 id="更换新框架…"><a href="#更换新框架…" class="headerlink" title="更换新框架…"></a>更换新框架…</h4><p>改完新面板不久后，@Daiyangcheng 开始写新的后端了。<br>新后端和旧的不同，直接抛弃了一直在用的 PHP，改为 Spring 框架。<br>早期的 v2 API 其实代码也不怎么好，因为 @Daiyangcheng 那会根本不会 Java，也是从 0 起手的。</p><p>在这之后一段时间我一直都在修改前端，现在你看到的整个面板基本上都被我改过，毕竟重构了这也不算夸张的（不过是基于原来代码，直接写新的我这种特别 lazy 的人是绝对不会做的）</p><h4 id="一个写前端的孩纸突然又开始捡起后端了，变成了赛博全栈！？"><a href="#一个写前端的孩纸突然又开始捡起后端了，变成了赛博全栈！？" class="headerlink" title="一个写前端的孩纸突然又开始捡起后端了，变成了赛博全栈！？"></a>一个写前端的孩纸突然又开始捡起后端了，变成了赛博全栈！？</h4><p>在改前端和写启动器的那段时间，我一直在吐槽 API 难用（<br>我一直在催 @Daiyangcheng 优化，但是他真的太忙了，基本上没改过啥。<br>但是你这接口我看了强迫症啊，刚好我涉猎过 Java 和 Kotlin，于是干脆自己动手改了。<br>这一改又是重构，原来的代码看的令人红温（</p><p><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2024/12/04/674fee45aacaf.webp" alt="红温了xd"></p><p>于是我又把每个接口的代码从参数传入到鉴权全部重写了一遍，改的那叫一个头大，顺便实现了几个一直没有的接口。<br>此外 API 文档和 Minecraft 联机功能也是我写的，约等于一个人把前后端全改完了，还写了份文档（byd 累死了</p><h4 id="即将到来的下一版本-API"><a href="#即将到来的下一版本-API" class="headerlink" title="即将到来的下一版本 API"></a>即将到来的下一版本 API</h4><p>其实改完后我还是有很多不满意的的地方，不过后面那段时间看基本没啥问题，跑去打游戏了，一直懒得改。<br>后面我的 BF 去上学了，无聊也没啥可以玩的，又回来改代码了（悲<br>这次也有很多大改动，还算理想的实现了很多原来设想的东西，包括:</p><ul><li>添加 Turnstile 人机验证</li><li>向外部应用提供 OAuth2.0 授权</li><li>修复了一些漏洞</li><li>将原有的 用户名 作为唯一标识改为 用户ID 作为唯一标识，API 全部改用 用户ID 进行操作</li><li>同时为面板实现了全部遗留 v1 接口，完全升级到 v2 API</li><li>一些技术上和代码逻辑的优化</li></ul><p>还有一些提上日程但是还没来得及实现的，这些也会在后续实现:</p><ul><li>WebAuthn 无密码登录</li><li>违规使用审计与计费</li><li>节点详细统计数据界面</li></ul><p>这期间也要感谢一些提供了建议的朋友，这里就不列举了。</p><h2 id="关于未来…"><a href="#关于未来…" class="headerlink" title="关于未来…"></a>关于未来…</h2><p>其实 Frp 这种方案在将来将会被淘汰，因为那会估计大家都普及了 IPv6 公网了，现在我一个四五线城市的都已经有 IPv6 公网了，IPv6 互联是迟早的事情。<br>我们也推荐我们的用户通过 IPv6 公网的方案获得更好的连接质量。<br>我还没有设想更多未来的事情，现在只是想做好当下的事情，为用户提供更好的内网穿透解决方案，仅此而已。<br>我们本身也不赚钱，甚至每个月都要贴钱进去，但是初心是不会改变的，我们会一直坚持公益服务下去。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本文主要从我自己的视角谈一谈 LoCyanFrp 的重构和技术相关变化。&lt;/p&gt;
&lt;h2 id=&quot;早期技术&quot;&gt;&lt;a href=&quot;#早期技术&quot; class=&quot;headerlink&quot; title=&quot;早期技术&quot;&gt;&lt;/a&gt;早期技术&lt;/h2&gt;&lt;h3 id=&quot;SakuraPanel&quot;&gt;</summary>
      
    
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/categories/LoCyanFrp/"/>
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/tags/LoCyanFrp/"/>
    
    <category term="杂谈" scheme="https://blog.amaicat.work/tags/%E6%9D%82%E8%B0%88/"/>
    
  </entry>
  
  <entry>
    <title>Spring AOP 实现为添加指定注解接口方法进行前置鉴权</title>
    <link href="https://blog.amaicat.work/2024/12/04/spring-aop-shi-xian-wei-tian-jia-zhi-ding-zhu-jie-jie-kou-jin-xing-qian-zhi-jian-quan/"/>
    <id>https://blog.amaicat.work/2024/12/04/spring-aop-shi-xian-wei-tian-jia-zhi-ding-zhu-jie-jie-kou-jin-xing-qian-zhi-jian-quan/</id>
    <published>2024-12-03T20:27:41.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<h2 id="需求概述"><a href="#需求概述" class="headerlink" title="需求概述"></a>需求概述</h2><p>我们现在需要添加一个注解，实现 Controller 下接口方法包含此注解时，前置鉴权条件，满足条件才执行接口逻辑</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><ol><li>新建一个注解，如 <code>@NeedAuthentication</code></li><li>添加一个 AspectJ 逻辑，指定 Spring AOP 切面注入方法</li><li>新建自定义异常，当验证不通过时抛出一个异常来终止执行</li><li>添加一个全局异常处理用于处理自定异常类型，返回未授权</li></ol><h2 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h2><p>直接上代码:</p><h3 id="NeedAuthentication-java"><a href="#NeedAuthentication-java" class="headerlink" title="NeedAuthentication.java"></a>NeedAuthentication.java</h3><div class="highlight-container" data-rel="JAVA"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> moe.muska.ami.demo.annotation;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.lang.annotation.*;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 声明注解所需的内容</span></span><br><span class="line"><span class="meta">@Target(ElementType.METHOD)</span></span><br><span class="line"><span class="meta">@Retention(RetentionPolicy.RUNTIME)</span></span><br><span class="line"><span class="keyword">public</span> <span class="meta">@interface</span> NeedAuthentication &#123;</span><br><span class="line">    <span class="comment">// 可以根据需要添加参数，并在之后的逻辑通过 reflect 获取使用</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><h3 id="AuthenticationAspect-java"><a href="#AuthenticationAspect-java" class="headerlink" title="AuthenticationAspect.java"></a>AuthenticationAspect.java</h3><div class="highlight-container" data-rel="JAVA"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> moe.muska.ami.demo.aspect;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> moe.muska.ami.demo.exception.UnauthorizedException;</span><br><span class="line"><span class="keyword">import</span> jakarta.annotation.Resource;</span><br><span class="line"><span class="keyword">import</span> jakarta.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.Aspect;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.Before;</span><br><span class="line"><span class="keyword">import</span> org.aspectj.lang.annotation.Pointcut;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.context.request.RequestContextHolder;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.context.request.ServletRequestAttributes;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Aspect</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthenticationAspect</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 设置 AOP 切面</span></span><br><span class="line">    <span class="comment">// @annotation 代表注解</span></span><br><span class="line">    <span class="meta">@Pointcut(&quot;@annotation(moe.muska.ami.demo.annotation.NeedAuthentication)&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">needAuthenticationMethods</span><span class="params">()</span> &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 定义前置逻辑</span></span><br><span class="line">    <span class="meta">@Before(&quot;needAuthenticationMethods()&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doAuth</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 获取请求</span></span><br><span class="line">        <span class="type">ServletRequestAttributes</span> <span class="variable">attributes</span> <span class="operator">=</span> (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();</span><br><span class="line">        <span class="keyword">assert</span> attributes != <span class="literal">null</span>;</span><br><span class="line">        <span class="type">HttpServletRequest</span> <span class="variable">request</span> <span class="operator">=</span> attributes.getRequest();</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 主鉴权逻辑</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 请求参数</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">requestUserId</span> <span class="operator">=</span> request.getParameter(<span class="string">&quot;user_id&quot;</span>);</span><br><span class="line">        <span class="type">String</span> <span class="variable">bearerToken</span> <span class="operator">=</span> request.getHeader(<span class="string">&quot;Authorization&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (requestUserId == <span class="literal">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnauthorizedException</span>(<span class="literal">null</span>);</span><br><span class="line">        <span class="keyword">if</span> (bearerToken == <span class="literal">null</span>) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnauthorizedException</span>(<span class="literal">null</span>);</span><br><span class="line">        <span class="type">long</span> userId;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            userId = Long.parseLong(requestUserId);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (NumberFormatException e) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnauthorizedException</span>(<span class="string">&quot;Authentication data type mismatch.&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 示例判断是否授权</span></span><br><span class="line">        <span class="keyword">if</span> (!authorize(userId, bearerToken)) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnauthorizedException</span>(<span class="literal">null</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 校验权限</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">authorize</span><span class="params">(<span class="type">long</span> userId, String bearerToken)</span> &#123;</span><br><span class="line">        <span class="comment">// Demo 就不写具体逻辑了，可以自己改为 false 查看授权失败是否返回正常</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></div><h3 id="UnauthorizedException-java"><a href="#UnauthorizedException-java" class="headerlink" title="UnauthorizedException.java"></a>UnauthorizedException.java</h3><div class="highlight-container" data-rel="JAVA"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> moe.muska.ami.demo.exception;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建一个自定义异常</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UnauthorizedException</span> <span class="keyword">extends</span> <span class="title class_">RuntimeException</span> &#123;</span><br><span class="line">    <span class="comment">// 如果你不需要返回消息，可以去除 super 字段的逻辑</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">UnauthorizedException</span><span class="params">(String message)</span> &#123;</span><br><span class="line">        <span class="built_in">super</span>(message);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><h3 id="AspectExceptionHandler-java"><a href="#AspectExceptionHandler-java" class="headerlink" title="AspectExceptionHandler.java"></a>AspectExceptionHandler.java</h3><div class="highlight-container" data-rel="JAVA"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> moe.muska.ami.demo.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> moe.muska.ami.demo.exception.UnauthorizedException;</span><br><span class="line"><span class="keyword">import</span> org.springframework.http.ResponseEntity;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ExceptionHandler;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestControllerAdvice;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 自定义异常处理</span></span><br><span class="line"><span class="meta">@RestControllerAdvice</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AspectExceptionHandler</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 设置异常类型为自定义异常类型</span></span><br><span class="line">    <span class="meta">@ExceptionHandler(UnauthorizedException.class)</span></span><br><span class="line">    <span class="keyword">public</span> ResponseEntity&lt;Map&lt;String, Object&gt;&gt; <span class="title function_">onHttpRequestMethodNotSupportedException</span><span class="params">(UnauthorizedException ex)</span> &#123;</span><br><span class="line">        <span class="comment">// 根据实际需求返回对应类型数据</span></span><br><span class="line">        <span class="comment">// 以下只是例子，请结合实际应用</span></span><br><span class="line">        <span class="keyword">return</span> builder.unauthorized();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><h3 id="Application-java"><a href="#Application-java" class="headerlink" title="Application.java"></a>Application.java</h3><div class="highlight-container" data-rel="JAVA"><figure class="iseeu highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> moe.muska.ami.demo;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.EnableAspectJAutoProxy;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 开启 AspectJ 自动代理</span></span><br><span class="line"><span class="meta">@EnableAspectJAutoProxy</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Application</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">        SpringApplication.run(Application.class, args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><p>都写在注释里了，可以自己研究一下</p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;需求概述&quot;&gt;&lt;a href=&quot;#需求概述&quot; class=&quot;headerlink&quot; title=&quot;需求概述&quot;&gt;&lt;/a&gt;需求概述&lt;/h2&gt;&lt;p&gt;我们现在需要添加一个注解，实现 Controller 下接口方法包含此注解时，前置鉴权条件，满足条件才执行接口逻辑&lt;/p&gt;
</summary>
      
    
    
    
    
    <category term="教程" scheme="https://blog.amaicat.work/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Spring Boot" scheme="https://blog.amaicat.work/tags/Spring-Boot/"/>
    
    <category term="Spring AOP" scheme="https://blog.amaicat.work/tags/Spring-AOP/"/>
    
  </entry>
  
  <entry>
    <title>Docker 禁止将容器端口映射到公网</title>
    <link href="https://blog.amaicat.work/2024/10/10/docker-jin-zhi-jiang-rong-qi-duan-kou-ying-she-dao-gong-wang/"/>
    <id>https://blog.amaicat.work/2024/10/10/docker-jin-zhi-jiang-rong-qi-duan-kou-ying-she-dao-gong-wang/</id>
    <published>2024-10-10T12:30:18.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<p>Docker 会直接绕过 ufw 之类的防火墙软件，将服务发布到公网，存在一定安全隐患，所以折腾了一下研究了几个办法阻止 Docker 把端口映射到公网上</p><h2 id="ufw-docker"><a href="#ufw-docker" class="headerlink" title="ufw-docker"></a>ufw-docker</h2><p><a class="link"   href="https://github.com/chaifeng/ufw-docker" >https://github.com/chaifeng/ufw-docker <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p><p>一键安装:</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">sudo wget -O /usr/local/bin/ufw-docker \</span><br><span class="line">  https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker</span><br><span class="line"><span class="built_in">chmod</span> +x /usr/local/bin/ufw-docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 写入 ufw 规则</span></span><br><span class="line">ufw-docker install</span><br></pre></td></tr></table></figure></div><p>开放端口:</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ufw-docker allow &lt;容器名&gt; &lt;容器内端口&gt;</span><br></pre></td></tr></table></figure></div><p>其他操作参考 README</p><h3 id="已知的一些缺点"><a href="#已知的一些缺点" class="headerlink" title="已知的一些缺点"></a>已知的一些缺点</h3><ul><li>不能指定外部端口映射，只能映射到同一个端口上</li><li>貌似没法开放 UDP 端口？(至少它把我邮件服务器干了)</li></ul><h2 id="绑定到指定-IP"><a href="#绑定到指定-IP" class="headerlink" title="绑定到指定 IP"></a>绑定到指定 IP</h2><p>将容器开放端口绑定到指定 IP 上，其他 IP 无法访问<br>要禁止外部网络访问，直接绑定到 <code>127.0.0.1</code> 或者其他代表本地的 IP，外网就无法访问了</p><h3 id="Docker-Compose"><a href="#Docker-Compose" class="headerlink" title="Docker Compose"></a>Docker Compose</h3><div class="highlight-container" data-rel="YAML"><figure class="iseeu highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">    <span class="attr">exmaple:</span></span><br><span class="line">        <span class="comment"># ...</span></span><br><span class="line">        <span class="attr">ports:</span></span><br><span class="line">            <span class="bullet">-</span> <span class="number">127.0</span><span class="number">.0</span><span class="number">.1</span><span class="string">:8080:80</span></span><br><span class="line">            <span class="comment"># - &lt;本地IP&gt;:&lt;本地端口&gt;:容器内端口</span></span><br><span class="line">        <span class="comment"># ...</span></span><br></pre></td></tr></table></figure></div><h3 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h3><p>启动的时候带上 <code>--ip=127.0.0.1</code> 参数即可<br>也可以修改 <code>daemon.json</code> 使默认 <code>bridge</code> 网络无法外网访问：</p><div class="highlight-container" data-rel="JSON"><figure class="iseeu highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="comment">// 要绑定的 IP</span></span><br><span class="line">    <span class="attr">&quot;ip&quot;</span><span class="punctuation">:</span> <span class="string">&quot;127.0.0.1&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure></div>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Docker 会直接绕过 ufw 之类的防火墙软件，将服务发布到公网，存在一定安全隐患，所以折腾了一下研究了几个办法阻止 Docker 把端口映射到公网上&lt;/p&gt;
&lt;h2 id=&quot;ufw-docker&quot;&gt;&lt;a href=&quot;#ufw-docker&quot; class=&quot;header</summary>
      
    
    
    
    
    <category term="Docker" scheme="https://blog.amaicat.work/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>我与 LoCyanFrp -（一）初识与深入</title>
    <link href="https://blog.amaicat.work/2024/10/05/wo-yu-locyanfrp-yi-chu-shi-yu-shen-ru/"/>
    <id>https://blog.amaicat.work/2024/10/05/wo-yu-locyanfrp-yi-chu-shi-yu-shen-ru/</id>
    <published>2024-10-05T00:38:24.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<p>LoCyanFrp 目前是我为现任站长的一个项目，这篇文章主要是想简单聊一聊，我与 LoCyanFrp，和其他友商的一些经历。</p><blockquote><p>LoCyanFrp 简写 LCF</p></blockquote><h2 id="关于这个项目"><a href="#关于这个项目" class="headerlink" title="关于这个项目"></a>关于这个项目</h2><h3 id="相识"><a href="#相识" class="headerlink" title="相识"></a>相识</h3><p>这个项目并不是我发起的。<br>2022年，我生日当天，刚好正在寻找一个免费的 Frp 服务。像往常一般，我在搜索引擎简单搜索了一下，找到了这家 Frp 内网穿透服务。却曾想，这成为了我接下来几年里的转折点。</p><h3 id="前世"><a href="#前世" class="headerlink" title="前世"></a>前世</h3><p>早期 LoCyanFrp 由站长 Daiyangcheng 以及另外两位成员 DXCFTDE、Zhiyuan36 共同维护。记得那时候还在用 Freenom 的免费域名，这个域名目前我还记得，是 <code>freenat.gq</code> 。不过这个域名现在已经被回收了，并不属于 LoCyanFrp 。<br>当时完全是使用的 SakuraPanel 以及 Daiyangcheng 手搓 ThinkPHP 框架造的后端，虽然能用，但是因为数据库问题出过一些事故（<del>吐槽一下 PHP 还没关 DEBUG 输出，官网上面两行大大的连不上数据库难绷</del>）。客户端也非常简陋，甚至没有图形化界面（就是 PyLauncher）<br>包括后来的实名，最开始是人工审核，后面换成了 BOT，现在还保留着这个功能，不过实际意义不大了<br>这期间我也是成功和站长和管理成员混熟了<del>成功混入</del></p><h4 id="一个小插曲"><a href="#一个小插曲" class="headerlink" title="一个小插曲"></a>一个小插曲</h4><p>刚好那天是我生日，于是我进官方群那会看到群里的人都在 @Daiyangcheng 要管理，我<del>凑热闹</del>结果他因为刚好当天是我生日送了我一天管理体验卡<del>结果后面因为比较活跃一直都是管理了</del></p><h2 id="从陌生到相识"><a href="#从陌生到相识" class="headerlink" title="从陌生到相识"></a>从陌生到相识</h2><p>从最开始的局外人，到成为团队的一员，总归来说是社区贡献。</p><h3 id="LCF-首页"><a href="#LCF-首页" class="headerlink" title="LCF 首页"></a>LCF 首页</h3><p>当时 ZDX(DXCFTDE) 写了个新的起始页，用的 MDUI 1<br>写出来有很多奇怪的地方，于是 DYC 就叫 ZDX 来问我改<del>byd为什么是我</del>，然后我看太炸裂了干脆直接帮他们改了<del>tmd我还改了</del></p><h3 id="LoCyanFrpPanel"><a href="#LoCyanFrpPanel" class="headerlink" title="LoCyanFrpPanel"></a>LoCyanFrpPanel</h3><p>当时初三，但是成就优异，并不是很担心学业，刚好设计了一套系统，本来打算实现的，不过后面弃坑了<br>结果技术全部用到了 LoCyanFrpPanel 上 xd</p><h4 id="关于一本书（题外）"><a href="#关于一本书（题外）" class="headerlink" title="关于一本书（题外）"></a>关于一本书（题外）</h4><blockquote><p>我没有恰广告，而是阐述我的观点</p></blockquote><p>书名叫《Vue.js 设计与实现》。<br>这本书非常详细的解释了 Vue 3 的设计及实现，这也是我学习 Vue 3 的起点。<br>在这之前，我一直都在写原生的 HTML5&#x2F;CSS3&#x2F;JS，当时看到很多网站都在使用框架，于是决定入门一个框架，最终决定入坑 Vue。<br>但是我并没有看过任何 Vue 3 完整的教程，而是从 Vue 3 的原理上去学习的。《Vue.js 设计与实现》这本书给了我很大的帮助，它详细的解释了 Vue 3 的设计理念，并给出了具体的实现。我初三中后期在校期间除了把没啥难度的试题做完，就是在看这本书，因为 Vue 3 的逻辑很有趣，同时这是我买的第一本关于程序相关的书，兴趣使然使我简单了解了 Vue 3 在各种方法上与 Vue 2 的差异，以及 Vue.js 的优点和简便性。<br>虽然最后看到 Diff 算法之后就没有看了，但是这本书影响了我后续编程的思想和代码理念，不仅局限于 Vue，在其他语言上我也深受此书启发。</p><blockquote><p>代码能跑和能优雅的运行永远是不一样的，能跑局限于能跑，而后者则更令人赏心悦目。<br>我不喜欢看到一大堆混乱的代码，也不喜欢看到一大堆的警告。</p></blockquote><h4 id="正题"><a href="#正题" class="headerlink" title="正题"></a>正题</h4><p>当时 LCF 正在更新 2.0，用 Vue + NaiveUI 写了一个面板，好看归好看，但是因为 @Daiyangcheng 当时糟糕的 Vue 水平，导致面板移动端适配很怪以及组件间距非常难绷，于是我就看到经常吐槽太史了以及经常给出一堆 CSS 样式，然后 DYC(Daiyangcheng) 按我说的去改了<br>不过后面还是有很多地方看着不满意（强迫症（悲）），干脆直接 fork 改</p><h3 id="Nya-LoCyanFrp-乐青映射启动器"><a href="#Nya-LoCyanFrp-乐青映射启动器" class="headerlink" title="Nya LoCyanFrp! 乐青映射启动器"></a>Nya LoCyanFrp! 乐青映射启动器</h3><p>此项目是我成为 LCT 成员的主要贡献。<br>当时 LCF 还没有一个带 GUI 的启动器，刚好另一边有其他项目拉我去开发（现在一直咕咕咕还没新建文件夹），定了前端要用 Flutter 开发，但是当时我并不会 Flutter，所以本来不打算学的，但是定好了大家都不打算改的样子，就顺便打算写个 LCF 启动器练练手的。<br>Flutter 我是从《Flutter 技术入门与实战》《Flutter 实战 第2版》这两本书中学来的，虽然随着 Dart 和 Flutter 更新这两本书内容稍微有点过时了，不过想学我还是很推荐这两本书的。<br>刚开始入坑 Flutter 并不顺手，因为当时我还没有那么成熟的界面设计观念，要设计一整套完整的交互，确实对于一个初三生有点那啥了（<br>后面也是因为各种原因弃坑大概有2个月？（记得不清楚），因为期间 LCF 官方在开发新的客户端，我就没管这个项目。<br>后面觉得 LCF 那个新客户端太丑了，功能啥也没有，觉得这根本不行啊（恼<br>于是又回坑去填坑了<br>当时已经有初版的 v2 API 了，但是那会我是 Query 一把梭类型（对的，令牌都用 Query Params），调 API 出了点小插曲，调用 dio 卡了半天<br>后面各种奇葩操作把启动器拼出来了，欸你别说比官方的好看（<br>这不得直接发 LCF 群找个幸运儿体验（x<br>在这里我要吐槽一下 Dart 的垃圾 IO 库，进程操作啥也没有，属于是要啥没啥，全部得自己造轮子系列<br>后面研究打包器发现沟槽的打包器有 BUG，又自己 fork 下来魔改，最后成功发布了 0.1.x 版本<br>但是后面有用户反馈说 macOS 版用不了，加上我没有 macOS 的设备，翻 Apple 那个构思文档翻了半天，最后才解决了权限之类的各种我自己根本不可能遇到的问题。</p><p>随着 Nya LoCyanFrp! 的不断完善，最终成为了新的官方启动器。<br>后续工作中，我也在潜移默化中成为了 LCT(LoCyanTeam) 的一员。</p><h2 id="我是如何成为站长的"><a href="#我是如何成为站长的" class="headerlink" title="我是如何成为站长的"></a>我是如何成为站长的</h2><p>我在 NyaLCF 开发以后，随着暑假过去，顺理成章成为了市一中的一员，但是后面因为一些我个人原因（性别认同之类的），导致我高一中期重度抑郁休学。<br>休学后我病情稍微好转一些，也和 DYC 的关系逐渐比较近，同时虽然抑郁但是有时候非常无聊我就会去更新 NyaLCF，本身原站长和 LCT 其他成员人就比较忙，作为为 LCF 产生了大量社区贡献的我最终成为了 LCT 的一员，后面由于原站长即将踏入高三，便把项目托付给我了。</p><p>自此我成为 LCF 的站长，但其实我并不是特别了解 Frp 及 SakuraPanel 的很多东西，后面虽然原站长暂时退出，但我依然会去请教相关问题，包括现在，我希望尊重原站长的意见，他虽然很忙但是还是很在意这个项目的，毕竟这也是他亲手创办的东西嘛。</p><p><em>——To be continued</em></p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;LoCyanFrp 目前是我为现任站长的一个项目，这篇文章主要是想简单聊一聊，我与 LoCyanFrp，和其他友商的一些经历。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;LoCyanFrp 简写 LCF&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;关于这个项目&quot;&gt;&lt;a</summary>
      
    
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/categories/LoCyanFrp/"/>
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/tags/LoCyanFrp/"/>
    
    <category term="杂谈" scheme="https://blog.amaicat.work/tags/%E6%9D%82%E8%B0%88/"/>
    
  </entry>
  
  <entry>
    <title>Dart 开发踩坑: ServerSocket.close();</title>
    <link href="https://blog.amaicat.work/2024/09/27/dart-kai-fa-cai-keng-serversocket.close/"/>
    <id>https://blog.amaicat.work/2024/09/27/dart-kai-fa-cai-keng-serversocket.close/</id>
    <published>2024-09-27T01:12:04.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<p>今天在写一个 ServerSocket 转发的时候，发现调用了 <code>close()</code> 方法，数据貌似还在传输：<br><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2024/09/27/66f67762f3db2.webp" alt="演示"><br>看起来很奇怪，然后去查了一下，发现了这个 Issue <a class="link"   href="https://github.com/dart-lang/sdk/issues/54882" >dart-lang&#x2F;sdk#54882 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a>，官方成员的回复是：</p><blockquote><p>Closing listening socket does not affect connections already established</p></blockquote><p>一不小心就踩坑了，这个居然不会影响现有连接，居然还要自己去实现，绝了</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;今天在写一个 ServerSocket 转发的时候，发现调用了 &lt;code&gt;close()&lt;/code&gt; 方法，数据貌似还在传输：&lt;br&gt;&lt;img loading=&quot;lazy&quot; src=&quot;https://apac-cloudflare-r2-img.1l1.icu/2024</summary>
      
    
    
    
    
    <category term="Dart" scheme="https://blog.amaicat.work/tags/Dart/"/>
    
  </entry>
  
  <entry>
    <title>Beszel：全新的服务器探针工具</title>
    <link href="https://blog.amaicat.work/2024/08/30/beszel-quan-xin-de-fu-wu-qi-tan-zhen-gong-ju/"/>
    <id>https://blog.amaicat.work/2024/08/30/beszel-quan-xin-de-fu-wu-qi-tan-zhen-gong-ju/</id>
    <published>2024-08-30T14:41:47.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<h2 id="关于-Beszel"><a href="#关于-Beszel" class="headerlink" title="关于 Beszel"></a>关于 Beszel</h2><p>一个轻量级的服务器资源监控，官方描述：</p><blockquote><p>A lightweight server resource monitoring hub with historical data, docker stats, and alerts.</p></blockquote><p>正如介绍所言，而且不但轻量，UI 界面也美观。</p><h3 id="一点关于博主更换-Beszel-的经历"><a href="#一点关于博主更换-Beszel-的经历" class="headerlink" title="一点关于博主更换 Beszel 的经历"></a>一点关于博主更换 Beszel 的经历</h3><p>博主曾经使用哪吒监控，但它并不好用，以下是原因：</p><ol><li>哪吒监控的前端并不好看</li><li>哪吒监控的前端对移动端适配很差，能用但是很糟心</li><li>哪吒监控的前端代码和处理逻辑非常糟糕，博主曾自制过主题</li><li>哪吒监控的后台没有搜索功能，有人可能会说 <code>Ctrl + F</code>，但其实服务器多了并没有自带搜索直观</li></ol><p>出于种种原因，我最终更换了 Beszel 作为服务器探针。</p><h2 id="部署-Hub"><a href="#部署-Hub" class="headerlink" title="部署 Hub"></a>部署 Hub</h2><p>Hub 就是 Beszel 的控制端，很简单，使用 Docker 就可以轻松部署。<br>我这里选择使用 Compose 部署，示例如下：</p><div class="highlight-container" data-rel="YAML"><figure class="iseeu highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">beszel:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">&#x27;henrygd/beszel&#x27;</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">&#x27;beszel&#x27;</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./data:/beszel_data</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">&quot;8090:8090&quot;</span></span><br></pre></td></tr></table></figure></div><p>将这个配置写到你喜欢的地方，比如 <code>/opt/beszel</code><br>然后：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /opt/beszel</span><br><span class="line">docker-compose up -d</span><br></pre></td></tr></table></figure></div><p>现在访问 <code>http://&lt;服务器地址&gt;:8090</code> 即可进入 Beszel 后台，在这里配置完管理员信息就完成了。</p><h2 id="部署-Agent"><a href="#部署-Agent" class="headerlink" title="部署 Agent"></a>部署 Agent</h2><p>Agent 同样可以使用 Docker Compose 部署。<br>在 Hub 的右上角点击 <code>Add System</code>，点击 <code>Copy docker compose</code> 即可复制 Agent 部署用的 <code>docker-compose.yml</code> 模板，参考上方 Hub 的部署方法，正常部署然后在 Hub 完成信息填写并添加即可。</p><h3 id="Watchtower-自动更新-Agent"><a href="#Watchtower-自动更新-Agent" class="headerlink" title="Watchtower 自动更新 Agent"></a>Watchtower 自动更新 Agent</h3><p>Beszel 不会自动更新 Agent，可以通过配置 Watchtower 实现容器自动更新：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d --name watchtower -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower beszel-agent</span><br></pre></td></tr></table></figure></div>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;关于-Beszel&quot;&gt;&lt;a href=&quot;#关于-Beszel&quot; class=&quot;headerlink&quot; title=&quot;关于 Beszel&quot;&gt;&lt;/a&gt;关于 Beszel&lt;/h2&gt;&lt;p&gt;一个轻量级的服务器资源监控，官方描述：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A </summary>
      
    
    
    
    
    <category term="Beszel" scheme="https://blog.amaicat.work/tags/Beszel/"/>
    
    <category term="探针" scheme="https://blog.amaicat.work/tags/%E6%8E%A2%E9%92%88/"/>
    
  </entry>
  
  <entry>
    <title>Flutter实现Monet莫奈取色</title>
    <link href="https://blog.amaicat.work/2024/08/28/flutter-shi-xian-monet-mo-nai-qu-se/"/>
    <id>https://blog.amaicat.work/2024/08/28/flutter-shi-xian-monet-mo-nai-qu-se/</id>
    <published>2024-08-28T14:45:30.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<p>Flutter 的 Material Design 3 居然没自带 Monet 取色，这就比较难受</p><h2 id="添加依赖包"><a href="#添加依赖包" class="headerlink" title="添加依赖包"></a>添加依赖包</h2><p>需要用到的是 <code>dynamic_color</code></p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">flutter pub add dynamic_color</span><br></pre></td></tr></table></figure></div><p>根据官方说明，各个平台取色方式如下：</p><p>Android S+: 用户壁纸颜色<br>Linux: GTK+ 主题的 @theme_selected_bg_color<br>macOS: 应用程序的 accent color<br>Windows: accent color 或者 window&#x2F;glass color</p><h2 id="修改入口文件"><a href="#修改入口文件" class="headerlink" title="修改入口文件"></a>修改入口文件</h2><p>修改你的 <code>main.dart</code> ，一个完整的示例如下：</p><div class="highlight-container" data-rel="DART"><figure class="iseeu highlight dart"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="string">&#x27;package:dynamic_color/dynamic_color.dart&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;package:flutter/material.dart&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> main() <span class="keyword">async</span> &#123;</span><br><span class="line">  runApp(<span class="keyword">const</span> MyApp());</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyApp</span> <span class="keyword">extends</span> <span class="title">StatelessWidget</span> </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> MyApp(&#123;<span class="keyword">super</span>.key&#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 默认主题色种子</span></span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">const</span> _defaultColorSeed = Colors.blueAccent;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 根组件</span></span><br><span class="line">  <span class="meta">@override</span></span><br><span class="line">  Widget build(BuildContext context) &#123;</span><br><span class="line">    Get.put(ProgressbarController());</span><br><span class="line">    <span class="comment">// Monet 取色</span></span><br><span class="line">    <span class="keyword">return</span> DynamicColorBuilder(</span><br><span class="line">      builder: (ColorScheme? lightDynamic, ColorScheme? darkDynamic) &#123;</span><br><span class="line">        ColorScheme lightColorScheme;</span><br><span class="line">        ColorScheme darkColorScheme;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (lightDynamic != <span class="keyword">null</span> &amp;&amp; darkDynamic != <span class="keyword">null</span>) &#123;</span><br><span class="line">          <span class="comment">// 亮色模式 Monet 取色</span></span><br><span class="line">          lightColorScheme = lightDynamic.harmonized();</span><br><span class="line">          <span class="comment">// 暗色模式 Monet 取色</span></span><br><span class="line">          darkColorScheme = darkDynamic.harmonized();</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="comment">// Fallback 颜色，当不支持 Monet 取色的时候使用</span></span><br><span class="line">          lightColorScheme = ColorScheme.fromSeed(</span><br><span class="line">            seedColor: _defaultColorSeed,</span><br><span class="line">          );</span><br><span class="line">          darkColorScheme = ColorScheme.fromSeed(</span><br><span class="line">            seedColor: _defaultColorSeed,</span><br><span class="line">            brightness: Brightness.dark,</span><br><span class="line">          );</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 覆盖取色后的颜色可以用 ColorScheme.copyWith(); 方法 </span></span><br><span class="line">        <span class="comment">// lightColorScheme.copyWith(secondary: Color.blue);</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> GetMaterialApp(</span><br><span class="line">          title: <span class="string">&#x27;Monet Example&#x27;</span>,</span><br><span class="line">          <span class="comment">// 亮色模式主题，直接调用获取到的 ColorScheme</span></span><br><span class="line">          theme: ThemeData(</span><br><span class="line">            useMaterial3: <span class="keyword">true</span>,</span><br><span class="line">            colorScheme: lightColorScheme,</span><br><span class="line">            <span class="comment">// ...</span></span><br><span class="line">          ),</span><br><span class="line">          <span class="comment">// 暗色模式主题，同上</span></span><br><span class="line">          darkTheme: ThemeData(</span><br><span class="line">            useMaterial3: <span class="keyword">true</span>,</span><br><span class="line">            brightness: Brightness.dark,</span><br><span class="line">            colorScheme: darkColorScheme,</span><br><span class="line">            <span class="comment">// ...</span></span><br><span class="line">          ),</span><br><span class="line">          <span class="comment">// 设置主题跟随系统</span></span><br><span class="line">          themeMode: ThemeMode.system,</span><br><span class="line">          <span class="comment">// ...</span></span><br><span class="line">        );</span><br><span class="line">      &#125;,</span><br><span class="line">    );</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><p>接下来，热重启应用程序即可看到效果~</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Flutter 的 Material Design 3 居然没自带 Monet 取色，这就比较难受&lt;/p&gt;
&lt;h2 id=&quot;添加依赖包&quot;&gt;&lt;a href=&quot;#添加依赖包&quot; class=&quot;headerlink&quot; title=&quot;添加依赖包&quot;&gt;&lt;/a&gt;添加依赖包&lt;/h2&gt;&lt;p&gt;需</summary>
      
    
    
    
    
    <category term="Flutter" scheme="https://blog.amaicat.work/tags/Flutter/"/>
    
    <category term="Monet" scheme="https://blog.amaicat.work/tags/Monet/"/>
    
  </entry>
  
  <entry>
    <title>中兴ZTE MyOS改用第三方启动器</title>
    <link href="https://blog.amaicat.work/2024/08/12/zhong-xing-zte-myos-gai-yong-di-san-fang-qi-dong-qi/"/>
    <id>https://blog.amaicat.work/2024/08/12/zhong-xing-zte-myos-gai-yong-di-san-fang-qi-dong-qi/</id>
    <published>2024-08-12T03:28:21.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<p>该方法仅供学习交流，所有操作造成的后果由使用者自负！</p><h2 id="准备"><a href="#准备" class="headerlink" title="准备"></a>准备</h2><ul><li>ADB</li><li>一款第三方桌面软件</li></ul><h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><p>首先确保已经把手机导航方式切换为传统按键导航。<br>然后打开手机开发人员选项，打开 ADB 调试功能。</p><p>确保已经安装好第三方启动器。<br>博主使用的是 <code>微软桌面</code> ，当然你用别的也不是不可以。</p><h3 id="方法一"><a href="#方法一" class="headerlink" title="方法一"></a>方法一</h3><p>ADB 连接到手机，使用命令设置默认主屏幕应用：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell pm set-home-activity com.microsoft.launcher</span><br></pre></td></tr></table></figure></div><h3 id="方法二"><a href="#方法二" class="headerlink" title="方法二"></a>方法二</h3><p>ADB 连接到手机，执行以下命令先禁用中兴自带的桌面软件：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell pm disable-user com.zte.mifavor.launcher</span><br></pre></td></tr></table></figure></div><p>然后回到手机，此时返回桌面，会提示选择打开方式，选中自己安装的第三方桌面软件并勾选 <code>设为默认</code> 。<br>此时手势导航不能用，我们解除禁用中兴的桌面软件：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell pm enable com.zte.mifavor.launcher</span><br></pre></td></tr></table></figure></div><p>然后去设置里面把导航方式切换回原来的导航方式即可正常使用。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;该方法仅供学习交流，所有操作造成的后果由使用者自负！&lt;/p&gt;
&lt;h2 id=&quot;准备&quot;&gt;&lt;a href=&quot;#准备&quot; class=&quot;headerlink&quot; title=&quot;准备&quot;&gt;&lt;/a&gt;准备&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;ADB&lt;/li&gt;
&lt;li&gt;一款第三方桌面软件&lt;/li&gt;
&lt;/</summary>
      
    
    
    
    
    <category term="中兴" scheme="https://blog.amaicat.work/tags/%E4%B8%AD%E5%85%B4/"/>
    
    <category term="MyOS" scheme="https://blog.amaicat.work/tags/MyOS/"/>
    
  </entry>
  
  <entry>
    <title>HUAWEI nova 3通过开启深色模式</title>
    <link href="https://blog.amaicat.work/2024/08/09/huawei-nova-3-tong-guo-adb-kai-qi-shen-se-mo-shi/"/>
    <id>https://blog.amaicat.work/2024/08/09/huawei-nova-3-tong-guo-adb-kai-qi-shen-se-mo-shi/</id>
    <published>2024-08-09T12:56:51.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<p>nova 3这台机子更新了HarmonyOS 2，但是却是基于AOSP9的版本，导致很多功能遗失，比如这个深色模式<br><del>HUAWEI nova 3 简直就是 wuawei 弃子</del></p><p>可以通过 ADB 设置属性开启 Android 9 中的深色模式，不过系统本身没有适配，只有应用会适配</p><div class="highlight-container" data-rel="PWSH"><figure class="iseeu highlight pwsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">adb shell settings put secure ui_night_mode <span class="number">2</span></span><br></pre></td></tr></table></figure></div><p>如果你像我的一样安装了 GMS 框架，但是发现设置了之后 Google 家的一些应用还一样浅色模式显示，得手动到应用的设置设成深色</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;nova 3这台机子更新了HarmonyOS 2，但是却是基于AOSP9的版本，导致很多功能遗失，比如这个深色模式&lt;br&gt;&lt;del&gt;HUAWEI nova 3 简直就是 wuawei 弃子&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;可以通过 ADB 设置属性开启 Android 9 中的深</summary>
      
    
    
    
    
    <category term="HarmonyOS" scheme="https://blog.amaicat.work/tags/HarmonyOS/"/>
    
  </entry>
  
  <entry>
    <title>不使用tailscale_enabler的方法在OpenWrt上安装最新版Tailscale</title>
    <link href="https://blog.amaicat.work/2024/07/30/bu-shi-yong-tailscale-enabler-zai-openwrt-shang-an-zhuang-zui-xin-ban-tailscale/"/>
    <id>https://blog.amaicat.work/2024/07/30/bu-shi-yong-tailscale-enabler-zai-openwrt-shang-an-zhuang-zui-xin-ban-tailscale/</id>
    <published>2024-07-29T22:15:48.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<h2 id="为什么不使用-tailscale-enabler"><a href="#为什么不使用-tailscale-enabler" class="headerlink" title="为什么不使用 tailscale_enabler ?"></a>为什么不使用 tailscale_enabler ?</h2><ol><li>tailscale_enabler 每次启动都要重新下载 Tailscale，我认为这是非常愚蠢的设计。</li><li>tailscale_enabler 部分资源使用 GitHub 下载，国内访问不畅通。</li></ol><h2 id="正文"><a href="#正文" class="headerlink" title="正文"></a>正文</h2><h3 id="下载安装最新版-Tailscale-的-ipk"><a href="#下载安装最新版-Tailscale-的-ipk" class="headerlink" title="下载安装最新版 Tailscale 的 ipk"></a>下载安装最新版 Tailscale 的 ipk</h3><p>访问 <a class="link"   href="https://pkgs.org/download/tailscale" >https://pkgs.org/download/tailscale <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a>，往下找到 OpenWrt，选择合适架构的 ipk 文件，点击进入，往下滑找到 <code>Download</code> 进入，有一个下载链接，下载并使用 opkg 安装。<br>我使用的是基于 OpenWrt 22 的系统，能正常使用，虽然这个是 OpenWrt 23 源中的文件。</p><p>安装好了之后，此时正常接入内网会显示不是最新版，先别着急，我们执行新版 Tailscale 带有的 <code>update</code> 命令：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tailscale update</span><br></pre></td></tr></table></figure></div><p>执行完毕后，你就会发现 Tailscale 已经正常升级到最新版。<br><img loading="lazy" src="https://apac-cloudflare-r2-img.1l1.icu/2024/07/30/66a887140ec84.webp" alt="Result"></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;为什么不使用-tailscale-enabler&quot;&gt;&lt;a href=&quot;#为什么不使用-tailscale-enabler&quot; class=&quot;headerlink&quot; title=&quot;为什么不使用 tailscale_enabler ?&quot;&gt;&lt;/a&gt;为什么不使用 tails</summary>
      
    
    
    
    
    <category term="OpenWrt" scheme="https://blog.amaicat.work/tags/OpenWrt/"/>
    
    <category term="Tailscale" scheme="https://blog.amaicat.work/tags/Tailscale/"/>
    
  </entry>
  
  <entry>
    <title>使用Docker部署Tailscale DERP</title>
    <link href="https://blog.amaicat.work/2024/07/25/shi-yong-docker-bu-shu-tailscale-derp/"/>
    <id>https://blog.amaicat.work/2024/07/25/shi-yong-docker-bu-shu-tailscale-derp/</id>
    <published>2024-07-25T11:07:33.000Z</published>
    <updated>2026-07-15T16:23:36.621Z</updated>
    
    <content type="html"><![CDATA[<h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><ul><li>一台能够跑Docker的服务器</li><li>服务器能开放stun的端口 <code>UDP/3478</code></li><li>一个域名</li><li>(可选)SSL证书</li></ul><p>本文假设服务器发行版为普通 Debian 12</p><blockquote><p>Docker 近期国内访问困难，以下是截止本文发布时可用的镜像：</p><ul><li>docker.1panel.live</li><li>dockerhub.icu</li></ul><p>关于 Docker 及 Docker Compose 安装本文不再赘述，请自行查阅其他文档。</p></blockquote><h2 id="防火墙放行端口"><a href="#防火墙放行端口" class="headerlink" title="防火墙放行端口"></a>防火墙放行端口</h2><p>iptables&#x2F;nftables和服务器安全组都要放行以下端口：</p><ul><li><code>UDP/3478</code></li><li><code>TCP/&lt;PORT&gt;</code></li></ul><p><code>&lt;PORT&gt;</code> 请改为一个你需要的端口</p><h2 id="（可选）安装-Tailscale"><a href="#（可选）安装-Tailscale" class="headerlink" title="（可选）安装 Tailscale"></a>（可选）安装 Tailscale</h2><p>此步骤用于鉴权，若你搭建的是公开 DERP 服务，那么可以跳过。</p><p>更新: 如果你想使用容器版本的 Tailscale，那么也可以跳过此步，往下一步有更多说明。</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://tailscale.com/install.sh | sh</span><br></pre></td></tr></table></figure></div><h2 id="写入-Docker-Compose"><a href="#写入-Docker-Compose" class="headerlink" title="写入 Docker Compose"></a>写入 Docker Compose</h2><p>创建 Derper 文件夹：</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mkdir</span> -p /opt/derper</span><br><span class="line"><span class="built_in">mkdir</span> -p /opt/derper/cert <span class="comment"># 证书目录</span></span><br></pre></td></tr></table></figure></div><p>请将 <code>&lt;PORT&gt;</code> 替换为你希望的 DERP 端口，<code>&lt;HOST&gt;</code> 替换为你希望的 DERP 连接域名。<br>本文假设你需要 SSL，故写入证书相关。关于证书请继续往下。若不需要 SSL，请自行移除 <code>-certdir=/cert/ -certmode=manual</code> 部分。<br>如果需要搭建的为公共 DERP，请移除 <code>-verify-clients</code> 部分。</p><p>如果你不需要鉴权，无需关心 Tailscale 客户端安装方式，因为并不需要安装。<br>如果你需要让 DERP 获取真实 IP，请将网络模式改为 <code>host</code> 模式（修改 STUN 端口可用 <code>-stun-port</code> 参数指定）。</p><h3 id="使用宿主机-Tailscale-客户端鉴权"><a href="#使用宿主机-Tailscale-客户端鉴权" class="headerlink" title="使用宿主机 Tailscale 客户端鉴权"></a>使用宿主机 Tailscale 客户端鉴权</h3><div class="highlight-container" data-rel="YAML"><figure class="iseeu highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">derper:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">qctt/derper</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">derper</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;&lt;PORT&gt;:443&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;3478:3478/udp&quot;</span></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./cert/:/cert/</span> <span class="comment"># 证书目录</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">/var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock:ro</span> <span class="comment"># 用于给私有DERP鉴权</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">/derper</span> <span class="string">-stun</span> <span class="string">-a</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span><span class="string">:443</span> <span class="string">-hostname</span> <span class="string">&lt;HOST&gt;</span> <span class="string">-certdir=/cert/</span> <span class="string">-certmode=manual</span> <span class="string">-verify-clients</span></span><br></pre></td></tr></table></figure></div><h3 id="使用容器版本-Tailscale-鉴权"><a href="#使用容器版本-Tailscale-鉴权" class="headerlink" title="使用容器版本 Tailscale 鉴权"></a>使用容器版本 Tailscale 鉴权</h3><div class="highlight-container" data-rel="YAML"><figure class="iseeu highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">services:</span></span><br><span class="line">  <span class="attr">tailscale_client:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">tailscale/tailscale:latest</span> </span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">derper-tailscale-client</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./tailscale:/var/lib/tailscale</span></span><br><span class="line">    <span class="attr">environment:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">TS_USERSPACE=true</span> <span class="comment"># 使用 userspace mode 以便无需映射 tun</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">TS_STATE_DIR=/var/lib/tailscale</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">TS_SOCKET=/var/lib/tailscale/run.sock</span> <span class="comment"># tailscaled socket</span></span><br><span class="line"></span><br><span class="line">  <span class="attr">derper:</span></span><br><span class="line">    <span class="attr">image:</span> <span class="string">qctt/derper</span></span><br><span class="line">    <span class="attr">container_name:</span> <span class="string">derper</span></span><br><span class="line">    <span class="attr">restart:</span> <span class="string">unless-stopped</span></span><br><span class="line">    <span class="attr">ports:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;&lt;PORT&gt;:443&quot;</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">&quot;3478:3478/udp&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">volumes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./cert/:/cert/</span> <span class="comment"># 证书目录</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">./tailscale/run.sock:/var/run/tailscale/tailscaled.sock:ro</span> <span class="comment"># 用于给私有DERP鉴权</span></span><br><span class="line">    <span class="attr">command:</span> <span class="string">/derper</span> <span class="string">-stun</span> <span class="string">-a</span> <span class="number">0.0</span><span class="number">.0</span><span class="number">.0</span><span class="string">:443</span> <span class="string">-http-port</span> <span class="number">-1</span> <span class="string">-hostname</span> <span class="string">&lt;HOST&gt;</span> <span class="string">-certdir=/cert/</span> <span class="string">-certmode=manual</span> <span class="string">-verify-clients</span></span><br></pre></td></tr></table></figure></div><p>使用 <code>docker compose logs tailscale_client -f</code> 查看 Tailscale 客户端的日志获取登录链接进行授权，或者使用 <code>TS_AUTH_KEY</code> 来授权。</p><h2 id="关于证书"><a href="#关于证书" class="headerlink" title="关于证书"></a>关于证书</h2><p>证书及私钥文件名为：</p><ul><li>&lt;HOST&gt;.crt</li><li>&lt;PORT&gt;.key</li></ul><p>如果你和我一样使用 1Panel 申请和管理证书，那么你可以在证书申请的配置中勾选 <code>推送证书到本地目录</code> 和 <code>申请证书之后执行脚本</code>，并填入：</p><p>推送证书到本地目录:</p><div class="highlight-container" data-rel="TEXT"><figure class="iseeu highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/opt/derper/cert</span><br></pre></td></tr></table></figure></div><p>申请证书之后执行脚本:</p><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">mv</span> /opt/derper/cert/fullchain.pem /opt/derper/cert/&lt;HOST&gt;.crt</span><br><span class="line"><span class="built_in">mv</span> /opt/derper/cert/privkey.pem /opt/derper/cert/&lt;HOST&gt;.key</span><br></pre></td></tr></table></figure></div><h2 id="启动-Derper-服务"><a href="#启动-Derper-服务" class="headerlink" title="启动 Derper 服务"></a>启动 Derper 服务</h2><div class="highlight-container" data-rel="BASH"><figure class="iseeu highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /opt/derper</span><br><span class="line">docker-compose up -d</span><br></pre></td></tr></table></figure></div><h2 id="添加到Tailscale"><a href="#添加到Tailscale" class="headerlink" title="添加到Tailscale"></a>添加到Tailscale</h2><p>在你的Tailscale管理界面找到 <code>Access Controls</code> (<a class="link"   href="https://login.tailscale.com/admin/acls/file" >点我直达 <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a>)<br>在其中插入片段，示例如下</p><div class="highlight-container" data-rel="JSON"><figure class="iseeu highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;acls&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;ssh&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    <span class="attr">&quot;derpMap&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;Regions&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">            <span class="attr">&quot;900&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">                <span class="attr">&quot;RegionID&quot;</span><span class="punctuation">:</span>   <span class="number">900</span><span class="punctuation">,</span> <span class="comment">// 900以上</span></span><br><span class="line">                <span class="attr">&quot;RegionCode&quot;</span><span class="punctuation">:</span> <span class="string">&quot;cni-zj-nb&quot;</span><span class="punctuation">,</span> <span class="comment">// 区域代码，会在 `tailscale netcheck` 显示</span></span><br><span class="line">                <span class="attr">&quot;RegionName&quot;</span><span class="punctuation">:</span> <span class="string">&quot;中国-湖北&quot;</span><span class="punctuation">,</span> <span class="comment">// 区域名称，会在 `tailscale netcheck` 显示</span></span><br><span class="line">                <span class="attr">&quot;Nodes&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">                    <span class="punctuation">&#123;</span></span><br><span class="line">                        <span class="attr">&quot;Name&quot;</span><span class="punctuation">:</span>     <span class="string">&quot;zj-nb-1&quot;</span><span class="punctuation">,</span> <span class="comment">// 随意填写</span></span><br><span class="line">                        <span class="attr">&quot;RegionID&quot;</span><span class="punctuation">:</span> <span class="number">900</span><span class="punctuation">,</span> <span class="comment">// 对应上方ID</span></span><br><span class="line">                        <span class="attr">&quot;HostName&quot;</span><span class="punctuation">:</span> <span class="string">&quot;xxxxx.xxx&quot;</span><span class="punctuation">,</span> <span class="comment">// 填写你的DERP服务域名</span></span><br><span class="line">                        <span class="attr">&quot;DERPPort&quot;</span><span class="punctuation">:</span> <span class="number">12345</span><span class="punctuation">,</span> <span class="comment">// 你的DERP服务端口</span></span><br><span class="line">                    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">                <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">            <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">            <span class="comment">// 更多DERP节点</span></span><br><span class="line">        <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></div><p>使用 <code>tailscale netcheck</code> 检查，发现多出自建DERP，成功</p><div class="highlight-container" data-rel="PLAINTEXT"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">Report:</span><br><span class="line">        * UDP: true</span><br><span class="line">        * IPv4: yes, xxx.xxx.xxx.xxx:xxxxx</span><br><span class="line">        * IPv6: no, but OS has support</span><br><span class="line">        * MappingVariesByDestIP: true</span><br><span class="line">        * PortMapping:</span><br><span class="line">        * CaptivePortal: false</span><br><span class="line">        * Nearest DERP: 中国-湖北-崇阳</span><br><span class="line">        * DERP latency:</span><br><span class="line">                - cni-hb-cy: 41.4ms  (中国-湖北-崇阳)</span><br><span class="line">                - cni-zj-nb: 59.6ms  (中国-浙江-宁波)</span><br><span class="line">                - lax: 239.7ms (Los Angeles)</span><br><span class="line">                - sfo: 245.8ms (San Francisco)</span><br><span class="line">                - sea: 251.3ms (Seattle)</span><br><span class="line">                - den: 255.6ms (Denver)</span><br><span class="line">                - tor: 267ms   (Toronto)</span><br><span class="line">                - dfw: 269ms   (Dallas)</span><br><span class="line">                - ord: 269.5ms (Chicago)</span><br><span class="line">                - hnl: 271.7ms (Honolulu)</span><br><span class="line">                - nyc: 278.9ms (New York City)</span><br><span class="line">                - mia: 286.8ms (Miami)</span><br><span class="line">                - tok: 336.3ms (Tokyo)</span><br><span class="line">                - lhr: 343.1ms (London)</span><br><span class="line">                - cnh: 361ms   (中国香港)</span><br><span class="line">                - par: 361.5ms (Paris)</span><br><span class="line">                - fra: 364ms   (Frankfurt)</span><br><span class="line">                - mad: 366.2ms (Madrid)</span><br><span class="line">                - syd: 370.7ms (Sydney)</span><br><span class="line">                - ams: 377.1ms (Amsterdam)</span><br><span class="line">                - waw: 380.1ms (Warsaw)</span><br><span class="line">                - hkg: 386.6ms (Hong Kong)</span><br><span class="line">                - sin: 400ms   (Singapore)</span><br><span class="line">                - sao: 404ms   (São Paulo)</span><br><span class="line">                - blr: 463.2ms (Bangalore)</span><br><span class="line">                - dbi: 466.5ms (Dubai)</span><br><span class="line">                - nai: 509.7ms (Nairobi)</span><br><span class="line">                - jnb: 518.5ms (Johannesburg)</span><br><span class="line">                - usa:         (美国)</span><br></pre></td></tr></table></figure></div>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;准备工作&quot;&gt;&lt;a href=&quot;#准备工作&quot; class=&quot;headerlink&quot; title=&quot;准备工作&quot;&gt;&lt;/a&gt;准备工作&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;一台能够跑Docker的服务器&lt;/li&gt;
&lt;li&gt;服务器能开放stun的端口 &lt;code&gt;UDP/3478&lt;/c</summary>
      
    
    
    
    
    <category term="教程" scheme="https://blog.amaicat.work/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Tailscale" scheme="https://blog.amaicat.work/tags/Tailscale/"/>
    
    <category term="DERP" scheme="https://blog.amaicat.work/tags/DERP/"/>
    
  </entry>
  
  <entry>
    <title>Paper 服务端及其衍生端开启 HAProxy 支持，同时让 Frpc 转发用户真实 IP 到服务端</title>
    <link href="https://blog.amaicat.work/2024/07/23/paper-fu-wu-duan-ji-qi-yan-sheng-duan-kai-qi-haproxy-zhi-chi-tong-shi-rang-frpc-zhuan-fa-yong-hu-zhen-shi-ip-dao-fu-wu-duan/"/>
    <id>https://blog.amaicat.work/2024/07/23/paper-fu-wu-duan-ji-qi-yan-sheng-duan-kai-qi-haproxy-zhi-chi-tong-shi-rang-frpc-zhuan-fa-yong-hu-zhen-shi-ip-dao-fu-wu-duan/</id>
    <published>2024-07-23T05:36:25.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Frpc-添加参数开启-HAProxy-转发"><a href="#Frpc-添加参数开启-HAProxy-转发" class="headerlink" title="Frpc 添加参数开启 HAProxy 转发"></a>Frpc 添加参数开启 HAProxy 转发</h2><p>以下示例均为 <code>ini</code> 配置，其他配置请自行变通。</p><p>在 Frpc 配置文件对应隧道配置后加入：</p><div class="highlight-container" data-rel="INI"><figure class="iseeu highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">proxy_protocol_version</span> = v2</span><br></pre></td></tr></table></figure></div><p>e.g.</p><div class="highlight-container" data-rel="INI"><figure class="iseeu highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[testTunnel]</span></span><br><span class="line"><span class="attr">privilege_mode</span> = <span class="literal">true</span></span><br><span class="line"><span class="attr">type</span> = tcp</span><br><span class="line"><span class="attr">local_ip</span> = <span class="number">127.0</span>.<span class="number">0.1</span></span><br><span class="line"><span class="attr">local_port</span> = <span class="number">25565</span></span><br><span class="line"><span class="attr">remote_port</span> = <span class="number">11451</span></span><br><span class="line"><span class="attr">use_encryption</span> = <span class="number">0</span></span><br><span class="line"><span class="attr">use_compression</span> = <span class="number">0</span></span><br><span class="line"><span class="attr">proxy_protocol_version</span> = v2</span><br></pre></td></tr></table></figure></div><p>重启 Frpc（如果正在运行）。</p><h2 id="Paper-Global-配置开启-HAProxy-支持"><a href="#Paper-Global-配置开启-HAProxy-支持" class="headerlink" title="Paper Global 配置开启 HAProxy 支持"></a>Paper Global 配置开启 HAProxy 支持</h2><p>演示版本为 <code>Paper-1.21-109</code> ，配置文件位于 <code>config/paper-global.yml</code>。<br>将 <code>proxies.proxy-protocol</code> 设置为 <code>true</code> 。</p><div class="highlight-container" data-rel="YAML"><figure class="iseeu highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">proxies:</span></span><br><span class="line">  <span class="attr">bungee-cord:</span></span><br><span class="line">    <span class="attr">online-mode:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">proxy-protocol:</span> <span class="literal">true</span> <span class="comment"># &lt;--- 这里</span></span><br><span class="line">  <span class="attr">velocity:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">online-mode:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">secret:</span> <span class="string">&#x27;&#x27;</span></span><br></pre></td></tr></table></figure></div><p>重启服务端（如果正在运行）。</p><h2 id="All-done"><a href="#All-done" class="headerlink" title="All done"></a>All done</h2><p>如果你是按照教程配置的，那么现在加入服务器已经会显示客户端的实际 IP 。</p><div class="highlight-container" data-rel="PLAINTEXT"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[21:23:54] [User Authenticator #0/INFO]: UUID of player Muska_Ami is &lt;UUID&gt;</span><br><span class="line">[21:23:57] [Server thread/INFO]: Muska_Ami joined the game</span><br><span class="line">[21:23:57] [Server thread/INFO]: Muska_Ami[/117.183.xxx.xxx:24884] logged in with entity id 25 at ([world]-0.5, 69.0, -3.5)</span><br></pre></td></tr></table></figure></div>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;Frpc-添加参数开启-HAProxy-转发&quot;&gt;&lt;a href=&quot;#Frpc-添加参数开启-HAProxy-转发&quot; class=&quot;headerlink&quot; title=&quot;Frpc 添加参数开启 HAProxy 转发&quot;&gt;&lt;/a&gt;Frpc 添加参数开启 HAProxy </summary>
      
    
    
    
    
    <category term="教程" scheme="https://blog.amaicat.work/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="Frp" scheme="https://blog.amaicat.work/tags/Frp/"/>
    
    <category term="Minecraft" scheme="https://blog.amaicat.work/tags/Minecraft/"/>
    
    <category term="Paper" scheme="https://blog.amaicat.work/tags/Paper/"/>
    
  </entry>
  
  <entry>
    <title>Nya LoCyanFrp! v0.2.0 计划</title>
    <link href="https://blog.amaicat.work/2024/07/19/nya-locyanfrp-v0.2.0-ji-hua/"/>
    <id>https://blog.amaicat.work/2024/07/19/nya-locyanfrp-v0.2.0-ji-hua/</id>
    <published>2024-07-19T01:29:34.000Z</published>
    <updated>2026-07-15T16:23:36.620Z</updated>
    
    <content type="html"><![CDATA[<h2 id="关于该计划"><a href="#关于该计划" class="headerlink" title="关于该计划"></a>关于该计划</h2><p>由于当前启动器的代码体量并不小，为了便于维护，打算进一步模块化。<br>同时避免重复代码，将 <code>nyalcf_core</code> 完全分离，以便开发新的命令行版本（原定是用 Terminal UI 实现，但是后面还是决定直接用 CLI 了）。</p><h2 id="项目目录树"><a href="#项目目录树" class="headerlink" title="项目目录树"></a>项目目录树</h2><ul><li>nyalcf_core - 核心模块</li><li>nyalcf_inject - 通讯模块</li><li>nyalcf_gui - 图形化版本<ul><li>nyalcf_ui - 用户界面模块</li><li>nyalcf_core_extend - 核心扩展模块</li><li>nyalcf_inject_extend - 通讯扩展模块</li></ul></li><li>nyalcf_cli - 命令行版本</li></ul><p>由于命令行版本刚起步，模块信息可能日后会有变动。</p><h2 id="关于核心改动"><a href="#关于核心改动" class="headerlink" title="关于核心改动"></a>关于核心改动</h2><p>从 <code>nyalcf_core</code> 里面提取了小部分的代码，这些代码与 <code>nyalcf_ui</code> 深度绑定导致无法移除，所以统一提取到 <code>nyalcf_core_extend</code> 来解决这个问题。<br>同时 <code>nyalcf_inject</code> 本身也有部分与 <code>nyalcf_ui</code> 代码存在绑定关系，同样提取到了 <code>nyalcf_inject_extend</code> 以便去除 Flutter 依赖使得可以直接在命令行版本中使用 <code>nyalcf_inject</code> 。</p><h2 id="其他改动"><a href="#其他改动" class="headerlink" title="其他改动"></a>其他改动</h2><ul><li>现在窗口可以缩放的更小了</li><li>优化了开源许可证页面的展示</li><li>窗口默认大小变的更大了</li><li>深度链接集成</li></ul><p>更多改动在实际开发中可能会产生，最终结果请以往后 Releases 发布内容为准。<br>如果你有兴趣来维护这个项目，欢迎提交 PR 。贡献相关请查阅 <a class="link"   href="https://github.com/Muska-Ami/NyaLCF?tab=readme-ov-file#how-to-contribute" >https://github.com/Muska-Ami/NyaLCF?tab=readme-ov-file#how-to-contribute <i class="fa-regular fa-arrow-up-right-from-square fa-sm"></i></a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;关于该计划&quot;&gt;&lt;a href=&quot;#关于该计划&quot; class=&quot;headerlink&quot; title=&quot;关于该计划&quot;&gt;&lt;/a&gt;关于该计划&lt;/h2&gt;&lt;p&gt;由于当前启动器的代码体量并不小，为了便于维护，打算进一步模块化。&lt;br&gt;同时避免重复代码，将 &lt;code&gt;nyalc</summary>
      
    
    
    
    
    <category term="LoCyanFrp" scheme="https://blog.amaicat.work/tags/LoCyanFrp/"/>
    
    <category term="Nya LoCyanFrp!" scheme="https://blog.amaicat.work/tags/Nya-LoCyanFrp/"/>
    
    <category term="乐青映射" scheme="https://blog.amaicat.work/tags/%E4%B9%90%E9%9D%92%E6%98%A0%E5%B0%84/"/>
    
  </entry>
  
</feed>
