不二云端 - 运维经验 2025-08-10T12:11:04+08:00 Typecho https://2sv.cn/feed/atom/category/%E8%BF%90%E7%BB%B4%E7%BB%8F%E9%AA%8C/ <![CDATA[导入任何Linux系统容器镜像到wsl]]> https://2sv.cn/archives/279/ 2025-08-10T12:11:04+08:00 2025-08-10T12:11:04+08:00 Eleven http://www.buer.cc AI摘要:WSL支持将任何Linux容器镜像导入为子系统,适用于需要特定发行版或版本的用户。以Ubuntu 24.04为例,通过Docker拉取并导出容器镜像为tar文件,随后在Windows上使用PowerShell导入并创建新的WSL子系统。用户可以进一步设置该子系统的默认登录用户。

Powered by AISummary.

除了Microsoft Store中含有的Linux子系统镜像、Microsoft官方提供的Linux子系统镜像https://learn.microsoft.com/en-us/windows/wsl/install-manual以及他人制作的Linux子系统镜像可以创建为Wsl子系统外,WSL还支持将任意Linux容器镜像导入为Wsl子系统,这对于想要拥有某个特定发行版、特定版本的子系统的人说是一个福音。

以Ubuntu24.04为例,由于Ubuntu24.04刚发行不久,此时Microsoft官方还没有提供该发行版,但DockerHub上已经存在Ubuntu24.04的容器镜像。按照下面的步骤,可以完成Ubuntu2404子系统的创建。

前提条件:

已经拥有一个docker(或者podman)并已启动
windows上已经安装好wsl
步骤1:通过docker拉取ubuntu2404容器镜像,并将其导出为tar归档文件(ubuntu2404.tar)

sudo docker pull ubuntu:24.04
sudo docker run ubuntu:24.04
container_id=$(sudo docker container ls -a | grep -i 'ubuntu:24.04' | awk '{print $1}')
sudo docker export $container_id > ubuntu2404.tar

步骤2:将导出的ubuntu2404.tar文件复制到windows上,假设存放路径为V:\wsl\ubuntu2404.tar

步骤3:Windows上打开PowerShell,将ubuntu2404.tar文件导入到wsl

# 假设想要将导入后创建的Ubuntu2404子系统保存在目录V:\wsl\Ubuntu24-04_v1中
# 并且该子系统的名称为Ubuntu2404
wsl --import Ubuntu2404 V:\wsl\Ubuntu24-04_v1 V:\wsl\ubuntu2404.tar

现在,Ubuntu2404子系统已经创建好了(可通过wsl -l -v命令查看),已经可以进入该子系统并设置该子系统,比如设置该子系统的默认登录用户。

# 登录子系统
wsl -d Ubuntu2404
# 进入子系统后,创建新用户(用户名longshuai,uid/gid为1200)并修改密码,稍后设置为该子系统的默认登录用户
# 顺便把root用户的密码也修改
root@DESKTOP:$ useradd -u 1200 -s /bin/bash -m -d /home/longshuai longshuai
root@DESKTOP:$ passwd
root@DESKTOP:$ passwd longshuai
# 如果通过下面的方式设置默认的登录用户无效,可使用工具LxRunOffline来设置
root@DESKTOP:$ echo -e "[user]\ndefault=longshuai" >> /etc/wsl.conf
root@DESKTOP:$ exit
]]>
<![CDATA[什么是 LLMs.txt?它对SEO有用吗?WordPress 网站如何生成 LLMs.txt?]]> https://2sv.cn/archives/277/ 2025-08-05T16:27:58+08:00 2025-08-05T16:27:58+08:00 Eleven http://www.buer.cc AI摘要:LLMs.txt 是一种专为大型语言模型(LLMs)设计的网站文件,通过提供简化和结构化的内容,帮助 AI 更高效地理解和索引网站信息。虽然它对传统 SEO 无直接影响,但能提升网站在 AI 搜索中的表现,优化 AI 问答的准确性。WordPress 网站可以通过插件轻松生成 LLMs.txt 文件,以支持 AI 模型更好地解析内容。

Powered by AISummary.

大型语言模型 (LLM)越来越依赖网站信息,但面临一个关键的限制:上下文窗口太小,无法完整处理大多数网站。将包含导航、广告和 JavaScript 的复杂 HTML 页面转换为 LLM 友好的纯文本既困难又不精确。

虽然网站既服务于人类读者,也服务于大型语言模型 (LLM),但后者受益于更简洁、更专业的信息,这些信息集中在一个易于访问的单一位置。这对于开发环境等用例尤为重要,因为LLM 需要快速访问编程文档和 API。

为了解决以上问题,LLMs.txt 应运而生!

什么是 LLMs.txt?

请输入图片描述

LLMs.txt 是一种专为大型语言模型(LLMs)设计的网站标准化文件,旨在帮助 AI 更高效、准确地理解和索引网站内容。其核心特点与作用如下:

