2月 21

服务器 自动封锁和解封IP 对付攻击

  服务器流量暴涨,首先通过访问日志查看。每个IP并发不是很高,分布也很广,但是都是只访问主页,可见不是抓取服务导致。通过“netstat -nat|awk ‘{print awk $NF}’|sort|uniq -c|sort -n”t命令查看,连接中还有很多SYN_RECV、TIME_WAIT、ESTABLISHED。看来是小型的攻击。首先是修改web服务的配置,缩减了timeout时间,在nginx上禁止一部分并发比较高的IP,小改系统参数。流量降了20M,但还是太高。nginx虽然禁止了IP,如果用浏览看是一个空白页面,但是每个连接还会产生很小的流量。最后决定将最小的返回值也封掉,直接在iptables上drop掉连接。每个超限IP暂定封2天。写个脚本自动运行。

  此脚本在在centos5.3+python2.6.6使用通过。需要注意,此脚本统计日志完毕会将nginx日志文件清空,如需保留日志,请自行修改。每次加载iptables规则时会清楚上次所有规则,如果有使用其它规则也要自行处理。

#!/bin/python
#-*- coding:utf-8 -*-
# Filename:    drop_ip_iptables.py
# Revision:    1.0
# Date:        2013-2-21
# Author:      simonzhang
# web:         www.simonzhang.net
# Email:       simon-zzm@163.com
### END INIT INFO
import os
import time
from string import strip


#### 参数和脚本中使用到的系统命令
nginx_log = "/usr/local/nginx/logs/nginx.access.log"
# 统计nginx日志中IP访问数量
check_comm = "/bin/cat %s |awk ' ''{print $1}'|sort |uniq -c|sort -n -k1 -r" % nginx_log
# 放在crontab中10分钟跑一次,访问超出n次的全部封掉
overproof = 3000
# 被封地址记录文件
# 文件中记录封IP时间和IP地址。时间单位为秒
lock_ip_list = "/usr/local/nginx/logs/lock_ip_list.txt"
# 被封地址解开时间。时间单位为秒
unlock_time = 3600*24*2 


def manage_lock_ip():
    # 获取当前时间
    get_now_time = int(time.time())
    # 管理日志字典
    man_ip = {}
    # 处理日志中的IP
    try:
        log_file = open('%s' % lock_ip_list, 'rb').readlines()
        for get_ip_info in log_file:
            _get_ip_info = strip(get_ip_info).split(' ')
            man_ip['%s' % _get_ip_info[1]] = int(_get_ip_info[0])
    except:
        exit(0)
    # 清空iptable列表,和ip记录日志
    os.popen('/sbin/iptables -F')
    clean_file = open('%s' % lock_ip_list, 'rb+')
    clean_file.truncate()
    # 开始处理IP,被封没有超时的IP写入iptables和日志中
    log_file = open('%s' % lock_ip_list, 'ab')
    for loop_ip in man_ip.keys():
        if (get_now_time - man_ip[loop_ip]) < unlock_time:
            os.popen('/sbin/iptables -I INPUT -s %s -j DROP' % loop_ip)
            log_file.write('%s %s\n' % (man_ip[loop_ip], loop_ip))
    log_file.close()
        


def main():
    # 已封IP地址字典
    drop_ip_list = {}
    # 加载已封IP日志
    try:
        log_file = open('%s' % lock_ip_list, 'rb').readlines()
        for get_drop_ip_info in log_file:
            _get_drop_ip_info = strip(get_drop_ip_info).split(' ')
            drop_ip_list['%s' % _get_drop_ip_info[1]] = int(_get_drop_ip_info[0])
    except:
        os.mknod('%s' % lock_ip_list)
    # 获取nginx日志中的访问超高的ip并写入日志
    access_high_ip = os.popen('%s' % check_comm).readlines()
    for get_ip_count in access_high_ip:
        try :
            _get_ip_count = strip(get_ip_count).split(' ')
            _get_ip = _get_ip_count[1]
            _get_count = _get_ip_count[0]
        except:
            pass
        if (int(_get_count) > int(overproof)) and (_get_ip not in drop_ip_list.keys()):
            now_time = int(time.time())
            log_file = open('%s' % lock_ip_list, 'ab+')
            log_file.write('%s %s\n' % (now_time, _get_ip))
            log_file.close()
    # 统计完毕清空nginx日志
    log_file = open('%s' % nginx_log, 'wb')
    log_file.truncate()
    # 处理要封的IP和要解开的IP
    manage_lock_ip()


if __name__ == '__main__':
    main()

