Bueno, la desventura de QuotaCOP ha sido como ponerle un calsoncillo a
un pulpo.

Posteo esta experiencia en la lista con las esperanza de que suceda una
de estas tres cosas:

-contactamos a Vivanco
-tratamos de adivinar como funciona
-alguien diga públicamente como lo hizo pinchar
-el autor se encabrone con mi critica y nos ilumine
 mostrando cuan fácil es de instalar su engendro

O lo que sería más mejoL en todavía:

Escribimos un puñetero gestor de quotas que se nos acomode y el damos
soporte en RepoGUTL...

Aunque con squish me fue de maravillas, me encantaría hacer un gestor de
quotas para squid, que responda a nuestras particulares necesidades y se
que en esta lista hay gente que puede hacerlo también, así que les pido que
se conduelan con la situación y echen una mano.



Pero con respecto al QuotaCOP:

El tal QuotaCOP viene sin manual, sin Readme y sin las coordenadas para
hacerle una señal de humo al autor, malamente un correo al cual no responde
cuanto le escribes. Debajo pone un número de serie: 201012121023
Evidentemente una fecha.

#   Created by: Willians Vivanco. willian...@infomed.sld.cu
#   Serial number: 201012121023

Vea usted, tiene nombre de músico... Con tan escasas pistas solo podemos
escribir y prenderle una velita a (inserte su santo aquí) para que nos
responda el autor.

Yo no hablo parsel y el programa está escrito en el idioma de la
serpientes (python). Pero bueno, visto desde ruby no tiene mucha
diferencia, así que pude entender alguito, supongo que el que sepa
python no tenga problemas para leerlo.

Por lo que veo en el código parece que se conecta a un servidor MySQL y
hace unas consultas. Por su puesto, el formato de dichas tablas hubieren
sido escritos en un fichero ".sql" que TAMPOCO viene con el solitario
script.

Para mayor agravante, el programador no tiene la menor idea de para que
se usan los comentarios. 71 flamantes lineas de código sin un puñetero
comentario. Todas muy organizadas pero poco explicitas, la clásica
pitonica: -el código es claro ¿pa que comentarios?

lazaro@utopian:~$ dev/utils/lineas.rb QuotaCOP 

  Para un total de 103 lineas:

  19 lineas en blanco\n
  13  # comentarios
  71 lineas de {codigo}
  OJO! probable codigo sin comentar [71 > 13*2]


Los 13 comentarios son para la lisencia GNU

Además de parsel, el hombre habla SQL antiguo, porque las consultas son
a código de SQL puro. ¿No hay ORM en python?
 
Además el fichero usa un ".ini" (estilo Windows) en el que supuestamente se
escribió un configuración. Supongo que al que conozca como funciona el
gestor de ficheros de configuración de python; esto no le de muchos dolores
de cabeza.

Aún así adivinar la parte de SQL es todo una proeza que pondría a prueba al
mejor de los adivinos y habría que buscar a un tipo timbaluo en SQL, que
por medio de las consultas adivine como está compuesta la tabla.

Toda esa matraca, para ejecutar tcpkill desde el command shell usando
python, pal problema de las cuotas que se acaban con descargas largas.
Soy del criterio de que si vas a ejecutar comando, mira, has un
shellscript de bash y pal diablo.


Sin más, los dejo con Vivanco y el contenido del fichero QuotaCOP.tar.gz

Vean que elegancia de código. 

Si tuviera comentarios fuera más lindo aún:


#!/usr/bin/env python

#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.

#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

#   Created by: Willians Vivanco. willian...@infomed.sld.cu
#   Serial number: 201012121023

import datetime
import os
import MySQLdb
from ConfigParser import ConfigParser

CONFDIR = '/usr/local/etc'
LOGDIR = '/var/log'
REQUESTSDIR = '/tmp'

def now():
        return str(datetime.datetime.now())

logFile = open(os.path.join(LOGDIR, 'quotacop.log'), 'aw')

