让traefik代替你的 waf(使用CrowdSec)+ nginx + acme.sh + mtls-auth

traefik 可以帮你: 自动续证书 反代(自动处理 ws、tls 证书、反代地址、压缩 etc.) 使用插件代替 waf 负载均衡(可以使用多个后端、k8s) 支持 mTLS 认证(如果你使用的是 Cloudflare 的 CDN) 前言 本文是对traefik的一个简单介绍,主要介绍如何使用 traefik 来代替 waf(使用 CrowdSec)、nginx、acme.sh、mtls-auth 等。 traefik会是你服务器的入口,所有的请求都会先经过 traefik,然后再转发到后端服务。 后端服务也不用配置绑定的端口和ip了(例如docker.port: 127.0.0.1:8080:8080,然后nginx反代,每个服务都要记住端口很麻烦),traefik 会自动处理。 info 主要贴出配置,注意多看注释 IMPORTANT CrowdSec 的工作原理之后会说 info 简单说一下 mtls 的好处 如果其他人通过你的域名扫描全网 ip,没有 mtls 很容易就扫到你的服务器 ip 了,然后被定点攻击 如果你使用了 mtls 认证,其他人就算扫到你的 ip 也无法访问你的服务,除非他有 cf 的客户端证书,这个只有 cf 有私钥,无法伪造 traefik 配置 此项配置了之后可以 自动帮你续证书 如果你用的是 cf 的 cdn,还可以自动 mtls 认证。 使用 CrowdSec 作为 WAF(之后再配置 CrowdSec) 扫 443 和 80 端口的请求直接丢弃 配置结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 traefik/ ├── acme.json ├── docker-compose.yml ├── cf-cert/ │ └── cloudflare-ca.pem ├── dynamic_conf/ │ ├── ban.html │ ├── cloudflare-mtls.yml │ ├── compressor.yml │ ├── crowdsec-middleware.yml │ └── drop-ip-access.yml └── logs/ └── traefik.log ERROR ban.html 我就不贴了,需要的自己 ai 写一个 IMPORTANT 如果要自动帮你续证书,记得acme.json的权限要设置为600,否则 traefik 无法写入证书。 如果你使用的是 cf 的 cdn,记得在添加你的 cf 证书。到这里下载证书。 记得事先创建traefik-net网络,或者在docker-compose.yml中注释掉网络部分。 docker-compose.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 services: traefik: image: traefik:latest # 建议使用明确的版本号,而不是 latest。现在用的是 v3 container_name: traefik restart: unless-stopped # --- 静态配置:通过 command 而不是文件 --- command: - "--entrypoints.websecure.http.middlewares=crowdsec-bouncer@file,global-compressor@file" # --- CrowdSec 插件配置 --- - "--experimental.plugins.crowdsec-bouncer-traefik-plugin.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" - "--experimental.plugins.crowdsec-bouncer-traefik-plugin.version=v1.4.4" # --- API 和仪表盘 --- # - "--api.dashboard=true" # 启用仪表盘 # # 警告:下面的 insecure=true 仅用于开发环境,方便通过 8080 端口访问。生产环境请务必通过安全路由暴露。 # - "--api.insecure=true" # --- 入口点定义 --- - "--entrypoints.web.address=:80" # 定义 HTTP 入口点,监听80端口 - "--entrypoints.websecure.address=:443" # 定义 HTTPS 入口点,监听443端口 # --- Cloudflare IPs --- - "--entrypoints.web.forwardedheaders.trustedips=173.245.48.0/20,103.21.244.0/22,103.22.200.0/22,103.31.4.0/22,141.101.64.0/18,108.162.192.0/18,190.93.240.0/20,188.114.96.0/20,197.234.240.0/22,198.41.128.0/17,162.158.0.0/15,104.16.0.0/13,104.24.0.0/14,172.64.0.0/13,131.0.72.0/22" # --- Docker Provider 配置 --- - "--providers.docker=true" # 启用 Docker 服务发现 - "--providers.docker.exposedbydefault=false" # 默认不暴露任何容器,更安全 - "--providers.docker.network=traefik-net" # 指定Traefik监听哪个网络 #配置log - "--log.level=DEBUG" # 设置日志级别为DEBUG - "--log.filePath=/var/log/traefik.log" # 设置日志文件路径 # - "--log.format=json" # 设置日志格式为JSON,便于后续处理 # --- 文件 Provider 配置 --- - "--providers.file=true" # 启用文件提供者 - "--providers.file.directory=/etc/traefik/dynamic_conf" # 指定动态配置文件目录 - "--providers.file.watch=true" # 启用动态配置文件监控 - "--accesslog=true" # 启用访问日志 - "--accesslog.format=json" # 建议使用json格式,便于后续处理 # --- Let's Encrypt (SSL证书) 配置 --- # 暂时注释掉,在您配置好域名后可以启用 - "--certificatesresolvers.myresolver.acme.httpchallenge=true" - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web" - "--certificatesresolvers.myresolver.acme.email=xxx" - "--certificatesresolvers.myresolver.acme.storage=/etc/traefik/acme.json" # 注意:请确保acme.json文件权限为600,Traefik才能写入证书 # --- 端口映射 --- ports: - "80:80" - "443:443" # - "8080:8080" # 暴露仪表盘的8080端口(仅开发) # --- 挂载卷 --- volumes: # 挂载Docker socket,让Traefik可以监听到容器的创建和销毁 - "/var/run/docker.sock:/var/run/docker.sock:ro" # 挂载acme.json文件,用于持久化SSL证书 - "./acme.json:/etc/traefik/acme.json" # 挂载动态配置文件目录 - "./dynamic_conf:/etc/traefik/dynamic_conf:ro" # 挂载日志目录 - "./logs:/var/log:rw" - "./cf-cert:/etc/traefik/cf-cert:ro" # --- 网络 --- networks: - traefik-net networks: traefik-net: name: traefik-net external: true cloudflare-mtls.yml 1 2 3 4 5 6 7 8 tls: options: # 给这个 TLS 选项起一个名字 cloudflare-mtls: minVersion: VersionTLS12 clientAuth: caFiles: - /etc/traefik/cf-cert/cloudflare-ca.pem clientAuthType: "RequireAndVerifyClientCert" compressor.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # traefik/dynamic_conf/middlewares.yml http: middlewares: # 定义一个全局可用的压缩中间件,我们给它起个名字叫 'global-compressor' global-compressor: compress: # 在这里可以设置更详细的参数,进行精细化控制 # 排除不需要压缩的内容类型(例如图片,因为它们已经被压缩过了) excludedContentTypes: - "image/png" - "image/jpeg" - "image/gif" - "application/pdf" # 设置压缩算法,默认是gzip # 也可以使用 'br' (Brotli) 或者 'deflate' # 但注意,Brotli在某些浏览器上支持不如gzip # algorithm: "gzip" # 默认是gzip,通常不需要显式设置 # 设置压缩级别,范围是1到9,数字越大压缩率越高,但CPU消耗也越大 # 设置一个最小响应体大小,小于这个大小的响应不进行压缩 (避免浪费CPU) minResponseBodyBytes: 1024 # 即只压缩大于1KB的响应 crowdsec-middleware.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 http: middlewares: crowdsec-bouncer: plugin: crowdsec-bouncer-traefik-plugin: CrowdsecLapiKey: "" #填自己的 Enabled: "true" crowdsecMode: "stream" # logLevel: "DEBUG" banHTMLFilePath: "/etc/traefik/dynamic_conf/ban.html" #自己生成 forwardedHeadersCustomName: "CF-Connecting-IP" forwardedHeadersTrustedIPs: # Cloudflare IPs - "173.245.48.0/20" - "103.21.244.0/22" - "103.22.200.0/22" - "103.31.4.0/22" - "141.101.64.0/18" - "108.162.192.0/18" - "190.93.240.0/20" - "188.114.96.0/20" - "197.234.240.0/22" - "198.41.128.0/17" - "162.158.0.0/15" - "104.16.0.0/13" - "104.24.0.0/14" - "172.64.0.0/13" - "131.0.72.0/22" # Local IPs - "10.0.10.23/32" - "10.0.20.0/24" # Local IPs clientTrustedIPs: - "192.168.0.0/16" - "10.0.0.0/8" - "172.16.0.0/12" drop-ip-access.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 http: routers: catchall-http: rule: "HostRegexp(`{host:.+}`)" entryPoints: - web service: "blackhole-http-svc" # 指向HTTP黑洞服务 priority: 1 services: blackhole-http-svc: loadBalancer: servers: - url: "http://10.255.255.1:80" # TCP部分:处理所有未匹配的HTTPS请求 (例如 https://<IP>) tcp: routers: catchall-tls: rule: "HostSNI(`*`)" # 匹配任何TLS连接 entryPoints: - websecure service: "blackhole-tcp-svc" # 指向TCP黑洞服务 priority: 1 tls: passthrough: false services: blackhole-tcp-svc: loadBalancer: servers: # TCP服务使用 'address' 字段 - address: "192.0.2.1:1" crowdsec 配置 这里配置 CrowdSec,通过 docker 搭建。 整个安全方案由两部分组成: CrowdSec Agent (crowdsec 服务): 负责分析日志、检测威胁,并管理决策(例如,哪个 IP 应该被禁止)。 Traefik Bouncer (作为 Traefik 插件): 在 Traefik 中运行,负责执行 CrowdSec Agent 的决策,直接在流量入口处阻止恶意 IP。 工作流程 Traefik 接收外部请求,并将访问日志(JSON 格式)输出。 CrowdSec Agent (crowdsec 服务) 通过挂载的 Docker Socket 读取 Traefik 的日志。 Agent 使用 crowdsecurity/traefik collection 中的解析器和场景分析日志,检测到攻击行为(如暴力破解、扫描等)。 一旦检测到威胁,CrowdSec 会生成一个“决策”,将攻击者的 IP 标记为恶意,并推送到 local API。 local API马上推送到所有Bouncer(如果还配置了其他Bouncer),其中Traefik 中的 CrowdSec Bouncer 插件会获取最新的决策列表。 当被标记为恶意的 IP 再次尝试访问时,Bouncer 会在 Traefik 层面直接拒绝该请求,从而保护所有后端服务。 crowdsec-bouncer-traefik-plugin.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 services: crowdsec: image: crowdsecurity/crowdsec:latest container_name: crowdsec restart: unless-stopped environment: - GID=999 - COLLECTIONS=crowdsecurity/traefik #安装了 crowdsecurity/traefik 集合,CrowdSec 知道 Traefik 日志长什么样。当它发现某个容器(也就是 Traefik 容器)的日志格式与 Traefik 解析器匹配时,就会自动开始采集和分析这些日志。 volumes: - /var/run/docker.sock:/var/run/docker.sock:ro #允许 CrowdSec 监控其他容器的日志 - ./data:/var/lib/crowdsec/data - ./config:/etc/crowdsec networks: - traefik-net networks: traefik-net: external: true 反代配置 主要通过 traefik 的标签(labels)来配置反代。 docker-compose.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 services: umami: image: ghcr.io/umami-software/umami:postgresql-latest # ports: # - "3000:3000" environment: DATABASE_URL: DATABASE_TYPE: postgresql init: true restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"] interval: 5s timeout: 5s retries: 5 networks: - traefik-net labels: - traefik.enable=true - traefik.http.routers.umami.rule=Host(`stats.xingpingcn.top`) # 替换为你的域名。会自动帮你申请证书,记得把ip指向vps ip或者cname到cf的cdn - traefik.http.services.umami.loadbalancer.server.port=3000 # umami 默认端口。traefik会主动处理,不需要要你自己设置端口。如果有另一个服务在网络traefik-net上监听3000端口,traefik会自动处理冲突。服务b想连接此服务,直接使用服务名和端口,例如 `http://umami:3000` - traefik.http.routers.umami.entrypoints=websecure - traefik.http.routers.umami.tls=true - traefik.http.routers.umami.tls.certresolver=myresolver # 使用之前定义的证书解析器 - traefik.http.routers.umami.tls.options=cloudflare-mtls@file # 使用之前定义的 mtls 选项。traefik似乎不支持全局设置 networks: traefik-net: name: traefik-net external: true

