这篇学习笔记,是工作中经常用到的Apache的基本配置,一定要熟练掌握。
1. 默认虚拟主机
1.1. 虚拟主机和默认虚拟主机
首先我们要了解一下虚拟主机的概念。早期的Linux服务器上,一个服务器只能运行一个网站。但随着技术的发展,一个服务器上可以跑多个网站了,这样可以帮助我们节省成本。其实,这里的服务器就叫做主机,早期一个主机对应一个站点。而现在,一个主机可以跑多个站点,所以就有了虚拟主机的概念。
既然服务器上可以有多个虚拟主机,每个虚拟主机都会定义一个域名(当然也可以定义多个),只要把这个域名解析指向到该台服务器,我们自然就可以访问这个站点了。域名解析服务器IP地址,是由DNS服务器来完成的。
加入你访问的域名指向了你的服务器,而你又在这台服务器上配置标记了这个域名,这样这个域名就能够被正常访问。但是如果没有标记的域名也指向了这台服务器,那会有什么情况发生呢?这就又有了默认虚拟主机的概念产生。
httpd有一个特点,它首先是支持多个虚拟主机的,也就是可以在一个服务器上运行多个站点,标记多个域名。有标记的域名指向这台服务器,就会由对应的虚拟主机来处理。任何一个其它的没有标记的域名指向这台服务器,即只要没有对应的虚拟主机,就会由默认虚拟主机来处理。
那么这个默认虚拟主机该如何配置呢?下面就是配置它的方法。
1.2. 虚拟主机的配置
httpd的主配置文件是http.conf。我们先来在主配置文件中找到虚拟主机的配置语句,并开启这个功能,如下:
在httpd的主配置文件httpd.conf中开启了虚拟主机的功能之后,再来编辑虚拟主机配置文件/usr/local/apache2.4/conf/extra/httpd-vhosts.conf,后面的操作都是在这个文件里面完成的。
打开虚拟主机的配置文件,可以先看看该文件最后面两端(以<VirtualHost *:80>
开头,以</VirtualHost>
结尾),这样一段就是一个虚拟主机,在这里面可以定义网站的域名和对应的网站程序所在目录。而默认虚拟主机就是第一个配置段。做实验:把该配置文件里面的两端<VirtualHost>
重新编辑如下:
上述配置说明:
ServerAdmin
指定管理员邮箱,这个没有什么实质作用,平时不用它。DocumentRoot
为该虚拟主机站点的根目录,网站的程序就放在这个目录下面。ServerName
为网站的域名,在这后面只能写一个域名。ServerAlias
为网站的第二域名,在这后面可以写多个域名,用空格分隔。ErrorLog
为站点的错误日志。CustomLog
为站点的访问日志,在工作中这个访问日志用得很多,需要关注一下。
假如在虚拟主机配置文件中,我们只定义了两个站点:aming.com和123.com,那么当把第三个域名abc.com指向本机的时候,当在浏览器访问abc.com时,会去访问aming.com(因为它是第一段定义的,所以是默认虚拟主机)。不妨来做个实验:
由上例可以看出,默认虚拟主机为aming.com,不过把什么域名指向该服务器,只要配置文件中没有标记,就会访问这个默认虚拟主机。
2. 用户认证
2.1. 对整站做用户认证
这个功能就是在用户访问网站的时候,需要输入用户名和密码才能顺利访问。一些比较重要的站点或者网站后台通常会加上用户认证,目的是保证安全。
先来对123.com站点做一个全站的用户认证:把123.com那个虚拟主机编辑成如下内容:
以上配置文件中的说明:
<Directory /data/wwwroot/www.123.com>
指定认证的目录AllowOverride AuthConfig
这个相当于打开认证的开关AuthName "123.com user auth"
自定义认证的名字,作用不大AuthType Basic
认证的类型,一般为Basic,其它类型几乎不用AuthUserFile /data/.htpasswd
指定密码文件所在位置require valid-user
指定需要认证的用户为全部可用用户</Directory>
结束标识
这样httpd的配置文件就配置完成了,但还需要创建密码文件,操作步骤如下:
上述配置文件中的说明:
htpasswd
命令为创建用户的工具,-c
为create(创建),-m
指定密码加密方式为MD5。/data/.htpasswd
为密码文件,aming
为要创建的用户。- 第一次执行该命令需要加
-c
,第二次再创建新的用户时,就不用加-c
了,否则/data/.htpasswd
文件会被重置,之前的用户被清空。
配置完成后,用浏览器访问一下www.123.com,不过得提前在真实机上面更改一下hosts文件,把www.123.com域名指向这台Linux机器,这样才能通过浏览器访问成功。
若是访问成功了,就会出现一个认证的提示框,需要输入用户名和密码。输入正确的用户名和密码后,才能进入到www.123.com的网站。
2.2. 针对某个目录或文件做用户认证
当然也可以针对某个目录或文件做用户认证,比如要对www.123.com/admin/目录进行认证,只需要修改一个地方,把<Directory /data/wwwroot/www.123.com>
改为 <Directory /data/wwwroot/www.123.com/admin/>
。如果是一个文件,比如www.123.com/admin.php,则需要这样做:
但是这样修改后会有一个问题,网址中带有admin.php的链接都会弹出认证窗口。
3. 配置域名301跳转
这个用法比较普遍,一个网站可能会有多个域名,但是输入指向的一个网站的多个域名可能会发现,浏览器里的网址总是会变成一个固定的域名,这其实就是域名的跳转功能。
做域名跳转有什么用呢?主要是有两方面的作用:
- 一个站点有多个域名会对SEO有影响,说白了就是百度搜索关键词的排名有影响,如果把多个域名全部跳转到指定的一个域名,这样以这个域名为中心,就可以把权重集中在这个域名上,所以搜索关键词的排名也就靠前了。
- 如果之前的某个域名不再使用了,但是搜索引擎还留着之前老域名的链接,这意味着用户可能会搜到我们的网站并且点击老的域名,因此需要把老域名做个跳转,跳到新域名,这样用户搜的时候,也可以访问到网站。
下面来做实验实现这样一个需求,把123.com域名跳转到www.123.com,配置如下:
上述配置文件的说明:
<IfModule mod_rewrite.c>
要实现跳转功能需要mod_rewrite模块支持。RewriteEngine on
打开rewrite功能RewriteCond %{HTTP_HOST} !^www.123.com$
定义rewrite的条件,当主机名(域名)是123.com的时候满足条件。RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]
定义rewrite的规则,当满足上面的条件时,这条规则才会执行。这里是有正则表达式存在的。RewriteRule后面由空格分成三个部分,第一部分为当前的URL,不过这个URL是不把主机头(也就是域名)算在内的;第二部分为要跳转的目标地址,这个地址可以写全(包含了主机头),当然也可以不加主机头,默认就是前面定义的ServerName;第三部分为一些选项,需要用方括号括起来,301为状态码,它称作”永久重定向”(还有一种跳转码为302,叫做”临时重定向”),L表示”last”,意思是跳转一次就结束了。
要实现域名跳转,需要有rewrite
模块支持,所以先查看httpd是否已经加载该模块,如果没有还需要配置:
配置完后,进行测试,可以用curl测试也可以看到效果,如下:
可以看到状态码为301,跳转后的网站(Location那行)为http://www.123.com。
如果是多个域名,应该这样配置:
或者
4. 配置访问日志
这一节包含了两个内容,一个是Apache日志切割,另一个是不记录指定文件类型日志。
访问日志的作用很大,不仅可以记录网站的访问情况,还可以在网站有异常发生时帮助我们定位问题,比如当有攻击时,是可以通过查看日志看到一些规律的。要配置httpd访问日志,首先要在主配置文件中定义日志的格式,打开主配置文件:
说明:
- 可以阿奎那到有两个格式的日志,建议使用第一个,记录的信息会更全。
- 日志格式的说明如下:
%h
为访问网站的IP%l
为远程登陆名,这个字段基本上为”-“%u
为用户名,当使用用户认证时,这个字段为认证的用户名%t
为时间%r
为请求的动作(比如用curel -I
时就为HEADE)%s
为请求的状态码,写成%>s
为最后的状态码%b
为传输数据大小%{Referer}i
为referer信息(请求本次地址上一次的地址就为referer,比如在百度中搜索到该网站的地址,然后通过百度的搜索结果页面点击进入该网站,那这次请求的referer就是baidu,当然这个地址是很长的)%{User-Agent}i
为浏览器标识,比如你用Firefox或者Chrome浏览器,则该字段显示内容不一样,是带有浏览器的标识的。
- 对于这个日志格式,还可以自定义调整各个字段的位置,也可以额外增加其他字段,比如可以增加
%D
(请求耗费时间) - 在工作中一般不会去改它,默认的日志格式就够用了
然后继续编辑虚拟主机的配置文件,添加一行内容,即改成如下:
保存配置文件后,测试语法并重新加载配置:
发现生成了日志,并且有相关的日志记录。另外,用浏览器访问一下,再次查看日志,多了一行,如下所示:
一个网站会有很多元素,尤其是图片、js、css等静态文件非常多,用户每请求一个页面就会访问诸多的图片、js等静态元素,这些元素的请求都会被记录到日志中。如果一个站点访问量很大,那么访问日志文件增长会非常快,一天可以达到几GB。这不仅对于服务器的磁盘空间造成影响,更重要的是会影响磁盘的读写速度。而且,访问日志很重要,又不能不去记录,这该怎么办呢?
好在这些巨量的静态元素请求记录到日志里意义并不大,所以可以限制这些静态元素去记录日志,并且需要把日志按天归档,一天一个日志,这样也可以防止单个日志文件过大。配置如下:
上面配置文件的说明:
- 先定义了一个
image-request
环境变量,把gif、jpg、png、bmp、swf、js、css等格式的文件全部归类到image-request
里 - 后面的
env=!image-request
有用到一个!
,相当于取反,意思是把image-request
以外的类型文件记录到日志里 - 正常应该
CustomLog
后面为日志文件名,但在这里用了一个管道,它会把日志内容交给后面的rotatelogs
命令处理。 - 这个
rotatelogs
为httpd自带切割日志的工具,它会把访问日志按照我们定义的文件名格式进行切割,其中86400单位为秒,相当于一天。-l
的作用是校准时区为UTC,也就是北京时间。
保存配置文件后,测试配置文件是否有错误,没有错误重新加载服务,然后测试看是否有我们自己定义的格式日志产生:
这里的123.com-access_20180308.log就是新生成的日志,而且以后每天生成一个按日期命名的日志。
接下来测试一下”在日志不记录静态元素”的配置:
可以看到,123.com-access_20180308日志中只有aming.txt的请求日志,但没有aming.jpg的请求日志。这说明去除静态元素的记录日志配置成功了,这样一来,日志文件会瘦身很多。
当然,httpd的错误日志的切割也一样,如下:
说明:
- 日志切割的是两行,注意不要写成多于两行。
- ErrorLog是错误日志,CustomLog是访问日志。
- 其实错误日志所记录的东西并不会太多,所以没有必要对错误日志进行分割。
- 在Apache的log目录中,错误日志有两个,其中一个是apache总的错误日志,另外一个是针对虚拟主机的错误日志。
- 可以把清除过期日志用计划任务的方式来实现,比如清除一个月前的日志,在每天某点某分执行这个操作。
5. 配置静态元素过期时间
有时,会在日志里发现有这样的状态码304,这个状态码表示该文件已经缓存在用户的电脑里了,再次请求它的时候就不用从服务器上下载,而是直接访问用户电脑里面的缓存。这样做的目的是降低服务器的资源消耗,还可以提升用户访问网站的速度。平时我们访问一个网站时,很多元素为静态的小图片,那这些小图片完全可以缓存在咱们的电脑里,这样再次访问该站点时,速度就会很快。
那到底能够缓存多久呢?如果服务器上的某个图片更新了,那么应该访问新的图片才对。这就涉及一个静态文件缓存时长的问题,也叫做缓存过期时间。在httpd的配置文件中,我们是可以控制这个时间的。
编辑虚拟主机配置文件,内容如下:
这部分用到了mod_expires
模块。这里gif、jpeg、png格式的文件过期时长为1天,css、js、flash格式文件过期时长为2小时,其它文件过期时长为0,也就是不缓存。保存配置文件,检查配置是否有问题,没问题重新加载服务:
检查httpd是否加载expires模块:
下面使用curl来测试它的效果:
可以看到max-age=86400,这说明jpg的图片将缓存86400秒,也就是一天。而这里的状态码为200而不是304,这是因为测试工具是curl,没有缓存功能。再测试一下txt文件:
其中max-age=0,说明没有缓存该类型的文件。
6. 配置防盗链
配置防盗链非常的重要,这也是在工作中经常会做的工作。
防盗链,通俗讲,就是不让别人盗用你网站上上的资源,这个资源,通常指的是图片、视频、歌曲、文档等。讲解防盗链配置之前,先了解一下referer的概念,上面在讲解日志格式的时候也提到过它。当你通过A网站的一个页面里面的连接去访问B网站的一个页面时,那么这个B网站页面的referer就是A网站的页面地址。
接下来配置防盗链的过程:
上面配置内容的说明:
- 首先定义允许访问链接的referer,其中
^$
为空referer,当直接在浏览器里输入图片地址去访问它时,它的referer就为空。 - 然后又使用filesmatch来定义需要保护的文件类型,访问txt、doc、mp3、zip、rar、jpg、gif格式的文件,当访问这样类型的文件时就会被限制。
下面是测试过程:
7. 访问控制
对于一些比较重要的网站内容,除了可以使用用户认证限制访问之外,还可以通过其他一些方法做到限制,比如可以限制IP,也可以限制user_agent。限制IP指的是限制访问网站的来源IP,而限制user_agent,通常用来限制恶意或者不正常的请求。
有的公司使用httpd,会对安全要求非常严格,凡是涉及后台的访问都要做IP限制,只允许公司内网IP或者被信任的公网IP访问。这样做的目的是为了防止别有用心的人拿到后台权限,并获得内部数据。
先来看如何限制IP访问,编辑虚拟机配置文件,改成如下内容:
上述配置文件的说明:
- 使用
<Directory>
来指定要限制访问的目录 Order
定义控制顺序,哪个在前面就先匹配哪个规则。在本例中deny
在前,所以先匹配Deny from all
,这样所有的来源IP都会被限制,然后匹配Allow from 127.0.0.1
,这样又允许了127.0.0.1这个IP。- 最终的效果就是,只允许来源IP为127.0.0.1的访问。
下面是验证过程:
在上例中,本机有两个IP,一个是192.168.1.111,另一个是127.0.0.1,通过这两个IP都可以访问到站点。而来源IP分别为192.168.1.111和127.0.0.1,其实和本机IP是一样的。可以看到,我们所配置的功能已经实现了:用192.168.1.111访问的状态是403,表示没有权限;用127.0.0.1访问的状态是200,表示成功访问。
再来用浏览器测试一下,测试完成后查看一下httpd的访问日志:
也可以单独针对某个文件来做限制,编辑虚拟机配置文件,修改如下:
8. 禁止解析PHP
对于使用PHP语言编写的网站,有一些目录是有需求上传文件的。如果网站的代码有漏洞,让一些别有用心的人上传了一个用PHP代码写的木马,由于网站可以执行PHP程序,最终会让别人拿到服务器的权限。为了避免这种情况发生,我们需要把能上传文件的目录直接禁止解析PHP代码(不用担心会影响网站的访问,若是这种目录也需要解析PHP,那说明程序员不合格)。
配置如下:
验证过程如下:
显示了PHP的源代码,这说明PHP没有被正常解析。
9. 禁止指定的user_agent访问
user_agent是浏览器标识,当用curl访问时user_agent为"curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
,当用Chrome浏览器访问时user_agent为"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
。
通常在工作中会对user_agent做一些访问,比如可以限制一些不太友好的搜索引擎爬虫。你之所以能在百度上面搜到某个网站,是因为百度会派一些蜘蛛爬虫来抓取网站的数据。蜘蛛爬虫抓取数据类似于用户用浏览器访问网站,当蜘蛛爬虫太多或者访问太频繁,就会浪费服务器的资源。另外,也可以限制恶意请求,这种恶意请求我们通常称作cc攻击,它的原理很简单,就是用很多用户的电脑同时访问同一个站点,当访问量或者频率达到一定层次,会耗尽服务器资源,从而使之不能正常提供服务。这种cc攻击其实有很明显的规律,其中这些恶意请求的user_agent相同或者相似,那么我们就可以通过限制user_agent发挥防攻击的作用。
下面是针对user_agent来做访问控制:
上述配置的说明:
- 这个需求也用到了
rewrite
模块 %{HTTP_USER_AGENT}
为user_agent的内置变量- 在本例中当user_agent匹配usrl或者baidu.com时,都会触发下面的规则。
- 方括号中的
OR
表示或者,NC
表示不区分大小写,F
表示Forbidden。
验证过程如下:
curl的-A选项指定user_agent。第一个请求,user_agent为”usrl…”的,匹配了第一个条件,所以会403.第二个请求,user_agent为自定义的”123123”,没有匹配任何条件,所以状态码为200。
10. Apache通过rewrite限制某个目录
我们可以用allow和deny去限制网站根目录下的某个子目录,当然,利用rewrite
也可以实现,配置如下:
这段配置,会把只要包含/tmp/字样的请求都限制了。