一、本质与定位
‌AI 专用索引文件‌
类似 sitemap.xml 的站点地图功能,但专注于服务 AI 模型,而非搜索引擎爬虫。它提供网站内容的精简结构化索引,通常以 Markdown 格式存储于网站根目录(如 https://example.com/llms.txt)。
‌与传统文件的区别‌
‌VS robots.txt‌:后者控制爬虫访问权限,而 LLMs.txt 提供内容导航与语义说明,不限制访问。
‌VS sitemap.xml‌:LLMs.txt 包含内容摘要、分类标签及更新状态等上下文信息,而非仅页面链接。
二、核心功能
‌提升 AI 理解效率‌
通过剥离网页中的 HTML/CSS/JavaScript 等视觉渲染元素,直接提供纯文本核心内容,减少信息噪音与 Token 消耗,加速 AI 处理响应。
‌结构化内容导航‌
为 LLM 标注关键页面属性(如用途、分类、重要度),引导模型优先抓取高价值内容(如 API 文档、最新公告)。
‌支持 Markdown 版本访问‌
网站可为每个页面提供 Markdown 版本(例如在原始 URL 后追加 .md),供 AI 直接解析纯净文本。
三、典型应用场景
‌版权与合规声明‌:部分实现方案允许声明内容使用权限,规范 AI 模型的数据抓取行为

‌AI 问答优化‌:当用户向 ChatGPT、Claude 等询问网站信息时,LLMs.txt 帮助模型快速定位准确答案,避免因网页噪音导致错误。

‌开发者文档适配‌:如 Apifox、VitePress 等技术平台通过集成 LLMs.txt,显著提升 AI 对 API 文档的解析精度。

LLMs.txt 对SEO有用吗?

LLMs.txt 对 ‌传统搜索引擎优化(SEO)没有直接影响‌,但可能通过间接方式影响网站在 AI 搜索环境中的表现,具体分析如下:

一、对传统 SEO 无直接作用

谷歌官方明确否定其 SEO 价值‌

谷歌搜索倡导者 John Mueller 将 LLMs.txt 类比为已废弃的“关键词元标签”(keywords meta tag),强调其不被搜索引擎用作排名信号,且存在滥用风险。
‌与搜索引擎爬虫无关‌
LLMs.txt 专为大型语言模型(如 ChatGPT、Gemini)设计,不控制搜索引擎爬虫的访问权限或索引行为,传统 SEO 规则(如关键词密度、反向链接)仍独立生效。

二、潜在间接影响与 AI 场景价值

‌提升 AI 搜索结果可见性‌

通过为 LLM 提供结构化内容摘要,可优化网站在 AI 问答中的引用准确性(例如 ChatGPT 回答用户问题时更易调取正确信息),间接扩大内容触达范围。

‌降低 AI 误解风险‌

剥离广告、导航等噪音的 Markdown 格式能避免 AI 因抓取冗余内容导致错误解读,尤其对技术文档(如 API 说明)、实时资讯类站点效果显著。

‌优化 AI 索引效率‌

标注页面优先级与分类标签(如 #安全 #必备),可引导 LLM 优先抓取高价值内容,突破上下文长度限制,尤其利于大型网站。

三、实操建议

‌无需替代传统 SEO 工作‌:LLMs.txt 应视为补充而非替代,需同步维护 robots.txt 和 sitemap.xml。
‌技术文档站点建议部署‌:API 服务商(如 Apifox)、开源项目(如 Vue/Vite)可通过 LLMs.txt 显著提升 AI 助手解析效率。
‌避免滥用风险‌:堆砌无关关键词或操纵 AI 行为可能降低内容可信度,需遵循简洁、真实原则。
‌总结‌:LLMs.txt 当前对 Google 等传统搜索引擎的 SEO 排名无影响,但能增强内容在 AI 生态中的可见性与准确性,是面向未来搜索场景的策略性补充。

WordPress 网站如何生成 LLMs.txt?

WordPress 网站要生成 LLMs.txt 非常简单,只需要安装相关的插件即可,比如 Website LLMs.txt 或 LLMs.txt and LLMs-Full.txt Generator 都是不错的插件,二选一安装使用即可,如果你有使用 Yoast SEO 插件,貌似它已经集成了这个功能,就不需要借助其他插件了。

]]>
<![CDATA[如何修复 WordPress 错误:Non-existent changeset UUID]]> https://2sv.cn/archives/276/ 2025-08-05T16:26:02+08:00 2025-08-05T16:26:02+08:00 Eleven http://www.buer.cc AI摘要:遇到WordPress错误“Non-existent changeset UUID”时,问题通常出在“设置 – 常规”中两个网址不一致。解决方法是将这两个网址修改为一致,即可修复该错误。

Powered by AISummary.

访问 外观 – 自定义 界面的时候,看到错误提示 Non-existent changeset UUID,如下图所示:
请输入图片描述
说真的,倡萌也是第一次看到这个错误,搜索了一下,原来问题出在 设置 – 常规 中设置的两个网址不一致导致的:
请输入图片描述
解决办法就是将这两个网址修改为一样的就好了!

]]>
<![CDATA[支持MySQL、PostgreSQL和Redis集群部署,1Panel开源面板v2.0.5版本发布]]> https://2sv.cn/archives/273/ 2025-08-01T17:26:23+08:00 2025-08-01T17:26:23+08:00 Eleven http://www.buer.cc AI摘要:1Panel v2.0.5版本发布,新增MySQL、PostgreSQL和Redis集群部署功能,支持一键部署和可视化操作,降低技术门槛。此外,增加了邮件告警功能,实现短信和邮件双通道告警,提升告警的覆盖范围。版本还支持主从节点灵活切换,确保系统高可用性和简化维护流程。

Powered by AISummary.

2025年7月24日,现代化、开源的Linux服务器运维管理面板1Panel正式发布v2.0.5版本。在这一版本中,1Panel新增数据库集群部署、邮件告警和主从节点灵活切换三项功能,聚焦为企业级运维场景提供更优使用体验。

1Panel v2.0.5版本是1Panel开源面板项目在交付企业级集群化和高可用能力方面迈出的关键一步,也是对社区用户长期支持与反馈的回应。从单机到多节点,从单实例数据库到数据库集群,从单一告警到邮件短信双通道,1Panel正在努力成为“可用、好用、值得信赖”的下一代Linux服务器运维面板。

■ 新增MySQL、PostgreSQL和Redis集群部署功能

数据库是数字化业务的核心。针对用户的集群化部署需求,1Panel v2.0.5版本在原有的数据库一键部署的基础之上,新增了MySQL、PostgreSQL和Redis的集群部署功能。

MySQL、PostgreSQL和Redis集群部署的功能优势主要体现在以下三方面:

  1. 一键部署MySQL主从集群,轻松实现读写分离;
  2. 快速搭建PostgreSQL集群,支持事务一致性;
  3. 使用Redis Cluster,满足高并发和大数据量缓存场景需要。

更加重要的是,无需借助繁琐的命令行,用户仍然可以通过可视化的“傻瓜式”操作来进行MySQL、PostgreSQL和Redis的集群安装部署,从而大幅降低搭建高可用数据库集群的技术门槛。

请输入图片描述

■ 新增邮件告警,关键事件不错过

在系统运行中,可靠的告警机制对及时发现系统风险尤为关键。1Panel v2.0.5版本在原有短信告警的基础上,新增了邮件告警功能。

