¿De qué país son los que intentan acceder ilegalmente a mi servidor por SSH?
Hola, soy un inútil. Estoy publicando un servidor FreeBSD de Vultr de forma pública, y me preguntaba quiénes son las personas que intentan acceder por SSH, así que lo estoy investigando. Por cierto, en el caso de FreeBSD, te envía un "security run output" a tu propio dominio, informándote sobre los intentos que ha habido.
Así es como se ve. Así que, usando geoip, vamos a echar un vistazo a qué país pertenecen las direcciones IP globales de las personas que intentan esto. Por cierto, el comando geoiplookup se puede instalar de la siguiente manera:
sudo pacman -S geoip
Este es el comando:
$ geoiplookup dirección IP
GeoIP Country Edition: RU, Russian Federation
Formateo de texto con bash
Primero, traeré la cadena de datos original "security run output" a mi ThinkPad (o a cualquier lugar) y luego la formatearé.
cat vultr | grep -oP "from.*port" | awk '{print $(NF-1)}' | sort | uniq > grepip
En el caso anterior, extraigo la descripción que contiene la cadena 'from' hasta 'port' de la descripción "security run output" llamada 'vultr', utilizando el valor que coincide con 'grep -o' y la expresión regular de Perl con 'P'.
Se verá algo así:
from dirección IP port
La razón por la que no usé awk en este punto es que la salida de error cambia si la contraseña es incorrecta o si el usuario objetivo no existe en mi servidor, si se usa el espacio como delimitador. Por lo tanto, extraje la cadena completa desde 'from' hasta 'port' para capturarlo todo. Luego, con awk, extraigo solo la dirección IP del primer registro al final, elimino las IP duplicadas con sort y uniq, y lo escribo en un archivo llamado grepip. Y luego, en bash, después de ejecutar geoiplookup en esta IP, haremos que nos dé un recuento ligero por país.
$ cat country.sh
#!/bin/bash
# Archivo de direcciones IP
INPUT="grepip"
# Archivo de salida
OUTPUT="countries.log"
# Inicialización
> $OUTPUT
# Ejecuta geoiplookup para cada dirección IP y obtiene la información del país
while IFS= read -r ip; do
geoiplookup "$ip" | awk -F: '{print $2}' >> $OUTPUT
done < "$INPUT"
# Agrupa y muestra la información del país
sort $OUTPUT | uniq -c | sort -tr
Ahora le damos permisos de ejecución.
chmod +x ./country.sh
Ahora solo hay que ejecutarlo.
$ ./country.sh
1 BE, Belgium
1 BG, Bulgaria
1 BR, Brazil
1 CH, Switzerland
1 HK, Hong Kong
1 HU, Hungary
1 IR, Iran, Islamic Republic of
1 IT, Italy
1 LT, Lithuania
1 MT, Malta
1 MX, Mexico
1 MY, Malaysia
1 NO, Norway
1 PA, Panama
1 PE, Peru
1 SE, Sweden
1 SK, Slovakia
1 TH, Thailand
1 TM, Turkmenistan
1 TZ, Tanzania, United Republic of
1 UZ, Uzbekistan
1 ZA, South Africa
2 RO, Romania
2 UA, Ukraine
3 PL, Poland
6 GB, United Kingdom
7 VN, Vietnam
8 CA, Canada
8 ID, Indonesia
9 RU, Russian Federation
9 SG, Singapore
10 FR, France
10 KR, Korea, Republic of
11 DE, Germany
11 NL, Netherlands
16 CN, China
18 IN, India
43 US, United States
Interesante...
Visualización de gráficos con Matplotlib para mayor claridad
Bueno, se entiende por el texto, pero si el número es grande, se vuelve difícil de leer, ¿verdad? Así que queremos mostrarlo en un gráfico.
Además, si lo convertimos en un script, podemos hacer que se genere como un trabajo cron. Por lo tanto, mostraremos los gráficos con Matplotlib, una útil biblioteca de Python. Instalación y código:
pip install matplotlib
cat AreYouFrom.py
#!/usr/bin/python3
import matplotlib.pyplot as plt
import collections
# Lee el archivo y cuenta los accesos por país
country_counts = collections.Counter()
with open('countries.txt', 'r') as file:
for line in file:
# Obtiene la información del país
country = line.strip().split(",")[1]
country_counts[country] += 1
# Ordena los datos
countries, counts = zip(*country_counts.most_common())
# Crea el gráfico
plt.figure(figsize=(10, 6))
plt.bar(countries, counts, color='skyblue')
plt.xlabel('Country')
plt.ylabel('Accesses')
plt.title('Accesses by Country')
plt.xticks(rotation=90)
plt.tight_layout()
# Exporta la imagen como archivo png
plt.savefig('accesses.png')
Con esto, podemos generar el gráfico y exportarlo como imagen.
chmod +x AreYouFrom.py
(¡Qué nombre de archivo tan de inglés de secundaria!)

¡Tachán! Parece que la mayoría proviene de Estados Unidos.
Agrupación por puertos a los que se intenta acceder por SSH
Ahora, investiguemos por los puertos a los que se intenta acceder.
Con esto, pude hacer grep solo para los puertos.
cat vultr | grep -oP "port [123456789].*ssh2$" | grep -oP "[123456789].* "
Esto se exporta como ports.txt.
Sin embargo, dado que todos los números de puerto son diferentes, al generar el gráfico, los dividiremos en bloques.
$ cat AreYouPort.py
#!/usr/bin/python3
import matplotlib.pyplot as plt
from collections import Counter
# Lee los números de puerto del archivo
with open('ports.txt', 'r') as file:
ports = [int(line.strip()) for line in file]
# Calcula la distribución de frecuencia de los números de puerto
counter = Counter(ports)
blocks = {}
for port, count in counter.items():
block = (port // 10000) * 10000
if block not in blocks:
blocks[block] = 0
blocks[block] += count
# Crea el gráfico
x = list(blocks.keys())
y = list(blocks.values())
plt.figure(figsize=(12, 6))
plt.bar(x, y, width=6000, color='skyblue', edgecolor='black')
plt.xlabel('Port Number')
plt.ylabel('Frequency')
plt.title('Port Numbers by Frequency')
plt.xticks(x, [f'{i}-{i+9999}' for i in x], rotation=45)
plt.grid(True, axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
# Guarda en un archivo PNG
plt.savefig('port_numbers.png')
Y entonces....

¿Por qué hay tantos intentos en números de puerto improbables, con valores superiores a 30,000...? Así que eso es todo por hoy. Nos vemos la próxima.