ПРОЕКТЫ 


  АРХИВ 


Apache-Talk @lexa.ru 

Inet-Admins @info.east.ru 

Filmscanners @halftone.co.uk 

Security-alerts @yandex-team.ru 

nginx-ru @sysoev.ru 


  СТАТЬИ 


  ПЕРСОНАЛЬНОЕ 


  ПРОГРАММЫ 



ПИШИТЕ
ПИСЬМА












     АРХИВ :: nginx-ru
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


 




Copyright © Lexa Software, 1996-2009.