Red de conocimiento informático - Material del sitio web - Cómo evitar que ddos ​​maliciosos se rastreen en nginx

Cómo evitar que ddos ​​maliciosos se rastreen en nginx

El sitio web que escribí, no sé por qué siempre hay muchas IP de acceso maliciosas, que no son usuarios normales. Antes de acceder, también pensé si podría ser el proxy del operador. IP de exportación del servidor, pero parece que no es así, no te preocupes por ahora, prohíbelo más tarde

Entonces, ¿cómo prohibir? Las reglas son relativamente simples, es decir, después de exceder un umbral, utilice el siguiente comando de iptables

iptables -I INPUT -s -j DROP

servicio de guardar iptables

servicio de reinicio de iptables

Cómo ¿Cuenta la IP de acceso de nginx? Actualmente, es relativamente sencillo leer el archivo nginx access.log y luego analizarlo. Si excede el umbral en un día, ejecutaremos el comando anterior y prohibiremos la IP.

Un problema es que lo que necesitamos es monitorear el archivo access.log todo el tiempo en lugar de leerlo una vez. Por supuesto, podemos bloquear la IP más tarde al final de cada día, pero esto no puede. Dale arrogancia al rastreador. Entonces

Creo que es mejor bloquearlo de inmediato.

He escrito una función similar a tail para leer un archivo antes. Al abrirlo, primero localiza el tamaño del archivo y luego comienza a leer las líneas en un bucle para procesarlo. es un poco diferente. Utilizo tail directamente para ubicar la secuencia de ese archivo en el sys.stdin de mi programa, para poder leer fácilmente todas las secuencias

tail /var/log/nginx/. access.log | python .py

Pero access.log de nginx se logrará una vez al día. ¿Cómo se hace? El método recomendado en el sitio web oficial de nginx

mv access.log. .log.0

kill -USR1 `cat master.nginx.pid`

dormir 1

gzip access.log.0 # hacer algo con el acceso. log.0

Mi vps es procesado por logrotated, que se puede encontrar en /etc/logrotate.d/nginx

/var/log/nginx/*.log {

diario

faltaok

rotar 52

comprimir

retrasarcomprimir

notifempty

crear 640 nginx adm

scripts compartidos

postrotar

[ -f /var/run/nginx.pid ] && matar -USR1 `cat / var/run /nginx.pid`

endscript

}

La creación expresada aquí significa que el archivo se volverá a crear. De hecho, no hay datos nuevos en un archivo tan antiguo, pero debido a que se usa tail y no hay eof, al leer directamente, encontrará que la función file.readline () se atascará, lo que provocará que el programa se congele. para que el programa no pueda salir automáticamente. Luego elegí usar select para manejarlo y agregué un tiempo de espera de 10 segundos. A juzgar por el tráfico actual, básicamente hay muchas solicitudes por segundo. Si no hay datos durante 10 segundos, algo sucede. equivocado.

mientras sys.stdin en select.select([sys.stdin], [], [], 10)[0]:

Entonces, si no hay selección, significa Básicamente, el archivo de registro de nginx se rotó, por lo que cuando encontré tal situación, simplemente salí del programa y lo terminé.

¿Qué debo hacer si finalizo el programa? Originalmente quería reiniciar el programa, pero sentí que podría no ser apropiado, así que usé crontab para manejarlo y lo verifiqué cada 2 minutos. En varios inicios, utilicé Flock para evitar que el programa se reiniciara

*/2 * * * * Flock -xn /dev/shm/blocker.lock -c "sh /srv/www/beauty/daemon. /nginx_ip_blocker.sh"

Aquí se adjunta código

#coding=utf-8

importar sistema

importar re

importar sistema operativo

importar urllib

importar urllib2

importar fecha y hora

importar hora, sistema operativo

importar registro

importar json

importar selección

logging.basicConfig(level=logging.DEBUG, datefmt='%Y%m%d %H:% M:%S', format='[%( asctime)s] %(message)s')

"""

iptables -I INPUT -s -j DROP

servicio iptables guardar

servicio iptables reiniciar

Este script se utiliza principalmente para prohibir las direcciones IP que acceden maliciosamente a nginx

"""

MAX_IP=7000

def get_date():

return time.strftime("%Y%m%d")

def ban_one_ip(ip):

os.system("iptables -I INPUT -s %s -j DROP; servicio iptables guardar; servicio iptables reiniciar"%ip)

def find_ip_and_ban ():

para ip en ip_map:

if ip_map.get(ip)>MAX_IP:

imprime "prohibir ip, cuenta %s:%s "%(ip_map.get(ip), ip)

ip_map[ip] = 0

ban_one_ip(ip)

hoy = Ninguno

ip_map = {}

def process_log(lines):

ip_map global;

global hoy;

ahora = get_date ()

si ahora != hoy:

hoy = ahora

ip_map = {}

para línea en líneas:

ip = line.split (" ")[0]

recuento = ip_map.get(ip,0)

recuento += 1

ip_map[ip]=count;

find_ip_and_ban()

COUNT=50

def mai

n():

brk=False

while True:

tmp = 0;

líneas =[]

brk=False

mientras que sys.stdin en select.select([sys.stdin], [], [], 10)[0]:

línea = sys .stdin.readline()

si no es línea:

brk=True

imprime 'leer a eof'

descanso

líneas.append(línea)

tmp+=1

si tmp>CONTAR:

descanso

más:

brk=True

imprimir 'tiempo de espera de lectura'

pausa

proceso_log(líneas)

imprimir "leer líneas:%s"%len(líneas)

if brk:

break

if brk:

print "break fuera"

if __name__ == "__main__":

main()