<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>隧道 on 猫猫鱼的小窝</title>
    <link>https://cat.fjh1997.top/tags/%E9%9A%A7%E9%81%93/</link>
    <description>Recent content from 猫猫鱼的小窝</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    
    <managingEditor>xxx@example.com (catcatyu)</managingEditor>
    <webMaster>xxx@example.com (catcatyu)</webMaster>
    
    <copyright>本博客所有文章除特别声明外，均采用 BY-NC-SA 许可协议。转载请注明出处！</copyright>
    
    <lastBuildDate>Sun, 13 Sep 2026 21:20:00 +0800</lastBuildDate>
    
    
    <atom:link href="https://cat.fjh1997.top/tags/%E9%9A%A7%E9%81%93/atom.xml" rel="self" type="application/rss&#43;xml" />
    

    
    

    <item>
      <title>用 Cloudflare Tunnel 绕过腾讯云对未备案域名的拦截与高频 TLS 的 RST 注入</title>
      <link>https://cat.fjh1997.top/posts/202609131.html</link>
      <pubDate>Sun, 13 Sep 2026 21:20:00 &#43;0800</pubDate>
      <author>xxx@example.com (catcatyu)</author>
      <guid>https://cat.fjh1997.top/posts/202609131.html</guid>
      <description>
        <![CDATA[<h1>用 Cloudflare Tunnel 绕过腾讯云对未备案域名的拦截与高频 TLS 的 RST 注入</h1><p>作者：catcatyu（xxx@example.com）</p>
        
          <p>背景：给学校 Web 安全课搭靶场，腾讯云大陆服务器（Ubuntu 24.04）上跑了三个靶站，用 nginx 按 Host 分流到 bug1/bug2/bug3 三个子域。域名没备案，于是踩了一整条腾讯云拦截链，最后用 Cloudflare Tunnel 一步到位。本文记录完整的排查和绕过过程。</p>
<h2 id="第一层拦截未备案域名的-80-端口">
<a class="header-anchor" href="#%e7%ac%ac%e4%b8%80%e5%b1%82%e6%8b%a6%e6%88%aa%e6%9c%aa%e5%a4%87%e6%a1%88%e5%9f%9f%e5%90%8d%e7%9a%84-80-%e7%ab%af%e5%8f%a3"></a>
第一层拦截：未备案域名的 80 端口
</h2><p>腾讯云对大陆服务器上未备案的域名拦截方式很明确：<strong>按 Host 头拦明文 HTTP</strong>。不管你跑在 80 还是 8080 之类任意端口，只要请求里 Host 是未备案域名，都会被 302 到 dnspod 的 webblock 页面。</p>
<p>但 <strong>443 的 TLS + SNI 不拦</strong>——TLS 握手之后腾讯看不到 Host 头，SNI 检查又没做。</p>
<p>所以第一版方案：域名托管到 Cloudflare（橙云），SSL 模式设 <strong>Full</strong>。这样访客不管走 http 还是 https，CF 都从 443 回源，完全绕开 80 端口的明文拦截。三站全通，稳定跑了一段时间。</p>
<h2 id="第二层cf-的两个副作用">
<a class="header-anchor" href="#%e7%ac%ac%e4%ba%8c%e5%b1%82cf-%e7%9a%84%e4%b8%a4%e4%b8%aa%e5%89%af%e4%bd%9c%e7%94%a8"></a>
第二层：CF 的两个副作用
</h2><p>上 POC 扫描工具（dddd，nuclei 内核）后遇到两个问题：</p>
<p><strong>1. Bot 防护按 UA 拦截（error 1010）</strong>。扫描器目录探测用的 UA 是 <code>Python-urllib/2.5</code>，直接被 CF 403。关掉 Bot Fight Mode 和 Browser Integrity Check 即可。</p>
<p><strong>2. CF 替换响应头导致被动指纹丢失</strong>。CF 会把源站的 <code>Server:</code> 头改写成 <code>cloudflare</code>，其他特征头也可能剥离。我的扫描器靠被动指纹（响应头/body 特征）来决定打哪些 POC，指纹丢了 POC 就不触发。修复方式是在源站 nginx 加自定义头：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-nginx" data-lang="nginx"><span class="line"><span class="cl"><span class="k">add_header</span> <span class="s">X-Powered-By</span> <span class="s">&#34;ThinkPHP&#34;</span> <span class="s">always</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>CF 对自定义头是透传的，指纹恢复，扫描正常命中。到这里一切正常——直到某天扫描突然全挂。</p>
<h2 id="第三层腾讯云-ccddos-防护的-rst-注入">
<a class="header-anchor" href="#%e7%ac%ac%e4%b8%89%e5%b1%82%e8%85%be%e8%ae%af%e4%ba%91-ccddos-%e9%98%b2%e6%8a%a4%e7%9a%84-rst-%e6%b3%a8%e5%85%a5"></a>
第三层：腾讯云 CC/DDoS 防护的 RST 注入
</h2><p>某天集中跑了很多轮批量扫描之后，所有请求开始返回 <strong>Cloudflare error 525</strong>（CF 与源站 SSL 握手失败）。排查过程：</p>
<ol>
<li>服务器本机 <code>curl https://127.0.0.1</code> → 200，源站 nginx 本身没问题</li>
<li>直连源站 IP 的 443（<code>--resolve</code> 绕过 DNS）→ 也失败，errno 113。<strong>不是 CF 单向的问题</strong></li>
<li>SSH（22 端口）完全正常 → 不是整机断网</li>
<li>服务器上 tcpdump 抓包，看到关键现象：</li>
</ol>
<pre tabindex="0"><code>CF 的 TCP 握手 + ClientHello 到达源站，内核正常 ACK，
但 nginx 的 ServerHello 从未发出，约 52μs 后一个 RST 把连接掐断。
</code></pre><p>这个 52μs 的 RST 是<strong>注入的</strong>——腾讯云的 CC/DDoS 防护识别到境外 IP（CF 回源节点）的高频 TLS 连接，直接在链路上注入 RST。而且它是<strong>概率性</strong>的：反复测试发现不是按域名拦、也不是按 IP 无差别拦，时好时坏，成功率飘忽。等几个小时也不会完全恢复，半激活状态会持续很久。</p>
<p>结论：只要流量从<strong>入站方向</strong>进 443，无论直连还是过 CDN，都可能被干扰。</p>
<h2 id="解法cloudflare-tunnel-出站隧道">
<a class="header-anchor" href="#%e8%a7%a3%e6%b3%95cloudflare-tunnel-%e5%87%ba%e7%ab%99%e9%9a%a7%e9%81%93"></a>
解法：Cloudflare Tunnel 出站隧道
</h2><p>思路很直接：腾讯云拦的是入站，那让源站<strong>主动向外</strong>建立持久连接，访问流量全部从隧道里走，入站拦截彻底失效。</p>
<h3 id="步骤">
<a class="header-anchor" href="#%e6%ad%a5%e9%aa%a4"></a>
步骤
</h3><p><strong>1. 安装 cloudflared</strong>（服务器连不上 GitHub，本地走代理下载再 scp 上去）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">curl -sL -x http://127.0.0.1:10808 -o cloudflared-linux-amd64.deb <span class="se">\
</span></span></span><span class="line"><span class="cl">  <span class="s2">&#34;https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb&#34;</span>
</span></span><span class="line"><span class="cl">scp cloudflared-linux-amd64.deb root@服务器IP:/tmp/
</span></span><span class="line"><span class="cl">dpkg -i /tmp/cloudflared-linux-amd64.deb
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>2. 授权并创建隧道</strong>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cloudflared tunnel login        <span class="c1"># 浏览器打开链接，选择域名授权</span>
</span></span><span class="line"><span class="cl">cloudflared tunnel create lab-tunnel
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>3. 写配置</strong> <code>/root/.cloudflared/config.yml</code>：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">tunnel</span><span class="p">:</span><span class="w"> </span><span class="l">&lt;tunnel-uuid&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">credentials-file</span><span class="p">:</span><span class="w"> </span><span class="l">/root/.cloudflared/&lt;tunnel-uuid&gt;.json</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">ingress</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l">bug1.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">http://127.0.0.1:80</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l">bug2.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">http://127.0.0.1:80</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">hostname</span><span class="p">:</span><span class="w"> </span><span class="l">bug3.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">http://127.0.0.1:80</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">service</span><span class="p">:</span><span class="w"> </span><span class="l">http_status:404</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>ingress 指向 <code>127.0.0.1:80</code>，nginx 继续按 server_name 分流，<strong>原有 vhost 配置一行不用改</strong>。</p>
<p><strong>4. 切换 DNS</strong>。先把域名上原有的三条 A 记录（橙云指向服务器 IP）删掉，再绑隧道 CNAME：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cloudflared tunnel route dns lab-tunnel bug1.example.com
</span></span><span class="line"><span class="cl">cloudflared tunnel route dns lab-tunnel bug2.example.com
</span></span><span class="line"><span class="cl">cloudflared tunnel route dns lab-tunnel bug3.example.com
</span></span></code></pre></td></tr></table>
</div>
</div><p>不删旧 A 记录会报 already exists 冲突。</p>
<p><strong>5. 装成 systemd 服务</strong>（重启不丢）：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">cloudflared service install
</span></span><span class="line"><span class="cl">systemctl <span class="nb">enable</span> --now cloudflared
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="效果">
<a class="header-anchor" href="#%e6%95%88%e6%9e%9c"></a>
效果
</h3><p>cloudflared 建立了 4 条 QUIC 出站连接（落地在 LAX/SJC），三站全部恢复 200，之前加的 <code>X-Powered-By</code> 自定义指纹头照样透传，扫描器 21 发命中全部恢复，之后多轮扫描零失败。</p>
<h2 id="小结">
<a class="header-anchor" href="#%e5%b0%8f%e7%bb%93"></a>
小结
</h2><table>
  <thead>
      <tr>
          <th>层级</th>
          <th>拦截方式</th>
          <th>绕过方式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>未备案域名 80 端口</td>
          <td>按 Host 头 302 webblock</td>
          <td>CF 橙云 Full 模式 443 回源</td>
      </tr>
      <tr>
          <td>CF Bot 防护</td>
          <td>按 UA 403（error 1010）</td>
          <td>关 Bot Fight Mode / 换 UA</td>
      </tr>
      <tr>
          <td>CF 头改写</td>
          <td>被动指纹丢失</td>
          <td>源站加自定义头，CF 透传</td>
      </tr>
      <tr>
          <td>CC/DDoS 防护 RST 注入</td>
          <td>入站高频 TLS 注入 RST（概率性）</td>
          <td><strong>Cloudflare Tunnel 出站隧道</strong></td>
      </tr>
  </tbody>
</table>
<p>经验总结：</p>
<ul>
<li>腾讯云对未备案域名的明文 HTTP 是死路，443 TLS+SNI 是活路，但活路会被 CC 防护的概率性 RST 注入污染</li>
<li>遇到 525 + 直连源站握手失败 + 本机正常 + SSH 正常的组合，优先怀疑链路中间的防护设备，抓包看 RST 时序（μs 级 RST 基本就是注入）</li>
<li>出站隧道是治本方案：云厂商对出站方向的管控远松于入站，cloudflared 用 QUIC 长连接，扫描类高频流量全部走隧道，源站甚至可以不再暴露公网 443</li>
<li>附带收益：切隧道后源站 IP 不再需要 DNS 解析暴露，可以配合防火墙把 80/443 入站全关，只留 SSH</li>
</ul>

        
        <hr><p>本文2026-09-13首发于<a href='https://cat.fjh1997.top/'>猫猫鱼的小窝</a>，最后修改于2026-09-13</p>]]>
      </description>
      
    </item>
    
  </channel>
</rss>
