lius 发布的文章

一、故障概述

在 Typecho 博客系统执行文章保存操作(POST /action/contents-post-edit)时,页面返回 HTTP 504 Gateway Timeout 错误。对存储、资源、数据库及 PHP 环境进行分层排查后,确认底层运行正常,问题定位为反向代理超时配置。

二、排查过程与实证结果

1、存储系统验证

排查命令:在 Pod 内执行

time touch /var/www/html/nfs_test && echo "test">/var/www/html/nfs_test && rm /var/www/html/nfs_test

实测结果

real    0m0.125s
user    0m0.000s
sys     0m0.001s

结论:NFS 文件读写操作耗时仅 0.125 秒,无 I/O 延迟或挂载异常,可排除存储瓶颈。

2、资源使用率检查

排查命令kubectl top pod miiv-lnp-557f547c45-d4745

实测结果

NAME                        CPU(cores)   MEMORY(bytes)
miiv-lnp-557f547c45-d4745   13m          25Mi

结论:Pod CPU 使用率 13m、内存 25Mi,资源配额充足,无资源争抢或耗尽情况。

3、数据库状态分析

排查命令SHOW FULL PROCESSLIST;

实测结果

| Id     | User    | Host            | db      | Command | Time | State    | Info                  |
| 404341 | root    | localhost       | NULL    | Query   |    0 | starting | SHOW FULL PROCESSLIST |
| 404377 | typecho | 10.42.2.3:45330 | typecho | Sleep   |   61 |          | NULL                  |
| 404378 | typecho | 10.42.2.3:45340 | typecho | Sleep   |   61 |          | NULL                  |

结论:数据库连接均为 Sleep 状态,无长时间运行查询,无连接阻塞或死锁,负载正常。

4、PHP 执行能力测试

测试脚本:创建 PHP 文件模拟耗时操作,访问

<?php
echo "Start: " . date('Y-m-d H:i:s') . "\n";
sleep(2); // 模拟耗时操作
echo "End: " . date('Y-m-d H:i:s') . "\n";
?>

实测结果

Start: 2026-05-02 12:56:03
End: 2026-05-02 12:56:05

结论:PHP-FPM 可正常处理 2 秒耗时请求,脚本执行不受限制,应用层基础处理能力无异常。

5、故障日志定位

日志内容

10.42.1.2 - - [02/May/2026:12:44:32 +0000] "POST /action/contents-post-edit?_=94be44fc416e098a75bd09ba9d85aec0 HTTP/1.1" 504 569

关键信息:文章保存请求触发 504 超时,与 PHP 正常处理能力测试结果不一致。

结论:问题并非应用层逻辑错误,而是网关层超时配置导致。

6、调整反向代理超时配置

修改 Nginx 或 Ingress Controller 配置,增加proxy_read_timeoutproxy_send_timeout值(建议设置为 120 秒以上)

示例配置(Nginx):

location~\.php$ {
    proxy_read_timeout 120s;
    proxy_send_timeout 120s;
}

重新发布文章发现正常(耗时还是有问题)

三、根因分析

综合实测数据,系统底层环境(存储、资源、数据库、PHP)均无异常。HTTP 504 错误本质为反向代理等待后端响应超过预设超时阈值。PHP 可正常处理 2 秒耗时请求,说明基础执行能力正常;但文章保存操作可能包含额外处理逻辑(如插件触发、缓存更新等),导致总耗时超过网关默认超时时间(通常为 60 秒)。

四、解决方案

关闭Typecho中的AISummary插件正常

ypecho 动态 IP 环境适配与故障排查指南

场景一:解决动态 IP 导致的后台死链问题

Typecho 是一个使用 PHP 编写的博客系统。在部署环境(如容器、动态 IP 服务器)中,如果域名或 IP 地址不固定,系统生成的后台按钮链接往往会指向旧的 IP 地址或错误的端口,导致访问异常。

为了解决这个问题,我们需要开启相对地址模式。虽然开启后永久链接(伪静态)可能无法正常使用,但这能确保后台按钮在 IP 变动时依然可用。

开启相对地址的两种方法

方法一:修改数据库(不推荐)
直接修改数据库 typecho_options 表,将 siteUrl 字段的值改为相对路径(如 /)。

