第 2.1 部分 Web 服务器 Apache
Apache¶
在本章中,您将学习关于 web 服务器 Apache 的知识。
目标:您将学习如何
安装和配置 Apache
apache、http、httpd
知识:
复杂度:
阅读时间: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中进行,或者在代理级别进行(ProxyKeepalive
和ProxyKeepaliveTimeout
)。
部分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
服务器的服务器控制接口。
这是一个非常有用的命令,可以使用 -t
或 configtest
运行配置文件语法测试。
注意
与 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
用户和组指令 ¶
User
和 Group
指令定义 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