--- name: TAP Solver migrado pra ADV-22 (24/7 sem PC) 2026-04-30 description: TAP Kasada bypass funcionando 100% headless na VM Ubuntu remota com IP residencial BH; PC do Jesiel agora opcional type: project originSessionId: 4f44a92f-ea25-4ff4-b6f6-022e683fdd40 --- # TAP RESOLVIDO 24/7 SEM PC — VM ADV-22 — 2026-04-30 ## A vitória **Kasada do TAP aceitou Chrome headless launchado por Playwright na ADV-22.** Diferença chave vs. o servidor scraper US (que era bloqueado): IP público da VM é `186.247.226.26 — Belo Horizonte, MG, Brasil` (residencial nativo). Não precisa nem do exit-node Android. ## Testes validados | Teste | HTTP | Tempo | Voos | Source | |---|---|---|---|---| | CNF→LIS 2026-06-15 1ª busca | 200 | 30.3s | 194 | kasada_local | | GRU→OPO 2026-07-20 | 200 | 24.3s | 223 | kasada_local | Voo exemplo CNF→LIS: TP 104, 17:25→06:45 9h20min direto, Business Top Executive R$ 14.707,96. ## Arquitetura final ``` [Servidor scraper 173.208.187.154 PM2 15 (scraper-tap-milesgo, porta 3022)] │ └── http://100.91.20.22:9090/search ───Tailscale───> │ [VM ADV-22 / 186.247.226.26 Belo Horizonte] ├── systemd: tap-solver.service (Node 20 + Playwright-core) ├── Google Chrome 147 stable headless --remote-debugging-port=9222 ├── user-data-dir: /home/customer/skymilhas-chrome-profile ├── systemd: ts-keepalive.service (ping 100.126.1.5 a cada 15s) └── tailscaled (zieltelles@ tailnet) ``` ## Arquivos chave **No servidor scraper (173.208.187.154):** - `/opt/skymilhas/scrapers/tap/index.js` linha 13: `const SOLVER_URL = 'http://100.91.20.22:9090';` - Backup: `/opt/skymilhas/scrapers/tap/index.js.bak-pre-adv22-` - Chave SSH pra acessar VM: `~/.ssh/id_ed25519_adv22` (id pública instalada em authorized_keys da VM) **Na VM ADV-22 (100.91.20.22, porta SSH 2222):** - `/opt/tap-solver/tap-solver.mjs` — solver Linux (lança Chrome via spawn + connectOverCDP) - `/opt/tap-solver/package.json` — playwright-core ^1.55.0 - `/opt/tap-solver/node_modules/playwright-core` — instalado - `/etc/systemd/system/tap-solver.service` — autostart - `/etc/systemd/system/ts-keepalive.service` — mantém Tailscale direct vivo - `/etc/sudoers.d/customer-nopasswd` — sudo passwordless pro customer - `/home/customer/.ssh/authorized_keys` — chave pública do scraper-server - `/var/log/tap-solver.log` — log do solver (append-only) **No PC Jesiel (working directory):** - `tap-local/adv22-install.sh` — instalação Node 20 + Chrome stable + libs - `tap-local/adv22-solver/tap-solver.mjs` — fonte do solver - `tap-local/adv22-solver/package.json` - `tap-local/adv22-solver/tap-solver.service` - `tap-local/adv22-solver/install-solver.sh` — deploy script ## Como acessar a VM **Via skymilhas-server (única rota confiável — tem keep-alive):** ```bash # Do PC Jesiel: echo "y" | "/c/Program Files/PuTTY/plink.exe" -ssh customer@173.208.187.154 -pw "CRBtGb5ftDeZ" -batch "ssh -i ~/.ssh/id_ed25519_adv22 -p 2222 -o StrictHostKeyChecking=no customer@100.91.20.22 'COMANDO'" ``` **SSH direto do PC Jesiel:** instável (NAT do PC + Tailscale oscila). Sempre usar via scraper-server. **Comandos úteis na VM:** ```bash sudo systemctl status tap-solver # ver estado solver sudo systemctl restart tap-solver # restart manual (Chrome reinicia junto) sudo journalctl -u tap-solver -f # acompanhar log em tempo real tail -f /var/log/tap-solver.log # log do solver curl http://127.0.0.1:9090/health # status (dentro da VM) curl http://127.0.0.1:9090/restart-chrome # força restart do Chrome curl http://127.0.0.1:9090/cache/clear # limpa cache de buscas ``` ## Setup feito (cronologia) 1. **Tailscale na VM**: instalado via `curl -fsSL https://tailscale.com/install.sh | sh`. Migrou de tailnet `samueltelles2022@` (IP antigo 100.107.110.23) pra `zieltelles@` via `tailscale logout` + `tailscale up --ssh`. 2. **UFW**: liberado `allow in on tailscale0`. Tailscale SSH foi desabilitado depois (interfere em SSH passwordless). 3. **SSH key**: chave ed25519 gerada no scraper-server, pública instalada em `~/.ssh/authorized_keys` da VM, conexão via porta 2222 (porta 22 fica intercept por Tailscale SSH check). 4. **sudo nopasswd**: configurado em `/etc/sudoers.d/customer-nopasswd` pra simplificar sessões automatizadas. 5. **Node 20 LTS**: via Nodesource APT. 6. **Chrome 147 stable**: via repo Google (`https://dl.google.com/linux/chrome/deb`). 7. **Chrome runtime deps**: libnss3, libxss1, libasound2t64, libatk-bridge2.0-0, libgtk-3-0, libgbm1, fonts-liberation, libu2f-udev, xdg-utils, xvfb. 8. **Playwright-core**: `npm install --omit=dev` em `/opt/tap-solver`. 9. **Solver Linux**: lança Chrome filho via spawn (`--remote-debugging-port=9222 --user-data-dir=... --headless=new --no-sandbox`) e conecta via `connectOverCDP`. 10. **systemd unit tap-solver**: enable + start; auto-restart on failure (RestartSec=5). 11. **systemd unit ts-keepalive**: pinga skymilhas-server a cada 15s pra manter rota Tailscale direct viva (sem isso a rota fechava por idle e SSH/curl externo dava timeout). 12. **Scraper apontado**: `SOLVER_URL` em `/opt/skymilhas/scrapers/tap/index.js` mudou de `100.121.140.97:9090` (PC) pra `100.91.20.22:9090` (VM); `pm2 restart scraper-tap-milesgo`. ## Pegadinhas que nos pegaram - **Tailscale SSH check**: quando ativo (`--ssh`), porta 22 da VM exige autorização interativa via URL pra cada SSH novo. Bypass: usar porta 2222 (sshd nativo). - **Tailnet errada inicialmente**: VM autenticou em `samueltelles2022@` por ser conta Google diferente; precisou logout + login com `zieltelles@`. - **Conexão Tailscale fechando por idle**: sem tráfego periódico, NAT residencial fecha o "buraco" UDP. Solução: `ts-keepalive.service` com ping a cada 15s. - **PC do Jesiel não pinga ADV-22**: NAT do roteador do PC + NAT do roteador da VM = double NAT que Tailscale não consegue furar direct. Tudo passa pelo skymilhas-server (que tem IP público fixo). ## PC do Jesiel — pode desligar? **Sim, mas testa antes** o tap-solver do PC ainda está enable no Startup do Windows? Se sim, ele continua rodando em paralelo. Não atrapalha (servidor aponta pra VM agora), mas consome recursos do PC. Pra parar definitivo: ```powershell # Parar tap-solver do PC e desabilitar autostart Stop-ScheduledTask -TaskName "TAP Solver" -ErrorAction SilentlyContinue Disable-ScheduledTask -TaskName "TAP Solver" -ErrorAction SilentlyContinue Get-Process -Name "node","chrome" -ErrorAction SilentlyContinue | Where-Object { $_.MainWindowTitle -like "*TAP*" -or $_.Path -like "*tap-local*" } | Stop-Process -Force ``` Ou simplesmente: NÃO rodar mais o `START-TAP-SOLVER-SAFE.bat` no boot. ## Pendências (baixa prioridade) - ~~Watchdog externo monitorando `/health` da VM~~ ✅ feito: `tap-watchdog.service` no scraper-server, /var/log/tap-watchdog.log, auto-restart Chrome se chrome_down >60s - ~~Métricas no painel monitor (PM2 26)~~ ✅ feito: tap-solver-adv22 aparece em /api/services com chrome status, uptime, totalSearches, successfulSearches, chromeRestarts - ~~Backup chrome-profile~~ ✅ feito: cron diário 4h, retain 7, /opt/tap-solver/backups/, logrotate 14d - ~~Adicionar campos no scraper TAP~~ ✅ feito 2026-04-30: bagagemInclusa, reembolsavel, fareBasis, rbd, tarifaCodigoComercial, tarifaHierarquia, superSaver, descontoMilesGo, descontoPromocode, descontoSlider, taxaOnlineBooking, taxaCartao, avisos {codeshare,outraCompanhia,embargo,economy,mudancaAeroporto}, haul, aeronaveModelo (decodifica equipment IATA→nome humano) - ~~Propagar campos no gateway~~ ✅ feito: tanto `voosPorEmpresa` quanto `todosVoos` repassam tudo. Gateway em `/opt/skymilhas/server.js` linhas ~6135 (vooCompleto) e ~6210 (todosVoosOrdenados). Backup `.bak-pre-tapfields-` - ~~Paralelizar solver multi-tab~~ ✅ feito: até 3 buscas simultâneas no mesmo Chrome com queue de espera. `MAX_CONCURRENT` env var (default 3). Validado: 3 paralelas em ~32s vs 90s serial. Health endpoint expõe activeJobs/queueLen/peakConcurrent - ~~Frontend não buscava dados~~ ✅ feito 2026-04-30: `modo_dev_cache=1` no banco bloqueava chamadas reais à API. Desativado (`UPDATE configuracoes SET valor='0' WHERE chave='modo_dev_cache'`) - ~~Frontend só mostrava Economy~~ ✅ feito: scraper agora dedupa voos por flightNumber e popula `tarifasDisponiveis: [...]` com TODAS as fareFamilies (Economy 4 + Premium Economy 2 + Business 2 = 8 por voo). Cada voo flag `isPrimaryFare` true pra menor preço - ~~Lentidão front mesmo com cache~~ ✅ feito: gateway tinha `JSON.stringify(data, null, 2)` (pretty-print = 50% overhead) + sem gzip. Removido pretty-print + ativada compressão gzip dinâmica (level 6, threshold 2KB) em sendJson. Payload caiu 1.82MB → 59KB (97% redução). Tempo network site→gateway: 1.9s → 0.48s (4x). PHP já manda `Accept-Encoding: gzip` (CURLOPT_ENCODING vazio decodifica automático) - Tarifa em milhas (resgate Miles&Go): TAP retorna `points: null` em buscas por dinheiro. Precisa endpoint separado `?awardSearch=true` ou login Miles&Go. Não investigado a fundo ainda **Why:** Jesiel queria solução 24/7 sem depender do PC dele. ADV-22 (VM Ubuntu 24.04 remota com IP residencial BH) resolveu — Kasada aceita o Chrome headless lá, diferente do servidor scraper US que era 100% bloqueado. **How to apply:** TAP agora roda independente. Jesiel pode desligar PC sem afetar o sistema. Se quiser replicar pra outras cias com Kasada/anti-bot, mesmo padrão funciona desde que IP da VM seja residencial brasileiro nativo.