使用 rsync 与 mariadb-dump 备份 freebsd jail 中网站与数据库

1. 使用 rsync 备份网站(适合内网)

为了在不影响宿主机 22 端口的前提下使用 rsync,最标准且高效的做法是:在 web_jail 内部开启一个独立的、仅供备份使用的 rsync 守护进程(Daemon 模式),监听标准的 873 端口。然后通过宿主机 PF 将外部非标端口(如 40873)映射进去。这样可以完全避开 ssh(22 端口)的冲突,且备份速度极快。

  • 在 web_jail 内部配置 rsync 守护进程
    • 进入 web_jail
      1
      jexec web_jail csh
    • 安装 rsync
      1
      pkg install rsync
    • 创建并编辑 rsync 配置文件 /usr/local/etc/rsync/rsyncd.conf:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      # 运行用户和组,必须是 www 才能读取网站内容
      uid = www
      gid = www
      use chroot = no
      max connections = 4
      pid file = /var/run/rsyncd.pid
      log file = /var/log/rsyncd.log

      # 定义一个备份模块叫 [backup_site]
      [backup_site]
      path = /usr/local/www/mywebsite
      comment = My Website Content
      read only = yes ; 备份只需只读,保证安全性
      list = yes
      auth users = backupuser ; 备份专有虚拟账号
      secrets file = /usr/local/etc/rsyncd.secrets
      hosts allow = 10.0.0.1 192.168.1.0/24 ; 仅允许宿主机网关和局域网网段访问
    • 创建密码文件 /usr/local/etc/rsyncd.secrets(格式为 用户名:密码):
      1
      backupuser:你的备份密钥明文
    • 极其重要: 修改密码文件的权限,rsync 要求该文件必须是 600 权限,否则拒绝启动:
      1
      chmod 600 /usr/local/etc/rsyncd.secrets
    • 开启 rsync 自启并启动它:
      1
      2
      sysrc rsyncd_enable=YES
      service rsyncd start
  • 在宿主机修改 pf 防火墙映射端口
    • 编辑宿主机的 /etc/pf.conf,将局域网的 40873 端口转发给 web_jail 的 873 端口:
      1
      2
      # add rsync forward rule, any host's 40873 forward to web jail 873
      rdr on $ext_if proto tcp from any to ($ext_if) port 40873 -> $web_jail port 873
    • 重载防火墙:
      1
      service pf restart
  • 局域网内其它电脑执行备份命令
    • 在局域网的备份服务器上,你只需要先创建一个密码文件 /etc/rsync.pass
      1
      echo "你的备份密钥明文" > /etc/rsync.pass
    • 必须限制权限(Rsync 客户端规定,如果密码文件权限不是 600,会直接报错拒绝运行):
      1
      chmod 600 /etc/rsync.pass
    • 执行 rsync 备份命令
      1
      rsync -avz --progress --password-file=/etc/rsync.pass backupuser@your_host_ip_address::backup_site /your_local_backup_path/ --port=40873
2. 使用 mariadb-dump 备份 mariadb 数据库

对于数据库备份,mariadb-dump 本质上是一个数据库客户端工具,它可以通过 tcp 网络远程连接到 mariadb 服务端。我们只需:在宿主机 pf 防火墙上将局域网的非标端口(如 43306)转发到 mariadb_jail 的 3306 端口,并在数据库内授予特定的备份账号远程访问权限。

  • 在宿主机修改 PF 防火墙映射端口
    • 编辑宿主机的 /etc/pf.conf:
      针对限定只能由宿主机网关访问
      1
      2
      3
      # 找到原来那句 mariadb 转发规则,修改为如下(注意末尾追加了 nat-to $int_if)
      # 这会让所有经过此端口的外部局域网流量,在进入 jail 时其源 ip 都变成宿主机网关 lo1 的 ip (10.0.0.1)
      rdr on $ext_if proto tcp from 192.168.1.0/24 to ($ext_if) port 43306 -> $mariadb_jail port 3306 nat-to $int_if
      针对整个网段访问
      1
      2
      # add mariadb forward rule, any host's 43306 forward to mariad jail 3306
      rdr on $ext_if proto tcp from any to ($ext_if) port 43306 -> $mariadb_jail port 3306
    • 重载防火墙:
      1
      service pf restart
  • 在 mariadb_jail 内授权局域网备份账号
    • 进入 mariadb_jail:
      1
      jexec mariadb_jail csh
    • 登录 mariadb 命令行:
      1
      mariadb -u root -p
    • 创建一个专门用于备份的账号
      限定只能由宿主机网关(进行过 NAT 转换后的局域网请求在 jail 看来是由宿主机网关 10.0.0.1 发出的)访问:
      1
      2
      3
      4
      CREATE USER 'db_backup'@'10.0.0.1' IDENTIFIED BY 'your_maraidb_backup_password';
      GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'db_backup'@'10.0.0.1';
      FLUSH PRIVILEGES;
      EXIT;
      或者整个网段都可以访问
      1
      2
      3
      4
      CREATE USER 'db_backup'@'%' IDENTIFIED BY 'your_maraidb_backup_password';
      GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON *.* TO 'db_backup'@'%';
      FLUSH PRIVILEGES;
      EXIT;
    • 退出 jail:
      1
      exit
  • 局域网内其它电脑执行备份命令
    1
    mariadb-dump -h your_host_ip_address -P 43306 -u db_backup -pyour_maraidb_backup_password --all-databases > /your_local_backup_path/all_databases_backup.sql
    或者
    1
    mariadb-dump --skip-ssl --add-drop-database -h your_host_ip_address -P 43306 -u root -pyour_mariadb_backup_password --databases backup_database_name | gzip > hd.sql.gz