现在,1Panel能够同时通过邮件和短信双通道,将告警信息第一时间推送给系统运维人员。相比单一通道,双通道告警能够覆盖更多场景,保障告警信息触达用户的即时性,为用户构建更为完善的监控闭环。
请输入图片描述

■ 支持主从节点灵活切换

在分布式和多节点管理场景下,如何在主节点发生故障时快速切换节点,保障业务的正常可用,一直是高可用系统运维的核心。本次更新后,1Panel正式支持主从节点切换模式。运维人员可以根据需要,将某个从节点升级为主节点,或将主节点降级为从节点重新加入集群。

主从节点切换为用户带来的价值包括:

  1. 紧急情况下从节点可以快速接管,保证业务持续可用;
  2. 主从节点切换操作简单快捷,有效降低系统维护成本;
  3. 角色信息清晰,管理流程更加可控。
    请输入图片描述
]]>
<![CDATA[MaxKB+MinerU:通过API实现PDF文档解析并存储至知识库]]> https://2sv.cn/archives/272/ 2025-08-01T17:22:33+08:00 2025-08-01T17:22:33+08:00 Eleven http://www.buer.cc AI摘要:MinerU v2.0是一款开源的高性能PDF文档解析工具,支持将PDF转换为Markdown和JSON格式,并提升了复杂图表的解析效果。通过与MaxKB结合,用户可以实现自动化文档解析与上传,构建高效的知识库。MinerU提供API接口,支持将PDF文档解析、下载和上传到MaxKB,增强知识库问答系统的性能。文章详细介绍了如何通过API集成MinerU与MaxKB,构建完整的解析与存储流程。

Powered by AISummary.

MinerU是一款开源的高质量数据提取工具,能够将PDF文档转换为Markdown和JSON格式。2025年6月13日,MinerU发布了v2.0版本,相较于v1.0版本实现了架构和功能的全面重构与升级。在优化代码结构和交互方式的同时,v2.0版本还集成了小参数量、高性能多模态文档解析模型,能够实现端到端的高速、高精度文档理解。实际测试表明,新版本对复杂图表的解析效果较上一版本有明显提升,目前已经能够满足90%以上的复杂文档解析需求。

值得一提的是,MinerU出色的PDF文档解析能力特别适合与MaxKB开源项目配合使用。通过"MinerU+MaxKB"的组合方案,用户不仅能够获得高质量的文档解析效果,还能显著提升知识库问答系统的性能。为方便用户集成,MinerU项目现已提供API对接服务(https://mineru.net/apiManage)。接下来,本文将详细介绍如何通过MinerU在线API实现与MaxKB的对接。

一、实现方法

当用户提供文件地址后,系统会将该地址赋值给file_url变量,并作为参数传递给MinerU文件解析服务。MinerU在完成文件解析后,会返回一个任务ID(task_id)。系统会将其传入MinerU的查询接口,当检测到任务处理完成时,自动获取结果文件的下载链接(full_url)。随后,系统执行文件下载操作,将结果文件保存到MaxKB容器的/opt/maxkb/download目录下。最后,系统会自动完成文件上传和智能分段处理,将内容存储到知识库中。
请输入图片描述

二、MaxKB函数创建

我们需要在MaxKB的函数库中创建四个核心功能函数,其用途分别为:

  1. 调用MinerU单个文件解析;
  2. 从MinerU获取任务结果;
  3. 通过URL链接下载文件至服务器;
  4. 将解析后的ZIP文件上传至知识库。

相关的代码说明如下:

■ MinerU单个文件解析函数:负责调用MinerU的单文件解析服务,通过传入PDF文档的在线地址来创建解析任务,并返回对应的task_id;

import requests


def create_task(file_url):
    url = 'https://mineru.net/api/v4/extract/task'
    token = '自己申请的 Token'


    header = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {token}'
    }


    data = {
    'url': file_url,
    'is_ocr': True,  #是否启动 ocr 功能,默认 false
    'enable_formula': True,  #是否开启公式识别,默认 true
    'enable_table': True,    #是否开启表格识别,默认 true
    'language': "ch",    #指定文档语言,默认 ch,可以设置为auto
    'model_version': "v2",  #mineru模型版本,两个选项:v1、v2,默认v1。
    }


    res = requests.post(url,headers=header,json=data,timeout=5)
    res_data = res.json()
    task_id_data = res_data["data"]["task_id"]
    return task_id_data

请输入图片描述
■ MinerU获取任务结果函数:用于查询任务状态,通过传入task_id获取解析结果,成功后将返回ZIP格式解析文件的下载地址;

import time
import requests
def querybyid(task_id,max_retries=100,retry_interval=5):
    url = f'https://mineru.net/api/v4/extract/task/{task_id}'
    token = '申请的Token'
    header = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {token}'
    }


    retries = 0
    while retries < max_retries:
        try:
            res = requests.get(url, headers=header, timeout=5)
            res.raise_for_status()  # 检查请求是否成功
            data = res.json()
            if "data" in data and "full_zip_url" in data["data"] and data["data"]["full_zip_url"]:
                return data["data"]["full_zip_url"]
            else:
                print(f"full_zip_url 为空,正在等待任务完成。已重试 {retries + 1} 次,共 {max_retries} 次。")
                time.sleep(retry_interval)
                retries += 1
        except requests.exceptions.RequestException as e:
            print(f"请求失败,错误信息:{e}。正在重试...")
            time.sleep(retry_interval)
            retries += 1
    raise Exception(f"在 {max_retries} 次重试后,仍未获取到有效的 full_zip_url。")

请输入图片描述
■ 文件下载函数:根据提供的ZIP文件下载链接,将文件保存至容器内的/opt/maxkb/download目录。需要注意的是,MaxKB默认使用sandbox用户运行,需确保该用户对/opt/maxkb/download目录有读写权限;

import os
import requests
from urllib.parse import urlparse


