3.4 配置Apache服务器
前面已经提到,Apache通过三个配置文件完成几乎所有的配置。这三个文件分别为:
● httpd.conf:主要的Web服务器配置;
● access.conf:访问限制和安全;
● srm.conf:MIME与文件关联。
图3.2 在Mozilla下看到的Apache服务器的初始页面
从传统上说,Apache从三个文件中读取服务器运行配置。而从Apache版本1.3.4开始,服务器运行配置只存储在一个文件中(httpd.conf文件)。其他文件仍然存在,但是只包含注释,告诉用户该文件只是由于历史原因而保留,应该将所有配置放入httpd.conf文件。但是,随Red Hat Linux 6.0发售的1.3.6版本中,配置文件仍旧拆分为三个文件。本书就假设把Apache的所有配置信息默认为全部放置在httpd.conf一个文件中。
★ 注意 ★
如果愿意,仍然可以使用三个配置文件的方案。但是,这三个文件之间的设置差异经过这么多年后已经变得非常模糊。
当Apache进程启动或者重新启动时,该进程从配置文件中读取数据。使用httpd reload命令可以使Apache进程重新装载配置信息。
3.4.1 httpd.conf文件中的全局配置选项
httpd.conf文件是Apache的主配置文件,其中包含大量的Apache的配置选项,比较常用的配置选项如表3-3所示:
表3-3 httpd.conf文件中的主要配置参数
下面详细介绍httpd.conf文件中常用的配置参数。
1.ServerType指令
ServerType指令指示服务器的类型。服务器有两种类型:standalone和xnetd。将其设置为standalone表示服务器启动一个服务进程时刻等待用户HTTP请求,当用户的请求响应后该进程并不消亡。当Server-Type设置为xinetd时,对于任何传入的HTTP请求,产生一个新的服务器,该服务器在请求服务完成以后立即消亡。这可能在测试配置更改方面有用。因为每次产生一个新的服务器时都要重新装载配置文件。当然该操作非常慢,因为对于每个请求都有服务器启动的开销。
2.ServerRoot指令
用来设置服务器目录的绝对路径,它通知服务器到哪个位置查找所有的资源和配置文件。在配置文件中所指定的资源,有许多是相对于ServerRoot目录的。如果从RPM安装则ServerRoot指令设置为/etc/httpd,如果从源代码安装则为/usr/local/apache。
3.Port指令
指定服务器运行在哪个端口上。默认为80,这是标准的HTTP端口号。用户在某些特定情况下可能要让服务器运行在另外的端口上,例如当用户想要运行一个测试服务器而不希望其他人知道时,这时候可以指定服务器侦听非80端口。有些版本用Listen指令完成该配置。修改httpd.conf里面关于Listen的选项,例如:
Listen 8000指令就是使Apache监听8000端口。而如果要同时指定监听端口和监听地址,可以使用:
Listen 15.2.49.1:80 Listen 15.2.49.2:8000
这样就使得Apache同时监听在15.2.49.1的80端口和15.2.49.2的8000端口。
4.User和Group指令
用来设置用户ID和组ID,服务器将使用它们来处理请求。通常保留这两个设置的默认值:nobody和nogroup,并且分别在对应的/etc/passwd和/etc/group文件中验证它们(由于它们是由RedHatLinux提供的,因此它们已经被定义)。如果想使用其他的UID或GID,可以对默认设置进行修改,但是要知道,服务器将以在这里定义的用户和组的权限开始运行。这表明,假如有一个安全性的漏洞,不管是在服务器上,还是在自己的CGI程序中,这些程序都将以指定的UID运行。如果服务器以root或其他一些具有特权的用户的身份运行,那么某些人就可以利用这些安全性的漏洞对站点做一些危险的操作。除了使用名字来指定User和Group指令外,还可以使用UID和GID编号来指定它们。如果使用编号,一定要确保所指定的编号与想要指定的用户号和组号一致,并且要在编号前面加上符号#。
5.ServerAdmin指令
应该被设置为管理服务器的Web管理人员的地址,它应该是一个有效的E-mail地址或别名,如webmaster@yourserver.com。把这一值设置为一个有效的地址十分重要,因为当服务器出现问题时,这一地址将被返回给访问者。
6.ServerName指令
用来设置服务器将返回的主机名,它应该被设置为一个完全限定的域名。例如,将它设置为www.yourserver.com而不是简单的www。如果服务器通过Internet访问而不是仅仅在局域网中访问,该设置尤为重要。实际上不需要设置该值,除非需要返回的不是该计算机的规范名字。如果不设置该值,服务器将自行判定这一名字并把它设置为服务器的规范名字。但是,用户若想让服务器返回比较友好、易记的地址,如www.your.domain。但是不管怎样,ServerName应该是网络的一个真正的域名系统(DNS)的名字。如果用户正在管理自己的DNS,则记住需要为主机添加一个别名。
7.DocumentRoot指令
设置为文档目录树的绝对路径,该路径是Apache提供文件的顶级目录。在默认情况下,它被设置为/home/httpd/html;如果是用户自己构造代码,它设置为/usr/local/apache/htdocs。在版本1.3.4以前,该指令出现在srm.conf文件中。例如如果设置DocumentRoot为/webpage/main,那么当访问http://localhost/index.html时实际就是访问/webpage/main目录下的index.html文件。
8.UserDir指令
定义和本地用户的主目录相对的目录,可以将公共的HTML文档放入该目录中。说是相对目录是因为每个用户都有自己的HTML目录。该指令默认的设置为public_html。因此,每个用户在自己的主目录下都能够创建称为public_html的目录,在该目录下的HTML文档可以通过http://servername/~username访问。这里username是特定用户的名称。在版本1.3.4以前,该指令出现在srm.conf文件中。
9.DirectoryIndex指令
指明作为目录索引的文件名,例如,当请求的URL为http://www.server.com/Directory/时,指明哪个文件作为目录的索引。通常在这里放入许多文件非常有用,这样当index.html (默认的值)找不到时,可以使用另一个文件替换。该指令最有用的应用是在目录中有一个CGI程序运行,作为默认的动作。在这种情况下,该指令类似于DirectoryIndexindex. htmlindex.cgi。在版本1.3.4以前,该指令出现在srm.conf文件中。
10.TimeOut指令
在httpd.conf文件里可设置网络超时时间,其命令格式为TimeOut n。其中n为整数,单位是秒。
11.MaxSpareServers指令
设置Apache的最大空闲进程数。命令格式如下:
MaxSpareServers 30
上述指令表明:当空闲进程超过30个的时候,Apache主进程会杀掉多余的空闲进程而保持空闲进程为30个以节省系统资源。非常繁忙的站点调节这个参数才是必要的,但是在任何时候把这个参数调到很大都不是一个好办法。同时也可以设置类似参数MinSpareServers来限制最少空闲进程数目来加快反应速度。
12.StartServers指令
指明启动Apache后等待接受请求的空闲子进程数量。
13.MaxKeepAliveRequests指令
设置每个连接的最大请求数。用法如下:MaxKeepAliveRequests 100这样就能保证在一个连接中,如果同时请求数达到100就不再响应这个连接的新请求,保证了系统资源不会被某个连接大量占用。但是在实际配置中要求尽量把这个数值调高来获得较高的系统性能。
14.KeepAlive和KeepAliveTimeout指令
设置session的持续时间,例如以下两个设置:
KeepAlive on KeepAliveTimeout 15
这样就能限制每个session的保持时间是15秒钟。session的使用可以使得很多请求都可以通过同一个TCP连接来发送,节约了网络资源和系统资源。
15.HostnameLookups指令
设置Apache对客户端进行域名验证。该参数可以设置on、off或double。如果是使用on,那么只有进行一次反查;如果用double,那么进行反查之后还要进行一次正向解析,只有两次的结果互相符合才行;而off就是不进行域名验证。如果为了安全,建议使用double;为了加快访问速度,建议使用off。
16.BindAddress指令
设置Apache只在特定的IP地址监听,从而只响应特定IP地址的HTTP请求。
17.LimitRequestBody指令
设置HTTP请求的消息主体的大小,单位为字节。CGI脚本一般把表单里中的内容作为消息的主体提交给服务器处理,所以现在消息主体的大小在使用CGI的时候很有用。例如使用CGI来上传文件时,如果有如下设置:LimitRequestBody 102400,那么上传文件超过100k的时候就会报错。
18.MaxClients指令
设置Apache的最大连接数。
3.4.2 .htaccess文件和访问限制
任何出现在配置文件httpd.conf中的指令都可能出现在.htaccess文件中。该文件在httpd.conf文件的AccessFileName指令中指定,用于进行针对单一目录的配置。作为系统管理员,可以指定该文件的名字和可以通过该文件内容覆盖的服务器配置。当站点有多组内容提供者并希望控制这些用户对他们的空间进行操作时该指令非常有用。例如,httpd.conf文件中下面部分指出了AccessFileName参数的值:
//AccessFileName: The name of the file to look for in each directory //for access control information. See also the AllowOverride directive. // AccessFileName .htaccess
要限制.htaccess文件能够覆盖的内容,需要使用AllowOverride指令。该指令可以进行全局设置或者单个目录设置。要配置默认可以使用的选项,需要使用Options指令。
例如,在httpd.conf文件中,可以见到如下清单:
# # Aliases: Add here as many aliases as you need(with no limit). The format # is Alias fakename realname # # Note that if you include a trailing / on fakename then the server will # require it to be present in the URL. So "/icons" isn't aliased in this # example, only "/icons/". If the fakename is slash-terminated, then the # realname must also be slash terminated, and if the fakename omits the # trailing slash, the realname must also omit it. # # We include the /icons/ alias for FancyIndexed directory listings. If you # do not use FancyIndexing, you may comment this out. # Alias /icons/ "/var/www/icons/" <Directory "/var/www/icons"> Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all </Directory>
1.Options指令
Options可以为None、All或者任何Indexes、Includes、FollowSymLinks、ExecCGI或者MultiViews的组合。MultiViews不包含在All中,必须显式指定。这些选项解释如下。
● None:该目录没有启用任何可用的选项。
● All:该目录启用了所有选项,除了MultiViews。
● Indexes:当Index.html文件或者另一个DirectoryIndex文件不存在时,目录中的文件列表将作为HTML页产生,显示给用户。
● Includes:该目录允许服务器侧包含(SSI)。如果允许包含但是不允许在包含中有exec选项,则可以写为IncludesNoExec。基于安全的原因,对于没有完全控制权限的目录,如UserDir目录,该选项是一个很好的主意。
● FollowSymLinks:允许访问符号链接到文档目录的目录。这种方法不好,不要将整个服务器全部设置为该选项。对某个目录可以这样设置,但是在仅当有足够的理由时才这样设置。该选项是一个潜在的安全隐患,因为允许Web用户跳出文档目录以外,并且可能潜在地允许用户访问文件系统的分区,而这些地方是不希望其他人访问的。
● ExecCGI:即使该目录不是ScriptAlias化的目录,也在其中允许CGI程序。
● MultiViews:该选项是mod_negotiation模块的一部分。当客户请求的文档没有找到时,服务器试图计算最适合客户请求的文档。
2.AllowOverrides指令
AllowOverrides指令指定.htaccess文件可以覆盖的选项。可以对每个目录进行设置。例如,可以对主要文档root和UserDir目录的覆盖有不同的标准。该功能对于用户目录特别有用,在这些目录中用户没有访问主服务器配置文件的权限。
AllowOverrides可以设置为All或者Options.htaccess、FileInfo.htaccess、AuthConfig. htaccess以及Limit.htaccess选项的组合。这些选项含义如下。
● All:表示不读取.htaccess文件配置内容。
● Options.htaccess:文件可以为该目录添加没有在Options指令中列出的选项。
● FileInfo.htaccess:文件包含修改文档类型信息的指令。
● AuthConfig.htaccess:文件可能包含验证指令。
● Limit.htaccess:文件可能包含allow、deny、order指令。
3.order指令
order只能设置为Order allow,deny或Orderdeny,allow,表明用户是先设置允许的访问地址还是先设置禁止访问的地址。
4.allow指令
指明允许访问的地址或地址序列。如allow from all指令表明允许所有IP来的访问请求。
5.deny指令
指明禁止访问的地址或地址序列。如deny from all指令表明禁止所有IP来的访问请求。
★ 注意 ★
在版本1.3.4以前,对.htaccess文件的配置出现在access.conf文件中。
3.4.3 httpd.conf文件中的CGI设置
用HTML编写的网页只是静态网页,而用户若想与Web服务器交互,则可以采用CGI的形式。CGI(Common Gateway Interface),即公用网关接口。简单地说,就是运行在Web服务器上的程序。CGI脚本有两种使用方法:作为一个表单的Action调用和作为一个网页URL点击调用。
1.表单的Action调用CGI程序
例如图3.3所示的表单,要求用户输入姓名和身份证号码。
图3.3 一个实际的表单
图3.3所示的表单对应的HTML语句如下:
<form method="POST" action="/cgi-bin/login"> 姓 名:<input type="text" name="T1" size="20"><br> 身份证号码:<input type="text" name="T2" size="20"><br> <input type="submit" value="提 交" name="B1"> <input type="reset" value="重 写" name="B2"></p> </form>
其中,action指示该表单提交后将交给/cgi-bin/login程序处理。这里/cgi-bin/login就是一个CGI程序。
2.基于URL链接的CGI程序
其HTML语句如下:
<body> <a href="/cgi-bin/displaytime">显示服务器时间</a> </body>
同时displaytime文件的脚本如下:
#!/bin/sh echo Content-type: text/plain //告诉浏览器显示文本的类型 echo /bin/date //显示Linux系统时钟
那么单击【显示服务器时间】超级链接后,系统将显示类似于“Tue Jul 08 16:15:57 EDT 2005”的系统时间,如图3.4所示。
要想让Apache服务器具有如上动态显示内容的功能,就必须设置好服务器的CGI目录。在httpd.conf文件中,可以看到如下语句:
<Directory "/var/www/cgi-bin"> AllowOverride None Options ExecCGI </Directory>
图3.4 显示服务器时间的超级链接
这就是设置CGI目录的语句。Options参数设置为ExecCGI表示该目录允许执行CGI程序。CGI程序可以是任意语言编写的可执行程序,包括PHP,JSP等网页制作语言程序,也可以是C语言源代码编译产生的可执行程序。当然用得最多的CGI程序还是C语言程序和Perl脚本程序。
★ 注意 ★
CGI目录及该目录下所有可执行程序必须是任何可执行的,否则用户通过浏览器访问网页时不能正确执行该CGI程序。用chmod命令将文件属性改为755即可。
3.4.4 httpd.conf文件中的URL路径名设置
用户在浏览器中输入一个URL,例如www.server.com,该URL对应的Web服务器将返回一个页面。这个过程如下:
(1)用户输入一个合法的URL;
(2)服务器根据其配置,找到一个与此URL对应的文件;
(3)服务器将该文件返回给用户浏览器;
(4)用户浏览器根据返回的文件解析并显示。
这里涉及一个由URL转换为服务器上某个文件的问题,这个问题是由Web服务器根据具体配置完成的。本节主要介绍在Apache里如何根据URL地址定位文件在文件系统中的位置。URL地址定位涉及Apache中如表3-4所示的模块和指令:
表3-4 URL定位涉及的主要模块和指令
1.DocumentRoot
Apache根据请求定位文件的默认操作是,取出URL路径(即URL中的主机名和端口部分)附加到由DocumentRoot指定的文件系统路径后面,组成在网上所看见的文件树结构。
如果服务器由多个虚拟主机,则Apache会用各虚拟主机自己的DocumentRoot来组成文件系统路径;还可能根据由mod_vhost_alias提供的指令动态地针对所请求的地址或端口定位文件。
2.DocumentRoot以外的文件
实际应用中,经常有必要允许网络对DocumentRoot以外的文件进行访问。对此,Apache提供了多种方法。在Linux系统中,可以在文件系统的DocumentRoot目录下安置符号链接(也称为软链接)以访问其外部文件,考虑到安全问题,这种方法仅在相应目录的Options中设置了FollowSymLinks或SymLinksIfOwnerMatch时才有效。
另一种方法是,使用Alias指令可以映射文件系统的任何部分到网络空间中。例如下面的命令
Alias /docs /var/web
可以把URLhttp://www.example.com/docs/dir/file.html映射为/var/web/dir/file.html。ScriptAlias指令功能相似,而且使所有目标路径下的所有文件被视为CGI脚本。
AliasMatch和ScriptAliasMatch指令可以实现基于正则表达式的匹配和替换,以提供更大的灵活性。例如:
ScriptAliasMatch ^/~([a-zA-Z0-9]*)/cgi-bin/(.*)/home/$1/cgi-bin/$2
上述命令可以映射http://example.com/~user/cgi-bin/script.cgi为/home/user/cgi-bin/script. cgi,并视之为CGI脚本。
3.用户目录
在Linux系统中,一个特定用户user的主目录通常是~user/。模块mod_userdir在网络上沿用了这个概念,允许使用URL访问位于各用户主目录下的文件,例如:
http://www.example.com/~user/file.html
出于安全原因,不应该给予网络用户直接操作主目录的权限,而应该在用户主目录下建一个新目录,把网络文件放在新目录中,并用UserDir指令告诉服务器。默认的用户目录设置是Userdir public_html,因此,上述例子中的URL会映射到/home/user/public_html/file.html,其中/home/user/是/etc/passwd指定的用户主目录。当/etc/passwd没有指定主目录,那就要用到Userdir指令的另几种形式。
有些用户觉得符号“~”(时常会被编码为%7e)很别扭,希望用其他形式来表达用户目录。虽然模块mod_userdir并不支持,但是,如果合理规划服务器上的用户目录,则还是有可能用AliasMatch指令来达到这个目的。例如,如果希望http://www.example.com/upages/user/file.html映射到/home/user/public_html/file.html,可以这样使用AliasMatch指令:
AliasMatch ^/upages/([a-zA-Z0-9]*)/?(.*)/home/$1/public_html/$2
4.URL的重定向
上述指令都指示Apache返回给客户文件系统的某个特定内容,但是有时候,需要通知客户其请求的内容位于其他URL,并使客户产生新的对其他URL的请求,这种机制称为“重定向(redirection)”,可以用Redirect指令实现。例如:如果DocumentRoot的目录/foo/被转移到了/bar/,则可以这样引导客户访问新的位置:
Redirect permanent/foo/http://www.example.com/bar/
这个命令重定向任何以/foo/开头的URL路径到位于同一个服务器www.example.com的/bar/。当然,可以重定向到任何服务器,而不仅仅是原来的那个服务器。
Apache还提供了RedirectMatch指令来解决复杂的重定向问题。例如,要重定向对站点主页的请求到其他站点,而保留其他所有请求,可以这样配置:
RedirectMatch permanent ^/$ http://www.example.com/startpage.html
另一种方法是,暂时地重定向站点的所有页面到一个特定页面,如:
RedirectMatch temp .* http://www.example.com/startpage.html
5.反向代理
Apache还允许将远程文档纳入到本地服务器的网络空间,由于Web服务器从远程服务器取得文档并返回给客户,在其中扮演了一个代理服务器的角色,所以这种机制被称为反向代理(reverse proxying),不同于标准代理的是:在客户看来,他请求的文档似乎原本就位于这个反向代理服务器上。
下例演示了当客户请求位于/foo/目录下的文档时,服务器从internal.example.com的/bar/目录下取回文档并返回给客户,似乎文档原本就在本地服务器上
ProxyPass /foo/ http://internal.example.com/bar/ ProxyPassReverse /foo/ http://internal.example.com/bar/
ProxyPass指令使服务器正确地取回文档,同时,ProxyPassReverse指令改变了起始于internal.examle.com的请求,使之指向本地服务器上的目录。需要注意的是,被取回文档中的连接是不会被改写的,因此,文档中的所有绝对路径连接会突破代理机制而直接从internal.example.com取得。
6.URL的重写引擎
模块mod_rewrite提供了更强大的URL重写引擎,可以根据请求中诸如浏览器类型、源IP地址等特征来决定最终提交给客户的内容,还可以使用外部数据库或程序来决定如何处理一个请求,并可以执行上述的所有三种映射:内部重定向、外部重定向和代理。
7.“文件未找到”错误
URL到文件系统的匹配失败是不可避免的,其产生原因有多种。有时是文档被转移了,对此最好是用URL的重定向来引导用户访问新的位置。另外,虽然资源已经转移到新的位置,但是原来的书签和连接仍然有效。
另一种常见的原因是在浏览器或者HTML连接中URL的无意的输入错误,Apache提供了模块mod_speling(sic)以帮助解决这个问题。如果激活了这个模块,它会接管“文件没找到”的错误并查找相似文件,如果找到了唯一的一个,mod_speling会重定向到这个文件,如果不止一个,则会列出一张表反馈给用户。
mod_speling的一个很有用的特性是,它可以忽略大小写查找文件,对不注意URL大小写的用户和Linux文件系统尤为实用。但是,使用mod_speling来纠正偶然的URL错误会给服务器带来额外的负担,因为每次“不正确”的请求都会引发URL重定向和来自客户的新请求。
如果所有的努力都失败了,Apache会返回一个出错信息页面,其状态码为404(文件没找到),其页面内容取决于ErrorDocument指令,并可以灵活地自定义其形式,详见自定义出错响应(Custom error responses)和国际服务器出错响应(International Server Error Responses)。
3.4.5 httpd.conf文件中的MIME类型
浏览器支持多种格式文件的显示,常见的文件格式有plain、html等。在Linux下一般用/usr/local/apache/etc/mime.types文件保存文件的MIME类型。用下列命令可以将不同的MIME类型数据保存到文件/usr/local/apache/etc/mime.types:
TypesConfig /usr/local/apache/etc/mime.types
在Apache的配置文件中可以通过下面指令指示浏览器的默认MIME类型:
DefaultType text/plain
上述命令表明:如果文档使用了非标准的后缀,Web服务器不能决定一个文档的默认类型,那么服务器就使用DefaultType指令定义的MIME类型将文档发送给客户浏览器。上述指令设置为text/plain。这样设置的问题是,如果服务器不能判断出文档的MIME,那么很多情况下该文档为一个二进制文档,但使用text/plain格式发送回去,浏览器将在内部打开它而不会提示保存。因此建议将这个设置更改为:
application/octet-stream
这样浏览器将提示用户进行保存。