Apache深度优化

博文大纲:
Apache深度优化

  • 一、开启apache的Gzip(deflate)功能
  • 二、开启expires缓存功能
  • 三、禁止Apache进行目录遍历
  • 四、隐藏apache的版本信息
  • 五、apache日志切割
  • 六、配置防盗链

一、开启Apache的Gzip(deflate)功能

gzip 可以极大的加速网站, 有时压缩比率高到 80%,最少都有 40%以上, 还是相当不错的。
在 Apache2 之后的版本, 模块名不叫 gzip,而叫 mod_deflate
如果要开启apache的压缩功能,需要在编译安装apache时,增加“--enable-deflate”配置项,并且必须在主配置文件中打开下面两个模块:


LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so

注意:如果在编译安装时,没有增加“--enable-deflate”选项,可以使用DSO方式安装此功能,如下:

[root@www ~]# cd /root/httpd-2.4.23/modules/filters/ #切换至apache 源码包 mod_deflate 所在的目录下
[root@www ~]#  /usr/local/http-2.4.23/bin/apxs -c -i -a mod_deflate.c #以 dso 的方式编译安装到 apache 中

如果报错:

Apache深度优化
原因是缺少 zlib-devel 的安装包,装上就可以了。

[root@www filters]# ll /usr/local/http-2.4.23/modules/mod_deflate.so #检查 mod_deflate 是否安装,成功安装这里会显示出该文件

关于上面执行的命令“/usr/local/http-2.4.23/bin/apxs -c -i -a mod_deflate.c”。

选项解释如下:

-c:表示需要执行编译操作;
-i:表示需要执行安装操作,以安装一个或多个动态共享对象到服务器的modeles目录中。
-a:此选项是自动增加一个LoadModule 行到 httpd.conf 文件中,以启用此模块,或者,如果此行已经存在,则启用它。

安装完成后,我们可以发现在检查Apache配置文件时出现错误:
Apache深度优化
解决方法:
需要在LoadModuledeflate_modulemodules/mod_deflate.so 的前面加载 zlib.so。
刚才yum安装zlib时,它默认安装在了/usr/lib64目录下,所以在apache主配置文件中,在 LoadModule deflate_module modules/mod_deflate.so 这行的上一行添加 LoadFile /usr/lib64/libz.so 即可。

最后确认开启压缩功能(apache主配置文件中必须开启以下三行,这三行不一定在同一位置,但是LoadFile /usr/lib64/libz.so必须在那两个之前):


LoadFile /usr/lib64/libz.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so

在 httpd.conf 中加入以下代码,可以加到任何空白地方,不了解 apache 的话,如果担心加错地方,就放到 http.conf 文件的最后一行。
注:在添加代码前最好先查一查要添加的代码是否存在

