Linux 服务器安全加固技术(7)
原创
寰宇秘阁
寰宇秘阁
寰宇密阁
2026年10月8日 14:00
安徽
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
引言
谈到 Web 服务器安全,很多管理员的第一反应是加固 Apache 或 nginx 本身。然而现实中,真正的威胁往往不在服务器软件层面,而在其上承载的 Web 应用和后端数据库。Apache 或 nginx 即便偶尔曝出严重漏洞(尤其是加密相关的缺陷),通常也能在短时间内获得补丁并随发行版更新迅速分发。但 WordPress、Joomla、Nextcloud、phpMyAdmin 这类 Web 应用的安全维护则是另一番景象——它们不属于系统包管理器的管辖范围,没有自动更新机制,更新流程复杂且容易被忽视。
本文聚焦两大核心安全主题:HTTPS 传输加密的正确配置和数据库(MySQL/MariaDB)的安全加固。文章将从证书获取、Apache 配置到数据库认证体系、权限管理、网络隔离,给出完整的理论讲解和实操指南,同时对比 RHEL 系与 Debian/Ubuntu 系的差异。
一、Web 应用安全的常见问题
在进入 HTTPS 和数据库的具体配置之前,有必要先审视 Web 应用层面的安全现状。
框架安装后不更新。 无论是 PHP 生态的 Zend Framework、JavaScript 生态的 Node.js,还是 Java 生态的 Spring MVC,开发团队往往在项目初期安装一次框架就再也不碰了。原因很现实——担心升级引发兼容性问题。但旧版本框架中的已知漏洞恰恰是攻击者最喜欢的突破口。
Web 应用缺乏自动更新机制。 与通过 apt 或 dnf 管理的系统软件不同,手动安装的 Web 应用需要手动更新。问题在于\"没人觉得这是自己的事\":系统管理员认为 Web 应用不属于自己的 Linux 基础设施范畴,CMS 内容管理者则认为自己只负责内容而非软件维护。这种责任界定的模糊地带,往往导致漏洞长期暴露。
建立明确的安全责任机制至关重要。 企业管理层或安全负责人需要明确定义谁负责 Web 应用的更新维护,并建立管理员与应用使用者之间的沟通渠道。例如,即便 Nextcloud 的日常用户不负责执行更新,当 Web 界面提示有新版本时,至少应该通知管理员。
善用安全插件。 许多主流 Web 应用提供安全增强插件。以 WordPress 为例,Wordfence Security 插件(基础版免费)能提供登录暴力破解防护、基本的应用层防火墙功能,以及异常事件邮件告警。这类插件不能替代系统层面的安全措施,但能显著提升应用自身的防御能力。
二、证书类型与获取
HTTPS 加密的基础是数字证书。根据获取方式,证书大致分为三类:
2.1 自签名证书
使用 openssl 工具可以自行生成证书。自签名证书的加密质量与其他证书完全相同,但由于签发者不是国际认可的证书颁发机构(CA),浏览器会显示醒目的安全警告。这种证书适合内部测试或开发环境,但不适合面向公众的生产站点。
需要注意的是,任何人都可以用 openssl 为任意域名生成证书——包括 my.us-bank.com 这样的敏感域名。这正是浏览器必须验证证书签发者的原因。
2.2 Let’s Encrypt 免费证书
Let’s Encrypt 项目彻底改变了证书的获取门槛。它提供免费的域名验证(Domain Validation, DV)证书。在签发过程中,Let’s Encrypt 服务器会验证申请者确实控制着目标域名——如果你无法证明对域名的所有权,签发就会失败。
生成和续期证书需要客户端工具。相比早期流行的 certbot,acme.sh(https://github.com/acmesh-official/acme.sh)在实际使用中表现更为稳定可靠。除了 Let’s Encrypt,类似的免费证书项目还有 ZeroSSL 等,部分主机商也开始提供来自不同 CA 的免费证书。
Let’s Encrypt 的安全边界。 DV 证书能保证签发者确实拥有该域名,攻击者无法为 my.us-bank.com 申请到 Let’s Encrypt 证书。但攻击者可以注册一个视觉上极为相似的域名(如 us-bánk.com,注意其中的特殊字符 á),为其申请合法的 DV 证书,然后通过钓鱼邮件将受害者引导至该站点。DV 证书无法防御这类国际化域名(IDN)钓鱼攻击。
2.3 商业证书
Thawte、Symantec(原 Verisign)等商业 CA 提供付费证书。购买商业证书的费用实际上并非为加密本身付费,而是为更严格的身份验证流程付费。CA 会核验企业注册信息和相关文件,这种验证分为两个级别:
– 组织验证(Organization Validation, OV): 验证申请者所属的组织确实存在且合法。
– 扩展验证(Extended Validation, EV): 更为严格的验证流程,浏览器会显示绿色锁标或企业名称,向用户提供更高的信任信号。
三种证书的加密质量完全相同(在正确配置的前提下),区别仅在于身份验证的严格程度。选择哪种证书取决于业务需求:个人博客用 Let’s Encrypt 足矣,银行或电商平台则可能需要 EV 证书来增强用户信任。
三、证书文件组成
无论证书来源如何,一套完整的证书由以下文件组成,内容均为十六进制编码的文本,需要 openssl 等工具才能解读:
| 文件 | 说明 |
|---|---|
company-abc.pem 或 .crt |
证书文件本身,包含公钥和域名信息 |
chain.pem |
证书链文件,包含中间 CA 的证书,用于建立从你的证书到根 CA 的信任链 |
fullchain.pem |
证书和证书链的合并文件,可替代上述两个文件 |
company-abc.key 或 privkey.pem |
私钥文件,必须严格保密 |
私钥文件是整个证书体系中最敏感的部分。一旦泄露,攻击者可以解密所有使用该证书加密的通信。务必设置严格的文件权限,仅允许 root 和 Web 服务器进程读取。
四、Apache HTTPS 配置
4.1 启用 mod\_ssl 模块
Apache 的 HTTPS 功能依赖 mod_ssl 模块。不同发行版的启用方式有所不同。
Ubuntu/Debian: mod_ssl 已默认安装,只需激活:
a2enmod ssl
systemctl restart apache2
RHEL 及其衍生版: 需要先安装 SSL 模块:
dnf install mod_ssl
systemctl restart httpd
4.2 部署证书文件
Apache 需要读取证书和私钥文件。通常的做法是将文件复制到 Apache 配置目录下:
# Debian/Ubuntu
cp company-abc.pem chain.pem company-abc.key /etc/apache2/
# RHEL
cp company-abc.pem chain.pem company-abc.key /etc/httpd/
Let’s Encrypt 证书例外: 由于 Let’s Encrypt 证书有效期仅 90 天,客户端工具会在到期前自动续期。因此不应复制这些文件,而应让 Apache 直接引用 /etc/letsencrypt 目录下的原始路径,这样续期后无需手动更新配置。
4.3 VirtualHost 配置示例
接下来需要在 Apache 配置中添加 HTTPS 站点。配置文件的位置因发行版而异:
– RHEL: /etc/httpd/conf.d/ssl.conf
– Ubuntu: /etc/apache2/sites-available/company-abc-ssl.conf(可参考默认的 default-ssl.conf 模板)
以下是一个最小化的 HTTPS VirtualHost 配置示例,与默认的 HTTP 站点并行运行,通过端口 443 进行区分:
# RHEL: /etc/httpd/conf.d/ssl.conf
# Ubuntu: /etc/apache2/sites-available/company-abc-ssl.conf
<VirtualHost *:443>
ServerName www.company-abc.de
DocumentRoot /var/www/
SSLEngine on
SSLCertificateFile /etc/apache2/company-abc.fullchain.pem
SSLCertificateKeyFile /etc/apache2/company-abc.key
<Directory /var/www/>
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
关键指令说明:
– SSLEngine on:激活 SSL/TLS 加密功能。
– SSLCertificateFile:指定证书文件路径。如果使用 fullchain.pem,则无需单独指定证书链。
– SSLCertificateKeyFile:指定私钥文件路径。
4.4 启用站点并重启服务
配置完成后,需要让 Apache 加载新配置。首次启用 HTTPS 时必须使用 restart 而非 reload:
# RHEL
systemctl restart httpd
# Ubuntu(需要先启用站点配置文件)
a2ensite company-abc-ssl
systemctl restart apache2
五、HTTPS 安全最佳实践
仅仅启用 HTTPS 并不够。HTTPS 涵盖了众多协议版本和加密套件,其中不少已经过时甚至存在已知漏洞。浏览器和服务器在建立连接时会协商使用双方都支持的\"最安全\"的方式,但攻击者的策略恰恰相反——他们会探测你的服务器仍然支持的\"最不安全\"的协议,然后利用其弱点发起攻击。
5.1 SSLCipherSuite 和 SSLProtocol
通过 SSLCipherSuite 和 SSLProtocol 指令,可以明确指定服务器接受哪些加密方法、拒绝哪些。这能有效提升安全性,代价是可能导致极老旧的浏览器无法连接——但在当今环境下,这通常是可以接受的取舍。
5.2 Mozilla SSL Configuration Generator
手动编写 SSLCipherSuite 字符串既冗长又容易出错。Mozilla 提供了一个在线工具 SSL Configuration Generator(http://s-prs.co/v5696118),只需选择 Web 服务器类型和目标安全级别,即可自动生成配置。
5.3 SSLPolicy 简化配置
当前版本的 Apache 支持 SSLPolicy 关键字,可以用一行配置替代冗长的加密套件列表:
– SSLPolicy modern: 当前推荐的安全设置,适用于面向公众的 Web 服务器。
– SSLPolicy intermediate: 折中方案,兼顾部分使用旧版浏览器的用户。
– SSLPolicy old: 兼容到 Windows XP / Internet Explorer 6 时代,但安全性极低,强烈不推荐。
5.4 SSL Server Test
配置完成后,务必使用 Qualys 的 SSL Server Test(https://www.ssllabs.com/ssltest)对站点进行安全评估。该工具会全面检测服务器的 HTTPS 配置,报告支持的协议版本、加密套件强度、证书有效性等,并给出优化建议和安全评级。
六、MySQL 与 MariaDB 概述
许多 Web 服务器将 MySQL 或 MariaDB 作为后端数据库。两者渊源颇深,但在安全配置方面存在显著差异,需要分别对待。
6.1 MariaDB 的诞生
MariaDB 是 MySQL 被 Oracle 收购后,由原始开发者创建的开源分支。早期两者完全兼容,但随着各自独立发展,功能差异越来越大,尤其在认证机制方面差异显著。这也导致安全配置的讨论需要针对不同的发行版和数据库版本分别展开。
6.2 发行版中的包提供情况
各主流发行版对 MySQL 和 MariaDB 的支持策略不同:
- 部分发行版仅默认提供 MariaDB。
- RHEL 和 Ubuntu 同时提供两者,但 Ubuntu 上的 MariaDB 包来自社区维护的 universe 源,没有官方更新保证。
- 默认包版本通常远落后于上游最新版。如果需要新版本,Oracle 为 MySQL 提供了官方包源(https://dev.mysql.com/downloads),MariaDB 也有类似的官方源。建议使用这些官方源,避免来路不明的第三方源。
七、数据库登录认证系统
MySQL 和 MariaDB 的认证体系支持两种方式,理解这一点是进行安全加固的基础。
7.1 方式一:用户名 + 主机名 + 密码
这是传统的认证方式。建立连接时,数据库服务器检查三个要素:
1、登录用户名(如 root、webapp)
2、连接来源主机(如 localhost、192.168.1.%)
3、密码
三者的组合必须与 mysql.user 表中的记录匹配,连接才会被允许。需要特别注意的是,数据库用户名与 Linux 系统用户名完全独立管理。数据库中的 root 用户只是恰好同名,并非 Linux 的 root 账户。
7.2 方式二:Linux 账户映射
这种方式建立了 Linux 系统账户与数据库用户之间的直接映射关系。最典型的场景是:Linux 的 root 用户登录后,可以直接以数据库 root 身份连接,无需额外输入密码。
其背后的技术实现有所不同:
– MySQL 使用 auth_socket 插件
– MariaDB 使用 unix_socket 插件
7.3 mysql.user 表
无论采用哪种认证方式,所有认证规则都存储在 mysql 数据库的 user 表中。这个表在安装时自动创建,定义了谁可以登录以及如何登录。管理员可以自由修改这张表,但关键问题是:安装后的默认配置是否安全?答案因发行版而异。
7.4 两阶段访问控制
重要概念:成功登录只是第一阶段。登录之后,权限(privileges)系统决定用户能执行哪些操作、能访问哪些数据库和表。这是一个两阶段的访问控制模型:先认证身份,再鉴定权限。
八、Debian/Ubuntu 上的默认安全配置
在当前版本的 Debian 和 Ubuntu 上,MySQL/MariaDB 服务器安装后的默认配置是安全的。
root 用户通过账户映射自动认证。 Linux root 用户可以直接运行 mysql 命令连接到数据库服务器,无需密码:
root# mysql
Server version: 8.0.29-0ubuntu0.22.04.2
...
mysql>exit
非 root 用户默认无法连接。 其他 Linux 用户无法连接到数据库服务器,这意味着默认配置不存在越权访问的风险。只有 root 才能创建额外的数据库用户。
创建额外的管理员账户。 在实际运维中,通常需要创建一个基于密码认证的管理员账户,以便非 root 用户也能进行数据库管理:
root# mysql
mysql> CREATE USER root2@localhost IDENTIFIED BY 'strenggeheim';
mysql> GRANT ALL ON *.* TO root2@localhost WITH GRANT OPTION;
mysql>exit
注意这里使用 root2 而非 root——覆盖默认的 root 配置会破坏账户映射机制。创建完成后,任何 Linux 用户都可以通过密码登录:
user$ mysql -u root2 -p
Enter password: *********
九、RHEL 上的 MySQL 安全加固
与 Debian/Ubuntu 形成鲜明对比,RHEL 8 和 9 上的 MySQL 安装后是不安全的(insecure by default)。任何能登录到 RHEL 服务器的用户,都可以通过 mysql -u root 获得数据库的完全管理权限,无需任何密码。
9.1 mysql\_secure\_installation
MySQL 提供了 mysql_secure_installation 命令来执行初始安全加固。以下是其交互流程:
mysql_secure_installation
There are three levels of password validation policy:
LOW Length >=8
MEDIUM Length >=8, numeric, mixed case, and special characters
STRONG Length >=8, numeric, mixed case, special characters, dictionary file
Please enter 0=LOW, 1=MEDIUM and 2=STRONG:
2
Please set the password for root here.
New password: ************
Re-enter new password: ************
Disallow root login remotely?
y
Remove test database and access to it?
y
Reload privilege tables now?
y
这个命令完成了几项关键的安全加固操作:
1、设置密码强度策略。 LOW 仅要求长度不少于 8 位;MEDIUM 要求包含数字、大小写字母和特殊字符;STRONG 在 MEDIUM 基础上增加字典文件校验,防止使用常见弱密码。
2、为 root 设置密码。 这是最关键的一步,消除了无密码登录的风险。
3、禁止远程 root 登录。 root 账户只能从 localhost 连接,攻击者无法从网络上直接尝试暴力破解 root 密码。
4、删除测试数据库。 安装时自动创建的 test 数据库及其宽松的访问权限被清除。
在 RHEL 上安装 MySQL 后,必须立即执行 mysql_secure_installation。这不是可选步骤。
十、RHEL 上的 MariaDB 安全加固
MariaDB 在 RHEL 上的安全状况取决于版本。
10.1 RHEL 9:默认安全
RHEL 9 上的 MariaDB 采用了与 Debian/Ubuntu 相同的安全策略——通过 Linux 账户映射进行认证,必须以 Linux root 身份才能以数据库 root 登录。默认配置是安全的。
10.2 RHEL 8:存在历史安全问题
RHEL 8 及其兼容衍生版(如 CentOS 8、Rocky Linux 8、AlmaLinux 8)上的 MariaDB 默认配置存在严重安全问题:root 用户没有密码,任何用户都可以获得数据库的 root 权限。
手动设置密码的方法如下:
user$ mysql -u root
mysql> UPDATE mysql.user SET password=PASSWORD('secret')
WHERE user='root' AND plugin='';
mysql> FLUSH PRIVILEGES;
mysql>exit
此后登录需要提供密码:
user$ mysql -u root -p
Enter password: ******
10.3 密码独立管理原则
Linux 系统密码和数据库密码是两套完全独立的体系。无论使用哪个发行版和数据库,绝对不要在两个系统中使用相同的密码。如果攻击者通过其中一个系统获取了密码,他不应该能借此进入另一个系统。
十一、密码哈希安全问题
当前版本的 MySQL 和 MariaDB 使用安全的哈希算法存储密码,但历史版本存在严重的安全缺陷,如果你仍在运行旧版本或从旧版本迁移,必须了解这些风险。
11.1 不安全的 SHA-1 哈希
MySQL 5.5 及更早版本、MariaDB 10.3 及更早版本使用已废弃的 SHA-1 方法生成密码哈希。其内部实现对应如下 SQL 表达式:
CONCAT('*', UPPER(SHA1(UNHEX(SHA1('secret')))))
过程是:对密码计算 SHA-1 哈希,将十六进制结果用 UNHEX 转换为二进制字符串,再对该字符串计算第二次 SHA-1 哈希,最后转大写并加上 * 前缀。
11.2 无 salt 的致命缺陷
这个方案最大的问题不仅是 SHA-1 本身已不再安全,更在于没有使用 salt(随机盐值)。没有 salt 意味着相同的密码永远产生相同的哈希值。例如,密码 secret 在所有 MySQL 和 MariaDB 数据库中的哈希都是 *462366917EEDD1970A48E87D8EF59EB67D2CA26F。
11.3 查找表攻击
这种确定性的映射关系使得查找表(lookup table)攻击成为可能。攻击者只需获取 mysql.user 表的内容(或其备份文件),就可以在 https://crackstation.net 等网站上查询已知哈希值对应的明文密码。如果查到的密码还被用于其他系统(如 Linux 登录),后果将是灾难性的。
补救措施: 如果你仍在运行这些旧版本,应尽快升级到当前版本;如果暂时无法升级,至少确保所有数据库密码都是高强度的随机密码,且不与其他系统共用。
十二、权限管理
成功登录数据库服务器只是第一步。登录之后,权限系统控制着用户能做什么。
12.1 GRANT 命令
在实际操作中,最常见的需求是为某个用户授予对特定数据库的完全访问权限。标准流程如下:
mysql> CREATE USER username@localhost IDENTIFIED BY 'totallysecret';
mysql> CREATE DATABASE newdatabase;
mysql> GRANT ALL ON newdatabase.* TO username@localhost;
这样 username 对 newdatabase 拥有完全权限,但无法访问其他数据库。
12.2 为备份创建只读账户
自动化备份场景中,最佳实践是使用权限最小化的专用账户,而非使用具有完全权限的管理员账户:
mysql> CREATE USER backupuser@localhost IDENTIFIED BY 'totallysecret';
mysql> GRANT Select, Show View, Lock Tables, Reload
ON newdatabase.* TO backupuser@localhost;
这个账户只拥有读取数据、查看视图、锁表和刷新权限——刚好满足 mysqldump 等备份工具的需求,即使账户凭据泄露,攻击者也无法修改或删除数据。
十三、服务器配置安全
除了认证和权限,数据库服务器本身的网络配置也是安全加固的重要环节。相关配置位于 [mysqld] 段中,修改后需要重启数据库服务才能生效。
配置文件位置因发行版而异:
– RHEL: /etc/my.cnf 和 /etc/my.cnf.d/*.conf
– Ubuntu: /etc/mysql/my.cnf、 /etc/mysql/conf.d/*.conf 和 /etc/mysql/mysql.conf.d/*.conf
13.1 bind-address = 127.0.0.1(限制本地访问)
这是最重要的网络安全配置之一:
[mysqld]
bind-address = 127.0.0.1
该设置确保数据库服务器只接受来自本机的连接,拒绝所有网络连接。如果 MySQL/MariaDB 仅供本机上的 PHP 脚本或其他本地应用使用(这是最常见的场景),强烈建议启用此设置。
Debian/Ubuntu 默认已启用此设置;RHEL 需要手动添加。
13.2 skip-networking(完全禁用网络)
比 bind-address = 127.0.0.1 更严格的选项:
[mysqld]
skip-networking
该设置彻底禁用所有网络连接,包括本地的 TCP/IP 连接。应用程序只能通过 Unix socket 文件与数据库通信。PHP 脚本和 C 程序通常支持 socket 连接,但所有 Java 程序都依赖 TCP/IP,无法在此配置下工作。因此在大多数场景中,bind-address = 127.0.0.1 是更实用的选择。
13.3 IPv6 连接控制
MySQL 和 MariaDB 默认拒绝 IPv6 连接。如果需要同时允许 IPv4 和 IPv6 连接:
[mysqld]
bind-address = ::
但仅修改 bind-address 还不够——还需要通过 GRANT 命令或直接修改 mysql.user 表的 host 列,为相应的 IPv6 地址授予访问权限。
13.4 防火墙与 Fail2ban
如果确实需要允许网络连接(移除 bind-address 限制),务必同时做好以下防护:
– 防火墙规则。 在 RHEL 和 SUSE 上,需要显式放行端口 3306,并通过防火墙规则限制允许连接的源 IP 范围。
– Fail2ban 集成。 配置 Fail2ban 来监控数据库的登录失败日志,自动封禁暴力破解的 IP 地址。Fail2ban 已经内置了 MySQL/MariaDB 的监控规则,但可能需要根据发行版做适当调整。
总结
Web 服务器安全是一个系统工程,仅靠加固 Apache 或 nginx 本身远远不够。本文从两个关键维度展开了讨论:
HTTPS 配置方面: 从证书获取到 Apache 配置,再到加密套件优化,核心要点包括——优先使用 Let’s Encrypt 免费证书降低成本门槛;正确配置 SSLEngine、SSLCertificateFile 和 SSLCertificateKeyFile 指令;通过 SSLPolicy 或 SSLCipherSuite 禁用不安全的协议版本;最后使用 SSL Server Test 验证配置。
数据库安全方面: MySQL 和 MariaDB 的安全加固需要关注认证体系、权限管理和网络隔离三个层面。特别需要注意不同发行版的默认安全状态差异——Debian/Ubuntu 默认安全,RHEL 上的 MySQL 则需要立即执行 mysql_secure_installation。权限配置遵循最小权限原则,网络配置优先使用 bind-address = 127.0.0.1 限制为本地访问。
安全从来不是一次性的工作。证书需要定期续期,数据库密码需要定期更换,密码哈希算法需要与时俱进。更重要的是,那些被忽视的 Web 应用和框架,可能才是整个系统中最薄弱的环节——建立明确的安全责任机制和更新流程,比任何单一技术手段都更为关键。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论