找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3788

积分

0

好友

496

主题
发表于 2026-5-19 20:23:59 | 查看: 77| 回复: 0

数据安全思维导图

这是一篇非常系统的内容,旨在帮助你构建一个安全稳定的个人网站或博客。我们将深入探讨数据备份、主机防护和图床安全等关键环节,解答你关于博客运营中的诸多疑问。

B站视频版本https://www.bilibili.com/video/BV1j1uJzdEvH

你好,我是真成。当我们的博客系统搭建完毕并开始日常更新后,除了内容创作,还有一项工作必须提上日程——数据安全。这并非杞人忧天,服务器中勒索病毒、密码被暴力破解、图床流量被盗刷等事件时有发生。为了避免这些不必要的损失,为我们的数据、服务器和图床建立一道防线就显得至关重要。

在本篇中,我们将重点介绍如何对 WordPress 的 MySQL 数据库和项目源文件进行备份,配置服务器端口的安全策略,以及设置 OSS 图床的防盗链。如果你也对运维和开发社区的技术实战感兴趣,云栈社区里还有很多同路人一起分享这类经验。

数据备份

为了让思路更清晰,我们先梳理一下数据备份的整体流程:

  1. 数据打包:编写 Shell 脚本,将数据库和 WordPress 项目源数据打包到服务器本地。
  2. 数据推送:编写 Python 脚本,将打包好的数据文件上传到 OSS 对象存储中进行持久化保存。
  3. 定时执行:创建定时任务,让以上脚本每天自动运行。

为什么不直接把数据存在服务器本地呢?因为我们就一台服务器,如果数据只放在本地,一旦服务器磁盘损坏或系统崩溃,备份的意义就大打折扣。所以,把它上传到远端的 OSS 里才是更稳妥的选择。

数据打包

我们先从数据打包开始,编写一个 Shell 脚本来导出数据库并压缩项目文件。

1)  脚本逻辑

  • 导出 WordPress 的 MySQL 数据库。
  • 打包 WordPress 项目的源数据目录。
  • 将以上两部分打包成一个最终的压缩文件。

2)  脚本运行说明

  • 修改脚本中配置参数部分的相关变量。
  • 使用 source 命令执行脚本。

    注意:这里必须使用 source 命令来执行脚本,因为后续的 .oss_env 文件需要通过脚本中 export 的变量来获取文件路径和名称。

3)  创建并编写脚本文件

请务必通过 `vi` 或 `vim` 编辑器手动复制以下内容,防止变量赋值出现偏差。脚本的执行日志将存放在 `/var/log/wordpress_db_backup.log`。

