Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Месть ботам
adept wrote:
Проще сделать иптаблесом, в нем есть
замечательная штука, TARPIT
Словно самому сложно написать. За два кило в коде можно ещё с рюшками и
финтифлюшками.
Аттачу что писал полгода назад во время очередного ддоса. В локальном
каталоге ищет файл tarpit.html с полным текстом ответа (с заголовками).
Режет окно, слушает запрос и начинает отдавать содержимое файла по байту
в секунду. Рекомендую не делать файл совсем большим так как за сутки
соответственно отдаст только 85k.
Минус - жрёт память, в районе гига на 100k подключений. Сейчас бы писал
на lua, да лень уже.
--
Sphinx of black quartz judge my vow.
#!/usr/bin/env python-shared
# vim:set fileencoding=utf-8
from __future__ import division, print_function, unicode_literals
import gevent.monkey
gevent.monkey.patch_all()
import datetime, gevent.pool, signal, socket, sys
answer = []
pool = gevent.pool.Pool()
port = 8081
pitted = {}
sockets = set()
for line in open('tarpit.html', 'rb'):
answer += line
def serve_one(conn, addr):
global answer, sockets
sockets.add(conn)
buf = ''
if addr[0] in pitted:
pitted[addr[0]] += 1
else:
pitted[addr[0]] = 1
try:
conn.settimeout(300)
while True:
gevent.sleep(1)
byte = conn.recv(1)
if byte == '':
break
if byte in ('\r', '\n'):
buf += byte
if buf == '\r\n\r\n':
break
else:
buf = ''
x = 0
while True:
gevent.sleep(1)
conn.settimeout(300)
x += conn.send(answer[x])
conn.settimeout(0)
try:
conn.recv(1)
except socket.error as err:
if err[0] == 35:
pass
else:
raise err
if x >= len(answer):
break
conn.shutdown(socket.SHUT_RDWR)
conn.close()
except socket.error as err:
if not type(err) == socket.timeout:
if not err[0] in [32, 54]:
print('disconnected:', repr(err), 'at line',
sys.exc_info()[2].tb_lineno)
if not err[0] in [1, 32, 54]:
raise err
finally:
conn.close()
if pitted[addr[0]] == 1:
del pitted[addr[0]]
else:
pitted[addr[0]] -= 1
sockets.discard(conn)
def listen(pool):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1)
sockets.add(s)
s.bind(('', port))
s.listen(256)
print('Bound to port:', port)
while True:
try:
pool.spawn(serve_one, *s.accept())
except socket.error as err:
if err[0] == 53:
pass
else:
raise(err)
def siginfo_handler(signum, frame):
print('tarpitted(', port, '):', len(pitted), 'addresses,', len(pool) -
1, 'connections')
signal.signal(signal.SIGINFO, siginfo_handler)
try:
pool.spawn(listen, pool)
pool.join()
except KeyboardInterrupt:
pass
finally:
print('killing sockets')
for socket in sockets:
socket.close()
sys.exit(1)
_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://mailman.nginx.org/mailman/listinfo/nginx-ru
|