2025/7/16
articleCard.readMore

列举几个免费域名和权威dns服务器

免费域名 www.sitelutions.com 优点 这个能分配一个二级子域名,有很多域名,可以自定义NS 长期免费 缺点 但是不是所有都可以用,能用的子域名都不能部署在vercel,可以部署在netlify freedomain.one 同上 nic.eu.org 这个基本大家都有了 优点 子域名都能部署在vercel 长期免费 有dnssec 缺点 大概率被墙 申请要等比较久 cloudns.net 这本身是一个dns服务器,但是可以获得一个子域名 优点 可以绑定到cf 缺点 只能绑定到cf 新账号分配的子域名似乎不能绑定到cf www.azote.org 优点 可以申请很多域名 缺点 不能绑定到cf,但是可以通过cf的SaaS来CNAME进行域名加速 secure.nom.za 优点 可以绑定到cf 缺点 一个月不用会被回收 硅云 优点 免费一年的.xyz或者.top域名 缺点 只有新用户才有1年的免费使用 国产 此外还有pp.ua,虽然免费但是要绑定银行卡,每年续费 https://dns.beaa.cn/ 免费二级域名 免费权威dns服务器 cloudns.net 这本身是一个dns服务器,但是可以获得一个子域名 优点 申请简单,可以拿到一个免费域名 可以转移到cf,这样就没有解析次数限制 缺点 速度一般 新账号分配的子域名似乎不能绑定到cf 如果用它自己的dns解析只能每个月用500k次,转到cf就没有限制了 NS1 优点 可以说是目前最牛的DNS服务器了,最近被IBM收购,文档有点乱,应该很快就会改 相对于其他国外的dns服务器来说,免费版在国内速度不错。而且他有国内和京东云合作的中国特供dns服务器,非常快,但是不免费 功能非常强大,免费版就可以体验到特色功能filter chain。我写过一篇教程介绍如何使用。付费版还有更多强大功能。 每个月5m次解析,1个filter chain 可以接入http测速等监控工具(包括第三方服务和自定义的),实现自动故障转移 可以有国内的分路线解析。我写过一篇教程介绍如何使用 有dnssec 缺点 申请困难 不知道为什么会有很多dns解析占用你的免费额度 netlify 是的,就是那个可以部署项目的netlify,他也有dns服务 优点 它是接入ns1的,也就是说你可以享受ns1的速度,但是没有ns1的次数限制 缺点 基本上就体验不到ns1的各种功能了 vercel 优点 一样的没有次数限制,速度可以 缺点 功能少 华为云 优点 有分路线解析 国际版不用绑定手机号和银行卡 SOA没有指向此NS也能添加域名 缺点 速度一般,不稳定 分路线解析一般般,识别不能说很准确 作为国内dns服务器功能较少,如307重定向这种,和类似dnspod的http监控 500条dns记录。是的,他能绑定50个域名,可是总共只能添加500条dns解析。有点神经病了,不过它可以申请提高这个限制,我不知道容易不容易 无dnssec cf 优点 免费,无限制 可以用cdn 缺点 没有分路线解析 国内解析很慢,cdn很慢 不能添加子域名,某些特殊的子域名可以 dnspod 优点 有免费的http测速和负载均衡 缺点 国际版也要绑定银行卡 dns.he.net 国外老牌 优点 国内速度快 有ddns SOA没有指向此NS也能添加域名 记录类型多 缺点 暂时想不到 geoscaling.com 优点 就像它的名字一样,可以根据地理位置解析 速度还行 缺点 想要按照地理位置解析,规则编写起来很麻烦

2025/6/22
articleCard.readMore

如何白嫖和使用GitHub models的LLM(gpt4o和Llama-3.1-405b)

刚刚通过了申请,然后马上去玩了一下GitHub提供LLM,总的来说,Llama-3.1-405b每天可以用50次,gpt4o 150次! 你需要先申请,然后等着通过。 通过之后,根据你的使用方法来填写url nextchat、oneapi https://models.inference.ai.azure.com/chat/completions# 注:后面的井号不可省略 lobechat https://models.inference.ai.azure.com token的话就是你的GitHub token。没有token的看这里 模型看这里 GitHub models模型 https://github.com/marketplace/models 你可以点进去看每个模型的详细,在右边有显示现在的速率是高还是低 之后你可以通过这里查看对应的限制速率。 GitHub models速率限制 https://docs.github.com/zh/github-models/prototyping-with-ai-models#rate-limits 总的来说,Llama-3.1-405b每天可以用50次,gpt4o 150次!

2025/6/22
articleCard.readMore

解决升级umamiv2.11时出现的P3009错误

鉴于中文互联网上关于这个问题的内容很少,我还是水一篇吧 前言 先放issue p3009 issue https://github.com/umami-software/umami/issues/2645#issuecomment-2080419741 我是在vercel上部署的,所以issue里面提到的用py或者shell去迁移数据库的方法我是实现不了的,只能在build阶段就把问题解决。 解决方法 在package.json找到 package.json 1 "build-db": "npm-run-all copy-db-files build-db-client", 然后改成 package.json 1 2 "build-db": "npm-run-all copy-db-files build-db-client resolve-db", "resolve-db": "prisma migrate resolve --applied '05_add_visit_id'", 就可以了 我是怎么样定位到问题所在的 还是再写多一点 打开vercel日志,之后打开GitHub vercel日志 GitHub 图片里面写的很明白,看不到或者看不懂评论区留言

2025/6/22
articleCard.readMore

你的常用域名被其他vercel账号使用的解决方法

先放链接 社区维护者答复 https://github.com/orgs/vercel/discussions/6285 由于vercel最近在你的个人账户里添加了一个团队(team),你会发现你左上角的头像变了,然后点击中间domain按钮的时候发现里面并没有你之前使用过的域名。这个时候你在项目里添加域名,会提示说域名已经被其他账号使用。但是很困惑的是,只在前几天之前,你一直能够没有限制地添加域名,为什么这几天就变了。 这是由于你的项目现在全部变为你的team的项目,而你的域名却仍然在你的账号之下。 解决方法也很简单,点击右上角你的账号设置,然后点击左边的domain,选择你想要转移的域名,点击左边的三个点的按钮,然后点击move,就可以开始转移了。 设置域名转移

2025/6/22
articleCard.readMore

curl遇到的坑

一开始我是这么写的 bash 1 2 3 4 5 6 7 8 9 10 11 12 # 获取更新后的证书和私钥文件路径 CERT_PATH=$(cat ./netlify_cert/domain.com.cert.pem) KEY_PATH=$(cat ./netlify_cert/domain.com.key.pem) FULLCHAIN_CERT_PATH=$(cat ./netlify_cert/domain.com.fullchain.pem) # 使用 Netlify API 上传证书 curl -X POST \ -H "Authorization: Bearer $NETLIFY_API_KEY" \ -d "key=${KEY_PATH}" \ -d "ca_certificates=${FULLCHAIN_CERT_PATH}" \ -d "certificate=${CERT_PATH}" \ "https://api.netlify.com/api/v1/sites/${NETLIFY_SITE_ID}/ssl" 这么写看着没用什么问题,但是-d命令是默认进行urlencode的,这样子我的证书就会改变。需要改成--form-string才行。 这种默认就urlencode的,curl -h中又没说明,真的好坑

2025/6/22
articleCard.readMore

cron笔记

