深入理解Apache
虚拟主机
环境:
Rehat 9
Apache 2.0.54
IP:192.168.0.111
概论:
访问
web
服务
,
本质上看
(
从协议上
)
是访问某个
IP
的主机上的某个端口
(
默认是
80)
通常需要通过访问不同的域名或者端口实现对不同网站的访问
(
具体到服务器里就是不同目录
),
这个时候就需要设置虚拟主机
(VirtualHost).
通常分为这样
3
种
:
基于域名
,
基于端口
,
基于
IP,
以及它们的混合
准备工作:
在
apache
的主目录
/var/www/html/
下分别建立四个文件夹
s1,s2,s3,s4,
在里面建立不同网站的主页文件
,
如
s1
下面建立
index.html
内容为
this is s1, s2
下面建立
index.html
内容为
this is s2,
依此类推
.
配置
server
的
bind
服务
,
为它添加
2
个域名
s1.domain1.com, s2.domain1.com,.(
其实是完全按我之前写的
DNS设置的文章
配的
,
只做了小小的改动而已
)
将客户机的
DNS
指向
server,
在客户机上
ping
这
2
个域名都能返回正确的
IP.
另外注意一点
:
每次修改配置文件
httpd.conf
之后
apache
要重新启动
,
才能使配置生效
下面是每种虚拟主机的配置过程
1.
基于域名
这是一种最通用的情况
,
已经给服务器设置了多个域名
,
然后希望访问不同的域名来访问不同的网站文件
.
修改
httpd.conf
的配置
# Use name-based virtual hosting.
#
NameVirtualHost *
表示在
apache
监听的所有
IP
和所有端口
(
此时只有
80)
上做多域名虚拟主机
<VirtualHost *>
DocumentRoot /var/www/html/s1
ServerName s1.domain1.com
ErrorLog logs/ error_log
TransferLog logs/ access_log
</VirtualHost>
<VirtualHost *>
DocumentRoot /var/www/html/s2
ServerName s2.domain1.com
ErrorLog logs/error_log
TransferLog logs/access_log
</VirtualHost>
测试虚拟主机配置
[root@server1 conf]# ../bin/httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:* is a NameVirtualHost
default server s1.domain1.com (/usr/local/apache2/conf/httpd.conf:1066)
port * namevhost s1.domain1.com (/usr/local/apache2/conf/httpd.conf:1066)
port * namevhost s2.domain1.com (/usr/local/apache2/conf/httpd.conf:1075)
Syntax OK
说明语法没问题
,
然后在测试机上访问这两个域名
:s1.domain1.com
和
s2.domain1.com
可以看到各自的页面
问题
:
如果以
IP
访问
,
看到的是什么
?
是
s1
的页面
,
注意上面的这段话
*:* is a NameVirtualHost
default server s1.domain1.com
意思十分明显
,
我们在
*:*(apache
监听的任意
IP
任意端口上
)
做了多域名虚拟主机
,
而
s1.domain1.com
是这个缺省的服务器
.
也就是说访问
*:*,
除非访问的是我们设置的域名
,
否则默认会转向到
s1.domain1.com.
2.
基于端口
通过访问同一个
IP(
或者域名
)
的不同端口来访问到不同的文件
对
httpd.conf
做如下修改
增加监听口
Listen 80
Listen 81
将之前做的多域名虚拟主机去掉
(
因为此时是用
IP
加端口来访问的
),
即
# Use name-based virtual hosting.
#
# NameVirtualHost *
注释掉这句话
以下是虚拟主机配置
(
注意下面的配置部分我并没用
ServerName
字段
)
<VirtualHost *:80>
DocumentRoot /var/www/html/s1
ErrorLog logs/error_log
TransferLog logs/ access_log
</VirtualHost>
<VirtualHost *:81>
DocumentRoot /var/www/html/s2
ErrorLog logs/ error_log
TransferLog logs/ access_log
</VirtualHost>
验证虚拟主机配置
[root@server1 conf]# ../bin/httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:80 192.168.0.111 (/usr/local/apache2/conf/httpd.conf:1065)
*:81 192.168.0.111 (/usr/local/apache2/conf/httpd.conf:1074)
Syntax OK
在客户端通过访问
IP:80
和
IP:81
看到不同页面
混合实验
看到这里我们就可以做一个稍微复杂的实验
,
在不同的端口上做不同域名的访问
.
例如
在
80
上访问
s1.domain1.com
和
s2.domain1.com
在
81
上访问
s3.domain2.com
和
s4.domain2.com
当然这样访问是要带端口号的
,
上面因为是
80
默认端口所以不需要写端口号
访问这四个域名
+
端口分别访问到不同的页面
.
配置过程
首先在
bind
上增加两个域名指向服务器
. s3.domain2.com,s4.domain2.com,
增加之后记得要重启
bind.
然后修改
httpd.conf
文件
增加监听口
Listen 80
Listen 81
虚拟主机设置
# Use name-based virtual hosting.
#
NameVirtualHost *:80
NameVirtualHost *:81
表示要在本机的所有
IP
的
80
和
81
上面做多域名
(NameVirtualHost:
即为名称虚拟主机的意思
)
<VirtualHost *:80>
DocumentRoot /var/www/html/s1
ServerName s1.domain1.com
ErrorLog logs/ error_log
TransferLog logs/ access_log
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/html/s2
ServerName s2.domain1.com
ErrorLog logs/ error_log
TransferLog logs/access_log
</VirtualHost>
<VirtualHost *:81>
DocumentRoot /var/www/html/s3
ServerName s3.domain2.com
ErrorLog logs/error_log
TransferLog logs/access_log
</VirtualHost>
<VirtualHost *:81>
DocumentRoot /var/www/html/s4
ServerName s4.domain2.com
ErrorLog logs/error_log
TransferLog logs/access_log
</VirtualHost>
检查虚拟主机设置
root@server1 conf]# /usr/local/apache2/bin/httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
*:83 192.168.0.111 (/usr/local/apache2/conf/httpd.conf:1098)
*:81 is a NameVirtualHost
default server s3.domain2.com
(/usr/local/apache2/conf/httpd.conf:1082)
这句话表示这是访问
81
端口默认访问到
s3
上
(
后面会看到效果
)
port 81 namevhost s3.domain2.com (/usr/local/apache2/conf/httpd.conf:1082)
port 81 namevhost s4.domain2.com (/usr/local/apache2/conf/httpd.conf:1090)
*:80 is a NameVirtualHost
default server s1.domain1.com
(/usr/local/apache2/conf/httpd.conf:1065)
这句话表示这是访问
80
端口默认访问到
s1
上
(
后面会看到效果
)
port 80 namevhost s1.domain1.com (/usr/local/apache2/conf/httpd.conf:1065)
port 80 namevhost s2.domain1.com (/usr/local/apache2/conf/httpd.conf:1073)
Syntax OK
重新启动服务
/usr/local/apache2/apachectl restart
访问测试页面
:
[url]http://s1.domain1.com/[/url]
[url]http://s2.domain1.com/[/url]
注意这两个是默认端口
80
[url]http://s3.domain2.com:81/[/url]
[url]http://s4.domain2.com:81/[/url]
这里是通过不同域名访问
81
注意如果后两个不带端口
,
如直接访问
[url]http://s4.domain2.com[/url]
看到的会是
s1
的页面
,
因为从
80
端口访问默认匹配到第一个虚拟主机了
,
上面说了
s1
是
80
上的默认主机
同样的
,
如果用
80
端口上设的域名访问
81
端口
, [url]http://s1.domain1.com:81/[/url],
则会看到
s3
的页面
.
因为
s3
是
81
上的默认主机
.
3.
基于IP
的虚拟主机
将不同的网站挂在不同的
IP
上
,
访问不同的
IP,
所看到的是不同网站
.
因为一般服务器没那么多公网
IP,
而且大家一般都是用域名访问的
.
所以这个基本没用
.
但是可以用来测试和学习
.
适用环境
:server
上没有配置域名
,
只能用
IP
访问
.
为了实验效果
,
我们先来停掉
DNS
服务
.
首先为服务器增加一个
IP,192.168.0.112
[root@server1 network-scripts]# cp ifcfg-eth0 ifcfg-eth0:0
[root@server1 network-scripts]# vi ifcfg-eth0:0
DEVICE=eth0:0 //
设备名称
ONBOOT=yes //
随系统启动
BOOTPROTO=static
IPADDR=192.168.0.112
//
新设的
IP
NETMASK=255.255.255.0
GATEWAY=192.168.0.1
激活这个设备
[root@server1 network-scripts]# ifdown eth0;ifup eth0
查看当前
ip
设置
[root@server1 network-scripts]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:0A:EB:XX:XX:XX
inet addr:192.168.0.111 Bcast:192.168.0.255 Mask:255.255.255.0
eth0:0 Link encap:Ethernet HWaddr 00:0A:EB:XX:XX:XX
inet addr:192.168.0.112 Bcast:192.168.0.255 Mask:255.255.255.0
ping
这个
112
确实启用成功
.
这样增加
IP
的工作就完成了
,
下面对
httpd.conf
做修改
# Use name-based virtual hosting.
#
#NameVirtualHost *
去掉基于多域名的主机
<VirtualHost 192.168.0.111>
DocumentRoot /var/www/html/s1
# ServerName s1.domain1.com
ErrorLog logs/ error_log
TransferLog logs/ access_log
</VirtualHost>
<VirtualHost 192.168.0.112>
DocumentRoot /var/www/html/s2
# ServerName ss2.domain1.com
ErrorLog logs/ error_log
TransferLog logs/ access_log
</VirtualHost>
注意上面红色的部分
,
由于此时没用多域名所以我将
ServerName
字段去掉了
(
在多端口的时候这样做是可以的
).
但是出现了下面的错误
,
可以看到它是把
IP
作为域名给解析了
.
"httpd.conf" 1157L, 38072C written
[root@server1 conf]# ../bin/httpd -S
[Mon Jul 30 14:09:06 2007] [error] (EAI 2)Name or service not known: Failed to resolve server name for 192.168.0.112 (check DNS) -- or specify an explicit ServerName
[Mon Jul 30 14:09:06 2007] [error] (EAI 2)Name or service not known: Failed to resolve server name for 192.168.0.111 (check DNS) -- or specify an explicit ServerName
VirtualHost configuration:
192.168.0.111:* bogus_host_without_reverse_dns (/usr/local/apache2/conf/httpd.conf:1065)
192.168.0.112:* bogus_host_without_reverse_dns (/usr/local/apache2/conf/httpd.conf:1074)
Syntax OK
下面我们将
ServerName
字段加上去
,
后面的名称我们随意写
<VirtualHost 192.168.0.111>
DocumentRoot /var/www/html/s1
ServerName s1
ErrorLog logs/dbpi_web-error_log
TransferLog logs/dbpi_web-access_log
</VirtualHost>
<VirtualHost 192.168.0.112>
DocumentRoot /var/www/html/s2
ServerName s2
ErrorLog logs/dbpi_web-error_log
TransferLog logs/dbpi_web-access_log
</VirtualHost>
然后再来检查虚拟主机配置
[root@server1 conf]# ../bin/httpd -S
VirtualHost configuration:
192.168.0.111:* s1 (/usr/local/apache2/conf/httpd.conf:1065)
192.168.0.112:* s2 (/usr/local/apache2/conf/httpd.conf:1075)
Syntax OK
在客户机上测试访问
192.168.0.111
和
192.168.0.112
成功
.
个人觉得这应该是一处
bug,
因为在这种情况下并不需要域名访问
,
采用的是完全以实际
IP
进行访问
.
相应的
ServerName
这个字段应该是没有意义的
(
正如多端口时我们这样做
,
完全没问题
).
事实也表明了我们任意起名字也是可以通过的
.
最后说一个
Apache
常常会碰到的问题
启动
apache
时会有警告
httpd: Could not determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
还是能够正常的启动和访问
,
只是有这个问题
.
解决:
#ServerName [url]www.example.com:80[/url]
将这句话修改如下
ServerName 192.168.0.111
当然根据你的实际情况修改为本机的
IP
或者域名
本文出自 “yahoon的小屋” 博客,谢绝转载!