使用腾讯云EdgeOne +STUN来实现完美的家庭网络CDN回源访问

平替方案:

之前发过一篇使用CDN来实现最快国内最快重定向的文章,这里使用又拍云的边缘函数功能,来代替cf的workers重定向功能。现在腾讯云新出了个EdgeOne CDN,支持重定向和边缘函数,最重要的是免费使用,不限流量,这就很有搞头了

一、前提准备

  • 一个域名(强烈建议为备案域名)
  • 会使用lucky的stun功能并已经会实现重定向访问

为什么强烈建议使用备案域名,因为是可以使用国内的CDN节点,当然不备案也是可以的, 但是只能使用海外节点,速度的话肯定是没有国内的好的

二、注册EdgeOne

Edge one免费版是需要兑换码的,你可以选择自己制作任务获取兑换码,或者也可以想博主一样,直接去闲鱼花一块钱买一个兑换码

具体流程这里就不多展示可以,可以去网上找教程如何激活

三、配置EdgeOne

注册好账号后,就可以添加我们的域名了。

EdgeOne免费版只支持添加一个域名,但是对于我们自己使用的话是没什么问题的。

点击域名管理来新增一个域名,选择免费版套餐即可成功添加域名

此时还需要添加CNAME接入,但是由于博主这边已经绑定了新的域名,因此没办法继续演示了。这里就简单说说:添加CNAME到你的域名解析站点,我这里是将*.a.com添加进去,即全部站点。添加CNAME后等待几分钟就可以看到域名可以正常使用了

默认是有一个全局站点规则的,但是其并不能非常兼容我们的Web站点。例如缓存了一些动态页面的内容,导致没办法进行实时数据同步显示等

在站点加速可以直接看到全局配置的,下面说一下我的配置

  • 开启强制 HTTPS
  • 开启HTTP/2 回源
  • 开启OCSP 装订
  • 开启IPv6 访问
  • 开启WebSocket
  • 开启客户端 IP 头部设置并为EO-Client-IP
  • 开启gRPC

这些没什么好说的,自己看这些功能对应的描述即可

配置规则的内容就比较多了,可以在原来wordpress的模板进行添加

主要是添加了一个浏览器缓存一个小时:gif、png、bmp、jpeg、css、js、svg、webp、avif

TLS证书的话可以直接在腾讯云的的SSL证书页面手动上传一个泛域名证书就可以了,腾讯云是没办法申请泛域名证书的,因此只能我们自己手动上传泛域名证书

这个回源站点的话就填写自己的stun公网ip+端口号,下面我会说明如何使用API实现自动同步回源端口

四、API Explorer调试

得益于腾讯云具备完善的API调用体系,因此我们可以直接实现腾讯云在线的API接口帮我们编写好API脚本,测试通过后再部署到我们的设备上

打开腾讯云的API Explorer,点我直达

这里直接修改对应的表单数据就可以了

站点ID可以在Edgeone管理页面找到,

域名就填写你的站点域名因为之前添加的解析域名为*.a.com,因此这里也填写*.a.com

OriginType填IP_DOMAIN,意味使用IP/域名进行回源,并且在Origin填入你的公网IP地址,最后在底部的HttpsOriginPort填上你的STUN穿透端口就可以完成

此时可以点击在线调试来测试填写是信息是否生效。如果没有返回任何报错信息,就说明我们的API调用是生效的

点击签名示例打开API创建页面,也可以点我打开

创建好密钥后保存好secret_id和secret_key

在代码示例->HTTP Request处保存Shell工程到本地进行测试

修改内部的secret_id和secret_key你的secret_id和secret_key,保存后尝试运行,看看是否可以正常使用。这里建议直接在lucky内的计划任务内运行,以免不同环境对json数据的解析效果不一致

这里粘贴一下我使用的脚本,注意{STUN_EO-CDN_IP}{STUN_EO-CDN_PORT}是lucky的全局变量,请自行替换成自己的STUN穿透名称