cron笔记,包含cron不执行shell脚本的解决办法 也许shell脚本本身可以执行,但是cron中不能执行,需要像下面这样设置 cron-for-run-per-1h.cron 1 2 3 SHELL=/bin/bash 0 * * * * . /etc/profile;/bin/sh /pathto/run.sh NOTE 最后一定要有一个回车!后者会导入失败 run.sh 1 2 3 4 5 #!/bin/bash PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LOGS_FILE="/pathto/logs/$(date "+%Y-%m-%d-%H-%M-%S").log" cd /pathto docker-compose up >> $LOGS_FILE 2>&1 最后设置到cron run.sh 1 crontab /pathto/cron-for-run-per-1h.cron warning 使用此命令会覆盖之前所有的cron任务 如果你不想覆盖之前的,那么就/etc/cron.d中新建文件,然后写进去。 warning cron的话基本必有一个?,它仅可存在于dayofmouth或者dayofweek 个人docker配置备份 Dockerfile 1 2 3 4 5 6 FROM python:3.11 WORKDIR /bin/test COPY ./requirements.txt ./ RUN pip install -r ./requirements.txt ENTRYPOINT [ "python" ] CMD [ "./test.py" ] docker-compose.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 version: '3.8' services: enhanced-faas: build: context: ./ container_name: enhanced-faas volumes: - "./:/bin/test" expose: - 443,80 command: ./main.py networks: - nginx-proxy networks: nginx-proxy: external: true

2025/6/22
articleCard.readMore

使用rclone和alist加密和备份你的数据到公有云

因为我用的甲骨文 vps,可能会玄学删 vps,所以需要频繁备份。放在国内公有云又怕审查,放谷歌微软的公有云容量又太少,歪门邪道又可能被删数据。有了 alist 就可以方便加密和解密数据,把加密后的数据放国内公有云就不怕审查了。用 alist 还有一个好处就是,如果你的数据同步到了多个公有云,alist 是可以很方便集中显示和管理公有云的文件的。rclone 也是常规的同步工具,直接备份 docker 文件夹就是了,这边就稍微记录一下。 前言 想要达成前面说到的目的,你需要: 需要的东西 alist,并注册多个国内公有云账号,会把 vps 的数据同步到多个公有云 安装好 rclone。直接用官网提供的 bash,就没必要用 docker 了,因为可能要经常敲命令行,如果用 docker 还得进入 docker 才可以敲。 配置 alist alist 可以很方便加密数据并上传到公有云。见官网教程。 这里稍微说明一下怎么做 先把公有云(如阿里云,天翼云)添加到alist 之后创建Crypt驱动,填写Crypt的路径,并且填写加密后的文件所在路径。例如,阿里云挂在到了/ali,那么需要在这个/ali里面预先创建一个空的文件夹,例如/ali/test,之后在Crypt配置里,填写Crypt本身的路径,例如/Crypt,之后填写加密后的文件所在路径,也就是/ali/test。 那么就可以通过访问/Crypt来加密解密/ali/test里的文件了,上传文件到/Crypt也就同样可以加密文件到/ali/test。 之后如果你选择把同一个文件加密到多个公有云,使用 alist 的别名功能可以方便集中显示和管理分布在各个公有云的文件。 同样不要忘记导出 alist 的配置,可以用中文的密码,更加难破解。在 alist 的 dash 中不能直接输入中文,可以在别处输入了密码后,再复制粘贴到 dash。 配置 rclone 通过 alist 来中转而不是直接在 rclone 中挂载公有云的原因是,rclone 挂载起来没有 alist 方便,而且 alist 文档写的比较清楚。我一开始是用 rclone 来挂载谷歌云盘的,官网教程用的谷歌云盘的 oauth api,结果弄到后面需要我在有浏览器的电脑里,下载 rclone 然后再用浏览器登录,把 cookie 复制到 vps,,, rclone 可以直接挂载 alist 的 webdav,例如挂载 alist 的 /ali/test,就填写 http://127.0.0.1:port/dav/ali/test,注意你 alist 的端口,还要要加/dav前缀。 输入 rclone config 就可以挂载 webdav。webdav 的用户和密码同 alist 的登录用户密码。 配置同步 rclone sync and copy rclone sync命令可以方便同步改变了内容的文件,例如 test.txt 中改变了一个字符,这时候运行同步命令就可以同步,如果再一次运行同步命令,则不会重复上传文件到公有云,节省了带宽。如果删除文件也会同步删除,rclone copy则不会同步删除。sync命令同样可以备份公有云端要删除的文件,具体见官网文档。 建议把同步命令写到 .sh 里,方便管理。rclone sync需要先了解怎么用。 /home/rclone/bash.sh 1 2 3 4 5 6 7 8 9 rclone sync /home/dcoker-data ali:/dcoker-data \ --copy-links --exclude-from /home/exclude.txt –ignore-size --disable-http-keep-alives --update ## --copy-links 复制软连接 ## --exclude-from 排除某些文件或者文件夹。语法见 <https://rclone.org/filtering/> # --dry-run 检查哪些文件要同步 可以在 exclude.txt 中定义不同步哪些文件。这里给一个样板。 /home/exclude.txt 1 2 3 4 5 6 7 tmp/** icon_cache/** **pycache**/** netlify_cert/logs/** \*.pem alist/alist-data/log/** alist/alist-data/temp/** 可以定时备份。 cron 1 2 3 4 5 6 7 8 9 10 11 12 # 手动把本文件放在/etc/cron.d # 最后运行 service cron restart # 如果需要使用其他用户运行,请改掉 root # 需要注意的是最后的那个空行不能删除 SHELL=/bin/bash 0 0/8 \*\* ? root /bin/bash /home/rclone/bash.sh > /tmp/rclone.log 2>&1

2025/6/22
articleCard.readMore

让在vpc中的aws lambda函数不通过nat获得访问互联网的能力

如果在使用aws lambda中,你的lambda函数需要访问aws的其他服务,例如EFS、RDS,那么大概率需要将你的lambda和efs放置在同一vpc中(不在同一vpc的情况下你可以使用endpoint),这个时候即使你的lambda是在公开子网(public subnet)中也是是没有访问互联网的能力的,这是因为你的lambda只有子网的ip10.0.0.0,流量路由到互联网网关的时候会被网关丢弃,因为你没有配置公网ip。本文会给出几个解决方案,并分析优缺点。 因为aws的文档大部分是英文,中文文档都是机翻,所以有些专有名词的翻译就很别扭,所以干脆直接用英文。 前言 正如前面所说,你的lambda函数所在的vpc需要配置公网ip才能拥有访问互联网的能力。你可能会说,为什么我平时用的lambda不需要加入vpc呢? 这是因为: 你的lambda没有手动配置vpc。如果你的lambda没有手动配置vpc,那么aws会把你的lambda放进aws自己管理的vpc中,在该vpc中拥有公网ip,你的lambda可以访问互联网,但是你的lambda函数并不能访问该vpc下的其他aws服务(当然不能,难道你还能访问aws他自己的私有服务吗) 你的lambda并没有使用到其他aws服务。要使用其他aws服务,则该服务一定是要加入到你自己的vpc中的,例如你要把信息写进json文件并持久化,你需要s3或者EFS;例如你要访问ec2实例或RDS数据库。如果只是临时写入文件则可以在/tmp目录下写入,lambda运行结束则会被清空,不能持久化。 要让lambda拥有同时访问互联网和vpc下的服务的能力,首先你要有公网ip,另外你的lambda能访问vpc下的服务。 我查阅了网上提到的几种方法,并总结下来 存在的解决方案有: 配置nat网关。 配置endpoint。将你的程序解耦,分为两个lambda函数,一个用于访问互联网,另一个访问aws服务,二者通过endpoint进行通讯。 通过API gateway。同样地,你的程序需要解耦,其中用于访问aws服务的lambda被主lambda函数通过API调用。 通过aws lambda api。使用aws sdk(python使用boto3),通过invoke方法同步或异步调用另一个lambda。 解决方案 配置nat网关 这是官方推荐的方法。 如何配置 新建一个vpc,选择带有公网子网和私有子网的模板,然后勾选nat网关就可以。在可视化界面中你可以看到私有子网通过路由表(route table)将流量路由到nat网关。你把你的lambda和aws服务放进私有子网内,你的lambda就拥有了同时访问互联网和vpc下的aws服务的能力。路由表会根据destination帮你处理好一切。 优缺点 最简单也最贵。单单是一个nat网关开着它就要30美元一个月,转发的流量还需要另外收费。不清楚公网ip是否另外收费 配置endpoint aws设置endpoint的目的是为了让处于不同的vpc下的服务不通过互联网而通过aws的内部网络相互通讯,从而减少安全风险。 如何配置 利用这个特性,你可以在将需要访问互联网的lambda放在aws他自己管理的vpc中(在创建lambda的时候默认会放进该vpc),将另一个lambda放到你的vpc中,该lambda函数用于访问同vpc下的aws服务,例如RDS。前者lambda通过endpoint访问后者。 值得注意的是,endpoint是安装在服务消费者(service consumers)上的,在上面的例子中,假设我是希望能访问互联网的lambda访问处于自定义vpc中的lambda,读取RDS数据并发送邮件。在这里,服务消费者是访问互联网的lambda,服务提供者(service providers)是处于自定义vpc中的lambda,前面提到,endpoint应该被安装在服务消费者——也就是访问互联网的lambda中,但是,该lambda是放在aws自己管理的vpc中的,我们没有权限去创建一个endpoint,只能改变思路,就像下面的图所示,把处于自定义vpc中的lambda作为服务消费者,读取数据库,之后通过endpoint调用vpc外面的lambda。 NOTE 在你的lambda中,可以通过编程的方式使用aws sdk(python是boto3)链接endpoint。sdk通常是发送一个http请求来调用endpoint。 示例 优缺点 优点 费用比nat低 由于解耦,程序逻辑更加清晰,并且能提高复用率。如果你使用RDS,需要使用RDS proxy来复用同一个数据库连接。 缺点 高延迟+双重冷(热)启动 受到lambda的并发限制。免费账号只有10个并发,如果你要多次读写数据库则速度会很慢 通过API gateway API gateway的最佳用途应该是用来写REST api,你可以通过API gateway调用lambda函数 如何配置 编写两个lambda,其中用于访问aws服务的lambda设置API gateway触发器(trigger),因而用于访问互联网的lambda可以通过发送http请求到该url而调用另一个lambda,进而访问aws服务。 设置API gateway触发器(trigger) 优缺点 优点 有免费额度 不用设置endpoint 可以使用http来调用,调用起来更加方便 由于解耦,程序逻辑更加清晰,并且能提高复用率。如果你使用RDS,需要使用RDS proxy来复用同一个数据库连接。 缺点 高延迟+双重冷(热)启动 受到lambda的并发限制。免费账号只有10个并发,如果你要多次读写数据库则速度会很慢 通过aws lambda api 和其他aws服务一样,lambda也有自己的api。其中就包括调用lambda函数的invoke方法。 如何配置 如果你使用python,详见invoke 优缺点 优点 api本身免费,运行的lambda有免费额度 由于解耦,程序逻辑更加清晰,并且能提高复用率。如果你使用RDS,需要使用RDS proxy来复用同一个数据库连接。 缺点 只能通过aws sdk使用,否则你要自行编写认证程序 高延迟+双重冷(热)启动 受到lambda的并发限制。免费账号只有10个并发,如果你要多次读写数据库则速度会很慢

