CentOS7-Linux-服务器秘籍-全-

CentOS7 Linux 服务器秘籍(全)

原文:zh.annas-archive.org/md5/85DEE4E32CF6CFC6347B684FDF685546

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

本书是备受好评的《CentOS Linux 服务器食谱》的第二版。随着 2014 年年中 CentOS 7 的推出,这个著名的操作系统迎来了一系列重大变化和新特性。例如,新的安装程序、系统管理服务套件、防火墙守护进程、增强的 Linux 容器支持以及新的标准文件系统。由于操作系统的新进展,《CentOS 6 Linux 服务器食谱》中很大一部分的食谱变得过时甚至无法使用,因此更新本书的原始内容至关重要。但本书不仅仅是第一版内容的复习:还新增了两章,以跟上最新的开源技术并提供更好的安全性:操作系统级虚拟化和 SELinux。最后,为了使本书成为更全面的服务器管理书籍,还增加了一章关于服务器监控的内容。

构建服务器可能会带来挑战。在最好的情况下也常常是困难的,在最坏的情况下则是令人沮丧的。它们可能代表最大的问题,也可能给你带来极大的自豪和成就感。尽管“服务器”这个词可以描述很多事物,但本书的目的是揭开企业级计算系统的神秘面纱,旨在帮助你构建你选择的专业服务器解决方案。CentOS 是一个基于社区的企业级操作系统。它是免费提供的,并且作为 Red Hat Enterprise Linux(RHEL)的完全兼容衍生版本,它是全球组织、公司、专业人士和家庭用户打算运行服务器的首选操作系统。它被广泛认为是一个非常强大和灵活的 Linux 发行版,无论你打算运行 Web 服务器、文件服务器、FTP 服务器、域服务器还是多角色解决方案,本书的目的都是提供一系列即用型解决方案,展示你如何快速使用 CentOS 操作系统构建一个功能全面的服务器系统。因此,可以说这本书不仅仅是对另一个基于服务器的操作系统的又一次介绍。这是一本关于企业级操作系统的食谱,提供了一种逐步使其工作的方法。因此,无论你是新手还是经验丰富的用户,每个人都能在这本书中找到有用的内容,因为这本书将成为你完成任务的实用指南,也是所有 CentOS 事物的起点。

本书内容概述

第一章,安装 CentOS,是一系列介绍您安装服务器任务的配方,更新,并通过添加额外工具来增强最小安装。它旨在让您开始,并提供一个参考,向您展示实现所需安装的多种方式。

第二章,配置系统,旨在在成功安装后提供帮助,并为您提供一系列配方,使您能够实现所需的服务器初始配置。从向您展示如何处理文本文件,然后更改语言和时间日期设置,您不仅将学习如何配置网络设置,还将学习如何解析完全限定域名以及如何使用内核模块。

第三章,管理系统,提供了构建块,使您能够掌握您的服务器并控制您的环境。在这里,您将通过传播大量信息来启动您作为服务器管理员的角色,这些信息将引导您完成开发全面考虑和专业服务器解决方案所需的多种步骤。

第四章,使用 YUM 管理软件包,旨在向您介绍在 CentOS 7 上使用软件包的工作。从升级系统到查找、安装、卸载以及通过添加额外的仓库来增强系统,本章的目的是解释开源命令行包管理工具,即 Yellowdog Updater Modified(YUM)以及 RPM 包管理器。

第五章,管理文件系统,专注于与服务器文件系统的工作。从创建模拟磁盘设备以测试概念到高级格式化和分区命令,您将学习如何使用逻辑卷管理器,维护文件系统以及使用磁盘配额。

第六章,提供安全性,讨论了实施一系列解决方案的必要性,这些解决方案将提供您运行成功服务器解决方案所需级别的保护。从保护您的 ssh 和 FTP 服务,到了解新的 firewalld 管理器和创建证书,您将看到构建一个不仅考虑减少外部攻击风险,而且为您的用户提供额外保护的服务器是多么容易。

第七章,构建网络,解释了在您的网络计算机中实现各种形式的资源共享所需的步骤。从 IP 地址和打印设备到各种形式的文件共享协议,无论您是打算支持家庭网络还是完整的商业环境,本章在任何服务器中都扮演着至关重要的角色。

第八章,使用 FTP,专注于 VSFTP 的角色,并提供了一系列的食谱,将为您提供所需的指导,以在 CentOS 7 服务器上安装、配置和管理您想要提供的文件传输协议(FTP)。

第九章,使用域名,考虑了在 CentOS 7 服务器上实施域名、域名解析和 DNS 查询所需的步骤。域名系统在任何服务器中都扮演着至关重要的角色,无论您是打算支持家庭网络还是完整的商业环境,本章的目的是提供一系列的解决方案,将为您提供一个未来证明的解决方案的开始。

第十章,使用数据库,提供了一系列的食谱,旨在解释在 CentOS 7 服务器上部署 MySQL 和 PostgreSQL 所需的必要步骤。

第十一章,提供邮件服务,向您介绍如何为您的 CentOS 7 服务器启用域范围内的邮件传输代理。从构建本地 POP3/SMTP 服务器到配置 Fetchmail,本章的目的是为您的所有未来基于电子邮件的需求提供基础。

第十二章,提供 Web 服务,深入研究了著名的 Apache 服务器技术的角色,无论您是打算运行开发服务器还是实时生产服务器,本章都为您提供了必要的步骤,以提供您成为基于 Web 的发布解决方案大师所需的功能。

第十三章,操作系统级虚拟化,向您介绍使用最先进的开源平台 Docker 的 Linux 容器世界,并指导您构建、运行和共享您的第一个 Docker 镜像。

第十四章,使用 SELinux,有助于理解和解开 CentOS 7 中最不为人知的话题之一——安全增强型 Linux 的神秘面纱。

第十五章,监控 IT 基础设施,介绍并展示了如何设置 Nagios Core,这是监控整个 IT 基础设施的行业标准。

本书所需

本书的要求相对简单,首先是需要下载 CentOS 操作系统。该软件是免费的,但你需要一台能够充当服务器的计算机,一些免费的安装介质(空白 CD-R/DVD-R 或 USB 设备),互联网连接,一些空闲时间,以及享受乐趣的愿望。

话虽如此,许多读者都会意识到,你不需要一台备用计算机来利用这本书,因为始终可以选择在虚拟化软件上安装 CentOS。这种方法非常常见,在这些页面中包含的食谱仍然适用的情况下,你应该知道本书不考虑使用虚拟化软件。因此,任何关于使用该软件的支持请求都应直接向相应的供应商提出。

本书适合谁

这是一本关于构建服务器解决方案的实用指南,而不是关于 CentOS 本身。本书将向你展示如何让 CentOS 运行起来。它是一本为初学者到中级 Linux 用户编写的书,他们打算将 CentOS 作为下一个服务器的基础。但是,如果你对整个操作系统还不熟悉,那么不用担心;本书还将为你提供构建完整服务器解决方案所需的逐步方法,并附带许多行业技巧。

章节

在本书中,你会发现一些频繁出现的标题(准备就绪,如何做,它是如何工作的,还有更多)。

为了给出如何完成食谱的明确指示,我们使用以下章节:

准备就绪

本节告诉你食谱中可以期待的内容,并描述如何设置任何软件或任何预先设置,这些是食谱所必需的。

如何做…

本节包含遵循食谱所需的步骤。

它是如何工作的…

本节通常包含对上一节中发生的事情的详细解释。

还有更多…

本节包含有关食谱的额外信息,旨在使读者对食谱有更深入的了解。

约定

在本书中,你会发现许多文本样式,用于区分不同类型的信息。以下是这些样式的一些示例及其含义的解释。

文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄如下所示:“为了本食谱的目的,假设所有下载将存储在 Windows 上的个人C:\Users\<username>\Downloads文件夹中,或者如果使用 OS X 系统,则存储在/Users/<username>/Downloads文件夹中。”

代码块的设置如下:

<?xml version="1.0" encoding="utf-8"?>
<service>
  <description>enable FTPS ports</description>
  <port protocol="tcp" port="40000-40100"/>
  <port protocol="tcp" port="21"/>
  <module name="nf_conntrack_ftp"/>
</service>

任何命令行输入或输出如下所示:

sudo diskutil unmountDisk /dev/disk3
sudo dd if=./CentOS-7-x86_64-Minimal-XXXX.iso of=/dev/disk3 bs=1M

新术语重要词汇以粗体显示。您在屏幕上看到的单词,例如在菜单或对话框中,如下所示:“单击下一步按钮将您移动到下一个屏幕。”

注意

警告或重要注意事项以这样的框显示。

提示

提示和技巧如下所示。

读者反馈

我们始终欢迎读者的反馈。请告诉我们您对这本书的看法——您喜欢或不喜欢的地方。读者反馈对我们很重要,因为它帮助我们开发您将真正从中受益的标题。

要向我们发送一般反馈,只需发送电子邮件至<feedback@packtpub.com>,并在您的消息主题中提及书的标题。

如果您在某个主题上具有专业知识,并且有兴趣撰写或为书籍做出贡献,请参阅我们的作者指南,网址为www.packtpub.com/authors

客户支持

既然您是 Packt 书籍的自豪拥有者,我们有一系列的事情可以帮助您从购买中获得最大收益。

勘误

尽管我们已经尽一切努力确保我们内容的准确性,但错误仍然会发生。如果您在我们的书中发现错误——可能是文本或代码中的错误——如果您能向我们报告,我们将不胜感激。通过这样做,您可以节省其他读者的烦恼,并帮助我们改进这本书的后续版本。如果您发现任何勘误,请通过访问www.packtpub.com/submit-errata来报告它们,选择您的书,点击勘误提交表单链接,并输入您的勘误细节。一旦您的勘误经过验证,您的提交将被接受,勘误将被上传到我们的网站或添加到该标题的勘误部分下的任何现有勘误列表中。

要查看以前提交的勘误,请访问www.packtpub.com/books/content/support并在搜索字段中输入书名。所需信息将出现在勘误部分下。

盗版

互联网上版权材料的盗版是所有媒体持续存在的问题。在 Packt,我们非常认真地保护我们的版权和许可。如果您在互联网上遇到任何形式的我们作品的非法副本,请立即向我们提供位置地址或网站名称,以便我们可以采取补救措施。

请通过 <copyright@packtpub.com> 联系我们,并提供涉嫌盗版材料的链接。

我们感谢您在保护我们的作者和为我们带来有价值内容的能力方面提供的帮助。

问题

如果您在本书的任何方面遇到问题,可以通过 <questions@packtpub.com> 联系我们,我们将尽力解决问题。

第一章:安装 CentOS

在本章中,我们将涵盖:

  • 在 Windows 或 OS X 上下载 CentOS 并确认校验和

  • 在 Windows 或 OS X 上创建 USB 安装介质

  • 使用图形安装程序执行 CentOS 安装

  • 通过 HTTP 进行网络安装

  • 使用 kickstart 文件安装 CentOS

  • 重新安装引导加载程序

  • 在救援模式下排除系统故障

  • 开始使用并自定义引导加载程序

  • 更新安装并使用额外的管理和发展工具增强最小安装

引言

本章是一系列涵盖安装 CentOS 7 操作系统基本实践的操作的集合。本章的目的是向您展示您可以多快地让 CentOS 运行起来,同时让您能够使用一些“行业技巧”来定制您的安装。

在 Windows 或 OS X 上下载 CentOS 并确认校验和

在本操作中,我们将学习如何使用典型的 Windows 或 OS X 桌面计算机下载并确认一个或多个 CentOS 7 磁盘映像的校验和。CentOS 通过 HTTP、FTP 或 rsync 协议从全球各地的一系列镜像站点或通过 BitTorrent 网络以各种格式提供。对于从互联网下载非常重要的文件,例如操作系统映像,验证这些文件的校验和被认为是最佳实践,以确保任何生成的媒体在安装时都能按预期运行和执行。这也确保了文件是真实的,并且来自原始来源。

准备

要完成此操作,假设您正在使用具有完全管理权限的典型 Windows(Windows 7、Windows Vista 或类似)或 OS X 计算机。您需要互联网连接以下载所需的安装文件,并且需要访问具有适当软件的标准 DVD/CD 刻录机,以便从映像文件创建相关的安装磁盘。对于此操作,假设所有下载将存储在 Windows 上的个人C:\Users\<username>\Downloads文件夹中,或者如果使用 OS X 系统,则存储在/Users/<username>/Downloads文件夹中。

如何操作...

无论您下载哪种类型的安装文件,以下技术都可以应用于 CentOS 项目提供的所有映像文件:

  1. 让我们首先在网络浏览器中访问www.centos.org,导航到立即获取 CentOS按钮链接。然后点击文本中的当前镜像列表链接。

  2. 镜像站点被分类,因此从链接列表中选择一个地理位置接近您当前位置的镜像。例如,如果您在伦敦(英国),您可以选择来自欧盟英国的镜像。现在通过选择 HTTP 或 FTP 链接来选择一个镜像站点。

  3. 做出选择后,现在将看到所有可用 CentOS 版本的目录列表。要继续,只需单击读取7的相应文件夹。接下来,您将看到一个额外的目录列表,如atomiccentospluscloud等。我们选择isos目录继续。

  4. CentOS 7 目前仅支持 64 位架构,因此浏览到唯一可用的标记为x86_64的目录,这是一个包含 64 位版本的容器。

  5. 现在将为您提供一系列可供下载的文件。首先下载有效的校验和结果副本,标识为md5sum.txt

  6. 如果您是 CentOS 新手或打算遵循本书中找到的配方,那么最小安装是理想的。这包含尽可能少的软件包以拥有一个功能系统,因此选择以下内容(XXXX是此版本的月份标记):

    CentOS-7-x86_64-Minimal-XXXX.iso
    
    
  7. 仅在基于 Windows 的系统上(在 Mac 上,此工具已在系统中可用),在浏览器中访问mirror.centos.org/centos/dostools/并下载程序md5sum.exe

  8. 现在在 Windows 上,打开命令提示符(通常位于开始 | 所有程序 | 附件 | 命令提示符)并输入以下命令到打开的窗口中(在所有行的末尾按下回车键):

    cd downloads
    dir
    
    
  9. 在 OS X 上,打开程序Finder | Applications | Utilities | Terminal,然后输入以下命令(在所有行的末尾按下回车键):

    cd ~/Downloads
    ls
    
    
  10. 现在您应该看到下载文件夹中的所有文件(包括所有下载的 CentOS 安装图像文件、md5sum.txt 文件以及在 Windows 上的 md5sum.exe 程序)。

  11. 根据显示的文件名,修改以下命令以检查您下载的 ISO 图像文件的校验和。在 Windows 上,输入以下命令(根据需要更改XXXX月份标记):

    md5sum.exe CentOS-7-x86_64-Minimal-XXXX.iso
    
    
  12. 在 OS X 上,请使用以下命令:

    md5 CentOS-7-x86_64-Minimal-XXXX.iso
    
    
  13. 按下回车键继续,然后等待命令提示符响应。响应被称为 MD5 总和,结果可能看起来像以下内容:

    d07ab3e615c66a8b2e9a50f4852e6a77  CentOS-7-x86_64-Minimal-1503-01.iso
    
    
  14. 现在查看总和,并与md5sum.txt文件中与您的特定图像文件相关的列表进行比较(在文本编辑器中打开)。如果两个数字匹配,那么您可以确信您确实下载了一个有效的 CentOS 图像文件。如果不是,您的下载文件可能已损坏,因此请重新启动此过程,再次下载图像文件。

  15. 完成后,只需使用您首选的桌面软件将您的图像文件刻录到空白 CD-ROM 或 DVD-ROM 上,或者从中创建 USB 安装介质,我们将在本章的下一个配方中向您展示。

它是如何工作的…

那么我们从这次经历中学到了什么?

下载 CentOS 安装镜像只是构建完美服务器的第一步。尽管这个过程非常简单,但许多人忘记了确认校验和的必要性。在本书中,我们将使用最小安装镜像,但您应该知道还有其他安装选项可供您选择,例如 NetInstall、DVD、Everything 和各种 LiveCDs。

在 Windows 或 OS X 上创建 USB 安装介质

在本操作中,我们将学习如何在 Windows 或 OS X 上创建 USB 安装介质。如今,越来越多的服务器系统、台式机和笔记本电脑在发货时不带任何光驱。使用 USB 设备安装新操作系统,例如 CentOS Linux,对于它们来说变得至关重要,因为没有其他安装选项可用,因为没有其他方式可以启动安装介质。此外,使用 USB 介质安装 CentOS 可以比使用 CD/DVD 方法快得多。

准备工作

在我们开始之前,假设您已经按照前面的操作步骤,下载了最小化的 CentOS 镜像并确认了相关镜像文件的校验和。同时,假设所有下载内容(包括下载的 ISO 文件)都存储在 Windows 上的C:\Users\<username>\Downloads文件夹中,或者在使用 OS X 系统时,存储在/Users/<username>/Downloads文件夹中。接下来,您需要一个能够被操作系统识别的空闲 USB 设备,该设备有足够的总空间,并且是空的或者其上的数据可以丢弃。准备作为 CentOS 7 最小版本安装介质的 USB 设备所需的总空间大约为 700 兆字节。如果您使用的是 Windows 计算机,您需要一个有效的互联网连接来下载额外的软件。在 OS X 上,您需要一个管理员用户账户。

如何操作...

开始此操作前,启动您的 Windows 或 OS X 操作系统,然后连接一个足够容量的空闲 USB 设备,并等待它被 Windows 下的文件管理器或 OS X 下的Finder识别。

  1. 在基于 Windows 的系统上,我们需要下载一个额外的软件叫做dd。访问您最喜欢的浏览器中的www.chrysocome.net/dd。现在下载那里最新的dd-XX.zip文件,其中XX是最新的稳定版本号。例如,dd-0.5.zip

  2. 在 Windows 上,使用文件管理器导航到您的Downloads文件夹。在这里,您将找到dd-05.zip文件。右键点击它并选择全部提取,然后提取dd.exe文件,不要创建任何子目录。

  3. 在 Windows 上,打开命令提示符(通常位于开始 | 所有程序 | 附件 | 命令提示符)并输入以下命令:

    cd downloads
    dd.exe --list
    
    
  4. 在 OS X 上,打开Finder | 应用程序 | 实用工具 | 终端程序,然后输入以下命令:

    cd ~/Downloads
    diskutil list
    
    
  5. 在 Windows 系统中,要找到你想要用作安装介质的正确 USB 设备的名称,请查看命令输出中的removable media部分。在此之下,你应该会找到一条以Mounting on开头的行,后面跟着一个驱动器字母,例如,\.\e:。这个用晦涩方式书写的驱动器字母是下一步中最重要的部分,所以请记下来。

  6. 在 OS X 系统中,设备路径可以在前一个命令的输出中找到,格式为/dev/disk<number>,其中number是磁盘的唯一标识符。磁盘编号从零(0)开始。磁盘0很可能是 OS X 恢复磁盘,而磁盘1很可能是你的主 OS X 安装。要识别你的 USB 设备,尝试比较NAMETYPESIZE列与你的 USB 闪存盘的规格。如果你已经确定了设备名称,请记下来,例如,/dev/disk3

  7. 在 Windows 系统中,输入以下命令,假设你选作安装介质的 USB 设备在 Windows 中的设备名称为\\.\e:(根据需要更改此设置,并小心输入——这可能会造成巨大的数据丢失)。同时,在下一个命令中将XXXX替换为正确的iso文件版本号:

    dd.exe if=CentOS-7-x86_64-Minimal-XXXX.iso of=\\.\e: bs=1M
    
    
  8. 在 OS X 系统中,你需要两个命令,这两个命令会要求输入管理员密码(将XXXXdisk3替换为正确的版本号和正确的 USB 设备路径):

    sudo diskutil unmountDisk /dev/disk3
    sudo dd if=./CentOS-7-x86_64-Minimal-XXXX.iso of=/dev/disk3 bs=1m
    
    
  9. dd程序完成后,会有一些输出统计信息,显示复制过程耗时以及传输了多少数据。在 OS X 系统中,忽略任何关于磁盘不可读的警告信息。

  10. 恭喜!你现在已经创建了你的第一个 CentOS 7 USB 安装介质。现在你可以在 Windows 或 OS X 系统中安全地移除 USB 驱动器,并物理拔出设备,将其用作在目标机器上安装 CentOS 7 的启动设备。

它是如何工作的...

那么,我们从这次经历中学到了什么?

本教程的目的是向你介绍使用dd命令行程序在 USB 设备上创建 CentOS 安装 ISO 文件的精确副本的概念。dd程序是一个基于 Unix 的工具,可用于将位从源复制到目标文件。这意味着源被逐位读取并写入目标,不考虑内容或文件分配;它只是涉及读取和写入纯原始数据。它期望两个基于文件名的参数:输入文件(if)和输出文件(of)。我们将使用 CentOS 镜像文件作为我们的输入文件名,将其精确地1:1克隆到 USB 设备上,该设备可通过其设备文件作为我们的输出文件参数访问。bs参数定义了块大小,即一次要复制的数据量。请小心,这是一个绝对的专业工具,在复制数据时会覆盖目标上的任何现有数据,而无需进一步确认或任何安全检查。因此,至少要双重检查目标 USB 设备的驱动器字母,切勿混淆它们!例如,如果你在D:上安装了第二个硬盘,在E:上安装了 USB 设备(在 OS X 上,分别为/dev/disk2/dev/disk3),并且你混淆了驱动器字母E:D:(或/dev/disk3/dev/disk2),你的第二个硬盘将被擦除,几乎没有恢复任何丢失数据的机会。所以请小心处理!如果你对正确的输出文件设备有疑问,切勿启动dd程序!

总之,可以公平地说,对于创建 CentOS 7 的 USB 安装媒体,存在比dd命令更为便捷的解决方案,例如 Fedora Live USB Creator。但本教程的目的不仅在于制作一个即用的 CentOS USB 安装器,还在于让你熟悉dd命令。这是一个常见的 Linux 命令,每位 CentOS 系统管理员都应该知道如何使用。它可以用于广泛的日常任务,例如安全擦除硬盘、网络速度基准测试或创建随机二进制文件。

使用图形安装程序执行 CentOS 安装

在本教程中,我们将学习如何使用 CentOS 7 中引入的新图形安装程序界面执行典型的 CentOS 安装。在很多方面,这被认为是安装系统的推荐方法,因为它不仅允许你创建所需的硬盘分区,还允许你在很多方面自定义安装(例如,键盘布局、软件包选择、安装类型等)。然后,你的安装将构成一个服务器的基础,在这个服务器上,你可以构建、开发和运行任何类型的服务,你将来可能希望提供这些服务。

准备就绪

在我们开始之前,假设您已经按照之前的步骤操作,其中您被展示了如何下载 CentOS 镜像,确认相关镜像文件的校验和,并创建相关的安装光盘或 USB 介质。您的系统必须是 64 位(x86_64)架构,至少需要 406MB RAM 来加载图形安装程序(如果安装图形窗口管理器如 Gnome,则建议 1GB 或更多),并且至少有 10GB 的可用硬盘空间。

如何操作...

要开始这个步骤,插入您的安装介质(CD/DVD 或 USB 设备),重新启动计算机,并在启动时按下选择启动设备的正确键。然后从列表中选择插入的设备(对于许多计算机,这可以通过F11F12访问,但在您的系统上可能不同。请参考您的主板手册)。

  1. 在欢迎屏幕上,测试此媒体并安装 CentOS 7选项已被预选,我们将使用此选项。准备好后,按回车键继续。

  2. 加载一些初始文件后,安装程序开始测试安装介质。单个测试应在 30 秒到五分钟之间,并会报告您的安装介质上是否有任何错误。当这个过程完成后,系统最终将加载图形安装程序。

  3. CentOS 安装程序现在将显示图形安装欢迎屏幕。从这一点开始,您可以使用键盘和鼠标(后者强烈推荐),但如果您打算使用数字键盘,请记得在键盘上启用数字锁定。

  4. 在左侧,您会看到主要的语言类别,在右侧,安装程序的子语言。您还可以使用左下角的文本框搜索语言。对语言设置的所有更改将立即生效,因此,当您准备好后,选择继续按钮以继续。

  5. 现在我们到达了主要的安装菜单,称为安装摘要

  6. 这里显示的大多数选项已经有一些预设值,无需更改即可使用,而那些没有默认值且需要您注意的选项则标有红色感叹号,例如系统类别下的安装目的地。因此,让我们使用鼠标点击它。

  7. 点击安装位置按钮后,你将看到一个图形列表,列出了当前连接到你计算机的所有硬盘设备,你可以用它们来安装操作系统。你可以通过点击正确的硬盘图标来选择你的目标硬盘。然后它会在上面打上勾。如果你不确定正确的硬盘,尝试通过比较菜单中显示的品牌和总大小来识别它。在安装可以进行之前,你必须选择一个硬盘。请小心并明智地选择你的目标硬盘,因为安装过程中它将擦除任何现有数据。准备就绪后,点击完成按钮。

  8. 如果你的选定硬盘已经包含数据,那么在点击完成时,你可能会看到一个可以被描述为警告/错误消息的信息。该消息可能显示:你没有足够的可用空间来安装 CentOS。别担心!这是预期中的,消息只是要求你重新初始化你的硬盘,因为 CentOS 只能安装在空白的硬盘上。在大多数情况下,特别是如果你在硬盘上有多个分区,只需点击回收空间,这将显示一个新窗口,其中列出了该驱动器上的所有分区。在这里,只需点击删除所有,然后再次点击回收空间,以丢弃该硬盘上的任何数据,这将完成硬盘初始化的任务,并允许你继续下一步。完成后,点击完成按钮。

  9. 回到安装摘要屏幕,安装位置项上的感叹号现在应该消失了。

  10. 系统类别下,我们可以选择性地点击网络与主机名。在接下来的页面中,左侧你可以选择你希望连接到互联网的主要网络适配器,并通过点击它来选中。对于选中的设备,点击右侧的开关以启用并自动连接,使用开关的开启位置。最后,在关闭此子菜单之前,将其文本字段中的主机名更改为适当的名称。点击完成

  11. 现在回到安装摘要屏幕,所有重要设置都已经完成或获得了预设值,所有感叹号都消失了。如果你对这些设置满意,点击开始安装按钮,或者根据需要更改设置。

  12. 在下一个屏幕上,你需要为 root 用户创建并确认一个 root 密码,同时新系统在后台进行安装。选择一个不少于六个字符的安全密码。

  13. 在此屏幕上,你还可以创建一个标准用户账户,这是非常推荐的。如果你创建了一个新用户,请不要勾选使该用户成为管理员。准备就绪后,点击完成(如果你输入了一个弱密码,你需要通过点击两次来确认)。

  14. CentOS 现在将在后台对硬盘进行分区和格式化,并解决任何依赖关系,安装程序将开始向硬盘写入数据。这可能需要一些时间,但进度条将指示安装状态。完成后,安装程序将通知您整个过程已完成,并且安装成功。准备好后,点击重启按钮。现在从驱动器中取出安装介质。

  15. 恭喜!您已成功在计算机上安装了 CentOS 7。

它是如何工作的…

在本教程中,您已经了解了如何安装 CentOS 7 操作系统。在介绍了图形安装过程的典型方法之后,您现在可以对服务器进行额外的配置更改和软件包安装,以满足您打算让服务器承担的角色。这个图形安装程序旨在非常直观和灵活,使得安装过程非常简单,因为它将引导用户完成一些强制性任务,这些任务必须在开始安装主系统之前完成。

通过 HTTP 进行网络安装

在本教程中,我们将学习如何通过 HTTP(使用 URL 方法)启动网络安装过程,以便安装 CentOS 7。这是一个使用一个小型映像文件来启动计算机,并允许用户通过网络连接选择并安装他想要的软件包和服务的过程,而不安装其他任何东西,从而提供了极大的灵活性。

准备就绪

在我们开始之前,假设您已经知道如何下载和校验 CentOS 7 安装映像,以及如何从中创建相关的安装介质。对于本教程,我们需要下载并创建网络安装映像的安装介质(下载最新的 CentOS-7-x86_64-NetInstall-XXXX.iso 文件),而不是本章中另一个教程中显示的最小 ISO。此外,假设您至少已经通过一次图形安装过程,确切知道如何从安装介质启动并使用安装程序。

如何操作…

要开始本教程,请插入您准备好的网络安装介质,从它启动计算机,并等待欢迎屏幕出现:

  1. 在欢迎屏幕上,测试此介质并安装 CentOS 7选项已被预选,我们将使用此选项。准备好后,按回车键继续。

  2. 测试完成后,图形安装程序将加载并显示典型的图形安装摘要屏幕。

    注意

    在这里,安装程序应该像在正常图形安装教程中一样进行配置,除了对网络和主机名以及安装源菜单项进行以下强制性更改(由红色感叹号指示)。

  3. 在我们能够通过网络安装 CentOS 之前,我们必须确保我们有可用的网络连接。因此,您应该首先点击 网络和主机名 菜单项,并将您的网络适配器激活到连接状态。有关更多详细信息,请参阅正常安装食谱。

  4. 接下来,点击 安装源 进入设置。由于我们将通过 HTTP(也称为 URL 方法)进行安装,因此您应该在 您想使用哪种安装源? 部分中保留默认的 网络 选项。

  5. 现在在标准的 http:// 文本框中输入以下 URL,我们将使用它来下载所有必需的安装包:mirror.centos.org/centos/7/os/x86_64/

  6. 或者,您也可以使用个人仓库,这需要您提前创建(请参阅 第四章,使用 YUM 管理软件包

  7. 准备就绪后,点击 完成 开始初始化过程。

  8. 成功后,安装程序将开始检索适当的 install.img 文件。这可能需要几分钟才能完成,但一旦解决,进度条将指示所有下载活动。当此过程成功完成后,安装源 处的感叹号将消失,但会出现另一个感叹号,告诉用户缺少 软件选择。点击它并选择适合您需求的选项。对于本食谱的目的,只需在 基本环境 下选择 最小安装,然后点击 完成

  9. 如果 您想使用哪种安装源? 保持灰色且无法更改,则您的网络适配器存在连接问题。如果出现这种情况,请返回配置 网络和主机名 并更改网络设置,直到达到连接状态。

  10. CentOS 7 现在将以常规方式安装操作系统,并在安装过程完成后向您表示祝贺。由于所有软件包都必须从互联网上获取,因此它可能比从物理安装介质安装要慢。

工作原理...

本食谱的目的是向您介绍 CentOS 网络安装过程的概念,以展示这种方法可以多么简单。通过完成本食谱,您不仅通过将初始下载限制为仅安装过程所需的文件来节省时间,而且还能够利用完整的图形安装方法,而无需完整的 DVD 套件。

使用 kickstart 文件安装 CentOS 7

虽然使用图形安装程序手动安装 CentOS 7 在一台服务器上是可以的,但在多台系统上这样做可能会很繁琐。Kickstart 文件可以自动化服务器系统的安装过程,这里我们将展示如何实现这一点。它们是简单的基于文本的配置文件,提供了关于目标系统应如何设置和安装的详细和精确的指令(例如,安装哪种键盘布局或额外的软件包)。

准备就绪

为了成功完成此方法,您需要访问一个已安装的 CentOS 7 系统以获取我们要使用的 kickstart 配置文件并用于自动化安装。在这个预安装的 CentOS 服务器上,您还需要一个有效的互联网连接来下载额外的软件。

接下来,我们需要下载并创建 DVD 或 Everything 映像的安装介质(下载最新的CentOS-7-x86_64-DVD-XXXX.isoCentOS-7-x86_64-Everything-XXXX.iso文件),而不是本章中另一方法中显示的最小 iso 文件。然后,您需要另一个在 Linux 系统上可读写的 USB 设备(格式化为 FAT16、FAT32、EXT2、EXT3、EXT4 或 XFS 文件系统)。

如何操作...

为了使此方法生效,我们首先需要物理访问另一个已完成 CentOS 7 安装的 kickstart 文件,我们将使用它作为新 CentOS 7 安装的模板。

  1. 在现有的 CentOS 7 系统上以 root 身份登录,并通过输入以下命令并按回车键执行来确保 kickstart 配置文件存在(这将显示文件的详细信息):

    ls -l /root/anaconda-ks.cfg
    
    
  2. 接下来,物理上插入一个 USB 设备,然后输入以下命令,这将为您提供当前连接到计算机的所有硬盘设备的列表:

    fdisk -l
    
    
  3. 尝试通过比较其大小、分区以及识别的文件系统与您的 USB 设备的规格来确定设备名称。设备名称将是/dev/sdX的形式,其中X是一个字母字符,如bcde等。如果您无法使用fdisk命令找到正确的设备名称,请尝试以下技巧:运行fdisk -l两次 - 首先在未插入 USB 设备的情况下,然后在插入 USB 设备的情况下,比较第二次输出如何变化 - 它比第一次输出多一个设备名称:您感兴趣的设备名称!

  4. 如果您在列表中找到了正确的设备名称,请创建一个目录以将其挂载到当前文件系统:

    mkdir /mnt/kickstart-usb
    
    
  5. 接下来,实际上将 USB 设备挂载到此文件夹,假设您选择的 USB 分区位于/dev/sdc1(根据需要更改此设置):

    mount /dev/sdc1 /mnt/kickstart-usb
    
    
  6. 现在,我们将在 USB 设备上创建 kickstart 文件的工作副本以进行定制:

    cp /root/anaconda-ks.cfg /mnt/kickstart-usb
    
    
  7. 然后,使用您喜欢的文本编辑器打开 USB 设备上的复制 kickstart 文件(这里我们将使用编辑器 nano,如果您还没有安装它,请输入yum install nano):

    nano /mnt/kickstart-usb/anaconda-ks.cfg
    
    
  8. 现在,我们将修改文件以在新目标系统上安装 CentOS。在 nano 中,使用上下箭头键转到以(<your_hostname>将是您在安装过程中给出的主机名,例如minimal.home)开头的行:

    network  --hostname=<your_hostname>
    
    
  9. 现在,编辑<your_hostname>字符串,为其赋予一个新的唯一主机名。例如,在任何现有名称的末尾添加一个-2,如下所示:

    network  --hostname=minimal-2.home
    
    
  10. 接下来,使用上下箭头键将光标向下移动,直到它停在写着%packages.的行上。在其下方附加以下行(您可以进一步自定义此设置,并提供您希望自动安装的其他软件包):

    mariadb-server
    httpd
    rsync
    net-tools
    
    
  11. 现在保存并关闭文件,在 nano 编辑器中,使用Ctrl+o键组合(这意味着,按住键盘上的Ctrl键,然后按o键,不要松开Ctrl键)来写入更改。然后按Return确认文件名,并按Ctrl+x退出编辑器。

  12. 接下来,安装以下 CentOS 软件包:

    yum install system-config-kickstart
    
    
  13. 现在,我们使用ksvalidator程序验证 kickstart 文件的语法,该程序包含在我们刚刚安装的软件包中:

    ksvalidator /mnt/kickstart-usb/anaconda-ks.cfg
    
    
  14. 如果config文件没有错误,现在使用以下命令卸载 USB 闪存驱动器:

    cd
    umount /mnt/kickstart-usb
    
    
  15. 当您再次获得新的命令提示符时,从系统中物理拔出包含 kickstart 文件的 USB 设备,以便在目标机器上使用。

  16. 现在,您需要物理访问您想要安装 CentOS 的目标机器,使用刚刚创建的 kickstart 文件。断开任何其他不需要在安装过程中使用的外部文件存储设备。

  17. 开启计算机并插入准备好的 CentOS 安装介质(必须是 CentOS DVD 或 Everything 安装盘镜像,准备在 CD/DVD 光盘或 USB 设备安装器上)。同时,将包含在先前步骤中创建的 kickstart 文件的 USB 闪存驱动器连接到计算机(如果使用 USB 驱动器安装 CentOS,则总共需要两个空闲的 USB 端口来完成此操作)。

  18. 接下来,启动服务器并在初始启动屏幕期间按下与引导您刚刚连接的 CentOS 安装介质相关的正确键。

  19. 在 CentOS 安装程序开始加载后,将显示常见的标准 CentOS 7 安装欢迎屏幕,并且测试此媒体并安装 CentOS 7选项将由光标预先选中。

  20. 接下来,在键盘上按一次Esc键,切换到boot: prompt

  21. 现在我们准备好开始 kickstart 安装了。为此,您需要知道 USB 设备上 kickstart 文件所在的确切分区名称。输入以下命令,假设您的分区位于/dev/sdc1(根据需要更改此设置),然后按Return键开始 kickstart 安装过程:

    linux ks=hd:sdc1:/anaconda-ks.cfg
    
    

    注意

    如果你无法找到 USB 闪存盘的正确设备和分区名称,你需要在救援模式下启动目标系统(参考在救援模式下排除系统故障的解决方案),通过比较其大小、分区以及识别的文件系统与你的闪存盘规格来确定正确的设备名称和分区号。

  22. 现在,新系统将自动使用提供的 kickstart 文件中的指令进行安装。你可以查看安装输出消息,因为它会向用户显示详细的安装进度。

  23. 如果系统安装完成,重启系统并登录到你的新机器,以验证新系统是否按照我们使用 kickstart 文件描述的方式进行了设置。

它是如何工作的...

在这个解决方案中,你已经看到,每个运行 CentOS 7 安装的服务器都在其根目录中保留了 kickstart 文件,该文件包含了系统安装过程中设置的详细信息。kickstart 文件可以用来自动化多个具有相同配置的系统的安装。这可以节省大量时间,因为安装过程中不需要用户交互。此外,如果目标机器的 RAM 不符合图形化安装的最低要求,但需要文本模式安装器不提供的其他功能(如自定义分区),我们也可以使用这种方法。kickstart 配置文件是简单的纯文本文件,可以手动从头创建。由于使用 kickstart 语法构建系统有相当多的不同命令,我们使用了一个现有的文件作为模板,并对其进行了定制以满足我们的需求,而不是完全从头开始。我们没有使用最小化安装镜像来驱动我们的 kickstart 安装,因为我们安装了一些额外的软件包,这些软件包不包含在最小化 ISO 文件中,例如 Apache Web 服务器。

开始和自定义引导加载程序

当你打开计算机时,引导加载程序是第一个启动的程序,负责加载并将控制权转移到下层的操作系统。如今,几乎任何现代 Linux 发行版都使用GRand Unified Bootloader 版本 2GRUB2)来启动系统。它在配置上非常灵活,并支持许多不同的操作系统。在这个解决方案中,我们将展示如何通过禁用菜单显示的等待时间来定制 GRUB2 引导加载程序,从而提高系统启动时间。

准备工作

要完成这个解决方案,你需要访问一个已经安装了 CentOS 7 操作系统(最小化安装或其他类型的 CentOS 7 安装都可以)的系统,并具有 root 权限。此外,你还需要具备使用文本编辑器(如 nano)修改配置文件的基本经验。

如何操作...

我们通过使用我们选择的文本编辑器打开主 GRUB2 配置文件并对其进行修改,开始这个食谱。

  1. 首先以 root 身份登录到你的系统,并为 GRUB2 配置文件创建一个备份副本,以备需要时回滚。按下返回键完成:

    cp /etc/default/grub /etc/default/grub.BAK
    
    
  2. 使用以下命令打开我们要编辑的主 GRUB2 配置文件,并按下返回键(这里我们将使用编辑器 nano,如果你还没有安装它,请输入yum install nano):

    nano /etc/default/grub
    
    
  3. 在光标所在的第一行按下返回键插入新行,然后插入以下行:

    GRUB_HIDDEN_TIMEOUT=0
    
    
  4. 在以下行的开头添加一个#符号,如下所示:

    GRUB_TIMEOUT=0
    
    
  5. 现在在 nano 中使用Ctrl+o保存文件(并按返回确认保存的文件名)。使用Ctrl+x退出编辑器,然后运行以下命令:

    dmesg | grep -Fq "EFI v"
    
    
  6. 如果前面的命令没有产生任何输出,运行以下命令:

    grub2-mkconfig -o /boot/grub2/grub.cfg
    
    
  7. 否则,如果有输出,运行:

    grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
    
    
  8. 如果grub2-mkconfig成功,它将打印Done.。现在使用以下命令重新启动你的系统:

    reboot
    
    
  9. 在重启过程中,你会发现 GRUB2 引导菜单不再出现,系统将更快地启动。

它是如何工作的...

完成这个食谱后,我们现在知道如何自定义 GRUB2 引导加载程序。在这个非常简单的食谱中,我们只向你展示了引导加载程序的一些基本修改,但它可以做更多!它支持广泛的文件系统,并且可以启动几乎任何兼容的操作系统。如果你计划在同一台机器上运行多个操作系统,这也是特别有用的。要了解更多关于 GRUB2 配置文件语法的信息,请输入info grub2 | less命令,并转到6.1 简单配置处理部分(阅读第二章,系统配置中的食谱使用 less 浏览文本文件,了解如何浏览此文档)。

在救援模式下排除系统故障

我们都会犯错,这对新手 Linux 系统管理员尤其如此。Linux 的学习曲线可能很陡峭,迟早会在你的职业生涯中遇到 CentOS 安装由于各种原因无法启动的情况,包括硬件问题或人为错误,如配置错误。如果这种情况发生在你身上,那么你可以使用 CentOS 救援模式来启动一个无法启动的系统,并尝试撤消你的错误或找出问题的根源。在本食谱中,我们将向你展示三个常见的情况,何时使用此选项:

  • 访问文件系统以恢复重要数据或撤消对配置文件的更改,如果 CentOS 无法启动

  • 更改 root 密码,如果你忘记了它

  • 重新安装引导加载程序,这可能在同一硬盘上安装另一个操作系统时损坏 CentOS

准备就绪

要完成此操作,您需要一个标准的 CentOS 7 操作系统安装媒体(CD/DVD 或 USB 设备)。为了从系统中恢复数据,您需要将某种外部存储设备连接到系统,例如外部硬盘或一个正常工作的网络连接到另一台计算机,以便将所有珍贵数据复制到不同位置。

如何操作...

要开始此操作,您应该从 CentOS 安装 CD/DVD 或 USB 设备启动服务器,并等待直到第一个欢迎屏幕出现,光标等待在测试此媒体并安装 CentOS 7菜单选项上。

进入救援模式

  1. 从主菜单中,使用向下箭头键选择故障排除,然后按回车键继续。

  2. 故障排除屏幕上,使用向下箭头键高亮显示救援 CentOS 系统。准备就绪后,按回车键继续。

  3. 经过一些加载时间后,我们进入救援屏幕,其中包括各种确认子屏幕。要开始此部分,使用左右箭头键选择继续,然后按回车键继续。

  4. 在第一个子屏幕上,选择确定并按回车键继续。

  5. 同样,在接下来的子屏幕中,选择确定并按回车键继续。

  6. 在下一个屏幕上,选择启动shell,并使用Tab键,高亮显示确定,然后按回车键继续。

  7. 完成上述步骤后,将启动一个 shell 会话。您将在显示屏底部注意到这一点。shell 会话的当前状态将显示如下:

    bash-4.2#_
    
    
  8. 在提示符下,输入以下指令以更改根文件系统,然后在按回车键完成您的请求之前:

    chroot /mnt/sysimage
    
    
  9. 恭喜!您已进入救援模式。在任何时候退出,只需输入以下命令,然后按回车键以完成您的请求(现在不要这样做,因为这将重启系统):

    reboot
    
    
  10. 在基本救援模式达到后,我们根据问题的类型有以下选项。

访问文件系统

如果您现在处于救援模式并需要从文件系统备份重要文件,您需要一个数据传输的目的地位置。为了将我们想要从服务器恢复的数据传输到另一台计算机,请将外部 USB 设备物理连接到它。您也可以使用网络存储进行恢复。例如,您可以导入 NFS 服务器共享并将数据复制到它。请参阅第七章,构建网络中的使用 NFS操作。

  1. 在救援模式命令行中,输入以下命令,该命令将显示系统上所有当前连接的分区,然后按回车键完成您的请求:

    fdisk -l
    
    
  2. 现在,您需要找出连接设备的正确设备名称和分区号;比较各个设备的总大小或文件系统输出与您的 USB 设备的规格可以帮助您完成此过程。您还可以尝试以下技巧:运行fdisk -l命令两次,第一次插入 USB 设备,然后再次拔出 USB 设备,并比较两个命令的输出。应该会有一个设备名称不同,这就是您正在寻找的!

  3. 如果在列表中找到了正确的设备名称,请创建一个目录以将 USB 设备挂载到文件系统:

    mkdir /mnt/hdd-recovery
    
    
  4. 接下来,将磁盘分区挂载到此文件夹。这里我们假设感兴趣的 USB 设备的设备名称为sdd1(如果您的系统不同,请更改):

    mount /dev/sdd1 /mnt/hdd-recovery
    
    
  5. 救援系统自动将原始系统的硬盘的根分区挂载在特定文件夹下(位于/mnt/sysimage下),如果需要访问它,例如更改导致启动问题的配置文件或进行完整或部分备份。例如,如果需要备份 Apache Web 服务器配置文件,请使用:

    cp -r /mnt/sysimage/etc/http /mnt/hdd-recovery
    
    
  6. 如果需要访问当前挂载的根分区以外的分区上的数据,请使用fdisk -l来识别感兴趣的分区。然后创建一个目录,将分区挂载到该目录,并切换到该目录以访问数据,就像挂载 USB 设备时所做的那样。

  7. 要完成备份文件,请输入:

    reboot
    
    

访问文件系统

  1. 如果在救援模式下更改 root 密码,只需使用以下命令并提供新密码:

    passwd
    
    
  2. 要完成更改密码,请输入:

    reboot
    
    

重新安装 CentOS 引导加载程序

  1. 现在,我们将使用fdisk命令来查找所有当前分区的名称。为此,请输入以下指令,然后按回车键以完成请求:

    fdisk –l
    
    
  2. 现在运行以下命令:

    dmesg | grep -Fq "EFI v"
    
    
  3. 如果前面的命令没有产生任何输出,请在fdisk列表的引导列中查找*符号以找到正确的起始分区,并假设您的引导磁盘位于/dev/sda1(根据需要更改此设置),请输入以下内容:

    grub2-install /dev/sda
    
    
  4. 否则,如果有输出,请运行以下命令:

    yum reinstall grub2-efi shim
    
    
  5. 如果没有错误报告,控制台应响应如下:

    # this device map was generated by anaconda
    (hd0) /dev/sda
    
    
  6. 最后一步的控制台输出确认 GRUB 已成功恢复。

  7. 要重新启动计算机,请输入:

    reboot
    
    

它是如何工作的...

救援模式环境提供的工具可以解决各种广泛的问题。这些问题通常涉及启动问题,但也可能来自其他类型,例如忘记 root 密码。救援模式可以救急,掌握它是一项非常重要的技能。因此,我们认为应该将这样的操作指南放在手边。

提示

请记住,在处理引导加载程序命令时要小心,因为不当使用可能会导致操作系统无法启动。

更新安装并增强最小化安装,添加额外的管理和开发工具

在本食谱中,我们将学习如何通过添加额外的工具来增强最小化安装,这些工具将为你提供各种管理和开发选项,反过来,在你的服务器生命周期中证明是至关重要的,并且对于本书中的一些食谱来说是必不可少的。最小化安装可能是最有效的服务器安装方式,但即便如此,最小化安装确实需要一些额外的功能,以使其成为一个更具吸引力的模型。

准备就绪

要完成这个食谱,你需要一个具有 root 权限的 CentOS 7 操作系统的最小化安装,并且需要连接到互联网,以便下载额外的包。

如何做到这一点...

我们将从这个食谱开始更新系统。

  1. 要更新系统,请以 root 身份登录并输入:

    yum -y update
    
    
  2. CentOS 现在将搜索相关的更新,如果可用,它们将被安装。完成后,根据更新了什么(即内核和新安全功能等),你可以决定重新启动计算机。要这样做,请输入:

    reboot
    
    
  3. 你的服务器现在将重新启动并返回到登录屏幕。我们现在将完成这个食谱,并通过一系列包组来增强我们当前的安装,这些包组在未来将证明非常有用。要这样做,请以 root 身份登录并输入:

    yum -y groupinstall "Base" "Development Libraries" "Development Tools"
    yum -y install policycoreutils-python
    
    

它是如何工作的...

本食谱的目的是增强 CentOS 7 操作系统的最小化安装,通过这样做,你不仅介绍了自己给Yellowdog Updater ModifiedYUM)包管理器(我们将在本书后面再次回到这一点),而且你现在拥有了一个能够运行大量应用程序的系统,开箱即用。

那么我们从这次经历中学到了什么?

我们首先通过更新系统来开始这个配置过程,以确保系统是最新的。在这个阶段,通常重启系统是个好主意。虽然我们不期望经常这样做,但在安装操作系统后首次更新时是必要的,因为很可能有重大的更新可用。这样做的原因通常是基于希望利用新的内核或更新的安全补丁。在下一阶段,配置过程展示了如何添加一系列可能在将来证明非常有用的软件包组。为了节省时间,我们将安装三个主要软件包组的指令打包在一起:BaseDevelopment LibrariesDevelopment Tools。仅此一项操作就安装了超过 200 个单独的软件包,从而使您的服务器能够编译代码并运行大量即装即用的应用程序,这些应用程序可能在服务器的整个生命周期内都需要。要查看某个组中所有软件包的列表,例如 Base 组,可以运行 yum groupinfo Base 命令。我们还安装了 policycoreutils-python 软件包,它提供了管理 Linux 安全增强访问控制的工具和程序,我们将在本书的各个章节中频繁使用这些工具。

第二章:配置系统

在本章中,我们将涵盖以下主题:

  • 使用 less 浏览文本文件

  • 介绍 Vim

  • 使用正确的语言

  • 使用 NTP 和 chrony 套件同步系统时钟

  • 设置主机名并解析网络

  • 成为超级用户

  • 建立静态网络连接

  • 自定义系统横幅和消息

  • 初始化内核

介绍

本章是一系列涵盖建立服务器基本需求的基本实践的集合。对于许多人来说,构建服务器可能常常看起来是一项艰巨的任务,因此本章的目的是为您提供一种即时方法来实现所需的目标。

使用 less 浏览文本文件

在本书中,您将经常使用使用 less 程序或类似导航的程序和工具来查看和阅读文件内容或显示输出。起初,控制可能会显得有些不直观。在本节中,我们将向您展示如何使用 less 控制来浏览文件的基本知识。

准备工作

要完成本节内容,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装。

如何操作...

  1. 首先,以 root 身份登录并输入以下命令以打开使用 less 进行导航的程序:

    man man
    
    
  2. 要导航,请按键以逐行滚动,按空格键以向下滚动一页,按b键以向上滚动一页。您可以使用正斜杠键/在文本中搜索,然后输入搜索词,按Return键进行搜索。按n键跳转到下一个搜索结果。按q键退出。

工作原理...

在这里,在这篇简短的节中,我们向您展示了 less 导航的基本知识,这对于阅读 man 页面至关重要,并且在本书中被许多其他程序用于显示文本。我们只向您展示了基本命令,还有很多需要学习。请阅读 less 手册以了解更多关于man less命令的信息。

介绍 Vim

在本节中,我们将简要介绍文本编辑器 Vim,它是本书中使用的标准文本编辑器。您也可以使用您喜欢的任何其他文本编辑器,例如 nano 或 emacs。

准备工作

要完成本节内容,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装。

如何操作...

我们将从安装vim-enhanced包开始本节,因为它包含一个您可以用来学习使用 Vim 的教程:

  1. 首先,以 root 身份登录并安装以下包:

    yum install vim-enhanced
    
    
  2. 之后,输入以下命令以启动 Vim 教程:

    vimtutor
    
    
  3. 这将打开 Vim 教程,在 Vim 编辑器中。要导航,请按键以逐行滚动。要退出教程,请按Esc键,然后输入:q!,接着按Return键退出。

  4. 现在,你应该阅读文件并学习课程,以获得对 Vim 的基本理解,学习如何编辑你的文本文件。

它是如何工作的...

本配方中显示的教程应该被视为学习 Linux 最强大和有效的文本编辑器之一的基础知识的起点。Vim 的学习曲线非常陡峭,但如果你花大约半小时的时间来学习 vimtutor 指南,你应该能够毫无问题地完成所有常见的文本编辑任务,例如打开、编辑和保存文本文件。

说正确的语言

在本配方中,我们将向你展示如何为整个系统和单个用户更改 CentOS 7 安装的语言设置。更改这个的需求很少,但可能是重要的,例如,如果我们不小心在安装过程中选择了错误的语言。

准备工作

要完成这个配方,你需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,以及你选择的基于控制台的文本编辑器。你应该已经阅读了使用 less 导航文本文件配方,因为本配方中的一些命令将使用 less 来打印输出。

如何做到这一点...

如果你想更改 CentOS 7 系统的系统范围语言设置,你需要调整两个类别的设置。我们首先更改系统区域设置信息,然后更改键盘设置:

  1. 首先,以 root 用户身份登录并输入以下命令,以显示控制台、图形窗口管理器(X11 布局)的当前区域设置,以及当前键盘布局:

    localectl status
    
    
  2. 接下来,要更改这些设置,我们首先需要了解系统上所有可用的区域设置和键盘设置(两个命令都使用less导航):

    localectl list-locales
    localectl list-keymaps
    
    
  3. 如果你在我们的示例中从上面的输出中选择了正确的区域设置,de_DE.utf8keymap de-mac(根据你自己的适当需求进行更改),你可以使用以下命令更改你的区域设置和键盘设置:

    localectl set-locale LANG=de_DE.utf8
    localectl set-keymap de-mac
    
    
  4. 现在,使用相同的命令再次验证你的更改的持久性:

    localectl status
    
    

它是如何工作的...

正如我们所见,localectl命令是一个非常方便的工具,可以管理 CentOS 7 系统中所有重要的语言设置。

那么我们从这次经历中学到了什么?

我们首先以 root 用户身份登录到命令行。然后,我们使用status参数运行localectl命令,这为我们提供了系统当前语言设置的概览。该命令的输出向我们展示了 CentOS 7 系统中的语言属性可以分为区域设置(系统区域设置)和键盘映射(VC 键盘映射和所有 X11 布局属性)设置。

Linux 上的区域设置用于设置系统的语言以及其他特定于语言的属性。这可以包括来自错误消息、日志输出、用户界面以及如果您使用的是 Gnome 等窗口管理器,甚至是 图形用户界面GUI)的文本。区域设置还可以定义特定于区域的格式,例如纸张尺寸、数字及其自然排序、货币信息等。它们还定义字符编码,如果您选择了一种具有无法在标准 ASCII 编码中找到的字符的语言,这可能很重要。

另一方面,键盘映射设置定义了键盘上每个键的确切布局。

接下来,要更改这些设置,我们首先使用 localectl 命令和 list-locales 参数来检索系统上所有区域设置的完整列表,以及 list-keymaps 来显示系统上所有键盘设置的列表。从 list-locales 参数输出的区域设置使用非常紧凑的注释来定义语言:

Language[_Region][.Encoding][@Modificator]

只有 Language 部分是强制性的,其余部分都是可选的。语言和地区的示例包括:en_US 表示英语和美国地区或美式英语,es_CU 表示西班牙语和古巴地区或古巴西班牙语。

编码对于特殊字符(如德语变音符号或法语重音符号)很重要。这些特殊字符的内存表示可以根据所使用的编码类型以不同的方式解释。通常应使用 UTF-8,因为它能够对每种语言中的几乎任何字符进行编码。

修饰符用于更改由区域设置定义的设置。例如,sr_RS.utf8@latin 用于您希望为塞尔维亚的塞尔维亚语提供拉丁语设置,而通常使用西里尔语定义。这将更改为西方设置,例如排序、货币信息等。

要更改实际的区域设置,我们使用了 set-locale LANG=de_DE.utf8 参数。在这里,编码被选择来正确显示德语变音符号。请注意,我们使用了 LANG 选项来为所有可用的区域设置选项设置相同的区域设置值(例如,de_DE.utf8)。如果您不想为所有可用选项设置相同的区域设置值,您可以使用更精细的控制来控制单个区域设置选项。请参考使用手册页的区域设置描述,man 7 locale(在最小安装上;您需要在使用 yum install man-pages 命令之前安装所有 Linux 文档手册页)。您可以使用类似的语法设置这些附加选项,例如,要设置时间区域设置,请使用:

localectl set-locale LC_TIME="de_DE.utf8"

接下来,我们使用list-keymaps参数显示所有可用的键盘映射代码。正如我们从运行localectl status中看到的,键盘映射可以分为非图形(VC 键盘映射)和图形(X11 布局)设置,这允许在使用 Gnome 等窗口管理器时以及在控制台中灵活配置不同的键盘布局。运行带有参数set-keymap de-maclocalectl命令,将当前键盘映射设置为德国苹果 Macintosh 键盘模型。此命令将给定的键盘类型应用于正常的 VC 和 X11 键盘映射。如果希望 X11 与控制台的映射不同,请使用localectl --no-convert set-x11-keymap cz-querty,其中我们使用cz-querty作为键盘映射代码到捷克 querty 键盘模型(根据需要更改此设置)。

还有更多…

有时,单个系统用户需要与系统区域设置(只能由 root 用户设置)不同的语言设置,根据他们的区域键盘差异以及与系统交互时使用他们首选的人类语言。只要没有被本地环境变量覆盖,系统范围的区域设置就会由每个用户继承。

注意

更改系统范围的区域设置并不一定会影响用户已为自己定义的其他区域设置。

要打印任何系统用户的当前区域设置环境变量,我们可以使用命令locale。要设置具有适当变量名称的单个环境变量;例如,要将时间区域设置为美国时间,我们将使用以下行:

export LC_TIME="en_US.UTF-8"

但是,我们很可能希望将所有区域设置更改为相同的值;这可以通过设置LANG来实现。例如,要将所有区域设置更改为美式英语,请使用以下行:

export LANG="en_US.UTF-8"

要测试区域设置更改的效果,我们现在可以生成一个错误消息,该消息将显示在由locale命令设置的语言中。以下是将区域设置从英语更改为德语的不同语言输出:

export LANG="en_US.UTF-8"
ls !

以下输出将被打印:

ls: cannot access !: No such file or directory

现在,更改为德语区域设置:

export LANG="de_DE.UTF-8"
ls !

以下输出将被打印:

ls: Zugriff auf ! nicht möglich: Datei oder Verzeichnis nicht gefunden

在活动控制台中使用export命令设置区域设置不会在关闭窗口或打开新终端会话后继续存在。如果希望使这些更改永久生效,可以在主目录中的名为.bashrc的文件中设置任何区域设置环境变量,例如LANG变量,该文件将在每次打开 shell 时读取。在我们的示例中,要将区域设置永久更改为de_DE.UTF-8(根据需要更改此设置),请使用以下行:

echo "export LANG='de_DE.UTF-8'" >> ~/.bashrc

使用 NTP 和 chrony 套件同步系统时钟

在本食谱中,我们将学习如何使用网络时间协议NTP)和 chrony 套件将系统时钟与外部时间服务器同步。从需要为文档、电子邮件和日志文件打时间戳,到安全运行和调试网络,或者仅仅与共享设备和服务交互,您的服务器上的所有操作都依赖于保持一个准确的系统时钟,本食谱的目的就是向您展示如何实现这一点。

准备工作

要完成本食谱,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便下载额外软件包的能力。

如何操作...

在本食谱中,我们将使用chrony服务来管理我们的时间同步。由于 chrony 在 CentOS 最小化安装中默认未安装,我们将从安装它开始:

  1. 首先,以 root 身份登录并安装chrony服务,然后启动它并验证它是否正在运行:

    yum install -y chrony
    systemctl start chronyd
    systemctl status chronyd
    
    
  2. 此外,如果我们想让 chrony 永久运行,我们需要在服务器启动时启用它:

    systemctl enable chronyd
    
    
  3. 接下来,我们需要检查系统是否已经使用 NTP 通过网络同步我们的系统时钟:

    timedatectl  | grep "NTP synchronized"
    
    
  4. 如果上一步的输出显示NTP 同步,我们需要使用以下命令启用它:

    timedatectl set-ntp yes
    
    
  5. 如果您再次运行第 3 步中的命令,您应该会看到它现在正在同步 NTP。

  6. chrony 的默认安装将使用一个可以访问原子钟的公共服务器,但为了优化服务,我们需要对使用哪些时间服务器进行一些简单的更改。为此,使用您喜欢的文本编辑器打开主要的 chrony 配置文件,如下所示:

    vi /etc/chrony.conf
    
    
  7. 在文件中,向下滚动并查找包含以下内容的行:

    server 0.centos.pool.ntp.org iburst
    server 1.centos.pool.ntp.org iburst
    server 2.centos.pool.ntp.org iburst
    server 3.centos.pool.ntp.org iburst
    
    
  8. 用首选本地时间服务器的列表替换显示的值:

    server 0.uk.pool.ntp.org iburst
    server 1.uk.pool.ntp.org iburst
    server 2.uk.pool.ntp.org iburst
    server 3.uk.pool.ntp.org iburst
    
    

    注意

    访问www.pool.ntp.org/以获取一份地理位置接近您当前位置的本地服务器列表。请记住,使用三个或更多服务器往往有助于提高 NTP 服务的准确性。

  9. 完成后,保存并关闭文件,然后使用sytstemctl命令同步您的服务器:

    systemctl restart chronyd
    
    
  10. 要检查config文件中的修改是否成功,您可以使用以下命令:

    systemctl status chronyd
    
    
  11. 要检查 chrony 是否正在处理您的系统时间同步,请使用以下命令:

    chronyc tracking
    
    
  12. 要检查 chrony 用于同步的网络源,请使用以下命令:

    chronyc sources
    
    

工作原理...

我们的 CentOS 7 操作系统在每次启动时都会根据硬件时钟设置时间,这是一个位于计算机主板上的小型电池驱动时钟。通常,这个时钟不够准确或者设置不正确,因此最好从互联网上的可靠来源(使用真正的原子时间)获取系统时间。chrony 守护进程chronyd通过使用 NTP 协议与远程服务器进行通信的过程来设置和维护系统时间。

那么,我们从这次经历中学到了什么?

作为第一步,我们安装了chrony服务,因为它在 CentOS 7 最小安装中默认不可用。之后,我们使用timedatectl set-ntp yes命令启用了系统时间与 NTP 的同步。

之后,我们打开了主要的 chrony 配置文件/etc/chrony.conf,并展示了如何更改使用的外部时间服务器。如果您的服务器位于企业防火墙后面并且拥有自己的 NTP 服务器基础设施,这尤其有用。

重新启动服务后,我们学习了如何使用chronyc命令检查和监视我们的新配置。这是一个有用的命令行工具(c 代表客户端),用于与 chrony 守护进程(本地或远程)交互和控制。我们使用tracking参数与chronyc一起使用,这向我们展示了与特定服务器的当前 NTP 同步过程的详细信息。如果您需要进一步帮助关于输出中显示的属性,请参考chronyc命令的man页面(man chronyc)。

我们还使用sources参数与chronyc程序一起使用,这向我们展示了使用的 NTP 时间服务器的概述。

您还可以使用较旧的date命令来验证正确的时间同步。重要的是要意识到同步服务器的过程可能不是即时的,并且可能需要一段时间才能完成。然而,您现在可以放心地知道,您现在知道如何安装、管理和使用 NTP 协议同步时间。

还有更多...

在本食谱中,我们使用chrony服务和 NTP 协议设置系统时间。通常,系统时间设置为协调世界时UTC)或世界时间,这意味着它是全球统一使用的一种标准时间。从它开始,我们需要使用时区来计算我们的本地时间。要找到正确的时间区域,请使用以下命令(阅读使用 less 浏览文本文件食谱以处理输出):

timedatectl list-timezones

如果您找到了正确的时间区域,请记下来并在下一个命令中使用它;例如,如果您位于德国并且靠近柏林市,请使用以下命令:

timedatectl set-timezone Europe/Berlin

再次使用timedatectl检查您的本地时间是否正确:

timedatectl | grep "Local time"

最后,如果它是正确的,您可以同步硬件时钟与系统时间以使其更精确:

hwclock --systohc

设置主机名和解决网络问题

设置主机名的过程通常与安装过程相关联。如果您需要更改它或您服务器的域名系统DNS)解析器,本指南将向您展示如何操作。

准备

要完成本指南,您需要具备具有 root 权限的 CentOS 7 操作系统的有效安装,以及您选择的基于控制台的文本编辑器。

如何操作...

要开始本指南,我们将首先以 root 身份访问系统并打开以下文件,以便为您的当前服务器命名或重命名主机名:

  1. 以 root 身份登录并输入以下命令以查看当前主机名:

    hostnamectl status
    
    
  2. 现在,将主机名值更改为您的首选名称。例如,如果您想将服务器称为jimi,您将输入(适当更改):

    hostnamectl set-hostname jimi
    
    

    注意

    静态主机名区分大小写,并且限制为使用互联网友好的字母数字字符串。总长度不应超过 63 个字符,但尽量保持更短。

  3. 接下来,我们需要服务器的 IP 地址。输入以下命令以查找它(您需要在输出中识别正确的网络接口):

    ip addr list
    
    
  4. 之后,我们将设置完全限定域名FQDN),为此,我们需要打开并编辑主机文件:

    vi /etc/hosts
    
    
  5. 在这里,您应该添加一条符合您需求的新行。例如,如果您的服务器主机名称为 jimi(IP 地址为192.168.1.100,域名为henry.com),您需要追加的最终行将如下所示:

    192.168.1.100        jimi.henry.com jimi
    
    

    注意

    对于仅在本地网络上找到的服务器,建议使用非基于互联网的顶级地址。例如,您可以使用.local.lan,甚至是.home,通过使用这些引用,您将避免与典型的.com.co.uk.net域名混淆。

  6. 接下来,我们将打开resolv.conf文件,该文件负责配置系统将使用的静态 DNS 服务器地址:

    vi /etc/resolv.conf
    
    
  7. 用以下内容替换文件内容:

    # use google for dns
    nameserver 8.8.8.8
    nameserver 8.8.4.4
    
    
  8. 完成后,保存并关闭文件,然后重新启动服务器以使更改立即生效。为此,请返回控制台并输入:

    reboot
    
    
  9. 成功重启后,您可以通过输入以下命令并等待响应来检查您的新主机名和 FQDN:

    hostname --fqdn
    
    
  10. 要测试我们是否可以使用静态 DNS 服务器地址将域名解析为 IP 地址,请使用以下命令:

    ping -c 10 google.com
    
    

它是如何工作的...

主机名是为网络上的机器创建的唯一标签。它限制为基于字母数字的字符,并且可以通过使用hostnamectl命令来更改服务器的主机名。DNS 服务器用于将域名翻译成 IP 地址。有多个公共 DNS 服务器可用;在后面的指南中,我们将构建我们自己的 DNS 服务。

那么,我们从这次经历中学到了什么?

在本食谱的第一阶段,我们使用hostnamectl命令更改了服务器当前使用的主机名。该命令可以设置三种不同类型的主机名。使用带有set-hostname参数的命令将为所有三个主机名设置相同的名称:高级的pretty主机名,可能包含各种特殊字符(例如,Lennart's Laptop),静态主机名,用于在启动时初始化内核主机名(例如lennarts-laptop),以及瞬态主机名,它是从网络配置中接收的默认主机名。

接下来,我们设置了服务器的 FQDN。FQDN 是主机名加上其后的域名。当你运行私有 DNS 或允许外部访问你的服务器时,域名变得重要。除了使用 DNS 服务器设置 FQDN 外,还可以通过更新位于/etc/hosts的 hosts 文件来实现。

该文件由 CentOS 用于将主机名映射到 IP 地址,并且在新安装的、未配置的服务器上经常发现它是错误的。因此,我们首先必须使用ip addr list找出服务器的 IP 地址。

一个 FQDN 应该由一个简短的主机名和域名组成。根据本食谱中所示的示例,我们为名为henry的服务器设置了 FQDN,其 IP 地址为192.168.1.100,域名为henry.com

保存此文件可以说完成了这个过程。然而,由于内核在启动过程中记录了主机名,因此别无选择,只能重启服务器才能使用更改后的设置。

接下来,我们打开了系统的resolv.conf文件,该文件保存了系统 DNS 服务器的 IP 地址。如果服务器没有使用或没有 DNS 记录,系统将无法在任何程序中使用域名作为网络目的地。在我们的示例中,我们输入了公共 Google DNS 服务器的 IP 地址,但你可以使用任何你想要或必须使用的 DNS 服务器(在企业环境中,在防火墙后面,你通常必须使用内部 DNS 服务器基础设施)。在成功重启后,我们使用hostname命令确认了你的新设置,该命令可以根据给定的参数打印出主机名或 FQDN。

因此,综上所述,可以说这个食谱不仅向你展示了如何重命名服务器和解决网络问题,还向你展示了主机名和域名之间的区别:

正如我们所学,服务器不仅可以通过更短、更易记、更快捷的单字节主机名来识别,还由三个用句点分隔的值组成(例如 jimi.henry.com)。这些值之间的关系可能在一开始显得奇怪,尤其是对于许多人来说,它们似乎是一个单一的值。但是,通过完成这个配方,您已经发现域名与主机名是不同的,因为域名是由解析器子系统确定的,只有将它们组合在一起,您的服务器才会产生整个系统的完全限定域名(FQDN)。

还有更多...

主机文件包含一系列 IP 地址及其对应的域名。如果您的网络中存在未在现有 DNS 记录中列出的 IP 地址的计算机,为了加快网络速度,通常建议您将这些计算机添加到此文件中。

此操作可在任何操作系统上实现,但在 CentOS 上,只需使用您喜欢的文本编辑器打开主机文件,如下所示:

vi /etc/hosts

现在,滚动到文件底部,通过将此处显示的域名和 IP 地址替换为更适合您自己需求的值,添加以下值:

192.168.1.100    www.example1.lan
192.168.1.101    www.example2.lan

您甚至可以使用外部地址,例如:

83.166.169.228  www.packtpub.com

这种方法为您提供了创建域名与 IP 地址映射的机会,无需使用 DNS。它可以应用于任何工作站或服务器。列表大小不受限制,您甚至可以使用这种方法通过将所有请求重定向到已知网站的不同 IP 地址来阻止对某些网站的访问。例如,如果www.website.com的真实地址是192.168.1.200,而您想限制对其的访问,只需在您希望阻止访问的计算机上对主机文件进行以下更改:

127.0.0.1    www.website.com

这并非万无一失,但在这种情况下,任何尝试访问www.website.com的系统都会自动被重定向到127.0.0.1,即本地网络地址,从而阻止访问。

完成操作后,请记得以常规方式保存并关闭文件,然后继续享受更快速、更安全的域名解析带来的好处,无论是在任何可用的网络上。

建立静态网络连接

在本配方中,我们将学习如何为新创建或现有的 CentOS 服务器配置静态 IP 地址。

虽然动态分配的 IP 地址或 DHCP 保留可能适用于大多数台式机和笔记本电脑用户,但如果您正在设置服务器,通常需要静态 IP 地址。从网页到电子邮件,从数据库到文件共享,静态 IP 地址将成为您的服务器提供一系列应用程序和服务的永久位置。本配方的目的是向您展示实现这一目标是多么容易。

准备就绪

要完成此操作,您需要一个具有 root 权限和您选择的基于控制台的文本编辑器的 CentOS 7 操作系统的工作安装。

如何操作...

为了本操作的目的,您将能够在目录/etc/sysconfig/network-scripts/中找到所有相关文件。首先,您需要找出要设置为静态的网络接口的正确名称。如果您需要将多个网络接口设置为静态,请为每个设备重复此操作。

  1. 要执行此操作,以 root 身份登录并键入以下命令以获取系统所有网络接口的列表:

    ip addr list
    
    
  2. 如果您只安装了一个网络卡,那么很容易找到其名称;只需选择未命名为lo(这是环回设备)的那个。如果您有多个,查看不同设备的 IP 地址可以帮助您选择正确的设备。在我们的示例中,设备名为enp0s3

  3. 接下来,备份网络接口配置文件(根据需要更改enp0s3部分,如果您的网络接口名称不同):

    cp /etc/sysconfig/network-scripts/ifcfg-enp0s3/etc/sysconfig/network-scripts/ifcfg-enp0s3.BAK
    
    
  4. 当您准备好继续时,在您最喜欢的文本编辑器中打开以下文件,如下所示:

    vi /etc/sysconfig/network-scripts/ifcfg-enp0s3
    
    
  5. 现在,向下浏览文件并应用以下更改:

    NM_CONTROLLED="no"
    BOOTPROTO=none
    DEFROUTE=yes
    PEERDNS=no
    PEERROUTES=yes
    IPV4_FAILURE_FATAL=yes
    
    
  6. 现在,通过根据需要自定义XXX.XXX.XXX.XXX的值来添加您的 IP 信息:

    IPADDR=XXX.XXX.XXX.XXX
    NETMASK= XXX.XXX.XXX.XXX
    BROADCAST= XXX.XXX.XXX.XXX
    
    
  7. 我们现在必须添加一个默认网关。通常,这应该是您的路由器的地址。要执行此操作,只需在文件底部添加新行,如下所示,并根据需要自定义值:

    GATEWAY=XXX.XXX.XXX.XXX
    
    
  8. 准备好后,保存并关闭文件,然后为要设置为静态的任何剩余以太网设备重复此步骤。执行此操作时,请记住为每个设备分配不同的 IP 地址。

  9. 完成后,保存并关闭此文件,然后重新启动您的网络服务:

    systemctl restart network
    
    

它是如何工作的...

在本操作中,您已经看到了将服务器的 IP 地址从外部 DHCP 提供商获得的动态值更改为由您分配的静态值的过程。此 IP 地址现在将形成一个独特的网络位置,您将能够从中提供各种服务和应用程序。这是一个永久性的修改,是的,您可以说这个过程本身相对简单。

那么,我们从这次经历中学到了什么?

通过识别您选择的网络接口名称并创建原始以太网配置文件的备份来开始本教程,然后我们打开了位于/etc/sysconfig/network-scripts/ifcfg-XXX(其中XXX是您的接口名称,例如enp0s3)的配置文件。由于不再需要网络管理器的服务,我们通过将值设置为no来禁用NM_CONTROLLED。接下来,由于我们正在转向静态 IP 地址,BOOTPROTO已被设置为none,因为我们不再使用 DHCP。为了完成我们的配置更改,我们接着添加了特定的网络值,并设置了 IP 地址、子网掩码、广播和默认网关地址。

为了帮助创建静态 IP 地址,默认网关是一个非常重要的设置,因为它允许服务器通过路由器与更广阔的世界通信。

完成后,我们被要求保存并关闭文件,然后为任何剩余的以太网设备重复此步骤。完成这些操作后,我们被要求重新启动网络服务,以完成本教程并使我们的更改立即生效。

成为超级用户

在本教程中,我们将学习如何授予指定的用户或组执行各种具有提升权限的命令的能力。

在 CentOS Linux 系统中,许多文件、文件夹或命令只能由名为root的用户访问或执行,该用户可以控制 Linux 系统上的所有内容。每个系统拥有一个 root 用户可能满足您的需求,但对于那些希望获得更高灵活性、可靠的审计跟踪以及能够向选定的可信用户提供有限的管理权限的人来说,您来对地方了。本教程的目的是向您展示如何激活和配置sudo超级用户执行)命令。

准备工作

为了完成本教程,您需要一个具有 root 权限的 CentOS 7 最小安装操作系统。假设您的服务器维护一个或多个用户(除了 root 之外),他们有资格获得这种权限提升。如果在安装过程中没有创建系统用户账户,请首先应用本教程,管理用户及其组,在第三章,管理系统

如何操作...

为了开始本教程,我们将首先使用非特权用户测试sudo命令。

  1. 首先,使用非 root 用户账户登录到您的系统,然后输入以下命令以验证sudo未启用(在提示时使用您的用户账户密码):

    sudo ls /var/log/audit
    
    
  2. 这将打印出以下错误输出,其中<username>是您当前登录的用户:

    <username> is not in the sudoers file.  This incident will be reported.
    
    
  3. 现在,使用以下命令注销系统用户:

    logout
    
    
  4. 接下来,以 root 身份登录并使用以下命令为非 root 用户赋予 sudo 权限(适当更改<username>):

    usermod -G wheel <username>
    
    
  5. 现在,你可以通过再次注销 root 并重新登录步骤 1 中的用户来测试sudo是否工作,然后再次尝试:

    sudo ls /var/log/audit
    
    
  6. 祝贺你,现在你已经将一个普通用户设置为拥有 sudo 权限,可以查看和执行限制给 root 用户的文件和目录。

它是如何工作的...

与某些 Linux 发行版不同,CentOS 默认不提供 sudo。相反,你通常只被允许以 root 用户身份访问系统的受限部分。这提供了一定程度的安全性,但对于多用户服务器来说,除非你简单地为这些人提供完整的管理员 root 访问权限,否则几乎没有灵活性。这并不明智,因此本食谱的目的是向你展示如何为一个或多个用户提供执行具有提升权限的命令的权利。

那么,我们从这次经历中学到了什么?

我们首先以一个没有 root 权限或 sudo 权限的普通用户账户登录系统。使用这个用户,我们尝试列出一个通常只有 root 用户才能看到的目录,因此我们在其上应用了sudo命令。但失败了,给出了我们不在 sudoers 列表中的错误。

sudo命令为指定的用户或组提供了执行命令的能力,就像他们是 root 用户一样。所有操作都会被记录(在一个名为/var/log/secure的文件中),因此将会有所有命令和参数使用的痕迹。

我们随后以真正的 root 用户身份登录,并为希望获得 sudo 权限的系统用户添加了一个名为 wheel 的组。这个组被用作特殊的管理组,其所有成员都会自动获得 sudo 权限。

从现在开始,指定的用户可以使用 sudo 来执行任何具有提升权限的命令。为此,用户需要在任何命令前输入sudo这个词,例如,他们可以运行以下命令:

sudo yum update

系统会要求他们确认自己的用户密码(不是 root 密码!),在成功验证后,程序将以 root 用户身份执行。

最后,我们可以说在 CentOS Linux 系统上有三种成为 root 的方式:

首先,以真正的 root 用户身份登录系统。其次,你可以使用命令su – root,同时任何普通系统用户登录,输入 root 用户的密码以永久切换到 root shell 提示符。第三,你可以给一个普通用户 sudo 权限,以便他们可以使用自己的密码执行单个命令,就像他们是 root 用户一样,同时保持自己的登录状态。

注意

sudo超级用户执行)不应与su替代用户)命令混淆,后者允许你永久切换到另一个用户,而不是像 root 用户那样只执行单个命令。

sudo命令为拥有大量用户的服务器提供了极大的灵活性,其中一名管理员不足以管理整个系统。

自定义系统横幅和消息

在本食谱中,我们将学习如何在用户通过 SSH 或控制台成功登录到我们的 CentOS 7 系统,或在图形窗口管理器中打开新的终端窗口时显示欢迎消息。这通常用于向用户显示信息性消息,或出于法律原因。

准备就绪

要完成此食谱,你需要具有 root 权限的 CentOS 7 操作系统的最小安装和所选的基于控制台的文本编辑器。

如何操作...

  1. 首先,使用你的 root 用户账户登录到你的系统,并使用你喜欢的文本编辑器创建以下新文件:

    vi /etc/motd
    
    
  2. 接下来,我们将在此新文件中放入以下内容:

    ###############################################
    # This computer system is for authorized users only.
    # All activity is logged and regularly checked.
    # Individuals using this system without authority or
    # in excess of their authority are subject to
    # having all their services revoked...
    ###############################################
    
    
  3. 保存并关闭此文件。

  4. 恭喜,现在你已经为通过 ssh 或控制台成功登录系统的用户设置了横幅消息。

它是如何工作的...

出于法律原因,强烈建议计算机在允许用户登录之前显示横幅;律师建议,只有在犯罪者知道他打算获得未经授权的访问时,才能犯下未经授权访问的罪行。登录横幅是实现这一点的最佳方式。除了这个原因,你还可以向用户提供有用的系统信息。

那么,我们从这次经历中学到了什么?

我们从这个食谱开始,打开文件/etc/motd,代表每日消息;用户在控制台或 ssh 登录后将显示此内容。接下来,我们在该文件中放入标准的法律免责声明并保存文件。

还有更多...

正如我们所见,/etc/motd文件在用户成功登录系统后显示静态文本。如果你想在首次建立 ssh 连接时也显示一条消息,可以使用 ssh 横幅。默认情况下,ssh 守护进程配置文件中的横幅行为是禁用的,这意味着如果用户建立 ssh 连接,将不会显示任何消息。要启用此功能,请以 root 身份登录到服务器,使用你喜欢的文本编辑器打开/etc/ssh/sshd_config文件,并在文件末尾添加以下内容:

Banner /etc/ssh-banner

然后,创建并打开一个名为/etc/ssh-banner的新文件,并输入一个新的自定义 ssh 问候消息。

最后,使用以下命令重新启动你的 ssh 守护进程:

systemctl restart sshd.service

下次有人建立到你的服务器的 ssh 连接时,将打印出这条新消息。

motd文件只能打印静态消息和一些系统信息细节,但如果用户成功登录,则无法在其中生成真正的动态消息或使用 bash 命令。

此外,motd在非登录 shell 中不起作用,例如当你在图形窗口管理器中打开一个新的终端时。为了实现这一点,我们可以在/etc/profile.d目录中创建一个自定义脚本。如果用户登录到系统,该目录中的所有脚本都会自动执行。首先,我们删除/etc/motd文件中的任何内容,因为我们不想显示两个欢迎横幅。然后,我们打开新文件/etc/profile.d/motd.sh,使用文本编辑器创建一个自定义消息,例如以下内容,我们可以在其中使用 bash 命令并编写小脚本(使用反引号在该文件中运行 bash shell 命令):

#!/bin/bash
echo -e "
##################################
#
# Welcome to `hostname`, you are logged in as `whoami`
# This system is running `cat /etc/redhat-release`
# kernel is `uname -r`
# Uptime is 
`uptime | sed 's/.*up ([^,]*), .*/1/'`
# Mem total `cat /proc/meminfo | grep MemTotal | awk {'print $2'}` kB
###################################"

初始化内核

Linux 内核是一个构成操作系统核心的程序。它可以直接访问底层硬件,并使用户能够通过 shell 与之交互。

在本食谱中,我们将学习如何通过使用动态加载的内核模块来初始化内核。内核模块是设备驱动程序文件(或文件系统驱动程序文件),它们为特定的硬件部件添加支持,以便我们可以访问它们。

作为系统管理员,你不会经常与内核模块打交道,但如果你遇到设备驱动问题或不支持的硬件,对它们有一个基本的了解可能是有益的。

准备就绪

要完成本食谱,你需要具备具有 root 权限的 CentOS 7 操作系统的最小安装。

如何做到这一点...

  1. 首先,使用 root 用户账户登录到你的系统,并输入以下命令以显示当前加载的所有 Linux 内核模块的状态:

    lsmod
    
    
  2. 在输出中,你将看到所有加载的设备驱动程序(模块);让我们看看cdromfloppy模块是否已被加载:

    lsmod | grep "cdrom\|floppy"
    
    
  3. 在大多数服务器上,将会有以下输出:

    cdrom                  42556  1 sr_mod
    floppy                 69417  0
    
    
  4. 现在,我们想要展示关于sr_mod cdrom 模块的详细信息:

    modinfo sr_mod
    
    
  5. 接下来,从内核中卸载这两个模块(只有当模块和硬件已经在你的系统上被找到并加载时,你才能这样做;否则跳过此步骤):

    modprobe -r -v sr_mod floppy
    
    
  6. 检查模块是否已被卸载(输出现在应该是空的):

    lsmod | grep "cdrom\|floppy"
    
    
  7. 现在,要显示系统上所有可用的内核模块列表,请使用以下目录,你可以在其中浏览:

    ls /lib/modules/$(uname -r)/kernel
    
    
  8. 让我们从子目录/lib/modules/$(uname -r)/kernel/drivers/中选择一个名为bluetooth的模块,并验证它尚未加载(输出应该是空的):

    lsmod | grep btusb
    
    
  9. 获取有关模块的更多信息:

    modinfo btusb
    
    
  10. 最后,加载这个蓝牙 USB 模块:

    modprobe btusb
    
    
  11. 再次验证它现在是否已加载:

    lsmod | grep "btusb"
    
    

它是如何工作的...

内核模块是系统硬件与内核和操作系统通信所需的驱动程序(此外,加载和启用文件系统也需要它们)。它们是动态加载的,这意味着只有驱动程序或模块在运行时加载,这反映了你自己的特定硬件。

那么,我们从这次经历中学到了什么?

我们开始使用lsmod命令查看系统中当前加载的所有内核模块。输出显示三列:模块名称、模块加载时占用的 RAM 量,以及使用该模块的进程数和使用它的其他模块的依赖项列表。接下来,我们检查内核是否已经加载了cdromfloppy模块。在输出中,我们看到cdrom模块依赖于sr_mod模块。因此,接下来我们使用modinfo命令获取有关它的详细信息。在这里,我们了解到sr_mod是 SCSI cdrom驱动程序。

由于我们只在首次安装基础系统时需要软盘和 cdrom 驱动程序,我们现在可以禁用这些内核模块,为我们节省一些内存。我们使用modprobe -r命令卸载模块及其依赖项,并再次使用lsmod检查这是否成功。

接下来,我们浏览了标准内核模块目录(例如,/lib/modules/$(uname -r)/kernel/drivers)。uname子字符串命令打印出当前内核版本,以确保在系统上安装了多个内核版本后,我们总是列出当前内核模块。

这个内核模块目录使用子目录将系统上所有可用的模块结构化和分类。我们导航到drivers/bluetooth并选择了btusb模块。对btusb模块执行modinfo,我们发现它是通用蓝牙 USB 驱动程序。最后,我们决定我们需要这个模块,所以我们再次使用modprobe命令加载它。

还有更多...

重要的是要说明,使用modprobe命令加载和卸载内核模块不是持久的;这意味着如果你重新启动系统,所有对内核模块的更改都将消失。要在启动时加载内核模块,创建一个新的可执行脚本文件,/etc/sysconfig/modules/<filename>.modules,其中<filename>是你选择的名称。在那里,你放入modprobe执行命令,就像在正常命令行上一样。以下是启动时额外加载蓝牙驱动程序的示例,例如/etc/sysconfig/modules/btusb.modules

#!/bin/sh
if [ ! -c /dev/input/uinput ] ; then
exec /sbin/modprobe btusb >/dev/null 2>&1
fi

最后,你需要通过以下行使你的新模块文件可执行:

chmod +x /etc/sysconfig/modules/btusb.modules

重启后,使用lsmod命令重新检查新模块的设置。

例如,要在启动时移除内核模块sr_mod,我们需要使用rdblacklist内核启动选项将模块名称列入黑名单。我们可以通过将此选项附加到 GRUB2 配置文件/etc/default/grub中的GRUB_CMDLINE_LINUX指令末尾来设置此选项,使其看起来像:

GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet rdblacklist=sr_mod"

如果你需要将多个模块列入黑名单,rdblacklist选项可以像rdblacklist=sr_mod rdblacklist=nouveau这样指定多次。

接下来,使用grub2-mkconfig命令重新创建 GRUB2 配置(要了解更多信息,请阅读第一章中的入门和自定义引导加载程序配方,安装 CentOS)。

grub2-mkconfig -o /boot/grub2/grub.cfg

最后,我们还需要使用位于/etc/modprobe.d/目录下您选择的new.conf文件中的黑名单指令来blacklist模块名称。

echo "blacklist sr_mod" >> /etc/modprobe.d/blacklist.conf

第三章:系统管理

在本章中,我们将涵盖以下主题:

  • 了解和管理后台服务

  • 解决后台服务问题

  • 使用 journald 跟踪系统资源

  • 配置 journald 以使其持久化

  • 管理用户及其组

  • 使用 cron 安排任务

  • 使用 rsync 同步文件并执行更多操作

  • 维护备份和创建快照

  • 监控重要的服务器基础设施

  • 使用 Git 和 Subversion 进行控制

简介

本章是一系列解决方案的集合,旨在提供基于性能的服务器维护需求。从监控可用磁盘空间,到处理系统服务和管理远程文件同步,本章的目的是展示你如何快速且轻松地掌握服务器维护任务。

了解和管理你的后台服务

系统服务是每个 Linux 服务器最基本的概念之一。它们是持续在你的系统中运行的程序,等待外部事件来处理某些事务或一直执行。通常,在使用服务器时,系统用户不会注意到这些正在运行的服务,因为它们作为后台进程运行,因此不可见。任何 Linux 服务器上都有许多服务一直在运行。这些可以是 Web 服务器、数据库、FTP、SSH 或打印、DHCP、或 LDAP 服务器等。在本操作方法中,我们将展示如何管理和处理它们。

准备就绪

要完成此操作,你需要一个具有 root 权限的 CentOS 7 操作系统的安装,以及你选择的基于控制台的文本编辑器,以及连接到互联网以便下载额外的软件包。这里展示的一些命令在其输出中使用了less导航。请阅读第二章,系统配置中的使用 less 浏览文本文件操作方法,以学习如何浏览它们。

如何操作...

systemctl是一个程序,我们将使用它在 CentOS 7 系统中管理所有后台服务任务。在这里,我们将展示如何使用它,以 Apache Web 服务器服务为例,以便熟悉它。要全面了解 Apache,请阅读第十二章,提供 Web 服务

  1. 首先,我们以 root 身份登录并安装 Apache Web 服务器软件包:

    yum install httpd
    
    
  2. 接下来,我们将检查 Apache 的服务状态:

    systemctl status httpd.service
    
    
  3. 在后台启动 Web 服务器服务并再次打印出其状态:

    systemctl start httpd.service
    systemctl status httpd.service
    
    
  4. 接下来,让我们打印出系统后台当前运行的所有服务列表;在这个列表中,你应该识别出你刚刚启动的httpd服务:

    systemctl -t service -a --state running
    
    
  5. 现在,让我们备份 Apache 配置文件:

    cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.BAK
    
    
  6. 现在,我们将使用 sed 对主 Apache 配置文件进行一些更改:

    sed -i 's/Options Indexes FollowSymLinks/Options -Indexes +FollowSymLinks/g' /etc/httpd/conf/httpd.conf
    
    
  7. 现在,输入以下命令来停止和启动服务并应用我们的更改:

    systemctl stop httpd.service
    systemctl start httpd.service
    systemctl status httpd.service
    
    
  8. 接下来,让我们启用httpd服务,使其在启动时自动启动:

    systemctl enable httpd.service
    
    
  9. 最后一个命令将展示如何重启服务:

    systemctl restart httpd.service
    
    

它是如何工作的...

正如我们所见,systemctl实用程序可用于完全控制系统的服务。systemctlsystemd的控制程序,systemd是 CentOS 7 Linux 中的系统和服务的管理器。systemctl命令还可以用于其他各种任务,但在这里我们专注于管理服务。

那么,我们从这次经历中学到了什么?

我们从这个配方开始,以 root 身份登录并安装了 Apache Web 服务器包,因为我们想用它来展示如何使用systemctl程序管理服务。Apache 或httpd.service,正如systemd所称的,只是我们将使用的一个例子;在基本服务器环境中可能运行的其他重要服务可能是sshd.servicemariadb.servicecrond.service等。之后,我们使用systemctl status命令参数检查了 httpd 的当前状态。输出显示了我们两个字段:LoadedActiveLoaded字段告诉我们它是否当前已加载,以及它是否将在启动时自动启动;Active字段表示服务当前是否正在运行。接下来,我们展示了如何使用systemctl启动服务。服务的精确启动语法是systemctl start <服务名称>.service

注意

通过启动一个服务,程序通过创建一个新进程并将其移动到后台,使其作为非交互式后台进程运行,从而与终端分离。这有时被称为守护进程

接下来,在我们启动了 Apache Web 服务器守护进程之后,我们再次使用 systemctl 的status参数来展示如果我们运行它,状态是如何变化的。输出显示该服务当前已加载但在重启时被禁用。我们还看到它正在运行,以及该服务的最新日志输出和其他关于该进程的详细信息。要获取系统上所有服务的所有状态信息的概览,请使用systemctl --type service --allsystemctl服务不必一直运行。它的状态也可以是停止、降级、维护等。接下来,我们使用以下命令获取系统上所有当前正在运行的服务的列表:

systemctl -t service -a --state running

如您所见,我们在这里使用了-t标志来过滤仅显示类型服务单元。正如您可能猜到的,systemctl不仅可以处理服务单元,还可以处理许多其他单元类型。systemd单元是systemd可以使用配置文件管理的资源,它们封装了关于服务、监听套接字、保存的系统状态快照、挂载设备以及其他与系统相关的对象的信息。要获取所有可能的单元类型的列表,请键入systemctl -t help。这些配置单元文件位于系统中的特殊文件夹中,它们所属的类型可以从扩展名中读取;所有服务单元文件都具有文件扩展名.service(例如,设备单元文件具有扩展名.device)。系统将它们存储在两个地方。所有在安装期间由基本系统安装的systemd单元文件都位于/usr/lib/systemd/system,所有其他来自安装包(如 Apache)的服务或您自己的配置应该放到/etc/systemd/system。我们可以在/usr/lib/systemd/system/httpd.service找到我们的 Apache 服务配置文件。接下来,我们向用户展示了如何停止服务,这是启动它的反向操作,使用语法systemctl stop <服务名称>。最后,作为最后一步,我们使用了 systemctl 的restart参数,它只需一步即可处理服务的停止和启动,减少了输入。如果服务挂起且无响应,并且您需要快速重置它以使其工作,这通常很有用。在展示如何停止和重启服务之前,我们做了另一件重要的事情。当 Apache 服务正在运行时,我们使用sed命令更改了其主要服务配置文件,添加了一个-Indexes选项,该选项禁用了目录网站文件列表,这是提高 Web 服务器安全性的常见措施。由于 Apache Web 服务器已经在运行并在服务启动期间将配置加载到内存中,因此对该文件的任何更改都不会被正在运行的服务识别。

注意

通常情况下,为了应用任何配置文件的更改,运行的服务需要进行完整的服务重启,因为配置文件通常只在启动初始化期间加载。

现在,想象一下你的 Web 服务器可以从互联网访问,并且此刻有很多人在同时访问你的网页或应用程序。如果你正常重启 Apache,Web 服务器将有一段时间无法访问(直到服务器重启完成),因为进程实际上会结束,然后重新开始。所有当前用户如果在那时请求内容,都会收到 HTML 404 错误页面。此外,所有当前会话信息也会丢失;想象一下,你有一个在线网店,人们使用购物车或登录。所有这些信息也会消失。为了避免重要服务(如 Apache Web 服务器)的中断,这些服务中的一些具有reload选项(但并非每个服务都有此功能!),我们可以应用此选项而不是restart参数。此选项只是重新加载并应用服务的配置文件,而服务本身保持在线,执行过程中不会被打断。对于 Apache,你可以使用以下命令行:systemctl reload httpd.service。要获取所有具有重新加载功能的服务列表,请使用以下命令:

grep -l "ExecReload" /usr/lib/systemd/system/*.service /etc/systemd/system/*.service

因此,完成这个配方后,我们可以说我们现在知道如何使用基本的systemctl参数来管理服务。它是一个非常强大的程序,可以用于比仅仅启动和停止服务更多的事情。此外,在这个配方中,我们使用了不同的名称,它们都意味着相同:系统服务、后台进程或守护进程。

还有更多...

还有一种重要的单元类型叫做目标。目标也是单元文件,你的系统中已经有相当数量的目标可用。要显示它们,请使用以下命令:

ls -a /usr/lib/systemd/system/*.target /etc/systemd/system/*.target

简而言之,目标是一系列单元文件的集合,如服务或其他目标。它们可以用来创建类似于早期 CentOS 版本中的运行级别环境。运行级别定义了在系统处于何种状态时应加载哪些服务。例如,有图形状态,或救援模式状态等。要查看常见的运行级别如何对应于我们的目标,可以运行以下命令,该命令显示了它们之间的所有符号链接:

ls -al /lib/systemd/system | grep runlevel

目标可以依赖于其他目标;为了获得目标依赖关系的良好概览,我们可以运行以下命令,显示从多用户目标到所有其他目标的所有依赖关系(绿色表示活跃,红色表示不活跃):

systemctl list-dependencies multi-user.target

你可以使用以下命令显示我们当前所在的目标:

systemctl get-default

你也可以切换到另一个目标:

systemctl set-default multi-user.target

故障排除后台服务

通常,系统管理员工作的大部分时间都在解决服务器出现问题时的故障。这对于系统服务尤其如此,因为它们一直在运行并处理信息。服务可能依赖于其他服务和服务器的系统,系统管理员的生活中将会遇到系统服务失败或拒绝启动的情况。在这里,在这个步骤中,我们将向你展示如果出现问题如何解决它们。

准备就绪

要完成这个步骤,你需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,以及你选择的基于控制台的文本编辑器;你还应该完成了本章中的了解和管理你的后台服务步骤,在那里我们安装了 Apache 网络服务器。

如何做到这一点...

为了向你展示如何解决服务问题,我们将在 Apache 服务的配置文件中引入一个随机错误,然后向你展示如何解决和修复它:

  1. 以 root 身份登录,并输入以下命令将内容追加到httpd.conf

    echo "THIS_IS_AN_ERRORLINE" >> /etc/httpd/conf/httpd.conf
    
    
  2. 接下来,重新加载httpd服务并显示其输出:

    systemctl reload httpd.service
    systemctl status httpd.service -l
    
    
  3. 让我们撤销这个错误行:

    sed -i 's/THIS_IS_AN_ERRORLINE//g' /etc/httpd/conf/httpd.conf
    
    
  4. 现在,再次重启服务:

    systemctl reload httpd.service
    systemctl status httpd.service
    
    

它是如何工作的...

在这个相当短的步骤中,我们向你展示了如果服务包含错误,示例服务将如何表现,以及你可以做些什么来修复它以开始。当服务出现故障时,有很多不同的场景可能会出现问题,解决这些问题可能是系统管理员工作的重要部分。

那么,我们从这次经历中学到了什么?

我们从这个步骤开始,在 Apache 主配置文件中引入了一行文本,该文本不包含任何有效的配置语法,因此httpd服务无法解释它。然后,我们使用systemctl reload参数重新加载我们服务器的配置文件。如前所述,并非所有服务都有重新加载选项,因此如果你的服务不支持这一点,请使用restart参数代替。由于 Apache 将尝试加载我们当前更改的配置文件,它将拒绝接受新的配置,因为我们在其中引入了错误的语法。由于我们只是重新加载配置,正在运行的 Apache 进程不会受到这个问题的影响,并将继续在线使用其原始配置。systemctl参数将打印出以下错误消息,给我们下一步该做什么的提示:

Job for httpd.service failed. Take a look at systemctl status httpd.service and journalctl -xe for details.

正如错误输出所建议的,systemctl状态参数是一个非常强大的工具,可以看到服务背后的情况,并试图找出任何失败的原因(在这里你也可以看到 Apache 仍在运行)。如果你使用-l标志启动systemctl状态,它会打印出更长的输出版本,这可以帮助你更多。

这个命令的输出向我们展示了配置重新加载失败的精确原因,因此我们可以轻松地追踪问题的根源(输出已被截断):

AH00526: Syntax error on line 354 of /etc/httpd/conf/httpd.conf:
Invalid command ERRORLINE, perhaps misspelled or defined by a module, is not included in the server configuration.

这个输出是完整的journald日志信息的一部分。如果你想了解更多关于它的信息,请参考本章中的使用 journald 跟踪系统资源食谱。因此,通过这个输出中非常有用的信息,我们可以轻松地发现问题,并使用sed命令重新引入ERRORLINE,然后重新加载服务;这次一切都会正常工作。

因此,总的来说,我们可以说systemctl status命令是一个非常方便的命令,在找出服务问题时非常有帮助。大多数服务对语法错误非常敏感,有时可能只是一个错位的空格字符导致服务拒绝工作。因此,系统管理员必须始终精确工作。

使用 journald 跟踪系统资源

日志文件包含系统消息和来自服务、内核以及各种运行应用程序的输出。在许多情况下,它们非常有用,例如,用于解决系统问题、监控服务或其他系统资源,或者在安全事件发生后进行安全取证。在本食谱中,你将学习如何使用 journald 进行日志记录服务的基本操作。

准备工作

要完成这个食谱,你需要一个安装了 CentOS 7 操作系统的工作环境,具备 root 权限和一个你选择的基于控制台的文本编辑器。此外,正确设置时间和日期对于整个日志记录概念至关重要,因此请在使用本食谱之前,应用来自第二章,配置系统使用 NTP 和 chrony 套件同步系统时钟食谱。此外,对 systemd 和单元有基本了解可能会有优势。这在本书的了解和管理后台服务食谱中有所涉及。Journalctl 使用less导航来显示输出;如果你不知道如何使用它,请阅读来自第二章,配置系统使用 less 导航文本文件食谱。

如何操作...

在 CentOS 7 中,我们有两个日志记录机制可供选择,分别是rsyslogjournald日志系统,后者是新的systemd系统管理器的一个组件,用于查看和管理日志信息。在这里,我们将向你展示如何使用journalctl命令,它是journald守护进程的控制客户端:

  1. 首先,以 root 身份登录,并输入以下命令来查看整个日志:

    journalctl
    
    
  2. 接下来,我们只想显示在特定时间范围内的消息(相应地更改日期):

    journalctl --since "2015-07-20 6:00:00" --until "2015-07-20 7:30:00"
    
    
  3. 之后,我们想通过所有来自 sshd 服务的消息来过滤日志系统:

    journalctl -u sshd.service --since "yesterday"
    
    
  4. 现在,我们只想显示类型为错误的消息:

    journalctl -p err -b
    
    
  5. 要获取journalctl最详细的版本,请使用verbose选项:

    journalctl -p err -b -o verbose
    
    
  6. 要获取日志输出的当前视图,请使用以下命令(这不是less导航——使用组合键Ctrl+C退出此视图):

    journalctl -f
    
    

它是如何工作的...

在 CentOS 7 中,我们可以使用新的journald日志记录系统,它是systemd系统管理的一部分。它是一个集中式工具,将记录系统上的几乎所有内容,包括从早期启动到内核、服务以及所有程序消息的所有输出。与其他日志记录机制相比,主要优势在于您不必为每个服务或其他资源配置日志记录,因为一切都已经为通过集中式systemd系统控制和运行的所有应用程序设置好了。

那么,我们从这次经历中学到了什么?

我们通过运行journalctl命令开始了我们的旅程,该命令在不带任何参数的情况下向我们展示了完整的日志记录,包括从系统启动到最新的系统消息,按照它们出现的顺序,将新消息附加到底部(按时间顺序)。如果您的系统已经运行了一段时间,它可能包含数十万行日志数据,以这种原始形式处理非常不切实际。

此输出由journald守护进程持续捕获,但不写入文本文件,如rsyslog等其他日志系统所做的那样。相反,它使用结构化和索引的二进制文件,存储大量额外的元信息,如用户 ID、时间戳等,这使得将其转换为各种不同的输出格式变得容易。如果您想通过另一个工具进一步处理日志信息,这可能会非常方便。由于无法读取二进制文件,您将需要客户端journalctl来查询journald数据库。由于手动解析如此大量的数据几乎是不可能的,因此我们利用了 journalctl 丰富的过滤选项。首先,我们使用--since--until参数提取特定时间范围内的所有日志消息。指定时间和日期的语法非常灵活,理解诸如昨天现在之类的短语,但我们坚持使用简单的日期语法,YYYY-MM-DD HH:MM:SS。接下来,我们使用 journalctl 的-u参数过滤特定单元类型的日志消息。我们使用它来过滤来自 sshd 守护程序服务的消息。我们添加了另一个使用--since参数的过滤器,这进一步收紧了-u单元过滤器的结果,仅输出昨天发生的 sshd 服务结果。我们应用的下一个过滤器是使用参数字符串-p err -b,它按优先级或日志级别过滤日志数据库。每个日志消息都可以有一个关联的优先级,该优先级确定消息的重要性。要了解有关不同日志级别的更多信息,请参阅手册,使用命令行man 3 syslog(如果此手册不可用,请键入yum install man-pages进行安装)。我们的命令将打印出所有标记为错误或以上的日志消息,包括:错误严重警报紧急

接下来,我们使用了相同的命令参数,但添加了-o verbose,这提供了最详细的日志信息输出。最后,我们介绍了-f参数(用于跟随),它将为我们提供最新的日志消息的实时视图,并保持此连接打开,当新消息出现时,将其附加到输出的末尾。这在测试设置或启动/停止服务时查看系统反应通常很有用。

总之,可以说在 CentOS 7 上,两个日志系统并存:较旧的rsyslog和较新的journald,后者是您首选的系统故障排除工具。但请记住,在 CentOS 7 上,journald并不是rsyslog的完全替代品。journald中缺少一些rsyslog的功能,而且还有许多工具和脚本,如日志摘要工具或监控套件如 Nagios,它们仅与rsyslog配合使用。

系统管理员在解决系统错误或意外服务器行为时经常面临巨大挑战。通常,在应用正则表达式搜索或 Linux 命令行功夫时,通过搜索大量不同的日志文件文本来找到单一故障点并不容易。Journald 提供了一个非常方便的替代方案,通过提供一个强大且定义良好的集中查询系统,快速高效地完成日志文件分析!

配置 journald 以使其持久

Journald 相对于其他日志系统如rsyslog的优势在于,它非常高效,并且会自动记录系统上的几乎所有内容,无需进行任何配置,因为它属于systemd套件的一部分。主要缺点是,journald的所有日志信息在系统重启后都会丢失。Journald 日志可以产生大量数据,并且默认情况下所有日志信息仅保存在内存中,如果你需要访问较旧的日志信息或分析系统崩溃重启的原因,这并不实用。在本教程中,我们将向你展示如何配置journald以使其持久。

准备就绪

要完成这个教程,你需要一个具有 root 权限的 CentOS 7 操作系统的最小安装,以及你选择的基于控制台的文本编辑器。

如何操作...

开始这个教程,我们需要创建一个位置来保存我们的持久日志数据库:

  1. 以 root 用户身份登录并创建以下目录:

    mkdir /var/log/journal
    
    
  2. 接下来,将新目录添加到journald中,用作存储位置并修复权限:

    systemd-tmpfiles --create --prefix /var/log/journal
    
    
  3. 现在,重启journald

    systemctl restart systemd-journald
    
    
  4. 最后,为了检查日志是否在重启后存活,重启计算机并输入以下命令:

    journalctl --boot=-1
    
    

工作原理...

我们通过创建新目录/var/log/journal开始了这个教程。默认情况下,journald将其日志数据库写入/run/log/journal,这是一个仅用于运行时信息的目录,其内容在系统重启后不会保留。之后,我们使用systemd-tmpfiles命令为journald设置新目录。最后,我们重启了journald服务器守护进程,以将我们的更改应用到系统。为了测试持久性是否正常工作,重启你的服务器,然后使用journalctl –boot=-1。这将向我们展示上次启动以来的所有日志信息。如果持久性没有正常工作,它会打印出以下错误;否则,它会正确显示上次启动之前的所有日志消息:

Failed to look up boot -1: Cannot assign requested address

在这个相当简单的教程中,我们展示了如何使journald在系统重启后保持持久性。如果你需要查看过去的旧日志文件,这会非常有用,有时这能帮助你找出问题,例如过去硬件故障的根源。

管理用户及其组

在这个操作中,我们将学习如何在 CentOS 7 上管理系统的用户和组。基本的用户和组管理技能是 CentOS 系统管理员最重要的基础之一。

准备就绪

要完成这个操作,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,以及您选择的基于控制台的文本编辑器。

如何操作...

这个操作向您展示了如何通过学习如何添加、删除和修改用户和组来管理它们:

  1. 要开始这个操作,我们以 root 身份登录,并输入以下命令以获取系统中所有已知用户的列表:cat /etc/passwd

  2. 现在,显示 root 用户的 ID(UID)和组 ID(GID):

    id root
    
    
  3. 接下来,我们将运行以下命令以在系统中添加一个新用户(将your_new_username替换为您选择的用户名):

    useradd your_new_username
    
    
  4. 然而,为了完成这个过程,您将被要求提供一个合适的密码。为此,输入以下命令(将your_new_username替换为您选择的用户名),然后在提示时输入一个安全的密码:

    passwd your_new_username
    
    

    注意

    密码不应少于六个字符,但也不应超过十六个字符。它们应由字母数字值组成,并且出于显而易见的原因,您必须避免使用空格。不要使用字典中的单词,并避免使用已知或明显的短语。

  5. 接下来,创建一个新组并给它一个特殊的名称:

    groupadd your_new_group
    
    
  6. 然后,我们将新用户添加到这个新组中:

    usermod -G your_new_group your_new_username
    
    
  7. 最后,让我们打印出新用户的用户 ID 和组 ID,看看发生了哪些变化:

    id your_new_username
    
    

它是如何工作的...

这个操作的目的是创建一个新用户和组,并展示如何将它们连接在一起。

那么,我们从这次经历中学到了什么?

首先,我们打印出/etc/passwd文件的内容,以显示系统中所有当前用户。这个列表不仅包含属于真实人物的普通用户账户,还包含用于控制和拥有特定应用程序或服务的账户。然后,我们使用id命令来显示我们现有用户 root 的唯一用户 UID 和 GID。在 Linux 中,每个用户都可以通过他们的 UID 和 GID 来识别,并且文件系统中的每个文件都有特定的权限设置,这些设置管理文件所有者、组所有者和其他用户的访问权限。对于这三个组中的每一个,您都可以使用chmod命令启用或禁用读、写和执行权限(使用man chmod了解更多信息,并查看man chown)。所有者和组权限对应于一个 UID 和 GID,我们可以使用ls -l为每个文件显示这些信息。

接下来,我们执行了useradd命令,要求我们为新用户提供一个合适的名称,这将使服务器能够使用一组默认值和标准建立新身份,包括用户 ID、家目录、主组(GID),并将默认 shell 设置为 bash。完成此过程只需确认一个合适的密码。要删除用户,有相反的命令userdel,其工作方式类似,但可以给出-f选项以删除家目录而不是将其留在系统上。接下来,我们使用了groupadd命令,顾名思义,它将创建一个新组并为它分配一个新的唯一 GID。之后,我们使用usermod -G命令将我们的用户添加到之前创建的新组中。如前所述,每个用户都有一个唯一的 UID 和 GID。第一个组是主组,是必需的;但是,用户可以属于多个不同的组,这些组称为辅助组。创建新文件时需要主组,因为它将设置创建它的用户的 GID 和 UID。要删除组,我们可以使用groupdel命令。最后,我们再次使用id命令查看新用户的 UID、主 GID 以及我们添加给它的新的辅助 GID 组。

现在,您只需使用几个命令即可完全控制用户和组:useraddusermoduserdelgroupaddgroupmodgroupdel

使用 cron 安排任务

在本食谱中,我们将探讨服务器自动化的作用以及通过引入您到基于时间的作业调度程序 cron 来在预定义周期内运行特定任务的便利性。Cron 允许通过使管理员能够根据任何小时、任何天或任何月确定预定义的计划来自动化任务。它是 CentOS 操作系统的标准组件,本食谱的目的是向您介绍管理重复任务的概念,以便利用这一宝贵工具并使 CentOS 为您工作。

准备就绪

要完成本食谱,您需要具有 root 权限的 CentOS 7 操作系统的最小安装,以及您选择的基于控制台的文本编辑器。crontab程序使用 Vim 进行文件编辑。如果您不知道如何使用 Vim,请查看食谱Vim 简介中的教程,位于第二章,配置系统

如何操作...

本食谱的目的是创建一个脚本,该脚本将每五分钟将时间和日期以及您选择的几句话写入文本文件。这可能看起来是一个相对简单的练习,但意图是向您展示,从这种简单性出发,cron 可以用于做更多的事情,这将使与 CentOS 一起工作成为一种绝对的乐趣。

  1. 要开始这个配方,请以 root 身份登录并创建您的第一个 cron 作业,方法是输入:

    crontab -e
    
    
  2. 我们现在将创建一个简单的 cron 作业,该作业将日期和时间与单词 hello world 一起写入位于 /root/cron-helloworld.txt 的文件中,每五分钟一次。为此,添加以下行:

    */5 * * * * echo `date` "Hello world" >>$HOME/cron-helloworld.txt
    
    
  3. 完成后,只需保存文件并退出编辑器。系统现在将响应以下消息:

    crontab: installing
     new crontab
    
    
  4. 前面的消息通知您,服务器现在正在创建新的 cron 作业,并将自动激活它。您可以通过查看位于 /root/cron-helloworld.txt 的文件来查看脚本的输出(您必须等待 5 分钟),或者通过监视位于 /var/log/cron 的日志文件(使用 tail -f /var/log/cronCtrl+C 退出)。

它是如何工作的...

Cron 是一个程序的名称,它允许 CentOS 用户在指定的时间和日期自动执行命令或脚本。Cron 的设置保存在一个名为 crontab 的用户特定文件中,正如我们在本配方中看到的那样,可以编辑此文件以创建所需的自动化任务。

那么我们从这次经历中学到了什么?

使用的示例非常简单,但在许多方面,这是这个配方的目的。Crontab 使用一个守护进程 crond,它一直在后台运行,并每分钟检查一次是否有任何计划的任务需要执行。如果找到任务,则 cron 将执行它。要编辑现有的 crontab 文件或创建新的 crontab,我们使用 crontab -e 命令。要查看当前的 cron 作业列表,可以键入 crontab -l。或者,要查看另一个用户的当前作业列表,可以键入 crontab -u username -l。任务或作业通常称为 cron 作业,并且通过在我们的第一个脚本中避免复杂性,目的是向您展示命令构造的本质非常简单。cron 作业的形成如下所示:

<minute> <hour> <day of the month> <month of the year> <day of the week> <command>

条目由单个或制表符分隔,允许的值主要是数字(即,0-59 表示分钟,0-23 表示小时,1-31 表示月份中的日期,1-12 表示年份中的月份,0-7 表示星期几)。然而,这样说也是正确的,即存在更具体的运算符(/-)和特定的 cron 快捷方式(即,@yearly@daily@hourly@weekly),这些允许额外的控制。例如,/ 运算符用于逐步指定单位,可以读作 ,所以在我们的配方中使用 */5 将使任务每五分钟运行一次,而使用 */1 将使任务每分钟运行一次。此外,您应该知道,使用此语法将使所有命令与小时对齐。因此,考虑到这一点,对于任何想要编写他们的第一个 cron 作业的人来说,最合适的模板或起点是开始使用一系列五个星号,然后是命令,如下所示:

* * * * * /absolute/path/to/script.sh

然后,继续配置所需的分钟、小时、日期、月份和星期值。例如,如果您希望在每个工作日(周一至周五)的晚上 8 点(20:00 小时)运行特定的 PHP 脚本,它可能看起来像这样:

0 20 * * 1-5 /full/path/to/your/php/script.php

因此,考虑到这一点,通过完成本食谱,您可以看到 cron 如何用于管理数据库备份,运行预定系统备份,通过在预定义间隔激活脚本来支持网站,或运行各种 bash 脚本等等。

还有更多...

要删除或禁用 cron 作业,只需从单个用户的 cron 文件中删除指令,或者在行首放置一个哈希(#)。单个 cron 文件可以在/var/spool/cron/<username>找到,使用哈希将禁用 cron 作业或允许您编写注释。要完全删除crontab文件,您还可以使用crontab -r。例如,如果您想删除主食谱中创建的 cron 作业,您可以以 root 身份登录并开始输入命令crontab -e。此时,您可以删除整行或将其注释掉,如下所示:

# */15 * * * * echo `date` "Hello world" >>$HOME/cron-helloworld.txt

接下来,保存文件。在文件系统中还有一些特殊的 cron 目录,用于系统范围的 cron 作业。如果您将脚本文件放入其中,它将在特定时间点自动运行。这些目录在/etc目录中被称为cron.dailycron.hourlycron.weeklycron.monthly,它们的名称指的是它们运行的时间点。如果您不再想执行脚本,只需将其从文件夹中删除即可。查看监控重要服务器基础设施的示例。

使用 rsync 同步文件并执行更多操作

rsync是一个程序,可用于在各种本地和远程位置之间同步文件和目录。它可以与多种操作系统交互,通过 SSH 工作,提供增量备份,在远程机器上执行命令,并取代cpscp命令的需求。rsync程序对于打算运行服务器或管理计算机网络的任何系统管理员来说都是无价之宝,因为它不仅简化了备份过程,还可以用于执行完整的备份解决方案。因此,本食谱的目的是提供一个合适的起点,以快速成为您信赖的朋友的小工具。

准备就绪

要完成本食谱,您需要具有 root 权限的 CentOS 7 操作系统的安装,您选择的基于控制台的文本编辑器以及连接到 Internet 以促进下载其他软件包的连接。

如何操作...

在本食谱的过程中,将假定您知道要同步的源文件和目录的位置,并且有一个合适的目的地:

  1. 要开始本教程,请以 root 身份登录并键入以下内容安装rsync

    yum install rsync
    
    
  2. 现在,为我们的同步创建一个目标目录(根据需要更改文件夹名称):

    mkdir ~/sync-target
    
    
  3. 要开始同步过程,只需重复以下命令,通过修改用于/path/to/source/files/的值来满足您的需求:

    rsync -avz --delete /path/to/source/files/  ~/sync-target
    
    
  4. 在确认前面的指令后,您的系统现在将响应一个实时报告,说明正在复制的内容。当这个过程完成后,您可以比较两个目录,看看内容是否完全相同。为此,请使用diff命令(如果两者相同,则不会写入输出):

    diff -r /path/to/source/files/ ~/sync-target
    
    

它是如何工作的...

在本教程中,我们考虑了通过命令行使用rsync。当然,这只是使用这个工具的众多方式之一,但通过这种方法,我们能够探索这个非常有价值的实用程序提供的一些功能。

那么,我们从这次经历中学到了什么?

Rsync 并不是为了复杂而设计的。它是一个快速且高效的文件同步工具,旨在通过在命令行上为您提供完整的访问权限来实现多功能性。它可以用来在同一台机器上或在完全不同的系统上维护目录的精确副本(或镜像),它通过一次复制所有文件,然后在下次运行时仅更新已更改的文件来实现这一点。这可以节省大量的带宽,并且应该是您在网络上复制数据时的主要工具。使用短语--delete很重要,因为它指示rsync删除目标上不存在于源中的文件,而所选标志意味着rsync应该使用-a存档模式来递归复制文件和目录,同时保持所有权限和基于时间的信息;–v)详细模式,以便您可以看到正在发生的事情;以及–z在文件传输期间压缩数据,以节省带宽并减少完成整个过程所需的时间。

如您所见,rsync非常灵活,并且有许多超出本教程目的的选项,但如果您想排除某些文件,您始终可以通过调用--exclude标志来扩展原始指令。通过这样做,您告诉rsync备份整个目录,但确保不包括预定义的文件和文件夹模式。例如,如果您正在将文件从服务器复制到 USB 设备,并且您不想包括大型文件(如.iso映像)或 ZIP 文件,那么您的命令可能与此类似:

rsync --delete -avz --exclude="*.zip" --exclude="*.iso"  /path/to/source/ /path/to/external/disk/

最后,关于详细程度的话题。详细程度非常有用,但倾向于使用字节作为其主要测量单位可能会引起混淆。因此,为了改变这一点,您可以调用带有–h(或人类可读)选项的rsync,如下所示:

rsync -avzh --exclude="home/path/to/file.txt" /home/ /path/to/external/disk/

维护备份和快照

在本配方中,我们将向您展示如何定期进行数据备份,这些备份将使用crond守护进程对系统的一些目录进行快照。这将定期运行rsync程序,以实现完全自动化的备份解决方案。

准备就绪

要完成此配方,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,以及您选择的基于控制台的文本编辑器。如果您阅读了本章中的使用 rsync 同步文件并执行更多操作使用 cron 安排任务配方,以获得对所用命令的更深入理解,那将是有益的。

如何操作...

在继续此配方之前,在您的服务器上安装rsync程序非常重要。

  1. 首先,以 root 身份登录并创建一个目录,我们的备份将存放在那里:

    mkdir /backups
    
    
  2. 现在,我们将创建以下 shell 脚本文件并打开它进行编辑:

    mkdir ~/bin;vi ~/bin/mybackup.sh
    
    
  3. 输入以下内容,将环境变量DESTSOURCE中的/backups替换为您希望备份的目录,以及收件人的EMAIL

    #!/bin/bash
    SBJT="cron backup report for `hostname -s` from $(date +%Y%m%d:%T)"
    FROM=root@domain
    EMAIL=johndoe@internet.com
    SOURCE=/root
    DEST=/backups
    LFPATH=/tmp
    LF=$LFPATH/$(date +%Y%m%d_%T)_logfile.log
    rsync --delete --log-file=$LF -avzq $SOURCE $DEST
    (echo "$SBJT"; echo; cat $LF ) | sendmail -f $FROM -t $EMAIL
    
    
  4. 使脚本可执行:

    chmod a+x /root/bin/mybackup.sh
    
    
  5. 现在,使用以下命令打开crontab

    crontab -e
    
    
  6. 接下来,通过在文档末尾添加以下行来创建以下条目,然后保存并关闭它:

    30 20 * * * /root/bin/mybackup.sh
    
    

它是如何工作的...

在本配方中,我们为单个系统目录创建了一个完全自动化的备份解决方案,该解决方案将在某个时间点创建文件的快照。备份过程完成后,您将收到一封电子邮件,通知您已进行备份,并附有对所采取行动的简要回顾。

那么我们从这次经历中学到了什么?

我们通过创建一个目录来开始此配方,我们的备份将放置在那里。接下来,我们创建了实际的脚本并填充了一些命令。第 1 行将文件定义为 bash 脚本,第 2-6 行是您可以修改和自定义以满足您自己需求的变量。第 7-8 行根据日期创建日志文件的路径和名称,第 9 行调用rsync,它将同步所有源文件到目标目录/backups。它使用特殊的--log-file参数,该参数将所有输出写入给定文件。最后一行(10)将此日志文件的内容发送到电子邮件地址。

请记住,您应该根据需要自定义值(即更改使用的电子邮件地址,选择源目录,选择目标目录等)。在它能够被cron使用和执行之前,我们使其可执行。最后,我们将此脚本添加为 cron 作业,以便在每天的 20:30 小时运行。但是,由于这可能需要几个小时,如果您想立即测试脚本,可以使用以下命令在命令行上执行它:

/root/bin/mybackup.sh

总之,不言而喻,备份应该位于外部驱动器或单独的分区上,但是完成这个介绍后,我认为你会同意rsync处于理想的位置,它将使任何服务器管理员能够制定自己的政策,以维护重要数据的有效备份。

监控重要的服务器基础设施

在本配方中,我们将使用一个小脚本来定期监控可用文件系统的磁盘空间,如果超过某个百分比阈值,脚本将发送带有警告消息的邮件。

准备就绪

要完成这个配方,你需要一个具有 root 权限和所选控制台文本编辑器的 CentOS 7 操作系统的有效安装。你应该已经阅读了使用 cron 安排任务配方,以便对 cron 系统的原理有一个基本的了解。

如何做到这一点...

  1. 要开始这个配方,请以 root 身份登录并创建以下文件,该文件将包含我们的监控脚本:

    vi /etc/cron.daily/monitor_disk_space.sh
    
    
  2. 现在,请输入以下内容:

    #!/bin/bash
    EMAIL="root@localhost"
    THRESHOLD=70
    df -H | grep -vE '^Filesystem|tmpfs|cdrom' | awk '{ print $5 " " $6 }' | while read output;
    do
     usep=$(echo $output | awk '{ print $1}' | cut -d'%' -f1  )
     partition=$(echo $output | awk '{ print $2 }' )
     if [ $usep -ge $THRESHOLD ]; then
     (echo "Subject: Alert: Free space low on `hostname -s`, $usep % used on $partition"; echo)| 
     sendmail -t $EMAIL
     fi
    done
    
    
  3. 现在,保存文件并使其可执行:

    chmod +x /etc/cron.daily/monitor_disk_space.sh
    
    

它是如何工作的...

我们使这个脚本可执行,并将其放入/etc/cron.daily目录中,这就是我们需要做的所有事情,以便通过crond服务每天自动运行这个脚本。

这个简单的脚本向我们展示了构建监控脚本是多么容易,这可以成为安装和配置大型监控套件(如 Nagios)的真正替代方案。您可以使用所示的脚本作为起点,添加更多需要监控的重要资源,例如 CPU 负载、可用 RAM 等。

我们使用了一个执行 Linux 命令df的脚本,这是一个报告文件系统磁盘空间使用情况的工具。从这个命令的输出中,脚本然后解析了USE%列(使用 Unix 工具awkcut),这给了我们总磁盘使用百分比。然后,这个数字将与用户可以通过编辑脚本并更改环境变量THRESHOLD设置的阈值进行比较。如果提取的百分比数字高于我们的阈值,将向定义了环境变量EMAIL的电子邮件地址发送电子邮件(如果需要,请相应更改)。

使用 GIT 和 Subversion 进行控制

文档修订控制系统或版本控制系统,有时也称为版本控制系统,用于管理文档的更改。随着现代工作越来越多地将来自世界各地的人们联系起来,共同合作并共同处理各种文档(例如,软件源代码),这些系统变得越来越重要,因此管理不同人使用修订版进行的文件更改变得非常重要。在本配方中,我们将向您展示如何使用现代版本控制系统,如 GIT 和 Subversion,来管理配置文件的版本控制。

准备就绪

要完成本教程,你需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,以及一个互联网连接,以便于下载额外的软件包。

如何操作...

在本教程中,我们将把完整的 Linux 主配置目录/etc/置于 Git 仓库的版本控制之下,以跟踪我们对配置文件所做的所有更改:

  1. 首先,以 root 身份登录,安装 Git,并通过提供电子邮件地址和用户名来配置它(请将your_usernameyour_email_address替换为真实姓名):

    yum install git
    git config --global user.email  "your_email_address"
    git config --global user.name "your_username"
    
    
  2. 现在,让我们在/etc目录中创建一个新的仓库:

    cd /etc/
    git init
    
    
  3. 现在,我们有了新的仓库,让我们将/etc/目录中的所有文件置于版本控制之下:

    git add *
    
    
  4. 要提交文件到仓库,创建你的第一个版本,请输入以下内容:

    git commit -a -m "inital commit of the full /etc/ directory"
    
    
  5. 现在,让我们更改一个文件:

    echo "FILE HAS CHANGED" >> yum.conf
    
    
  6. 接下来,展示你的仓库中的更改:

    git status
    
    
  7. 接下来,我们将提交这些更改并创建一个新的版本:

    git commit -a -m "changing yum.conf files"
    
    
  8. 接下来,展示迄今为止的所有提交:

    git log --pretty=oneline --abbrev-commit
    
    
  9. 这将输出我的系统上的以下提交(你的系统上的数字哈希值将不同):

    8069c4a changing yum.conf
    5f0d50a inital commit of the full /etc directory
    
    
  10. 基于前一步骤的输出,我们现在将展示两个版本号之间的所有差异(根据前一步骤的输出,在你的系统上更改数字哈希值):

    git diff 8069c4a 5f0d50a
    
    
  11. 要完成本教程,我们将撤销我们对原始文件版本的更改(初始提交):

    git checkout 5f0d50a
    
    

它是如何工作的

在本教程中,我们向你展示了如何使用 Git 来管理/etc目录中的系统配置文件的更改。如果你正在进行测试,这可能很重要,因为你会对某些配置文件进行大量更改,并且希望跟踪这些更改。这样做的好处是,如果你以后需要撤销更改或回退到特定版本,或者比较不同文件版本,你不需要记住你采取的每一个步骤。

那么,我们从这次经历中学到了什么?

我们首先安装了 Git,并向其配置中添加了用户名和电子邮件地址,这对于后续使用至关重要。然后,我们切换到 /etc 目录,并在那里初始化(使用 init 参数)一个新的空 Git 项目,这被称为仓库,用于跟踪与之关联的所有文件。此命令将在其中添加一个隐藏的 .git 目录,其中包含完整的文件更改和修订信息。接下来,我们添加了该目录中的所有文件(使用通配符 * 运算符),包括所有子目录到下一个修订版。修订版就像文件在给定时间点的状态,由唯一的哈希 ID 标识,例如 8069c4a。然后,我们实际创建了一个新修订版,使用 commit 参数并提供有意义的 message 使用 -m 参数。在我们设置 Git 仓库并将所有文件添加到其中之后,对 /etc 目录中文件的每次更改都会被监视。接下来,我们在仓库中修改了主 YUM 配置文件,通过使用 echo >> 命令在末尾添加一个随机字符串。如果我们现在再次使用 git 的 status 参数,我们会在输出中看到 Git 系统已通知该文件已被更改。我们现在可以使用 git 的 commit 参数再次创建一个包含更改文件的新修订版,并在此处使用另一个有意义的 message 说明 yum.conf 已被更改。然后我们使用了 git log 命令。这将向我们展示所有已提交的修订版及其唯一的 md5 哈希字符串 ID。使用此 ID,我们可以为 git diff 命令提供燃料,以查看两个修订版之间的所有文件更改。要了解更多输出格式,请使用 man git-diff-files 并阅读其 COMBINED DIFF FORMAT 部分。在我们最后一步中,我们使用了 checkout 命令转到特定文件修订版;在这里,我们恢复了所有更改并返回到原始文件状态。

Git 是一个非常强大的版本管理工具,在本教程中我们只是浅尝辄止地了解了它的功能。要学习更多关于 Git 的精彩技巧,如分支、合并、拉取请求等,可以从输入 man gittutorial 开始,阅读 Git 教程页面。

不仅如此...

您还可以使用 Subversion 程序将 /etc 目录置于版本控制之下。Subversion 是另一种常见的文档修订控制系统,与 Git 的主要区别在于它使用中央服务器来跟踪文件更改。Git 是分布式的,这意味着在 Git 项目上工作的每个人都会在本地计算机上拥有完整的仓库。在这里,我们将向您展示使用 Subversion 代替 Git 所需的精确步骤:

  1. 首先,安装 Subversion 并为我们的 /etc 仓库配置一个新的服务器目录:

    yum install subversion
    mkdir -p /var/local/svn/etc-repos
    svnadmin create --fs-type fsfs /var/local/svn/etc-repos
    
    
  2. 现在,将 /etc 文件系统就地导入到我们的新仓库中:

    svn mkdir file:///var/local/svn/etc-repos/etc 
    -m "Make a directory in the repository to correspond to /etc"
    
    
  3. 现在,切换到 /etc 目录并将所有文件添加到一个新修订版中:

    cd /etc
    svn checkout  file:///var/local/svn/etc-repos/etc ./
    svn add *
    
    
  4. 现在,创建您的第一个提交:

    svn commit -m "inital commit of the full /etc/ directory"
    
    
  5. 接下来,修改yum.conf文件:

    echo "FILE HAS CHANGED" >> yum.conf
    
    
  6. 将你的更改提交到新的文件版本:

    svn commit -m "changing yum.conf files"
    
    
  7. 现在,展示变更日志:

    svn log -r 1:HEAD
    
    
  8. 显示我们两个提交之间的文件差异(第一个提交是/etc导入):

    svn diff -r 2:3
    
    
  9. 最后,恢复到我们yum.conf文件的第一个版本:

    svn update -r 2 yum.conf
    
    

第四章:使用 YUM 管理软件包

在本章中,我们将涵盖以下主题:

  • 使用 YUM 更新系统

  • 使用 YUM 搜索软件包

  • 使用 YUM 安装软件包

  • 使用 YUM 删除软件包

  • 保持 YUM 的清洁和整洁

  • 了解您的优先级

  • 使用第三方仓库

  • 创建 YUM 仓库

  • 使用 RPM 软件包管理器

引言

本章是一系列教程的集合,提供了对扩展服务器所需的工具的回顾。软件包管理是任何基于 Linux 的系统的核心,本章的目的强调了在基于 CentOS 的服务器上管理软件包所需的关键工具。

使用 YUM 更新系统

在本教程中,我们将探讨Yellowdog Updater, ModifiedYUM)软件包管理器在运行系统更新方面的角色。每隔一段时间,您可能会意识到有更新,或者可能只是想了解是否存在更新。应用补丁和更新是每个服务器管理员的常规任务,一个最新的系统可以帮助提高或确保您的服务器的安全性,因为软件错误和漏洞一直在被发现,并且必须及时修复。在本教程中,您将学习如何借助 YUM 实现这一点。

准备工作

要完成本教程,您需要具备具有 root 权限的 CentOS 7 操作系统的正常安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便于下载额外软件包的能力。

如何操作...

您可以根据自己的选择的时间表经常运行本教程,但应该经常进行,完全了解有时某些更新可能需要完全系统重启:

  1. 以 root 身份登录并检查是否有任何适用于您已安装软件包的更新。为此,请登录并输入以下命令:

    yum check-update
    
    
  2. 如果没有可用的更新,那么更新过程将结束,不需要进行进一步的工作。然而,如果有可用的更新,YUM 现在将返回来自系统已知仓库的所有软件包更新的列表。要完成更新过程,请输入以下命令:

    yum -y update
    
    
  3. 通过使用-y标志,前面的命令现在将绕过确认交易摘要的需要,您的系统现在将立即进行更新过程。完成后,您将获得一个最终报告,该报告标识了已安装的依赖项和已更新的软件包。

  4. 通常情况下,不需要进一步的工作,您可以恢复正常的操作。然而,如果安装了新的内核,或者进行了重要的安全更新,可能需要重启系统以使新的更改生效。为此,请输入以下命令:

    reboot
    
    

    注意

    尽管关于更新是否需要在实践中进行全面系统重启存在很多争议,但这只有在进行内核更新后才需要考虑,内核更新是对glibc和在启动过程中激活的特定安全功能的更新。

它是如何工作的...

YUM 是 CentOS 默认的包管理器,其职责之一是自动计算哪些包可能需要更新,哪些依赖项是必需的,并以非常简单的方式管理整个系统更新过程。

那么,我们从这次经历中学到了什么?

我们通过使用yum命令和check-update选项检查系统是否有可用更新来开始这个配方。这样,YUM 现在将检查中央存储库以确认我们的系统是否有适用的更新。存储库是一个包含预制软件包和实用程序的远程目录或网站。YUM 将使用此设施自动定位和获取正确的Red Hat Package ManagerRPM)和依赖项,如果有可用更新,YUM 将相应地响应,提供有关哪些包和依赖项可用的完整摘要。因此,YUM 是一个非常有用的工具,毫无疑问,其机制确实简化了与包管理相关的流程,因为它可以与存储库对话,这使我们不必手动查找和安装新应用程序或更新。如果有可用更新,输出将向我们显示受影响的包,然后我们可以继续使用 YUM 的update参数更新系统。在这种情况下,前面的命令包括-y标志。这是为了绕过同意交易摘要的需要,并确认我们已经在运行前面的检查后同意进行这些更新。否则,你只需使用Y键确认请求。

还有更多...

你还可以使用更新参数来更新单个包而不是整个系统,只需提供包名,例如:yum update package_name。YUM 将确保在安装应用程序时满足所有要求,并自动安装系统上尚未存在的任何依赖项的包。然而,我确信你会很高兴听到这一点,如果新应用程序有与现有软件冲突的要求,YUM 将中止过程而不对系统进行任何更改。如果你想使用特定时间间隔自动更新系统,可以安装yum-cron包,该包可以高度定制,但超出了本书的范围。安装后启动,使用man yum-cron

使用 YUM 搜索包

在本食谱中,我们将研究使用 YUM 查找包的作用。YUM 是为了改进 RPM 软件包的安装而开发的,它用于访问提供服务器提供的全方位服务的不断增长的数学包列表。YUM 使用起来很简单,但如果你不确定包的名称,那么作为服务器管理员的工作就会变得更加困难。为了克服这一点,YUM 维护了广泛的发现工具,本食谱的目的是向您展示如何使用此功能来搜索各种存储库并找到您需要的包。

准备工作

要完成本食谱,您需要具有 root 权限的 CentOS 7 操作系统的工作安装、您选择的基于控制台的文本编辑器以及互联网连接。

如何做到这一点...

本食谱将向您展示如何通过调用 YUM 的搜索选项来找到一个或多个包。为此,您需要以 root 用户身份登录并完成以下过程:

  1. 要搜索单个包,请将 keyword 值替换为适当的短语、字符串或参数,然后键入以下内容:

    yum search keyword
    
    
  2. 等待搜索结果的摘要,当生成列表时,您可以通过简单地将 package_name 替换为适当的值来查询任何显示的包:

    yum info package_name
    
    
  3. 如果前面的结果令人满意,并且您想查看与该包相关的依赖项列表,请键入以下内容:

    yum deplist package_name
    
    

它是如何工作的...

使用 YUM 搜索包的方式与在 万维网WWW)上搜索任何内容的方式相同。您可以搜索的单词类型可以像您喜欢的那样具体或一般。它们甚至可以由完整或部分单词组成;找到您可能感兴趣的包后,您会注意到,本食谱还向您展示了如何发现有关该包的更多信息。

那么,我们从这次经历中学到了什么?

YUM 维护了广泛的搜索功能,允许您通过关键字、包名和路径名查询包。例如,如果您想找到编译 C、Objective-C 和 C++ 代码的正确包,可以使用 yum search compiler 查询。在命令行上使用这些搜索词时,会出现许多相关结果,每个包都附有简短描述,使我们能够通过简单的排除过程来选择最明显或最相关的值。考虑到这一点,您可以使用 info 参数向 YUM 查询以了解有关某些包的更多信息。此选项显示了完整的包详细信息以及包旨在提供的功能的详细描述。一般来说,您可能不需要知道更多细节。

然而,在某些情况下,您可能想知道该软件包如何与整个服务器交互(特别是如果您正在处理源安装或修复损坏的软件包),因此我们可以使用 YUM 的deplist参数,它可以提供相当详细的报告;如果您碰巧有任何损坏的软件包,您可以使用此输出来详细说明您可能需要或不需要安装哪些依赖项来解决潜在问题。当调试依赖关系或处理基于源的安装时,此命令特别有用。

还有更多...

有时,您可能不想搜索特定的软件包,而是可能更愿意以目录式格式显示您存储库的内容。同样,这很容易做到,YUM 提供了以下命令来实现这一功能。如果您想简单地列出当前系统使用的存储库中所有可用的软件包,请键入yum list all。然而,由于此列表可能非常详尽,您可能更愿意通过使用yum list all | less来分页浏览结果。类似地,如果您只想列出系统上当前安装的所有软件,请键入yum list installed | less。如果您想确定哪些软件包提供了特定的文件或功能,只需随时运行以下命令,将your_filename_here替换为与您自己的需求更相关的内容:yum provides your_filename_here

使用 YUM 安装软件包

在本教程中,我们将探讨 YUM 在服务器上安装新软件包的作用。对于每位服务器管理员来说,安装应用程序和服务是一项重要任务。有多种方法可以实现这一点,但最有效的方法涉及使用 YUM 包管理器。YUM 能够搜索任意数量的存储库,自动解决软件包依赖关系,并指定安装一个或多个软件包。YUM 是现代且确定性的方法,用于在服务器上安装软件包,本教程的目的就是向您展示如何做到这一点。

准备工作

要完成本教程,您需要具备 CentOS 7 操作系统的有效安装,拥有 root 权限,选择一个基于控制台的文本编辑器,以及连接到互联网以便下载额外的软件包。如果您已经找到了一些有趣的软件包来安装,那么使用使用 YUM 搜索软件包教程中的说明来学习这些软件包是很好的。

如何做到这一点...

本教程将向您展示如何通过调用 YUM 安装选项来安装一个或多个软件包。为此,您需要以 root 用户身份登录并完成以下过程:

  1. 要安装单个软件包,请将package_name值替换为适当的值,然后键入以下内容:

    yum install package_name
    
    
  2. 你的系统现在将提供一个交易报告,需要你的批准。因此,当提示时,只需使用YN键并按Return键来接受或拒绝交易,如下所示:

    Is this ok [y/d/N]: y
    
    
  3. 如果你拒绝了交易,那么不需要进行进一步的工作,你将退出软件包管理例程。然而,如果你确认了交易,那么请观察安装进度,最终它会显示一个Complete!消息。

  4. 恭喜!你现在已经成功安装了你选择的软件包。

它是如何工作的...

所有软件包都存储在 RPM 软件包文件格式中,而 YUM 的作用是提供对存储在互联网上各种仓库中的这些文件的访问。YUM 是 CentOS 软件包管理背后的力量,它确实使得安装过程变得非常简单,但我们从这次经历中学到了什么?

调用install命令后,YUM 将在各个仓库中进行搜索,以找到与所讨论的软件包相关的相关标题和元数据。例如,如果你想安装一个名为wget的软件包,你将首先发出这样的install命令:yum install wget。然后,YUM 将定位该软件包,并生成一个交易摘要,该摘要不仅指示所需的磁盘空间和预期的安装大小,还将指示所请求的软件包所需的任何必要依赖项。YUM 将检查几个不同的仓库(baseextras,和updates),并在解决了任何必要依赖项的需求后,YUM 将要求我们在继续安装过程之前确认请求。因此,正如你所见,通过使用Y键,我们将向 YUM 提供执行请求的权限,这将导致下载、验证和安装相关软件包。

还有更多...

有时你可能希望一次性安装多个软件包。要实现这一点,只需调用相同的install命令,但不是指定单个软件包,而是以形成一个长购物清单的方式列出你可能需要的所有软件包:

yum install package_name1 package_name2 package_name3

你可以以这种方式安装的软件包数量没有限制,但始终在每个软件包名称之间留一个空格,并保持命令在一行上。对于非常长的安装指令,可能会发生行包装。

你不需要以任何特定顺序列出软件包,请求将以与原始配方完全相同的方式处理,并且在列出交易摘要后,它将保持待定状态,直到确认或拒绝。再次使用Y键确认你的请求,以便完成该过程。

使用 YUM 删除软件包

在这个食谱中,我们将探讨使用 YUM 的目的,即从你的服务器上移除软件包。在你的服务器生命周期中,某些应用程序和服务可能不再需要。在这种情况下,通常你会想要移除这些软件包以优化你的工作环境,而这个食谱的目的就是向你展示如何做到这一点。

准备工作

要完成这个食谱,你需要一个安装了 CentOS 7 操作系统的工作环境,具有 root 权限,选择一个基于控制台的文本编辑器,以及互联网连接。

如何操作...

这个食谱将向你展示如何通过调用yum remove选项来移除一个或多个软件包。为此,你需要以 root 用户身份登录并完成以下过程:

  1. 要移除单个软件包,将package_name替换为适当的值,并输入以下内容:

    yum remove package_name
    
    
  2. 等待交易摘要和确认提示显示,然后按Y键确认,或按N键拒绝交易,如下所示:

    Is this ok [y/d/N]: y
    
    
  3. 如果你拒绝了交易,那么不需要进一步的工作,你将退出 YUM。然而,如果你确认了交易,那么只需观察软件包移除的进度,直到它被确认并打印出Complete!消息。

它是如何工作的...

不再需要的应用程序可以通过 YUM 移除。这个过程非常直观,类似于安装新软件包,只需要你确认要移除的软件包名称。

那么,我们从这次经历中学到了什么?

调用了remove命令后,YUM 将在你的系统中搜索相关软件包;通过阅读软件包头和元数据,它还将确定这将影响哪些依赖项。例如,如果我们想移除名为wget的软件包,我们将开始发出remove命令,如下所示:yum remove wget。然后,YUM 将从你的系统中找到软件包详细信息,并获取一个交易摘要,其中可能包括任何不再需要的必要依赖项。打印出的交易将保持待定状态,直到你指示 YUM 移除相关软件包。确认后,YUM 将完成交易,这将导致移除软件包或软件包。如果摘要提到任何依赖项,你应该格外小心,因为这些可能被其他 RPM 所需。如果你担心某些依赖项应该保留在系统上,通常一个好的做法是结束当前交易,并简单地停用或禁用相关软件。与install命令一样,你也可以一次移除多个软件包,软件包名称之间留一个空格:

yum remove package_name1 package_name2 package_name3

保持 YUM 的整洁

在这个步骤中,我们将调查 YUM 在确保工作缓存保持最新方面的作用。作为其典型操作模式的一部分,YUM 将创建一个由元数据和软件包组成的缓存。这些文件非常有用,但随着时间的推移,它们会积累到一定程度,你可能会发现 YUM 行为异常或不如预期。这种情况发生的频率因系统而异,但通常意味着 YUM 缓存系统需要你立即关注。这种情况可能会非常令人沮丧,但这个步骤的目的是提供一个快速解决方案,帮助你清理缓存并将 YUM 恢复到原始工作状态。

准备就绪

要完成这个步骤,你需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,一个你选择的基于控制台的文本编辑器,以及一个互联网连接,以便于下载额外的软件包。

如何操作...

在我们开始之前,重要的是要意识到,虽然我们正在解决当前的问题,但这个相同的步骤可以按需运行,以保持 YUM 处于最佳工作状态:

  1. 我们将从这个步骤开始,让 YUM 清理任何缓存的软件包信息。为此,以 root 身份登录并输入以下内容:

    yum clean packages
    
    
  2. 允许系统响应一段时间,完成后,输入以下命令以删除任何缓存的基于 XML 的元数据:

    yum clean metadata
    
    
  3. 再次等待 YUM 响应,准备就绪后,输入以下命令以删除任何缓存的数据库文件:

    yum clean dbcache
    
    
  4. 接下来,你需要清理所有文件以确认前面的指令,并确保不使用不必要的磁盘空间。为此,输入以下行:

    yum clean all
    
    
  5. 最后,你需要通过输入以下内容来重建 YUM 缓存:

    yum makecache
    
    

它是如何工作的...

YUM 是一个非常强大的工具,以其解决软件包依赖关系和自动化软件包管理过程的能力而闻名,但正如所有事物一样,有时即使是最好的工具也会感到困惑,可能会报告错误或行为异常。解决这个问题相对简单,本步骤中概述的方法也将有助于保持你的软件包管理器在你的操作系统生命周期内保持健康运行状态。

那么,我们从这次经历中学到了什么?

在 YUM 的典型运行过程中,它会在/var/cache/yum位置创建一个元数据和包的缓存。这些文件至关重要,但随着它们的大小增长,这个缓存最终会减慢该工具的整体使用速度,甚至可能导致一些问题。为了解决这个问题,我们首先使用以下命令清理当前基于包的缓存,使用 YUM 的clean packages参数选项。然后,我们通过执行clean metadata命令清理元数据缓存,这将删除任何多余的基于 XML 的文件。YUM 在其正常操作中使用 SQLite 数据库,因此下一步是使用clean dbcache参数删除任何剩余的数据库文件。接下来,我们清理所有与启用仓库相关的文件,以回收任何未使用的磁盘空间:yum clean all。最后,我们通过使用makecache选项重建缓存,将 YUM 恢复到正常工作状态。

还有更多...

在典型的服务器上,YUM 是一个出色的工具,它将解决与包依赖关系和包管理相关的最复杂问题。然而,在明知混合了不兼容的仓库或使用了不完整的源的情况下,YUM 可能无法提供帮助。

注意

记住,在这种情况下,你应该将以下建议视为仅是临时补救措施。忽视 YUM 提供的任何警告只会导致将来出现更大的问题。

如果发生这种情况,并且错误是基于 RPM 的,作为临时修复,你可以使用以下命令跳过损坏的包:

yum -y update --skip-broken

这个命令将允许 YUM 继续工作,绕过任何有错误的包,但正如前面所述,这应该被视为仅是临时修复。你应该始终意识到,一个依赖关系损坏的系统不被认为是一个健康的系统。这种情况应该不惜一切代价避免,在这种情况下,修复此类错误应该成为你的首要任务。

了解你的优先级

在本食谱中,我们将探讨准备 YUM 管理额外仓库的任务,通过安装一个名为YUM priorities的插件。YUM 有能力从各种远程位置搜索、删除、安装、检索和更新包。这些功能使 YUM 成为一个强大的工具,但如果你决定添加额外的第三方仓库,有可能冲突会导致系统不稳定。稳定性是使用 CentOS 操作系统的众多优势之一,本食谱的目的是展示如何在同时允许添加新仓库的情况下保持这种信心。

准备就绪

要完成这个食谱,你需要一个具有 root 权限的 CentOS 7 操作系统的正常安装,一个基于控制台的文本编辑器,以及一个互联网连接,以便下载额外的包。

如何做...

本食谱将向您展示如何准备 YUM,以便通过安装和配置 YUM 优先级来管理使用一个或多个第三方仓库的过程:

  1. 要开始这个食谱,请以 root 身份登录并输入以下内容:

    yum install yum-plugin-priorities
    
    
  2. 确认安装,完成后输入以下内容:

    vi /etc/yum/pluginconf.d/priorities.conf
    
    
  3. 您应该确保此文件指示插件已启用。它应该显示指令enabled = 1。通常不需要在此文件中进行任何更改,但如果您已进行任何更改,请在继续之前保存并关闭文件。

  4. 现在我们需要为每个仓库建立一个优先级值。这是一个升序的数值,其中最高优先级被赋予最低的数字。为此,按照以下所示打开以下文件:

    vi /etc/yum.repos.d/CentOS-Base.repo
    
    
  5. [base]部分末尾添加以下行:

    priority=1
    
    
  6. 现在,在[updates]部分末尾添加以下行:

    priority=1
    
    
  7. 最后,在[extras]部分末尾添加以下行:

    priority=1
    
    
  8. 完成后,保存并关闭文件,然后运行软件包更新:

    yum update
    
    

它是如何工作的...

YUM 优先级是一个简单的插件,它使 YUM 能够决定在安装和更新新软件包时哪些仓库将具有最高优先级。使用此插件将减少软件包混淆的可能性,确保任何特定软件包始终从同一仓库安装或更新。这样,您可以添加无限数量的仓库,并使 YUM 保持对软件包管理的控制。

那么,我们从这次经历中学到了什么?

通过安装yum-plugin-priorities软件包并确保在其配置文件中启用它,我们简单地增强了 YUM。然后我们发现优先级是按升序设置的,其中最低值优先于所有其他值。当然,这简化了整个过程,因此我们确保默认仓库被赋予值1priority=1)。这将确保默认仓库保持最高优先级,因此当您决定添加其他仓库时,可以为它们分配优先级值 2、3、4…和 10,或更多。另一方面,应该注意的是,我们只在三个主要部分设置了此值:[base][updates][extras]。简单来说,这只是因为其他部分显示为禁用。例如,您可能已经注意到/etc/yum.repos.d/CentOS-Base.repo中的[centosplus]部分包含以下行:enabled=0,而[updates][extras]部分显示此值为enabled=1。当然,如果您打算激活此仓库,则需要为其设置优先级值,但为了本食谱的目的,不需要进行此操作。最后,我们运行了一个简单的 YUM 软件包更新以激活我们的修订设置。

因此,正如我们所见,YUM 优先级是一个极其灵活的软件包,它使您能够确定在扩展安装选项时哪些存储库具有优先权。然而,您应该始终意识到,YUM 优先级可能并不适合您的系统,因为您赋予了它决定哪些软件包将被忽略、哪些软件包将被安装、哪些软件包将被更新以及以何种顺序和从哪个存储库获取它们的权力。对于大多数不倾向于远离典型服务器功能的用户来说,这可能不是立即关注的问题;您甚至可以安全地忽略这个警告。但如果稳定性和安全性是压倒性的关注点,并且您确实打算从外部存储库使用额外的软件包,那么您应该仔细考虑使用此插件,或者至少考虑并研究所使用的第三方存储库的完整性。

使用第三方存储库

在本配方中,我们将探讨充分利用 CentOS 可用软件包的愿望,通过安装 EPEL 和 Remi 存储库。CentOS 是一个以稳定性为傲的企业级操作系统,在您的服务器生命周期中,可能并非您需要的每一件软件都能在默认存储库中找到。您也可能需要当前软件的更新软件包,出于这些原因,许多服务器管理员选择安装 EPEL 和 Remi 存储库。这些不是唯一可用的存储库,但由于它们代表了最受欢迎的组合之一,因此本配方的目的是向您展示如何将 EPEL 和 Remi 存储库添加到您的系统中。

准备工作

要完成这个配方,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便于下载额外软件包的能力。

如何操作...

在我们开始之前,假设您已经遵循了之前的配方,该配方向您展示了如何安装和激活 YUM 优先级。

  1. 首先,以 root 身份登录并使用 YUM 安装 EPEL 发布存储库:

    yum install epel-release
    
    
  2. 接下来,从您的家目录中,键入以下命令以下载remi release rpm软件包:

    curl -O http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
    
    

    注意

    请注意,当您阅读本文时,此 URL 可能已更改;如果是这样,请进行一些互联网研究,以了解是否有新的 URL 可用。

  3. 前面的文件现在应该位于您的家目录中。要继续,请键入以下命令:

    rpm -Uvh remi-release-7.rpm
    
    
  4. 安装完成后,使用您最喜欢的文本编辑器打开 Remi 存储库文件:

    vi /etc/yum.repos.d/remi.repo
    
    
  5. enabled=0更改为enabled=1,并在[remi]部分的末尾添加行priority=10

  6. 现在,使用您最喜欢的文本编辑器打开 EPEL 存储库文件:

    vi /etc/yum.repos.d/epel.repo
    
    
  7. 再次,如果未自动设置,请将enabled=0更改为enabled=1,并在[epel]部分中添加行priority=10

  8. 最后,按照以下方式更新 YUM:

    yum update
    
    
  9. 如果有可用更新,请选择Y继续。完成更新过程后,您现在将能够从 Remi 和 EPEL 存储库下载和安装软件包,作为默认使用的补充。

它是如何工作的...

为了使用和享受第三方存储库的好处,您首先需要使用 YUM 和 RPM 包管理器安装并启用它。

那么,我们从这次经历中学到了什么?

开始执行配方后,安装 Remi 和 EPEL 存储库的任务是一个非常顺畅的过程。虽然使用 YUM 安装 EPEL 存储库非常安全,不会对系统造成影响,但 Remi 存储库的先前 URL 由存储库所有者自行维护,因此您应始终确保它们是最新的。然而,一旦获得了必要的存储库设置文件,接下来就是使用基于 RPM 的命令在系统上安装所有必要的存储库文件。完成这一步后,我们还需要打开每个已安装存储库的相关配置文件并启用它们(通过将enabled=0更改为enabled=1),并设置优先级值(priority=10)。前一个值仅会打开存储库,而后一个值将由 YUM 用于在我们调用update命令时正确识别哪些存储库最为合适。正如在前一个关于 YUM 优先级的配方中所讨论的,一个简单的经验法则是记住这句话:“数字越低,优先级越高。”这本身(取决于您的目的)可能不是一件坏事,但对于本配方的目的,它表明默认的 CentOS 存储库应该优先于所有其他存储库。当然,您可能不同意这一点,并且确实没有任何阻止您将相同的优先级规则应用于第三方供应商,但我确实在您深入之前提醒您,特别是在这是为了关键任务生产服务器的情况下。请记住,如果所有优先级值都相同,那么 YUM 将默认尝试下载最新版本。

将 Remi 和 EPEL 的优先级设置得比现有的基于 CentOS 的仓库更高,是基于考虑安全更新的需要。除非你另有决定,否则始终建议基础文件应首先来自 CentOS。这包括但不限于内核更新、SELinux 及相关软件包。第三方仓库应用于获取无法从原始来源获得的额外软件包,或访问可能不适用于 CentOS 基础版本的特定更新。这可能包括 Apache、MariaDB 或 PHP 等软件包。最后,你可能会注意到 Remi 和 EPEL 仓库共享相同的优先级值。这是有意为之,因为这些仓库通常被视为合作伙伴。然而,如果你决定开始混合使用仓库,或使用此方法作为安装此处未提及的其他仓库的途径,那么你应该始终进行研究,并逐个评估每个第三方仓库。Remi 和 EPEL 仓库非常受欢迎,所以如果你确实打算添加更多第三方资源,请围绕主题进行阅读,谨慎选择你的仓库,并保持忠诚。

还有更多...

CentOS 7 有许多其他有趣的仓库,例如专注于硬件相关软件包的 ELRepo,如文件系统驱动、图形驱动、网络驱动、声音驱动以及摄像头或视频驱动。访问elrepo.org学习如何安装和访问它。

创建 YUM 仓库

如果你在本地网络中维护多个 CentOS 服务器,并希望节省互联网带宽或加快重复下载相同远程仓库软件包的速度,或者处于一个非常受限的网络环境中,你的客户端无法访问任何远程 CentOS 仓库,你可能需要考虑运行自己的 YUM 仓库。拥有自己的仓库也是一个很好的解决方案,如果你想向本地用户推出一些自定义或非官方的 RPM 软件包(例如内部配置文件或程序),或者你只是想创建一个官方 CentOS 7 仓库的镜像站点。在本方法中,我们将向你展示如何设置你自己的第一个 YUM CentOS 7 仓库,以及如何为你的本地网络提供服务。

准备就绪

要完成此配方,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及连接到互联网以方便下载额外软件包。为了使此配方工作,您还需要将 CentOS 7 Everything DVD iso 文件图像放置在服务器的根目录中,如果您还没有下载它,请参考第一章中的第一个配方,安装 CentOS(但下载最新的CentOS-7-x86_64-Everything-XXXX.iso文件而不是最小 iso 文件)。此外,我们需要一个正在运行的 Apache Web 服务器来共享我们的 YUM 仓库到我们的本地网络;请阅读第十二章中的第一个配方,提供 Web 服务,以了解如何设置它。

如何操作...

要创建我们自己的 YUM 仓库,我们需要createrepo程序,该程序在 CentOS 7 上默认未安装。让我们从安装它开始我们的旅程。在本例中,我们将使用 IP 地址192.168.1.7作为我们的 YUM 仓库服务器:

  1. 以 root 身份登录到您的服务器并安装以下软件包:

    yum install createrepo
    
    
  2. 接下来,对于您想要共享的每个仓库,在 Apache Web 根目录下的/var/www/html/repository/下创建一个子文件夹,当 Apache 运行时,该文件夹将公开可用;例如,要共享完整的 CentOS 7 Everything仓库包,您可以使用:

    mkdir -p /var/www/html/repository/centos/7.1
    
    
  3. 现在,将您选择的 RPM 包文件放入此处创建的仓库文件夹中。在我们的示例中,我们将把Everything iso 文件中的所有 RPM 包放入我们新的本地仓库位置,之后我们将把 iso 文件的内容挂载到文件系统上:

    mount ~/CentOS-7-x86_64-Everything-1503-01.iso /mnt/
    cp -r /mnt/Packages/* /var/www/html/repository/centos/7.1/
    
    
  4. 之后,我们需要为复制到 Apache Web 根目录中的所有新文件更新 SELinux 安全上下文:

    restorecon -v -R /var/www/html
    
    
  5. 现在,对于我们想要设置的每个仓库,运行以下命令:

    createrepo --database /var/www/html/repository/centos/7.1
    
    
  6. 恭喜,您现在已经成功创建了您的第一个 YUM 仓库,该仓库可以通过正在运行的 Apache Web 服务器从同一网络中的任何计算机访问。为了测试它,以 root 身份登录到任何其他可以 ping 通我们的仓库服务器的 CentOS 7 系统,并将我们的新仓库添加到其 YUM 仓库配置目录中:

    vi /etc/yum.repos.d/myCentosMirror.repo
    
    
  7. 将以下内容添加到这个空文件中(根据您的需要适当更改baseurl):

    [myCentosMirror]
    name=my CentOS 7.1 mirror
    baseurl=http://192.168.1.7/repository/centos/7.1
    gpgcheck=1
    gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-7
    
    
  8. 保存并关闭文件,然后测试您的新仓库是否可用(它应该出现在列表中)在您的客户端上:

    yum repolist | grep myCentosMirror
    
    
  9. 现在,为了测试我们的新 YUM 仓库,我们可以尝试以下命令:

    yum --disablerepo="*" --enablerepo="myCentosMirror" list available
    
    

它是如何工作的...

在本节中,我们已经向你展示了安装和设置本地 YUM 仓库是多么容易。然而,我们只向你展示了如何创建所有 CentOS 7 Everything iso RPM 包的镜像站点,但你可以重复此过程来创建你想要与你的网络共享的任何类型的包的 YUM 仓库。

那么,我们从这次经历中学到了什么?

设置自己的 YUM 仓库只需安装createrepo包,并将你想要共享的所有 RPM 包复制到 Apache 文档根目录下的一个子文件夹中(在我们的例子中,我们需要挂载 CentOS 7 Everything iso 文件到文件系统,以便访问我们想要共享的包含的 RPM 包文件)。由于 Apache 的文档根目录受 SELinux 控制,之后我们需要将该目录中新 RPM 文件的安全上下文设置为httpd_sys_content_t类型标签;否则,通过 Web 服务器将无法访问。最后,我们需要在我们的新仓库文件夹上运行createrepo命令,这将创建我们新仓库所需的元数据,以便任何想要连接到仓库的 YUM 客户端稍后可以对其进行查询。

随后,为了测试我们的新仓库,我们在另一台想要使用这项新服务的 CentOS 7 系统上创建了一个新的仓库定义文件,该系统必须与我们的 YUM 仓库服务器处于同一网络中。在这个自定义的.repo配置文件中,我们设置了正确的仓库 URL 路径,启用了gpg检查,并采用了标准的 CentOS 7 gpgkey,以便我们的 YUM 客户端能够验证官方仓库包的有效性。最后,我们使用带有--disablerepo="*"--enablerepo="myCentosMirror"参数的yum命令,这将确保只使用我们的新自定义仓库作为源。你可以将这两个参数与任何其他yum命令(如installsearchinfolist等)结合使用。这只是为了测试;如果你想要将你的新仓库与现有的仓库结合使用,请使用 YUM 优先级(如本章另一节中所述)。

还有更多...

现在,在我们向我们的网络宣布新的集中式 YUM 仓库之前,我们应该首先更新自 CentOS Everything iso 发布以来已更改的所有 RPM 包。为此,请访问www.centos.org并选择一个rsync://镜像链接,该链接地理位置上靠近您当前的位置。例如,如果您位于德国,一个选项可能是rsync://ftp.hosteurope.de/centos/(有关导航 CentOS 网站的更详细说明,请阅读第一章-version number (1.4.6)-release(1)-CPU architecture (x86_64)


接下来,我们使用 RPM 包管理器安装了下载的`pv`包,该管理器可以通过命令行上的`rpm`命令执行。我们使用了带有`-Uvh`命令参数的`rpm`命令,以及下载的包 rpm 文件的完整名称。

### 注意

如果使用 rpm 命令安装或升级 rpm 软件包,您应该始终使用`-Uvh`,但有一个例外;即内核包。`-U`会在更新时删除旧包,如果您安装新内核,这不是您想要的。请改用`-i`(用于安装),因为这将保留旧内核文件,以便在遇到问题时可以回退到较早的版本。

`-U`是安装或升级包的参数。如果系统上未安装该包,它将被安装;否则,如果 RPM 包版本比已安装的版本新,`rpm`将尝试升级它。`-v`参数打印更详细的输出,而`-h`显示一个漂亮的进度条。如果您在系统上未启用 EPEL 仓库的情况下安装`pv`包,将收到以下警告消息:

pv-1.6.0-1.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 3fc56f51: NOKEY


RPM 在安装前会自动检查包的签名有效性,以确保包的内容自签名后未被篡改。同时,它还会检查 RPM 包的可信度,因为应该由官方第三方权威供应商使用加密密钥进行签名。您可以忽略此消息,因为 EPEL 仓库的包来自安全源。要永久信任 EPEL 源,您可以使用以下命令在系统上安装其`gpg`公钥,从而消除所有未来的签名警告消息:

rpm --import https://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-7


成功安装包后,我们现在拥有一个名为`pv`的漂亮命令行工具,它可以显示通过 Unix 管道的数据进度,如果您通过管道传输大量数据,这可能会很有用,因为您通常永远不会知道当前的进度状态。之后,我们查询了存储有关 CentOS 7 系统上所有已安装包信息的 RPM 数据库,使用带有`-q`标志的`rpm`命令。在处理 RPM 数据库时,我们必须使用真实的包名(`pv`)而不是安装包时使用的文件名(`pv-1.4.6-1.x86_64.rpm`)。在卸载已安装的包时也是如此;请指定包名,而不是版本号或完整文件名。

要获取有关已安装包`pv`的详细信息,我们使用了`-qi`(`i`表示信息),并使用`-ql`参数;我们显示了包中所有文件的完整文件名和路径。`-qd`显示了包中包含文档的所有文件。要了解更多的查询选项,请键入`man rpm`并查看`PACKAGE QUERY OPTIONS`部分。

总之,我们可以说,在系统管理员的生活中,有时需要安装一个不是通过官方仓库分发的软件(例如,非开源、前沿程序或测试版、有许可证不允许将其放入仓库的软件,如 Java,或来自独立开发者的软件),这时需要下载单独的 RPM 包并手动安装它们。在幕后,YUM 也依赖并使用 RPM 包管理器,因此你也可以使用 YUM 程序来安装 rpm 文件(`yum install <filename.rpm>`)。然而,当涉及到查询你下载的 rpm 文件或系统上已安装的包时,有时使用较旧的`rpm`命令而不必安装额外的基于 YUM 的软件(如`yum-utils`)会更好。

RPM 的最大弱点是它不支持仓库,并且缺少依赖管理系统。如果你仅使用 RPM 在 CentOS 系统上安装所有软件,你很容易遇到包依赖问题,因为你无法安装特定的包,因为它依赖于其他一些包。通常,当你尝试安装依赖的包时,你需要它们依赖的其他包,如此类推。这可能是一项非常繁琐的工作,应该始终通过使用 YUM 来避免。

## 还有更多...

`rpm`命令不仅可以用于查询 rpm 数据库中关于已安装包的信息,还可以用于查询你下载的 rpm 文件。例如,使用`-qlp`参数来显示本地`rpm`包文件中的所有文件:

rpm -qlp ~/pv-1.4.6-1.el7.x86_64.rpm


要从`rpm`文件中获取关于包的详细信息,使用`-qip`参数,如下所示:

rpm -qip ~/pv-1.4.6-1.el7.x86_64.rpm


如果你想安装一个本地下载的 RPM 包,并且该包有依赖关系,你可以使用`yum localinstall`命令。一旦提供了包的文件名,该命令将安装本地包,并尝试从远程源解决所有依赖关系,例如:

wget http://location/to/a/rpm/package_name.rpm
yum localinstall package_name.rpm



# 第五章:管理文件系统

在本章中,我们将涵盖以下主题:

+   创建虚拟块设备

+   格式化和挂载文件系统

+   使用磁盘配额

+   维护文件系统

+   扩展文件系统的容量

# 简介

本章是一系列步骤的集合,旨在满足驱动基于 CentOS 的服务器解决方案的需求。从格式化和挂载磁盘到扩展逻辑卷以及维护文件系统和磁盘配额,本章的目的是向你展示如何快速轻松地掌握管理当今最苛刻环境中用户需求任务的技能。

# 创建虚拟块设备

在本步骤中,我们将创建一个虚拟块设备,用于模拟真实设备和分区,以便我们可以在本章后续的所有步骤中测试驱动概念和命令。使用真实磁盘和分区通常涉及丢失重要数据甚至需要重新安装整个系统的风险。虚拟块设备是学习技术和尝试操作的理想选择,然后再切换到“生产模式”。稍后,如果你获得了足够的经验并感到安全,你可以轻松地将其替换为“真实”硬件设备、分区以及逻辑卷(这是 LVM 的一部分;请参阅后面的步骤)。你所需要做的就是将你的虚拟设备替换为“真实”块设备名称。

## 准备工作

要完成这个步骤,你需要一个具有 root 访问权限的 CentOS 7 操作系统的最小安装。为了创建一个虚拟块设备,你应该至少有一 GB 的可用硬盘空间,我们将暂时使用这些空间来创建和制作。你可以在之后删除这部分预留空间(或者在重启后它会自动删除)。这只是为了测试。

## 如何操作...

1.  首先,以`root`身份登录并创建一个精确大小为 1GB 的空文件:

    ```
    dd if=/dev/zero of=/tmp/test-image.dd bs=1M count=1000

    ```

1.  现在,让我们从刚刚创建的文件中创建一个循环设备:

    ```
    losetup -fP  /tmp/test-image.dd

    ```

1.  接下来,打印生成的循环设备名称:

    ```
    losetup -a

    ```

1.  由于这将是当前系统中创建的第一个循环设备,输出将如下所示(如果你之前创建了循环设备,`loop0`可能是一个不同的数字):

    ```
    /dev/loop0: [0035]:3714186 (/tmp/test-image.dd)

    ```

1.  要获取当前系统上所有已附加的块设备的列表以及重要详细信息,请键入以下内容:

    ```
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL

    ```

1.  现在,让我们在我们的新循环设备上创建一个类型为`gpt`的新分区表(确认删除任何数据):

    ```
    parted /dev/loop0 mklabel gpt

    ```

1.  最后,从你的循环设备创建设备映射,使其更类似于真实的硬盘分区:

    ```
    kpartx -a /dev/loop0

    ```

## 它是如何工作的...

在本步骤中,我们学习了如何创建一个虚拟块设备,作为测试如何在本章后续步骤中创建分区、逻辑卷和文件系统的起点。

那么,我们从这次经历中学到了什么?

我们通过使用`dd`工具在`/tmp`目录中创建一个大小为 1GB 的新空文件来开始这个操作。`dd`用于制作文件的精确副本(有时称为克隆),并期望两个参数:输入文件(`if`参数)和输出文件(`of`参数)。我们使用`zero`设备(`/dev/zero`)作为输入文件,它返回一个包含零的无尽字节流。然后,我们通过定义块大小(`bs`)和`count`参数来限制流。`bs`定义了一次读取的数据量(以字节为单位),而`count`参数计算`bs`将允许重复多少次。因此,这些参数可以被理解为*当达到块大小乘以计数的数据量时停止复制过程*。在我们的示例中,我们使用了`1`*兆字节乘以 1000 = 1GB*的块大小。这些零字节数据被写入到我们的输出文件(`of`),称为`/tmp/test-image.dd`。

在我们创建了这个空文件之后,我们用它创建了一个临时的**循环**设备。循环设备只是一个伪设备,它使得可以将文件用作**块设备**。通常,这样的文件是一个 CD ISO 镜像,将其用作循环设备将使其可访问,就像它是一个正常的硬件驱动器一样。任何允许以块为单位读写数据的设备都可以称为块设备;为了获取系统中所有可用块设备的列表,我们使用了`lsblk`命令,正如您所见,这也包括我们的循环设备。标准的循环设备名称以数字零开头,例如`/dev/loop0`。

之后,我们使用`parted`命令在我们的循环设备上创建了一个新的**分区表**。分区表是操作系统在磁盘上维护的一个表,描述了磁盘上的分区,我们必须先创建分区表,然后才能创建分区。我们使用了分区表类型`gpt`,但您也可以在这里使用旧的 msdos 类型。

通常,在虚拟块设备上创建分区表时,我们无法访问单个分区或为其上的不同分区创建文件系统,因为分区不能单独寻址。在这里,我们使用`kpartx`命令从分区表创建设备映射,这允许我们稍后使用表示法`/dev/loop0p1`访问循环设备 0 上的分区 1,以及`/dev/loop0p2`访问循环设备 0 上的分区 2,以便为单个分区创建文件系统。

恭喜,您现在已经创建了一个带有标准分区表的新虚拟块设备,它可以像普通磁盘设备一样被使用和访问。

## 还有更多...

如果我们想要移除一个虚拟块设备,首先需要将其从文件系统中卸载,如果它当前已挂载(例如,`umount /dev/loop0p1`)。接下来,我们需要使用`-d`参数将虚拟块设备文件从循环设备中分离,如下所示:`losetup -d /dev/loop0`。之后,如果我们愿意,可以删除块文件:`rm /tmp/test-image.dd`。

# 格式化和挂载文件系统

在本食谱中,您将了解标准 CentOS 文件系统**XFS**、**Ext4**和**Btrfs**。文件系统是任何操作系统最基本的部分之一,几乎所有东西都依赖于它们。在这里,您将学习如何在 CentOS 7 中创建不同类型的标准文件系统,以及如何将它们链接到您的系统,以便我们随后可以访问它们进行读写。这两种技术被称为**格式化**和**挂载**文件系统;虽然您不经常这样做,但它仍然是 Linux 系统管理员最基本的任务之一。

## 准备就绪

要完成此食谱,您需要具备具有 root 访问权限的 CentOS 7 操作系统的最小安装。我们还将使用虚拟块设备而不是实际磁盘设备,因为使用“虚拟”设备演示创建文件系统和格式化磁盘的使用情况比擦除实际硬盘内容更好。因此,您应该已经应用了*创建虚拟块设备*食谱,并创建了一个 1GB 的虚拟块设备,在本例中将被命名为`/dev/loop0`。

如果您想将此方法应用于实际磁盘设备,您只需将`/dev/loop0`替换为正确的分区——例如,对于逻辑卷(lv),如`/dev/mapper/myServer/data`,对于 SATA 设备,如`/dev/sdX`,或对于基于 IDE 的硬盘名称,如`/dev/hdX`(其中`X`是字符`a-z`)。

## 如何操作...

在我们的示例中,此块设备被标记为`/dev/loop0`。请注意,如果您创建了多个块设备,您的编号可能会有所不同,因此请相应地更改名称:

1.  首先,让我们以`root`身份登录并显示所有当前可用的块设备的信息:

    ```
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL

    ```

1.  现在,重新检查我们是否在设备上安装了有效的分区表:

    ```
    parted /dev/loop0 print

    ```

1.  前面的行应该打印出以下内容:`Partition Table: gpt`。如果不是这种情况,让我们创建一个新的分区表(确认删除任何数据):

    ```
    parted /dev/loop0 mklabel gpt

    ```

1.  现在,我们将创建一个覆盖整个磁盘空间的新分区,并使用`ext4`文件系统标签(尚未安装文件系统;它只是一个标签):

    ```
    parted -a optimal /dev/loop0 mkpart primary ext4 2048KiB 100%

    ```

1.  再次打印分区表以显示我们刚刚创建的新分区:

    ```
    parted /dev/loop0 print

    ```

1.  现在,让我们删除分区:

    ```
    parted /dev/loop0 rm 1

    ```

1.  我们还可以创建一个带有 btrfs 标签的分区:

    ```
    parted -a optimal /dev/loop0 unit MB mkpart primary btrfs 2048KiB 100%

    ```

1.  之后,让我们创建一个覆盖整个磁盘的 XFS 标签分区:

    ```
    parted /dev/loop0 rm 1
    parted -a optimal /dev/loop0 mkpart primary xfs 2048KiB 100%

    ```

1.  现在,再次显示块表以查看我们更改了什么:

    ```
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL

    ```

1.  由于我们只定义了分区类型*标签*,我们仍然没有在分区上安装有效的文件系统;因此,在下一步中,我们使用正确的类型格式化磁盘。在我们的示例中,我们使用 XFS。请根据需要更改`mkfs -t <type>`,如果您使用`ext4`或`btrfs`:

    ```
    mkfs -t xfs /dev/loop0p1

    ```

1.  接下来,让我们将虚拟块设备分区挂载到系统上,挂载到目录`/media/vbd-1`,并请根据需要更改`-t <type>`,如果您使用`ext4`或`btrfs`:

    ```
    mkdir /media/vbd-1
    mount -t xfs /dev/loop0p1  /media/vbd-1

    ```

1.  最后,测试我们是否可以对新文件系统进行读写:

    ```
    echo "this is a test" > /media/vbd-1/testfile.txt
    cat /media/vbd-1/testfile.txt

    ```

## 它是如何工作的…

在这个过程中,我们向用户展示了如何创建 CentOS 7 标准分区,覆盖整个磁盘,然后我们在这些分区上创建了一些文件系统,这称为格式化,使用了不同的文件系统类型。CentOS 7 中的标准文件系统是 XFS,但正如我们在本过程中所学到的,还有许多其他可用的文件系统,包括流行的 ext4 和 btrfs。XFS 是一种非常健壮且高性能的文件系统,适用于大型存储配置;它被认为非常成熟和稳定。在 CentOS 7 之前,标准文件系统是 ext4,但它有一些限制,并且在处理数百万个文件时性能不佳,被认为勉强适合当今非常大的文件系统。btrfs 是一个相对较新的文件系统,包含在 CentOS 7 中,但在撰写本文时仍处于开发阶段,不应在生产系统中使用。预计在后续的 CentOS 7 小版本中将得到全面支持,并有可能在未来取代 XFS 成为 CentOS 的标准文件系统类型,因为它具有一系列非常有前景的特性和增强功能,例如写时复制,每次写入文件时都会复制文件,这使得能够回溯到以前的文件版本。

那么,我们从这次经历中学到了什么?

我们通过使用`lsblk`命令开始这个过程,该命令用于打印系统上当前连接的所有可用块设备的列表。我们使用这个命令来检查我们想要用于安装分区和文件系统的目标块设备是否可用。在我们的例子中,我们将使用`/dev/loop0`设备,如果您的系统上名称不同,请更改此名称(如前所述,您也可以使用“真实”磁盘块设备,例如`/dev/sda`,但始终要小心!)。确认设备准备就绪后,我们使用`parted`命令检查磁盘的分区表。分区表对于任何硬盘都是必需的,以便跟踪其上的分区信息。如您所见,我们创建分区表和分区的首选工具是*parted*,因为它是 CentOS 7 官方推荐的工具,但也有其他程序可以执行相同任务,例如`fdisk`或`gdisk`。如果没有可用的分区表,我们必须使用 parted 的`mklabel gpt`参数创建一个类型为`gpt`的分区表。

接下来,在我们创建了分区表之后,我们在其上放置了一些分区。因此,我们使用 parted 的`mkpart`命令,并带有`-a optimal primary ext4 2048KiB 100%`选项。

### 注意

始终小心使用`parted`命令,并在执行前仔细检查所有内容,因为其大多数命令都会彻底销毁磁盘上当前存储的所有数据。

这将创建一个新的分区,从 2,048 千字节(kb)开始直到磁盘末端。我们没有从磁盘的最开始(0%)开始,因为 2,048 kb 是磁盘上第一个扇区的开始,留下一些空间来存储一些额外的数据。`-a optimal`将分区对齐到物理块大小的倍数,这将保证最佳性能。接下来,我们使用`rm`选项和数字`1`删除了分区,这指的是我们刚刚创建的第一个分区。我们重新创建了类型为`btrfs`和最终`xfs`的新分区。在磁盘分区之后,我们需要在其上创建一个实际的文件系统,因为 parted 仅将分区标记为特定类型,但并不进行实际的格式化。为了创建文件系统,我们使用`mkfs`工具。你可以使用`-t`标志运行它,就像我们所做的那样,或者使用点表示法,例如`mkfs.xfs`,来指定你想要格式化的类型。`mkfs`命令为我们提供了详细的输出,例如已经写入了多少块等等。

最后,在我们为磁盘分区创建了文件系统之后,我们可以使用`mount`命令使其可用并在当前系统中工作。`mount`要么将设备的文件系统附加到我们系统的根文件系统,要么将其分离。因此,我们需要首先创建一个目录来定义我们想要将其附加到哪里。我们使用目录`/media/vbd-1`作为实际`mount`命令的参数,语法为`mount -t <文件系统类型> <设备> <目录>`。对于几乎所有标准文件系统,你可以跳过`-t`参数,因为它会自动检测正确的类型。要从系统中分离文件系统,你可以使用`umount`命令,参数是你想要移除的设备(你也可以使用它所挂载的文件夹;两者都有效!)。在我们的例子中,要卸载我们的循环设备的第一分区,请输入`umount /dev/loop0p1`。

在挂载我们格式化的分区设备之后,我们可以像访问根目录下的任何其他组件一样访问它。

## 还有更多...

在本食谱中,我们总是使用一个分区覆盖整个可用磁盘空间。通常,你会在一个磁盘上有多个分区,所以让我们创建这种布局。在这个例子中,我们在`/dev/loop0`上创建三个 100 MB 的分区:

1.  首先,让我们再次使用`rm`参数删除我们的分区,以便我们可以添加新的分区:

    ```
    parted /dev/loop0 rm 1

    ```

1.  现在,让我们创建三个等分的分区:

    ```
    parted -a optimal /dev/loop0 unit MiB mkpart primary ext4 2048KiB 100
    parted -a optimal /dev/loop0 unit MiB mkpart primary ext4 100 200
    parted -a optimal /dev/loop0 unit MiB mkpart primary ext4 300 400

    ```

1.  让我们回顾一下我们的布局:

    ```
    parted /dev/loop0 print

    ```

    ### 注意

    使用`gpt`分区表,我们可以在任何磁盘上创建多达 128 个主分区;当使用较旧的`msdos`分区类型时,最多有四个主分区。如果你需要更多,你必须从主分区中创建扩展分区。

# 使用磁盘配额

在管理具有多个系统用户的 Linux 多用户系统时,明智的做法是设置某种限制或限制系统共享资源的限制。在文件系统级别,您可以限制可用硬盘空间或总文件数到固定大小,可以是用户、组或目录级别。引入这些规则可以防止人们“滥发”系统,填满其可用空间,并且通常您的用户将更加意识到重要和不重要数据之间的区别,并且更有可能保持其主目录整洁和干净。在本食谱中,我们将向您展示如何为 XFS 文件系统设置**磁盘配额**限制系统,该系统对系统用户帐户允许存储的数据量施加限制。

## 准备就绪

要完成本食谱,您需要具有 root 访问权限的 CentOS 7 操作系统的最小安装和您选择的基于控制台的文本编辑器。为了使本食谱工作,并且为了设置配额,您至少需要一个系统用户帐户,除了您的 root 帐户;如果您还没有一个,请参阅第三章,*管理用户和他们的组*,了解如何创建一个。此外,在本食谱的主要部分中,假设您的 CentOS 7 使用 XFS 文件系统,这是安装时的标准。最后,您的 CentOS 7 安装需要安装在至少 64 GB 空间的磁盘上,否则安装程序不会创建单独的逻辑`/home`卷,这是本食谱中使配额工作的要求。

## 如何做到这一点...

在这里,我们将学习如何为 XFS 文件系统设置配额系统的两种不同方式:首先,设置用户和组的限制,然后设置目录(项目)级别的限制。磁盘配额系统必须在文件系统挂载时设置。

### 启用用户和组配额

1.  首先,以`root`身份登录并打开包含静态挂载信息的`fstab`文件:

    ```
    vi /etc/fstab

    ```

1.  现在,将光标导航到包含`/home`的行(使用*上*和*下*箭头键),并将其移动到单词`defaults`,然后在`defaults`之后添加以下文本,用逗号分隔:

    ```
    ,uquota,gquota

    ```

1.  完整的行将如下所示(您的设备名称将根据您的个人 LVM 名称而不同;在这里,它是`myserver`):

    ```
    /dev/mapper/myserver-home /home  XFS    defaults,uquota,gquota 0 0

    ```

1.  保存并关闭文件,然后重新挂载`/home`分区以激活`quota`指令:

    ```
    umount /home;mount -a

    ```

1.  接下来,为特定用户名为`john`的用户(根据您系统上可用的用户进行适当更改)创建用户配额,限制其总文件大小:

    ```
    xfs_quota -x -c 'limit bsoft=768m bhard=1g john' /home/

    ```

1.  接下来,为另一个用户`joe`可以拥有的总*数量*文件创建用户配额:

    ```
    xfs_quota -x -c 'limit isoft=1000 ihard=5000 joe' /home/

    ```

1.  让我们为`devgrp`用户组中的每个人设置文件数量和大小限制(文件系统组`devgrp`必须存在):

    ```
    xfs_quota -x -c 'limit -g bsoft=5g bhard=6g isoft=10000 ihard=50000 devgrp' /home

    ```

1.  最后,显示`home`卷的整个配额报告:

    ```
    xfs_quota -x -c 'report -bi -h' /home

    ```

### 启用项目(目录)配额

为了启用单个目录的磁盘配额而不是用户或组配额,我们必须将名为 `pquota` 的项目配额指令添加到包含该目录的卷中。由于我们将使用名为 `/srv/data` 的目录进行项目配额,我们需要将完整的底层 `/` 根分区置于配额控制之下。对于根分区,我们必须设置内核引导选项的配额标志:

1.  首先,在备份该文件后,以 root 身份打开以下文件:

    ```
    cp /etc/default/grub /etc/default/grub.BAK
    vi /etc/default/grub

    ```

1.  在行尾(在它之前添加一个空格字符)以 `GRUB_CMDLINE_LINUX=` 开头,在结束的双引号之前,添加 `rootflags=pquota` 指令,如下所示:

    ```
    GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap crashkernel=auto rhgb quiet rootflags=pquota"

    ```

1.  保存并关闭文件,然后使用我们的新引导选项重建 `grub` 配置:

    ```
    grub2-mkconfig -o /boot/grub2/grub.cfg

    ```

1.  现在,在你的 `/etc/fstab` 中为根卷添加 `pquota` 标志:

    ```
    vi /etc/fstab

    ```

1.  将光标导航到包含根挂载点 / 的行,并将其移动到单词 `defaults`,然后添加以下文本,用逗号分隔:

    ```
    ,prjquota

    ```

1.  完整的行将类似于以下内容:

    ```
    /dev/mapper/myserver-root /         XFS    defaults,prjquota 0 0

    ```

1.  接下来,重启计算机以将更改应用到 `root` 卷:

    ```
    reboot

    ```

1.  重启后,确保 `root` 卷已启用项目配额,该配额在卷选项中定义为 `prjquota` 标志(否则,如果设置错误且不起作用,它将显示为 `noquota`):

    ```
    cat /etc/mtab  | grep root

    ```

1.  接下来,让我们创建我们想要设置配额的目标文件夹:

    ```
    mkdir /srv/data

    ```

1.  我们需要添加一个项目名称和一个关联的新唯一 ID:

    ```
    echo "myProject:1400" >> /etc/projid

    ```

1.  现在,定义 `/srv/data` 将使用我们项目 ID 的配额规则:

    ```
    echo "1400:/srv/data" >> /etc/projects

    ```

1.  接下来,为 `root` 卷初始化 `project` 配额:

    ```
    xfs_quota -xc 'project -s myProject' /

    ```

1.  最后,应用以下规则来创建特定的目录限制:

    ```
    xfs_quota -x -c 'limit -p bsoft=1000m bhard=1200m myProject' /

    ```

1.  打印出我们为这个设备设定的配额规则:

    ```
    xfs_quota -x -c 'report -bi -h' /

    ```

## 它是如何工作的...

在本教程中,你学会了在用户、组或目录(项目)级别设置配额系统是多么容易。此外,你还了解到有两种基本方式来定义配额:要么对 *总文件大小*(称为块)施加限制,要么对 *文件数量*(称为 inode)设置限制。

那么,我们从这次经历中学到了什么?

我们从这个配方开始设置用户和组配额。正如你所见,通过在`/etc/fstab`文件中选择的分区添加相关的指令,可以轻松启用配额系统。因此,我们从这个文件开始,为 XFS 用户和组配额向我们的`/home`分区添加了特殊的配额关键词。为了应用这些更改,我们不得不使用`mount`命令重新挂载文件系统。由于配额系统已成功启动,我们使用`xfs_quota -x -c`命令行在我们的启用文件系统`/home`上设置了一些配额限制。`-x`启用专家模式,而`-c`允许我们在命令行上运行命令作为参数。当运行`xfs_quota`而不带`-c`选项时,你将进入一个交互式提示。首先,我们为用户`john`和`joe`设置了某些用户限制。我们通过定义以下参数及其数字来实现这一点:`bsoft`,`bhard`,`isoft`,`ihard`。如你所见,对于文件大小(**块**)和文件数量(**索引节点**)都有软限制和硬限制。块配额可以以典型的度量单位给出,如千字节(`k`),兆字节(`m`)和千兆字节(`g`),而索引节点是一个数字。软限制是一个阈值,当超过时,会在命令行上打印出警告消息,而硬限制将阻止用户在配额保护下的文件系统中添加更多数据或文件。之后,我们设置了一个基于组的配额。如果你使用`-g`标志,限制将为一个组而不是用户定义。根据用户应被允许拥有的文件数量或总文件大小,将用户分成不同的组,使用组规则可能非常有帮助。最后,我们为所有当前配额限制生成了一个报告。我们使用的命令是`'report -bi -h'`,它为已使用的文件空间(`-b`表示块)和总文件数量(`-i`表示索引节点)生成报告。`-h`指定我们希望输出以兆字节或千兆字节为单位,便于人类阅读。

为了测试配额是否有效,让我们为用户`jack`创建以下块和索引节点配额:

xfs_quota -x -c 'limit bhard=20m jack' /home/
xfs_quota -x -c 'limit ihard=1000 jack' /home/


以用户`jack`的身份登录(`su - jack`)并运行以下命令:

dd if=/dev/urandom of=~/test.dd bs=1M count=21


通过此命令,用户`john`将尝试创建一个 21 兆字节大小的文件,但在开始写入第二十兆字节时,将出现以下错误消息:

dd: error writing '/home/jack/test.dd': Disk quota exceeded


现在,删除`~/test.dd`文件,以便我们可以开始另一个测试。如果你超过了文件数量限制,同样的情况也会发生。通过尝试创建 2000 个多文件来测试以下配额限制,而配额限制为 1000;通过添加大量新文件来实现这一点:`for i in {1..2000}; do touch ~/test$i.txt; done`。这将导致以下错误消息:

touch: cannot touch '/home/jack/test1001.txt': Disk quota exceeded


要暂时关闭特定文件系统的用户和组配额检查,可以以`root`用户身份运行`xfs_quota -x -c 'off -u -g' /home/`(`-u`代表用户,`-g`代表组)。这只是一时的;要重新启用它,需要重新挂载感兴趣的文件系统,即`umount /home;mount -a`。要删除特定的配额规则,只需将其限制设置为零,例如:

xfs_quota -x -c 'limit bhard=0 john' /home


接下来,我们在*目录*级别而不是用户/组级别设置配额。这是 XFS 文件系统独有的功能;所有其他文件系统只能在磁盘或分区级别设置配额。如果您不想为特权用户或组设置配额限制,则能够控制目录层次结构的磁盘使用量非常有用。要激活目录配额,我们首先必须将其作为内核引导选项启用,因为默认情况下,根卷被标记为`noquota`。此外,我们在`/etc/fstab`中为根分区添加了`prjquota`指令以使其生效。如果您想了解更多关于内核引导选项的信息,请阅读第一章中的引导加载程序配方,*安装 CentOS*。要为根分区设置文件系统标志,我们需要重新启动系统。完成此操作后,我们通过查看`mtab`文件确保已成功设置引导选项,该文件列出了所有当前挂载的文件系统。接下来,我们在`/etc/projid`文件中设置了一个具有关联唯一项目 ID(我们随机选择`1400`)的项目名称。在下一步中,我们将此新项目 ID(`1400`)应用于`/etc/projects`文件中的目录`/srv/data`。该系统允许将特定的项目配额规则应用于许多不同的目录。之后,我们使用`xfs_quota`命令的`project`选项为根分区初始化项目配额,并为该项目名称创建了一个`limit`配额规则。在`/etc/projects`文件中定义的与相应项目 ID 对应的目录都会受到此规则的影响。这种类型的系统可用于精细的多文件夹配额规则。对于每个目录,您可以设置一个新的项目名称或重用特定的名称,使该系统非常灵活。

在本例中,我们为项目名称`myProject`设置了 1200 兆字节的块大小硬限制。要测试此配额,请输入以下内容:

dd if=/dev/zero of=/srv/data/dd.img bs=1M count=1201


使用以下命令行错误消息,应该可以在写入 1200 兆字节后准确停止`dd`:

dd: error writing '/srv/data/dd.img': No space left on device


## 还有更多...

顾名思义,本例中所示的`xfs_quota`程序仅适用于 XFS 文件系统。如果您想为其他文件系统(如 ext4 或 btrfs)在用户或组级别使用磁盘配额,则必须安装`quota`软件包(`yum install quota`)。设置配额的方式与本例中所示的步骤类似;请阅读手册`man quota`以开始使用。

# 维护文件系统

在本教程中,我们将学习如何检查和可选地修复 CentOS 7 文件系统的完整性。文件系统不一致是罕见的事件,文件系统检查通常在启动时自动运行。但是,系统管理员也应该知道如何手动运行这些测试,如果他们认为文件系统存在问题。

## 准备工作

要完成本教程,你需要一个具有 root 权限的 CentOS 7 操作系统的正常安装。我们将使用虚拟块设备而不是真实磁盘设备,因为我们*不能*在*已挂载*的磁盘上应用任何文件系统检查。因此,你应该已经应用了*格式化和挂载文件系统*教程,并创建了一个 1GB 的虚拟块设备,有两个分区,每个分区大小为总大小的一半:首先是一个带有 XFS 的分区,然后是另一个带有 ext4 文件系统的分区。在本例中,我们将使用名为`/dev/loop0`的虚拟块设备。

如前所述,这些可以很容易地替换为真实的磁盘名称。

## 如何操作...

1.  首先,以`root`身份登录,并显示当前连接到系统的块设备信息:

    ```
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL

    ```

1.  在这里,你应该看到`loop0`设备上有两个分区:`/dev/loop0p1`和`/dev/loop0p2`。如果你看到它们当前被挂载到系统上,请现在卸载它们:

    ```
    umount /dev/loop0p1
    umount /dev/loop0p2

    ```

1.  现在,让我们检查示例中的 loop0p1(适当更改)的 XFS 文件系统:

    ```
    xfs_repair -n /dev/loop0p1

    ```

1.  对于磁盘上的第二个 ext4 分区,我们将使用以下行:

    ```
    fsck -f /dev/loop0p2

    ```

## 工作原理...

在本教程中,我们学习了在 XFS 或 ext4 文件系统上运行文件系统检查是多么简单。你应该学到的最重要的一课是,在运行任何文件系统检查之前,你总是必须*卸载*你的磁盘分区!

那么,我们从这次经历中学到了什么?

由于我们不能在任何已挂载的设备上运行文件系统检查,如果你想检查系统的磁盘和分区,通常你必须在*救援*模式下运行这些检查,其中你的文件系统未挂载(例如,你不能卸载根分区来检查,因为它一直需要由系统使用,而对于单独的 home 分区,这是可能的)。

对于 XFS 文件系统,我们使用`xfs_repair`工具,对于其他所有文件系统,我们将使用带有`-f`参数(强制)的`fsck`程序来检查我们的文件系统。

重要的是要注意,我们总是需要运行`fsck`而不是特定的`fsck.<文件系统类型>`(如`fsck.ext4`,`fsck.btrfs`),因为它会自动检测正确的工具。这是必要的,因为如果你在错误的文件系统上运行错误的特定`fsck.<文件系统类型>`工具(比如在 btrfs 文件系统上运行`fsck.ext4`),它可能会完全破坏它!

## 还有更多...

到目前为止,我们只向你展示了如何使用`xfs_repair`和`fsck`*检查*文件系统。如果在 XFS 文件系统的“检查”运行期间出现错误,请在不使用`-n`选项的情况下运行`xfs_repair`——例如,使用`xfs_repair /dev/loop0p1`。在非 XFS 分区(如 ext4)上,你将使用`fsck`的`-a`选项(`a`代表自动修复)——例如,`fsck -a /dev/loop0p2`。对于`fsck`,如果你有很多错误,最好也使用`-y`,这样你就不必确认每个错误修复。

现在,让我们模拟如果我们使用虚拟块设备获得了一个损坏的 XFS 文件系统会发生什么(*千万不要*在任何真实磁盘分区上这样做!):

1.  首先,将`/dev/loop0p1`分区挂载到你的根文件系统上:

    ```
    mkdir /media/vbd-1
    mount -t xfs /dev/loop0p1  /media/vbd-1

    ```

1.  接下来,在这个挂载的文件系统上创建大量文件——例如,`2000`个文件:

    ```
    for i in {1..2000}; do dd if=/dev/urandom bs=16 count=1 of=/media/vbd-1/file$i; done

    ```

1.  现在,卸载设备并使用`dd`破坏文件系统:

    ```
    umount /dev/loop0p1
    dd bs=512 count=10 seek=100 if=/dev/urandom of=/dev/loop0p1

    ```

1.  现在,运行文件系统检查:

    ```
    xfs_repair -n /dev/loop0p1

    ```

1.  这很可能会向你显示一份损坏文件的列表;为了修复它,请使用以下行:

    ```
    xfs_repair /dev/loop0p1

    ```

你还可以在你的 ext4 虚拟块设备上模拟文件系统损坏,然后使用`fsck -ay /dev/loop0p2`修复它。

# 扩展文件系统的容量

CentOS 7 使用**逻辑卷管理器**(**LVM**)来组织你的分区的结构和可用容量。它是一个非常动态和灵活的系统,可以随着时间的推移进行扩展或重新排列,并且在当今最苛刻和不断变化的环境中是必不可少的。目前,到处都可以听到大数据或云计算这样的流行词。由于不断产生大量数据,存储需求和磁盘空间必须以同样的稳定速度增长,。在这个食谱中,你将学习如何使用 LVM 系统,以及如何扩展你的物理驱动器,以及如何缩小和扩展你的文件系统的容量。

## 准备就绪

要完成这个食谱,你需要一个安装了 CentOS 7 操作系统并具有 root 权限的工作环境。我们将使用虚拟块设备而不是真实磁盘设备,从头开始教你如何设置 LVM,然后如何使用它。请阅读*创建虚拟块设备*食谱,并创建三个 1GB 的虚拟块设备,使用 GPT 分区表,在本例中将被标记为`/dev/loop0`、`/dev/loop1`和`/dev/loop2`。

再次,如果你准备好了,可以自由使用真实磁盘设备。

## 如何做到这一点...

首先,我们将开始创建一个类似于标准 CentOS 7 LVM 结构的 LVM 测试环境,该结构在每个服务器系统的安装过程中设置:

1.  首先,让我们以`root`身份登录并显示有关我们的虚拟块设备的信息:

    ```
    lsblk -io NAME,SIZE

    ```

1.  接下来,在每个三个虚拟块设备上创建跨越整个磁盘的新分区(不带文件系统标签):

    ```
    parted -a optimal /dev/loop0 mkpart primary  2048KiB 100%
    parted -a optimal /dev/loop1 mkpart primary  2048KiB 100%
    parted -a optimal /dev/loop2 mkpart primary  2048KiB 100%

    ```

1.  现在,让我们在每个循环设备上创建 LVM*物理卷*(输入`yes`以移除`gpt`标签):

    ```
    pvcreate /dev/loop0p1
    pvcreate /dev/loop1p1
    pvcreate /dev/loop2p1

    ```

1.  接下来,显示有关我们的物理卷的信息:

    ```
    pvdisplay

    ```

1.  接下来,我们将在第一个物理卷上创建一个新的 LVM 卷组:

    ```
    vgcreate myVG1 /dev/loop0p1

    ```

1.  现在,显示有关创建的组的信息:

    ```
    vgdisplay myVG1

    ```

1.  之后,让我们在我们的第一个卷组上创建一些逻辑卷,这些逻辑卷将被视为我们 Linux 系统中的虚拟分区:

    ```
    lvcreate -L 10m  -n swap myVG1
    lvcreate -L 100m -n home myVG1
    lvcreate -L 400m -n root myVG1

    ```

1.  接下来,显示有关逻辑卷的信息:

    ```
    lvdisplay myVG1

    ```

1.  现在,显示我们的底层卷组还剩下多少可用空间,如果你想扩展一些逻辑卷,这将变得很重要(查看输出中的`Free PE / Size`部分):

    ```
    vgdisplay myVG1

    ```

1.  之后,让我们在那些新的逻辑卷上创建文件系统:

    ```
    mkswap /dev/myVG1/swap
    mkfs.xfs /dev/myVG1/home
    mkfs.xfs /dev/myVG1/root

    ```

1.  现在,在我们创建了测试 LVM 系统(它与真实的 CentOS LVM 标准布局非常相似,但尺寸较小)之后,让我们开始使用它。

1.  首先,让我们将`root`分区的大小从当前的`400`兆字节(`M`)缩小`200`兆字节,然后,让我们将`home`分区的大小增加`500`兆字节(确认可能的数据丢失):

    ```
    lvresize -L -200m /dev/myVG1/root
    lvresize -L +500m /dev/myVG1/home

    ```

1.  再次使用`vgdisplay myVG1`来查看运行前面的命令后卷组的可用空间如何变化(查看`Free PE / Size`)。

1.  现在,让我们扩展增长,逻辑卷上的 XFS 文件系统:

    ```
    mkdir /media/home-test;mount /dev/myVG1/home /media/home-test
    xfs_growfs /dev/myVG1/home

    ```

    ### 注意

    非常重要的一点是,不要使用`resize2fs`来扩展 XFS 文件系统,因为它们不兼容,可能会导致文件系统损坏。

1.  现在,假设过了一段时间你的数据再次增长,你需要将 home 分区扩展到 1.5 千兆字节(`G`),但你的底层卷组只剩下 184.00 MiB。首先,我们需要将本菜谱开始时准备的两个物理卷添加到我们的卷组中:

    ```
    vgextend myVG1 /dev/loop1p1 /dev/loop2p1
    vgdisplay myVG1

    ```

1.  之后,我们的卷组中有足够的可用空间(查看`Free PE / Size`)来扩展我们的 home 逻辑卷(卷必须保持挂载状态):

    ```
    lvresize -L +1500m /dev/myVG1/home
    xfs_growfs /dev/myVG1/home

    ```

## 它是如何工作的...

在本菜谱中,我们向您展示了如何使用 LVM 处理 XFS 分区。它是为了动态管理多个硬盘上的磁盘空间而开发的。您可以轻松地将多个物理硬盘合并在一起,使它们对系统来说就像一个单一的虚拟硬盘。这使得它比使用传统的静态分区更加灵活和可扩展。传统的分区受限于它们所在的硬盘总容量,不能超过这个容量,而且它们的静态分区布局不容易改变。此外,我们还介绍了一些重要的 LVM 技术术语,它们为硬盘提供了不同的抽象层,本节将解释这些概念背后的内容:**物理卷**(**pv**)、**卷组**(**vg**)和**逻辑卷**(**lv**)。

那么,我们从这次经历中学到了什么?

我们从这个菜谱开始,创建了三个每个 1 千兆字节(`G`)的虚拟块设备,然后在每个设备上创建了一个跨越整个设备的分区。之后,我们使用`pvcreate`命令将这些单分区设备定义为物理卷(pv)。pv 是 LVM 术语,定义了 LVM 世界中的存储单元。它必须定义在分区、全驱动器或循环设备上。pv 只是对周围分区中所有可用空间的抽象,以便我们可以基于 LVM 进行工作。接下来,我们使用`vgcreate`命令创建了一个卷组(vg),在这里我们还必须定义一个我们选择的卷组名称,并将第一个 pv 作为基本存储卷放入其中。如你所见,一个 vg 至少包含一个 pv(我们稍后会添加更多 pv)。向 vg 添加或从 vg 删除 pv 是整个 LVM 系统可扩展性概念的核心。pv 不必都是相同的大小,并且可以通过添加数十个新物理驱动器(全部定义为 pv)来扩展 vg。你的系统上可以有多个 vg,并且可以通过你给它们的唯一名称来识别它们。因此,总之,要扩展 vg 的空间,你必须从物理驱动器创建 pv,然后你可以添加它们。

最终,我们在我们的卷组(vg)上创建了逻辑卷(lv),这些逻辑卷在卷组内部可以像真实的物理分区一样被看到和使用。在这里,我们使用`lvcreate`命令创建了三个 lv,通过这个命令我们需要定义我们想要放置目标 lv 的 vg 的名称(记住,你的系统上可以有多个 vg),以及卷的大小,以及作为最后一个参数的名称。你可以将多个 lv 添加到一个 vg 中,并且不需要使用 vg 底层可用空间中的全部分配空间。你可以非常灵活地使用它。最好的部分是,你关于卷的大小和布局的决定不必永远固定;你可以在任何时候更改它们。这是一个非常动态的系统,可以扩展和缩小,删除和创建,而不需要事先卸载卷。但是你必须记住,所有 lv 都绑定到一个 vg,没有 vg 就不可能创建它们,也不能超出其空间边界。如果你需要将 lv 的空间扩展到基础 vg 的边界之外,你必须扩展 vg,如本菜谱所示。

### 注意

你可能已经注意到,对于每个 LVM 术语,都有一个“显示”和“创建”命令,所以很容易记住:`pvdisplay`,`vgdisplay`,`lvdisplay`,`pvcreate`,`vgcreate`,`lvcreate`。

在成功创建了逻辑卷之后,您可以像处理系统上的其他块设备分区一样处理它们。唯一的区别是它们位于特殊的设备文件夹中:`/dev/<vg name>/<lv name>`或`/dev/mapper/<vg name>/<lv name>`。例如,在本示例中创建的家卷的名称为`/dev/myVG1/home`。最后,为了将它们用作正常的挂载点,我们在它们上创建了一些测试文件系统。

在本食谱的第二部分中,我们向您展示了如何扩展我们的卷组以及如何缩小和扩展我们的逻辑卷测试系统。

我们首先使用`vgdisplay myVG1`命令来显示卷组上当前可用的空间。在命令输出中,我们看到我们的当前卷组总共有`996M`(`VG Size`),我们的逻辑卷(`swap`,`home`,`root`)的已分配大小为`512M`(`Alloc PE / Size`),空闲大小为`484M`(`Free PE /Size`)。接下来,我们使用`lvresize`命令来缩小和扩展逻辑卷的根和家。`-L`参数设置卷的新大小,使用`+`或`-`符号,值将添加到或从逻辑卷的实际大小中减去。如果没有它,该值将被视为绝对值。请记住,我们只能增加家分区,因为当前卷布局没有占用卷组的总空间。调整大小后,如果我们再次使用`vgdisplay`命令,我们会看到我们现在在卷组中占用了更多的空间;其空闲大小已减少到`184M`。由于我们将`home`卷从`100M`扩展到`500M`,因此我们需要记住也要扩展其 XFS 文件系统,因为扩展卷不会自动扩展其文件系统。因此,当前卷的`400M`未分配,没有任何文件系统信息。我们使用了`xfs_growfs`命令,该命令将不定义限制参数,使用完整的未分配区域用于 XFS 文件系统。如果您想调整任何其他文件系统类型的大小,例如 ext4,则可以使用`resize2fs`命令代替。

最后,我们想将家卷扩展`1.5G`,但我们只有`184M`剩余的空间来扩展。这就是 LVM 真正*闪耀*的地方,因为我们可以简单地向其中添加更多的物理卷(在现实世界中,您只需在服务器中安装新的硬盘并将其用作 pvs)。我们向您展示了如何使用`vgextend`命令将两个 1G 大小的 pvs 添加到卷组中来*扩展*卷组的容量。之后,我们使用`vgdisplay`查看我们的卷组现在已经增长了 3G 的总大小,所以最后我们可以扩展我们的家逻辑卷,因为它现在可以适合它。作为最后一步,我们再次扩展了 XFS 文件系统,以填充整个 2G 的家卷大小。

请始终牢记,如果你在多个物理硬盘上使用 vg,你的数据将会在这些硬盘之间分布。LVM 并非 RAID 系统,不具备冗余性,因此如果一个硬盘损坏,你的整个 vg 也会随之失效,数据将丢失!为了解决这个问题,一个建议的解决方案是在硬盘上使用物理 RAID 系统,并在其上创建 LVM。


# 第六章:提供安全性

在本章中,我们将介绍以下主题:

+   锁定远程访问并加固 SSH

+   安装和配置 fail2ban

+   使用防火墙

+   通过示例伪造防火墙规则

+   生成自签名证书

+   使用安全的 FTP 替代方案

# 引言

本章是一系列操作的集合,为服务器在几乎任何环境中提供安全性提供了坚实的基础。安全性是优秀管理员的基础,本章说明了您可以如何快速轻松地设计和实施一系列检查点,以提供所需的保护。

# 锁定远程访问并加固 SSH

在本操作中,我们将学习如何提供额外的安全措施以加固安全 Shell 环境。**安全 Shell**(**SSH**)是提供远程访问服务器的基本工具包。远程机器的实际距离无关紧要,但 Shell 环境使您能够执行维护、升级、软件包安装和文件传输;您还可以在安全环境中执行作为管理员所需执行的任何操作。这是一个重要的工具;作为进入系统的门户,本操作的目的是向您展示如何执行一些基本的配置更改,以保护您的服务器免受不受欢迎的访客。

## 准备

要完成此操作,您需要具备 CentOS 7 操作系统的最小安装、具有 root 权限、您选择的基于控制台的文本编辑器以及连接到互联网以下载其他软件包的能力。假设您的服务器已经至少维护了一个基于非 root 的管理员帐户,可以使用此操作提供的功能。

## 如何操作...

SSH 的作用对于远程管理服务器至关重要,因此有必要提供一些基本步骤以确保其安全:

1.  首先,以`root`身份登录并创建原始配置文件的备份,方法是键入以下命令:

    ```
    cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

    ```

1.  现在,通过键入以下内容打开主`sshd`配置文件:

    ```
    vi /etc/ssh/sshd_config

    ```

1.  我们将首先调整允许完成登录过程的时间,因此请向下滚动并找到以下行:

    ```
    #LoginGraceTime 2m

    ```

1.  取消注释此行并将其值更改为更合适的值,例如:

    ```
    LoginGraceTime 30

    ```

1.  现在,再向下滚动几行并找到以下行:

    ```
    #PermitRootLogin yes

    ```

1.  将其更改为以下内容:

    ```
    PermitRootLogin no

    ```

1.  找到以下行:

    ```
    X11Forwarding yes

    ```

1.  并将其更改为以下内容:

    ```
    X11Forwarding no

    ```

1.  在重新启动 SSH 服务之前,保存并关闭文件,如下所示:

    ```
    systemctl restart sshd

    ```

1.  在此阶段,您可能希望在退出当前会话之前,使用新设置创建一个新的 SSH 会话。这是为了确保一切正常工作,并避免意外锁定自己无法访问服务器。如果您在启动新的 SSH 会话时遇到困难,只需返回到原始会话窗口并进行必要的调整(然后重新启动 SSH 服务)。但是,如果没有遇到任何困难,并且您已成功登录到辅助会话,则可以通过键入`exit`关闭原始 shell 环境。

    ### 注意

    请记住,遵循本教程后,您现在应该发现 shell 的 root 访问权限已被拒绝,您必须使用标准用户帐户登录。任何需要 root 权限的进一步工作都需要使用`su`或`sudo`命令,具体取决于您的偏好。

## 它是如何工作的...

SSH 是一项至关重要的服务,它使您能够远程访问服务器。没有它,服务器管理员将无法工作。在本教程中,我们向您展示了如何使该服务更加安全。

那么,我们从这次经历中学到了什么?

我们首先创建了原始主`sshd`配置文件的备份副本。接下来是打开并编辑它。SSH 的配置文件维护了一个长长的设置列表,这些设置非常适合大多数内部需求,但对于生产环境中的服务器,通常建议更改默认的 SSH 配置文件以满足您的特定需求。在这方面,第一步是建议更改登录宽限时间,`LoginGraceTime 30`。与默认的两分钟不同,前面的值将只允许最多 30 秒。这是用户可以连接但尚未开始身份验证过程的时间段;数字越低,保持打开的未经验证的连接就越少。接下来,我们通过使用`PermitRootLogin no`指令删除了远程用户以 root 用户身份登录的能力。在大多数情况下,这是必须的,除非服务器处于受控环境中,否则远程服务器不应允许直接 root 登录。这样做的原因是为了降低被黑客攻击的风险。每个 SSH 黑客试图破解的第一件事是 root 用户的密码。如果您不允许 root 登录,攻击者还需要猜测用户名,这要复杂得多。下一个设置简单地禁用了`X11Forwarding`。在这些情况下,通常是一个好主意,应用短语“如果您不使用它,请禁用它”。为了完成本教程,您需要重新启动 SSH 服务器,以便允许更改立即生效,并启动一个新的 SSH 会话,以确保修改确实按预期工作。没有任何系统是绝对安全的,但通过这样做,您现在可以放心,知道您已经使 SSH 服务器更加安全。

## 还有更多...

为了使您的 SSH 服务器更加安全,还有几个主题需要涵盖:我们应该更改 SSH 端口号,并向您展示如何限制特定系统用户的 SSH 访问。

### 更改服务器 SSH 端口号

端口 22 是所有 SSH 服务器使用的默认端口,更改使用的端口号可以在一定程度上增加服务器整体安全性。再次打开主 SSH 守护程序配置文件`sshd_config`。现在,向下滚动并找到以下行:

Port 22


删除前面的`#`字符(取消注释)并将端口号更改为另一个值,将`XXXX`替换为适当的端口号:

Port XXXX


您必须确保新端口号未被使用,完成后保存文件并关闭。请记住,此处所做的任何更改都会反映在您的防火墙配置中。因此,我们还需要在 firewalld 中打开新端口。通过环境变量`NEWPORT`设置新端口(将`XXXX`替换为您的新 SSH 端口),然后执行以下`sed`命令以更改 SSH firewalld 服务文件并在之后重新加载`firewalld`守护进程(有关详细信息,请阅读本章中的防火墙配方):

NEWPORT=XXXX
sed "s/port="22"/port="$NEWPORT"/g" /usr/lib/firewalld/services/ssh.xml > /etc/firewalld/services/ssh.xml firewall-cmd --reload


此外,我们还需要告诉 SELinux(参见第十四章,*使用 YUM 管理包*)。

## 如何操作...

`fail2ban`默认未安装,因此我们需要调用 YUM 包管理器并下载必要的包:

1.  为了开始本食谱,以`root`身份登录并输入以下命令:

    ```
    yum install fail2ban-firewalld fail2ban-systemd

    ```

1.  在你的首选文本编辑器中创建一个新的配置文件,如下所示:

    ```
    vi  /etc/fail2ban/jail.local

    ```

1.  放入以下内容:

    ```
    [DEFAULT]
    findtime = 900
    [sshd]
    enabled = true

    ```

1.  现在,添加以下定义封禁期限的行。它是以秒为单位计算的,因此调整时间期限以反映一个更合适的值。在这种情况下,我们选择将其设为一小时:

    ```
    bantime  = 3600

    ```

1.  然后,添加最大登录尝试次数:

    ```
    maxretry = 5

    ```

1.  如果你通过非`22`的定制端口运行 SSH,你需要告诉`fail2ban`这一点(用你选择的端口号替换`XXXX`),否则跳过此步骤:

    ```
    port=XXXX

    ```

1.  现在,以通常的方式保存并关闭文件,然后继续在启动时启用`fail2ban`服务。为此,输入以下命令:

    ```
    systemctl enable fail2ban

    ```

1.  为了完成本食谱,你现在应该通过输入以下命令来启动服务:

    ```
    systemctl start fail2ban

    ```

## 它是如何工作的...

`fail2ban`旨在监控那些在你的服务器上反复登录失败的用户,其主要目的是减轻旨在破解密码和窃取用户凭据的攻击。它通过持续读取系统日志文件来工作,如果其中包含指示多次失败尝试的模式,那么它将采取行动对抗违规 IP 地址。我们都知道服务器不是孤立存在的,通过使用这个工具,在几分钟内,服务器将运行在额外的保护层之下。

那么,我们从这次经历中学到了什么?

`fail2ban`并未包含在标准的 CentOS 仓库中,因此您的服务器需要能够访问 EPEL 仓库。`fail2ban`软件包的安装非常简单;除了主要的`fail2ban`软件包外,我们还安装了另外两个软件包,以便将其集成到 CentOS 7 的新`systemd`和 firewalld 服务器技术中。接下来,为了进行本地定制,我们创建了一个新的`jail.local`文件。我们首先为所有目标(在`[DEFAULT]`部分中指定)指定了`findtime`参数,这是用户尝试登录的时间。该值以秒为单位,意味着如果用户在指定时间内未能成功登录,则他们将被禁止。接下来,我们通过添加一个`[sshd]`部分来启用`fail2ban`服务。在该部分中,我们引入了`bantime`值,该值表示如果主机违反规则,将被阻止访问服务器的总秒数。基于此,您被要求确定在阻止之前允许的最大登录尝试次数。此外,如果您更改了服务的标准监听端口,则必须使用`port`指令定义自定义端口。为了测试您的设置,请尝试使用 SSH 认证用户并提供错误的密码五次。在第六次尝试时,您应该在一个小时内无法返回到登录提示!

保护`sshd`服务免受暴力攻击只是开始的第一步,而使用`failban`还有很多需要学习的地方。要排查服务问题,请查看位于`/var/log/fail2ban.log`的日志文件。为了获取一些关于如何使用它的想法,请打开以下示例`failban`配置文件:`less /etc/fail2ban/jail.conf`。

# 与防火墙协同工作

防火墙是一种程序,它监控和控制系统网络接口的传入和传出网络流量,并可以限制传输到仅对计算机系统或网络有用和无害的数据。默认情况下,CentOS 提供了一个极其强大的防火墙,直接构建在内核中,称为**netfilter**。虽然在旧版本的 CentOS 中,我们使用著名的 iptables 应用程序来控制它,但在版本 7 中,新的标准 netfilter 管理程序已更改为名为`firewalld`的服务,该服务默认情况下已在每个 CentOS 7 服务器上安装并启用。

这是一个非常强大的服务,可以完全控制服务器的防火墙安全,并且比 iptables 更容易使用。它的主要优点是它具有更好的结构和更逻辑的方法来管理和配置现代防火墙解决方案的各个方面。因此,它将成为您服务器安全的基础,因此本食谱的目的是让您快速了解 firewalld 的基本原理。

## 准备就绪

要完成本食谱,您需要具有 root 权限的 CentOS 7 操作系统的最小安装以及您选择的基于控制台的文本编辑器。

## 如何做到这一点...

由于`firewalld`服务在每个 CentOS 7 服务器上默认运行,因此我们可以直接通过以`root`用户身份登录到服务器来开始使用该服务。

1.  键入以下命令以查询与区域相关的信息:

    ```
    firewall-cmd --get-zones | tr " " "\n"
    firewall-cmd --list-all-zones
    firewall-cmd --get-default-zone
    firewall-cmd --list-all

    ```

1.  我们可以通过使用以下行切换到不同的防火墙`默认`区域:

    ```
    firewall-cmd --set-default-zone=internal

    ```

1.  临时将网络接口添加到`区域`:

    ```
    firewall-cmd --zone=work --add-interface=enp0s8

    ```

1.  现在,临时将服务添加到`区域`:

    ```
    firewall-cmd --zone=work --add-service=ftp

    ```

1.  测试添加接口和服务是否成功:

    ```
    firewall-cmd --zone=work --list-all

    ```

1.  现在,永久添加服务:

    ```
    firewall-cmd --permanent --zone=work --add-service=ftp
    firewall-cmd --reload
    firewall-cmd --zone=work --list-all

    ```

1.  最后,让我们通过打开以下文件来创建一个新的防火墙区域:

    ```
    vi /etc/firewalld/zones/seccon.xml

    ```

1.  现在输入以下内容:

    ```
    <?xml version="1.0" encoding="utf-8"?>
    <zone>
      <short>security-congress</short>
      <description>For use at the security congress. </description>
      <service name="ssh"/>
    </zone>
    ```

1.  保存并关闭,然后重新加载`防火墙`配置,以便我们可以看到新区域:

    ```
    firewall-cmd --reload

    ```

1.  最后,检查新区域是否可用:

    ```
    firewall-cmd --get-zones

    ```

## 它是如何工作的...

与 iptables 相比,新的 firewalld 系统隐藏了创建复杂网络规则的过程,并且具有非常简单的语法,出错的可能性较小。它可以在运行时动态重新加载 netfilter 设置,而无需重新启动整个服务,并且我们可以在每个系统上设置多个防火墙配置,这使得它在不断变化的网络环境中工作时非常出色,例如对于移动设备如笔记本电脑。在本食谱中,我们向您介绍了 firewalld 的两个基本构建块:**区域**和**服务**。

那么,我们从这次经历中学到了什么?

我们从这个食谱开始使用`firewall-cmd`来获取系统上可用防火墙区域的信息。Firewalld 引入了网络或防火墙区域的新概念,它为服务器的网络接口及其相关连接分配不同级别的信任。在 CentOS 7 中,已经存在一些预定义的 firewalld 区域,所有这些区域(例如,`private`、`home`、`public`等,除了`trusted`区域)将阻止任何形式的传入网络连接到服务器,除非它们被附加到区域的特殊规则明确允许(这些规则称为 firewalld 服务,我们将在后面看到)。我们使用`firewall-cmd`查询区域信息,使用`--get-zones`或(更详细)使用`--list-all-zones`参数。每个这些区域都作为一个完整和全面的防火墙,您可以根据系统的环境和位置使用。例如,顾名思义,`home`区域适用于您的计算机位于家庭区域的情况。如果选择此选项,您基本上信任网络上的所有其他计算机和服务不会损害您的计算机,而公共区域更多地用于公共场所,如公共接入点等。在这里,您不信任网络上的其他计算机和服务不会伤害您。在 CentOS 7 上,安装后设置的标准`default`区域配置是`public`区域,我们使用命令的`--get-default-zone`参数显示,并使用`--list-all`更详细地显示。

### 注意

简而言之,firewalld 区域主要是关于控制服务器上的传入连接。使用 firewalld 限制传出连接也是可能的,但这超出了本书的范围。

此外,为了获取所有当前可用区域的更多技术信息,我们使用了防火墙客户端的`--list-all-zones`参数。在命令的输出中,您会注意到一个区域可以有一些关联的网络接口和一个属于它的服务列表,这些是应用于传入网络连接的特殊防火墙规则。您可能还会注意到,虽然默认列出所有区域及其关联服务的详细信息,但所有 firewalld 区域都非常限制,几乎不允许任何东西连接到服务器。此外,从上面的命令输出中还可以看到另一个非常重要的概念。我们的`public`区域被标记为`default`和`active`。虽然`active`区域是直接与网络接口关联的区域,但如果您有多个网络适配器可用,`default`区域确实可以变得非常重要。在这里,它充当标准的最小防火墙保护和回退策略,以防您错过了为每个接口分配一些活动区域。对于只有一个网络接口设置的系统,`default`区域还将自动设置`active`区域。要设置`default`区域,我们使用了`--set-default-zone`参数,并且要使区域对某个接口处于活动状态,我们使用了`--add-interface`。请注意,如果您不指定`--zone`参数,大多数`firewall-cmd`命令将使用`default`区域来应用设置。Firewalld 正在监听系统上的每个网络接口,并等待新的网络数据包到达。总之,我们可以说,如果有新的数据包进入特定接口,Firewalld 接下来要做的是找出与我们网络接口关联的正确区域(使用其活动配置,或者如果没有可用的话,使用其默认配置);找到它之后,它将对属于它的网络数据包应用所有服务规则。

接下来,我们向您展示了如何使用 firewalld 服务。简单来说,firewalld 服务是规则,它们在我们的防火墙内打开并允许与我们的服务器建立特定连接。使用这种服务文件定义允许包含的规则的可重用性,因为它们可以添加或删除到任何区域。此外,使用系统中已有的预定义 firewalld 服务,而不是手动查找并打开协议、端口或端口范围,使用复杂的 iptables 语法为您的系统服务感兴趣,可以使您的管理工作变得更加容易。我们通过调用`--add-service`将`ftp`服务添加到`work`区域。之后,我们使用`--list-all`打印出 work 区域的详细信息。firewalld 被设计为具有分离的运行时和永久配置。对运行时配置的任何更改都会立即生效,但会消失,而永久配置将在重新加载或重启 firewalld 服务后仍然存在。一些命令,如切换默认区域,会将更改写入两个配置,这意味着它们会立即在运行时应用,并且在服务重启后仍然持久。其他配置设置,如将服务添加到区域,仅写入运行时配置。如果重新启动 firewalld,重新加载其配置,或重新启动计算机,这些临时更改将丢失。为了使这些临时更改永久化,我们可以使用`--permanent`标志与`firewall-cmd`程序调用一起将其写入永久配置文件。

与运行时选项不同,这里的更改不会立即生效,只有在服务重启/重新加载或系统重启后才会生效。因此,对于这种仅运行时命令的永久设置,最常见的方法是首先使用`--permanent`参数应用设置,然后重新加载防火墙的配置文件以实际激活它们。

最后,我们向您展示了如何创建自己的区域,这只是一个您需要在`/etc/firewalld/zones/`目录中创建的 XML 文件,我们在其中指定了名称、描述以及您想要激活的所有服务。如果您在任何防火墙配置文件中做了更改,别忘了之后重新加载防火墙配置。

为了完成这个配置,我们将撤销对`work`区域所做的永久性更改,并重新加载 firewalld 以重置在本配置中应用的所有非永久性更改:

firewall-cmd --permanent --zone=work --remove-service=ftp
firewall-cmd --reload


## 还有更多...

为了解决阻止服务的问题,而不是完全关闭防火墙,您应该将`zone`切换到`trusted`,这将打开所有传入端口到防火墙:

firewall-cmd --set-default-zone=trusted


一旦您完成了测试,只需切换回您之前所在的区域,例如:

firewall-cmd --set-default-zone=public


# 通过示例构建防火墙规则

在本教程中,我们希望向您展示如何创建您自己的 firewalld 服务定义,或者如何更改现有的服务定义,这是任何 CentOS 7 系统管理员都应该知道的,如果预定义的服务文件不符合您系统的需求。

## 准备就绪

要完成本教程,您需要一个最小安装的 CentOS 7 操作系统,具有`root`权限和一个基于控制台的文本编辑器。我们将更改 firewalld 中 SSH 服务的端口号,因此请确保您已按照教程*锁定远程访问并加固 SSH*中的说明配置了新端口。在我们的示例中,我们将端口更改为`2223`。此外,我们将为一个小型的基于 Python 的 Web 服务器创建一个新的 firewalld 服务,我们将使用它来演示如何将新的系统服务集成到 firewalld 中。在开始之前,通过*使用防火墙*教程掌握 firewalld 的基础知识是有益的。

## 如何操作...

在本教程中,我们将向您展示如何更改和如何创建新的 firewalld 服务定义。在本教程中,我们假设我们处于默认的公共区域。

### 更改现有的 firewalld 服务(ssh)

1.  首先,以`root`身份登录,并将`ssh`服务复制到正确的位置以进行编辑:

    ```
    cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services

    ```

1.  接下来,打开`ssh`服务定义文件:

    ```
    vi /etc/firewalld/services/ssh.xml

    ```

1.  将端口从`22`更改为`2223`,然后保存文件并关闭它:

    ```
    <port protocol="tcp" port="2223"/>

    ```

1.  最后,重新加载防火墙:

    ```
    firewall-cmd --reload

    ```

### 创建您自己的新服务

执行以下步骤以创建您自己的新服务:

1.  打开一个新文件:

    ```
    vi /etc/firewalld/services/python-webserver.xml

    ```

1.  输入以下服务定义:

    ```
    <?xml version="1.0" encoding="utf-8"?>
    <service>
      <short>Python Webserver</short>
      <description>For pythons webservers</description>
      <port port="8000" protocol="tcp"/>
    </service>
    ```

1.  保存并关闭文件,然后最后重新加载防火墙:

    ```
    firewall-cmd --reload

    ```

1.  现在,将此新服务添加到我们的`default`区域:

    ```
    firewall-cmd --add-service=python-webserver

    ```

1.  之后,运行以下命令以在端口`8000`上启动一个简单的 Python Web 服务器(按下*Ctrl* + *C*组合键停止它):

    ```
    python -m SimpleHTTPServer 8000

    ```

1.  恭喜!您的新网络服务器位于端口`8000`,现在可以从您网络中的其他计算机访问了。

    ```
    http://<ip address of your computer>:8000/
    ```

## 它是如何工作的...

在本教程中,我们展示了如何轻松地自定义或定义新的 firewalld 服务,如果预定义的服务需要更改,或者对于全新的系统服务,这些服务根本未定义。服务定义文件是简单的 XML 文件,您在其中为给定的系统服务或程序定义规则。我们的 firewalld 服务文件存放在两个不同的目录中:`/usr/lib/firewalld/services`用于系统安装时提供的所有预定义服务,以及`/etc/firewalld/services`用于所有自定义和用户创建的服务。

那么,我们从这次经历中学到了什么?

我们首先通过在正确的位置`/etc/firewalld/services`创建 SSH firewalld 服务文件的工作副本来开始这个配置。我们可以直接复制原始文件,因为该目录中的所有文件都会覆盖`/usr/lib/firewalld/services`中的默认配置文件。接下来,我们打开文件并将其默认端口从`22`更改为`2223`。每当更改系统服务的标准监听端口时,我们都需要这样做,以便让防火墙知道它应该允许通过更改后的端口的网络流量。打开文件时,您会看到服务文件是简单的 XML 文本文件,包含一些强制性和一些可选的标签和属性。它们包含一个或多个端口和协议的列表,这些定义了如果服务连接到某个区域,firewalld 应该启用什么。XML 文件中还可以有另一个重要设置:辅助模块。例如,如果您打开位于`/usr/lib/firewalld/services/samba.xml`的 SAMBA 服务文件,您会看到标签`<module name="nf_conntrack_netbios_ns"/>`。这些是特殊的内核 netfilter 辅助模块,可以动态加载到基于内核的防火墙中,并且对于某些系统服务(如 Samba 或 FTP)是必需的,这些服务在临时 TCP 或 UDP 端口上创建动态连接,而不是使用静态端口。重新加载防火墙配置后,我们现在应该能够使用更改后的端口从网络中的另一台计算机测试连接。

在本配置的第二部分,我们为一个新的系统服务创建了一个全新的服务文件,这是一个简单的 Python Web 服务器,监听端口 8000,显示简单的目录内容列表。因此,我们为 Python Web 服务器创建了一个简单的 XML 服务文件,包括正确的端口 8000,重新启动了防火墙,然后将这个新服务添加到我们的默认公共区域,以便我们实际上可以通过该服务打开连接。现在,您应该能够使用同一网络中的另一台计算机浏览到我们的 Web 服务器的起始页面。但是,由于我们没有使用`--permanent`标志,如果您重新启动 firewalld 守护进程,`python-webserver`服务将从`public`区域消失(或者您也可以使用参数`--remove-service=python-webserver`)。

总之,我们可以说,在 CentOS 7 中推荐的防火墙选择是 firewalld,因为所有重要的系统服务都已经通过预定义的服务规则设置为使用它。您应该记住,Linux 防火墙是一个非常复杂的主题,很容易填满整本书,而且您可以使用`firewall-cmd`做更多的事情,这些在这本书中无法涵盖。

## 还有更多...

通常,您可能只想快速打开特定端口来测试事物,然后再编写自己的自定义服务定义。为此,您可以使用以下命令行,该命令行将在`default`区域上临时使用 tcp 协议打开端口`2888`:

firewall-cmd --add-port=2888/tcp


测试完成后,只需重新加载防火墙配置即可再次删除并关闭特定端口。

# 生成自签名证书

在本教程中,我们将学习如何使用 OpenSSL 工具包创建自签名**安全套接字层**(**SSL**)证书。SSL 是一种用于加密通信两端(例如服务器和客户端)之间的消息的技术,以便第三方无法读取它们之间发送的消息。证书不用于加密数据,但它们在通信过程中非常重要,以确保您与之通信的一方正是您认为的那一方。没有它们,身份冒充攻击将更加常见。

## 准备工作

要完成此操作,您需要一个具有 root 权限和您选择的基于控制台的文本编辑器的 CentOS 7 操作系统的工作安装。

### 注意

一般来说,如果您打算在生产服务器上使用 SSL 证书,您可能希望从受信任的证书颁发机构购买 SSL 证书。关于哪种证书最适合您的需求和预算,您有很多选择,但为了本教程的目的,我们将仅限于讨论自签名证书,这对于任何开发服务器或内部网络来说已经足够了。

## 如何操作...

1.  首先,以`root`身份登录并转到以下目录,以便我们可以使用 Makefile 生成我们想要的证书和密钥文件:

    ```
    cd /etc/pki/tls/certs

    ```

1.  现在,要创建一个包含嵌入式公钥的自签名证书(两者都在文件`server.crt`中)以及服务器的私钥(文件名为`server.key`),请输入以下命令:

    ```
    make server.crt

    ```

1.  然后,系统会要求您输入密码并收到一系列问题,您应该用适当的值回答。通过特别注意通用名称值来完成所有必需的详细信息,该值应反映您将为此证书使用的服务器的域名或 IP 地址。例如,您可以输入:

    ```
    mylocaldomainname.home

    ```

1.  要创建一个包含自签名证书、公钥和私钥的`pem`文件,有效期为五年,请输入以下命令:

    ```
    make server.pem DAYS=1825

    ```

1.  现在,让我们为 Apache Web 服务器创建一个密钥对(一个私钥和包含公钥的自签名证书),我们需要启用`https`,它将在`/etc/pki/tls/private/localhost.key`和`/etc/pki/tls/certs/localhost.crt`中生成(使用安全密码并在第二个命令中重复):

    ```
    make testcert

    ```

1.  要创建一个**证书签名请求**(**CSR**)文件而不是自签名证书,请使用以下命令:

    ```
    make server.csr

    ```

## 它是如何工作的...

在本教程中,我们向您介绍了使用**公钥加密技术**(**PKI**)的 SSL 技术(其中存在两种形式的密钥:公钥和私钥)。在服务器上,我们存储私钥,而客户端获得公钥。从一端发送到另一端的每条消息都由属于一侧的密钥加密,并且只能由另一侧的相应密钥解密。例如,使用服务器的私钥加密的消息只能由客户端的公钥解密和阅读,反之亦然。公钥通过证书文件发送给客户端,它是文件的一部分。如前所述,公钥负责加密和解密数据,而证书则负责识别服务器与客户端,并确保您实际上连接到了您试图连接的同一服务器。如果您想在 FTPS、HTTPS、POP3S、IMAPS、LDAPS、SMTPS 等协议中设置使用 SSL 加密的安全服务,您需要一个签名的服务器证书来配合工作。如果您想将这些服务用于您的业务,并希望使用和处理这些服务的人信任它们,例如在公共互联网上,您的证书应该由官方的**认证机构**(**CA**)签名。证书的价格按订阅支付,可能非常昂贵。如果您不打算向公众提供您的证书或启用了 SSL 的服务,或者您只想在公司内部网内提供这些服务,或者只是想在购买前测试一下,您也可以使用 OpenSSL 工具包自行签名(自签名)证书。

### 注意

自签名证书与来自官方 CA 的证书之间的唯一区别是,大多数使用证书进行通信的程序会向您发出警告,表示它不知道该 CA,并且您不应该信任它。在确认安全风险后,您可以正常使用该服务。

那么,我们从这次经历中学到了什么?

我们从这个食谱开始,前往 CentOS 7 中所有系统证书的标准位置:`/etc/pki/tls/certs`。在这里,我们可以找到一个 Makefile,这是一个方便生成公钥/私钥对、SSL CSR 和自签名 SSL 测试证书的辅助脚本。它通过隐藏 OpenSSL 程序的复杂命令行参数来工作。它非常易于使用,并且将自动通过你的文件名参数的文件扩展名识别你的目标。因此,通过提供带有`.crt`扩展名的输出文件名来生成 SSL 密钥对是一个简单的过程。如前所述,你将被要求输入密码和一系列关于证书所有权的问题,其中最重要的是通用名称。这应该反映你计划使用此证书的服务器的域名,因为大多数程序,如网络浏览器或电子邮件客户端,将检查域名以查看它们是否有效。运行此命令的结果是证书及其嵌入的公钥在文件`server.crt`中,以及称为`server.key`的服务器的相应私钥。

接下来,我们创建了一个`.pem`文件,并提供了一个`DAYS`参数,使证书有效期为五年,而不是默认的一年,当你不带它运行时。`pem`文件是一个容器文件,包含密钥对的两部分:私钥和自签名证书(带有其嵌入的公钥)。这种文件格式有时是某些程序(如`vsftpd`)所要求的,以启用 SSL 加密,而不是提供两个分离的文件中的密钥对。接下来,我们运行了 Makefile 目标`testcert`,它生成了私钥以及公钥,以及正确位置的证书,Apache Web 服务器期望在那里设置 HTTPS。请注意,如果你需要稍后重复任何 Makefile 运行,你需要删除生成的输出文件;例如,对于 Apache,你需要在可以再次构建输出文件之前删除以下文件:

rm /etc/pki/tls/certs/localhost.crt /etc/pki/tls/private/localhost.key
make testcert


最后,我们向你展示了如何生成 CSR 文件,如果你计划从受信任的证书颁发机构购买 SSL 证书,这将需要。

## 还有更多...

我们没有涵盖 Makefile 脚本在生成证书方面提供的所有可能性。如果你运行命令`make`而不给出任何目标参数,程序将打印出一个使用帮助文本,其中包含所有可能的选项。

正如我们所学,公钥和私钥是成对生成的,并将加密和解密对方的消息。你可以通过比较以下输出(必须完全相同)来验证你的密钥对是否有效且属于一起:

openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5


# 使用 FTP 的安全替代方案

尽管 FTP 仍然流行用于共享数据或在网络上传输文件,但您必须意识到您正在使用一个非常不安全的网络协议,该协议默认情况下没有内置保护。这意味着在网络传输过程中,您的数据完全暴露给潜在的攻击者。这绝不是您希望用于传输敏感数据(如登录凭据)的方式。为了避免这些潜在风险,我们将在此菜谱中向您展示如何使用和设置两种替代方案来保护 FTP,即使用 FTPS(FTP over SSL 或 FTP/SSL)或 SFTPS(启用 SSH 的 FTP)。

## 准备就绪

要完成此菜谱,您需要一个具有 root 权限的 CentOS 7 操作系统的最小安装和一个您选择的基于控制台的文本编辑器。您应该已经安装并配置了一个基本的 vsftpd 服务器(请参阅[第十二章](part0098_split_000.html#2TEN41-4cf34a6d07944734bb93fb0cd15cce8c "Chapter 12. Providing Web Services"),*提供 Web 服务*了解如何操作)。此外,为了设置 SFTP,我们需要创建一些自签名证书;如果您想了解其背后的详细信息,请阅读本章中的*生成自签名证书*菜谱。

## 如何操作...

您必须事先决定是要使用 SFTP 还是 FTPS。这两种方法不能同时应用,因此您必须首先决定选择哪种选项。如果您在这两种方法之间切换,您需要先恢复`vsftpd.conf`或`sshd_config`的默认配置文件状态。

### 使用 SSL 保护您的 vsftpd 服务器 - FTPS

要使用 SSL-FTPS 保护您的 vsftpd 服务器,请执行以下步骤:

1.  以`root`身份登录并转到标准证书位置:

    ```
    cd /etc/pki/tls/certs

    ```

1.  现在,让我们为我们的`ftp-server`配置创建一个 SSL 密钥对,该密钥对包括证书及其嵌入的公钥以及私钥在一个文件中(请记住,`Common name`值应反映您的 FTP 服务器的域名):

    ```
    make ftp-server.pem

    ```

1.  更改到更安全的文件访问规则:

    ```
    chmod 400 /etc/pki/tls/certs/ftp-server.pem

    ```

1.  现在,在对其进行操作之前,首先备份`vsftpd.conf`文件。

    ```
    cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.BAK

    ```

1.  现在,启用 SSL 并将我们刚刚创建的密钥对文件添加到我们的`vsftpd`配置中:

    ```
    echo "rsa_cert_file=/etc/pki/tls/certs/ftp-server.pem
    ssl_enable=YES
    force_local_data_ssl=YES
    force_local_logins_ssl=YES
    pasv_min_port=40000
    pasv_max_port=40100" >> /etc/vsftpd/vsftpd.conf

    ```

1.  接下来,我们需要添加一个新的 firewalld 服务文件,因此打开以下内容:

    ```
    vi /etc/firewalld/services/ftps.xml

    ```

1.  请输入以下内容:

    ```
    <?xml version="1.0" encoding="utf-8"?>
    <service>
      <description>enable FTPS ports</description>
      <port protocol="tcp" port="40000-40100"/>
      <port protocol="tcp" port="21"/>
      <module name="nf_conntrack_ftp"/>
    </service>
    ```

1.  最后,重新加载防火墙,添加`ftps`服务,并重启您的`vsftpd`服务器:

    ```
    firewall-cmd --reload; firewall-cmd --permanent --add-service=ftps; firewall-cmd --reload
    systemctl restart vsftpd

    ```

### 使用 SSH 保护您的 vsftpd 服务器 - SFTP

要使用 SSL-SFTP 保护您的 vsftpd 服务器,请执行以下步骤:

1.  首先,为所有有效的 SFTP 用户创建一个组:

    ```
    groupadd sshftp

    ```

1.  我们将对`sshd`主配置文件进行操作,因此在进行任何更改之前,请先备份:

    ```
    cp /etc/ssh/sshd_config  /etc/ssh/sshd_config.BAK

    ```

1.  现在,打开`sshd_config`文件,转到包含`Subsystem`指令的行,禁用它(这意味着在该行前面加上`#`符号),并添加以下行,如下所示:

    ```
    #Subsystem       sftp    /usr/libexec/openssh/sftp-server
    Subsystem sftp internal-sftp

    ```

1.  接下来,在文件末尾添加以下行以启用 SFTP:

    ```
    Match Group sshftp
    ChrootDirectory /home
    ForceCommand internal-sftp

    ```

1.  最后,重启`sshd`守护进程。

    ```
    systemctl restart sshd

    ```

## 它是如何工作的...

在这个过程中,你学会了如何通过从标准 FTP 协议切换到使用 SSL 上的 FTP 或 SSH 上的 FTP 来使你的文件共享更安全。无论你选择哪种选项,SSL 都用于在传输过程中加密数据,这有助于保护你的隐私。你选择哪种变体取决于你,但要记住,SFTP 设置起来稍微容易一些,因为你不需要在你的防火墙中配置额外的端口或证书,因为一切都在 SSH 上运行,这在大多数系统上应该是默认启用的。

那么,我们从这次经历中学到了什么?

我们首先通过配置 FTPS 开始这个过程。我们进入了一个特殊的目录,叫做`/etc/pki/tls/certs`,CentOS 在这里存储所有的证书。在其中,有一个 Makefile,我们用它来创建一个包含公钥/私钥对和自签名证书的`.pem`文件,这是我们 FTP 服务器配置所需的。之后,我们使用 chmod 确保只有 root 用户可以读取这个文件。然后,我们在主`vsftpd`配置文件中追加了六行代码(首先,我们备份了原始文件);它们相当直观:启用 SSL 协议,使用自签名证书,禁止任何非 SSL 通信,并使用一个固定的被动控制端口范围。此外,我们创建了一个新的防火墙服务,它将打开 FTPS 所需的被动控制端口。

之后,我们通过 chroot jail 配置了 SFTP。如果不使用 chroot jail 设置 SFTP,每个登录用户都可以查看根文件系统,这是非常不安全的。SFTP 的配置完全在主`sshd`配置文件中完成。在备份原始文件后,我们将 FTP 子系统更改为`internal-sftp`,这是一个更新的 FTP 服务器版本,性能更好,并在同一进程中运行。接下来,我们在`vsftpd`配置文件中添加了三行;只有`sshftp`组中的用户使用 SFTP,并被放入 chroot jail 中,只能查看其`home`目录及以下的文件。`ForceCommand`忽略用户的所有本地设置,并在此处强制执行这些规则。要添加新的 chroot SFTP 用户,你只需创建一个标准的 Linux 用户账户,并将他们添加到`sshftp`用户组。

## 还有更多...

如果你想测试你的已启用 FTPS 服务器,你需要一个支持“FTP over TLS”的 FTP 客户端。你需要在你的 FTP 客户端设置中找到并启用这个选项。在 Linux 下,你可以安装`lftp`客户端来测试你是否可以连接到我们的 FTPS 服务器。首先,安装`lftp`包(例如,`yum install lftp`)。然后,使用 TLS 配置客户端:

echo "set ftp:ssl-auth TLS
set ftp:ssl-force true
set ftp:ssl-protect-list yes
set ftp:ssl-protect-data yes
set ftp:ssl-protect-fxp yes
set ssl:verify-certificate no" >~/.lftprc


现在,你可以使用以下命令连接并测试你的 FTPS 服务器:

lftp -u username


如果你想测试你的已启用 SFTP 服务器,你需要一个名为`sftp`的程序:

sftp john@ -p 22


### 注意

你必须记住,对`sshd_config`所做的所有更改也会反映在 SFTP 中。因此,如果你禁用了 root 登录或使 SSH 在不同于`22`的端口上运行,当你尝试登录 SFTP 时,必须考虑到这一点。


# 第七章:构建网络

在本章中,我们将涵盖以下主题:

+   使用 CUPS 打印

+   运行 DHCP 服务器

+   使用 WebDAV 进行文件共享

+   安装和配置 NFS

+   使用 NFS

+   使用 Samba 安全共享资源

# 引言

本章是一系列食谱的集合,涵盖了当今工作环境的许多方面。从跨不同类型的办公计算机系统的打印和文件共享到保持您的计算机在线,本章提供了关于如何快速使用 CentOS 来实施必要的工具,这些工具将在您的网络环境中最大化效率的必要细节。

# 使用 CUPS 打印

**打印服务器**允许本地打印设备连接到网络并被多个用户和部门共享。使用这样的系统有很多优点,包括不需要为每个用户、房间或部门购买专用的打印机硬件。**通用 Unix 打印系统**(**CUPS**)是 Linux 以及包括 OS X 在内的 Unix 发行版上打印服务器的事实标准。它采用典型的客户端/服务器架构,网络中的客户端将打印作业发送到中央打印服务器,该服务器安排这些任务,然后将实际的打印任务委派给本地连接到我们的打印服务器的打印机,或者将打印作业远程发送到具有请求打印机的物理连接的计算机,或者发送到独立的网络打印机。如果您在 CUPS 系统中设置打印机,几乎所有 Linux 和 OS X 打印应用程序在您网络中的任何客户端上都将自动配置为开箱即用,无需安装额外的驱动程序。在这里,在本食谱中,我们将向您展示如何开始使用 CUPS 打印服务器系统。

## 准备

要完成这个食谱,您将需要一个具有 root 权限的工作 CentOS 7 操作系统安装,您选择的基于控制台的文本编辑器,以及连接到互联网以下载额外的软件包。在这个食谱中,我们将使用具有 IP 地址`192.168.1.8`的网络接口,以及相应的网络地址`192.168.1.0/24`,将 CUPS 打印服务器提供给我们的网络。

## 怎么做...

我们从这个食谱开始安装 CUPS 打印服务器软件,这在新鲜的 CentOS 7 最小系统上默认不可用:

1.  为此,以`root`身份登录并安装以下软件包:

    ```
    yum install cups

    ```

1.  接下来,为 CUPS 服务器创建一个 SSL 证书,我们将需要它来进行安全的身份验证到 CUPS Web 应用程序(在询问时添加一个安全密码):

    ```
    cd /etc/pki/tls/certs
    make cups-server.key

    ```

1.  现在,让我们打开 CUPS 主配置文件以自定义服务器(首先备份):

    ```
    cp /etc/cups/cupsd.conf /etc/cups/cupsd.conf.BAK
    vi /etc/cups/cupsd.conf

    ```

1.  首先,为了让 CUPS 在整个网络上可用,找到以下行:`Listen localhost:631`,然后将其更改为:

    ```
    Listen 631
    ```

1.  接下来,我们想要配置对基于 Web 的 CUPS 前端所有常规网页的访问。搜索`<Location />`指令(不要与其他指令如`<Location /admin>`混淆),并通过添加您的网络地址来更改整个块。更改后,整个块看起来像这样:

    ```
    <Location />
     Order allow,deny
     Allow 192.168.1.0/24
    </Location>
    ```

1.  接下来,为`/admin`和`/admin/conf Location`指令设置访问权限,仅授予本地服务器的访问权限:

    ```
    <Location /admin>
       Order allow,deny
       Allow localhost
    </Location>
    <Location /admin/conf>
       AuthType Default
       Require user @SYSTEM
       Order allow,deny
       Allow localhost
    </Location>
    ```

1.  最后,将我们的 SSL 证书信息添加到配置文件的末尾:

    ```
    ServerCertificate /etc/pki/tls/certs/cups-server.crt
    ServerKey /etc/pki/tls/certs/cups-server.key
    ```

1.  关闭并保存文件,然后重新启动 CUPS 服务器并在启动时启用它:

    ```
    systemctl restart cups.service systemctl enable cups.service

    ```

1.  现在,我们必须在 firewalld 中打开 CUPS 服务器端口,以便网络中的其他计算机可以连接到它:

    ```
    firewall-cmd --permanent --add-service=ipp firewall-cmd --reload

    ```

1.  您可以通过从`192.168.1.0/24`网络中的另一台计算机浏览以下位置来测试您的 CUPS 服务器的可访问性(在浏览器询问时允许安全异常):

    ```
    https://<IP address of your CUPS server>:631
    ```

1.  要访问 CUPS 前端内的管理区域,您需要位于运行 CUPS 的服务器上(在 CentOS 7 最小安装上,请安装窗口管理器和浏览器),然后使用系统用户`root`和适当的密码登录。

## 它是如何工作的...

在本配方中,我们向您展示了安装和设置 CUPS 打印服务器是多么容易。

那么,我们从这次经历中学到了什么?

我们的旅程始于在我们的服务器上安装 CUPS 服务器软件包,因为默认情况下 CentOS 7 系统上不可用。之后,我们生成了一个 SSL 密钥对,我们将在稍后的过程中需要它(了解更多信息,请阅读第六章中的*生成自签名证书*配方,*提供安全性*)。它用于允许通过安全的 HTTPS 连接加密提交您的登录凭据到 CUPS 管理 Web 前端。接下来,我们使用我们选择的文本编辑器打开了 CUPS 的主配置文件`/etc/cups/cupsd.conf`。如您所见,配置格式与 Apache 配置文件格式非常相似。我们开始通过删除本地主机名来更改`Listen`地址,从而允许您网络中的所有客户端(`192.168.1.0/24`)访问我们的 CUPS 服务器端口`631`,而不是仅允许本地接口连接到打印服务器。

### 注意

默认情况下,CUPS 服务器启用了`浏览功能`,它会每 30 秒向同一子网上的所有客户端计算机广播系统中所有共享打印机的更新列表。如果还想向其他子网广播,请使用`BrowseRelay`指令。

接下来,我们配置了对 CUPS Web 界面的访问。这个前端可以用来方便地浏览网络上所有可用的打印机,或者如果您使用管理员账户登录,甚至可以安装新打印机或配置它们。由于用户界面中有不同的任务,因此可以使用三个不同的指令来精细调整其访问权限。可以使用`<Location />`指令设置对所有正常网页的访问,而所有管理页面可以使用`<Location /admin>`管理,更具体地更改配置可以使用`<Location /admin/conf>`标签。在这些`Location`标签中的每一个中,我们都添加了不同的`Allow`指令,从而允许从您的完整网络(例如,`192.168.1.0/24`)访问正常的 CUPS 网页(例如,浏览所有可用的网络打印机),而访问特殊管理页面则限制为运行 CUPS 服务的`localhost`服务器。请记住,如果这对您的环境来说太严格,您可以随时调整这些`Allow`设置。此外,还有各种其他类型的`Location`可用,例如用于在其他子网中激活我们的服务的类型。请使用`man cupsd.conf`阅读 CUPS 配置手册。接下来,我们配置了 SSL 加密,从而为 Web 界面激活了安全的`https://`地址。然后,我们首次启动了 CUPS 服务器,并启用了它在服务器启动时自动启动。最后,我们添加了`ipp` firewalld 服务,从而允许 CUPS 客户端连接到服务器。

## 不仅如此...

既然我们已经成功设置并配置了 CUPS 服务器,那么是时候向其添加一些打印机并打印测试页了。在这里,我们将向您展示如何使用命令行将*两种不同*类型的打印机添加到系统中。

### 注意

使用基于图形的 Web 界面 CUPS,也可以添加或配置打印机。

首先,我们将安装一个真正的*网络*打印机,该打印机已经在我们 CUPS 服务器所在的同一网络(在我们的例子中,是`192.168.1.0/24`网络)中可用,然后是一个本地连接的打印机(例如,通过 USB 连接到我们的 CUPS 服务器或同一网络中的任何其他计算机)。

### 注意

为什么您应该将已连接的网络打印机安装到我们的 CUPS 服务器上?CUPS 不仅仅可以打印:它是一个集中式打印服务器,因此可以管理打印机及其作业的调度和队列,为不同子网中的打印机提供服务,并为任何 Linux 或 Mac 客户端提供统一的打印协议和标准,以便方便访问。

### 如何将网络打印机添加到 CUPS 服务器

要开始将网络打印机添加到我们的 CUPS 服务器,我们将使用`lpinfo -v`命令列出 CUPS 服务器已知的所有可用打印设备或驱动程序。通常情况下,CUPS 服务器会自动识别所有本地(USB、并行、串行等)和远程可用(网络协议,如`socket`、`http`、`ipp`、`lpd`等)的打印机,而不会出现任何问题。在我们的示例中,以下网络打印机已成功识别(输出已被截断):

network dnssd://Photosmart%20C5100%20series%20%5BF8B652%5D._pdl-datastream._tcp.local/


接下来,我们将把这个打印机安装到 CUPS 服务器上,使其处于其控制之下。首先,我们需要找到正确的打印机驱动程序。正如我们在最后输出中看到的,它是一台 HP Photosmart C5100 系列打印机。因此,让我们在 CUPS 服务器上所有当前安装的驱动程序列表中搜索该驱动程序:

lpinfo --make-and-model HP -m | grep Photosmart


列表中不包含我们的型号 C5100,因此我们必须使用以下命令安装额外的 HP 驱动程序包:

yum install hplip


现在,如果我们再次发出命令,我们就能找到正确的驱动程序:

lpinfo --make-and-model HP -m | grep Photosmart | grep c5100


### 注意

对于其他打印机型号和制造商,也有其他可用的驱动程序包,例如,`gutenprint-cups` RPM 包。

这个打印机的正确驱动程序将显示如下:

drv:///hp/hpcups.drv/hp-photosmart_c5100_series.ppd


现在,我们准备好使用以下语法安装打印机:

lpadmin -p -v -m -L -E


在我们的示例中,我们使用以下命令安装了它:

lpadmin -p hp-photosmart -v "dnssd://Photosmart%20C5100%20series%20%5BF8B652%5D._pdl-datastream._tcp.local/" -m "drv:///hp/hpcups.drv/hp-photosmart_c5100_series.ppd" -L room123 -E


现在,打印机应该处于我们 CUPS 服务器的控制之下,并且应该立即在整个网络中共享并被任何 Linux 或 OS X 计算机看到(在 CentOS 7 最小客户端上,你还需要首先安装`cups`包,并使用 firewalld 的`ipp-client`服务启用传入的`ipp`连接,然后我们 CUPS 服务器共享的网络打印机信息才会变得可用)。

你可以稍后通过打开并更改位于`/etc/cups/printers.conf`的文件来更改此打印机的配置。要实际打印测试页,你现在应该能够使用其名称`hp-photosmart`从任何客户端访问打印机(在 CentOS 7 最小客户端上,你需要安装`cups-client`包):

echo "Hello printing world" | lpr -P hp-photosmart -H 192.168.1.8:631


### 如何将本地打印机共享到 CUPS 服务器

如果你想将物理连接到我们 CUPS 服务器的本地打印机共享出去,只需将打印机插入系统(例如,通过 USB),然后按照之前的步骤操作,即*如何将网络打印机添加到 CUPS 服务器*。在步骤`lpinfo -v`中,你应该看到它以`usb://`地址出现,因此你需要获取这个地址并遵循剩余的步骤。

如果您想连接并共享位于 CUPS 网络中任何其他计算机上的中央 CUPS 服务器上的打印机,请在该其他计算机上安装`cups`守护程序(遵循主节中的所有步骤),然后按照本节中的说明安装打印机驱动程序。这将确保本地 CUPS 守护程序将在网络上提供打印机,就像在我们的中央 CUPS 服务器上一样。现在它已在网络上可用,您可以轻松地将其添加到我们的主 CUPS 服务器,以享受中央打印服务器带来的所有好处。

在本节中,我们仅触及了设置 CUPS 服务器的基础知识,并为您介绍了基础知识。总有更多要学习的内容,您可以构建非常复杂的 CUPS 服务器系统,在企业环境中管理数百台打印机,这超出了本节的范围。

# 运行 DHCP 服务器

如果需要建立网络连接,每台计算机都需要在其系统上安装正确的**互联网协议**(**IP**)配置才能进行通信。使用**动态主机控制协议**(**DHCP**)从*中央点*自动分配 IP 客户端配置可以使管理员的工作更轻松,并且与在网络中的每台计算机系统上手动设置静态 IP 信息相比,简化添加新机器到网络的过程。在小型家庭网络中,人们通常直接在互联网路由器上安装内置的 DHCP 服务器,但这些设备通常缺乏高级功能,并且只有一套基本的配置选项。大多数情况下,这对于大型网络或企业环境来说是不够的,在这些环境中,您更有可能找到专用的 DCHP 服务器,以应对更复杂的场景和更好的控制。在本节中,我们将向您展示如何在 CentOS 7 系统上安装和配置 DHCP 服务器。

## 准备工作

要完成本节,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器以及互联网连接,以便下载额外的软件包。预计您的 DHCP 服务器将使用静态 IP 地址;如果您没有静态 IP 地址,请参阅第二章中的“构建静态网络连接”节。如果您还计划通过 DHCP 向客户端发送 DNS 信息,则应已应用第八章中的“安装和配置简单名称服务器”节。

## 如何操作...

在本例中,我们将为静态网络接口配置 DHCP 服务器,该接口为单个网络提供所有可用的 IP 地址,所有直接连接到它的计算机(它们都在同一子网中)。

1.  首先,以`root`身份登录,并输入以下命令以安装 DHCP 服务器软件包:

    ```
    yum install dhcp

    ```

1.  在我们的示例中,我们将使用名为`ifcfg-enp5s0f1`的网络接口来处理我们的 DHCP 请求。接下来,我们需要收集一些非常重要的网络信息,我们将在稍后配置 DHCP 服务器时使用(将网络接口名称更改为适合您自己的需求):

    ```
    cat /etc/sysconfig/network-scripts/ifcfg-enp5s0f1

    ```

1.  从这次输出中,我们需要以下信息,请记下来(很可能,您的输出会有所不同):

    ```
    BOOTPROTO="static"
    IPADDR="192.168.1.8"
    NETMASK="255.255.255.0"
    GATEWAY="192.168.1.254"

    ```

1.  我们还需要子网网络地址,这可以通过以下行计算得出:

    ```
    ipcalc -n 192.168.1.8/24

    ```

1.  这将打印以下输出(请记下来以备后用):

    ```
    NETWORK=192.168.1.0

    ```

1.  现在,我们将打开主 DHCP 配置文件,在此之前,我们需要对原始文件进行备份:

    ```
    cp /etc/dhcp/dhcpd.conf /etc/dhcp/dhcpd.conf.BAK
    vi /etc/dhcp/dhcpd.conf

    ```

1.  将以下行附加到文件末尾,考虑到您在前面的步骤中从个人网络接口配置中获得的配置(`routers = GATEWAY`,`subnet = NETWORK`):

    ```
    authoriative;
    default-lease-time 28800;
    max-lease-time 86400;
    shared-network MyNetwork {
        option domain-name           "example.com";
        option domain-name-servers      8.8.8.8, 8.8.4.4;
        option routers                  192.168.1.254;
        subnet 192.168.1.0 netmask 255.255.255.0 {
            range 192.168.1.10 192.168.1.160;
        }
    }
    ```

1.  最后,启动并启用 DHCP 服务:

    ```
    systemctl start dhcpd
    systemctl enable dhcpd

    ```

## 它是如何工作的...

在本食谱中,我们向您展示了为单个网络设置 DHCP 服务器是多么容易。有了这个,每当有新机器加入网络时,计算机都会自动获得正确的 IP 信息,这是它连接到网络所必需的,无需任何进一步的人工干预。

那么,我们从这次经历中学到了什么?

我们通过安装 DHCP 服务器软件包开始了这个配方,因为它不是随 CentOS 7 一起提供的。由于我们的 DHCP 守护进程通过网络接口与其客户端通信以分配 IP 信息,因此下一步我们必须选择将用于该服务的网络设备。在我们的示例中,我们选择了名为`enp5s0f1`的设备。默认情况下,DHCP 服务器可以管理与关联网络接口相同的子网中的所有可用 IP 地址。请记住,主 DHCP 服务器的网络接口必须配置为静态获取其自己的 IP 信息,而不是通过(另一个)DHCP 服务器!接下来,我们使用`cat`命令打印出我们`enp5s0f1`网络接口配置文件中所有有趣的行,这些行我们将需要用于配置 DHCP 服务器。之后,我们使用`ipcalc`工具计算我们 DHCP 服务器的网络接口的(子网)网络地址。然后,我们打开了主 DHCP 服务器配置,开始配置一些*全局*设置,并定义了一个新的*共享网络*。在全局设置中,我们首先将我们的 DHCP 服务器设置为`authoriative`,这意味着它是网络中唯一且主要的负责 DHCP 服务器。接下来,我们将`default-lease-time`定义为`28800`秒,即八小时,将`max-lease-time`定义为`86400`,即 24 小时。租约时间是 DHCP 服务器将 IP 地址“出租”给客户端的时间,之后客户端必须再次向 DHCP 服务器注册以请求 IP 租约的延期。如果它没有在那时请求现有租约的续订,IP 地址将从客户端释放并放回空闲 IP 地址池中,准备提供给想要连接到网络的新机器。客户端可以自行定义它想要租用 IP 地址的时间。如果客户端没有向 DHCP 服务器提供时间范围,将使用默认租约时间。

所有共享同一物理网络接口的子网都应在`shared-network`声明中定义,因此我们使用方括号定义了这个区域。这也称为作用域。在我们的示例中,我们只有一个网络,因此只需要一个共享网络作用域。在其中,我们首先定义了一个`domain-name`选项,该选项将被发送并可被客户端用作其基础域名。接下来,我们将**域名服务器**(**DNS**)添加到我们的配置中。向客户端发送 DNS 信息不是 DHCP 服务器的强制要求,但可能很有用。客户端为给定网络获得的信息越多,越好,因为需要的手动配置步骤就越少。

### 注意

您可以通过 DHCP 向客户端发送有关其连接到的网络的大量其他有用信息:网关、时间、WINS 等。

在我们的示例中,我们使用了官方的 Google DNS 服务器;如果您已经设置了自己的 DNS 服务器(请参阅第八章,*使用 FTP*),您也可以在这里使用这些地址。接下来,我们指定了`routers`选项,这是另一个有用的信息,也将发送给客户端。之后,我们指定了任何 DHCP 服务器最重要的部分:`subnet`范围。在这里,我们定义了分配给客户端的 IP 地址的网络范围。我们需要提供子网网络地址、其子网掩码,然后是我们要允许客户端的开始和结束 IP 地址范围。在我们的示例中,我们允许主机 IP 地址从`192.168.1.10`,`192.168.1.11`,`192.168.1.12` ...到`192.168.1.160`。如果您有多个子网,可以使用多个`subnet`范围指令(称为多宿主 DHCP 服务器)。

接下来,我们启动了 DHCP 服务器并在启动时启用它。现在,您的客户端应该能够从我们的新系统动态获取 IP 地址。

总之,我们只向您展示了一些非常基本的 DHCP 服务器配置选项,以帮助您入门,并且还有许多其他设置可用,允许您构建非常复杂的 DHCP 服务器解决方案。要更好地了解其可能性,请查看 DHCP 服务器文档提供的示例配置文件`less /usr/share/doc/dhcp-4*/dhcpd.conf.example`。

## 还有更多...

在主配方中,我们配置了基本的 DHCP 服务器,以便能够向客户端发送完整的 IP 网络信息,使他们能够加入我们的网络。要使用此服务器,您需要在客户端的网络接口上启用 DHCP 寻址。在 CentOS 客户端上,请不要忘记使用`BOOTPROTO=dhcp`并删除所有静态条目,例如`IPADDR`在适当的网络脚本`ifcfg`文件中(阅读配方,*构建静态网络连接*在第二章,*配置系统*以帮助您开始使用网络脚本文件)。然后,要进行 DHCP 请求,请使用`systemctl restart network`重新启动网络或尝试重新启动客户端系统(使用`ONBOOT=yes`选项)。使用`ip addr list`进行确认。

# 使用 WebDAV 进行文件共享

**基于 Web 的分布式创作和版本控制**(**WebDAV**)开放标准可用于网络上的文件共享。它是一种流行的协议,可以方便地访问远程数据,就像一个*在线硬盘*。许多在线存储和电子邮件提供商通过 WebDAV 账户提供在线空间。大多数图形化的 Linux 或 Windows 系统都可以在其文件管理器中开箱即用地访问 WebDAV 服务器。对于其他操作系统,也有免费的选择。另一个很大的优势是 WebDAV 运行在普通的 HTTP 或 HTTPS 端口上,因此您可以确保它几乎在任何环境中都能工作,即使是在受限的防火墙后面。

在这里,我们将向您展示如何安装和配置 WebDAV 作为 FTP 协议的替代方案,以满足您的文件共享需求。我们将使用 HTTPS 作为我们的通信协议,以实现安全连接。

## 准备就绪

要完成本教程,您需要一个具有 root 权限的工作 CentOS 7 操作系统和一个您选择的基于控制台的文本编辑器。您需要一个在您的网络中可访问的带有 SSL 加密的工作 Apache Web 服务器;请参阅第十一章,*提供邮件服务*,了解如何安装 HTTP 守护程序,特别是*使用 SSL 设置 HTTPS*的教程。此外,熟悉 Apache 配置文件格式也是有利的。

## 如何操作…

1.  创建一个用于共享数据和 WebDAV 锁文件的位置:

    ```
    mkdir -p /srv/webdav /etc/httpd/var/davlock

    ```

1.  由于 WebDAV 作为 Apache 模块在 HTTPS 上运行,我们必须为标准`httpd`用户设置适当的权限:

    ```
    chown apache:apache /srv/webdav /etc/httpd/var/davlock
    chmod 770 /srv/webdav

    ```

1.  现在,创建并打开以下 Apache WebDAV 配置文件:

    ```
    vi /etc/httpd/conf.d/webdav.conf

    ```

1.  输入以下内容:

    ```
    DavLockDB "/etc/httpd/var/davlock"
    Alias /webdav /srv/webdav
    <Location /webdav>
        DAV On
        SSLRequireSSL
        Options None
        AuthType Basic
        AuthName webdav
        AuthUserFile /etc/httpd/conf/dav_passwords
        Require valid-user
    </Location>
    ```

1.  保存并关闭文件。现在,要添加一个名为`john`的新 WebDAV 用户(在提示时为该用户输入新密码):

    ```
    htpasswd -c /etc/httpd/conf/dav_passwords john

    ```

1.  最后,重新启动 Apache2 Web 服务器:

    ```
    systemctl restart httpd

    ```

1.  要测试我们是否可以连接到我们的 WebDAV 服务器,您可以使用任何客户端网络上的图形用户界面(大多数 Linux 文件管理器支持 WebDAV 浏览),或者我们可以使用命令行挂载驱动器。

1.  在任何客户端机器上以`root`身份登录,该机器与我们的 WebDAV 服务器位于同一网络中(在 CentOS 上,您需要从 EPEL 仓库安装`davfs2`文件系统驱动程序包,并且必须禁用文件锁的使用,因为当前版本无法与文件锁一起工作),输入我们的 DAV 用户账户名为`john`的密码,并在询问时确认自签名证书:

    ```
    yum install davfs2
    echo "use_locks 0" >> /etc/davfs2/davfs2.conf
    mkdir /mnt/webdav
    mount -t davfs https://<WebDAV Server IP>/webdav /mnt/webdav

    ```

1.  现在,让我们看看是否可以写入新的网络存储类型:

    ```
    touch /mnt/webdav/testfile.txt

    ```

1.  如果您遇到连接问题,请检查 WebDAV 服务器上的防火墙设置,以及客户端上的`http`和`https`服务。

## 它是如何工作的…

在本教程中,我们向您展示了如何轻松设置 WebDAV 服务器以实现简单的文件共享。

那么,我们从这次经历中学到了什么?

我们的旅程始于创建两个目录:一个用于存放 WebDAV 服务器的所有共享文件,另一个用于为 WebDAV 服务器进程创建锁定文件数据库。后者是必需的,以便用户可以*阻止*对文档的访问,以避免与其他人发生冲突,如果文件当前正在被他们修改。由于 WebDAV 作为本机 Apache 模块(`mod_dav`)运行,该模块在 CentOS 7 中默认启用,因此我们只需要创建一个新的 Apache 虚拟主机配置文件,我们可以在其中设置所有 WebDAV 设置。首先,我们必须将 WebDAV 主机链接到用于跟踪用户锁定的锁定数据库的完整路径。接下来,我们为 WebDAV 共享文件夹定义了一个别名,然后使用`Location`指令对其进行了配置。如果有人在`/webdav`路径 URL 上使用特定的 HTTP 方法,这将激活。在此区域内,我们指定此 URL 将是一个 DAV 启用的共享,为其启用 SSL 加密,并指定基于用户的密码身份验证。用户帐户的密码将存储在名为`/etc/httpd/conf/dav_passwords`的用户帐户数据库中。为了在此数据库文件中创建有效帐户,我们随后在命令行上使用了 Apache2 `htpasswd`实用程序。最后,我们重新启动了服务以应用我们的更改。

为了测试,我们使用了`davfs`文件系统驱动程序,您需要在 CentOS 7 上使用 EPEL 存储库中的`davfs2`包进行安装。还有许多其他选项,例如`cadaver` WebDAV 命令行客户端(也来自 EPEL 存储库);或者,您可以直接使用 GNOME、KDE 或 Xfce 等图形用户界面中的集成 WebDAV 支持来访问它。

# 安装和配置 NFS

**网络文件系统**(**NFS**)协议通过网络连接实现对文件系统的远程访问。它基于客户端-服务器架构,允许中央服务器与其他计算机共享文件。客户端可以将这些导出的共享挂载到自己的文件系统中,以便方便地访问,就像它们位于本地存储上一样。虽然 Samba 和 AFP 在 Windows 和 OS X 上更常见的分布式文件系统,但 NFS 现在已成为事实上的标准,是任何 Linux 服务器系统的关键组成部分。在本食谱中,我们将向您展示如何轻松设置 NFS 服务器以在网络上共享文件。

## 准备工作

要完成此操作,您需要具备 CentOS 7 操作系统的有效安装,具有 root 权限,您选择的基于控制台的文本编辑器以及连接到互联网以方便下载其他软件包。预计您的 NFS 服务器和所有客户端将能够相互 ping 通,并且通过静态 IP 地址相互连接(请参阅第二章,*配置系统*中的*建立静态网络连接*配方)。在我们的示例中,NFS 服务器以 IP`192.168.1.10`运行,两个客户端的 IP 分别为`192.168.1.11`和`192.168.1.12`,网络的域名为`example.com`。

## 如何操作...

在本节中,我们将学习如何安装和配置 NFS 服务器,并在客户端上创建和导出共享。

### 安装和配置 NFS 服务器

NFSv4 默认未安装,因此我们将首先下载并安装所需的软件包:

1.  为此,请以`root`身份登录到您要运行 NFS 守护程序的服务器上,并键入以下命令以安装所需的软件包:

    ```
    yum install nfs-utils

    ```

1.  为了使 NFSv4 正常工作,我们需要所有客户端和 NFS 服务器的*相同基*域。因此,如果我们尚未使用 DNS 设置域名(请参阅第九章,*域操作*),我们将在`/etc/hosts`文件中为我们的计算机设置一个新主机名:

    ```
    echo "192.168.1.10 myServer.example.com" >> /etc/hosts
    echo "192.168.1.11 myClient1.example.com" >> /etc/hosts
    echo "192.168.1.12 myClient2.example.com" >> /etc/hosts
    ```

1.  现在,打开`/etc/idmapd.conf`文件,并输入 NFS 服务器的基域名(不是完整的域名);查找读取`#Domain = local.domain.edu`的行,并将其替换为以下内容:

    ```
    Domain = example.com
    ```

1.  接下来,我们需要为服务器打开一些防火墙端口,以便它具有适当的 NFS 访问权限:

    ```
    for s in {nfs,mountd,rpc-bind}; do firewall-cmd --permanent --add-service $s; done; firewall-cmd --reload

    ```

1.  最后,让我们启动 NFS 服务器服务并在重启时启用它:

    ```
    systemctl start rpcbind nfs-server systemctl enable rpcbind nfs-server systemctl status nfs-server

    ```

### 创建导出共享

既然我们的 NFS 服务器已配置并运行,现在是时候创建一些文件共享,我们可以将其导出到我们的客户端:

1.  首先,让我们为我们的共享创建一个文件夹并更改其权限:

    ```
    mkdir /srv/nfs-data

    ```

1.  创建一个具有特定 GID 的新组,并将其与导出关联,然后更改权限:

    ```
    groupadd -g 50000 nfs-share;chown root:nfs-share /srv -R;chmod 775 /srv -R

    ```

1.  打开以下文件:

    ```
    vi /etc/exports

    ```

1.  现在,输入以下文本,但输入时要非常专注:

    ```
    /srv/nfs-data *(ro) 192.168.1.11(rw) 192.168.1.12(rw) /home *.example.com(rw)

    ```

1.  保存并关闭文件,然后使用以下命令重新导出`/etc/exports`中的所有条目:

    ```
    exportfs -ra

    ```

## 它是如何工作的...

在 CentOS 7 上,您可以安装版本 4 的 NFS,它比以前的版本有一些增强,例如更灵活的认证选项,并且与旧版本的 NFS 完全向后兼容。在这里,我们向您展示了安装和配置 NFS 服务器以及为我们的客户端创建一些共享导出是多么容易。

那么,我们从这次经历中学到了什么?

我们首先通过安装`nfs-utils`包来启动这个配置过程,因为在 CentOS 7 上默认情况下 NFS 服务器功能是不可用的。接下来,我们使用`/etc/hosts`文件配置了服务器域名,因为在我们的示例中,我们还没有配置自己的 DNS 服务器。如果你已经设置了 DNS 服务器,你应该遵循与此处类似的域名模式,因为这对 NFSv4 的正常工作至关重要,因为所有客户端和服务器都应该位于同一个基本域中。在我们的示例中,我们指定了它们都是`example.com`的子域:`myClient1.example.com`,`myClient2.example.com`和`myServer.example.com`。这是一种确保数据共享安全的方法,因为 NFS 服务器只允许来自客户端的文件访问,如果域名匹配(在我们的示例中,服务器和客户端都是`example.com`域的一部分)。接下来,我们将这个基本域放入`idmapd.conf`文件中,该文件负责将用户名和组 ID 映射到 NFSv4 ID。之后,我们在 firewalld 实例中启用了`nfs`,`mountd`和`rpc-bind`服务,这些都是客户端和服务器之间完整支持和通信所必需的。为了完成我们的基本配置,我们启动了`rpcbind`和 NFS 服务器,并设置了开机自启。

在成功设置 NFS 服务器之后,我们为其添加了一些导出项,实际上允许客户端从服务器访问一些共享文件夹。因此,我们在文件系统中创建了一个特殊的目录,用于存放我们所有的共享文件。我们将这个共享文件夹`/srv/nfs-data`与一个新组`nfs-share`关联,并赋予其读/写/执行权限。出于实际原因,我们将在组级别上控制我们的导出 Linux 文件权限。名称并不重要,但其组标识符(GID)必须设置为静态值(例如,`50000`)。这个新的 GID 在服务器和每个客户端上都必须相同,对于每个想要拥有写权限的用户来说,因为 NFS 在服务器和客户端之间通过用户(UID)或 GID 级别在网络上传递任何访问权限。整个共享的魔法发生在`/etc/exports`文件中。它包含一个表格;在其中,你指定了所有关于你的共享文件夹及其客户端访问安全性的重要信息。这个文件中的每一行都相当于系统中的一个共享文件夹,以及一个允许访问它们的以空格分隔的主机列表,以及它们的访问选项。如你所见,有不同的方法来定义目标客户端,使用 IP 地址或主机名。对于主机名,你可以使用通配符如`*`和`?`来使文件更紧凑,并允许一次多个机器,但你也可以为每个单独的主机名定义导出选项。解释所有选项超出了本书的范围;如果你需要更多帮助,请阅读导出手册,可以通过`man exports`找到。

例如,行 `/srv/nfs-data *(ro) 192.168.1.11(rw) 192.168.1.12(rw)` 定义了我们希望将 `/srv/nfs-data` 文件夹的内容导出到所有主机名(因为使用了 `*` 符号);只读 (`ro`) 意味着每个客户端都可以读取文件夹的内容但不能写入。对于 IP 地址以 `192.168.1` 结尾,且末尾为 `11` 和 `12` 的客户端,我们允许读写 (`rw`)。第二行定义了我们正在将 `/home` 目录导出到 `*.example.com` 子域中的所有客户端,并具有读写能力。每当您对 `/etc/exports` 文件进行更改时,运行 `exportfs -r` 命令以将更改应用到 NFS 服务器。

最后,我们可以说在 CentOS 7 中设置和启动 NFSv4 非常容易。它是 Linux 系统之间共享文件或集中式家目录的完美解决方案。

# 使用 NFS

在客户端计算机可以使用 NFS 服务器共享的文件系统导出之前,它必须配置为正确访问该系统。在本步骤中,我们将向您展示如何在客户端机器上设置和使用 NFS。

## 准备工作

要完成此操作,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,您选择的基于控制台的文本编辑器,以及互联网连接以便下载额外的软件包。我们假设您已经遵循了 *安装和配置 NFS* 的步骤,并已经设置了一个 NFS 服务器,例如在本例中。我们假设所有客户端都可以相互 ping 通,并且连接到了 NFS 服务器,并且将使用静态 IP 地址(请参阅 第二章 *系统配置* 中的 *建立静态网络连接* 步骤)。在我们的示例中,NFS 服务器运行在 IP `192.168.1.10` 上,两个客户端分别在 IP `192.168.1.11` 和 `192.168.1.12` 上。

## 操作步骤...

在我们的客户端系统上,我们也需要相同的 NFS 软件包,以及与服务器上类似的配置,以便在它们之间建立通信:

1.  首先,以 `root` 身份登录到您的客户端,并应用与 *安装和配置 NFS* 步骤中完全相同的步骤,直到步骤 3 结束。跳过步骤 4,因为不需要打开 firewalld 服务。然后,在步骤 5 中,使用以下命令,这些命令不会启动和启用 `nfs-server`,而只会启动 `rpcbind` 服务:

    ```
    systemctl start rpcbind
    systemctl enable rpcbind

    ```

1.  在此停止,不要应用原始步骤中的其他内容。为了测试与我们的 NFS 服务器的连接,请使用以下命令:

    ```
    showmount -e myServer.example.com

    ```

1.  现在,为了测试挂载 NFS 导出是否有效,您可以手动使用新用户 `john` 进行测试。首先需要将 `john` 添加到 `nfs-share` 组中,以便我们可以在共享上进行写操作:

    ```
    groupadd -g 50000 nfs-share;useradd john;passwd john;usermod -G nfs-share john
    mount -t nfs4 myServer.example.com:/srv/nfs-data /mnt
    su - john;touch /mnt/testfile.txt

    ```

1.  如果在共享目录中创建文件成功,您可以将导入项放入`fstab`文件中,以便在系统启动时自动挂载:

    ```
    vi /etc/fstab

    ```

1.  添加以下行:

    ```
    myServer.example.com:/srv/nfs-data  /mnt nfs defaults 0 0

    ```

1.  最后,要从`fstab`重新挂载所有内容,请键入以下内容:

    ```
    mount -a

    ```

## 它是如何工作的...

在本食谱中,我们向您展示了从现有的 NFSv4 服务器使用一些共享文件系统导出是多么容易。

那么,我们从这次经历中学到了什么?

正如您所见,要设置 NFS 客户端,您需要与 NFS 服务器本身非常相似的设置,除了启动`rpcbind`服务而不是`nfs-server`(顾名思义,仅在服务器端需要)。`rpcbind`服务是一个端口映射器,用于**远程过程调用**(**RPC**),这是 NFS 工作所需的通信标准。在配置中您应该记住的另一个非常重要的步骤是在`/etc/idmapd.conf`文件中设置域名。我们必须在服务器上使用*相同*的基本域名(`example.com`),以便在服务器和客户端之间进行 NFSv4 通信。在启动并启用`rpcbind`服务后,我们可以将 NFS 共享挂载到本地目录,要么直接使用`mount`命令(使用`-t`类型`nfs4`),要么通过`fstab`文件。请记住,每个想要对共享具有适当的读/写/执行权限的系统用户都需要在 NFS 服务器上具有*相同*的权限;在我们的示例中,我们在相同的 GID 级别上管理正确的权限。我们使用默认选项挂载共享;如果您需要不同的或高级的选项,请参阅`man fstab`。为了应用对`fstab`文件的更改,执行`mount -a`以从该文件重新挂载所有内容。

# 使用 Samba 安全地共享资源

**Samba**是一个软件包,它使您能够跨网络共享文件、打印机和其他常见资源。对于任何工作环境来说,它都是一个无价的工具。在异构网络(即不同的计算机系统,如 Windows 和 Linux)上共享文件资源的最常见方式之一是安装和配置 Samba 作为独立文件服务器,通过*用户级安全*使用系统用户的家目录提供基本的文件共享服务。独立服务器被配置为提供本地身份验证和对其维护的所有资源的访问控制。总而言之,每个管理员都知道 Samba 仍然是一个非常流行的开源发行版,本食谱的目的是向您展示如何提供一种即时文件共享方法,该方法可以在整个工作环境中无缝集成任何数量的用户在任何类型的现代计算机上。

## 准备

要完成此配方,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,您选择的基于控制台的文本编辑器,以及连接到 Internet 以便下载其他软件包。预计您的服务器将使用静态 IP 地址。

## 如何操作...

Samba 默认不安装,因此我们将从下载和安装所需软件包开始。

1.  为此,以`root`身份登录并键入以下命令以安装所需的软件包:

    ```
    yum install samba samba-client samba-common

    ```

1.  完成此操作后,第一步是重命名原始配置文件:

    ```
    mv /etc/samba/smb.conf /etc/samba/smb.conf.BAK

    ```

1.  现在,在您喜欢的文本编辑器中创建一个新的配置文件,方法是键入以下内容:

    ```
    vi /etc/samba/smb.conf

    ```

1.  开始构建新的配置,方法是添加以下行,将显示的值替换为更好地代表您自己需求的值:

    ```
    [global]
    unix charset = UTF-8
    dos charset = CP932
    workgroup = <WORKGROUP_NAME>
    server string = <MY_SERVERS_NAME>
    netbios name = <MY_SERVERS_NAME>
    dns proxy = no
    wins support = no
    interfaces = 127.0.0.0/8 XXX.XXX.XXX.XXX/24 <NETWORK_NAME>
    bind interfaces only = no
    log file = /var/log/samba/log.%m
    max log size = 1000
    syslog only = no
    syslog = 0
    panic action = /usr/share/samba/panic-action %d
    ```

    ### 注意

    `WORKGROUP_NAME`是 Windows 工作组的名称。如果您没有此值,请使用标准 Windows 名称`WORKGROUP`。`MY_SERVERS_NAME`指的是您的服务器名称。在大多数情况下,这可能是`FILESERVER`或`SERVER1`等形式。`XXX.XXX.XXX.XXX/XX`指的是 Samba 服务运行的主要网络地址,例如`192.168.1.0/24`。`NETWORK_NAME`指的是您的以太网接口的名称。这可能是`enp0s8`。

1.  现在,我们将配置 Samba 作为独立服务器。为此,只需继续将以下行添加到主配置文件中:

    ```
    security = user
    encrypt passwords = true
    passdb backend = tdbsam
    obey pam restrictions = yes
    unix password sync = yes
    passwd program = /usr/bin/passwd %u
    passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
    pam password change = yes
    map to guest = bad user
    usershare allow guests = no
    ```

1.  对于这个配方,我们不打算将 Samba 配置为域主或主浏览器。为此,添加以下行:

    ```
    domain master = no
    local master = no
    preferred master = no
    os level = 8
    ```

1.  现在,我们将添加对主目录共享的支持,允许有效用户访问其主目录。此功能将支持适当的读/写权限,并且所有文件夹都将保持对其他用户的私密性。为此,添加以下新行:

    ```
    [homes]
         comment = Home Directories
         browseable = no
         writable = yes
         valid users = %S
         create mask =0755
         directory mask =0755
    ```

1.  保存并关闭文件。要测试我们刚刚创建的 Samba 配置文件的语法,请使用以下命令:

    ```
    testparm

    ```

1.  现在,将现有系统用户`john`添加到 Samba 用户管理系统(这是为了稍后测试;请根据您系统上的用户名适当更改):

    ```
    smbpasswd -a john

    ```

1.  现在,保存文件并关闭它;回到命令行,打开防火墙中的端口:

    ```
    firewall-cmd --permanent --add-service=samba && firewall-cmd --reload

    ```

1.  配置 SELinux 以使用 Samba 主目录:

    ```
    setsebool -P samba_enable_home_dirs on

    ```

1.  现在,确保`samba`和`nmb`服务将在启动过程中启动,并立即启动它们:

    ```
    systemctl enable smb && systemctl enable nmb systemctl start smb && systemctl start nmb

    ```

## 它是如何工作的...

本配方的目的是安装 Samba 并配置其文件共享服务,从而为您的网络中的所有现代计算机系统提供完全的连接性。

那么,我们从这次经历中学到了什么?

安装了必要的软件包后,我们将原始安装的配置文件重命名,以便在以后出现问题时备份,然后我们开始从头设置 Samba,从空白的`smb.conf`配置文件开始。打开这个新文件后,我们开始设置全局配置选项;第一步是声明与基于 Unicode 的字符集兼容。您需要注意,由于您的具体情况和网络,值可能会有所不同。更多信息请参阅`man smb.conf`。

完成这一步后,我们接着确认了工作组和服务器的名称,禁用了 WINS,建立了 Samba 日志文件,并注册了网络接口。然后,我们选择了以下独立选项,包括基于用户的安全选项、密码加密和`tdbsam`数据库后端。首选的安全模式是用户级安全,采用这种方法意味着每个共享可以分配给特定用户。因此,当用户请求连接共享时,Samba 通过验证配置文件和 Samba 数据库中的授权用户提供的用户名和密码来验证此请求。接下来,我们添加了`master`信息。在混合操作系统环境中,当单个客户端试图成为主浏览器时,将产生已知的冲突。这种情况可能不会破坏整个文件共享服务,但会在 Samba 日志文件中记录潜在问题。因此,通过配置 Samba 服务器不声明自己为主浏览器,您将能够降低此类问题被报告的可能性。因此,完成这些步骤后,该方案接下来考虑了启用`homes`目录文件共享的主要任务。当然,您可以尝试显示的选项,但这一简单的指令集不仅确保了有效用户能够使用相关的读/写权限访问其主目录,而且通过将`browseable`标志设置为`no`,您还能够隐藏主目录,使其不在公共视图中显示,从而为用户提供更高程度的隐私。在我们的设置中,Samba 与您的 Linux 系统用户配合工作,但您应该记住,任何现有或新用户都不会自动添加到 Samba 中,必须使用`smbpasswd -a`手动添加。

因此,在保存您的新配置文件后,我们使用`testparm`程序测试其正确性,并使用`samba`服务在 firewalld 中打开与 Samba 相关的传入端口。下一步是确保在启动过程中使用`systemctl`使 Samba 及其相关进程可用。Samba 为了正确工作需要两个主要进程:`smbd`和`nmbd`。从`smbd`开始,该服务的角色是为使用 SMB(或 CIFS)协议的 Windows 客户端提供文件共享、打印服务、用户认证和资源锁定。同时,`nmbd`服务的角色是监听、理解和回复 NetBIOS 名称服务的请求。

### 注意

Samba 通常包括另一个名为`winbindd`的服务,但由于提供基于**Windows Internet Naming Service**(**WINS**)的服务或 Active Directory 认证需要额外的考虑,这超出了本食谱的范围,因此它被广泛忽略。

因此,我们的最终任务是启动 Samba 服务(`smb`)和相关的 NetBIOS 服务(`nmb`)。

您现在知道安装、配置和维护 Samba 是多么简单。总有更多要学习的内容,但这个简单的介绍已经说明了 Samba 的相对易用性和其语法的简单性。它提供了一个解决方案,能够支持各种不同的需求和一系列不同的计算机系统,它将满足您未来多年的文件共享需求。

## 还有更多...

您可以从网络中的任何客户端测试我们的 Samba 服务器配置,只要该客户端可以 ping 通服务器。如果是基于 Windows 的客户端,请打开**Windows 资源管理器**地址栏,并使用以下语法:`\\<Samba 服务器的 IP 地址>\<Linux 用户名>`。例如,我们使用`\\192.168.1.10\john`(成功连接后,您需要输入 Samba 用户名的密码)。在任何 Linux 客户端系统上(在 CentOS 7 上需要安装`samba-client`包),要列出 NFS 服务器的所有可用共享,请使用以下命令:

smbclient -L -U


在我们的示例中,我们将使用以下内容:

smbclient -L 192.168.1.10 -U john


要进行测试,请使用以下语法挂载共享(这需要在 CentOS 7 上安装`cifs-utils`包):

mount -t cifs /// -o "username="


在我们的示例中,我们将使用以下内容:

mkdir /mnt/samba-share
mount -t cifs //192.168.1.10/john /mnt/samba-share -o "username=john"


您还可以将此导入放入`/etc/fstab`文件中以进行永久挂载,使用以下语法:

/// cifs 0 0


例如:

例如,向文件中添加以下行:

//192.168.1.10/john /mnt/samba-share cifs username=john,password=xyz 0 0


如果您不想在此文件中使用明文密码,请阅读有关使用`man mount.cifs`的凭据的部分,然后创建一个凭据文件,并使用`chmod 600`在您的主目录中保护它,以确保没有其他人可以读取它。

在本章中,我们向您展示了如何将 Samba 配置为独立服务器并启用家目录,以及如何从客户端连接到它以开始使用。但 Samba 的功能远不止于此!它可以提供打印服务或充当完整的域控制器。如果您想了解更多信息,请随时访问[`www.packtpub.com/`](https://www.packtpub.com/)以了解其他可用材料。


# 第八章:使用 FTP

在本章中,我们将介绍以下主题:

+   安装和配置 FTP 服务

+   使用虚拟 FTP 用户

+   定制 FTP 服务

+   解决用户和文件传输问题

# 引言

本章是一系列操作的集合,提供了揭示 Linux 世界中最基本服务之一的步骤,并提供了安装、配置和无犹豫地提供文件传输协议所需的起点。

# 安装和配置 FTP 服务

尽管存在几种现代且非常安全的网络文件共享技术,但古老的**文件传输协议**(**FTP**)仍然是计算机之间共享和传输文件的最广泛使用的协议之一。在 Linux 世界中,有多种不同的 FTP 服务器可用。在本操作中,您将学习如何安装和配置**非常安全的 FTP 守护程序**(**vsftpd**),这是一个著名的 FTP 服务器解决方案,支持广泛的功能,并允许您在本地网络和互联网上上传和分发大文件。在这里,我们将展示如何安装 vsftpd 守护程序,并提供一些基本设置,主要目标是提高守护程序的安全性。

### 注意

完成此操作后,建议使用 SSL/TLS 加密以进一步增强您的 FTP 服务器(请参阅第六章,*使用 SELinux*,以了解更多关于 SELinux 的信息。接下来,我们在`systemd`中启用`vsftpd`开机启动并启动服务。此时,`vsftpd`将开始运行,并且可以使用任何常规的 FTP 桌面软件进行测试。用户可以使用有效的系统用户名和密码通过连接到服务器的名称、域或 IP 地址(取决于服务器的配置)进行登录。

本食谱的目的是向你展示`vsftpd`并不是一个难以安装和配置的软件包。总有很多事情要做,但是通过这个简单的介绍,我们已经迅速启用了我们的服务器来运行标准的 FTP 服务。

## 还有更多...

安装并配置了基本的 FTP 服务后,你可能会想知道如何将用户引导到其主目录中的特定文件夹。为此,打开你选择的编辑器中的主配置文件`/etc/vsftpd/vsftpd.conf`。

滚动到文件底部,并通过将`<users_local_folder_name>`值替换为更适合你需求的值来添加以下行:

local_root=<users_local_folder_name>


例如,如果这个 FTP 服务器主要是为了访问和上传用户私人网页的内容,而这些网页托管在同一服务器上,你可能需要配置 Apache 使用用户的主目录中的一个名为/`home/<username>/public_html`的文件夹。为此,你可以在`vsftpd`配置文件的底部添加以下参考:

local_root=public_html


完成后,保存并关闭配置文件,然后重新启动`vsftpd`服务。在测试此新功能时,请确保`local_root`位置存在于你想要登录的用户的家目录中(例如,`~/public_html`)。

# 使用虚拟 FTP 用户

在本食谱中,你将学习如何实现虚拟用户,以摆脱使用本地系统用户账户的限制。在你的服务器生命周期中,可能会有时候你希望为没有本地系统账户的用户启用 FTP 认证。你可能还希望考虑实施一个解决方案,允许特定个人维护多个账户,以便访问服务器上的不同位置。这种配置意味着使用虚拟用户提供了一定程度的灵活性。由于你不是使用本地系统账户,可以说这种方法提供了改进的安全性。

## 准备就绪

要完成此步骤,你需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,以及你选择的基于控制台的文本编辑器。预计你的服务器将使用静态 IP 地址,并且`vsftpd`已经安装了 chroot 监狱并且正在运行。此步骤需要安装`policycoreutils-python`包。

## 如何做到这一点...

1.  第一步是作为 root 登录到我们的`vsftpd`服务器,并创建一个名为`virtual-users.txt`的纯文本文件,该文件维护虚拟用户的用户名和密码列表。为此,请输入以下命令:

    ```
    vi /tmp/virtual-users.txt

    ```

1.  现在以以下方式添加你的用户名和相应的密码:

    ```
    virtual-username1
    password1
    virtual-username2
    password2
    virtual-username3
    password3

    ```

    ### 注意

    根据需要为每个用户重复此过程,但出于明显的原因,请保持良好的密码策略,并且不要重复使用同一个虚拟用户名。

1.  完成操作后,只需按照常规方式保存并关闭文件。然后,通过输入以下命令来构建数据库文件:

    ```
    db_load -T -t hash -f /tmp/virtual-users.txt /etc/vsftpd/virtual-users.db

    ```

1.  完成此操作后,我们现在将创建将使用此数据库验证虚拟用户的 PAM 文件。为此,请输入以下命令:

    ```
    vi /etc/pam.d/vsftpd-virtual

    ```

1.  现在添加以下行:

    ```
    auth required pam_userdb.so db=/etc/vsftpd/virtual-users
    account required pam_userdb.so db=/etc/vsftpd/virtual-users

    ```

1.  完成后,按照常规方式保存并关闭文件。按照以下方式在你的首选文本编辑器中打开主`vsftpd`配置文件:

    ```
    vi /etc/vsftpd/vsftpd.conf

    ```

1.  现在,在打开的文件中,找到`pam_service_name=vsftpd`行,并通过在行首添加`#`符号来禁用它,使其读作如下:

    ```
    #pam_service_name=vsftpd

    ```

1.  向下滚动到文件底部,并通过自定义`local_root`的值以满足你自己的特定需求来添加以下行——这将是所有虚拟用户将*居住*的基本目录(例如,我们将使用`/srv/virtualusers/$USER`,如下所示):

    ```
    virtual_use_local_privs=YES
    guest_enable=YES
    pam_service_name=vsftpd-virtual
    user_sub_token=$USER
    local_root=/srv/virtualusers/$USER
    hide_ids=YES

    ```

1.  现在在你之前定义的`/tmp/virtual-users.txt`文件中为每个虚拟用户创建一个子文件夹,并在你使用`local_root`指令指定的目录中。记得将此文件夹的所有权委派给 FTP 用户。为了保持我们的`/srv/virtualusers`示例,我们将使用以下命令以自动方式执行此操作(再次,如果需要,请自定义`/srv/virtualusers`目录):

    ```
    for u in `sed -n 1~2p /tmp/virtual-users.txt`;
    do
    mkdir -p /srv/virtualusers/$u
    chown ftp: /srv/virtualusers/$u
    done

    ```

1.  现在我们需要通知 SELinux 允许对我们的自定义`local_root`目录进行读/写访问,该目录位于典型的`/home`目录之外:

    ```
    setsebool -P allow_ftpd_full_access on
    semanage fcontext -a -t public_content_rw_t "/srv/virtualusers(/.*)?"
    restorecon -R -v /srv/virtualusers

    ```

1.  接下来,按照以下方式重新启动 FTP 服务:

    ```
    systemctl restart vsftpd

    ```

1.  出于安全原因,现在删除纯文本文件,并使用以下命令保护生成的数据库文件:

    ```
    rm /tmp/virtual-users.txt
    chmod 600 /etc/vsftpd/virtual-users.db

    ```

## 它是如何工作的...

遵循前面的步骤后,你现在将能够邀请无限数量的虚拟用户访问你的 FTP 服务。此功能的配置非常简单;你的整体安全性得到了提升,并且所有访问都限制在你选择的定义的`local_root`目录中。请注意,使用虚拟用户将禁用系统用户从第一个步骤登录到 FTP 服务器。

那么我们从这次经历中学到了什么?

我们首先创建了一个新的临时文本文件,该文件将包含我们所有用户名及其对应的明文密码。然后,我们逐个添加所有必需的用户名和密码,每行一个。完成对每个虚拟用户的这一步骤后,我们保存并关闭了文件,然后运行了 CentOS 7 默认安装的`db_load`命令。该命令用于从我们的文本文件生成一个 BerkeleyDB 数据库,稍后将用于 FTP 用户认证。完成这一步骤后,我们的下一个任务是在`/etc/pam.d/vsftpd-virtual`创建一个 Pluggable Authentication Modules(PAM)文件。该文件读取前面的数据库文件,使用典型的 PAM 配置文件语法(更多信息,请参阅`man pam.d`)为我们的`vsftpd`服务提供认证。然后,我们打开、修改并添加新的配置指令到主`vsftpd`配置文件`/etc/vsftpd/vsftpd.conf`,以便让`vsftpd`通过 PAM 意识到我们的虚拟用户认证。

最重要的设置是`local_root`指令,它定义了所有虚拟用户目录的基本位置。别忘了在路径末尾加上`$USER`字符串。然后,您被提示为文本文件中定义的每个虚拟用户创建相关的虚拟主机文件夹。

由于虚拟用户不是真正的系统用户,我们必须将 FTP 系统用户分配给我们的新 FTP 用户,以完全拥有这些文件。我们使用 bash `for`循环来自动化对临时`/tmp/virtual-users.txt`文件中定义的所有用户的处理过程。接下来,我们设置了正确的 SELinux 布尔值,以允许虚拟用户访问系统,并为我们的`/srv/virtualusers`目录设置了正确的上下文。应用所有这些更改只需使用`systemctl`命令重新启动`vsftpd`服务。

之后,我们删除了包含我们明文密码的临时用户文本文件。我们通过删除除 root 之外的所有访问权限来保护 BerkeleyDB 数据库文件。如果您定期更新、添加或删除 FTP 用户,最好不要删除这个临时明文`/tmp/virtual-users.txt`文件,而是将其放在安全的地方,例如`/root`目录。然后,您应该使用`chmod 600`来保护它。然后,每当您对这个文件进行更改时,都可以重新运行`db_load`命令以保持用户信息的最新状态。如果您需要在以后添加新用户,您还必须为他们创建新的虚拟用户文件夹(请重新运行第 9 步的命令)。之后运行`restorecon -R -v /srv/virtualusers`命令。

现在,您可以通过使用本菜谱中创建的新账户登录 FTP 服务器来测试您的新虚拟用户账户。

# 自定义 FTP 服务

在本教程中,您将学习如何自定义您的`vsftpd`安装。`vsftpd`有许多配置参数,这里我们将展示如何创建一个自定义欢迎横幅,更改服务器的默认超时时间,限制用户连接,以及禁止用户访问服务。

## 准备就绪

要完成本教程,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装和一个您选择的基于控制台的文本编辑器。预计您的服务器将使用静态 IP 地址,并且`vsftpd`已经安装了 chroot 监狱并且正在运行。

## 如何做到这一点...

1.  首先,以 root 身份登录并打开主要的`vsftpd`配置文件:

    ```
    vi /etc/vsftpd/vsftpd.conf

    ```

1.  首先提供一个替代的欢迎信息,取消注释以下行,并根据需要修改信息。例如,您可以使用这个:

    ```
    ftpd_banner=Welcome to my new FTP server

    ```

1.  要更改默认 FTP 超时时间,取消注释这些行并根据需要替换数值:

    ```
    idle_session_timeout=600
    data_connection_timeout=120

    ```

1.  现在,我们将限制连接:数据传输速率每秒字节数,客户端数量,以及每个 IP 地址的最大并行连接数。在文件末尾添加以下行:

    ```
    local_max_rate=1000000
    max_clients=50 
    max_per_ip=2

    ```

1.  接下来,保存并关闭文件。要禁止特定用户,您可以使用以下命令,同时将用户名替换为适合您需求的适当系统用户值:

    ```
    echo "username" >> /etc/vsftpd/user_list

    ```

1.  现在要应用更改,请重启 FTP 服务:

    ```
    systemctl restart vsftpd

    ```

## 它是如何工作的...

在本教程中,我们已经展示了一些最重要的`vsftpd`设置。涵盖所有配置参数超出了本教程的范围。要了解更多信息,请阅读整个主要的`vsftpd`配置文件`/etc/vsftpd/vsftpd.conf`,因为它包含了许多有用的注释;或者,您可以阅读`man vsftpd.conf`手册。

那么我们从这次经历中学到了什么?

我们首先打开主要的`vsftpd`配置文件,然后使用`ftpd_banner`指令激活并自定义欢迎横幅。在下次成功登录时,您的用户应该看到您的新消息。接下来,当处理大量用户时,您可能想要考虑更改默认超时值并限制连接,以提高您的 FTP 服务的效率。

首先,我们更改了服务器的超时数值。`idle_session_timeout`为`600`秒将使在 10 分钟内不活跃(未执行 FTP 命令)的用户注销,而`data_connection_timeout`为`120`秒将在客户端数据传输停滞(未进展)20 分钟后终止连接。然后我们更改了连接限制。`local_max_rate`为`1000000`字节每秒将限制单个用户的数据传输速率大约为每秒一兆字节。`max_clients`值为`50`将告诉 FTP 服务器只允许 50 个并行用户访问系统,而`max_per_ip`为`2`只允许每个 IP 地址两个连接。

然后我们保存并关闭了文件。最后,我们展示了如何禁止用户使用我们的 FTP 服务。如果您想禁止特定用户使用 FTP 服务,则应将该用户的名称添加到`/etc/vsftpd/user_list`文件中。如果您需要随时重新启用该用户,只需通过从`/etc/vsftpd/user_list`中删除相关用户来反转之前的操作。

# 解决用户和文件传输问题

分析日志文件是解决 Linux 上各种问题或改进服务最重要的技术。在本教程中,您将学习如何配置和启用 vsftpd 的广泛日志记录功能,以帮助系统管理员在出现问题时或仅监视此服务的使用情况。

## 准备就绪

要完成本教程,您需要具备具有 root 权限的 CentOS 7 操作系统的有效安装,以及您选择的基于控制台的文本编辑器。预计您的服务器将使用静态 IP 地址,并且`vsftpd`已经安装了 chroot 监狱并正在运行。

## 如何做到这一点...

1.  要执行此操作,请以 root 身份登录,并键入以下命令以使用您喜欢的文本编辑器打开主配置文件:

    ```
    vi /etc/vsftpd/vsftpd.conf

    ```

1.  现在,将以下行添加到配置文件的末尾,以启用详细的日志记录功能:

    ```
    dual_log_enable=YES
    log_ftp_protocol=YES

    ```

1.  最后,重新启动`vsftpd`守护程序以应用更改:

    ```
    systemctl restart vsftpd

    ```

## 它是如何工作的...

在本教程中,我们展示了如何启用两个独立的日志记录机制:首先,`xferlog`日志文件将记录有关用户上传和下载的详细信息,然后是`vsftpd`日志文件,其中包含客户端和服务器之间的每个 FTP 协议事务,输出`vsftpd`可能的最详细的日志信息。

那么我们从这次经历中学到了什么?

在本教程中,我们打开了主要的`vsftpd`配置文件,并在文件末尾添加了两条指令。首先,`dual_log_enable`确保`xferlog`和`vsftpd`日志文件都将用于记录日志。之后,我们通过启用`log_ftp_protocol`来增加`vsftpd`日志文件的详细程度。

重新启动服务后,`/var/log/xferlog`和`/var/log/vsftdp.log`这两个日志文件将被创建并填充有用的 FTP 活动信息。现在,在我们打开文件之前,让我们创建一些 FTP 用户活动。使用`ftp`命令行工具在服务器上以任何 FTP 用户身份登录,并在`ftp>`提示符下发出以下 FTP 命令,将客户端上的随机文件上传到服务器:

put ~/.bash_profile bash_profile_test


现在,回到服务器上,检查`/var/log/xferlog`文件以查看有关上传文件的详细信息,并打开`/var/log/vsftpd.log`以查看其他用户活动(例如登录时间或其他用户发出的 FTP 命令)。

请注意,日志文件仅记录用户和 FTP 活动,并不用于调试`vsftpd`服务的问题,例如配置文件错误。要调试服务的一般问题,请使用`systemctl status vsftpd -l`或`journalctl -xn`。


# 第九章:使用域

在本章中,我们将涵盖:

+   安装和配置仅缓存名称服务器

+   设置仅授权的名称服务器

+   创建集成名称服务器解决方案

+   填充域

+   构建一个辅助(从属)DNS 服务器

# 引言

本章是一系列尝试揭开网络世界中使一切正常工作的关键组件技术的神秘面纱的章节。从电子邮件到网页,从远程登录到在线聊天,本章提供了使用 CentOS 快速提供域名服务所需的详细信息,该服务将为您的办公环境提供动力。

# 安装和配置仅缓存名称服务器

计算机之间的每项网络通信只能通过使用唯一 IP 地址来识别通信的确切端点。对于人脑来说,数字总是比给*事物*命名更难记住和工作。因此,IT 先驱从 70 年代初开始发明将名称转换为物理网络地址的系统,使用文件和后来的简单数据库。在现代计算机网络和互联网上,计算机名称与 IP 地址之间的关系在**域名系统**(**DNS**)数据库中定义。它是一个全球分布式系统,提供域名到 IP 地址的解析,以及反向解析,即 IP 地址到域名的解析。DNS 是一个庞大的主题,本章的目的是通过向您展示如何安装和设置自己的仅缓存和转发名称服务器,为您提供完美的起点。我们将使用*Unbound*,这是一个高度安全且快速的递归和缓存 DNS 服务器解决方案,因此是我们的首选。但您需要记住,Unbound 不能用作完全授权的 DNS 服务器(这意味着它提供自己的域名解析记录),我们将在后面的章节中使用流行的 BIND 服务器。仅缓存 DNS 服务器将用于将所有名称解析查询转发到远程 DNS 服务器。这样的系统旨在通过缓存任何域名解析请求的结果来加快对互联网的总体访问。当缓存 DNS 服务器找到客户端查询的答案时,它将答案返回给客户端。但是,它还将答案存储在其缓存中一段时间。然后,缓存可以用作后续请求的来源,以加快总往返时间。

## 准备就绪

要完成此操作,您需要一个具有 root 权限、静态 IP 地址和您选择的基于控制台的文本编辑器的 CentOS 7 操作系统的工作安装。下载额外软件包时需要互联网连接。在本例中,我们的 DNS 服务器在具有网络地址`192.168.1.0/24`的私有网络中运行。

## 如何操作...

在本食谱中,我们将首先配置一个*仅缓存*的 DNS 服务器,然后是一个*仅转发*的 DNS 服务器。

### 配置仅缓存 Unbound DNS 服务器

在本节中,我们将考虑 Unbound 作为仅缓存名称服务器的角色,处理对其他远程 DNS 服务器的递归 DNS 请求,并在一定时间内缓存查询以提高响应时间,当服务器再次被请求相同名称解析时:

1.  首先,以 root 身份登录并键入以下内容安装所需软件包:

    ```
    yum install unbound bind-utils

    ```

1.  现在制作`unbound`配置文件的副本,以便我们以后可以恢复更改,然后使用您喜欢的文本编辑器打开它:

    ```
    cp /etc/unbound/unbound.conf /etc/unbound/unbound.conf.BAK
    vi /etc/unbound/unbound.conf

    ```

1.  向下滚动找到以下行:`# interface: 0.0.0.0`。删除`#`符号以取消注释它(激活它),使其读作如下:

    ```
    interface: 0.0.0.0
    ```

1.  接下来,向下滚动找到以下行:`# access-control: 127.0.0.0/8 allow`。取消注释该行以激活它,并根据需要更改网络地址:

    ```
    access-control: 192.168.1.0/24 allow
    ```

1.  保存并关闭文件,然后创建用于安全 DNSSEC 支持的 RSA 密钥对证书,之后再检查更改后的配置文件的正确性:

    ```
    unbound-control-setup && unbound-checkconf
    ```

1.  接下来,在服务器上的 firewalld 配置中打开 DNS 服务,因为我们希望能够在网络中的其他客户端上使用我们的新 DNS 服务进行查询:

    ```
    firewall-cmd --permanent --add-service dns &&  firewall-cmd --reload

    ```

1.  现在确保服务将在启动时可用,并在之后启动它:

    ```
    systemctl enable unbound && systemctl start unbound

    ```

1.  要测试我们是否可以到达我们的 Unbound DNS 服务器并进行查询,请从同一台服务器上执行以下命令,该服务器正在本地运行我们的 Unbound DNS 服务,这应该会返回[www.packtpub.com](http://www.packtpub.com)的 IP 地址:

    ```
    nslookup www.packtpub.com 127.0.0.1

    ```

1.  对于请求的更详细视图,您还可以在 DNS 服务器上本地运行:

    ```
    unbound-host -d www.packtpub.com

    ```

1.  从网络中的任何其他客户端(需要安装`bind-utils`),您也可以使用我们的新 DNS 服务器查询任何公共域名。例如,如果我们的 DNS 服务器的 IP 是`192.168.1.7`:

    ```
    nslookup www.packtpub.com 192.168.1.7

    ```

1.  最后,让我们在服务器本身上使用我们的新名称服务器。为此,在制作备份副本后,使用您喜欢的文本编辑器打开以下文件:

    ```
    cp /etc/resolv.conf /etc/resolv.conf.BAK; vi /etc/resolv.conf

    ```

1.  删除所有当前的名称服务器引用,并用以下内容替换它们:

    ```
    nameserver 127.0.0.1
    ```

    ### 注意

    如果您在网络脚本接口中设置了某些 DNS 服务器信息(例如,在配置静态 IP 地址时,请参阅第二章服务器的解析 IP 地址。在 DNS 服务器上,您还可以使用`unbound-host -d`命令来获得 Unbound 服务内部 DNS 查询的更技术性的视图。

在我们成功完成这些测试后,我们更新了 DNS 服务器上的当前名称服务器解析器信息,使用我们运行在本地主机上的新 DNS 服务。

## 还有更多...

现在我们想要看看 BIND 将如何执行缓存 DNS 信息。为此,在您的 DNS 服务器上,只需选择一个您之前未访问过的目标网站,并使用`dig`命令。例如:

dig www.wikipedia.org


运行此测试后,您可能会看到一个查询时间,结果如下:

;; Query time: 223 msec


现在重复这个练习,重新测试同一个 URL。根据您的网络环境,这可能会产生以下结果:

;; Query time: 0 msec


现在为另一个网站再次执行此操作。在每次重复前面的命令时,您不仅应该看到查询时间的减少,还应该体验到输出交付的更快响应时间。同样的结果将在浏览器刷新率中体现,因此我们可以这样说,这个简单的练习不仅向您介绍了 Unbound,而且最终将有助于提高您在浏览万维网时本地网络的速度。

# 设置一个仅授权的 DNS 服务器

在本节中,我们将学习如何创建一个*权威专用* DNS 服务器,它可以自己回答关于其控制下的域的查询,而不是将查询重定向到其他 DNS 服务器(例如我们之前的缓存专用 DNS 服务器)。我们将创建一个 DNS 服务器,以解析我们自己的私有本地网络中的所有我们自己的主机名和服务。

如前所述,虽然 Unbound 应该是您在需要缓存专用 DNS 服务器时的首选,因为它是目前最安全的 DNS 服务器解决方案,但它只有有限的权威功能,这通常对于专业 DNS 服务器使用来说是不够的。在这里,我们将使用流行的权威 BIND DNS 服务器包,而不是查询我们的本地服务器名称,并配置一个新的 DNS 区域以提供高度可定制的名称解析。从技术上讲,我们将为我们自己的域编写一个*正向*和*反向区域*文件。区域文件是包含实际域名到 IP 地址映射或相反的文本文件,即 IP 地址映射到域名映射。虽然对任何 DNS 服务器的大多数查询都是将名称翻译为 IP 地址,但反向部分也很重要,如果您需要为任何给定 IP 地址提供正确的域名,则需要设置。我们将配置 BIND 为权威专用,这意味着服务器只会回答它具有权威性的查询(在其区域中有匹配的记录),因此如果 DNS 服务器无法解析请求的域,它将停止请求,并且不会使用递归请求联系其他 DNS 服务器以获取并构建正确的答案。

## 准备工作

要完成此操作,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,一个静态 IP 地址,以及您选择的基于控制台的文本编辑器。下载额外软件包时需要互联网连接。在本例中,我们的 DNS 服务器在私有网络中运行,网络地址为`192.168.1.0/24`。我们的 DNS 服务器应该管理我们决定作为`centos7.home`(形式为`domain.toplevel-domain`)的本地私有域。新 DNS 服务器的 IP 地址将是`192.168.1.7`,并且应该获得主机名`ns1`,从而得到完全限定域名(FQDN)`ns1.centos7.home`。(有关 FQDN 的更多信息,请参阅第二章             ; Minimum negative caching
    ```

1.  之后,添加文件的其余内容:

    ```
    ; add your name servers here for your domain
            IN      NS      ns1.centos7.home.
    ; add your mail server here for the domain  
            IN      MX      10   mailhost.centos7.home.
    ; now follows the actual domain name to IP 
    ; address mappings:

    ; first add all referenced hostnames from above
    ns1        IN      A       192.168.1.7
    mailhost   IN      A       192.168.1.8
    ; add all accessible domain to ip mappings here
    router     IN      A       192.168.1.0
    www        IN      A       192.168.1.9
    ftp        IN      A       192.168.1.10
    ; add all the private clients on the Lan here
    client1    IN      A       192.168.1.11
    client2    IN      A       192.168.1.12
    client3    IN      A       192.168.1.13
    ; finally we can define some aliases for 
    ; existing domain name mappings
    webserver  IN      CNAME   www
    johnny     IN      CNAME   client2
    ```

1.  当你完成操作后,请先保存并关闭文件,然后再为我们的私有子网络创建反向区域文件,该子网络用于我们的域名(`C-Class` 是指前三个数字(八位组),它们之间用点分隔:`XXX.XXX.XXX`。例如,对于 `192.168.1.0/24` 子网,`C-Class` 是 `192.168.1`:

    ```
    vi /var/named/db.<C-Class of our search IP in reverse order>

    ```

1.  在我们的示例中,一个解析我们 `centos7.home` 的 `192.168.1` C-Class 子网的反向区域文件将是:

    ```
    vi /var/named/db.1.168.192

    ```

1.  首先,像第 10 步一样输入完全相同的 SOA,然后将以下内容添加到文件的末尾:

    ```
    ;add your name servers for your domain
                 IN      NS      ns1.centos7.home.
    ; here add the actual IP octet to
    ; subdomain mappings:
    7      IN      PTR     ns1.centos7.home.
    8      IN      PTR     mailhost.centos7.home.
    9      IN      PTR     www.centos7.home.
    10     IN      PTR     ftp.centos7.home.
    11     IN      PTR     client1.centos7.home.
    12     IN      PTR     client2.centos7.home.
    13     IN      PTR     client3.centos7.home.
    ```

1.  保存并关闭文件,然后将我们的新区域对添加到命名配置中。为此,再次打开 `named.conf`:

    ```
    vi /etc/named.conf

    ```

1.  现在找到包含 `"/etc/named.rfc1912.zones"` 的行。紧接在这行之后,为你的工作留出空间,并添加适当的区域声明以启用你的*反向*区域,如下所示(将 `XXX.XXX.XXX` 替换为你的反向区域文件名的反向 C-Class,在我们的示例中是 `1.168.192`):

    ```
    zone "XXX.XXX.XXX.in-addr.arpa." IN {
      type master;
      file "/var/named/db.XXX.XXX.XXX";
      update-policy local;
    };
    ```

1.  完成这一步后,你现在可以继续为你的正向区域添加一个区域声明,如下所示(将 `<domain>.<top-level domain>.db` 替换为你的正向区域文件名,在我们的示例中是 `centos7.home`):

    ```
    zone "<domain>.<top-level domain>." IN {
      type master;
      file "/var/named/<domain>.<top-level domain>.db";
      update-policy local;
    };
    ```

1.  完成操作后,请保存并关闭文件,然后使用以下命令重启 `bind` 服务:

    ```
     named-checkconf && systemctl restart named
    ```

## 它是如何工作的...

所有 DNS 服务器都配置为执行缓存功能,但是缓存专用服务器仅限于从远程 DNS 服务器回答查询的能力,而权威名称服务器是维护特定记录的主区域的 DNS 服务器。

那么,我们从这次经历中学到了什么?

本教程的目的是设置一个仅权威的 BIND DNS 服务器,并为它提供一个新的区域。DNS 区域定义了单个域下的所有可用资源(主机名和服务)。任何 DNS 区域都应始终包含正向和反向区域文件。为了理解区域配置,我们首先需要讨论 DNS 层次结构。例如,取本教程中的一个 DNS 域名`client1.centos7.home`。我们私有网络中的每台计算机都有一个主机名(例如,`client1`或`www`),并且属于一个域。域由**二级域名**(**SLD**)(例如,`centos7`)和**顶级域名**(**TLD**)(例如,`home`、`org`、`com`等)组成。在 TLD 之上是根域(用`.`点表示),这在与其他程序或配置一起工作时经常被忽略。然而,在处理或定义 FQDN 的区域配置时,非常重要的一点是永远不要忘记在 TLD 后面添加这个点`.`。例如,我们`client1`计算机的 DNS 域名是`client1.centos7.home`,而`/etc/hosts`文件中的 FQDN 通常写成`client1.centos7.home`(从技术上讲这是不正确的,但大多数情况下是足够的)。根域非常重要,因为它包含了根 DNS 服务器,如果权威 DNS 服务器在其自己的记录(区域)或缓存中找不到请求域的现有条目,它将首先被查询。但是,我们在所有其他域层次结构中也有 DNS 服务器,这就是 DNS 服务器进行递归请求的方式。根 DNS 服务器,像任何其他 DNS 服务器一样,解析其区域文件中定义的所有子域,即 TLD。这些 TLD 本身可以解析所有 SLD(也在它们的区域文件中定义)。二级域解析其所有主机名(作为特殊子域,它们指的是网络上的单个计算机或服务)。因此,任何 DNS 请求都会通过不同的 DNS 服务器层次结构,从根 DNS 到 TLD DNS,再到 SLD DNS 服务器。根和 TLD DNS 服务器不能完全解析完整的域名 DNS 查询,如`www.centos7.home`,而是将解析下一个 DNS 层次结构的正确地址。这个系统确保根 DNS 总是能找到正确的 TLD DNS 服务器地址,TLD DNS 服务器总是将请求发送到正确的 SLD DNS,后者拥有正确的区域文件,并最终能够回答请求的 DNS 查询。

那么,我们从这次经历中学到了什么?

正如我们所学,区域文件是一个简单的文本文件,由指令和资源记录组成,由于包含大量两字母缩写,它可能看起来相当复杂。请记住,您需要在基础域级别(例如,`centos7.home`)为所有在该域下运行的主机名和服务(例如,`www`、`host1`、`api`等)设置一对区域文件(正向和反向)。安装`named` DNS 服务器(它是**伯克利互联网名称域**(**BIND**)软件包的一部分)后,我们复制了原始主配置文件,并将默认监听端口从 53 更改为 8053(因为 unbound 已经在端口 53 上监听),但仍仅监听 localhost,并禁用了 IPv6 以保持与其他主要 DNS 服务器的兼容性(因为 IPv6 支持在互联网上仍然有限)。此外,我们在这里禁用了递归,因为我们的 BIND DNS 服务器必须是权威的,这意味着当它无法从自己的区域记录中解析查询时,不允许将 DNS 请求转发到其他远程 DNS 服务器。

然后我们开始创建并自定义我们自己的正向 DNS 区域文件,文件名约定为`/var/named/<domain>.<top-level domain>.db`。该文件以`$TTL`控制语句打开,该语句代表**生存时间**,并向其他名称服务器提供一个时间值,该值决定了它们可以从该区域缓存记录的时间长度。与其他许多指令一样,此指令默认以秒为单位定义,但您也可以使用 BIND 特定的简写形式来表示分钟(`m`)、小时(`h`)、天(`d`)和周(`w`),正如我们在示例中所示(`3h`)。接下来,我们提供了一个**授权开始**(**SOA**)记录。该记录包含有关整个区域的具体信息。这从区域名称(`@`)开始,指定区域类(`IN`),该名称服务器的 FQDN 格式为`hostname.domain.TLD.`,以及区域管理员的电子邮件地址。后一个值通常采用`hostmaster.hostname.domain.TLD.`的形式,并通过将典型的`@`符号替换为点(`.`)来形成。完成此操作后,接下来就是打开括号以分配区域的序列号、刷新值、重试值、过期值和负缓存`生存时间`值。这些指令可以总结如下:

+   序列号(`serial-number`)值是一个数值,通常采用反向日期(`YYYYMMDD`)的形式,并附加一个值(`VV`),该值在每次修改或更新区域文件时递增,以指示该名称服务需要重新加载区域。值`VV`通常从`00`开始,下次修改此文件时,只需将其递增为`01`、`02`、`03`等。

+   `刷新时间`值决定了辅助或从属名称服务器将多频繁地询问主名称服务器区域是否发生了任何更改。

+   `重试时间`值决定了辅助或从属名称服务器在序列号失败后应多久检查一次主服务器。如果在`到期时间`值指定的时间范围内发生故障,辅助名称服务器将停止响应作为请求的权威。

+   `最小 TTL`值决定了其他名称服务器可以缓存否定响应的时间长度。

完成这一部分并关闭相应的括号后,我们接着添加了权威名称服务器信息(`NS`),使用`IN NS <名称服务器的 FQDN>`定义。通常情况下,您至少会有两个,如果不是三个名称服务器(将每个名称服务器的 FQDN 放在新的`IN NS`行中)。然而,如果您的服务器运行在办公室或家庭环境中,并且您希望享受本地名称解析的好处,例如`.home`、`.lan`或`.dev`,那么设置一个名称服务器就特别有用。接下来,我们需要为区域指定邮件服务器,因此需要包含**邮件交换器**(**MX**)记录的引用。格式为`IN MX <优先级> <您的邮件服务器的 FQDN>`。如果您定义了多个邮件服务器(每个在其单独的`IN MX`行中),优先级就变得重要了——数字越低,优先级越高。在这方面,辅助邮件服务器应该有一个更高的值。

### 注意

在`SOA`、`NS`和`MX`行中,我们已经引用了尚未定义为 IP 映射的主机名(`A`记录)。我们可以这样做,因为区域文件不是按顺序处理的。但不要忘记稍后为每个主机名创建相应的`A`行。

根据您的需求,您可能还想将您的名称服务器用作邮件服务器(那么您会写成`MX 10 ns1.centos7.home.`),尽管在示例中您可能有一个专门用于该角色的服务器。

接下来,需要创建适当的`A`记录(`A`代表地址)并将适当的 IP 地址分配给显示的值。这是任何域名解析请求到服务器的心脏。`A`记录用于将 FQDN 链接到 IP 地址,但大部分前面的设置将基于您的确切需求。在这里,您可以定义所有要在网络中映射的本地主机名。由于我们已经在区域文件中使用并引用了一些域名,例如名称服务器或邮件服务器,我们将从这些开始。之后,我们为所有公开可用和内部客户端定义了主机名到 IP 地址的映射。请记住,使用`A`记录时,您可以有多个相同的 IP 地址到不同主机名的映射。例如,如果您在网络中没有为每个服务配备专用服务器,而是有一台运行所有`DNS`、`邮件`、`Web`和`FTP`服务的服务器,您可以编写以下行:

ns1 IN A 192.168.1.7
mailhost IN A 192.168.1.7
www IN A 192.168.1.7
ftp IN A 192.168.1.7


您还可以使用规范名称(`CNAME`)记录来完成此任务,它用于为现有的`A`记录分配别名。可以说,`CNAME`值通过指向`A`记录,使您的 DNS 数据更易于管理。因此,如果您考虑需要更改`A`记录的 IP 地址,所有指向该记录的`CNAME`记录都会自动更新。然而,正如本教程所尝试展示的,替代解决方案是拥有多个`A`记录,这意味着需要进行多次更新才能更改 IP 地址。

在本教程的这一阶段,我们将注意力转向了反向 DNS 区域。与正向区域文件一样,反向区域文件也有一个特殊的命名约定`/var/named/db.<C-Class of our search IP in reverse order>`。将反向区域文件命名为`db.1.168.192`可能一开始看起来很奇怪,但当你看到反向查找的工作原理时,它就有意义了。它从最高节点(在我们的例子中是`192`,对应于正向区域文件中的根域)开始,并从那里向下遍历。正如你所看到的,我们在这个文件中放置的内容在指令和在正向区域文件中使用的资源之间有一些相似之处。然而,重要的是要记住,反向 DNS 与正向 DNS 是完全独立和不同的。

反向 DNS 区域旨在帮助将 IP 地址转换为域名。这可以通过使用**指针资源记录**(**PTR**)来实现,该记录将唯一的 IP 地址分配给一个或多个主机名。因此,您必须确保每个`A`记录都有一个唯一的 PTR 记录。每个反向区域文件收集完整的 C 类地址范围(例如,前三个点分数字`192.168.1`)的 IP 到主机名转换。此类 IP 范围的最后一个八位字节是可以在该文件中定义的所有主机名。请记住,PTR 记录中第一列的 IP 地址值应该只显示这个最后一个八位字节。例如,在反向区域文件`db.1.168.192`中的行`9 IN PTR www.centos7.home.`将能够将任何反向 IP 地址请求`192.168.1.9`解析为域值`www.centos7.home`。

在本教程中,我们创建了正向和反向区域文件,然后通过将新区域添加到 BIND 服务器来完成 named 服务的配置,以便开始解析我们网络的本地域名。在这些新添加的正向和反向区域定义块中,我们定义了自己是主区域持有者,并指定了`update-policy local;`,因为如果我们想从本地主机使用`nsupdate`命令动态更新我们的区域,这是必需的(稍后会看到)。您可以添加无限数量的区域对,但请记住,每个正向或反向区域定义必须在大括号中给出单个区域条目。

总之,我们可以说正向和反向区域文件是基于单个基础域名定义的,一个基础域名对应一个正向区域文件。对于反向区域文件,情况略有不同,因为我们处理的是 IP 地址。我们根据域的网络地址的 C 类地址范围创建一个区域文件,这里的最后一个八位组称为主机名,我们在此特定文件中定义映射。

BIND 是一个庞大的主题,还有很多需要学习,本食谱仅作为介绍。在大多数情况下,你甚至可能会发现你的初始学习阶段将成为一个试错过程,但这将得到改善。记住,熟能生巧,如果你创建了额外的正向区域,请始终在反向区域文件中引用它们。

## 还有更多...

在为 BIND 服务器创建并添加了区域后,你现在可以测试配置了。为此,你可以使用`host`、`dig`或`nslookup`命令仅从 localhost 解析内部主机名。例如,为了测试正向 DNS 解析,我们可以使用`dig`命令,指定我们的 DNS 服务器在 localhost 上运行,端口为`8053`:`dig -p 8053 @127.0.0.1 client2.centos7.home`。这应该能成功完成 DNS 查找并返回以下行(输出已截断):

;; ANSWER SECTION:
client2.centos7.home. 10800 IN A 192.168.1.12


对于反向查找,你将使用 IP 地址(在本例中,使用的 IP 地址应对应于你已配置反向 DNS 的域):`nslookup -port=8053 192.168.1.12 127.0.0.1`。由于我们已经将 BIND 配置为仅权威 DNS 服务器,因此任何超出我们区域本地记录的 DNS 请求都无法完全解析。为了测试这一点,使用`dig -p 8053 @127.0.0.1 www.google.com`,它应该返回状态`REFUSED`和`WARNING: recursion requested but not available`消息。

出于安全考虑,我们仅将 BIND 服务器限制为 localhost,不允许它连接到其他 DNS 服务器。因此,你不能将其作为私有网络的唯一 DNS 解决方案。相反,在下一个配方中,我们将学习如何结合 Unbound 和 BIND 来创建一个集成且非常安全的全能 DNS 服务器解决方案。但如果你不想这样做,并且想将 BIND 作为你的单一且完整的权威 DNS 服务器解决方案(这在 CentOS 7 上不再推荐),你可以通过禁用或卸载 Unbound,恢复原始的`named.conf.BAK`配置文件,并在 BIND 配置文件中启用以下指令来实现:`allow-query {localhost;192.168.1.0/24;}`;(允许整个`192.168.1.0/24`网络进行 DNS 请求),`listen-on port 53 {any;}`;(在任何网络上监听请求),`listen-on-v6 port 8053 { none; }`;(禁用 IPv6)。如果你想让 BIND 转发所有它不权威的内容,而不是使用递归来找出答案,也可以添加以下指令(在这个例子中,我们使用官方的 Google DNS 服务器进行任何转发请求,但你可以根据需要进行更改):`forwarders { 8.8.8.8;};forward only;`。然后重启`bind`服务。

# 创建一个集成的名称服务器解决方案

到目前为止,在本章中,我们使用 Unbound 作为仅缓存的 DNS 服务器解决方案,因为它非常安全和快速,而使用 BIND 作为我们的仅权威 DNS 服务器,因为它的区域管理高度可配置和可定制。BIND 已经存在很长时间,是有史以来使用最广泛的 DNS 软件。然而,过去发现了一些严重的漏洞(幸运的是已经修复)。在本配方中,我们将结合 Unbound 和 BIND,以获得两全其美的效果:只有非常安全的 Unbound 服务将直接暴露给你的私有网络,并可以从你的客户端接收和提供 DNS 查询。BIND 服务仅绑定到 localhost,正如在前一个配方中配置的那样,只允许解析内部主机名,并且没有直接访问互联网或你的客户端的权限。如果客户端连接到你的 Unbound 服务并请求解析私有网络中的内部主机名,Unbound 将在本地查询 BIND 服务器以进行 DNS 解析并将响应缓存。另一方面,如果客户端请求解析外部域名,Unbound 本身将递归查询或转发其他远程 DNS 服务器并将响应缓存。这两种 DNS 服务器系统的集成使其成为完美的全能 DNS 服务器解决方案。

## 准备就绪

要完成这个配方,你需要一个正常运行的 CentOS 7 操作系统和一个你选择的基于控制台的文本编辑器。预计在本章中找到的配方指导下,一个仅缓存的 Unbound 服务器(端口 53)和一个仅权威的 BIND 服务器(端口 8053)已经安装并正在运行。

## 操作方法...

在本教程中,我们将向您展示如何配置 Unbound,以便当客户端请求内部主机名时,它能够查询我们本地运行的权威性仅限的 BIND 服务。对于其他任何请求,应将其作为递归 DNS 请求发送到远程根服务器以构建答案:

1.  以 root 用户身份登录运行 Unbound 和 BIND 服务的我们的服务器,并打开 Unbound 的主配置文件:

    ```
    vi /etc/unbound/unbound.conf

    ```

1.  首先在`server:`子句中的某个位置添加以下行:

    ```
    local-zone: "168.192.in-addr.arpa." nodefault

    ```

1.  接下来,我们需要允许 Unbound 连接到默认禁用的 localhost,查找读取以下内容的行:`# do-not-query-localhost: yes`,然后激活并将其设置为 no:

    ```
    do-not-query-localhost: no

    ```

1.  接下来,由于我们的 BIND 服务器未使用 DNSSEC 配置,因此我们需要告诉 Unbound 无论如何都要使用它(默认情况下,Unbound 拒绝连接到未使用 DNSSEC 的 DNS 服务器)。查找以`# domain-insecure: "example.com"`开头的行,然后激活它并将其更改为以下内容:

    ```
    domain-insecure: "centos7.home."
    domain-insecure: "168.192.in-addr.arpa."

    ```

1.  接下来,我们需要告诉 Unbound 将我们内部域`centos7.home.`的所有请求转发到本地运行的 BIND 服务器(端口`8053`)。在文件末尾添加以下内容:

    ```
    stub-zone:
     name: "centos7.home."
     stub-addr: 127.0.0.1@8053

    ```

1.  此外,我们还需要告诉 Unbound 对我们的内部域使用 BIND 进行任何反向查找时执行相同的操作:

    ```
    stub-zone:
     name: "1.168.192.in-addr.arpa."
     stub-addr: 127.0.0.1@8053

    ```

1.  保存并关闭文件,然后重新启动 Unbound 服务:

    ```
    unbound-checkconf && systemctl restart unbound

    ```

## 工作原理

恭喜!您现在拥有一个完整的权威且非常安全的 DNS 服务器解决方案,采用集成方法结合了 Unbound 和 BIND 的所有优点。在本教程中,我们向您展示了如何使用存根区域配置 Unbound 服务,以便连接到内部运行的 BIND 服务以处理正向和反向请求。`存根区域`是 Unbound 的一个特殊功能,用于配置无法通过公共互联网服务器访问的权威数据。其`名称`字段定义了 Unbound 将转发任何传入 DNS 请求的区域名称,而`存根地址`字段配置了访问 DNS 服务器的位置(IP 地址和端口);在我们的示例中,这是本地运行的 BIND 服务器,端口为`8053`。为了让 Unbound 能够连接到 localhost,我们首先必须使用`do-not-query-localhost: no`指令允许这样做,必须将我们的正向和反向域标记为`不安全`,还必须定义一个新的`本地区域`,这是必要的,以便 Unbound 知道客户端可以向`存根区域`权威服务器发送查询。

## 还有更多...

为了测试我们的新 Unbound/BIND DNS 集群,请从同一网络中的另一台计算机向 Unbound 服务发出一个公共和一个内部主机名的 DNS 请求(您也可以在 DNS 服务器本身上运行类似的测试)。如果我们的 Unbound/BIND DNS 集群的 IP 为`192.168.1.7`,则应能够从网络中的任何其他计算机获得`dig @192.168.1.7 www.packtpub.com`和`dig @192.168.1.7 client1.centos7.home`的正确答案。

如果您需要解决服务问题或需要监控新安装的 Unbound/BIND DNS 服务器的 DNS 查询,您可以配置日志记录参数。对于 BIND,在主配置文件`named.conf`中,您可以设置日志输出的详细程度(或日志级别)。这个参数称为`severity`,可以在`logging`指令中找到。它已经设置为`dynamic`,这意味着可以输出尽可能多的日志消息。然后,您可以使用`tail -f /var/named/data/named.run`来读取当前日志。对于 Unbound,您可以在其主配置文件`unbound.conf`中使用`verbosity`指令设置详细程度级别,该级别默认为最低的`1`,但可以增加到`5`。要了解更多关于不同级别的信息,请使用`man unbound.conf`。使用`journald`读取 Unbound 日志信息,使用命令`journalctl -f -u unbound.service`(按下*Ctrl*+*c*键退出命令)。

我们不仅可以记录系统和服务的日志信息,还可以启用查询日志。对于 Unbound,只需使用`verbosity`为`3`或以上来记录查询信息。对于 BIND,为了激活查询日志(查询输出将发送到日志文件`named.run`),使用命令`rndc querylog on`(要关闭它,使用`rndc querylog off`)。请记住,在配置生产系统上的 DNS 服务器时,应关闭任何过多的日志信息,例如查询日志,因为它可能会降低您的服务性能。您还可以安装其他第三方工具,如`dnstop`(来自`EPEL`存储库)来监控您的 DNS 活动。

# 填充域

在本教程中,我们将向您展示如何快速向权威的 BIND 服务器添加新的本地域记录条目,这些条目目前对您的名称服务器来说是未知的。

## 准备工作

要完成本教程,您需要一个正常运行的 CentOS 7 操作系统和一个基于控制台的文本编辑器。预计 Unbound 和 BIND 都已经安装并正在运行,并且您已经阅读并应用了本章中的区域教程,并为您的私有网络的主机名解析准备了所需的正向和反向区域文件。

## 如何操作...

如果您想向 DNS 服务器添加新的域名到 IP 地址映射,例如为本地网络中的新主机或未知主机,您有两种选择。由于我们已经为本地网络创建了区域文件,因此我们可以简单地为每个新子域在我们的基本域名中添加新的`A`(和/或`CNAME`)以及相应的`PTR`条目到我们的正向和反向区域文件配置中,使用我们选择的文本编辑器。或者,我们可以使用`nsupdate`命令行工具以交互方式添加这些记录,而无需重新启动 DNS 服务器。在本节中,我们将向您展示如何准备和使用`nsupdate`工具。在我们的示例中,我们将为 IP 地址为`192.168.1.14`的计算机添加一个新的子域`client4.centos7.home`到我们的 DNS 服务器的区域:

1.  以 root 身份登录运行 BIND 服务的服务器。现在首先我们需要激活`named`,以便允许其通过 SELinux 写入区域文件:

    ```
    setsebool -P named_write_master_zones 1

    ```

1.  接下来,我们需要解决一些与命名配置目录的权限问题,否则`nsupdate`无法稍后更新我们的区域文件:

    ```
    chown :named /var/named -R; chmod 775 /var/named -R

    ```

1.  由于我们的 BIND 服务器运行在端口`8053`上,请键入以下命令以在本地启动交互式`nsupdate`会话:

    ```
    nsupdate -p 8053 -d -l

    ```

1.  在提示符(`>`)下,首先通过键入以下内容连接到本地 DNS 服务器(按*Return*键完成命令):

    ```
     local 127.0.0.1

    ```

1.  要向 DNS 服务器添加新的正向域名到 IP 映射,请键入以下内容:

    ```
    update add client4.centos7.home. 115200 A 192.168.1.14
    send

    ```

1.  现在使用以下命令添加反向关系:

    ```
    update add 14.1.168.192.in-addr.arpa. 115200 PTR client4.centos7.home.
    send

    ```

    如果更新命令的输出包含消息`NOERROR`,请按*Ctrl*+*c*键退出交互式`nsupdate`会话。

1.  最后,检查新区域条目的域名和 IP 解析是否正常工作(这也应该通过 Unbound 服务器远程工作):

    ```
    dig -p 8053 @127.0.0.1  client4.centos7.home.
    nslookup -port=8053 192.168.1.14 127.0.0.1

    ```

## 它是如何工作的…

在这个相当简单的教程中,我们向您展示了如何使用`nsupdate`工具在运行时动态添加新的域名解析记录,而无需重新启动您的 BIND DNS 服务器。

那么,我们从这次经历中学到了什么?

在本教程中,我们向您介绍了`nsupdate`命令行工具,该工具可以在不编辑区域文件或重新启动服务器的情况下对正在运行的 BIND DNS 数据库进行更改。如果您已经在 DNS 服务器上配置了区域文件,那么这是对 DNS 服务器进行更改的首选方式。它有几个选项,例如,您可以连接到远程 DNS 服务器,但由于简单性和安全原因,我们将仅使用和允许最简单的形式,并且仅将`nsupdate`连接到我们的本地 BIND 服务器(要使用`nsupdate`远程连接到 BIND 服务器,您需要进行更多配置,例如生成安全密钥对,打开防火墙等)。

在允许`named`写入其自己的区域文件(否则会被 SELinux 禁止)并修复默认 named 配置目录的一些权限问题后,我们使用`-l`(本地连接)和`-p 8053`(连接到 BIND DNS 服务器端口`8053`)启动了`nsupdate`程序。`-d`为我们提供了调试输出,这对于解决问题非常有用。然后,我们被一个交互式 shell 提示,在那里我们可以运行 BIND 特定的`update`命令。首先,我们设置`local` `127.0.0.1`,这连接到我们的本地服务器,然后我们使用`update add`命令向正在运行的 DNS 服务器添加一个新的正向`A`记录。语法类似于在区域文件中定义记录。在这里,我们使用以下行添加一个新的`A`记录,TTL 为三天(115200 秒),域名为`client4.centos7.home`,解析到 IP 地址`192.168.1.14`。下一行用于为我们的新域配置一些反向解析规则,并将域名作为`PTR`条目添加到我们的反向区域中。在这里,需要注意的是,您需要以下列方式定义反向`update add`规则的域部分:`<规则的主机名>.<反向 C 类>.in-addr.arpa`。为了最终执行我们的命令并将它们永久保存在 DNS 服务器的数据库中,而不需要重新启动服务器,我们使用`send`命令分别对反向和正向命令,因为它们针对不同的区域。最后,我们测试了新添加到 DNS 服务器的区域文件中的条目是否正常工作,通过查询 BIND 服务器。

# 构建辅助(从属)DNS 服务器

为了确保网络的高可用性,在您的环境中运行多个 DNS 服务器以应对任何服务器故障是有益的。如果您运行的是公共 DNS 服务器,这一点尤其重要,因为持续访问服务至关重要,而且同时拥有五个或更多 DNS 服务器并不罕见。由于配置和管理多个 DNS 服务器可能耗时,BIND DNS 服务器使用节点之间传输区域文件的功能,以便每个 DNS 服务器都具有相同的域解析和配置信息。为了实现这一点,我们需要定义一个主 DNS 服务器和一个或多个辅助或从属 DNS 服务器。然后,我们只需要在主服务器上调整一次区域文件,它就会将当前版本传输到我们所有的辅助服务器,保持一切一致和最新。对于客户端来说,连接到哪个 DNS 服务器将没有区别。

## 准备就绪

要完成此配方,您将至少需要两个在同一网络中可以相互看到和 ping 通的 CentOS 7 服务器。需要互联网连接以下载并在我们想要包含在我们的 DNS 服务器*农场*中的所有计算机上安装 BIND 服务器软件。在本示例中,我们有两个服务器,`192.168.1.7`,它已经安装并配置为 BIND 服务器,以及`192.168.1.15`,它将是子网`192.168.1.0/24`内的第二个 BIND 服务器。您还应该阅读并应用本章中的区域文件配方,并创建正向和反向区域文件,因为这是我们想要在 DNS 服务器之间传输的内容。

## 如何操作...

我们通过在想要包含在我们的 BIND DNS 服务器集群中的每个 CentOS 7 计算机上安装 BIND 来开始这个配方。为此,请遵循配方*设置权威 DNS 服务器*为所有剩余系统。在我们开始之前,我们需要定义哪个服务器将是我们的主 DNS 服务器。为了简化我们的示例,我们将选择 IP 地址为`192.168.1.7`的服务器。现在让我们让我们的 DNS 服务器节点了解它们的角色。

### 对主 DNS 服务器进行的更改

1.  让我们以 root 身份登录到主服务器并打开其主配置:

    ```
    vi /etc/named.conf

    ```

1.  现在我们定义哪些辅助 DNS 服务器将被允许接收区域文件,在新的一行中,在选项花括号之间写下以下命令(我们只有一个辅助 DNS 服务器,其 IP 地址为`192.168.1.15`,请根据需要更改):

    ```
    allow-transfer { 192.168.1.15; };
    notify yes;
    ```

1.  此外,我们还必须允许其他名称服务器连接到我们的主名称服务器。为此,您需要将`listen-on`指令更改为包括 DNS 服务器的主网络接口(在我们的示例中为`192.168.1.7`,因此请相应更改):

    ```
    listen-on port 8053 { 127.0.0.1;192.168.1.7; };

    ```

1.  保存并关闭文件。现在在您的服务器防火墙中打开新端口`8053`(或者为其创建一个 firewalld 服务,参见第六章,*提供安全性*):

    ```
    firewall-cmd --permanent --zone=public --add-port=8053/tcp --add-port=8053/udp;firewall-cmd --reload

    ```

1.  保存并关闭文件。接下来,更新我们之前创建的区域文件,以包括系统中所有新名称服务器的 IP 地址。更改正向和反向区域文件,`/var/named/centos7.home.db`和`/var/named/db.1.168.192`,以包括我们的新辅助 DNS 服务器。在正向区域文件中,添加以下行(您也可以使用`nsupdate`程序来执行此操作)到适当的节中:

    ```
    NS  ns2.centos7.home.
    ns2  A   192.168.1.15

    ```

1.  在反向区域文件中,添加到适当的节中:

    ```
    NS  ns2.centos7.home.
    15 PTR ns2.centos7.home.

    ```

1.  最后,重启 BIND 并重新检查配置文件:

    ```
    named-checkconf && systemctl restart named

    ```

### 对辅助 DNS 服务器进行的更改

为了简化和演示,只需在您想要用作 BIND 从属服务器的任何服务器上安装`named`(我们只在这里展示重要的配置):

1.  以 root 身份登录到新服务器,安装 BIND,并打开其主配置:

    ```
    yum install bind; vi /etc/named.conf

    ```

1.  现在找到行`include /etc/named.rfc1912.zones`。紧跟在这行之后,为你的工作创建空间,并添加以下区域(适当地替换区域和文件名):

    ```
     zone "centos7.home" IN {
     type slave;
     masters port 8053 { 192.168.1.7; };
     file "/var/named/centos7.home.db";
    };
     zone "1.168.192.in-addr.arpa" IN {
     type slave;
     masters port 8053{ 192.168.1.7; };
     file "/var/named/db.1.168.192.db";
     };

    ```

1.  保存并关闭文件。然后修复一些不正确的 BIND 文件夹权限,并启用`named`写入其区域文件目录,然后重新启动 BIND:

    ```
    chown :named /var/named -R; chmod 775 /var/named -R
    setsebool -P named_write_master_zones 1
    named-checkconf && systemctl restart named

    ```

1.  现在使用以下命令启动新的区域传输:

    ```
    rndc refresh centos7.home.

    ```

1.  等待一段时间后,为了测试辅助 DNS 服务器是否按预期工作,检查主区域文件是否已被传输:

    ```
    ls /var/named/*.db

    ```

1.  最后,我们现在可以测试我们是否也可以在辅助 DNS 服务器上查询我们的本地域:

    ```
    dig @127.0.0.1 client2.centos7.home.

    ```

## 它是如何工作的...

在本配方中,我们向您展示了如何在您的网络中设置辅助 BIND 服务器,这有助于提高您的 DNS 服务器系统的稳定性和可用性。

那么我们从这次经历中学到了什么?

我们首先决定哪些服务器应作为主 DNS 服务器,哪些应作为从 DNS 服务器。然后在主服务器上打开 BIND 主配置文件,并引入两行代码,将我们的服务器配置为 DNS 集群的头部。`allow-transfer`指令定义了我们希望向哪些客户端传输更新的区域文件,而`notify yes`指令启用了当区域文件发生任何更改时的自动传输。如果你有多个辅助 BIND DNS 服务器,可以在`allow-transfer`指令中添加多个 IP 地址,用分号隔开。然后,我们打开在本章前一个配方中创建的区域文件,并引入新的一行`IN NS <IP 地址>`,这定义了我们需要的辅助 DNS 服务器的 IP 地址,以便在我们的系统中的每个 DNS 节点上都能意识到。如果我们有多个服务器,那么我们就引入多个`IN NS`行。最后,我们引入了一个小注释,以便在辅助服务器上轻松检查区域文件传输是否成功。

之后,我们配置了我们的从 DNS 服务器。在这里,我们引入了与主服务器上的 BIND 配置相同的区域文件定义,不同的是我们使用了类型`slave`而不是 master 来表示我们是辅助 DNS 服务器,并且将从主节点获取区域文件的副本,通过使用`masters`指令定义主 DNS 服务器的 IP 地址(请不要忘记,在我们的例子中,我们的主 BIND 监听在非默认端口`8053`上)。

由于我们没有在从 DNS 服务器上自己创建或复制区域文件,因此在重新启动 BIND 服务后,使用`ls`命令很容易检查区域文件传输是否成功。最后,我们通过运行测试查询使用`dig`或`nslookup`来验证传输的区域文件内容,看看我们是否可以在辅助 DNS 服务器上解析相同的本地主机名。记住,如果你后来对你的主区域文件进行了更改,你必须增加它们的`serial`号,以便这些更改被传输到你所有的从服务器。


# 第十章:使用数据库

在本章中,我们将涵盖:

+   安装 MariaDB 数据库服务器

+   管理 MariaDB 数据库

+   允许对 MariaDB 服务器的远程访问

+   安装 PostgreSQL 服务器和管理数据库

+   配置对 PostgreSQL 的远程访问

+   安装 phpMyAdmin 和 phpPgAdmin

# 引言

本章是一系列配方的集合,提供了在 Linux 世界中实施和维护两个最流行的数据库管理系统所需的步骤。数据的需求无处不在,对于几乎任何服务器来说,它都是*必须提供的服务*,本章提供了在任何环境中部署这些数据库系统所需的起点。

# 安装 MariaDB 数据库服务器

支持超过 70 种排序规则,30 多种字符集,多种存储引擎,以及在虚拟化环境中的部署,MySQL 是一个关键任务的数据库服务器,被全球的生产服务器所使用。它能够托管大量的独立数据库,并能为你的整个网络提供各种角色的支持。MySQL 服务器已经成为**万维网** (**WWW**) 的代名词,被桌面软件使用,扩展本地服务,并且是全球最受欢迎的关系数据库系统之一。本配方的目的是向你展示如何下载、安装和锁定 MariaDB,这是 CentOS 7 中 MySQL 的默认实现。MariaDB 是开源的,与 MySQL 完全兼容,并增加了几个新功能;例如,非阻塞客户端 API 库,具有更好性能的新存储引擎,增强的服务器状态变量,以及复制。

## 准备工作

为了完成这个配方,你需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,一个你选择的基于控制台的文本编辑器,以及一个互联网连接以下载额外的软件包。预计你的服务器将使用静态 IP 地址。

## 如何操作...

由于 MariaDB **数据库管理系统** (**DBMS**) 在 CentOS 7 上默认未安装,我们将从这个配方开始安装所需的软件包。

1.  首先,以 root 身份登录并输入以下命令来安装所需的软件包:

    ```
    yum install mariadb-server mariadb

    ```

1.  完成后,确保服务在启动时启动,然后再启动服务:

    ```
    systemctl enable mariadb.service && systemctl start mariadb.service

    ```

1.  最后,使用以下命令开始安全安装过程:

    ```
    mysql_secure_installation

    ```

1.  当你首次运行前面的命令时,系统会要求你提供一个密码,但由于此值尚未设置,请按*Enter*键表示该值(空白)无。

1.  现在,你将被问到一系列简单的问题,这些问题将帮助你在加固 MariaDB DBMS 系统的过程中。除非你已经是 MariaDB 专家并且确实需要某个特定功能,否则选择 Yes (`Y`) 回答每个问题以获得最大安全性是一个好建议。

1.  最后,测试你是否可以使用 MariaDB 命令行客户端`mysql`本地连接并登录到 MariaDB 服务。如果以下命令输出了 MariaDB 服务器已知的所有用户名及其关联的主机,则测试通过(在提示时输入你在上一步设置的管理员 root 密码):

    ```
    echo "select User,Host from user" | mysql -u root -p mysql

    ```

## 它是如何运作的...

MariaDB 是一个快速、高效、多线程且强大的 SQL 数据库服务器。它支持多个用户,并提供多种存储引擎的访问。通过遵循几个简短的步骤,你现在知道如何安装、保护并登录到你的 MariaDB 服务器。

那么,我们从这次经历中学到了什么?

我们首先安装了 MariaDB 服务器所需的软件包(`mariadb-server`),以及用于控制和查询服务器的客户端 Shell 接口(`mariadb`)。完成这一步后,我们确保 MariaDB 守护进程(`mariadb.service`)会在启动过程中启动,然后我们才真正启动它。此时,我们有了一个可用的安装,但为了确保我们的安装是安全的,我们随后调用了安全安装脚本,引导我们通过几个简单的步骤来加强我们的基本安装。由于基本安装过程不允许我们为 root 用户设置默认密码,我们在这里作为脚本的第一步进行了设置,这样我们就可以确保没有人可以在没有所需授权的情况下访问 MariaDB 的 root 用户账户。然后我们发现,典型的 MariaDB 安装保留了一个匿名用户。这样做的目的是允许任何人在没有有效用户账户的情况下登录到我们的数据库服务器。它通常仅用于测试目的,除非你处于需要此功能的特殊情况,否则总是建议删除此功能。接下来,为了确保 root 用户无法访问我们的 MariaDB 服务器安装,我们选择禁止远程 root 访问,然后删除测试数据库并重新加载权限表。最后,我们运行了一个小测试,看看我们是否可以使用 root 用户连接到数据库,并从`user`表(这是标准`mysql`数据库的一部分)查询一些数据。

完成这些步骤后,我们了解到安装和保护 MariaDB 服务器的过程非常简单。当然,总有一些事情可以做,以使安装更有用,但这个食谱的目的是向你展示,安装新数据库系统最重要的部分是使其安全。记住,运行`mysql_secure_installation`对于所有 MariaDB 服务器都是推荐的,无论你是在构建开发服务器还是用于生产环境的服务器,这都是明智的。作为服务器管理员,安全应始终是你的首要任务。

# 管理 MariaDB 数据库

在本配方中,我们将学习如何为 MariaDB 服务器创建一个新的数据库和数据库用户。MariaDB 可以与各种图形工具(例如,免费的 MySQL Workbench)结合使用,但在您只需要创建一个数据库、提供关联用户并分配正确权限的情况下,通常使用命令行执行此任务非常有用。被称为 MariaDB shell 的这个简单的交互式基于文本的命令行工具支持完整的 SQL 命令范围,并提供对数据库服务器的本地和远程访问。该 shell 为您提供了对数据库服务器的完全控制,因此它代表了您开始 MariaDB 工作的完美工具。

## 准备工作

要完成本配方,您需要一个正常运行的 CentOS 7 操作系统。预计您的服务器上已经安装并运行了 MariaDB 服务器。

## 如何做到这一点...

MariaDB 命令行工具支持在批处理模式(从文件或标准输入读取)和交互模式(输入语句并等待结果)中执行命令。在本配方中,我们将使用后者。

1.  首先,使用您喜欢的任何系统用户登录到您的 CentOS 7 服务器,然后输入以下命令,以便使用名为`root`的主要 MariaDB 管理用户通过 MariaDB shell 访问 MariaDB 服务器(使用在前一个配方中创建的密码):

    ```
    mysql -u root -p

    ```

1.  成功登录后,您将看到 MariaDB 命令行界面。此功能由 MariaDB shell 提示符表示:

    ```
    MariaDB [(none)]>

    ```

1.  在第一步中,我们将创建一个新的数据库。为此,只需通过将以下命令中的`<database-name>`替换为适当的值来定制命令:

    ```
    CREATE DATABASE <database-name> CHARACTER SET utf8 COLLATE utf8_general_ci;

    ```

    ### 注意

    如果您是第一次接触 MariaDB shell,请记住在每行末尾加上分号(`;`),并在输入每个命令后按*Enter*键。

1.  创建了我们的数据库后,我们现在将创建一个 MariaDB 用户。每个用户将由一个用户名和一个与操作系统用户完全独立的密码组成。出于安全考虑,我们将确保数据库的访问仅限于本地主机。要继续,只需通过更改以下命令中的`<username>`、`<password>`和`<database-name>`值来定制命令以反映您的需求:

    ```
    GRANT ALL ON <database-name>.* TO '<username>'@'localhost' IDENTIFIED BY '<password>' WITH GRANT OPTION;

    ```

1.  接下来,让 MariaDB DBMS 知道您的新用户:

    ```
    FLUSH PRIVILEGES;

    ```

1.  现在,只需输入以下命令即可退出 MariaDB shell:

    ```
    EXIT;

    ```

1.  最后,您可以通过以下方式从命令行访问 MariaDB shell 来测试新`<username>`的可访问性:

    ```
    mysql -u <username> -p

    ```

1.  现在回到 MariaDB shell(`MariaDB [(none)]>`),输入以下命令:

    ```
    SHOW DATABASES;
    EXIT;

    ```

## 它是如何工作的...

在本配方过程中,您不仅被展示了如何创建数据库,还展示了如何创建数据库用户。

那么,我们从这次经历中学到了什么?

我们通过使用`mysql`命令以 root 用户身份访问 MariaDB shell 开始了这个操作步骤。这样,我们就可以使用简单的 SQL 函数`CREATE DATABASE`创建一个数据库,并为`<database-name>`字段提供一个自定义名称。我们还指定了`utf8`作为新数据库的字符集,以及`utf8_general_ci`作为排序规则。字符集是数据库中字符的编码方式,而排序规则是一组比较字符集中的字符的规则。由于历史原因,并为了保持 MariaDB 与旧版本服务器的向后兼容性,默认字符集是`latin1`和`latin1_swedish_ci`,但对于任何现代数据库,您应该始终倾向于使用`utf-8`,因为它是国际字符集(非英语字母)最标准和兼容的编码。但是,可以通过使用以下命令来修改此命令,以检查数据库名称是否已在使用中:`CREATE DATABASE IF NOT EXISTS <database-name>`。这样,您就可以使用以下命令删除或移除数据库:

DROP DATABASE IF EXISTS ;


完成这些操作后,只需通过运行我们的`GRANT ALL`命令为新数据库用户添加适当的权限。在这里,我们为本地主机上的`<username>`提供了通过定义的`<password>`获得完全权限。由于选择了特定的`<database-name>`,因此这种级别的权限将限于该特定数据库,并且使用`<database-name>.*`允许我们将这些规则指定给该数据库中的所有表(使用星号符号)。为了向选定的用户提供特定权限,一般语法是:

GRANT [type of permission] ON .

TO ''@'';


出于安全考虑,在本操作步骤中,我们将`<hostname>`限制为本地主机,但如果您想授予远程用户权限,则需要更改此值(稍后会看到)。在我们的示例中,我们将`[type of permission]`设置为`ALL`,但您始终可以通过提供单个或以逗号分隔的权限类型列表来决定最小化特权,如下所示:

GRANT SELECT, INSERT, DELETE ON .* TO ''@'localhost';


使用前面的技术,以下是可以使用的权限的总结:

+   `ALL`:允许`<username>`值拥有所有可用的权限类型

+   `CREATE`:允许`<username>`值创建新表或数据库

+   `DROP`:允许`<username>`值删除表或数据库

+   `DELETE`:允许`<username>`值删除表行

+   `INSERT`:允许`<username>`值插入表行

+   `SELECT`:允许`<username>`值从表中读取

+   `UPDATE`:允许`<username>`值更新表行

然而,一旦授予了特权,操作步骤就会向您展示我们必须`FLUSH`系统,以便使我们的新设置对系统本身可用。需要注意的是,MariaDB shell 中的所有命令都应以分号(`;`)结尾。完成任务后,我们只需使用`EXIT;`语句退出控制台。

MariaDB 是一个出色的数据库系统,但像所有服务一样,它可能会被滥用。因此,始终保持警惕,并且通过考虑之前的建议,你可以确信你的 MariaDB 安装将保持安全和稳定。

## 还有更多...

创建受限用户是提供数据库访问的一种方式,但如果你的开发团队需要持续访问开发服务器,你可能希望考虑提供一个拥有超级用户权限的通用用户。要实现这一点,只需使用管理员用户 root 登录到 MariaDB shell,然后按照以下方式创建一个新用户:

GRANT ALL ON . TO ''@'localhost' IDENTIFIED BY '' WITH GRANT OPTION;


通过这样做,你将使`<username>`能够添加、删除和管理整个 MariaDB 服务器上的数据库(`*.*`中的星号告诉 MariaDB 将权限应用于数据库服务器上找到的所有数据库及其关联表),但由于管理功能的范围,这个新用户账户将所有活动限制在本地主机。所以简单来说,如果你想为`<username>`提供对任何数据库或任何表的访问权限,始终使用星号(`*`)代替数据库名或表名。最后,每次更新或更改用户权限时,请务必在使用`EXIT;`命令退出 MariaDB shell 之前使用`FLUSH PRIVILEGES`命令。

### 审查和撤销权限或删除用户

除非用户账户正在使用,否则保留活动状态并不是一个好主意,因此你首先在 MariaDB shell 中(使用管理员用户 root 登录)考虑的是通过输入以下内容来审查它们当前的状态:

SELECT HOST,USER FROM mysql.user WHERE USER='';


完成此操作后,如果你打算`REVOKE`权限或从此处列出的用户中删除用户,你可以使用`DROP`命令来执行此操作。首先,你应该审查感兴趣的用户拥有的权限,通过运行:

SHOW GRANTS FOR ''@'localhost';


你现在有两种选择,首先是撤销用户的权限,如下所示:

REVOKE ALL PRIVILEGES, GRANT OPTION FROM ''@'localhost';


然后你可以选择重新分配权限,使用主配方中提供的公式,或者你可以决定通过输入以下内容来删除用户:

DROP USER ''@'localhost';


最后,使用`FLUSH PRIVILEGES;`以通常的方式更新所有你的权限,然后在使用`EXIT;`命令退出 shell 之前。

# 允许远程访问 MariaDB 服务器

除非你正在运行 MariaDB 数据库服务器来驱动同一服务器硬件上的本地 Web 应用程序,否则如果禁止远程访问数据库服务器,大多数工作环境将变得毫无用处。在许多 IT 环境中,你会发现高可用性、集中式的专用数据库服务器在硬件上进行了优化(例如,大量的 RAM),并托管多个数据库,允许从外部到服务器的数百个并行连接。在本配方中,我们将向你展示如何使远程连接到服务器成为可能。

## 准备就绪

要完成此配方,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装。预计 MariaDB 服务器已经安装并运行,并且您已经阅读并应用了*管理 MariaDB 数据库*配方,以了解权限以及如何测试(本地)数据库连接。

## 如何做到这一点...

在我们的示例中,我们希望从同一网络中的客户端计算机(IP 地址为`192.168.1.33`)访问 IP 地址为`192.168.1.12`的 MariaDB 数据库服务器。请根据您的需求适当更改:

1.  首先,以 root 身份登录到您的 MariaDB 数据库服务器,并为传入的 MariaDB 连接打开防火墙:

    ```
    firewall-cmd --permanent --add-service=mysql && firewall-cmd --reload

    ```

1.  之后,我们需要创建一个可以远程连接到我们的 MariaDB 服务器的用户账户(因为我们已经阻止`root`这样做,以增强安全性),使用 MariaDB 命令行界面`mysql`以用户`root`登录数据库服务器,并输入以下 MariaDB 语句(将`XXXX`替换为您选择的密码,也可以根据需要调整用户名和客户端的远程 IP 地址——在我们的例子中,客户端的 IP 地址是`192.168.1.33`):

    ```
    GRANT SELECT ON mysql.user TO 'johndoe'@'192.168.1.33' IDENTIFIED BY 'XXXX';
    FLUSH PRIVILEGES;EXIT;

    ```

1.  现在我们可以从我们网络中 IP 地址为`192.168.1.33`的客户端计算机测试连接。这台计算机需要安装 MariaDB shell(在 CentOS 7 客户端上,安装软件包`mariadb`),并且需要能够 ping 通运行 MariaDB 服务的服務器(在我们的示例中,IP 为`192.168.1.12`)。您可以通过使用以下命令测试与服务器的连接(成功的话,这将打印出`mysql`用户表的内容):

    ```
    echo "select user from mysql.user" | mysql -u johndoe -p mysql -h 192.168.1.12

    ```

## 工作原理...

我们的旅程始于通过使用 firewalld 预定义的 MariaDB 服务打开标准的 MariaDB 防火墙端口 3306,该服务在 CentOS 7 上默认是禁用的。之后,我们配置了允许访问数据库服务器的 IP 地址,这是在数据库级别使用 MariaDB shell 完成的。在我们的示例中,我们使用`GRANT SELECT`命令允许用户`johndoe`在客户端 IP 地址`192.168.1.33`和密码`'XXXX'`访问名为`mysql`的数据库和用户表,仅进行`SELECT`查询。请记住,在这里您也可以在`<hostname>`字段中使用通配符`%`(表示任何字符)。例如,为了定义 C 类网络中的任何可能的主机名组合,您可以使用`%`符号,如下所示`192.168.1.%`。授予对`mysql.user`数据库和表的访问权限仅用于测试目的,您应该在完成测试后使用以下命令从该访问权限中删除用户`johndoe`:`REVOKE ALL PRIVILEGES`, `GRANT OPTION FROM 'johndoe'@'192.168.1.33';`。如果您愿意,也可以删除用户`DROP USER 'johndoe'@'192.168.1.33';`,因为我们不再需要它了。

# 安装 PostgreSQL 服务器和管理数据库

在本食谱中,我们不仅将学习如何在服务器上安装 PostgreSQL DBMS,还将学习如何添加新用户并创建我们的第一个数据库。PostgreSQL 被认为是世界上最先进的开源数据库系统。它以稳定、可靠和精心设计的系统而闻名,完全能够支持高事务和关键任务应用程序。PostgreSQL 是 Ingres 数据库的后代。它由来自世界各地的大量贡献者社区驱动和维护。它可能不如 MariaDB 灵活或普及,但由于 PostgreSQL 是一个非常安全的数据库系统,在数据完整性方面表现出色,因此本食谱的目的是向您展示如何开始探索这个被遗忘的朋友。

## 准备工作

为了完成本食谱,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及互联网连接以便下载额外的软件包。预计您的服务器将使用静态 IP 地址。

## 如何操作...

PostgreSQL(也称为 Postgres)是一个对象关系数据库管理系统。它支持大部分 SQL 标准,并且可以通过服务器管理员以多种方式进行扩展。然而,为了开始,我们必须首先安装必要的软件包:

1.  首先以 root 身份登录您的服务器,然后输入:

    ```
    yum install postgresql postgresql-server

    ```

1.  安装数据库系统后,我们现在必须通过输入以下命令在启动时启用数据库服务器:

    ```
    systemctl enable postgresql

    ```

1.  完成上述步骤后,按照以下方式初始化数据库系统:

    ```
    postgresql-setup initdb

    ```

1.  现在通过启动数据库服务器来完成此过程:

    ```
    systemctl start postgresql

    ```

1.  现在为您的`postgres`管理员设置一个新的初始密码。由于默认的`postgres`用户目前使用的是对等认证,我们需要以`postgres`用户身份执行任何与 Postgres 相关的命令:

    ```
    su - postgres -c "psql --command '\password postgres'"

    ```

1.  为了消除`postgres`用户必须在系统用户基础上登录才能执行如`psql`等与 Postgres 相关的命令的要求,并允许使用数据库用户账户登录,我们需要将`localhost`的认证方法从`peer`更改为`md5`。您可以手动执行此操作,或者使用`sed`工具,如下所示,首先备份文件:

    ```
    cp /var/lib/pgsql/data/pg_hba.conf /var/lib/pgsql/data/pg_hba.conf.BAK
    sed -i 's/^\(local.*\)peer$/\1md5/g' /var/lib/pgsql/data/pg_hba.conf

    ```

1.  接下来,我们必须重启`postgresql`服务以应用我们的更改:

    ```
    systemctl restart postgresql

    ```

1.  现在,您将能够使用用户`postgres`登录到您的 Postgres 服务器,而无需先登录`postgres` Linux 系统用户:

    ```
    psql -U postgres

    ```

1.  要退出 shell(`postgres=#`),请输入以下命令(然后按*回车*键):

    ```
    \q

    ```

1.  现在,我们将发出一个 shell 命令来创建一个新的数据库用户,通过将 `<username>` 替换为适合您自己需求的相应用户名(在提示时输入新用户的密码,重复它,然后输入管理员用户 `postgres` 的密码以应用这些设置):

    ```
    createuser -U postgres -P <username>

    ```

1.  现在,也在 shell 中创建您的第一个数据库,并将其分配给我们新用户,通过将 `<database-name>` 和 `<username>` 的值替换为更适合您需求的值(输入 `postgres` 用户的密码):

    ```
    createdb -U postgres <database-name> -O <username>

    ```

1.  最后,通过打印所有数据库名称来测试您是否可以使用新用户访问 Postgres 服务器:

    ```
    psql -U <username> -l

    ```

## 它是如何工作的...

PostgreSQL 是一种对象关系型数据库管理系统,它适用于所有 CentOS 服务器。虽然 Postgres 可能不如 MariaDB 常见,但其架构和丰富的功能确实使其成为许多关注数据完整性的公司的吸引解决方案。

那么我们从这次经历中学到了什么?

我们从这个配方开始,通过使用 `yum` 安装必要的服务器和客户端 `rpm` 包。完成此操作后,我们在启动时使 Postgres 系统可用,然后使用 `postgresql-setup initdb` 命令初始化数据库系统。我们通过启动数据库服务完成了这个过程。在下一阶段,我们被要求为 Postgres 管理员用户设置密码以加强系统安全性。默认情况下,`postgresql` 包创建一个名为 `postgres` 的新 Linux 系统用户(也用作访问我们的 Postgres DBMS 的管理员 Postgres 用户帐户),通过使用 `su - postgres - c`,我们能够以 `postgres` 用户身份执行 `psql` 命令,这在安装时是强制性的(这称为对等身份验证)。

设置管理员密码后,为了更像 MariaDB shell 类型的登录过程,其中每个数据库用户(包括管理员 `postgres` 用户)都可以使用数据库 `psql` 客户端的用户 `-U` 参数登录,我们将这种 `peer` 身份验证更改为 `md5` 数据库密码身份验证,用于本地主机在 `pg_hba.conf` 文件中(请参阅下一个配方)。重新启动服务后,我们然后使用 Postgres 的 `createuser` 和 `createdb` 命令行工具创建一个新的 Postgres 用户并将其连接到新数据库(我们需要为 `postgres` 用户提供 `-U` 参数,因为只有他有权限)。最后,我们向您展示了如何使用新用户使用 `-l` 标志(列出所有可用数据库)测试与数据库的连接。此外,您可以使用 `-d` 参数使用以下语法连接到特定数据库:`psql -d <database-name> -U <username>`。

## 还有更多...

除了使用`createuser`或`createdb`Postgres 命令行工具(正如我们在这个示例中向你展示的那样)来创建数据库和用户之外,你还可以使用 Postgres shell 来完成相同的操作。实际上,这些命令行工具实际上只是 Postgres shell 命令的包装器,两者之间没有实质性的区别。`psql`是用于在 Postgres 服务器上输入 SQL 查询或其他命令的主要命令行客户端工具,类似于本章中另一个示例中向你展示的 MariaDB shell。在这里,我们将使用名为`template1`的模板启动`psql`,这是用于开始构建数据库的样板(或默认模板)。登录后(`psql -U postgres template1`),输入管理员密码,你应该会看到交互式 Postgres 提示符(`template1=#`)。现在,要在`psql` shell 中创建一个新用户,请输入:

CREATE USER WITH PASSWORD '';


要创建数据库,请输入:

CREATE DATABASE ;


将最近创建的数据库的所有权限授予新用户的选项是:

GRANT ALL ON DATABASE to ;


要退出交互式 shell,请使用:`\q`,然后按*回车*键。

完成这个示例后,你可以说你不仅知道如何安装 PostgreSQL,而且这个过程还突显了这个数据库系统与 MariaDB 之间的一些简单的架构差异。

# 配置对 PostgreSQL 的远程访问

在这个示例中,我们将学习如何配置对默认情况下禁用的 Postgres 服务器的远程访问。Postgres 使用一种称为基于主机的身份验证的方法,这个示例的目的是向你介绍其概念,以便为你提供运行安全可靠的数据库服务器所需的访问权限。

## 准备工作

要完成这个示例,你需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,以及你选择的文本编辑器。预计 PostgreSQL 已经安装并正在运行。

## 如何操作...

在前面的示例中,我们已经使用`sed`修改了基于主机的身份验证配置文件`pg_hba.conf`,以管理我们的 Postgres 客户端身份验证,从对等模式更改为`md5`。在这里,我们将对其进行更改,以管理对我们的 Postgres 服务器的远程访问。

1.  首先,以 root 身份登录,并打开防火墙以允许任何传入的 PostgreSQL 连接到服务器:

    ```
    firewall-cmd --permanent --add-service=postgresql;firewall-cmd --reload

    ```

1.  现在,在你的首选文本编辑器中打开基于主机的身份验证配置文件,方法是输入:

    ```
    vi /var/lib/pgsql/data/pg_hba.conf

    ```

1.  滚动到文件末尾,并添加以下行,使这些行读作如下内容(将`XXX.XXX.XXX.XXX/XX`值替换为你想要授予访问权限的网络地址。例如,如果你的服务器 IP 地址是`192.168.1.12`,那么网络地址将是`192.168.1.0/24`):

    ```
    host    all          all         XXX.XXX.XXX.XXX/XX    md5

    ```

1.  完成后,只需以通常的方式保存并关闭文件,然后通过输入打开主 Postgres 配置文件:

    ```
    vi /var/lib/pgsql/data/postgresql.conf

    ```

1.  将以下行添加到文件末尾:

    ```
    listen_addresses = '*'
    port = 5432

    ```

1.  完成后,以通常的方式保存文件,然后通过输入以下命令重新启动数据库服务器:

    ```
    systemctl restart postgresql

    ```

1.  在同一网络中的任何其他计算机上(由之前设置的`XXX.XXX.XXX.XXX/XX`值定义),您现在可以使用`psql` shell 测试与您的 Postgres 服务器的远程连接是否正常工作(如果您的客户端计算机是 CentOS,您需要使用`yum install postgresql`安装它),通过远程登录到服务器并打印出一些测试数据。在我们的例子中,Postgres 服务器正在运行,IP 地址为`192.168.1.12`。

    ```
    psql -h 192.168.1.12 -U <username> -d <database-name>

    ```

## 它是如何工作的...

PostgreSQL 是一个安全可靠的数据库系统,但我们访问它的方式(无论是远程还是本地)常常会引起混淆。本食谱的目的是揭开基于主机的认证的神秘面纱,并提供一个易于使用的解决方案,帮助您让系统运行起来。

那么我们从这次经历中学到了什么?

我们首先在防火墙中打开 Postgres 服务的标准端口,以便首先从任何远程计算机建立连接。然后,我们使用最喜欢的文本编辑器打开名为`pg_hba.conf`的 Postgres 基于主机的认证配置文件。请记住,我们已经在之前的食谱中将所有本地连接从`对等`更改为`md5`认证,以提供基于用户的认证。插入的主机记录行指定了连接类型、数据库名称、用户名、客户端 IP 地址范围和认证方法。虽然许多之前的命令可能已经理解,但重要的是要认识到有几种不同的认证方法:

+   **信任**: 无条件允许连接,并允许任何人无需密码即可连接到数据库服务器。

+   **拒绝**: 允许数据库服务器无条件拒绝连接,在过滤某些 IP 地址或某些主机时,这一功能仍然很有用。

+   **md5**: 意味着客户端需要提供一个 MD5 加密的密码进行认证。

+   **对等和标识**: 如果客户端登录的 Linux 用户名在系统中作为数据库用户被找到,则授予访问权限。标识用于远程连接,而对等用于本地连接。

完成这项任务后,我们保存并关闭文件,然后打开位于`/var/lib/pgsql/data/postgresql.conf`的主 PostgreSQL 配置文件。你可能知道也可能不知道,除非服务器以适当的`listen_addresses`值启动,否则远程连接是不可能的。默认设置将此设置为本地回环地址,因此有必要允许数据库服务器监听所有网络接口(用星号或`*`表示)以接收 5432 端口的 Postgres 连接。完成后,我们只需保存文件并重新启动数据库服务器。

总有更多的东西要学习,但通过完成这个配方,你不仅对基于主机的认证有了更好的理解,而且你还有能力在本地和远程访问你的 PostgreSQL 数据库服务器。

# 安装 phpMyAdmin 和 phpPgAdmin

使用 MariaDB 或 Postgres 命令行 shell 足以执行基本的数据库管理任务,例如用户权限设置或创建简单的数据库,正如我们在本章中向你展示的那样。随着你的模式和表之间的关系变得更加复杂,以及你的数据增长,你应该考虑使用一些图形数据库用户界面以获得更好的控制和工作性能。对于新手数据库管理员来说也是如此,因为这样的工具为你提供了语法高亮和验证,有些工具甚至有数据库的图形表示(例如,显示实体关系模型)。在这个配方中,我们将向你展示如何安装市场上最流行的两个图形开源数据库管理软件,即`phpMyadmin`和`phpPgAdmin`,它们是基于 Web 的浏览器应用程序,用 PHP 编写。

## 准备就绪

要完成这个配方,你需要具备以下条件:CentOS 7 操作系统的有效安装,具有 root 权限,你选择的基于控制台的文本编辑器,以及互联网连接以便下载额外的软件包。预计你的 MariaDB 或 PostgreSQL 服务器已经按照本章中的配方运行。此外,你需要一个运行中的 Apache 网络服务器,该服务器已安装 PHP,并且必须可以从你的私人网络中的所有计算机访问以部署这些应用程序(请参阅第十二章,*提供网络服务*以获取说明)。此外,你需要启用 EPEL 存储库以安装正确的软件包(请参阅第四章中的配方*使用第三方存储库*,*使用 YUM 管理软件包*)。最后,你需要在你的网络中有一台计算机,该计算机具有图形窗口管理器和现代网络浏览器,以便访问这些网络应用程序。

## 如何做到这一点...

在这个配方中,我们将首先向你展示如何安装和配置`phpMyAdmin`以进行远程访问,然后是如何为`phpPgAdmin`做同样的事情。

### 安装和配置 phpMyAdmin

要安装和配置 phpMyAdmin,请执行以下步骤:

1.  输入以下命令以安装所需的软件包:

    ```
    yum install phpMyAdmin

    ```

1.  现在创建主`phpMyadmin`配置文件的副本:

    ```
    cp /etc/httpd/conf.d/phpMyAdmin.conf /etc/httpd/conf.d/phpMyAdmin.conf.BAK

    ```

1.  接下来,打开主`phpMyAdmin.conf`配置文件,并在您想要授权访问 Web 应用程序的已定义子网的网络地址下添加一行`Require ip XXX.XXX.XXX.XXX/XX`,例如,在`Require ip 127.0.0.1`行下添加`Require ip 192.168.1.0/24`。您需要在文件中执行此操作两次,或者可以使用`sed`自动执行此操作,如下所示。在命令行中,根据您自己的子网网络地址相应地定义环境变量`NET=`。

    ```
    NET="192.168.1.0/24"

    ```

1.  然后输入以下行以将更改应用到配置文件:

    ```
    sed -i "s,\(Require ip 127.0.0.1\),\1\nRequire ip $NET,g" /etc/httpd/conf.d/phpMyAdmin.conf

    ```

1.  之后,重新加载您的 Apache 服务器,现在您应该能够从子网中的任何其他计算机浏览到运行 Web 应用程序的服务器的 IP 地址的`phpMyAdmin`网站,例如`192.168.1.12`(使用 MariaDB 管理员用户 root 或其他数据库用户登录):

    ```
    http://192.168.1.12/phpMyAdmin

    ```

### 安装和配置 phpPgAdmin

以下是安装和配置 phpPgAdmin 的步骤:

1.  输入以下命令以安装所需的软件包:

    ```
    yum install phpPgAdmin

    ```

1.  在编辑`phpPgAdmin`主配置之前,首先对其进行备份:

    ```
    cp /etc/httpd/conf.d/phpPgAdmin.conf /etc/httpd/conf.d/phpPgAdmin.conf.BAK

    ```

1.  允许远程访问`phpPgAdmin`与`phpMyAdmin`非常相似。在这里,您也可以在`phpPgAdmin.conf`文件中的`Require local`行下添加一行`Require ip XXX.XXX.XXX.XXX/XX`,其中包含您定义的子网网络地址,或者使用`sed`实用程序自动执行此操作:

    ```
    NET="192.168.1.0/24"
    sed -i "s,\(Require local\),\1\nRequire ip $NET,g" /etc/httpd/conf.d/phpPgAdmin.conf

    ```

1.  重启 Apache 并浏览到`phpPgAdmin`主页:

    ```
    http://192.168.1.12/phpPgAdmin

    ```

## 它是如何工作的...

在这个相当简单的教程中,我们向您展示了如何在同一台服务器上安装两个最流行的 MariaDB 和 Postgres 的图形化管理工具,这些工具作为 Web 应用程序在您的浏览器中运行(使用 PHP 编写),并启用了对它们的远程访问。

那么我们从这次经历中学到了什么?

使用`yum`包管理器安装`phpMyAdmin`以管理 MariaDB 数据库和`phpPgAdmin`以管理 Postgres 数据库就像安装相应的`rpm`包一样简单。由于这两个工具在官方的 CentOS 7 仓库中找不到,您需要在能够访问和安装这些包之前启用第三方仓库 EPEL。默认情况下,在安装这两个 Web 应用程序时,拒绝来自服务器本身(仅本地)以外的任何连接。由于我们希望从网络中的不同计算机访问它,因此安装了 Web 浏览器后,您需要首先允许远程连接。对于这两个 Web 应用程序,可以使用 Apache 的`Require ip`指令来实现,该指令是 Apache 的`mod_authz_core`模块的一部分。在`phpMyAdmin`和`phpPgAdmin`的配置文件中,我们定义了一个完整的子网,例如`192.168.1.0/24`,以允许连接到服务器,但您也可以在这里使用单个 IP 地址,您希望允许访问该地址。`sed`命令将这些重要的`Require`行插入到配置文件中,但如前所述,如果您愿意,也可以通过使用您选择的文本编辑器编辑这些文件来手动完成。重新加载 Apache 配置后,您就可以使用本食谱中显示的两个 URL 浏览到网页。在两个网站的首页上,您可以使用任何数据库用户登录,无需为他们启用远程权限;任何具有本地权限的用户都足够了。

总之,我们可以说我们只向您展示了两种管理工具的基本配置。总有更多需要学习的内容;例如,您应该考虑使用 SSL 加密来保护 PHP 网站,或者配置您的实例以连接到不同的数据库服务器。此外,如果您更喜欢使用桌面软件来管理数据库,可以查看开源的 MySQL Workbench 社区版,该版本可以从官方 MySQL 网站下载,适用于所有主要操作系统(Windows、OS X、Linux)。


# 第十一章:提供邮件服务

在本章中,我们将涵盖:

+   使用 Postfix 配置域内邮件服务

+   使用 Postfix

+   使用 Dovecot 投递邮件

+   使用 Fetchmail

# 简介

本章是一系列配方的集合,提供了实施和维护当今互联网上最古老、最多才多艺的技术之一的必要步骤。每个人都希望能够发送和接收电子邮件,本章提供了部署这种服务所需的起点,以便及时且高效地进行。

# 使用 Postfix 配置域内邮件服务

Postfix 是一个**邮件传输代理**(**MTA**),负责使用 SMTP 协议在邮件服务器之间传输电子邮件。Postfix 现在是 CentOS 7 上的默认 MTA。在这里,与其他大多数关键网络服务一样,其默认配置允许发送邮件,但不接受来自本地主机以外的任何主机的传入网络连接。如果你只需要一个本地 Linux 用户邮件系统,并且从 localhost 发送邮件到其他外部邮件服务器,这是有道理的。但如果你想为自己的私有网络和域运行自己的集中式邮件服务器,这就相当限制了。因此,本配方的目的是将 Postfix 设置为域内邮件服务,允许网络中的任何主机发送电子邮件,如果收件人是本地域内的有效电子邮件地址,则将其投递到邮件服务器上的正确邮箱。

## 准备工作

要完成本配方,你需要一个具有 root 权限的 CentOS 7 操作系统的安装,你选择的基于控制台的文本编辑器,以及连接到互联网以下载额外的软件包。你需要正确设置你的本地网络,并确保所有想要通过你的单域邮件服务器发送邮件的计算机都在同一个网络中,并且可以 ping 通这个服务器。此外,为任何邮件服务器正确设置系统时间也非常重要。在开始配置之前,请应用第二章,“配置系统”中的“使用 NTP 和 chrony 套件同步系统时钟”配方。最后,你需要为你的邮件服务器设置一个**完全限定域名**(**FQDN**)。请参考第二章,“配置系统”中的“设置你的主机名并解析网络”配方。预计你的服务器将使用静态 IP 地址,并且它将维护一个或多个系统用户帐户。还假设你将按照本章中出现的顺序逐个配方地工作。

## 如何操作...

Postfix 默认安装在所有 CentOS 7 版本上,并且应该处于运行状态。在我们的示例中,我们希望为我们的网络 192.168.1.0/24 构建一个中央邮件服务器,其本地域名为`centos7.home`。

1.  首先以 root 身份登录,并测试 Postfix 是否已经在本地工作,并且可以向您的系统用户发送本地邮件。输入以下命令向指定的 Linux 用户`<username>`发送邮件:

    ```
    echo "This is a testmail" | sendmail <username>

    ```

1.  在 CentOS 7 上,Postfix 也已经配置为无需对配置文件进行任何更改即可向外部电子邮件地址发送邮件(但仅从 localhost)。例如,您可以直接使用:

    ```
    echo "This is a testmail" | sendmail contact@example.com

    ```

    ### 注意

    如果您没有受信任的域和证书支持您的 Postfix 服务器,在大量垃圾邮件的时代,大多数外部邮件服务器将拒绝或将此类邮件直接放入垃圾邮件文件夹。

1.  要查看本地邮件是否已成功投递,请显示最新的邮件日志(按*Ctrl*+*C*退出日志):

    ```
    tail -f /var/log/maillog

    ```

1.  接下来,检查我们的服务器是否有可用的 FQDN。这是强制性的,如果没有正确设置,请参阅第二章,*配置系统*以设置一个(在我们的示例中,这将输出名称`mailserver.centos7.home`):

    ```
    hostname --fqdn

    ```

1.  现在在打开此文件之前创建主 Postfix 配置文件的备份副本:

    ```
    cp /etc/postfix/main.cf /etc/postfix/main.cf.BAK && vi /etc/
    postfix/main.cf

    ```

1.  首先,我们希望 Postfix 监听所有网络接口,而不仅仅是本地接口。激活或取消注释以下行(这意味着删除行首的`#`符号),该行以`inet_interfaces`开头,使其读取如下:

    ```
    inet_interfaces = all

    ```

1.  现在,在下面的一些行中,您会找到读取`inet_interfaces = localhost.`的行。通过在行首放置一个`#`符号来禁用它或注释掉它:

    ```
    # inet_interfaces = localhost

    ```

1.  接下来,我们需要设置邮件服务器的本地域名。例如,如果我们的邮件服务器的 FQDN 是`mailserver.centos7.home`,并且这个邮件服务器负责为整个私有`centos7.home`域投递邮件,那么域名将是(最好将其放在读取`#mydomain = domain.tld`的行下方):

    ```
    mydomain = centos7.home

    ```

1.  考虑到此服务器可能成为域范围内的邮件服务器,您现在应该更新以下以`mydestination`开头的行,使其读取如下(例如,在`mydestination`部分,注释掉第一行`mydestination`并取消注释第二行):

    ```
    mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

    ```

1.  接下来,我们需要指定相对于用户主目录的邮箱文件路径名。为此,向下滚动并找到以`home_mailbox`开头的行,并取消注释以下选项(删除行首的`#`符号):

    ```
    home_mailbox = Maildir/

    ```

1.  保存并关闭文件。现在我们希望在防火墙中打开正确的 Postfix 服务器端口,以允许服务器接收 SMTP 连接:

    ```
    firewall-cmd --permanent --add-service=smtp && firewall-cmd --reload

    ```

1.  接下来,如下重新启动 Postfix 服务:

    ```
    systemctl restart postfix

    ```

1.  之后,登录到同一网络中的另一台计算机并安装**瑞士军刀 SMTP**(**swaks**),以远程测试我们的 Postfix 服务器连接。在 CentOS 上,输入以下内容(需要事先安装 EPEL 存储库):

    ```
    yum install swaks

    ```

1.  现在,为了测试是否可以使用标准 SMTP 邮件端口 25 连接到我们新的 Postfix 服务器,我们的 Postfix 服务器运行在 IP 地址`192.168.1.100`,我们远程发送一封邮件给 Linux 系统用户`john`,他在我们的 Postfix 服务器上有一个系统用户账户:

    ```
    swaks --server 192.168.1.100 --to john@centos7.home

    ```

1.  Swaks 创建的输出应该给我们一个提示,表明邮件传输是否成功。例如(输出已被截断):

    ```
    -> This is a test mailing
    <-  250 2.0.0 Ok: queued as D18EE52B38
     -> QUIT
    <-  221 2.0.0 Bye
    ```

1.  您还可以通过以用户`john`登录到 Postfix 服务器,然后检查并阅读您的本地邮箱收件箱,来测试最后一个命令是否成功,收件箱应该包含一个由 swaks 工具发送的测试邮件的文件(文件名在您的计算机上会有所不同),如下所示:

    ```
    ls ~/Maildir/new
    less ~/Maildir/new/14941584.Vfd02I1M246414.mailserver.centos7.home

    ```

## 它是如何工作的...

我们已经看到,Postfix 默认安装并运行在每个 CentOS 7 系统上,在其基本配置中,邮件服务器监听本地主机地址以接收邮件,因此您已经可以在服务器本地 Linux 系统用户之间发送本地邮件,而无需联系外部 MTA。它已经在运行,因为您的系统已经在使用它为多个本地服务,例如 crond 守护进程或发送关于安全漏洞的警告(例如,以非 sudo 用户身份运行`sudo`命令)。

在我们解释这个配方是如何工作之前,我们需要回顾一些关于 Postfix MTA 系统的更多基础知识。Postfix MTA 服务可以接收来自邮件客户端或其他远程 MTA 服务器的传入电子邮件,使用 SMTP 协议。如果传入的电子邮件是针对 MTA 服务器配置的最终目的地域(例如,一封发送到收件人地址`john@centos7.home`的邮件传入到配置的`centos7.home` Postfix MTA 服务器),它将把邮件投递到服务器上安装的本地邮箱(无论是在文件系统中还是在数据库系统中,如 MariaDB)。如果传入的邮件不是针对这个服务器,它将被转发(转发)到另一个 MTA。

请记住,这就是 Postfix 服务器所能做的一切,不多也不少:接收来自邮件客户端或其他 MTA 的传入 SMTP 连接,将邮件投递到服务器上的本地邮箱,并使用 SMTP 将邮件转发到其他 MTA。与普遍看法相反,Postfix 不能将其本地邮箱中的邮件传输给最终用户。这里我们需要另一种类型的 MTA,称为**投递代理**,它使用不同的邮件协议,如 IMAP 或 POP3。

在这个方法中,我们配置了我们的 Postfix 服务器,以便同一网络中的其他计算机和服务器也可以向我们的 Postfix 服务器发送邮件,这些邮件默认是被阻止的(默认情况下只有服务器本身可以发送邮件)。如果从我们网络中的另一台计算机发送的入站电子邮件,其收件人的电子邮件地址中的域名与我们的 Postfix 服务器的 FQDN 相同,那么它将被传递到由电子邮件的收件人部分定义的适当的本地邮箱;所有外部电子邮件地址都会被转发到一个外部 MTA。

那么我们从这次经历中学到了什么?

我们首先测试了是否可以向系统用户发送本地邮件。在这里,我们以 root 用户身份登录,并使用 Postfix 软件包中包含的 sendmail 程序向有效的本地系统用户发送邮件。每当你使用 sendmail 发送邮件时,你应该能够在`/var/log/maillog`文件中看到一些新行出现,该文件包含邮件的状态信息和其他重要的日志文本。如果你从`root`向用户`john`发送了一条消息,并且你的服务器的 FQDN 是`centos7.home`,那么追加到日志文件的新输出行应该包含一些内容,例如`from=<root@centos7.home>`,`to=<john@centos7.home>`,以及如果成功交付,则包含`status=sent`信息。如果没有出现这样的日志信息,请检查 Postfix 服务的运行状态。

随后,我们展示了我们服务器的 FQDN。正确设置这一点非常重要,因为这些信息将用于在连接到其他 MTA 或邮件客户端时对 Postfix 服务器进行身份验证。MTA 会检查其合作伙伴宣布的 FQDN,有些甚至会拒绝连接,如果未提供或与服务器的实际 DNS 域名不同。在我们的初步测试之后,我们开始编辑 Postfix 的主配置文件,首先对其进行了备份。如前所述,默认情况下,只有位于运行 Postfix 服务的同一服务器上的用户才能在它们之间发送邮件,因为服务器默认仅监听环回设备。因此,我们首先启用了 Postfix 以监听所有可用网络接口,使用`inet_interfaces = all`参数。这确保了我们网络中的所有客户端都可以连接到此服务器。接下来,我们使用`mydomain`参数设置了我们想要的 Postfix 域名。为了使 Postfix 在我们的网络中工作,此处定义的域名变量的值必须与我们的服务器网络的域名完全相同。之后,我们通过选择添加`$mydomain`参数的行来更改`mydestination`参数。这将定义我们的 Postfix 邮件服务器视为最终目的地的所有域。如果 Postfix 邮件服务器被配置为某个域的最终目的地,它将把消息投递到接收用户的本地邮箱,可以在`/var/spool/mail/<username>`(我们将在下一步更改此位置)而不是将邮件转发到其他 MTA(由于我们在示例中将`$mydomain`添加到了最终目的地的列表中,我们将投递所有发送到`centos7.home`域的邮件)。

在这里,您还需要记住,默认情况下,Postfix *信任*与 Postfix 服务器位于同一 IP 子网中的所有其他计算机(SMTP 客户端),以便通过我们的中央服务器向外部电子邮件地址发送邮件(转发邮件到外部 MTAs),这可能对您的网络策略来说过于宽松。由于电子邮件垃圾邮件是互联网上的一个持续问题,我们不希望允许任何用户滥用我们的邮件服务器发送垃圾邮件(开放中继邮件服务器会这样做;它从任何客户端接收任何内容并将其发送到任何邮件服务器),我们可以通过设置`mynetworks_style = host`来进一步提高安全性,该设置仅信任并允许本地主机向外部 MTAs 发送邮件。减少垃圾邮件风险的另一种方法可能是使用`mynetworks`参数,您可以在其中指定允许连接到我们的邮件服务器并通过它发送电子邮件的网络或 IP 地址;例如,`mynetworks = 127.0.0.0/8, 192.168.1.0/24`。要了解更多关于所有可用 Postfix 设置的信息,请参考 Postfix 配置参数手册,使用命令`man 5 postconf`。之后,我们更改了本地邮件应该存储的位置。默认情况下,所有传入邮件都发送到位于`/var/spool/mail/<username>`的中央邮箱空间。为了使本地用户能够在自己的主目录中接收邮件,我们为`home_mailbox`选项使用了`Maildir`参数,该参数将系统更改为将所有邮件发送到`/home/<username>/Maildir/`而不是。之后,我们在 firewalld 中打开了标准 SMTP 协议端口,使用 Postfix 用于与其他 MTAs 或发送传入邮件的邮件客户端通信的 SMPT 服务。

Postfix 已经配置为在启动时启动,但为了完成本节食谱,我们重新启动了 Postfix 服务,以便它接受新的配置设置。在这一阶段,配置 Postfix 的过程已经完成,但为了测试远程访问,我们需要登录到同一网络中的另一台计算机。在这里,我们安装了一个名为`swaks`的小型基于命令行的邮件客户端,它可以用来测试本地或远程 SMTP 服务器连接。我们通过向我们的远程 Postfix 邮件服务器发送邮件并提供收件人用户和我们的 SMTP 服务器的 IP 地址来运行测试。完成此操作后,您应该已收到测试消息,并且作为结果,您应该很高兴知道一切正常工作。但是,如果您碰巧遇到任何错误,则应参考位于`/var/log/maillog`的邮件服务器日志文件。

## 还有更多...

在本节食谱中,我们将更改您的电子邮件发件人地址,加密 SMTP 连接,并配置您的 BIND DNS 服务器以包含我们新邮件服务器的信息。

### 更改电子邮件的显示域名

如果一个 MTA 发送电子邮件,Postfix 默认会自动在发件人的电子邮件地址后附加主机名,除非另有明确说明,这是一个很好的功能,可以帮助你在本地网络中追踪哪台计算机发送了电子邮件(否则,如果你有多台计算机通过名为**root**的用户发送邮件,那么找到邮件的原始来源将会很困难)。通常在向远程 MTA 发送消息时,你不希望本地主机名出现在电子邮件中。

这里最好只保留域名。为了改变这一点,转到你想要从中发送邮件的 Postfix MTA,打开 Postfix 配置文件`/etc/postfix/main.cf`,并通过取消注释(删除行首的`#`符号)以下行来启用此功能以确定原始来源(之后重新启动 Postfix 服务):

myorigin = $mydomain


### 使用 TLS-(SSL)加密进行 SMTP 通信

即使你在一个小型或私人环境中运行自己的 Postfix 服务器,也应该始终意识到,正常的 SMTP 流量将通过互联网以明文形式发送,这使得任何人都有可能嗅探通信。TLS 将允许我们在服务器和邮件客户端之间建立加密的 SMTP 连接,这意味着整个通信将被加密,第三方无法读取。为了做到这一点,如果你还没有购买官方 SSL 证书或为你的域名生成一些自签名证书,请先在这里创建一个(阅读第六章,*提供安全*中的*生成自签名证书*配方了解更多信息)。首先以 root 用户登录到你的服务器,然后转到标准证书位置:`/etc/pki/tls/certs`。接下来,创建一个包含证书及其嵌入的公钥以及私钥的 TLS/SSL 密钥对(输入你的 Postfix 的 FQDN 作为`通用名称`,例如,`mailserver.centos7.home`),为此输入`make postfix-server.pem`。之后,使用你喜欢的文本编辑器打开 Postfix 主配置文件`/etc/postfix/main.cf`,并在文件末尾添加以下行:

smtpd_tls_cert_file = /etc/pki/tls/certs/postfix-server.pem
smtpd_tls_key_file = $smtpd_tls_cert_file
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtpd_tls_loglevel = 1


然后保存并关闭此文件。请注意,将`smtpd_tls_security_level`设置为`may`将激活 TLS 加密(如果邮件客户端程序中可用),否则将使用未加密的连接。只有在您绝对确定所有向您的邮件服务器发送邮件的用户都支持此功能时,才应将此值设置为`encrypt`(这将强制在任何情况下都使用 SSL/TLS 加密)。如果任何发送者(外部 MTA 或邮件客户端)不支持此功能,连接将被拒绝。这意味着来自这些来源的电子邮件将不会被投递到您的本地邮箱。我们还为从我们的 Postfix 服务器到其他 MTAs 的可能的出站 SMTP 连接指定了 TLS 加密,使用`smtp_tls_security_level = may`。通过将 Postfix 的客户端和服务器模式 TLS 日志级别设置为`1`,我们可以获得更详细的输出,以便检查 TLS 连接是否正常工作。一些非常古老的邮件客户端使用古老的 465 端口进行 SSL/TLS 加密的 SMTP,而不是标准的 25 端口。

为了激活此功能,打开`/etc/postfix/master.cf`并搜索,然后取消注释(删除每行开头的`#`)以下行,使其读作:

smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes


保存并关闭文件,然后重新启动 Postfix。接下来,我们需要在防火墙中打开 SMTPS 端口,以允许传入连接到我们的服务器。由于 CentOS 7 中没有可用的 SMTPS firewalld 规则,我们将首先使用`sed`实用程序创建我们自己的服务文件:

sed 's/25/465/g' /usr/lib/firewalld/services/smtp.xml | sed 's/Mail (SMTP)/Mail (SMTP) over SSL/g' > /etc/firewalld/services/smtps.xml
firewall-cmd --reload
firewall-cmd --permanent --add-service=smtps; firewall-cmd --reload


现在,您应该能够测试是否可以使用我们的`swaks`SMTP 命令行工具,使用`-tls`参数从远程计算机到运行在 IP 192.168.1.100 上的 Postfix 服务器建立 SMTPS 连接,例如`swaks --server 192.168.1.100 --to john@centos7.home -tls`。此命令行将测试 SMTP 服务器是否支持 TLS 加密(`STARTTLS`),并在任何原因不可用时退出并显示错误消息。正常工作的输出将如下所示(截断以仅向您显示最重要的行):

-> STARTTLS
<- 220 2.0.0 Ready to start TLS
=== TLS started with cipher TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128
~> This is a test mailing
<~ 250 2.0.0 Ok: queued as E36F652B38


然后,您还可以通过转到 Postfix 服务器上的主邮件日志文件并查找与上一步的 swaks 测试邮件相对应的以下行(您的输出将不同)来重新检查您的 TLS 设置:

Anonymous TLS connection established from unknown[192.168.1.22]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)


### 配置 BIND 以使用您的新邮件服务器

在我们的域内 Postfix 服务器安装和配置完成后,我们现在应该使用 DNS 服务器在我们的域中宣布这一新的邮件服务。请参考第八章,*使用 FTP*,了解如何设置和配置 BIND 服务器,特别是如果您还没有阅读过,请阅读有关**邮件交换器**(**MX**)记录的部分。然后在您的 BIND 正向和相应的反向区域文件中添加一个新的 MX 记录。在您的正向区域文件中,为我们的 Postfix 服务器添加以下行,IP 为`192.168.1.100`:

IN MX 10 mailhost.centos7.home.
mailhost IN A 192.168.1.100


在您的反向区域文件中,您可以添加以下行:

100 IN PTR mailhost.centos7.local.


# 使用 Postfix

在前面的一个教程中,我们学习了如何安装和配置 Postfix 作为我们的域内电子邮件服务器。在处理电子邮件时,Linux 提供了许多不同的工具和程序,我们已经向您展示了如何通过`sendmail`程序以及`swaks`工具发送电子邮件。在本教程中,我们将向您展示如何使用 Unix 和 Linux 中最常用的邮件工具之一,名为`mailx`,它具有`sendmail`包中缺少的一些有用功能,用于发送邮件或阅读您的邮箱。

## 如何操作...

我们将从在我们的服务器上安装`mailx`包开始,该服务器运行我们的域内 Postfix 服务,因为默认情况下 CentOS 7 上不提供它。

1.  首先以 root 身份登录并键入以下命令:

    ```
    yum install mailx

    ```

1.  最简单的方法是使用`mailx`的标准输入模式,如下所示:

    ```
    echo "this is the mail body." | mail -s "subject" john@centos7.home

    ```

1.  您还可以从文本文件发送邮件。这在从 shell 脚本调用`mailx`命令时很有用,使用多个收件人,或者向电子邮件附加一些文件:

    ```
    cat ~/.bashrc | mail -s "Content of roots bashrc file" john
    echo "another mail body" | mail -s "body" john,paul@example.com,chris
    echo "this is the email body" | mailx -s "another testmail but with attachment" -a "/path/to/file1" -a "/path/to/another/file" john@gmail.com

    ```

### 将 mailx 连接到远程 MTA

`mailx`相对于`sendmail`程序的一大优势是,我们可以直接连接并与远程 MTA 邮件服务器通信。为了测试这一功能,请登录到另一台基于 Linux 的计算机,该计算机应与我们的 Postfix 服务器位于同一网络中,安装`mailx`包,并通过我们的 Postfix 服务器的 IP 地址`192.168.1.100`发送邮件(我们已经在之前的教程中打开了传入 SMTP 防火墙端口)。在我们的示例中,我们将向用户`john`发送一封本地邮件:

echo "This is the body" | mail -S smtp=192.168.1.100 -s "This is a remote test" -v john@centos7.home


### 从邮箱中阅读本地邮件

不仅`mailx`程序可以将电子邮件消息发送到任何 SMTP 服务器,当在 Postfix 服务器上本地启动时,它还提供了一个方便的邮件阅读器界面,用于您的本地邮箱。如果您使用`-f`指定用户邮箱运行邮件程序,程序将开始显示所有收件箱电子邮件。但请记住,`mailx`只能在程序在同一服务器上启动时读取本地邮箱(如果您想使用它远程访问您的邮箱,则需要安装 MTA 访问代理,如 Dovecot—稍后介绍—使用 POP3 或 IMAP)。例如,作为 Linux 系统用户`john`登录到 Postfix 服务器,然后,要使用您的用户的本地邮箱打开邮件阅读器,请键入:`mailx -f ~/Maildir`。

现在你将看到当前收件箱中所有邮件消息的列表。如果你想阅读特定的邮件,你需要输入它的编号并按下*回车*键。阅读后,你可以输入*d*后跟*回车*来删除它,或者输入*r*后跟*回车*来回复它。要返回到当前邮件消息概览屏幕,输入*z*后跟*回车*。如果你有超过一屏的邮件消息,输入*z-*(z 减号)后跟*回车*来返回一页。输入*x*后跟*回车*来退出程序。要了解更多信息,请参考`mailx`手册(`man mailx`)。

## 它是如何工作的...

在这个示例中,我们展示了如何安装和使用`mailx`,这是一个用于发送和阅读互联网邮件的程序。它基于一个名为 Berkely mail 的旧 Unix 邮件程序,并提供了 POSIX `mailx`命令的功能。它应该安装在每个严肃的 CentOS 7 服务器上,因为它比`sendmail`程序有一些优势,并且理解 IMAP、POP3 和 SMTP 协议(如果你需要一个更加用户友好的邮件阅读器和发送器,你可以查看 mutt。输入`yum install mutt`来安装它。然后输入`man mutt`来阅读它的手册)。

我们从这次经历中学到了什么?

我们首先在 Postfix 服务器上使用 YUM 包管理器安装了`mailx`包。它包含了`mailx`命令行程序,可以通过`mail`或`mailx`命令运行。之后,我们使用`-s`参数运行程序,该参数指定电子邮件主题,并且还需要一个收件人电子邮件地址作为参数,可以是外部地址或本地 Linux 系统用户名或邮件。如果没有其他设置,`mailx`会默认它与邮件服务器在同一台服务器上运行,因此它会隐式地将邮件发送到本地主机 MTA,在我们的例子中是 Postfix。此外,在最简单的形式中,`mailx`启动时进入交互模式,允许你在命令行手动输入消息正文字段。这对于快速编写测试邮件很有用,但在大多数情况下,你会通过管道将内容从另一个来源输入到`mailx`。这里我们展示了如何使用`echo`命令将字符串写入`mailx`的标准输入(STDIN),但你也可以使用`cat`命令将文件内容输入到`mailx`。

一个常用的例子是通过`cron`在特定预定时间点将某种文件输出或失败命令的日志文件内容发送给管理员用户或系统报告。之后,我们发现可以通过逗号分隔电子邮件地址的方式向多个收件人发送邮件,并向您展示了如何使用`-a`选项在邮件中附带附件。在下一节中,我们向您展示了如何使用`-S`选项设置内部选项(`variable=value`)向远程 SMTP 邮件服务器发送邮件。如果您未在 DNS 服务器上指定标准邮件服务器,或者需要测试远程邮件服务器,这是一个非常有用的功能。最后,在最后一节中,我们向您展示了如何使用`mailx`在您的 Postfix 服务器上阅读本地邮箱。它具有方便的浏览功能,可以阅读、删除和回复,并为您的本地邮箱进行高级电子邮件管理。您可以通过在`mailx`交互式会话中输入命令,然后按下*回车*键来实现这一点。请记住,如果您不喜欢这种方式浏览邮件,您还可以始终使用命令行工具(如`grep`、`less`等)在用户`~/Maildir`目录中阅读或过滤邮件。例如,要搜索所有新邮件中区分大小写的`PackPub.com`关键字,请输入`grep -i packtpub ~/Maildir/new`。

# 使用 Dovecot 发送邮件

在之前的操作中,您已经了解了如何将 Postfix 配置为域范围的邮件传输代理。正如我们在本章第一个操作中学到的,Postfix 只理解 SMTP 协议,并且在将消息从另一个 MTA 或邮件用户客户端传输到其他远程邮件服务器或将邮件存储到其本地邮箱方面做得非常出色。存储或转发邮件后,Postfix 的工作就结束了。Postfix 只能理解和使用 SMTP 协议,并且不能将消息发送到除 MTA 之外的任何其他地方。邮件消息的任何可能的收件人现在都需要使用 ssh 登录到运行 Postfix 服务的服务器,并查看其本地邮箱目录,或者使用`mailx`本地查看其消息,以定期检查是否有新邮件。这是非常不方便的,没有人会使用这样的系统。相反,用户选择从自己的工作站访问和阅读邮件,而不是从我们的 Postfix 服务器所在的位置。因此,开发了另一组 MTA,有时称为**访问代理**,其主要功能是将本地邮箱消息从运行 Postfix 守护程序的服务器同步或传输到外部邮件程序,用户可以在其中阅读这些消息。这些 MTA 系统使用不同于 SMTP 的协议,即 POP3 或 IMAP。其中一个 MTA 程序是 Dovecot。大多数专业服务器管理员都认为 Postfix 和 Dovecot 是完美的合作伙伴,本操作的目的是学习如何配置 Postfix 与 Dovecot 配合工作,以便为我们的邮箱提供基本的 POP3/IMAP 和 POP3/IMAP over SSL(POP3S/IMAPS)服务,为本地网络上的用户提供行业标准的电子邮件服务。

## 准备就绪

要完成此操作,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,您选择的基于控制台的文本编辑器,以及连接到互联网以下载其他软件包。还假设您按照本章中出现的顺序逐个操作,因此预计已将 Postfix 配置为域范围的邮件传输代理。

### 注意

本操作作为设置本地网络上受信任用户的 POP3S/IMAPS 服务的指南。如果不采取额外的安全措施,则不适合在互联网上使用。

## 如何操作...

Dovecot 默认不安装,因此我们必须首先按照给出的步骤安装必要的软件包:

1.  首先,以 root 身份登录并输入以下命令:

    ```
    yum install dovecot

    ```

1.  安装后,通过输入以下命令在启动时启用 Dovecot 服务:

    ```
    systemctl enable dovecot

    ```

1.  现在,在创建备份副本后,使用您喜欢的文本编辑器打开 Dovecot 主配置文件,方法是输入:

    ```
    cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.BAK
    vi /etc/dovecot/dovecot.conf

    ```

1.  首先通过激活(删除行首的`#`符号)并修改以下行来确认我们要使用的`协议`,使其读作:

    ```
    protocols = pop3 imap imaps pop3s

    ```

1.  接下来,启用 Dovecot 监听所有网络接口而不仅仅是回环地址。搜索行`#listen = *`, `::`,然后将其修改为:

    ```
    listen = *

    ```

1.  现在以通常的方式保存并关闭文件,然后在您最喜欢的文本编辑器中打开`10-mail.conf`文件之前,先对其进行备份:

    ```
    cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.BAK
    vi /etc/dovecot/conf.d/10-mail.conf

    ```

1.  向下滚动并取消注释(删除`#`字符)以下行,使其读作:

    ```
    mail_location = maildir:~/Maildir

    ```

1.  再次,在创建备份副本之前,以通常的方式保存并关闭文件,然后在您最喜欢的文本编辑器中打开以下文件:

    ```
    cp /etc/dovecot/conf.d/20-pop3.conf /etc/dovecot/conf.d/20-pop3.conf.BAK
    vi /etc/dovecot/conf.d/20-pop3.conf

    ```

1.  首先取消注释以下行:

    ```
    pop3_uidl_format = %08Xu%08Xv

    ```

1.  现在向下滚动并修改以下行:

    ```
    pop3_client_workarounds = outlook-no-nuls oe-ns-eoh

    ```

1.  以通常的方式保存并关闭文件。现在我们将允许纯文本登录。为此,在打开以下文件之前先进行备份:

    ```
    cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.BAK
    vi /etc/dovecot/conf.d/10-auth.conf

    ```

1.  将行`#disable_plaintext_auth = yes`更改为:

    ```
    disable_plaintext_auth = no

    ```

1.  保存并关闭文件。在我们的最终配置设置中,我们将告诉 Dovecot 使用我们的自签名服务器证书。只需使用本章另一食谱中的 Postfix 证书或创建一个新的(否则跳过此步骤):

    ```
    cd /etc/pki/tls/certs; make postfix-server.pem

    ```

1.  在备份文件后打开 Dovecot 的标准 SSL 配置文件:

    ```
    cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.BAK
    vi /etc/dovecot/conf.d/10-ssl.conf

    ```

1.  现在将以下行(`ssl = required`)更改为读作:

    ```
    ssl = yes

    ```

1.  现在将以下两行更改为指向您服务器自己的证书路径:

    ```
    ssl_cert = < /etc/pki/tls/certs/postfix-server.pem
    ssl_key = </etc/pki/tls/certs/postfix-server.pem

    ```

1.  保存并关闭此文件。接下来,在我们的防火墙中启用 IMAP、IMAPS、POP3 和 POP3S 端口,以允许在相应端口上的传入连接。对于 POP3 和 IMAP,我们需要指定自己的`firewalld`服务文件,因为它们在 CentOS 7 中默认不可用:

    ```
    sed 's/995/110/g' /usr/lib/firewalld/services/pop3s.xml | sed 's/ over SSL//g' > /etc/firewalld/services/pop3.xml
    sed 's/993/143/g' /usr/lib/firewalld/services/imaps.xml | sed 's/ over SSL//g' > /etc/firewalld/services/imap.xml
    firewall-cmd --reload
    for s in pop3 imap pop3s imaps; do firewall-cmd --permanent --add-service=$s; done;firewall-cmd --reload

    ```

1.  现在在启动 Dovecot 服务之前保存并关闭文件:

    ```
    systemctl start dovecot

    ```

1.  最后,为了测试我们的新 POP3/SMTP 网络服务,只需在同一网络中的另一台计算机上登录并运行以下命令,使用`mailx`访问远程 Postfix 服务器上的本地邮箱,该服务器由 Dovecot 提供,使用不同的访问代理协议。在我们的示例中,我们希望使用 IP `192.168.1.100`远程访问系统用户`john`在 Postfix 服务器上的本地邮箱(要登录到 john 的账户,您需要他的 Linux 用户密码):

    ```
    mailx -f pop3://john@192.168.1.100
    mailx -f imap://john@192.168.1.100

    ```

1.  接下来,为了测试安全连接,使用以下命令并在确认证书是自签名且不受信任时输入`yes`:

    ```
    mailx -v -S nss-config-dir=/etc/pki/nssdb -f pop3s://john@192.168.1.100
    mailx -v -S nss-config-dir=/etc/pki/nssdb -f imaps://john@192.168.1.100

    ```

1.  对于所有四个命令,您应该看到用户`john`邮箱的正常`mailx`收件箱视图,其中包含所有邮件消息,就像您在 Postfix 服务器上本地运行`mailx`命令以阅读本地邮件一样。

## 工作原理...

成功完成此配方后,您刚刚为网络中的所有有效服务器用户创建了一个基本的 POP3/SMTP 服务(带或不带 SSL 加密),该服务将从 Postfix 服务器向客户端的电子邮件程序传递本地邮件。每个本地系统用户都可以直接进行身份验证并连接到邮件服务器,并远程获取他们的邮件。当然,还有很多可以做的事情来增强服务,但现在您可以让所有本地系统账户持有者配置他们最喜欢的电子邮件桌面软件,使用您的服务器发送和接收电子邮件消息。

### 注意

与 IMAP 不同,POP3 将邮件从服务器下载到本地机器上,并在之后删除它们,而 IMAP 则与邮件服务器同步您的邮件,而不删除它们。

那么我们从这次经历中学到了什么?

我们首先通过安装 Dovecot 来开始这个配置过程。完成这一步后,我们启用了 Dovecot 在启动时运行,并接着对一系列配置文件进行了一些简短的修改。首先,我们需要确定在`/etc/dovecot/dovecot.cf`文件中的 Dovecot 配置文件中将使用哪种协议:IMAP、POP3、IMAPS 和 POP3S。与其他大多数基本的网络服务一样,安装后它们仅监听回环设备,因此我们启用了 Dovecot 以监听服务器上安装的所有网络接口。在`10-mail.conf`文件中,我们确认了 Dovecot 的邮箱目录位置(使用`mail_location`指令),这是 Postfix 在接收邮件时将它们放入的位置,以便 Dovecot 可以在这里找到它们并拾取。接下来,我们在`20-pop3.conf`文件中打开了 POP3 协议,添加了一个与各种电子邮件客户端(例如 Outlook 客户端)相关的修复,使用了`pop3_uidl_format`和`pop3_client_workarounds`指令。最后,我们通过在`/etc/dovecot/conf.d/10-auth.conf`文件中进行几处更改,启用了纯文本授权。请记住,在没有 SSL 加密的情况下使用纯文本授权与 POP3 或 IMAP 被认为是不安全的,但由于我们专注于局域网(为一组可信的服务器用户),我们不一定将此视为风险。之后,我们通过将`10-ssl.conf`文件中的`ssl`指令指向一些现有的自签名服务器证书,启用了 POP3 和 IMAP 的 SSL(POP3S 和 IMAPS)。在这里,我们将`ssl = required`更改为`ssl=yes`,以不强制客户端连接到 Dovecot 服务时使用 SSL 加密,因为我们确实希望给用户选择启用加密认证的选项,但如果他喜欢的话,不要将其作为强制性的,特别是对于较旧的客户端。之后,为了让我们的 Dovecot 服务可以从网络中的其他计算机访问,我们必须启用四个端口以允许 POP3、IMAP、POP3S 和 IMAPS,即 993、995、110、143,通过使用预定义的`firewalld`服务文件并为我们自己创建缺失的 IMAP 和 POP3 文件。稍后,我们启动了 Dovecot 服务,并使用`mailx`命令远程测试了我们新的 POP3/IMAP 服务器。通过提供一个`-f`文件参数,我们能够指定我们的协议和位置。对于使用 SSL 连接,我们需要提供一个额外的`nss-config-dir`选项,指向我们在 CentOS 7 中存储证书的本地网络安全性服务数据库。

记住,如果你遇到任何错误,你应该始终参考位于`/var/log/maillog`的日志文件。在真正的企业环境中不应使用纯文本授权,而应首选 POP3/IMAP 的 SSL。

## 还有更多...

在主配方中,你被展示了如何安装 Dovecot 以允许具有系统账户的受信任本地系统用户发送和接收电子邮件。这些用户将能够使用他们现有的用户名作为电子邮件地址的基础,但通过做一些改进,你可以快速启用别名,这是一种为现有用户定义替代电子邮件地址的方式。

要开始构建用户别名列表,你应该首先在你的首选文本编辑器中打开以下文件:

vi /etc/aliases


现在将你的新身份添加到文件末尾,其中`<username>`将是实际系统账户的名称:

users aliases for mail

newusernamea:
newusernameb:


例如,如果你有一个名为`john`的用户,目前仅接受来自`john@centos7.home`的电子邮件,但你想为`john`创建一个名为`johnwayne@centos7.home`的新别名,你将这样写:

johnwayne: john


为所有别名重复此操作,但完成后记得以通常的方式保存并关闭文件,然后运行以下命令:`newaliases`。

### 设置电子邮件软件

市场上有大量的电子邮件客户端,到目前为止,你将希望开始设置你的本地用户能够发送和接收电子邮件。这并不复杂,但为了有一个良好的起点,你将希望考虑以下原则。电子邮件地址的格式将是`system_username@domain-name.home`。

传入的 POP3 设置将类似于以下内容:

mailserver.centos7.home, Port 110
Username: system_username
Connection Security: None
Authentication: Password/None


对于 POP3S,只需将端口更改为`995`并使用`连接安全性`:`SSL/TLS`。对于 IMAP,只需将端口更改为`143`,对于 IMAPS 使用端口`993`和`连接安全性`:`SSL/TLS`。

外发的 SMTP 设置将类似于以下内容:

mailserver.centos7.home, Port 25
Username: system_username
Connection Security: None
Authentication: None


# 使用 Fetchmail

到目前为止,在本章中,我们已经向您展示了两种不同形式的 MTA。首先,我们向您介绍了 Postfix MTA,这是一种用于将电子邮件从邮件客户端路由到邮件服务器或邮件服务器之间,并使用 SMTP 协议将它们传递到邮件服务器上的本地邮箱的传输代理。然后,我们向您展示了另一种有时称为访问代理的 MTA,Dovecot 程序可以用于此目的。这将从本地 Postfix 邮箱向任何远程邮件客户端程序提供邮件,使用 POP3 或 IMAP 协议。现在,我们将向您介绍第三种 MTA,可以称为检索代理,并解释我们将使用 Fetchmail 程序的目的。如今,几乎每个人都有多个电子邮件帐户,来自一个或多个不同的邮件提供商,如果您需要登录所有这些不同的 Webmail 站点或使用邮件程序中的不同帐户,则可能难以维护。这就是 Fetchmail 发挥作用的地方。它是一个程序,在您的域内 Postfix 邮件服务器上运行,可以从您所有不同的邮件提供商那里检索所有不同的电子邮件,并将它们传递到 Postfix MTA 的本地用户邮箱中。一旦它们存储在适当的位置,用户就可以通过 Dovecot 访问代理提供的通常方式通过 POP3 或 IMAP 访问所有这些邮件。在本操作中,我们将向您展示如何安装并将 Fetchmail 集成到运行 Postfix MTA 的服务器中。

## 准备工作

要完成此操作,您需要具备 CentOS 7 操作系统的有效安装,拥有 root 权限,选择一个基于控制台的文本编辑器,以及连接到互联网以便下载额外的软件包。假设您是按照本章节中出现的顺序逐个进行操作,因此预计 Postfix 已配置为域内邮件传输代理(MTA),Dovecot 已安装以提供 POP3/IMAP 邮件访问服务。为了在本操作中测试 Fetchmail,我们还需要注册一些外部电子邮件地址:您需要外部电子邮件服务器地址的名称和您电子邮件提供商的端口,以及您的用户登录凭据。通常,您可以在电子邮件提供商网站的常见问题(FAQ)部分找到这些信息。此外,对于某些电子邮件地址,您需要在电子邮件设置中首先启用 POP3 或 IMAP,然后才能使用 Fetchmail。

## 操作步骤...

由于 Fetchmail 并非默认安装,因此我们必须首先安装必要的软件包。请按照以下步骤操作:

1.  首先,登录运行 Postfix 服务器的邮件服务器并输入:

    ```
    yum install fetchmail

    ```

1.  安装完成后,我们将登录到我们希望为其实现 Fetchmail 下载外部邮件的系统用户账户,在我们的例子中是系统用户`john`:`su - john`。现在让我们使用外部电子邮件地址配置 Fetchmail。如果您的邮件提供商名为`mailhost.com`,它在`pop.mailhost.com`上运行 POP3 服务器,在`imap.mailhost.com`上运行 IMAP,用户名为`<user-name>`,这里(请替换您自己的值)是一个示例命令行,用于测试与该提供商的连接并从中获取邮件:

    ```
    fetchmail pop.mailhost.com -p pop3 -u <user-name> -k -v

    ```

1.  如果您想使用同一提供商的 IMAP:

    ```
    fetchmail imap.mailhost.com -p IMAP -u <user-name> -v

    ```

1.  如果 Fetchmail 命令成功,所有新消息将从服务器下载到您的用户账户的本地邮箱中。

## 它是如何工作的...

在本教程中,我们向您展示了如何安装和测试 Fetchmail,它为我们的 Postfix 服务器上拥有本地邮箱的任何用户账户提供了自动邮件检索功能。因此,对于使用 POP3 或 IMAP 连接到邮件服务器的客户端,通过这种方式获取的邮件看起来就像正常的入站电子邮件。Fetchmail 常用于将所有不同的邮件账户合并到一个账户中,但如果您的邮件提供商没有良好的病毒或垃圾邮件过滤器,您也可以使用它。您从主机邮件服务器下载邮件,然后使用 SpamAssassin 或 ClamAV 等工具处理邮件,再将邮件发送给客户。

我们从这次经历中学到了什么?

我们首先通过安装 YUM 包来开始 Fetchmail 的配置。由于我们希望为名为`john`的系统用户邮箱设置 Fetchmail,接下来我们以该用户身份登录。之后,我们通过运行一个简单的命令行来测试 Fetchmail 程序,以从单个邮件提供商处获取邮件。如前所述,为了成功登录到外部邮件提供商,您需要知道服务器的准确登录信息(服务器地址、端口、用户名和密码,以及协议类型)才能使用 Fetchmail。

请记住,虽然一些电子邮件提供商允许用户决定是否使用 SSL 进行安全连接,但像[gmail.com](http://gmail.com)这样的主机仅允许安全连接。这意味着,如果主要电子邮件提供商不支持不带 SSL 连接的 POP3/IMAP 访问,本教程中所示的示例命令可能会失败。请继续阅读下一节,了解如何使用带有 SSL POP3/IMAP 加密的 Fetchmail。

如果您的邮件提供商同时提供 SSL 加密,您应该始终优先选择 SSL 加密。此外,一些提供商如[gmail.com](http://gmail.com)默认只允许用户通过 webmail 使用其服务,并禁用 POP3/IMAP 服务功能;您需要在提供商网站上的账户设置中启用它们(稍后说明)。

我们使用`-p`参数指定使用 fetchmail 命令的邮件协议。使用`-u`参数,我们指定了登录邮件服务器时使用的用户标识,这完全取决于我们的电子邮件提供商。对于 POP3,我们应用了`-k`标志,以确保电子邮件仅从服务器获取,但永远不会被删除(这是使用 POP3 协议时的默认行为)。最后,我们使用`-v`来使输出更加详细,并为我们简单的测试提供更多信息。如果您的电子邮件提供商支持 SSL,您还需要在 Fetchmail 命令中添加一个`-ssl`标志以及邮件服务器的根证书(请参阅下一节了解更多信息)。如果您运行前面的命令,Fetchmail 将立即开始询问服务器上的收件箱中的任何邮件,并将任何邮件下载到用户的本地邮箱。

## 还有更多...

在本节中,我们将向您展示如何配置 Fetchmail,以便使用 POP3S、IMAPS 以及 POP3 和 IMAP 协议从一些实际生活中的邮件提供商下载所有电子邮件到本地邮箱的 Postfix 服务器上,使用配置文件。最后,我们将向您展示如何自动化 Fetchmail 过程。

### 配置 Fetchmail 与 gmail.com 和 outlook.com 电子邮件账户

在这里,我们将配置 Fetchmail 将从以下不同的外部邮件账户下载:流行的[gmail.com](http://gmail.com)和[outlook.com](http://outlook.com)电子邮件提供商以及假设的`my-email-server.com`。

正如我们在主要配方中学到的,Fetchmail 默认通过命令行处理配置选项,这不应是您首选的使用 Fetchmail 自动从不同邮件账户下载邮件的方式。通常情况下,Fetchmail 应该作为服务在后台以守护模式运行,或者使用`cron`作业在启动时运行,并按照特定的时间间隔轮询定义在特殊配置文件中的一系列邮件服务器。通过这种方式,您可以方便地配置多个邮件服务器和一长串其他选项。

### 注意

在撰写本书时,为了使[gmail.com](http://gmail.com)与 Fetchmail 协同工作,您需要使用您的用户账户登录[gmail.com](http://gmail.com)网站,并首先在**转发和 POP/IMAP**中启用 IMAP。此外,在**我的账户**中的**登录与安全**下启用**允许安全性较低的应用程序**。对于[outlook.com](http://outlook.com),登录到您的邮件账户网页,然后点击**选项**,再次点击**选项**,接着点击**使用 POP 连接设备和应用**,然后点击**启用 POP**。

无论是[outlook.com](http://outlook.com)还是[gmail.com](http://gmail.com)都使用安全的 POP3S 和 IMAPS 协议,因此您需要首先在您的 Fetchmail 服务器上下载并安装他们用于签署其 SSL 证书的根证书,以便能够使用他们的服务。在这里,我们可以安装 Mozilla CA 证书包,该证书包由 Mozilla 基金会编译,并包括所有主要网站和服务使用的最常用的根服务器证书,例如我们的邮件提供商使用的证书。对于[gmail.com](http://gmail.com),我们需要 Equifax Secure Certificate Authority 根证书,而对于[outlook.com](http://outlook.com),我们需要 Globalsign 的根服务器证书。Fetchmail 需要这些根证书来验证从电子邮件服务器下载的任何其他 SSL 证书的有效性。以 root 身份登录到您的 Postfix 服务器并安装以下软件包:

yum install ca-certificates


之后,以 Linux 系统用户身份登录,例如,`john`,我们将为其创建一个新的 Fetchmail 配置文件,并且他已经在我们的服务器上拥有位于其主目录下的`~/Maildir`的本地 Postfix 邮箱目录。在配置 Fetchmail 配置文件中的任何账户之前,您应该始终首先使用 Fetchmail 命令行测试到特定账户的连接和身份验证是否正常,如前一个配方所示。为了测试我们不同邮件提供商的账户,我们需要三个不同的命令行调用。为了测试您的提供商是否使用 SSL 加密,您需要`–ssl`标志;对于不允许非 SSL 连接的邮件提供商,典型的输出可能是:

Fetchmail: SSL connection failed.
Fetchmail: socket error while fetching from @
Fetchmail: Query status=2 (SOCKET)


如果您的 google 和 outlook 用户名是`johndoe`,在两个邮件提供商处进行测试,对于使用 IMAPS 协议尝试与 google 进行测试(在提示时输入您的电子邮件用户的密码):

fetchmail imap.gmail.com -p IMAP --ssl -u johndoe@gmail.com -k -v


如果登录成功,输出应该类似于(已截断):

Fetchmail: IMAP< A0002 OK johndoe@gmail.com authenticated (Success)
9 messages (2 seen) for johndoe at imap.gmail.com.
Fetchmail: IMAP> A0005 FETCH 1:9 RFC822.SIZE


对于使用 POP3S 测试[outlook.com](http://outlook.com),请使用:

fetchmail pop-mail.outlook.com -p POP3 --ssl -u johndoe@outlook.com -k -v


成功后,输出应该类似于(已截断):

Fetchmail: POP3> USER johndoe@outlook.com
Fetchmail: POP3< +OK password required
Fetchmail: POP3< +OK mailbox has 1 messages


对于我们在`my-email-server.com`上的第三个假设电子邮件账户,我们将使用不带 SSL 的 POP3 或 IMAP 来测试它,使用我们的账户:

fetchmail pop3.my-email-server.com -p POP3 -u johndoe -k -v
fetchmail imap.my-email-server.com -p IMAP -u johndoe -v


您还应该检查从外部提供商获取的所有邮件是否已正确下载。使用`mailx`命令查看系统用户的本地邮箱(`mailx -f ~/Maildir`)。在我们成功验证 Fetchmail 能够连接到服务器并获取一些邮件之后,我们现在可以在系统用户的家目录中创建一个本地 Fetchmail 配置文件,以便自动化此过程并为多个邮件地址进行配置。首先使用`vi ~/.fetchmailrc`打开一个新文件。请记住,可以在命令行上放置的所有命令也可以在配置文件中使用,只是名称略有不同(并且更多)。现在输入以下内容(将`john`替换为您的实际 Linux 系统用户,`johndoe`替换为您的电子邮件用户账户名,`secretpass`替换为该账户的实际邮件密码):

set postmaster "john"
set logfile fetchmail.log
poll imap.gmail.com with proto IMAP
user 'johndoe@gmail.com' there with password 'secretpass' is john here
ssl
fetchall
poll pop-mail.outlook.com with proto POP3
user 'johndoe@outlook.com' there with password 'secretpass' is john here
ssl
fetchall
poll pop3.my-email-server.com with proto POP3
user 'johndoe@my-email-server.com' there with password 'secretpass' is john here
fetchall


保存并关闭此文件。在此文件中,我们使用了以下重要命令:

+   `postmaster`:定义将接收 Fetchmail 遇到问题时的所有警告或错误邮件的本地 Linux 用户。

+   `logfile`:定义一个日志文件名,这对于我们监督和调试 Fetchmail 输出非常有帮助,当它在后台长时间连续运行时。

+   `poll`部分:指定从特定邮件提供商下载邮件。对于每个邮件账户,您将定义一个这样的轮询部分。如您所见,语法与我们测试单个连接时在命令行上使用的语法非常相似。使用`proto`定义`mail`协议,`user`是邮件账户的登录用户,`password`是账户的登录密码,使用`is <username> here`参数指定此邮件账户绑定到哪个本地系统用户账户。对于 SSL 连接,您需要`ssl`标志,我们指定了`fetchall`参数以确保我们也下载电子邮件提供商标记为`read`的所有电子邮件消息,否则 Fetchmail 不会下载已读邮件。

接下来更改`.fetchmailrc`文件的权限,因为它包含密码,因此不应被我们自己的用户以外的任何人读取:

chmod 600 ~/.fetchmailrc


最后,我们使用配置文件中的设置执行 Fetchmail。为了测试,我们将使用一个非常详细的参数:`fetchmail -vvvv`。现在,来自您所有不同电子邮件提供商的所有新邮件都应该被获取,因此之后您应该检查输出,看看每个服务器是否都已准备好并且可以像我们之前在命令行测试中进行的单个测试一样被轮询。所有新邮件都应该被下载到本地邮箱,因此为了阅读本地邮件,您可以像往常一样使用`mailx`命令,例如:`mail -f ~/Maildir`。

### 自动化 Fetchmail

正如刚才所说,我们现在可以随时手动启动轮询过程,只需在命令行中输入`fetchmail`即可。这将轮询并从我们在新配置文件中指定的邮件服务器获取所有新邮件,然后在处理每个条目一次后退出程序。现在仍然缺少的是一个机制,以特定间隔持续查询我们的邮件服务器,每当可以获取新邮件时更新我们的邮箱。您可以使用两种方法。要么将`fetchmail`命令作为 cron 作业运行,要么作为替代方案,您可以以守护进程模式启动 Fetchmail(在您的`.fetchmailrc`配置文件中使用参数`set daemon`激活它。)并将其置于后台。这样,Fetchmail 将始终运行,并在给定的时间点唤醒,开始轮询,直到处理完所有内容,然后回到睡眠状态,直到下一个间隔到达。

由于两种方法基本相同,这里我们将向您展示如何将 Fetchmail 作为 cron 作业运行,这设置起来要容易得多,因为我们不必创建一些自定义的 systemd 服务文件(目前在 CentOS 7 中没有现成的`fetchmail systemd`服务)。对于每个系统用户(例如,`john`),他们都有一个`fetchmail`配置文件,要每 10 分钟启动一次电子邮件服务器轮询过程,请输入以下命令一次以注册 cron 作业:

crontab -l | { cat; echo "*/10 * * * * /usr/bin/fetchmail &> /dev/null
"; } | crontab -


### 注意

不要将 Fetchmail 轮询周期设置得短于每 5 分钟一次,否则一些邮件提供商可能会阻止或禁止您,因为它只是使他们的系统过载。


# 第十二章:提供 Web 服务

在本章中,我们将介绍以下内容:

+   安装 Apache 并提供网页服务

+   启用系统用户并构建发布目录

+   实施基于名称的托管

+   使用 Perl 和 Ruby 实现 CGI

+   安装、配置和测试 PHP

+   保护 Apache

+   使用安全套接字层(SSL)设置 HTTPS

# 引言

本章是一系列食谱的集合,提供了为网页提供服务的必要步骤。从安装 Web 服务器到通过 SSL 提供动态页面,本章提供了在任何时间和任何地点实施行业标准托管解决方案所需的起点。

# 安装 Apache 并提供网页服务

在本食谱中,我们将学习如何安装和配置 Apache Web 服务器以启用静态网页服务。Apache 是世界上最受欢迎的开源 Web 服务器之一。它作为后端运行着超过一半的互联网网站,并可用于提供静态和动态网页。通常被称为`httpd`,它支持广泛的功能。本食谱的目的是向您展示如何轻松地使用 YUM 包管理器进行安装,以便您可以保持服务器最新的安全更新。Apache 2.4 在 CentOS 7 上可用。

## 准备就绪

要完成本食谱,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及连接到互联网以下载其他软件包的能力。预计您的服务器将使用静态 IP 地址和主机名。

## 如何操作...

Apache 默认未安装,因此我们将从使用 YUM 包管理器安装必要的软件包开始。

1.  首先,以 root 身份登录并输入以下命令:

    ```
    yum install httpd

    ```

1.  通过输入以下内容创建主页:

    ```
    vi /var/www/html/index.html

    ```

1.  现在添加所需的 HTML。您可以使用以下代码作为起点,但预计您会希望对其进行修改以满足您的需求:

    ```
    <!DOCTYPE html>
    <html lang="en">
    <head><title>Welcome to my new web server</title></head>
    <body><h1>Welcome to my new web server</h1>
    <p>Lorem ipsum dolor sit amet, adipiscing elit.</p></body>
    </html>
    ```

1.  您现在可以使用以下命令删除 Apache 2 测试页面:

    ```
    rm -f /etc/httpd/conf.d/welcome.conf

    ```

1.  完成这些步骤后,我们现在将考虑为基本使用配置`httpd`服务的需要。为此,打开您最喜欢的文本编辑器中的`httpd`配置文件,输入(在您已经备份文件之后):

    ```
    cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.BAK
    vi /etc/httpd/conf/httpd.conf

    ```

1.  现在向下滚动找到行`ServerAdmin root@localhost`。设置此值的传统方法基于使用 webmaster 身份,因此只需修改电子邮件地址以反映更符合您自己需求的内容。例如,如果您的服务器的域名是`www.centos7.home`,那么您的条目将与此类似:

    ```
    ServerAdmin webmaster@centos7.home

    ```

1.  现在向下滚动几行,找到以下`ServerName`指令:`#ServerName www.example.com:80`。取消注释此行(即删除其前面的#符号),并将值`www.example.com`替换为更适合您自己需求的值。例如,如果您的服务器域名为`www.centos7.home`,则您的条目将如下所示:

    ```
    ServerName www.centos7.home:80

    ```

1.  接下来,我们将稍微扩展一下`DirectoryIndex`指令。找到`DirectoryIndex index.html`这一行,它是`<IfModule dir_module>`块的一部分,然后将其更改为:

    ```
    DirectoryIndex index.html index.htm

    ```

1.  保存并关闭文件,然后键入以下命令以测试配置文件:

    ```
    apachectl configtest

    ```

1.  接下来,让我们通过允许传入的`http`连接(默认为端口 80)到服务器来配置 Web 服务器的防火墙:

    ```
    firewall-cmd --permanent --add-service http && firewall-cmd --reload 

    ```

1.  现在继续设置`httpd`服务以在启动时启动并启动该服务:

    ```
    systemctl enable httpd && systemctl start httpd

    ```

1.  现在,您可以从与您的 Web 服务器位于同一网络中的任何计算机上测试`httpd`(两个系统应该能够相互看到并进行 ping 操作),通过将以下 URL 中的`XXX.XXX.XXX.XXX`替换为您的服务器 IP 地址,以查看我们创建的自定义 Apache 测试页面:

    ```
    http://XXX.XXX.XXX.XXX.

    ```

1.  或者,如果您没有 Web 浏览器,可以使用`curl`从网络中的任何计算机上获取我们的测试页面,以检查 Apache 是否正在运行:

    ```
    curl http://XXX.XXX.XXX

    ```

## 它是如何工作的...

Apache 是一个软件包,它使您能够发布和提供 Web 页面,并且更常被称为`httpd`、Apache2 或简称为 Apache。本食谱的目的是向您展示 CentOS 如何轻松地让您开始创建您的第一个网站。

那么我们从这次经历中学到了什么?

我们首先通过 YUM 包管理器安装了名为`httpd`的 Apache,并了解到在 CentOS 7 上,默认提供静态 HTML 的位置是`/var/www/html`。因此,我们的首要任务是创建一个合适的欢迎页面,我们将其放置在`/var/www/html/index.html`。我们使用了一个基本的 HTML 模板来帮助您起步,并期望您会希望自定义这个页面的外观和感觉。接着,我们删除了位于`/etc/httpd/conf.d/welcome.conf`的默认 Apache 2 欢迎页面。随后,下一步是在备份`httpd.conf`配置文件后,使用我们喜欢的文本编辑器打开它,以便在出现问题时可以恢复更改。首先,我们定义了服务器的电子邮件地址和服务器名称,这些信息通常出现在服务器生成的网页的错误消息中;因此,它应该反映您的域名。接下来,我们调整了`DirectoryIndex`指令,该指令定义了在请求目录时将首先发送给浏览器的文件。通常,人们请求的不是特定的网页而是目录。例如,如果您浏览到`www.example.com`,您请求的是一个目录,而`www.example.com/welcome.html`是一个特定的网页。默认情况下,Apache 发送请求目录中的`index.html`,但我们扩展了这一点,因为许多网站使用`.htm`扩展名。最后,我们以通常的方式保存并关闭了`httpd`配置文件,然后使用`apachectl configtest`命令检查 Apache 配置文件是否存在任何错误。这应该会打印出一条`Syntax OK`消息,然后我们可以启用`httpd`服务在启动时自动启动。我们必须在 firewalld 中打开标准的 HTTP 端口 80,以允许对服务器的传入 HTTP 请求,最后我们启动了`httpd`服务。请记住,如果配置文件已被更改,您也可以始终在不完全重启服务的情况下重新加载 Apache 的配置文件,方法是使用:`systemctl reload httpd`。完成这些步骤后,只需从同一网络中的另一台计算机打开浏览器,并选择一种查看我们新 Apache 启动页面的方法。您可以使用服务器的 IP 地址(例如,`http://192.168.1.100`),而那些支持主机名的人可以输入主机名(例如,`http://www.centos7.home`)。Apache 的访问和错误日志文件可以在`/var/log/httpd`中找到。要实时查看谁正在访问您的 Web 服务器,请打开`/var/log/httpd/access_log`;要查看所有错误,请输入`/var/log/httpd/error_log`。

尽管 Apache 是一个庞大的主题,我们无法涵盖其每一个细节,但在接下来的章节中,我们将继续揭示更多的功能,这些功能将帮助您构建一个理想的 Web 服务器。

# 启用系统用户和构建发布目录

在本食谱中,我们将学习 Apache 如何为您提供允许系统用户在其家目录中托管网页的选项。这种方法自 Web 托管开始以来就被 ISP 使用,并且在许多方面,由于它能够避免更复杂的虚拟托管方法,它继续蓬勃发展。在前一个食谱中,您被展示了如何安装 Apache Web 服务器,并且出于为系统用户提供托管设施的愿望,本食谱的目的是向您展示如何在 CentOS 7 中实现这一点。

## 准备就绪

要完成本食谱,您将需要一个具有 root 权限的工作 CentOS 7 操作系统安装和一个您选择的基于控制台的文本编辑器。预计您的服务器将使用支持主机名或域名的静态 IP 地址,并且 Apache Web 服务器已经安装并正在运行。此外,服务器上至少应有一个系统用户帐户。

## 如何操作...

为了提供本食谱所提供的功能,不需要额外的软件包,但我们需要对 Apache 配置文件进行一些修改。

1.  首先,以 root 身份登录,并在您最喜欢的文本编辑器中打开 Apache 用户目录配置文件,首先创建其备份副本,然后输入以下命令:

    ```
    cp /etc/httpd/conf.d/userdir.conf /etc/httpd/conf.d/userdir.conf.BAK
    vi /etc/httpd/conf.d/userdir.conf

    ```

1.  在文件中,找到读作`UserDir disabled`的指令。将其更改为以下内容:

    ```
    UserDir public_html

    ```

1.  现在滚动到`<Directory "/home/*/public_html">`部分,并用这里的块替换现有的块:

    ```
    <Directory /home/*/public_html>
        AllowOverride All
        Options Indexes FollowSymLinks
        Require all granted
    </Directory>
    ```

1.  保存并退出文件。现在以任何系统用户身份登录,以便与您的发布网页目录一起工作(`su - <username>`),然后在您的家目录中创建一个网页发布文件夹和一个新的用户主页:

    ```
    mkdir ~/public_html && vi ~/public_html/index.html

    ```

1.  现在添加所需的 HTML。您可以使用以下代码作为起点,但预计您会对其进行修改以满足自己的需求:

    ```
    <!DOCTYPE html>
    <html lang="en">
    <head><title>Welcome to my web folder's home page</title></head>
    <body><h1>Welcome to my personal home page</h1></body>
    </html>
    ```

1.  现在通过键入以下内容来修改 Linux 系统用户的`<username>`家目录的权限:

    ```
    chmod 711 /home/<username>

    ```

1.  将`public_html`的读/写权限设置为`755`,以便 Apache 稍后可以执行它:

    ```
    chmod 755 ~/public_html -R

    ```

1.  现在再次以 root 身份登录,使用`su - root`命令来适当地配置 SELinux,以便使用 http 家目录:

    ```
    setsebool -P httpd_enable_homedirs true

    ```

1.  作为 root,更改用户网页公共目录的 SELinux 安全上下文(这需要安装`policycoreutils-python`软件包),用户名为`<user>`:

    ```
    semanage fcontext -a -t httpd_user_content_t /home/<user>/public_html
    restorecon -Rv /home/<user>/public_html

    ```

1.  要完成本食谱,只需重新加载`httpd`服务配置:

    ```
    apachectl configtest && systemctl reload httpd

    ```

1.  您现在可以通过在任何浏览器中浏览到(适当替换<username>):`http://<SERVER IP ADDRESS>/~<username>`来测试您的设置。

## 它是如何工作的...

在本食谱中,我们了解到通过在 Apache Web 服务器上启用用户目录来托管自己的对等体是多么容易。

我们从这次经历中学到了什么?

我们首先通过在 Apache 的`userdir.conf`中进行一些小的配置更改来开始这个配方,以便设置用户目录支持。我们通过将`UserDir`指令从禁用调整为指向每个用户主目录内的 HTML 网页目录的名称来激活用户目录,该目录将包含我们所有用户的网页内容,并将其称为`public_html`(您可以更改此目录名称,但`public_html`是命名它的既定标准)。然后,我们继续修改`<Directory /home/*/public_html>`标签。此指令将其封闭的所有选项应用于开始标签`/home/*/public_html`定义的文件系统部分。在我们的示例中,为该目录启用了以下选项:当目录没有`index.html`时,使用`Indexes`显示目录的文件和文件夹内容作为 HTML。正如我们将在配方*Securing Apache*中看到的,这应该避免用于您的网络根目录,而对于提供用户目录,如果您只想让您的家庭文件夹对您的同行可访问,以便他们可以快速共享一些文件(如果您有任何安全问题,请删除此选项),这可能是一个不错的选择。`FollowSymLinks`选项允许从`public_html`目录到文件系统中任何其他目录或文件的符号链接(`man ln`)。同样,避免在您的网络根目录中使用,但对于家庭目录,如果您需要在不将它们复制到其中的情况下使文件或文件夹在`public_html`文件夹中可访问,这可能很有用(用户目录通常有磁盘配额)。接下来,我们配置了对`public_html`文件夹的访问控制。我们通过设置`Require` `all granted`来实现这一点,这告诉 Apache,在这个`public_html`文件夹中,任何人都可以通过 HTTP 协议访问内容。如果您想限制对`public_html`文件夹的访问,则可以替换`all granted`为不同的选项。例如,要基于主机名允许访问,请使用`Require host example.com`。使用`ip`参数,我们可以将`public_html`文件夹限制为仅内部可用的网络,例如`Require ip 192.168.1.0/24`。如果您的 Web 服务器具有多个网络接口,并且一个 IP 地址用于连接到公共 Internet,另一个用于您的内部专用网络,这特别有用。您可以在`Directory`块内添加多个`Require`行。请始终至少设置`Require local`,这允许本地访问。

保存工作后,我们开始对主目录进行各种更改。首先,我们在用户的主目录中创建了实际的`public_html`文件夹,这将成为稍后个人网页发布的实际文件夹。接下来,我们将权限更改为`755`,这意味着我们的用户可以在文件夹中执行所有操作,但其他用户和组只能读取和执行其内容(并进入该文件夹)。这种权限是必需的,因为如果有人通过 Apache Web 服务器请求其内容,`public_html`文件夹中的所有文件都将由名为`apache`的用户和组`apache`访问。如果未为`其他用户`标志设置读取或执行权限(`man chmod`),我们将在浏览器中收到`访问被拒绝`的消息。如果我们不提前更改父`/home/<username>`目录的权限,也会出现这种情况,因为父目录权限可以影响其子文件夹的权限。CentOS Linux 中的普通用户主目录具有`700`权限,这意味着主目录的所有者可以执行任何操作,但其他所有人都完全被锁定在主文件夹及其内容之外。

如前所述,Apache 用户需要访问子文件夹`public_html`,因此我们必须将主文件夹的权限更改为`711`,以便其他人至少可以进入目录(然后也可以访问子文件夹`public_html`,因为这被设置为可读/写访问)。接下来,我们为 SELinux 设置新网页文件夹的安全上下文。在运行 SELinux 的系统上,必须将所有 Apache 网页发布文件夹设置为`httpd_user_content_t` SELinux 标签(及其内容),以便使它们对 Apache 可用。此外,我们确保设置了正确的 SELinux 布尔值以启用 Apache 主目录(默认情况下已启用):`httpd_enable_homedirs`为`true`。阅读第十四章,*使用 SELinux*了解更多关于 SELinux 的信息。

您应该知道,管理主目录的过程应该为每个用户重复。您不必每次启用新系统用户时都重新启动 Apache,但是,在第一次完成这些步骤后,只需重新加载`httpd`服务的配置以反映对配置文件所做的初始更改即可。从这一点开始,您的本地系统用户现在可以使用基于其用户名的唯一 URL 发布网页。

# 实施基于名称的托管

通常情况下,如果您按照之前的步骤安装了 Apache,您可以托管一个可以通过服务器 IP 地址或 Apache 运行的域名访问的网站,例如`http://192.168.1.100`或`http://www.centos7.home`。这种系统对于服务器资源来说非常浪费,因为您需要为每个想要托管的域名单独安装服务器。**基于名称的**或**虚拟主机**用于在同一 Apache Web 服务器上托管多个域名。如果已经通过 DNS 服务器或本地`/etc/hosts`文件将多个不同的域名分配给您的 Apache Web 服务器的 IP 地址,则可以为每个可用的域名配置虚拟主机,以将用户引导至 Apache 服务器上包含站点信息的特定目录。任何现代的网络空间提供商都使用这种类型的虚拟主机将一个 Web 服务器的空间分割成多个站点。只要您的 Web 服务器能够处理其流量,就没有限制可以创建的站点数量。在本步骤中,我们将学习如何在 Apache Web 服务器上配置基于名称的虚拟主机。

## 准备工作

要完成本步骤,您需要一个具有 root 权限的 CentOS 7 操作系统的正常安装,以及您选择的基于控制台的文本编辑器。预计您的服务器将使用静态 IP 地址,Apache 已安装并正在运行,并且您已经在之前的步骤中启用了系统用户发布目录。如果没有事先设置一个或多个域名或子域名,虚拟主机将无法工作。

为了测试,您可以在`/etc/hosts`中设置(参见第二章中的“设置主机名和解决网络问题”步骤),或者在您的 BIND DNS 服务器中配置一些 A 或 CNAMES(参考第九章),使用不同的域名或子域名,如`www.centos7.home`,全部指向您的 Apache Web 服务器的 IP 地址。

### 注意

一个常见的误解是,Apache 可以自行为您的 Apache Web 服务器创建域名。这是不正确的。您希望使用虚拟主机将不同的域名连接到不同目录之前,需要在 DNS 服务器或`/etc/hosts`文件中设置这些域名,使其指向您的 Apache 服务器的 IP 地址。

## 如何操作...

为了本配方的目的,我们将构建一些具有以下 Apache 示例子域名的本地虚拟主机:`www.centos7.home`,`web1.centos7.home`,`web2.centos7.home`和`<username>.centos7.home`,对应于 Web 发布文件夹`/var/www/html`,`/var/www/web1`,`/var/www/web2`和`/home/<username>/public_html`,以及域的网络名称`centos7.home`。这些名称是可互换的,预计您将希望根据更适合您自己需求和情况的内容来定制此配方。

1.  首先,以 root 身份登录到您的 Apache 服务器,并创建一个新的配置文件,该文件将包含我们所有的虚拟主机定义:

    ```
    vi /etc/httpd/conf.d/vhost.conf

    ```

1.  现在,请输入以下内容,将`centos7.home`的值和用户名`<username>`定制以适应您自己的需求:

    ```
    <VirtualHost *:80>
        ServerName centos7.home
        ServerAlias www.centos7.home
        DocumentRoot /var/www/html/
    </VirtualHost>   
    <VirtualHost *:80>
        ServerName  web1.centos7.home
        DocumentRoot /var/www/web1/public_html/
    </VirtualHost>
    <VirtualHost *:80>
        ServerName  web2.centos7.home
        DocumentRoot /var/www/web2/public_html/
    </VirtualHost>
    <VirtualHost *:80>
        ServerName  <username>.centos7.home
        DocumentRoot /home/<username>/public_html/
    </VirtualHost>
    ```

1.  现在以通常的方式保存并关闭文件,然后继续为当前缺失的两个虚拟主机创建目录:

    ```
    mkdir -p /var/www/web1/public_html /var/www/web2/public_html

    ```

1.  完成此操作后,我们现在可以使用我们喜欢的文本编辑器为缺失的子域`web1`和`web2`创建默认索引页面,如下所示:

    ```
    echo "<html><head></head><body><p>Welcome to Web1</p></body></html>" > /var/www/web1/public_html/index.html
    echo "<html><head></head><body><p>Welcome to Web2</p></body></html>" > /var/www/web2/public_html/index.html

    ```

1.  现在重新加载 Apache Web 服务器:

    ```
    apachectl configtest && systemctl reload httpd

    ```

1.  现在,为了简单的测试目的,我们将在想要访问这些虚拟主机的客户端计算机的`hosts`文件中配置我们新的 Apache Web 服务器的所有子域,但请记住,您也可以在 BIND DNS 服务器中配置这些子域。以 root 身份登录到此客户端计算机(它需要与我们的 Apache 服务器在同一网络中),并将以下行添加到`/etc/hosts`文件中,假设我们的 Apache 服务器具有 IP 地址 192.168.1.100:

    ```
    192.168.1.100 www.centos7.home
    192.168.1.100 centos7.home
    192.168.1.100 web1.centos7.home
    192.168.1.100 web2.centos7.home
    192.168.1.100 john.centos7.home

    ```

1.  现在,在这台计算机上,打开浏览器并通过在地址栏中输入以下地址来测试(将`<username>`替换为您为虚拟主机定义的用户名):`http://www.centos7.home`,`http://web1.centos7.home`,`http://web2.centos7.home`和`http://<username>.centos7.home`。

## 它是如何工作的...

本配方的目的是向您展示实现基于名称的虚拟主机是多么容易。这种技术将提高您的工作效率,采用这种方法将为您提供无限的机会来进行基于域名的网络托管。

那么,我们从这次经历中学到了什么?

我们首先创建一个新的 Apache 配置文件来存放我们所有的虚拟主机配置。请记住,在`/etc/httpd/conf.d/`目录中以`.conf`扩展名结尾的所有文件将在 Apache 启动时自动加载。接着,我们继续添加相关的指令块,从我们的默认服务器根目录`centos7.home`和别名`www.centos7.home`开始。任何虚拟主机块中最重要的选项是`ServerName`指令,它将我们 Web 服务器的 IP 地址的现有域名映射到文件系统上的特定目录。当然,您可以包含更多的设置,但之前的解决方案提供了基本的构建块,使您能够将其作为完美的起点。接下来,我们为我们的`centos7.home`子域`web1`、`web2`和`<username>`创建了单独的条目。请记住,每个虚拟主机都支持典型的 Apache 指令,并且可以根据您的需要进行定制。请参考官方的 Apache 手册(安装 YUM 包`httpd-manual`,然后转到位置`/usr/share/httpd/manual/vhosts/`)以了解更多信息。在我们为每个想要的子域创建了虚拟主机块之后,我们继续创建了存放实际内容的目录,并在每个目录中创建了一个基本的`index.html`。在这个例子中,我们的`web1`和`web2`内容目录被添加到了`/var/www`。这并不是说你不能在其他地方创建这些新文件夹。实际上,大多数生产服务器通常将这些新目录放在主文件夹中,如我们的`/home/<username>/public_html`示例所示。但是,如果您确实打算采用这种方法,请记住修改这些新目录的权限和所有权,以及 SELinux 标签(在`/var/www`之外,您需要将 Apache 目录标记为`httpd_sys_content_t`),以便它们可以按预期使用。最后,我们重新加载了 Apache Web 服务,以便我们的新设置会立即生效。然后,我们可以在客户端的`/etc/hosts`中或在 BIND DNS 服务器上正确设置后,直接在浏览器中使用子域名浏览到我们的虚拟主机。

# 使用 Perl 和 Ruby 实现 CGI

在本章之前的食谱中,我们的 Apache 服务仅提供静态内容,这意味着网页浏览器请求的所有内容在服务器上已经处于恒定状态,例如作为不会改变的纯 HTML 文本文件。Apache 只是将 Web 服务器上特定文件的内容作为响应发送到浏览器,然后在那里进行解释和渲染。如果没有办法改变发送给客户端的内容,互联网将会非常无聊,也不会像今天这样取得巨大成功。甚至连最简单的动态内容示例,例如显示带有 Web 服务器当前本地时间的网页,都不可能实现。

因此,早在 20 世纪 90 年代初,一些聪明的人开始发明机制,使 Web 服务器和安装在服务器上的可执行程序之间的通信成为可能,以动态生成网页。这意味着发送给用户的 HTML 内容可以根据不同的上下文和条件改变。这些程序通常用脚本语言编写,如 Perl 或 Ruby,但也可以用任何其他计算机语言编写,如 Python、Java 或 PHP(见后文)。因为 Apache 是用纯 C 和 C++编写的,所以它不能执行或解释任何其他编程语言,如 Perl。因此,需要在服务器和程序之间建立一座桥梁,定义一些外部程序如何与服务器交互。这些方法之一被称为**通用网关接口**(**CGI**),这是一种非常古老的方式来提供动态内容。大多数 Apache Web 服务器使用某种形式的 CGI 应用程序,在这个食谱中,我们将向您展示如何安装和配置 CGI 以与 Perl 和 Ruby 一起使用,以生成我们的第一个动态内容。

### 注意

还存在一些特殊的 Apache Web 服务器模块,如`mod_perl`、`mod_python`、`mod_ruby`等,这些模块通常应该被优先考虑,因为它们直接将语言的解释器嵌入到 Web 服务器进程中,因此与任何接口技术(如 CGI)相比,它们要快得多。

## 准备就绪

为了完成这个食谱,你需要一个带有 root 权限的 CentOS 7 操作系统的有效安装,你选择的基于控制台的文本编辑器,以及一个互联网连接,以便下载额外的软件包。

预计你的服务器将使用静态 IP 地址,Apache 已安装并正在运行,并且你的服务器支持一个或多个域或子域。

## 如何操作...

由于 Perl 和 Ruby 这两种脚本语言在 CentOS 7 Minimal 中默认不安装,我们将从使用 YUM 安装所有必需的软件包开始这个食谱。

1.  开始时,以 root 身份登录并输入以下命令:

    ```
    yum install perl perl-CGI ruby

    ```

1.  接下来,重新启动 Apache Web 服务器:

    ```
    systemctl restart httpd

    ```

1.  接下来,我们需要为使用 CGI 脚本适当地配置 SELinux:

    ```
    setsebool -P httpd_enable_cgi 1

    ```

1.  然后,我们需要为 SELinux 的工作更改我们`cgi-bin`目录的正确安全上下文:

    ```
    semanage fcontext -a -t httpd_sys_script_exec_t /var/www/cgi-bin
    restorecon -Rv /var/www/cgi-bin

    ```

### 创建你的第一个 Perl CGI 脚本

1.  现在通过打开新文件`vi /var/www/cgi-bin/perl-test.cgi`并输入以下内容来创建以下 Perl CGI 脚本文件:

    ```
    #!/usr/bin/perl
    use strict;
    use warnings;
    use CGI qw(:standard);
    print header;
    my $now = localtime;
    print start_html(-title=>'Server time via Perl CGI'),
    h1('Time'),
    p("The time is $now"),
    end_html;
    ```

1.  接下来,将文件权限更改为 755,以便我们的`apache`用户可以执行它:

    ```
    chmod 755 /var/www/cgi-bin/perl-test.cgi

    ```

1.  接下来,为了测试并实际看到从前面的脚本生成的 HTML,你可以在命令行上直接执行`perl`脚本;只需输入:

    ```
    /var/www/cgi-bin/perl-test.cgi

    ```

1.  现在在网络中的一台计算机上打开浏览器,运行你的第一个 Perl CGI 脚本,它将通过使用 URL 打印本地时间:

    ```
    http://<server name or IP address>/cgi-bin/perl-test.cgi

    ```

1.  如果脚本不工作,请查看日志文件`/var/log/httpd/error_log`。

### 创建你的第一个 Ruby CGI 脚本

1.  创建新的 Ruby CGI 脚本文件`vi /var/www/cgi-bin/ruby-test.cgi`,并放入以下内容:

    ```
    #!/usr/bin/ruby
    require "cgi"
    cgi = CGI.new("html4")
    cgi.out{
     cgi.html{
     cgi.head{ cgi.title{"Server time via Ruby CGI"} } +
     cgi.body{
     cgi.h1 { "Time" } +
     cgi.p { Time.now}
     }
     }
    }

    ```

1.  现在将文件权限更改为`755`,以便我们的`apache`用户可以执行它:

    ```
    chmod 755 /var/www/cgi-bin/ruby-test.cgi

    ```

1.  要实际查看从前面脚本生成的 HTML,您可以在命令行上直接执行 Ruby 脚本;只需键入`/var/www/cgi-bin/ruby-test.cgi`。当显示行`offline mode: enter name=value pairs on standard input`时,按*Ctrl*+*D*查看实际的 HTML 输出。

1.  现在,在您的网络中的计算机上打开一个浏览器,运行您的第一个 Ruby CGI 脚本,该脚本将通过以下 URL 打印本地时间:

    ```
    http://<server name or IP address>/cgi-bin/ruby-test.cgi

    ```

1.  如果它不工作,请查看日志文件`/var/log/httpd/error.log`。

## 它是如何工作的...

在这个配方中,我们向您展示了使用 CGI 创建一些动态网站是多么容易。当访问 CGI 资源时,Apache 服务器在服务器上执行该程序,并将输出发送回浏览器。这个系统的主要优点是 CGI 不受任何编程语言的限制,只要程序可以在 Linux 命令行上执行并生成某种形式的文本输出即可。CGI 技术的主要缺点是它是一种非常老旧且过时的技术:对 CGI 资源的每个用户请求都会启动程序的新进程。例如,对 Perl CGI 脚本的每个请求都会启动并将新的解释器实例加载到内存中,这将产生大量开销,因此使得 CGI 仅适用于较小的网站或较低的并行用户请求数。如前所述,还有其他技术可以解决这个问题,例如 FastCGI 或 Apache 模块,如`mod_perl`。

那么我们从这次经历中学到了什么?

我们从这个配方开始,以 root 身份登录,并安装了`perl`解释器和`CGI.pm`模块,因为它们不包含在 Perl 标准库中(我们将在脚本中使用它),以及安装了 Ruby 编程语言的`ruby`解释器。之后,为了确保我们的 Apache Web 服务器注意到我们系统上安装的新编程语言,我们重新启动了 Apache 进程。

接下来,我们确保 SELinux 已启用以与 CGI 脚本配合工作,然后我们为标准的 Apache `cgi-bin`目录`/var/www/cgi-bin`提供了正确的 SELinux 上下文类型,以允许系统范围内的执行。要了解更多关于 SELinux 的信息,请阅读第十四章,*使用 SELinux*。然后,我们将 Perl 和 Ruby CGI 脚本放入此目录,并使它们对 Apache 用户可执行。在主 Apache 配置文件中,`/var/www/cgi-bin`目录默认被定义为标准 CGI 目录,这意味着您放入此目录的任何可执行文件,只要具有适当的访问和执行权限以及`.cgi`扩展名,都会自动定义为 CGI 脚本,并且可以从您的网络浏览器访问和执行,无论它使用哪种编程或脚本语言编写。为了测试我们的脚本,我们随后打开了一个网络浏览器,并访问了 URL `http://<服务器名称或 IP 地址>/cgi-bin/`,后面跟着`.cgi`脚本的名称。

## 还有更多...

如果您希望在其他网站目录中也能执行 CGI 脚本,您需要将以下两行(`Options`和`AddHandler`)添加到任何虚拟主机或现有的`Directive`指令中,或者按照以下方式创建一个新的(请记住,您还需要为新的 CGI 位置设置 SELinux `httpd_sys_script_exec_t`标签):

<Directory "/var/www/html/cgi-new">
Options +ExecCGI
AddHandler cgi-script .cgi


# 安装、配置和测试 PHP

**超文本预处理器**(**PHP**)仍然是用于 Web 开发的最流行的服务器端脚本语言之一。它已经支持一些很好的功能,例如开箱即用地连接到关系数据库(如 MariaDB),这可以用来非常快速地实现现代 Web 应用程序。虽然可以看到一些大型企业倾向于放弃 PHP 而转向一些新技术,如 Node.js(服务器端 JavaScript),但它仍然是消费者市场上的主要脚本语言。世界上每家托管公司都提供某种 LAMP 堆栈(Linux、Apache、MySQL、PHP)来运行 PHP 代码。此外,许多非常流行的 Web 应用程序都是用 PHP 编写的,例如 WordPress、Joomla 和 Drupal,因此可以说 PHP 几乎是任何 Apache Web 服务器的必备功能。在本操作指南中,我们将向您展示如何在 Apache Web 服务器上开始安装和运行 PHP,使用模块`mod_php`。

## 准备就绪

要完成此操作,您需要一个具有 root 权限的工作 CentOS 7 操作系统安装,以及您选择的基于控制台的文本编辑器和互联网连接。预计您的服务器将使用静态 IP 地址,Apache 已安装并正在运行,并且您的服务器支持一个或多个域或子域。

## 如何操作...

我们将从安装 PHP 超文本处理器开始,同时安装 Apache 的`mod_php`模块,这两者在 CentOS 7 最小安装中默认不安装。

1.  首先,以 root 身份登录并输入以下命令:

    ```
    yum install mod_php

    ```

1.  现在,在我们先对原始文件进行备份之后,让我们打开标准的 PHP 配置文件:

    ```
    cp /etc/php.ini /etc/php.ini.bak && vi /etc/php.ini

    ```

1.  找到行`; date.timezone =`并将其替换为您自己的时区。所有可用的 PHP 时区列表可以在`http://php.net/manual/en/timezones.php`找到。例如(请确保删除前面的`;`,因为这会禁用命令的解释;这称为注释掉),要将时区设置为欧洲柏林市,请使用:

    ```
    date.timezone = "Europe/Berlin"

    ```

1.  为了确保新模块和设置已正确加载,请重启 Apache Web 服务器:

    ```
    systemctl restart httpd

    ```

1.  为了与前一个配方中的 CGI 示例保持一致,我们将创建我们的第一个动态 PHP 脚本,该脚本将打印出当前本地服务器时间,并在脚本`vi /var/www/html/php-test.php`中运行流行的 PHP 函数`phpinfo()`,我们可以使用它来打印出重要的 PHP 信息:

    ```
    <html><head><title>Server time via Mod PHP</title></head>
    <h1>Time</h1>
    <p>The time is <?php print Date("D M d, Y G:i a");?></p><?php phpinfo(); ?></body></html>
    ```

1.  要实际查看从前面脚本生成的 HTML,您可以直接在命令行上执行 PHP 脚本;只需输入:`php /var/www/html/php-test.php`。

1.  现在,在您网络中的计算机上打开浏览器,运行您的第一个 PHP 脚本,该脚本将通过以下 URL 打印本地时间:`http://<服务器名称或 IP 地址>/php-test.php`。

## 如何操作...

在本配方中,我们向您展示了通过使用`mod_php`模块将 PHP 轻松安装并集成到任何 Apache Web 服务器中是多么容易。该模块启用了一个内部 PHP 解释器,该解释器直接在 Apache 进程中运行,比使用 CGI 更高效,并且应该是任何可用时的首选方法。

那么我们从这次经历中学到了什么?

我们从使用 YUM 安装`mod_php`模块开始本节,这将安装 PHP 作为依赖项,因为这两者都不在任何标准的 CentOS 7 最小安装中。安装`mod_php`添加了`/etc/php.ini`配置文件,我们在备份原始文件后打开了它。该文件是主要的 PHP 配置文件,应谨慎编辑,因为许多设置可能与您的 Web 服务器的安全性相关。如果您刚刚开始使用 PHP,请将文件中的所有内容保持原样,不要更改任何内容,除了`date.timezone`变量。我们将其设置为反映我们当前的时区,这对于 PHP 是必要的,因为它被许多不同的时间和日期函数使用(我们还将在我们第一个 PHP 脚本中使用一些日期函数,如下所示)。接下来,我们重新启动了 Apache Web 服务器,它也会自动重新加载 PHP 配置。之后,我们创建了我们的第一个 PHP 脚本,并将其放入主 Web 根目录`/var/www/html/php-test.php`;这会打印出当前服务器时间以及`phpinfo()` PHP 函数的结果。这为您提供了一个分类良好的表格概览,显示了当前的 PHP 安装,帮助您诊断与服务器相关的问题或查看哪些模块在 PHP 中可用。

与 CGI 相比,您可能会问自己为什么我们不需要将 PHP 脚本放入任何特殊文件夹,如`cgi-bin`。通过安装`mod_php`,一个名为`/etc/httpd/conf.d/php.conf`的 Apache 配置文件被部署到 Apache 配置文件夹中,这正是回答了这个问题,它指定了每当 PHP 脚本从 Web 目录中的任何位置获得`.php`扩展名时,它们将被执行为有效的 PHP 代码。

# 确保 Apache 安全

尽管 Apache HTTP 服务器是 CentOS 7 中包含的最成熟和最安全的服务器应用程序之一,但总有余地进行改进,并且有大量选项和技术可用于进一步强化您的 Web 服务器的安全性。虽然我们无法向用户展示每一个安全特性,因为这超出了本书的范围,但在本节中,我们将尝试教授在为生产系统保护 Apache Web 服务器时被认为是良好实践的内容。

## 准备工作

要完成本节,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,以及您选择的基于控制台的文本编辑器。预计您的服务器将使用静态 IP 地址,并且 Apache 已安装并正在运行,并且您的服务器支持一个或多个域或子域。

## 如何操作...

大多数安全选项和技术都必须在 Apache 的主配置文件中设置,因此我们将从在喜欢的文本编辑器中打开它开始本节。

### 配置 httpd.conf 以提供更好的安全性

1.  首先,以 root 身份登录并打开 Apache 的主配置文件:

    ```
    vi /etc/httpd/conf/httpd.conf

    ```

1.  现在转到你的主文档根目录。为此,搜索名为:

    ```
    <Directory "/var/www/html">

    ```

1.  在开始`<Directory "/var/www/html">`和结束`</Directory>`标签之间找到行`Options Indexes FollowSymLinks`,然后通过在前面放置一个`#`来禁用(注释掉)该行,使其读取:

    ```
    #  Options Indexes FollowSymLinks

    ```

1.  现在滚动到配置文件的末尾,在`# Supplemental configuration`行之前插入以下行。我们不希望服务器通过标头泄露任何详细信息,因此我们输入:

    ```
    ServerTokens Prod

    ```

1.  之后,重新加载 Apache 配置以应用你的更改:

    ```
    apachectl configtest && systemctl reload httpd

    ```

### 移除不需要的 httpd 模块

即使是稳定性最高、成熟度最高、经过充分测试的程序也可能包含漏洞,正如最近关于 OpenSSL 中的 Heartbleed 漏洞或 Bash 中的 Shellshock 漏洞的新闻所显示的那样,Apache Web 服务器也不例外。因此,通常有益的是移除所有不需要的软件以限制功能,从而减少系统中出现安全问题的可能性。对于 Apache Web 服务器,我们可以移除所有不需要的模块以提高安全性(这也可以提高性能和内存消耗)。让我们通过审查所有当前安装的 Apache 模块来开始这个过程。

1.  要显示所有当前安装和加载的 Apache 模块,请以 root 用户身份输入:

    ```
    httpd -M

    ```

1.  前面命令输出的所有模块都通过`/etc/httpd/conf.modules.d`文件夹中的特殊配置文件加载到 Apache Web 服务器中,它们根据其主要目标分组到以下文件中:

    ```
    00-base.conf, 00-dav.conf, 00-lua.conf, 00-mpm.conf, 00-proxy.conf, 00-ssl.conf, 00-systemd.conf, 01-cgi.conf, 10-php.conf

    ```

1.  因此,与其逐一检查所有模块,`conf.modules.d`文件夹中的这种文件结构可以使我们的生活变得更加轻松,因为我们可以在整个模块组中启用/禁用。例如,如果你知道自己不需要任何 Apache DAV 模块,因为你不会提供任何 WebDAV 服务器,你可以通过将`00-dav.conf`配置文件的扩展名重命名来禁用所有与 DAV 相关的模块,因为只有以`.conf`结尾的文件才会被 Apache 自动读取和加载。为此,请输入:

    ```
    mv /etc/httpd/conf.modules.d/00-dav.conf /etc/httpd/conf.modules.d/00-dav.conf.BAK

    ```

1.  之后,重新加载 Apache 配置以将你的更改应用于模块目录:

    ```
    apachectl configtest && systemctl reload httpd

    ```

1.  如果你需要更精细的控制,你也可以在所有这些配置文件中启用/禁用单个模块。例如,在你的首选文本编辑器中打开`00-base.conf`,并通过在要禁用的行的开头添加`#`来禁用单个行。例如:

    ```
    # LoadModule userdir_module modules/mod_userdir.so

    ```

1.  如果你决定稍后使用一些禁用的模块文件,只需将`.BAK`文件重命名为原始文件名,或者在重新加载`httpd`之前,在特定的模块配置文件中删除`#`。

### 保护你的 Apache 文件

提高 Apache Web 服务器安全性的另一种简单方法是保护服务器端脚本和配置。在我们的场景中,有一个用户(root)单独负责并维护整个 Apache Web 服务器、网站(例如,将新的 HTML 页面上传到服务器)、服务器端脚本和配置。因此,我们将给予他/她完整的文件权限(读/写/执行)。`apache`用户仍然需要适当的读取和执行权限来服务和访问所有与 Apache 相关的文件,从而最小化您的 Apache Web 服务器向其他系统用户暴露潜在安全风险或通过 HTTP 攻击被破坏的风险。这可以通过两个步骤完成:

1.  首先,我们将更改或重置完整的 Apache 配置目录和标准 Web 根目录的所有权,所有者为`root`,组为`apache`:

    ```
    chown -R root:apache /var/www/html /etc/httpd/conf*

    ```

1.  之后,我们将更改文件权限,以便除了我们专门的`apache`用户(以及`root`)之外,任何人都无法读取这些文件:

    ```
    chmod 750 -R /var/www/html /etc/httpd/conf*

    ```

## 它是如何工作的...

我们从这个食谱开始,打开主 Apache 配置文件`httpd.conf`,以更改我们主 Apache 根 Web 内容目录`/var/www/html`的设置。在这里,我们禁用了完整的`Options`指令,包括`Indexes`和`FollowSymLinks`参数。正如我们所学,如果您从 Apache 服务器请求目录而不是文件,`index.html`或该目录中的`index.htm`文件将自动发送。现在,`Indexes`选项配置 Apache Web 服务器,以便如果在请求的目录中找不到这样的文件,Apache 将自动生成该目录内容的列表,就像您在命令行中输入`ls`(用于列出目录)一样,并将其作为 HTML 页面显示给用户。我们通常不希望这个功能,因为它可能会向未经授权的用户暴露秘密或私人数据,许多系统管理员会告诉您,索引通常被认为是一种安全威胁。`FollowSymLinks`指令也不应在生产系统中使用,因为如果您使用不当,它很容易暴露文件系统的一部分,例如完整的根目录。最后,我们添加了另一个措施来提高服务器的基本安全性,这是通过禁用服务器版本横幅信息来实现的。当 Apache Web 服务器生成网页或错误页面时,有价值的信息(例如 Apache 服务器版本和激活的模块)会自动发送到浏览器,潜在的攻击者可以从中获取有关您系统的宝贵信息。我们通过简单地将`ServerTokens`设置为`Prod`来阻止这种情况发生。之后,我们向您展示了如何禁用 Apache 模块以减少系统中错误和利用的一般风险。最后,我们展示了如何调整您的 Apache 文件权限,这也是一种很好的通用保护措施。

在加固 Apache Web 服务器时,有许多其他因素需要考虑,但大多数这些技术,如限制 HTTP 请求方法,`TraceEnable`,设置带有`HttpOnly`和安全标志的 cookie,禁用 HTTP 1.0 协议或 SSL v2,或使用有用的安全相关 HTTP 或自定义标头(如`X-XSS-Protection`)修改 HTTP 标头,都是更高级的概念,并且可能会过度限制通用目的的 Apache Web 服务器。

# 使用安全套接字层(SSL)设置 HTTPS

在本操作中,我们将学习如何通过使用 OpenSSL 创建自签名 SSL 证书来为 Apache Web 服务器添加安全连接。如果网站在服务器上运行时传输敏感数据,如信用卡或登录信息,则通常需要 Web 服务器。在前一个操作中,您已经了解了如何安装 Apache Web 服务器,随着对安全连接的需求不断增长,本操作的目的是向您展示如何通过教您如何扩展 Apache Web 服务器的功能来增强当前服务器配置。

## 准备工作

要完成此操作,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及互联网连接以便于下载额外的包。预计 Apache Web 服务器已安装并正在运行。在这里,我们将为 Apache 创建一个新的 SSL 证书。如果您想了解更多信息,请参考第六章,*提供安全性*,以获取有关生成自签名证书的建议。由于正确的域名对于 SSL 的工作至关重要,我们将继续将 Apache Web 服务器的配置域名命名为`centos7.home`以使此操作生效(根据您的需要进行更改)。

## 如何操作...

Apache 默认不支持 SSL 加密,因此我们将首先使用 yum 包管理器安装必要的包`mod_ssl`。

1.  首先,以 root 身份登录并输入以下命令:

    ```
    yum install mod_ssl

    ```

1.  在安装 mod_ssl 包的过程中,会自动生成一个自签名证书以及 Apache Web 服务器的密钥对;这些证书缺少您 Web 服务器域名的正确通用名称。在我们能够使用下一步中的`Makefile`重新生成我们自己的所需 SSL 文件之前,我们需要删除这些文件:

    ```
    rm /etc/pki/tls/private/localhost.key /etc/pki/tls/certs/localhost.crt

    ```

1.  我们现在需要为我们的 Apache Web 服务器创建我们打算使用的自签名证书和服务器密钥。为此,请输入以下命令:

    ```
    cd /etc/pki/tls/certs

    ```

1.  要创建自签名 Apache SSL 密钥对,包括证书及其嵌入的公钥以及私钥,请输入:

    ```
    make testcert

    ```

1.  在创建证书的过程中,首先您将被要求输入一个新的密码,然后验证它。之后,您需要第三次输入它。通常,输入一个安全的密码。然后,您将被问一系列问题。填写所有必需的详细信息,特别注意通用名称值。此值应反映您的 Web 服务器的域名或 SSL 证书所针对的 IP 地址。例如,您可以输入:

    ```
    www.centos7.home

    ```

1.  当您创建证书的过程完成后,我们将通过以下方式打开主要的 Apache SSL 配置(在备份之后):

    ```
    cp /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.BAK
    vi /etc/httpd/conf.d/ssl.conf

    ```

1.  向下滚动到以`<VirtualHost _default_:443>`开头的部分,并找到该块内的行`# DocumentRoot "/var/www/html"`。然后通过删除`#`字符来激活它,使其读作:

    ```
    DocumentRoot "/var/www/html"

    ```

1.  在下面,找到读作`#ServerName www.example.com:443`的行。激活此行并修改显示的值以匹配创建证书时使用的通用名称值,如下所示:

    ```
    ServerName www.centos7.home:443

    ```

1.  保存并关闭文件,接下来我们需要在我们的 firewalld 中启用 HTTPS 端口,以允许通过端口`443`进行传入的 HTTP SSL 连接:

    ```
    firewall-cmd --permanent --add-service=https && firewall-cmd --reload

    ```

1.  现在重新启动 Apache `httpd`服务以应用您的更改。请注意,如果提示,您必须输入创建 SSL 测试证书时添加的 SSL 密码:

    ```
    systemctl restart httpd

    ```

1.  做得好!现在您可以通过替换我们为服务器定义的所有可用 HTTP URL,使用 HTTPS 而不是 HTTP 来访问您的服务器。例如,转到`https://www.centos7.home`而不是`http://www.centos7.home`。

    ### 注意

    当您访问此网站时,您会收到一条警告消息,指出签名证书颁发机构是未知的。使用自签名证书时,这种异常是可以预料的,并且可以确认。

## 它是如何工作的...

我们通过使用 YUM 包管理器安装`mod_ssl`开始了这个过程,这是默认的 Apache 模块,用于启用 SSL。接下来,我们前往 CentOS 7 中所有系统证书的标准位置,即`/etc/pki/tls/certs`。在这里,我们可以找到一个`Makefile`,这是一个方便生成自签名 SSL 测试证书的辅助脚本,它为你隐藏了 OpenSSL 程序的复杂命令行参数。请记住,`Makefile`目前缺少一个`clean`选项,因此每次运行它时,我们都需要手动删除以前运行生成的任何旧版本文件,否则它将不会开始做任何事情。删除旧的 Apache SSL 文件后,我们使用`make`命令和`testcert`参数,这将为 Apache Web 服务器创建自签名证书,并将它们放在标准位置,这些位置已经在`ssl.conf`文件中配置好了(`SSLCertificateFile`和`SSLCertificateKeyFile`指令),因此我们不需要在这里做任何更改。在过程中,在完成一系列问题之前,你会被要求提供一个密码。完成问题,但要特别注意通用名称。正如在主配方中提到的,这个值应该反映你的服务器域名或 IP 地址。在下一阶段,你需要在你的首选文本编辑器中打开 Apache 的 SSL 配置文件,该文件位于`/etc/httpd/conf.d/ssl.conf`。在其中,我们启用了`DocumentRoot`指令,将其置于 SSL 控制之下,并激活了`ServerName`指令,其预期域值必须与我们定义的通用名称值相同。然后,我们保存并关闭了配置文件,并在防火墙中启用了 HTTPS 端口,从而允许通过标准 HTTPS `443`端口进行传入连接。完成这些步骤后,你现在可以享受使用自签名服务器证书的安全连接的好处。只需在任何 URL 地址前输入`https://`而不是`http://`即可。但是,如果你打算在面向公众的生产服务器上使用 SSL 证书,那么最好的选择是从受信任的证书颁发机构购买 SSL 证书。

## 还有更多...

我们了解到,由于我们的 SSL 证书受密码保护,因此每当需要重启 Apache Web 服务器时,都需要输入密码。这对于服务器重启来说是不切实际的,因为 Apache 会在没有密码的情况下拒绝启动。为了消除密码提示,我们将把密码放在一个特殊文件中,并确保只有 root 用户可以访问它。

1.  创建包含你密码的文件的备份:

    ```
    cp /usr/libexec/httpd-ssl-pass-dialog /usr/libexec/httpd-ssl-pass-dialog.BAK

    ```

1.  现在用以下内容覆盖这个密码文件,将命令行中的`XXXX`替换为你的当前 SSL 密码:

    ```
    echo -e '#!/bin/bash\necho "XXXX"' >  /usr/libexec/httpd-ssl-pass-dialog

    ```

1.  最后,更改权限,使得只有 root 用户可以读取和执行它们:

    ```
    chmod 500 /usr/libexec/httpd-ssl-pass-dialog

    ```


# 第十三章:操作系统级虚拟化

在本章中,我们将涵盖:

+   安装和配置 Docker

+   下载镜像并运行容器

+   从 Dockerfile 创建自己的镜像并上传到 Docker Hub

+   设置和使用私有 Docker 仓库

# 引言

本章是一系列食谱的集合,提供了安装、配置和使用 Docker 的基本步骤,Docker 是一个开放平台,通过操作系统级虚拟化技术构建、运输、共享和运行分布式应用程序,这种技术在 Linux 世界中已经存在多年,并且可以提供比传统虚拟化技术更快的速度和效率优势。

# 安装和配置 Docker

传统的虚拟化技术提供*硬件虚拟化*,这意味着它们创建了一个完整的硬件环境,因此每个**虚拟机**(**VM**)都需要一个完整的操作系统来运行它。因此,它们有一些主要缺点,因为它们很重,运行时会产生大量开销。这就是开源 Docker 容器化引擎提供有吸引力的替代方案的地方。它可以帮助您在 Linux 容器中构建应用程序,从而提供应用程序虚拟化。

这意味着您可以将任何选择的 Linux 程序及其所有依赖项和自己的环境打包,然后共享它或运行多个实例,每个实例都是完全隔离和分离的进程,在任何现代 Linux 内核上运行,从而提供本机运行时性能、易于移植性和高可扩展性。在这里,在本食谱中,我们将向您展示如何在您的 CentOS 7 服务器上安装和配置 Docker。

## 准备就绪

要完成本食谱,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便下载额外的`rpm`包和测试 Docker 镜像。

## 如何做到这一点...

虽然 Docker 在官方的 CentOS 7 仓库中作为一个包可用,但我们将在我们的系统上使用官方的 Docker 仓库来安装它。

1.  首先,以 root 身份登录并更新您的 YUM 包,然后使用以下命令下载并执行官方的 Docker Linux 安装脚本:

    ```
    yum update && curl -sSL https://get.docker.com/ | sh

    ```

1.  接下来,在启动 Docker 守护进程之前(第一次启动时会花费一些时间),启用 Docker 在启动时自动启动:

    ```
    systemctl enable docker && systemctl start docker

    ```

1.  最后,启动 Docker 后,您可以通过输入以下内容来验证它是否正常工作:

    ```
    docker run hello-world

    ```

## 它是如何工作的...

在 CentOS 7 上安装任何软件时,大多数情况下,使用官方 CentOS 仓库中的包而不是从第三方位置下载和安装是一个非常好的建议。在这里,我们通过使用官方 Docker 仓库安装 Docker 来做出例外。我们这样做是因为 Docker 是一个非常年轻的项目,发展迅速,变化频繁。虽然您可以使用 Docker 运行任何 Linux 应用程序,包括关键的 Web 服务器或处理机密数据的程序,但 Docker 程序中发现的或引入的错误可能会产生严重的安全后果。通过使用官方 Docker 仓库,我们确保始终能够尽快从这一快速发展的项目的开发者那里获得最新的更新和补丁。因此,将来任何时候您输入`yum update`,您的包管理器都会自动查询并检查 Docker 仓库,看看是否有新的 Docker 版本可供您使用。

那么我们从这次经历中学到了什么?

我们通过以 root 身份登录服务器并更新 YUM 包的数据库开始这个操作步骤。然后,我们使用一个命令从[`get.docker.com/`](https://get.docker.com/)下载并执行官方 Docker 安装脚本,一步完成。该脚本的作用是将官方 Docker 仓库添加到 YUM 包管理器作为新的包源,然后自动在后台安装 Docker。之后,我们通过使用`systemd`在启动时启用 Docker 服务并启动它。最后,为了测试我们的安装,我们发出了`docker run hello-world`命令,该命令从官方 Docker 注册表下载一个特殊的镜像来测试我们的安装。如果一切顺利,您应该会看到以下成功消息(输出已截断):

Hello from Docker


这条消息表明您的安装似乎运行正常。

# 下载镜像并运行容器

一个常见的误解是 Docker 是一个运行容器的系统。Docker 只是一个构建工具,用于将任何基于 Linux 的软件及其所有依赖项打包到一个包含运行所需一切的完整文件系统中:代码、运行时、系统工具和系统库。运行 Linux 容器的技术称为操作系统级虚拟化,它提供了在每个现代 Linux 内核中默认构建的多个隔离环境。这保证了它无论部署在什么环境中都将始终以相同的方式运行;从而使您的应用程序具有可移植性。因此,当涉及到将您的 Docker 应用程序分发到 Linux 容器时,必须引入两个主要的概念性术语:**Docker 镜像**和**容器**。如果您曾经想设置并运行自己的 WordPress 安装,在本操作步骤中,我们将向您展示如何通过从官方 Docker Hub 下载预制的 WordPress 镜像来以最快的方式实现这一点;然后我们将从中运行一个容器。

## 准备就绪

要完成此教程,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便下载额外的 Docker 镜像。预计 Docker 已经安装并正在运行。

## 如何操作...

从 Docker Hub 下载的官方 WordPress 镜像不包含自己的 MySQL 服务器。相反,它依赖于外部的 MySQL 服务器,因此我们将从安装并运行一个从 Docker Hub 下载的 MySQL Docker 容器开始这个教程。

1.  首先,以 root 身份登录并键入以下命令,将`<PASSWORD>`替换为您自己选择的强 MySQL 数据库密码(在撰写本文时,最新的 WordPress 需要 MySQL v.5.7;这在未来可能会改变,因此请查看官方 WordPress Docker Hub 页面):

    ```
    docker run --restart=always --name wordpressdb -e MYSQL_ROOT_PASSWORD=<PASSWORD> -e MYSQL_DATABASE=wordpress -d mysql:5.7

    ```

1.  接下来,安装并运行官方 WordPress 镜像,并将其作为 Docker 容器运行,将其连接到 MySQL 容器(提供与前一步骤相同的`<PASSWORD>`字符串):

    ```
    docker run --restart=always -e WORDPRESS_DB_PASSWORD=<password> -d --name wordpress --link wordpressdb:mysql -p 8080:80 wordpress

    ```

1.  现在,MySQL 和 WordPress 容器应该已经在运行。要检查当前正在运行的容器,请键入:

    ```
    docker ps

    ```

1.  要获取所有 Docker WordPress 容器设置,请使用:

    ```
    docker inspect wordpress

    ```

1.  要检查我们的 WordPress 容器的日志文件,请运行以下命令:

    ```
    docker logs -f wordpress

    ```

1.  在同一网络中与运行 Docker 守护进程的服务器相连的计算机上打开浏览器,输入以下命令以访问您的 WordPress 安装(将 IP 地址替换为您的 Docker 服务器的 IP 地址):

    ```
    http://<IP ADDRESS OF DOCKER SERVER>:8080/

    ```

## 它是如何工作的...

Docker 镜像是一组构成软件应用程序及其功能依赖的所有文件,以及有关您修改或改进其内容时所做的任何更改的信息(以更改日志的形式)。它是您的应用程序的不可运行、只读版本,可以与 ISO 文件相比较。如果您想运行这样的镜像,Linux 容器将自动从它创建出来。这就是实际执行的内容。它是一个真正的可扩展系统,因为您可以从同一镜像运行多个容器。正如我们所见,Docker 不仅仅是您需要与镜像和容器一起工作的工具,它还是一个完整的平台,因为它还提供了访问各种 Linux 服务器软件的预制镜像的工具。这整个 Docker 系统的美丽之处在于,大多数时候您不必重新发明轮子,试图从头开始创建自己的 Docker 镜像。只需访问 Docker Hub([`hub.docker.com`](https://hub.docker.com)),搜索您想要作为容器运行的软件,找到它后,只需使用`docker run`命令,提供 Docker Hub 镜像的名称,就完成了。当考虑到尝试让最新流行的程序与您需要编译的所有依赖项一起工作并尝试安装它们时,Docker 真的可以成为救星。

那么我们从这次经历中学到了什么?

我们的旅程始于使用`docker run`命令,该命令从远程 Docker Hub 仓库下载了两个镜像并将其放入本地镜像存储(称为`mysql:5.7`和`wordpress`),然后运行它们(创建容器)。要获取机器上所有下载的镜像列表,请键入`docker images`。正如我们所见,两个`run`命令行都提供了`-e`命令行参数,我们需要设置一些基本的环境变量,这些变量随后将在容器内可见。这些包括我们想要运行的 MySQL 数据库以及设置和访问它们的 MySQL 根密码。这里我们看到 Docker 的一个非常重要的特性:能够相互通信的容器!通常,您可以将应用程序从不同的 Docker 容器部件堆叠在一起,使整个系统非常易于使用。另一个重要参数是`-p`,它用于从我们的主机端口`8080`创建到内部 HTTP 端口 80 的端口映射,并打开防火墙以允许此端口上的传入流量。`--restart=always`对于使图像容器可重新启动很有用,因此容器会在主机机器重新启动时自动重新启动。之后,我们向您介绍了 Docker 的`ps`命令行参数,该参数打印出所有正在运行的 Docker 容器。此命令应打印出两个名为`wordpressdb`和`wordpress`的运行容器,以及它们的`CONTAINER_ID`。此 ID 是唯一的 MD5 哈希,我们将在大多数 Docker 命令行输入中使用它,无论何时我们需要引用特定的容器(在本食谱中,我们通过容器名称引用,这也是可能的)。之后,我们向您展示了如何使用`inspect`参数打印出容器的配置。然后,为了以开放流的形式获取 Wordpress 容器的日志文件,我们使用了日志`-f`参数。最后,由于`-p 8080:80`映射允许在端口 8080 上对我们的服务器进行传入访问,因此我们可以从同一网络中的任何计算机使用浏览器访问我们的 Wordpress 安装。这将打开 Wordpress 安装屏幕。

### 注意

请注意,如果您在任何时候从 Docker 下载任何容器时遇到任何连接问题,例如`dial tcp: lookup index.docker.io: no such host`,请在再次尝试之前重新启动 Docker 服务。

## 还有更多...

在本节中,我们将向您展示如何启动和停止容器以及如何附加到您的容器。

### 停止和启动容器

在主配方中,我们使用了 Docker 的`run`命令,它实际上是两个其他 Docker 命令的包装:`create`和`start`。正如这些命令的名称所暗示的,`create`命令从现有镜像创建(克隆)一个容器,如果它不在本地镜像缓存中,则从给定的 Docker 注册表(如预定义的 Docker hub)下载它,而`start`命令实际上启动它。要获取计算机上所有容器(运行或停止)的列表,请输入:`docker ps -a`。现在识别一个停止或启动的容器,并找出其特定的`CONTAINER_ID`。然后,我们可以通过提供正确的`CONTAINER_ID`来启动一个停止的容器或停止一个运行的容器,例如`docker start CONTAINER_ID`。示例包括:`docker start 03b53947d812`或`docker stop a2fe12e61545`(`CONTAINER_ID`哈希值将根据你的计算机而变化)。

有时你可能需要删除一个容器;例如,如果你想在从镜像创建容器时完全更改其命令行参数。要删除容器,请使用`rm`命令(但请记住,它必须在停止后才能删除):`docker stop b7f720fbfd23; docker rm b7f720fbfd23`

### 连接并与你的容器交互

Linux 容器是完全隔离的进程,在你的服务器上运行在分离的环境中,无法像使用`ssh`登录普通服务器那样登录到它。如果你需要访问容器的 BASH shell,则可以运行`docker exec`命令,这对于调试问题或修改容器(例如,安装新软件包或更新程序或文件)特别有用。请注意,这只适用于运行中的容器,并且你需要在运行以下命令之前知道容器的 ID(输入`docker ps`以查找):`docker exec -it CONTAINER_ID /bin/bash`,例如`docker exec -it d22ddf594f0d /bin/bash`。一旦成功连接到容器,你将看到一个略有变化的命令行提示符,其中`CONTAINER_ID`作为主机名;例如,`root@d22ddf594f0d:/var/www/html#`。如果你需要退出容器,请输入`exit`。

# 通过 Dockerfiles 创建自己的镜像并上传到 Docker Hub

除了图像和容器,Docker 还有一个非常重要的术语叫做**Dockerfile**。Dockerfile 就像是一个创建特定应用程序环境的食谱,意味着它包含了构建特定镜像文件的蓝图和确切描述。例如,如果我们想要容器化一个基于 Web 服务器的应用程序,我们会在 Dockerfile 中定义所有依赖项,比如提供系统依赖项的基础 Linux 系统,如 Ubuntu、Debian、CentOS 等(这并不意味着我们*虚拟化*了完整的操作系统,而只是使用了系统依赖项),以及所有应用程序、动态库和服务,如 PHP、Apache 和 MySQL,还包括所有特殊的配置选项或环境变量。有两种方法可以构建自己的自定义镜像。一种方法是从我们之前在 Wordpress 食谱中下载的现有基础镜像开始,然后使用 BASH 附加到容器,安装额外的软件,对配置文件进行更改,然后将容器作为新镜像提交到注册表。或者,在本食谱中,我们将教您如何从新的 Dockerfile 为 Express.js Web 应用程序服务器构建自己的 Docker 镜像,并将其上传到您自己的 Docker Hub 账户。

## 准备就绪

要完成本食谱,您需要一个具有 root 权限的 CentOS 7 操作系统的工作安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便与 Docker Hub 通信。预计 Docker 已经安装并正在运行。此外,为了将您的新镜像上传到 Docker Hub,您需要在 Docker Hub 上创建一个新的用户账户。只需访问[`hub.docker.com/`](https://hub.docker.com/)并免费注册。在我们的示例中,我们将使用一个虚构的新 Docker Hub 用户 ID,称为`johndoe`。

## 如何操作...

1.  首先,以 root 身份登录,使用您的 Docker Hub 用户 ID 创建一个新的目录结构(将`johndoe`目录名称适当地替换为您自己的 ID),并打开一个空的 Dockerfile,您将在其中放入镜像构建的蓝图:

    ```
    mkdir -p ~/johndoe/centos7-expressjs
    cd $_; vi Dockerfile

    ```

1.  将以下内容放入该文件中:

    ```
    FROM centos:centos7
    RUN yum install -y epel-release;yum install -y npm;
    RUN npm install express --save
    COPY . ./src
    EXPOSE 8080
    CMD ["node", "/src/index.js"]

    ```

1.  保存并关闭文件。现在创建您的第一个 Express.js Web 应用程序,我们将在新容器上部署它。在当前目录中打开以下文件:

    ```
    vi index.js

    ```

1.  现在将以下 JavaScript 内容放入:

    ```
    var express = require('express'), app = express();
    app.get('/', function (req, res) {res.send('Hello CentOS 7 cookbook!\n');});
    app.listen(8080);

    ```

1.  现在要从这个 Dockerfile 构建一个镜像,请保持在当前目录中,并使用以下命令(不要忘记此行末尾的点,并将`johndoe`替换为您自己的 Docker Hub ID):

    ```
    docker build -t johndoe/centos7-expressjs .

    ```

1.  成功构建镜像后,让我们将其作为容器运行:

    ```
    docker run -p 8081:8080 -d johndoe/centos7-expressjs

    ```

1.  最后,测试我们是否可以向我们新创建的容器中运行的 Express.js Web 应用程序服务器发出 HTTP 请求:

    ```
    curl -i localhost:8081

    ```

1.  如果 Docker 镜像成功运行在 Express.js 服务器上,应该会出现以下 HTTP 响应(截断至最后一行):

    ```
    Hello CentOS 7 cookbook!

    ```

### 将您的映像上传到 Docker Hub

1.  创建一个新的 Docker Hub 账号 ID,名为`johndoe`后,我们将开始使用以下命令登录网站——保持在您放置 Dockerfile 的目录中,例如`~/johndoe/centos7-expressjs`(在提示时提供用户名、密码和注册电子邮件):

    ```
    docker login

    ```

1.  现在,要将本教程中创建的新映像推送到 Docker Hub(再次将`johndoe`替换为您自己的用户 ID),请使用:

    ```
    docker push johndoe/centos7-expressjs

    ```

1.  上传后,您将能够在 Docker Hub 网页搜索中找到您的映像。或者,您可以使用命令行:

    ```
    docker search expressjs

    ```

## 它是如何工作的...

在这篇简短的教程中,我们向您展示了如何创建您的第一个 Dockerfile,该文件将创建一个用于运行 Express.js 应用程序的 CentOS 7 容器,这是一种现代的 LAMP 堆栈替代方案,您可以在客户端和服务器端编程 JavaScript。

那么我们从这次经历中学到了什么?

如您所见,Dockerfile 是一种优雅的方式来描述创建映像的所有指令。命令易于理解,您使用特殊的关键字来指示 Docker 如何操作以从其生成映像。`FROM`命令告诉 Docker 我们应该使用哪个基础映像。幸运的是,已经有人从 CentOS 7 系统依赖项创建了基础映像(这将从 Docker Hub 下载)。接下来,我们使用`RUN`命令,它只是在 BASH 命令行上执行命令。我们使用此命令在我们的系统上安装依赖项以运行 Express.js 应用程序(它是基于 Node.js rpm 包的,我们首先通过安装 EPEL 存储库来访问它)。`COPY`命令将文件从我们的主机复制到容器上的特定位置。我们需要这个来复制我们的`index.js`文件,该文件将在稍后的步骤中创建我们所有的 Express.js Web 服务器代码到容器上。`EXPOSE`,顾名思义,将内部容器端口暴露给外部主机系统。由于默认情况下 Express.js 监听 8080 端口,我们需要在这里这样做。虽然到目前为止显示的所有这些命令只在创建映像时执行一次,但下一个命令`CMD`将在我们每次启动容器时运行。`node /src/index.js`命令将被执行,并指示系统使用`index.js`文件启动 Express.js Web 服务器(我们已经通过从主机复制它来提供此文件)。我们不想深入讨论程序的 JavaScript 部分——它只是处理 HTTP GET 请求并返回`Hello World`字符串。在本教程的第二部分中,我们向您展示了如何将我们新创建的映像推送到 Docker Hub。为此,请使用您的 Docker 用户账户登录。然后我们可以将我们的映像推送到存储库。

由于这是一个非常简单的 Dockerfile,关于这个主题还有很多要学习的内容。要查看 Dockerfile 中所有可用命令的列表,请使用`man Dockerfile`。此外,你应该访问 Docker Hub 并浏览一些有趣项目的 Dockerfiles(在*GitHub 上托管的源代码库*部分下),以学习如何仅用几个命令就能创建一些高度复杂的镜像文件。

# 设置和使用私有 Docker Registry

在本章的前一个配方中,我们已经了解到将自己的镜像上传到官方 Docker Hub 是多么容易,但我们在那里上传的所有内容都将公开。如果你在一个企业环境中处理私有或闭源项目,或者只是想在向所有人发布之前测试一些东西,那么你很可能更倾向于拥有自己的、受保护的或企业范围内的私有 Docker Registry。在本配方中,我们将向你展示如何设置和使用你自己的 Docker Registry,该 Registry 将在你自己的私有网络中可用,并通过 TLS 加密和用户认证进行保护,这样你就可以精确控制谁可以使用它(推送和拉取镜像到和从它)。

## 准备工作

要完成这个配方,你需要一个安装了 CentOS 7 操作系统并具有 root 权限的工作环境,一个你选择的基于控制台的文本编辑器,以及一个互联网连接以便下载额外的软件包。在我们的例子中,我们将在 IP 地址为`192.168.1.100`的服务器上安装 Docker Registry。根据你的需求适当调整配方的命令。你需要为这台服务器设置一个完全限定域名(FQDN),否则注册表将无法工作。为了简化,我们将使用`/etc/hosts`方法而不是设置和配置一个 DNS 服务器(如果你想这样做,请参阅第九章/Docker registry/g' | sed 's/<description>.*<\/description>//g' > /etc/firewalld/services/docker-reg.xml
    firewall-cmd --reload
    firewall-cmd --permanent --add-service=docker-reg; firewall-cmd --reload

    ```

### 需要在每个需要访问我们注册表的客户端上执行的步骤

1.  最后,我们可以通过在同一网络中的任何计算机上以 root 身份登录来测试连接到我们自己的新 TLS 增强的私有 Docker 注册表的用户身份验证。

1.  第一步是在每个想要连接到 Docker 注册表的客户端上安装 Docker:

    ```
    yum update && curl -sSL https://get.docker.com/ | sh

    ```

1.  接下来,在每个想要连接到我们新 Docker 注册表的客户端上,首先在客户端上设置服务器的证书,然后我们才能连接到它(此步骤仅在 CentOS 7 客户端上测试过):

    ```
    mkdir -p /etc/docker/certs.d/$DCKREG\:5000
    curl http://$DCKREG/docker-registry.crt -o /tmp/cert.crt
    cp /tmp/cert.crt /etc/docker/certs.d/$DCKREG\:5000/ca.crt
    cp /tmp/cert.crt /etc/pki/ca-trust/source/anchors/docker-registry.crt
    update-ca-trust

    ```

1.  为了测试,我们首先从官方 Docker Hub 拉取一个新的小的测试镜像。使用您的 Docker Hub 帐户登录到官方 Docker Hub(请参阅本章中的前一个配方):

    ```
    docker login

    ```

1.  现在拉取一个名为`busybox`的小镜像:

    ```
    docker pull busybox

    ```

1.  之后,将 Docker 注册表服务器切换到我们在此配方中设置的自己的服务器(输入用户名和密码,例如,`johndoe / mysecretpassword`。电子邮件字段留空):

    ```
    docker login $DCKREG:5000

    ```

1.  接下来,为了将 Docker 镜像从客户端推送到我们新的私有 Docker 注册表,我们需要将其标记为在我们的注册表域中:

    ```
    docker tag busybox $DCKREG:5000/busybox

    ```

1.  最后,将镜像推送到我们自己的注册表:

    ```
    docker push $DCKREG:5000/busybox

    ```

1.  恭喜!你刚刚将你的第一个镜像推送到了你的私有 Docker 仓库。现在,你可以在任何配置为与我们的仓库通信的其他客户端上拉取这个镜像`$DCKREG:5000/busybox`。要获取所有可用镜像的列表,请使用(根据需要更改账户信息):

    ```
    curl https://johndoe:mysecretpassword@$DCKREG:5000/v2/_catalog

    ```

## 它是如何工作的...

在本食谱中,我们向你展示了如何在服务器上的 Docker 容器中设置你自己的 Docker 注册表。理解这一点非常重要:你需要为你的注册表服务器配置一个 FQDN,因为这是整个系统工作的必要条件。

那么,我们从这次经历中学到了什么?

我们首先在每台计算机上通过`/etc/hosts`方法配置 Docker 注册表的完全限定域名(FQDN)。然后,我们在 Docker 注册表服务器上创建了一个新证书,该证书将用于客户端和注册表之间通过 TLS 加密进行安全通信。接下来,我们在`httpd`服务器上安装了新生成的证书,以便稍后所有客户端都可以访问;同时,在特定的 Docker 目录中,以便 Docker 也可以访问;并且在服务器默认信任的证书位置,我们还为该服务器重建了证书缓存。之后,我们使用`docker run`命令下载、安装并在该服务器上的 Docker 容器中运行我们的新 Docker 注册表。我们提供了一组参数来配置 TLS 加密和用户认证。

在下一步中,我们连接到注册表以创建新的`htpasswd`账户。每当你的注册表需要新账户时,你都可以重复此步骤。别忘了之后重启注册表容器。接下来,对于我们希望与之通信的每个客户端,我们都需要在服务器本身上的相同位置安装服务器证书;因此,我们从之前实现的 HTTP 源下载了它,并将其复制到各个位置。为了在客户端上测试,接下来我们连接到官方 Docker Hub 下载我们想要在下一步推送到我们自己的注册表的随机镜像。我们将`busybox`镜像下载到我们自己的镜像缓存中,然后切换到连接到我们的新私有 Docker 注册表。在我们能够将镜像上传到新位置之前,我们必须给它一个适合新服务器名称的适当标签,然后我们才能够将镜像推送到我们的新 Docker 注册表。该服务器现在在整个网络中端口 5000 上可用。请记住,如果你不想在客户端上再使用自己的注册表,你可以随时切换回官方`docker`仓库,使用`docker login`。

关于 Docker,还有很多东西需要学习。在本章的食谱中,我们只是触及了 Docker 平台的表面。如果你想了解更多关于它的信息,请考虑访问[`www.Packtpub.com`](https://www.Packtpub.com),并查看该网站上提供的许多相关书籍。


# 第十四章:使用 SELinux

在本章中,我们将介绍以下主题:

+   安装和配置重要的 SELinux 工具

+   使用 SELinux 安全上下文

+   处理策略

+   故障排除 SELinux

# 引言

本章是一系列食谱的集合,旨在揭开**安全增强型 Linux**(**SELinux**)的神秘面纱,这是一种成熟的技术,用于使用基本安全系统中添加的额外安全功能来强化您的 Linux 系统。它在 CentOS 世界中已经存在多年,但对于许多系统管理员来说,它仍然是一个鲜为人知且令人困惑的话题。

# 安装和配置重要的 SELinux 工具

任何 Linux 系统最重要的安全特性是提供访问控制——通常称为**自主访问控制**(**DAC**)——它允许对象(如文件)的所有者为其设置安全属性(例如,使用`chown`和`chmod`命令决定谁可以读写文件)。虽然这种古老且非常简单的安全系统在古老的 UNIX 时代是足够的,但它并不能满足现代安全需求,其中服务器和服务不断连接到互联网。

通常,安全漏洞可以由攻击者通过利用有缺陷或配置错误的应用程序及其权限来发起。这就是为什么开发了 SELinux。其主要目的是增强 Linux 中 DAC 系统的安全性。它通过在 DAC 之上添加一个额外的安全层来实现这一点,该层称为**强制访问控制**(**MAC**),它可以为系统中的每个单独组件提供细粒度的访问控制。SELinux 已经在 CentOS 7 上启用,并且对于任何直接连接到互联网的服务器都是绝对推荐的。在本食谱中,我们将安装额外的工具并配置它们,以更好地管理您的 SELinux 系统,并帮助进行故障排除和监控过程。

## 准备工作

要完成这个食谱,您需要一个具有 root 权限的工作 CentOS 7 操作系统安装,以及一个互联网连接以下载额外的软件包。为了获得最佳学习体验,建议您按照本章中出现的顺序逐个食谱地进行,因为它们是相互构建的。

## 如何操作...

在本书中,我们已经应用了诸如`semanage`之类的程序,该程序来自`rpm` `policycoreutils-python`包,以管理我们的 SELinux 环境。如果您错过了安装它,我们将从这个食谱开始这样做(如果您之前已经这样做过,请跳过步骤 1):

1.  以 root 身份登录并安装以下基本工具包以使用 SELinux:

    ```
    yum install policycoreutils-python

    ```

1.  现在,我们需要一些额外的工具,这些工具在本书的后续过程中也将需要:

    ```
    yum install setools setools-console setroubleshoot*

    ```

1.  接下来,安装并配置 SELinux 手册页,因为它们在 CentOS 7 上默认不可用,但对于获取有关特定策略、安全上下文和 SELinux 布尔值的详细信息非常重要。首先,我们需要安装另一个软件包:

    ```
    yum install policycoreutils-devel

    ```

1.  接下来,让我们为系统上当前可用的所有 SELinux 安全上下文策略生成所有手册页,然后更新手册页数据库:

    ```
    sepolicy manpage -a -p /usr/share/man/man8; mandb

    ```

## 它是如何工作的...

通过遵循这个配方,我们安装了日常工作中需要的所有 SELinux 工具。此外,我们生成了所有可用的 SELinux 手册页,这将是我们使用 SELinux 和解决 SELinux 服务问题时的主要信息来源。

SELinux 有两个主要和基本的术语,我们需要在深入了解本章其余部分的配方之前理解:**标签**(或更技术性地,安全上下文)和**策略**。从 SELinux 的角度来看,Linux 系统被划分为许多不同的对象。例如,对象是系统中的所有文件、进程、用户、套接字和管道。在 SELinux 上下文中,每个这样的对象都获得一个特殊的标签。SELinux 策略是使用定义在它们上的标签控制对这些对象的访问的规则:在每次尝试访问这样的对象(例如,文件读取)时,系统上可用的所有 SELinux 策略都将被搜索,以查看是否有针对特定标签的规则来做出访问控制决策(允许或拒绝访问)。

那么,我们从这次经历中学到了什么?

许多系统管理员似乎避免使用 SELinux*像瘟疫一样*,并且在许多指令手册和教程中倾向于在安装 CentOS 7 后立即完全禁用它,因为人们似乎害怕它,不想弄乱它,或者甚至感到沮丧,如果某些网络服务没有正确地从盒子中工作。通常,他们将任何连接问题归咎于 SELinux,因此看起来更容易完全禁用它,而不是通过深入了解 SELinux 的内部工作来找出真正的原因。如果你禁用它,你将错过 CentOS 7 最重要的安全功能之一,这可以在攻击事件中防止对你的系统造成很大伤害!在过去的几年中,SELinux 项目已经发展了很多,并且比以往任何时候都更容易使用。出现了许多方便的工具来使用它,并且我们得到了一套完整的工作策略来使用所有主要应用程序和服务。通过安装这些工具,我们现在准备好使用 SELinux 并以最方便的方式工作。

## 还有更多...

谈到 SELinux 时,有三种不同的模式。**增强**模式是唯一真正保护我们并增强服务器安全的模式,还有另外两种模式:**禁用**和**宽容**。禁用意味着 SELinux 被关闭,这在本书中永远不会成为我们的选项,并且不再进一步讨论,因为放弃这一出色的 CentOS 特性没有意义。当禁用时,我们的系统没有通过 SELinux 得到增强,我们手头唯一的保护来源是传统的 DAC 系统。宽容模式意味着 SELinux 已开启,策略规则已加载,所有对象都带有特定的安全上下文标签,但系统并不强制执行这些策略。这就像许多基于 Linux 的命令行工具的干运行参数:它在 SELinux 增强安全保护下模拟系统,并将系统记录的每个 SELinux 策略违规行为记录下来,就像在实际运行时一样。这是调试系统或分析正常强制运行对系统可能产生的后果的好方法。

通常,如果您不确定使用 SELinux 的影响,就会使用这种模式。由于这种模式并没有真正为我们提供任何额外的安全性,如果我们想要增强安全性,最终需要切换到**强制**模式!再次强调,这是唯一保护我们的模式;SELinux 完全运行,加载了所有策略,并在系统上强制执行这些规则。您应该始终在任何系统上追求强制模式!要查看当前模式,请使用命令`sestatus`。我们可以在输出中的`当前模式`行中看到当前的 SELinux 模式。在 CentOS 7 上,SELinux 默认处于强制模式,这再次告诉我们系统完全受到其保护。要将此模式更改为宽容模式,请使用命令`setenforce` `宽容`。现在,再次使用`sestatus`验证您的设置。要恢复更改回强制模式,请使用`setenforce enforcing`。使用`setenforce`设置 SELinux 模式只是暂时设置,它不会在重启后存活(查看`sestatus`输出中的`配置模式`文件)。要永久更改此设置,请打开`/etc/selinux/config`文件并更改`SELINUX=`配置参数。

# 使用 SELinux 安全上下文

正如我们从本章前一个配方中学到的,SELinux 都是关于标签和策略的。在本配方中,我们将向您展示如何使用这些标签,也称为安全上下文。

## 准备就绪

要完成这个配方,您需要一个具有 root 权限的 CentOS 7 操作系统的安装。假设您是通过本章的配方一步步进行的,那么到目前为止,您应该已经从前一个配方中安装了 SELinux 工具,并为策略生成了所有 SELinux 手册页。您可能会注意到,本配方中我们将向您展示的一些命令已经在本书的其他配方中应用过。我们将在这里详细解释它们。为了使用`netstat`程序,请使用 YUM 包管理器安装`net-tools`包。

## 如何做到这一点...

正如我们在之前的配方中学到的,SELinux 系统中的几乎每个组件都是一个对象(文件、目录、进程、用户等)。我们将从这个配方开始,向您展示如何使用`-Z`命令行标志打印出所有类型的对象的 SELinux 标签,这是 SELinux 系统上的许多基本 Linux 命令所支持的。

1.  首先,以 root 身份登录并键入以下命令,以从各种类型的对象探索 SELinux 安全上下文信息:

    ```
    id -Z
    ls -Z
    ps -auxZ
    netstat -tulpenZ

    ```

1.  接下来,要列出系统上所有文件和目录的可用安全上下文名称,请使用以下命令(我们仅过滤了`httpd`标签):

    ```
    semanage fcontext -l | grep httpd

    ```

1.  接下来,让我们创建一个我们可以操作的新空文件:

    ```
    touch /tmp/selinux-context-test.txt

    ```

1.  显示新文件的当前安全上下文(应包含类型`user_tmp_t`):

    ```
    ls -Z /tmp/selinux-context-test.txt

    ```

1.  最后,将`user_tmp_t`类型更改为随机的`samba_share_t`标签名称:

    ```
    semanage fcontext -a -t samba_share_t /tmp/selinux-context-test.txt
    restorecon -v /tmp/selinux-context-test.txt

    ```

1.  执行测试以验证您的更改:

    ```
    ls -Z /tmp/selinux-context-test.txt

    ```

## 它是如何工作的...

在本配方中,我们向您展示了如何显示各种 SELinux 对象类型的标签(安全上下文),如何显示所有可用标签名称,以及如何在文件对象的示例上修改或设置它们。在日常工作中,大多数管理员都会确认,我们必须管理安全上下文的最重要对象是文件、目录和进程。此外,您需要记住,每个 SELinux 对象只能有一个安全上下文。

那么,我们从这次经历中学到了什么?

正如我们所见,我们可以在许多不同的标准 Linux 命令行工具上使用`-Z`参数来打印出它们的 SELinux 安全上下文。在这里,我们向您展示了显示用户、文件和目录、进程以及网络连接标签的示例,我们可以使用`id`、`ls`、`ps`和`netstat`命令查询这些标签。在这些命令的输出中,我们看到每个此类对象的安全上下文标签都由三个值组成:用户(标记为`_u`)、角色(`_r`)和类型(`_t`)。类型字段被用作标准 SELinux 类型(称为目标型)中所有访问控制决策的主要机制,因此我们通常将整个 SELinux 访问控制过程称为**类型强制**(**TE**)。

对象标签中的其他值用户和角色对于非常高级的 SELinux 配置来说不是必要的,这里不讨论。为了显示我们系统上所有可用的上下文类型,使用命令行`seinfo -t`。这些 SELinux 类型是我们需要理解的一个非常重要的概念。对于文件和目录对象,它们用于*捆绑*相互关联的对象组,并且应该受到相同的保护或处理,以便我们可以对它们定义特定的策略规则。例如,我们可以将标准邮件假脱机目录`/var/spool/mail`中的每个文件分配为类型`mail_spool_t`,然后创建一个访问规则策略,在其中我们将使用此类型来允许特定的访问。在进程的上下文中,类型值称为域。在这里,类型用于隔离和*沙盒*进程:任何具有指定域名的进程只能与同一域中的其他进程通信和交互(有一些例外,如未讨论的转换)。通过域隔离进程大大降低了安全风险。当进程被攻陷时,它们只能损害自己,而不会影响其他任何东西。

### 注意

SELinux 有时被称为沙盒系统。从软件总是会有漏洞的假设出发,SELinux 提供了隔离软件组件的方法,使得一个组件的漏洞不会影响到另一个组件。

如果你输入`ps -auxZ`,你还会发现有一些进程在一个名为`unconfined_t`的域中运行。带有此标签的进程不受 SELinux 策略的保护,这意味着如果一个未受限的进程被攻陷,SELinux 不会阻止攻击者访问其他系统资源和数据。在这里,安全性退回到标准的 DAC 规则,这将成为你唯一的保护措施。

在我们讨论了如何显示安全上下文之后,接下来的章节中我们向您展示了如何设置和更改它们。在某些较旧的文档以及某些 SELinux 策略的`man`页中,您会遇到使用名为`chcon`的工具的示例,该工具用于修改对象的安全上下文。使用此工具已不再推荐,您应始终将此类命令行示例替换为较新的`semanage fcontext -a -t`命令行与`restorecon`程序的组合。对于`semanage`,您提供带有`-t`的标签类型名称,然后提供要为其设置标签的文件名。然后,使用`restorecon`,您提供要应用之前由`semanage`所做更改的文件名。这是因为安全上下文可以在两个级别上设置。它可以设置为策略并在文件系统级别上设置。`chcon`命令直接在文件系统上设置新上下文,而策略上下文未更改。这可能会导致问题,例如,如果您想稍后重置或更改文件系统的安全上下文(这称为重新标记)——这意味着所有安全上下文将从策略应用到文件系统,覆盖您使用`chcon`所做的所有更改。因此,最好使用`semanage`,它将写入策略,然后使用`restorecon`,它将使策略标签与文件系统同步,保持一切最新。如果您想为目录而不是单个文件设置标签,可以使用正则表达式;要查看一些示例和进一步的命令行选项,请键入`man semanage-fcontext`并浏览到`EXAMPLES`部分。

# 处理策略

在每个 SELinux 系统的核心是策略。这些是定义我们所有对象之间的访问权限和关系的精确规则。正如我们之前所学,我们系统的所有对象都有标签,其中一个标签是类型标识符,可用于执行策略中规定的规则。在每个启用 SELinux 的系统中,默认情况下,除非策略规则另有定义,否则对任何对象的所有访问都是禁止的。在本节中,我们将向您展示如何查询和自定义 SELinux 策略。您可能会注意到,本书中其他章节的一些命令已经应用于`httpd`或`ftpd`守护进程等。在这里,您将了解策略是如何工作的。

## 准备就绪

要完成此操作,您需要一个具有 root 权限的 CentOS 7 操作系统的正常安装。假设您是按照本章的食谱一个接一个地操作,那么到现在为止,您应该已经从之前的食谱中安装了 SELinux 工具,并为策略生成了所有 SELinux 手册页。对于我们这里的测试,我们将使用 Apache Web 服务器,因此请确保它已在您的系统上安装并运行(请参阅[第十二章](part0098_split_000.html#2TEN41-4cf34a6d07944734bb93fb0cd15cce8c "第十二章. 提供 Web 服务"),*提供 Web 服务*中的食谱*安装 Apache 并提供网页*)。

## 如何操作...

1.  首先,以 root 身份登录,并输入以下命令以显示所有 SELinux 布尔策略设置,仅过滤出`httpd`守护进程的设置:

    ```
    semanage boolean -l | grep httpd

    ```

1.  要获取有关特定策略及其包含的布尔值的更多信息,请阅读相应的手册页;例如,对于`httpd`,请输入以下内容:

    ```
    man httpd_selinux

    ```

1.  在这里,在`httpd`策略的手册页中,我们将找到有关每个可用的`httpd`策略布尔值的详细信息。例如,有一个关于`httpd_use_nfs`的部分。要切换单个策略功能,请使用`setsebool`命令以及策略布尔名称和`on`或`off`参数,如下所示:

    ```
    setsebool httpd_use_nfs on
    setsebool httpd_use_nfs off

    ```

## 它是如何工作的...

在本食谱中,我们向您展示了如何使用 SELinux 布尔值。请记住,SELinux 遵循最小权限模型,这意味着 SELinux 策略仅启用任何对象(如系统服务)执行其任务所需的最少功能,并且不会更多。这些策略功能可以通过相应的 SELinux 布尔值在运行时进行控制(激活或停用),而无需了解策略编写的内部工作原理。这是一个使策略可定制且极其灵活的概念。在本书的其他食谱中,我们已经通过启用 SELinux 布尔值来添加特殊策略功能,例如启用 Apache 或 FTP 主目录,这些功能默认情况下都是禁用的。

我们从这次经历中学到了什么?

SELinux Booleans 就像开关一样,用于启用或禁用 SELinux 策略中的某些功能。我们从这个菜谱开始使用 `semanage` 命令来显示系统上所有可用的 Booleans,并通过 `http` 过滤以获取仅与该服务相关的那些。如您所见,系统上有大量的 Booleans 可用,其中大多数是禁用或关闭的(最小权限模型);要获取有关特定策略及其 Boolean 值的更多信息,请使用我们在之前的菜谱中安装的 SELinux 手册页。有时,找到感兴趣的特定手册页可能会很困难。使用以下命令搜索可用的手册页名称:`man -k _selinux | grep http`。在我们的示例中,`httpd_selinux` 是获取有关 `httpd` 策略详细信息的正确手册页。最后,如果我们决定切换特定的 SELinux Boolean 功能,我们将使用 `setsebool` 命令。您应该记住,以这种方式设置 Booleans 仅在重启之前有效。要使这些设置永久生效,请使用 `-p` 标志,例如,`setsebool -P httpd_use_nfs on`。

## 还有更多...

凭借我们从之前的菜谱中获得的所有知识,我们现在能够展示一个将所有内容结合起来的示例。在这里,我们将看到 `httpd` 服务的 SELinux 安全上下文和策略在行动。如果 Apache 网络服务器正在运行,我们可以使用以下行获取 `httpd` 进程的 SELinux 域名:

ps auxZ | grep httpd


这将向我们展示 `httpd` 域(类型)称为 `httpd_t`。要获取 Web 根目录的 SELinux 标签,请输入以下命令:

ls -alZ /var/www/html


这将告诉我们 Apache 网络服务器的 Web 根目录的安全上下文类型称为 `httpd_sys_content_t`。现在,有了这些信息,我们可以从我们的策略中获取 Apache 域的确切规则:

sesearch --allow | grep httpd_t


这将打印出每个 `httpd` 策略规则。如果我们过滤输出以获取 `httpd_sys_content_t` 上下文类型,以下行再次出现:

allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open }


这向我们展示了哪些源目标上下文被允许访问,哪些目标目标上下文,以及使用哪些访问权限。在我们的 Apache Web 服务器示例中,这指定了运行在域`httpd_t`上的`httpd`进程可以访问、打开和修改文件系统上所有匹配`httpd_sys_content_t`上下文类型(所有位于`/var/www/html`目录中的文件都符合这一标准)的文件。现在,为了验证这条规则,创建一个临时文件并将其移动到 Apache Web 根目录:`echo "CentOS7 Cookbook" > /tmp/test.txt;mv /tmp/test.txt /var/www/html`。任何文件都会继承创建它的目录的安全上下文。如果我们直接在 Web 根目录中创建文件,或者复制文件(复制意味着创建一个副本),它将自动处于正确的`httpd_sys_content_t`上下文,并且完全可由 Apache 访问。但是,由于我们将文件从`/tmp`目录移动,它将保持在 Web 根目录中的`user_tmp_t`类型。如果你现在尝试获取 URL,例如,`curl http://localhost/test.txt`,你应该会收到 403 禁止消息。这是因为`user_tmp_t`类型不是`httpd_t`策略规则中文件对象的一部分,因为正如之前所说,默认情况下,未在策略规则中定义的一切都将被阻止。为了使文件可访问,我们现在将更改其安全上下文标签为正确的类型:

semanage fcontext -a -t httpd_sys_content_t /var/www/html/test.txt
restorecon -v /var/www/html/test.txt


现在再次获取`curl http://localhost/test.txt`,它应该是可访问的,并打印出正确的文本:CentOS7 cookbook。

请记住,如果你复制一个文件,安全上下文类型会从目标父目录继承。如果你想在复制时保留原始上下文,请使用`cp -preserve=context`命令。

# SELinux 故障排除

在本节中,你将学习如何排除 SELinux 策略故障,这通常在你被拒绝访问某些 SELinux 对象时需要,并且你需要找出原因。在本节中,我们将向你展示如何使用`sealert`工具,该工具将创建易于理解和处理的人类可读错误消息。

## 准备工作

为了完成本节,你需要一个具有 root 权限的 CentOS 7 操作系统的有效安装。假设你正在逐个阅读本章节,因此到现在为止,你应该已经安装了 SELinux 工具并应用了本章中的*Working with policies*节,因为我们将产生一些 SELinux 拒绝事件,以向你展示如何使用日志文件工具。

## 如何操作...

1.  开始之前,请以 root 身份登录并引发一个 SELinux 拒绝事件:

    ```
    touch /var/www/html/test2.html
    semanage fcontext -a -t user_tmp_t /var/www/html/test2.html
    restorecon -v /var/www/html/test2.html
    curl http://localhost/test2.html

    ```

1.  现在,让我们生成一个最新的人类可读日志文件:

    ```
    sealert -a /var/log/audit/audit.log

    ```

1.  在程序输出中,你将获得任何 SELinux 问题的详细描述,并且在每个所谓的警报末尾,你甚至会找到一个建议的解决方案来修复问题;在我们的示例中,感兴趣的警报应该读取(输出已截断),如下所示:

    ```
    SELinux is preventing /usr/sbin/httpd from open access on the file /var/www/html/test2.html.
    /var/www/html/test2.html default label should be httpd_sys_content_t

    ```

## 它是如何工作的...

在本食谱中,我们向您展示了如何轻松使用`sealert`程序解决 SELinux 问题。我们首先通过在 Web 根目录中创建一个新文件并为其分配错误的上下文类型值`user_tmp_t`来引发 SELinux 拒绝访问问题,该值在`httpd`策略中没有定义访问规则。然后,我们使用`curl`命令尝试获取网站,并在 SELinux 日志中实际产生**访问向量缓存**(**AVC**)拒绝消息。当 SELinux 拒绝访问时,会记录拒绝消息。所有 SELinux 日志信息的主要存储位置是审计日志文件,该文件位于`/var/log/audit/audit.log`,并且更容易阅读的拒绝消息也将写入`/var/log/messages`。在这里,我们不是手动搜索错误消息并合并两个日志文件,而是使用`sealert`工具,这是一个方便的程序,它将解析审计和消息日志文件,并以人类可读的格式呈现有价值的 AVC 内容。在每个警报消息的末尾,您还将找到一个针对问题的建议解决方案。请注意,这些是自动生成的消息,应在应用之前始终进行质疑。


# 第十五章:监控 IT 基础设施

在本章中,我们将涵盖以下主题:

+   安装和配置 Nagios Core

+   在远程客户端主机上设置 NRPE

+   监控重要的远程系统指标

# 引言

本章是一系列食谱的集合,提供了设置行业标准的开源网络监控框架:Nagios Core 的必要步骤。

# 安装和配置 Nagios Core

在本食谱中,我们将学习如何安装 Nagios Core 版本 4,这是一个开源网络监控系统,用于检查主机和服务是否正常工作,并在出现问题或服务不可用时通知用户。Nagios 提供了监控您完整 IT 基础设施的解决方案,并设计了一个高度可扩展和可定制的架构,远远超出了简单的 bash 脚本来监控您的服务。(请参阅第三章,*管理系统*中的*监控重要服务器基础设施*食谱。)

## 准备工作

要完成本食谱,您需要一个具有 root 权限的 CentOS 7 操作系统的有效安装,您选择的基于控制台的文本编辑器,以及连接到互联网以便于下载额外软件包的能力。Nagios Core 4 在官方源中不可用,而是来自 EPEL 仓库;请确保在安装之前已安装它(请参阅第四章,*使用 YUM 管理软件包*中的*使用第三方仓库*食谱)。对于 Nagios Web 前端,您还需要一个运行的 Apache2 Web 服务器以及 PHP(请参阅第十二章,*提供 Web 服务*中的食谱)安装在您的 Nagios 服务器上。在我们的示例中,Nagios 服务器的 IP 地址为 192.168.1.7,它将能够监控整个 192.168.1.0/24 子网中的所有 IT 基础设施。

## 如何操作...

Nagios Core 4 默认不可用,因此让我们从安装所有必需的软件包开始:

1.  为此,以 root 身份登录并键入以下命令:

    ```
    yum install nagios nagios-plugins-all nagios-plugins-nrpe nrpe

    ```

1.  首先,创建一个名为 `nagiosadmin` 的新用户账户,该账户用于对 Web 前端进行身份验证(在提示时输入一个安全的密码),然后重新加载 Apache 配置:

    ```
    htpasswd /etc/nagios/passwd nagiosadmin  && systemctl reload httpd

    ```

1.  现在,为 `nagiosadmin` 网络用户添加一个电子邮件地址到 Nagios 配置中,打开以下文件,并搜索并替换字符串 `nagios@localhost`,将其替换为您想要使用的适当电子邮件地址(可以是域内或外部电子邮件地址):

    ```
    vi /etc/nagios/objects/contacts.cfg

    ```

1.  现在,我们需要调整主配置文件以激活 `/etc/nagios/servers` 作为我们服务器的定义配置目录,我们将在稍后放置所有服务器配置文件,但首先,请备份:

    ```
    cp /etc/nagios/nagios.cfg  /etc/nagios/nagios.cfg.BAK
    sed -i -r 's/^#cfg_dir=(.+)servers$/cfg_dir=\1servers/g' 
    /etc/nagios/nagios.cfg

    ```

1.  我们需要创建在上一步中刚刚定义的服务器配置目录:

    ```
    mkdir /etc/nagios/servers
    chown nagios: /etc/nagios/servers;chmod 750 /etc/nagios/servers

    ```

1.  之后,要检查 `nagios.cfg` 语法的正确性,请运行以下命令:

    ```
    nagios -v /etc/nagios/nagios.cfg

    ```

1.  最后,在启动时启用 Nagios 守护进程并启动服务:

    ```
    systemctl enable nagios && systemctl start nagios

    ```

## 它是如何工作的...

在本方法中,我们向您展示了如何在 CentOS 7 上安装 Nagios Core v4 服务器(Core 是 Nagios 项目的开源版本)。除了主要的 Nagios 软件包外,我们还需要在我们的 Nagios 服务器上安装 NRPE 软件包和所有 Nagios 插件。安装后,我们创建了一个用户帐户,该帐户能够登录到 Web 前端,并在主 Nagios 配置文件中设置了该用户的电子邮件地址。接下来,我们使用 `sed` 激活了 `/etc/nagios/servers` 目录,我们将在本章后面的方法中将所有服务器定义文件放入该目录。然后,我们创建了目录并更改了权限以允许 Nagios 用户访问。要测试 Nagios 服务器安装,请在同一子网 192.168.1.0/24 中的计算机上打开 Web 浏览器,打开以下 URL(在我们的示例中,Nagios 服务器的 IP 地址为 192.168.1.7,因此请相应更改),然后使用新创建的 `nagiosadmin` 用户帐户登录到 `http://192.168.1.7/nagios`。

# 在远程客户端主机上设置 NRPE

**Nagios 远程插件执行器**(**NRPE**)是一个系统守护进程,使用特殊的客户端-服务器协议,并且应该安装在您希望通过远程 Nagios 服务器监控的所有客户端主机上。它允许中央 Nagios 服务器在这些客户端主机上安全地触发任何 Nagios 检查,并且开销很低。在这里,我们将向您展示如何设置和配置任何 CentOS 7 客户端以使用 NRPE;如果您在网络中有多个计算机需要监控,则需要为每个实例应用此方法。

## 准备就绪

要完成此方法,您需要一台除 Nagios 服务器之外的计算机,该计算机安装了 CentOS 7 操作系统,并具有 root 权限,您希望监控该计算机,并且需要在计算机上安装您选择的基于控制台的文本编辑器,以及连接到互联网以便下载额外的软件包。该计算机需要能够通过网络访问我们的 Nagios 服务器。在我们的示例中,Nagios 服务器的 IP 地址为 `192.168.1.7`,我们的客户端系统的 IP 地址为 `192.168.1.8`。

## 如何操作...

1.  以 root 用户身份登录到 CentOS 7 客户端系统,并安装所有 Nagios 插件以及 NRPE:

    ```
    yum install epel-release;yum install nrpe nagios-plugins-all nagios-plugins-nrpe

    ```

1.  之后,打开主 NRPE 配置文件(首先进行备份):

    ```
    cp /etc/nagios/nrpe.cfg /etc/nagios/nrpe.cfg.BAK && vi /etc/nagios/nrpe.cfg

    ```

1.  找到以 `allowed_hosts` 开头的行,并添加 Nagios 服务器的 IP 地址,用逗号分隔,以便我们可以与之通信(在我们的示例中,`192.168.1.7`,因此请相应更改);它应该如下所示:

    ```
    allowed_hosts=127.0.0.1,192.168.1.7

    ```

1.  保存并关闭文件,然后在启动时启用 NRPE 并启动它:

    ```
    systemctl enable nrpe && systemctl start nrpe

    ```

1.  然后在 firewalld 中启用 NRPE 端口。为此,为 NRPE 创建一个新的 firewalld 服务文件:

    ```
    sed 's/80/5666/g' /usr/lib/firewalld/services/http.xml | sed 's/WWW (HTTP)/Nagios NRPE/g' | sed 's/<description>.*<\/description>//g' > /etc/firewalld/services/nrpe.xml
    firewall-cmd --reload
    firewall-cmd --permanent --add-service=nrpe; firewall-cmd --reload

    ```

1.  最后,测试 NRPE 连接。为此,以 root 用户身份登录到您的 Nagios 服务器(例如,在`192.168.1.7`)并执行以下命令以在我们的客户端(`192.168.1.8`)上检查 NRPE:

    ```
    /usr/lib64/nagios/plugins/check_nrpe -H 192.168.1.8 -c check_load

    ```

1.  如果输出显示带有数字的`OK - load average`消息,那么您已成功在客户端配置了 NRPE!

## 工作原理...

在本食谱中,我们向您展示了如何在您希望使用 Nagios 服务器监控的 CentOS 7 客户端上安装 NRPE。如果您想监控运行其他发行版(如 Debian 或 BSD)的其他 Linux 系统,您应该能够使用它们自己的包管理器找到适当的包,或者从源代码编译 NRPE。除了 NRPE 包之外,我们还在这台机器上安装了所有 Nagios 插件,因为 NRPE 只是在客户端计算机上运行监控命令的守护进程,但它不包括这些插件。安装后,NRPE 默认只监听本地主机(`127.0.0.1`)连接,因此我们随后不得不将其更改为也监听来自我们的 Nagios 服务器的连接,该服务器使用 IP `192.168.1.7`,在主 NRPE 配置文件中使用`allowed_hosts`指令。NRPE 端口`5666`需要来自 Nagios 服务器的传入连接,因此我们还需要在防火墙中打开它。由于默认情况下没有 firewalld 规则可用,我们创建了自己的新服务文件并将其添加到当前的 firewalld 配置中。之后,我们可以通过在我们的 Nagios 服务器上运行一个`check_nrpe`命令来测试我们的 NRPE 安装,使用客户端的 IP 地址和一个随机检查命令(`check_load`返回系统的负载)。

# 监控重要的远程系统指标

Nagios 插件`check_multi`是一个便捷的工具,可以在单个检查命令中执行多个检查,并生成一个总体返回状态和输出。在本食谱中,我们将向您展示如何设置它并使用它快速监控客户端上的一系列重要系统指标。

## 准备工作

假设您已经按照本章的食谱逐一操作,因此到现在为止,您应该已经有一个运行的 Nagios 服务器和另一个您想要监控的客户端计算机,该计算机已经可以通过其 NRPE 服务从外部被我们的 Nagios 服务器访问。您想要监控的这台客户端计算机需要安装 CentOS 7 操作系统,具有 root 权限,并在其上安装了您选择的基于控制台的文本编辑器,以及连接到互联网以便下载额外的软件包。客户端计算机将具有 IP 地址`192.168.1.8`。

## 如何操作...

`check_multi` Nagios 插件可在 Github 上获得,因此我们将开始本食谱以安装`git`程序,方法是下载它:

1.  以 root 用户身份登录到客户端计算机,如果尚未安装 Git,请进行安装:

    ```
    yum install git

    ```

1.  现在,通过从源代码编译来下载并安装`check_multi`插件:

    ```
    cd /tmp;git clone git://github.com/flackem/check_multi;cd /tmp/check_multi
    ./configure --with-nagios-name=nagios --with-nagios-user=nagios --with-nagios-group=nagios --with-plugin-path=/usr/lib64/nagios/plugins --libexecdir=/usr/lib64/nagios/plugins/
    make all;make install;make install-config

    ```

1.  接下来,我们安装另一个非常有用的插件,名为`check_mem`,该插件在 CentOS 7 Nagios 插件`rpms`中不可用。

    ```
    cd /tmp;git clone https://github.com/justintime/nagios-plugins.git
    cp /tmp/nagios-plugins/check_mem/check_mem.pl  /usr/lib64/nagios/plugins/

    ```

1.  接下来,让我们创建一个`check_multi`命令文件,该文件将包含您希望在单次运行中组合的所有客户端检查;打开以下文件:

    ```
    vi /usr/local/nagios/etc/check_multi/check_multi.cmd

    ```

1.  插入以下内容:

    ```
    command[ sys_load::check_load ] = check_load -w 5,4,3 -c 10,8,6
    command[ sys_mem::check_mem ] = check_mem.pl -w 10 -c 5 -f -C
    command[ sys_users::check_users ] = check_users -w 5 -c 10
    command[ sys_disks::check_disk ] = check_disk -w 5% -c 2% -X nfs
    command[ sys_procs::check_procs ] = check_procs

    ```

1.  接下来,使用以下命令行测试我们上一步创建的命令文件:

    ```
    /usr/lib64/nagios/plugins/check_multi -f   /usr/local/nagios/etc/check_multi/check_multi.cmd

    ```

1.  如果一切正确,它应该打印出您的五个插件检查的结果和一个总体结果,例如,`OK - 5 plugins checked`。接下来,我们将在客户端的 NRPE 服务上安装这个新命令,以便 Nagios 服务器能够通过调用其名称远程执行它。打开 NRPE 配置文件:

    ```
    vi /etc/nagios/nrpe.cfg

    ```

1.  在文件的末尾,紧接在最后一个`# command`行下面添加以下行,以便向我们的 Nagios 服务器公开一个名为`check_multicmd`的新命令。

    ```
    command[check_multicmd]=/usr/lib64/nagios/plugins/check_multi -f   /usr/local/nagios/etc/check_multi/check_multi.cmd

    ```

1.  最后,让我们重新加载 NRPE:

    ```
    systemctl restart nrpe

    ```

1.  现在,让我们检查是否可以从我们的 Nagios 服务器执行我们在上一步中定义的新的`check_multicmd`命令。以 root 身份登录并输入以下命令(根据您的客户端适当更改 IP 地址`192.168.1.8`):

    ```
    /usr/lib64/nagios/plugins/check_nrpe  -H 192.168.1.8 -c "check_multicmd"

    ```

1.  如果输出与在客户端本地运行它(查看前一步)相同,我们可以成功地通过我们的服务器在客户端上执行远程 NRPE 命令,因此让我们在我们的 Nagios 服务器系统上定义该命令,以便我们可以在 Nagios 系统中开始使用它。打开以下文件:

    ```
    vi /etc/nagios/objects/commands.cfg

    ```

1.  在文件末尾插入以下内容,以定义一个名为`check_nrpe_multi`的新命令,我们可以在任何服务定义中使用它:

    ```
    define command {
     command_name check_nrpe_multi
     command_line $USER1$/check_nrpe -H $HOSTADDRESS$ -c "check_multicmd"
    }

    ```

1.  接下来,我们将在 Nagios 服务器上为我们要监控的客户端定义一个新的服务器定义(为配置文件指定一个合适的名称,例如,其域名或 IP 地址):

    ```
    vi /etc/nagios/servers/192.168.1.8.cfg

    ```

1.  插入以下内容,这将定义一个带有其服务的新主机,使用我们刚刚创建的新 Nagios 命令:

    ```
    define host {
     use                   linux-server
     host_name              host1
     address               192.168.1.22
     contact_groups         unix-admins
    }
    define service {
     use generic-service
     host_name host1
     check_command check_nrpe_multi
     normal_check_interval 15
     service_description check_nrpe_multi service
    }

    ```

1.  最后,我们需要配置所有应该在出现错误时为我们的新服务接收通知电子邮件的人员。打开以下文件:

    ```
    vi /etc/nagios/objects/contacts.cfg

    ```

1.  在文件末尾插入以下内容:

    ```
    define contactgroup{
     contactgroup_name       unix-admins
     alias                   Unix Administrators
     }
    define contact {
     contact_name                    pelz
     use                             generic-contact
     alias                           Oliver Pelz
     contactgroups                   unix-admins
     email                           oliverpelz@mymailhost.com
    }

    ```

1.  现在,重新启动 Nagios 服务:

    ```
    systemctl restart nagios

    ```

## 工作原理...

我们首先从作者的 Github 仓库安装了`check_multi`和`check_mem`插件,它们是简单的命令行工具。Nagios 通过运行这些外部命令来执行检查,并使用返回代码以及命令的输出来判断检查是否成功。Nagios 拥有一个非常灵活的架构,可以通过插件、附加组件和扩展轻松扩展。所有类型的扩展都可以在[`exchange.nagios.org/`](https://exchange.nagios.org/)找到一个中心位置进行搜索。接下来,我们为`check_multi`添加了一个新的命令文件,其中我们放置了五个不同的系统`check_`命令。这些检查作为定制监控需求的一个起点,将检查系统负载、内存消耗、系统用户、可用空间和进程。所有可用的`check_`命令都可以在`/usr/lib64/nagios/plugins/check_*`找到。正如您在我们的命令文件中看到的,这些`check_`命令的参数可能非常不同,解释它们所有超出了本食谱的范围。它们中的大多数用于设置阈值以达到某个状态,例如`CRITICAL`状态。要获取有关特定命令的更多信息,请使用命令的`--help`参数。例如,要了解`check_load -w 5,4,3 -c 10,8,6`命令中的所有参数的作用,请使用`run /usr/lib64/nagios/plugins/check_load --help`。您可以轻松地从现有插件中添加任意数量的新检查命令到我们的命令文件,或者如果您愿意,可以下载并安装任何新命令。`check_multi`插件还附带了许多命令文件示例,对于学习非常有用,因此请查看目录:`/usr/local/nagios/etc/check_multi/*.cmd`。

之后,我们通过在客户端本地以`-f`参数从`check_multi`命令干运行来检查我们刚刚创建的新命令文件的正确性。在其输出中,您将找到所有单个输出的信息,就像您单独运行这五个命令一样。如果单个检查失败,整个`check_multi`也会失败。接下来,我们在 NRPE 配置文件中定义了一个新的 NRPE 命令`check_multicmd`,然后可以从 Nagios 服务器执行,我们在下一步从 Nagios 服务器进行了测试。为了测试成功,我们期望得到与从客户端本身调用命令时相同的结果。之后,我们在 Nagios 服务器上的`commands.cfg`中定义了这个命令,以便我们可以在任何服务定义中通过引用命令名称`check_nrpe_multi`来重复使用它。接下来,我们创建了一个以 IP 地址命名的新服务器文件(只要它在目录中具有`.cfg`扩展名,您可以将其命名为任何您喜欢的名称),我们想要监控的客户端的 IP 地址为:`192.168.1.8.cfg`。它包含恰好一个主机定义和一个或多个服务定义,这些定义通过主机定义中的`host_name`值与服务定义中的`host_name`值相关联。

在主机定义中,我们定义了一个`contact_groups`联系人,该联系人与`contacts.cfg`文件中的联系人组和联系人条目相关联。如果检查的服务出现任何错误,这些将用于发送通知电子邮件。服务定义中最重要的值是`check_command check_nrpe_multi`行,它执行我们之前创建的唯一检查命令。此外,`normal_check_interval`也很重要,因为它定义了在正常情况下服务检查的频率。在这里,它每 15 分钟检查一次。您可以向主机添加任意数量的服务定义。

现在,请前往您的 Nagios 网页前端检查您新添加的主机和服务。在这里,点击**主机**标签,您将看到在本教程中定义的新主机**host1**,它应该会提供有关其状态的信息。如果您点击**服务**标签,您将看到**check_nrpe_multi**服务。它应该显示**状态**为**待定**、**正常**或**关键**,这取决于单个检查的成功与否。如果您点击其**check_nrpe_multi**链接,您将看到有关检查的详细信息。

在本章中,我们只能向您展示 Nagios 的基础知识,但总有更多需要学习的内容,因此请阅读官方 Nagios Core 文档,网址为[`www.nagios.org`](https://www.nagios.org),或者查看书籍《Learning Nagios 4》,*Packt Publishing*,作者 Wojciech Kocjan。
posted @ 2024-05-16 19:38  绝不原创的飞龙  阅读(24)  评论(0编辑  收藏  举报