3. 使用 rsync 备份网站(适合公网)

要在公网环境下使用 rsync 远程备份 web_jail 中的内容,安全性是首要考虑的问题。由于之前的局域网方案使用的是纯 tcp 协议的 rsync 守护进程(Daemon 模式),其数据在网络上是明文传输的。如果直接暴露到公网,不仅密码容易被拦截,还容易遭受扫描攻击。在公网环境下,最安全、标准的做法是:利用 ssh 隧道技术(或通过 pf 进行非标 ssh 端口转发)在 web_jail 内部署独立的 ssh 服务,实现全加密传输。由于外网的动态 ip 随时会变,我们还需要配合之前配置的 DDNS(动态域名)。以下是完整的公网 rsync 安全备份设置步骤:

  • 在 web_jail 内部配置独立的 SSH 备份通道
    为了不影响宿主机 22 端口的正常运维,我们直接在 web_jail 内部开启它自己的 sshd 服务,用于接收外网的 rsync 加密流量。
    • 进入 web_jail:
      1
      jexec web_jail csh
    • 生成 jail 内部的 ssh 密钥对(首次启动 sshd 需要):
      1
      ssh-keygen -A
    • 开启 sshd 自启并启动它:
      1
      2
      sysrc sshd_enable=YES
      service sshd start
    • 创建一个用于外网备份的普通用户(绝对不要用 root 跑外网 rsync):
      1
      2
      3
      # 创建名为 rsync_user 的用户,专门用于外网备份
      pw useradd rsync_user -m -s /bin/sh
      passwd rsync_user # 为其设置一个极其复杂的强密码
    • 退出 jail
      1
      exit
  • 在宿主机修改 PF 防火墙(开放外网非标端口)
    我们需要在宿主机上挑一个极不容易被扫描到的非标端口(例如 42022),将其映射到 web_jail 内部的 22 端口。
    • 打开宿主机的 /etc/pf.conf:
      1
      ee /etc/pf.conf
    • 增加一条允许来自任何外网(any)访问 42022 的转发规则:
      1
      2
      # add ssh forward rule, any host's 42022 forward to web jail ssh port 22
      rdr on $ext_if proto tcp from any to ($ext_if) port 42022 -> $web_jail port 22
    • 重载防火墙:
      1
      service pf restart
  • 为外网备份机配置 ssh 密钥登录
    把 ssh 端口暴露给外网会面临暴力破解风险。最佳方案是禁用密码,改用公钥认证。
    • 在您的外网备份机上,生成一对密钥(如果已有则跳过):
      1
      ssh-keygen -t ed25519
    • 将外网备份机的公钥(~/.ssh/id_ed25519.pub 的内容),复制并写入到 web_jail 内部刚刚创建的用户的授权文件中。
      在宿主机上快速操作的命令如下:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      # 创建目标文件夹
      mkdir -p /usr/local/jails/web_jail/home/rsync_ext/.ssh

      # 将您的外网机公钥粘贴进该文件
      ee /usr/local/jails/web_jail/home/rsync_ext/.ssh/authorized_keys

      # 修正权限(SSH 对权限要求极严,否则无法登录)
      chown -R 1002:1002 /usr/local/jails/web_jail/home/rsync_ext/.ssh # 如果 rsync_user 的 UID 不是 80 请对应修改
      chmod 700 /usr/local/jails/web_jail/home/rsync_ext/.ssh
      chmod 600 /usr/local/jails/web_jail/home/rsync_ext/.ssh/authorized_keys
  • 在外网备份机上执行公网 rsync
    此时,所有的安全链路已经搭建完毕。在外网的备份机上,你不再需要像局域网那样使用双冒号 :: 模式,而是直接使用标准基于 ssh 的 rsync 命令。由于宿主机的 ip 是动态的,这里直接使用您之前做好的 DDNS 域名。在外网备份机上执行以下命令:
    1
    rsync -ae "ssh -p 42022" rsync_user@your_ddns_domain_or_your_ip_address:/usr/local/www/mywebsite/ /your_backup_path/