2025/6/22
articleCard.readMore

甲骨文密钥ssh连不上且忘记登录密码解决方法

试过很多方法,搞了一个通宵才搞定 有试过进 bios 改 init=/bin/bash,结果卡在 random: crng init done 了 有试过连 VNC,结果发现要密码。这点甲骨文很坑,因为我一直都是用的密钥登录的,根本没有设置过密码,默认密码也没告诉过我。所以这都是血的教训,以后一定要改密码先 最后是开了一台新机然后把引导卷从主力鸡上分离出来,放到工具鸡里面重置密码。然后再通过 VNC 连接机子,这时候就可以输入刚刚设置的密码进入系统救小鸡了。 前期工作 正如前面说的,开了一台新机然后把引导卷从主力鸡上分离出来,放到工具鸡里面重置密码。(如果工具鸡超出免费额度可能要扣钱) IMPORTANT 开的工具鸡要和主力鸡的架构一样,系统也尽量一样 之后就是从主力鸡下面分离引导卷。其实也不难,就文字简单描述一下 打开主力鸡控制台,主力鸡关机,之后选择存储,点击右边三个点,选择分离 新建工具鸡,之后进工具鸡的存储,选择添加附加存储卷(不是引导卷) 之后开始 ssh 连接工具鸡 还有一点很重要的,就是要进去新版的控制台页面(一般没有改动的都是新版 ui),在更换系统那个 tag 下找到 cloud shell 连接 VNC(旁边是上传本地 rsa 公钥,cloud shell 其实就是自动帮你创建和上传),这个之后要用到。 重置密码 首先查看挂载的盘在哪。输入fdisk -l,看硬盘大小猜测哪个才是挂载的盘。 cd / && mkdir mnt-tmp 如果附加卷是 /dev/sdb1,就输入 mount /dev/sdb1 /mnt-tmp。这步是为了挂载附加卷 chroot /mnt-tmp,它能让你在主力机的文件系统里执行命令。 passwd root 或者 passwd ubuntu。反正重置你的有root权限的用户就是了 记住密码。 exit && umount /mnt-tmp 恢复主力鸡 从工具鸡里分离附加卷,在主力机里添加引导卷。工具鸡可以不用关机也能分离 主力机开机并且连接好 VNC INFO 不会开 VNC 的看前期工作第四点 进去 VNC 输入用户密码做该做的事情。 完了删除工具鸡,记得把引导卷也删了,不然要继续扣钱。

2025/6/22
articleCard.readMore

邓晓芒《黑格尔辩证法讲演录》读书笔记

邓晓芒的这本书只能利用碎片时间去看了,目前只读了一半,而且笔记也不知道会不会去写,,先挖坑 这本书其实是邓在武汉大学的课堂的录音记录,由他研究生整理转为文字的 前言 为什么要读黑格尔?其实没太多想法,就是想读。如果硬是要找一个原因,那就是黑格尔和马克思有联系吧,毕竟马克思也算是他的学生了。读马克思主义著作的时候(特别是绿色的那本通识课教课书和《矛盾论》),总是被“辩证法”搞得晕头转向,看过了很多人的解析,唯独没看过黑格尔自己对辩证法的阐述,最终也只是停留马克思那句“辩证法在对现存事物的肯定的理解中同时包含对现存事物的否定的理解,即对现存事物的必然灭亡的理解;辩证法对每一种既成的形式都是从不断的运动中,因而也是从它的暂时性方面去理解辩证法不崇拜任何东西,按其本质来说,它是批判的和革命的”。这句话,我是当作熵增原理来理解的,也就是说混乱度总是不断得增加的,事物不停地否定其自身,趋向无序。但是这个理解,现在想想又是有问题的,如果人类社会是趋于无序的,那么马克思所设想的共产主义社会,就是为了解决资本主义社会下“社会生产的无政府状态”啊,共产主义就是为了在社会生产上实现有序化(另一设想“人的自由全面发展”也许可以当作是一种无序化(和景观社会相反),但这并不是盲目的,而是自觉自为的无序化,这种“自觉自为”又可以理解为另一种有序化,也就是说每个人都“自觉自为”地追求着每个人自己的自由,从整体上看这也是一种有序化);而且把辩证法当作是熵增原理来看,这和恩格斯总结的辩证法的第三条规律“否定之否定”矛盾了,因为他的“否定之否定”是把人类历史看作是螺旋上升的,而不是螺旋下降的,很明显,人类社会是有目的地对外做功来减少熵增的,“生命以负熵为食”。所以辩证法就不能用单纯的熵增来看待了,熵增原理可以解释对外做功能够减少孤立系统的熵(当然对于地球来说仍然是熵增,而且增加速率会更加大),但是解释不了为什么要对外做功,即人类为什么会有目的,人类社会为什么会有目的。 对于黑格尔的兴趣,也来自一本关于Mega2(《马克思恩格斯全集》历史考证版第二版)的论文集,读前言的时候看到马克思的资本论和黑格尔的辩证法有很大的关系。其实在这之前,我就对教课书上普遍讲的“马克思对黑格尔的辩证法的颠倒”表示怀疑,如果只是对黑格尔的理论的简单颠倒,那马克思其实没什么原创水平,而且黑格尔作为辩证思维的创始人,应该是对自己的理论的反面有过反思的,是思考过的。虽然我对黑格尔的辩证法不熟悉,在阅读关于马克思的理论的论文时候,那些教授会说一句什么对黑格尔的颠倒,但是他却没有说明这是一种什么样的颠倒,读起来稀里糊涂的,被我用奥卡姆剃刀剃掉了。在读了邓的这本书的前面50%的情况下,我的直觉还是挺对的。 写到这里先烂尾了,,,

2024/10/1
articleCard.readMore

提升部署在cloudflare、vercel或netlify的网站在中国国内的访问速度和稳定性

前言 因为官方默认的cname解析出来的ip在国内访问的稳定性都很差,所以写了这个项目 IMPORTENT 本 post 更新不及时,请点击下方 GitHub repo 查看! 如何使用 先放repo,欢迎提交issue。 enhanced-FaaS-in-China https://github.com/xingpingcn/enhanced-FaaS-in-China 如果你的网站部署在cf,则把cname记录改为: cf-cname.xingpingcn.top 使用此dns解析建议:如果你的域名托管在cloudflare,那么使用这个cname很有可能会遇到403。建议把你的域名托管在非cloudflare平台,然后再在cf平台中删除你的站点,之后再使用。测速的时候一定要看下面的图。如果有些服务,例如cf worker,必须要把域名托管在cf,那么建议你使用cf的saas功能。 如果你的网站部署在vercel,则把cname记录改为: vercel-cname.xingpingcn.top 如果你的网站部署在netlify,则把cname记录改为: netlify-cname.xingpingcn.top 如果你的网站部署在netlify和vercel上,则把cname记录改为: verlify-cname.xingpingcn.top 使用此dns解析建议:先把cname记录改为官方提供的url,等ssl/tls证书生成之后再把cname记录改为verlify-cname.xingpingcn.top 怎么测速 可能存在的问题 浙江、福建、河南的个别isp访问可能会失败 目前似乎只有泉州被墙(官方的cname也是同样的问题,或许是isp限制导致的) 对于测速工具的选择,itdog.cn测出来的结果有点问题(会出现大片的红,原因未知),可以试试用boce.com、cesu.net之内的来测 测速结果 CF cf-22点 cf-22点-官方 cf-23点-官方 Vercel vercel中午-官方 vercel中午 vercel-23点晚高峰-官方 vercel-23点晚高峰 Netlify netlify中午-官方 netlify中午 netlify-23点晚高峰-官方 vercel-23点晚高峰 Q&A Q:和官方提供的cname有什么差别? A: 官方的cname有时在平均速度上是很快的,但是缺乏稳定性,会出现好几个省份都访问不了的情况,又或者个别省份相应时间非常长 而我的cname在平均速度上可能不是最快的,平均响应速度尽量维持在1秒内,最长的响应时间控制在2秒内,而返回非200状态码的省份尽量少于等于2个 Q:为什么分路线解析不准确? A:我使用的是权威DNS服务器自带的路线解析,可能存在误判。如果你想要更加精准的分路线解析,可以自行选取其他DNS服务器——如dnspod——并添加Netlify.json或Vercel.json里的IP到A记录。或使用NS1.COM作为权威DNS服务器,并设置根据ASN进行路线解析。你可以看看我写的ASN列表。 Q:为什么设置了你的CNAME解析后网站不能访问? A: 这大概率是使用了verlify-cname.xingpingcn.top导致的。需要先把CNAME记录改为官方提供的链接,等待SSL证书生成后再重新设置。这是由于该解析包含两个平台的IP,平台每次访问都会获得二者之一的IP,因而认为你在平台所填写的域名并不是你所拥有的。但是一旦生成证书后,证书就会缓存在平台上。 netlify支持上传自己的证书。如果还是不行就申请一个能自动续期的证书,写webhook,在证书更新的时候自动部署到netlify。 Q:为什么有的路线(如电信)的DNS A记录解析是官方提供的默认IP? A: 这是因为该路线的其他IP质量较差,所以暂时停止解析其路线,改用官方提供的默认IP。你可以通过同时将网站部署在vercel和netlify,把cname解析改为verlify-cname.xingpingcn.top,从而提高容错率。两个平台同一线路同时失效的概率要低许多。 Q:为什么json文件有的路线是一个空列表? A: 同上