再补充两条日志分析命令
# 单位时间内统计单个IP只访问首页的数量:
#check_comm = “/bin/cat %s|grep ‘GET / HTTP/1.1’|awk ‘ ”{print $1}’|sort |uniq -c|sort -n -k1 -r” % nginx_log
# 单位时间内统计单个IP访问相同页面的数量
#check_comm = “/bin/cat %s|awk -F'”‘ ‘{print $1 $2}’|awk ‘ ”{print $1″ “$6” “$7” “$8}’|sort -k2,4 -r|uniq -c|sort -n -k1 -r” % nginx_log

源码下载
drop_ip_tables

11月 09

用nginx的cache 对本地静态文件做缓存

需要对静态文件做缓存,但是静态文件也是在本地,由同一个nginx来解析。
使用if不能嵌套,所以只能使用本地的IP跳转一下,我的cache使用的nginx命名cache_one配置如下。如果本地跳转有问题可以再hosts表中修改一下指向。

   #######################pic
   upstream  local_img {
            server localhost:81;
       }
    server{
        listen       81;
        server_name 127.0.0.1;
        location / {
                root /image/;
                client_max_body_size   10m;
                access_log off;
                autoindex off;
                }
    }
   server {
        listen       80;
        server_name img.test.com;
        proxy_cache cache_one;
        location / {
                proxy_redirect off;
                proxy_cache_valid 200 304 12h;
                proxy_cache_valid 301 302 1m;
                proxy_cache_key $host$uri$is_args$args;
                add_header X-Cache $upstream_cache_status;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_pass http://local_img;
                access_log off;
                }
    }
5月 16

tomcat7 虚拟主机

  之前一直在用tomcat5,现在用tomcat7,幸好配置没有变化,把几处重要的配置写出来,备忘。
  需求1)tomcat做连接优化。
2)tomcat下的默认使用ROOT,message.simonzhang.net的域名,使用tomcat,webapps下的message

修改一、

    

修改二、

      
        
      
      
      
        
      

需要注意compressableMimeTy配置,tomcat前端有nginx或者apace等服务如果已经启动了压缩的处理,这里就不用配置了。。

4月 13

nginx 区分移动设备配置

  当期需求,要将来访请求区分开,pc使用页面展示,android和iphone转向相应的页面,配置如下,文中连接只是为了演示:
server {
listen 80;
access_log off;
server_name simonzhang.net www.simonzhang.net ;
modern_browser unlisted;
set $ismob 0;
if ( $http_user_agent ~ “^((.*iPhone.*)|(.*iOS.*)|(.*Safari.*))$”) {
set $ismob 1;
rewrite ^(.*) http://www.simonzhang.net/?page_id=782 break;
}
if ( $http_user_agent ~ “^((.*Android.*))$”) {
set $ismob 1;
rewrite ^(.*) http://www.pixshow.net/robots.txt break;
}
if ( $http_user_agent ~ “^((.*Windows NT.*)|(.*Intel Mac OS.*))$”) {
set $ismob 1;
rewrite ^(.*) http://www.simonzhang.net/ break;
}
rewrite ^(.*) http://www.pixshow.net/ break;
}

注:此类配置并不能百分之百区分出设备,毕竟有写设备还是不守规矩。

4月 20

nginx连接python+django,测试uWSGI和fastcgi性能

【编写测试:张子萌 2011-4-19

当前状况是nginx0.9pcrepython2.6Mysql-pythonDjango已经安装完毕。

nginx已经安装在/program/nginx目录中。项目位置:/program/www/mysite

首先验证uWSGI

1、开始安装uWSGIuwsgi地址。

http://projects.unbit.it/uwsgi/

下载

# wget http://projects.unbit.it/downloads/uwsgi-0.9.7.2.tar.gz

# tar zxvf uwsgi-0.9.7.2.tar.gz

# cd uwsgi-0.9.7.2

# make

# cp uwsgi /usr/bin

2Nginx配置,只列出主要部分部分。nginx默认已经支持uWSGIfastcgi

server部分如下

server {

listen 80;

server_name localhost 172.27.224.235;

location / {

uwsgi_pass 127.0.0.1:9000;

include uwsgi_params;

access_log off;

}

}

3UWSGI配置,参数部分按照实际修改。

# mkdir -p /program/uwsgi

# mkdir -p /program/mysite/logs

# cd /program/uwsgi

# vi uwsgi.xml

内容如下:

127.0.0.1:9000 #设定监听ip和端口

4 #worker模式支持多线程和多进程混合模型的MPM

#如果对workprefork工作模式不清楚自行查资料

4 #使用进程数

100 #监听满后排队数量,超过排队数量服务将会拒绝连接

true #主线程enable

