国外vps被封?使用Cloudflare + Nginx + v2**y,戴丽服务搭建
<div class="ce-block" data-id="JlRNwC8dap" ><div class="ce-block__content" style="">
<h1 class="ce-header ce-header--left">Cloudflare + Nginx + v2**y:戴丽服务搭建与排障指南</h1>
</div>
</div><div class="ce-block ce-block--focused" data-id="n3tdFjW7xH" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">昨天刷到一个免费注册域名的帖子在<span> </span><a href="https://my.dnshe.com/" rel="noopener nofollow ugc">https://my.dnshe.com/</a><span> </span>注册了一个**.cc.cd的二级域名;可以在cf托管。于是找到之前被封的一个vps,搭建了一个戴丽服务:本文记录一套使用 Cloudflare 橙云戴丽、Nginx 和 v2**y 的部署方法:客户端通过域名访问 Cloudflare,由 Cloudflare 通过 HTTPS 回源到 VPS,再由 Nginx 将 WebSocket 请求转交给本机 v2**y。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="0fIBnmeOwa" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">除了安装配置,文章也整理了本次实际遇到的两个问题:TUN 模式下的 DNS 解析异常,以及客户端误用 TCP、未开启 TLS 导致连接失败。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="nNI9BWyULX" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">全文使用<span> </span><code>example.com</code><span> </span>作为示例域名。操作前请统一替换为自己的实际域名,UUID 则在自己的服务器上生成。</div>
</div>
</div><div class="ce-block" data-id="8_RJy_upcS" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">一、先理解整条访问链路</h2>
</div>
</div><div class="ce-block" data-id="iBWEe2mraH" >
<div class="ce-block__content">
<div class="cdx-block">
<div class="tc-wrap">
<div class="tc-table">
<div class="tc-row">
<div class="tc-cell">环节</div>
<div class="tc-cell">作用</div>
</div>
<div class="tc-row">
<div class="tc-cell">客户端</div>
<div class="tc-cell">接收需要戴丽的请求,封装为 VMess 数据,通过 WebSocket 和 TLS 发出</div>
</div>
<div class="tc-row">
<div class="tc-cell">Cloudflare</div>
<div class="tc-cell">接收客户端连接,将请求转发至 VPS 源站</div>
</div>
<div class="tc-row">
<div class="tc-cell">Nginx</div>
<div class="tc-cell">处理源站 HTTPS,根据<span> </span><code>/bridge</code><span> </span>路径转发 WebSocket 请求</div>
</div>
<div class="tc-row">
<div class="tc-cell">v2**y</div>
<div class="tc-cell">验证 UUID、解析 VMess 数据,连接真正的目标地址</div>
</div>
<div class="tc-row">
<div class="tc-cell">目标网站</div>
<div class="tc-cell">接收来自 VPS 的请求;出口通常是 VPS 的公网 IP</div>
</div>
</div>
</div>
</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="cO3po8sjVS" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">响应沿相反方向返回客户端。</div>
</div>
</div><div class="ce-block" data-id="pAzayjnKd2" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">为什么源站 IP 无法直连,也可能使用这套方案?</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="0ScXCnlpCV" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">开启橙云后,客户端查询域名得到的是 Cloudflare 边缘 IP,Cloudflare 再根据控制台中的记录连接 VPS。客户端不需要直接连接 VPS 的公网 IP。<a href="https://developers.cloudflare.com/dns/proxy-status/" rel="noopener nofollow ugc">Cloudflare 戴丽状态说明</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="Om1C_hYthQ" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">因此,实际需要满足的是:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="ZNXAcPN6Gv" >
<div class="ce-block__content">
<ul class="cdx-list-unordered"><li class="cdx-list__item">客户端能够访问该域名对应的 Cloudflare 边缘节点。</li><li class="cdx-list__item">Cloudflare 能够通过 HTTPS 连接 VPS。</li><li class="cdx-list__item">VPS 能够访问目标网站或服务。</li></ul>
</div>
</div><div class="ce-block ce-block--focused" data-id="OuvU-0pC9g" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">域名只是使用 Cloudflare DNS、但记录未开启橙云时,不具备上述转发效果。Cloudflare 节点和域名的可达性仍受实际网络影响,这套方案不能保证长期在所有网络上可用。</div>
</div>
</div><div class="ce-block" data-id="9SRUyrZryw" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">TLS、WebSocket 和 VMess 分别负责什么?</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="m_W5Rktnb-" >
<div class="ce-block__content">
<ul class="cdx-list-unordered"><li class="cdx-list__item">TLS:保护链路传输。客户端到 Cloudflare、Cloudflare 到 Nginx 是两段独立的 TLS 连接。</li><li class="cdx-list__item">WebSocket:承载戴丽数据,使其能够经过 HTTP 反向戴丽链路。</li><li class="cdx-list__item">VMess:负责客户端与 v2**y 之间的认证和戴丽数据传输。本文客户端使用<span> </span><code>auto</code><span> </span>加密,内部 VMess 数据仍有加密保护。</li><li class="cdx-list__item">UUID:VMess 的认证凭据,客户端和服务端必须一致。</li><li class="cdx-list__item"><code>/bridge</code>:WebSocket 路径,客户端、Nginx 和 v2**y 必须一致。</li></ul>
</div>
</div><div class="ce-block ce-block--focused" data-id="rUYhbBVnzC" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">Cloudflare 会终止客户端 TLS,因此不能将整条链路理解为一条从客户端直达 VPS 的 TLS 连接。<a href="https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/" rel="noopener nofollow ugc">Full (strict) 说明</a>、<a href="https://www.v2fly.org/config/protocols/vmess.html" rel="noopener nofollow ugc">VMess 配置说明</a></div>
</div>
</div><div class="ce-block" data-id="ioqxdhapic" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">二、准备环境和参数</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="jOxrvveWAQ" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">本文使用以下环境:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="YC0BEGd7If" >
<div class="ce-block__content">
<ul class="cdx-list-unordered"><li class="cdx-list__item">一台能够管理的 Ubuntu / Debian VPS,使用 systemd。</li><li class="cdx-list__item">一个已经接入 Cloudflare、状态为 Active 的域名。</li><li class="cdx-list__item">Windows 客户端 v2**yN。</li><li class="cdx-list__item">VPS 公网 TCP 443 端口可供 Cloudflare 回源。</li></ul>
</div>
</div><div class="ce-block ce-block--focused" data-id="-g6ca1wNOP" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">如果 VPS 已经安装 Nginx 或 v2**y,请先检查现有配置,合并对应配置,避免覆盖正在使用的服务。以下步骤按新部署示例编写。</div>
</div>
</div><div class="ce-block" data-id="ccxjCFlSZ9" >
<div class="ce-block__content">
<div class="cdx-block">
<div class="tc-wrap">
<div class="tc-table">
<div class="tc-row">
<div class="tc-cell">参数</div>
<div class="tc-cell">本文示例</div>
</div>
<div class="tc-row">
<div class="tc-cell">连接域名</div>
<div class="tc-cell"><code>example.com</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">公网 HTTPS 端口</div>
<div class="tc-cell"><code>443</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">v2**y 监听地址</div>
<div class="tc-cell"><code>127.0.0.1</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">v2**y 监听端口</div>
<div class="tc-cell"><code>10000</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">WebSocket 路径</div>
<div class="tc-cell"><code>/bridge</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">协议</div>
<div class="tc-cell"><code>VMess</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">传输方式</div>
<div class="tc-cell"><code>ws</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">客户端加密方式</div>
<div class="tc-cell"><code>auto</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">AlterID</div>
<div class="tc-cell"><code>0</code></div>
</div>
</div>
</div>
</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="SOTEz3XMd1" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">如果改用<span> </span><code>富强.example.com</code>,需要同步修改 DNS 记录、Nginx 的<span> </span><code>server_name</code><span> </span>和客户端的地址、Host、SNI。</div>
</div>
</div><div class="ce-block" data-id="WLcYa1HlIa" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">三、配置 Cloudflare DNS</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="pwZYSmBt28" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">进入域名的<span> </span>DNS → Records → Add record,添加:</div>
</div>
</div><div class="ce-block" data-id="xlDWGR4jbL" >
<div class="ce-block__content">
<div class="cdx-block">
<div class="tc-wrap">
<div class="tc-table">
<div class="tc-row">
<div class="tc-cell">字段</div>
<div class="tc-cell">内容</div>
</div>
<div class="tc-row">
<div class="tc-cell">Type</div>
<div class="tc-cell"><code>A</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">Name</div>
<div class="tc-cell"><code>@</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">IPv4 address</div>
<div class="tc-cell">VPS 的实际公网 IPv4</div>
</div>
<div class="tc-row">
<div class="tc-cell">Proxy status</div>
<div class="tc-cell">Proxied,橙云开启</div>
</div>
<div class="tc-row">
<div class="tc-cell">TTL</div>
<div class="tc-cell"><code>Auto</code></div>
</div>
</div>
</div>
</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="eMTG6rviJt" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"><code>@</code><span> </span>代表主域名<span> </span><code>example.com</code>。若使用<span> </span><code>V*N.example.com</code>,Name 填<span> </span><code>V*N</code>。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="YWvweNO9Jr" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">保存后可以在 Windows PowerShell 中查询:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="hkg0wWmUHH" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-hkg0wWmUHH">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-hkg0wWmUHH">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-hkg0wWmUHH" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-hkg0wWmUHH">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439mdvUH = document.getElementById('codeflask-hkg0wWmUHH');
var isCollapsed1790134439mdvUH = true;
const flask1790134439mdvUH = new CodeFlask(editorElem1790134439mdvUH, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439mdvUH = `nslookup example.com`;
code1790134439mdvUH = code1790134439mdvUH.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439mdvUH.addLanguage('shell', Prism.languages['shell']);
flask1790134439mdvUH.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439mdvUH.updateCode(code1790134439mdvUH);
const currentCode1790134439mdvUH = flask1790134439mdvUH.getCode();
var coderow1790134439mdvUH = parseInt('');
if (coderow1790134439mdvUH === undefined || coderow1790134439mdvUH !== coderow1790134439mdvUH || coderow1790134439mdvUH === 0) {
coderow1790134439mdvUH = flask1790134439mdvUH.lineNumber;
}
if (coderow1790134439mdvUH < 20) {
editorElem1790134439mdvUH.parentElement.style.height = '300px';
editorElem1790134439mdvUH.style.height = '300px';
} else if (coderow1790134439mdvUH >= 20) {
editorElem1790134439mdvUH.parentElement.style.height = '500px';
editorElem1790134439mdvUH.style.height = '500px';
}
//console.log({currentCode1790134439mdvUH})
const copyBtn1790134439mdvUH = document.getElementById('codeflask-copy-hkg0wWmUHH');
copyBtn1790134439mdvUH.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439mdvUH).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439mdvUH.innerHTML;
copyBtn1790134439mdvUH.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439mdvUH.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439mdvUH);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439mdvUH);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439mdvUH.innerHTML;
copyBtn1790134439mdvUH.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439mdvUH.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439mdvUH = document.getElementById('codeflask-bottomBtn-hkg0wWmUHH');
const Toggle1790134439mdvUH = document.getElementById('codeflask-Toggle-hkg0wWmUHH');
bottomBtn1790134439mdvUH.addEventListener('click', function() {
if (isCollapsed1790134439mdvUH) {
// 展开代码
isCollapsed1790134439mdvUH = false;
const codeElement1790134439mdvUH = editorElem1790134439mdvUH.querySelector('.codeflask__code');
if (codeElement1790134439mdvUH) {
const actualHeight1790134439mdvUH = codeElement1790134439mdvUH.scrollHeight + 20;
editorElem1790134439mdvUH.parentElement.style.height = actualHeight1790134439mdvUH + 'px';
editorElem1790134439mdvUH.style.height = actualHeight1790134439mdvUH + 'px';
}
bottomBtn1790134439mdvUH.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439mdvUH.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439mdvUH = true;
if (coderow1790134439mdvUH < 20) {
editorElem1790134439mdvUH.parentElement.style.height = '300px';
editorElem1790134439mdvUH.style.height = '300px';
} else if (coderow1790134439mdvUH >= 20) {
editorElem1790134439mdvUH.parentElement.style.height = '500px';
editorElem1790134439mdvUH.style.height = '500px';
}
bottomBtn1790134439mdvUH.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439mdvUH.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439mdvUH.addEventListener('click', function() {
bottomBtn1790134439mdvUH.click();
});
</script><div class="ce-block ce-block--focused" data-id="oFL4PgqR2h" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">橙云生效后,应查询到 Cloudflare 的地址。新增记录可能受已有 DNS 缓存影响,不要把一次查询无结果直接当成记录不存在。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="80t3AbSoYK" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">证书中的<span> </span><code>example.com</code><span> </span>或<span> </span><code>*.example.com</code><span> </span>仅表示证书覆盖范围,不会自动创建 DNS 记录。</div>
</div>
</div><div class="ce-block" data-id="DP-BK4FE_q" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">四、安装 Nginx 和 v2**y</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="wFeQOV4LLZ" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">本节命令全部在 VPS 的 Linux 终端执行。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="jmXq1Bldcp" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">安装依赖:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="EImX6S8R_e" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-EImX6S8R_e">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-EImX6S8R_e">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-EImX6S8R_e" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-EImX6S8R_e">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439uTPYu = document.getElementById('codeflask-EImX6S8R_e');
var isCollapsed1790134439uTPYu = true;
const flask1790134439uTPYu = new CodeFlask(editorElem1790134439uTPYu, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439uTPYu = `sudo apt update
sudo apt install -y nginx curl ca-certificates unzip nano`;
code1790134439uTPYu = code1790134439uTPYu.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439uTPYu.addLanguage('shell', Prism.languages['shell']);
flask1790134439uTPYu.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439uTPYu.updateCode(code1790134439uTPYu);
const currentCode1790134439uTPYu = flask1790134439uTPYu.getCode();
var coderow1790134439uTPYu = parseInt('');
if (coderow1790134439uTPYu === undefined || coderow1790134439uTPYu !== coderow1790134439uTPYu || coderow1790134439uTPYu === 0) {
coderow1790134439uTPYu = flask1790134439uTPYu.lineNumber;
}
if (coderow1790134439uTPYu < 20) {
editorElem1790134439uTPYu.parentElement.style.height = '300px';
editorElem1790134439uTPYu.style.height = '300px';
} else if (coderow1790134439uTPYu >= 20) {
editorElem1790134439uTPYu.parentElement.style.height = '500px';
editorElem1790134439uTPYu.style.height = '500px';
}
//console.log({currentCode1790134439uTPYu})
const copyBtn1790134439uTPYu = document.getElementById('codeflask-copy-EImX6S8R_e');
copyBtn1790134439uTPYu.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439uTPYu).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439uTPYu.innerHTML;
copyBtn1790134439uTPYu.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439uTPYu.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439uTPYu);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439uTPYu);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439uTPYu.innerHTML;
copyBtn1790134439uTPYu.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439uTPYu.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439uTPYu = document.getElementById('codeflask-bottomBtn-EImX6S8R_e');
const Toggle1790134439uTPYu = document.getElementById('codeflask-Toggle-EImX6S8R_e');
bottomBtn1790134439uTPYu.addEventListener('click', function() {
if (isCollapsed1790134439uTPYu) {
// 展开代码
isCollapsed1790134439uTPYu = false;
const codeElement1790134439uTPYu = editorElem1790134439uTPYu.querySelector('.codeflask__code');
if (codeElement1790134439uTPYu) {
const actualHeight1790134439uTPYu = codeElement1790134439uTPYu.scrollHeight + 20;
editorElem1790134439uTPYu.parentElement.style.height = actualHeight1790134439uTPYu + 'px';
editorElem1790134439uTPYu.style.height = actualHeight1790134439uTPYu + 'px';
}
bottomBtn1790134439uTPYu.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439uTPYu.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439uTPYu = true;
if (coderow1790134439uTPYu < 20) {
editorElem1790134439uTPYu.parentElement.style.height = '300px';
editorElem1790134439uTPYu.style.height = '300px';
} else if (coderow1790134439uTPYu >= 20) {
editorElem1790134439uTPYu.parentElement.style.height = '500px';
editorElem1790134439uTPYu.style.height = '500px';
}
bottomBtn1790134439uTPYu.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439uTPYu.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439uTPYu.addEventListener('click', function() {
bottomBtn1790134439uTPYu.click();
});
</script><div class="ce-block ce-block--focused" data-id="Bi3KxFVjpa" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 下载并运行 V2Fly 官方安装脚本:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="CmZDWUG6UH" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-CmZDWUG6UH">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-CmZDWUG6UH">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-CmZDWUG6UH" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-CmZDWUG6UH">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439zH32k = document.getElementById('codeflask-CmZDWUG6UH');
var isCollapsed1790134439zH32k = true;
const flask1790134439zH32k = new CodeFlask(editorElem1790134439zH32k, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439zH32k = `curl -fL https://raw.githubusercontent.com/v2fly/fhs-install-v2**y/master/install-release.sh \
-o /tmp/install-v2**y.sh`;
code1790134439zH32k = code1790134439zH32k.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439zH32k.addLanguage('shell', Prism.languages['shell']);
flask1790134439zH32k.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439zH32k.updateCode(code1790134439zH32k);
const currentCode1790134439zH32k = flask1790134439zH32k.getCode();
var coderow1790134439zH32k = parseInt('');
if (coderow1790134439zH32k === undefined || coderow1790134439zH32k !== coderow1790134439zH32k || coderow1790134439zH32k === 0) {
coderow1790134439zH32k = flask1790134439zH32k.lineNumber;
}
if (coderow1790134439zH32k < 20) {
editorElem1790134439zH32k.parentElement.style.height = '300px';
editorElem1790134439zH32k.style.height = '300px';
} else if (coderow1790134439zH32k >= 20) {
editorElem1790134439zH32k.parentElement.style.height = '500px';
editorElem1790134439zH32k.style.height = '500px';
}
//console.log({currentCode1790134439zH32k})
const copyBtn1790134439zH32k = document.getElementById('codeflask-copy-CmZDWUG6UH');
copyBtn1790134439zH32k.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439zH32k).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439zH32k.innerHTML;
copyBtn1790134439zH32k.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439zH32k.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439zH32k);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439zH32k);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439zH32k.innerHTML;
copyBtn1790134439zH32k.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439zH32k.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439zH32k = document.getElementById('codeflask-bottomBtn-CmZDWUG6UH');
const Toggle1790134439zH32k = document.getElementById('codeflask-Toggle-CmZDWUG6UH');
bottomBtn1790134439zH32k.addEventListener('click', function() {
if (isCollapsed1790134439zH32k) {
// 展开代码
isCollapsed1790134439zH32k = false;
const codeElement1790134439zH32k = editorElem1790134439zH32k.querySelector('.codeflask__code');
if (codeElement1790134439zH32k) {
const actualHeight1790134439zH32k = codeElement1790134439zH32k.scrollHeight + 20;
editorElem1790134439zH32k.parentElement.style.height = actualHeight1790134439zH32k + 'px';
editorElem1790134439zH32k.style.height = actualHeight1790134439zH32k + 'px';
}
bottomBtn1790134439zH32k.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439zH32k.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439zH32k = true;
if (coderow1790134439zH32k < 20) {
editorElem1790134439zH32k.parentElement.style.height = '300px';
editorElem1790134439zH32k.style.height = '300px';
} else if (coderow1790134439zH32k >= 20) {
editorElem1790134439zH32k.parentElement.style.height = '500px';
editorElem1790134439zH32k.style.height = '500px';
}
bottomBtn1790134439zH32k.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439zH32k.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439zH32k.addEventListener('click', function() {
bottomBtn1790134439zH32k.click();
});
</script><div class="ce-block ce-block--focused" data-id="HIsxY6DE4o" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 上一步下载成功后执行:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="-9dFPZaiIE" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy--9dFPZaiIE">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle--9dFPZaiIE">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask--9dFPZaiIE" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn--9dFPZaiIE">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439I1d3N = document.getElementById('codeflask--9dFPZaiIE');
var isCollapsed1790134439I1d3N = true;
const flask1790134439I1d3N = new CodeFlask(editorElem1790134439I1d3N, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439I1d3N = `sudo bash /tmp/install-v2**y.sh`;
code1790134439I1d3N = code1790134439I1d3N.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439I1d3N.addLanguage('shell', Prism.languages['shell']);
flask1790134439I1d3N.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439I1d3N.updateCode(code1790134439I1d3N);
const currentCode1790134439I1d3N = flask1790134439I1d3N.getCode();
var coderow1790134439I1d3N = parseInt('');
if (coderow1790134439I1d3N === undefined || coderow1790134439I1d3N !== coderow1790134439I1d3N || coderow1790134439I1d3N === 0) {
coderow1790134439I1d3N = flask1790134439I1d3N.lineNumber;
}
if (coderow1790134439I1d3N < 20) {
editorElem1790134439I1d3N.parentElement.style.height = '300px';
editorElem1790134439I1d3N.style.height = '300px';
} else if (coderow1790134439I1d3N >= 20) {
editorElem1790134439I1d3N.parentElement.style.height = '500px';
editorElem1790134439I1d3N.style.height = '500px';
}
//console.log({currentCode1790134439I1d3N})
const copyBtn1790134439I1d3N = document.getElementById('codeflask-copy--9dFPZaiIE');
copyBtn1790134439I1d3N.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439I1d3N).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439I1d3N.innerHTML;
copyBtn1790134439I1d3N.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439I1d3N.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439I1d3N);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439I1d3N);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439I1d3N.innerHTML;
copyBtn1790134439I1d3N.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439I1d3N.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439I1d3N = document.getElementById('codeflask-bottomBtn--9dFPZaiIE');
const Toggle1790134439I1d3N = document.getElementById('codeflask-Toggle--9dFPZaiIE');
bottomBtn1790134439I1d3N.addEventListener('click', function() {
if (isCollapsed1790134439I1d3N) {
// 展开代码
isCollapsed1790134439I1d3N = false;
const codeElement1790134439I1d3N = editorElem1790134439I1d3N.querySelector('.codeflask__code');
if (codeElement1790134439I1d3N) {
const actualHeight1790134439I1d3N = codeElement1790134439I1d3N.scrollHeight + 20;
editorElem1790134439I1d3N.parentElement.style.height = actualHeight1790134439I1d3N + 'px';
editorElem1790134439I1d3N.style.height = actualHeight1790134439I1d3N + 'px';
}
bottomBtn1790134439I1d3N.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439I1d3N.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439I1d3N = true;
if (coderow1790134439I1d3N < 20) {
editorElem1790134439I1d3N.parentElement.style.height = '300px';
editorElem1790134439I1d3N.style.height = '300px';
} else if (coderow1790134439I1d3N >= 20) {
editorElem1790134439I1d3N.parentElement.style.height = '500px';
editorElem1790134439I1d3N.style.height = '500px';
}
bottomBtn1790134439I1d3N.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439I1d3N.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439I1d3N.addEventListener('click', function() {
bottomBtn1790134439I1d3N.click();
});
</script><div class="ce-block ce-block--focused" data-id="jJGB7SlMfL" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">该安装方式默认使用<span> </span><code>/usr/local/etc/v2**y/config.json</code>,服务名称为<span> </span><code>v2**y</code>。本文使用 v2**y 5.x 的命令行以及传统 JSON 配置格式,不使用<span> </span><code>jsonv5</code><span> </span>格式。<a href="https://github.com/v2fly/fhs-install-v2**y" rel="noopener nofollow ugc">官方安装说明</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="jC4XYZ2R3i" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">查看安装版本:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="8vtEhcj01K" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-8vtEhcj01K">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-8vtEhcj01K">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-8vtEhcj01K" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-8vtEhcj01K">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439Rz0fd = document.getElementById('codeflask-8vtEhcj01K');
var isCollapsed1790134439Rz0fd = true;
const flask1790134439Rz0fd = new CodeFlask(editorElem1790134439Rz0fd, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439Rz0fd = `/usr/local/bin/v2**y version`;
code1790134439Rz0fd = code1790134439Rz0fd.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439Rz0fd.addLanguage('shell', Prism.languages['shell']);
flask1790134439Rz0fd.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439Rz0fd.updateCode(code1790134439Rz0fd);
const currentCode1790134439Rz0fd = flask1790134439Rz0fd.getCode();
var coderow1790134439Rz0fd = parseInt('');
if (coderow1790134439Rz0fd === undefined || coderow1790134439Rz0fd !== coderow1790134439Rz0fd || coderow1790134439Rz0fd === 0) {
coderow1790134439Rz0fd = flask1790134439Rz0fd.lineNumber;
}
if (coderow1790134439Rz0fd < 20) {
editorElem1790134439Rz0fd.parentElement.style.height = '300px';
editorElem1790134439Rz0fd.style.height = '300px';
} else if (coderow1790134439Rz0fd >= 20) {
editorElem1790134439Rz0fd.parentElement.style.height = '500px';
editorElem1790134439Rz0fd.style.height = '500px';
}
//console.log({currentCode1790134439Rz0fd})
const copyBtn1790134439Rz0fd = document.getElementById('codeflask-copy-8vtEhcj01K');
copyBtn1790134439Rz0fd.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439Rz0fd).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439Rz0fd.innerHTML;
copyBtn1790134439Rz0fd.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439Rz0fd.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439Rz0fd);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439Rz0fd);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439Rz0fd.innerHTML;
copyBtn1790134439Rz0fd.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439Rz0fd.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439Rz0fd = document.getElementById('codeflask-bottomBtn-8vtEhcj01K');
const Toggle1790134439Rz0fd = document.getElementById('codeflask-Toggle-8vtEhcj01K');
bottomBtn1790134439Rz0fd.addEventListener('click', function() {
if (isCollapsed1790134439Rz0fd) {
// 展开代码
isCollapsed1790134439Rz0fd = false;
const codeElement1790134439Rz0fd = editorElem1790134439Rz0fd.querySelector('.codeflask__code');
if (codeElement1790134439Rz0fd) {
const actualHeight1790134439Rz0fd = codeElement1790134439Rz0fd.scrollHeight + 20;
editorElem1790134439Rz0fd.parentElement.style.height = actualHeight1790134439Rz0fd + 'px';
editorElem1790134439Rz0fd.style.height = actualHeight1790134439Rz0fd + 'px';
}
bottomBtn1790134439Rz0fd.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439Rz0fd.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439Rz0fd = true;
if (coderow1790134439Rz0fd < 20) {
editorElem1790134439Rz0fd.parentElement.style.height = '300px';
editorElem1790134439Rz0fd.style.height = '300px';
} else if (coderow1790134439Rz0fd >= 20) {
editorElem1790134439Rz0fd.parentElement.style.height = '500px';
editorElem1790134439Rz0fd.style.height = '500px';
}
bottomBtn1790134439Rz0fd.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439Rz0fd.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439Rz0fd.addEventListener('click', function() {
bottomBtn1790134439Rz0fd.click();
});
</script><div class="ce-block ce-block--focused" data-id="rRUjtuOnGM" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 生成 UUID:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="uPVeC0i7_H" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-uPVeC0i7_H">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-uPVeC0i7_H">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-uPVeC0i7_H" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-uPVeC0i7_H">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439Diice = document.getElementById('codeflask-uPVeC0i7_H');
var isCollapsed1790134439Diice = true;
const flask1790134439Diice = new CodeFlask(editorElem1790134439Diice, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439Diice = `cat /proc/sys/kernel/random/uuid`;
code1790134439Diice = code1790134439Diice.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439Diice.addLanguage('shell', Prism.languages['shell']);
flask1790134439Diice.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439Diice.updateCode(code1790134439Diice);
const currentCode1790134439Diice = flask1790134439Diice.getCode();
var coderow1790134439Diice = parseInt('');
if (coderow1790134439Diice === undefined || coderow1790134439Diice !== coderow1790134439Diice || coderow1790134439Diice === 0) {
coderow1790134439Diice = flask1790134439Diice.lineNumber;
}
if (coderow1790134439Diice < 20) {
editorElem1790134439Diice.parentElement.style.height = '300px';
editorElem1790134439Diice.style.height = '300px';
} else if (coderow1790134439Diice >= 20) {
editorElem1790134439Diice.parentElement.style.height = '500px';
editorElem1790134439Diice.style.height = '500px';
}
//console.log({currentCode1790134439Diice})
const copyBtn1790134439Diice = document.getElementById('codeflask-copy-uPVeC0i7_H');
copyBtn1790134439Diice.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439Diice).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439Diice.innerHTML;
copyBtn1790134439Diice.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439Diice.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439Diice);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439Diice);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439Diice.innerHTML;
copyBtn1790134439Diice.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439Diice.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439Diice = document.getElementById('codeflask-bottomBtn-uPVeC0i7_H');
const Toggle1790134439Diice = document.getElementById('codeflask-Toggle-uPVeC0i7_H');
bottomBtn1790134439Diice.addEventListener('click', function() {
if (isCollapsed1790134439Diice) {
// 展开代码
isCollapsed1790134439Diice = false;
const codeElement1790134439Diice = editorElem1790134439Diice.querySelector('.codeflask__code');
if (codeElement1790134439Diice) {
const actualHeight1790134439Diice = codeElement1790134439Diice.scrollHeight + 20;
editorElem1790134439Diice.parentElement.style.height = actualHeight1790134439Diice + 'px';
editorElem1790134439Diice.style.height = actualHeight1790134439Diice + 'px';
}
bottomBtn1790134439Diice.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439Diice.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439Diice = true;
if (coderow1790134439Diice < 20) {
editorElem1790134439Diice.parentElement.style.height = '300px';
editorElem1790134439Diice.style.height = '300px';
} else if (coderow1790134439Diice >= 20) {
editorElem1790134439Diice.parentElement.style.height = '500px';
editorElem1790134439Diice.style.height = '500px';
}
bottomBtn1790134439Diice.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439Diice.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439Diice.addEventListener('click', function() {
bottomBtn1790134439Diice.click();
});
</script><div class="ce-block ce-block--focused" data-id="BCEdPhhJmI" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">保存这个值,服务端和客户端均使用同一个 UUID。</div>
</div>
</div><div class="ce-block" data-id="FAizKVow8B" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">五、配置 v2**y 服务端</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="ursXT3vHQh" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">编辑配置文件:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="Fc8U3kpvPL" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-Fc8U3kpvPL">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-Fc8U3kpvPL">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-Fc8U3kpvPL" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-Fc8U3kpvPL">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439a67A6 = document.getElementById('codeflask-Fc8U3kpvPL');
var isCollapsed1790134439a67A6 = true;
const flask1790134439a67A6 = new CodeFlask(editorElem1790134439a67A6, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439a67A6 = `sudo nano /usr/local/etc/v2**y/config.json`;
code1790134439a67A6 = code1790134439a67A6.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439a67A6.addLanguage('shell', Prism.languages['shell']);
flask1790134439a67A6.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439a67A6.updateCode(code1790134439a67A6);
const currentCode1790134439a67A6 = flask1790134439a67A6.getCode();
var coderow1790134439a67A6 = parseInt('');
if (coderow1790134439a67A6 === undefined || coderow1790134439a67A6 !== coderow1790134439a67A6 || coderow1790134439a67A6 === 0) {
coderow1790134439a67A6 = flask1790134439a67A6.lineNumber;
}
if (coderow1790134439a67A6 < 20) {
editorElem1790134439a67A6.parentElement.style.height = '300px';
editorElem1790134439a67A6.style.height = '300px';
} else if (coderow1790134439a67A6 >= 20) {
editorElem1790134439a67A6.parentElement.style.height = '500px';
editorElem1790134439a67A6.style.height = '500px';
}
//console.log({currentCode1790134439a67A6})
const copyBtn1790134439a67A6 = document.getElementById('codeflask-copy-Fc8U3kpvPL');
copyBtn1790134439a67A6.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439a67A6).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439a67A6.innerHTML;
copyBtn1790134439a67A6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439a67A6.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439a67A6);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439a67A6);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439a67A6.innerHTML;
copyBtn1790134439a67A6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439a67A6.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439a67A6 = document.getElementById('codeflask-bottomBtn-Fc8U3kpvPL');
const Toggle1790134439a67A6 = document.getElementById('codeflask-Toggle-Fc8U3kpvPL');
bottomBtn1790134439a67A6.addEventListener('click', function() {
if (isCollapsed1790134439a67A6) {
// 展开代码
isCollapsed1790134439a67A6 = false;
const codeElement1790134439a67A6 = editorElem1790134439a67A6.querySelector('.codeflask__code');
if (codeElement1790134439a67A6) {
const actualHeight1790134439a67A6 = codeElement1790134439a67A6.scrollHeight + 20;
editorElem1790134439a67A6.parentElement.style.height = actualHeight1790134439a67A6 + 'px';
editorElem1790134439a67A6.style.height = actualHeight1790134439a67A6 + 'px';
}
bottomBtn1790134439a67A6.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439a67A6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439a67A6 = true;
if (coderow1790134439a67A6 < 20) {
editorElem1790134439a67A6.parentElement.style.height = '300px';
editorElem1790134439a67A6.style.height = '300px';
} else if (coderow1790134439a67A6 >= 20) {
editorElem1790134439a67A6.parentElement.style.height = '500px';
editorElem1790134439a67A6.style.height = '500px';
}
bottomBtn1790134439a67A6.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439a67A6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439a67A6.addEventListener('click', function() {
bottomBtn1790134439a67A6.click();
});
</script><div class="ce-block ce-block--focused" data-id="jLykS7Vu5N" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 填入以下内容,将 <code>REPLACE_WITH_YOUR_UUID</code> 替换为刚才生成的 UUID:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="vAx3zNauEn" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">javascript</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-vAx3zNauEn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-vAx3zNauEn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-vAx3zNauEn" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-vAx3zNauEn">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439P6Lz6 = document.getElementById('codeflask-vAx3zNauEn');
var isCollapsed1790134439P6Lz6 = true;
const flask1790134439P6Lz6 = new CodeFlask(editorElem1790134439P6Lz6, {
language: 'javascript',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439P6Lz6 = `{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10000,
"protocol": "vmess",
"settings": {
"clients": [
{
"id": "REPLACE_WITH_YOUR_UUID",
"alterId": 0
}
]
},
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"path": "/bridge"
}
}
}
],
"outbounds": [
{
"protocol": "freedom"
}
]
}`;
code1790134439P6Lz6 = code1790134439P6Lz6.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439P6Lz6.addLanguage('javascript', Prism.languages['javascript']);
flask1790134439P6Lz6.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439P6Lz6.updateCode(code1790134439P6Lz6);
const currentCode1790134439P6Lz6 = flask1790134439P6Lz6.getCode();
var coderow1790134439P6Lz6 = parseInt('');
if (coderow1790134439P6Lz6 === undefined || coderow1790134439P6Lz6 !== coderow1790134439P6Lz6 || coderow1790134439P6Lz6 === 0) {
coderow1790134439P6Lz6 = flask1790134439P6Lz6.lineNumber;
}
if (coderow1790134439P6Lz6 < 20) {
editorElem1790134439P6Lz6.parentElement.style.height = '300px';
editorElem1790134439P6Lz6.style.height = '300px';
} else if (coderow1790134439P6Lz6 >= 20) {
editorElem1790134439P6Lz6.parentElement.style.height = '500px';
editorElem1790134439P6Lz6.style.height = '500px';
}
//console.log({currentCode1790134439P6Lz6})
const copyBtn1790134439P6Lz6 = document.getElementById('codeflask-copy-vAx3zNauEn');
copyBtn1790134439P6Lz6.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439P6Lz6).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439P6Lz6.innerHTML;
copyBtn1790134439P6Lz6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439P6Lz6.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439P6Lz6);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439P6Lz6);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439P6Lz6.innerHTML;
copyBtn1790134439P6Lz6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439P6Lz6.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439P6Lz6 = document.getElementById('codeflask-bottomBtn-vAx3zNauEn');
const Toggle1790134439P6Lz6 = document.getElementById('codeflask-Toggle-vAx3zNauEn');
bottomBtn1790134439P6Lz6.addEventListener('click', function() {
if (isCollapsed1790134439P6Lz6) {
// 展开代码
isCollapsed1790134439P6Lz6 = false;
const codeElement1790134439P6Lz6 = editorElem1790134439P6Lz6.querySelector('.codeflask__code');
if (codeElement1790134439P6Lz6) {
const actualHeight1790134439P6Lz6 = codeElement1790134439P6Lz6.scrollHeight + 20;
editorElem1790134439P6Lz6.parentElement.style.height = actualHeight1790134439P6Lz6 + 'px';
editorElem1790134439P6Lz6.style.height = actualHeight1790134439P6Lz6 + 'px';
}
bottomBtn1790134439P6Lz6.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439P6Lz6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439P6Lz6 = true;
if (coderow1790134439P6Lz6 < 20) {
editorElem1790134439P6Lz6.parentElement.style.height = '300px';
editorElem1790134439P6Lz6.style.height = '300px';
} else if (coderow1790134439P6Lz6 >= 20) {
editorElem1790134439P6Lz6.parentElement.style.height = '500px';
editorElem1790134439P6Lz6.style.height = '500px';
}
bottomBtn1790134439P6Lz6.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439P6Lz6.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439P6Lz6.addEventListener('click', function() {
bottomBtn1790134439P6Lz6.click();
});
</script><div class="ce-block ce-block--focused" data-id="TvEMxKnQY0" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">这里的<span> </span><code>streamSettings.security = none</code><span> </span>表示<span> </span>Nginx 到本机 v2**y 这一段不使用 TLS。它不是客户端 VMess 的加密方式,也不表示公网链路没有加密。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="53ZujEtCK-" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"><code>listen</code><span> </span>使用<span> </span><code>127.0.0.1</code>,因此无需在公网开放 10000 端口。Nginx 负责处理外部 HTTPS 连接,再转发给 v2**y。<a href="https://www.v2fly.org/config/transport/websocket.html" rel="noopener nofollow ugc">WebSocket 配置说明</a></div>
</div>
</div><div class="ce-block" data-id="9yTwZ4Bo9Z" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">六、创建并保存源站证书</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="2DjjsalE9q" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">在 Cloudflare 控制台进入:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="90BUyDuoMW" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">SSL/TLS → Origin Server → Create Certificate</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="R8H6qrGV0u" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">选择 Cloudflare 自动生成私钥和 CSR,密钥类型可以使用 RSA。证书覆盖域名保留:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="IjO1VK1G8y" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-IjO1VK1G8y">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-IjO1VK1G8y">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-IjO1VK1G8y" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-IjO1VK1G8y">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439VTNrC = document.getElementById('codeflask-IjO1VK1G8y');
var isCollapsed1790134439VTNrC = true;
const flask1790134439VTNrC = new CodeFlask(editorElem1790134439VTNrC, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439VTNrC = `example.com
*.example.com`;
code1790134439VTNrC = code1790134439VTNrC.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439VTNrC.addLanguage('shell', Prism.languages['shell']);
flask1790134439VTNrC.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439VTNrC.updateCode(code1790134439VTNrC);
const currentCode1790134439VTNrC = flask1790134439VTNrC.getCode();
var coderow1790134439VTNrC = parseInt('');
if (coderow1790134439VTNrC === undefined || coderow1790134439VTNrC !== coderow1790134439VTNrC || coderow1790134439VTNrC === 0) {
coderow1790134439VTNrC = flask1790134439VTNrC.lineNumber;
}
if (coderow1790134439VTNrC < 20) {
editorElem1790134439VTNrC.parentElement.style.height = '300px';
editorElem1790134439VTNrC.style.height = '300px';
} else if (coderow1790134439VTNrC >= 20) {
editorElem1790134439VTNrC.parentElement.style.height = '500px';
editorElem1790134439VTNrC.style.height = '500px';
}
//console.log({currentCode1790134439VTNrC})
const copyBtn1790134439VTNrC = document.getElementById('codeflask-copy-IjO1VK1G8y');
copyBtn1790134439VTNrC.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439VTNrC).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439VTNrC.innerHTML;
copyBtn1790134439VTNrC.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439VTNrC.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439VTNrC);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439VTNrC);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439VTNrC.innerHTML;
copyBtn1790134439VTNrC.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439VTNrC.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439VTNrC = document.getElementById('codeflask-bottomBtn-IjO1VK1G8y');
const Toggle1790134439VTNrC = document.getElementById('codeflask-Toggle-IjO1VK1G8y');
bottomBtn1790134439VTNrC.addEventListener('click', function() {
if (isCollapsed1790134439VTNrC) {
// 展开代码
isCollapsed1790134439VTNrC = false;
const codeElement1790134439VTNrC = editorElem1790134439VTNrC.querySelector('.codeflask__code');
if (codeElement1790134439VTNrC) {
const actualHeight1790134439VTNrC = codeElement1790134439VTNrC.scrollHeight + 20;
editorElem1790134439VTNrC.parentElement.style.height = actualHeight1790134439VTNrC + 'px';
editorElem1790134439VTNrC.style.height = actualHeight1790134439VTNrC + 'px';
}
bottomBtn1790134439VTNrC.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439VTNrC.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439VTNrC = true;
if (coderow1790134439VTNrC < 20) {
editorElem1790134439VTNrC.parentElement.style.height = '300px';
editorElem1790134439VTNrC.style.height = '300px';
} else if (coderow1790134439VTNrC >= 20) {
editorElem1790134439VTNrC.parentElement.style.height = '500px';
editorElem1790134439VTNrC.style.height = '500px';
}
bottomBtn1790134439VTNrC.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439VTNrC.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439VTNrC.addEventListener('click', function() {
bottomBtn1790134439VTNrC.click();
});
</script><div class="ce-block ce-block--focused" data-id="tijEWsKAAg" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">其中,前者覆盖主域名,后者覆盖一级子域名,例如<span> </span><code>富强.example.com</code>。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="_TfA7HRHjd" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">创建后选择 PEM 格式,将<span> </span>Origin Certificate<span> </span>和<span> </span>Private Key<span> </span>分别保存到 VPS。先创建目录:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="5eFjtb3ahS" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-5eFjtb3ahS">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-5eFjtb3ahS">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-5eFjtb3ahS" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-5eFjtb3ahS">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439p19dr = document.getElementById('codeflask-5eFjtb3ahS');
var isCollapsed1790134439p19dr = true;
const flask1790134439p19dr = new CodeFlask(editorElem1790134439p19dr, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439p19dr = `sudo mkdir -p /etc/nginx/ssl`;
code1790134439p19dr = code1790134439p19dr.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439p19dr.addLanguage('shell', Prism.languages['shell']);
flask1790134439p19dr.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439p19dr.updateCode(code1790134439p19dr);
const currentCode1790134439p19dr = flask1790134439p19dr.getCode();
var coderow1790134439p19dr = parseInt('');
if (coderow1790134439p19dr === undefined || coderow1790134439p19dr !== coderow1790134439p19dr || coderow1790134439p19dr === 0) {
coderow1790134439p19dr = flask1790134439p19dr.lineNumber;
}
if (coderow1790134439p19dr < 20) {
editorElem1790134439p19dr.parentElement.style.height = '300px';
editorElem1790134439p19dr.style.height = '300px';
} else if (coderow1790134439p19dr >= 20) {
editorElem1790134439p19dr.parentElement.style.height = '500px';
editorElem1790134439p19dr.style.height = '500px';
}
//console.log({currentCode1790134439p19dr})
const copyBtn1790134439p19dr = document.getElementById('codeflask-copy-5eFjtb3ahS');
copyBtn1790134439p19dr.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439p19dr).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439p19dr.innerHTML;
copyBtn1790134439p19dr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439p19dr.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439p19dr);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439p19dr);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439p19dr.innerHTML;
copyBtn1790134439p19dr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439p19dr.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439p19dr = document.getElementById('codeflask-bottomBtn-5eFjtb3ahS');
const Toggle1790134439p19dr = document.getElementById('codeflask-Toggle-5eFjtb3ahS');
bottomBtn1790134439p19dr.addEventListener('click', function() {
if (isCollapsed1790134439p19dr) {
// 展开代码
isCollapsed1790134439p19dr = false;
const codeElement1790134439p19dr = editorElem1790134439p19dr.querySelector('.codeflask__code');
if (codeElement1790134439p19dr) {
const actualHeight1790134439p19dr = codeElement1790134439p19dr.scrollHeight + 20;
editorElem1790134439p19dr.parentElement.style.height = actualHeight1790134439p19dr + 'px';
editorElem1790134439p19dr.style.height = actualHeight1790134439p19dr + 'px';
}
bottomBtn1790134439p19dr.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439p19dr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439p19dr = true;
if (coderow1790134439p19dr < 20) {
editorElem1790134439p19dr.parentElement.style.height = '300px';
editorElem1790134439p19dr.style.height = '300px';
} else if (coderow1790134439p19dr >= 20) {
editorElem1790134439p19dr.parentElement.style.height = '500px';
editorElem1790134439p19dr.style.height = '500px';
}
bottomBtn1790134439p19dr.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439p19dr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439p19dr.addEventListener('click', function() {
bottomBtn1790134439p19dr.click();
});
</script><div class="ce-block ce-block--focused" data-id="8EOkM0cFgL" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 编辑证书文件,粘贴完整证书内容:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="Dh9tJRUiTf" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-Dh9tJRUiTf">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-Dh9tJRUiTf">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-Dh9tJRUiTf" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-Dh9tJRUiTf">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439KCZDa = document.getElementById('codeflask-Dh9tJRUiTf');
var isCollapsed1790134439KCZDa = true;
const flask1790134439KCZDa = new CodeFlask(editorElem1790134439KCZDa, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439KCZDa = `sudo nano /etc/nginx/ssl/example.com.pem`;
code1790134439KCZDa = code1790134439KCZDa.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439KCZDa.addLanguage('shell', Prism.languages['shell']);
flask1790134439KCZDa.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439KCZDa.updateCode(code1790134439KCZDa);
const currentCode1790134439KCZDa = flask1790134439KCZDa.getCode();
var coderow1790134439KCZDa = parseInt('');
if (coderow1790134439KCZDa === undefined || coderow1790134439KCZDa !== coderow1790134439KCZDa || coderow1790134439KCZDa === 0) {
coderow1790134439KCZDa = flask1790134439KCZDa.lineNumber;
}
if (coderow1790134439KCZDa < 20) {
editorElem1790134439KCZDa.parentElement.style.height = '300px';
editorElem1790134439KCZDa.style.height = '300px';
} else if (coderow1790134439KCZDa >= 20) {
editorElem1790134439KCZDa.parentElement.style.height = '500px';
editorElem1790134439KCZDa.style.height = '500px';
}
//console.log({currentCode1790134439KCZDa})
const copyBtn1790134439KCZDa = document.getElementById('codeflask-copy-Dh9tJRUiTf');
copyBtn1790134439KCZDa.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439KCZDa).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439KCZDa.innerHTML;
copyBtn1790134439KCZDa.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439KCZDa.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439KCZDa);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439KCZDa);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439KCZDa.innerHTML;
copyBtn1790134439KCZDa.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439KCZDa.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439KCZDa = document.getElementById('codeflask-bottomBtn-Dh9tJRUiTf');
const Toggle1790134439KCZDa = document.getElementById('codeflask-Toggle-Dh9tJRUiTf');
bottomBtn1790134439KCZDa.addEventListener('click', function() {
if (isCollapsed1790134439KCZDa) {
// 展开代码
isCollapsed1790134439KCZDa = false;
const codeElement1790134439KCZDa = editorElem1790134439KCZDa.querySelector('.codeflask__code');
if (codeElement1790134439KCZDa) {
const actualHeight1790134439KCZDa = codeElement1790134439KCZDa.scrollHeight + 20;
editorElem1790134439KCZDa.parentElement.style.height = actualHeight1790134439KCZDa + 'px';
editorElem1790134439KCZDa.style.height = actualHeight1790134439KCZDa + 'px';
}
bottomBtn1790134439KCZDa.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439KCZDa.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439KCZDa = true;
if (coderow1790134439KCZDa < 20) {
editorElem1790134439KCZDa.parentElement.style.height = '300px';
editorElem1790134439KCZDa.style.height = '300px';
} else if (coderow1790134439KCZDa >= 20) {
editorElem1790134439KCZDa.parentElement.style.height = '500px';
editorElem1790134439KCZDa.style.height = '500px';
}
bottomBtn1790134439KCZDa.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439KCZDa.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439KCZDa.addEventListener('click', function() {
bottomBtn1790134439KCZDa.click();
});
</script><div class="ce-block ce-block--focused" data-id="qt2o0RrOIM" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 编辑私钥文件,粘贴完整私钥内容:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="VT0jXZ8pyd" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-VT0jXZ8pyd">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-VT0jXZ8pyd">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-VT0jXZ8pyd" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-VT0jXZ8pyd">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439Kgrm7 = document.getElementById('codeflask-VT0jXZ8pyd');
var isCollapsed1790134439Kgrm7 = true;
const flask1790134439Kgrm7 = new CodeFlask(editorElem1790134439Kgrm7, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439Kgrm7 = `sudo nano /etc/nginx/ssl/example.com.key`;
code1790134439Kgrm7 = code1790134439Kgrm7.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439Kgrm7.addLanguage('shell', Prism.languages['shell']);
flask1790134439Kgrm7.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439Kgrm7.updateCode(code1790134439Kgrm7);
const currentCode1790134439Kgrm7 = flask1790134439Kgrm7.getCode();
var coderow1790134439Kgrm7 = parseInt('');
if (coderow1790134439Kgrm7 === undefined || coderow1790134439Kgrm7 !== coderow1790134439Kgrm7 || coderow1790134439Kgrm7 === 0) {
coderow1790134439Kgrm7 = flask1790134439Kgrm7.lineNumber;
}
if (coderow1790134439Kgrm7 < 20) {
editorElem1790134439Kgrm7.parentElement.style.height = '300px';
editorElem1790134439Kgrm7.style.height = '300px';
} else if (coderow1790134439Kgrm7 >= 20) {
editorElem1790134439Kgrm7.parentElement.style.height = '500px';
editorElem1790134439Kgrm7.style.height = '500px';
}
//console.log({currentCode1790134439Kgrm7})
const copyBtn1790134439Kgrm7 = document.getElementById('codeflask-copy-VT0jXZ8pyd');
copyBtn1790134439Kgrm7.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439Kgrm7).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439Kgrm7.innerHTML;
copyBtn1790134439Kgrm7.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439Kgrm7.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439Kgrm7);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439Kgrm7);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439Kgrm7.innerHTML;
copyBtn1790134439Kgrm7.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439Kgrm7.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439Kgrm7 = document.getElementById('codeflask-bottomBtn-VT0jXZ8pyd');
const Toggle1790134439Kgrm7 = document.getElementById('codeflask-Toggle-VT0jXZ8pyd');
bottomBtn1790134439Kgrm7.addEventListener('click', function() {
if (isCollapsed1790134439Kgrm7) {
// 展开代码
isCollapsed1790134439Kgrm7 = false;
const codeElement1790134439Kgrm7 = editorElem1790134439Kgrm7.querySelector('.codeflask__code');
if (codeElement1790134439Kgrm7) {
const actualHeight1790134439Kgrm7 = codeElement1790134439Kgrm7.scrollHeight + 20;
editorElem1790134439Kgrm7.parentElement.style.height = actualHeight1790134439Kgrm7 + 'px';
editorElem1790134439Kgrm7.style.height = actualHeight1790134439Kgrm7 + 'px';
}
bottomBtn1790134439Kgrm7.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439Kgrm7.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439Kgrm7 = true;
if (coderow1790134439Kgrm7 < 20) {
editorElem1790134439Kgrm7.parentElement.style.height = '300px';
editorElem1790134439Kgrm7.style.height = '300px';
} else if (coderow1790134439Kgrm7 >= 20) {
editorElem1790134439Kgrm7.parentElement.style.height = '500px';
editorElem1790134439Kgrm7.style.height = '500px';
}
bottomBtn1790134439Kgrm7.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439Kgrm7.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439Kgrm7.addEventListener('click', function() {
bottomBtn1790134439Kgrm7.click();
});
</script><div class="ce-block ce-block--focused" data-id="hc3iQSRbJU" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 设置文件权限:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="zgS2wtnwbg" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-zgS2wtnwbg">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-zgS2wtnwbg">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-zgS2wtnwbg" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-zgS2wtnwbg">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439I87Sg = document.getElementById('codeflask-zgS2wtnwbg');
var isCollapsed1790134439I87Sg = true;
const flask1790134439I87Sg = new CodeFlask(editorElem1790134439I87Sg, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439I87Sg = `sudo chmod 644 /etc/nginx/ssl/example.com.pem
sudo chmod 600 /etc/nginx/ssl/example.com.key`;
code1790134439I87Sg = code1790134439I87Sg.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439I87Sg.addLanguage('shell', Prism.languages['shell']);
flask1790134439I87Sg.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439I87Sg.updateCode(code1790134439I87Sg);
const currentCode1790134439I87Sg = flask1790134439I87Sg.getCode();
var coderow1790134439I87Sg = parseInt('');
if (coderow1790134439I87Sg === undefined || coderow1790134439I87Sg !== coderow1790134439I87Sg || coderow1790134439I87Sg === 0) {
coderow1790134439I87Sg = flask1790134439I87Sg.lineNumber;
}
if (coderow1790134439I87Sg < 20) {
editorElem1790134439I87Sg.parentElement.style.height = '300px';
editorElem1790134439I87Sg.style.height = '300px';
} else if (coderow1790134439I87Sg >= 20) {
editorElem1790134439I87Sg.parentElement.style.height = '500px';
editorElem1790134439I87Sg.style.height = '500px';
}
//console.log({currentCode1790134439I87Sg})
const copyBtn1790134439I87Sg = document.getElementById('codeflask-copy-zgS2wtnwbg');
copyBtn1790134439I87Sg.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439I87Sg).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439I87Sg.innerHTML;
copyBtn1790134439I87Sg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439I87Sg.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439I87Sg);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439I87Sg);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439I87Sg.innerHTML;
copyBtn1790134439I87Sg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439I87Sg.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439I87Sg = document.getElementById('codeflask-bottomBtn-zgS2wtnwbg');
const Toggle1790134439I87Sg = document.getElementById('codeflask-Toggle-zgS2wtnwbg');
bottomBtn1790134439I87Sg.addEventListener('click', function() {
if (isCollapsed1790134439I87Sg) {
// 展开代码
isCollapsed1790134439I87Sg = false;
const codeElement1790134439I87Sg = editorElem1790134439I87Sg.querySelector('.codeflask__code');
if (codeElement1790134439I87Sg) {
const actualHeight1790134439I87Sg = codeElement1790134439I87Sg.scrollHeight + 20;
editorElem1790134439I87Sg.parentElement.style.height = actualHeight1790134439I87Sg + 'px';
editorElem1790134439I87Sg.style.height = actualHeight1790134439I87Sg + 'px';
}
bottomBtn1790134439I87Sg.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439I87Sg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439I87Sg = true;
if (coderow1790134439I87Sg < 20) {
editorElem1790134439I87Sg.parentElement.style.height = '300px';
editorElem1790134439I87Sg.style.height = '300px';
} else if (coderow1790134439I87Sg >= 20) {
editorElem1790134439I87Sg.parentElement.style.height = '500px';
editorElem1790134439I87Sg.style.height = '500px';
}
bottomBtn1790134439I87Sg.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439I87Sg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439I87Sg.addEventListener('click', function() {
bottomBtn1790134439I87Sg.click();
});
</script><div class="ce-block ce-block--focused" data-id="EPo6WDer8u" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">文件名可以自定义,只需与 Nginx 配置对应;实际覆盖哪些域名由证书内容决定。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="qQrkpXB7DE" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">Origin CA 证书用于 Cloudflare 到源站的连接。客户端通过橙云访问时看到的是 Cloudflare 边缘证书;如果关闭橙云直接访问源站,浏览器通常不会信任 Origin CA 证书。<a href="https://developers.cloudflare.com/ssl/origin-configuration/origin-ca/" rel="noopener nofollow ugc">Origin CA 官方说明</a></div>
</div>
</div><div class="ce-block" data-id="0rOVTdzB3z" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">七、配置 Nginx</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="mzWBMNoKwl" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">新建站点配置:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="YSFsg3qyo4" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-YSFsg3qyo4">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-YSFsg3qyo4">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-YSFsg3qyo4" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-YSFsg3qyo4">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439nZCiz = document.getElementById('codeflask-YSFsg3qyo4');
var isCollapsed1790134439nZCiz = true;
const flask1790134439nZCiz = new CodeFlask(editorElem1790134439nZCiz, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439nZCiz = `sudo nano /etc/nginx/conf.d/v2**y.conf`;
code1790134439nZCiz = code1790134439nZCiz.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439nZCiz.addLanguage('shell', Prism.languages['shell']);
flask1790134439nZCiz.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439nZCiz.updateCode(code1790134439nZCiz);
const currentCode1790134439nZCiz = flask1790134439nZCiz.getCode();
var coderow1790134439nZCiz = parseInt('');
if (coderow1790134439nZCiz === undefined || coderow1790134439nZCiz !== coderow1790134439nZCiz || coderow1790134439nZCiz === 0) {
coderow1790134439nZCiz = flask1790134439nZCiz.lineNumber;
}
if (coderow1790134439nZCiz < 20) {
editorElem1790134439nZCiz.parentElement.style.height = '300px';
editorElem1790134439nZCiz.style.height = '300px';
} else if (coderow1790134439nZCiz >= 20) {
editorElem1790134439nZCiz.parentElement.style.height = '500px';
editorElem1790134439nZCiz.style.height = '500px';
}
//console.log({currentCode1790134439nZCiz})
const copyBtn1790134439nZCiz = document.getElementById('codeflask-copy-YSFsg3qyo4');
copyBtn1790134439nZCiz.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439nZCiz).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439nZCiz.innerHTML;
copyBtn1790134439nZCiz.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439nZCiz.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439nZCiz);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439nZCiz);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439nZCiz.innerHTML;
copyBtn1790134439nZCiz.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439nZCiz.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439nZCiz = document.getElementById('codeflask-bottomBtn-YSFsg3qyo4');
const Toggle1790134439nZCiz = document.getElementById('codeflask-Toggle-YSFsg3qyo4');
bottomBtn1790134439nZCiz.addEventListener('click', function() {
if (isCollapsed1790134439nZCiz) {
// 展开代码
isCollapsed1790134439nZCiz = false;
const codeElement1790134439nZCiz = editorElem1790134439nZCiz.querySelector('.codeflask__code');
if (codeElement1790134439nZCiz) {
const actualHeight1790134439nZCiz = codeElement1790134439nZCiz.scrollHeight + 20;
editorElem1790134439nZCiz.parentElement.style.height = actualHeight1790134439nZCiz + 'px';
editorElem1790134439nZCiz.style.height = actualHeight1790134439nZCiz + 'px';
}
bottomBtn1790134439nZCiz.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439nZCiz.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439nZCiz = true;
if (coderow1790134439nZCiz < 20) {
editorElem1790134439nZCiz.parentElement.style.height = '300px';
editorElem1790134439nZCiz.style.height = '300px';
} else if (coderow1790134439nZCiz >= 20) {
editorElem1790134439nZCiz.parentElement.style.height = '500px';
editorElem1790134439nZCiz.style.height = '500px';
}
bottomBtn1790134439nZCiz.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439nZCiz.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439nZCiz.addEventListener('click', function() {
bottomBtn1790134439nZCiz.click();
});
</script><div class="ce-block ce-block--focused" data-id="acNDxw0FL5" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 写入:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="D9Clf2rv_d" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-D9Clf2rv_d">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-D9Clf2rv_d">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-D9Clf2rv_d" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-D9Clf2rv_d">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439HEe8D = document.getElementById('codeflask-D9Clf2rv_d');
var isCollapsed1790134439HEe8D = true;
const flask1790134439HEe8D = new CodeFlask(editorElem1790134439HEe8D, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439HEe8D = `server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
location = /bridge {
proxy_pass http://127.0.0.1:10000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
location / {
default_type text/plain;
return 200 "Service is running.\n";
}
}`;
code1790134439HEe8D = code1790134439HEe8D.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439HEe8D.addLanguage('shell', Prism.languages['shell']);
flask1790134439HEe8D.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439HEe8D.updateCode(code1790134439HEe8D);
const currentCode1790134439HEe8D = flask1790134439HEe8D.getCode();
var coderow1790134439HEe8D = parseInt('');
if (coderow1790134439HEe8D === undefined || coderow1790134439HEe8D !== coderow1790134439HEe8D || coderow1790134439HEe8D === 0) {
coderow1790134439HEe8D = flask1790134439HEe8D.lineNumber;
}
if (coderow1790134439HEe8D < 20) {
editorElem1790134439HEe8D.parentElement.style.height = '300px';
editorElem1790134439HEe8D.style.height = '300px';
} else if (coderow1790134439HEe8D >= 20) {
editorElem1790134439HEe8D.parentElement.style.height = '500px';
editorElem1790134439HEe8D.style.height = '500px';
}
//console.log({currentCode1790134439HEe8D})
const copyBtn1790134439HEe8D = document.getElementById('codeflask-copy-D9Clf2rv_d');
copyBtn1790134439HEe8D.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439HEe8D).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439HEe8D.innerHTML;
copyBtn1790134439HEe8D.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439HEe8D.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439HEe8D);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439HEe8D);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439HEe8D.innerHTML;
copyBtn1790134439HEe8D.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439HEe8D.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439HEe8D = document.getElementById('codeflask-bottomBtn-D9Clf2rv_d');
const Toggle1790134439HEe8D = document.getElementById('codeflask-Toggle-D9Clf2rv_d');
bottomBtn1790134439HEe8D.addEventListener('click', function() {
if (isCollapsed1790134439HEe8D) {
// 展开代码
isCollapsed1790134439HEe8D = false;
const codeElement1790134439HEe8D = editorElem1790134439HEe8D.querySelector('.codeflask__code');
if (codeElement1790134439HEe8D) {
const actualHeight1790134439HEe8D = codeElement1790134439HEe8D.scrollHeight + 20;
editorElem1790134439HEe8D.parentElement.style.height = actualHeight1790134439HEe8D + 'px';
editorElem1790134439HEe8D.style.height = actualHeight1790134439HEe8D + 'px';
}
bottomBtn1790134439HEe8D.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439HEe8D.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439HEe8D = true;
if (coderow1790134439HEe8D < 20) {
editorElem1790134439HEe8D.parentElement.style.height = '300px';
editorElem1790134439HEe8D.style.height = '300px';
} else if (coderow1790134439HEe8D >= 20) {
editorElem1790134439HEe8D.parentElement.style.height = '500px';
editorElem1790134439HEe8D.style.height = '500px';
}
bottomBtn1790134439HEe8D.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439HEe8D.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439HEe8D.addEventListener('click', function() {
bottomBtn1790134439HEe8D.click();
});
</script><div class="ce-block ce-block--focused" data-id="BlCbKvcMCH" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">这份配置将<span> </span><code>/bridge</code><span> </span>精确匹配到 v2**y,其他路径返回一个简单页面。<code>proxy_pass</code><span> </span>后没有附加路径,因此会保留原始请求路径。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="u_F55TlTQU" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"><code>proxy_http_version 1.1</code>、<code>Upgrade</code><span> </span>和<span> </span><code>Connection</code><span> </span>用于 WebSocket 升级。不要把客户端配置为普通 VMess TCP 后直接连接这套 HTTP 戴丽入口。<a href="https://nginx.org/en/docs/http/websocket.html" rel="noopener nofollow ugc">Nginx WebSocket 说明</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="FynU5JbXQy" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">检查两个配置:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="XzsuzEGDN0" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-XzsuzEGDN0">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-XzsuzEGDN0">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-XzsuzEGDN0" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-XzsuzEGDN0">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439C7471 = document.getElementById('codeflask-XzsuzEGDN0');
var isCollapsed1790134439C7471 = true;
const flask1790134439C7471 = new CodeFlask(editorElem1790134439C7471, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439C7471 = `sudo /usr/local/bin/v2**y test -c /usr/local/etc/v2**y/config.json
sudo nginx -t`;
code1790134439C7471 = code1790134439C7471.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439C7471.addLanguage('shell', Prism.languages['shell']);
flask1790134439C7471.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439C7471.updateCode(code1790134439C7471);
const currentCode1790134439C7471 = flask1790134439C7471.getCode();
var coderow1790134439C7471 = parseInt('');
if (coderow1790134439C7471 === undefined || coderow1790134439C7471 !== coderow1790134439C7471 || coderow1790134439C7471 === 0) {
coderow1790134439C7471 = flask1790134439C7471.lineNumber;
}
if (coderow1790134439C7471 < 20) {
editorElem1790134439C7471.parentElement.style.height = '300px';
editorElem1790134439C7471.style.height = '300px';
} else if (coderow1790134439C7471 >= 20) {
editorElem1790134439C7471.parentElement.style.height = '500px';
editorElem1790134439C7471.style.height = '500px';
}
//console.log({currentCode1790134439C7471})
const copyBtn1790134439C7471 = document.getElementById('codeflask-copy-XzsuzEGDN0');
copyBtn1790134439C7471.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439C7471).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439C7471.innerHTML;
copyBtn1790134439C7471.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439C7471.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439C7471);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439C7471);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439C7471.innerHTML;
copyBtn1790134439C7471.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439C7471.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439C7471 = document.getElementById('codeflask-bottomBtn-XzsuzEGDN0');
const Toggle1790134439C7471 = document.getElementById('codeflask-Toggle-XzsuzEGDN0');
bottomBtn1790134439C7471.addEventListener('click', function() {
if (isCollapsed1790134439C7471) {
// 展开代码
isCollapsed1790134439C7471 = false;
const codeElement1790134439C7471 = editorElem1790134439C7471.querySelector('.codeflask__code');
if (codeElement1790134439C7471) {
const actualHeight1790134439C7471 = codeElement1790134439C7471.scrollHeight + 20;
editorElem1790134439C7471.parentElement.style.height = actualHeight1790134439C7471 + 'px';
editorElem1790134439C7471.style.height = actualHeight1790134439C7471 + 'px';
}
bottomBtn1790134439C7471.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439C7471.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439C7471 = true;
if (coderow1790134439C7471 < 20) {
editorElem1790134439C7471.parentElement.style.height = '300px';
editorElem1790134439C7471.style.height = '300px';
} else if (coderow1790134439C7471 >= 20) {
editorElem1790134439C7471.parentElement.style.height = '500px';
editorElem1790134439C7471.style.height = '500px';
}
bottomBtn1790134439C7471.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439C7471.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439C7471.addEventListener('click', function() {
bottomBtn1790134439C7471.click();
});
</script><div class="ce-block ce-block--focused" data-id="k0fIdRMvW-" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 确认 v2**y 输出 <code>Configuration OK.</code>,Nginx 输出语法检查通过后,再启动服务。上述 v2**y 检查命令适用于 5.x。<a href="https://github.com/v2fly/v2**y-core/blob/master/main/commands/test.go" rel="noopener nofollow ugc">v2**y test 命令定义</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="5NrLacRx4e" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-5NrLacRx4e">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-5NrLacRx4e">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-5NrLacRx4e" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-5NrLacRx4e">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439YT6Lg = document.getElementById('codeflask-5NrLacRx4e');
var isCollapsed1790134439YT6Lg = true;
const flask1790134439YT6Lg = new CodeFlask(editorElem1790134439YT6Lg, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439YT6Lg = `sudo systemctl enable --now v2**y nginx
sudo systemctl restart v2**y
sudo systemctl reload nginx`;
code1790134439YT6Lg = code1790134439YT6Lg.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439YT6Lg.addLanguage('shell', Prism.languages['shell']);
flask1790134439YT6Lg.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439YT6Lg.updateCode(code1790134439YT6Lg);
const currentCode1790134439YT6Lg = flask1790134439YT6Lg.getCode();
var coderow1790134439YT6Lg = parseInt('');
if (coderow1790134439YT6Lg === undefined || coderow1790134439YT6Lg !== coderow1790134439YT6Lg || coderow1790134439YT6Lg === 0) {
coderow1790134439YT6Lg = flask1790134439YT6Lg.lineNumber;
}
if (coderow1790134439YT6Lg < 20) {
editorElem1790134439YT6Lg.parentElement.style.height = '300px';
editorElem1790134439YT6Lg.style.height = '300px';
} else if (coderow1790134439YT6Lg >= 20) {
editorElem1790134439YT6Lg.parentElement.style.height = '500px';
editorElem1790134439YT6Lg.style.height = '500px';
}
//console.log({currentCode1790134439YT6Lg})
const copyBtn1790134439YT6Lg = document.getElementById('codeflask-copy-5NrLacRx4e');
copyBtn1790134439YT6Lg.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439YT6Lg).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439YT6Lg.innerHTML;
copyBtn1790134439YT6Lg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439YT6Lg.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439YT6Lg);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439YT6Lg);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439YT6Lg.innerHTML;
copyBtn1790134439YT6Lg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439YT6Lg.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439YT6Lg = document.getElementById('codeflask-bottomBtn-5NrLacRx4e');
const Toggle1790134439YT6Lg = document.getElementById('codeflask-Toggle-5NrLacRx4e');
bottomBtn1790134439YT6Lg.addEventListener('click', function() {
if (isCollapsed1790134439YT6Lg) {
// 展开代码
isCollapsed1790134439YT6Lg = false;
const codeElement1790134439YT6Lg = editorElem1790134439YT6Lg.querySelector('.codeflask__code');
if (codeElement1790134439YT6Lg) {
const actualHeight1790134439YT6Lg = codeElement1790134439YT6Lg.scrollHeight + 20;
editorElem1790134439YT6Lg.parentElement.style.height = actualHeight1790134439YT6Lg + 'px';
editorElem1790134439YT6Lg.style.height = actualHeight1790134439YT6Lg + 'px';
}
bottomBtn1790134439YT6Lg.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439YT6Lg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439YT6Lg = true;
if (coderow1790134439YT6Lg < 20) {
editorElem1790134439YT6Lg.parentElement.style.height = '300px';
editorElem1790134439YT6Lg.style.height = '300px';
} else if (coderow1790134439YT6Lg >= 20) {
editorElem1790134439YT6Lg.parentElement.style.height = '500px';
editorElem1790134439YT6Lg.style.height = '500px';
}
bottomBtn1790134439YT6Lg.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439YT6Lg.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439YT6Lg.addEventListener('click', function() {
bottomBtn1790134439YT6Lg.click();
});
</script><div class="ce-block ce-block--focused" data-id="MZUcK1kV1X" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 查看运行状态和监听端口:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="Om-cJ6vqrJ" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-Om-cJ6vqrJ">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-Om-cJ6vqrJ">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-Om-cJ6vqrJ" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-Om-cJ6vqrJ">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439O8cj1 = document.getElementById('codeflask-Om-cJ6vqrJ');
var isCollapsed1790134439O8cj1 = true;
const flask1790134439O8cj1 = new CodeFlask(editorElem1790134439O8cj1, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439O8cj1 = `sudo systemctl status v2**y nginx --no-pager
sudo ss -lntp`;
code1790134439O8cj1 = code1790134439O8cj1.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439O8cj1.addLanguage('shell', Prism.languages['shell']);
flask1790134439O8cj1.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439O8cj1.updateCode(code1790134439O8cj1);
const currentCode1790134439O8cj1 = flask1790134439O8cj1.getCode();
var coderow1790134439O8cj1 = parseInt('');
if (coderow1790134439O8cj1 === undefined || coderow1790134439O8cj1 !== coderow1790134439O8cj1 || coderow1790134439O8cj1 === 0) {
coderow1790134439O8cj1 = flask1790134439O8cj1.lineNumber;
}
if (coderow1790134439O8cj1 < 20) {
editorElem1790134439O8cj1.parentElement.style.height = '300px';
editorElem1790134439O8cj1.style.height = '300px';
} else if (coderow1790134439O8cj1 >= 20) {
editorElem1790134439O8cj1.parentElement.style.height = '500px';
editorElem1790134439O8cj1.style.height = '500px';
}
//console.log({currentCode1790134439O8cj1})
const copyBtn1790134439O8cj1 = document.getElementById('codeflask-copy-Om-cJ6vqrJ');
copyBtn1790134439O8cj1.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439O8cj1).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439O8cj1.innerHTML;
copyBtn1790134439O8cj1.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439O8cj1.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439O8cj1);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439O8cj1);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439O8cj1.innerHTML;
copyBtn1790134439O8cj1.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439O8cj1.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439O8cj1 = document.getElementById('codeflask-bottomBtn-Om-cJ6vqrJ');
const Toggle1790134439O8cj1 = document.getElementById('codeflask-Toggle-Om-cJ6vqrJ');
bottomBtn1790134439O8cj1.addEventListener('click', function() {
if (isCollapsed1790134439O8cj1) {
// 展开代码
isCollapsed1790134439O8cj1 = false;
const codeElement1790134439O8cj1 = editorElem1790134439O8cj1.querySelector('.codeflask__code');
if (codeElement1790134439O8cj1) {
const actualHeight1790134439O8cj1 = codeElement1790134439O8cj1.scrollHeight + 20;
editorElem1790134439O8cj1.parentElement.style.height = actualHeight1790134439O8cj1 + 'px';
editorElem1790134439O8cj1.style.height = actualHeight1790134439O8cj1 + 'px';
}
bottomBtn1790134439O8cj1.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439O8cj1.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439O8cj1 = true;
if (coderow1790134439O8cj1 < 20) {
editorElem1790134439O8cj1.parentElement.style.height = '300px';
editorElem1790134439O8cj1.style.height = '300px';
} else if (coderow1790134439O8cj1 >= 20) {
editorElem1790134439O8cj1.parentElement.style.height = '500px';
editorElem1790134439O8cj1.style.height = '500px';
}
bottomBtn1790134439O8cj1.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439O8cj1.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439O8cj1.addEventListener('click', function() {
bottomBtn1790134439O8cj1.click();
});
</script><div class="ce-block ce-block--focused" data-id="jnpx-9Y-KY" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">应能看到 Nginx 监听公网 443,以及 v2**y 监听<span> </span><code>127.0.0.1:10000</code>。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="56CT2KITkE" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">同时在服务商安全组和服务器防火墙中放行回源所需的 TCP 443。如果正在使用 UFW,可添加:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="P16mDy4hbJ" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-P16mDy4hbJ">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-P16mDy4hbJ">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-P16mDy4hbJ" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-P16mDy4hbJ">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439mgc78 = document.getElementById('codeflask-P16mDy4hbJ');
var isCollapsed1790134439mgc78 = true;
const flask1790134439mgc78 = new CodeFlask(editorElem1790134439mgc78, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439mgc78 = `sudo ufw allow 443/tcp`;
code1790134439mgc78 = code1790134439mgc78.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439mgc78.addLanguage('shell', Prism.languages['shell']);
flask1790134439mgc78.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439mgc78.updateCode(code1790134439mgc78);
const currentCode1790134439mgc78 = flask1790134439mgc78.getCode();
var coderow1790134439mgc78 = parseInt('');
if (coderow1790134439mgc78 === undefined || coderow1790134439mgc78 !== coderow1790134439mgc78 || coderow1790134439mgc78 === 0) {
coderow1790134439mgc78 = flask1790134439mgc78.lineNumber;
}
if (coderow1790134439mgc78 < 20) {
editorElem1790134439mgc78.parentElement.style.height = '300px';
editorElem1790134439mgc78.style.height = '300px';
} else if (coderow1790134439mgc78 >= 20) {
editorElem1790134439mgc78.parentElement.style.height = '500px';
editorElem1790134439mgc78.style.height = '500px';
}
//console.log({currentCode1790134439mgc78})
const copyBtn1790134439mgc78 = document.getElementById('codeflask-copy-P16mDy4hbJ');
copyBtn1790134439mgc78.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439mgc78).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439mgc78.innerHTML;
copyBtn1790134439mgc78.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439mgc78.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439mgc78);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439mgc78);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439mgc78.innerHTML;
copyBtn1790134439mgc78.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439mgc78.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439mgc78 = document.getElementById('codeflask-bottomBtn-P16mDy4hbJ');
const Toggle1790134439mgc78 = document.getElementById('codeflask-Toggle-P16mDy4hbJ');
bottomBtn1790134439mgc78.addEventListener('click', function() {
if (isCollapsed1790134439mgc78) {
// 展开代码
isCollapsed1790134439mgc78 = false;
const codeElement1790134439mgc78 = editorElem1790134439mgc78.querySelector('.codeflask__code');
if (codeElement1790134439mgc78) {
const actualHeight1790134439mgc78 = codeElement1790134439mgc78.scrollHeight + 20;
editorElem1790134439mgc78.parentElement.style.height = actualHeight1790134439mgc78 + 'px';
editorElem1790134439mgc78.style.height = actualHeight1790134439mgc78 + 'px';
}
bottomBtn1790134439mgc78.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439mgc78.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439mgc78 = true;
if (coderow1790134439mgc78 < 20) {
editorElem1790134439mgc78.parentElement.style.height = '300px';
editorElem1790134439mgc78.style.height = '300px';
} else if (coderow1790134439mgc78 >= 20) {
editorElem1790134439mgc78.parentElement.style.height = '500px';
editorElem1790134439mgc78.style.height = '500px';
}
bottomBtn1790134439mgc78.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439mgc78.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439mgc78.addEventListener('click', function() {
bottomBtn1790134439mgc78.click();
});
</script><div class="ce-block ce-block--focused" data-id="QbqDY2QWPE" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">不需要为了本教程额外启用 UFW,也不需要开放公网 10000。使用 Origin CA 的本流程无需为了申请证书开放 80。</div>
</div>
</div><div class="ce-block" data-id="1GHVT4uEef" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">八、完成 Cloudflare HTTPS 与 WebSocket 设置</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="BcuoJMHxB_" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">源站 Nginx 的证书和 443 端口就绪后,回到<span> </span>SSL/TLS → Overview → Configure,选择<span> </span>Full (strict)。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="vzB-d8dyp0" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">这个模式会加密回源连接,并检查源站证书的有效期、域名和签发机构。若同一域名区域下还有其他站点,全局模式调整也会影响它们,应确保相关源站支持该模式。<a href="https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/" rel="noopener nofollow ugc">Full (strict) 官方说明</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="_23rfXEYsL" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">在<span> </span>Network<span> </span>页面确认<span> </span>WebSockets<span> </span>已开启,并确认<span> </span>Edge Certificates<span> </span>中覆盖连接域名的证书已生效。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="4TzXrNGyTl" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">Cloudflare 支持戴丽 WebSocket,但初次握手仍可能受到安全规则影响。若该路径被浏览器验证码拦截,戴丽客户端无法完成这种交互,需要查看命中的具体规则,而不是关闭整个站点的安全功能。<a href="https://developers.cloudflare.com/network/websockets/" rel="noopener nofollow ugc">Cloudflare WebSocket 说明</a></div>
</div>
</div><div class="ce-block" data-id="9l2IYbC_t7" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">九、配置 v2**yN 客户端</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="vQeDy-1GsD" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">添加一个 VMess 节点,填写:</div>
</div>
</div><div class="ce-block" data-id="e8Da4GEt6P" >
<div class="ce-block__content">
<div class="cdx-block">
<div class="tc-wrap">
<div class="tc-table">
<div class="tc-row">
<div class="tc-cell">客户端字段</div>
<div class="tc-cell">配置值</div>
</div>
<div class="tc-row">
<div class="tc-cell">别名</div>
<div class="tc-cell">自定义,例如<span> </span><code>CF-VMess</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">地址 address</div>
<div class="tc-cell"><code>example.com</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">端口 port</div>
<div class="tc-cell"><code>443</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">用户 ID</div>
<div class="tc-cell">服务端配置中的同一个 UUID</div>
</div>
<div class="tc-row">
<div class="tc-cell">额外 ID / AlterID</div>
<div class="tc-cell"><code>0</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">加密方式 security</div>
<div class="tc-cell"><code>auto</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">传输协议 network</div>
<div class="tc-cell"><code>ws</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">伪装域名 / WebSocket Host</div>
<div class="tc-cell"><code>example.com</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">路径 path</div>
<div class="tc-cell"><code>/bridge</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">传输层安全 TLS</div>
<div class="tc-cell"><code>tls</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">SNI / ServerName</div>
<div class="tc-cell"><code>example.com</code></div>
</div>
<div class="tc-row">
<div class="tc-cell">跳过证书验证 / allowInsecure</div>
<div class="tc-cell">关闭 / false</div>
</div>
</div>
</div>
</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="SczfvID94I" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">客户端地址、Host 和 SNI 填实际连接域名,不要填写<span> </span><code>*.example.com</code>。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="btYTJk76Nx" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">保存后设为活动节点。初次测试时保持<span> </span>TUN 关闭,使用<span> </span>自动配置系统戴丽,先验证浏览器戴丽访问是否正常。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="Z40YMrxTNF" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">系统戴丽主要作用于遵循系统戴丽设置的应用,并不等于所有应用流量都被接管。如果以后需要 TUN,可在基本连接正常后单独配置和验证其 DNS、路由行为。<a href="https://github.com/2dust/v2**yN/wiki/%E7%B3%BB%E7%BB%9F%E4%BB%A3%E7%90%86%E5%92%8C%E8%B7%AF%E7%94%B1" rel="noopener nofollow ugc">v2**yN 系统戴丽说明</a></div>
</div>
</div><div class="ce-block" data-id="aMaezRKnTO" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">十、按层验证,不要只看测速结果</h2>
</div>
</div><div class="ce-block" data-id="JX8rzo3Sck" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">1. 验证 DNS</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="rNHOn-_fxz" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">在客户端电脑查询:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="LaN4c9J6ne" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-LaN4c9J6ne">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-LaN4c9J6ne">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-LaN4c9J6ne" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-LaN4c9J6ne">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439Zi59R = document.getElementById('codeflask-LaN4c9J6ne');
var isCollapsed1790134439Zi59R = true;
const flask1790134439Zi59R = new CodeFlask(editorElem1790134439Zi59R, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439Zi59R = `nslookup example.com`;
code1790134439Zi59R = code1790134439Zi59R.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439Zi59R.addLanguage('shell', Prism.languages['shell']);
flask1790134439Zi59R.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439Zi59R.updateCode(code1790134439Zi59R);
const currentCode1790134439Zi59R = flask1790134439Zi59R.getCode();
var coderow1790134439Zi59R = parseInt('');
if (coderow1790134439Zi59R === undefined || coderow1790134439Zi59R !== coderow1790134439Zi59R || coderow1790134439Zi59R === 0) {
coderow1790134439Zi59R = flask1790134439Zi59R.lineNumber;
}
if (coderow1790134439Zi59R < 20) {
editorElem1790134439Zi59R.parentElement.style.height = '300px';
editorElem1790134439Zi59R.style.height = '300px';
} else if (coderow1790134439Zi59R >= 20) {
editorElem1790134439Zi59R.parentElement.style.height = '500px';
editorElem1790134439Zi59R.style.height = '500px';
}
//console.log({currentCode1790134439Zi59R})
const copyBtn1790134439Zi59R = document.getElementById('codeflask-copy-LaN4c9J6ne');
copyBtn1790134439Zi59R.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439Zi59R).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439Zi59R.innerHTML;
copyBtn1790134439Zi59R.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439Zi59R.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439Zi59R);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439Zi59R);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439Zi59R.innerHTML;
copyBtn1790134439Zi59R.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439Zi59R.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439Zi59R = document.getElementById('codeflask-bottomBtn-LaN4c9J6ne');
const Toggle1790134439Zi59R = document.getElementById('codeflask-Toggle-LaN4c9J6ne');
bottomBtn1790134439Zi59R.addEventListener('click', function() {
if (isCollapsed1790134439Zi59R) {
// 展开代码
isCollapsed1790134439Zi59R = false;
const codeElement1790134439Zi59R = editorElem1790134439Zi59R.querySelector('.codeflask__code');
if (codeElement1790134439Zi59R) {
const actualHeight1790134439Zi59R = codeElement1790134439Zi59R.scrollHeight + 20;
editorElem1790134439Zi59R.parentElement.style.height = actualHeight1790134439Zi59R + 'px';
editorElem1790134439Zi59R.style.height = actualHeight1790134439Zi59R + 'px';
}
bottomBtn1790134439Zi59R.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439Zi59R.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439Zi59R = true;
if (coderow1790134439Zi59R < 20) {
editorElem1790134439Zi59R.parentElement.style.height = '300px';
editorElem1790134439Zi59R.style.height = '300px';
} else if (coderow1790134439Zi59R >= 20) {
editorElem1790134439Zi59R.parentElement.style.height = '500px';
editorElem1790134439Zi59R.style.height = '500px';
}
bottomBtn1790134439Zi59R.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439Zi59R.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439Zi59R.addEventListener('click', function() {
bottomBtn1790134439Zi59R.click();
});
</script><div class="ce-block ce-block--focused" data-id="7a3k6wptnL" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">检查返回的地址,也要注意查询实际使用了哪台 DNS 服务器。</div>
</div>
</div><div class="ce-block" data-id="wD4uCPa8WS" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">2. 验证 HTTPS</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="I9os71r9EL" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">在浏览器访问<span> </span><code>https://example.com/</code>,应看到:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="HOAhKYdRda" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-HOAhKYdRda">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-HOAhKYdRda">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-HOAhKYdRda" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-HOAhKYdRda">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439zg3DZ = document.getElementById('codeflask-HOAhKYdRda');
var isCollapsed1790134439zg3DZ = true;
const flask1790134439zg3DZ = new CodeFlask(editorElem1790134439zg3DZ, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439zg3DZ = `Service is running.`;
code1790134439zg3DZ = code1790134439zg3DZ.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439zg3DZ.addLanguage('shell', Prism.languages['shell']);
flask1790134439zg3DZ.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439zg3DZ.updateCode(code1790134439zg3DZ);
const currentCode1790134439zg3DZ = flask1790134439zg3DZ.getCode();
var coderow1790134439zg3DZ = parseInt('');
if (coderow1790134439zg3DZ === undefined || coderow1790134439zg3DZ !== coderow1790134439zg3DZ || coderow1790134439zg3DZ === 0) {
coderow1790134439zg3DZ = flask1790134439zg3DZ.lineNumber;
}
if (coderow1790134439zg3DZ < 20) {
editorElem1790134439zg3DZ.parentElement.style.height = '300px';
editorElem1790134439zg3DZ.style.height = '300px';
} else if (coderow1790134439zg3DZ >= 20) {
editorElem1790134439zg3DZ.parentElement.style.height = '500px';
editorElem1790134439zg3DZ.style.height = '500px';
}
//console.log({currentCode1790134439zg3DZ})
const copyBtn1790134439zg3DZ = document.getElementById('codeflask-copy-HOAhKYdRda');
copyBtn1790134439zg3DZ.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439zg3DZ).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439zg3DZ.innerHTML;
copyBtn1790134439zg3DZ.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439zg3DZ.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439zg3DZ);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439zg3DZ);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439zg3DZ.innerHTML;
copyBtn1790134439zg3DZ.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439zg3DZ.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439zg3DZ = document.getElementById('codeflask-bottomBtn-HOAhKYdRda');
const Toggle1790134439zg3DZ = document.getElementById('codeflask-Toggle-HOAhKYdRda');
bottomBtn1790134439zg3DZ.addEventListener('click', function() {
if (isCollapsed1790134439zg3DZ) {
// 展开代码
isCollapsed1790134439zg3DZ = false;
const codeElement1790134439zg3DZ = editorElem1790134439zg3DZ.querySelector('.codeflask__code');
if (codeElement1790134439zg3DZ) {
const actualHeight1790134439zg3DZ = codeElement1790134439zg3DZ.scrollHeight + 20;
editorElem1790134439zg3DZ.parentElement.style.height = actualHeight1790134439zg3DZ + 'px';
editorElem1790134439zg3DZ.style.height = actualHeight1790134439zg3DZ + 'px';
}
bottomBtn1790134439zg3DZ.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439zg3DZ.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439zg3DZ = true;
if (coderow1790134439zg3DZ < 20) {
editorElem1790134439zg3DZ.parentElement.style.height = '300px';
editorElem1790134439zg3DZ.style.height = '300px';
} else if (coderow1790134439zg3DZ >= 20) {
editorElem1790134439zg3DZ.parentElement.style.height = '500px';
editorElem1790134439zg3DZ.style.height = '500px';
}
bottomBtn1790134439zg3DZ.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439zg3DZ.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439zg3DZ.addEventListener('click', function() {
bottomBtn1790134439zg3DZ.click();
});
</script><div class="ce-block ce-block--focused" data-id="juQlQjdcR7" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">这说明当前访问路径中的域名、Cloudflare 和 Nginx 页面响应正常,尚未验证 VMess 认证。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="6BWGwB5qEP" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">也可以在 Windows PowerShell 中执行:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="RR8KtX7iUH" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-RR8KtX7iUH">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-RR8KtX7iUH">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-RR8KtX7iUH" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-RR8KtX7iUH">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439T1nQr = document.getElementById('codeflask-RR8KtX7iUH');
var isCollapsed1790134439T1nQr = true;
const flask1790134439T1nQr = new CodeFlask(editorElem1790134439T1nQr, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439T1nQr = `curl.exe -I https://example.com/`;
code1790134439T1nQr = code1790134439T1nQr.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439T1nQr.addLanguage('shell', Prism.languages['shell']);
flask1790134439T1nQr.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439T1nQr.updateCode(code1790134439T1nQr);
const currentCode1790134439T1nQr = flask1790134439T1nQr.getCode();
var coderow1790134439T1nQr = parseInt('');
if (coderow1790134439T1nQr === undefined || coderow1790134439T1nQr !== coderow1790134439T1nQr || coderow1790134439T1nQr === 0) {
coderow1790134439T1nQr = flask1790134439T1nQr.lineNumber;
}
if (coderow1790134439T1nQr < 20) {
editorElem1790134439T1nQr.parentElement.style.height = '300px';
editorElem1790134439T1nQr.style.height = '300px';
} else if (coderow1790134439T1nQr >= 20) {
editorElem1790134439T1nQr.parentElement.style.height = '500px';
editorElem1790134439T1nQr.style.height = '500px';
}
//console.log({currentCode1790134439T1nQr})
const copyBtn1790134439T1nQr = document.getElementById('codeflask-copy-RR8KtX7iUH');
copyBtn1790134439T1nQr.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439T1nQr).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439T1nQr.innerHTML;
copyBtn1790134439T1nQr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439T1nQr.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439T1nQr);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439T1nQr);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439T1nQr.innerHTML;
copyBtn1790134439T1nQr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439T1nQr.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439T1nQr = document.getElementById('codeflask-bottomBtn-RR8KtX7iUH');
const Toggle1790134439T1nQr = document.getElementById('codeflask-Toggle-RR8KtX7iUH');
bottomBtn1790134439T1nQr.addEventListener('click', function() {
if (isCollapsed1790134439T1nQr) {
// 展开代码
isCollapsed1790134439T1nQr = false;
const codeElement1790134439T1nQr = editorElem1790134439T1nQr.querySelector('.codeflask__code');
if (codeElement1790134439T1nQr) {
const actualHeight1790134439T1nQr = codeElement1790134439T1nQr.scrollHeight + 20;
editorElem1790134439T1nQr.parentElement.style.height = actualHeight1790134439T1nQr + 'px';
editorElem1790134439T1nQr.style.height = actualHeight1790134439T1nQr + 'px';
}
bottomBtn1790134439T1nQr.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439T1nQr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439T1nQr = true;
if (coderow1790134439T1nQr < 20) {
editorElem1790134439T1nQr.parentElement.style.height = '300px';
editorElem1790134439T1nQr.style.height = '300px';
} else if (coderow1790134439T1nQr >= 20) {
editorElem1790134439T1nQr.parentElement.style.height = '500px';
editorElem1790134439T1nQr.style.height = '500px';
}
bottomBtn1790134439T1nQr.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439T1nQr.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439T1nQr.addEventListener('click', function() {
bottomBtn1790134439T1nQr.click();
});
</script><div class="ce-block ce-block--focused" data-id="CEFnd0LP71" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">预期返回 HTTP 200。若要验证国内直连 Cloudflare,应临时关闭 TUN 并清除系统戴丽后测试;经已有戴丽成功访问,不能证明国内直连也一定可达。</div>
</div>
</div><div class="ce-block" data-id="wL-1caXFxf" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">3. 验证 WebSocket</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="8nDyf7ChSo" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">在具备 curl 的 Linux / macOS 终端执行以下握手检查。若要检查客户端到 Cloudflare 这一段,应在客户端所在网络执行,而不只在 VPS 上执行:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="he1zIoa5EL" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-he1zIoa5EL">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-he1zIoa5EL">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-he1zIoa5EL" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-he1zIoa5EL">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439e538L = document.getElementById('codeflask-he1zIoa5EL');
var isCollapsed1790134439e538L = true;
const flask1790134439e538L = new CodeFlask(editorElem1790134439e538L, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439e538L = `curl --http1.1 -i --max-time 5 https://example.com/bridge \
-H 'Connection: Upgrade' \
-H 'Upgrade: websocket' \
-H 'Sec-WebSocket-Version: 13' \
-H 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=='`;
code1790134439e538L = code1790134439e538L.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439e538L.addLanguage('shell', Prism.languages['shell']);
flask1790134439e538L.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439e538L.updateCode(code1790134439e538L);
const currentCode1790134439e538L = flask1790134439e538L.getCode();
var coderow1790134439e538L = parseInt('');
if (coderow1790134439e538L === undefined || coderow1790134439e538L !== coderow1790134439e538L || coderow1790134439e538L === 0) {
coderow1790134439e538L = flask1790134439e538L.lineNumber;
}
if (coderow1790134439e538L < 20) {
editorElem1790134439e538L.parentElement.style.height = '300px';
editorElem1790134439e538L.style.height = '300px';
} else if (coderow1790134439e538L >= 20) {
editorElem1790134439e538L.parentElement.style.height = '500px';
editorElem1790134439e538L.style.height = '500px';
}
//console.log({currentCode1790134439e538L})
const copyBtn1790134439e538L = document.getElementById('codeflask-copy-he1zIoa5EL');
copyBtn1790134439e538L.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439e538L).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439e538L.innerHTML;
copyBtn1790134439e538L.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439e538L.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439e538L);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439e538L);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439e538L.innerHTML;
copyBtn1790134439e538L.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439e538L.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439e538L = document.getElementById('codeflask-bottomBtn-he1zIoa5EL');
const Toggle1790134439e538L = document.getElementById('codeflask-Toggle-he1zIoa5EL');
bottomBtn1790134439e538L.addEventListener('click', function() {
if (isCollapsed1790134439e538L) {
// 展开代码
isCollapsed1790134439e538L = false;
const codeElement1790134439e538L = editorElem1790134439e538L.querySelector('.codeflask__code');
if (codeElement1790134439e538L) {
const actualHeight1790134439e538L = codeElement1790134439e538L.scrollHeight + 20;
editorElem1790134439e538L.parentElement.style.height = actualHeight1790134439e538L + 'px';
editorElem1790134439e538L.style.height = actualHeight1790134439e538L + 'px';
}
bottomBtn1790134439e538L.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439e538L.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439e538L = true;
if (coderow1790134439e538L < 20) {
editorElem1790134439e538L.parentElement.style.height = '300px';
editorElem1790134439e538L.style.height = '300px';
} else if (coderow1790134439e538L >= 20) {
editorElem1790134439e538L.parentElement.style.height = '500px';
editorElem1790134439e538L.style.height = '500px';
}
bottomBtn1790134439e538L.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439e538L.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439e538L.addEventListener('click', function() {
bottomBtn1790134439e538L.click();
});
</script><div class="ce-block ce-block--focused" data-id="NeJDj4LNh7" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">预期看到<span> </span><code>101 Switching Protocols</code>,表示 WebSocket 升级成功。该命令不会发送完整 VMess 会话,之后超时或连接关闭不代表前面的握手失败。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="OT98Kn8nK0" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">直接在浏览器访问<span> </span><code>/bridge</code><span> </span>不会自动构造上述握手,因此不能用普通页面响应代替 WebSocket 测试。</div>
</div>
</div><div class="ce-block" data-id="_tC8zSbkJ4" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">4. 验证完整戴丽访问</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="LA2e6HoXUb" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">在 v2**yN 中选中节点,开启系统戴丽,再访问需要经过戴丽的目标网站。此步骤才同时验证 VMess 认证、VPS 出站和应用访问。</div>
</div>
</div><div class="ce-block" data-id="q-gus4QayF" >
<div class="ce-block__content">
<div class="cdx-block">
<div class="tc-wrap">
<div class="tc-table">
<div class="tc-row">
<div class="tc-cell">现象</div>
<div class="tc-cell">已验证的范围</div>
</div>
<div class="tc-row">
<div class="tc-cell">DNS 返回 Cloudflare 地址</div>
<div class="tc-cell">域名解析与橙云入口</div>
</div>
<div class="tc-row">
<div class="tc-cell">HTTPS 返回 200</div>
<div class="tc-cell">页面访问链路</div>
</div>
<div class="tc-row">
<div class="tc-cell">WebSocket 返回 101</div>
<div class="tc-cell">WebSocket 转发链路</div>
</div>
<div class="tc-row">
<div class="tc-cell">客户端通过该节点访问目标成功</div>
<div class="tc-cell">完整戴丽链路</div>
</div>
</div>
</div>
</div>
</div>
</div><div class="ce-block" data-id="IO2wHoBY8K" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">十一、本次遇到的两个实际问题</h2>
</div>
</div><div class="ce-block" data-id="wlWwn5jXyW" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">问题一:公共 DNS 正常,但本机始终打不开网页</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="ztZndLU308" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">当时公共 DNS 已经返回 Cloudflare 地址,外部检测也能够访问页面,但 Windows 本机查询出现:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="LYvXIQh67g" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-LYvXIQh67g">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-LYvXIQh67g">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-LYvXIQh67g" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-LYvXIQh67g">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439Wx131 = document.getElementById('codeflask-LYvXIQh67g');
var isCollapsed1790134439Wx131 = true;
const flask1790134439Wx131 = new CodeFlask(editorElem1790134439Wx131, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439Wx131 = `DNS request timed out.
服务器: UnKnown
Address: 172.19.0.2
名称: example.com`;
code1790134439Wx131 = code1790134439Wx131.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439Wx131.addLanguage('shell', Prism.languages['shell']);
flask1790134439Wx131.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439Wx131.updateCode(code1790134439Wx131);
const currentCode1790134439Wx131 = flask1790134439Wx131.getCode();
var coderow1790134439Wx131 = parseInt('');
if (coderow1790134439Wx131 === undefined || coderow1790134439Wx131 !== coderow1790134439Wx131 || coderow1790134439Wx131 === 0) {
coderow1790134439Wx131 = flask1790134439Wx131.lineNumber;
}
if (coderow1790134439Wx131 < 20) {
editorElem1790134439Wx131.parentElement.style.height = '300px';
editorElem1790134439Wx131.style.height = '300px';
} else if (coderow1790134439Wx131 >= 20) {
editorElem1790134439Wx131.parentElement.style.height = '500px';
editorElem1790134439Wx131.style.height = '500px';
}
//console.log({currentCode1790134439Wx131})
const copyBtn1790134439Wx131 = document.getElementById('codeflask-copy-LYvXIQh67g');
copyBtn1790134439Wx131.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439Wx131).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439Wx131.innerHTML;
copyBtn1790134439Wx131.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439Wx131.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439Wx131);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439Wx131);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439Wx131.innerHTML;
copyBtn1790134439Wx131.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439Wx131.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439Wx131 = document.getElementById('codeflask-bottomBtn-LYvXIQh67g');
const Toggle1790134439Wx131 = document.getElementById('codeflask-Toggle-LYvXIQh67g');
bottomBtn1790134439Wx131.addEventListener('click', function() {
if (isCollapsed1790134439Wx131) {
// 展开代码
isCollapsed1790134439Wx131 = false;
const codeElement1790134439Wx131 = editorElem1790134439Wx131.querySelector('.codeflask__code');
if (codeElement1790134439Wx131) {
const actualHeight1790134439Wx131 = codeElement1790134439Wx131.scrollHeight + 20;
editorElem1790134439Wx131.parentElement.style.height = actualHeight1790134439Wx131 + 'px';
editorElem1790134439Wx131.style.height = actualHeight1790134439Wx131 + 'px';
}
bottomBtn1790134439Wx131.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439Wx131.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439Wx131 = true;
if (coderow1790134439Wx131 < 20) {
editorElem1790134439Wx131.parentElement.style.height = '300px';
editorElem1790134439Wx131.style.height = '300px';
} else if (coderow1790134439Wx131 >= 20) {
editorElem1790134439Wx131.parentElement.style.height = '500px';
editorElem1790134439Wx131.style.height = '500px';
}
bottomBtn1790134439Wx131.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439Wx131.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439Wx131.addEventListener('click', function() {
bottomBtn1790134439Wx131.click();
});
</script><div class="ce-block ce-block--focused" data-id="qSVAe97OjH" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">进一步查看网卡配置,发现<span> </span><code>172.19.0.2</code><span> </span>属于本机<span> </span><code>singbox_tun</code><span> </span>虚拟网卡,查询实际经过 v2**yN / sing-box 的 TUN DNS。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="Z8xfKyMKVg" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">关闭 TUN 后,网页恢复访问。这将问题范围缩小到了当时的 TUN DNS 解析链路;不能仅凭这个现象断言是哪一个上游 DNS、缓存或路由规则出错。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="evlWJbK5An" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">遇到类似情况,可以按顺序排查:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="u_OiaJu-zh" >
<div class="ce-block__content">
<ol class="cdx-list-ordered" style="list-style-type:none; margin-left: -15px;"><li class="cdx-list__item">1. 记录当前客户端配置,临时关闭 TUN。</li><li class="cdx-list__item">2. 清除系统戴丽,单独验证直连域名。</li><li class="cdx-list__item">3. 在管理员 PowerShell 中清除系统 DNS 缓存并重新查询。</li><li class="cdx-list__item">4. 若恢复正常,再检查戴丽客户端的 DNS 与路由配置。</li></ol>
</div>
</div><div class="ce-block ce-block--focused" data-id="YXEgacrWsh" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-YXEgacrWsh">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-YXEgacrWsh">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-YXEgacrWsh" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-YXEgacrWsh">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439kthqA = document.getElementById('codeflask-YXEgacrWsh');
var isCollapsed1790134439kthqA = true;
const flask1790134439kthqA = new CodeFlask(editorElem1790134439kthqA, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439kthqA = `ipconfig /flushdns
nslookup example.com`;
code1790134439kthqA = code1790134439kthqA.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439kthqA.addLanguage('shell', Prism.languages['shell']);
flask1790134439kthqA.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439kthqA.updateCode(code1790134439kthqA);
const currentCode1790134439kthqA = flask1790134439kthqA.getCode();
var coderow1790134439kthqA = parseInt('');
if (coderow1790134439kthqA === undefined || coderow1790134439kthqA !== coderow1790134439kthqA || coderow1790134439kthqA === 0) {
coderow1790134439kthqA = flask1790134439kthqA.lineNumber;
}
if (coderow1790134439kthqA < 20) {
editorElem1790134439kthqA.parentElement.style.height = '300px';
editorElem1790134439kthqA.style.height = '300px';
} else if (coderow1790134439kthqA >= 20) {
editorElem1790134439kthqA.parentElement.style.height = '500px';
editorElem1790134439kthqA.style.height = '500px';
}
//console.log({currentCode1790134439kthqA})
const copyBtn1790134439kthqA = document.getElementById('codeflask-copy-YXEgacrWsh');
copyBtn1790134439kthqA.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439kthqA).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439kthqA.innerHTML;
copyBtn1790134439kthqA.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439kthqA.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439kthqA);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439kthqA);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439kthqA.innerHTML;
copyBtn1790134439kthqA.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439kthqA.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439kthqA = document.getElementById('codeflask-bottomBtn-YXEgacrWsh');
const Toggle1790134439kthqA = document.getElementById('codeflask-Toggle-YXEgacrWsh');
bottomBtn1790134439kthqA.addEventListener('click', function() {
if (isCollapsed1790134439kthqA) {
// 展开代码
isCollapsed1790134439kthqA = false;
const codeElement1790134439kthqA = editorElem1790134439kthqA.querySelector('.codeflask__code');
if (codeElement1790134439kthqA) {
const actualHeight1790134439kthqA = codeElement1790134439kthqA.scrollHeight + 20;
editorElem1790134439kthqA.parentElement.style.height = actualHeight1790134439kthqA + 'px';
editorElem1790134439kthqA.style.height = actualHeight1790134439kthqA + 'px';
}
bottomBtn1790134439kthqA.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439kthqA.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439kthqA = true;
if (coderow1790134439kthqA < 20) {
editorElem1790134439kthqA.parentElement.style.height = '300px';
editorElem1790134439kthqA.style.height = '300px';
} else if (coderow1790134439kthqA >= 20) {
editorElem1790134439kthqA.parentElement.style.height = '500px';
editorElem1790134439kthqA.style.height = '500px';
}
bottomBtn1790134439kthqA.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439kthqA.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439kthqA.addEventListener('click', function() {
bottomBtn1790134439kthqA.click();
});
</script><div class="ce-block ce-block--focused" data-id="CkINBMGJ_s" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"> 可以用以下命令查看 DNS 绑定到了哪张网卡:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="r9pXODB6Hh" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-r9pXODB6Hh">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-r9pXODB6Hh">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-r9pXODB6Hh" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-r9pXODB6Hh">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439PnGY2 = document.getElementById('codeflask-r9pXODB6Hh');
var isCollapsed1790134439PnGY2 = true;
const flask1790134439PnGY2 = new CodeFlask(editorElem1790134439PnGY2, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439PnGY2 = `netsh interface ipv4 show dnsservers`;
code1790134439PnGY2 = code1790134439PnGY2.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439PnGY2.addLanguage('shell', Prism.languages['shell']);
flask1790134439PnGY2.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439PnGY2.updateCode(code1790134439PnGY2);
const currentCode1790134439PnGY2 = flask1790134439PnGY2.getCode();
var coderow1790134439PnGY2 = parseInt('');
if (coderow1790134439PnGY2 === undefined || coderow1790134439PnGY2 !== coderow1790134439PnGY2 || coderow1790134439PnGY2 === 0) {
coderow1790134439PnGY2 = flask1790134439PnGY2.lineNumber;
}
if (coderow1790134439PnGY2 < 20) {
editorElem1790134439PnGY2.parentElement.style.height = '300px';
editorElem1790134439PnGY2.style.height = '300px';
} else if (coderow1790134439PnGY2 >= 20) {
editorElem1790134439PnGY2.parentElement.style.height = '500px';
editorElem1790134439PnGY2.style.height = '500px';
}
//console.log({currentCode1790134439PnGY2})
const copyBtn1790134439PnGY2 = document.getElementById('codeflask-copy-r9pXODB6Hh');
copyBtn1790134439PnGY2.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439PnGY2).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439PnGY2.innerHTML;
copyBtn1790134439PnGY2.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439PnGY2.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439PnGY2);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439PnGY2);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439PnGY2.innerHTML;
copyBtn1790134439PnGY2.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439PnGY2.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439PnGY2 = document.getElementById('codeflask-bottomBtn-r9pXODB6Hh');
const Toggle1790134439PnGY2 = document.getElementById('codeflask-Toggle-r9pXODB6Hh');
bottomBtn1790134439PnGY2.addEventListener('click', function() {
if (isCollapsed1790134439PnGY2) {
// 展开代码
isCollapsed1790134439PnGY2 = false;
const codeElement1790134439PnGY2 = editorElem1790134439PnGY2.querySelector('.codeflask__code');
if (codeElement1790134439PnGY2) {
const actualHeight1790134439PnGY2 = codeElement1790134439PnGY2.scrollHeight + 20;
editorElem1790134439PnGY2.parentElement.style.height = actualHeight1790134439PnGY2 + 'px';
editorElem1790134439PnGY2.style.height = actualHeight1790134439PnGY2 + 'px';
}
bottomBtn1790134439PnGY2.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439PnGY2.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439PnGY2 = true;
if (coderow1790134439PnGY2 < 20) {
editorElem1790134439PnGY2.parentElement.style.height = '300px';
editorElem1790134439PnGY2.style.height = '300px';
} else if (coderow1790134439PnGY2 >= 20) {
editorElem1790134439PnGY2.parentElement.style.height = '500px';
editorElem1790134439PnGY2.style.height = '500px';
}
bottomBtn1790134439PnGY2.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439PnGY2.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439PnGY2.addEventListener('click', function() {
bottomBtn1790134439PnGY2.click();
});
</script><div class="ce-block ce-block--focused" data-id="gY2ZFJHpuV" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left"><code>UnKnown</code><span> </span>只是 DNS 服务器名称未能显示,单独出现并不能证明 DNS 故障;本次关键现象是查询超时且没有返回地址。<code>172.19.0.2</code><span> </span>也不是所有客户端固定使用的地址,要以实际网卡配置为准。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="qel_XP0y3d" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">TUN 可以接管 DNS 请求,所以只刷新 Windows 缓存不一定能清除戴丽核心或上游 DNS 中的问题。<a href="https://sing-box.sagernet.org/zh/configuration/inbound/tun/" rel="noopener nofollow ugc">sing-box TUN 文档</a></div>
</div>
</div><div class="ce-block" data-id="2WrjnKvVPa" >
<div class="ce-block__content" style="">
<h3 class="ce-header ce-header--left">问题二:网页能打开,但 v2**yN 节点连接失败</h3>
</div>
</div><div class="ce-block ce-block--focused" data-id="WpP-pc8--d" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">当时客户端仍保留默认参数:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="dWHaaeOyQB" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-dWHaaeOyQB">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-dWHaaeOyQB">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-dWHaaeOyQB" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-dWHaaeOyQB">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439PJKzs = document.getElementById('codeflask-dWHaaeOyQB');
var isCollapsed1790134439PJKzs = true;
const flask1790134439PJKzs = new CodeFlask(editorElem1790134439PJKzs, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439PJKzs = `network = tcp
TLS = 未开启
Host = 空
path = 空`;
code1790134439PJKzs = code1790134439PJKzs.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439PJKzs.addLanguage('shell', Prism.languages['shell']);
flask1790134439PJKzs.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439PJKzs.updateCode(code1790134439PJKzs);
const currentCode1790134439PJKzs = flask1790134439PJKzs.getCode();
var coderow1790134439PJKzs = parseInt('');
if (coderow1790134439PJKzs === undefined || coderow1790134439PJKzs !== coderow1790134439PJKzs || coderow1790134439PJKzs === 0) {
coderow1790134439PJKzs = flask1790134439PJKzs.lineNumber;
}
if (coderow1790134439PJKzs < 20) {
editorElem1790134439PJKzs.parentElement.style.height = '300px';
editorElem1790134439PJKzs.style.height = '300px';
} else if (coderow1790134439PJKzs >= 20) {
editorElem1790134439PJKzs.parentElement.style.height = '500px';
editorElem1790134439PJKzs.style.height = '500px';
}
//console.log({currentCode1790134439PJKzs})
const copyBtn1790134439PJKzs = document.getElementById('codeflask-copy-dWHaaeOyQB');
copyBtn1790134439PJKzs.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439PJKzs).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439PJKzs.innerHTML;
copyBtn1790134439PJKzs.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439PJKzs.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439PJKzs);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439PJKzs);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439PJKzs.innerHTML;
copyBtn1790134439PJKzs.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439PJKzs.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439PJKzs = document.getElementById('codeflask-bottomBtn-dWHaaeOyQB');
const Toggle1790134439PJKzs = document.getElementById('codeflask-Toggle-dWHaaeOyQB');
bottomBtn1790134439PJKzs.addEventListener('click', function() {
if (isCollapsed1790134439PJKzs) {
// 展开代码
isCollapsed1790134439PJKzs = false;
const codeElement1790134439PJKzs = editorElem1790134439PJKzs.querySelector('.codeflask__code');
if (codeElement1790134439PJKzs) {
const actualHeight1790134439PJKzs = codeElement1790134439PJKzs.scrollHeight + 20;
editorElem1790134439PJKzs.parentElement.style.height = actualHeight1790134439PJKzs + 'px';
editorElem1790134439PJKzs.style.height = actualHeight1790134439PJKzs + 'px';
}
bottomBtn1790134439PJKzs.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439PJKzs.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439PJKzs = true;
if (coderow1790134439PJKzs < 20) {
editorElem1790134439PJKzs.parentElement.style.height = '300px';
editorElem1790134439PJKzs.style.height = '300px';
} else if (coderow1790134439PJKzs >= 20) {
editorElem1790134439PJKzs.parentElement.style.height = '500px';
editorElem1790134439PJKzs.style.height = '500px';
}
bottomBtn1790134439PJKzs.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439PJKzs.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439PJKzs.addEventListener('click', function() {
bottomBtn1790134439PJKzs.click();
});
</script><div class="ce-block ce-block--focused" data-id="9zaV37uO-2" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">而服务端部署的是<span> </span><code>VMess + WebSocket + TLS</code>。两端传输参数不一致,连接自然无法完成。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="fI26c1mII8" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">修改为:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="6hCvUWaN0T" >
<div class="ce-block__content">
<div class="cdx-block ce-rawtool">
<textarea class="ce-rawtool__textarea cdx-input">
network = ws
TLS = tls
Host = example.com
path = /bridge
SNI = example.com
</textarea>
</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="60Q_9_FhMR" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">并确认 UUID 与服务端一致后,节点连接成功。</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="fP-KQIsJAE" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">客户端的延迟<span> </span><code>-1</code><span> </span>或“跳过测试”只表示该次测试没有成功,不能直接当成 VPS 不可达或 Cloudflare 无法回源的证据。</div>
</div>
</div><div class="ce-block" data-id="SnsPL4yt-t" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">十二、其他常见问题</h2>
</div>
</div><div class="ce-block" data-id="1UjkCAwUhW" >
<div class="ce-block__content">
<div class="cdx-block">
<div class="tc-wrap">
<div class="tc-table">
<div class="tc-row">
<div class="tc-cell">现象</div>
<div class="tc-cell">优先检查</div>
</div>
<div class="tc-row">
<div class="tc-cell">域名无法解析</div>
<div class="tc-cell">DNS 记录、域名委派、本机 DNS、TUN DNS、缓存</div>
</div>
<div class="tc-row">
<div class="tc-cell">Cloudflare 521</div>
<div class="tc-cell">源站拒绝连接;检查 Nginx 是否监听和防火墙规则</div>
</div>
<div class="tc-row">
<div class="tc-cell">Cloudflare 522</div>
<div class="tc-cell">Cloudflare 回源连接超时;检查网络、安全组及源站状态</div>
</div>
<div class="tc-row">
<div class="tc-cell">Cloudflare 525</div>
<div class="tc-cell">Cloudflare 与源站 TLS 握手失败</div>
</div>
<div class="tc-row">
<div class="tc-cell">Cloudflare 526</div>
<div class="tc-cell">Full (strict) 模式下源站证书验证失败</div>
</div>
<div class="tc-row">
<div class="tc-cell"><code>/bridge</code><span> </span>返回 502</div>
<div class="tc-cell">检查 v2**y 是否运行、是否监听 127.0.0.1:10000,以及 Nginx 错误日志</div>
</div>
<div class="tc-row">
<div class="tc-cell">普通页面正常,WebSocket 握手异常</div>
<div class="tc-cell">三处路径是否一致、升级头、Cloudflare WebSocket 设置与安全规则</div>
</div>
<div class="tc-row">
<div class="tc-cell">WebSocket 返回 101,但戴丽仍失败</div>
<div class="tc-cell">UUID、VMess 配置、系统时间、服务端出站网络</div>
</div>
</div>
</div>
</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="SKO7C2fwQe" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">HTTP 错误码只能帮助定位范围,最终应结合响应来源及日志判断。<a href="https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/" rel="noopener nofollow ugc">Cloudflare 5xx 错误文档</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="YctK0A1OQI" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">服务端常用排查命令:</div>
</div>
</div><div class="ce-block ce-block--focused" data-id="LH0PgY3ed9" >
<div class="ce-block__content">
<div class="editorjs-codeFlask_Wrapper">
<div class="editorjs-codeFlask_Header">
<div class="editorjs-codeFlask_LangDisplay">shell</div>
<button class="editorjs-codeFlask_CopyButton" title="复制代码" id="codeflask-copy-LH0PgY3ed9">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button class="editorjs-codeFlask_Toggle" id="codeflask-Toggle-LH0PgY3ed9">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</button>
</div>
<div class="editorjs-codeFlask_ContentContainer">
<div class="editorjs-codeFlask_Editor" id="codeflask-LH0PgY3ed9" >
</div>
</div>
<div class="editorjs-codeFlask_BottomButtonContainer" id="codeflask-bottomBtn-LH0PgY3ed9">
<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="static/js/editorjs/tools/codeflask/codeflask150.min.js?xvG"></script>
<script type="application/javascript">
const editorElem1790134439c5t5M = document.getElementById('codeflask-LH0PgY3ed9');
var isCollapsed1790134439c5t5M = true;
const flask1790134439c5t5M = new CodeFlask(editorElem1790134439c5t5M, {
language: 'shell',
lineNumbers: true,
styleParent: this.shadowRoot,
rtl: false,
readonly: true
});
var code1790134439c5t5M = `sudo journalctl -u v2**y -n 100 --no-pager
sudo tail -n 100 /var/log/nginx/error.log
sudo tail -n 100 /var/log/nginx/access.log
sudo ss -lntp
timedatectl status`;
code1790134439c5t5M = code1790134439c5t5M.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'");
flask1790134439c5t5M.addLanguage('shell', Prism.languages['shell']);
flask1790134439c5t5M.onUpdate((code) => {
// do something with code here.
// this will trigger whenever the code
// in the editor changes.
// console.log(code)
});
// flask.updateCode('');
// This will also trigger .onUpdate()
flask1790134439c5t5M.updateCode(code1790134439c5t5M);
const currentCode1790134439c5t5M = flask1790134439c5t5M.getCode();
var coderow1790134439c5t5M = parseInt('');
if (coderow1790134439c5t5M === undefined || coderow1790134439c5t5M !== coderow1790134439c5t5M || coderow1790134439c5t5M === 0) {
coderow1790134439c5t5M = flask1790134439c5t5M.lineNumber;
}
if (coderow1790134439c5t5M < 20) {
editorElem1790134439c5t5M.parentElement.style.height = '300px';
editorElem1790134439c5t5M.style.height = '300px';
} else if (coderow1790134439c5t5M >= 20) {
editorElem1790134439c5t5M.parentElement.style.height = '500px';
editorElem1790134439c5t5M.style.height = '500px';
}
//console.log({currentCode1790134439c5t5M})
const copyBtn1790134439c5t5M = document.getElementById('codeflask-copy-LH0PgY3ed9');
copyBtn1790134439c5t5M.addEventListener('click', function() {
try {
// 先检查 Clipboard API 是否可用
if (navigator.clipboard && navigator.clipboard.writeText) {
// 使用 Clipboard API 复制代码
navigator.clipboard.writeText(code1790134439c5t5M).then(function() {
// 复制成功提示
const originalText = copyBtn1790134439c5t5M.innerHTML;
copyBtn1790134439c5t5M.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
// 一段时间后恢复原文本
setTimeout(function() {
copyBtn1790134439c5t5M.innerHTML = originalText;
}, 2000);
}).catch(function(err) {
// 复制失败处理
console.error('复制失败:', err);
// 降级方案:使用传统的复制方法
fallbackCopyTextToClipboard(code1790134439c5t5M);
});
} else {
// Clipboard API 不可用时直接使用降级方案
fallbackCopyTextToClipboard(code1790134439c5t5M);
}
// 提取降级方案为独立函数
function fallbackCopyTextToClipboard(text) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
const originalText = copyBtn1790134439c5t5M.innerHTML;
copyBtn1790134439c5t5M.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> 已复制';
setTimeout(function() {
copyBtn1790134439c5t5M.innerHTML = originalText;
}, 2000);
} catch (copyErr) {
console.error('传统复制方法也失败了:', copyErr);
} finally {
document.body.removeChild(textArea);
}
}
} catch (err) {
console.error('复制功能不可用:', err);
}
});
const bottomBtn1790134439c5t5M = document.getElementById('codeflask-bottomBtn-LH0PgY3ed9');
const Toggle1790134439c5t5M = document.getElementById('codeflask-Toggle-LH0PgY3ed9');
bottomBtn1790134439c5t5M.addEventListener('click', function() {
if (isCollapsed1790134439c5t5M) {
// 展开代码
isCollapsed1790134439c5t5M = false;
const codeElement1790134439c5t5M = editorElem1790134439c5t5M.querySelector('.codeflask__code');
if (codeElement1790134439c5t5M) {
const actualHeight1790134439c5t5M = codeElement1790134439c5t5M.scrollHeight + 20;
editorElem1790134439c5t5M.parentElement.style.height = actualHeight1790134439c5t5M + 'px';
editorElem1790134439c5t5M.style.height = actualHeight1790134439c5t5M + 'px';
}
bottomBtn1790134439c5t5M.innerHTML = '<button class="editorjs-codeFlask_BottomToggle" title="折叠代码"><span class="toggle-icon">▲</span> 折叠</button>';
Toggle1790134439c5t5M.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>';
} else {
// 折叠代码
isCollapsed1790134439c5t5M = true;
if (coderow1790134439c5t5M < 20) {
editorElem1790134439c5t5M.parentElement.style.height = '300px';
editorElem1790134439c5t5M.style.height = '300px';
} else if (coderow1790134439c5t5M >= 20) {
editorElem1790134439c5t5M.parentElement.style.height = '500px';
editorElem1790134439c5t5M.style.height = '500px';
}
bottomBtn1790134439c5t5M.innerHTML = '<button class="editorjs-codeFlask_BottomToggle expand-mode" title="展开代码" data-empty="false"><span class="toggle-icon">▼</span> 展开</button>';
Toggle1790134439c5t5M.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>';
}
});
Toggle1790134439c5t5M.addEventListener('click', function() {
bottomBtn1790134439c5t5M.click();
});
</script><div class="ce-block ce-block--focused" data-id="7vqb9nPNMT" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">VMess 依赖时间校验,客户端和服务器都应保持系统时间同步。仅改变时区不能修复实际时钟偏差。<a href="https://www.v2fly.org/config/protocols/vmess.html" rel="noopener nofollow ugc">VMess 时间要求</a></div>
</div>
</div><div class="ce-block ce-block--focused" data-id="JH-aUzJhxX" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">此外,ping 测试的是 ICMP:ping 不通并不足以证明 TCP 服务无法访问;测试 TCP 端口也需要确认该端口确实有服务监听。</div>
</div>
</div><div class="ce-block" data-id="BFbjIhlaQW" >
<div class="ce-block__content" style="">
<h2 class="ce-header ce-header--left">十三、部署完成后的核对</h2>
</div>
</div><div class="ce-block ce-block--focused" data-id="keBAHtcVy6" >
<div class="ce-block__content">
<ul class="cdx-list-unordered"><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>域名已接入 Cloudflare,实际连接域名的记录开启橙云。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>Cloudflare 边缘证书已生效,WebSocket 已开启。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>Nginx 源站证书覆盖连接域名,回源使用 Full (strict)。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>Cloudflare 能访问 VPS 的 TCP 443。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>v2**y 监听<span> </span><code>127.0.0.1:10000</code>,公网无需开放 10000。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>客户端使用<span> </span><code>ws + tls</code>,Host、SNI 和地址正确。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>客户端、Nginx、v2**y 的路径均为<span> </span><code>/bridge</code>。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>UUID 一致,AlterID 为 0,客户端加密方式为 auto。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>HTTPS、WebSocket 和完整戴丽访问均已分别验证。</li><li class="cdx-list__item"><span class="chcklst-box fa fa-square-o list-item-checkbox"></span><span> </span>若启用 TUN,已单独验证 DNS 与路由。</li></ul>
</div>
</div><div class="ce-block ce-block--focused" data-id="3Dk-6AopZC" >
<div class="ce-block__content">
<div class="ce-paragraph cdx-block ce-paragraph--left">本次排障最有用的方法是按层检查:先确认 DNS,再检查 HTTPS 和 WebSocket,最后验证 VMess 认证与出站。这样可以避免把本机 DNS 异常当作服务端故障,也能快速发现客户端参数与服务端不一致的问题。</div>
</div>
</div><style type="text/css">
.ce-block {
margin-top: 20px;
margin-bottom: 20px;
}
.ce-block__content,.ce-toolbar__content {
/* max-width:calc(100% - 50px) */
margin-left: auto;
margin-right: auto;
}
/**
* Plugin styles
*/
.ce-header {
position: relative;
padding: 1px 0px 1px 15px;
margin: 0;
line-height: 1.25em;
outline: none;
margin-bottom: 10px;
}
.ce-header p,
.ce-header div {
padding: 0 !important;
margin: 0 !important;
}
.ce-header::before {
content: "";
background-color: #3e8fe3;
width: 6px;
height: 100%;
position: absolute;
left: 0;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
/**
* Styles for Plugin icon in Toolbar
*/
.ce-header__icon {
}
.ce-header::before {
position: absolute;
content: attr(data-placeholder);
color: #707684;
font-weight: normal;
display: none;
cursor: text;
}
.ce-header:empty::before {
display: block;
}
.ce-header:empty:focus::before {
display: none;
}
/* FontSize */
h1.ce-header {
font-size: 2.0em;
}
h2.ce-header {
font-size: 1.7em;
}
h3.ce-header {
font-size: 1.4em;
}
h4.ce-header {
font-size: 1.15em;
}
h5.ce-header {
font-size: 0.95em;
}
h6.ce-header {
font-size: 0.8em;
}
/* Alignment*/
.ce-header--right {
text-align: right;
}
.ce-header--center {
text-align: center;
}
.ce-header--left {
text-align: left;
}
.ce-header--justify {
text-align: justify;
}
</style><style type="text/css">
.ce-block {
margin-bottom: 20px;
}
.ce-block__content,.ce-toolbar__content {
/* max-width:calc(100% - 50px) */
margin-left: auto;
margin-right: auto;
}
.ce-paragraph {
line-height: 1.6em;
outline: none;
text-indent: 2em;
font-size: 16px;
}
.ce-paragraph--right {
text-align: right;
}
.ce-paragraph--center {
text-align: center;
}
.ce-paragraph--left {
text-align: left;
}
.ce-paragraph--justify {
text-align: justify;
}
.ce-paragraph-text-indent {
text-align: justify;
}
.ce-paragraph:empty::before{
content: attr(data-placeholder);
color: #707684;
font-weight: normal;
opacity: 0;
}
/** Show placeholder at the first paragraph if Editor is empty */
.codex-editor--empty .ce-block:first-child .ce-paragraph:empty::before {
opacity: 1;
}
.codex-editor--toolbox-opened .ce-block:first-child .ce-paragraph:empty::before,
.codex-editor--empty .ce-block:first-child .ce-paragraph:empty:focus::before {
opacity: 0;
}
.ce-paragraph p:first-of-type{
margin-top: 0;
}
.ce-paragraph p:last-of-type{
margin-bottom: 0;
}
.svg-icon {
width: 1em;
height: 1em;
}
.svg-icon path,
.svg-icon polygon,
.svg-icon rect {
fill: #4691f6;
}
.svg-icon circle {
stroke: #4691f6;
stroke-width: 1;
}
</style><style type="text/css">
.ce-block {
margin-bottom: 20px;
}
.ce-block__content,.ce-toolbar__content {
/* max-width:calc(100% - 50px) */
margin-left: auto;
margin-right: auto;
}
.tc-wrap {
--color-background:#f9f9fb;
--color-text-secondary:#7b7e89;
--color-border:#e8e8eb;
--cell-size:0px;
--toolbox-icon-size:18px;
--toolbox-padding:6px;
--toolbox-aiming-field-size:calc(var(--toolbox-icon-size) + var(--toolbox-padding)*2);
border:1px solid var(--color-border);
position:relative;
height:100%;
width:100%;
margin-top:var(--toolbox-icon-size);
box-sizing:border-box;
display:grid;
grid-template-columns:calc(100% - var(--cell-size)) var(--cell-size);
}
.tc-wrap--readonly {
grid-template-columns:100% var(--cell-size)
}
.tc-wrap svg {
vertical-align:top
}
@media print {
.tc-wrap {
border-left-color:var(--color-border);
border-left-style:solid;
border-left-width:1px;
grid-template-columns:100% var(--cell-size)
}
}@media print {
.tc-wrap .tc-row:after {
display:none
}
}.tc-table {
position:relative;
width:100%;
height:100%;
display:grid;
font-size:14px;
line-height:1.4;
}
.tc-table:after {
width:calc(var(--cell-size));
height:100%;
left:calc(var(--cell-size)*-1);
top:0
}
.tc-table:after,.tc-table:before {
position:absolute;
content:""
}
.tc-table:before {
width:100%;
height:var(--toolbox-aiming-field-size);
top:calc(var(--toolbox-aiming-field-size)*-1);
left:0
}
.tc-table--heading .tc-row:first-child {
font-weight:600;
border-bottom:2px solid var(--color-border);
}
.tc-table--heading .tc-row:first-child :empty:before {
content:attr(heading);
color:var(--color-text-secondary)
}
.tc-table--heading .tc-row:first-child:after {
bottom:-2px;
border-bottom:2px solid var(--color-border)
}
.tc-add-column,.tc-add-row {
display:flex;
color:var(--color-text-secondary)
}
@media print {
.tc-add {
display:none
}
}.tc-add-column {
padding:4px 0;
justify-content:center;
border-top:1px solid var(--color-border);
}
@media print {
.tc-add-column {
display:none
}
}.tc-add-row {
height:var(--cell-size);
align-items:center;
padding-left:4px;
position:relative;
}
.tc-add-row:before {
content:"";
position:absolute;
right:calc(var(--cell-size)*-1);
width:var(--cell-size);
height:100%
}
@media print {
.tc-add-row {
display:none
}
}.tc-add-column,.tc-add-row {
transition:0s;
cursor:pointer;
will-change:background-color;
}
.tc-add-column:hover,.tc-add-row:hover {
transition:background-color .1s ease;
background-color:var(--color-background)
}
.tc-add-row {
margin-top:1px;
}
.tc-add-row:hover:before {
transition:.1s;
background-color:var(--color-background)
}
.tc-row {
display:grid;
grid-template-columns:repeat(auto-fit,minmax(10px,1fr));
position:relative;
border-bottom:1px solid var(--color-border);
}
.tc-row:after {
content:"";
pointer-events:none;
position:absolute;
width:var(--cell-size);
height:100%;
bottom:-1px;
right:calc(var(--cell-size)*-1);
border-bottom:1px solid var(--color-border)
}
.tc-row--selected {
background:var(--color-background)
}
.tc-row--selected:after {
background:var(--color-background)
}
.tc-cell {
border-right:1px solid var(--color-border);
padding:6px 12px;
overflow:hidden;
outline:none;
line-break:normal;
}
.tc-cell--selected {
background:var(--color-background)
}
.tc-wrap--readonly .tc-row:after {
display:none
}
.tc-toolbox {
--toolbox-padding:6px;
--popover-margin:30px;
--toggler-click-zone-size:30px;
--toggler-dots-color:#7b7e89;
--toggler-dots-color-hovered:#1d202b;
position:absolute;
cursor:pointer;
z-index:1;
opacity:0;
transition:opacity .1s;
will-change:left,opacity;
}
.tc-toolbox--column {
top:calc(var(--toggler-click-zone-size)*-1);
transform:translateX(calc(var(--toggler-click-zone-size)*-1/2));
will-change:left,opacity
}
.tc-toolbox--row {
left:calc(var(--popover-margin)*-1);
transform:translateY(calc(var(--toggler-click-zone-size)*-1/2));
margin-top:-1px;
will-change:top,opacity
}
.tc-toolbox--showed {
opacity:1
}
.tc-toolbox .tc-popover {
position:absolute;
top:0;
left:var(--popover-margin)
}
.tc-toolbox__toggler {
display:flex;
align-items:center;
justify-content:center;
width:var(--toggler-click-zone-size);
height:var(--toggler-click-zone-size);
color:var(--toggler-dots-color);
opacity:0;
transition:opacity .15s ease;
will-change:opacity;
}
.tc-toolbox__toggler:hover {
color:var(--toggler-dots-color-hovered)
}
.tc-toolbox__toggler svg {
fill:currentColor
}
.tc-wrap:hover .tc-toolbox__toggler {
opacity:1
}
.tc-settings .cdx-settings-button {
width:50%;
margin:0
}
.tc-popover {
--color-border:#eaeaea;
--color-background:#fff;
--color-background-hover:rgba(232,232,235,0.49);
--color-background-confirm:#e24a4a;
--color-background-confirm-hover:#d54040;
--color-text-confirm:#fff;
background:var(--color-background);
border:1px solid var(--color-border);
box-shadow:0 3px 15px -3px rgba(13,20,33,.13);
border-radius:6px;
padding:6px;
display:none;
will-change:opacity,transform;
}
.tc-popover--opened {
display:block;
animation:menuShowing .1s cubic-bezier(.215,.61,.355,1) forwards
}
.tc-popover__item {
display:flex;
align-items:center;
padding:2px 14px 2px 2px;
border-radius:5px;
cursor:pointer;
white-space:nowrap;
-webkit-user-select:none;
-moz-user-select:none;
user-select:none;
}
.tc-popover__item:hover {
background:var(--color-background-hover)
}
.tc-popover__item:not(:last-of-type) {
margin-bottom:2px
}
.tc-popover__item-icon {
display:inline-flex;
width:26px;
height:26px;
align-items:center;
justify-content:center;
background:var(--color-background);
border-radius:5px;
border:1px solid var(--color-border);
margin-right:8px
}
.tc-popover__item-label {
line-height:22px;
font-size:14px;
font-weight:500
}
.tc-popover__item--confirm {
background:var(--color-background-confirm);
color:var(--color-text-confirm);
}
.tc-popover__item--confirm:hover {
background-color:var(--color-background-confirm-hover)
}
.tc-popover__item--confirm .tc-popover__item-icon {
background:var(--color-background-confirm);
border-color:rgba(0,0,0,.1);
}
.tc-popover__item--confirm .tc-popover__item-icon svg {
transition:transform .2s ease-in;
transform:rotate(90deg) scale(1.2)
}
.tc-popover__item--hidden {
display:none
}
@keyframes menuShowing {
0% {
opacity:0;
transform:translateY(-8px) scale(.9)
}
70% {
opacity:1;
transform:translateY(2px)
}
to {
transform:translateY(0)
}
}
</style><style type="text/css">
.ce-block {
margin-bottom: 20px;
}
.ce-block__content,.ce-toolbar__content {
/* max-width:calc(100% - 50px) */
margin-left: auto;
margin-right: auto;
}
.cdx-list {
margin:0;
outline:none;
display:block;
counter-reset:item;
padding:6px;
}
.cdx-list__item {
line-height:1.45em;
display:block;
padding-top:8px;
margin-left: 2em;
}
.cdx-list__item-children {
display:block;
}
.cdx-list__item {
outline:none
}
.cdx-list__item-content {
word-break:break-word;
white-space:pre-wrap;
grid-area:content;
padding-left:8px
}
.cdx-list__item:before {
counter-increment:item;
white-space:nowrap
}
.cdx-list-li-container {
display: flex;
}
.cdx-list-ordered .cdx-list__item:before {
/* content:counters(item,".",numeric) "." */
}
.cdx-list-ordered {
list-style-type: none;
margin-left: -15px;
counter-reset:item;
font-size: 16px;
}
.cdx-list-unordered {
font-size: 16px;
}
.cdx-list-unordered .cdx-list__item:before {
content:"•"
}
.cdx-list-checklist .cdx-list__item:before {
content:""
}
.cdx-list__settings .cdx-settings-button {
width:50%
}
.cdx-list__checkbox {
padding-top:calc((1.45em - 1.2em) / 2);
grid-area:checkbox;
width:1.2em;
height:1.2em;
display:flex;
cursor:pointer;
font-size: 16px;
}
.cdx-list__checkbox svg {
opacity:0;
height:1.2em;
width:1.2em;
left:-1px;
top:-1px;
position:absolute
}
@media (hover:hover) {
.cdx-list__checkbox:not(.cdx-list__checkbox--no-hover):hover .cdx-list__checkbox-check svg {
opacity:1
}
}.cdx-list__checkbox--checked-1 {
line-height:1.45em
}
@media (hover:hover) {
.cdx-list__checkbox--checked-1:not(.cdx-list__checkbox--checked-1--no-hover):hover .cdx-checklist__checkbox-check {
background:#0059AB;
border-color:#0059AB
}
}.cdx-list__checkbox--checked-1 .cdx-list__checkbox-check {
background:#369FFF;
border-color:#369FFF
}
.cdx-list__checkbox--checked-1 .cdx-list__checkbox-check svg {
opacity:1
}
.cdx-list__checkbox--checked-1 .cdx-list__checkbox-check svg path {
stroke:#fff
}
.cdx-list__checkbox--checked-1 .cdx-list__checkbox-check:before {
opacity:0;
visibility:visible;
transform:scale(2.5)
}
.cdx-list__checkbox-check {
cursor:pointer;
display:inline-block;
position:relative;
margin:0 auto;
width:1.2em;
height:1.2em;
box-sizing:border-box;
border-radius:5px;
border:1px solid #C9C9C9;
background:#fff
}
.cdx-list__checkbox-check:before {
content:"";
position:absolute;
top:0;
right:0;
bottom:0;
left:0;
border-radius:100%;
background-color:#369FFF;
visibility:hidden;
pointer-events:none;
transform:scale(1);
transition:transform .4s ease-out,opacity .4s
}
.cdx-list__checkbox-check--disabled {
pointer-events:none
}
.cdx-list-start-with-field {
background:#F8F8F8;
border:1px solid rgba(226,226,229,.2);
border-radius:6px;
padding:2px;
display:grid;
grid-template-columns:auto auto 1fr;
grid-template-rows:auto
}
.cdx-list-start-with-field--invalid {
background:#FFECED;
border:1px solid #E13F3F
}
.cdx-list-start-with-field--invalid .cdx-list-start-with-field__input {
color:#e13f3f
}
.cdx-list-start-with-field__input {
font-size:16px;
outline:none;
font-weight:500;
font-family:inherit;
border:0;
background:transparent;
margin:0;
padding:0;
line-height:22px;
min-width:calc(100% - 10px)
}
.cdx-list-start-with-field__input::placeholder {
color:#797979;
font-weight:500
}
</style><style type="text/css">
.ce-block {
margin-bottom: 20px;
}
.ce-block__content,.ce-toolbar__content {
/* max-width:calc(100% - 50px) */
margin-left: auto;
margin-right: auto;
position: relative;
}
/* 主容器 */
.editorjs-codeFlask_Wrapper {
border: 1px solid #dcdfe6;
border-radius: 5px;
background-color: #f6f8fa;
margin-bottom: 10px;
position: relative;
transition: all 0.3s ease;
width: 100%;
min-height: 100px;
overflow: hidden;
}
/* 标题栏 */
.editorjs-codeFlask_Header {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 8px 12px;
background-color: #e9ecef;
border-bottom: 1px solid #dcdfe6;
position: relative;
z-index: 0; /* 从10降低到2 */
}
/* 语言显示 */
.editorjs-codeFlask_LangDisplay {
padding: 2px 8px;
background-color: #409eff;
color: white;
border-radius: 3px;
font-size: 12px;
font-weight: 500;
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
}
/* 内容容器 - 禁止纵向滚动 */
.editorjs-codeFlask_ContentContainer {
position: relative;
min-height: 100px;
overflow-x: hidden; /* 禁止横向滚动 */
overflow-y: hidden;
transition: height 0.3s ease;
}
/* 编辑器容器 - 禁止纵向滚动 */
.editorjs-codeFlask_Editor {
position: relative;
min-height: 100px;
overflow-x: hidden; /* 禁止横向滚动 */
overflow-y: hidden;
transition: height 0.3s ease;
}
/* 底部按钮容器 - 优化为更简洁的样式 */
.editorjs-codeFlask_BottomButtonContainer {
display: flex;
justify-content: center;
align-items: center;
padding: 4px;
background-color: #f8f9fa;
border-top: 1px solid #e9ecef;
position: relative;
z-index: 0;
}
/* 底部横向折叠/展开按钮 - 优化样式,使其更融入设计 */
.editorjs-codeFlask_BottomToggle {
width: 100%;
background-color: transparent;
color: #606266;
border: none;
border-radius: 4px;
padding: 6px 12px;
font-size: 12px;
font-weight: 400;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
text-align: center;
position: relative;
}
.editorjs-codeFlask_BottomToggle:hover {
background-color: #e9ecef;
color: #409eff;
}
.editorjs-codeFlask_BottomToggle:active {
background-color: #dee2e6;
}
.editorjs-codeFlask_BottomToggle .toggle-icon {
font-size: 11px;
transition: transform 0.3s ease;
}
/* 展开按钮(显示"展开"文本)上边缘添加渐变虚化效果 */
.editorjs-codeFlask_BottomToggle:has(span.toggle-icon:contains("▲"))::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 6px;
background: linear-gradient(to bottom, rgba(248, 249, 250, 0) 0%, rgba(248, 249, 250, 1) 100%);
pointer-events: none;
}
/* 展开按钮(显示"展开"文本)上边缘添加渐变虚化效果 */
/* 删除不被广泛支持的:contains()选择器 */
.editorjs-codeFlask_BottomToggle.expand-mode::before {
content: '';
position: absolute;
top: -60px;
left: 0;
right: 0;
height: 60px;
background: linear-gradient(to bottom, rgb(255 255 255 / 0%) 0%, rgba(248, 249, 250, 1) 100%);
pointer-events: none;
}
/* CodeFlask 主容器样式 */
.editorjs-codeFlask_Editor .codeflask {
position: relative;
background: #fafafa;
border-radius: 0 0 4px 4px;
min-height: 100px;
overflow-x: hidden; /* 禁止横向滚动 */
overflow-y: hidden;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
}
/* 行号容器 */
.editorjs-codeFlask_Editor .codeflask.codeflask--has-line-numbers:before {
content: '';
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 40px;
background-color: #f5f5f5;
border-right: 1px solid #e0e0e0;
z-index: 0;
}
/* 行号 */
.editorjs-codeFlask_Editor .codeflask__lines {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 40px;
padding: 10px 0;
background-color: #f5f5f5;
border-right: 1px solid #e0e0e0;
z-index: 0;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 14px;
line-height: 21px;
color: #666;
text-align: right;
user-select: none;
overflow: hidden;
}
.editorjs-codeFlask_Editor .codeflask__lines__line {
padding-right: 8px;
}
/* 文本区域 - 输入框 */
.editorjs-codeFlask_Editor .codeflask__textarea {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 10px;
border: none;
background: transparent;
color: transparent;
caret-color: #333;
resize: none;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 14px;
line-height: 21px;
z-index: 1;
overflow-x: hidden; /* 禁止横向滚动 */
overflow-y: hidden;
white-space: pre-wrap; /* 自动换行 */
tab-size: 4;
outline: none;
}
/* 添加选中文本样式 */
.editorjs-codeFlask_Editor .codeflask__textarea::selection {
background-color: #b3d4fc;
color: #333;
}
.editorjs-codeFlask_Editor .codeflask__textarea::-moz-selection {
background-color: #b3d4fc;
color: #333;
}
/* 代码预览区域 */
.editorjs-codeFlask_Editor .codeflask__pre {
position: absolute;
top: 0;
left: 0;
width: 100%; /* 确保宽度不超出容器 */
height: 100%;
padding: 10px;
margin: 0;
border: none;
background: transparent;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 14px;
line-height: 21px;
z-index: 0;
overflow-x: hidden; /* 禁止横向滚动 */
overflow-y: hidden;
white-space: pre-wrap; /* 自动换行 */
pointer-events: none;
}
/* 代码高亮区域 */
.editorjs-codeFlask_Editor .codeflask__code {
display: block;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
font-size: 14px;
line-height: 21px;
color: #333;
white-space: pre-wrap; /* 自动换行 */
tab-size: 4;
overflow: visible;
}
/* 语法高亮样式 - 确保Prism.js样式正确应用 */
.editorjs-codeFlask_Editor .codeflask__code {
background: transparent !important;
}
/* 通用语法高亮token样式 */
.editorjs-codeFlask_Editor .token.comment,
.editorjs-codeFlask_Editor .token.prolog,
.editorjs-codeFlask_Editor .token.doctype,
.editorjs-codeFlask_Editor .token.cdata {
color: #708090;
}
.editorjs-codeFlask_Editor .token.punctuation {
color: #999;
}
.editorjs-codeFlask_Editor .token.namespace {
opacity: 0.7;
}
.editorjs-codeFlask_Editor .token.property,
.editorjs-codeFlask_Editor .token.tag,
.editorjs-codeFlask_Editor .token.boolean,
.editorjs-codeFlask_Editor .token.number,
.editorjs-codeFlask_Editor .token.constant,
.editorjs-codeFlask_Editor .token.symbol,
.editorjs-codeFlask_Editor .token.deleted {
color: #905;
}
.editorjs-codeFlask_Editor .token.selector,
.editorjs-codeFlask_Editor .token.attr-name,
.editorjs-codeFlask_Editor .token.string,
.editorjs-codeFlask_Editor .token.char,
.editorjs-codeFlask_Editor .token.builtin,
.editorjs-codeFlask_Editor .token.inserted {
color: #690;
}
.editorjs-codeFlask_Editor .token.operator,
.editorjs-codeFlask_Editor .token.entity,
.editorjs-codeFlask_Editor .token.url,
.editorjs-codeFlask_Editor .language-css .token.string,
.editorjs-codeFlask_Editor .style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, 0.5);
}
.editorjs-codeFlask_Editor .token.atrule,
.editorjs-codeFlask_Editor .token.attr-value,
.editorjs-codeFlask_Editor .token.keyword {
color: #07a;
}
.editorjs-codeFlask_Editor .token.function,
.editorjs-codeFlask_Editor .token.class-name {
color: #dd4a68;
}
.editorjs-codeFlask_Editor .token.regex,
.editorjs-codeFlask_Editor .token.important,
.editorjs-codeFlask_Editor .token.variable {
color: #e90;
}
/* 复制按钮样式 */
.editorjs-codeFlask_CopyButton {
background-color: #409eff;
color: white;
border: none;
border-radius: 3px;
padding: 6px 12px;
margin-right: 8px;
font-size: 12px;
cursor: pointer;
transition: background-color 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
min-width: 28px;
height: 28px;
}
.editorjs-codeFlask_CopyButton:hover {
background-color: #66b1ff;
}
.editorjs-codeFlask_CopyButton.copied {
background-color: #67c23a;
}
/* 折叠/展开按钮样式 */
.editorjs-codeFlask_Toggle {
background-color: #909399;
color: white;
border: none;
border-radius: 3px;
padding: 0 8px;
font-size: 12px;
cursor: pointer;
transition: background-color 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
min-width: 28px;
height: 28px;
font-weight: bold;
}
.editorjs-codeFlask_Toggle:hover {
background-color: #a6a9ad;
}
/* 响应式调整 */
@media (max-width: 768px) {
.editorjs-codeFlask_Header {
padding: 6px 8px;
}
.editorjs-codeFlask_Editor .codeflask__textarea,
.editorjs-codeFlask_Editor .codeflask__pre,
.editorjs-codeFlask_Editor .codeflask__code {
font-size: 13px;
line-height: 19px;
padding: 8px;
}
.editorjs-codeFlask_Editor .codeflask.codeflask--has-line-numbers:before {
width: 35px;
}
.editorjs-codeFlask_Editor .codeflask__lines {
width: 35px;
font-size: 12px;
}
}
/* 滚动条样式 - 完全隐藏纵向滚动条 */
.editorjs-codeFlask_Wrapper ::-webkit-scrollbar {
width: 0;/* 纵向滚动条宽度为0 */
height: 6px;/* 横向滚动条保持6px宽度 */
}
.editorjs-codeFlask_Wrapper ::-webkit-scrollbar-track {
background: transparent;
border-radius: 0;
}
.editorjs-codeFlask_Wrapper ::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 0;
}
/* Firefox 滚动条隐藏 */
.editorjs-codeFlask_Wrapper {
scrollbar-width: none;/* Firefox 隐藏纵向滚动条 */
}
.editorjs-codeFlask_Wrapper ::-moz-scrollbar {
width: 0;
height: 6px;
}
/* 焦点状态 */
.editorjs-codeFlask_Wrapper:focus-within {
border-color: #409eff;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
/* 只读模式样式 */
.editorjs-codeFlask_Wrapper.readonly .editorjs-codeFlask_Header {
background-color: #f5f7fa;
}
.editorjs-codeFlask_Wrapper.readonly .editorjs-codeFlask_Editor .codeflask__textarea {
cursor: default;
}
/* 确保所有元素正确显示 */
.editorjs-codeFlask_Wrapper * {
box-sizing: border-box;
}
/* 修复行号对齐 */
.editorjs-codeFlask_Editor .codeflask--has-line-numbers .codeflask__textarea,
.editorjs-codeFlask_Editor .codeflask--has-line-numbers .codeflask__pre {
padding-left: 50px;
}
.editorjs-codeFlask_Editor .codeflask--has-line-numbers .codeflask__lines {
padding-top: 10px;
}
/* 语言显示元素 - 添加点击样式 */
.editorjs-codeFlask_LangDisplay {
padding: 2px 8px;
background-color: #409eff;
color: white;
border-radius: 3px;
font-size: 12px;
font-weight: 500;
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
transition: all 0.2s ease;
}
.editorjs-codeFlask_LangDisplay:hover {
background-color: #66b1ff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* 语言选择弹窗 */
.editorjs-codeFlask_LanguagePopup {
background-color: white;
border: 1px solid #dcdfe6;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
width: 250px;
max-height: 300px;
z-index: 1000;
overflow: hidden;
}
/* 搜索框 */
.editorjs-codeFlask_LanguageSearch {
width: 100%;
padding: 8px 12px;
border: none;
border-bottom: 1px solid #ebeef5;
font-size: 12px;
outline: none;
box-sizing: border-box;
}
/* 语言列表 */
.editorjs-codeFlask_LanguagesList {
max-height: 250px;
overflow-y: auto;
}
/* 语言选项 */
.editorjs-codeFlask_LanguageItem {
padding: 8px 12px;
font-size: 12px;
cursor: pointer;
transition: background-color 0.2s ease;
}
.editorjs-codeFlask_LanguageItem:hover {
background-color: #f5f7fa;
}
.editorjs-codeFlask_LanguageItem.selected {
background-color: #ecf5ff;
color: #409eff;
font-weight: 500;
}
/* 滚动条样式 */
.editorjs-codeFlask_LanguagesList::-webkit-scrollbar {
width: 6px;
}
.editorjs-codeFlask_LanguagesList::-webkit-scrollbar-track {
background-color: #f5f7fa;
}
.editorjs-codeFlask_LanguagesList::-webkit-scrollbar-thumb {
background-color: #c0c4cc;
border-radius: 3px;
}
.editorjs-codeFlask_LanguagesList::-webkit-scrollbar-thumb:hover {
background-color: #909399;
}
</style><style type="text/css">
.ce-block {
margin-bottom: 20px;
}
.ce-block__content,.ce-toolbar__content {
/* max-width:calc(100% - 50px) */
margin-left: auto;
margin-right: auto;
}
.ce-rawtool__textarea {
width: 100%;
min-height: 300px;
resize: vertical;
border-radius: 8px;
border: 0;
background-color: #1e2128;
font-family: Menlo, Monaco, Consolas, Courier New, monospace;
font-size: 12px;
line-height: 1.6;
letter-spacing: -0.2px;
color: #a1a7b6;
overscroll-behavior: contain;
}
</style><style type="text/css">
.inline-code {
background: rgba(250, 239, 240, 0.78);
color: #b44437;
padding: 3px 4px;
border-radius: 5px;
margin: 0 1px;
font-family: inherit;
font-size: 0.86em;
font-weight: 500;
letter-spacing: 0.3px;
}
</style>
页:
[1]