```bash
$ mkdir -p /opt/module/wordpress/script
$ vi /opt/module/wordpress/script/wordpress_db_data_backup.sh
#!/bin/bash

# 配置参数
DB_HOST=${DB_HOST:-localhost}
DB_USER=${DB_USER:-root}
DB_PASSWORD=${DB_PASSWORD:-mysql@qiuyl.com}
DB_NAME=${DB_NAME:-qiuyl}
MAX_BACKUPS=${MAX_BACKUPS:-1}
LOG_FILE=${LOG_FILE:-/var/log/wordpress_db_backup.log}
# WrodPress数据目录
WORDPRESS_DATA_DIR=${WORDPRESS_DATA_DIR:-/opt/module/wordpress/wordpress_data}
# mysql、wordpress备份数据保存目录
BACKUP_DIR=${BACKUP_DIR:-/opt/wordpress_backup}
# mysql、wordpress备份数据通过tar压缩后保存目录
TAR_WORDPRESS_DATA_DIR=${TAR_WORDPRESS_DATA_DIR:-/opt/wordpress_backup_data}

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}

LOCAL_PWD=`pwd`
# 创建备份目录
mkdir -p $BACKUP_DIR
# 清空目录
rm -rf $BACKUP_DIR/*

# 生成备份文件名
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/mysql-${DB_NAME}-${TIMESTAMP}.sql.gz"
echo $BACKUP_FILE
# 1. 执行备份命令
log "Starting MySQL backup..."
docker exec mysql-5.7 mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASSWORD --single-transaction $DB_NAME | gzip > $BACKUP_FILE

# 检查备份结果
if [ $? -eq 0 ]; then
    log "1.DB_Backup succeeded: $BACKUP_FILE"
else
    log "DB_Backup failed!"
    exit 1
fi

# 清理db旧备份(注释掉)

# 2. 备份WordPress数据文件
WORDPRESS_BACKUP_FILE_NAME="${BACKUP_DIR}/wordpress-${TIMESTAMP}.tar"
cd $WORDPRESS_DATA_DIR
tar -zcf $WORDPRESS_BACKUP_FILE_NAME ./*
log "2.WordPress数据源备份 Succeeded:${WORDPRESS_BACKUP_FILE_NAME}"

# 清理wordpress旧备份(注释掉)

# 3. 压缩WordPress数据文件
mkdir -p $TAR_WORDPRESS_DATA_DIR
TAR_WORDPRESS_DATA_NAME="wordpress_data_${TIMESTAMP}.tar"
cd $BACKUP_DIR
tar -zcf $TAR_WORDPRESS_DATA_NAME ./*
mv $TAR_WORDPRESS_DATA_NAME $TAR_WORDPRESS_DATA_DIR
log "3.tar压缩 wordpress data Succeeded:${TAR_WORDPRESS_DATA_DIR}/${TAR_WORDPRESS_DATA_NAME}"
cd $LOCAL_PWD

# 4. 用于.oss_env文件获取的变量
export MYSQL_BACKUP_LOCAL_FILE_PATH="${TAR_WORDPRESS_DATA_DIR}/${TAR_WORDPRESS_DATA_NAME}"
export MYSQL_BACKUP_FILE_NAME=${TAR_WORDPRESS_DATA_NAME}
```

4)  执行方式

如果你想修改配置参数并重新执行脚本,需要先用 `unset` 清除已加载的环境变量,防止旧值干扰。然后用 `source` 命令运行脚本:

```bash
source /opt/module/wordpress/script/wordpress_db_data_backup.sh
```
😜 小贴士:如果你修改了脚本里的变量值,记得先执行一次 `unset` 命令哦:
```bash
unset LOCAL_PWD DB_HOST DB_USER DB_PASSWORD DB_NAME MAX_BACKUPS LOG_FILE WORDPRESS_DATA_DIR BACKUP_DIR TAR_WORDPRESS_DATA_DIR MYSQL_BACKUP_LOCAL_FILE_PATH MYSQL_BACKUP_FILE_NAME
```

数据推送

打包好数据后,下一步就是把它自动推送到阿里云的对象存储 OSS 上。这个过程分四步走:

  1. 创建阿里云 RAM 用户,只授予 OSS 的上传权限。
  2. 运维/DevOps/SRE工作中常见的Python环境配置。
  3. 编写 Python 脚本来实现上传。
  4. 设定 Linux 定时任务,把这一切串联起来。

创建RAM用户

为安全起见,我们不为 RAM 用户分配过多权限,做到“最小权限原则”。

1)  创建用户:进入 RAM 访问控制 控制台,创建一个专门用于数据备份的编程访问用户。
创建RAM用户
2)  创建 AccessKey:为该用户创建 AccessKey(即 AKSK),并妥善保管。
创建AccessKey
如果你担心 AKSK 泄露,可以为其设置更严格的网络访问限制,但我们的脚本在阿里云服务器上通过内网运行,一般不需要开启此限制。
AccessKey操作选项
网络访问限制策略
3)  创建私有 Bucket:登录 OSS 控制台,新建一个 Bucket。为兼顾安全和成本,建议选择“私有”读写权限和“低频访问”存储类型。虽然数据存取频率不高,但单价更划算。新建的地域建议与你的 ECS 服务器保持一致,方便内网互通。
创建Bucket配置
4)  RAM 用户授权:在 OSS 控制台的对应 Bucket 页面,进入「权限控制」>「Bucket 授权策略」,选择「新增授权」。找到你刚创建的 RAM 用户,只授予 oss:PutObject (上传文件) 权限即可。
Bucket授权策略新增