def download_file(download_url, save_dir='/opt/maxkb/download'):
    
    os.makedirs(save_dir, exist_ok=True)


    # 获取文件名
    parsed_url = urlparse(download_url)
    filename = os.path.basename(parsed_url.path)
    save_path = os.path.join(save_dir, filename) # 文件下载后保存的目录,需要默认用户对此目录有读写权限


    # 下载文件
    try:
        response = requests.get(download_url, stream=True)
        response.raise_for_status()  # 检查请求是否成功


        total_size = int(response.headers.get('content-length', 0))
        block_size = 1024  # 1KB
        progress = 0
        
        print(f"开始下载 {filename} 到 {save_dir}")
        with open(save_path, 'wb') as f:
            for data in response.iter_content(block_size):
                f.write(data)
                progress += len(data)
                # 打印下载进度
                print(f"下载进度: {progress / total_size * 100:.2f}%", end='\r')
        print(f"\n下载完成: {save_path}")
        return save_path
    except requests.exceptions.RequestException as e:
        print(f"下载失败: {e}")
        return None

请输入图片描述
■ ZIP文件上传至知识库:通过MaxKB API将服务器上的ZIP解析文件上传至知识库存储。

import json
import logging
import requests
# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


def initialize(file_path):
    config = {
        # MaxKB API密钥
        'authorization_apikey': 'user-ac86ec515de17969f2f8a9c8ab21e52f',    
        # 文件分段处理的API地址
        'split_url': 'http://10.1.11.58:8080/api/dataset/document/split',
        # 目标知识库的API地址
        'upload_url': 'http://10.1.11.58:8080/api/dataset/3d1d5d4e-5576-11f0-bc5c-0242ac120003/document/_bach',
        'file_path': rf'{file_path}',
        'file_name': '函数库上传文档分段'
    }
    return config


    
def upload_file(config):
    headers = {
        'accept': 'application/json',
        'AUTHORIZATION': f'{config["authorization_apikey"]}'
    }
    try:
        files = {'file': open(config["file_path"], 'rb')}
        response = requests.post(config["split_url"], headers=headers, files=files)
        response.raise_for_status()
        response_data = response.json()
        map_content = {}
        for item in response_data.get("data", []):
            for content_item in item.get("content", []):
                map_content[content_item.get("title", "")] = content_item.get("content", "")
        return map_content
    except requests.exceptions.RequestException as e:
        logging.error(f"文件分段上传失败: {e}")
        return {}
    except Exception as e:
        logging.error(f"处理文件内容时出错: {e}")
        return {}




def send_post_request(config, map_content):
    headers = {
        "Content-Type": "application/json",
        "Authorization": f'{config["authorization_apikey"]}'
    }
    paragraphs = [{"title": key, "content": value} for key, value in map_content.items()]
    document_wrapper = {
        "name": config["file_name"],
        "paragraphs": paragraphs
    }
    json_body = json.dumps([document_wrapper])
    try:
        response = requests.post(config["upload_url"], headers=headers, data=json_body)
        response.raise_for_status()
        logging.info(f"上传文件响应: {response.text}")
        return True
    except requests.exceptions.RequestException as e:
        logging.error(f"上传文件失败: {e}")
        return False




def main(file_path):
    config = initialize(file_path)
    map_content = upload_file(config)
    if not map_content:
        logging.error("文件分段上传失败或内容为空,程序终止")
        return False
    if not send_post_request(config, map_content):
        logging.error("文件上传失败,程序终止")
        return False
    
    return "文件已上传成功,并保持在知识库中"

请输入图片描述

三、在MaxKB中创建应用

在上述四个函数创建完成后,我们可以在MaxKB中尝试创建高级应用。输入或提取上传文件的链接后,按照前文顺序依次添加MinerU单个文件解析函数节点→从MinerU获取任务结果函数节点→下载文件函数节点→文件上传函数节点。
请输入图片描述
小助手提示“文件上传成功”,即可回到知识库页面,在目标知识库中看到新上传的文档。
请输入图片描述
请输入图片描述
总结来说,MinerU v2.0是一款开源、高性能的PDF文档解析工具,具备强大的多模态处理能力。通过MaxKB与MinerU的深度联动,可以基于函数调用构建清晰高效的 “文件地址→解析→下载→上传” 自动化流程,无缝衔接原始文档与结构化知识库的构建。

“MinerU+MaxKB”的组合方案,不仅可以显著提升文档解析的精度与效率,更能大幅增强知识库问答系统的能力与效果。

]]>
<![CDATA[利用 Cloudflare Worker 镜像 GitHub 站点实现在墙内访问]]> https://2sv.cn/archives/269/ 2025-07-31T17:45:28+08:00 2025-07-31T17:45:28+08:00 Eleven http://www.buer.cc AI摘要:本文介绍了如何利用 Cloudflare Worker 实现 GitHub 站点的镜像,并通过自有域名实现墙内访问。首先,创建并部署 Cloudflare Worker,使用 JavaScript 代码将 GitHub 站点内容转发到自定义域名。接着,配置访问控制和屏蔽特定地区与IP,最终通过绑定自定义域名绕过 DNS 污染,确保能够在墙内顺利访问镜像站。

Powered by AISummary.

请输入图片描述
Cloudflare Worker 是 Cloudflare 公司提供的一项服务,它允许开发者在 Cloudflare 的边缘服务器上运行自定义的 JavaScript 代码。通俗地说,它就像是一个小型的服务器,可以在互联网上的不同地点快速执行你编写的代码。

Cloudflare Worker 的主要用途包括网站加速和优化、路由请求、访问控制、CDN 功能增强、网站镜像与转发等。

本文将使用其网站镜像和访问控制的能力,实现 GitHub 站点的镜像,并通过自有域名实现在墙内的访问。

镜像 GitHub 站点

  1. 创建 Worker

首先,登录 Cloudflare,切换至 Workers & Pages 菜单,点击 创建 按钮:
请输入图片描述
等待页面刷新,再点击点击 创建 Worker按钮新建一个 Worker:
请输入图片描述
接着,设置一个三级域名 https://demo.93653142.workers.dev,点击 部署 按钮:
请输入图片描述
再接着点击 编辑代码 按钮进行代码编辑
请输入图片描述
最后,粘贴以下代码片段后,右边就可以显示访问后的效果展示,点击 部署 完成部署,然后通过域名 https://demo.93653142.workers.dev/ 访问镜像站:
请输入图片描述


// 你要镜像的网站.
const upstream = 'github.com'
 
// 镜像网站的目录,比如你想镜像某个网站的二级目录则填写二级目录的目录名,镜像 google 用不到,默认即可.
const upstream_path = '/'
 