方法二:修改核心代码(推荐)
通过修改核心文件来绕过后台对“绝对 URL”的强制校验。

操作步骤:

1.定位文件:var/Widget/Options/General.php

2.查找代码(约 87 行):

->addRule('url', _t('请填写一个合法的URL地址'))

3.修改代码:

->addRule('xssCheck', _t('请填写一个合法的URL地址'))

4.保存文件,刷新后台即可生效。

修改效果Typecho 后台不再强制校验站点地址协议和域名,后台所有链接自动适配当前访问地址,彻底解决动态 IP / 端口导致的死链问题。

场景二:后台 “Server Error” 排查与修复

访问后台模块(如附件管理)出现 Server Error (500) 且无具体报错时,按以下步骤修复。

1. 开启调试模式

编辑网站根目录 config.inc.php,在 <?php 下方直接粘贴:

// ----------调试使用-------
define('__TYPECHO_DEBUG__', true);
error_reporting(E_ALL);
ini_set('display_errors', 'On');
// 强制输出错误到浏览器,防止被 Nginx 拦截
ini_set('html_errors', 'Off');
// -------------------------

2. 分析报错信息

典型错误
TypeError: Argument 1 passed to Typecho\Common::mimeIconType() must be of the type string, null given

原因:数据库中部分附件 mime 字段为 NULL,但函数强制要求字符串,导致崩溃。

3. 修复方案

编辑文件admin/manage-medias.php

修改前(报错)

<?php $mime = \Typecho\Common::mimeIconType($attachments->attachment->mime); ?>

修改后(修复)

<?php $mime = \Typecho\Common::mimeIconType($attachments->attachment->mime ?? ''); ?>

修复后完整代码段

<?php while ($attachments->next()): ?>

<?php $mime = \Typecho\Common::mimeIconType($attachments->attachment->mime ?? ''); ?>

4. 结果与注意

保存后刷新后台,Server Error 消失,附件管理正常显示。

️ 注意:调试完成后,务必注释 / 删除 config.inc.php 里的调试代码,避免生产环境泄露敏感信息。

Centos7.6部署OpenVPN

1、下载证书生成工具easy-rsa

yum -y install easy-rsa

2、创建证书环境目录

