本文介绍如何从头开始为Apache配置多个虚拟主机。
Apache可以通过三种方式实现在同一台物理机上配置多个虚拟主机:
- 基于不同的端口号
- 基于不同的IP地址
- 基于不同的hostname
本文介绍2和3。
注意:本文环境是Suse Linux,安装的Apache也是由Novell公司的Suse源里提供的Apache2.2。Apache的默认配置、文件的路径之类的可能会与其它版本的Apache有所不同,所以此文仅供参考。但是配置方法适用于所有2.2的Apache。
基于IP地址的虚拟主机设置。
假设当前物理机的IP地址是10.52.19.44,我们希望创建20个虚拟主机。这里用两个domain来做例子: www.domain1.com(10.52.19.60), www.domain2.com(10.52.19.61)。步骤如下:
-
为服务器配置虚拟IP。我们的主机上只有一块网卡,配置多个虚拟IP就可以用不同的IP来接收数据包。
vim /etc/sysconfig/network/ifcfg-eth0, 然后更改如下:
BOOTPROTO='static' BROADCAST='' ETHTOOL_OPTIONS='' IPADDR='10.52.19.44/24' GATEWAY='10.52.19.254' MTU='' NAME='' NETWORK='' REMOTE_IPADDR='' STARTMODE='auto' USERCONTROL='no' _nm_name='eth0' IPADDR_0='10.52.19.60' LABEL_0='1' NETMASK_0='255.255.255.0' IPADDR_2='10.52.19.61' LABEL_2='2' NETMASK_2='255.255.255.0'
重启网络服务使设置生效:
service network restart
-
启动Apache的SSL服务。
我们尽量遵守软件提供商希望的方法来配置我们的软件。对这个Apache的版本来说,所有SSL相关的设置都是要配置到
<IfDefine SSL>
标签中,所以只有当这个对应的参数配置过以后,Apache才会启动SSL,否则一切SSL的配置都不会生效。(当然也可以把所有SSL相关的配置都放到这个标签之外,但是这样的话如果我们想禁用SSL就会非常麻烦)vim /etc/sysconfig/apache2,修改如下:
APACHE_SERVER_FLAGS="SSL"
-
创建相关的文件夹:
1) 为我们的Domain创建DocumentRoot文件夹,这里使用脚本test.sh:
#!/bin/bash for i in `cat urls` do mkdir /Apps/$i echo "<h1>Index Page for $i</h1>" > $i/index.html done
需要创建一个名为“urls”的文件并且放到与test.sh相同的路径下:
www.domain1.com www.domain2.com
修改脚本权限,运行:
cd /Apps/ chmod +x test.sh ./test.sh
2) 稍微修改脚本,创建相关的日志文件夹。 (比如把“/Apps“修改为”/Apps/logs“)
-
我们使用自签名证书进行测试。创建自签名证书的方法:
cd /etc/Apache2/SSL/ openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout ssl.key -out ssl.crt
命令执行后会有交互界面输入相关信息,关键的信息是”Common Name“,这儿要填写完整域名(比如www.domain1.com)
-
配置Apache监听的IP和端口:
vim /etc/apache2/listen.conf
Listen 10.52.19.60:80 Listen 10.52.19.61:80 <IfDefine SSL> <IfDefine !NOSSL> <IfModule mod_ssl.c> Listen 10.52.19.60:443 Listen 10.52.19.61:443 </IfModule> </IfDefine> </IfDefine>
-
创建虚拟主机,这里使用脚本:
1) 创建一个虚拟主机的模板,命名为”temp“放到/etc/apache2/vhost.d/。
<VirtualHost 10.52.19.60:80> ServerName www.domain.comwww.domain.com:80 DocumentRoot /Apps/www.domain.com ErrorLog /Apps/logs/www.domain.com/error_log LogLevel warn CustomLog /Apps/logs/www.domain.com/access_log combined RewriteEngine on </VirtualHost> <IfDefine SSL> <IfDefine !NOSSL> <VirtualHost 10.52.19.60:443> DocumentRoot /Apps/www.domain.com ServerName www.domain.com:443 ErrorLog /Apps/logs/www.domain.com/error_log TransferLog /Apps/logs/www.domain.com/access_log SSLEngine on # 4 possible values: All, SSLv2, SSLv3, TLSv1. Allow TLS only: SSLProtocol all -SSLv2 -SSLv3 # "openssl ciphers -v" for a complete list of ciphers that are # available. SSLCipherSuite ALL:!aNULL:!eNULL:!SSLv2:!LOW:!EXP:!MD5:@STRENGTH SSLCertificateFile /etc/apache2/SSL/ssl.crt #SSLCertificateFile /etc/apache2/ssl.crt/server-dsa.crt SSLCertificateKeyFile /etc/apache2/SSL/ssl.key #SSLCertificateKeyFile /etc/apache2/ssl.key/server-dsa.key #SSLCertificateChainFile /etc/apache2/ssl.crt/ca.crt #SSLCACertificatePath /etc/apache2/ssl.crt #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt #SSLCARevocationPath /etc/apache2/ssl.crl #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl #SSLVerifyClient require #SSLVerifyDepth 10 <Files ~ "\.(cgi|shtml|phtml|php3?)$"> SSLOptions +StdEnvVars </Files> <Directory "/srv/www/cgi-bin"> SSLOptions +StdEnvVars </Directory> CustomLog /Apps/logs/www.domain.com/ssl_request_log ssl_combined </VirtualHost> </IfDefine> </IfDefine>
2) 在同一个文件夹下创建文件”urls”,内容如下:
www.domain1.com 10.52.19.60 www.domain2.com 10.52.19.61
3) 建立一个脚本(test.sh),内容如下:
#!/bin/bash while read line do ##提取出domain name HOST=`echo $line | awk '{print $1}'` ##提取出对应的IP IP=`echo $line | awk '{print $2}'` ##修改虚拟主机中的domain name和IP,然后建立对应的虚拟主机配置文件 sed -e 's/10.52.19.60/'$IP'/g' -e 's/www.domain.com/'$HOST'/g' temp > vhost-$HOST.conf echo "Virtual Host for $HOST has been created!" done < urls
4) 脚本加权限执行:
cd /etc/apache/vhost.d/ chmod +x test.sh ./test.sh
-
重启Apache服务:
service apache2 restart
如何测试虚拟主机是否生效:
在测试的PC上,打开浏览器输入对应的IP地址,看看会不会跳转到对应的index.html页面
基于hostname的虚拟主机设置。
假设当前物理机的IP地址是10.52.19.44,我们希望创建20个虚拟主机。这里用两个domain来做例子。虚拟主机拥有不同的主机名,但是我们希望用同一个IP。 例如:www.domain1.com(10.52.19.44), www.domain2.com(10.52.19.44),我们希望通过www.domain1.com访问Apache服务器的时候,用户访问到domain1的所有文件;通过www.domain2.com访问Apache服务器的时候,用户访问到domain2的所有文件。
为了可以方便地批量创建虚拟主机,我写了一个脚本实现所有功能。首先可以看看我们文件夹下面的所有文件列表:
/tmp/configure # ls -R
.:
SSL test.sh urls vhost-temp
./SSL:
www.domain1.com www.domain2.com
./SSL/www.domain1.com:
ssl.crt ssl.key
./SSL/www.domain2.com:
ssl.crt ssl.key
test.sh内容如下:
#!/bin/bash
## Define variables
today=`date +"%Y%m%d"`
ipaddr=`ifconfig eth0 | grep "inet addr" | awk -F ":" '{print $2}' | awk '{print $1}'`
## Make the required directories and copy required files
mkdir /Apps/logs/
mkdir /etc/apache2/backup_$today
cp -r SSL/ /etc/apache2/
cp httpd.conf /etc/apache2/
for i in `cat urls`
do
mkdir /Apps/$i
mkdir /Apps/logs/$i
echo "<h1>Index Page for $i</h1>" > /Apps/$i/index.html
sed -e 's/www.domain.com/'$i'/g' vhost-temp > /etc/apache2/vhosts.d/vhost-$i.conf
echo "Virtual Host for $i has been created!"
done
## Backup the modified files
cd /etc/apache2
cp httpd.conf backup_$today
cp listen.conf backup_$today
##Change listen.conf
echo "NameVirtualHost $ipaddr:80" >> listen.conf
echo "NameVirtualHost $ipaddr:443" >> listen.conf
sed -i -e 's/Listen 80/Listen '$ipaddr':80/g' -e 's/Listen 443/Listen '$ipaddr':443/g' listen.conf
##Restart service
service apache2 restart
urls:
www.domain1.com
www.domain2.com
vhost-temp:
<VirtualHost 10.52.19.44:80>
ServerName www.domain.com
DocumentRoot /Apps/www.domain.com
ErrorLog /Apps/logs/www.domain.com/error_log
LogLevel warn
CustomLog /Apps/logs/www.domain.com/access_log combined
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD|POST)$
RewriteRule .* - [F]
#RewriteCond %{SERVER_PORT} !^443$
#RewriteRule ^/(.*)$ https://%{SERVER_NAME}/$1 [L,R]
RewriteRule ^/$ http://%{SERVER_NAME}/index.html
</VirtualHost>
<IfDefine SSL>
<IfDefine !NOSSL>
<VirtualHost 10.52.19.44:443>
ServerName www.domain.com
DocumentRoot /Apps/www.domain.com
ErrorLog /Apps/logs/www.domain.com/error_log
TransferLog /Apps/logs/www.domain.com/access_log
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(GET|HEAD|POST)$
RewriteRule .* - [F]
#RewriteCond %{SERVER_PORT} !^443$
#RewriteRule ^/(.*)$ https://%{SERVER_NAME}/$1 [L,R]
RewriteRule ^/$ https://%{SERVER_NAME}/index.html
SSLEngine on
# 4 possible values: All, SSLv2, SSLv3, TLSv1. Allow TLS only:
SSLProtocol all -SSLv2 -SSLv3
# "openssl ciphers -v" for a complete list of ciphers that are
# available.
SSLCipherSuite ALL:!aNULL:!eNULL:!SSLv2:!LOW:!EXP:!MD5:@STRENGTH
SSLCertificateFile /etc/apache2/SSL/www.domain.com/ssl.crt
#SSLCertificateFile /etc/apache2/ssl.crt/server-dsa.crt
SSLCertificateKeyFile /etc/apache2/SSL/www.domain.com/ssl.key
#SSLCertificateKeyFile /etc/apache2/ssl.key/server-dsa.key
#SSLCertificateChainFile /etc/apache2/ssl.crt/ca.crt
#SSLCACertificatePath /etc/apache2/ssl.crt
#SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt
#SSLCARevocationPath /etc/apache2/ssl.crl
#SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl
#SSLVerifyClient require
#SSLVerifyDepth 10
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>
<Directory "/srv/www/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
CustomLog /Apps/logs/www.domain.com/ssl_request_log ssl_combined
</VirtualHost>
</IfDefine>
</IfDefine>
加权限执行test.sh即可。
如何测试虚拟主机是否工作正常:
在测试用的PC上添加如下内容到hosts文件(C:\Windows\System32\drivers\etc\hosts for Windows, /etc/hosts for Lunix/Max)
10.52.19.44 www.domain1.com
10.52.19.44 www.domain2.com
随后打开浏览器,访问对应的域名,查看是否访问到对应域名下的文件
基于端口的虚拟主机设置与基于IP的很类似,只要修改一下监听的端口和虚拟主机中的相关配置即可。