Skip to main content

第10章 使用 Apache 服务部署静态网站

章节简述

本章首先向读者介绍什么是 Web 服务程序及其用途,然后通过对比当前主流的 Web 服务程序,使读者更好地理解各自的优势和特点。接着,通过对 httpd 服务程序中的“全局配置参数”“区域配置参数”及“注释信息”的理论讲解和实战部署,确保读者学会 Web 服务程序的配置方法,并真正掌握在 Linux 系统中配置服务的技巧。

本章还会讲解 SELinux 服务的作用、3 种工作模式以及策略管理方法,确保读者掌握SELinux 域和 SELinux 安全上下文的配置方法。随后,本章将引领读者依次完成多个基于 httpd 服务程序的实用功能的部署实验,包括 httpd 服务程序的基本部署、个人用户主页功能、密码加密认证方式的实现,以及分别基于 IP 地址、主机名(域名)、端口号部署虚拟主机网站功能。

10.1 网站服务程序

1970 年,作为互联网前身的 ARPANET(阿帕网)已初具雏形,并开始向非军用部门开放,许多大学和商业机构陆续接入。虽然彼时阿帕网的规模(只有 4 台主机联网运行)还不如现在的局域网成熟,但是它依然为网络技术的进步打下了扎实的基础。

想必大多数人都是通过访问网站而开始接触互联网的吧。我们平时访问的网站服务就是Web 网络服务,一般是指允许用户通过浏览器访问互联网中各种资源的服务。如图 10-1 所示, Web 网络服务是一种被动访问的服务程序,即只有接收到互联网中其他主机发出的请求后才会响应,最终用于提供服务程序的 Web 服务器会通过 HTTP(超文本传输协议)或 HTTPS(超文本传输安全协议)把请求的内容传送给用户。

目前提供 Web 网络服务的程序有IIS、Nginx 和 Apache 等。其中,IIS(Internet Information Service,互联网信息服务)是 Windows 系统中默认的 Web 服务程序,这是一款图形化的网站管理工具,不仅可以提供 Web 网站服务,还能够提供FTP、NMTP、SMTP 等服务。但 IIS 只能在 Windows 系统中使用,暂时不在我们的学习范围之内。

图10-1 主机与Web服务器之间的通信

2004 年 10 月 4 日,为俄罗斯知名门户站点而开发的 Web 服务程序Nginx 横空出世。Nginx程序作为一款轻量级的网站服务软件,因其稳定性和丰富的功能而快速占领服务器市场,但Nginx 最被认可的还是其系统资源消耗低且并发能力强的特性,因此得到了国内诸如新浪、网易、腾讯等门户网站的青睐。本书将在第 20 章讲解 Nginx 服务程序。

Apache 程序是目前拥有较高市场占有率的 Web 服务程序之一,其跨平台和安全性被广泛认可且拥有快速、可靠、简单的 API 扩展。图 10-2 所示为 Apache 服务基金会的著名Logo, 名字取自美国印第安人的土著语,寓意为“拥有高超的作战策略和无穷的耐性”。Apache 服务程序可以运行在 Linux、UNIX 甚至是 Windows 系统中,它支持基于 IP、域名及端口号的虚拟主机功能,支持多种认证方式,集成有代理服务器模块、安全 Socket 层(SSL),能够实时监视服务状态与定制日志消息,并支持各类丰富的模块。

然而,Apache 作为老牌的 Web 服务程序,不仅在 Web 服务器软件市场上具有很高的占有率,而且是 RHEL 10 系统中的默认 Web 服务程序,也是 RHCSA 和RHCE 认证考试的必考内容。因此,无论是从实际应用还是红帽认证考试的角度,都有必要深入学习 Apache 服务程序的部署及其丰富的功能。

图10-2 Apache软件基金会著名的Logo

总体来说,Nginx作为后起之秀,已经凭借自身的优势与努力赢得了大批站长的信赖。本书配套的在线学习站点 https://www.linuxprobe.com 就是基于Nginx服务程序部署的,不得不说Nginx真的很棒!

我们再来回忆一下软件仓库的配置过程。

第 1 步:把系统镜像挂载到/media/cdrom 目录。

root@linuxprobe:~# mkdir -p /media/cdrom
root@linuxprobe:~# mount /dev/cdrom /media/cdrom
mount: /media/cdrom: WARNING: source write-protected, mounted read-only.

第 2 步:使用 Vim 文本编辑器创建软件仓库的配置文件,下述命令中具体参数的含义可参考 4.1.4 节。

root@linuxprobe:~# vim /etc/yum.repos.d/rhel10.repo
[BaseOS]
name=BaseOS
baseurl=file:///media/cdrom/BaseOS
enabled=1
gpgcheck=0
[AppStream]
name=AppStream
baseurl=file:///media/cdrom/AppStream
enabled=1
gpgcheck=0

第 3 步:动手安装 Apache 服务程序。注意,在使用 dnf 命令进行安装时,跟在命令后面的 Apache 服务的软件包名称为 httpd,使用-y 参数直接安装即可,无须二次确认。

root@linuxprobe:~# dnf install httpd -y
Updating Subscription Management repositories.
Last metadata expiration check: 0:00:05 ago on Sun 23 Mar 2025 01:24:37 AM CST.
Dependencies resolved.
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
httpd x86_64 2.4.62-4.el10 AppStream 54 k
Installing dependencies:
apr x86_64 1.7.3-10.el10 AppStream 132 k
apr-util x86_64 1.6.3-20.el10 AppStream 101 k
apr-util-lmdb x86_64 1.6.3-20.el10 AppStream 17 k
httpd-core x86_64 2.4.62-4.el10 AppStream 1.5 M
httpd-filesystem noarch 2.4.62-4.el10 AppStream 17 k
httpd-tools x86_64 2.4.62-4.el10 AppStream 88 k
redhat-logos-httpd noarch 100.0-2.el10 AppStream 18 k
Installing weak dependencies:
apr-util-openssl x86_64 1.6.3-20.el10 AppStream 18 k
mod_http2 x86_64 2.0.29-1.el10 AppStream 169 k
mod_lua x86_64 2.4.62-4.el10 AppStream 61 k
………………省略部分输出信息………………
Installed:
apr-1.7.3-10.el10.x86_64 apr-util-1.6.3-20.el10.x86_64
apr-util-lmdb-1.6.3-20.el10.x86_64 apr-util-openssl-1.6.3-20.el10.x86_64
httpd-2.4.62-4.el10.x86_64 httpd-core-2.4.62-4.el10.x86_64
httpd-filesystem-2.4.62-4.el10.noarch httpd-tools-2.4.62-4.el10.x86_64
mod_http2-2.0.29-1.el10.x86_64 mod_lua-2.4.62-4.el10.x86_64
redhat-logos-httpd-100.0-2.el10.noarch