#!/bin/bash
secret_id="你的secret_id"
secret_key="你的secret_key"
Zone_id="你的zone_id"
DomainName="你的站点域名"
IP="{STUN_EO-CDN_IP}"
PORT="{STUN_EO-CDN_PORT}"
token=""

service="teo"
host="teo.ap-guangzhou.tencentcloudapi.com"
region="ap-guangzhou"
action="ModifyAccelerationDomain"
version="2022-09-01"
algorithm="TC3-HMAC-SHA256"
timestamp=$(date +%s)
date=$(date -u -d @$timestamp +"%Y-%m-%d")
payload="{\"ZoneId\":\"$Zone_id\",\"DomainName\":\"$DomainName\",\"OriginInfo\":{\"OriginType\":\"IP_DOMAIN\",\"Origin\":\"$IP\"},\"HttpsOriginPort\":$PORT}"

# ************* 步骤 1:拼接规范请求串 *************
http_request_method="POST"
canonical_uri="/"
canonical_querystring=""
canonical_headers="content-type:application/json; charset=utf-8\nhost:$host\nx-tc-action:$(echo $action | awk '{print tolower($0)}')\n"
signed_headers="content-type;host;x-tc-action"
hashed_request_payload=$(echo -n "$payload" | openssl sha256 -hex | awk '{print $2}')
canonical_request="$http_request_method\n$canonical_uri\n$canonical_querystring\n$canonical_headers\n$signed_headers\n$hashed_request_payload"

# ************* 步骤 2:拼接待签名字符串 *************
credential_scope="$date/$service/tc3_request"
hashed_canonical_request=$(printf "$canonical_request" | openssl sha256 -hex | awk '{print $2}')
string_to_sign="$algorithm\n$timestamp\n$credential_scope\n$hashed_canonical_request"

# ************* 步骤 3:计算签名 *************
secret_date=$(printf "$date" | openssl sha256 -hmac "TC3$secret_key" | awk '{print $2}')
secret_service=$(printf $service | openssl dgst -sha256 -mac hmac -macopt hexkey:"$secret_date" | awk '{print $2}')
secret_signing=$(printf "tc3_request" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$secret_service" | awk '{print $2}')
signature=$(printf "$string_to_sign" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$secret_signing" | awk '{print $2}')

# ************* 步骤 4:拼接 Authorization *************
authorization="$algorithm Credential=$secret_id/$credential_scope, SignedHeaders=$signed_headers, Signature=$signature"

# ************* 步骤 5:构造并发起请求 *************
curl -XPOST "https://$host" -d "$payload" -H "Authorization: $authorization" -H "Content-Type: application/json; charset=utf-8" -H "Host: $host" -H "X-TC-Action: $action" -H "X-TC-Timestamp: $timestamp" -H "X-TC-Version: $version" -H "X-TC-Region: $region" -H "X-TC-Token: $token"
ShellScript

点击手动触发看看是否可以正常解析,查看日志如果没有问题的话接下来就是实现STUN自动同步更新

在你的STUN穿透规则内粘贴上自定义和脚本触发代码即可完成自动更新

五、特定url重定向下载

虽然EdgeOne支持不限量流量,但是大文件下载的话还是会限速的。但是我们可以利用边缘函数功能来实现特定URL前缀进行重定向下载,其他页面则正常使用CDN回源。

在EdgeOne->边缘函数->函数管理来添加一个边缘函数,模板选择Hello World

函数名称为redirect,粘贴下列代码:

// 配置参数
const CONFIG = {
    // 需要重定向的域名
    sourceDomain: 'a.com',
    // 重定向后的域名
    targetDomain: 's.a.com',
    // 目标端口号
    targetPort: '3587'
  };
  
  addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request));
  });
  
  async function handleRequest(request) {
    const url = new URL(request.url);
    const hostname = url.hostname;
  
    // 只要 hostname 中包含 sourceDomain,就将 sourceDomain 替换为 targetDomain,并指定 port
    if (hostname.includes(CONFIG.sourceDomain)) {
      const newHost = hostname.replace(CONFIG.sourceDomain, CONFIG.targetDomain);
      const targetUrl = `https://${newHost}:${CONFIG.targetPort}${url.pathname}${url.search}`;
  
      // 返回 302 临时重定向,如果有需要,可以改成 307 重定向
      return Response.redirect(targetUrl, 302);
    }
    // 如果不是目标域名,则返回 404
    return new Response('Not Found', { status: 404 });
  }
