Apache HTTP Server 虚拟主机配置(三)

 
 

什么是虚拟主机

"虚拟主机"是指在一个机器上运行多个网站(比如:www.company1.com  和 www.company2.com  )。如果每个网站拥有不同的IP地址,则虚拟主机可以是"基于IP"的;如果只有一个IP地址,也可以是"基于主机名"的,其实现对最终用户是透明的。物理服务器只有一个,而且web服务器也只有一个,却可以服务多个不同的站点。

如果要调试你的虚拟主机配置,你会发现Apache的 -S 命令行开关很有用。比如:

[root@localhost ~]# httpd -S
 

虚拟主机类型支持

同IP,同端口,不同域名,虽然被解析到同一个IP上,但是通过http头的 host 能够区分

不同IP, 同端口,每个虚拟主机使用不同的IP地址(但是IP地址有点贵)

  • 基于端口的虚拟主机

同IP,不同端口,但是困扰的是浏览器默认的端口都是80

基于IP的虚拟主机使用连接的IP地址来决定相应的虚拟主机。这样,你就需要为每个虚拟主机分配一个独立的IP地址。而基于域名的虚拟主机是根据客户端提交的HTTP头中标识主机名的部分决定的。使用这种技术,很多虚拟主机可以共享同一个IP地址。

基于域名的虚拟主机相对比较简单,因为你只需要配置你的DNS服务器将每个主机名映射到正确的IP地址,然后配置Apache HTTP服务器,令其辨识不同的主机名就可以了。基于域名的服务器也可以缓解IP地址不足的问题。所以,如果没有特殊原因使你必须使用基于IP的虚拟主机,您最好还是使用基于域名的虚拟主机。

基于IP的虚拟主机使用连接的IP地址来决定相应的虚拟主机。这样,你就需要为每个虚拟主机分配一个独立的IP地址。而基于域名的虚拟主机是根据客户端提交的HTTP头中标识主机名的部分决定的。使用这种技术,很多虚拟主机可以共享同一个IP地址。

我们知道,TCP/IP网络通信都是建立在 socket <IP:PORT> 之上的。<IP:PORT>就能唯一标识网络上的哪个主机哪个进程。当我们通过浏览器访问:http://www.baidu.com  的时候,首先DNS会把www.baidu.com这个域名解析为IP地址,然后才能在网络中路由。既然域名都会被解析为IP地址,那么怎么实现基于域名的虚拟主机呢?

仅仅是TCP/IP是无法做到的,但是HTTP协议却能够实现这一点。在http协议首部,定义了一个 host 参数,通过它就可以区分究竟访问的哪个虚拟主机。httpd 可以根据 host 区分到底访问的是哪一个虚拟主机。

《HTTP权威指南》

  缺失主机信息是原始HTTP规范的疏忽,它错误的假设每个web服务器上只托管了一个网站。在这个期间涌现了以下4种技术来解决这个问题。

(1)通过URL路径进行虚拟主机托管

在url中添加专门的路径部分,以便服务器判断是哪个网站。

(2)通过端口号进行主机托管

为每个站点分配一个端口号。

(3)通过IP地址进行主机托管

为不同的虚拟站点分配专门的ip地址,把这些地址绑定到一台单独的机器上。

(4)通过Host首部进行主机托管

通过Htpp/1.0增强版和HTTP/1.1正式版定义Host请求首部来携带网站名称。

  • 通过URL路径进行虚拟主机托管

通过分配不同的url路径,把共享服务器上的虚拟站点隔离开。

如:

http://www.xx123.com/zyt/index.html

http://www.xx356.com/icrt/index.html

当请求到达服务时,其中并没有主机信息,但是服务器可以通过路径来区分它们。请求zyt的网址是:GET /zyt/index.html,请求icrt的网址是: GET /icrt/index.html 这不是一个好办法/zyt 和/icrt是多余的,更坏的是http://www.xx123.com和http://www.xx356.com不能用了。

这种方案在实际中很少会用到。

  • 通过端口号进行主机托管