2024/4/1
articleCard.readMore

在存在父子文件结构情况下使用python import

前言 网上的资料大多数都比较乱,包括stackoverflow也是,也就产生了这篇笔记。 文件结构和可能存在的引用链条 现在有这样一个文件夹 文件夹 1 2 3 4 5 6 7 8 9 root |____ a.py # 该文件作为演示的运行入口文件 |____ b.py |____ c.py |____ dir1 |____d.py |____e.py |____dir2 |____x.py IMPORTANT 我使用的是python3.11,该版本中不需要__init__.py也能把文件夹变成一个package。 如果你不能引入子文件夹,则直接在该文件夹中新建一个__init__.py,内容为空。 可能存在的引用链条有 a -> d -> b(引用父文件) python 1 2 3 4 # a.py import d # d.py import b a -> d -> x -> e(引用子文件后再引用其父文件) a -> b -> c a -> d -> x -> c 非运行入口文件和运行入口文件 IMPORTANT 一定要区分哪个是运行入口文件! 在python a.py中,a.py就是运行入口文件,其他的都不是。如果你cd dir1 & python e.py,那么a.py就不是运行入口文件了,e.py才是。一般而言运行入口文件使用绝对引入。 绝对引入和相对引入 import a就是绝对引入,from . import a就是相对引入。也就是说带.的就是相对引入。 a -> d -> b(引用父文件) python 1 2 3 4 5 # a.py from dir1 import d # d.py from .. import b #正确写法 import b 如果你这么写的话一定会报错的,Attempted relative import with no known parent package,不报错你也不会来看我的博客() 这里假设a.py是运行入口文件,正确的写法是直接import b,这是因为b.py和a.py同级,也就是说如果是要引入同运行入口文件同级的.py,则直接import就可以。 a -> d -> x -> e(引用子文件后再引用其父文件) 这个在d.py中就是正常的from .dir1 import x,但是需要注意的是,在x.py中需要使用from .. import e,这和上面那个引用父文件的方法不一样,所以说一定要注意哪个才是运行入口文件!! a -> d -> x -> c 这里也出现了a.py引用同级的c.py的情况,与x.py引用e.py不同,x.py引用c.py的时候直接import c就可以。 a -> b -> c 最后这个也是同级,import c就可以。 在运行入口文件中引用其父文件 不是不可以,其实没什么必要这么做,因为如果后续要继续改的话会频繁出错,例如如果存在另一个同级或非同级的文件,此文件要引用原来的运行入口文件,那么原运行入口文件所引用的文件很可能就引用失败。 所以我看有些库,例如requests,官方的asyncio都是只有一个层级,大家都是非运行入口文件,互相引用的时候都是用相对引入。 如果你真的要在运行入口文件中引用其父文件,那么这样写 dir1/d.py 1 2 3 4 import sys from os import path sys.path(path.dirname(path.dirname(path.abspath(__file__)))) import a

2024/3/11
articleCard.readMore

在python中运行bash实时输出结果(windows)

在windows的cmd中是不能运行bash的,我们需要利用git工具的bash来运行,但是用subprocess.run()会出问题,例如不能使用已经添加到环境变量的命令,如nvm、adb等;因此改用subprocess.Popen() 批量输入并且最后输出所有结果 bash_path用于定位你的git工具的bash,参数cwd=用于定位你的工作目录,和在文件夹中右键git bash here是一样的效果。 输入的命令可以带有空格,但是必须在最后加上\n example-1 1 2 3 4 5 6 7 8 9 10 11 12 13 import subprocess bash_path = r'F:\Program Files\Git\bin\bash.exe' subp = subprocess.Popen(bash_path,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding='utf8',cwd='$your_path') #输入的命令可以带有空格,但是必须在最后加上`\n` subp.stdin.write('nvm -v\n') subp.stdin.flush() subp.stdin.write('nvm -v\n') subp.stdin.flush() subp.stdin.write('nvm -v\n') subp.stdin.flush() #不要忘记了关闭subp,否则会阻塞 subp.stdin.close() print(subp.stdout.read()) output 1 2 3 1.1.11 1.1.11 1.1.11 实时输入并输出结果 需要用到多线程threading和队列queue来实时获取输出结果。最后也不要忘记调用子进程的close()方法。 example-2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import subprocess import queue import threading,time bash_path = r'F:\Program Files\Git\bin\bash.exe' def thread_for_listen(subp,q): for line in iter(subp.stdout.readline,''): q.put(line) subp = subprocess.Popen(bash_path,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding='utf8',cwd='./public') q = queue.Queue() p1 = threading.Thread(target =thread_for_listen,args=(subp,q)) p1.start() for i in range(5): subp.stdin.write('nvm -v\n') subp.stdin.flush() print(q.get(),end='') time.sleep(0.3) print('wake up after 0.3s') subp.stdin.close() q.task_done() output 1 2 3 4 5 6 7 8 9 10 1.1.11 wake up after 0.3s 1.1.11 wake up after 0.3s 1.1.11 wake up after 0.3s 1.1.11 wake up after 0.3s 1.1.11 wake up after 0.3s

2024/3/11
articleCard.readMore

使用freecdn-js提高hexo博客的cdn稳定性(接入透明模式)

由于cdn.jsdelivr.net在国内不太稳定,替代的jsd.cdn.zzko.cn稳定性稍好,但是也不是100%稳定,因而需要一个脚本实时切换到合适的CDN。freecdn-js能实现这个需求。freecdn-js是纯前端的,使用service worker,只需要插入一段js代码就可以,因此改造成本很低。但是我的文件(图片、js等)储存在GitHub图床,而freecdn-js本身需要被加速的文件的hash值,因此需要自己写脚本处理下载图片并计算。因为图片等文件的cdn链接是直接写在.md文件中的,所以写了一个正则脚本来提取cdn的链接。 脚本使用方法 cdn链接处理脚本 https://github.com/xingpingcn/picture-bed-using-freecdn 我写的脚本发布在GitHub上,匹配了![img](url)、{%link%}、{%image%}、headimg四个tag。脚本请到GitHub下载。 可以屏蔽相关cdn(更改host或用v2rayN路由屏蔽)测试freecdn-js是否能切换备用cdn。 扩展教程在这里:使用npm空间存放图片和html并利用cdn加速 需要的包版本 package version 1 2 3 urllib3 1.25.11 nodejs 16.10.0 freecdn 0.3.1 以下引用GitHub上的README.md文件 README.md https://github.com/xingpingcn/picture-bed-using-freecdn Windows的大坑! 此为大坑!务必阅读 如果利用Windows来写博客,那么提交git的时候会出现LF will be replaced by CRLF the next time Git touches it的提示,CR(回车)就是\r,LF(换行)就是\n,Windows平台默认换行符就是CRLF(\r\n),此变换会导致本地文件的hash和存放在npm或者git空间的文件的hash不一致;需要运行以下命令行: BASH 1 2 #提交检出均不转换 git config --global core.autocrlf false 适用于Windows系统,且只在Windows上开发的情况。在提交、检出时不会对CRLF/LF换行符进行转换 接入透明模式【可选】 建议暂时不配置 经过一段时间的观察,透明模式会起到严重的“减速”作用,FCP延后非常多。 本来想试试http2服务器一次性推送freecdn.js和相关的txt的,结果发现chrome从106版本就不支持http2服务器推送了。谷歌给出的替代方案是使用103 early hints,但是nginx现在还不支持。谷歌给出的另一个代替方案是传统的link rel=preload。link rel=preload确实可以在一次性推送freecdn.js和相关的txt,但是在安装了Service Worker之后依然会再次加载freecdn.js和相关的txt,结果就是速度没变,流量还浪费不少。又或者是我设置的问题,,, 配置透明模式 freecdn透明模式的优势和配置文件看下面的链接 freecdn透明模式 https://github.com/EtherDream/freecdn/tree/master/docs/transparent-mode 博客使用render.com托管静态资源;因为freecdn的透明模式仅仅提供了nginx配置,而且render刚刚好也支持docker,那就直接用nginx-docker吧。 render.com免费提供每月100g流量、750小时实例时间、500min构建时间、0.1cpu和512mRAM Render spins down a Free web service that goes 15 minutes without receiving inbound traffic. Render spins the service back up whenever it next receives a request to process.Learn more 首先在你的博客根目录下的source创建Dockerfile文件。(生成博客的时候会把source内的文件移动到将要被上传到repo的文件夹内) ./source/Dockerfile 1 2 3 4 5 FROM nginx COPY ./ /usr/share/nginx/html COPY ./freecdn-boot.conf /etc/nginx COPY ./nginx.conf /etc/nginx/nginx.conf EXPOSE 443 然后下载freecdn的两个配置文件,freecdn-boot.conf和nginx.conf,同样放在博客根目录,只需要改动nginx.conf。 ./source/nginx.conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 events { worker_connections 1024; } http { server { # freecdn nginx conf include freecdn-boot.conf; root /usr/share/nginx/html; expires 1h; default_type text/plain; include mime.types; # HTTPS conf listen 443; location /works { return 200 "it works"; } gzip on; gzip_static on; gzip_types text/plain text/xml text/javascript text/css application/x-javascript application/json application/xml application/xml+rss ; } } br和gzip压缩在render平台自动开启,见官网docs。 上传到GitHub reop(hexo d)后,在render.com创建一个web service,然后选择你的repo部署就可以了。 render.com 白嫖到底! 由于免费的render web service会在15分钟之内没有连接访问的情况下断开,并在下一次访问之后重启启动,而重新启动需要较长时间;因此用cf worker去定时访问网站。 需要一个cf账号,没有的先去注册 点击左侧的worker and page,创建一个worker,这个时候不能改动代码,先确认创建。之后点击触发器标签,并找到Cron 触发器,填入3/13 * * * *,这行代码表示在每个小时过3分钟之后触发一次定时器,然后每过13分钟再触发一次(如果和每个小时过3分钟这一条件冲突,则重置触发器,即在每个小时过3分钟之后再次触发,如此反复)。设置效果如下图所示 之后编辑worker。点击快速编辑,写入以下代码 ./worker.js 1 2 3 4 5 6 7 export default { async scheduled(event, env, ctx) { var res = await fetch('https://xxx.com/favicon.ico'); var data = res.json(); console.log(data); }, }; async scheduled表时当触发器触发时运行代码(题外话:这是不是可以当作一个免费的攻击服务器??),fetch代表访问你的网站的资源,await似乎是必需的,因为没有await的话在render的log里面看不到worker的访问记录。

