<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>GzV8.com &#187; Apache</title>
	<atom:link href="http://www.gzv8.com/archives/category/apache/feed" rel="self" type="application/rss+xml" />
	<link>http://www.gzv8.com</link>
	<description>互联网引擎</description>
	<lastBuildDate>Thu, 06 Jan 2011 04:08:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>我的服务器攻击别人了！！ (已解决，把肉鸡抓住了！)</title>
		<link>http://www.gzv8.com/archives/370</link>
		<comments>http://www.gzv8.com/archives/370#comments</comments>
		<pubDate>Thu, 06 Jan 2011 04:02:39 +0000</pubDate>
		<dc:creator>qbanke</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Linux & Unix]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[服务器]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=370</guid>
		<description><![CDATA[在星期五的时候，上着上着，突然页面打开相当慢。
原本以为是网络问题，没大留意。但频繁出现数次，还居然一直持续。
在Cacti中查看，网卡占用居然达到机房百兆宽带的所有，12m/s
查看网卡的实时流量，得到了相同结果。
而且 CPU 也有点不正常，用 Top 命令查看，占用最高的是 Httpd 进程。即 Apache
原以为是受到了页面攻击，但这样在进程里头出现的，还应该有 Nginx 跟 Mysql 才对。
不会就这么孤独地只有 Apache。
正在我继续查找原因，攻击停下来了，网卡流量恢复正常。
查看了所有的 WEB 访问日志，无一是有能够解释到该现状的记录。
因为如果是 页面攻击，就好比是压力测试般，肯定会有某个或几个地址有重复不断的垃圾请求。
但日志上显示得相当悠然。
好了，没过多久，流量又来了！httpd 进程把 2个 cpu核心占用到 100%
网卡冲到 12m/s
使用网络命令 netstat -ant 查看，没有 DDOS 之类攻击所产生的 wait 。
而且链接IP还越来越少，这时候从本地 Ping 服务器的响应基本上是 timeout 了
一但把 Apache 停下来，流量就会消失。再次启动！没过多久又会再来。
为了知道到底是哪个 IP 令我产生这样的事，我安装了既时流量检测工具 iftop
iftop介绍详见：http://www.oschina.net/p/iftop
经检测，传输量最大的 IP 是 60.219.100.3 这个IP，直接访问能打开到网站。
使用 IPtables 命令禁止该IP访问本机！！无效，流量继续！
哟？？？？！！ 再次使用 IPtables 命令禁止本机访问该IP ！！！这下流量终于停了。
哟！！这事情就明白多了，绝对能断点我的服务器成为了肉鸡，受到操控对特定目标进行了攻击。
而进行攻击的木马，不是啥米东西，而是 PHP 程序！
应该是在服务器里头某个虚拟主机网站有漏洞，被放入了 PHP DDOS 攻击木马！
然而，剩下的问题就更加复杂了，如何在海量文件的目录里头找到那个木马？
希望是有一个杀毒程序能帮我扫描到&#8230;.但我还没能找到这个，如果网友们有的不妨推荐推荐。
我的思路是，开启 Apache 的 Server [...]]]></description>
			<content:encoded><![CDATA[<p>在星期五的时候，上着上着，突然页面打开相当慢。</p>
<p>原本以为是网络问题，没大留意。但频繁出现数次，还居然一直持续。</p>
<p>在Cacti中查看，网卡占用居然达到机房百兆宽带的所有，12m/s</p>
<p>查看网卡的实时流量，得到了相同结果。</p>
<p>而且 CPU 也有点不正常，用 Top 命令查看，占用最高的是 Httpd 进程。即 Apache</p>
<p>原以为是受到了页面攻击，但这样在进程里头出现的，还应该有 Nginx 跟 Mysql 才对。</p>
<p>不会就这么孤独地只有 Apache。</p>
<p>正在我继续查找原因，攻击停下来了，网卡流量恢复正常。</p>
<p>查看了所有的 WEB 访问日志，无一是有能够解释到该现状的记录。</p>
<p>因为如果是 页面攻击，就好比是压力测试般，肯定会有某个或几个地址有重复不断的垃圾请求。</p>
<p>但日志上显示得相当悠然。</p>
<p>好了，没过多久，流量又来了！httpd 进程把 2个 cpu核心占用到 100%</p>
<p>网卡冲到 12m/s</p>
<p>使用网络命令 netstat -ant 查看，没有 DDOS 之类攻击所产生的 wait 。</p>
<p>而且链接IP还越来越少，这时候从本地 Ping 服务器的响应基本上是 timeout 了</p>
<p>一但把 Apache 停下来，流量就会消失。再次启动！没过多久又会再来。</p>
<p>为了知道到底是哪个 IP 令我产生这样的事，我安装了既时流量检测工具 iftop</p>
<p>iftop介绍详见：<a href="http://www.oschina.net/p/iftop">http://www.oschina.net/p/iftop</a></p>
<p>经检测，传输量最大的 IP 是 60.219.100.3 这个IP，直接访问能打开到网站。</p>
<p>使用 IPtables 命令禁止该IP访问本机！！无效，流量继续！</p>
<p>哟？？？？！！ 再次使用 IPtables 命令禁止本机访问该IP ！！！这下流量终于停了。</p>
<p>哟！！这事情就明白多了，绝对能断点我的服务器成为了肉鸡，受到操控对特定目标进行了攻击。</p>
<p>而进行攻击的木马，不是啥米东西，而是 PHP 程序！</p>
<p>应该是在服务器里头某个虚拟主机网站有漏洞，被放入了 PHP DDOS 攻击木马！</p>
<p>然而，剩下的问题就更加复杂了，如何在海量文件的目录里头找到那个木马？</p>
<p>希望是有一个杀毒程序能帮我扫描到&#8230;.但我还没能找到这个，如果网友们有的不妨推荐推荐。</p>
<p>我的思路是，开启 Apache 的 Server Status。 这家伙能实时查看到 Apache 正在执行那个程序。</p>
<p>而且详细到执行时间，输出数据量等等&#8230;</p>
<p>详细可见：<a href="http://www.oschina.net/bbs/thread/12650">http://www.oschina.net/bbs/thread/12650</a></p>
<p>好了！这下我就可以坐着等兔子再次跑上门来！</p>
<p>还有一个方法，就是把 PHP safe_mod 打开，能禁用掉一些例如 调用 系统 Shell 参数的语法。</p>
<p>来导致木马无法执行。可以我倒还真想把这兔子抓住，所以现在在等待中&#8230;</p>
<p>####################</p>
<p>2010-11-9 更新</p>
<p>####################</p>
<p>PHP safe_mod 不能随意打开！期中一个副作用就是导致 Cacti 无法调用 rrdtools 等参数。</p>
<p>就算设置了例外目录也无效！</p>
<p>最后我在 Apache，PHP 上都配置了 php_admin_value open_basedir 选项。</p>
<p>使得虚拟主机的用户无法越权访问到所属目录外的文件，当然也包括 shell 命令了。</p>
<p>但无效，黑客依然能利用暗藏在目录里头的肉鸡程序发动攻击。</p>
<p>虽然攻击事件在凌晨或者早上！！虽然我没在电脑旁！！</p>
<p>但我使用了 curl 对 ApacheStatus 页面的定时抓取作为了日志！！</p>
<p>与 Cacti 配合，一发现高流量！就追索该时间的日志！！</p>
<p>哈哈！这下子被逮个正着！！！！！</p>
<p>以下是 ApacheStatus 的截图，Req 项特别高的！就是 PHP肉鸡程序送发送的  UDP 攻击数据包。</p>
<p><a href="http://www.oschina.net/uploads/bbs/2010/1109/175859_xwAY_17.jpg" target="_blank"><img src="http://www.oschina.net/uploads/bbs/2010/1109/175859_xwAY_17.jpg" alt="" /></a></p>
<p>在此也顺便公布攻击来源，辽宁省盘锦市 联通 119.115.80.102 但也有可能是一台跳板肉鸡。</p>
<p>至此，我服务器上存在漏洞的网站被暂时关闭了，经查看文件修改日期，黑客还放了不少后门程序。</p>
<p>看了得好好清除清除才能再次上线了。</p>
<p>而抓到的肉鸡！用 VI 打开，居然是使用 Zend 加密的！！</p>
<p>有没朋友对加密这东西有办法解决的，短信我，我给你发去研究研究。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/370/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Zlib (GZIP) 压缩优化开启配置</title>
		<link>http://www.gzv8.com/archives/368</link>
		<comments>http://www.gzv8.com/archives/368#comments</comments>
		<pubDate>Thu, 06 Jan 2011 04:01:28 +0000</pubDate>
		<dc:creator>qbanke</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=368</guid>
		<description><![CDATA[GZIP 的实现有好多种方法。包括有
1，Nginx 的 GZIP 配置
2，Apache 的 mod_deflate.so  模块
3，各种 PHP 程序中通过 PHP自身 实现压缩。
等等&#8230;
期中使用 PHP 自身也有2种实现方法，一种是开启zlib.output_compression，一种是 ob_gzhandler编码
在默认情况下，zlib.output_compression是关闭的，如需开启需编辑php.ini文件，找到以下选项并开启：
zlib.output_compression = On
zlib.output_compression_level = 6
完成后可以通过phpinfo()函数检测结果，当zlib.output_compression的Local Value和MasterValue的值同为On时，表示已经生效，这时候访问的PHP页面（包括伪静态页面）已经GZIP压缩了，通过Firebug或者在线网页GZIP压缩检测工具可检测到压缩的效果。
但如果需要使用ob_gzhandler(默认)，则需关闭zlib.output_compression(2个同时开启会出乱子)，把php.ini文件内容更改为：
zlib.output_compression = Off
zlib.output_compression_level = -1
ob_gzhandler是多数程序(discuz,phpwind等)推荐的用法
]]></description>
			<content:encoded><![CDATA[<p>GZIP 的实现有好多种方法。包括有</p>
<p>1，Nginx 的 GZIP 配置</p>
<p>2，Apache 的 mod_deflate.so  模块</p>
<p>3，各种 PHP 程序中通过 PHP自身 实现压缩。</p>
<p>等等&#8230;</p>
<p>期中使用 PHP 自身也有2种实现方法，一种是开启zlib.output_compression，一种是 ob_gzhandler编码</p>
<p>在默认情况下，zlib.output_compression是关闭的，如需开启需编辑php.ini文件，找到以下选项并开启：</p>
<p>zlib.output_compression = On<br />
zlib.output_compression_level = 6</p>
<p>完成后可以通过phpinfo()函数检测结果，当zlib.output_compression的Local Value和MasterValue的值同为On时，表示已经生效，这时候访问的PHP页面（包括伪静态页面）已经GZIP压缩了，通过Firebug或者<a href="http://tool.chinaz.com/Gzips/Default.aspx">在线网页GZIP压缩检测工具</a>可检测到压缩的效果。</p>
<p>但如果需要使用ob_gzhandler(默认)，则需关闭zlib.output_compression(2个同时开启会出乱子)，把php.ini文件内容更改为：</p>
<p>zlib.output_compression = Off<br />
zlib.output_compression_level = -1</p>
<p>ob_gzhandler是多数程序(discuz,phpwind等)推荐的用法</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/368/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>开启Apache Server Status</title>
		<link>http://www.gzv8.com/archives/363</link>
		<comments>http://www.gzv8.com/archives/363#comments</comments>
		<pubDate>Thu, 06 Jan 2011 03:59:09 +0000</pubDate>
		<dc:creator>qbanke</dc:creator>
				<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=363</guid>
		<description><![CDATA[


Apache的日志又多又杂，如果靠分析日志或者查看服务器进程来监视Apache运行状态的话，比较繁冗。其实在Apache 1.3.2及以后的版本中就自带一个查看Apache状态的功能模块server-status
打开Apache Server Status如果你的Apache配置文件httpd.conf或者extra/httpd-info.conf中有LoadModule status_module modules/mod_status.so话，说明你的Apache已经加载了此模块；或者编译的时候加上了–enable-module=so也表明服务器支持server-status。
如果Apache没有加载这个模块，如果是linux服务器，就得重新编译Apache，加上–enable-module=so参数即可；如果你是windows系统的话，无需任何编译，只要把刚才时候说的LoadModule status_module modules/mod_status.so这句加上，如果前面有带#号，开启的话，需要将#去除。
 
配置Apache Server Status

&#60;location /ccvita-server-status&#62; SetHandler server-status Order Deny,Allow Deny from all Allow from www.ccvita.com&#60;/location&#62;ExtendedStatus On


这是一个完整的server-status的配置。第一行的ccvita-server-status表示以后可以用类似http://www.ccvita.com/ccvita-server-status来访问，同时http://www.ccvita.com/ccvita-server-status?refresh=N将表示访问状态页面可以每N秒自动刷新一次；Deny from表示禁止的访问地址；Allow from表示允许的地址访问；ExtendedStatus On表示的是待会访问的时候能看到详细的请求信息，另外该设置仅能用于全局设置，不能在特定的虚拟主机中打开或关闭。启用扩展状态信息将会导致服务器运行效率降低。



]]></description>
			<content:encoded><![CDATA[<div>
<div>
<div id="_mcePaste"><span style="font-family: 微软雅黑, Verdana, Simsun, sans-serif; line-height: 22px; -webkit-border-horizontal-spacing: 1px; -webkit-border-vertical-spacing: 1px;"></p>
<p style="margin-top: 5px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 0em; padding: 0px;">Apache的日志又多又杂，如果靠分析日志或者查看服务器进程来监视Apache运行状态的话，比较繁冗。其实在Apache 1.3.2及以后的版本中就自带一个查看Apache状态的功能模块server-status</p>
<p style="margin-top: 5px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 0em; padding: 0px;"><strong style="padding: 0px; margin: 0px;">打开Apache Server Status</strong><br style="padding: 0px; margin: 0px;" />如果你的Apache配置文件httpd.conf或者extra/httpd-info.conf中有LoadModule status_module modules/mod_status.so话，说明你的Apache已经加载了此模块；或者编译的时候加上了–enable-module=so也表明服务器支持server-status。</p>
<p style="margin-top: 5px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 0em; padding: 0px;">如果Apache没有加载这个模块，如果是linux服务器，就得重新编译Apache，加上–enable-module=so参数即可；如果你是windows系统的话，无需任何编译，只要把刚才时候说的LoadModule status_module modules/mod_status.so这句加上，如果前面有带#号，开启的话，需要将#去除。</p>
<p style="margin-top: 5px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 0em; padding: 0px;"><span id="more-333" style="padding: 0px; margin: 0px;"> </span></p>
<p style="margin-top: 5px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 0em; padding: 0px;"><strong style="padding: 0px; margin: 0px;">配置Apache Server Status</strong></p>
<div class="hl-surround" style="padding: 0px; margin: 0px;">
<div class="hl-main" style="padding: 0px; margin: 0px;">&lt;location /ccvita-server-status&gt;<br style="padding: 0px; margin: 0px;" /> SetHandler server-status<br style="padding: 0px; margin: 0px;" /> Order Deny,Allow<br style="padding: 0px; margin: 0px;" /> Deny from all<br style="padding: 0px; margin: 0px;" /> Allow from www.ccvita.com<br style="padding: 0px; margin: 0px;" />&lt;/location&gt;<br style="padding: 0px; margin: 0px;" />ExtendedStatus On</div>
<div class="hl-main" style="padding: 0px; margin: 0px;"></div>
</div>
<p style="margin-top: 5px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 0em; padding: 0px;">这是一个完整的server-status的配置。<br style="padding: 0px; margin: 0px;" />第一行的ccvita-server-status表示以后可以用类似http://www.ccvita.com/ccvita-server-status来访问，同时<br style="padding: 0px; margin: 0px;" />http://www.ccvita.com/ccvita-server-status?refresh=N将表示访问状态页面可以每N秒自动刷新一次；<br style="padding: 0px; margin: 0px;" />Deny from表示禁止的访问地址；<br style="padding: 0px; margin: 0px;" />Allow from表示允许的地址访问；<br style="padding: 0px; margin: 0px;" />ExtendedStatus On表示的是待会访问的时候能看到详细的请求信息，另外该设置仅能用于全局设置，不能在特定的虚拟主机中打开或关闭。启用扩展状态信息将会导致服务器运行效率降低。</p>
<p></span></div>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/363/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP服务器端特性的配置加强PHP的安全</title>
		<link>http://www.gzv8.com/archives/361</link>
		<comments>http://www.gzv8.com/archives/361#comments</comments>
		<pubDate>Thu, 06 Jan 2011 03:58:25 +0000</pubDate>
		<dc:creator>qbanke</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=361</guid>
		<description><![CDATA[通过对php一些服务器端特性的配置加强php的安全
前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题，以及如何通过应用程序漏洞突破系统，这篇文章我们来通过对php的一些服务器端特性来进行配置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题，对用户输入进行严格的过滤，但是常在岸边走哪有不湿鞋，吃烧饼哪有不掉芝麻，人有失蹄马有失手，连著名的phpnuke、phpMyAdmin等程序都出现过很严重的问题，更何况象我等小混混写的脚本。所以现在我们假设php脚本已经出现严重问题，比如象前一阵子 phpnuke的可以上传php脚本的大问题了，我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。
1、编译的时候注意补上已知的漏洞
从4.0.5开始，php的mail函数加入了第五个参数，但它没有好好过滤，使得php应用程序能突破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源码包里ext/standard/mail.c文件，禁止mail函数的第五参数或过滤shell字符。在mail.c文件的第152行，也就是下面这行：
if (extra_cmd != NULL) {
后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php那么我们就修补了这个漏洞。
2、修改php.ini配置文件
以php发行版的php.ini-dist为蓝本进行修改。
1)Error handling and logging
在Error handling and logging部分可以做一些设定。先找到：
display_errors = On
php缺省是打开错误信息显示的，我们把它改为：
display_errors = Off
关闭错误显示后，php函数执行错误的信息将不会再显示给用户，这样能在一定程度上防止攻击者从错误信息得知脚本的物理位置，以及一些其它有用的信息，起码给攻击者的黑箱检测造成一定的障碍。这些错误信息可能对我们自己有用，可以让它写到指定文件中去，那么修改以下：
log_errors = Off
改为：
log_errors = On
以及指定文件，找到下面这行：
;error_log = filename
去掉前面的;注释，把filename改为指定文件，如/usr/local/apache/logs/php_error.log
error_log = /usr/local/apache/logs/php_error.log
这样所有的错误都会写到php_error.log文件里。
2)Safe Mode
php的safe_mode功能对很多函数进行了限制或禁用了，能在很大程度解决php的安全问题。在Safe Mode部分找到：
safe_mode = Off
改为：
safe_mode = On
这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和&#8220;被禁止，其它的一些执行函数如：exec(), system(), passthru(), popen()将被限制只能执行safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序，找到以下：
safe_mode_exec_dir =
指定要执行的程序的路径，如：
safe_mode_exec_dir = /usr/local/php/exec
然后把要用的程序拷到/usr/local/php/exec目录下，这样，象上面的被限制的函数还能执行该目录里的程序。
关于安全模式下受限函数的详细信息请查看php主站的说明：
http://www.php.net/manual/en/features.safe-mode.php ;
3)disable_functions
如果你对一些函数的危害性不太清楚，而且也没有使用，索性把这些函数禁止了。找到下面这行：
disable_functions =
在”=“后面加上要禁止的函数，多个函数用”,“隔开。
3、修改httpd.conf
如果你只允许你的php脚本程序在web目录里操作，还可以修改httpd.conf文件限制php的操作路径。比如你的web目录是/usr/local/apache/htdocs，那么在httpd.conf里加上这么几行：
&#60;Directory /usr/local/apache/htdocs&#62;
php_admin_value open_basedir /usr/local/apache/htdocs
&#60;/Directory&#62;
这样，如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许，如果错误显示打开的话会提示这样的错误：
Warning: open_basedir restriction in effect. File is in wrong directory in
/usr/local/apache/htdocs/open.php on [...]]]></description>
			<content:encoded><![CDATA[<p>通过对php一些服务器端特性的配置加强php的安全</p>
<p>前面象Shaun Clowes和rfp等都比较详细的介绍了php、cgi程序在编程过程中遇到的问题，以及如何通过应用程序漏洞突破系统，这篇文章我们来通过对php的一些服务器端特性来进行配置加强php的安全。写cgi脚本的时候我们的确一定注意各种安全问题，对用户输入进行严格的过滤，但是常在岸边走哪有不湿鞋，吃烧饼哪有不掉芝麻，人有失蹄马有失手，连著名的phpnuke、phpMyAdmin等程序都出现过很严重的问题，更何况象我等小混混写的脚本。所以现在我们假设php脚本已经出现严重问题，比如象前一阵子 phpnuke的可以上传php脚本的大问题了，我们如何通过对服务器的配置使脚本出现如此问题也不能突破系统。</p>
<p><strong>1、编译的时候注意补上已知的漏洞</strong></p>
<p>从4.0.5开始，php的mail函数加入了第五个参数，但它没有好好过滤，使得php应用程序能突破safe_mode的限制而去执行命令。所以使用4.0.5和4.0.6的时候在编译前我们需要修改php源码包里ext/standard/mail.c文件，禁止mail函数的第五参数或过滤shell字符。在mail.c文件的第152行，也就是下面这行：</p>
<p>if (extra_cmd != NULL) {</p>
<p>后面加上extra_cmd=NULL;或extra_cmd = php_escape_shell_cmd(extra_cmd);然后编译php那么我们就修补了这个漏洞。</p>
<p><strong>2、修改php.ini配置文件</strong></p>
<p>以php发行版的php.ini-dist为蓝本进行修改。</p>
<p>1)Error handling and logging</p>
<p>在Error handling and logging部分可以做一些设定。先找到：</p>
<p>display_errors = On</p>
<p>php缺省是打开错误信息显示的，我们把它改为：</p>
<p>display_errors = Off</p>
<p>关闭错误显示后，php函数执行错误的信息将不会再显示给用户，这样能在一定程度上防止攻击者从错误信息得知脚本的物理位置，以及一些其它有用的信息，起码给攻击者的黑箱检测造成一定的障碍。这些错误信息可能对我们自己有用，可以让它写到指定文件中去，那么修改以下：</p>
<p>log_errors = Off</p>
<p>改为：</p>
<p>log_errors = On</p>
<p>以及指定文件，找到下面这行：</p>
<p>;error_log = filename</p>
<p>去掉前面的;注释，把filename改为指定文件，如/usr/local/apache/logs/php_error.log</p>
<p>error_log = /usr/local/apache/logs/php_error.log</p>
<p>这样所有的错误都会写到php_error.log文件里。</p>
<p>2)Safe Mode</p>
<p>php的safe_mode功能对很多函数进行了限制或禁用了，能在很大程度解决php的安全问题。在Safe Mode部分找到：</p>
<p>safe_mode = Off</p>
<p>改为：</p>
<p>safe_mode = On</p>
<p>这样就打开了safe_mode功能。象一些能执行系统命令的函数shell_exec()和&#8220;被禁止，其它的一些执行函数如：exec(), system(), passthru(), popen()将被限制只能执行safe_mode_exec_dir指定目录下的程序。如果你实在是要执行一些命令或程序，找到以下：</p>
<p>safe_mode_exec_dir =</p>
<p>指定要执行的程序的路径，如：</p>
<p>safe_mode_exec_dir = /usr/local/php/exec</p>
<p>然后把要用的程序拷到/usr/local/php/exec目录下，这样，象上面的被限制的函数还能执行该目录里的程序。</p>
<p>关于安全模式下受限函数的详细信息请查看php主站的说明：</p>
<p><a href="http://www.php.net/manual/en/features.safe-mode.php">http://www.php.net/manual/en/features.safe-mode.php</a> ;</p>
<p>3)disable_functions</p>
<p>如果你对一些函数的危害性不太清楚，而且也没有使用，索性把这些函数禁止了。找到下面这行：</p>
<p>disable_functions =</p>
<p>在”=“后面加上要禁止的函数，多个函数用”,“隔开。</p>
<p><strong>3、修改httpd.conf</strong></p>
<p>如果你只允许你的php脚本程序在web目录里操作，还可以修改httpd.conf文件限制php的操作路径。比如你的web目录是/usr/local/apache/htdocs，那么在httpd.conf里加上这么几行：</p>
<p>&lt;Directory /usr/local/apache/htdocs&gt;</p>
<p>php_admin_value open_basedir /usr/local/apache/htdocs</p>
<p>&lt;/Directory&gt;</p>
<p>这样，如果脚本要读取/usr/local/apache/htdocs以外的文件将不会被允许，如果错误显示打开的话会提示这样的错误：</p>
<p>Warning: open_basedir restriction in effect. File is in wrong directory in</p>
<p>/usr/local/apache/htdocs/open.php on line 4 等等。</p>
<p><strong>4、对php代码进行编译</strong></p>
<p>Zend对php的贡献很大，php4的引擎就是用Zend的，而且它还开发了ZendOptimizer和ZendEncode等许多php的加强组件。优化器ZendOptimizer只需<a href="http://www.zend.com/">http://www.zend.com</a>注册就可以免费得到，下面几个是用于4.0.5和4.0.6的ZendOptimizer，文件名分别对于各自的系统：</p>
<p>ZendOptimizer-1.1.0-PHP_4.0.5-FreeBSD4.0-i386.tar.gz</p>
<p>ZendOptimizer-1.1.0-PHP_4.0.5-Linux_glibc21-i386.tar.gz</p>
<p>ZendOptimizer-1.1.0-PHP_4.0.5-Solaris-sparc.tar.gz</p>
<p>ZendOptimizer-1.1.0-PHP_4.0.5-Windows-i386.zip</p>
<p>优化器的安装非常方便，包里面都有详细的说明。以UNIX版本的为例，看清操作系统，把包里的ZendOptimizer.so文件解压到一个目录，假设是/usr/local/lib下，在php.ini里加上两句：</p>
<p>zend_optimizer.optimization_level=15</p>
<p>zend_extension=&#8221;/usr/local/lib/ZendOptimizer.so&#8221; 就可以了。用phpinfo()看到Zend图标左边有下面文字：</p>
<p>with Zend Optimizer v1.1.0, Copyright (c) 1998-2000, by Zend Technologies</p>
<p>那么，优化器已经挂接成功了。</p>
<p>但是编译器ZendEncode并不是免费的，这里提供给大家一<a href="http://www.phpease.com/">http://www.PHPease.com</a>的马勇设计的 编译器外壳，如果用于商业目的，请<a href="http://www.zend.com/">http://www.zend.com</a>联系取得许可协议。</p>
<p>php脚本编译后，脚本的执行速度增加不少，脚本文件只能看到一堆乱码，这将阻止攻击者进一步分析服</p>
<p>务器上的脚本程序，而且原先在php脚本里以明文存储的口令也得到了保密，如mysql的口令。不过在服务器端改脚本就比较麻烦了，还是本地改好再上传吧。</p>
<p><strong>5、文件及目录的权限设置</strong></p>
<p>web目录里除了上传目录，其它的目录和文件的权限一定不能让nobody用户有写权限。否则，攻击者可以修改主页文件，所以web目录的权限一定要设置好。</p>
<p>还有，php脚本的属主千万不能是root，因为safe_mode下读文件的函数被限制成被读文件的属主必须和当前执行脚本的属主是一样才能被读，否则如果错误显示打开的话会显示诸如以下的错误：</p>
<p>Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not</p>
<p>allowed to access /etc/passwd owned by uid 0 in /usr/local/apache/htdocs/open.php</p>
<p>on line 3</p>
<p>这样我们能防止许多系统文件被读，比如：/etc/passwd等。</p>
<p>上传目录和上传脚本的属主也要设成一样，否则会出现错误的，在safe_mode下这些要注意。</p>
<p><strong>6、mysql的启动权限设置</strong></p>
<p>mysql要注意的是不要用root来启动，最好另外建一个mysqladm用户。可以在/etc/rc.local等系统启动脚本里加上一句：</p>
<p>su mysqladm -c &#8220;/usr/local/mysql/share/mysql/mysql.server start&#8221;</p>
<p>这样系统重启后，也会自动用mysqladmin用户启动mysql进程。</p>
<p><strong>7、日志文件及上传目录的审核及</strong></p>
<p>查看日志和人的惰性有很大关系，要从那么大的日志文件里查找攻击痕迹有些大海捞针，而且也未必有。</p>
<p>web上传的目录里的文件，也应该经常检查，也许程序有问题，用户传上了一些非法的文件，比如执行脚本等。</p>
<p><strong>8、操作系统自身的补丁</strong></p>
<p>一样，给系统打已知漏洞的补丁是系统管理员最基本的职责，这也是最后一道防线。</p>
<p>经过以上的配置，虽然说不上固若金汤，但是也在相当程度上给攻击者的测试造成很多麻烦，即使php脚本程序出现比较严重的漏洞，攻击者也无法造成实际性的破坏。</p>
<p>如果您还有更古怪，更变态的配置方法，希望能一起分享分享；）</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/361/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mysql 升级到 5.5 GA 时，PHP 5.2.6 编译出错！已解决！</title>
		<link>http://www.gzv8.com/archives/356</link>
		<comments>http://www.gzv8.com/archives/356#comments</comments>
		<pubDate>Thu, 06 Jan 2011 03:54:47 +0000</pubDate>
		<dc:creator>qbanke</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[默认分类]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=356</guid>
		<description><![CDATA[最近经常有人问我 MySQL Query Cache 相关的问题，就整理一点 MySQL Query Cache 的内容，以供参考。
顾名思义，MySQL Query Cache 就是用来缓存和 Query 相关的数据的。具体来说，Query Cache 缓存了我们客户端提交给 MySQL 的 SELECT 语句以及该语句的结果集。大概来讲，就是将 SELECT 语句和语句的结果做了一个 HASH 映射关系然后保存在一定的内存区域中。
在大部分的 MySQL 分发版本中，Query Cache 功能默认都是打开的，我们可以通过调整 MySQL Server 的参数选项打开该功能。主要由以下5个参数构成：

query_cache_limit：允许 Cache 的单条 Query 结果集的最大容量，默认是1MB，超过此参数设置的 Query 结果集将不会被 Cache
query_cache_min_res_unit：设置 Query Cache 中每次分配内存的最小空间大小，也就是每个 Query 的 Cache 最小占用的内存空间大小
query_cache_size：设置 Query Cache 所使用的内存大小，默认值为0，大小必须是1024的整数倍，如果不是整数倍，MySQL 会自动调整降低最小量以达到1024的倍数
query_cache_type：控制 Query Cache 功能的开关，可以设置为0(OFF),1(ON)和2(DEMAND)三种，意义分别如下：

0(OFF)：关闭 Query Cache 功能，任何情况下都不会使用 [...]]]></description>
			<content:encoded><![CDATA[<p>最近经常有人问我 MySQL Query Cache 相关的问题，就整理一点 MySQL Query Cache 的内容，以供参考。</p>
<p>顾名思义，MySQL Query Cache 就是用来缓存和 Query 相关的数据的。具体来说，Query Cache 缓存了我们客户端提交给 MySQL 的 SELECT 语句以及该语句的结果集。大概来讲，就是将 SELECT 语句和语句的结果做了一个 HASH 映射关系然后保存在一定的内存区域中。</p>
<p>在大部分的 MySQL 分发版本中，Query Cache 功能默认都是打开的，我们可以通过调整 MySQL Server 的参数选项打开该功能。主要由以下5个参数构成：</p>
<ul>
<li>query_cache_limit：允许 Cache 的单条 Query 结果集的最大容量，默认是1MB，超过此参数设置的 Query 结果集将不会被 Cache</li>
<li>query_cache_min_res_unit：设置 Query Cache 中每次分配内存的最小空间大小，也就是每个 Query 的 Cache 最小占用的内存空间大小</li>
<li>query_cache_size：设置 Query Cache 所使用的内存大小，默认值为0，大小必须是1024的整数倍，如果不是整数倍，MySQL 会自动调整降低最小量以达到1024的倍数</li>
<li>query_cache_type：控制 Query Cache 功能的开关，可以设置为0(OFF),1(ON)和2(DEMAND)三种，意义分别如下：
<ul>
<li>0(OFF)：关闭 Query Cache 功能，任何情况下都不会使用 Query Cache</li>
<li>1(ON)：开启 Query Cache 功能，但是当 SELECT 语句中使用的 SQL_NO_CACHE 提示后，将不使用Query Cache</li>
<li>2(DEMAND)：开启 Query Cache 功能，但是只有当 SELECT 语句中使用了 SQL_CACHE 提示后，才使用 Query Cache</li>
</ul>
</li>
<li>query_cache_wlock_invalidate：控制当有写锁定发生在表上的时刻是否先失效该表相关的 Query Cache，如果设置为 1(TRUE)，则在写锁定的同时将失效该表相关的所有 Query Cache，如果设置为0(FALSE)则在锁定时刻仍然允许读取该表相关的 Query Cache。</li>
</ul>
<p><strong>Query Cache 如何处理子查询的？</strong><br />
这是我遇到的最为常见的一个问题。其实 Query Cache 是以客户端请求提交的 Query 为对象来处理的，只要客户端请求的是一个 Query，无论这个 Query 是一个简单的单表查询还是多表 Join，亦或者是带有子查询的复杂 SQL，都被当作成一个 Query，不会被分拆成多个 Query 来进行 Cache。所以，存在子查询的复杂 Query 也只会产生一个Cache对象，子查询不会产生单独的Cache内容。UNION[ALL] 类型的语句也同样如此。</p>
<p><strong>Query Cache 是以 block 的方式存储的数据块吗？</strong><br />
不是，Query Cache 中缓存的内容仅仅只包含该 Query 所需要的结果数据，是结果集。当然，并不仅仅只是结果数据，还包含与该结果相关的其他信息，比如产生该 Cache 的客户端连接的字符集，数据的字符集，客户端连接的 Default Database等。</p>
<p><strong>Query Cache 为什么效率会非常高，即使所有数据都可以 Cache 进内存的情况下，有些时候也不如使用 Query Cache 的效率高？</strong><br />
Query Cache 的查找，是在 MySQL 接受到客户端请求后在对 Query 进行权限验证之后，SQL 解析之前。也就是说，当 MySQL 接受到客户端的SQL后，仅仅只需要对其进行相应的权限验证后就会通过 Query Cache 来查找结果，甚至都不需要经过 Optimizer 模块进行执行计划的分析优化，更不许要发生任何存储引擎的交互，减少了大量的磁盘 IO 和 CPU 运算，所以效率非常高。</p>
<p><strong>客户端提交的 SQL 语句大小写对 Query Cache 有影响吗？</strong><br />
有，由于 Query Cache 在内存中是以 HASH 结构来进行映射，HASH 算法基础就是组成 SQL 语句的字符，所以必须要整个 SQL 语句在字符级别完全一致，才能在 Query Cache 中命中，即使多一个空格也不行。</p>
<p><strong>一个 SQL 语句在 Query Cache 中的内容，在什么情况下会失效？</strong><br />
为了保证 Query Cache 中的内容与是实际数据绝对一致，当表中的数据有任何变化，包括新增，修改，删除等，都会使所有引用到该表的 SQL 的 Query Cache 失效。</p>
<p><strong>为什么我的系统在开启了 Query Cache 之后整体性能反而下降了？</strong><br />
当开启了 Query Cache 之后，尤其是当我们的 query_cache_type 参数设置为 1 以后，MySQL 会对每个 SELECT 语句都进行 Query Cache 查找，查找操作虽然比较简单，但仍然也是要消耗一些 CPU 运算资源的。而由于 Query Cache 的失效机制的特性，可能由于表上的数据变化比较频繁，大量的 Query Cache 频繁的被失效，所以 Query Cache 的命中率就可能比较低下。所以有些场景下，Query Cache 不仅不能提高效率，反而可能造成负面影响。</p>
<p><strong>如何确认一个系统的 Query Cache 的运行是否健康，命中率如何，设置量是否足够？</strong><br />
MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态，具体如下：</p>
<p>mysql&gt; SHOW VARIABLES LIKE &#8216;%query_cache%&#8217;;</p>
<ul>
<li>Qcache_free_blocks：目前还处于空闲状态的 Query Cache 中内存 Block 数目</li>
<li>Qcache_free_memory：目前还处于空闲状态的 Query Cache 内存总量</li>
<li>Qcache_hits：Query Cache 命中次数</li>
<li>Qcache_inserts：向 Query Cache 中插入新的 Query Cache 的次数，也就是没有命中的次数</li>
<li>Qcache_lowmem_prunes：当 Query Cache 内存容量不够，需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数</li>
<li>Qcache_not_cached：没有被 Cache 的 SQL 数，包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL</li>
<li>Qcache_queries_in_cache：目前在 Query Cache 中的 SQL 数量</li>
<li>Qcache_total_blocks：Query Cache 中总的 Block 数量</li>
</ul>
<p>可以根据这几个状态计算出 Cache 命中率，计算出 Query Cache 大小设置是否足够，总的来说，我个人不建议将 Query Cache 的大小设置超过256MB，这也是业界比较常用的做法。<br />
<strong><br />
MySQL Cluster 是否可以使用 Query Cache？</strong><br />
其实在我们的生产环境中也没有使用 MySQL Cluster，所以我也没有在 MySQL Cluster 环境中使用 Query Cache 的实际经验，只是 MySQL 文档中说明确实可以在 MySQL Cluster 中使用 Query Cache。从 MySQL Cluster 的原理来分析，也觉得应该可以使用，毕竟 SQL 节点和数据节点比较独立，各司其职，只是 Cache 的失效机制会要稍微复杂一点。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/356/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache CPU 无端端卡住在 100%</title>
		<link>http://www.gzv8.com/archives/229</link>
		<comments>http://www.gzv8.com/archives/229#comments</comments>
		<pubDate>Thu, 11 Mar 2010 07:35:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[100%]]></category>
		<category><![CDATA[cpu]]></category>
		<category><![CDATA[eaccelerator]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[卡]]></category>
		<category><![CDATA[慢]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=229</guid>
		<description><![CDATA[这个问题实在好怪，折腾了的一个多月。
情况是这样的：
新配了一台服务器，全新 RedHat 5.4 X64 的OS ，Intel 5500系列的CPU
Apache 2.2.14  + PHP 5.2.6 + Zend 3.3.x + eaccelerator 0.9.4
每到了一段时间，八核CPU就会有2核 始终恒定在 100% 占用进程是 httpd 即 apache
由于还有其他6核的资源，所以访问没有任何影响。
找了好久原因，一度怀疑是 mod_mpm 的问题，调整了无数次参数。
后来由于流量越来越高，出现的频率越来越频繁，差不多2天就又变成这样了。
查看 error_log 看到不断有提示：
child pid ***** exit signal Segmentation fault (11)
child pid ***** exit signal Segmentation fault (11)
child pid ***** exit signal Segmentation fault (11)
重启 Apache 的时候还更会一堆过来。
好不容易找到原因，原来是因为 PHP 加速器 eaccelerator 0.9.4 跟 [...]]]></description>
			<content:encoded><![CDATA[<p>这个问题实在好怪，折腾了的一个多月。<br />
情况是这样的：</p>
<p>新配了一台服务器，全新 RedHat 5.4 X64 的OS ，Intel 5500系列的CPU<br />
Apache 2.2.14  + PHP 5.2.6 + Zend 3.3.x + eaccelerator 0.9.4</p>
<p>每到了一段时间，八核CPU就会有2核 始终恒定在 100% 占用进程是 httpd 即 apache<br />
由于还有其他6核的资源，所以访问没有任何影响。<br />
找了好久原因，一度怀疑是 mod_mpm 的问题，调整了无数次参数。<br />
后来由于流量越来越高，出现的频率越来越频繁，差不多2天就又变成这样了。<br />
查看 error_log 看到不断有提示：</p>
<p>child pid ***** exit signal Segmentation fault (11)<br />
child pid ***** exit signal Segmentation fault (11)<br />
child pid ***** exit signal Segmentation fault (11)</p>
<p>重启 Apache 的时候还更会一堆过来。<br />
好不容易找到原因，原来是因为 PHP 加速器 eaccelerator 0.9.4 跟 As5.4 X64 内核的兼容有问题。<br />
之前在 As5.3 X64 上是完全正常的</p>
<p>于是下载了最新的 eaccelerator V0.9.6<br />
重新编译 eaccelerator 升级覆盖，问题解决！</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/229/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>合理设置apache httpd的最大连接数</title>
		<link>http://www.gzv8.com/archives/218</link>
		<comments>http://www.gzv8.com/archives/218#comments</comments>
		<pubDate>Thu, 11 Mar 2010 07:29:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[MaxClients]]></category>
		<category><![CDATA[MaxRequestsPerChild]]></category>
		<category><![CDATA[MinSpareServers]]></category>
		<category><![CDATA[mpm]]></category>
		<category><![CDATA[ServerLimit]]></category>
		<category><![CDATA[StartServers]]></category>
		<category><![CDATA[最大]]></category>
		<category><![CDATA[连接数]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=218</guid>
		<description><![CDATA[合理设置apache httpd的最大连接数
转载自：http://hi.baidu.com/rainchen/blog/item/095f0a551fa802c5b645ae46.html





手头有一个网站在线人数增多，访问时很慢。初步认为是服务器资源不足了，但经反复测试，一旦连接上，不断点击同一个页面上不同的链接，都能迅速打开，这种现象就是说明apache最大连接数已经满了，新的访客只能排队等待有空闲的链接，而如果一旦连接上，在keeyalive 的存活时间内（KeepAliveTimeout，默认5秒）都不用重新打开连接，因此解决的方法就是加大apache的最大连接数。
1.在哪里设置？
服务器的为FreeBSD 6.2 ，apache 2.24，使用默认配置（FreeBSD 默认不加载自定义MPM配置），默认最大连接数是250
在/usr/local/etc/apache22/httpd.conf中加载MPM配置（去掉前面的注释）：
# Server-pool management (MPM specific)
Include etc/apache22/extra/httpd-mpm.conf
可见的MPM配置在/usr/local/etc/apache22/extra/httpd-mpm.conf，但里面根据httpd的工作模式分了很多块，哪一部才是当前httpd的工作模式呢？可通过执行 apachectl -l 来查看：
Compiled in modules:
              core.c
              prefork.c
              http_core.c
              mod_so.c
看到prefork 字眼，因此可见当前httpd应该是工作在prefork模式，prefork模式的默认配置是：
&#60;IfModule mpm_prefork_module&#62;
                StartServers                      5
                MinSpareServers                   5
                MaxSpareServers                  10
                MaxClients                      150
                MaxRequestsPerChild               0
&#60;/IfModule&#62;
2.要加到多少？
连接数理论上当然是支持越大越好，但要在服务器的能力范围内，这跟服务器的CPU、内存、带宽等都有关系。
查看当前的连接数可以用：
ps aux &#124; grep httpd &#124; wc -l
或：
pgrep httpd&#124;wc -l
计算httpd占用内存的平均数:
ps aux&#124;grep -v grep&#124;awk &#8216;/httpd/{sum+=$6;n++};END{print sum/n}&#8217;
由于基本都是静态页面，CPU消耗很低，每进程占用内存也不算多，大约200K。
服务器内存有2G，除去常规启动的服务大约需要500M（保守估计），还剩1.5G可用，那么理论上可以支持1.5*1024*1024*1024/200000 = 8053.06368
约8K个进程，支持2W人同时访问应该是没有问题的（能保证其中8K的人访问很快，其他的可能需要等待1、2秒才能连上，而一旦连上就会很流畅）
控制最大连接数的MaxClients ，因此可以尝试配置为：
&#60;IfModule mpm_prefork_module&#62;
                StartServers                      5
                MinSpareServers                   5
                [...]]]></description>
			<content:encoded><![CDATA[<div>合理设置<a onclick="tagshow(event, 'apache');" href="javascript:;" target="_self"><strong>apache</strong></a> httpd的最大连接数</div>
<div><a onclick="tagshow(event, '%D7%AA%D4%D8');" href="javascript:;" target="_self"><strong>转载</strong></a>自：<a href="http://hi.baidu.com/rainchen/blog/item/095f0a551fa802c5b645ae46.html">http://hi.baidu.com/rainchen/blog/item/095f0a551fa802c5b645ae46.html</a></div>
<table border="0">
<tbody>
<tr>
<td>
<div id="blog_text">
<p>手头有一个网站在线人数增多，访问时很慢。初步认为是服务器资源不足了，但经反复<a onclick="tagshow(event, '%B2%E2%CA%D4');" href="javascript:;" target="_self"><strong>测试</strong></a>，一旦连接上，不断点击同一个页面上不同的链接，都能迅速打开，这种现象就是说明apache最大连接数已经满了，新的访客只能排队等待有空闲的链接，而如果一旦连接上，在keeyalive 的存活时间内（KeepAliveTimeout，默认5秒）都不用重新打开连接，因此解决的方法就是加大apache的最大连接数。</p>
<p>1.在哪里设置？</p>
<p>服务器的为FreeBSD 6.2 ，apache 2.24，使用默认配置（FreeBSD 默认不加载<a href="http://httpd.apache.org/docs/2.2/mod/mpm_common.html" target="_blank">自定义MPM配置</a>），默认最大连接数是250</p>
<p>在/usr/local/etc/apache22/httpd.conf中加载MPM配置（去掉前面的注释）：<br />
# Server-pool management (MPM specific)<br />
Include etc/apache22/extra/httpd-mpm.conf</p>
<p>可见的MPM配置在/usr/local/etc/apache22/extra/httpd-mpm.conf，但里面根据httpd的<a onclick="tagshow(event, '%B9%A4%D7%F7');" href="javascript:;" target="_self"><strong>工作</strong></a>模式分了很多块，哪一部才是当前httpd的工作模式呢？可通过执行 apachectl -l 来查看：<br />
Compiled in modules:<br />
              core.c<br />
              prefork.c<br />
              http_core.c<br />
              mod_so.c</p>
<p>看到prefork 字眼，因此可见当前httpd应该是工作在prefork模式，prefork模式的默认配置是：<br />
&lt;IfModule mpm_prefork_module&gt;<br />
                StartServers                      5<br />
                MinSpareServers                   5<br />
                MaxSpareServers                  10<br />
                MaxClients                      150<br />
                MaxRequestsPerChild               0<br />
&lt;/IfModule&gt;</p>
<p>2.要加到多少？</p>
<p>连接数理论上当然是支持越大越好，但要在服务器的能力范围内，这跟服务器的CPU、内存、带宽等都有关系。</p>
<p>查看当前的连接数可以用：<br />
ps aux | grep httpd | wc -l</p>
<p>或：<br />
pgrep httpd|wc -l</p>
<p>计算httpd占用内存的平均数:<br />
ps aux|grep -v grep|awk &#8216;/httpd/{sum+=$6;n++};END{print sum/n}&#8217;</p>
<p>由于基本都是静态页面，CPU消耗很低，每进程占用内存也不算多，大约200K。</p>
<p>服务器内存有2G，除去常规启动的服务大约需要500M（保守估计），还剩1.5G可用，那么理论上可以支持1.5*1024*1024*1024/200000 = 8053.06368</p>
<p>约8K个进程，支持2W人同时访问应该是没有问题的（能保证其中8K的人访问很快，<a onclick="tagshow(event, '%C6%E4%CB%FB');" href="javascript:;" target="_self"><strong>其他</strong></a>的可能需要等待1、2秒才能连上，而一旦连上就会很流畅）</p>
<p>控制最大连接数的MaxClients ，因此可以尝试配置为：<br />
&lt;IfModule mpm_prefork_module&gt;<br />
                StartServers                      5<br />
                MinSpareServers                   5<br />
                MaxSpareServers                  10<br />
                ServerLimit                    5500<br />
                MaxClients                     5000<br />
                MaxRequestsPerChild               100<br />
&lt;/IfModule&gt;</p>
<p>注意，MaxClients默认最大为250，若要超过这个值就要显式设置ServerLimit，且ServerLimit要放在MaxClients之前，值要不小于MaxClients，不然重启httpd时会有提示。</p>
<p>重启httpd后，通过反复执行pgrep httpd|wc -l 来观察连接数，可以看到连接数在达到MaxClients的设值后不再增加，但此时访问网站也很流畅，那就不用贪心再设置更高的值了，不然以后如果网站访问突增不小心就会耗光服务器内存，可根据以后访问压力趋势及内存的占用变化再逐渐调整，直到找到一个最优的设置值。</p>
<p>(MaxRequestsPerChild不能设置为0，可能会因内存泄露导致服务器崩溃）</p>
<p><a href="http://www.chedong.com/tech/apache_install.html#scale" target="_blank">更佳最大值计算的公式</a>：</p>
<p>apache_max_process_with_good_perfermance &lt; (total_hardware_memory / apache_memory_per_process ) * 2<br />
apache_max_process = apache_max_process_with_good_perfermance * 1.5</p>
</div>
</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/218/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>分享一个 Nginx + Apache 公用 80 端口的配置方案。</title>
		<link>http://www.gzv8.com/archives/181</link>
		<comments>http://www.gzv8.com/archives/181#comments</comments>
		<pubDate>Thu, 11 Mar 2010 07:10:17 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[80 端口]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=181</guid>
		<description><![CDATA[一个典型的 Nginx + Apache 应用方案可以是
Nginx 占用 80 端口，过滤静态请求，然后动态请求即 Proxy 到 Apache 的 8080 端口。
Proxy 反向代理的好处是访问的时候，始终就是 80 端口，来访者不会觉察到有任何的区别。
但有的应用确非常“聪明”，识别到 Apache 所位于的端口是 8080 ，就会把相关的超链接都一并加上 :8080 的后续。这么就死定了，还能有正常访问麽？！
有个方法可以解决这事，就是把 apache 也运行在80端口上。
同一台服务器，有Nginx 也有 Apache，2个httpd服务，都是80，不会冲突麽？
下边就是举例方法。
Nginx.conf 的配置中
server {
listen 80;
server_name www.ABC.com;
}
修改一下。
server {
listen 192.168.3.3:80;       #指定Nginx只占用某个IP的80端口。
listen 192.168.10.3:80;           #如果你服务器中有多个IP，还可以指定多个。
server_name www.ABC.com;
}
如果你在Nginx有多个虚拟主机，每一个都需要这么修改。
然后轮到 apache 的 httpd.conf
把原来的
Listen 80
改为
Listen 127.0.0.1:80
跟Nginx一样，指定apache所占用的IP及端口。
保存退出，重启apache即可生效。
如果你 apache 上也有多个虚拟主机。无需好像Nginx那样逐一修改，只要都是 80 端口既可。
如：
NameVirtualHost *:80
&#60;VirtualHost *:80&#62;
    ServerAdmin hello@abc.com
    DocumentRoot /data/web_server/admin
    ServerName www.ABC.com
&#60;/VirtualHost&#62;
这样，Nginx 跟 Apache [...]]]></description>
			<content:encoded><![CDATA[<p>一个典型的 Nginx + Apache 应用方案可以是</p>
<p>Nginx 占用 80 端口，过滤静态请求，然后动态请求即 Proxy 到 Apache 的 8080 端口。<br />
Proxy 反向代理的好处是访问的时候，始终就是 80 端口，来访者不会觉察到有任何的区别。</p>
<p>但有的应用确非常“聪明”，识别到 Apache 所位于的端口是 8080 ，就会把相关的超链接都一并加上 :8080 的后续。这么就死定了，还能有正常访问麽？！</p>
<p>有个方法可以解决这事，就是把 apache 也运行在80端口上。<br />
同一台服务器，有Nginx 也有 Apache，2个httpd服务，都是80，不会冲突麽？</p>
<p>下边就是举例方法。</p>
<p>Nginx.conf 的配置中</p>
<p>server {</p>
<p>listen 80;<br />
server_name <a href="http://www.abc.com/">www.ABC.com</a>;</p>
<p>}</p>
<p>修改一下。</p>
<p>server {</p>
<p>listen 192.168.3.3:80;       #指定Nginx只占用某个IP的80端口。<br />
listen 192.168.10.3:80;           #如果你服务器中有多个IP，还可以指定多个。<br />
server_name <a href="http://www.abc.com/">www.ABC.com</a>;</p>
<p>}</p>
<p>如果你在Nginx有多个虚拟主机，每一个都需要这么修改。</p>
<p>然后轮到 apache 的 httpd.conf</p>
<p>把原来的</p>
<p>Listen 80</p>
<p>改为</p>
<p>Listen 127.0.0.1:80</p>
<p>跟Nginx一样，指定apache所占用的IP及端口。<br />
保存退出，重启apache即可生效。<br />
如果你 apache 上也有多个虚拟主机。无需好像Nginx那样逐一修改，只要都是 80 端口既可。</p>
<p>如：</p>
<p>NameVirtualHost *:80</p>
<p>&lt;VirtualHost *:80&gt;<br />
    ServerAdmin <a href="mailto:hello@abc.com">hello@abc.com</a><br />
    DocumentRoot /data/web_server/admin<br />
    ServerName <a href="http://www.abc.com/">www.ABC.com</a><br />
&lt;/VirtualHost&gt;</p>
<p>这样，Nginx 跟 Apache 就仅会占用指定IP的80端口，不会冲突。<br />
只要调整一下 Nginx proxy 的参数。<br />
“聪明”应用问题就能解决了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/181/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Apache + JK + Tomcat + 虚拟主机 架构的整合配置方式。</title>
		<link>http://www.gzv8.com/archives/158</link>
		<comments>http://www.gzv8.com/archives/158#comments</comments>
		<pubDate>Thu, 11 Mar 2010 07:00:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JDK]]></category>
		<category><![CDATA[jk]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=158</guid>
		<description><![CDATA[关于有虚拟主机 Apache + JK +（ tomcat1 / tomcat 2） 这么一个架构的配置方式
之前发过在回帖中，发现的人不多，现在开主题发。
步骤不多，也把各个配置的细节，用途都写出来了，新手们认真看。
首先配的是 httpd.conf 的虚拟主机配置
如下：httpd.conf 找到 #NameVirtualHost 去掉前边的 # 然后配置如下
NameVirtualHost *:80
#########################################
&#60;VirtualHost *:80&#62;
    ServerAdmin xxx@xxx.com
    DocumentRoot &#8220;/opt/webroot&#8221;
    ServerName localhost
    #ErrorLog logs/error.log
    JkMountFile conf/localhost.properties
&#60;/VirtualHost&#62;
#########################################
&#60;VirtualHost *:80&#62;
    ServerAdmin xxx@xxx.com
    DocumentRoot &#8220;/opt/web1&#8243;
    ServerAlias www.web1.com
    #ErrorLog logs/error.log
    JkMountFile conf/web1.properties   #加载mod_jk配置路径
&#60;/VirtualHost&#62;
#########################################
&#60;VirtualHost *:80&#62;
    ServerAdmin xxx@xxx.com
    DocumentRoot &#8220;/opt/web2&#8243;
    ServerAlias www.web2.com
    #ErrorLog logs/error.log
    JkMountFile conf/web2.properties  #加载mod_jk配置路径
&#60;/VirtualHost&#62;
##################################
以上配置的前提是你已经顺利编译安装好 mod_jk 模块
然后修改 mod_jk 的全局配置 httpd-jk.conf
vim conf/extra/httpd-jk.conf
LoadModule      [...]]]></description>
			<content:encoded><![CDATA[<p>关于有虚拟主机 Apache + JK +（ tomcat1 / tomcat 2） 这么一个架构的配置方式</p>
<p>之前发过在回帖中，发现的人不多，现在开主题发。</p>
<p>步骤不多，也把各个配置的细节，用途都写出来了，新手们认真看。</p>
<p>首先配的是 httpd.conf 的虚拟主机配置</p>
<p>如下：httpd.conf 找到 #NameVirtualHost 去掉前边的 # 然后配置如下</p>
<p>NameVirtualHost *:80</p>
<p>#########################################</p>
<p>&lt;VirtualHost *:80&gt;<br />
    ServerAdmin xxx@xxx.com<br />
    DocumentRoot &#8220;/opt/webroot&#8221;<br />
    ServerName localhost<br />
    #ErrorLog logs/error.log<br />
    JkMountFile conf/localhost.properties<br />
&lt;/VirtualHost&gt;</p>
<p>#########################################</p>
<p>&lt;VirtualHost *:80&gt;<br />
    ServerAdmin xxx@xxx.com<br />
    DocumentRoot &#8220;/opt/web1&#8243;<br />
    ServerAlias <a href="http://www.web1.com/">www.web1.com</a><br />
    #ErrorLog logs/error.log<br />
    JkMountFile conf/web1.properties   #加载mod_jk配置路径<br />
&lt;/VirtualHost&gt;</p>
<p>#########################################</p>
<p>&lt;VirtualHost *:80&gt;<br />
    ServerAdmin xxx@xxx.com<br />
    DocumentRoot &#8220;/opt/web2&#8243;<br />
    ServerAlias <a href="http://www.web2.com/">www.web2.com</a><br />
    #ErrorLog logs/error.log<br />
    JkMountFile conf/web2.properties  #加载mod_jk配置路径<br />
&lt;/VirtualHost&gt;</p>
<p>##################################</p>
<p>以上配置的前提是你已经顺利编译安装好 mod_jk 模块</p>
<p>然后修改 mod_jk 的全局配置 httpd-jk.conf</p>
<p>vim conf/extra/httpd-jk.conf</p>
<p>LoadModule      jk_module       modules/mod_jk.so</p>
<p>JkWorkersFile   conf/workers.properties   #指定各个配置文件路径<br />
JkMountFile     conf/urimap.properties<br />
JkLogFile       logs/mod_jk.log<br />
JkLogLevel      warn</p>
<p>&lt;Location /jkstatus&gt;    #管理页面<br />
    JkMount status<br />
&lt;/Location&gt;<br />
:wq 保存退出</p>
<p>#########################</p>
<p>然后创建各自的 web1.properties ，web2.properties 配置文件，目录路径跟 httpd.conf 相同</p>
<p># vim conf/web1.properties</p>
<p>/*=tomcat_web1 </p>
<p>!/*.gif=web1 <br />
!/*.jpg=web1<br />
!/*.png=web1<br />
!/*.html=web1<br />
!/*.htm=web1</p>
<p>#第一行的意思是把请求转往代号为 tomcat_web1(命名可与虚拟主机无关) 的 tomcat 端, 一会我们需要在 workers.properties 配置中设置。<br />
#而剩下的是不需要转往 tomcat 的请求类型, 因为 tomcat 处理静态文件性能很差, 所以这里的规则就是过滤，把静态文件处理留给apache。<br />
:wq 保存退出</p>
<p>web2.properties 的配置方式跟 web1 相同。</p>
<p>#################################</p>
<p> 编辑 jk 全局配置</p>
<p># Vim workers.properties</p>
<p>worker.list=tomcat_web1,tomcat_web2,status     #告诉 jk 你需要他统管的 tomcat 名(代号) 最后一个&#8221;status&#8221; 是jk 的管理页面</p>
<p>worker.status.type=status  #为 status 路径设置属性为管理页面。</p>
<p>############# 先配置好每个 tomcat 与 JK 的链接参数 ################<br />
worker.s1.type=ajp13    #协议类型<br />
worker.s1.host=127.0.0.1 #tomcat所在服务器的ip，如果是本机就是 127.0.0.1<br />
worker.s1.port=8108 #tomcat的端口<br />
worker.s1.lbfactor=1 #如果是均衡负载状态,多个tomcat的负载比例。</p>
<p>worker.s2.type=ajp13<br />
worker.s2.host=127.0.0.1<br />
worker.s2.port=8109<br />
worker.s2.lbfactor=1</p>
<p>############## 再配置 tomcat 与 jk 的调度 ###############</p>
<p>worker.tomcat_web1.type=lb    #lb 的意思是可集成多个tomcat均衡负载，但只有一个tomcat 的时候也可以使用。<br />
worker.tomcat_web1.balance_workers=s1  #开头的&#8221;worker.tomcat_web1&#8243;对应web1.properties的配置。这里配置群组的tomcat成员。&#8221;s1&#8243; 是成员代号。对应上边tomcat的链接参数。<br />
worker.tomcat_web1.sticky_session=True #是否打开session 粘贴。</p>
<p>worker.tomcat_web2.type=lb #意义同上<br />
worker.tomcat_web2.balance_workers=s2<br />
worker.tomcat_web2.sticky_session=True</p>
<p>:wq 配置完成后保存退出</p>
<p> ###########################</p>
<p>配置路径名：</p>
<p>编辑或创建 urimap.properties</p>
<p># vim urimap.properties</p>
<p>/*=lb         # 把请求发往 lb<br />
/jkstatus=status  # 把JK管理页面的连接定为 <a href="http://www.web1.com/jkstatus">http://www.web1.com/jkstatus</a> 或者 <a href="http://www.web2.com/jkstatus">http://www.web2.com/jkstatus</a> </p>
<p>:wq 保存退出</p>
<p>你也可以修改或创建相同目录里localhost.properties 把 管理页面链接加到里边。这么链接地址就为 <a href="http://localhost/jkstatus">http://localhost/jkstatus</a><br />
#####################</p>
<p>然后就剩下 tomcat 了</p>
<p>修改端口号对应tomcat 组这个不用说了吧？</p>
<p>最重要说的是既然在各自的 web1.properties 跟 workers.properties中配置了 tomcat 名, 这么除了告诉jk tomcat的IP地址以及端口号, 还必须告诉 tomcat 他的名字。</p>
<p>Engine jvmRoute=&#8221;tomcat_web1&#8243;</p>
<p>分别在 tomcat1 跟 tomcat2 的  server.xml 中找到相应的配置. 改上相应的参数！</p>
<p>到此，即完成整个 Apache + JK + tomcat 的配置过程。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/158/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nginx realip_module 模块 = Apache mod_rpaf</title>
		<link>http://www.gzv8.com/archives/139</link>
		<comments>http://www.gzv8.com/archives/139#comments</comments>
		<pubDate>Thu, 11 Mar 2010 04:56:06 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Apache]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[mod_rpaf]]></category>
		<category><![CDATA[realip_module]]></category>

		<guid isPermaLink="false">http://www.gzv8.com/?p=139</guid>
		<description><![CDATA[Apache 有个第三方开发的 mod_rpaf ，用于当 Apache 置于 proxy 后端的时候接收到前端送来的 IP head
从而获取到真实的IP. 不然日志跟应用都始终只能获取到 反向代理服务端的IP
详细请看：http://www.oschina.net/discuss/thread/675
简单说就是，Nginx &#8211;&#62; Apache 能获取到用户访问的真实IP .
但如果反过来，又或者是 Squid &#8211;&#62; Nginx 呢？
有这么一情况，某网站静态文件很多，而且用户访问的来源有网通，有电信，有铁通&#8230;设置还有国外。
为了令处于不同网络运营商的用户收取静态文件的速度都有良好的体现，该网站分别在这些不同运营商的积分中部署了Squid，然后统一 Proxy 到主站的 Nginx 上，形成分布式缓存架构。
如果单是这样的话，主站上 Nginx 的日志，或者应用所获得的IP来源，始终都只会是各个机房中 Squid 的IP。而不是用户的真实IP。Apache 的话，能通过以上所提到的mod_rpaf解决。当然，强大的 Nginx 也有自己的看家法宝。
Nginx 有个在编译时默认不加载的模块 http_realip_module ，就是用来实现这一功能。
但网上很多作者对这一模块的理解完全错误，以为是 Proxy 参数里头的 proxy_set_header 。
proxy_set_header 用于向后端转发 IP head，这一参数是位于 proxy_module  模块中的，而并非 http_realip_module .
好多的博主写文章的时候，都把这模块的用途写成了“为后端应用提供 realip ”
Nginx 官方 wiki 对于该模块的说明 http://wiki.nginx.org/NginxHttpRealIpModule
“It is useful if nginx [...]]]></description>
			<content:encoded><![CDATA[<p>Apache 有个第三方开发的 mod_rpaf ，用于当 Apache 置于 proxy 后端的时候接收到前端送来的 IP head<br />
从而获取到真实的IP. 不然日志跟应用都始终只能获取到 反向代理服务端的IP</p>
<p>详细请看：<a href="http://www.oschina.net/discuss/thread/675">http://www.oschina.net/discuss/thread/675</a></p>
<p>简单说就是，Nginx &#8211;&gt; Apache 能获取到用户访问的真实IP .</p>
<p>但如果反过来，又或者是 Squid &#8211;&gt; Nginx 呢？</p>
<p>有这么一情况，某网站静态文件很多，而且用户访问的来源有网通，有电信，有铁通&#8230;设置还有国外。<br />
为了令处于不同网络运营商的用户收取静态文件的速度都有良好的体现，该网站分别在这些不同运营商的积分中部署了Squid，然后统一 Proxy 到主站的 Nginx 上，形成分布式缓存架构。</p>
<p>如果单是这样的话，主站上 Nginx 的日志，或者应用所获得的IP来源，始终都只会是各个机房中 Squid 的IP。而不是用户的真实IP。Apache 的话，能通过以上所提到的mod_rpaf解决。当然，强大的 Nginx 也有自己的看家法宝。</p>
<p>Nginx 有个在编译时默认不加载的模块 http_realip_module ，就是用来实现这一功能。<br />
但网上很多作者对这一模块的理解完全错误，以为是 Proxy 参数里头的 proxy_set_header 。</p>
<p>proxy_set_header 用于向后端转发 IP head，这一参数是位于 proxy_module  模块中的，而并非 http_realip_module .<br />
好多的博主写文章的时候，都把这模块的用途写成了“为后端应用提供 realip ”</p>
<p>Nginx 官方 wiki 对于该模块的说明 <a href="http://wiki.nginx.org/NginxHttpRealIpModule">http://wiki.nginx.org/NginxHttpRealIpModule</a></p>
<p>“It is useful if nginx works behind some proxy of L7 load balanver, and request come from local IP, but proxy add request header with client&#8217;s IP.</p>
<p>This module isn&#8217;t built by default, enable it with the configure option ”</p>
<p>说简单了，就是 Nginx 的 http_realip_module = Apache 的 mod_rpaf 用于接受前端发来的 IP head 信息，从获取到真是的用户IP。</p>
<p>配置方式相当简单，重新编译 Nginx 加上 &#8211;with-http_realip_module 参数，如：</p>
<p>./configure &#8211;prefix=/opt/nginx &#8211;with-http_stub_status_module  &#8211;with-pcre=../pcre-6.6 &#8211;with-http_realip_module<br />
make<br />
make install</p>
<p>怎么？Nginx 的服务正在跑着？要重启不容易？<br />
简单，原来你的 Nginx 装在哪，重新编译的时候就选哪，直接 make install 进去就会把原来的覆盖掉。</p>
<p>然后执行 Killall -s USR2 nginx 即可平滑升级。<br />
编辑 Nginx.conf</p>
<p>在 location 里头插入</p>
<p>set_real_ip_from   192.168.1.0/24;     指定接收来自哪个前端发送的 IP head 可以是单个IP或者IP段<br />
set_real_ip_from   192.168.2.1;  <br />
real_ip_header     X-Real-IP;         IP head  的对应参数，默认即可。</p>
<p>配置跟 mod_rpaf  大致相同！</p>
<p>配置完成后 sbin/nginx -t 测试语法<br />
测试无误执行 Killall -s HUP nginx 平滑加载配置。</p>
<p>这么就无间断完成了Nginx这一模块的加载。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gzv8.com/archives/139/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

