Created by ZynTarvo · Telegram: @zyntarvo · Nothing Is Impossible
The world’s first web Control Panel for Evilginx — plus a fully automatic installer.
No Linux wizardry. No coding. Enter the server IP and password, click Install, and get a working Evilginx C2 with a browser dashboard: phishlets, lures, sessions, domains, services.
Built for red teamers, pentesters, and anyone who wants Evilginx running in minutes instead of fighting the terminal for hours.
- Auto-install on Ubuntu
- Web C2 panel with login
- Manage phishlets, lures and captured sessions from the browser
- Session Map on Dashboard — unique session IPs on a dark world map; search by ID/IP, pick a country, click a marker to zoom country → district → street → max
- Proxy Manager — Linode Nanodes, custom
ip:port@login:pass, DataImpulse residential, Manual Rise / Manual Install Squid hops, assign to phishlets, live traffic - E-Terminal (Evilginx CLI) and a full Linux shell in the browser
- Live host Health (CPU, RAM, disk, traffic) and per-service journalctl follow
- AI-Assistant — OpenRouter chat + Autofix for TLS, certs, Evilginx process, config, and phishlet ops (your key stays on the C2 box, never in this repo)
This project does not steal anyone’s work.
Evilginx2 is the original engine by Kuba Gretzky (@mrgretzky). We clone it cleanly, then add a web control panel and a one-click installer on top — so people who are just starting in cybersecurity can use the tool without living in the command line.
Think of it as a companion: the same Evilginx, made simpler to install and operate. After clone, the installer patches core/http_proxy.go so an origin HTTP 429 is reported to the panel (/api/internal/egx-429) and Proxy Manager can rotate the hop.
Requirements: Windows PC with Python 3, and an Ubuntu 20.04 / 22.04 / 24.04 / 26.04 server (root SSH).
- Clone this repository
- Double-click
START.bat(or runpython evilginx_setup.py) - Fill in IP, SSH port, username, password
- Choose a button:
- INSTALL — full stack on a fresh server: Go 1.20, DNS port 53, clone kgretzky/evilginx2, 429 hook, build, upload the panel, systemd
- INSTALL ONLY CP — panel only. Does not install or replace Evilginx. Finds the binary already on the box (stock
build/evilginx, Proevilginx2, systemd unit, orPATH), writes the panel.envto that engine, and starts the C2. Extra flags from the existing process (-developer,-dashboard,-block-vpn, …) are kept. The 429 proxy-rotate hook is applied only whencore/http_proxy.gomatches; a custom/Pro binary is never rebuilt.
Panel URL: http://YOUR_SERVER_IP:8443
Login is the same as SSH (user + password).
Encrypted session, username / password, neon lynx mark. Also works on mobile:
The sidebar is the whole product. Each page below is what you see after login.
Home screen. At a glance:
| Block | What it shows |
|---|---|
| Active Phishlets | How many phishlets are currently enabled |
| Total Sessions | All captured visitor sessions |
| JWT Captured | Sessions where a JWT was taken (cookie value looks like eyJ…) |
| Server Uptime | How long the panel host has been up |
| Session Map | Unique session IPs on a dark world map (see below) |
| Sessions Timeline | Last 7 days: total / JWT / cookies / empty |
| Session Breakdown | Donut chart of JWT vs cookies vs empty |
| Recent JWT Sessions | Latest successful JWT rows with View / Delete |
Session Map (v3.5.6) — every captured session IP as a marker, same data as the Sessions table.
- Filters: ALL / WITH JWT / WITH TOKENS / EMPTY. Search and the country list follow the active filter
- Phishlet dropdown: default All; pick one phishlet and the map, counts, search, and country list follow it
- Markers: mint = cookies/tokens, purple = JWT, red = empty. A solid dot is one session from that IP; a ring (larger marker) means several sessions share the IP
- Live search (ID or IP): type as you go, pick a hit from the list (or Enter). The map flies to max zoom and opens the popup
- Country dropdown: lists countries with session counts; picking one fits that country on the map. Empty value restores the world view
- Click a marker to fly in four steps: country → district → street → max zoom (building / max tile level)
- Popup: IP, country, region, city, street (from the map tiles after street zoom), session IDs, JWT / tokens / empty
- + / − step those same zoom levels; the globe button and the search X restore the default world view (same as a page reload)
- Geo is a local DB-IP City Lite database on the C2 box plus an IP cache. No Mapbox key, no live geo HTTP API
YAML modules that tell Evilginx how to proxy a target site.
- + New Phishlet — create a new YAML in the phishlets folder
- Refresh — reload the list from disk / Evilginx
- Table: Name, Author, Hostname, Status (enabled / disabled), Visible
- Edit — open the in-browser YAML editor (find / replace / save)
- Enable / Disable — toggle live on the running Evilginx process
- Delete — remove the phishlet file
Service control + per-phishlet networking.
- ONLINE / OFFLINE — Evilginx process status
- STOP / RESTART — stop or bounce the engine
- Quick Setup — one wizard: domain, hostname, IPv4, lure path, enable
- Per row: Edit hostname / domain / IP / lure / blacklist, Enable / Disable, Delete
| Field | Meaning |
|---|---|
| DOMAIN | Base domain Evilginx answers on |
| PHISHLET HOSTNAME | Hostname bound to that phishlet |
| IPV4 EXTERNAL | Public IP of the box |
| LURE PATH | URL path of the lure (often /) |
| BLACKLIST MODE | Evilginx blacklist (off / unauth / all) |
The links you actually send. Each lure is tied to a phishlet.
- + New Lure — create a lure for a chosen phishlet
- Table: #, Phishlet, Path, URL, Paused (Active / Paused)
- Edit — path, redirect URL, UA filter, Open Graph title / description / image / URL
- Copy URL — copy the live lure link
- Delete — drop the lure
Outbound proxy fleet on Linode, run from the panel — no SSH, no cloud console. Typical path is four clicks: paste API key → pick a region → Deploy → pick a phishlet and Assign.
Connect
- Paste a Linode Personal Access Token (the panel stores it on the C2 box)
- Status line shows Linode connected and the Evilginx public IP (UFW on each proxy allows only that IP)
Deploy (a couple of clicks)
| Step | What you do |
|---|---|
| 1 | Set how many servers (Nanode 1GB) |
| 2 | Search a region by city / country / code, pick up to N regions |
| 3 | Click Deploy Proxies |
The progress bar covers the whole job, not just VM create: Linode boot → SSH → cloud-init finished → apt idle → 5 second settle → Squid on port 50100 with auth. 100% means the proxy actually answers. Failed installs are kept (Repair / Destroy) — the panel never auto-deletes a Linode.
Custom proxies
Paste your own hops — no Linode required. Same assign list, cards, charts, and carousel as the Nanode fleet.
- One proxy per line:
ip:port@login:pass(password may contain@) - Also accepted:
user:pass@ip:port,ip:port:user:pass,ip:port(no auth) - PROTOCOL applies to the whole paste. Evilginx types: HTTP, HTTPS, SOCKS5, SOCKS5H
- Add Proxies — bulk add. Duplicates are skipped
- Custom rows show a purple custom badge (Linode stays a cloud icon) so you can tell them apart
- Tick them on a phishlet and Assign — they join the pool. If Carousel is on for that phishlet, custom hops rotate with Linode hops
- Instance card: IP, geo region, endpoint, protocol, assigned phishlets, sidecar traffic. Remove deletes the panel record only (the remote proxy is not touched). Start / Stop / Restart stay Linode-only
Manual Rise
Same Squid as a Linode Nanode, as a bash script you paste on any Ubuntu 22.04/24.04. The lightbox shows generated user / password / port 50100. Copy Script, run as root on the hop. The script detects that machine’s public IP, opens 50100/tcp from any address, and prints ADD_LINE=ip:50100@user:pass — paste that line into Add Custom Proxies as HTTP.
Manual Install
The panel SSHs into a server you already have and installs that same Squid (no paste, no Linode). Fields: server IP, SSH port, SSH login, password. Toggle PEM key instead of password if the box has no password auth (paste or upload a private key, optional passphrase). Start waits for SSH, installs Squid on 50100, checks CONNECT from the C2, and adds the hop as a custom HTTP proxy. Credentials for SSH are used once for the install and are not stored in git.
DataImpulse residential
Optional rotating residential gateway. Paste your DataImpulse login/password (and optional ISO country, host, port) in the Proxy Manager card. Enable on a phishlet detaches Linode/custom hops for that phishlet only. Each visitor gets a sticky sessid; after ~20s idle — or on an auth 429 — the next visit gets a new sessid → new IP. Gateway credentials stay in linode_proxy.json on the C2 box, never in this repository. Disable / Detach / the chip × turns it off without deleting the Linode fleet.
Assign to a phishlet
- Choose the phishlet, tick proxy IP addresses (Linode, custom, and DataImpulse), click Assign
- Detach / chip × unbinds that hop (Linode VM stays; DataImpulse is only disabled for that phishlet)
- Current assignments shows every phishlet → IP chip (active hop marked with ●)
Carousel sits between Assign and Detach. It is per phishlet (the cyan CAROUSEL badge on the row means it is on).
| After 3 origin 429s in 15 minutes | |
|---|---|
| Off (default) | 429 does nothing. Assigned hop(s) stay as you set them. No jump to another proxy and no fallback to the Evilginx server IP. |
| On | Current hop stays assigned and is moved to the end of the queue. Traffic switches to the next live proxy. A → B → C → A. Live Squid CONNECT tunnels of the old hop are closed so the switch is immediate. |
A node that is still booting is never rotated off. Manual Detach / the chip × still unbind as before.
Evilginx is restarted once on Assign so outbound traffic for that phishlet goes through the pool. Origin HTTP 429 is reported by the patched Evilginx binary (/api/internal/egx-429).
Traffic
Charts, the assignment chips, and Traffic Out on each proxy card update live (same idea as a new JWT on the dashboard). Counters live in RAM on the panel — no extra load on Evilginx and no extra origin requests, even when traffic is heavy. Linode CPU on the cards still refreshes on a slow timer.
- Outbound per proxy — bars labelled by public IP (not Linode label), split by phishlet
- Share by phishlet — donut of total outbound bytes / requests
- Table: phishlet, instance name, IP, bytes out / in, request count
- History is kept after detach, so you still see what that IP already carried
Instance cards
Each Nanode is a card: IP, region + flag, endpoint :50100, Linode power state, CPU, live in/out.
- Assigned Phishlets — current bind only
- Traffic Out — cumulative bytes per phishlet (kept after detach)
- Destroy — delete the Linode
- Start / Stop / Restart — Linode power (assignments are kept)
- Repair — wait for full boot + 5s, then install/verify Squid (instance is never deleted)
The bell (notification centre) logs deploy, repair, 429 rotate, and power events.
Browse the server from the browser: /root, evilginx2, evilginx-panel, phishlets, configs.
- Up / Home — navigate
- New File / New Folder
- Make Service — turn a script into a systemd unit from the UI
- Refresh
- Click a file to view / edit (YAML, configs, etc.)
- Columns: Name, Size, Modified, Perms
systemd manager so you are not SSH-ing just to restart a daemon.
- Filters: RUNNING / CUSTOM / ALL
- + New Service — register your own unit
- Per service: Stop, Restart, autostart toggle icons, Logs, Live journal, Show (script path + Modify), Delete (custom units)
evilginx-panelis tagged CUSTOM — that is this web panel
Same lightbox as the other panel forms. The cyan broadcast button on a service row (or LIVE inside snapshot logs) runs journalctl -u SERVICENAME -f.
- Last lines plus new events in real time
- Follow starts only when you open the window — zero extra load while it is closed
- Stops on CLOSE, Escape, or opening another modal
- One live follow at a time
Telegram alerts when a session actually has tokens — not every empty hit.
- Telegram Bot Token + Chat ID
- Toggles: master enable, notify on JWT, notify on any cookies / tokens
- Save Settings / Stop / Send Test / Reset Sent IDs
- Status line shows whether the watcher is active and how many messages were sent
The captured-session database.
- Filters: ALL / WITH JWT / WITH TOKENS / EMPTY — each button shows how many records match that filter
- The line under the filters repeats the count for the active filter (and for search)
- Search by ID, IP, username
- Refresh / CLEAR DATABASE
- Columns: ID, phishlet, remote IP, cookie count, JWT badge, username, password, time
- Click the purple JWT badge to open the decoder lightbox
- View — full session detail (cookies, tokens)
- Delete — remove one row
Same lightbox as the other panel forms. Click JWT on a session row (or YES / the JWT button inside session detail).
- Full encoded token, colored in three parts like jwt.io (header / payload / signature)
- Decoded header and payload as JSON
- Validity dates in plain language, not Unix timestamps — e.g.
20 августа 2026 — 19 августа 2031 - Separate issued (
iat) and expires (exp) rows with time - Copy token
- If one session has several JWTs, switch between them by cookie name
Mobile view stacks the same table as cards:
Live Evilginx console in the browser (xterm.js). Same commands as the Evilginx CLI: phishlets, lures, config, sessions.
- Restart / Stop / Start the Evilginx process from the toolbar
- Output, tables, and the
:prompt stay on the page — no extra SSH client
A real Linux shell on the server — login bash, same as if you opened a normal console over SSH.
- Full interactive PTY:
ls,apt,systemctl, editors, pipes, Ctrl+C - Runs as the panel user (root on a default install), home directory,
.bashrcloaded - Restart if you typed
exitor the shell died - Independent from E-Terminal: Evilginx CLI and Linux do not share a session
Live host metrics under Terminal in the sidebar. Cheap /proc reads only while this page is open.
- Banner: All systems nominal (or warning / critical)
- Gauges: CPU, RAM, Disk, Inbound, Outbound
- Chart: CPU %, RAM %, inbound KB/s
- Load 1 / 5 / 15, RAM used, disk free
- Status pills: HEALTHY / WARNING / CRITICAL
- Timer stops when you leave the page or hide the tab — the server is not polled in the background
Sidebar item under Health. On-server operator that talks to OpenRouter — you paste your own API key in the panel. The key is stored only on the C2 box (/root/evilginx-panel/ai_openrouter.json, mode 600). It is not shipped in this repository and the installer never uploads one.
First run
- Open AI-Assistant
- Paste an OpenRouter key (
sk-or-v1-…) → Connect - Pick a model from the searchable dropdown (Free / Paid, vision tag)
- Autofix and chat unlock
AUTOFIX
One click. The panel collects live diagnostics (Evilginx process, config.json, phishlets, ports, disk, certs) and the model is required to call tools — it does not stop at “let me check”. Typical jobs:
- Let's Encrypt 429 / autocert ON with too many hosts
- Install an existing wildcard cert into
crt/sites/<domain>/ - Restart / start / stop Evilginx
- Broken
unauth_url, empty lure hostname, phishlet enable - systemd / log / disk checks on the box
Live steps show in the chat (tool name + short result). English or Russian — it answers in the language you type.
CHAT
Same tools as Autofix, plus your message. You can:
- Type a problem or paste logs
- Attach a screenshot / photo (paperclip, drag-and-drop, or Ctrl+V)
- Attach small files (
.txt,.log,.json,.yaml,.conf,.pem,.crt, up to 8 MB)
Send analyzes and can apply a fix on the server.
What it will not do
- Dump captured sessions, cookies, passwords, JWT,
.env, or the OpenRouter key - Run blocked shell (
rm -rf /,wget/curloutbound,passwd, reboot, …) - Rewrite a working phishlet YAML unless the file is invalid
Layout
- Desktop / tablet: Model on the left (search is inside the dropdown), masked key hint, Disconnect, Clear chat
- Phone: settings collapse to one model strip; Autofix is a slim bar; compose stays one row (clip + input + send)
Disconnect removes the key from the box. Clear chat wipes the thread file, not the key.
START.bat → launch the GUI installer
evilginx_setup.py → SSH installer (Ubuntu 20.04–26.04)
payload/ → panel that gets uploaded to the server
app.py
ai_assistant.py → OpenRouter Autofix + chat (key file is created on the server, not in git)
proxy_engine.py → Linode fleet, custom hops, DataImpulse, Manual Rise/Install Squid, 429 rotate, carousel, live traffic
patches/ → apply_egx_429_hook.py (after clone, before go build)
templates/ → login + dashboard
static/ → lynx logo + favicons
geo/ → DB-IP City Lite MMDB (downloaded at install, not in git)
docs/screenshots/ → UI shots from the demo video
If this panel saved you time and you want to say thank you, USDT on Ethereum (ERC-20) is enough:
0xFd051b2267b75C9c2513Cb9BAd546e3C51d5dB44
No pressure. Use the tool, learn, and pass it on.
Telegram: @zyntarvo
- Evilginx2 — Kuba Gretzky
- Control Panel + Auto Installer — ZynTarvo · Telegram @zyntarvo
ZynTarvo — Nothing Is Impossible


