cfgConn = ConfigParser()
cfgConn.read(os.path.join(CONFDIR, 'proxyquota.ini'))
connHost = cfgConn.get('db', 'host')
connUser = cfgConn.get('db', 'user')
connPass = cfgConn.get('db', 'password')
connDBname = cfgConn.get('db', 'dbname')

conn = MySQLdb.connect(host=connHost, user=connUser, passwd=connPass, 
db=connDBname)
connCursor = conn.cursor()
connQuery = 'SELECT client_ip,quota,used FROM quota WHERE quota!=0'
connCursor.execute(connQuery)
connResults = dict(map(lambda x: (x[0], (x[1:3])), connCursor.fetchall()))

logFile.write('\n\n[ %s ] Starting QuotaCOP\n' % now())
logFile.write('[ %s ] Killing hanged tcpkill processes...\n' % now())
os.system('killall -KILL tcpkill 2> /dev/null')
logFile.write('[ %s ] Collecting active requests...\n' % now())
os.system('squidclient mgr:active_requests | egrep "^Connection" -A 15 > 
/tmp/active_requests')

arFile = open(os.path.join(REQUESTSDIR, 'active_requests'))
arLines = arFile.readlines()
logFile.write('[ %s ] Received %s requests. Processing...\n' % (now(), 
len(arLines)/16))
startLine = 0
linesPerBlock = 15
endLine = startLine + linesPerBlock
victims = {}
positiveConns = 0

logTypes = ('TCP_MISS', 'TCP_CLIENT_REFRESH_MISS', 'TCP_NEGATIVE_HIT', 
'TCP_REFRESH_MISS', 'TCP_SWAPFAIL_MISS')
delayPools = ('delay_pool 2')

while endLine < len(arLines):
        currentBlock = arLines[startLine:endLine]
        
        userName = currentBlock[13].split(' ')[1].strip()
        logType = currentBlock[8].split(' ')[1].strip()
        delayPool = currentBlock[14].strip()
        wroteValue = int(currentBlock[1].split('wrote')[1].strip())
        peerIp = currentBlock[4].split(':')[1].strip()
        peerPort = currentBlock[4].split(':')[2].strip()
        if peerIp.startswith('192'):
                peerIface = 'eth1'
        else:
                peerIface = 'eth0'

        if (userName) and (logType in logTypes) and (delayPool in delayPools):
                if userName not in victims:
                        victims[userName] = [wroteValue, 
(peerIp,peerPort,peerIface)]
                else:
                        victims[userName][0] += wroteValue  
                        victims[userName].append((peerIp,peerPort,peerIface))

        startLine = endLine + 1
        endLine = startLine + linesPerBlock

for user in victims:
        if user in connResults:
                if connResults[user][0] < (connResults[user][1] + 
victims[user][0]):
                        for conn2Kill in victims[user][1:]:
                                positiveConns += 1
                                logFile.write('[ %s ] User %s have an 
established connection out of quota: %s:%s...' % (now(), user, conn2Kill[0], 
conn2Kill[1]))
                                os.system('tcpkill -i %s -9 host %s and port %s 
> /dev/null 2>&1 &' % (conn2Kill[2], conn2Kill[0], conn2Kill[1]))
                                logFile.write(' Sending tcpkill command...\n')
        else:
                logFile.write('[ %s ] WARNING: User %s is not in quota db\n' % 
(now(),user))

logFile.write('[ %s ] %s Killed.' % (now(), positiveConns))

arFile.close()
conn.close()
logFile.close()


-- 
Este mensaje ha sido analizado por MailScanner
en busca de virus y otros contenidos peligrosos,
y se considera que está limpio.

______________________________________________________________________
Lista de correos del Grupo de Usuarios de Tecnologías Libres de Cuba.
Gutl-l@jovenclub.cu
https://listas.jovenclub.cu/cgi-bin/mailman/listinfo/gutl-l

Responder a