Apache HTTP配置虚拟主机(二)

本文详细介绍如何在Apache中配置和使用CGI提供动态内容,包括启用CGI、ScriptAlias的使用及安全实践。同时,深入探讨大规模动态虚拟主机的配置方法,利用mod_vhost_alias实现高效、灵活的主机管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


建议先了解一下上一篇文章 Apache HTTP配置虚拟主机(一)

1. 使用CGI提供动态内容

    CGI(通用网关接口)为Web服务器定义了一种与外部内容生成程序进行交互的方式,这些程序通常称为CGI程序或CGI脚本。这是在网站上放置动态内容的最简单,最常见的方法。

1.1 配置Apache启用CGI

    如果Apache是​​使用共享模块支持构建的,则需要确保已加载该模块。在httpd.conf中,需要确保该 LoadModule 指令未被注释掉:
    LoadModule cgid_module modules/mod_cgid.so
    在Windows上,或使用非线程MPM(例如prefork),正确配置的指令如下所示:
    LoadModule cgi_module modules/mod_cgi.so
    因为我使用系统默认的配置,所以httpd使用prefork,使用 cgi_module 模块,没有使用cgid_module模块。

# httpd -V
Server version: Apache/2.2.15 (Unix)
...
Server MPM:     Prefork
# httpd -t -D DUMP_MODULES
...
cgi_module (shared)
1.1.1 ScriptAlias

    ScriptAlias将URL映射到文件系统位置,并将目标指定为CGI脚本。句法为:

ScriptAlias URL-path file-path|directory-path

    句法中的URL-path将被映射到以第二个参数开头的脚本,该参数是本地文件系统中的完整路径名。
示例:

ScriptAlias /cgi-bin/ /web/cgi-bin/

    注意:/web/cgi-bin/最后的斜杠不能少!否则无法定位到该目录下的程序!
    一个指向 http://example.com/cgi-bin/foo 的请求将会使服务器运行脚本 /web/cgi-bin/foo。此配置实质上等效于:

Alias /cgi-bin/ /web/cgi-bin/
<Location /cgi-bin >
  SetHandler cgi-script
  Options +ExecCGI
</Location>

    Alias 和 ScriptAlias 通常用于 DocumentRoot 目录之外的目录,它们之间的区别就是 ScriptAlias 有附加含义,即该URL前缀下的所有内容都将被视为CGI程序。
    最好避免将CGI脚本放置在 DocumentRoot(即网站根目录),以免在配置发生更改时意外泄露源代码。如果确实需要将CGI脚本放在可从Web访问的目录中,请不要使用 ScriptAlias,而是使用<Directory>,SetHandler和,Options,如:

<Directory /usr/local/apache2/htdocs/cgi-bin >
  SetHandler cgi-script
  Options ExecCGI
</Directory>

    这是必要的,因为多个URL路径可以映射到相同的文件系统位置,如果它们不受<Directory>的限制,则有可能绕过 ScriptAlias 并暴露CGI脚本的源代码。

1.1.2 ScriptAlias目录之外的CGI

    出于安全原因,CGI程序通常仅限于ScriptAlias目录。这样,管理员可以严格控制允许谁使用CGI程序。但是,如果采取了适当的安全预防措施,则可以从任意目录运行CGI程序。例如,您可能希望使用UserDir指令让用户在其主目录中拥有Web内容 。如果他们想拥有自己的CGI程序,但无权访问主cgi-bin目录,则他们将需要能够在其他地方运行CGI程序。
    允许在任意目录中执行CGI有两个步骤。首先,必须使用AddHandler或SetHandler指令激活cgi脚本。以下AddHandler指令告诉服务器将带有cgi或pl扩展名的所有文件视为CGI程序。

AddHandler cgi-script .cgi .pl

    其次, 必须在Options指令中指定ExecCGI。下面的指令告诉Apache允许执行CGI文件。

<Directory /usr/local/apache2/htdocs/somedir>
  Options +ExecCGI
</Directory>

    示例,允许CGI程序执行用户目录下以.cgi结尾的任何文件 ,可以使用以下配置:

<Directory /home/*/public_html>
  Options +ExecCGI
  AddHandler cgi-script .cgi
</Directory>

    如果希望指定一个用户目录的cgi-bin子目录,其中所有内容都将被视为cgi程序,则可以使用以下命令:

<Directory /home/*/public_html/cgi-bin>
  Options ExecCGI
  SetHandler cgi-script
</Directory>
1.2 编写CGI程序

    ``常规’'编程和CGI编程之间有两个主要区别。首先,CGI程序的所有输出内容必须在MIME-type报头之后,这个HTTP类型的报头告诉客户端它正在接收哪种内容。大多数时候,这看起来像:

Content-type: text/html

    其次,输出必须为HTML或浏览器将能够显示的其他格式。大多数情况下是HTML,但有时可能会编写一个CGI程序来输出gif图像或其他非HTML内容。

1.2.1 第一个CGI程序

    输入以下内容,将其保存到名为的文件中first.pl,并将其放在 cgi-bin目录中。

#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, World.";

    第一行告诉apache,需要使用perl来解释这个程序;第二行打印报文的内容类型声明,然后是两个回车换行符对。这将在报头后放置一个空行,以指示HTTP报头的结尾和正文内容的开头;第三行打印内容。