安装Python3环境

虽然操作系统的默认 Python-3.6.8 版本理论上受 OSS SDK 支持,但实测中发现部分依赖(如 oss2)已不兼容,所以我们手动安装 Python-3.10.10。

1)  安装编译环境

Alibaba Cloud Linux / CentOS 系统用户请执行:
```bash
# 安装必要的编译工具
yum -y install openssl-devel libffi-devel bzip2-devel
yum -y groupinstall "Development Tools"
# 注意:Alibaba Cloud Linux 可能只需安装 zlib-devel
yum install -y zlib-devel
```

2)  编译安装 Python-3.10.10

我们先安装新版 OpenSSL,再编译 Python,确保它能支持 HTTPS。
```bash
mkdir -p /opt/module/openssl && cd /opt/module/openssl
wget https://www.openssl.org/source/openssl-1.1.1q.tar.gz --no-check-certificate
tar zxf openssl-1.1.1q.tar.gz && cd openssl-1.1.1q
./config --prefix=/usr/local/openssl-1.1.1
sudo make && sudo make install

# 安装Python3.10.10
mkdir -p /opt/module/Python && cd /opt/module/Python
wget https://www.python.org/ftp/python/3.10.10/Python-3.10.10.tgz
tar -xf Python-3.10.10.tgz && cd Python-3.10.10
yum install -y zlib-devel  # 如果上面装过可以忽略
./configure --prefix=/usr/local/python3.10.10 --enable-optimizations --with-openssl=/usr/local/openssl-1.1.1 --with-openssl-rpath=auto
make altinstall

# 添加全局环境变量
cat >> /etc/profile <<EOF
export PYTHON_HOME=/usr/local/python3.10.10
export PATH=\$PYTHON_HOME/bin:\$PATH
EOF
source /etc/profile

python3.10 --version
```

3)  配置虚拟环境

为保持依赖隔离,我们使用 `virtualenv` 创建一个干净的 Python 环境。
```bash
cd /opt/module/wordpress/script
pip3.10 install virtualenv
virtualenv venv
# 进入虚拟环境并安装 oss2
source venv/bin/activate
pip3.10 install oss2
# 退出虚拟环境
deactivate
```

Python脚本上传文件到OSS

1)  脚本逻辑: 从环境变量读取配置和文件路径,将本地文件上传到指定的 OSS Bucket。
2)  创建上传脚本

    cat > /opt/module/wordpress/script/wordpress_data_oss_upload.py <<EOF
    # -*- coding: utf-8 -*-
    import oss2
    import os
    from getpass import getpass

    # 通过环境变量获取配置
    access_key_id = os.environ.get('OSS_ACCESS_KEY_ID')
    access_key_secret = os.environ.get('OSS_ACCESS_KEY_SECRET')
    endpoint = os.environ.get('OSS_ENDPOINT')
    bucket_name = os.environ.get('OSS_BUCKET_NAME')
    file_path = os.environ.get('OSS_LOCAL_FILE_PATH')
    object_name = os.environ.get('OSS_OBJECT_NAME')

    def main():
        print("[DEBUG] 当前环境变量:")
        print(f"ACCESS_KEY_ID: {access_key_id}")
        print(f"ACCESS_KEY_SECRET: {'*' * len(access_key_secret) if access_key_secret else '未设置'}")
        print(f"OSS_ENDPOINT: {endpoint}")
        print(f"OSS_BUCKET_NAME: {bucket_name}")
        print(f"OSS_OBJECT_NAME: {object_name}")
        print(f"文件路径: {file_path}")

        if not all([access_key_id, access_key_secret]):
            print("错误:缺少OSS认证信息!请设置环境变量:")
            print("export OSS_ACCESS_KEY_ID='your_access_key_id'")
            print("export OSS_ACCESS_KEY_SECRET='your_access_key_secret'")
            return

        auth = oss2.Auth(access_key_id, access_key_secret)
        bucket = oss2.Bucket(auth, f'http://{endpoint}', bucket_name)

        try:
            if not os.path.isfile(file_path):
                raise FileNotFoundError(f"文件 {file_path} 不存在或不是文件")

            result = bucket.put_object_from_file(object_name, file_path)

            if result.status == 200:
                print("--------------------------------------------------")
                print(f"上传成功!OSS路径:{object_name}")
                print(f"ETag(完整性校验):{result.etag}")
            else:
                print(f"上传异常,HTTP状态码:{result.status}")

        except oss2.exceptions.OssError as e:
            print(f"OSS操作失败:{e.status_code} {e.code} {e.message}")
        except Exception as e:
            print(f"运行时错误:{str(e)}")

    if __name__ == "__main__":
        main()
    EOF