<IfModule mod_deflate.c>         <!--deflate模块配置-->
DeflateCompressionLevel 6     <!--压缩等级范围0-9,数字越大,压缩比越高,建议取中,否则会加大CPU的压力-->
SetOutputFilter DEFLATE     <!--设置输出过滤器,对输出启用压缩,就像一个开关一样,告诉apache对传输到浏览器的内容进行压缩-->
AddOutputFilterByType DEFLATE text/*
<!--设置对文件是对文本的内容进行压缩,如text/html  text/css text/plain等-->
AddOutputFilterByType  DEFLATE  application/ms*  application/vnd* application/postscript application/javascript application/x-javascript 
<!--对JavaScript文件进行压缩-->
AddOutputFilterByType DEFLATE application/x-httpd-php application/x-httpd-fastphp
<!--对php类型的文件进行压缩-->
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary
<!--设置图片类型不进行压缩,图片压缩后的大小可能超过原来的大小,而且可能会失真,所以不对图片进行压缩。注:?号表示不会捕获()里的内容了-->
SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
<!--同上,就是设置不对 exe,tgz,gz 等的文件进行压缩-->
SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip dont-vary 
<!--同上就是设置不对 pdf,avi,mp3 等的文件进行压缩-->
</IfModule>
<!--以下是设置压缩信息的日志输出-->
DeflateFilterNote Input input_info      <!--声明输入流的 byte 数量-->
DeflateFilterNote Output output_info     <!--声明输出流的 byte 数量-->
DeflateFilterNote Ratio ratio_info     <!--声明压缩的百分比-->
LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate    <!--声明日志格式-->
CustomLog logs/deflate_log.log deflate    <!--指定日志的存放路径-->

根据上面的配置,定义自己需要的压缩项目,要压缩的文件类型根据自己所需要的配置即可(注:除了图片之外,flash 的 swf 文件也是不用启用 GZip 压缩的。)。

去除注释后的代码如下:

<IfModule mod_deflate.c>         
DeflateCompressionLevel 6  
SetOutputFilter DEFLATE  
AddOutputFilterByType DEFLATE text/*
AddOutputFilterByType  DEFLATE  application/ms*  application/vnd* application/postscript application/javascript application/x-javascript 
AddOutputFilterByType DEFLATE application/x-httpd-php application/x-httpd-fastphp
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .(?:pdf|mov|avi|mp3|mp4|rm)$ no-gzip dont-vary 
</IfModule>
DeflateFilterNote Input input_info   
DeflateFilterNote Output output_info   
DeflateFilterNote Ratio ratio_info  
LogFormat '"%r" %{output_info}n/%{input_info}n (%{ratio_info}n%%)' deflate 
CustomLog logs/deflate_log.log deflate 

修改完成后保存退出并重启 httpd 服务
使用谷歌浏览器测试访问,如下图显示结果:(提示:在访问测试页之前按 F12 键)

Apache深度优化

查看压缩信息产生的日志:

[root@apache http-2.4.23]# cat logs/deflate_log.log      #查看压缩日志
"GET / HTTP/1.1" 74/4545 (1%)    #74表示压缩后的大小,4545表示压缩前的大小,末尾的括号中是压缩率
"GET / HTTP/1.1" 74/4545 (1%)
"-" -/- (-%)
[root@apache http-2.4.23]# ll htdocs/index.html     #可以查看网页的大小是否为压缩前的大小“4545”
-rw-r--r--. 1 root root 4545 10月 12 23:00 htdocs/index.html

二、开启expires缓存功能

expires功能可以较少20%~30%左右的重复请求,让重复的用户对指定的页面请求结果都cache在本地,而无需向服务器发出请求。但是经常发生更改的文件不建议这么做。

1、未启用 缓存机制的情况下,先查看以下获取的响应报文

[root@apache htdocs]# curl -I 127.0.0.1/test.jpg      #访问一个图片
HTTP/1.1 200 OK
# Date: Sun, 13 Oct 2019 02:10:34 GMT
Server: Apache/2.4.23 (Unix)
Last-Modified: Mon, 22 Jul 2019 05:55:51 GMT
ETag: "415bf-58e3eba7687c0"
Accept-Ranges: bytes
Content-Length: 267711
Content-Type: image/jpeg            #这就是内容的格式,在定义缓存机制时的类型就是根据这来定义的
#可以看到,上面没有出现cache等相关字样

2、配置expires缓存功能:

[root@apache htdocs]# vim /usr/local/http-2.4.23/conf/httpd.conf     #编辑主配置文件
                       ..................#省略部分内容
LoadModule expires_module modules/mod_expires.so     #去掉此行注释符号
#然后在配置文件的末尾添加以下expires规则
<IfModule mod_expires.c>
ExpiresActive On            #开启缓存机制
#以下是定义各种类型的文件缓存多长时间
ExpiresByType text/css "now plus 1 month"
ExpiresByType application/x-javascript "now plus 5 day"
ExpiresByType image/jpeg "access plus 30 days"   #这里将图片的缓存时间设置为30天
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/png "access plus 1 minute"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresDefault "now plus 0 minute"    #这行表示上面没有定义的,则不进行缓存。
</IfModule>
#写入后,保存退出即可。
[root@apache htdocs]# apachectl -t         #测试配置文件是否有误
Syntax OK
[root@apache htdocs]# apachectl restart      #重启apache,以便刚才的更改生效

无注释的配置文件如下:

LoadModule expires_module modules/mod_expires.so
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "now plus 1 month"
ExpiresByType application/x-javascript "now plus 5 day"
ExpiresByType image/jpeg "access plus 30 days"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/bmp "access plus 1 month"
ExpiresByType image/x-icon "access plus 1 month"
ExpiresByType image/png "access plus 1 minute"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
ExpiresDefault "now plus 0 minute"
</IfModule>

缓存机制的配置格式:ExpiresByType type/encoding "<base> [plus] {<num><type>}"

1、其中<base>是下列之一:

  • access(相对于客户端访问的时间)
  • now(相当于access)
  • modification(相对于最后一次修改源文件后的缓存时间)
    2、该plus关键字是可选的。num 应该是整数值,并且type是以下之一:
  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds

也可以使用以下格式来定义缓存机制:

ExpiresByType image/jpeg A2592000 #表示图片的缓存是1个月
ExpiresByType text/html M604800 #表示HTML文档的有效期是最后修改时刻后的一星期

如果使用“A”(等同于access)“M”(等同于modification)来定义缓存有效期,那么只能以秒来计算。
结论:expires模块可以将到期日期设置为相对于上次修改源文件的时间,还是相对于客户端访问的时间。

3、进行访问测试,查看是否有缓存机制:


[root@apache htdocs]# curl -I 127.0.0.1/test.jpg    #访问某个图片
HTTP/1.1 200 OK
Date: Sun, 13 Oct 2019 02:16:44 GMT
Server: Apache/2.4.23 (Unix)
Last-Modified: Mon, 22 Jul 2019 05:55:51 GMT
ETag: "415bf-58e3eba7687c0"
Accept-Ranges: bytes
Content-Length: 267711
Cache-Control: max-age=2592000       #这就是缓存的时间,单位是秒
Expires: Tue, 12 Nov 2019 02:16:44 GMT
Content-Type: image/jpeg

关于缓存的配置格式,可以阅读其官方文档进行详细了解

三、Apache 禁止目录遍历

当web服务器收到请求报文时,会自动在网页根目录下寻找index.html文件,那么,如果没有这个文件呢?


[root@apache htdocs]# ls    #确认web服务器的网页根目录没有index.html文件
a.sh  images  test.jpg

客户端就会看到以下界面:
Apache深度优化

可以看到,如果没有index.html文件,那么我们的网页结构就直接暴露给了client,这样多少会存在一些隐患,所以,怎么解决呢?

解决方法如下:


[root@apache htdocs]# vim ../conf/httpd.conf     #编辑主配置文件
Options Indexes FollowSymLinks      #定位到这行
#更改如下:
Options  FollowSymLinks         #将中间的Indexes删除即可保存退出
[root@apache htdocs]# apachectl restart        #重启apache以便生效

Indexes 的作用就是当该目录下没有 index.html 文件时,就显示目录结构。

客户端再次访问:
Apache深度优化

OK!!!看到的是403页面。

四、Apache隐藏版本

[root@apache htdocs]# curl -I 127.0.0.1    #查看默认apache的状态信息
HTTP/1.1 403 Forbidden
Date: Sun, 13 Oct 2019 03:08:39 GMT
'Server: Apache/2.4.23 (Unix) '     #可以看到apache的详细版本信息
Content-Type: text/html; charset=iso-8859-1

若想隐藏,须进行以下操作:


[root@apache htdocs]# cd ../conf/
[root@apache conf]# vim httpd.conf     #编辑主配置文件
Include conf/extra/httpd-default.conf       #去掉此行前的注释符号后保存退出
[root@apache conf]# pwd       #查看当前工作路径
/usr/local/http-2.4.23/conf
[root@apache conf]# vim extra/httpd-default.conf    #编辑此文件
#找到下面这两行:
ServerTokens Full
ServerSignature Off
#更改如下:
ServerTokens Prod
ServerSignature On
#更改后保存退出
[root@apache conf]# apachectl restart     #重启服务,以便更改生效
[root@apache conf]# curl -I 127.0.0.1     #再次访问查看
HTTP/1.1 403 Forbidden
Date: Sun, 13 Oct 2019 03:19:17 GMT
Server: Apache           #发现只有apache了,而没有了详细的版本
Content-Type: text/html; charset=iso-8859-1

如果你需要彻底将版本之类的信息进行改头换面,你就需要在编译之前做准备或者进行重新编译了。在重新编译时,修改apache的源码包下 include 目录下的 ap_release.h 配置文件

#define AP_SERVER_BASEVENDOR "Apache Software Foundation" #服务的供应商名称
#define AP_SERVER_BASEPROJECT "Apache HTTP Server" #服务的项目名称
#define AP_SERVER_BASEPRODUCT "Apache" #服务的产品名
#define AP_SERVER_MAJORVERSION_NUMBER 2 #主要版本号
#define AP_SERVER_MINORVERSION_NUMBER 4 #小版本号
#define AP_SERVER_PATCHLEVEL_NUMBER 23 #补丁级别
#define AP_SERVER_DEVBUILD_BOOLEAN 0 #

上述列出的行, 已经给出了注释,大家可以修改成自己想要的,然后编译安装之后,对方就彻底不知道你的版本号了。

五、 Apache 日志切割

为什么要分割日志:
随着网站的访问越来越大, WebServer 产生的日志文件也会越来越大,如果不对日志进行分割,那么只能一次将大的日志(如 Apache 的日志)整个删除,这样也丢失了很多对网站比较宝贵的信息,因为这些日志可以用来进行访问分析、网络安全监察、网络运行状况监控等,因此管理好这些海量的日志对网站的意义是很大的。

方法1:使用rotatelogs(apache自带的工具)按天分割日志,每隔一天记录一个日志

[root@apache conf]# vim httpd.conf   #编辑主配置文件
#将以下两行配置注释掉(去除默认的日志记录)
#ErrorLog "logs/error_log"
#CustomLog "logs/access_log" common
#然后最好在CustomLog "logs/access_log" common配置的下一行添加如下内容(以下内容不可以直接复制,请看下面的解释):
ErrorLog "|/usr/local/http-2.4.23/bin/rotatelogs -l logs/error_%Y-%m-%d.log 86400"
CustomLog "|/usr/local/http-2.4.23/bin/rotatelogs -l logs/access_%Y-%m-%d.log 86400" combined
#添加后,保存退出即可

上面两行的配置项,必须在<IfModule log_config_module> </IfModule>标签中写入。这就是我为什么说最好写在CustomLog "logs/access_log" common配置的下一行的原因,因为这行就在该标签中,写在它的下一行,错不了。

在上面添加的内容中,86400为轮转的时间,单位是秒(也就是一天生成一个日志文件);
需要注意我这里的rotatelogs命令的绝对路径,需根据自己的实际安装路径来定,不要直接复制。

[root@apache conf]# apachectl restart    #重启服务,以便更改生效
[root@apache conf]# ls ../logs/   #查看日志文件,会发现没有access的切割日志
access_log  'error_2019-10-13.log'  error_log  httpd.pid
#此时,原来的access_log和error_log日志文件已经可以删除了
#没有access的切割日志是因为更改后还没有访问过
[root@apache conf]# curl 127.0.0.1 &> /dev/null    #访问一下
[root@apache conf]# ls ../logs/    #再次查看,就有了
'access_2019-10-13.log  error_2019-10-13.log'  httpd.pid
access_log             error_log

由于 apache 自带的日志轮询工具 rotatelogs,据说在进行日志切割时容易丢日志,因此我们通常使用 cronolog (也就是方法2)进行日志轮询。

方法2:使用cronolog为每一天建立一个新的日志
同样需要注释掉主配置文件中的下面两行


#ErrorLog "logs/error_log"
#CustomLog "logs/access_log" common

下载我提供的cronolog源码包
链接: https://pan.baidu.com/s/1LBFHHUKWT13VeAjzs36GoA

[root@apache src]# rz           #使用xshell上传我提供的源码包
#进行编译安装
[root@apache src]# tar zxf cronolog-1.6.2.tar.gz   
[root@apache src]# cd cronolog-1.6.2/
[root@apache cronolog-1.6.2]# ./configure && make && make install
[root@apache conf]# pwd      #切换工作路径至此
/usr/local/http-2.4.23/conf
[root@apache conf]# vim httpd.conf     #编辑主配置文件
#将方法1中写入的日志切割配置项删除,写入下面的两行配置
ErrorLog "|/usr/local/sbin/cronolog logs/error-%Y-%m-%d.log"
CustomLog "|/usr/local/sbin/cronolog logs/access-%Y-%m-%d.log" combined
#写完保存退出即可
[root@apache logs]# ls    #为了避免混乱,我移走了原有的日志文件
httpd.pid
[root@apache logs]# apachectl restart   #重启
[root@apache logs]# curl 127.0.0.1 &> /dev/null    #访问一下,以便生成访问日志文件
[root@apache logs]# ls     #查看确认,
access-2019-10-13.log  error-2019-10-13.log  httpd.pid

至此,即可实现了每天的日志文件分开单独存放。

如果 Apache 中有多个虚拟主机,最好每个虚拟主机中放置一个这样的代码,并将日志文件名改成不同的名字。

3、附加
如果网站访问量实在过于庞大,那么我们可能更需要的是将日志按小时分割,然后按小时分割的日志存放在一个目录中,也就是说,每天对应一个目录,这个 目录下存放的是当天产生的按小时分割的日志。

实现如下:

只需将方法2中写入的两行配置项,更改为如下即可:

[root@apache conf]# vim httpd.conf    #更改如下
ErrorLog "|/usr/local/sbin/cronolog logs/error_%Y-%m-%d/error_log.%H"
CustomLog "|/usr/local/sbin/cronolog logs/access_%Y-%m-%d/access_log.%H" combined
[root@apache conf]# apachectl restart    #重启
[root@apache logs]# curl 127.0.0.1      #访问一下
[root@apache http-2.4.23]# pwd     #切换工作路径
/usr/local/http-2.4.23  
[root@apache http-2.4.23]# tree logs/      #使用tree命令查看
logs/
|-- access_2019-10-13    #访问的日志日期
|   `-- access_log.12         #12点产生的
|-- error_2019-10-13      #错误的日志日期
|   `-- error_log.12          #也是12点产生的
`-- httpd.pid

注意:以上两个管道日志文件程序还有一点不同之处是使用 cronolog 时如果日志是放在某个不存在的路径则会自动创建目录,而使用 rotatelogs 时不能自动创建,这一点要特别注意

六、 配置防盗链

有时候,你的网站莫名其妙的访问量变大,不要高兴的太早,有可能是被别人盗链了。
举个例子:比如你搭了个 discuz 论坛,里面有些热点图片、 视频;然后别人将他网站上访问图片的地址重定向到你的 discuz 上,这样他的服务器就可以空闲出来了;也就是说别人访问他网站的图片视频,消耗的确是你服务器的资源;
解决这个问题的方法是配置下防盗链,让外来的盗不了链;
方法 1: Apache 防盗链的第一种实现方法,可以用 rewrite 实现。

首先要确认 Apache 的 rewrite module 可用:
[root@www ~]# apachectl -M | grep rewrite 
rewrite_module (shared)
打开 httpd.conf,确保有这么一行配置:
LoadModule rewrite_module modules/mod_rewrite.so
然后在找到自己网站对应的配置的地方(如在主配置文件中或虚拟主机中),加入下列代码:
ServerName www.benet.com
#防盗链配置
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://benet.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://benet.com$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.benet.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.benet.com$ [NC]
RewriteRule .*\.(gif|jpg|swf)$http://www.benet.com/about/nolink.png[R,NC,L]
注:相关选项的解释
1.RewriteEngine On #启用 rewrite, 要想 rewrite 起作用,必须要写上
2.RewriteCond test-string condPattern #写在 RewriteRule 之前,可以有一或 N 条,用于测试
rewrite 的匹配条件,具体怎么写,后面会详细说到。
3.RewriteRule Pattern Substitution #规则
4. %{HTTP_REFERER}:服务器变量, HTTPReferer 是 header 的一部分,当浏览器向 web
服务器发送请求的时候,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服
务器借此可以获得一些信息用于处理。比如从我主页上链接到一个朋友那里,他的服务器就
能够从 HTTP Referer 中统计出每天有多少用户点击我主页上的链接访问他的网站。
5.[ NC]指的是不区分大小写,[R]强制重定向 redirect
6. 字母 L 表示如果能匹配本条规则,那么本条规则是最后一条(Last),忽略之后的规则

注意:测试时注意清除缓存。
小结:
Apache深度优化

1、红色部分: 表示自己的信任站点。对我的站点来说,设置为 http://www.test.com 和http://test.com
2.、绿色部分: 要保护文件的扩展名(以|分开)。表示以这些为扩展名的文件,必须通过红色标注的网址引用,才可以访问。
3、蓝色部分: 定义被盗链时替代的图片,让所有盗链 jpg、gif、swf 等文件的网页,显示网页文档根目录下的 about/ nolink.png 文件。 注意:替换显示的图片不要放在设置防盗链的目录中,并
且该图片文件体积越小越好。当然你也可以不设置替换图片,而是使用这条语句即可:RewriteRule .*.(gif|jpg|png)$ - [F]
注:[F] (强制 URL 为被禁止的 forbidden),强制当前 URL 为被禁止的,即,立即反馈一个 HTTP 响应代码 403(被禁止的)。

方法 2: 通过判断浏览器头信息来阻止某些请求, 即利用 SetEnvIfNoCase 和 access。
这个方法可以通过阻止某些机器人或蜘蛛爬虫抓取你的网站来节省你的带宽流量。

语法: SetEnvIfNoCase attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
#SetEnvIfNoCase 当满足某个条件时,为变量赋值, 即根据客户端请求属性设置环境变量。

注: Referer :指明了请求当前资源原始资源的 URL,使用referer 是可以防盗链
然后在找到自己网站对应的配置的地方(如在主配置文件中或虚拟主机中),加入下列代码:

SetEnvIfNoCase Referer "^$" local_ref
SetEnvIfNoCase Referer"^http://www.benet.com/.*$" local_ref
SetEnvIfNoCase Referer"^http://benet.com/.*$"local_ref
<filesmatch"\.(mp3|mp4|zip|rar|jpg|gif|png)">
# 2.4 版本以下的
方法一:
Order Deny,Allow
Allow from env=local_ref
Deny from all
方法二:
Order Allow,Deny
Allow from env=local_ref
#2.4 版本以上,方法如下:
Require all denied
Require env local_ref
</filesmatch>

———————— 本文至此结束,感谢阅读

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章