该脚本用浏览器打开如下所示:
在这里插入图片描述
    如果报错,检查一下,确认赋予程序执行权限,并尝试在命令行运行:

# ./first.pl 
Content-type: text/html

Hello, World.

2. 动态配置的大规模虚拟主机

2.1 动态虚拟主机的产生

    如果httpd.conf包含许多 <VirtualHost>基本相同的部分,则此处介绍的技术很有用 。例如有3台虚拟主机,其配置文件位于/etc/httpd/conf.d,内容如下:

# cat virtualhost.conf 
<VirtualHost 192.168.198.133>
    ServerName                 customer-1.example.com
    DocumentRoot        "/www/hosts/customer-1.example.com/docs"
    ScriptAlias  "/cgi-bin/"  "/www/hosts/customer-1.example.com/cgi-bin/"
</VirtualHost>

<VirtualHost 192.168.198.133>
    ServerName                 customer-2.example.com
    DocumentRoot        "/www/hosts/customer-2.example.com/docs"
    ScriptAlias  "/cgi-bin/"  "/www/hosts/customer-2.example.com/cgi-bin/"
</VirtualHost>

<VirtualHost 192.168.198.133>
    ServerName                 customer-3.example.com
    DocumentRoot        "/www/hosts/customer-3.example.com/docs"
    ScriptAlias  "/cgi-bin/"  "/www/hosts/customer-3.example.com/cgi-bin/"
</VirtualHost>

    通过上文,我们知道ScriptAlias将访问响应目录下的CGI程序并返回运行结果。我们把上文的first.pl改动一下,分别放到3台主机相应文件夹:

# cat /www/hosts/customer-1.example.com/cgi-bin/test.pl  
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, customer-1.example.com.";
# cat /www/hosts/customer-2.example.com/cgi-bin/test.pl  
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, customer-2.example.com.";
# cat /www/hosts/customer-3.example.com/cgi-bin/test.pl  
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, customer-3.example.com.";

    在每个虚拟主机根目录下新建index.html,重新加载httpd,使用浏览器访问http://customer-1.example.com和http://customer-1.example.com/cgi-bin/test.pl,可以看到环境以及ok了。
    如果有大量配置相似的虚拟主机,我们希望<VirtualHost>用一种动态解决这些问题的机制来替换这些多个 模块。这具有许多优点:

  • 配置文件会变小,因此Apache启动速度更快,并且使用的内存更少。也许更重要的是,较小的配置更易于维护,并且留出更少的错误空间。
  • 添加虚拟主机仅需在文件系统中创建适当的目录,并在DNS中创建相应解析即可,无需重新配置或重新启动Apache。
    主要缺点是每个虚拟主机不能有不同的日志文件。不过我们可以用上一节介绍的split-logfile脚本将日志按照虚拟主机进行拆分。
2.2 动态虚拟主机的实现基础

    虚拟主机由两部分信息定义:其IP地址和HTTP请求中Host:报头的内容。Host:报头类似:

# curl -v http://www.baidu.com
* About to connect() to www.baidu.com port 80 (#0)
...
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: www.baidu.com

    为了使动态虚拟主机看起来像普通主机,需要从HTTP请求中确定几件事。最重要的是服务器名称,运行时使用的实际值由 UseCanonicalName 设置控制。配置为 UseCanonicalName Off,服务器名称取自Host:报头的内容。用UseCanonicalName DNS,它取自虚拟主机IP地址的反向DNS查找。前一种设置用于基于名称的动态虚拟主机,而后一种设置用于基于IP的主机。如果httpd因为没有Host:报头而无法计算出服务器名称,或者DNS查找失败,那么将ServerName配置为服务器名称。
    要确定的另一件事是文档根目录。在正常配置中,核心模块使用DocumentRoot将URI映射到文件名,DocumentRoot通过DOCUMENT_ROOT环境变量使用CGI脚本;在使用动态虚拟主机时,该工作必须由另一个模块(mod_vhost_alias或 mod_rewrite)接管,这两个模块都不负责设置DOCUMENT_ROOT环境变量,因此需要设置动态虚拟主机的根目录。

2.3 使用mod_vhost_alias的动态虚拟主机

    本示例使用mod_vhost_alias将2.1节的3台虚拟主机配置为动态虚拟主机。在httpd.conf中进行如下配置:

# get the server name from the Host: header
UseCanonicalName Off

# this log format can be split per-virtual-host based on the first field
# using the split-logfile utility.
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog "logs/access_log" vcommon

# include the server name in the filenames used to satisfy requests
VirtualDocumentRoot "/www/hosts/%0/docs"
VirtualScriptAlias  "/www/hosts/%0/cgi-bin"

    变量 %0 表示引用HTTP请求的服务器名,如 Host:报文所示。移除原虚拟主机配置,重新加载httpd,即可验证。
在这里插入图片描述
    注意:确保注释掉httpd.conf中/cgi-bin/的配置,否则脚本请求会被转发到/var/www/cgi-bin目录下,导致实验失败。

<IfModule alias_module>
    ...
    #ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>

    个人感觉动态虚拟主机在实际生产环境中应用比较少,所以就写到这吧。

参考文档

http://httpd.apache.org/docs/2.2/vhosts/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值