Apache 是一款使用量排名第一的 web 服務器,LAMP 中的 A 指的就是它。由於其開源、穩定、安全等特性而被廣泛使用。前邊的一篇文章中已經記錄過如何搭建 LAMP 架構,搭建僅是第一步,其中最為重要的就是 Apache 服務,也是 LAMP 的核心。下邊記錄了使用 Apache 以來經常用到的功能。
一、Apache的三種工作模式
Apache 一共有3種穩定的 MPM 模式(多進程處理模塊),它們分別是 prefork、worker、event。http-2.2版本的httpd默認的mpm工作模式為prefork,2.4版本的httpd默認是event工作模式。可以通過 httpd -V 來查看。
[root@linuxblogs ~]# httpd -V | grep -i "server mpm" Server MPM: Prefork
編譯的時候,可以通過 configure 的參數來指定:
--with-mpm=prefork|worker|event
1、prefork 工作模式
Apache在啟動之初,就預先fork一些子進程,然后等待請求進來。之所以這樣做,是為了減少頻繁創建和銷毀進程的開銷。每個子進程只有一個線程,在一個時間點內,只能處理一個請求。
優點:成熟穩定,兼容所有新老模塊。同時,不需要擔心線程安全的問題。
缺點:一個進程相對占用更多的系統資源,消耗更多的內存。而且,它並不擅長處理高並發請求。
2、worker 工作模式
使用了多進程和多線程的混合模式。它也預先fork了幾個子進程(數量比較少),然后每個子進程創建一些線程,同時包括一個監聽線程。每個請求過來,會被分配到1個線程來服務。線程比起進程會更輕量,因為線程通常會共享父進程的內存空間,因此,內存的占用會減少一些。在高並發的場景下,因為比起prefork有更多的可用線程,表現會更優秀一些。
優點:占據更少的內存,高並發下表現更優秀。
缺點:必須考慮線程安全的問題。
3、event 工作模式
它和worker模式很像,最大的區別在於,它解決了keep-alive場景下,長期被占用的線程的資源浪費問題。event MPM中,會有一個專門的線程來管理這些keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務線程,執行完畢后,又允許它釋放。這樣增強了高並發場景下的請求處理能力。
HTTP采用keepalive方式減少TCP連接數量,但是由於需要與服務器線程或進程進行綁定,導致一個繁忙的服務器會消耗完所有的線程。Event MPM是解決這個問題的一種新模型,它把服務進程從連接中分離出來。在服務器處理速度很快,同時具有非常高的點擊率時,可用的線程數量就是關鍵的資源限 制,此時Event MPM方式是最有效的,但不能在HTTPS訪問下工作。
二、Apache的用戶認證
有時候,我們需要給一些特殊的訪問設置一個用戶認證機制,增加安全。比如我們的個人網站,一般都是有一個管理后台的,雖然管理后台本身就有密碼,但我們為了更加安全,可以再設置一層用戶認證。
1、編輯配置文件
vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
在對應的虛擬主機配置中加入如下配置:(加粗部分是添加內容)
<VirtualHost *:80> DocumentRoot "/usr/local/apache2/htdocs" ServerName www.123.com ServerAlias www.abc.com <Directory /usr/local/apache2/htdocs/admin.php> AllowOverride AuthConfig AuthName "Please input you acount." AuthType Basic AuthUserFile /usr/local/apache2/htdocs/.htpasswd require valid-user </Directory>
</VirtualHost>
說明:首先指定要對哪個目錄進行驗證,AuthName自定義,AuthUserFile指定用戶密碼文件在哪里。
2、創建加密用的用戶名和密碼文件
htpasswd -c /usr/local/apache2/htdocs/.htpasswd liwei htpasswd -m /usr/local/apache2/htdocs/.htpasswd admin
創建第一個用戶時-c選項創建.htpasswd文件,-m選項增加用戶,根據提示輸入密碼。
3、重啟apache服務
apachectl -t apachectl graceful
先檢查配置是否正確,然后用graceful相當於是reload配置,不用重啟apache服務,效果一樣。測試,通過瀏覽器輸入 www.123.com/admin.php 提示輸入密碼。
三、設置默認虛擬主機
默認虛擬主機就是配置文件里的第一個虛擬主機。關於默認虛擬主機有個特點,凡是解析到這台服務器的域名,不管是什么域名,只要在配置文件中沒有配置,那么都會訪問到這個主機上來。如果我們直接用IP訪問,會訪問到這個站點上來。為了避免別人亂解析,所以應該把默認也就是第一個虛擬主機給禁止掉。我們使用allow,deny語句,已經禁止掉了。
1、配置默認虛擬主機
vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
添加一個虛擬主機的記錄:
<VirtualHost *:80> DocumentRoot "/var/123" ServerName xxxxx.com.cn <Directory /var/123> Order allow,deny Deny from all </Directory>
</VirtualHost>
創建/var/123目錄,並且設置600權限,daemon用戶無法訪問:
mkdir /var/123
chmod -R 600 /var/123
2、重啟apache服務器
apachectl -t apachectl graceful
如果用IP或其它解析的域名訪問,發現提示:
Forbidden
You don't have permission to access / on this server.
四、域名301跳轉
一個站點難免會有多個域名,而多個域名總得有一個主次,比如我的網站可以用兩個域名訪問:www.itepub.cn 和 www.linuxblogs.cn 但大家發現不管我用哪個域名訪問,最終都會跳轉到 www.linuxblogs.cn 上來。這個行為就叫做域名跳轉,這里的301只是一個狀態碼,跳轉除了301還有302,301是永久跳轉,302是臨時跳轉,網站上一定要設置為301,這樣對搜索引擎是比較友好的。
1、配置域名跳轉
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_HOST} ^www.abc.com$ RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]
</IfModule>
配置為:當訪問aaa時,跳轉到123的網站。
2、配置多個域名跳轉
<IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_HOST} ^www.abc.com$ [OR] RewriteCond %{HTTP_HOST} ^www.abcd.com$ RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]
</IfModule>
3、重啟服務器並測試
apachectl -t apachectl graceful
測試:
# curl -x192.168.0.8:80 www.abc.com -I HTTP/1.1 301 Moved Permanently Date: Tue, 25 Oct 2016 15:48:10 GMT Server: Apache/2.2.31 (Unix) PHP/5.5.38 Location: http://www.123.com/
Content-Type: text/html; charset=iso-8859-1
# curl -x192.168.0.8:80 www.abcd.com -I HTTP/1.1 301 Moved Permanently Date: Tue, 25 Oct 2016 15:48:49 GMT Server: Apache/2.2.31 (Unix) PHP/5.5.38 Location: http://www.123.com/
Content-Type: text/html; charset=iso-8859-1
通過上述測試,發現無論是abc或abcd都可以跳轉到 www.123.com 域名上來,通過瀏覽器訪問也一樣。
五、Apache日志切割
我們每訪問一次網站,那么就會記錄若干條日志。當然前提是已經設置了日志,日志不去管理,時間長了日志文件會越來越大,如何避免產生這么大的日志文件?其實apache有相關的配置,使日志按照我們的需求進行歸檔,比如每天一個新日志,或者每小時一個新的日志。
1、首先簡單設置日志的路徑名稱
vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
編輯添加內容如下:
ErrorLog "logs/error.log" CustomLog "logs/access.log" combined
指定了日志存放在/usr/local/apache2/logs目錄下分別為error.log和access.log,combined為日志顯示的格式,日志格式可以參考配置文件httpd.conf中格式的指定,如下:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common
2、設置apache日志分割
同樣編輯配置文件httpd-vhosts.conf
ErrorLog "|/usr/local/apache2/bin/rotatelogs -l /usr/local/apache2/logs/aaa-error_%Y%m%d.log 86400" CustomLog "|/usr/local/apache2/bin/rotatelogs -l /usr/local/apache2/logs/aaa-access_%Y%m%d.log 86400" combined
ErrorLog是錯誤日志,CustomLog是訪問日志。|就是管道符,意思是把產生的日志交給rotatelog這個工具,而這個工具就是apache自帶的切割日志的工具。-l的作用是校准時區為UTC,也就是北京時間。86400,單位是秒,正好是一天,那么日志會每天切割一次。而最后面的combined為日志的格式,在httpd.conf中有定義。
六、不記錄指定文件類型的日志
如果一個網站訪問量特別大,那么訪問日志就會很多,但有一些訪問日志我們其實是可以忽略掉的,比如網站的一些圖片,還有js、css等靜態對象。而這些文件的訪問往往是巨量的,而且即使記錄這些日志也沒有什么用,那么如何忽略不記錄這些日志呢?
1、配置日志不記錄圖片的訪問
vim /usr/local/apache2/conf/extra/httpd-vhosts.conf
相關配置為:
SetEnvIf Request_URI ".*\.gif$" image-request SetEnvIf Request_URI ".*\.jpg$" image-request SetEnvIf Request_URI ".*\.png$" image-request SetEnvIf Request_URI ".*\.bmp$" image-request SetEnvIf Request_URI ".*\.swf$" image-request SetEnvIf Request_URI ".*\.js$" image-request SetEnvIf Request_URI ".*\.css$" image-request CustomLog "|/usr/local ... _%Y%m%d.log 86400" combined env=!image-request
說明:在原來日志配置基礎上,增加了一些image-request的定義,比如把gif、jpg、bmp、swf、js、css等結尾的全標記為image-request,然后在配置日志后加一個標記env=!image-request,表示取反。
七、Apache配置靜態緩存
所說的靜態文件指的是圖片、js、css等文件,用戶訪問一個站點,其實大多數元素都是圖片、js、css等,這些靜態文件其實是會被客戶端的瀏覽器緩存到本地電腦上的,目的就是為了下次再請求時不再去服務器上下載,這樣就加快了速度,提高了用戶體驗。但這些靜態文件總不能一直緩存,它總有一些時效性,那么就得設置這個過期時間。
1、配置靜態緩存
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf <IfModule mod_expires.c> ExpiresActive on ExpiresByType image/gif "access plus 1 days" ExpiresByType image/jpeg "access plus 24 hours" ExpiresByType image/png "access plus 24 hours" ExpiresByType text/css "now plus 2 hour" ExpiresByType application/x-javascript "now plus 2 hours" ExpiresByType application/javascript "now plus 2 hours" ExpiresByType application/x-shockwave-flash "now plus 2 hours" ExpiresDefault "now plus 0 min"
</IfModule>
或者使用 mod_headers 模塊實現:
<IfModule mod_headers.c> # htm,html,txt 類的文件緩存一個小時 <filesmatch "\.(html|htm|txt)$"> header set cache-control "max-age=3600"
</filesmatch> # css, js, swf 類的文件緩存一個星期 <filesmatch "\.(css|js|swf)$"> header set cache-control "max-age=604800"
</filesmatch> # jpg,gif,jpeg,png,ico,flv,pdf 等文件緩存一年 <filesmatch "\.(ico|gif|jpg|jpeg|png|flv|pdf)$"> header set cache-control "max-age=29030400"
</filesmatch>
</IfModule>
說明:這里的時間單位可以 days、 hours 甚至是 min,兩種不同的方法,上面使用的是mod_expires,而下面用的是 mod_headers,要想使用這些模塊,必須要事先已經支持。如何查看是否支持,使用命令:
# /usr/local/apache2/bin/apachectl -M
2、重啟服務器並驗證
apachectl -t apachectl graceful
驗證:
# curl -x127.0.0.1:80 'http://www.123.com/static/image/common/online_admin.gif' -I HTTP/1.1 200 OK Date: Wed, 26 Oct 2016 03:51:26 GMT Server: Apache/2.2.31 (Unix) PHP/5.5.38 Last-Modified: Tue, 31 May 2016 03:08:36 GMT ETag: "46891b-16b-5341ab0597500" Accept-Ranges: bytes Content-Length: 363 Cache-Control: max-age=86400 Expires: Thu, 27 Oct 2016 03:51:26 GMT Content-Type: image/gif
八、Apache配置防盜鏈
如果你的網站有很多漂亮的圖片,比如你網站域名 www.123.com,圖片地址為 www.123.com/image/111.jpg,那么其它人就可以直接把這個地址放到他自己的網站上,他的用戶可以直接從他網站查看這張圖片,而實際圖片是從你的網站訪問的,所產生的帶寬消耗對你沒有任何意義,應該對這些圖片限制一下,凡是在第三方站點上,嚴禁訪問你站點的圖片,如何配置呢?
1、配置防盜鏈
# vim /usr/local/apache2/conf/extra/httpd-vhosts.conf SetEnvIfNoCase Referer "^http://.*\.123\.com" local_ref SetEnvIfNoCase Referer ".*\.abc\.com" local_ref SetEnvIfNoCase Referer "^$" local_ref <filesmatch "\.(txt|doc|mp3|zip|rar|jpg|gif)"> Order Allow,Deny Allow from env=local_ref </filesmatch>
說明:在這段配置中涉及到一個名詞referer,其實就是上次訪問的網站鏈接。配置referer是根據來源鏈接做限制的,如果來源鏈接不是我們想要的,就直接拒絕,這就是防盜鏈的原理。當然不止是圖片,mp3、rar、zip等文件同樣支持。上述配置中默認是除了定義的列表中的referer,其它都拒絕。
九、Apache訪問控制
其實我們可以對apache的訪問進行控制,可以設置白名單或黑名單。前面更改httpd.conf時候就已經看到了allow,deny這兩個關鍵詞,先來看看allow和deny的規則。
1、舉例1
Order deny,allow deny from all allow from 127.0.0.1
我們的判斷依據是這樣的:
- 看Order后面的,哪個在前,哪個在后
- 如果deny在前,那么就需要看deny from這句,然后看allow from這句
- 規則是一條一條匹配的,不管是deny在前還是allow在前,都會生效的。
2、舉例2
Order allow,deny deny from all allow from 127.0.0.1
這個就會deny所有了,127.0.0.1也會被deny。因為順序是先allow然后deny,雖然開始allow了127,但是后面又拒絕了它。
3、舉例3
Order allow,deny
deny from all
上面的規則就表示,全部都不能通過。
4、舉例4
Order deny,allow
deny from all
上面的規則表示,全部都不能通。
Order deny,allow
只有順序,沒有具體規則,表示全部都可以通行(默認的),因為allow在最后了。
Order allow,deny
這個表示,全部都不能通行(默認的),因為deny在最后。
5、針對某個目錄限制
比如這個目錄很重要,只允許我們公司的IP訪問,當然這個目錄可以是網站根目錄,也就是整個站點。
<Directory /usr/local/apache2/htdocs> Order deny,allow Deny from all Allow from 127.0.0.1
</Directory>
6、針對請求的URL去限制
<filesmatch "(.*)admin(.*)"> Order deny,allow Deny from all Allow from 127.0.0.1
</filesmatch>
這里用到了filesmatch語法,表示匹配的意思。
7、驗證
# curl -x192.168.0.8:80 www.123.com/admin.php -I HTTP/1.1 403 Forbidden Date: Wed, 26 Oct 2016 06:24:54 GMT Server: Apache/2.2.31 (Unix) PHP/5.5.38 Content-Type: text/html; charset=iso-8859-1
# curl -x127.0.0.1:80 www.123.com/admin.php -I HTTP/1.1 401 Authorization Required Date: Wed, 26 Oct 2016 06:25:03 GMT Server: Apache/2.2.31 (Unix) PHP/5.5.38 WWW-Authenticate: Basic realm="Please input you acount." Content-Type: text/html; charset=iso-8859-1
十、禁止解析PHP
某個目錄下禁止解析PHP,這個很有作用,我們做網站安全的時候,這個用的很多,比如某些目錄可以上傳文件,為了避免上傳的文件有木馬,所以我們禁止這個目錄下面的訪問解析PHP。
1、配置禁止解析php
<Directory /usr/local/apache2/htdocs/data> php_admin_flag engine off <filesmatch "(.*)php"> Order deny,allow Deny from all </filesmatch>
</Directory>
說明:php_admin_flag engine off這個語句就是禁止解析php的控制語句,但只這樣配置還不夠,因為這樣配置后用戶依然可以訪問php文件,只不過不解析了,但可以下載,用戶下載php文件也是不合適的,所以有必要再禁止一下。
十一、禁止指定user_agent
user_agent叫做瀏覽器標識,目前主流的瀏覽器有IE、chrome、Firefox、360、iphone的Safari、Android手機上的、百度搜索引擎、google搜索引擎等很多,每一種瀏覽器都有對應的user_agent。為了避免一些無用的搜索引擎或機器爬蟲之類引起的帶寬的無辜消耗。
<IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_HOST} ^www.abc.com$ [OR] RewriteCond %{HTTP_HOST} ^www.abcd.com$ RewriteRule ^/(.*)$ http://www.123.com/$1 [R=301,L]
RewriteCond %{HTTP_USER_AGENT} ".*Firefox.*" [NC,OR] RewriteCond %{HTTP_USER_AGENT} ".*Tomato Bot.*" [NC] RewriteRule .* - [F] </IfModule>
同樣是使用rewrite模塊來實現限制指定user_agent。本例中,RewriteRule .* - [F]可以直接禁止訪問,rewritecond用user_agent來匹配,NC表示不區分大小寫,OR表示或者,連接下一個條件。假如我們要把百度的搜索引擎限制掉,可以加一條這樣的規則:
RewriteCond %{HTTP_USER_AGENT} ^.*Baiduspider/2.0.* [NC] RewriteRule .* - [F]
十二、限制某個目錄
我們可以allow和deny去現在網站根目錄下的某個子目錄,當然這個rewrite也可以實現,配置如下:
<IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REQUEST_URI} ^.*/tmp/* [NC] RewriteRule .* - [F] </IfModule>
這段配置,會把只要是包含 /tmp/ 字樣的請求都限制了。
^_^...... 差不多到這里就要結束了,以后有新的常用功能再來更新。