2024/3/11
articleCard.readMore

免费通过NS1利用监控宝平台实现实时基于不同运营商的故障转移

本教程用到的资源全部都是免费且可持续使用的。NS1.com这个权威DNS服务器能根据ASN、国家或省份、DNS轮询(可加权)等方式解析域名,并且提供了API去控制某个解析(answer)是否响应。监控宝能实时监控网站(通过HTTP、PING、DNS方式等)并输出警告(webhook、Email、短信等),最高监控频率为2分钟。亚马逊的AWS Lambda是一个FaaS平台(serverless),可以作为连接NS1.com和监控宝之间的桥梁,当监控宝检测到网站速度变慢的时候发送信息到AWS Lambda,AWS Lambda得到信息后再传递给NS1.com,速度恢复的时候也是同样的操作。为什么要夹在一个AWS Lambda呢?这是因为监控宝发送的格式是固定的,并不能直接接入到NS1.com。 前言 需要用到的工具和技能有: 工具和技能 NS1.com。免费一个Filter Chain。Filter Chain就是根据不同条件进行响应的工具。 监控宝国际版。国际版可以用中国大陆和海外的手机号注册,同样可以用国内电信、移动、联通、教育网的监控节点。免费5个网站监控。 AWS Lambda。注册使用可能需要visa银行卡或其他银行卡验证。每月一百万次调用。 一点点耐心。 一点点点python技术。 NS1.com使用教程 Filter Chain的使用 NS1.COM官方文档|Filter Chain使用示例 https://help.ns1.com/hc/en-us/articles/360020683013 顾名思义就是不断地过滤不符合条件的answer,直到链(Chain)的结尾就是要返回给用户的解析结果。 因此每个过滤器的顺序十分重要(这一点官方文档写到比较隐晦,但是十分重要) 一般而言,以Up开头,Select First N结尾。前者代表是否开启该answer,我们使用监控包如果发现网站速度过慢则可以设置为Up: False;后者表示假如链(Chain)的结尾有多个answer,则返回前N个answer,默认N为1。可以通过调整Priority调整优先级。 这是我的设置 Filter Chain 建议勾选对应的复选框。因为每个人的设置不一样,请仔细阅读说明决定是否勾选! 之后我们要根据不同的运营商或者国家地区来返回DNS解析结果。因为NS1没有提供国内运营商的分类,但是提供了ASN来分类。我写了个爬虫小脚本,爬取不同运营商的ASN,使用以下这个项目获取,然后填入到对应区域。 中国大陆ASN https://github.com/xingpingcn/china-mainland-asn 我是创建了answer group来分类不同的运营商的。 answer设置 你也可以使用自动化工具来定时更新ASN。使用到的工具有aws lambda(下文有介绍)和aws cloud bridge的定时器(需自行配置),例如每隔10更新一次。 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import requests # key为你的ns1 feed label;value为下载asn列表用到的url的一部分,一般情况下不需要修改 asn_dict = { 'dianxin':'chinanet', 'yidong':'cmcc', 'liantong':'unicom' } ns1_api_key = '' source_id = '' ns1_req_url = f'https://api.nsone.net/v1/feed/{source_id}' headers = { "X-NSONE-Key":f"{ns1_api_key}" } for ns1_asn_label, gh_asn in asn_dict.items(): url_to_down = f'https://raw.githubusercontent.com/xingpingcn/china-mainland-asn/main/asn_txt/{gh_asn}.txt' response = requests.get(url_to_down).text asn_list_from_gh = response.split('\n')[1].split(',') data = { f"{ns1_asn_label}":{"asn":asn_list_from_gh} } res = requests.post(ns1_req_url,headers=headers,json=data) print(res.status_code) 之后可以选择country为CN的answer作为未命中规则的备选。之后再填写一个只有Up的answer作为除中国之外全球的DNS解析结果。 强烈建议 如果你使用render、railway、cf、cyclic、zeabur等托管你的网站,除中国之外全球的DNS解析结果是必须配置的,此设置用于ssl证书的申请。建议设置为加权的DNS轮询(此方法似乎对于netlify有点水土不服,因为只要DNS没解析到netlify就暂停ssl证书。其他的只要认证了网站就可以用一段时间,一般是3个月,下一个3个月会重新申请,认证一次不过会自动重试几次;成功一次就可以继续用3个月) 建议国内少用country,因为不太准 NS1 API的使用 设置DNS NS1.COM官方文档|NS1 data feed创建 https://help.ns1.com/hc/en-us/articles/360020474154-Create-a-data-feed 根据图的指引创建data source和data feed。详细看官方文档。 NS1 API的使用 可以看到上面的图,在answer里已经设置好了关联的data feed了(绿色箭头表示开启,红色表示关闭);先关联,之后我们会通过AWS Lambda来控制的。关联的data feed详细操作看官方文档。 NS1.COM官方文档|answer关联data feed https://help.ns1.com/hc/en-us/articles/360020471154-Automatic-failover answer关联data feed 编写feed更改请求-python NS1 API官方文档|修改data feed https://ns1.com/api?docId=2188 我们可以编写python以请求API来更改UP的状态。之后我们会把代码放到AWS Lambda来控制的。 注意填写必要的信息。 参数设置 status为True是开启,False是关闭。 source_id和label就是上面图中提到要记住的内容。 ns1_api_key需要自己到设置里申请。建议只开启必要的权限。 设置`KEY` 点击右上角的settings里的users&teams python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import requests status = True source_id = '' label='' ns1_api_key = '' url = f'https://api.nsone.net/v1/feed/{source_id}' headers = { "X-NSONE-Key":f"{ns1_api_key}" } data = { f"{label}":{"up":status} } res = requests.post(url,headers=headers,json=data) 使用AWS Lambda AWS Lambda支持python且可以通过各种条件来触发,现在我们用监控平台(本教程用的监控宝)的webhook来触发,发送POST请求到NS1来更新answer状态。 创建函数 点击创建函数——填写信息——点击高级设置 授权类型选NONE,勾选配置跨源资源共享(CORS) 监控宝官方文档|回调url实例 https://help.cloudwise.com/help/38/39/520 如果里选择使用监控宝,那么填入以下代码 ↓ 参数设置 url_token填写监控宝里回调url里的回调token。如果没有监控宝还没有设置,不要紧回来再弄。 其他参数请看这里 其中status会根据监控宝的状态自动设置。 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import requests import base64 import hashlib import json source_id = '' label='' status = True ns1_api_key = '' url_token = '' #回调token def g_md5(content): md5hash = hashlib.md5(content) md5 = md5hash.hexdigest() return md5 def lambda_handler(event, context): json_data = json.loads(event['body']) verify = str(json_data['msg_id'])+str(json_data['task_id'])+str(json_data['fault_time'])+url_token md5 = g_md5(verify.encode('utf-8')) if md5==json_data['token']: if json_data['message_status'] == 1 or json_data['message_status'] == '1': status = False elif json_data['message_status'] == 2 or json_data['message_status'] == '2': status = True url = f'https://api.nsone.net/v1/feed/{source_id}' headers = { "X-NSONE-Key":f"{ns1_api_key}" } data = { f"{label}":{"up":status} } res = requests.post(url,headers=headers,json=data) print(res.text,f'[status] \'up\': {status}') 这里不得不吐槽一句监控宝,回调url设置中的测试发送的json和实际应用中发送的json不一样的,如果发现测试报错请使用正常监控方式来测试 记得点击deploy! 设置层(layers) 因为AWS Lambda默认不能使用第三方库,因为用到了requests库,所以要自己上传requests库。或者你也可以自己用python原生库重写。 AWS官方文档|为依赖项创建Python层 https://docs.aws.amazon.com/zh_cn/lambda/latest/dg/python-package.html#python-package-dependencies-layers requests.zip可以根据官方文档自己生成,也可以上传我制作的requests.zip 下载|下载-GitHub|下载-备用 之后设置函数的层(layers),选择我们上传的requests.zip包。 使用监控平台 类似的平台还有观测云,免费版最高30分钟的检测频率,20万次访问每天好像是,节点11个,3网都有。 或者可以破解一些免费测速网站的js。 warning 监控宝似乎在14天试用期之后直接封我号了,发两份邮件也不回,建议改用观测云,配置都是差不多的。 监控宝 点击查看,但是不建议 监控宝可以使用回调url(webhook)来传递信息,设置如下图。 回调url就填写AWS Lambda提供的url AWS Lambda 回调url 之后创建监控任务,记得在Webhook通知那里选择你的回调url。 监控宝官方文档|回调url实例 https://help.cloudwise.com/help/38/39/520 观测云 aws lambda填入以下代码 python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import json import requests source_id = '' ns1_api_key = '' def lambda_handler(event, context): # print(event,type(event)) json_data = json.loads(event['body']) if json_data['isp'] == 'telecom': label = 'dianxin' # ns1的feed label,下同 elif json_data['isp'] == 'unicom': label = 'liantong' elif json_data['isp'] == 'cmcc': label = 'yidong' if json_data['df_status'] == 'critical': status = False else: status = True url = f'https://api.nsone.net/v1/feed/{source_id}' headers = { "X-NSONE-Key":f"{ns1_api_key}" } data = { f"{label}":{"up":status} } res = requests.post(url,headers=headers,json=data) print(res.text,f'[status] {label} -> \'up\': {status}') 观测云平台配置 观测云平台配置 观测云平台配置