JavaScript

这个代码是不是很熟悉?其实这个就是之前文章中用来重定向所使用的代码,注意将配置参数修改成你自己的域名和端口号

修改完成后点击创建并部署

如果你是第一次部署的话可以直接点击新增触发规则来添加,也可以在函数管理页面进行添加

这里关于规则的添加需要自己分析最后实际下载的url地址的格式,我这里列出几个我在用的重定向站点规则

  • 主机名——等于——*.a.com
  • HTTP请求头——自定义——Host——等于——cloudreve.a.com
  • 查询字符串——sign——存在
  • URL Path——正则匹配——/api/v4/file/content/*
  • 主机名——等于——*.a.com
  • HTTP请求头——自定义——Host——等于——openlist.a.com
  • 查询字符串——sign——存在
  • URL Path——等于——/d/*和/p/*

这样就可以实现正常访问是没有端口号的,下载的时候是重定向直连下载,达到最大下载速度

但是这里有一个需要注意的,因为重定向会导致请求的header丢失,故无法用于在header存在Cookie或鉴权字段的重定向请求。即重定向下载仅仅适用于可以直接使用curl https://xxx.a.com/dowload?sign=xxxx&token=xxxx类似的请求下载文件才可以使用重定向

添加完成后记得等3~5分钟,直到域名状态处于“已生效”才可以使用,否则是不会生效的

在STUN同步脚本的后面再附加上这脚本即可,主要修改成你的API Token和密钥

#!/bin/ash

# ===== payload 相关必要参数 =====
ZONE_ID="你的地区ID"
FUNCTION_ID="你的边缘函数ID"
SOURCE_DOMAIN="原域名"
TARGET_DOMAIN="重定向后域名"
TARGET_PORT="{STUN_HTTP2_PORT}"
secret_id="你的API Token"
secret_key="你的API密钥"
token=""

# 构造Json
FUNCTION_CONTENT=$(cat <<EOF
const CONFIG={
  sourceDomain:'$SOURCE_DOMAIN',
  targetDomain:'$TARGET_DOMAIN',
  targetPort:'$TARGET_PORT'
};
addEventListener('fetch',event=>{
  event.respondWith(handleRequest(event.request));
});
async function handleRequest(request){
  const url=new URL(request.url);
  const hostname=url.hostname;
  if(hostname.includes(CONFIG.sourceDomain)){
    const newHost=hostname.replace(CONFIG.sourceDomain,CONFIG.targetDomain);
    const targetUrl=\`https://\${newHost}:\${CONFIG.targetPort}\${url.pathname}\${url.search}\`;
    return Response.redirect(targetUrl,302);
  }
  return new Response('Not Found',{status:404});
}
EOF
)

service="teo"
host="teo.tencentcloudapi.com"
region=""
action="ModifyFunction"
version="2022-09-01"
algorithm="TC3-HMAC-SHA256"
timestamp=$(date +%s)
date=$(date -u -d @$timestamp +"%Y-%m-%d")
payload=$(printf '{"ZoneId":"%s","FunctionId":"%s","Content":"%s"}' \
  "$ZONE_ID" \
  "$FUNCTION_ID" \
  "$(printf '%s' "$FUNCTION_CONTENT" \
      | sed 's/\\/\\\\/g; s/"/\\"/g; s/$/\\n/' \
      | tr -d '\n')"
)

# ************* 步骤 1:拼接规范请求串 *************
http_request_method="POST"
canonical_uri="/"
canonical_querystring=""
canonical_headers="content-type:application/json; charset=utf-8\nhost:$host\nx-tc-action:$(echo $action | awk '{print tolower($0)}')\n"
signed_headers="content-type;host;x-tc-action"
hashed_request_payload=$(echo -n "$payload" | openssl sha256 -hex | awk '{print $2}')
canonical_request="$http_request_method\n$canonical_uri\n$canonical_querystring\n$canonical_headers\n$signed_headers\n$hashed_request_payload"

# ************* 步骤 2:拼接待签名字符串 *************
credential_scope="$date/$service/tc3_request"
hashed_canonical_request=$(printf "$canonical_request" | openssl sha256 -hex | awk '{print $2}')
string_to_sign="$algorithm\n$timestamp\n$credential_scope\n$hashed_canonical_request"

# ************* 步骤 3:计算签名 *************
secret_date=$(printf "$date" | openssl sha256 -hmac "TC3$secret_key" | awk '{print $2}')
secret_service=$(printf $service | openssl dgst -sha256 -mac hmac -macopt hexkey:"$secret_date" | awk '{print $2}')
secret_signing=$(printf "tc3_request" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$secret_service" | awk '{print $2}')
signature=$(printf "$string_to_sign" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$secret_signing" | awk '{print $2}')

# ************* 步骤 4:拼接 Authorization *************
authorization="$algorithm Credential=$secret_id/$credential_scope, SignedHeaders=$signed_headers, Signature=$signature"

# ************* 步骤 5:构造并发起请求 *************
curl -XPOST "https://$host" -d "$payload" -H "Authorization: $authorization" -H "Content-Type: application/json; charset=utf-8" -H "Host: $host" -H "X-TC-Action: $action" -H "X-TC-Timestamp: $timestamp" -H "X-TC-Version: $version" -H "X-TC-Region: $region" -H "X-TC-Token: $token"
echo "————重定向同步结束————"
ShellScript

六、自动更新SSL证书

腾讯云的免费证书是不支持泛域名解析的,但是可以支持用户上传的泛域名证书,因此我们可以在本地使用lucky生成后的证书通过API来上传证书,实现到期自动同步并替换证书

这里的脚本需要注意的是:域名和证书域名要一致,否则会导致一直上传新证书

例如你上传的是*.a.com的证书,那你的域名就填写*.a.com

在lucky的计划任务里面添加一个任务就可以了,可以设置为一周执行2次,刚好可以覆盖证书小于七天就替换的条件

另外也可以在SSL证书申请里面的证书映射内执行脚本

#!/usr/bin/python3
import os, time, json, requests, hashlib, hmac,sys
from datetime import datetime, timezone

# ================== 基本配置 ==================
DOMAIN = "你的域名"
CRT_FILE = "你的证书路径"
KEY_FILE = "你的密钥路径"
SECRET_ID = "EO的API ID"
SECRET_KEY = "EO的API密钥"

TOKEN = ""
SERVICE = "ssl"
HOST = "ssl.tencentcloudapi.com"
VERSION = "2019-12-05"
ALGO = "TC3-HMAC-SHA256"

API = {
    "ssl": ("ssl.tencentcloudapi.com", "2019-12-05"),
    "teo": ("teo.tencentcloudapi.com", "2022-09-01")
}

# ================== TC3 请求 ==================
def tc3(service, action, payload):
    host, version = API[service]
    ts = int(time.time())
    date = time.strftime("%Y-%m-%d", time.gmtime(ts))

    hashed = hashlib.sha256(payload.encode()).hexdigest()
    canonical = (
        "POST\n/\n\n"
        "content-type:application/json; charset=utf-8\n"
        f"host:{host}\n"
        f"x-tc-action:{action.lower()}\n\n"
        "content-type;host;x-tc-action\n"
        f"{hashed}"
    )

    scope = f"{date}/{service}/tc3_request"
    sign_str = f"{ALGO}\n{ts}\n{scope}\n{hashlib.sha256(canonical.encode()).hexdigest()}"

    k = hmac.new(f"TC3{SECRET_KEY}".encode(), date.encode(), hashlib.sha256).digest()
    for s in (service.encode(), b"tc3_request"):
        k = hmac.new(k, s, hashlib.sha256).digest()

    sig = hmac.new(k, sign_str.encode(), hashlib.sha256).hexdigest()

    headers = {
        "Authorization": f"{ALGO} Credential={SECRET_ID}/{scope}, SignedHeaders=content-type;host;x-tc-action, Signature={sig}",
        "Content-Type": "application/json; charset=utf-8",
        "Host": host,
        "X-TC-Action": action,
        "X-TC-Timestamp": str(ts),
        "X-TC-Version": version,
        "X-TC-Token": TOKEN
    }

    return requests.post(f"https://{host}", headers=headers, data=payload).json()

def die_if_error(resp, tag):
    err = resp.get("Response", {}).get("Error")
    if err:
        print(f"[ERROR] {tag} 失败")
        print(f"  Code   : {err.get('Code')}")
        print(f"  Message: {err.get('Message')}")
        sys.exit(2)

def load_cert():
    with open(CRT_FILE) as c, open(KEY_FILE) as k:
        return c.read(), k.read()

# ================== 查询证书 ==================
resp = tc3("ssl", "DescribeCertificates", "{}")
cert = next((c for c in resp.get("Response", {}).get("Certificates", [])
             if c.get("Domain") == DOMAIN), None)

# ================== 新增证书 ==================
if not cert:
    print("未找到证书,执行新增")

    crt, key = load_cert()
    resp = tc3("ssl", "UploadCertificate", json.dumps({
        "CertificatePublicKey": crt,
        "CertificatePrivateKey": key,
        "Repeatable": True
    }))

    cid = resp.get("Response", {}).get("CertificateId")
    if not cid:
        raise RuntimeError(f"新增证书失败: {resp}")

    print("新增证书成功:", cid)

    resp = tc3("teo", "ModifyHostsCertificate", json.dumps({
        "ZoneId": ZONE_ID,
        "Hosts": [DOMAIN],
        "Mode": "sslcert",
        "ServerCertInfo": [{"CertId": cid}]
    }))
    die_if_error(resp, "TEO 绑定")
    print("TEO 绑定成功")
    exit(0)

# ================== 到期判断 ==================
cid = cert["CertificateId"]
end = datetime.strptime(cert["CertEndTime"], "%Y-%m-%d %H:%M:%S").replace(tzinfo=timezone.utc)
days = int((end - datetime.now(timezone.utc)).total_seconds() // 86400)

print("证书ID:", cid)
print("剩余天数:", days)

if days > 7:
    print("有效期充足,退出")
    exit(0)

# ================== 更新证书 ==================
print("证书即将过期,开始更新")

crt, key = load_cert()
resp = tc3("ssl", "UpdateCertificateInstance", json.dumps({
    "OldCertificateId": cid,
    "CertificatePublicKey": crt,
    "CertificatePrivateKey": key,
    "Repeatable": True,
    "ResourceTypes": ["teo"]
}))

if resp.get("Response", {}).get("DeployStatus") != 0:
    raise RuntimeError(f"证书更新失败: {resp}")

time.sleep(10)
tc3("ssl", "DeleteCertificate", json.dumps({"CertificateId": cid}))
print("证书更新完成")
Python
#!/bin/bash
# 腾讯云 SSL 证书更新脚本
set -euo pipefail
# 基本信息
DOMAIN = "你的域名"
CRT_FILE = "你的证书路径"
KEY_FILE = "你的密钥路径"
SECRET_ID = "EO的API ID"
SECRET_KEY = "EO的API密钥"
SERVICE="ssl"
HOST="ssl.tencentcloudapi.com"
VERSION="2019-12-05"
ALGO="TC3-HMAC-SHA256"
TOKEN=""

timestamp=$(date +%s)
date=$(date -u -d @$timestamp +"%Y-%m-%d")

# ================== 通用 API 调用 ==================
api_call() {
    local service="$1"
    local host="$2"
    local version="$3"
    local action="$4"
    local payload="$5"

    local canonical_headers="content-type:application/json; charset=utf-8\nhost:$host\nx-tc-action:${action,,}\n"
    local signed_headers="content-type;host;x-tc-action"

    local hashed_payload
    hashed_payload=$(echo -n "$payload" | openssl sha256 -hex | awk '{print $2}')

    local canonical_request="POST\n/\n\n$canonical_headers\n$signed_headers\n$hashed_payload"
    local scope="$date/$service/tc3_request"
    local string_to_sign="$ALGO\n$timestamp\n$scope\n$(printf "$canonical_request" | openssl sha256 -hex | awk '{print $2}')"

    local k_date
    k_date=$(printf "$date" | openssl sha256 -hmac "TC3$SECRET_KEY" | awk '{print $2}')
    local k_service
    k_service=$(printf "$service" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$k_date" | awk '{print $2}')
    local k_signing
    k_signing=$(printf "tc3_request" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$k_service" | awk '{print $2}')

    local signature
    signature=$(printf "$string_to_sign" | openssl dgst -sha256 -mac hmac -macopt hexkey:"$k_signing" | awk '{print $2}')

    local auth="$ALGO Credential=$SECRET_ID/$scope, SignedHeaders=$signed_headers, Signature=$signature"

    curl -s -XPOST "https://$host" -d "$payload" \
        -H "Authorization: $auth" \
        -H "Content-Type: application/json; charset=utf-8" \
        -H "Host: $host" \
        -H "X-TC-Action: $action" \
        -H "X-TC-Timestamp: $timestamp" \
        -H "X-TC-Version: $version" \
        -H "X-TC-Token: $TOKEN"
}

# ================== Step 1:查询证书 ==================
resp=$(api_call "ssl" "ssl.tencentcloudapi.com" "2019-12-05" "DescribeCertificates" "{}")

CERT_INFO=$(echo "$resp" | jq -r \
    ".Response.Certificates[] | select(.Domain==\"$DOMAIN\") | [.CertificateId,.CertEndTime] | @tsv" \
    | head -n1)

CERT_ID=${CERT_INFO%%$'\t'*}
CERT_END_TIME=${CERT_INFO#*$'\t'}

# ================== Step 2:没有证书 → 新增 + 绑定 ==================
if [[ -z "$CERT_ID" ]]; then
    echo "未找到证书,执行新增"

    payload=$(jq -n \
        --arg crt "$(cat "$CRT_FILE")" \
        --arg key "$(cat "$KEY_FILE")" \
        '{CertificatePublicKey:$crt,CertificatePrivateKey:$key,Repeatable:true}')

    resp=$(api_call "ssl" "ssl.tencentcloudapi.com" "2019-12-05" "UploadCertificate" "$payload")
    NEW_CERT_ID=$(echo "$resp" | jq -r '.Response.CertificateId')

    if [[ -z "$NEW_CERT_ID" || "$NEW_CERT_ID" == "null" ]]; then
        echo "新增证书失败:"
        echo "$resp" | jq .
        exit 1
    fi

    echo "新增证书成功,证书ID: $NEW_CERT_ID"

    echo "开始绑定 TEO 资源..."
    payload=$(jq -n \
        --arg zone "$ZONE_ID" \
        --arg host "$DOMAIN" \
        --arg cert "$NEW_CERT_ID" \
        '{
            ZoneId: $zone,
            Hosts: [$host],
            Mode: "sslcert",
            ServerCertInfo: [
                { CertId: $cert }
            ]
        }')

    bind_resp=$(api_call "teo" "teo.tencentcloudapi.com" "2022-09-01" \
        "ModifyHostsCertificate" "$payload")

    ERROR_CODE=$(echo "$bind_resp" | jq -r '.Response.Error.Code // empty')
    ERROR_MSG=$(echo "$bind_resp" | jq -r '.Response.Error.Message // empty')

    if [[ -n "$ERROR_CODE" ]]; then
        echo "TEO 证书绑定失败"
        echo "错误码: $ERROR_CODE"
        echo "错误信息: $ERROR_MSG"
        exit 1
    fi

    echo "TEO 证书绑定成功"
    exit 0
fi

# ================== Step 3:已有证书 → 到期判断 ==================
echo "找到证书ID: $CERT_ID"
echo "证书到期时间: $CERT_END_TIME"

LEFT_DAYS=$(( ( $(date -d "$CERT_END_TIME" +%s) - $(date +%s) ) / 86400 ))
echo "剩余有效期: $LEFT_DAYS 天"

(( LEFT_DAYS > 7 )) && echo "有效期充足,退出" && exit 0

# ================== Step 4:更新证书 ==================
echo "证书即将过期,开始更新"

payload=$(jq -n \
    --arg id "$CERT_ID" \
    --arg crt "$(cat "$CRT_FILE")" \
    --arg key "$(cat "$KEY_FILE")" \
    '{OldCertificateId:$id,CertificatePublicKey:$crt,CertificatePrivateKey:$key,Repeatable:true,ResourceTypes:["teo"]}')

resp=$(api_call "ssl" "ssl.tencentcloudapi.com" "2019-12-05" \
    "UpdateCertificateInstance" "$payload")

DEPLOY_STATUS=$(echo "$resp" | jq -r '.Response.DeployStatus')
[[ "$DEPLOY_STATUS" != "0" ]] && echo "更新失败:" && echo "$resp" | jq . && exit 1

echo "证书更新成功,等待删除旧证书"
sleep 10

api_call "ssl" "ssl.tencentcloudapi.com" "2019-12-05" \
    "DeleteCertificate" "$(jq -n --arg id "$CERT_ID" '{CertificateId:$id}')" >/dev/null

echo "旧证书删除完成"

ShellScript

两个版本都是先检查有没有指定域名的证书->没有就上传并绑定对应EO域名资源;有就检测是否到期:小于7天就执行证书替换并删除旧证书


📌 本文由 FishBoss_Tca 原创,转载请注明作者和原文链接。
原文链接:https://www.ytca.top/stun/2547/

评论

  1. dh
    3 月前
    2025-9-22 21:40:05

    大佬 求完善教程

    • 博主
      dh
      3 月前
      2025-9-22 23:52:57

      我还没想法好怎么表述方便,因为调试的内容太多了,我也是一直一直调试才知道行不行,如果你有兴趣的话可以先加入qq,我可以跟您讲讲如调试
      2546046421

  2. q
    3 月前
    2025-9-26 2:53:35

    免费版不支持国内加速

    • 博主
      q
      3 月前
      2025-9-27 9:07:40

      国内加速是需要备案域名才可以

  3. dh
    3 月前
    2025-9-30 17:17:36

    开了openclash后stun就会穿透不成功

    • 博主
      dh
      2 月前
      2025-10-07 10:36:07

      stun不可以和代理软件一块使用

  4. 爱你哟
    2 月前
    2025-10-15 19:25:23

    搞了哈,没有搞明白,还是等大佬完善教程🍤

    • 博主
      爱你哟
      已编辑
      2 月前
      2025-10-15 22:07:33

      基本回源是写完的了,那个重定向的只是边缘计算使用的

  5. wingvc
    4 天前
    2025-12-13 7:00:52

    国内阿里云白嫖ESA到2050年了博主研究下?

    • 博主
      wingvc
      3 天前
      2025-12-14 15:41:15

      ESA不如EO,他们在国内版本的话都需要备案,并且并没有比EO有某方面的优势。更多的,EO的功能和所支持的特性还比ESA多

  6. archer
    已编辑
    17 小时前
    2025-12-16 11:38:14

    大佬我是业余菜鸟,有些疑惑请教一下:
    1.教程中stun规则我看图片显示的是开启了“不使用lucky内置端口转发”,我是先看了大佬的其他教程,之前设了转发到127.0.0.1:16666,要不要继续这样设置?
    2.我想实现在外网通过不同二级域名连上不同设备,比如nas.a.com连到nas、openwrt.a.com连到软路由,是不是还要用lucky设置反代理?监听端口还是上述设置的16666?
    3.是不是不用设置ddns了?我看lucky的ddns设置里也有edgeone,不用ddns有什么提升?
    4.教程中第五部分的第3项是不是应对IP发生变化后同步给edgeone的作用?其他的重定向是不是不是必需的步骤?
    5.如果上述理解未错误的话,我做完后未感受到速度有提升,比我之前用cf解析+大佬提供的优选cdn要慢得多,是因为我的域名未备案的原因吗?
    以上,望大佬不吝赐教,感谢!

    • 博主
      archer
      已编辑
      15 小时前
      2025-12-16 13:17:52

      1、是否设置“不使用lucky内置端口转发”取决与你的设备是否支持手动设置端口转发。
      因为STUN会占用一个端口,而这个端口是给外部连接使用的,但是这个STUN端口并不知道传入来的数据应该发往哪里,所以需要使用端口转发来将传入的数据发给需要服务的端口(例如反向代理、SSH)
      通常来说,如果你的lucky是在Openwrt上使用,我建议“不使用lucky内置端口转发”,这样做的话我们需要手动开启防火墙和对应的端口转发,而系统自带的端口转发是内核转发,效率高,并且占用的性能少;如果你是在飞牛OS上安装的Lucky,我建议使用Lucky自带的端口转发,这样比较方便,并且通常飞牛OS的机器性能都不会差,故影响的也不大
      2、反向代理的其中一个作用就是:一个端口号,服务多个域名,通过不同域名来分流不同的Web站点。我们默认将反向代理端口号开设在16666,这样对应的是STUN穿透后转发到的端口号也是16666,是与之对应的
      3、如果你只用EdgeOne的话理论来说确实不需要DDNS了,因为我们回源设置是直接填写IPV4地址的,但是我建议提还是保留IPv6的DDNS解析,以便EdgeOne回源失败后还可以通过IPV6进行远程访问查找问题
      4、第五章的特定url重定向是对有大文件下载/浏览需求而准备的,是可选的,如果你没有什么大文件下载的需求或者可以接受EdgeOne大文件下载限速的情况也可以直接跳过第五章。而第3点自动同步更新原理和之前的重定向访问思路是一致,都是为了同步变化后的端口
      5、至于使用了EdgeOne反而变慢的问题,从理论上来说确实会变慢,因为他们所使用的原理不一样
      EdgeOne是使用CDN中转,重定向是直接访问源站点。如果你要做对比的话应该拿CF开启小黄云和EO做对比
      另外,理论来说EdgeOne应该会比cf重定向要快,尤其是经常访问的站点。CDN会将数据缓存到与你最近的节点,提高一下次加载的速度。特别的,考虑到现今QoS非常严重的网络,有时候因为线路问题,跨运营商和跨省访问可能EdgeOne会更快,因为CDN用的是三网优化的网络,而重定向直连的话值对本地运营商网络做优化。
      至于你提到没有使用备案域名,使用的是国外的CDN节点,也是会拖慢访问速度的,如果你对网速比较敏,并且可以接受最终访问地址带端口号的话重定向访问也不是一个差的选择。这样的话你可以只考虑使用EdgeOne的边缘函数功能实现和之前教程原理一样的重定向访问,而不是回源代理请求全部流量,这样做确实会比cf的重定向会快一点

      如果你只是自己使用的话也可以考虑下面的方案,除了只能自用之外,几乎是完美的访问了。
      使用SVCB/HTTPS解析和HTTP3搭配Lucky的STUN穿透实现无端口号自用完美访问Web服务
      目前的话我是多种访问方式并存的形式,避免了一种访问方式失效后无法远程救急维护

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