// 镜像站是否有手机访问专用网址,没有则填一样的.
const upstream_mobile = 'github.com'
 
// 屏蔽国家和地区.
const blocked_region = ['KP', 'SY', 'PK', 'CU']
 
// 屏蔽 IP 地址.
const blocked_ip_address = ['0.0.0.0', '127.0.0.1']
 
// 镜像站是否开启 HTTPS.
const https = true
 
// 文本替换.
const replace_dict = {'$upstream': '$custom_domain', '//github.com': ''}
 
// 以下保持默认,不要动
addEventListener('fetch', event => {
  event.respondWith(fetchAndApply(event.request))
})
 
async function fetchAndApply(request) {
  const region = request.headers.get('cf-ipcountry').toUpperCase()
  const ip_address = request.headers.get('cf-connecting-ip')
  const user_agent = request.headers.get('user-agent')
 
  let response = null
  let url = new URL(request.url)
  let url_hostname = url.hostname
 
  if (https == true) {
    url.protocol = 'https:'
  } else {
    url.protocol = 'http:'
  }
 
  if (await device_status(user_agent)) {
    var upstream_domain = upstream
  } else {
    var upstream_domain = upstream_mobile
  }
 
  url.host = upstream_domain
  if (url.pathname == '/') {
    url.pathname = upstream_path
  } else {
    url.pathname = upstream_path + url.pathname
  }
 
  if (blocked_region.includes(region)) {
    response = new Response('Access denied: WorkersProxy is not available in your region yet.', {
      status: 403
    })
  } else if (blocked_ip_address.includes(ip_address)) {
    response = new Response('Access denied: Your IP address is blocked by WorkersProxy.', {
      status: 403
    })
  } else {
    let method = request.method
    let request_headers = request.headers
    let new_request_headers = new Headers(request_headers)
 
    new_request_headers.set('Host', url.hostname)
    new_request_headers.set('Referer', url.hostname)
 
    let original_response = await fetch(url.href, {
            method: method,
            headers: new_request_headers
    })
 
    let original_response_clone = original_response.clone()
    let original_text = null
    let response_headers = original_response.headers
    let new_response_headers = new Headers(response_headers)
    let status = original_response.status
 
    new_response_headers.set('access-control-allow-origin', '*')
    new_response_headers.set('access-control-allow-credentials', true)
    new_response_headers.delete('content-security-policy')
    new_response_headers.delete('content-security-policy-report-only')
    new_response_headers.delete('clear-site-data')
    
    const content_type = new_response_headers.get('content-type')
    if (content_type.includes('text/html') && content_type.includes('UTF-8')) {
      original_text = await replace_response_text(original_response_clone, upstream_domain, url_hostname)
    } else {
      original_text = original_response_clone.body
    }
 
    response = new Response(original_text, {
      status,
      headers: new_response_headers
    })
  }
  return response
}
 
async function replace_response_text(response, upstream_domain, host_name) {
  let text = await response.text()
 
  var i, j
  for (i in replace_dict) {
    j = replace_dict[i]
 
    if (i == '$upstream') {
      i = upstream_domain
    } else if (i == '$custom_domain') {
      i = host_name
    }
 
    if (j == '$upstream') {
      j = upstream_domain
    } else if (j == '$custom_domain') {
      j = host_name
    }
 
    let re = new RegExp(i, 'g')
    text = text.replace(re, j)
  }
  return text
}
 
async function device_status(user_agent_info) {
  var agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"]
  var flag = true
  for (var v = 0; v < agents.length; v++) {
    if (user_agent_info.indexOf(agents[v]) > 0) {
      flag = false
      break
    }
  }
  return flag
}

至此,镜像 GitHub 站点已完成,我们任意搜索一个 layui 的开源库,搜索结果如下图图所示。但是由于国内 workers.dev 域名的 DNS 已污染导致无法访问,所以需要绑定一个自定义域名来绕过该问题。
请输入图片描述

  1. 绑定自定义域名

先返回上一次,找到对应的 名称 点击 设置,添加自定义域 添加一个自定义域名:
请输入图片描述

最后,等待 DNS 解析生效,然后使用 添加的自定义域名进行访问

]]>
<![CDATA[利用Telegraph和Cloudflare自建图床实现外链图片存储]]> https://2sv.cn/archives/268/ 2025-07-31T17:38:08+08:00 2025-07-31T17:38:08+08:00 Eleven http://www.buer.cc AI摘要:本文介绍了如何利用Telegraph和Cloudflare自建图床以实现外链图片存储。通过Fork Telegraph-Image仓库并创建Cloudflare应用,用户可以将GitHub站点镜像并绑定自定义域名,从而实现高效的图片外链存储和快速加载。该方法相比传统图床方式,提供了更灵活且免费可用的解决方案。

Powered by AISummary.

Telegraph 简介
Telegraph 是一个免费开源的平台,通过它可以创建和共享图像、视频与文本。

Cloudflare 简介
Cloudflare 是一家全球 CDN 和安全提供商,可以提高网站的性能和安全性。

网站、博客和电商平台等,图片是必不可少的元素。当然图片需要存储空间和带宽来支持。对于流量小的站点来说,这还好。但如果是大流量的站点,将产生一些额外的存储和带宽费用,不太划算。针对这种情况,我们往往可以采取外链图片的方式。

但是,外链图片会占用大量的带宽和服务器资源。因此,大部分站点只供站内观看,不允许外链。而一般可外链图片的站点会给免费用户提供比较少的月流量,使用比较受限,只有成为付费用户之后才能提升外链流量。当然,也有网站专门提供免费外链图片服务。此类网站通常称之为图床,不限流量。

自建图床的常用方式有阿里云 OSS、GitHub、Google Drive 等。本文并不使用这些常用的自建图床方式,而是使用 Telegraph 和 Cloudflare 来自建图床。

本文将使用其网站镜像和访问控制的能力,实现 GitHub 站点的镜像,并通过自有域名实现在墙内的访问。

1.Fork Telegraph-Image 仓库

访问 Telegraph-Image 仓库地址,fork 到个人仓库:
请输入图片描述

  1. 创建应用并关联 Fork 的仓库

    在 Cloudflare 创建一个应用:
    请输入图片描述

点击 连接到 Git 按钮;

请输入图片描述