2024/3/11
articleCard.readMore

国内各个as自治系统[转]

国内至国际骨干 ISP 线路整理 电信的163骨干网自治系统编号 AS4134;电信的CN2骨干网自治系统编号 AS4809 联通的169骨干网自治系统编号 AS4837;联通的A网骨干网自治系统编号 AS9929 移动的CMNET境内骨干网自治系统编号 AS9808;移动的CMI境外骨干网自治系统编号 AS58453 CERNET骨干网自治系统编号 AS4538;CSTNET骨干网自治系统编号 AS7497

2024/3/11
articleCard.readMore

尝试在闲置的surface pro 4上运行安卓应用

目前的结论是能在使用触屏的同时运行安卓应用,也仅仅是能用。 目前尝试过几种方案 fydo os blissos Ubuntu+anbox fydo os 我只使用过免费版,目前体验下来是最流畅的,也是最不需要折腾的,但是目前免费版没触屏。遗憾 blissos 装上之后触屏时有时无,而在有的时候只是拙劣的鼠标点击模拟,基本的多指操作和滑动功能都没有,流畅度还不如fydo os,出的这个surface专版感觉就是纯粹让ppt好看些。 Ubuntu+anbox 最后只能尝试在Linux上运行安卓了。 我装的是LTS 22,安装好系统后还得找hy2能用的客户端(因为要去GitHub下资源),一番折腾后找到了nekoray这个带GUI的客户端(因为这个时候sing-box,clashmeta还有hy2官方都没有Linux GUI,而且路由配置还非常麻烦,没现成的作业可以抄),而nekoray后端用的就是sing-box,可惜nekoray自带广告。 之后刷入Surface Linux Kernel,触屏是有了,也仅仅是能用的程度,不太跟手,和win下的体验差太多。 之后安装anbox,一开始闪退,最后发现不是配置有问题,而是不支持5.17以上内核,安装Surface Linux Kernel的时候已经默认安装目前最新的6.6版本了,理论上降级是能用的,但是不知道修改过的Surface Linux Kernel能不能用,我也懒得再降级了。马上花10分钟打开PE滚回去windows。

2024/3/11
articleCard.readMore

npm图床(不需要本地部署)

本篇意在建立一个上传到GitHub repo自动发布package到npm空间的npm图床 前言 本篇为picture-bed-using-freecdn脚本的教程之一。脚本意在提高静态博客的cdn稳定性。 picture-bed-using-freecdn https://github.com/xingpingcn/picture-bed-use-freecdn 脚本的另一篇使用教程在这里 [使用freecdn-js提高hexo博客的cdn稳定性] 建立用于储存图片等静态资源的npm图床 可以放置js、css、图片(最好带上hash)等不经常变动的资源。 准备工作 准备工作网上有很多教程,这里不重复造轮子。请搜索“npm图床” 需要: npm账号,创建一个token; GitHub账号:创建一个repo,并在repo的setting创建一个名为NPM_TOKEN的secrets,值为上面的token。 添加NPM_TOKEN 创建package.json 该文件指定了要上传的图床的名字和图床版本(不需要事先在npm空间创建一个空的package);其中名字不能和现有的package重复,所以写的尽量长。 package.json 1 2 3 4 5 6 { "name": "", "version": "1.0.0", "description": "DO STUFF", "author": "XDF" } 看好名称写就行,version尽量和我一样就行。 创建GitHub action GitHub action可以在你把文件push或者release到repo时自动执行自定义命令,这里我们让他自动把我们push的图片发布到npm空间,使资源能通过npm cdn访问。 在reop的上方点击Action,然后点击new workflow,之后点击set up a workflow yourself ,名字随便(我这里是npm-publish.yml),之后填入以下信息: npm-publish.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 name: npm-publish on: push: branches: - master permissions: contents: write jobs: publish-npm: runs-on: ubuntu-latest # Clone 仓库 steps: - name: Checkout uses: actions/checkout@v4 with: ref: master # 安装 Node.js - name: Setup Node uses: actions/setup-node@v4 with: node-version: "20.x" registry-url: https://registry.npmjs.org/ # 发布 NPM 包 - name: Publish Package run: | git config --global user.email "email@email.com" git config --global user.name "user_name" npm version patch npm publish env: NODE_AUTH_TOKEN: $ - name: Push run: | git push 其中的master要换成你branch(分支)的名字。NPM_TOKEN就是最开始在secrets填写的token,因此名字要对应上。email和user_name可以随便写。 上传图片 使用图床工具或者手动上传到GitHub repo就能自动发布到npm空间,可以看到npm包的版本version变化了(npm不支持覆盖发布,所以版本一定会变化),同时.json文件里面的版本也变化了,这得益于GitHub action。 这里推荐一个图床工具吧,只用于GitHub的,比较轻量,使用浏览器就行。 PicX图床工具官方文档 https://picx-docs.xpoet.cn 使用图片 提供几个国内能用的npm cdn npm cdn 1 2 3 4 https://npm.onmicrosoft.cn/, https://jsd.onmicrosoft.cn/npm/, https://cdn.jsdelivr.net/npm/, https://unpkg.com/ 使用格式为: npm cdn 1 https://{cdn}/{npm_name}@{version}/path/to/resource.ext 例如 npm cdn 1 2 https://unpkg.com/html-hosting-for-xp@1.0.1/%E5%9C%A8python%E4%B8%AD%E8%BF%90%E8%A1%8Cbash%EF%BC%88windows%EF%BC%89.html https://jsd.onmicrosoft.cn/npm/p-hosting-for-xp@1.0.15/20230525/logo%20(2).ln5ua8psy9s.webp freecdn-js可以把资源的响应头中的mime改成text/html(而不是原来的text/plain),从而能够让浏览器渲染网页。我写的脚本支持自动把用于写作博客.md文件转换为对应的html cdn列表。见前言 建立用于储存html静态资源的npm图床 同样图床可以储存html文件。我是在本地编译好博客然后发布到GitHub repo的,因而在push之后依然可以在action中把html发布到npm空间。 package.json 1 2 3 4 5 6 7 8 9 { "name": "", "version": "1.0.0", "description": "DO STUFF", "author": "XDF" "files": [ "*.html" ] } 这里的package.json多了一个files的key,表示只发布html文件到npm空间。files是一个列表(array),和.gitignore文件的写作规则一样。 这里的action中的.yml文件和储存图片的repo的.yml一样,但是要删去npm version patch这行。 npm version patch的作用是更新version,在本地发布html之前(hexo d),在命令行输入npm version patch就能更新本地的package.json中的version(换而言之,在更新version之前,本地的package.json和.yml内容和目录要和GitHub repo的一致,然后push更新了version之后的.json之后,让action自动部署,发布html到npm空间) 如果用我的命令行上传博客会多次push本地文件,但是只在push html之前会更新version,那么之后的push会因为没有更新version而action部署失败,但是事实上没有什么影响 脚本的使用 脚本链接见前言。如果你要使用npm空间,要在config.py中写上你的npm包名,用于查询最新的version。 同样需要注意替换你的branch bash 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 f: cd f:/blog #博客根目录 hexo clean && hexo g cd f:/blog/package_json #储存package.json和.yml的文件夹(注意.yml路径!!) npm version patch cd f:/blog gulp # 上传之前确保./public存在package.json和.yml(注意.yml路径!!) xcopy .\package_json .\public /e/h hexo d cd f:/blog/.deploy_git python ../import_to_db_with_hexo_blog.py python ../import_to_db_with_urls_txt.py freecdn find --save freecdn manifest --merge ../pic.conf freecdn manifest --merge ../custom.conf -o manifest-full.txt #用于生成外置的freecdn-manifest.txt freecdn js --make --cdn "https://jsd.cdn.zzko.cn/gh/user/repo@main/freecdn-internal/ver/freecdn-main.min.js unpkg jsdelivr elemecdn " #此命令为配置cdn链接用于加速.min.js文件,详细请查看freecdn项目的GitHub git add --all git commit -m "update" git push origin main #如果需要添加origin地址,请自行添加。 python ../generate_external_manifest_file.py git add --all git commit -m "update" git push origin main #如果“is_refresh_tag”为 “True”需要上传多次 python ../refresh_cdn_cache.py #可能没用

2024/3/11
articleCard.readMore

docker学习笔记

