博客

  • 谷歌邮箱恢复

    本次恢复了Gmail,还有Google的域名邮箱。今天就分享这两件事情的解决方案吧。

    感受

    很早以前注册的gmail邮箱,绑定了不少业务,之前是转发到QQ邮箱,也就一直这么用着,也很少直接登陆gmail。毕竟登陆起来也麻烦。最近发现收不到邮件,着实有些难受。

    Gmail

    从历史记录来看,已经多次被“删除”了。这次登陆,继续点击申请恢复,等2天的样子,又能使用了。Gmail账号的恢复还是比较顺利,登陆提示申请,就点一下,填写一下申请原因,我写的是会给工作与生活造成困扰。绑了不少业务,着实不能随便被删除。被删除存在巨大的安全问题,万一被别人重新注册使用了,真不能想像会造成多大的问题。

    Google的域名邮箱

    现象

    ”’
    您的登录设置不符合贵组织的两步验证政策。
    请与您的管理员联系,以了解详情。
    ”’

    解决

    1. 发起一个Workspace 邮箱工单请求Google Admin Toolbox
    2. 等2个小时
    3. 收到邮件
    Hello,
    
    Your request to extend the 2-Step Verification(2SV) enforcement date has been processed. We have extended the enforcement date for the account associated with domain zhongdaiqi.com by 60 days. Please ensure that 2SV is enabled for all admins in your account within this period to avoid being locked out of the account.
    
    Please note that after the enforcement date, if any of the admins do not have 2SV enabled, they will be locked out of their account and will need to contact another admin or support to regain access to the account.
    
    Best regards,
    
    Google Workspace Support
    1. 重新配置域名解析
    • 把域名解析删除,重新配置。我还加了一个别名yue.ma
    • 现在不仅要配置mx记录,还要配置SPF、DKIM
    • 之前mx记录要配置5条,现在只要配置一条
    • 所有记录的主机头都配置成空的,我使用dnspod解析是@代表空主机头
  • NewbeeMD WordPress集成ByteMD编辑器

    https://github.com/zhongdaiqi/newbeemd

    插件newbeemd

    让wordpress集成ByteMD编辑器,感觉wordpress官方的编辑器用不习惯,还是这种markdown的好用。

    安装

    到项目地址下载插件包,在wordpress后台安装

    后续

    插件取名为NewbeeMD,已经按流程提交,等wordpress团队审核

    未通过审核之前,可以直接下载安装包,自助在wordpress后台安装插件

  • ModelScope魔塔免费Token

    每天会自动补充Token,可以选择的模型非常多

    https://www.modelscope.cn/register?inviteCode=freetoken2208&invitorName=AIDever

    魔塔的优势在于长期免费,模型选择多

    from openai import OpenAI
    
    client = OpenAI(
        base_url='https://api-inference.modelscope.cn/v1',
        api_key='密钥', # ModelScope Token
    )
    
    response = client.chat.completions.create(
        model='ZhipuAI/GLM-5.3:Zhipu-Coding', # ModelScope Model-Id, required
        messages=[{
            'role':
                'user',
            'content': [{
                'type': 'text',
                'text': '描述这幅图',
            }, {
                'type': 'image_url',
                'image_url': {
                    'url':
                        'https://modelscope.oss-cn-beijing.aliyuncs.com/demo/images/audrey_hepburn.jpg',
                },
            }],
        }],
        stream=True
    )
    
    done_reasoning = False
    for chunk in response:
        if chunk.choices:
            reasoning_chunk = chunk.choices[0].delta.reasoning_content
            answer_chunk = chunk.choices[0].delta.content
            if reasoning_chunk != '':
                print(reasoning_chunk, end='', flush=True)
            elif answer_chunk != '':
                if not done_reasoning:
                    print('\n\n === Final Answer ===\n')
                    done_reasoning = True
                print(answer_chunk, end='', flush=True)
  • chnroute-linux — 中国大陆 IP 段每日自动更新 + 「仅允许国内访问」落地

    https://github.com/zhongdaiqi/ipfire

    chnroute-linux — 中国大陆 IP 段每日自动更新 + 「仅允许国内访问」落地

    在 Linux 上每天自动拉取中国大陆(CN)IPv4/IPv6 地址段,清洗聚合后原子写入内核,
    配合入站白名单实现「仅允许国内 IP 访问」;同时可导出 ipset / nftables / RouterOS 三种格式,
    用于多 WAN 出口策略路由(PBR)与国内外分流。

    本方案是 chnroute 思路的工程化落地版:chnroute 源自 Linux 社区,本质是
    「中国大陆 CIDR 数据库」,用于在无 BGP 能力的边缘设备上实现近似 BGP 的按目标选路。


    一、实测结果(2026-09-30,国内家宽)

    APNIC 官方源         v4=8792 段  v6=2043 段      约 300 秒(国际出口慢)
    chnroutes2 聚合源    v4=3898 段                  1.7 秒
    china-operator-ip    v4=6207 段                  1.7 秒
    china-operator-ip6   v6=3414 段                  1.7 秒
    ...
    ─────────────────────────────────────────────────────────
    聚合结果             IPv4  5714 段 / 346,035,968 地址(约 3.46 亿,与 CNNIC 统计吻合)
                         IPv6  2247 段
    ISP 分组             电信 2843 段 / 移动 1003 段 / 联通 1733 段 / 教育网 85 段

    两个模式:

    模式 命令 耗时 说明
    全量(默认) --sources all ~300s APNIC 官方 + 聚合源,最权威
    快速 --sources aggregate ~74s 只用 jsdelivr 镜像聚合源,国内网络推荐

    GitHub 源可达性实测(这决定脚本必须做镜像回退):

    镜像 结果
    cdn.jsdelivr.net ✅ 96 KB / 1.7 s
    ghproxy.net ✅ 96 KB / 2.0 s
    raw.githubusercontent.com ❌ 超时(国内直连不通)
    raw.gitmirror.com ❌ DNS 解析失败

    二、文件清单

    文件 作用
    update_chnroute.py 主脚本:抓取 → 清洗 → 聚合 → 多格式导出 → 原子写入内核
    apply-whitelist.sh 启用「仅允许国内访问」入站白名单,自带防自锁自动回滚
    install.sh 一键部署(装文件、建目录、注册定时任务、首次运行)
    chnroute-update.service / .timer systemd 每日定时更新单元
    README.md 本文档

    三、快速开始

    # 0) 依赖(Debian/Ubuntu 示例)
    sudo apt update && sudo apt install -y python3 ipset iptables
    
    # 1) 一键安装(同时立即跑一次,只生成数据、不动内核)
    sudo ./install.sh --with-timer
    
    # 2) 确认数据合理(应为 4000~8000 段、覆盖 3.4 亿+ 地址)
    head -5 /var/lib/chnroute/chnroute-v4.txt
    cat /var/lib/chnroute/state.json
    
    # 3) 原子写入内核 ipset(可反复执行,更新过程不断流)
    sudo /usr/local/bin/update_chnroute.py --outdir /var/lib/chnroute --apply
    
    # 4) 启用「仅允许国内访问」
    echo "你的公网出口IP" | sudo tee -a /etc/chnroute/whitelist.txt
    sudo /usr/local/sbin/apply-whitelist.sh          # 应用,300 秒后自动回滚
    #   ↑ 立刻另开一个终端验证 SSH 是否还通
    sudo /usr/local/sbin/apply-whitelist.sh --commit # 确认无误,取消回滚,永久生效

    四、三个真正重要的工程细节

    1. 白名单不会把你锁在门外(防自锁三重保险)

    白名单一旦生效,境外 IP(包括你此刻的 SSH 跳板)会立刻被拒。所以 apply-whitelist.sh:

    1. 自动豁免:回环、内网(10/8、172.16/12、192.168/16)、本机全部公网 IP、
      当前所有已建立 TCP 会话的对端(也就是你正在用的那条 SSH 连接)、
      /etc/chnroute/whitelist.txt 自定义列表 —— 全部自动进豁免集合;
    2. 自动回滚:生效后立刻调度一个 300 秒的定时回滚(优先 systemd-run,退化到 at,再退化到后台进程)。
      规则就算写错,最多断 300 秒,机器会自己恢复;
    3. 显式提交:你在窗口期内确认 SSH 正常,执行 --commit 取消回滚,策略才永久生效。

    2. 数据更新是原子的,不丢包不乱序

    用「影子集合 + swap」,而不是「删除重建」:

    ipset create cn4-tmp ...   ←  灌入新数据到影子集合(线上集合仍在正常工作)
    ipset restore -exist < chnroute-ipset.v4   (集合名改写为 cn4-tmp)
    ipset swap cn4-tmp cn4     ←  内核里一次指针交换,瞬时生效,零空窗
    ipset destroy cn4-tmp

    如果新数据抓取失败或校验不过,cn4 保持原样 —— 白名单永远不会变成空集合。

    3. 完整性守卫:防止数据源异常导致白名单塌陷

    白名单塌陷 = 灾难(所有国内用户被拒之门外)。所以每次落地前强制校验:

    • 绝对下限:IPv4 ≥ 2000 段、≥ 1 亿地址(实测约 5714 段 / 3.46 亿)
    • 绝对上限:IPv4 ≤ 15 亿地址(超过说明把非 CN 网段并进来了)
    • 相对变化:较上次条目数/IP 数骤降超 20% 直接拒绝;骤增 3 倍以上也拒绝
    • 命中即退出码 2,文件与内核都不改动,保留上一次的可用数据
    • 确认数据源无误时用 --force 跳过

    五、脚本能力速查

    # 常用
    python3 update_chnroute.py --outdir /var/lib/chnroute            # 只生成数据
    python3 update_chnroute.py --sources aggregate --apply           # 快速模式 + 写内核
    python3 update_chnroute.py --isp --ros-pbr --format all --apply  # 全格式 + ISP 分组 + ROS PBR 模板
    python3 update_chnroute.py --backend nft --nft-table 'inet filter' --apply
    python3 update_chnroute.py --dry-run --apply                     # 只演示不落地
    python3 update_chnroute.py --log-file /var/log/chnroute/update.log
    参数 说明
    --sources all\|apnic\|aggregate 数据源组合,默认 all
    --isp 追加电信/移动/联通/教育网/科技网/鹏博士分组
    --format txt,ipset,nft,ros 输出格式,all 表示全部
    --set-prefix cn ipset 集合前缀 → cn4 / cn6
    --ros-list CN / --ros-pbr RouterOS list 名 / 生成 PBR 模板
    --apply / --backend 原子写入内核 / 选 ipset 或 nft
    --force 跳过完整性守卫(危险)
    --quiet / --log-file 静默 / UTF-8 日志落盘

    输出文件(--format all):

    chnroute-v4.txt / chnroute-v6.txt     纯 CIDR(带元信息头),通用格式
    chnroute-ipset.v4 / .v6               ipset restore 格式(原子 swap 用)
    chnroute.nft                          nftables set 定义(nft -f 单事务加载)
    chnroute-ros.rsc                      RouterOS address-list 批量导入脚本
    chnroute-ros-pbr.rsc                  RouterOS 策略路由模板(国内直连 / 境外分流)
    chnroute-diff.txt                     与上次更新的差异(新增/移除各 200 条)
    state.json                            本次摘要:段数、地址数、各源状态
    cn-chinanet.txt / cn-cmcc.txt / ...   ISP 分组(--isp 时生成)

    六、三种落地方式

    A) ipset + iptables(推荐,兼容性最好)

    sudo update_chnroute.py --outdir /var/lib/chnroute --format all --apply
    sudo apply-whitelist.sh --commit
    sudo apply-whitelist.sh --status     # 查看链与集合
    sudo apply-whitelist.sh --rollback   # 随时撤销

    生成的 IPv4 链结构(IPv6 同理走 ip6tables):

    CHNROUTE-IN:
      1. -m conntrack --ctstate ESTABLISHED,RELATED  -j ACCEPT   ← 放行已建立连接(响应包)
      2. -i lo                                        -j ACCEPT   ← 回环
      3. -m set --match-set chnroute-wl4 src          -j ACCEPT   ← 豁免集合(内网/本机/活跃会话/自定义)
      4. -m set --match-set cn4 src                   -j ACCEPT   ← 中国大陆
      5. -j DROP                                                  ← 其余拒绝(MODE=loose 时改为 RETURN)

    挂到 INPUT 首位(-I INPUT 1),优先于既有规则。可用环境变量覆盖:

    sudo SET4=cn4 MODE=strict ROLLBACK_DELAY=600 WHITELIST_FILE=/etc/chnroute/whitelist.txt ./apply-whitelist.sh

    B) nftables

    sudo update_chnroute.py --backend nft --nft-table 'inet filter' --format nft --apply

    nft -f chnroute.nft 整文件是一个事务,同名 set 被原子替换。在你自己的规则里引用:

    nft add rule inet filter input ip saddr @cn4 accept

    注意:nftables 的 set 与引用它的规则必须在同一张表内,所以用 --nft-table 指定你的表名(默认 inet filter)。

    C) RouterOS(多 WAN 策略路由)

    python3 update_chnroute.py --outdir ./out --format ros --isp --ros-pbr
    # 把 chnroute-ros.rsc 上传到设备 /file,然后:
    #   /import file-name=chnroute-ros.rsc

    生成的 chnroute-ros-pbr.rsc 是可直接改用的模板(国内直连、境外走代理线路):

    /ip firewall mangle
    add chain=prerouting src-address-list=LAN dst-address-list=CN  action=mark-routing new-routing-mark=to-cn       passthrough=yes
    add chain=prerouting src-address-list=LAN dst-address-list=!CN action=mark-routing new-routing-mark=to-overseas passthrough=yes
    
    /ip route
    add dst-address=0.0.0.0/0 gateway=<国内WAN>   routing-mark=to-cn       distance=1 check-gateway=ping
    add dst-address=0.0.0.0/0 gateway=<海外WAN>   routing-mark=to-overseas distance=1 check-gateway=ping

    配合 --isp 生成的 CN-CHINANET / CN-CMCC / CN-UNICOM 列表,还能做运营商级精细分流
    (三网互联互通瓶颈是实打实的,电信用户访问移动 IDC 绕行会显著抬高 RTT 与丢包)。
    check-gateway=ping + distance 分级实现链路健康感知与自动备份。


    七、定时更新

    sudo ./install.sh --with-timer    # systemd:每天 04:30 + 随机 30 分钟,自动 --apply
    sudo ./install.sh --with-cron     # 无 systemd 时用 crontab

    systemd 单元要点:

    • RandomizedDelaySec=1800 打散触发时间,避免与其他定时任务叠加
    • Persistent=true 关机/休眠错过时间点后开机补跑
    • TimeoutStartSec=900 超时视为失败,旧 ipset 不受影响
    • 日志落 /var/log/chnroute/update.log

    检查:

    systemctl list-timers chnroute-update.timer
    journalctl -u chnroute-update.service -n 50
    tail -f /var/log/chnroute/update.log

    八、常见问题

    Q:APNIC 源太慢(约 5 分钟),能快吗?
    用 --sources aggregate(~74 秒)。它走 jsdelivr 镜像上的 BGP 聚合数据,段数更少、覆盖一致。
    也可以把 systemd 单元的 --format all 改成加 --sources aggregate。

    Q:用户访问国内 CDN 但 CDN 回源在境外,会不会被误封?
    白名单只判源 IP。国内 CDN 边缘节点在国内,源 IP 就是国内的,不受影响。

    Q:白名单生效后,出站请求的响应包会被丢吗?
    不会。链首放行 ESTABLISHED,RELATED,你主动发起的连接,响应包照常进来。

    Q:要不要同时放行 UDP / DNS?
    白名单基于 address-list,协议无关。但如果只给国外用户开 DNS,那么他们连域名都解析不了 ——
    若确有境外用户,请把他们加进 /etc/chnroute/whitelist.txt 而不是开放端口。

    Q:误封了自己怎么救?

    1. 等 300 秒自动回滚(如果还没 --commit);
    2. 云控制台 VNC/串口执行 sudo /usr/local/sbin/chnroute-rollback.sh;
    3. 事先把出口 IP 写进 /etc/chnroute/whitelist.txt 是唯一可靠的预防手段。

    Q:IPv6 要不要一起管?
    要。只做 v4 白名单时,境外用户仍可经 IPv6 进来。脚本默认 v4/v6 一起生成;
    若服务器没有 IPv6,加 --no-ipv6。

    Q:想撤掉全部策略?
    sudo /usr/local/sbin/apply-whitelist.sh --rollback;完全卸载 sudo ./install.sh --uninstall。


    九、数据源与合规说明

    • APNIC 官方统计文件:delegated-apnic-latest,含 CN 的 allocated/assigned 记录,
      权威、只增不减。IPv4 记录以「地址个数」表示,脚本用 summarize_address_range 正确转 CIDR
      (例如 300 个地址 → /24 + /27 + /29 + /30,已单测验证)。
    • china-operator-ip:BGP 路由表聚合,附带 ISP(电信/移动/联通/教育网等)归属。
    • chnroutes2:已聚合的最小 CIDR 集,体积小、速度快。

    以上均为公开的 RIR/BGP 数据派生品,用于网络运维与访问控制;请遵守当地法律法规及所在单位的网络管理规定。

  • 记一次 Druid 连接 MySQL 报 Communications link failure 的排查过程

    ““markdown
    # 记一次 Druid 连接 MySQL 报 Communications link failure 的排查过程

    ## 问题现象

    Druid 连接池启动时报错:

    “`
    com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

    The last packet sent successfully to the server was 0 milliseconds ago.
    The driver has not received any packets from the server.
    at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:361)
    …
    Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol
    (protocol is disabled or cipher suites are in
    “`

    连接地址是 `jdbc:mysql://127.0.0.1:3306/k_k`,MySQL 就在本机。

    ## 排查过程

    ### 1. 先排除基础问题

    确认 MySQL 服务在运行、端口 3306 可通,排除服务没启动、防火墙拦截等常见原因。

    ### 2. 定位到 SSL 握手阶段

    堆栈里最关键的一行是:

    “`
    at com.mysql.cj.protocol.a.NativeProtocol.negotiateSSLConnection(NativeProtocol.java:361)
    “`

    说明 TCP 连接已经建立,问题出在 **SSL 握手阶段**,而不是网络不通。

    ### 3. 检查 MySQL 的 TLS 配置

    “`sql
    SHOW VARIABLES LIKE ‘tls_version’;
    “`

    结果:

    “`
    TLSv1,TLSv1.1,TLSv1.2
    “`

    MySQL 支持 TLSv1.2,但同时也启用了已被淘汰的 TLSv1 和 TLSv1.1。

    ### 4. 获取 CA 证书

    MySQL 启用 SSL 后,数据目录下会生成一组证书文件。先找到数据目录:

    “`sql
    SHOW VARIABLES LIKE ‘datadir’;
    “`

    在数据目录里找到 `ca.pem`,这就是服务端的 CA 证书。

    ### 5. 将 CA 证书导入 Java 信任库

    使用 JDK 自带的 `keytool`:

    “`bash
    /www/server/java/jdk1.8.0_371/bin/keytool -importcert \
    -alias MySQLCACert \
    -file /www/server/data/ca.pem \
    -keystore truststore.jks \
    -storepass 你的密码
    “`

    生成的 `truststore.jks` 位于执行命令时的当前目录。

    ### 6. 在 JDBC URL 中配置信任库

    “`
    jdbc:mysql://127.0.0.1:3306/k_k?sslMode=VERIFY_CA&trustCertificateKeyStoreUrl=file:/路径/truststore.jks&trustCertificateKeyStorePassword=你的密码
    “`

    重新启动后,**仍然报同样的错**。

    ## 真正的原因

    这是 **MySQL Connector/J 8.0.18 及更早版本的一个已知设计问题**:

    – Connector/J 8.0.16 出于兼容旧版 MySQL(yaSSL 编译)的考虑,**默认不启用 TLSv1.2**,只尝试用 TLSv1/TLSv1.1 协商。
    – JDK 8u371 默认**禁用了 TLSv1 和 TLSv1.1** 这两个不安全的旧协议。

    双方在“能用哪个协议”上谈不拢,SSL 握手直接失败。

    ## 解决方案

    在 JDBC URL 中显式指定 TLS 协议版本:

    “`
    jdbc:mysql://127.0.0.1:3306/k_k?sslMode=VERIFY_CA&trustCertificateKeyStoreUrl=file:/路径/truststore.jks&trustCertificateKeyStorePassword=你的密码&enabledTLSProtocols=TLSv1.2
    “`

    关键是 `enabledTLSProtocols=TLSv1.2`,它强制驱动使用 TLSv1.2,打破协议僵局。加上后连接正常。

    ## 几个容易踩的坑

    – **`ssl_cipher` 查询为空是正常的**,MySQL 8.0 的密码套件由底层 OpenSSL 管理,不再通过该变量显式列出。
    – **`ssl_ca` 只返回 `ca.pem` 而非完整路径也是正常的**,该变量存储的是配置文件里填写的值,要拿绝对路径得查 `datadir`。
    – **`keytool` 命令找不到**,是因为它不在系统 PATH 里,需要用 JDK `bin` 目录下的绝对路径执行。

    ## 后续可以改进的地方

    1. **升级驱动**:Connector/J 8.0.19 及以上版本已修复默认不启用 TLSv1.2 的问题,升级后可以去掉 `enabledTLSProtocols` 参数。
    2. **清理 MySQL 旧协议**:在 `my.cnf` 的 `[mysqld]` 段加上 `tls_version=TLSv1.2,TLSv1.3`,重启 MySQL,让服务端也彻底禁用旧协议,安全性更好。

    ## 最终可用配置

    “`
    jdbc:mysql://127.0.0.1:3306/k_k?sslMode=VERIFY_CA&trustCertificateKeyStoreUrl=file:/路径/truststore.jks&trustCertificateKeyStorePassword=你的密码&enabledTLSProtocols=TLSv1.2
    “`

    **版本信息**:
    – MySQL Connector/J 8.0.16
    – Druid 1.1.18
    – JDK 1.8.0_371
    ““