选择指定仓库开始安装:

请输入图片描述
点击 保存并部署 随后开始安装
请输入图片描述
等待安装完成后,可通过 Cloudflare 自动分配的域名访问,。
请输入图片描述
或点击 添加自定义域 绑定自定义域名
请输入图片描述
完成绑定后,可通过绑定的自定义域名进行或自动分配的域名访问,页面如下图:
请输入图片描述
因为使用 Cloudflare 的网络,图片的加载速度在某些地区可能得不到保证

]]>
<![CDATA[绕过CDN查找真实IP方法]]> https://2sv.cn/archives/267/ 2025-07-31T17:28:42+08:00 2025-07-31T17:28:42+08:00 Eleven http://www.buer.cc AI摘要:本文介绍了绕过CDN查找真实IP的多种方法。包括使用多地ping、nslookup、查询历史DNS记录、子域名扫描、网络空间引擎、国外DNS解析、邮件头信息等方式来识别CDN。还介绍了通过SSL证书、扫描全网、F5 LTM解码等技术进一步发现真实IP。此文为取证人员提供了对抗CDN隐藏IP技术的策略。

Powered by AISummary.

CDN 给用户带来便捷的同时也给取证人员带来了更大的挑战,如果网站存在 CDN,那么你拿到的 IP 也是一个分发的虚拟节点,在这个节点所搜集的信息基本是无用功。所以,我们必须绕过 CDN 去找到网站的真实 IP。

常见 CDN 服务商

一、国内 CDN 服务商

阿里云 CDN
百度云 CDN
七牛云 CDN
又拍云 CDN
腾讯云 CDN
Ucloud
360 CDN
网宿科技
ChinaCache
帝联科技

二、国外 CDN 服务商

CloudFlare
StackPath
Fastly
Akamai
CloudFront
Edgecast
CDNetworks
Google Cloud CDN
CacheFly
Keycdn
Udomain
CDN77
判断 CDN 的存在
那么我们要如何判断一个网站是否存在一个 CDN 呢?

方法 1:

很简单,使用各种多地 ping 的服务,查看对应 IP 地址是否唯一,如果不唯一多半是使用了 CDN,多地 Ping 网站有:

http://ping.chinaz.com/

http://ping.aizhan.com/

http://ce.cloud.360.cn/
请输入图片描述

方法 2:

使用 nslookup 进行检测,原理同上,如果返回域名解析对应多个 IP 地址多半是使用了 CDN。

有 CDN 的示例:
请输入图片描述
无 CDN 的示例:
请输入图片描述
绕过 CDN 寻找真实 IP

方法 1: 查询历史 DNS 记录

查看 IP 与 域名绑定的历史记录,可能会存在使用 CDN 前的记录,相关查询网站有:
https://dnsdb.io/zh-cn/ ###DNS 查询
https://x.threatbook.cn/ ### 微步在线
http://toolbar.netcraft.com/site_report?url= ### 在线域名信息查询
http://viewdns.info/ ###DNS、IP 等查询 https://tools.ipip.net/cdn.php ###CDN 查询 IP

方法 2: 子域名查询

由于目标服务可能在主站上做好了相应的 CDN,但是由于种种原因例如部署费用过高,或者对二级域名不上心等,所以导致二级域名没有部署到 CDN,这时我们可以从这个方面入手进行查询。利用子域名搜集工具等搜集到足够的子域名后,便可以对通过子域名进行真实 IP 的搜集。

下面介绍些常用的子域名查找的方法和工具:

1)微步在线 (https://x.threatbook.cn/)

微步在线功能强大,只需输入要查找的域名 (如 baidu.com),点击子域名选项就可以查找它的子域名了,但是免费用户查询次数有限。如图:

请输入图片描述
2)Dnsdb 查询法。(https://dnsdb.io/zh-cn/)

只需输入 baidu.com type:A 就能收集百度的子域名和 ip 了。如图:
请输入图片描述
3)各种子域名扫描器

这里,主要为大家推荐子域名挖掘机,仅需输入域名即可基于字典挖掘它的子域名,如图:
请输入图片描述
在开发网站的时候,开发者可能会将一时疏忽忘记将可能泄露信息的 php 探针等处理掉,让我们有机可乘

通过谷歌语法去搜集

inurl:phpinfo.php inurl:xxxxxx

方法 3: 网络空间引擎搜索法

常见的有以前的钟馗之眼,shodan,fofa 搜索。以 fofa 为例,只需输入:title:“网站的 title 关键字”或者 body:“网站的 body 特征”就可以找出 fofa 收录的有这些关键字的 ip 域名,很多时候能获取网站的真实 ip。
请输入图片描述

方法 4: 国外主机解析域名

大部分 CDN 厂商因为各种原因只做了国内的线路,而针对国外的线路可能几乎没有,此时我们使用国外的 DNS 查询,很可能获取到真实 IP。

国外多 PING 测试工具:

https://asm.ca.com/zh_cn/ping.php
http://host-tracker.com/
http://www.webpagetest.org/
https://dnscheck.pingdom.com/

方法 5: 网站邮件头信息

比如说,邮箱注册,邮箱找回密码、RSS 邮件订阅等功能场景,通过网站给自己发送邮件,从而让目标主动暴露他们的真实的 IP,查看邮件头信息,获取到网站的真实 IP。
请输入图片描述
方法 6: 通过 SSL 证书

证书颁发机构 (CA) 必须将他们发布的每个 SSL/TLS 证书发布到公共日志中,SSL/TLS 证书通常包含域名、子域名和电子邮件地址。因此可以利用 SSL/TLS 证书来发现目标站点的真实 IP 地址。
CDN 运营商在给服务器提供保护的同时,也会与其服务器进行加密通信(ssl),这时当服务器的 443 端口接入域名时也会在 443 端口暴露其证书,我们通过证书比对便可发现网站的真实 IP 地址。
SSL 证书搜索引擎:
https://censys.io/ipv4?q=github.com
请输入图片描述

方法 7: 网站漏洞查找

1)目标敏感文件泄露,例如:phpinfo 之类的探针、GitHub 信息泄露等。
2)XSS 盲打,命令执行反弹 shell,SSRF 等。
3)无论是用社工还是其他手段,拿到了目标网站管理员在 CDN 的账号,从而在从 CDN 的配置中找到网站的真实 IP。