可在在web服务器上为不同网站指定不同的端口号,不再使用80端口,而是采用其它端口号。这个解决方案也有问题:终端用户不乐意在url中指定非标准的端口号。如http://www.xx123.com:89

  • 通过IP地址进行主机托管

通过ip地址进行主机托管,是一个更常用、更好的办法。为每个虚拟网站分配一个或者多个唯一的ip地址。所有虚拟网站的ip地址都绑定到同一个共享服务器上。服务器可以查询http连接的目的ip地址,并以此来判断客户端的目标网站。

如:把ip:209.173.34.3分配给www.xxx123.com,把ip:209.172.34.2分配给www.xx356.com,把这两个ip地址都绑定到同一物理服务器上。

但是这样做也会带来一些麻烦:首先在计算机系统上能够绑定的虚拟ip地址通常是有限制的,其次ip地址是稀缺资源,最后托管都通过复制服务器来增加容量时,ip地址短缺的问题就更加严重了。尽管有这样的缺陷,但是它仍然得到广泛的应用。

  • 通过Host首部进行主机托管

为了避免过度的地址消耗和虚拟ip地址的限制,我们希望在虚拟站点间共享同一个ip地址,且仍然能够区分站点。为了解决这个问题,浏览器来服务器的实现都扩展了HTTP,把原始主机名给了服务器。不过,浏览器不能只发送完整的URL,因为这会使许多只能接收路径的服务器无法工作。替代的方法是,把主机名和端口号放在所请求的Host扩展首部中传送。

绝大多数现代浏览器和服务器都支持Host首部,但仍然有一些客户端以及网络机器人不支持它。

配置虚拟主机

