A lightweight, resilient web control plane for creating, monitoring, and synchronizing multi-core tunnels between Iranian and global nodes.
Hawal (ههواڵ, Kurdish for “friend” or “companion”) maintains all tunnel configurations in a single centralized panel and synchronizes them continuously to lightweight agents on your edge servers.
🌐 Languages: English | 🇮🇷 فارسی (Persian)
- ✨ Highlights & Features
- 🏛️ Architecture Overview
- 📋 System & Network Prerequisites
- ⚡ Quick & Easy Installation (1-Line Installer)
- 🐳 Alternative Deployment (Docker Compose)
- 🔒 Securing the Panel with SSL & Reverse Proxy
- 🎛️ Tunnel Cores & Selection Guide
- 🛡️ Paqet Deep-Dive & Real Wire Accounting
- 🛠️ Operations, Maintenance & Troubleshooting
- 📚 Documentation & Wiki
- 🔐 Security & Responsible Use
- 🤝 Contributing & License
- Centralized Web Control Plane: Create, edit, and stop multi-port tunnels from an intuitive browser dashboard.
- Zero-Touch Agent Enrollment: Deploy node agents with a single pre-authenticated
curlcommand generated by the panel. - Four Integrated Tunnel Cores:
- ⚡ Hawal Stealth Core: Native Python/C engine with packet padding and
TCP_NODELAY. - 🚀 Backhaul: High-concurrency multiplexed tunnels over WebSocket, TCP, or TLS.
- 🛡️ Paqet: Raw TCP packet manipulation combined with KCP congestion control for unstable links.
- 👻 GOST v3: Authenticated relay forwarding supporting TLS, WebSocket, KCP, and QUIC (Hysteria2 compatible).
- ⚡ Hawal Stealth Core: Native Python/C engine with packet padding and
- Real-Time Observability: Node CPU/RAM telemetry, active tunnel latency ping, packet-loss tracking, and live connection status.
- Accurate Wire Traffic Accounting: Exact destination raw-table accounting for Paqet (measuring actual wire bytes including KCP overhead).
- Embedded Database: Standalone SQLite database with zero external dependencies (no Redis or PostgreSQL needed).
- Systemd & Docker Ready: Full lifecycle management via native systemd services or Docker Compose.
Browser / Admin
│
▼
┌──────────────────────┐ Configuration Sync ┌──────────────────────┐
│ Hawal Master Panel │◄─────────────────────────────────────►│ Node Agent (Foreign) │
│ (Web UI, SQLite DB) │ (Heartbeat: 3–5s) │ /opt/hawal/agent.py │
└──────────────────────┘ └──────────┬───────────┘
▲ │
│ Sync │
┌──────────┴───────────┐ │
│ Node Agent (Iran) │ Encrypted Core Transport │
│ /opt/hawal/agent.py │═════════════════════════════════════════════════╪══════════════════╗
└──────────┬───────────┘ (Stealth / Backhaul / Paqet / GOST) │ ║
│ ▼ ║
▼ Target Service (Xray, 3X-UI) ║
Entry Port (Iran) (Listening on 127.0.0.1) ║
(e.g., 443, 8443) ║
Before starting the installation, ensure your environment meets the following technical requirements:
| Component | Minimum Specification | Recommended Specification |
|---|---|---|
| Operating System | Ubuntu 20.04+ / Debian 11+ | Ubuntu 22.04 / 24.04 LTS or Debian 12 |
| CPU / Architecture | 1 vCPU (x86_64 or aarch64) | 2+ vCPU (x86_64) |
| RAM | 512 MB | 1 GB or higher |
| Privileges | root or sudo access |
root access (required for systemd & iptables) |
| Dependencies | Python 3.8+, curl, tar |
Automatically verified and installed by script |
While accessing the panel via raw IP (http://SERVER_IP:9090) works for initial trials, using a domain or subdomain with SSL is strongly recommended for production deployments:
- Create an A-Record:
Point your chosen subdomain (e.g.
panel.yourdomain.com) to the public IP of the Master Panel server. - Cloudflare Consideration (DNS-Only Mode):
If managing DNS through Cloudflare, set the record to DNS-Only (Grey Cloud ⚪).
Note: Direct TCP connectivity avoids HTTP timeout disconnects on agent sync heartbeats. If proxied (Orange Cloud 🟠), ensure WebSockets are enabled in the Cloudflare dashboard.
- Reverse Proxy (SSL/TLS):
Run Nginx or Caddy on the panel server to terminate TLS on standard port
443and forward requests tohttp://127.0.0.1:9090. See our detailed Domain & SSL Reverse Proxy Guide.
Make sure your cloud firewall (Hetzner, OVH, DigitalOcean, AWS, etc.) permits traffic on these ports:
| Port Type | Example Ports | Direction & Protocol | Purpose |
|---|---|---|---|
| Panel Web Port | 9090 (or 443 via Reverse Proxy) |
Inbound TCP | Web dashboard access & Agent sync |
| Dedicated Core Port | 3107, 9999 |
Inbound TCP/UDP on Foreign VPS | Encrypted tunnel backbone between Iran and Kharej |
| User Forwarded Ports | 443, 8443, 2083 |
Inbound TCP/UDP on Iran VPS | Client-facing traffic entry points |
⚠️ Important: Never use the same port number for both the Core Port and a Forwarded Port. The core port handles the internal tunnel transport; forwarded ports are the external entry points.
Hawal provides an automated, zero-configuration installation script. Can you install easily? Yes, in under 60 seconds.
Run the following command on the server chosen to host the Hawal control plane:
curl -fsSL https://raw.githubusercontent.com/dalroot/hawal/master/install-panel.sh | bashWant to run on a custom port? Use the --port parameter:
curl -fsSL https://raw.githubusercontent.com/dalroot/hawal/master/install-panel.sh | bash -s -- --port 9090Once complete, open your browser and navigate to:
http://YOUR_SERVER_IP:9090
You do not need to configure configuration files on edge servers manually:
- Open the Hawal web dashboard and navigate to Node Management.
- Click Add Node, assign a descriptive name (e.g.
Hetzner-FrankfurtorIran-Tehran), and select the role (iranorkharej). - Copy the panel-generated enrollment command and execute it on the corresponding server:
curl -fsSL "http://PANEL_IP:9090/install?token=YOUR_NODE_TOKEN&role=kharej&name=Germany" | bash(If you configured a domain with SSL, substitute the URL with https://panel.yourdomain.com/install?...)
The agent will be installed as a systemd background daemon (hawal-agent.service) and its status in the dashboard will update to Online within a few seconds.
- Go to Tunnel Management in the panel and click Create Tunnel.
- Select your Iran Node and Foreign Node.
- Choose a tunnel core (e.g. Hawal Stealth Core or Backhaul).
- Assign a unique Core Port (e.g.
3107). - Configure the Port Mapping forwarding rules:
443=127.0.0.1:443 8443=127.0.0.1:8443 - Click Save & Deploy. Both node agents will automatically receive the instructions and establish the tunnel in real time.
For containerized environments, the Hawal panel can be launched via Docker Compose:
# Clone the repository
git clone https://github.com/dalroot/hawal.git
cd hawal
# Start the panel daemon
docker compose up -d --build
# View real-time logs
docker compose logs -f hawal-panelThe Docker container operates in host network mode and binds directly to port 9090.
To access your panel securely over HTTPS (https://panel.yourdomain.com):
# 1. Install Nginx and Certbot
sudo apt-get update && sudo apt-get install -y nginx certbot python3-certbot-nginx
# 2. Add Reverse Proxy Block
sudo bash -c 'cat > /etc/nginx/sites-available/hawal << EOF
server {
server_name panel.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:9090;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF'
# 3. Enable site and issue free SSL
sudo ln -sf /etc/nginx/sites-available/hawal /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d panel.yourdomain.com👉 For complete instructions including Caddy automatic SSL and Cloudflare nuances, consult the Domain & SSL Reverse Proxy Guide.
| Core | Recommended Scenario | Supported Transports | Operational Notes |
|---|---|---|---|
| ⚡ Hawal Stealth Core | General use, default resilient setup | stealth |
Proprietary padding, low CPU overhead, TCP_NODELAY optimization. |
| 🚀 Backhaul | High-throughput multiplexed traffic | ws, tcp, tcpmux, tls |
Industry standard multiplexing. Core port must remain distinct from entry ports. |
| 🛡️ Paqet | Highly restricted links with heavy packet loss | kcp |
Raw TCP socket packets with KCP. Requires root and dedicated server-side core port. |
| 👻 GOST v3 | Versatile fallback & multi-protocol relay | tls, ws, kcp, quic |
Encrypted relay carrying both TCP & UDP traffic (full QUIC / Hysteria2 compatibility). |
- Default Choice: Start with Hawal Stealth Core. It requires zero manual kernel tuning and delivers excellent resilience.
- High Bandwidth: Use Backhaul over WebSocket (
ws) ortcpmuxwhen standard multiplexing satisfies your ISP conditions. - Severe Jitter & Packet Loss: Choose Paqet if you are experienced with raw socket firewall rules. Never use ports
80or443as the Paqet core port (use3107,9999, etc.). - QUIC / UDP Traffic: Use GOST v3 when forwarding Hysteria2 or UDP-intensive services alongside standard TCP.
Paqet constructs raw TCP packets injected at the packet-filter layer and manages transport via KCP. Because packets bypass standard kernel sockets:
- Tools like
ssor/proc/PID/iocannot report Paqet traffic volume. - Hawal solves this by directly harvesting byte counters from the dedicated
rawtable ofiptableson the destination node. - The reported volume represents genuine wire usage, including retransmissions and KCP framing overhead.
- Rules for
NOTRACKand RST suppression are automatically provisioned and maintained byhawal-agent.
# Hawal Interactive CLI Dashboard (on any node)
hawal
# Check service status
systemctl status hawal-panel --no-pager # On Master Panel
systemctl status hawal-agent --no-pager # On Edge Nodes
# Inspect real-time service logs
journalctl -u hawal-panel -f # Panel logs
journalctl -u hawal-agent -f # Agent logs
# Check listening network ports
ss -lntup | grep -E '9090|3107'
# Restart services safely
systemctl restart hawal-panel
systemctl restart hawal-agent| Issue | Probable Cause | Solution |
|---|---|---|
| Node status is Offline | Firewall blocking port 9090 or incorrect node token | Ensure port 9090 (or 443) is open inbound on the panel; check journalctl -u hawal-agent. |
| Tunnel established but traffic fails | Core port and forwarded port collision | Ensure core port (e.g. 3107) is completely separate from forwarded client ports (e.g. 443). |
| Destination service unreachable | Target daemon not running on foreign node | Verify Xray/V2Ray/3X-UI is listening on the mapped loopback port (e.g. 127.0.0.1:443). |
| Paqet connection drops | Server core port blocked or raw table conflict | Ensure UDP/TCP on the core port is uninhibited and no external firewall flushes raw rules. |
Explore our dedicated documentation guides in the docs/ directory:
- 📖 Domain, Subdomain & SSL Setup Guide — Nginx, Caddy, Cloudflare, and SSL configuration.
- 📖 Node Agent Operator Guide — In-depth agent lifecycle, sync internals, and firewall requirements.
- 🇮🇷 مستندات فارسی ایجنت — راهنمای جامع فارسی معماری ایجنت نودها.
- 🇮🇷 راهنمای فارسی دامنه و اساسال — راهنمای کامل فارسی راهاندازی سابدامین و ریورس پروکسی.
- Node Token Secrecy: Agent tokens grant configuration synchronization authority. Never share them in public repositories or issue tickets.
- Access Control: Always isolate the Master Panel behind an authenticated reverse proxy or restricted firewall rules.
- Port Auditing: Regularly audit open ports using
ss -lntupornmapto prevent unauthorized exposed endpoints. - Compliance: Hawal is provided as an open-source network utility. Operators are solely responsible for adhering to relevant regulatory frameworks and datacenter terms of service.
Contributions, bug reports, and enhancements are warmly welcome! Please submit issues and pull requests following our community standards. When reporting an issue, please include your OS version, selected core, sanitized systemd logs, and reproduction steps.
Released under the MIT License © 2026 dalroot and Hawal contributors.