/program/uwsgi/uwsgi.pid #产生主进程号的位置

/program/mysite #项目的目录位置

django_uwsgi #模块信息,下一步中会编辑这个文件

true

true #打印内存请求日志信息

true #开启多线程

true #
每行都用string格式打印时间

512 #uwsgi需要使用内存的量,如当前配置为512M

/program/mysite/logs/django.log #此进程打印日志的位置

4、创建应用模块

# cd /program/mysite

# vi django_uwsgi.py

import os,sys

import django.core.handlers.wsgi

os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘testsite.settings’

path = ‘/program ###此处是防止找不到模块

if path not in sys.path:

sys.path.append(path)

print sys.path

application = django.core.handlers.wsgi.WSGIHandler()

5、启动服务

#/usr/bin/uwsgi -x /program/uwsgi/uwsgi.xml

启动nginx

6、查看进程

#[liuts@webserver nginx]# ps -ef|grep uwsgi|grep -v grep

root 25867 1 0 19:41 ? 00:00:00 /usr/bin/uwsgi -x /program/uwsgi/uwsgi.xml

root 25868 25867 0 19:41 ? 00:00:00 /usr/bin/uwsgi -x /program/uwsgi/uwsgi.xml

root 25869 25867 0 19:41 ? 00:00:00 /usr/bin/uwsgi -x /program/uwsgi/uwsgi.xml

root 25870 25867 0 19:41 ? 00:00:00 /usr/bin/uwsgi -x /program/uwsgi/uwsgi.xml

root 25871 25867 0 19:41 ? 00:00:00 /usr/bin/uwsgi -x /program/uwsgi/uwsgi.xml

7、查看监听端口

#[liuts@webserver nginx]# netstat -an|grep 9000

Tcp 0 127.0.0.1:9000 0.0.0.0:* LISTEN

8、访问测试

输入http://yourserverip/

注:附件中有启停uwsgi脚本,方便启停使用。

再次验证fastcgi

使用fastcgi需要安装flupflup一个用python写的web server

1、安装flup

下载地址

# wget http://www.saddi.com/software/flup/dist/flup-1.0.2.tar.gz

#tar zxvf flup-1.0.2.tar.gz

#cd flup-1.0.2

#python setup.py install

2、修改nginx配置

http部分,参数自己优化

fastcgi_connect_timeout 300;

fastcgi_send_timeout 300;

fastcgi_read_timeout 300;

fastcgi_buffer_size 64k;

fastcgi_buffers 4 64k;

fastcgi_busy_buffers_size 128k;

fastcgi_temp_file_write_size 128k;

location部分

fastcgi_pass 127.0.0.1:8000;

include fastcgi_params;

3、启动fastcgi

# /p

4、查看端口进程

#[liuts@webserver nginx]# netstat -an|grep 8000

Tcp 0 127.0.0.1:8000 0.0.0.0:* LISTEN

5、访问测试

输入http://yourserverip/

两个模块调试正常做个测试看看。

我用的是笔记本的虚拟机做的,虚拟机参数如下:

Cpu参数

processor : 0

vendor_id : GenuineIntel

cpu family : 6

model : 15

model name : Intel(R) Core(TM)2 Duo CPU T5870 @ 2.00GHz

内存参数:

MemTotal: 1034708 kB

Cached: 318512 kB

测试工具使用apache自带的ab压力测试工具。使用并发1000,连续60秒进行测试。

测试页面脚本如下,服务接到请求后首先获取系统时间,再做一个610的随机数累加,然后将信息返回给客户。

from django.http import HttpResponse

import datetime

import random

import MySQLdb

def current_datetime(request):

now = datetime.datetime.now()

html = “now %s. n” % now

########

r=random.randint(6,10)

html2=0

for i in range(r):

html2 = html2 + i

html=html+”==”+str(html2)+”==”

########

return HttpResponse(html)

uWSGI测试结果

测试时长: 60.312 seconds

Complete requests: 42055

并发数: 697.29 [#/sec]

平均返回相应时间: 1.434 [ms]

传输量: 135.18 [Kbytes/sec]

Cpu系统使用量平均:84%

Cpu用户使用量平均:16%

内存使用量:512M

Fastcgi测试结果

测试时长: 60.004 seconds

Complete requests: 32270

并发数: 537.80 [#/sec]

平均返回相应时间: 1.859 [ms]

传输量: 385.16 [Kbytes/sec]

Cpu系统使用量平均:51%

Cpu用户使用量平均:49%

内存使用量:500M

结论:

各项测试uWSGI明显优于Fastcgi。具体参数优化需要根据业务编写,然后再做测试。