这是一篇通过配置hysteria2学习docker-compose的笔记 前言 用官方的docker和配置3分钟就搭好了,但是想试试通过bridge和通过nginx反代来实现(最后没有实验),于是就开始了折腾,,, docker的network模式 docker会隔离文件、网络、进程,而网络的隔离程度分为4种: host 这个相当于和主机共用一个网络 none 容器不需要内部和外部网络 container 似乎是容器内的网络,和主机分离。 bridge 命令docker network create的默认模式,连接到该网络的容器可以互相连通,而且可以暴露端口给主机和主机通讯。客户端通过主机ip:port访问。 NOTE docker默认创建除container的三个网络。可以通过docker network ls查看。 bash 1 2 3 4 5 6 root@:/bin/hy2# docker network ls NETWORK ID NAME DRIVER SCOPE c069db7ead85 bridge bridge local cf668a8174a8 host host local 162c8b1b3229 nginx-proxy bridge local # `nginx-proxy`是我自己创建的。 4f9ce671d49a none null local NOTE 值得注意的是,docker默认创建一个名为docker0的网口用于连接主机和容器。通过ip link查看 进入hy2容器执行ip link命令可以看到,hy2的网卡(eth0)是和主机上的veth6f76815虚拟网卡连接(240:241) bash 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 root@445:/bin/hy2# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether [隐私删除] brd ff:ff:ff:ff:ff:ff altname enp0s3 altname ens3 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default link/ether 02:42:4e:38:4d:51 brd ff:ff:ff:ff:ff:ff 12: br-162c8b1b3229: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default link/ether 02:42:93:b0:6a:4a brd ff:ff:ff:ff:ff:ff 223: veth3452fbb@if222: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-162c8b1b3229 state UP mode DEFAULT group default link/ether d2:85:53:63:a1:76 brd ff:ff:ff:ff:ff:ff link-netnsid 0 241: veth6f76815@if240: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-162c8b1b3229 state UP mode DEFAULT group default link/ether aa:e0:71:cf:9e:50 brd ff:ff:ff:ff:ff:ff link-netnsid 1 root@445:/bin/hy2# docker exec -it hy2 /bin/bash 1cb800f27bd1:/# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 240: eth0@if241: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:14:00:03 brd ff:ff:ff:ff:ff:ff 1cb800f27bd1:/# 配置hy2的yaml 官方的yaml是使用的host模式,我现在要创建一个名为nginx-proxy的网络并且在配置文件中更改。 yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 version: "3.9" services: hysteria: image: tobyxdd/hysteria container_name: hy2 restart: always volumes: - acme:/acme - ./hysteria.yaml:/etc/hysteria.yaml command: ["server", "-c", "/etc/hysteria.yaml"] networks: - nginx-proxy ports: - "10808:443" # expose: # - "443" networks: nginx-proxy: external: true volumes: acme: 这样我以为就可以通过访问10808端口科学上网了。但是ping不通,,, 经过努力的排查,找到了docker inspect命令,发现容器被分配的IP是空的,,, 原来还需要手动通过输入docker network connect来连接,,,我看nginx是自动连接的,不知道对应的yaml怎么写。 结果还是是ping不通,,, 用iptables -t nat -nvL --line-number查看发现,Chain DOCKER里也有容器IP的DNAT了,为什么还是不行。 不细心眼力不好还发现不了,是暴露端口的时候默认暴露tcp,,,。结合hy2文档也知道hy2是基于udp的,然后更改配置 yml 1 2 3 4 5 services: hysteria: ports: - "10808:443/udp" ... 成功! 但是关闭连接的时候就会出错再也连不上,通过日志发现,原来关闭的时候通过tcp沟通的。 最终的配置文档应该像这样的 yml 1 2 3 4 5 6 services: hysteria: ports: - "10808:443/udp" - "10808:443/tcp" ... 最后删除多余的NAT,和设置新的NAT,并备份iptables warning iptables-save -f /etc/iptables/rules.v4适用于Debian,其他系统可能会恢复不了iptables bash 1 2 3 4 iptables -t nat -D PREROUTING 1 iptables -t nat -A PREROUTING -i eth0 -p udp --dport 20000:50000 -j DNAT --to-destination :10808 iptables-save -f /etc/iptables/rules.v4 systemctl restart iptables warning 如果使用ufw,则修改以下文件。重启ufw的时候不会删除iptables已经有的规则,也就是说重复重启ufw会添加多条相同的规则,需要手动删除。 /etc/ufw/sysctl.conf 1 net/ipv4/ip_forward=1 warning 注意!必须在前一个filter block最后,即COMMIT之后添加! 最后只放行那个要转发的端口! 例如ufw allow 12345,而不是ufw allow 20000-50000 /etc/ufw/before.rules 1 2 3 4 5 6 7 8 9 10 # 注意!必须在前一个filter block最后,即COMMIT之后添加! # don't delete the 'COMMIT' line or these rules won't be processed COMMIT # Custom *nat :PREROUTING ACCEPT [0:0] -A PREROUTING -i eth0 -p udp --dport 10000:30000 -j DNAT --to-destination :3456 COMMIT 最后放上配置 yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 listen: :10808 #acme: #domains: # - xxx #把xxx.com改成你的域名,需要先解析到服务器ip #email: @gmail.com #可以改成自己邮箱,也可以把test这里随便加几个字符 tls: cert: /etc/cert/domain.com.cert.pem key: /etc/cert/domain.com.key.pem auth: type: password password: #设置密码 masquerade: type: proxy proxy: url: https://bing.com #伪装网址 rewriteHost: true quic: initStreamReceiveWindow: 26843545 maxStreamReceiveWindow: 26843545 initConnReceiveWindow: 67108864 maxConnReceiveWindow: 67108864 nginx初次使用 由于nginx运行在docker内,而每个docker都会被network的虚拟网关分配一个ip,如果nginx要反代同一network内的docker container是不是就要预先知道它的ip呢?这样做其实也可以,但是如果机器重启就会出问题,因为重启后每个容器的ip会被重新分配,分配的规则我猜测是根据启动顺序来决定的。更优雅的方式是直接使用container的别名作为ip。 例如在同一网络内有两个container,别名分别为nginx_test和api,则nginx_test的反代配置应该是类似于这样的。 .conf 1 2 3 4 5 6 7 server { listen 80; server_name localhost; location /api { proxy_pass http://api:3000; } } 以上情况只是适用于nginx通过docker部署的情况。而我用的是直接安装在主机的方式,反代的容器需要暴露端口到localhost。 yml 1 2 3 4 5 6 services: hysteria: ports: - "127.0.0.1:3000:443/udp" - "127.0.0.1:3000:443/tcp" ... 这样子,使用ip:10808就不能访问了,必须在nginx那里反代proxy_pass http://127.0.0.1:3000;通过ip:443访问 WARNING hy2 并不支持和 nginx 共享 443 端口,所以需要自己用 acme 申请证书,然后在 hy2 的配置中填写 tls nginx安装和证书自动申请 意外地发现需要结合多个教程才能搞定,记录一下备忘 有两种方法,一种是acme.sh,一种是Certbot,后者更加方便,但是过程中做了什么我不知道,前者需要手动的地方更多,但是你会知道证书放在了哪里。 可以先设置软连接。注意路径,第一个为默认的nginx配置路径,第二个为你要软连接的路径。 bash 1 ln -s /etc/nginx/nginx.conf /home/nginx/nginx.conf acme.sh 先在conf中写好域名,acme.sh会根据配置帮你申请域名 conf 1 2 3 4 server { server_name domain.com; listen 80; } 安装acme.sh后,重新打开一个终端,输入以下命令;需要域名先指向你的vps bash 1 acme.sh --issue -d domain.com --nginx /home/nginx/nginx.conf 这里有个可以不用nginx的方法,如果使用的是华为云,可以运行以下命令。原理就是利用api自动添加txt记录。如果需要更多支持的dns请点击这里,基本上包含了主流dns服务器了。 bash 1 2 3 4 export HUAWEICLOUD_Username="" export HUAWEICLOUD_Password="" export HUAWEICLOUD_DomainName="" # 注意的是这个的中文名为账户名而不是域名,需要你去设置里面查看 acme.sh --issue --dns dns_huaweicloud -d example.com -d *.example.com #填写你的域名 最后运行以下命令。快到期会自动续。注意路径。 bash 1 2 3 4 acme.sh --install-cert -d domain.com \ --key-file /home/nginx/cert/domain.com.key.pem \ --fullchain-file /home/nginx/cert/domain.com.cert.pem \ --reloadcmd "nginx -s reload" 第一个命令是申请证书,证书会放在acme.sh自己脚本所在的目录,所以后面要使用--install-cert安装。这个并不会修改conf,所以要手动配置。 再打开conf,填写443端口,之后就会在过期前30天自动更新 conf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 server{ listen 443 ssl; server_name domain.com; location /{ client_max_body_size 64m; proxy_http_version 1.1; proxy_pass http://localhost:8080; # 请根据实际情况修改你的端口 proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_cache_bypass $http_upgrade; proxy_set_header Accept-Encoding gzip; proxy_read_timeout 360s; # GPT-4 需要较长的超时时间,请自行调整 } ssl_certificate /home/nginx/cert/domain.com.cert.pem; ssl_certificate_key /home/nginx/cert/domain.com.key.pem; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; access_log /home/nginx/log/domain.com.access.log; error_log /home/nginx/log/domain.com.error.log; } Certbot bash 1 2 sudo snap install --classic certbot sudo ln -s /snap/bin/certbot /usr/bin/certbott 之后conf中填写好443端口 使用 certbot 获取 SSL 证书:sudo certbot --nginx sudo vim ./push查看更改。重启nginx 重启nginx 有两个,前者确定不会重启nginx,后者应该会。 bash 1 2 nginx -s reload service nginx restart 容器更新 bash 1 2 3 docker-compose pull docker-compose up -d --remove-orphans # 重启 docker image prune # 删除旧的

2024/3/11
articleCard.readMore