mkdir -p /opt/easy-rsa
cp -a /usr/share/easy-rsa/3.0.8/* /opt/easy-rsa/
cp -a /usr/share/doc/easy-rsa-3.0.8/vars.example /opt/easy-rsa/vars

3、修改vars配置文件,取消下面配置的注释

vim /opt/easy-rsa/vars

set_var EASYRSA_DN      "cn_only"
set_var EASYRSA_REQ_COUNTRY     "CN"
set_var EASYRSA_REQ_PROVINCE    "HangZhou"
set_var EASYRSA_REQ_CITY        "Hangzhou"
set_var EASYRSA_REQ_ORG         "lius.fun"
set_var EASYRSA_REQ_EMAIL       "gua3j7@126.com"
set_var EASYRSA_NS_SUPPORT      "yes"

4、初始化,创建pki目录用于存储证书(以下都在/opt/easy-rsa目录下操作)

cd /opt/easy-rsa/
./easyrsa init-pki

5、创建根证书,根证书用于ca对之后生成的serverclient证书签名时使用

输入密码确定,其他默认回车
./easyrsa build-ca

6、创建server端证书密钥文件(nopass表示不加密密钥文件,生成过程中直接默认回车)

./easyrsa gen-req server nopass

7、给server端证书签名

./easyrsa sign server server

8、创建Diffie-Hellman文件,密钥交换时的Diffie-Hellman算法

./easyrsa gen-dh

9、创建client端证书密钥文件(nopass表示不加密密钥文件,生成过程中直接默认回车)

./easyrsa gen-req client nopass
交互界面默认回车

10、给client端证书签名

 ./easyrsa sign client client

二、OpenVPN服务端部署

1、安装openvpn

yum install -y openvpn

2、创建TLS认证密钥

#为了安全性考虑
mkdir /etc/openvpn
openvpn --genkey --secret /etc/openvpn/ta.key

3、创建新的配置文件/etc/openvpn/server.conf

vim /etc/openvpn/server.conf

#监听本机端口
port 1194
#指定采用的传输协议,可选tcp或udp
proto tcp
#指定创建的通信隧道类型,可选tun或tap
dev tun
#指定CA证书的文件路径
ca ca.crt
#指定服务器端的证书文件路径
cert server.crt
#指定服务器端的私钥文件路径
key server.key
#指定迪菲赫尔曼参数的文件路径,也就是交换证书
dh dh.pem
#给客户端分配地址池,注意:不能和VPN服务器内网网段有相同
server 10.8.0.0 255.255.255.0
#允许客户端访问内网网段,填写自己内网
push "route 10.66.17.0 255.255.255.0"
#服务器自动给客户端分配IP后,客户端下次连接时,仍然采用上次的IP地址"第一次分配的IP保存在ipp.txt中,下一次分配其中保存的IP"
ifconfig-pool-persist ipp.txt
#存活时间,10秒ping一次,120如未收到响应则视为断线
keepalive 10 120
#最多允许100个客户端连接
max-clients 100
#日志记录位置
status openvpn-status.log
#openvpn版本
verb 3
#允许客户端与客户端相连接,默认情况下客户端只能与服务器相连接
client-to-client
#openvpn日志记录位置
log /var/log/openvpn.log
#通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-key
#检测超时后,重新启动VPN,一直保持tun是linkup的.否则网络会先linkdown然后再linkup
persist-tun
#开启TLS-auth,使用ta.key防御攻击.服务器端的第二个参数值为0,客户端的为1
tls-auth /etc/openvpn/ta.key 0
 
#开启多人同时登录
duplicate-cn
#允许使用自定义脚本
script-security 3
#脚本路径
auth-user-pass-verify /etc/openvpn/check.sh via-env
#用户密码登陆方式验证:加上client-cert-not-required则代表只使用用户名密码方式验证登录,如果不加,则代表需要证书和用户名密码双重验证登录
username-as-common-name
#绑定客户端IP
client-config-dir /etc/openvpn/ccd

4、配置密码启动脚本和和密码本

vim /etc/openvpn/check.sh

#!/bin/sh
###########################################################
PASSFILE="/etc/openvpn/openvpnpass"
LOG_FILE="/var/log/openvpn-password.log"
TIME_STAMP=`date "+%Y-%m-%d %T"`
 
if [ ! -r "${PASSFILE}" ]; then
    echo "${TIME_STAMP}: Could not open password file \"${PASSFILE}\" for reading." >> ${LOG_FILE}
    exit 1
fi
 
CORRECT_PASSWORD=`awk '!/^;/&&!/^#/&&$1=="'${username}'"{print $2;exit}' ${PASSFILE}`
 
if [ "${CORRECT_PASSWORD}" = "" ]; then
    echo "${TIME_STAMP}: User does not exist: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
    exit 1
fi
if [ "${password}" = "${CORRECT_PASSWORD}" ]; then
    echo "${TIME_STAMP}: Successful authentication: username=\"${username}\"." >> ${LOG_FILE}
    exit 0
fi
 
echo "${TIME_STAMP}: Incorrect password: username=\"${username}\", password=\"${password}\"." >> ${LOG_FILE}
exit 1

echo "user password"  >>/etc/openvpn/openvpnpass
 
echo "ifconfig-push 10.8.0.25 10.8.0.26"  >>/etc/openvpn/ccd/user

5、增加执行权限

chmod 755 /etc/openvpn/check.sh

[collapse status="false" title="(可选)ifconfig-push中的每一对IP地址表示虚拟客户端和服务器的IP端点,必须取下面的集合之一"]

[ 1, 2] [ 5, 6] [ 9, 10] [ 13, 14] [ 17, 18]
[ 21, 22] [ 25, 26] [ 29, 30] [ 33, 34] [ 37, 38]
[ 41, 42] [ 45, 46] [ 49, 50] [ 53, 54] [ 57, 58]
[ 61, 62] [ 65, 66] [ 69, 70] [ 73, 74] [ 77, 78]
[ 81, 82] [ 85, 86] [ 89, 90] [ 93, 94] [ 97, 98]
[101,102] [105,106] [109,110] [113,114] [117,118]
[121,122] [125,126] [129,130] [133,134] [137,138]
[141,142] [145,146] [149,150] [153,154] [157,158]
[161,162] [165,166] [169,170] [173,174] [177,178]
[181,182] [185,186] [189,190] [193,194] [197,198]
[201,202] [205,206] [209,210] [213,214] [217,218]
[221,222] [225,226] [229,230] [233,234] [237,238]
[241,242] [245,246] [249,250] [253,254]

[/collapse]

6、拷贝证书到openvpn主配置文件目录下

cp -a /opt/easy-rsa/pki/ca.crt /etc/openvpn/
cp -a /opt/easy-rsa/pki/issued/server.crt /etc/openvpn/
cp -a /opt/easy-rsa/pki/private/server.key /etc/openvpn/
cp -a /opt/easy-rsa/pki/dh.pem /etc/openvpn/

7、启动服务端

systemctl start openvpn@server
systemctl status  openvpn@server
systemctl enable  openvpn@server

客户端文件配置

1、拷贝服务端生成的证书到openvpn客户端安装目录的config目录下

  可以先拷贝到client中,最后下载到客户端的config目录下

cp -a /opt/easy-rsa/pki/ca.crt  /etc/openvpn/client
cp -a /opt/easy-rsa/pki/issued/client.crt /etc/openvpn/client
cp -a /opt/easy-rsa/pki/private/client.key /etc/openvpn/client
cp -a /etc/openvpn/ta.key /etc/openvpn/client

2、在客户端openvpn安装目录的config目录下,新建一个client.ovpn文件,写入配置

#指定当前VPN是客户端

client
#使用tun隧道传输协议
dev tun
#使用udp协议传输数据
proto tcp
#openvpn服务器IP地址端口号,转发的填写公网IP 加对应转发端口
remote 192.168.1.1 1194
#断线自动重新连接,在网络不稳定的情况下非常有用
resolv-retry infinite
#不绑定本地特定的端口号
nobind
#防止从缓存中获取账号密码
auth-nocache
#指定CA证书的文件路径
ca ca.crt
#指定当前客户端的证书文件路径
cert client.crt
#指定当前客户端的私钥文件路径
key client.key
#指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
verb 3
#通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-key
#检测超时后,重新启动VPN,一直保持tun是linkup的。否则网络会先linkdown然后再linkup
persist-tun
#使用ta.key防御攻击。服务器端的第二个参数值为0,客户端的为1
tls-auth ta.key 1
#账号密码认证
auth-user-pass
#在TLS握手过程中,服务器会向客户端展示其证书,并且确保证书中的信息是有效
remote-cert-tls server
#启用LZO压缩
comp-lzo
#开启加密套件
#tls-cipher
#启用GCM加密套件
#cipher AES-256-GCM   
#tls-cipher TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384  

3、将以上配置文件放到客户端安装目录下的的/config目录下

启动Open VPN客户端软件,连接成功OpenVPN的图标会变成绿色

注:客户端要想跟内网通讯还需要openvpn服务端开启内核转发
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

并且添加防火墙方式访问内部网络

systemctl start firewalld
firewall-cmd --add-masquerade --permanent
firewall-cmd --add-service=openvpn --permanent
firewall-cmd --add-port=1194/tcp --permanent
firewall-cmd --reload

参考:
OpenVpn下载
CSDN参考
腾讯云参考


长亭雷池使用过程中

出现以下两种情况:

1、因规则配置,导致两次安全访问被拦截,尝试多种方法无法恢复访问,最终重新安装防火墙,浪费掉了一定的时间与精力
2、配置拦截规则后,规则拦截异常,以下为情况规则描述
异常规则.png

  拦截情况

拦截情况.png

为了预防这种情况的发生,可实行以下应急方案:

1、`/date`下的`safeline`进行定期备份,此文件夹下的配置文件是长亭雷池防火墙当时的状态,可以理解为一个快照
2、长亭雷池默认端口9443,以上方案生效时可以放开防火墙,实现`IP:9443`访问

在进行测试过程中,规范行为:

1、测试范围中`指定host`,影响最小化
2、发布黑名单之前进行`密码验证`,`完毕后`进行发布黑名单
3、配置`白名单`,针对指定IP组和域名的双重访问条件,使得访问颗粒最小化
测试请不要针对维护模式下的网站测试,维护模式各种规则均不生效