对于Apache而言,主机有两类(中心主机和虚拟主机):不能同时使用,如果要定义虚拟主机,那么必须为现存的主机也创建一个 <VirtualHost>

  1. 中心主机(Mainhost)    未配置虚拟主机时

  2. 虚拟主机(Vhost)          如果配置了中心主机,同时也想配置虚拟主机,那么把中心主机也配置虚拟主机

  • 取消中心主机(Mainhost)

    一、如果你想在现有的web服务器上增加虚拟主机,你必须也为现存的主机建造一个<VirtualHost>定义块。这个虚拟主机中ServerNameDocumentRoot所包含的内容应该与全局的ServerNameDocumentRoot保持一致。还要把这个虚拟主机放在配置文件的最前面,来让它扮演默认主机的角色。

    二、如果不想使用中心主机,那么可以直接在httpd.conf配置文件中注释掉中心主机的 DocumentRoot即可。

  • 虚拟主机的配置文件

    可以直接在主配置文件httpd.conf中直接配置,但是这样不利于维护,建议在/etc/httpd/conf.d/建立 *.conf 配置文件。前提是在httpd.conf中配置 Include conf.d/*.conf

我们通过<VirtualHost>指令来定义虚拟主机,ServerNmae和DocumentRoot是一个虚拟主机最基本的两个配置,其他可以在中心主机配置的指令,基本都可以应用于虚拟主机。

<VirtualHost IP:PORT>
ServerName
DocumentRoot "/path/to/"
</VirutalHost>
 

基于域名的虚拟主机(推荐使用该方式)

注意,在您的Apache服务器配置中创建一个基于域名虚拟主机并不会自动在您的DNS中对主机名做相应的更新。您必须自己在DNS中添加域名来指向您的IP地址。否则别人是无法访问您的web站点的。也可以在hosts文件中添加这一条目进行测试,但是这种方法仅适用于那些有这些hosts条目的机器来使用。

为了使用基于域名的虚拟主机,你必须指定服务器IP地址(和可能的端口)来使主机接受请求,这个可以用 NameVirtualHost 指令来进行配置。如果服务器上所有的IP地址都会用到,你可以用"*"作为NameVirtualHost的参数。如果你打算使用多端口(如运行SSL)你必须在参数中指定一个端口号,比如"*:80"。请注意,在NameVirtualHost指令中指定IP地址并不会使服务器自动侦听那个IP地址。请参阅设置Apache使用的地址和端口一章获取更多详情。另外,这里设定的IP地址必须对应服务器上的一个网络接口。

这样,当一个请求到达的时候,服务器会首先检查它是否使用了一个能和NameVirtualHost相匹配的IP地址。如果能够匹配,它就会查找每个与这个IP地址相对应的<VirtualHost>段,并尝试找出一个与请求的主机名相同的ServerNameServerAlias配置项。如果找到了,它就会使用这个服务器。否则,将使用符合这个IP地址的第一个列出的虚拟主机。

综上所述,第一个列出的虚拟主机充当了默认虚拟主机的角色。当一个IP地址与NameVirtualHost指令中的配置相符的时候,主服务器中的DocumentRoot将永远不会被用到。所以,如果你想创建一段特殊的配置用于处理不对应任何一个虚拟主机的请求的话,你只要简单的把这段配置放到<VirtualHost>段中,并把它放到配置文件的最前面就可以了。

需要注意的是:apache2.2 需要用 NameVirtualHost 指令配置, apache2.4 不需要

下一步就是为每个虚拟主机建立<VirtualHost>段。<VirtualHost>的参数与NameVirtualHost的参数必须是一样的(比如说,一个IP地址或"*"代表的所有地址)。在每个<VirtualHost>段中,至少要有一个ServerName指令来指定伺服哪个主机和一个DocumentRoot指令来说明这个主机的内容位于文件系统的什么地方。

以下试验中,请注意 iptables, SELinux 的设置;

# 修改配置文件
[root@localhost ~]# vi /etc/httpd/conf.d/virtual.conf
NameVirtualHost *:80 # apache 2.2 必须 <VirtualHost *:80>
ServerName www.a.com
DocumentRoot "/www/a.com"
</VirtualHost> <VirtualHost *:80>
ServerName www.b.org
DocumentRoot "/www/b.org"
</VirtualHost> # 创建web目录
[root@localhost ~]# mkdir -pv /www/a.com /www/b.org
mkdir: created directory `/www'
mkdir: created directory `/www/a.com'
mkdir: created directory `/www/b.org' # 编辑index.html
[root@localhost ~]# echo '<h1>www.a.com</h1>' > /www/a.com/index.html
[root@localhost ~]# echo '<h1>www.b.org</h1>' > /www/b.org/index.html # 检查虚拟主机配置
[root@localhost ~]# httpd -S
httpd: apr_sockaddr_info_get() failed for skype
httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:80 is a NameVirtualHost
default server www.a.com (/etc/httpd/conf.d/virtual.conf:3)
port 80 namevhost www.a.com (/etc/httpd/conf.d/virtual.conf:3)
port 80 namevhost www.b.org (/etc/httpd/conf.d/virtual.conf:8) # 重新载入配置文件
[root@localhost ~]# service httpd reload # 我们只能通过域名进行访问,如果直接使用IP,那么则会返回默认的虚拟主机。
# 1 可以修改客户机的host文件, win: C:\Windows\System32\drivers\etc
# 2 也可以搭建内部的DNS服务器进行解析 # 编辑hosts文件,有些机器的hosts可能被隐藏了
192.168.11.101 www.a.com
192.168.11.101 www.b.org C:\Users\yy>ping www.a.com
正在 Ping www.a.com [192.168.11.101] 具有 32 字节的数据:
来自 192.168.11.101 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.11.101 的回复: 字节=32 时间<1ms TTL=64 C:\Users\yy>ping www.b.org
正在 Ping www.b.org [192.168.11.101] 具有 32 字节的数
来自 192.168.11.101 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.11.101 的回复: 字节=32 时间<1ms TTL=64 # OK, 我们看到
# 通过浏览器访问, 注意首先要注释掉中心主机哈
 

最后,你可以把其他一些指令放入<VirtualHost>段中,以更好的配置一个虚拟主机。大部分指令都可以放入这些<VirtualHost>段中以改变相应虚拟主机配置。如果您想了解一个特定的指令是否可以这样运用,请参见指令的作用域主服务器(main server)范围内的配置指令(在所有<VirtualHost>配置段之外的指令)仅在它们没有被虚拟主机的配置覆盖时才起作用。

这样,当一个请求到达的时候,服务器会首先检查它是否使用了一个能和NameVirtualHost相匹配的IP地址。如果能够匹配,它就会查找每个与这个IP地址相对应的<VirtualHost>段,并尝试找出一个与请求的主机名相同的ServerNameServerAlias配置项。如果找到了,它就会使用这个服务器。否则,将使用符合这个IP地址的第一个列出的虚拟主机

综上所述,第一个列出的虚拟主机充当了默认虚拟主机的角色。当一个IP地址与NameVirtualHost指令中的配置相符的时候,主服务器中的DocumentRoot永远不会被用到。所以,如果你想创建一段特殊的配置用于处理不对应任何一个虚拟主机的请求的话,你只要简单的把这段配置放到<VirtualHost>段中,并把它放到配置文件的最前面就可以了。

配置实例框架:

注意
在您的Apache服务器配置中创建一个虚拟主机并不会自动在您的DNS中对主机名做相应更新。您必须自己在DNS中添加域名来指向您的IP地址。否则别人是无法看到您的web站点的。您可以在您的hosts文件中添加这一条目来进行测试,但这种方法仅适用于那些有这些hosts文件的机器来使用。 # 确保Apache在监听80端口
Listen 80 # 为虚拟主机在所有IP地址上监听
NameVirtualHost *:80 # apache2.2需要此指令启动基于域名的虚拟主机 # vhost for www.example.com
<VirtualHost *:80>
ServerName www.example.com
DocumentRoot "/www/example1"
ErrorLog "/www/example1/logs/error_log"
CustomLog "/www/example1/logs/access_log"
# 修饰目录访问属性
<Directory />
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
</Directory> # 您可以在这里添加其他指令 </VirtualHost> # vhost for www.example.org
<VirtualHost *:80>
ServerName www.example.org
DocumentRoot "/www/example2" # 您可以在这里添加其他指令 </VirtualHost>
 

因为 www.example.com  首先出现在配置文件中,所以它拥有最高优先级,可以认为是默认或主服务器。这意味着如果一个请求不能与某个ServerName指令相匹配,它将会由第一个<VirtualHost>段所伺服。

基于IP的虚拟主机

这样的服务器中每个基于IP的虚拟主机必须拥有不同的IP地址。可以通过配备多个真实的物理网络接口来达到这一要求,也可以使用几乎所有流行的操作系统都支持的虚拟界面来达到这一要求(详情请参见您的系统文档,这种功能一般被称作"IP别名",一般用"ifconfig"命令来进行设置)。

基于IP的虚拟主机应用也不多,以为IP地址是稀缺资源,而且价格昂贵。

有两种配置方法来使apache支持多主机:为每个虚拟主机运行不同的httpd守护进程;或者用同一个守护进程来支持所有虚拟主机。

以下情况使用多个守护进程:

  • 出于安全的考虑,比如说公司甲不希望公司乙的任何人能用除web以外的方式访问到他们的数据。在这种情况下,

  • 您需要启动两个守护进程。每个进程都使用不同的UserGroupListen,ServerRoot设置。

  • 您能够为机器上的每个IP地址提供内存和文件描述符需求。您只能Listen一个"通配符型"地址或一个特定的地址。

  • 所以不管出于什么原因,如果您需要侦听一个特定的地址,您就必须同时侦听所有特定的地址。(尽管可以让一

  • httpd侦听N-1个地址,而让另一个侦听剩下的地址)

以下情况使用单一守护进程:

  • httpd的配置可以为多个虚拟主机共享而不引起麻烦。

  • 机器要接受大量的访问请求,从而多启动一个守护进程会导致性能大幅度降低。

1、设置多个守护进程

为每个虚拟主机创建一个不同的httpd安装。每次安装都在配置文件中使用Listen指令指定守护进程伺服的IP地址(或虚拟主机)。比如:

Listen www.smallco.com:80
 

2、配置拥有多个虚拟主机的单一守护进程

在这种情况下,单一的httpd将伺服所有对主服务器和虚拟主机的请求。而配置文件中的VirtualHost指令将为每个虚拟主机配置不同的ServerAdminServerNameDocumentRootErrorLog,TransferLogCustomLog 。

[root@localhost ~]# vi /etc/httpd/conf.d/virtual.conf
<VirtualHost 192.168.11.101:80>
serverName www.a.com
DocumentRoot "/www/a.com"
</VirtualHost> <VirtualHost 192.168.11.102:80>
serverName www.b.org
DocumentRoot "/www/b.org"
</VirtualHost> # 检查虚拟主机配置
[root@localhost ~]# httpd -S # 重新读取配置文件
[root@localhost ~]# service httpd reload # 编辑index.html
[root@localhost ~]# echo '<h1>192.168.11.101</h1>' > /www/a.com/index.html
[root@localhost ~]# echo '<h1>192.168.11.102</h1>' > /www/b.org/index.html # 如何测试呢?我们通过添加网卡别名来达成
[root@localhost ~]# ifconfig eth1
eth1 Link encap:Ethernet HWaddr 00:0C:29:FB:65:36
inet addr:192.168.11.101 Bcast:192.168.11.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fefb:6536/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:168196 errors:0 dropped:0 overruns:0 frame:0
TX packets:44037 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:197148682 (188.0 MiB) TX bytes:3998845 (3.8 MiB)
Interrupt:19 Base address:0x2080 [root@localhost ~]# ifconfig eth1:0 192.168.11.102/24 up # 添加网卡别名
 

基于端口的虚拟主机

基于端口的虚拟主机在生产环境用的不多,因为客户端浏览器默认都是80端口,客户端并不知道我们配置端口是什么。除了通过链接地址进行跳转的情况以及公司内部使用。

必须配置httpd监听端口: Listen PORT(极为重要)

[root@localhost ~]# vi /etc/httpd/conf.d/virtual.conf
NameVirtualHost *:80 <VirtualHost 192.168.11.101:80>
serverName www.a.com
DocumentRoot "/www/a.com"
</VirtualHost> <VirtualHost 192.168.11.101:8080>
serverName www.b.org
DocumentRoot "/www/b.org"
</VirtualHost> # 修改主配置文件,修改监听端口(非常重要)
# 这样httpd才能向linux内核(BIND)注册端口,然后TCP/IP协议栈才知道把包传给哪个应用程序。
[root@localhost ~]# vi /etc/httpd/conf/httpd.conf
Listen 80
Listen 8080 [root@localhost ~]# httpd -t
[root@localhost ~]# service httpd restart # 由于修改了端口,需要restart [root@localhost ~]# echo '<h1>192.168.11.101: 80</h1>' > /www/a.com/index.html
[root@localhost ~]# echo '<h1>192.168.11.101: 8080</h1>' > /www/b.org/index.html
 

如果开启了防火墙,请检查防火墙设置,添加其端口的入站规则。

总结

定义一个站点,至少需要提供如下信息:

  • DocumentRoot

  • ServerName

  • IP

  • PORT

如果测试无法正常访问, 请检查iptables防火墙规则,以及SELinux设置。

更多详细信息, 请参考Apache官方网站。

Apache HTTP Server 虚拟主机配置的更多相关文章

  1. Apache 2.4虚拟主机配置

    托管它指的是多个站点的执行一台机器上 (例如 company1.example.com 和 company2.example.com) . 机能够"基于 IP",即每一个 IP 一 ...

  2. linux apache虚拟主机配置(基于ip,端口,域名)

    配置环境: linux版本:Centos6.4 httpd版本: [root@centos64Study init.d]# pwd/etc/init.d[root@centos64Study init ...

  3. windows环境下,apache虚拟主机配置

    在windows环境下,apache从配置文件的相关配置: Windows 是市场占有率最高的 PC 操作系统, 也是很多人的开发环境. 其 VirtualHost 配置方法与 Linux 上有些差异 ...

  4. server下apache2.4.*虚拟主机配置Forbidden You don't have permission to access / on this server.

    前言: 继前面两节笔记之后,在配置一个虚拟主机时,这中间却遇见了一个问题,这里需要描述做一下笔记,刚刚安装的是Ubuntu server,apt-get下来的apache的版本是2.4.7,之前一直用 ...

  5. Apache+php+mysql的安装与配置 - 之三(Apache的虚拟主机配置)

    Apache+php+mysql的安装与配置 - 之三(Apache的虚拟主机配置) Apache核心(Core)配置 VirtualHost 语法 <VirtualHost addr[:por ...

  6. apache 虚拟主机配置(根据不同的域名映射到不同网站)

    最近弄了台香港服务器做测试,Web服务器软件用的是Apache2.2,机器只有一台,ip只有一个,但是想测试几个站点,于是尝试了下Apache的虚拟主机配置.之前已经写过一篇博文了——<Apac ...

  7. Apache基于域名、端口、IP的虚拟主机配置(Centos 6.5)

    虚拟主机:部署多个站点,每个站点,希望用不同的域名和站点目录,或者是不同的端口,不同的ip,需要虚拟主机功能.一句话,一个http服务要配置多个站点,就需要虚拟主机. 虚拟主机分类:基于域名.基于端口 ...

  8. apache虚拟主机配置及解析

    Apache虚拟主机配置及解析 1.修改httpd-vhosts.conf 打开apache(Apache24)/conf/extra/httpd-vhosts.conf文件,添加虚拟主机信息,可以这 ...

  9. Apache虚拟主机配置

    在一个Apache服务器上可以配置多个虚拟主机,实现一个服务器提供多站点服务,其实就是访问同一个服务器上的不同目录.Apache虚拟主机配置有3中方法:基于IP配置.基于域名配置和基于端口配置,这里介 ...

随机推荐

  1. node+ajax实战案例(5)

    6.添加客户 6.1.点击添加按钮,弹出表单框 // 添加用户 显示对话框 var addBtn = document.getElementById('add-btn'); var addUser = ...

  2. 全国计算机等级考试二级笔试样卷Java语言程序设计

    一.选择题((1)-(35)每小题2分,共70分) 下列各题A).B).C).D)四个选项中,只有一个选项是正确的,请将正确选项涂写在答题卡相应位置上,答在试卷上不得分. (1)下列选项中不符合良好程 ...

  3. Maven中央仓库正式成为Oracle官方JDBC驱动程序组件分发中心

    1. 前言 相信参与使用Oracle数据库进行项目开发.运维的同学常常被Oracle JDBC驱动的Maven依赖折磨.现在这一情况在今年二月份得到了改变,甲骨文这个老顽固终于开窍了. 一位甲骨文的工 ...

  4. SpringBoot-读取classpath下文件

    文章目录 开发过程中,必不可少的需要读取文件,对于打包方式的不同,还会存在一些坑,比如以jar包方式部署时,文件都存在于jar包中,某些读取方式在开发工程中都可行,但是打包后,由于文件被保存在jar中 ...

  5. LeetCode-Queue

    简单题 1. 数据流中的移动平均值 $(leetcode-346) 暂无 2. 最近的请求次数(leetcode-933) 写一个 RecentCounter 类来计算最近的请求. 它只有一个方法:p ...

  6. MySQL实验 内连接优化order by+limit 以及添加索引再次改进

    MySQL实验 内连接优化order by+limit 以及添加索引再次改进 在进行子查询优化双参数limit时我萌生了测试更加符合实际生产需要的ORDER BY + LIMIT的想法,或许我们也可以 ...

  7. 深度学习论文翻译解析(九):Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition

    论文标题:Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition 标题翻译:用于视觉识别的深度卷积神 ...

  8. 记录一次dns引发的线程池故障

    # 问题描述 公司做的是一个支付系统,会对接很多第三方公司. 突然有一天,有一家第三方(简称金花平台)反应收不到我们的通知消息. # 排查过程 我们登陆自己的服务器,检查程序日志,是有给金花平台发送通 ...

  9. CTF_show平台 web题解 part2

    web10 WITH ROLLUP 绕过 点击取消键弹出源码下载: 源码如下: <?php $flag=""; function replaceSpecialChar($st ...

  10. pip install scrapy报错:error: Unable to find vcvarsall.bat解决方法

    今天在使用pip install scrapy 命令安装Scrapy爬虫框架时,出现了很让人头疼的错误,错误截图如下: 在网上查找解决方法时,大致知道了问题的原因.是因为缺少C语言的编译环境,其中一种 ...