Web服务之四:httpd虚拟主机
Apache虚拟主机相关概念
若不考虑虚拟的话,安装好Apache后可以提供一个网站或站点的运行平台给我们。需要注意的是,Apache本身不是一个站点,只是一个运行的服务器。这个服务器有时候又被称为Host也被称为物理主机,它指的是服务器本身能够运行的站点。
那么为什么要用到虚拟主机呢?我们要想实现Web站点而且能够在互联网上被访问,首先它得能够运行在一个操作系统上而且这个操作系统得运行在一个物理主机上,这是第一个前提。所以它是一个主机如果想要在互联网上能够被访问那我们需要一个主机、一个IP地址、一个实时在线的服务器,那这需要多少资源呢?对于众多小型站点来讲,压根用不上服务器,因为它可能每天只有3、5个访问量,只需要能够在线而已。如果我们为了这一点需求投入这么大的资源去运行这个站点的话,非常浪费。因此我们期望能够运行虚拟机或虚拟PC一样,能够在一台物理主机上虚拟出多个可以同时运行的站点或主机。
假设我们运行了一个Apache进程或服务,但这个服务运行起来之后,能够服务于多个不同的站点,这就意味着我们通过同一个主机访问多个不同的站点,它们打开展示的资源是不同的,而且对于终端用户来讲,它们意识不到这是个虚拟主机,甚至于它能够完全认为这是一台运行的独立的物理服务器,所以我们称之为虚拟主机。
对于Apache而言,虚拟主机有两类,若不使用虚拟主机的这台主机称为中心主机或核心主机,如果一旦启用了虚拟主机,就称为虚拟主机,一般来讲,中心主机与虚拟主机不能同时启用。而且,如果此前有中心主机的话,如果想保留站点的话,那么我们只能把中心主机也定义成一个虚拟主机来使用了。但我们又知道,对于一台服务器而言,它的某些资源是有限的,如IP地址、80端口等,对于TCP来讲80端口只有一个,而如何定义每一个不同的主机呢?对于一个Web服务器而言,怎么去定义Web服务器呢?用户访问的是"IP:PORT/RESOURCE",于是IP:PORT就定义了一台主机,而如果说想使用多个不同的主机,就有几种类型:
- 基于IP:每一个主机使用不同的地址,但它们的端口一致;
- 基于端口:对于同一个IP地址,使用不同的端口;但很多时候访问站点时,都是使用默认的80端口,一旦换了端口对方就不知道使用的是哪个端口了,因此较常用的就是基于IP的了,但是IP地址是一种稀缺资源,况且一个IP地址一年的使用费用也是不菲的,对于小站点来讲也没有必要占用IP地址,因此我们可以通过基于域名实现虚拟主机;
- 基于域名:IP、端口都相同,当每一个不同站点其主机名不一样,如www.test.com、www.a.org、www.b.net,这三个主机都解析到同一个IP地址上,但它们的主机名各不相同;
我们再来考虑一个问题,若三个站点放在同一个主机上,而且都解析到同一个IP上,那么两个不同的客户端访问时,它们访问的为什么不是同一个站点呢?要知道,Web会话的建立除了TCP/IP协议之外,还有http协议,而http协议有一个首部叫HOST,在HOST中表明了我们请求的主机或主机名,通过http协议附带的内容判断用户请求的到底是哪一个主机或站点,所以哪怕IP地址和端口号都一样也照样能够使用不同的虚拟主机。
需要注意的是在Apache2.2的时候,需要一个特殊的指令启用基于主机名的虚拟主机,这个指令叫NameVirtualHost,而Apache2.4时不需要。
一个站点最核心的应具备的东西:
(如在一个物理机上提供了两个不同的站点,而每一个站点独立具有的资源或者配置甚至是信息应该有哪些呢?)
- DocumentRoot:首先这个网站提供的网页可能不一样那么很有可能位于不同的目录下即DocumentRoot不同;
- ServerName:此外,如果是基于IP的主机那么IP应该不同,如果是基于端口的主机端口应该不同,如果是基于主机名的主机主机名应该不同。因此一个主机应该有其主机名;
- <Directory>容器:每一个用户的DocumentRoot允许哪些人访问是否需要进行认证等,没一个站点都可能不同,因此对于不同站点若需要认证应该封装不同的<Directory "">容器;
- 别名:此外,虚拟主机还能使用别名(路径别名,Alias)与ServerAlias(服务器别名,指的是主机名的别名)等;
- ...
虚拟主机可定义的属性:
<Location "/images"></Location>:<Location>与<Directory>一样,Directory是用来封装定义用户访问本地文件系统目录下的文件的时候应该具有什么样的属性,但最后可能有一些映射关系。而Location则是用来定义URL的,就是IP:PORT后的路径如果是images/,访问其中所有的资源时,它应该具有什么样权限,或者可以使用什么样的方法的。而Location对于虚拟主机来讲也是可以用的,明确说明对于当前的虚拟主机,它的某一个Location应该怎样被使用。如:/images目录下的所有文件只允许GET方法其它任何方法都不支持。
除此之外ScriptAlias是允许执行CGI脚本的目录的。而一个虚拟主机也可以使用ScriptAlias,明确说明当前主机所允许执行的脚本目录在哪。
CGI与动态网站:
我们再来回顾一下CGI,CGI(Common Gateway Interface)是一种协议,有了CGI技术,那么我们的服务器上的Apache进程就能通过CGI协议启动另外一个进程,这个进程能够执行一段脚本或程序,并且执行的程序还能够通过CGI协议将结果返回给Apache进程。
而动态网站可分为两类:
- 客户端动态:
把程序放在网站上,用户访问的时候这个程序或程序的源文件时这个程序先被下载到本地,在用户本地执行。所以对于不同的用户来讲访问的结果可能是不同的。这样做有一个弊端,若在网站上放了一个恶意指令就是让客户端格式化磁盘,用户下载到本地执行,会对客户端产生危害,所以客户端动态有着极大的不安全性。还有客户端动态的适用性不强,如:开发了一个Java脚本,客户端没有安装Java运行环境,就不能运行起来。
- 服务器端动态:
基于CGI技术实现,动态则表示是需要执行程序的,而Apache本身只能解析HTML或简单的文本文件,脚本需要各自各自的解释器执行。
虚拟主机的定义:
虚拟主机与中心主机不能同时使用,因此使用虚拟主机前需要先取消中心主机,注释中心主机的DocumentRoot即可。
<VirtualHost HOST>
</VirtualHost>
HOST的写法:
- 基于IP
IP:PORT,如:IP1:80、IP2:80
- 基于端口:
IP:80
IP:8080
- 基于主机名:
IP:80(表示当前主机上所有的IP都监听,使用*:80)
ServerName一定要不同
基于IP地址的虚拟主机的实现
取消中心主机,注释DocumentRoot即可:
可在此文件中定义VirtualHost,也可以单独建立一个文件来定义,单独建立一个文件管理起来更方便。
此处单独建立一个文件用于定义VirtualHost:
为IP地址添加别名当做第二个IP地址使用:
第二个是辅助性的地址
测试:
基于端口的虚拟主机的实现:
监听端口:
基于主机名的虚拟主机的实现
启用NameVirtualHost,并指定监听在哪个地址上的主机将会使用VirtualHost,*:80表示所有地址
编辑Windows物理机的host文件或搭建DNS服务器以解析主机名,此处为方便使用编辑主机名的方式:
若使用IP地址访问,将返回符合基于名称的虚拟主机的第一个:
以上三种方式的虚拟主机访问的错误虚拟主机访问的错误日志都放在/var/log/httpd/error_log中,访问日志都放在/var/log/httpd/access_log中。
自定义日志
若想不同的站点使用不同的日志,需要各自定义:
报错是因为日志文件未创建:
确保SELinux为启用:
刷新浏览器,查看对应的日志文件:
实现虚拟主机的访问控制 :
- 对于d.gov这个站点拒绝192.168.241.1访问,只拒绝这一主机的访问:
此时使用物理机(192.168.241.1)无法访问;
其它主机正常访问:
- 期望访问a.org时需要用户提供账号密码:
通过www.apache.org或在本机安装manual学习指令:
定义默认虚拟主机
当用户指定不存在的虚拟主机或使用IP地址时不想访问第一个或名称解析的结果是没有这个主机名,可通过配置默认主机实现:
需要注意的是:此项需要定义在前面,即基于名称虚拟主机的第一个;
修改系统上默认URL的修改,实现系统上开放Server Status
ServerHandler:实现让所有匹配到的文件都能有一个处理器处理,Handler是调用某个文件是应该执行的动作,具体的动作对于不同场景来讲是不同的,比如server-status是Apache内置的一个动作,具体参见文档;