3)  配置凭证文件 .oss_env:这个文件定义了 OSS 上传所需的变量。其中 OSS_LOCAL_FILE_PATHOSS_OBJECT_NAME 的值会引用上一步 Shell 脚本 export 的变量。

如何获取 Endpoint? 可以在 OSS 控制台的「Bucket 列表」>「概览」页面下的「访问端口」区域找到。
OSS Endpoint 访问端口

```bash
cat > /opt/module/wordpress/script/.oss_env <<EOF
export OSS_ACCESS_KEY_ID="xxxx"
export OSS_ACCESS_KEY_SECRET="xxxx"
export OSS_ENDPOINT="oss-cn-xxxx.aliyuncs.com"
export OSS_BUCKET_NAME="xxxx"
export OSS_LOCAL_FILE_PATH=\${MYSQL_BACKUP_LOCAL_FILE_PATH}
export OSS_OBJECT_NAME="backup_data/wordpress_data_backup/\${MYSQL_BACKUP_FILE_NAME}"
EOF
```

定时任务执行脚本

1)  整合串联脚本:这个脚本会依次执行数据打包和 OSS 上传任务。

    cat > /opt/module/wordpress/script/crontab_wordpress_data_backup.sh <<EOF
    unset LOCAL_PWD DB_HOST DB_USER DB_PASSWORD DB_NAME MAX_BACKUPS LOG_FILE WORDPRESS_DATA_DIR BACKUP_DIR TAR_WORDPRESS_DATA_DIR MYSQL_BACKUP_LOCAL_FILE_PATH MYSQL_BACKUP_FILE_NAME
    source /opt/module/wordpress/script/wordpress_db_data_backup.sh
    echo "========Python脚本上传文件到OSS========"
    unset OSS_ACCESS_KEY_ID OSS_ACCESS_KEY_SECRET OSS_ENDPOINT OSS_BUCKET_NAME OSS_LOCAL_FILE_PATH OSS_OBJECT_NAME
    source /opt/module/wordpress/script/venv/bin/activate
    source /opt/module/wordpress/script/.oss_env && python3.10 /opt/module/wordpress/script/wordpress_data_oss_upload.py
    deactivate
    EOF
> 最终你的 `/opt/module/wordpress/script/` 目录下应该有这些文件:
![脚本目录结构](https://static1.yunpan.plus/attachment/de2613b13c4bd9ca.webp)

2)  首次手动测试:在添加定时任务前,先手动执行一次主脚本,确保一切正常。

    source /opt/module/wordpress/script/crontab_wordpress_data_backup.sh
