
pingap v0.13.7
Un proxy inverso come nginx, costruito su pingora, semplice ed efficiente.
pingap
Prima che la versione di pingap sia stabile, non verranno accettate pull request. Se hai domande, crea prima una nuova issue.

Panoramica
Pingap è un reverse proxy ad alte prestazioni basato su Cloudflare Pingora. Semplifica la gestione operativa consentendo un hot-reloading dinamico della configurazione senza tempi di inattività tramite file TOML concisi e un'interfaccia di amministrazione web intuitiva.
Il suo punto di forza principale risiede in un potente sistema di plugin, che offre oltre venti funzionalità pronte all'uso per Autenticazione (JWT, Key Auth), Sicurezza (CSRF, Restrizioni IP/Referer/UA), Controllo del Traffico (Rate Limiting, Caching), Modifica dei Contenuti (Redirect, Sostituzione dei Contenuti) e Osservabilità (Request ID). Questo rende Pingap non solo un proxy, ma un gateway applicativo flessibile ed estensibile, progettato per gestire senza sforzo scenari complessi, dalla protezione delle API alle implementazioni di applicazioni web moderne.
中文说明 | Documentazione · 中文文档 | Esempi | Plugin | Crates
flowchart LR
internet("Internet") -- request --> pingap["Pingap"]
pingap -- proxy:pingap.io/api/* --> apiUpstream["10.1.1.1,10.1.1.2"]
pingap -- proxy:cdn.pingap.io --> cdnUpstream["10.1.2.1,10.1.2.2"]
pingap -- proxy:/* --> upstream["10.1.3.1,10.1.3.2"]
Caratteristiche Principali
-
🚀 Alte Prestazioni e Affidabilità
- Costruito con Rust per la sicurezza della memoria e prestazioni di prim'ordine.
- Basato su Cloudflare Pingora, una libreria di networking asincrono collaudata sul campo.
- Supporta il proxy di HTTP/1.1, HTTP/2 e gRPC-web.
-
🔧 Dinamico e Facile da Usare
- Modifiche alla configurazione senza tempi di inattività con hot-reloading.
- File di configurazione TOML semplici e leggibili.
- Interfaccia web completa per una gestione intuitiva in tempo reale.
- Supporta sia file che etcd come backend di configurazione.
- Supporta la registrazione della cronologia di configurazione, con ripristino in un clic alla versione storica.
-
🧩 Potente Estensibilità
- Un ricco sistema di plugin per gestire le attività comuni del gateway.
- Routing avanzato con corrispondenza per host, percorso ed espressioni regolari.
- Service discovery integrato tramite elenchi statici, DNS o label Docker.
- HTTPS automatizzato con Let's Encrypt (supporto sia per le challenge HTTP-01 che DNS-01).
-
📊 Osservabilità Moderna
- Metriche Prometheus native per il monitoraggio (modalità pull e push).
- Supporto OpenTelemetry integrato per il tracing distribuito.
- Log di accesso altamente personalizzabili con oltre 30 variabili.
- Metriche di prestazioni dettagliate, inclusi tempo di connessione upstream, tempo di elaborazione e altro.
🚀 Per Iniziare
Il modo più semplice per iniziare con Pingap è utilizzare Docker Compose.
- Crea un file
docker-compose.yml:
# docker-compose.yml
version: '3.8'
services:
pingap:
image: vicanso/pingap:latest # Per la produzione, usa una versione specifica come vicanso/pingap:0.12.1-full
container_name: pingap-instance
restart: always
ports:
- "80:80"
- "443:443"
volumes:
# Monta una directory locale per persistere tutte le configurazioni e i dati
- ./pingap_data:/opt/pingap
environment:
# Configura tramite variabili d'ambiente
- PINGAP_CONF=/opt/pingap/conf
- PINGAP_ADMIN_ADDR=0.0.0.0:80/pingap
- PINGAP_ADMIN_USER=pingap
- PINGAP_ADMIN_PASSWORD=<YourSecurePassword> # Cambia questa!
command:
# Avvia pingap e abilita l'hot-reloading
- pingap
- --autoreload
- Crea una directory dati ed esegui:
mkdir pingap_data
docker-compose up -d
- Accedi all'interfaccia di amministrazione:
La tua istanza Pingap è ora in esecuzione! Puoi accedere all'interfaccia di amministrazione web all'indirizzo http://localhost/pingap con le credenziali che hai impostato.
Installa il binario tramite curl
Per Linux e macOS, puoi installare l'ultimo binario precompilato in /usr/local/bin/pingap con un solo comando:
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | sh
Variabili d'ambiente opzionali:
PINGAP_FULL=1— installa la build-full(tutte le funzionalità opzionali abilitate)PINGAP_LIBC=gnu— su Linux, usa la build glibc invece della build statica musl predefinitaPINGAP_TLS=rustls— su Linux, installa la build-rustls-full(backend TLS rustls, tutte le funzionalità opzionali, senza OpenSSL); vedi Backend TLS
# Build con tutte le funzionalità
curl -sSL https://raw.githubusercontent.com/vicanso/pingap/main/install.sh | PINGAP_FULL=1 sh
Target supportati: Linux x86_64/arm64, Darwin x86_64/arm64. Consulta la pagina delle release per tutti gli asset disponibili.
Per istruzioni più dettagliate, incluso l'avvio da un binario, consulta la nostra Documentazione.
Avvia un proxy senza file di configurazione
Un singolo comando è sufficiente per servire un dominio su https e inoltrarlo a un backend:
# certificato richiesto a let's encrypt
pingap --domain=pingap.io --upstream=192.168.1.1:3000
# oppure usa il tuo certificato
pingap --domain=pingap.io --upstream=192.168.1.1:3000 --cert=/etc/ssl/pingap.io
Senza --cert, Pingap richiede un certificato a Let's Encrypt tramite la
challenge HTTP-01, quindi pingap.io deve risolvere su questo host e la porta 80 deve
essere raggiungibile da internet. Il certificato emesso viene conservato in
~/.pingap/acme/<domains>.toml e riutilizzato al riavvio — l'emissione è soggetta a
rate limiting, quindi non eliminarlo. Tutto il resto proviene comunque dalla riga di comando: modificare
--upstream ha effetto al successivo avvio senza toccare il certificato.
--cert accetta il certificato stesso o la directory che lo contiene — i layout comuni
fullchain.pem / privkey.pem, cert.pem / key.pem e tls.crt / tls.key
vengono rilevati automaticamente, usa --key per qualsiasi altra cosa. Il listener
predefinito è 0.0.0.0:443 quando è presente un certificato e 0.0.0.0:80 quando non c'è
né un certificato né un dominio, e --addr lo sovrascrive. --upstream
accetta un elenco separato da virgole di backend, --domain un elenco separato da virgole di
host (omettilo per servire ogni host su http semplice). Le richieste per un host
non elencato ricevono una risposta 404.
La configurazione viene generata a ogni avvio, quindi non può essere modificata tramite
l'interfaccia di amministrazione: per qualsiasi cosa oltre a un singolo server usa --conf, che non può essere
combinato con questi flag.
Configurazione Dinamica
Pingap è progettato per adattarsi alle modifiche di configurazione senza tempi di inattività.
Hot Reload (--autoreload): Per la maggior parte delle modifiche — come l'aggiornamento di upstream, location o plugin — Pingap applica la nuova configurazione entro 10 secondi senza riavvio. Questa è la modalità consigliata per gli ambienti containerizzati.
Riavvio Graceful (-a o --autorestart): Per modifiche fondamentali (come la modifica delle porte di ascolto del server), questa modalità esegue un riavvio completo senza tempi di inattività, garantendo che nessuna richiesta venga persa.
Il passaggio di consegne è guidato dalla prontezza piuttosto che da un timer: il processo sostitutivo viene avviato con -d -u, segnala tramite un unix socket accanto alla upgrade socket nel momento in cui è pronto a subentrare sui listener, e solo allora il processo in esecuzione invia a se stesso SIGQUIT. Se il sostituto termina, il suo daemon muore, o basic.restart_ready_timeout (predefinito 1m) scade prima, il riavvio viene abbandonato e il processo in esecuzione continua a servire.
🔧 Sviluppo
make dev
Se hai bisogno di un'amministrazione web, devi installare nodejs e compilare gli asset web.
# genera l'asset web di amministrazione
cd web
npm i
cd ..
make build-web
Backend TLS
La build predefinita termina TLS con OpenSSL, compilato dal sorgente dal crate openssl. Per compilare invece con rustls, che elimina la compilazione del sorgente OpenSSL (è comunque necessario un compilatore C: i provider crittografici di rustls, ring e aws-lc-rs, contengono C e assembly):
cargo build --release --no-default-features --features tls-rustls
# anche con le funzionalità opzionali
cargo build --release --no-default-features --features tls-rustls,full
La build rustls ignora le impostazioni per-server tls_min_version, tls_max_version, tls_cipher_list e tls_ciphersuites e registra un avviso quando vengono impostate: offre sempre TLS 1.2 e 1.3 con le suite di cifratura predefinite di rustls. Tutto il resto, inclusi i certificati SNI dinamici, l'emissione di CA autofirmate, ACME e l'opzione ca upstream, si comporta allo stesso modo. Una differenza da conoscere durante la verifica degli upstream: rustls (webpki) rifiuta un certificato server che porta CA:TRUE, che OpenSSL accetta, quindi un backend che usa un rapido certificato autofirmato openssl req -x509 necessita di una foglia adeguata firmata da una CA (o una foglia autofirmata senza il flag CA) prima che l'opzione ca upstream possa fidarsi di esso. Il log di avvio segnala con quale backend è stato compilato un binario.
📝 Configurazione
server "test" {
addr = "127.0.0.1:6118"
location "github-api" {
path = "/api"
proxy_set_headers = ["Host:api.github.com"]
rewrite = "^/api/(?<path>.+)$ /$1"
upstream "api" {
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
}
}
location "static" {
plugin "staticServe" {
category = "directory"
path = "~/Downloads"
step = "request"
}
}
}
[upstreams.api]
addrs = ["api.github.com:443"]
discovery = "dns"
sni = "api.github.com"
[plugins.staticServe]
category = "directory"
path = "~/Downloads"
step = "request"
[locations.github-api]
upstream = "api"
path = "/api"
proxy_set_headers = ["Host:api.github.com"]
rewrite = "^/api/(?<path>.+)$ /$1"
[locations.static]
plugins = ["staticServe"]
[servers.test]
addr = "127.0.0.1:6118"
locations = ["github-api", "static"]
Puoi trovare le istruzioni pertinenti qui: https://pingap.io/crates/config.
🔄 Passaggio del Proxy
graph TD;
server["HTTP Server"];
locationA["Location A"];
locationB["Location B"];
locationPluginListA["Proxy Plugin List A"];
locationPluginListB["Proxy Plugin List B"];
upstreamA1["Upstream A1"];
upstreamA2["Upstream A2"];
upstreamB1["Upstream B1"];
upstreamB2["Upstream B2"];
locationResponsePluginListA["Response Plugin List A"];
locationResponsePluginListB["Response Plugin List B"];
start("New Request") --> server
server -- "host:HostA, Path:/api/*" --> locationA
server -- "Path:/rest/*"--> locationB
locationA -- "Exec Proxy Plugins" --> locationPluginListA
locationB -- "Exec Proxy Plugins" --> locationPluginListB
locationPluginListA -- "proxy pass: 10.0.0.1:8001" --> upstreamA1
locationPluginListA -- "proxy pass: 10.0.0.2:8001" --> upstreamA2
locationPluginListA -- "done" --> response
locationPluginListB -- "proxy pass: 10.0.0.1:8002" --> upstreamB1
locationPluginListB -- "proxy pass: 10.0.0.2:8002" --> upstreamB2
locationPluginListB -- "done" --> response
upstreamA1 -- "Exec Response Plugins" --> locationResponsePluginListA
upstreamA2 -- "Exec Response Plugins" --> locationResponsePluginListA
upstreamB1 -- "Exec Response Plugins" --> locationResponsePluginListB
upstreamB2 -- "Exec Response Plugins" --> locationResponsePluginListB
locationResponsePluginListA --> response
locationResponsePluginListB --> response
response["HTTP Response"] --> stop("Logging");
📊 Prestazioni
CPU: M4 Pro, Thread: 1
Ping senza log di accesso
wrk 'http://127.0.0.1:6118/ping' --latency
Running 10s test @ http://127.0.0.1:6118/ping
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 66.41us 23.67us 1.11ms 76.54%
Req/Sec 73.99k 2.88k 79.77k 68.81%
Latency Distribution
50% 67.00us
75% 80.00us
90% 91.00us
99% 116.00us
1487330 requests in 10.10s, 194.32MB read
Requests/sec: 147260.15
Transfer/sec: 19.24MB
📦 Versione Rust
La nostra MSRV attuale è 1.96
📄 Licenza
Questo progetto è concesso in licenza sotto Apache License, Version 2.0.