marcelocardozo / antibot-laravel
Sistema de detecção e bloqueio de bots, proxies e VPNs para Laravel
Package info
github.com/marcelocardozo/antibot-laravel
Language:JavaScript
pkg:composer/marcelocardozo/antibot-laravel
Requires
- php: ^8.2
- illuminate/database: ^11.0|^12.0|^13.0
- illuminate/http: ^11.0|^12.0|^13.0
- illuminate/routing: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
- matomo/device-detector: ^6.0
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
- phpunit/phpunit: ^11.0
README
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