Complete!

第 4 步:启用 httpd 服务程序并将其加入开机启动项中,使其能够随系统开机运行,从而持续为用户提供 Web 服务。

root@linuxprobe:~# systemctl start httpd
root@linuxprobe:~# systemctl enable httpd
Created symlink '/etc/systemd/system/multi-user.target.wants/httpd.service' → '/usr/lib/systemd/system/httpd.service'.

第 5 步:设置firewall 防火墙策略,使其放行发往本机HTTP 的请求流量。

root@linuxprobe:~# firewall-cmd --permanent --add-service=http
success
root@linuxprobe:~# firewall-cmd --reload
success

大家在物理机的浏览器(这里以 Google Chrome 为例)的地址栏中输入http://192.168.10.10并按回车键,就可以看到用于提供 Web 服务的默认页面了,如图 10-3 所示。

如果访问失败,请检查虚拟机系统的 IP 地址是否为 192.168.10.10,网络适配器的连接模式是否为仅主机模式,以及物理机的 VMnet1 网卡的IP 地址是否与虚拟机系统的 IP 地址处于同一网段,如 192.168.10.1/255.255.255.0。如忘记操作方法,可回看图 8-16 和图 8-17,相信一定能回忆起来。

图10-3 httpd服务程序的默认页面

当然,同学们也可以在命令行中执行 firefox 命令,直接打开本地的火狐浏览器,这样更方便。

root@linuxprobe:~# firefox

10.2 配置服务文件参数

需要提醒大家的是,前文介绍的 httpd 服务程序的安装和运行知识,仅仅是一些皮毛, 我们依然有很长的道路要走。在 Linux 系统中配置服务,其实就是修改服务的配置文件。因此,还需要知道这些配置文件的所在位置以及用途。httpd 服务程序的主配置文件的名称及作用如表 10-1 所示。

表 10-1 httpd 服务程序的主配置文件的名称以及作用

文件名称作用
/etc/httpd服务目录
/etc/httpd/conf/httpd.conf主配置文件
/var/www/html网站数据目录
/var/log/httpd/access_log访问日志
/var/log/httpd/error_log错误日志

主配置文件中保存的是最重要的服务参数,一般会被保存到/etc 目录中以软件名称命名的一个文件夹中,名字为“服务名称.conf”,例如这里的/etc/httpd/conf/httpd.conf。大家在熟悉以后就能记住了。

