antibot-laravel maintained by marcelocardozo
Antibot para Laravel
Sistema de detecção e bloqueio de bots, proxies e VPNs para Laravel.
Detecta automaticamente ferramentas de automação (Selenium, Puppeteer, Playwright, Cypress, PhantomJS, etc.), analisa fingerprints do navegador, verifica proxies/VPNs via ProxyCheck.io e bloqueia visitantes suspeitos com base em um sistema de pontuação configurável.
Requisitos
- PHP 8.2+
- Laravel 11, 12 ou 13
- Chave de API do ProxyCheck.io (gratuito)
Instalação
composer require marcelocardozo/antibot-laravel
Publicar configuração, migrations e assets:
php artisan vendor:publish --provider="MarceloCardozo\Antibot\AntibotServiceProvider"
Ou publicar separadamente:
# Apenas configuração
php artisan vendor:publish --tag=antibot-config
# Apenas migrations
php artisan vendor:publish --tag=antibot-migrations
# Apenas assets (JS)
php artisan vendor:publish --tag=antibot-assets
# Apenas views (templates)
php artisan vendor:publish --tag=antibot-views
Executar as migrations:
php artisan migrate
Configuração
Adicione ao .env:
ANTIBOT_PROXYCHECK_API_KEY=sua-chave-aqui
ANTIBOT_TEST_IP=192.145.220.95
| Variável | Descrição |
|---|---|
ANTIBOT_PROXYCHECK_API_KEY |
Chave de API do ProxyCheck.io |
ANTIBOT_TEST_IP |
IP usado em localhost para testes (substitui 127.0.0.1) |
O arquivo config/antibot.php contém todas as opções:
return [
'route_prefix' => 'antibot', // Prefixo das rotas
'route_middleware' => ['web'], // Middleware das rotas
'pagina_inicial' => '/', // Página onde o antibot faz detecção + redirect
'redirect_url' => '', // Redirecionar após aprovação (vazio = libera a página)
'enviar_dados' => true, // Enviar dados do visitante na query string do redirect
'bloqueado_url' => '', // Bloqueados → 404 (vazio) ou URL customizada
'tempo_minimo' => 5000, // Tempo mínimo de verificação (ms)
'tela_carregamento' => 'spinner', // Template: 'spinner' ou 'cloudflare'
'score_minimo' => 50, // Score mínimo para bloquear
'bloquear_bot' => true, // Bloquear bots detectados
'bloquear_proxy' => true, // Bloquear proxies
'bloquear_vpn' => true, // Bloquear VPNs
'paises_permitidos' => ['BR'], // Países permitidos (vazio = todos)
'regras' => [ ... ], // 40+ regras de detecção com pontuação
];
Uso
Adicione a diretiva @antibot em todas as páginas Blade do seu site:
<!DOCTYPE html>
<html>
<head></head>
<body>
@antibot
<h1>Meu site</h1>
</body>
</html>
Comportamento por página
- Página inicial (
pagina_inicialno config): após aprovação, redireciona pararedirect_urlcom os dados do visitante na query string (IP, cidade, navegador, etc.). Seenviar_dadosforfalse, redireciona sem dados. - Demais páginas: após aprovação, simplesmente libera a página (remove o loading e exibe o conteúdo).
- Bloqueados: em qualquer página, redireciona para
bloqueado_urlou exibe o template 404.
Fluxo de verificação
- A página é ocultada e um loading é exibido
- 40+ verificações client-side são executadas
- APIs server-side analisam IP, proxy, VPN e User-Agent
- O resultado é salvo no banco de dados
- Se aprovado na
pagina_inicial: redireciona pararedirect_url - Se aprovado em outra página: libera a página
- Se bloqueado: redireciona para
bloqueado_urlou exibe 404
Redirecionamento
redirect_url — Após aprovação na página inicial
// config/antibot.php
// Padrão: não redireciona (libera a página)
'redirect_url' => '',
// Redireciona para outra página após aprovação
'redirect_url' => '/dashboard',
enviar_dados — Dados do visitante na query string
Quando enviar_dados é true (padrão), ao redirecionar para redirect_url, os dados do visitante são enviados como parâmetros na query string:
/dashboard?ip=177.0.0.1&city=Sao+Paulo&client_name=Chrome&os_name=Windows&...
Para desativar:
'enviar_dados' => false,
bloqueado_url — Visitantes bloqueados
// config/antibot.php
// Padrão: exibe o template 404 do pacote
'bloqueado_url' => '',
// Path relativo
'bloqueado_url' => '/acesso-negado',
// URL externa
'bloqueado_url' => 'https://google.com',
Facade
O pacote disponibiliza uma Facade para uso programático:
use MarceloCardozo\Antibot\Facades\Antibot;
// Resolver IP real do visitante
$ip = Antibot::resolveIp($request);
// Verificar proxy/VPN
$data = Antibot::check($ip);
// Retorna: ['ip', 'asn', 'provider', 'isocode', 'city', 'proxy', 'vpn', ...]
// Detectar dispositivo
$device = Antibot::detect($request->userAgent());
// Retorna: ['bot', 'client_name', 'device_type', 'os_name', ...]
// Flags de servidor suspeitas
$flags = Antibot::getServerFlags($request);
// Retorna: ['tool_ua', 'short_ua', 'no_accept_language', ...]
Model
O pacote registra o model Eloquent MarceloCardozo\Antibot\Models\Acesso que permite consultar os dados de detecção no seu código.
Campos disponíveis
| Campo | Tipo | Descrição |
|---|---|---|
id |
bigint | ID auto-incremento |
data_hora |
timestamp | Data/hora do acesso |
ip |
string | IP do visitante |
url |
text | URL acessada |
asn |
string | ASN do provedor |
hostname |
string | Hostname do IP |
provider |
string | Provedor de internet |
organisation |
string | Organização |
isocode |
string | Código do país (BR, US, etc.) |
regioncode |
string | Código da região |
city |
string | Cidade |
proxy |
string | "yes" ou "no" |
vpn |
string | "yes" ou "no" |
bot |
string | "yes" ou "no" |
client_name |
string | Navegador (Chrome, Firefox, etc.) |
client_type |
string | Tipo do client (browser, app, etc.) |
client_version |
string | Versão do navegador |
device_brand |
string | Marca do dispositivo |
device_model |
string | Modelo do dispositivo |
device_type |
string | Tipo (desktop, smartphone, tablet) |
os_name |
string | Sistema operacional |
os_platform |
string | Plataforma |
os_version |
string | Versão do SO |
os_family |
string | Família do SO |
bloqueado |
string | "true" ou "false" |
motivo_bloqueio |
text | Motivo(s) do bloqueio |
created_at |
timestamp | Criado em |
updated_at |
timestamp | Atualizado em |
Exemplo em Controller
<?php
namespace App\Http\Controllers;
use MarceloCardozo\Antibot\Models\Acesso;
class AntibotController extends Controller
{
// Listar todos os acessos com paginação
public function index()
{
$acessos = Acesso::latest()->paginate(20);
return view('antibot.index', compact('acessos'));
}
// Detalhes de um acesso específico
public function show(Acesso $acesso)
{
return view('antibot.show', compact('acesso'));
}
// Listar apenas bloqueados
public function bloqueados()
{
$bloqueados = Acesso::where('bloqueado', 'true')
->latest()
->paginate(20);
return view('antibot.bloqueados', compact('bloqueados'));
}
// Estatísticas
public function stats()
{
$total = Acesso::count();
$bloqueados = Acesso::where('bloqueado', 'true')->count();
$aprovados = Acesso::where('bloqueado', 'false')->count();
$proxies = Acesso::where('proxy', 'yes')->count();
$vpns = Acesso::where('vpn', 'yes')->count();
$bots = Acesso::where('bot', 'yes')->count();
$hoje = Acesso::whereDate('created_at', today())->count();
$bloqueadosHoje = Acesso::where('bloqueado', 'true')
->whereDate('created_at', today())
->count();
return view('antibot.stats', compact(
'total', 'bloqueados', 'aprovados',
'proxies', 'vpns', 'bots',
'hoje', 'bloqueadosHoje'
));
}
}
Consultas úteis
use MarceloCardozo\Antibot\Models\Acesso;
// Últimos 10 acessos bloqueados
$bloqueados = Acesso::where('bloqueado', 'true')
->latest()
->take(10)
->get();
// Acessos de um IP específico
$acessos = Acesso::where('ip', '177.0.0.1')->get();
// Verificar se um IP está bloqueado
$estaBloqueado = Acesso::where('ip', '177.0.0.1')
->latest()
->first()
?->isBloqueado(); // true ou false
// Acessos por país
$porPais = Acesso::select('isocode')
->selectRaw('count(*) as total')
->groupBy('isocode')
->orderByDesc('total')
->get();
// Acessos com proxy ou VPN
$suspeitos = Acesso::where('proxy', 'yes')
->orWhere('vpn', 'yes')
->latest()
->get();
// Total de bloqueados hoje
$total = Acesso::where('bloqueado', 'true')
->whereDate('created_at', today())
->count();
// Acessos de um navegador específico
$chrome = Acesso::where('client_name', 'Chrome')->get();
// Acessos mobile bloqueados
$mobileBloqueados = Acesso::where('device_type', 'smartphone')
->where('bloqueado', 'true')
->get();
Regras de detecção
O sistema usa 40+ regras com pontuação individual. Quando a soma dos pontos atinge o score_minimo (padrão: 50), o visitante é bloqueado.
Automação direta (80 pts cada)
| Regra | Detecta |
|---|---|
webdriver |
navigator.webdriver === true |
chromedriver |
Variáveis $cdc_ injetadas pelo ChromeDriver |
selenium |
Propriedades globais do Selenium |
puppeteer |
__puppeteer_evaluation_script__ |
playwright |
__playwright, __pw_manual |
cypress |
window.Cypress, window.cy |
phantomjs |
callPhantom, _phantom |
nightmare |
__nightmare |
webdriverio |
wdio, __wdio |
testcafe |
%testCafeDriverInstance% |
browserless |
__browserless, __chrome_aws_lambda |
stack_automacao |
Stack trace com nomes de ferramentas |
Fingerprint e ambiente
| Regra | Pts | Detecta |
|---|---|---|
ua_suspeito |
60 | Keywords de bot no User-Agent |
webdriver_patched |
60 | Undetected-chromedriver (getter customizado) |
chrome_falso |
30 | UA diz Chrome mas window.chrome ausente |
webgl_software |
30 | Renderer software (SwiftShader, Mesa) |
tela_zero |
30 | Dimensões da tela = 0 |
canvas_vazio |
25 | Canvas renderiza imagem vazia |
mobile_sem_touch |
25 | UA mobile sem suporte touch |
sem_color_depth |
20 | Color depth inválido |
platform_mismatch |
20 | UA e navigator.platform divergem |
perm_inconsistente |
20 | Permissões inconsistentes |
audio_vazio |
20 | Audio fingerprint vazio |
Para a lista completa, consulte config/antibot.php.
Desativar uma regra
// config/antibot.php
'regras' => [
'historico_curto' => ['ativo' => false, 'pts' => 5], // desativada
'webdriver' => ['ativo' => true, 'pts' => 80], // ativa
],
Templates de loading
Dois templates disponíveis, configuráveis em config/antibot.php:
spinner— Spinner minimalista (padrão)cloudflare— Visual estilo Cloudflare security check
'tela_carregamento' => 'cloudflare',
Para personalizar, publique as views e edite em resources/views/vendor/antibot/templates/.
Rotas registradas
| Método | URI | Descrição |
|---|---|---|
| GET | /antibot/config |
Configuração pública (JSON) |
| GET | /antibot/api/proxycheck |
Detecção de proxy/VPN |
| GET | /antibot/api/device-detector |
Detecção de dispositivo |
| POST | /antibot/api/salvar |
Salvar registro de acesso |
| GET | /antibot/templates/{template} |
Templates (404, spinner, cloudflare) |
O prefixo /antibot é configurável via config('antibot.route_prefix').
Licença
MIT