跳至内容

第 2.1 部分 Web 服务器 Apache

Apache

在本章中,您将学习关于 web 服务器 Apache 的知识。


目标:您将学习如何

✔ 安装和配置 Apache

🏁 apachehttphttpd

知识⭐ ⭐
复杂度⭐ ⭐

阅读时间:30 分钟


概述

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

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

Apache 的祖先是伊利诺伊大学国家超级计算应用中心开发的可访问服务器。当负责人于 1994 年离开 NCSA 时,该服务器的发展停止。用户继续修复错误并创建扩展,他们将其作为“补丁”分发,因此被称为“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 http://localhost

安装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中。

该文件包含三个部分,用于配置

  • 在**部分1**中,全局环境;
  • 在**部分2**中,默认站点和默认虚拟站点参数;
  • 在**部分3**中,虚拟主机。

**虚拟主机**允许您在同一服务器上将**多个虚拟站点上线**。然后根据这些站点的域名、IP地址等进行区分。

修改部分1或2中的值会影响所有托管的站点。

因此,在共享环境中,修改是在部分3中进行的。

为了方便以后的更新,强烈建议为每个虚拟站点创建一个部分3配置文件。

以下是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

部分1

部分1中遇到的各种指令是

选项信息
ServerTokens该指令将在后面的章节中介绍。
ServertRoot指示包含构成Apache服务器的所有文件的目录的路径。
超时请求超时(传入或传出)之前的秒数。
保持活动持久连接(每个TCP连接有多个请求)。
MaxKeepAliveRequests持久连接的最大数量。
KeepAliveTimeout在关闭TCP连接之前等待下一个客户端请求的秒数。
监听允许Apache监听特定的地址或端口。
LoadModule加载附加模块(模块越少,安全性越高)。
包括包含其他服务器配置文件。
ExtendedStatus在服务器状态模块中显示有关服务器的更多信息。
用户允许使用不同的用户启动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指令后,服务器上的每个资源请求都需要打开一个TCP连接,这从网络的角度来看非常耗时,并且需要大量的系统资源。

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

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

但是,务必尽可能精确地设置此值

  • 值过短会影响客户体验,
  • 值过长会影响服务器资源。

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

部分2

部分2设置主服务器使用的值。主服务器响应所有未由部分3中的Virtualhosts之一处理的请求。

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

选项信息
ServerAdmin指定出现在某些自动生成页面(如错误页面)上的电子邮件地址。
ServerName指定标识服务器的名称。它可以自动发生,但建议明确指定它(IP地址或DNS名称)。
DocumentRoot指定包含要提供给客户端的文件的目录。默认情况下为/var/www/html/。
ErrorLog指定错误文件的路径。
LogLevel调试、信息、通知、警告、错误、严重、警报、紧急。
LogFormat定义特定的日志格式。使用CustomLog指令完成。
CustomLog指定访问文件的路径。
ServerSignature在安全部分中可见。
别名指定树之外的目录,并使其通过上下文访问。上下文中最后一个斜杠的存在或不存在很重要。
目录按目录指定行为和访问权限。
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>

请注意,此模块提供的信息不应让您的用户访问。

共享主机 (部分3)

使用共享主机时,客户会认为他们访问了多个服务器。实际上,只有一台服务器和多个虚拟站点。

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

  • 声明多个监听端口
  • 声明多个监听IP地址(按IP进行虚拟主机)
  • 声明多个服务器名称(按名称进行虚拟主机)

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

httpd.conf文件的第3部分声明了这些虚拟主机。

强烈建议您为每个虚拟站点创建一个第3部分配置文件,以方便以后的更新。

选择“按IP”或“按名称”进行虚拟主机。混合使用两种解决方案不建议在生产环境中使用。

  • 在独立的配置文件中配置每个虚拟站点
  • 虚拟主机存储在 /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

安装后,您可以通过网络浏览器访问 http://127.0.0.1/manual 查看手册。

$ elinks http://127.0.0.1/manual

apachectl 命令

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

这是一个非常有用的命令,可以使用 -tconfigtest 运行配置文件语法测试。

注意

与 Ansible 处理程序一起使用时非常有用,可以测试配置。

安全性

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

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

用户和组指令

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