跳至内容

第二部分.1 Web 服务器 Apache

Apache

在本章中,您将了解 Web 服务器 Apache。


目标:您将学会如何

✔ 安装和配置 Apache

🏁 apache, http, httpd

知识⭐ ⭐
复杂度⭐ ⭐

阅读时间: 30 分钟


概述

Apache HTTP 服务器是志愿者团队 Apache Group 的工作成果。该团队旨在构建一个与商业产品同等水平但作为免费软件(其源代码可用)的 Web 服务器。

成百上千的用户加入了最初的团队,并贡献了想法、测试和代码,使得 Apache 成为世界上使用最广泛的 Web 服务器。

Apache 的前身是伊利诺伊大学国家超级计算应用中心开发的无障碍服务器。当负责人于 1994 年离开 NCSA 时,该服务器的演变停止了。用户继续修复 bug 并创建扩展,然后分发为“补丁”,因此得名“a patchee server”。

Apache 1.0 版本发布于 1995 年 12 月 1 日(30 多年前!)。

开发团队通过邮件列表协调工作,在此期间会讨论软件的提案和更改。更改在合并到项目之前会进行投票。任何人都可以加入开发团队。要成为 Apache Group 的一员,您必须积极为项目做出贡献。

Apache 服务器拥有强大的互联网影响力,在所有活跃网站的市场份额中占有约 50% 的份额。

Apache 经常因其最大的竞争对手 Nginx 服务器而失去市场份额。后者在提供网页方面速度更快,但功能不如巨头 Apache 完善。

安装

Apache 是跨平台的。它可以在 Linux、Windows、Mac 等系统上使用……

管理员将必须在两种安装方法之间进行选择

  • 软件包安装:发行版供应商提供稳定、受支持(但有时较旧)的版本

  • 从源代码安装:这涉及到管理员编译软件,他可以指定他或她感兴趣的选项,从而优化服务。由于 Apache 具有模块化架构,因此通常无需重新编译 Apache 软件即可添加或删除其他功能(添加或删除模块)。

强烈推荐基于软件包的安装方法。额外的存储库可用于在旧发行版上安装更新版本的 Apache,但没有人会在出现问题时提供支持。

在 Enterprise Linux 发行版上,httpd 包提供了 Apache 服务器。

将来,您可能需要安装一些额外的模块。以下是一些模块及其角色的示例

  • mod_access:按主机名、IP 地址或其他特征过滤客户端访问
  • mod_alias:允许创建别名或虚拟目录
  • mod_auth:认证客户端
  • mod_cgi:执行 CGI 脚本
  • mod_info:提供服务器状态信息
  • mod_mime:将文件类型与相应操作关联
  • mod_proxy:提供代理服务器
  • mod_rewrite:重写 URL
  • 其他
sudo dnf install httpd

安装在 Rocky Linux 9 上的版本是 2.4。

安装软件包会创建一个 apache 系统用户和相应的 apache 系统组。

$ grep apache /etc/passwd
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
$ grep apache /etc/group
apache:x:48:

启用并启动服务

$ sudo systemctl enable httpd --now
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service  /usr/lib/systemd/system/httpd.service.

您可以检查服务的状态

$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
     Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabl>     Active: active (running) since Fri 2024-06-21 14:22:34 CEST; 8s ago
       Docs: man:httpd.service(8)
   Main PID: 4387 (httpd)
     Status: "Started, listening on: port 80"
      Tasks: 177 (limit: 11110)
     Memory: 24.0M
        CPU: 68ms
     CGroup: /system.slice/httpd.service
             ├─4387 /usr/sbin/httpd -DFOREGROUND
             ├─4389 /usr/sbin/httpd -DFOREGROUND
             ├─4390 /usr/sbin/httpd -DFOREGROUND
             ├─4391 /usr/sbin/httpd -DFOREGROUND

不要忘记打开防火墙(请参阅安全部分)。