方法 8: 扫描全网

通过 Zmap、masscan 等工具对整个互联网发起扫描,针对扫描结果进行关键字查找,获取网站真实 IP。

https://github.com/zmap/zmap

https://github.com/robertdavidgraham/masscan

方法 9: 通过 F5 LTM 解码

LTM 是将所有的应用请求分配到多个节点服务器上。提高业务的处理能力,也就是负载均衡。
当服务器使用 F5 LTM 做负载均衡时,通过对 set-cookie 关键字的解码,可以获取服务器真实 ip 地址。
例如:

Set-Cookie: BIGipServerpool_9.29_5229=605532106.22012.0000

先把第一小节的十进制数,即 605532106 取出来
将其转为十六进制数 2417afca
接着从后至前,取四个字节出来:CA AF 17 24
最后依次转为十进制数 202.175.23.36,即是服务器的真实 ip 地址。
方法 10: 利用 HTTP 标头寻找真实原始 IP

例如,Censys 上用于匹配服务器标头的搜索参数是 80.http.get.headers.server :,查找由 CloudFlare 提供服务的网站的参数如下:

80.http.get.headers.server:cloudflare

总结
CDN 原本的目的是为了改善互联网的服务质量,提高访问网站速度,然而有些违法网站用了此技术,对我们的取证侦破带来不少麻烦,通过以上介绍一些简单的方法,可以有一定概率查找出 CDN 背后的真实服务器 IP。在办案过程中,如果确认了是国内的 CDN 厂商的话,也可以尝试去调证。

]]>
<![CDATA[利用kimi/豆包AI帮助你写简单的python代码,比如简单的挂机脚本]]> https://2sv.cn/archives/266/ 2025-07-30T16:21:29+08:00 2025-07-30T16:21:29+08:00 Eleven http://www.buer.cc AI摘要:文章介绍了如何利用 Kimi 和豆包 AI 来帮助编写简单的 Python 代码,例如挂机脚本。步骤包括安装 Python 环境、使用 Visual Studio Code 编辑代码,并借助 AI 提供的代码框架进行修改。通过图像识别,使用 pyautogui 或 OpenCV 库编写自动化脚本,可以实现自动点击、鼠标移动等功能,即使没有 Python 基础,也能通过 AI 自动解决报错和命令问题。

Powered by AISummary.

AI 发展的越来越好了,连我这种完全不了解 python 的人都稍微了解了一些,而且入门难度好低。不由得感叹

1,先去 https://www.python.org/ 安装好环境
2,Visual Studio Code – Code Editing. Redefined 安装 vs code 这个也是免费好用的工具,可以让我这种小白清晰可见代码,代码可视化

在 vs code 安装好插件即可使用
请输入图片描述

接下来就是开始使用 kimi,以及豆包两种 AI 去直接提出我们的需求,比如我需要它给我一段 简单的识别屏幕图像 然后去点击,也就是挂机脚本。
请输入图片描述

import pyautogui
import time
import random
from PIL import ImageGrab
 
def find_image(image_path):
"""在屏幕上查找图片的位置"""
screenshot = ImageGrab.grab()
try:
image_location = pyautogui.locateOnScreen(image_path, confidence=0.8)
return image_location
except pyautogui.ImageNotFoundException:
return None
 
import pyautogui
import time
import random
from PIL import ImageGrab
 
def click_image(image_path):
"""查找图片并点击"""
image_location = find_image(image_path)
if image_location:
print(f"图片 {image_path} 找到,位置:{image_location}")
# 随机延迟 0.1 秒至 0.3 秒
time.sleep(random.uniform(0.1, 0.3))
# 点击图片位置
pyautogui.click(image_location)
print("点击图片")
else:
print(f"图片 {image_path} 未找到")
 
# 使用函数
click_image('起钩.png')

我们提出的问题,AI 给出的答案是大概的,其中详细的参数需要自己填写,复制上面这段代码进入 vs code,新建一个 python 文件,粘贴,运行会报错,因为需要的库没有安装
import pyautogui
import time
import random
from PIL import ImageGrab

在 vs code 调试输出处会直接给出安装库命令,非常好用,只不过安装源不是国内,你只需要复制 vs code 提出的建议命令到 kimi/ 豆包 AI,举例子:import pyautogui 帮我替换国内的源

如果需要写一个简单的挂机脚本
请输入图片描述
上方的图片给出的运行库是 OpenCV,这个就比 pyautogui 强。

举例子 提出的问题是 用 CV2 库写一段代码图像识别代码,循环查找 P:/1/1.png,如果找到 P:/1/1.png,则 0.2 秒延迟后再移动到 x =541, y=1587 点击一次,点击后移动鼠标到 x =541, y=1087 循环结束,再进入下一个循环,同时循环查找 P:/1/111.png 和 P:/1/5.png,如果找到的是 P:/1/111.png,则 0.2 秒延迟后鼠标移动到 x =541, y=1587 点击一次,1 秒延迟后移动鼠标到 x =559, y=1832 点击一次,0.2 秒延迟后移动鼠标到 x =541, y=1087, 如果找到的是 P:/1/5.png,则 0.2 秒延迟后鼠标移动到 x =541, y=1587 点击一次,1 秒延迟后移动鼠标到 x =559, y=1832 点击一次,0.2 秒延迟后移动鼠标到 x =541, y=1087

import pyautogui
import cv2
import numpy as np
import time
from pynput.keyboard import Listener, Key
 
