Chapter10 - 提供 Apache-httpd-web 服务
配置 Apache HTTPD
Apache HTTPD 简介
Apache HTTPD 是Internet 上使用最多的Web服务器之一。Web 服务器是一个用 http(s)协议进行交流的守护进程,这是一个基于文本的协议,用于通过网络连接来发送和接收对象。http 通过线路以明文形式发送,默认情况下使用端口 80/tcp (但可以使用其他端口)。此协议还有一个经 TLS/SSL 加密的版本,称为 https 。默认情况下使用端口 443/TCP 。
基本的 http 交换具有一个连接到服务器的客户端,然后使用 GET 命令来请求资源。存在诸如 HEAD 和 POST 之类 的其他命令。允许客户端仅请求资源的无数据,或者向服务器发送更多信息。
以下是一个简短的交换中提取的内容:

客户端首先请求一个资源(GET 命令),然后量些额外的报头,向服务器告知客户端接受的编码类型,其首选语言等等。请求以一个空行结尾。

服务器随后以一个状态码(HTTP/1.1 200 OK) (后跟报头的列表。Content-Type 报头是强制探出头,告知客户端正在发送的内容类型。在报送完成后,服务器发送一个空行,后跟请求的内容。此内容的长度必须与 Content-Length 报头中指示的长度相匹配。
尽管 http 协议起初看上去似乎很简单,但要实施全部协议内容,包括安全措施,支持未完全前遵循标准的客户端以及支持动态生成的页面,这并非易事。这就是为会大部分应用程序开发者不自己编写 Web 服务器,面是编写应用程序以在诸如 Apache HTTPD 之类的Web 服务器后面运行。
关于 Apache HTTPD
Apache HTTPD 有时只称为 “Apache” 或者 httpd 通过完整支持 http 来实施完全可配置且可扩展的Web 服务器。可以通过模块来扩展 httpd 的功能,模块是很小的代码片段,插入到主Web 服务器框架中并扩展其功能。
在 RHEL 7上,在 httpd 软件包中提供了 Apache HTTPD ,web-server 软件包组将不仅安装 httpd 软件包本身,还将安装 httpd-manual 软件包。一量安装了 httpd-manual 并且 httpd.service 服务启动,http://localhost/manual 上便提供完成的 Apache HTTPD 手册。此手册包含 httpd 的所有配置指令的完整参考以及示例。因此,此手册是配置 httpd 时的宝贵资源。
RHEL 7还随附了一个名为 web-server-enviroment 的环境组。此环境组默认情况引入 web-server 组,但是具有几个另外的组(如备份工具和数据库客户端)标记为选项。
httpd 软件包的默认依赖项是httpd-tools 软件包。此软件包包括用于操纵密码映射和数据库的工具,用于将日志文件中的 IP 解析为主机名的工具以及用于对 Web 服务器进行基准测试和压力测试的工具 (ab).
Apache HTTPD 基本配置
安装 web-server 软件包组或 httpd 软件包后,默认配置将写入到 /etc/httpd/conf/httpd.conf 。
此配置针对通过纯http 进入任何主机名的请求来提供 /var/www/html 的内容。
httpd.conf 的基本语法由两部分组成:Key Value 配置指令和类似于 HTML 的<Blockname parameter>
块,后者中嵌入了其他配置指令。块范围之外的键值对会影响整个服务器配置,而块中的指令通常仅应用于块所指示的配置的某一部分,或者在满足了块设置的要求时才会应用。

1、此指令指定httpd 将在哪个位置中使用相对路径名来查找配置文件中引用的任何文件
2、此指令告知 httpd 在所有接口上开始侦听 80/TCP 。要仅侦听特定接口,可以使用语法 "Listen 1.2.3.4:80" (对于 IPv4) 或 “Listen [2001:db8::1]:80”(对于 IPv6 )
允许多个 listen 指令,但是重叠的 listen 指令将导致致命错误,致使 httpd 无法启动。
3、此指令包括其他文件,就如同这些文件已插入到配置文件以代替 Include 语句。如果指定了多个文件,则在包含这些文件之前,将首先按字母顺序对文件名进行排序。文件名可以绝对,也可以是相对于 ServerRoot ,并且包括通配符(如 *)。
指定不存在的文件将导致致命错误,致使 httpd 无法启动。
4,5、这两个指令指定在运行 httpd 守护进程时使用的用户和组。httpd 始终是以 root 用户身份启动。但是一旦执行了需要 root 特权的所有操作(例如 ,绑定低于 1024 的端口号),则将丢弃特权并且作为非特权用户继续执行。这是一种安全措施。
6、httpd 生成的一些错误页面可能包括一个链接,用户可以通过此连接来报告问题。将此指令设置为有效的电子邮件地址将使网络管理员能够更轻松的联系用户。不建议将此设置保留为默认值 root@localhost
7、<Directory>
块设置指定目录以及所有后代目录的配置指令
<Direcotry>
块中的常见指令包括以下几种:
- AllowOverride None: 对于按目录的配置设置,将不会查问 .htaccess 文件。将其设置为任何其他设置都将导致性能损失以及可能的安全后果。
- Require All Denied: httpd 将拒绝提供此目录的内容,当客户端请求时,将返回 HTTP/1.1 403 Forbidden 错误。
- Require All Granted: 允许访问此目录。对普通内容树之外的目录设置此选项可能会产生安全影响。
- Options [[+|-]OPTIONS] … :为某个目录开启(或关闭)特定选项。例如,如果请求了某个目录且该目录中不存在 index.html 文件,则 Indexes 选项将显示一个目录列表
8、此设置确定 httpd 将搜索请求文件的位置。重要的一点是,此处指定的目录可以由 httpd (常规权限和 SELinux) 读取,并且对应的<Directory>
块已声明为允许访问。
9、仅当加载指定扩展模块时,此块才会应用其内容。在此情况下,会加载 dir_module ,因此DirectoryIndex指令可用于指定在请求目录时应使用的文件。
10、<Files>块的运行方式与 <Directory>
块相同,但此处使用了表示个别(通配符)文件的选项。在此情况下,块阻止 httpd 提供任何安全性敏感的文件。如 .htaccess 和 .htpasswd 。
11、这指定 httpd 应将其遇到的错误记录到的文件。由于这是一个相对路径名,前面带有 ServerRoot 指令。在默认配置中, /etc/httpd/logs 是指向 /var/log/httpd/ 的符号链接。
12、CustomLog 指令采用两个参数:要记录到的文件和使用 logFormat 指令定义的日志格式。使用这些指令,管理员可以精确记录其需要的信息。大部分日志解析工具将假定使用默认的 combined 格式。
13、此设置向 text/plain 和 text/html 资源的Content-Type 报头中添加charset 部分。可以使用 AddDefaultCharset Off 将其禁用。
14、这与常规 include 的工作方式相同,但如果未找到文件,则不会生成错误。
启动Apache HTTPD
可以从 httpd.service systemd 单元中启动 httpd
[root@localhost ~]# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.
[root@localhost ~]# systemctl start httpd
一旦httpd 启动,可以使用 systemctl status -l httpd.service 来请求状态信息。如果 httpd 由于任何原因而启动失败,那么此输出通常将给出 httpd 启动失败的原因。
网络安全
firewalld 有两个预定义服务可用于 httpd . http 服务打开 80/tcp ,https 服务打开端口 443/tcp 。
[root@localhost ~]# firewall-cmd --permanent --add-service=http --add-service=https
success
[root@localhost ~]# firewall-cmd --reload
success
在默认配置中,SELinux 仅允许 httpd 绑定到一组特定端口。可以使用 semanage port -l | grep '^http_'命令来请求此完整列表。有关允许端口上下文及其指定用途的完整概述,请查阅 selinux-policy-devel 软件包中的 httpd_selinux(8) man page .
使用替代文档根目录
不需要提供 /var/www/html 的内容,但是当更改 DocumentRoot 设置时,还必须进行一些其他明天发:
- 文件系统权限:任何新的documentRoot 必须可由 apache 用户或 apache 组进行读取。在大部分情况下,DocumentRoot绝不能由 apache 用户或组进行写入。
- SELinux: 默认的 SELinux 策略都会限制 httpd 可以读取的上下文。Web 服务器内容的默认上下文是 httpd_sys_content_t 。规则已实施以便还使用此上下文重新标记 /srv/*/www/ 。要从这些标准位置之外的位置中提供内容,必须使用 semanage 来添加新的上下文规则。
[root@localhost ~]# mkdir -p /data/www
[root@localhost ~]# semanage fcontext -a -t httpd_sys_content_t '/data/www(/.*)?'
请查阅 selinx-policy-devel 软件包中的 httpd_selinux(8) man page 。了解其他允许的文件上下文及其指定用途。
允许对 DocumentRoot 进行写访问
在默认配置中,仅root 用户对标准的 DocumentRoot 具有写访问权限。要允许开发者写入到DocumentRoot,可以采用多种方法。
在DocumentRoot中,为Web开发者设置(默认)ACL 。例如,如果所有Web开发者属于 webmasters 组,并且 /var/www/html 用作 DocumentRoot。则以下将为其设置写访问权限 :
[root@localhost ~]# setfacl -R -m g:webmaster:rwX /var/www/html
[root@localhost ~]# setfacl -R -m d:g:webmaster:rwX /var/www/html
重要
大写的X位仅对目录(而非目录和常规文件)设置可执行位。配置对目录进行递归操作时,这特别重要。
- 创建由webmaster 组(设置的粘滞位)拥有的新 DocumentRoot
[root@localhost ~]# mkdir -p -m 2775 /new/docroot
[root@localhost ~]# chgrp webmaster /new/docroot
- 上一个 ACL (关闭了其他权限)和针对 apache 组添加的 ACL 的组合。
虚拟主机的配置和故障的排除
虚拟主机
虚拟主机允许单个 httpd 服务器为多个域提供内容。基于所连接到的服务器的 IP 地址,http 请求中客户端请求的主机名,或者这两者的组合,httpd 可以使用不同的配置设置,包括不同的DocumentRoot 。
如果启动多个(虚拟)计算机来为众多抵流量站点提供内容没有成本效益(例如,在共享主机环境中),则通常使用虚拟主机。
配置虚拟主机
虚拟主机是使用主配置中的<VirutualHost>
块来配置的。为便于管理,通常不会在 /etc/httpd/conf/httpd.conf 中定义这些虚拟主机块,而是单独的 /etc/httpd/conf.d/ 中单独的 .conf 文件中。
下面是一个示例文件/etc/httpd/conf.d/site1.conf 。

①此块提供了对进一步定义的 DocumentRoot的访问权限。
②这是块的主标记。 192.168.0.1:80 部分向 httpd 表明,应该为通过该 IP/端口组合进入的所有连接考虑此块。
③这里设置了DocumentRoot,但是仅限于此虚拟主机。
④此设置用于配置基于名称的虚拟主机。如果为相同的 IP/端口组合声明了多个<VirtualHost>
块,那么将使用将ServerName与客户端http请求中发送的hostname :头匹配的块。
单个 <VirtualHost>
块中只能有正好零个或一个ServerName 指令。如果需要将单个虚拟主机用于多个域名,则可以使用一个或欠点ServerAlias 语句。
⑤为帮助对不同网站的相关邮件进行排序,为所有虚拟主机设置唯一的ServerAdmin 地址会很有帮助。
⑥与此虚拟主机相关的所有错误消息的位置
⑦与此虚拟主机相关的所有访问权限消息的位置。
如果没有为某个虚拟主机明确进行设置,则将使用主配置中的相同设置。
基于名称的虚拟主机与基于IP的虚拟主机对比
默认情况下,每个虚拟主机都是一个基于 IP 的虚拟主机:根据客户端连接到的 IP地址来对进入虚拟主机的流量进行排序。如果为单个 IP/端口组合声明了多个虚拟主机,则将引用ServerName和 ServerAlias指令,从而有效启用基于名称的虚拟主机。
通配符和优先级
<VirutalHost>
指令的IP 地址部分可以替换为两个通配符中的一个:_default_
和 * .两者的含义完全相同:“匹配任何内容”
当某个请求进入时,httpd 将首先尝试匹配设置了显示 IP 地址的虚拟主机。如果这些匹配项失败,那么将检查具有通配符 IP 地址的虚拟主机。如果仍没有匹配项,则将使用 “主”服务器配置。
重要
<VirutalHost *:80>
始终将匹配端口 80/TCP 上的常规 http 流量,从而有有效禁止主服务器配置用于端口80 /TCP 上的流量。
如果没有为 ServerName 或ServerAlias 指令找到完全匹配项,并且为请求所有来自 IP/端口组合定义了多个虚拟主机,则将使用与某个 IP/端口相匹配的首个虚拟主机,且首个虚拟主机被为在配置文件中定义虚拟主机的顺序。
使用多个 *.conf 文件时,将以字母顺序排序方式包括这些文件。要创建概括性(默认)虚拟主机,配置文件应命名为类似于00-default.conf 的名称,以确保在任何其他对象之前包括配置文件。
虚拟主机故障排除
对虚拟班机进行故障排除时,多种方法会很有帮助。
- 为每个虚拟主机配置单独的 DocumentRoot,包含标识性内容。
- 为每个虚拟主机配置单独的日志文件,用于错误记录和访问记录。
- 评估 httpd 解析虚拟主机定义的顺序。将按照所包含的文件名的字母顺序来读取包含的文件。
- 逐一禁用虚拟主机以隔离问题。可以在配置文件中注释掉虚拟主机定义,并且可以临时将 include 文件重命名不以 .conf 结尾的其他文件名。
- journalctl UNIT=httpd.service 只能从 httpd.service 服务中隔离日志消息。
配置HTTPS
传输层安全性(TLS)
传输层安全性(TLS) 是用于加密网络通信的方法。TLS 是安全套接字层(SSL) 的后续版本。TLS 允许客户端验证服务器身份,并且允许服务器验证客户端的身份(后者为可选)。
TLS 基于证书的概念。一个证书包含多个部分:公钥、服务器身份和证书颁发机构的签名。对应的私钥绝对不会公开。使用私钥加密的任何数据只能通过公钥解密,反之亦然。
在初握手期间,当设置加密连接时,客户端和服务器同意一组由服务器和客户端均支持的加密密码,然后他们交换随机数据的位。客户使用此随机生成会话密钥,这是一个将用于更快速的对称加密的密钥,其中相同的密钥同时用于加密和解密。为确保此密钥不被泄露,它被发送到使用服务器的公钥(属于服务器证书)加密的服务器。
下图显示了一个 TLS 握手一个(简化)版本。

1、客户端通过ClientHello 消息启动与服务器的国家的。作为此消息的一部分,客户端改善32字节的随机数字,包括时间戳记以及客户端支持的加密协议和密码的列表。
2、服务器以 ServerHello 消息响应,包含另一个32字节随机数字,其中带有时间戳记以及客户端应使用的加密协议和密码。
服务器也会发送服务器证书,其中由公钥、常规服务器身份信息(如 FQDN)以及来自可信认证颁发机构(CA)的签名。此证书还可以包含已对证书签名的所有证书颁发机构(直至根 CA)的公共证书。
3、客户端通过检查提供身份信息是否匹配,以及验证所有签名,检查这些签名是否由客户端信任的 CA 生成,从而验证服务器证书。
如果证书确认,则客户端使用先前交换的随机数字来创建会话密钥,客户端随后使用来自服务器证书的公钥加密此会话密钥,然后使用ClientKeyExchange 消息将其发送到服务器。
4、服务器解密会话密钥,然后客户端和服务器均开始使用会话密钥来加密和解密通过连接发送的所有数据。
注意
这是实际协议的简化:例如,实际会话密钥绝对不会与很多密码套件一起传输,甚至不采用加密形式。服务器和客户端均创建一个将进行交换的预先主密钥,并且服务器和客户端均通过此密钥来计算实际会话。
在协商期间,服务器和客户端都还会使用各种方法来确保防止重播攻击和中间人攻击。
配置 TLS 证书
要配置带有TLS 的虚拟主机,必须完成多个步骤:
1、获取(签名)证书。
2、安装 Apache HTTPD 扩展模块以支持 TLS 。
3、使用之前获取的证书,将虚拟主机配置为使用 TLS。
获取证书
当获取证书时,有两个选项:创建自签名证书(由自己而不是由实际 CA 签名的证书),或者创建证书请求并让某个知名 CA 对该请求进行签名,以使其成为一个证书。
crypto-utils 软件包包含一个名称 genkey 的实用程序,同时支持这两种方法。要使用 geneky 创建证书(签名请求),请运行以下命令(其中<FQDN>
是客户端将用于连接到服务器的完全限定域名):
[root@server0 ~]# genkey <FQDN>
[root@server0 ~]# genkey server0.example.com
在创建期间,genkey 将询问所需密钥大小(至少选择 2048 位),是否应进行签名请求(回答“否”将创建自签名证书),是否应通过实密语来保护私钥,以及有关服务器身份的常规信息。
在此过程完成后,将生成多个文件:
- /etc/pki/tls/private/
<fqdn>
.key :这是私钥。私钥应保护在0600或0400 权限,以及SELinux 上下文 cert_t 。此私钥绝对不能与外部共享。 - /etc/pki/tls/certs/
<fqdn>
.0.csr :仅当你请求我签名请求是,都会生成此文件。这是您发送到 CA 以进行签名的文件。您不需要将私钥发送到您的CA 。 - /etc/pki/tls/certs/
<fqdn>
.crt :这是公共证书。仅当请求自签名时,都会生成此文件。如果申请了签名请求并且将其发送到 CA ,那么这是将从 CA 返回的文件。权限应保存持在0644,且 SELinux 上下文为 cert_t 。
安装 Apache HTTPD 模块
Apache HTTPD 需要安装扩展模块才能激活 TLS 支持。在 RHEL 7 中,您可以使用 mod_ssl 软件包来安装此模块。
此软件包将为侦听端口 443/TCP 的默认虚拟自动启用httpd。 此默认虚拟主机是在文件 /etc/httpd/conf.d/ssl.conf 中配置的。
配置带有 TLS 的虚拟主机
带有 TLS 虚拟主机配置方式与常规主机的配置方式相同,但有一些额外的参数。可以使用基于名称的带有 TLS 的虚拟主机,但是某些更旧的浏览器与此方法不兼容。
以下简化版本的 /etc/httpd/conf.d/ssl.conf :

1、此指令指示 https 侦听端口 443/tcp 。第二个参数 (https) 是可选的,因为 https 是端口443/tcp 的默认协议。
2、如果私钥以密语进行加密,则 httpd 需要一种方法以在系统启动时通过控制台向用户请求密语。此指令指定为检索该密语而要执行的程序 。
3、这些端口 443/TCP 上概括性虚拟主机的虚拟主机定义。
4、这是用于实际为此虚拟主机开启 TLS 的指令。
5、此指令指定 httpd 与客户机通信时希望使用的协议的列表。为提高安全性,还应禁用更旧且不安全的 SSLv3 协议:
SSLProtocol all -SSLv2 -SSLv3
6、此指令列出在与客户端通信时 httpd 将要使用的加密密码。密码的选择会对性能和安全性有很大影响。
7、此指令向 httpd 告知读取此虚拟主机的证书的位置。
8、此指令向 httpd 告知读取此虚拟主机的私钥的位置。httpd 在特权被丢弃之前读取所有私钥,以便对私钥的文件权限可以保持锁定。
如果使用 CA 签名的证书,并且证书自身未嵌入签名中使用的所有CA 证书(直至根 CA) 的副本,则服务器还将需要提供证书链接,也就是签名过程中串联在一起的所有 CA 证书的副本。
SSLCertificateChainFile 指令用于标识此类文件。
定义新的TLS 加密虚拟主机时,不需要复制ssl.conf 的所有内容。仅 <VirtualHost>
块(包含 SSLEngine on 指令和证书配置)是严格需要的。下面是基于名称的 TLS 虚拟主机的示例:
<VirtualHost *:443>
ServerName server0.example.com
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/server0.example.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/server0.example.com
SSLCertificateChainFile /etc/pki/tls/certs/example-ca.crt
</VirtualHost>
此示例缺少一此重要的指令,如DocumentRoot等,这些指令将从主配置中继承。
警告
如果不定义可以使用哪些协议和密码,将导致 httpd 使用这些设置的默认选项。httpd 默认值被这视为不安全,并且强烈建议将两者限制为更安全的子网。
配置转发保密
如果使用了较弱的加密密码,并且服务器的私钥已被入侵,例如,在服务器入侵或加密代码出现错误之后,攻击者可能会解密记录的会话。
防止这些类型的攻击便称为向前保密。通过在 SSLCipherSuite 指令中仔细调整允许的密码,以及让服务器始终从该列表中选择服务器和客户端均支持的最高优先级密码,可建立向前保密。
以下是一个示例,说明发布日期被视为允许的最佳密码集合。此列表对使用椭圆曲线 Diffie-Hellman ( EECDH) 算法执行初始会话密钥交换的密码划分优先级。使用 Diffie-Hallman 时,从不会传输实际的会话密钥,而是由两端计算得出。

SSLHonorCipherOrder on 指令命令 httpd 始终首选之前在 SSLCipherSuite 列表中列出的密码,无论客户端首选项如何。
重要
安全研究就像是不断进行的军备竞赛。建议管理员定期重新评估其所选密码。
配置 HTTP 严格传输安全性(HSTS)
一种常见的错误配置(并且将导致大部分新款出现警告)是让一个通过 https 提供的web 页面包含通过明文 http 提供的资源。
为防御这种类型的错误配置,请在启用了 TLS 的 <VirtualHost>
块中添加以下行:
Header always set Strict-Transport-Security "max-age=15768000"
发送这一额外标题将告知客户端,仅允许客户端针对此页面获取不是使用 TLS 提供的资源。
客户端通过 http 连接到本应在使用 https 连接的资源,可能出现另一个问题。
直接不通过 http 提供任何内容将缓解此问题,但更改妙的方法是自动将通过 http 连接的内容重定向到使用 https的相同资源 。
要设置这些重定向,请将相同 ServerName 和 ServerAlias 的 http 虚拟主机配置为 TLS 保护的虚拟主机(可以使用概括性虚拟主机),然后在<VirtualHost *:80>
块中添加以下行:
RewriteEngine on
RewriteRule ^(/.*)$ [https://%{HTTP_HOST}$1](https://%25%7Bhttps_post%7D%241/) [redirect=301]
RewriteEngine on 指令打开此虚拟主机的 URL 重写模块,而RewriteRule 匹配任何资源 (^(/.*)$
) 并使用 http Moved Permanently 消息 ([redirect=301])将其重定向到通过 https 提供的相同资源。 %{HTTP_HOST} 变量使用客户端所请求的主机名,而$1 部分是对正则表达式中第一组括号之间任何匹配内容的反向引用。
案例:
<VirtualHost *:80>
ServerName www0.example.com
ServerAlias www0
RewriteEngine on
ReWriteRule ^(/.*)$ https://%{HTTP_HOST}$1 [redirect=301]
</VirtualHost>
<VirtualHost *:443>
ServerName www0.example.com
ServerAlias www0
DocumentRoot /srv/www0/www
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/tls/certs/www0.crt
SSLCertificateKeyFile /etc/pki/tls/private/www0.key
</VirtualHost>
<Directory /srv/www0/www>
Require all granted
</Directory>
参照上示例,访问80 端口同样会被重定向,因为针对 *:80 做了概括性虚拟主机,导致 *:80 的第一个虚拟主机用作默认虚拟主机。要解决此问题可定义 <VirtualHost _default_:80>
块;例如在,/etc/httpd/conf/httpd.conf 中的include 之前 ,或者在 /etc/httpd/conf.d/00-default.conf 中作为单独文件。
集成动态内容
大部分现代网站都不会由静态内容组成。提供的的大部分内容实际根据需要而动态生成。可以通过多种方法将动态内容与 Apache HTTPD 集成。本部分描述了一些最常见的方法,但还有更多方法。
通用网关接口
生成动态内容最早方式之一是使用通用网关接口 (CGI)。当请求 CGI 资源时,httpd 不是简单读取和提供资源,而是作为进程来执行资源,并提供该进程的 stdout 。尽管 CGI 资源最常以脚本语言(如Perl)来编写,但CGI 资源被编辑为 C程序或 Java 可执行文件的情况也很觉。
使用环境变量将请求中的信息(包括客户端信息)提供给 CGI 程序 。
为 CGI 配置 httpd
要让 httpd 将位置视为 CGI 可执行文件,需在 httpd 配置中使用以下语法。
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
这指示 httpd 将针对 /cgi-bin/ URI 下面的文件的任何请求重定向到 /var/www/cgi-bin/ 目录,并将该目录中的文件视为可执行脚本。
使用 CGI 时会存在很多注意事项:
- 将以 apache 用户和组的身份来执行 CGI 脚本。
- apache 用户和组应具有 CGI 脚本的执行权限 。
- CGI 脚本应具有 httpd_sys_script_exec_t SELlinux 上下文。
- CGI 目录应具有Options None 。并且应使用正常的
<Directory>
块来授予访问权限。
提供动态 PHP 内容
提供动态内容的一种常见方法是使用 PHP 脚本语言。尽管可以使用旧式的 CGI 来提供 PHP 脚本,但通过让 httpd 在内部运行 PHP 解释器,可以提高性能和安全性。
通过安装 php 软件包,会将这一个特殊的 mod_php 模块添加到 httpd 。此模块的默认配置将以下行添加到 httpd 的主配置中:
<FilesMatch \.php$>
SetHandler application/x-httpd-php
<FilesMatch>
DirectoryIndex index.php
<FilesMatch>
块指示 httpd 对名称以 .php 结尾的任何文件使用 mod_php ,并且 DirectoryIndex 指令将 index.php 添加到请求目录时要搜寻的文件的列表。
提供动态 Python 内容
使用Python 脚本生成动态内容也很常见。可以使用常规 CGI 来提供 Python 脚本,但是python 以及 httpd 还支持更新的协议:Web服务器网关接口(WSGI) .
还可以安装 mod_wsgi 软件包,以向 httpd 中添加 WSGI 支持。
与 mod_php 或 CGI 方法不同的时, WSGI 不会为每个请求启动新脚本/解释器。相反,将启动一个主应用程序 ,并且所有请求都路由到该应用程序 中。
将http 配置为支持 WSGI 应用程序分为两个步骤:
1、安装 mod_wsgi 软件包
2、向虚拟主机定义中添加 WSGIScriptAlias 行。
以下是 WSGIScriptAlias 指令的示例,此指令针对 http://servername/myapp 以及其中任何资源的所有请求发送到 WSGI 应用程序 /srv/myapp/www/myapp.py:
WSGIScirptAlias /myapp/ /srv/myapp/www/myapp.py
apache 用户和组应具有 WSGI 应用程序的执行权限,并且这些应用程序的 SELinux 上下文设置为 httpd_sys_content_t 。
数据库连接性
大部分Web 应用程序将需要存储和检索持久数据。执行此操作的一种常见方法是将数据存储在数据库中,如MariaDB 或 PostgreSQL 。
如果数据库和Web服务器在同一主机上运行,并且数据库在使用标准的网络端口。则 SELinux 将允许从Web应用程序进行网络连接。
当使用远程主机上的数据库时,SELinux 布尔值 httpd_can_network_connect_db 必须设置为 1 以允许连接。
如果需要从Web应用程序进行与另一个主机的网络连接,并且目标不是众所周知的数据库端口,则 SELinux 布尔值 httpd_can_network_connect 必须设置为 1
各种其他 SELinux 布尔值还可以影响 httpd 执行 Web应用程序的方式。