![脚本执行日志](https://static1.yunpan.plus/attachment/4b9f959d6c93a4cb.webp)
执行后,去 OSS 控制台检查文件是否已成功上传。
![OSS文件列表](https://static1.yunpan.plus/attachment/e9b216edd0edfbd0.webp)

3)  创建定时任务:设置每天凌晨 3 点执行备份,并将日志记录到 /var/log/wordpress_data_backup.log

    # 编辑crontab定时任务
    $ crontab -e
    0 3 * * * source /opt/module/wordpress/script/crontab_wordpress_data_backup.sh >> /var/log/wordpress_data_backup.log
这样,一个从本地打包到远端存储的自动化数据备份流程就搭建完成了。

数据恢复

当意外发生时,如何将数据恢复如初?这里以数据库恢复为例,WordPress 源文件的恢复更简单,直接解压覆盖原目录即可。

1)  下载备份文件:在 OSS 控制台找到对应的 tar 包并下载到本地。
OSS文件列表和下载按钮
2)  上传至服务器:把下载好的 tar 包传到你的云服务器上,比如 /home/ 目录。
服务器文件列表
3)  解压并导入数据库

    # 解压主备份包
    [root@localhost home]# tar -vzxf wordpress_data_20250513-001649.tar
    ./
    mysql-qiuyl-20250513-001649.sql.gz
    wordpress-20250513-001649.tar

    # 从压缩的SQL文件生成可导入的SQL文件
    [root@localhost home]# zcat mysql-qiuyl-20250513-001649.sql.gz > mysql-qiuyl-20250513-001649.sql
重启 Wordpress 相关容器,并导入数据库。在此之前,建议先备份当前的旧数据。
```bash
cp -rf /opt/module/wordpress/mysql_data /home/mysql_data.bak
rm -rf /opt/module/wordpress/mysql_data
cd /opt/module/wordpress/docker-compose
docker compose down && docker compose up -d

# 导入数据库
yum install -y mariadb
mysql -h 127.0.0.1 -u root -pmysql@qiuyl.com
MySQL [(none)]> use qiuyl;
MySQL [qiuyl]> source /home/mysql-qiuyl-20250513-001649.sql;
```

主机安全

除了数据,服务器本身也需要一些基础的安全加固。这里分享两个最简单的操作:关闭 Ping 和关闭外网 SSH 连接。

1)  关闭 SSH (22端口):当博客运行稳定,没有频繁远程连接服务器的需求时,建议在安全组中关闭 SSH 的 22 端口。需要时再临时打开,这能极大概率避免被暴力破解。操作前,Telnet 22 端口是通的状态,关闭后则连接失败。
Telnet连接成功状态
删除22端口规则确认
22端口连接失败
连接工具断开状态

2)  禁止 PING (ICMP协议):禁止 Ping 可以有效防止无聊的 IP 存活扫描。在安全组中删除 ICMP 协议的出入方向规则即可。删除前Ping通,删除后Ping不通。
Ping通状态
删除ICMP规则确认
Ping超时状态

OSS安全

对于 OSS 的安全,可以利用它的“健康检测”功能来查漏补缺。不过对我们个人站长来说,最要紧的是给图床 Bucket 设置防盗链,防止图片被其他网站盗用导致流量费用激增。

OSS健康检测

在我的数据库/中间件/技术栈里,类似这种Nginx或CDN的防盗链配置是通用的安全思路。你可以直接参考阿里云的官方文档进行配置,以下是我常用的 Referer 白名单,可供参考,仅允许这些域名的网站引用我的图片资源:

*.aliyun.com
*.csdn.net
*.mdnice.com
*.nlark.com
*.qq.com
*.weixinbridge.com
*.yuque.com
http://www.qiuyl.com
https://www.qiuyl.com

参考资料

总结

通过以上从数据、主机到 OSS 的层层设防,我们已经能够为博客系统提供相对坚实的安全底座。虽然不敢说万无一失,但保守估计,这些措施足以帮助我们个人站长规避掉 80%-90% 的常见安全风险。

这篇教程中,我们只实现了数据上传到 OSS 的自动化,那当备份文件越积越多时,能否也用程序自动清理过期备份呢?答案是肯定的。阿里云 OSS 的 Python SDK 同样提供了删除对象的接口,这就留给大家自己去探索实践了。如果后续我完善了这一部分,也会在本系列中进行补充。

以上就是本篇的全部内容。下一篇,也是本系列的收官之作,我们将对整个建站流程进行一次全面的复盘与总结。

像素风格手指指向图标




上一篇:2000亿美元押注AI基建,AWS如何凭自研芯片与双模型绑定逆袭
下一篇:FreeRTOS信号量≠互斥锁:用一张时序图彻底讲清优先级继承如何解决反转问题
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-6-10 09:06 , Processed in 0.644416 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表