现在您可以检查服务的可用性

  • 从任何提供服务器 IP 地址的 Web 浏览器(例如,http://192.168.1.100/)。
  • 直接从您的服务器。

为此,您必须安装一个文本浏览器,例如 elinks。

sudo dnf install elinks

浏览您的服务器并检查默认页面

elinks https://

安装 httpd 包会生成一个需要完全理解的完整树状结构

/etc/httpd/
├── conf
│   ├── httpd.conf
│   └── magic
├── conf.d
│   ├── README
│   ├── autoindex.conf
│   ├── userdir.conf
│   └── welcome.conf
├── conf.modules.d
│   ├── 00-base.conf
│   ├── 00-brotli.conf
│   ├── 00-dav.conf
│   ├── 00-lua.conf
│   ├── 00-mpm.conf
│   ├── 00-optional.conf
│   ├── 00-proxy.conf
│   ├── 00-systemd.conf
│   ├── 01-cgi.conf
│   ├── 10-h2.conf
│   ├── 10-proxy_h2.conf
│   └── README
├── logs -> ../../var/log/httpd
├── modules -> ../../usr/lib64/httpd/modules
├── run -> /run/httpd
└── state -> ../../var/lib/httpd
/var/log/httpd/
├── access_log
└── error_log
/var/www/
├── cgi-bin
└── html

您会注意到 /etc/httpd/logs 文件夹是 /var/log/httpd 目录的符号链接。同样,您会注意到构成默认站点的文件位于 /var/www/html 文件夹中。

配置

最初,Apache 服务器的配置位于一个单独的 /etc/httpd/conf/httpd.conf 文件中。随着时间的推移,这个文件变得越来越重要,可读性也越来越差。

因此,现代发行版倾向于将 Apache 配置分布在 /etc/httpd/conf.d/etc/httpd/conf.modules.d 目录中的一系列 *.conf 文件中,通过 Include 指令附加到主 /etc/httpd/conf/httpd.conf 文件。

$ sudo grep "^Include" /etc/httpd/conf/httpd.conf
Include conf.modules.d/*.conf
IncludeOptional conf.d/*.conf

/etc/httpd/conf/httpd.conf 文件有大量的文档。通常,这些注释足以阐明管理员的选项。

全局服务器配置位于 /etc/httpd/conf/httpd.conf

此文件包含三个配置部分

  • 第一节,全局环境;
  • 第二节,默认站点和默认虚拟站点的参数;
  • 第三节,虚拟主机。

虚拟托管允许您在同一服务器上在线托管多个虚拟站点。然后根据其域名、IP 地址等来区分站点。

修改第一节或第二节中的值会影响所有托管的站点。

在共享环境中,修改因此在第三节中进行。

为方便将来的更新,强烈建议为每个虚拟站点创建一个第三节的配置文件。

这是 httpd.conf 文件的最小版本

ServerRoot "/etc/httpd"
Listen 80
Include conf.modules.d/*.conf
User apache
Group apache
ServerAdmin root@localhost
<Directory />
    AllowOverride none
    Require all denied
</Directory>
DocumentRoot "/var/www/html"
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>
<Files ".ht*">
    Require all denied
</Files>
ErrorLog "logs/error_log"
LogLevel warn
<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog "logs/access_log" combined
</IfModule>
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>
<IfModule mime_module>
    TypesConfig /etc/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    AddType text/html .shtml
    AddOutputFilter INCLUDES .shtml
</IfModule>
AddDefaultCharset UTF-8
<IfModule mime_magic_module>
    MIMEMagicFile conf/magic
</IfModule>
EnableSendfile on
IncludeOptional conf.d/*.conf

第一节

第一节中遇到的各种指令是

选项 信息
ServerTokens 此指令将在未来的章节中介绍。
ServertRoot 指示包含构成 Apache 服务器的所有文件的目录的路径。
Timeout 请求超时前的秒数(入站或出站)。
KeepAlive 持久连接(每个 TCP 连接有多个请求)。
MaxKeepAliveRequests 最大持久连接数。
KeepAliveTimeout 在关闭 TCP 连接之前等待下一个客户端请求的秒数。
Listen 允许 Apache 监听特定地址或端口。
LoadModule 加载附加模块(模块越少 = 安全性越高)。
Include 包含其他服务器配置文件。
ExtendedStatus 在服务器状态模块中显示有关服务器的更多信息。
UserGroup 允许使用不同的用户启动 Apache 进程。Apache 始终以 root 身份启动,然后更改其所有者和组。
多进程模块 (MPM)

Apache 服务器被设计成强大而灵活,能够运行在各种平台上。

不同的平台和环境通常意味着不同的功能或使用其他方法来尽可能高效地实现相同的功能。

Apache 的模块化设计允许管理员通过选择在编译或运行时加载哪些模块来选择在服务器中包含哪些功能。

这种模块化还包括最基本的 Web 服务器功能。

多进程模块 (MPM) 模块负责与机器的网络端口关联、接受请求并将它们分发给各种子进程。

MPM 模块的配置在 /etc/httpd/conf.modules.d/00-mpm.conf 配置文件中

# Select the MPM module which should be used by uncommenting exactly
# one of the following LoadModule lines.  See the httpd.conf(5) man
# page for more information on changing the MPM.

# prefork MPM: Implements a non-threaded, pre-forking web server
# See: https://httpd.apache.ac.cn/docs/2.4/mod/prefork.html
#
# NOTE: If enabling prefork, the httpd_graceful_shutdown SELinux
# boolean should be enabled, to allow graceful stop/shutdown.
#
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

# worker MPM: Multi-Processing Module implementing a hybrid
# multi-threaded multi-process web server
# See: https://httpd.apache.ac.cn/docs/2.4/mod/worker.html
#
#LoadModule mpm_worker_module modules/mod_mpm_worker.so

# event MPM: A variant of the worker MPM with the goal of consuming
# threads only for connections with active processing
# See: https://httpd.apache.ac.cn/docs/2.4/mod/event.html
#
LoadModule mpm_event_module modules/mod_mpm_event.so

如您所见,默认的 MPM 是 mpm_event

您的 Web 服务器的性能和功能很大程度上取决于 MPM 的选择。

选择一个模块而不是另一个模块是一项复杂任务,优化选定的 MPM 模块(客户端数量、查询等)也是如此。

Apache 配置默认假定一个中等繁忙的服务(最多 256 个客户端)。

关于 keepalive 指令

KeepAlive 指令禁用时,服务器上的每个资源请求都需要打开一个 TCP 连接,这从网络角度来看非常耗时,并且需要大量系统资源。

KeepAlive 指令设置为 On 时,服务器会在 KeepAlive 持续时间内保持与客户端的连接打开。

这种策略是一个快速的赢家,因为网页包含多个文件(图像、样式表、Javascript 等)。

但是,将此值设置得尽可能精确很重要

  • 值太短会损害客户,
  • 值太长会损害服务器资源。

每个客户虚拟主机的 KeepAlive 值允许每个客户有更高的粒度。在这种情况下,设置 KeepAlive 值直接在客户的 VirtualHost 中或在代理级别(ProxyKeepaliveProxyKeepaliveTimeout)进行。

第二节

第二节设置了主服务器使用的值。主服务器响应第三节中任何虚拟主机未处理的所有请求。

这些值也用作虚拟站点的默认值。

选项 信息
ServerAdmin 指定在某些自动生成的页面(例如错误页面)上显示的电子邮件地址。
ServerName 指定标识服务器的名称。它可以自动发生,但建议明确指定(IP 地址或 DNS 名称)。
DocumentRoot 指定包含要为客户端提供服务的目录。默认 /var/www/html/。
ErrorLog 指定错误文件的路径。
LogLevel debug, info, notice, warn, error, crit, alert, emerg。
LogFormat 定义特定的日志格式。通过 CustomLog 指令完成。
CustomLog 指定访问文件的路径。
ServerSignature 在安全部分看到。
Alias 指定树外的一个目录,并使其可以通过上下文访问。最后一个斜杠是否存在很重要。
Directory 按目录指定行为和访问权限。
AddDefaultCharset 指定发送页面的编码格式(带重音的字符可能会被替换为 ?...)。
ErrorDocument 自定义错误页面。
server-status 服务器状态报告。
server-info 服务器配置报告。
ErrorLog 指令

ErrorLog 指令定义要使用的错误日志。

此指令定义服务器记录其遇到的所有错误的文件的名称。如果文件路径不是绝对路径,则假定为相对于 ServerRoot。

DirectoryIndex 指令

DirectoryIndex 指令定义站点的首页。

此指令指定首先加载的文件名,该文件将充当站点索引或主页。

语法

DirectoryIndex display-page

未指定完整路径。文件搜索发生在 DocumentRoot 指定的目录中。

示例

DocumentRoot /var/www/html
DirectoryIndex index.php index.htm

此指令指定网站索引文件的名称。索引是当客户端键入网站 URL(无需键入索引名称)时打开的默认页面。此文件必须位于 DocumentRoot 指令指定的目录中。

DirectoryIndex 指令可以指定多个以空格分隔的索引文件名。例如,一个带有动态内容的默认索引页,以及作为第二个选择的静态页。

Directory 指令

Directory 标签用于定义特定于目录的指令。

此标签将权限应用于一个或多个目录。目录路径以绝对路径输入。

语法

<Directory directory-path>
Defining user rights
</Directory>

示例

<Directory /var/www/html/public>
    Require all granted   # we allow everyone
</Directory>

Directory 部分定义了一个指令块,该块应用于服务器文件系统的一部分。这里的指令将仅适用于指定的目录(及子目录)。

此块的语法接受通配符,但首选使用 DirectoryMatch 块。

在下面的示例中,我们将拒绝访问服务器的本地硬盘驱动器,无论客户端如何。 “/”目录代表硬盘驱动器的根目录。

<Directory />
    Require all denied
</Directory>

以下示例显示了授权访问所有客户端的“/var/www/html”发布目录。

<Directory /var/www/html>
    Require all granted
</Directory>

当服务器找到 .htaccess 文件时,它需要知道文件中放置的指令是否有权修改预先存在的配置。AllowOverride 指令控制 Directory 指令中的授权。当设置为 none 时,.htaccess 文件将被完全忽略。

mod_status

mod_status 显示一个 /server-status/server-info 页面,总结服务器状态

<Location /server-status>
    SetHandler server-status
    Require local
</Location>

<Location /server-info>
    SetHandler server-info
    Require local
</Location>

请注意,此模块提供的信息不应向您的用户公开。

共享托管 (第三节)

在共享托管中,客户认为他们正在访问多个服务器。实际上,只有一个服务器和多个虚拟站点。

要设置共享托管,您需要设置虚拟主机

  • 声明多个监听端口
  • 声明多个监听 IP 地址(按 IP 虚拟托管)
  • 声明多个服务器名称(按名称虚拟托管)

每个虚拟站点对应一个不同的树状结构。

httpd.conf 文件的第三节声明了这些虚拟主机。

强烈建议您为每个虚拟站点创建一个第三节的配置文件,以方便将来的更新。

选择“按 IP”或“按名称”的虚拟托管。不建议在生产环境中使用混合这两种解决方案。

  • 在独立的配置文件中配置每个虚拟站点
  • VirtualHosts 存储在 /etc/httpd/conf.d/
  • 文件扩展名为 .conf
VirtualHost 指令

VirtualHost 指令定义虚拟主机。

<VirtualHost IP-address[:port]>
    # if the "NameVirtualHost" directive is present
    # then "address-IP" must match the one entered
    # under "NameVirtualHost" as well as for "port".
 ...
 </VirtualHost>

如果您使用上面介绍的基本指令配置 Apache 服务器,您只能发布一个站点。事实上,您不能在默认设置下发布多个站点:相同的 IP 地址、相同的 TCP 端口,并且没有主机名或唯一主机名。

虚拟站点将使我们能够在同一个 Apache 服务器上发布多个网站。您将定义块,每个块描述一个网站。这样,每个站点将拥有自己的配置。

为了便于理解,一个网站通常与一台机器相关联。虚拟站点或主机之所以这样称呼,是因为它们消除了机器和网站之间的联系。

示例 1

Listen 192.168.0.10:8080
<VirtualHost 192.168.0.10:8080>
  DocumentRoot /var/www/site1/
  ErrorLog /var/log/httpd/site1-error.log
</VirtualHost>

Listen 192.168.0.11:9090
<VirtualHost 192.168.0.11:9090>
  DocumentRoot /var/www/site2/
  ErrorLog /var/log/httpd/site2-error.log
</VirtualHost>

基于 IP 的虚拟托管根据接收请求的 IP 地址和端口应用特定的指导方针。这通常意味着在不同的端口或接口上提供不同的网站。

NameVirtualHost 指令

NameVirtualHost 指令定义基于名称的虚拟主机。

此指令对于设置基于名称的虚拟主机是必需的。使用此指令,您可以指定服务器将在其上接收来自基于名称的虚拟主机的请求的 IP 地址。

语法

NameVirtualHost adresse-IP[:port]

示例

NameVirtualHost 160.210.169.6:80

该指令必须出现在虚拟站点描述块之前。它指定用于监听虚拟主机客户端请求的 IP 地址。

要监听服务器的所有 IP 地址上的请求,请使用 * 字符。

考虑更改

对于每个配置更改,都有必要使用以下命令重新加载配置

sudo systemctl reload httpd

手册

一个名为 'httpd-manual' 的包包含一个充当 Apache 用户手册的站点。

sudo dnf install httpd-manual
sudo systemctl reload httpd

安装后,您可以使用 Web 浏览器访问 http://127.0.0.1/manual 上的手册。

$ elinks http://127.0.0.1/manual

apachectl 命令

apachectl 是 Apache httpd 服务器的服务器控制接口。

它是一个非常有用的命令,带有 -tconfigtest 选项,可以测试配置文件语法。

注意

在使用 Ansible handler 测试配置时,它非常有用。

安全性

当您用防火墙保护服务器时(这是好事),您可能需要考虑打开它。

sudo firewall-cmd --zone=public --add-service=http
sudo firewall-cmd --zone=public --add-service=https
sudo firewall-cmd --reload

SELinux

默认情况下,如果 SELinux 安全处于活动状态,它会阻止从 /var/www/ 以外的目录读取站点。

包含站点的目录必须具有 httpd_sys_content_t 安全上下文。

您可以使用以下命令检查当前上下文

* ls -Z /dir

使用以下命令添加上下文

sudo chcon -vR --type=httpd_sys_content_t /dir

它还阻止打开非标准端口。打开端口是使用 semanage 命令的手动操作(默认未安装)。

sudo semanage port -a -t http_port_t -p tcp 1664

User 和 Group 指令

UserGroup 指令定义了一个 Apache 管理帐户和组。

历史上,root 运行 Apache,这导致了安全问题。root 始终运行 Apache,但随后更改了它的身份。通常是 User apache 和 Group apache

绝不 ROOT!

Apache 服务器(httpd 进程)以 root 超级用户帐户启动。每个客户端请求都会触发创建一个“子”进程。为了限制风险,这些子进程是从权限较低的帐户启动的。

User 和 Group 指令声明用于创建子进程的帐户和组。

此帐户和组必须存在于系统中(默认情况下,这会在安装过程中完成)。

文件权限

作为一般安全规则,Web 服务器内容不得属于运行服务器的进程。在我们的例子中,文件不应属于 apache 用户和组,因为它对文件夹具有写入访问权限。

您将内容分配给特权较低的用户、root 用户和关联的组。顺便说一句,您还借此机会限制了组的访问权限。

cd /var/www/html
sudo chown -R root:root ./*
sudo find ./ -type d -exec chmod 0755 "{}" \;
sudo find ./ -type f -exec chmod 0644 "{}" \;

作者:Antoine Le Morvan

贡献者:Steven Spencer, Ganna Zhyrnova