Apache HTTP Server 虚拟主机配置
Apache HTTP Server 虚拟主机配置(三)
什么是虚拟主机
"虚拟主机"是指在一个机器上运行多个网站(比如:www.company1.com 和 www.company2.com )。如果每个网站拥有不同的IP地址,则虚拟主机可以是"基于IP"的;如果只有一个IP地址,也可以是"基于主机名"的,其实现对最终用户是透明的。物理服务器只有一个,而且web服务器也只有一个,却可以服务多个不同的站点。
如果要调试你的虚拟主机配置,你会发现Apache的 -S 命令行开关很有用。比如:
[root@localhost ~]# httpd -S虚拟主机类型支持
- 基于主机名的虚拟主机(一个IP地址,多个网站) 
同IP,同端口,不同域名,虽然被解析到同一个IP上,但是通过http头的 host 能够区分
- 基于IP地址的虚拟主机(每个站点拥有一个的独立IP地址) 
不同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>
- 中心主机(Mainhost) 未配置虚拟主机时 
- 虚拟主机(Vhost) 如果配置了中心主机,同时也想配置虚拟主机,那么把中心主机也配置虚拟主机 
- 取消中心主机(Mainhost) - 一、如果你想在现有的web服务器上增加虚拟主机,你必须也为现存的主机建造一个 - <VirtualHost>定义块。这个虚拟主机中- ServerName和- DocumentRoot所包含的内容应该与全局的- ServerName和- DocumentRoot保持一致。还要把这个虚拟主机放在配置文件的最前面,来让它扮演默认主机的角色。- 二、如果不想使用中心主机,那么可以直接在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>段,并尝试找出一个与请求的主机名相同的ServerName或ServerAlias配置项。如果找到了,它就会使用这个服务器。否则,将使用符合这个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>段,并尝试找出一个与请求的主机名相同的ServerName或ServerAlias配置项。如果找到了,它就会使用这个服务器。否则,将使用符合这个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以外的方式访问到他们的数据。在这种情况下, 
- 您需要启动两个守护进程。每个进程都使用不同的 - User,- Group,- Listen,- ServerRoot设置。
- 您能够为机器上的每个IP地址提供内存和文件描述符需求。您只能 - Listen一个"通配符型"地址或一个特定的地址。
- 所以不管出于什么原因,如果您需要侦听一个特定的地址,您就必须同时侦听所有特定的地址。(尽管可以让一 
- 个 - httpd侦听N-1个地址,而让另一个侦听剩下的地址)
以下情况使用单一守护进程:
- httpd的配置可以为多个虚拟主机共享而不引起麻烦。 
- 机器要接受大量的访问请求,从而多启动一个守护进程会导致性能大幅度降低。 
1、设置多个守护进程
为每个虚拟主机创建一个不同的httpd安装。每次安装都在配置文件中使用Listen指令指定守护进程伺服的IP地址(或虚拟主机)。比如:
Listen www.smallco.com:802、配置拥有多个虚拟主机的单一守护进程
在这种情况下,单一的httpd将伺服所有对主服务器和虚拟主机的请求。而配置文件中的VirtualHost指令将为每个虚拟主机配置不同的ServerAdmin, ServerName, DocumentRoot, ErrorLog,TransferLog, CustomLog 。
[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 虚拟主机配置的更多相关文章
- Apache 2.4虚拟主机配置
		托管它指的是多个站点的执行一台机器上 (例如 company1.example.com 和 company2.example.com) . 机能够"基于 IP",即每一个 IP 一 ... 
- linux apache虚拟主机配置(基于ip,端口,域名)
		配置环境: linux版本:Centos6.4 httpd版本: [root@centos64Study init.d]# pwd/etc/init.d[root@centos64Study init ... 
- windows环境下,apache虚拟主机配置
		在windows环境下,apache从配置文件的相关配置: Windows 是市场占有率最高的 PC 操作系统, 也是很多人的开发环境. 其 VirtualHost 配置方法与 Linux 上有些差异 ... 
- server下apache2.4.*虚拟主机配置Forbidden  You don't have permission to access / on this server.
		前言: 继前面两节笔记之后,在配置一个虚拟主机时,这中间却遇见了一个问题,这里需要描述做一下笔记,刚刚安装的是Ubuntu server,apt-get下来的apache的版本是2.4.7,之前一直用 ... 
- Apache+php+mysql的安装与配置 - 之三(Apache的虚拟主机配置)
		Apache+php+mysql的安装与配置 - 之三(Apache的虚拟主机配置) Apache核心(Core)配置 VirtualHost 语法 <VirtualHost addr[:por ... 
- apache 虚拟主机配置(根据不同的域名映射到不同网站)
		最近弄了台香港服务器做测试,Web服务器软件用的是Apache2.2,机器只有一台,ip只有一个,但是想测试几个站点,于是尝试了下Apache的虚拟主机配置.之前已经写过一篇博文了——<Apac ... 
- Apache基于域名、端口、IP的虚拟主机配置(Centos 6.5)
		虚拟主机:部署多个站点,每个站点,希望用不同的域名和站点目录,或者是不同的端口,不同的ip,需要虚拟主机功能.一句话,一个http服务要配置多个站点,就需要虚拟主机. 虚拟主机分类:基于域名.基于端口 ... 
- apache虚拟主机配置及解析
		Apache虚拟主机配置及解析 1.修改httpd-vhosts.conf 打开apache(Apache24)/conf/extra/httpd-vhosts.conf文件,添加虚拟主机信息,可以这 ... 
- Apache虚拟主机配置
		在一个Apache服务器上可以配置多个虚拟主机,实现一个服务器提供多站点服务,其实就是访问同一个服务器上的不同目录.Apache虚拟主机配置有3中方法:基于IP配置.基于域名配置和基于端口配置,这里介 ... 
随机推荐
- openstack-taskflow 组件记录
			[Summary] TaskFlow 是一个为了 openstack 实现的 python 库,使得执行 task 变得简单,一致,易扩展,可靠: 它能以一种声明的方式,将轻量级 task 对象的创建 ... 
- 不就是语法和长难句吗—笔记总结Day2
			6.区别定语从句和同位语从句 I have a dream that sounds funny. (定语从句) I have a dream that I will become a rich man ... 
- Django项目中集成第三方登录时出现的错误
			原以为是被反爬 没想到 总结:这里的http应该是https协议,以后要更加小心 了,不能犯这种低级错误 
- (私人收藏)蓝色抽象科技感工作计划PPT模板
			蓝色抽象科技感工作计划PPT模板 https://pan.baidu.com/s/16iFYH94dVXp_izksVMGMBg0ozp 
- springSecurity使用
			目录 1.1 依赖包导入 2.1 没有安全机制下的一个web 3.1 做一个安全机制的web 官网https://spring.io/guides/gs/securing-web/ 无情的翻译官... ... 
- 小烈送菜——奇怪的dp
			小烈送菜 题目描述 小烈一下碰碰车就被乐满地的工作人员抓住了.作为扰乱秩序的惩罚,小烈必须去乐满地里的"漓江村"饭店端盘子. 服务员的工作很繁忙.他们要上菜,同时要使顾客们尽量高兴 ... 
- Caocao's Bridges   HDU - 4738 求桥
			题目描述 Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. ... 
- 文件读取一些payload
			Windows: C:boot.ini //查看系统版本 C:WindowsSystem32inetsrvMetaBase.xml //IIS配置文件 C:Windowsrepairsam //存储系 ... 
- PHP一维数组快速去重、去零
			1.一维数组去重: /** * 一维数组去重,返回格式为索引数组 * @param array $data 待去重的数组 * @return array */ public static functi ... 
- postman-3-请求
			请求头 单击Headers选项卡将显示请求头键-值编辑器.我们可以将任何字符串设置为请求头名称.在输入字段时,自动完成下拉菜单将补充常见HTTP请求头. Content-Type标题的值也可从自动完成 ... 
