De que país são os que estão tentando acessar meu servidor via SSH ilegalmente!
Olá, sou um incompetente. Estou publicando um servidor FreeBSD da Vultr publicamente, e fiquei curioso para saber quem são as pessoas que estão tentando acessá-lo via SSH. A propósito, no caso do FreeBSD, ele me envia um "security run output" para o meu próprio domínio, informando-me sobre as tentativas que ocorreram.
Assim. Então, vamos usar o geoip para descobrir de que país são os endereços IP globais das pessoas que estão tentando acessar. A propósito, o comando geoiplookup pode ser instalado da seguinte forma:
sudo pacman -S geoip
O comando é este
$ geoiplookup endereço IP
GeoIP Country Edition: RU, Russian Federation
Formatação de texto com bash
Primeiro, vamos pegar a string de dados original "security run output" para o meu ThinkPad (ou qualquer outro lugar) e formatá-la.
cat vultr | grep -oP "from.*port" | awk '{print $(NF-1)}' | sort | uniq > grepip
No caso acima, extraímos a descrição que contém a string 'from' até 'port' do 'security run output' chamado 'vultr', usando a correspondência de grep com -o e expressões regulares Perl com -P.
Fica algo como a seguinte string.
from endereço IP port
A razão pela qual não usei awk neste ponto é que a saída de erro muda se a senha estiver incorreta ou se o usuário de destino não existir no meu servidor, então extraí a string de 'from' a 'port' para pegar tudo. Em seguida, uso awk para extrair apenas o endereço IP no primeiro registro do final, removo IPs duplicados com sort e uniq, e gravo em um arquivo chamado grepip. Depois, vamos fazer com que o bash execute geoiplookup para esses IPs e faça uma contagem simples por país.
$ cat country.sh
#!/bin/bash
# Arquivo de endereços IP
INPUT="grepip"
# Arquivo de saída
OUTPUT="countries.log"
# Inicialização
> $OUTPUT
# Executa geoiplookup para cada endereço IP e obtém informações do país
while IFS= read -r ip; do
geoiplookup "$ip" | awk -F: '{print $2}' >> $OUTPUT
done < "$INPUT"
# Agrega e exibe as informações do país
sort $OUTPUT | uniq -c | sort -tr
Agora, vamos dar permissão de execução.
chmod +x ./country.sh
Basta executar.
$ ./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
Entendi...
Exibindo gráficos com Matplotlib para facilitar a compreensão
Bem, embora seja compreensível como texto, torna-se difícil de ler quando o número é grande, então gostaríamos de exibir um gráfico, certo?
Além disso, se for um script, pode ser gerado como um trabalho cron. Portanto, vamos exibir um gráfico usando a útil biblioteca Python Matplotlib. Instalação e código
pip install matplotlib
cat AreYouFrom.py
#!/usr/bin/python3
import matplotlib.pyplot as plt
import collections
# Lê o arquivo e agrega o número de acessos por país
country_counts = collections.Counter()
with open('countries.txt', 'r') as file:
for line in file:
# Obtém informações do país
country = line.strip().split(",")[1]
country_counts[country] += 1
# Ordena os dados
countries, counts = zip(*country_counts.most_common())
# Cria o 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()
# Salva a imagem como arquivo png
plt.savefig('accesses.png')
Com isso, você pode gerar o gráfico e a imagem.
chmod +x AreYouFrom.py
(Que nome de arquivo parece inglês de ensino médio!)

Tcharam! Parece que a maioria é dos Estados Unidos.
Agregando por porta que está tentando SSH
Agora, vamos verificar por porta que está sendo acessada.
Com isso, consegui extrair apenas as portas com grep.
cat vultr | grep -oP "port [123456789].*ssh2$" | grep -oP "[123456789].* "
Isso é salvo como ports.txt.
No entanto, como todos os números de porta são diferentes, vamos separá-los em blocos para a saída do gráfico.
$ cat AreYouPort.py
#!/usr/bin/python3
import matplotlib.pyplot as plt
from collections import Counter
# Lê os números das portas do arquivo
with open('ports.txt', 'r') as file:
ports = [int(line.strip()) for line in file]
# Calcula a distribuição de frequência dos números das portas
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
# Cria o 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()
# Salva como arquivo PNG
plt.savefig('port_numbers.png')
E então....

Por que há tantas tentativas em números de porta improváveis, com valores acima de 30.000...? Então, por hoje é só. Até a próxima.