大家在首次打开 httpd 服务程序的主配置文件后,可能会吓一跳—竟然有 358 行!这得至少需要一周的时间才能看完吧?!其实不需要这么久,因为在这个配置文件中,所有以井号(#)打头的行都是注释行,其目的是对 httpd 服务程序的功能或某一行参数进行介绍, 我们不需要逐行研究这些内容。

在httpd 服务程序的主配置文件中,存在 3 种类型的参数:注释行信息、全局配置、区域配置,如图 10-4 所示。

图10-4 httpd服务主配置文件的参数结构

各位读者在学习第 4 章时已经接触过注释行信息,因此这里主要讲解全局配置参数与区域配置参数的区别。顾名思义,全局配置参数就是一种全局性的配置参数,可作用于所有的子站点,既保证了子站点的正常访问,也有效降低了频繁写入重复参数的工作量。区域配置参数则是单独针对每个独立的子站点进行设置的。就像在大学食堂里面打饭,食堂负责打饭的阿姨先给每位同学来一碗标准大小的米饭(全局配置),然后再根据每位同学的具体要求盛放他们想吃的菜(区域配置)。在 httpd 服务程序的主配置文件中,最为常用的参数及用途如表 10-2 所示。

表 10-2 配置 httpd 服务程序时最常用的参数及用途

参数用途
ServerRoot服务目录
ServerAdmin管理员邮箱
User运行服务的用户
Group运行服务的用户组
ServerName网站服务器的域名
DocumentRoot网站数据目录
Listen监听的 IP 地址与端口号
DirectoryIndex默认的索引页面
ErrorLog错误日志文件
CustomLog访问日志文件
Timeout网页超时时间,默认为 300 秒

从表 10-2 中可知,DocumentRoot 参数用于定义网站数据的保存路径,其参数的默认值是/var/www/html(即把网站数据存放到这个目录中);而当前网站普遍的主页面名称是 index.html,因此向/var/www/html/index.html 文件中写入一段内容,替换掉 httpd 服务程序的默认主页面。该操作会立即生效。

root@linuxprobe:~# echo "Welcome To LinuxProbe.Com" > /var/www/html/index.html 

在执行上述操作之后,在浏览器中执行刷新操作(或按 F5 键),可以看到该程序的主页面内容已经发生了改变,如图 10-5 所示。

图10-5 首页面内容已经被修改

大家在完成这个实验之后,是不是信心爆棚了呢?!在默认情况下,网站数据保存在/var/www/html 目录中,如果想把保存网站数据的目录修改为/home/wwwroot 目录,该怎么操作呢?且看下文。

第 1 步:建立网站数据的保存目录,并创建主页文件。

root@linuxprobe:~# mkdir /home/wwwroot
root@linuxprobe:~# echo "The New Web Directory" > /home/wwwroot/index.html

第 2 步:打开 httpd 服务程序的主配置文件,将第 124 行用于定义网站数据保存路径的参数 DocumentRoot 修改为/home/wwwroot,同时还需要将第 129 行与第 136 行用于定义目录权限的参数 Directory 后面的路径也修改为/home/wwwroot。配置文件修改完毕后即可保存并退出。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf 
………………省略部分输出信息………………
119 #
120 # DocumentRoot: The directory out of which you will serve your
121 # documents. By default, all requests are taken from this directory, but
122 # symbolic links and aliases may be used to point to other locations.
123 #
124 DocumentRoot "/home/wwwroot"
125
126 #
127 # Relax access to content within /var/www.
128 #
129 <Directory "/home/wwwroot">
130 AllowOverride None
131 # Allow open access:
132 Require all granted
133 </Directory>
134
135 # Further relax access to the default document root:
136 <Directory "/home/wwwroot">
………………省略部分输出信息………………

第 3 步:重新启动 httpd 服务程序并验证效果,在浏览器中刷新页面后的内容如图 10-6所示。奇怪!怎么提示权限不足了?

root@linuxprobe:~# systemctl restart httpd

图10-6 Web页面提示权限不足

10.3 SELinux安全子系统

SELinux

图 10-7 SELinux 的 Logo

例如,你在自己的电脑上下载了一个美图软件,正全神贯注地使用它给照片进行美颜的时候,它却在后台默默监听着浏览器中输入的密码信息,而这显然不应该是它做的事情(哪怕是访问电脑中的图片资源,都情有可原)。SELinux 安全子系统就是为了杜绝此类情况而设计的,它能够从多方面监控违法行为:对服务程序的功能进行限制(SELinux 域限制可以确保服务程序做不了出格的事情);对文件资源的访问进行限制(SELinux 安全上下文确保文件资源只能被其所属的服务程序进行访问)。

Tips :
如果一般权限和防火墙是“门窗”的话,那么 SELinux 便是安装在门窗外面的“防护栏”,能够让系统内部更加安全。

刘遄老师经常会把 SELinux 域和 SELinux 安全上下文称为 Linux 系统中的双保险,系统内的服务程序只能规规矩矩地拿到自己应该获取的资源,这样即便黑客入侵了系统,也无法利用系统内的服务程序进行越权操作。但是,非常可惜的是,SELinux 服务比较复杂,配置难度也很大,加之很多运维人员对这项技术理解不深,从而导致很多服务器在部署好 Linux 系统后直接将 SELinux 禁用了。这绝对不是明智的选择。

SELinux 服务有 3 种配置模式,具体如下。

enforcing:强制启用安全策略模式,将拦截服务的不合法请求。

permissive:遇到服务越权访问时,只发出警告而不强制拦截。

disabled:对于越权的行为既不警告也不拦截。

本书中所有的实验都是在强制启用安全策略模式下进行的,虽然在禁用 SELinux 服务后确实能够减少报错几率,但这在生产环境中相当不推荐。建议大家检查一下自己的系统,查看 SELinux 服务主配置文件中定义的默认状态。如果是 permissive 或 disabled,建议赶紧修改为 enforcing。

root@linuxprobe:~# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# See also:
………………省略部分输出信息………………
SELINUX=enforcing
# SELINUXTYPE= can take one of these three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted

SELinux 服务的主配置文件中,定义的是 SELinux 的默认运行状态,可以将其理解为系统重启后的状态,因此它不会在更改后立即生效。可以使用 getenforce 命令获得当前SELinux 服务的运行模式:

root@linuxprobe:~# getenforce 
Enforcing

为了确认图 10-6 所示的结果是由 SELinux 而导致的,可以用 setenforce [0|1]命令修改 SELinux 当前的运行模式(0 为禁用,1 为启用)。注意,这种修改只是临时的,在系统重启后就会失效:

root@linuxprobe:~# setenforce 0
root@linuxprobe:~# getenforce
Permissive

再次刷新页面,这次可以看到正常的网页内容了,如图 10-8 所示。可见,问题是出在了SELinux 服务上。

图 10-8 页面内容按照预期显示

现在,我们来回忆一下前面的操作到底是哪里出了问题?

httpd 服务程序的功能是允许用户访问网站内容,因此 SELinux 肯定会默认放行用户对网站的请求操作。但是,我们将网站数据的默认保存目录修改为/home/wwwroot,这就产生问题了。在 6.1 节讲到,/home 目录是用来存放普通用户的家目录数据的,而现在,httpd 提供的网站服务却要去获取普通用户家目录中的数据,这显然违反了 SELinux 的监管原则。现在,把 SELinux 服务恢复到强制启用安全策略模式,然后分别查看原始网站数据的保

存目录与当前网站数据的保存目录是否拥有不同的 SELinux 安全上下文值。

在ls 命令中,-Z 参数用于查看文件的安全上下文值,-d 参数代表对象是文件夹。

root@linuxprobe:~# setenforce 1
root@linuxprobe:~# ls -Zd /var/www/html
system_u:object_r:httpd_sys_content_t:s0 /var/www/html
root@linuxprobe:~# ls -Zd /home/wwwroot
unconfined_u:object_r:user_home_dir_t:s0 /home/wwwroot

在文件上设置的 SELinux 安全上下文是由用户段、角色段以及类型段等多个信息项共同组成的。其中,用户段 system_u 代表系统进程的身份,角色段 object_r 代表文件目录的角色,类型段 httpd_sys_content_t 代表网站服务的系统文件。由于 SELinux 服务实在太过复杂,现在大家只需要简单熟悉 SELinux 服务的作用就可以。

针对当前这种情况,我们只需要使用 semanage 命令,将当前网站目录/home/wwwroot 的 SELinux 安全上下文修改为跟原始网站目录的一样就行了。

semanage 命令用于管理 SELinux 的策略,英文全称为 SELinux Management,语法格式为“semanage [参数] [文件]”。

SELinux 服务极大地提升了 Linux 系统的安全性,将用户权限牢牢地锁在笼子里。semanage 命令不仅可以像传统的 chcon 命令那样设置文件、目录的策略,还能够管理网络端口、消息接口(这些新特性将在本章后文中涵盖)。使用 semanage 命令时,经常用到的几个参数及其作用如表 10-3 所示。

表 10-3 semanage 命令中常用参数以及作用

参数作用
-l查询
-a添加
-m修改
-d删除

例如,向新的网站数据目录中新添加一条 SELinux 安全上下文,让这个目录以及里面的所有文件能被 httpd 服务程序访问到:

root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/*

注意,在执行上述设置之后,无法立即访问网站,还需要使用 restorecon 命令让设置好的 SELinux 安全上下文立即生效。在使用 restorecon 命令时,可以加上-Rv 参数对指定的目录进行递归操作,以及显示 SELinux 安全上下文的修改过程。最后,再次刷新页面,就能正常看到网页内容了,结果如图 10-9 所示。

root@linuxprobe:~# restorecon -Rv /home/wwwroot/
Relabeled /home/wwwroot from unconfined_u:object_r:user_home_dir_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

图 10-9 正常看到网页内容

真可谓是一波三折!原本认为只要把 httpd 服务程序配置妥当就大功告成,结果却反复受到了 SELinux 安全上下文的限制。所以,建议大家在配置 httpd 服务程序时,一定要细心、耐心。一旦成功配妥 httpd 服务程序,就会发现 SELinux 服务并没有那么难。

Tips :
在 RHCSA、RHCE 或RHCA 考试中,都要求先重启机器然后再执行判分脚本。因此, 建议读者在日常工作中养成将所需服务添加到开机启动项中的习惯,比如这里就需要添加systemctl enable httpd 命令。

10.4 个人用户主页功能

如果想在系统中为每位用户建立一个独立的网站,通常的方法是基于虚拟网站主机功能来部署多个网站。但这个工作会让管理员苦不堪言(尤其是用户数量很庞大时),而且在用户自行管理网站时,还会碰到各种权限限制,需要为此做很多额外的工作。其实,httpd 服务程序提供的个人用户主页功能完全可以胜任这个工作。该功能可以让系统内所有的用户在自己的家目录中管理个人的网站,而且访问起来也非常容易。

第 1 步:在httpd 服务程序中,默认没有开启个人用户主页功能。为此,需要编辑下面的配置文件,然后在第 17 行的UserDir disabled 参数前面加上井号(#),表示让 httpd 服务程序开启个人用户主页功能;同时再把第 24 行的 UserDir public_html 参数前面的井号(#) 去掉(UserDir 参数表示网站数据在用户家目录中的保存目录名称,即 public_html 目录)。最后,在修改完毕后记得保存。

root@linuxprobe:~# vim /etc/httpd/conf.d/userdir.conf 
1 #
2 # UserDir: The name of the directory that is appended onto a user's home
3 # directory if a ~user request is received.
4 #
5 # The path to the end user account 'public_html' directory must be
6 # accessible to the webserver userid. This usually means that ~userid
7 # must have permissions of 711, ~userid/public_html must have permissions
8 # of 755, and documents contained therein must be world-readable.
9 # Otherwise, the client will only receive a "403 Forbidden" message.
10 #
11 <IfModule mod_userdir.c>
12 #
13 # UserDir is disabled by default since it can confirm the presence
14 # of a username on the system (depending on home directory
15 # permissions).
16 #
17 # UserDir disabled
18
19 #
20 # To enable requests to /~user/ to serve the user's public_html
21 # directory, remove the "UserDir disabled" line above, and uncomment
22 # the following line instead:
23 #
24 UserDir public_html
25 </IfModule>
26
27 #
28 # Control access to UserDir directories. The following is an example
29 # for a site where these directories are restricted to read-only.
30 #
31 <Directory "/home/*/public_html">
32 AllowOverride FileInfo AuthConfig Limit Indexes
33 Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
34 Require method GET POST OPTIONS
35 </Directory>
36

第 2 步:在用户家目录中建立用于保存网站数据的目录及主页面文件。另外,还需要把家目录的权限修改为 755,保证其他人也有权限读取里面的内容。

root@linuxprobe:~# su - linuxprobe
linuxprobe@linuxprobe:~$ mkdir public_html
linuxprobe@linuxprobe:~$ echo "This is linuxprobe's website" > public_html/index.html
linuxprobe@linuxprobe:~$ chmod -R 755 /home/linuxprobe

第 3 步:重新启动 httpd 服务程序,在浏览器的地址栏中输入网址,其格式为“网址/~ 用户名”(其中的波浪号是必需的,而且网址、波浪号、用户名之间没有空格)。从理论上来讲,现在就可以看到用户的个人网站了。出乎意料的是,系统显示报错页面,如图 10-10 所示。这一定还是 SELinux 惹的祸。

linuxprobe@linuxprobe:~$ exit
logout
root@linuxprobe:~# systemctl restart httpd

图 10-10 禁止访问用户的个人网站

第 4 步:思考这次报错的原因是什么。httpd 服务程序在提供个人用户主页功能时,该用户的网站数据目录本身就应该存放到与这位用户对应的家目录中,所以应该不需要修改家目录的 SELinux 安全上下文。但是,前文还讲到了 SELinux 域的概念。SELinux 域确保服务程序不能执行违规的操作,只能本本分分地为用户提供服务。httpd 服务中突然开启的这项个人用户主页功能到底有没有被 SELinux 域默认允许呢?

接下来使用 getsebool 命令查询并过滤出所有与 HTTP 相关的安全策略。其中,off 为禁止状态,on 为允许状态。

root@linuxprobe:~# getsebool -a | grep http
httpd_anon_write --> off
httpd_builtin_scripting --> on
httpd_can_check_spam --> off
httpd_can_connect_ftp --> off
httpd_can_connect_ldap --> off
httpd_can_connect_mythtv --> off
httpd_can_connect_zabbix --> off
httpd_can_manage_courier_spool --> off
httpd_can_network_connect --> off
httpd_can_network_connect_cobbler --> off
httpd_can_network_connect_db --> off
httpd_can_network_memcache --> off
httpd_can_network_redis --> off
httpd_can_network_relay --> off
httpd_can_sendmail --> off
httpd_dbus_avahi --> off
httpd_dbus_sssd --> off
httpd_dontaudit_search_dirs --> off
httpd_enable_cgi --> on
httpd_enable_ftp_server --> off
httpd_enable_homedirs --> off
………………省略部分输出信息………………

面对如此多的 SELinux 域安全策略规则,实在没有必要逐个理解它们,我们只要能通过名字大致猜测出相关的策略用途就足够了。比如,想要开启 httpd 服务的个人用户主页功能, 那么用到的 SELinux 域安全策略应该是 httpd_enable_homedirs 吧?大致确定后就可以用 setsebool 命令来修改 SELinux 策略中各条规则的布尔值了。大家一定要记得在setsebool 命令后面加上-P 参数,让修改后的 SELinux 策略规则永久生效且立即生效。随后刷新网页,其效果如图 10-11 所示。

root@linuxprobe:~# setsebool -P httpd_enable_homedirs=on

图 10-11 正常看到个人用户主页面中的内容

有时,网站的拥有者并不希望直接将网页内容显示出来,而只想让通过身份验证的用户看到里面的内容,这时就可以在网站中添加密码功能了。

第 1 步:先使用 htpasswd 命令生成密码数据库。-c 参数表示第一次生成;后面再分别添加密码数据库的存放文件,以及验证要用到的用户名称(该用户不必是系统中已有的本地账户)。

root@linuxprobe:~# htpasswd -c /etc/httpd/passwd linuxprobe
New password:此处输入用于网页验证的密码
Re-type new password:再输入一遍进行确认
Adding password for user linuxprobe

第 2 步:继续编辑个人用户主页功能的配置文件。把第 31~37 行的参数信息修改成下列内容,其中以井号(#)开头的内容为添加的注释信息,可将其忽略。随后保存并退出配置文件,重启httpd 服务程序即可生效。

root@linuxprobe:~# vim /etc/httpd/conf.d/userdir.conf
………………省略部分输出信息………………
27 #
28 # Control access to UserDir directories. The following is an example
29 # for a site where these directories are restricted to read-only.
30 #
31 <Directory "/home/*/public_html">
32 AllowOverride all
#刚刚生成出的密码验证文件保存路径
33 authuserfile "/etc/httpd/passwd"
#当用户访问网站时的提示信息
34 authname "My private website"
#验证方式为口令模式
35 authtype basic
#访问网站时需要验证的用户名称
36 require user linuxprobe
37 </Directory>
root@linuxprobe:~# systemctl restart httpd

此后,当用户再想访问某个用户的个人网站时,就必须输入账户和密码才能正常访问了。另外,验证时使用的账户和密码是用 htpasswd 命令生成的专门用于网站登录的账户和密码, 而不是系统中的账户和密码,请不要搞错了。登录界面如图 10-12 与图 10-13 所示。

图 10-12 需要输入账户和密码才能访问

图 10-13 密码验证成功

10.5 虚拟网站主机功能

如果每台运行 Linux 系统的服务器上只能运行一个网站,那么人气低、流量小的草根站长就要被迫承担高昂的服务器租赁费用了,这显然也会造成硬件资源的浪费。在虚拟专用服务器(Virtual Private Server,VPS)与云计算技术诞生以前,IDC 服务供应商为了能够更充分地利用服务器资源,同时也为了降低购买门槛,纷纷启用了虚拟主机功能。

利用虚拟主机功能,可以把一台处于运行状态的物理服务器分割成多个“虚拟的服务器”。然而,该技术无法实现目前云主机技术的硬件资源隔离,而只能让这些虚拟的服务器共同使用物理服务器的硬件资源,供应商只能限制磁盘的使用空间大小。出于各种考虑的因素(主要是价格低廉),目前依然有很多企业或个人站长在使用虚拟主机的形式来部署网站。

Apache 的虚拟主机功能使服务器能够基于用户请求的不同 IP 地址、主机域名或端口号, 同时为多个网站提供访问服务。如图 10-14 所示,用户请求的资源不同,最终获取到的网页内容也各不相同。如果大家之前没有做过网站,可能不太理解其中的原理,等一会儿搭建出实验环境并看到实验效果之后,就能明白了。

图 10-14 用户请求网站资源

再次提醒大家,在做每个实验之前请先将虚拟机还原到最初始的状态,以免多个实验之间相互产生冲突。

10.5.1 基于 IP 地址

如果一台服务器有多个 IP 地址,而且每个 IP 地址与服务器上部署的每个网站一一对应, 这样当用户请求访问不同的 IP 地址时,会访问到不同网站的页面资源。而且,由于每个网站都有一个独立的 IP 地址,这对搜索引擎优化也大有裨益。因此以这种方式提供虚拟主机功能不仅最常见,而且也受到了网站站长的欢迎(尤其是草根站长)。

第 4 章和第 9 章分别讲解了配置网络的两种方法,大家在实验中和工作中可随意选择。就当前的实验来讲,需要配置的 IP 地址如图 10-15 所示。在配置完毕并重启网络服务之后, 记得检查网络的连通性,确保 3 个 IP 地址均可正常访问,如图 10-16 所示(这很重要,一定要测试好,然后再进行下一步)。

图 10-15 使用 nmtui 命令配置网络参数

root@linuxprobe:~# nmcli connection up ens160 
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)

图 10-16 分别检查 3 个 IP 地址的连通性

第 1 步:分别在/home/wwwroot 中创建用于保存不同网站数据的 3 个目录,并向其中分别写入网站的主页文件。每个主页文件中应有明确区分不同网站内容的信息,方便稍后能直观地检查效果。

root@linuxprobe:~# mkdir -p /home/wwwroot/10
root@linuxprobe:~# mkdir -p /home/wwwroot/20
root@linuxprobe:~# mkdir -p /home/wwwroot/30
root@linuxprobe:~# echo "IP:192.168.10.10" > /home/wwwroot/10/index.html
root@linuxprobe:~# echo "IP:192.168.10.20" > /home/wwwroot/20/index.html
root@linuxprobe:~# echo "IP:192.168.10.30" > /home/wwwroot/30/index.html

第 2 步:从 httpd 服务的配置文件中第 125 行处开始,分别追加写入 3 个基于 IP 地址的虚拟主机参数,然后保存并退出。记得需要重启 httpd 服务,这些配置才生效。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf
………………省略部分输出信息………………
125 <VirtualHost 192.168.10.10>
126 DocumentRoot /home/wwwroot/10
127 ServerName www.linuxprobe.com
128 <Directory /home/wwwroot/10>
129 AllowOverride None
130 Require all granted
131 </Directory>
132 </VirtualHost>

133 <VirtualHost 192.168.10.20>
134 DocumentRoot /home/wwwroot/20
135 ServerName www.linuxprobe.com
136 <Directory /home/wwwroot/20>
137 AllowOverride None
138 Require all granted
139 </Directory>
140 </VirtualHost>

141 <VirtualHost 192.168.10.30>
142 DocumentRoot /home/wwwroot/30
143 ServerName www.linuxprobe.com
144 <Directory /home/wwwroot/30>
145 AllowOverride None
146 Require all granted
147 </Directory>
148 </VirtualHost>
………………省略部分输出信息………………
root@linuxprobe:~# systemctl restart httpd

第 3 步:此时访问网站,则会看到 httpd 服务程序的默认主页面中显示“权限不足”。大家现在应该立刻就能反应过来—这是 SELinux 在捣鬼。由于当前的/home/wwwroot 目录及里面的网站数据目录的SELinux 安全上下文与网站服务不吻合,因此 httpd 服务程序无法获取这些网站数据目录。我们需要手动把新的网站数据目录的 SELinux 安全上下文设置正确(见前文的实验),并使用 restorecon 命令让新设置的 SELinux 安全上下文立即生效,这样就可以立即看到网站的访问效果了,如图 10-17 所示。

root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/10
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/10/*
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/20
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/20/*
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/30
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/30/*
root@linuxprobe:~# restorecon -Rv /home/wwwroot
Relabeled /home/wwwroot from unconfined_u:object_r:user_home_dir_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/10 from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/10/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/20 from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/20/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/30 from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/30/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

图 10-17 使用不同 IP 地址访问基于虚拟主机搭建的网站

10.5.2 基于主机域名

当服务器无法为每个网站都分配一个独立 IP 地址的时候,可以尝试让 Apache 自动识别用户请求的域名,从而根据不同的域名请求来传输不同的内容。这种情况下的配置更加简单, 只需要保证位于生产环境中的服务器上有一个可用的 IP 地址即可(这里以 192.168.10.10 为例)。由于当前还没有介绍如何配置 DNS 解析服务,因此需要手动定义 IP 地址与域名之间的对应关系。/etc/hosts 是 Linux 系统中用于强制把某个主机域名解析到指定 IP 地址的配置文件。简单来说,只要这个文件配置正确,即使网络参数中没有 DNS 信息也依然能够将域名解析为某个 IP 地址。

第 1 步:手动定义 IP 地址与域名之间对应关系的配置文件,保存并退出后会立即生效。可以通过分别 ping 这些域名来验证域名是否已经成功解析为IP 地址。

root@linuxprobe:~# vim /etc/hosts
# Loopback entries; do not change.
# For historical reasons, localhost precedes localhost.localdomain:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.10 www.linuxprobe.com www.linuxcool.com www.linuxdown.com
………………省略部分输出信息………………
root@linuxprobe:~# ping -c 4 www.linuxprobe.com
PING www.linuxprobe.com (192.168.10.10) 56(84) bytes of data.
64 bytes from www.linuxprobe.com (192.168.10.10): icmp_seq=1 ttl=64 time=0.869 ms
64 bytes from www.linuxprobe.com (192.168.10.10): icmp_seq=2 ttl=64 time=0.141 ms
64 bytes from www.linuxprobe.com (192.168.10.10): icmp_seq=3 ttl=64 time=0.099 ms
64 bytes from www.linuxprobe.com (192.168.10.10): icmp_seq=4 ttl=64 time=0.048 ms
--- www.linuxprobe.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3043ms
rtt min/avg/max/mdev = 0.048/0.289/0.869/0.336 ms
root@linuxprobe:~#

第 2 步:分别在/home/wwwroot 中创建用于保存不同网站数据的 3 个目录,并向其中分别写入网站的主页文件。每个主页文件中应有明确区分不同网站内容的信息,方便稍后更直观地检查效果。

root@linuxprobe:~# mkdir -p /home/wwwroot/linuxprobe
root@linuxprobe:~# mkdir -p /home/wwwroot/linuxcool
root@linuxprobe:~# mkdir -p /home/wwwroot/linuxdown
root@linuxprobe:~# echo "www.linuxprobe.com" > /home/wwwroot/linuxprobe/index.html
root@linuxprobe:~# echo "www.linuxcool.com" > /home/wwwroot/linuxcool/index.html
root@linuxprobe:~# echo "www.linuxdown.com" > /home/wwwroot/linuxdown/index.html

第 3 步:从 httpd 服务的配置文件中第 125 行处开始,分别追加写入 3 个基于主机名的虚拟主机参数,然后保存并退出。记得需要重启 httpd 服务,这些配置才生效。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf
………………省略部分输出信息………………
125 <VirtualHost 192.168.10.10>
126 Documentroot /home/wwwroot/linuxprobe
127 ServerName www.linuxprobe.com
128 <Directory /home/wwwroot/linuxprobe>
129 AllowOverride None
130 Require all granted
131 </Directory>
132 </VirtualHost>

133 <VirtualHost 192.168.10.10>
134 Documentroot /home/wwwroot/linuxcool
135 ServerName www.linuxcool.com
136 <Directory /home/wwwroot/linuxcool>
137 AllowOverride None
138 Require all granted
139 </Directory>
140 </VirtualHost>

141 <VirtualHost 192.168.10.10>
142 Documentroot /home/wwwroot/linuxdown
143 ServerName www.linuxdown.com
144 <Directory /home/wwwroot/linuxdown>
145 AllowOverride None
146 Require all granted
147 </Directory>
148 </VirtualHost>
………………省略部分输出信息………………
root@linuxprobe:~# systemctl restart httpd

第 4 步:因为当前的网站数据目录还是在/home/wwwroot 目录中,因此还是必须要正确设置网站数据目录文件的 SELinux 安全上下文,使其与网站服务功能相吻合。最后记得用restorecon 命令让新配置的 SELinux 安全上下文立即生效,这样就可以立即访问基于虚拟主机搭建的网站了,效果如图 10-18 所示。

root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/linuxprobe
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/linuxprobe/*
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/linuxcool
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/linuxcool/*
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/linuxdown
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/linuxdown/*
root@linuxprobe:~# restorecon -Rv /home/wwwroot
Relabeled /home/wwwroot from unconfined_u:object_r:user_home_dir_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/linuxprobe from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/linuxprobe/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/linuxcool from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/linuxcool/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/linuxdown from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/linuxdown/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0

由于RHEL 10 系统不自带浏览器,因此我们继续从物理机访问(已修改物理机的 hosts文件):

图 10-18 使用不同域名访问基于虚拟主机搭建的网站

10.5.3 基于端口号

基于端口号的虚拟主机功能允许用户通过指定的端口号来访问服务器上的网站资源。在使用 Apache 配置虚拟主机功能时,基于端口号的配置方式是最复杂的。我们不仅要考虑httpd 服务程序的配置因素,还需要考虑到 SELinux 服务对新开设端口的监控。一般来说, 使用 80、443、8080 等端口号来提供网站访问服务是比较合理的,如果使用其他端口号则会受到 SELinux 服务的限制。

在接下来的实验中,我们不但要考虑目录上应用的 SELinux 安全上下文的限制,还需要考虑SELinux 域对 httpd 服务程序的管控。

第 1 步:在/home/wwwroot 中分别创建用于保存不同网站数据的 3 个目录,并向其中分别写入网站的主页文件。每个主页文件中应有明确区分不同网站内容的信息,方便稍后能直观地检查效果。

root@linuxprobe:~# mkdir -p /home/wwwroot/6111
root@linuxprobe:~# mkdir -p /home/wwwroot/6222
root@linuxprobe:~# mkdir -p /home/wwwroot/6333
root@linuxprobe:~# echo "port:6111" > /home/wwwroot/6111/index.html
root@linuxprobe:~# echo "port:6222" > /home/wwwroot/6222/index.html
root@linuxprobe:~# echo "port:6333" > /home/wwwroot/6333/index.html

第 2 步:在 httpd 服务配置文件的第 48 行~50 行分别添加用于监听 6111、6222 和6333 端口的参数。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf 
………………省略部分输出信息………………
37 # Listen: Allows you to bind Apache to specific IP addresses and/or
38 # ports, instead of the default. See also the <VirtualHost>
39 # directive.
40 #
41 # Change this to Listen on a specific IP address, but note that if
42 # httpd.service is enabled to run at boot time, the address may not be
43 # available when the service starts. See the httpd.service(8) man
44 # page for more information.
45 #
46 #Listen 12.34.56.78:80
47 Listen 80
48 Listen 6111
49 Listen 6222
50 Listen 6333
………………省略部分输出信息………………

第 3 步:从 httpd 服务的配置文件中第 127 行处开始,分别追加写入 3 个基于端口号的虚拟主机参数,然后保存并退出。记得需要重启 httpd 服务,这些配置才生效。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf
………………省略部分输出信息………………
127 <VirtualHost 192.168.10.10:6111>
128 DocumentRoot /home/wwwroot/6111
129 ServerName www.linuxprobe.com
130 <Directory /home/wwwroot/6111>
131 AllowOverride None
132 Require all granted
133 </Directory>
134 </VirtualHost>

135 <VirtualHost 192.168.10.10:6222>
136 DocumentRoot /home/wwwroot/6222
137 ServerName www.linuxprobe.com
138 <Directory /home/wwwroot/6222>
139 AllowOverride None
140 Require all granted
141 </Directory>
142 </VirtualHost>

143 <VirtualHost 192.168.10.10:6333>
144 DocumentRoot /home/wwwroot/6333
145 ServerName www.linuxprobe.com
146 <Directory /home/wwwroot/6333>
147 AllowOverride None
148 Require all granted
149 </Directory>
150 </VirtualHost>
………………省略部分输出信息………………

第 4 步:因为我们把网站数据目录存放在/home/wwwroot 目录中,因此还是必须要正确设置网站数据目录文件的 SELinux 安全上下文,使其与网站服务功能相吻合。最后记得用restorecon 命令让新配置的 SELinux 安全上下文立即生效。

root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/6111
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/6111/*
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/6222
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/6222/*
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/6333
root@linuxprobe:~# semanage fcontext -a -t httpd_sys_content_t /home/wwwroot/6333/*
root@linuxprobe:~# restorecon -Rv /home/wwwroot/
Relabeled /home/wwwroot from unconfined_u:object_r:user_home_dir_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/6111 from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/6111/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/6222 from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/6222/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/6333 from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
Relabeled /home/wwwroot/6333/index.html from unconfined_u:object_r:user_home_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
root@linuxprobe:~# systemctl restart httpd
Job for httpd.service failed because the control process exited with error code.
See "systemctl status httpd.service" and "journalctl -xeu httpd.service" for details.

见鬼了!在妥当配置 httpd 服务程序和 SELinux 安全上下文并重启 httpd 服务后,竟然出现了报错信息。这是因为 SELinux 服务检测到 6111、6222 和 6333 端口原本不属于Apache 服务应该需要的资源,但现在却以 httpd 服务程序的名义监听使用了,所以 SELinux 会拒绝使用Apache 服务使用这3 个端口。可以使用semanage 命令查询并过滤出所有与HTTP 相关且 SELinux 服务允许的端口列表。

root@linuxprobe:~# semanage port -l | grep http
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989

第 5 步:SELinux 允许的与 HTTP 相关的端口号中默认没有包含 6111、6222 和 6333, 因此需要将这 3 个端口号手动添加进去。该操作会立即生效,而且在系统重启后依然有效。

root@linuxprobe:~# semanage port -a -t http_port_t -p tcp 6111
root@linuxprobe:~# semanage port -a -t http_port_t -p tcp 6222
root@linuxprobe:~# semanage port -a -t http_port_t -p tcp 6333
root@linuxprobe:~# semanage port -l | grep http
http_cache_port_t tcp 8080, 8118, 8123, 10001-10010
http_cache_port_t udp 3130
http_port_t tcp 6333, 6222, 6111, 80, 81, 443, 488, 8008, 8009, 8443, 9000
pegasus_http_port_t tcp 5988
pegasus_https_port_t tcp 5989

第6 步:在防火墙上开启“放行 6111、6222 和 6333 端口流量”的访问控制策略。设置好后再重启 httpd 服务程序,然后就可以看到网页内容了,如图 10-19 所示。

root@linuxprobe:~# firewall-cmd --permanent --add-port=6111/tcp
success
root@linuxprobe:~# firewall-cmd --permanent --add-port=6222/tcp
success
root@linuxprobe:~# firewall-cmd --permanent --add-port=6333/tcp
success
root@linuxprobe:~# firewall-cmd --reload
success
root@linuxprobe:~# systemctl restart httpd

图 10-19 使用不同端口号访问基于虚拟主机搭建的网站

10.6 Apache的访问控制

Apache 可以基于源主机名、源 IP 地址或源主机上的浏览器特征等信息对网站上的资源进行访问控制。它通过Allow 指令允许某个主机访问服务器上的网站资源,通过 Deny 指令实现禁止访问。在允许或禁止访问网站资源时,还会用到 Order 指令,这个指令用来定义Allow 或 Deny 指令起作用的顺序,其匹配原则是按照顺序进行匹配,若匹配成功则执行后面的默认指令。比如“Order Allow, Deny”表示先将源主机与允许规则进行匹配,若匹配成功则允许访问请求,反之则拒绝访问请求。

第 1 步:先在服务器上的网站数据目录中新建一个子目录,并在这个子目录中创建一个包含Successful 单词的主页文件。

root@linuxprobe:~# mkdir /var/www/html/server
root@linuxprobe:~# echo "Successful" > /var/www/html/server/index.html

第 2 步:打开 httpd 服务的配置文件,在第 163 行后面添加下述规则来限制源主机的访问。这段规则的含义是允许使用 Firefox 浏览器的主机访问服务器上的主页文件,除此之外的所有请求都将被拒绝。使用 Firefox 浏览器的访问效果如图 10-20 所示,使用其他浏览器的访问效果如图 10-21 所示。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf
………………省略部分输出信息………………
163 <Directory "/var/www/html/server">
164 SetEnvIf User-Agent "Firefox" ff=1
165 Order allow,deny
166 Allow from env=ff
167 </Directory>
………………省略部分输出信息………………
root@linuxprobe:~# systemctl restart httpd
root@linuxprobe:~# systemctl enable httpd
Created symlink '/etc/systemd/system/multi-user.target.wants/httpd.service' → '/usr/lib/systemd/system/httpd.service'.

图 10-20 Firefox 浏览器访问成功

图 10-21 其他浏览器访问失败

除了匹配源主机的浏览器特征之外,还能够通过匹配源主机的 IP 地址进行访问控制。例如,如果只允许 IP 地址为 192.168.10.20 的主机访问网站资源,那么就可以在 httpd 服务配置文件的第 163 行后面添加下述规则。这样在重启 httpd 服务程序后再用本机(即服务器,其 IP 地址为 192.168.10.10)来访问网站的主页时就会提示访问被拒绝了,如图 10-22 所示。

root@linuxprobe:~# vim /etc/httpd/conf/httpd.conf
………………省略部分输出信息………………
161 <Directory "/var/www/html/server">
162 Order allow,deny
163 Allow from 192.168.10.20
164 </Directory>
………………省略部分输出信息………………
root@linuxprobe:~# systemctl restart httpd

图 10-22 因 IP 地址不符合要求而被拒绝访问

复习题

  1. 什么是 Web 网络服务?

    答:一种允许用户通过浏览器访问互联网中各种资源的服务。

  2. 相较于 Nginx 服务程序,Apache 服务程序最大的优势是什么?

    答:Apache 服务程序具备跨平台特性、安全性,而且拥有快速、可靠、简单的 API 扩展。

  3. httpd 服务程序没有检查到主页文件,会提示报错信息吗?

    答:不会,httpd 服务在未找到网站主页文件时,会向访客显示一个默认页面。

  4. 简述Apache 服务主配置文件中全局配置参数、区域配置参数和注释行信息的作用。

    答:全局配置参数是一种全局性的配置参数,可作用于所有的子站点;区域配置参数则是单独针对每个独立的子站点设置的;而注释行信息一般用于对服务程序的功能或某一行参数进行介绍。

  5. 简述SELinux 服务的作用。

    答:让各个服务进程都受到约束,使其仅获取到本应获取的资源。

  6. 在使用getenforce 命令查看 SELinux 服务模式时,发现其配置模式为permissive, 这代表强制开启模式吗?

    答:不是,强制开启模式是 enforcing,而 permissive 是只发出警告而不强制拦截的模式。

  7. 在使用 semanage 命令修改了文件上应用的 SELinux 安全上下文后,还需要执行什么命令才可以让更改立即生效?

    答:还需要执行 restorecon 命令即可让新的 SELinux 安全上下文参数立即生效。

  8. 要想查询并过滤出所有与 HTTP 相关的 SELinux 域策略有哪些,应该怎么做呢?

    答:可以结合管道符来实现,即执行getsebool –a | grep http 命令。

  9. Apache 服务程序可以基于哪些资源来创建虚拟主机搭建的网站呢?

    答:可以基于IP 地址、主机名(域名)或者端口号来创建。

  10. 相对于基于IP 地址和基于主机名(域名)配置的虚拟主机网站来说,使用端口号配置的虚拟主机网站有哪些特点?

    答:在使用端口号来配置虚拟主机网站时,必须要考虑 SELinux 域针对 httpd 服务程序所用端口号的控制策略,还要在 httpd 服务程序的主配置文件中使用Listen 参数开启要监听的端口号。