def find_image(image_path):
    """使用 OpenCV 查找屏幕上的图片并返回其位置"""
    screen = pyautogui.screenshot()
    screen = cv2.cvtColor(np.array(screen), cv2.COLOR_RGB2BGR)
    image = cv2.imread(image_path, cv2.IMREAD_COLOR)  # 读取彩色图像
    res = cv2.matchTemplate(screen, image, cv2.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where(res >= threshold)
    if len(loc[0]) > 0:
        # 返回第一个匹配的位置
        top_left = loc[1][0], loc[0][0]
        return top_left
    else:
        print(f"未找到图片:{image_path}")
        return None
 
# 监听键盘事件  - 这是额外添加的,你只需要对 AI 说防止这段程序无限循环 -
def on_press(key):
    global running
    if key == Key.esc:
        running = False
 
def on_release(key):
    if key == Key.esc:
        return False
 
# 主循环
running = True
listener = Listener(on_press=on_press, on_release=on_release)
listener.start()
 
while running:
    # 循环查找 P:/1/1.png
    found = False
    while not found:
        location_1 = find_image('P:/1/1.png')
        if location_1:
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.click(541, 1587)  # 点击指定位置
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.moveTo(541, 1087)  # 移动到指定位置
            found = True  # 找到图片,退出循环
        else:
            time.sleep(0.3)  # 未找到图片,继续查找
 
    # 循环查找 P:/1/111.png 和 P:/1/5.png
    found = False
    while not found:
        location_111 = find_image('P:/1/111.png')
        location_5 = find_image('P:/1/5.png')
         
        if location_111:
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.click(541, 1587)  # 点击指定位置
            time.sleep(1)  # 1 秒延迟
            pyautogui.click(559, 1832)  # 点击指定位置
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.moveTo(541, 1087)  # 移动到指定位置
            found = True  # 找到图片,退出循环
        elif location_5:
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.click(541, 1587)  # 点击指定位置
            time.sleep(1)  # 1 秒延迟
            pyautogui.click(559, 1832)  # 点击指定位置
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.moveTo(541, 1087)  # 移动到指定位置
            found = True  # 找到图片,退出循环
        else:
            time.sleep(0.3)  # 未找到图片,继续查找
 
listener.stop()

请输入图片描述
请输入图片描述
移动某个窗口到固定的坐标
请输入图片描述
简单的挂机脚本结合上面那段代码即可运行,坐标需要自己调试一下

import pyautogui
import cv2
import numpy as np
import time
from pynput.keyboard import Listener, Key
import pygetwindow as gw
 
# 获取窗口
window = gw.getWindowsWithTitle('MuMu 模拟器 12')[0]  # 假设只有一个窗口名为 "MuMu 模拟器 12"
 
# 移动窗口到左上角
window.moveTo(0, 0)
 
# 获取窗口的大小
width, height = window.size
 
# 打印窗口的大小和坐标
print(f"窗口大小:{width}x{height}")
print(f"窗口坐标:{window.left},{window.top}")
 
 
 
 
def find_image(image_path):
    """使用 OpenCV 查找屏幕上的图片并返回其位置"""
    screen = pyautogui.screenshot()
    screen = cv2.cvtColor(np.array(screen), cv2.COLOR_RGB2BGR)
    image = cv2.imread(image_path, cv2.IMREAD_COLOR)  # 读取彩色图像
    res = cv2.matchTemplate(screen, image, cv2.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where(res >= threshold)
    if len(loc[0]) > 0:
        # 返回第一个匹配的位置
        top_left = loc[1][0], loc[0][0]
        return top_left
    else:
        print(f"未找到图片:{image_path}")
        return None
 
# 监听键盘事件
def on_press(key):
    global running
    if key == Key.esc:
        running = False
 
def on_release(key):
    if key == Key.esc:
        return False
 
 
# 主循环
running = True
listener = Listener(on_press=on_press, on_release=on_release)
listener.start()
 
while running:
    # 循环查找 P:/1/1.png
    found = False
    while not found:
        location_1 = find_image('P:/1/1.png')
        if location_1:
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.click(541, 1587)  # 点击指定位置
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.moveTo(541, 1087)  # 移动到指定位置
            found = True  # 找到图片,退出循环
        else:
            time.sleep(0.3)  # 未找到图片,继续查找
 
    # 循环查找 P:/1/111.png 和 P:/1/5.png
    found = False
    while not found:
        location_111 = find_image('P:/1/111.png')
        location_5 = find_image('P:/1/5.png')
         
        if location_111:
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.click(541, 1587)  # 点击指定位置
            time.sleep(1)  # 1 秒延迟
            pyautogui.click(559, 1832)  # 点击指定位置
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.moveTo(541, 1087)  # 移动到指定位置
            found = True  # 找到图片,退出循环
        elif location_5:
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.click(541, 1587)  # 点击指定位置
            time.sleep(1)  # 1 秒延迟
            pyautogui.click(559, 1832)  # 点击指定位置
            time.sleep(0.2)  # 0.2 秒延迟
            pyautogui.moveTo(541, 1087)  # 移动到指定位置
            found = True  # 找到图片,退出循环
        else:
            time.sleep(0.3)  # 未找到图片,继续查找

即使不会 python,也没关系,报错,不明白的命令也直接问 AI。

]]>
<![CDATA[Frp内网穿透服务端搭建教程-官方版本]]> https://2sv.cn/archives/265/ 2025-07-30T15:58:45+08:00 2025-07-30T15:58:45+08:00 Eleven http://www.buer.cc AI摘要:本文介绍了如何搭建Frp内网穿透服务端,包括下载官方版本、配置文件说明、设置开机自启等步骤。首先下载适合的系统版本,配置文件无需修改即可使用。然后,介绍了如何设置Frp服务开机自启,提供了具体的命令操作和配置路径的替换说明,完成后Frp服务会在系统启动时自动运行。

Powered by AISummary.

程序包均为免安装,下载即可使用

如果不知道自己系统是 amd 还是 arm,建议先下载 amd 版本,如果版本不对,后续启动会提示该错误,更换版本即可
请输入图片描述

官方下载地址https://github.com/fatedier/frp/releases
请输入图片描述
配置文件内容含义.内容不用修改,可直接使用
请输入图片描述

设置开机自启

  1. 执行以下命令

vim /lib/systemd/system/frps61.service

  1. 文件内容为

[Unit]Description=frps serviceAfter=network.target network-online.target syslog.targetWants=network.target network-online.target[Service]Type=simpleExecStart=/vdd/frp/frp_0.61.0_linux_amd64/frps -c /vdd/frp/frp_0.61.0_linux_amd64/frps.toml[Install]WantedBy=multi-user.target

注意:其中的 vdd/frp/frp_0.61.0_linux_amd64 替换成自己的路径

保存好文件后执行以下命令:

systemctl daemon-reloadsystemctl start frps61systemctl enable frps61

操作完成之后,即可实现开机自启

]]>