Torna agli aggiornamenti
New releaseAug 20, 2026

reproxy v1.7.1

Server HTTP(S) leggero perimetrale e reverse proxy con SSL automatico, discovery Docker/Consul, autenticazione per route, limitazione del tasso e failover basato su health check.

Condividi
Reproxy | Proxy inverso semplice

Reproxy è un semplice server HTTP(s) di perimetro / proxy inverso che supporta vari provider (docker, static, file, consul catalog). Uno o più provider forniscono informazioni sul server richiesto, l'URL richiesto, l'URL di destinazione e l'URL di health check. È distribuito come singolo binario o come container docker.

  • Terminazione automatica SSL con Let's Encrypt
  • Supporto di certificati SSL forniti dall'utente
  • Regole proxy semplici ma flessibili
  • Provider di regole proxy statico e da riga di comando
  • Provider di regole proxy dinamico basato su file
  • Provider Docker con rilevamento automatico
  • Provider Consul Catalog con rilevamento tramite tag di servizio
  • Supporto per più host (virtuali)
  • Compressione del traffico opzionale
  • Controllo degli accessi basato su IP opzionale
  • Autenticazione di base per rotta
  • Limiti di dimensione e timeout definibili dall'utente
  • Distribuzione come singolo binario
  • Distribuzione come container Docker
  • Server integrato per asset statici con modalità "SPA friendly" opzionale
  • Supporto per regole di reindirizzamento
  • Limitatore opzionale per l'attività complessiva e per l'attività dell'utente
  • Health check in tempo reale e fail-over/load-balancing
  • Server di gestione con informazioni sulle route e metriche Prometheus
  • Supporto per plugin tramite RPC per implementare funzionalità personalizzate
  • Logging opzionale sia in Apache Log Format che con report stdout semplificati.

build Coverage Status Go Report Card Docker Hub

Il server (host) può essere impostato come FQDN, ad esempio s.example.com, * (catch-all) o una regex. La corrispondenza esatta ha la priorità, quindi se ci sono due regole con server example.com e example\.(com|org), una richiesta a example.com/some/url corrisponderà alla prima. L'URL richiesto può essere una regex, ad esempio ^/api/(.*) e l'URL di destinazione può contenere gruppi catturati dalla regex, ad esempio http://d.example.com:8080/$1. Per l'esempio sopra, http://s.example.com/api/something?foo=bar verrà inoltrato a http://d.example.com:8080/something?foo=bar.

Per comodità, le richieste con / finale e senza gruppi regex vengono espanse a /(.*), e le destinazioni in tali casi vengono espanse a /$1. Ad esempio /api/ -> http://127.0.0.1/service verrà tradotto in ^/api/(.*) -> http://127.0.0.1/service/$1.

La sostituzione dell'host è supportata nell'URL di destinazione. Ad esempio, /files/${host} verrà sostituito con il nome dell'host corrispondente. È utilizzabile anche $host (senza parentesi).

Sono supportati sia HTTP che HTTPS. Per HTTPS, può essere utilizzato un certificato statico così come certificati ACME automatici (Let's Encrypt). Un server di asset opzionale può essere utilizzato per servire file statici. Avviare reproxy richiede almeno un provider definito. Il resto dei parametri sono strettamente opzionali e hanno valori predefiniti ragionevoli.

Esempi:

  • con un provider statico: reproxy --static.enabled --static.rule="*,example.com/api/(.*),https://api.example.com/$1"
  • con rilevamento automatico docker: reproxy --docker.enabled --docker.auto
  • come container docker: docker up -p 80:8080 umputun/reproxy --docker.enabled --docker.auto
  • con SSL automatico: docker up -p 80:8080 -p 443:8443 umputun/reproxy --docker.enabled --docker.auto --ssl.type=auto --ssl.fqdn=example.com

Installazione

Reproxy è distribuito come un piccolo binario autonomo e come immagine docker. Sia il binario che l'immagine supportano più architetture e più sistemi operativi, tra cui linux_x86_64, linux_arm64, linux_arm, macos_x86_64, macos_arm64, windows_x86_64 e windows_arm. Forniamo anche pacchetti deb e rpm sia per arm64 che per x86.

  • per una distribuzione binaria, scaricare il file appropriato nella sezione release
  • per utenti Homebrew: brew install umputun/apps/reproxy
  • il container docker è disponibile su Docker Hub e su Github Container Registry. Ad esempio docker pull umputun/reproxy o docker pull ghcr.io/umputun/reproxy.

L'ultima versione stabile ha il tag docker :vX.Y.Z (con alias :latest) e il master corrente ha il tag :master.

Provider

Le regole del proxy sono fornite da vari provider. Attualmente inclusi: file, docker, static e consul-catalog. Ogni provider può definire più regole di routing sia per le richieste inoltrate che per i file statici (asset). L'utente può impostare più provider contemporaneamente.

Vedi esempi di vari provider in examples

Provider statico

Questo è il provider più semplice che definisce tutte le regole di mappatura direttamente nella riga di comando (o nell'ambiente). Sono supportate più regole. Ogni regola è composta da 3 a 7 elementi separati da virgole: server,sourceurl,destination[,ping-url[,forward-health-checks[,timeout[,throttle]]]]. Ad esempio:

  • *,^/api/(.*),https://api.example.com/$1 - proxy tutte le richieste a qualsiasi host/server con prefisso /api verso https://api.example.com
  • example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping - proxy tutte le richieste a example.com con URL /foo/bar verso https://api.example.com/zzz e utilizza https://api.example.com/ping per il health check.
  • example.com,/foo/bar,https://api.example.com/zzz,https://api.example.com/ping,true - come sopra ma inoltra anche le richieste /ping e /health al backend.
  • example.com,^/upload/(.*),https://api.example.com/$1,,,5m - timeout di richiesta per-route di 5 minuti (il 4° e 5° campo lasciati vuoti per saltare ping-url e forward-health-checks).
  • example.com,^/login,https://api.example.com/login,,,,2 - limite per-route di 2 req/sec per utente (i campi posizionali precedenti sono lasciati vuoti).

Il 4° elemento definisce un URL di ping opzionale utilizzato per il reporting dello stato. Il 5° elemento abilita opzionalmente l'inoltro delle richieste di health check al backend (true, yes, 1). Vedi la sezione Health check per maggiori dettagli. Il 6° elemento è un timeout di richiesta opzionale per-route (durata Go, ad esempio 5m, 30s); 0 o vuoto eredita l'impostazione globale --timeout.write. Il 7° elemento è un limite opzionale di req/sec per utente per-route; 0 o vuoto eredita --throttle.user. I campi posizionali vuoti sono consentiti (ad esempio ,, per i campi intermedi non utilizzati).

Provider file

Questo provider utilizza un file yaml con regole di routing.

reproxy --file.enabled --file.name=config.yml

Esempio di config.yml:```yaml default: # the same as * (catch-all) server

Questo è un provider dinamico e la modifica del file verrà applicata automaticamente.

**È possibile servire più siti statici su domini diversi** utilizzando i nomi dei server come chiavi con `assets: true`:```yaml
site-en.example.com:
  - { route: "/", dest: "/var/www/en", "assets": true }
site-ru.example.com:
  - { route: "/", dest: "/var/www/ru", "assets": true }

Importante: il campo route per le regole degli asset deve essere un prefisso di percorso (es. /, /web/), non una regex. Pattern regex come ^/(.*) non funzionano con assets: true perché il matching degli asset statici utilizza il confronto dei prefissi di percorso, non la regex.

Docker provider

Il provider Docker supporta una scoperta completamente automatica (con --docker.auto) senza necessità di configurazione aggiuntiva. Per impostazione predefinita, reindirizza tutte le richieste come http://<url>/<nome container>/(.*) all'IP interno del container specificato e alla porta esposta. Solo i container attivi (in esecuzione) verranno rilevati.

Questa impostazione predefinita può essere modificata con le etichette:

  • reproxy.server - server (hostname) da abbinare. Può anche essere un elenco di server separati da virgola.
  • reproxy.route - route di origine (location)
  • reproxy.dest - percorso di destinazione. Nota: non è un URL completo, ma solo il percorso che verrà aggiunto a ip:porta del container
  • reproxy.port - porta di destinazione per il container rilevato
  • reproxy.ping - percorso di ping per il container di destinazione.
  • reproxy.remote - limita l'accesso alla route con un elenco di subnet o IP separati da virgola
  • reproxy.auth - richiede autenticazione di base per la route con coppie user:bcrypt_hash separate da virgola (generate da htpasswd -nbB)
  • reproxy.assets - imposta il mapping degli asset come web-root:location, ad esempio reproxy.assets=/web:/var/www
  • reproxy.keep-host - mantieni l'header host così com'è (yes, true, 1) o sostituisci con l'host di destinazione (no, false, 0)
  • reproxy.forward-health-checks - inoltra le richieste /ping e /health al backend invece di gestirle con reproxy (yes, true, 1). Utile quando il backend ha i propri endpoint di health check con risposte specifiche dell'applicazione.
  • reproxy.timeout - timeout della richiesta per route come durata Go (es. 5m, 30s). 0 o non impostato eredita il globale --timeout.write. I valori non validi vengono ignorati con un avviso.
  • reproxy.throttle - limite req/sec per route per utente. 0 o non impostato eredita --throttle.user. I valori non validi o negativi vengono ignorati con un avviso.
  • reproxy.enabled - abilita (yes, true, 1) o disabilita (no, false, 0) il container dalle destinazioni di reproxy.

Nota: senza --docker.auto, il container di destinazione deve avere almeno una delle etichette reproxy.* per essere considerato una destinazione potenziale.

Con --docker.auto, tutti i container con porta esposta verranno considerati come destinazioni di routing. Ci sono 3 modi per limitarlo:

  • Escludere esplicitamente alcuni container con --docker.exclude, ad es. --docker.exclude=c1 --docker.exclude=c2 ...
  • Consentire solo una particolare rete Docker con --docker.network
  • Impostare l'etichetta reproxy.enabled=false o reproxy.enabled=no o reproxy.enabled=0

Se non è definito reproxy.route, la route predefinita è ^/<nome_container>/(.*). Nel caso in cui tutte le sorgenti proxygate debbano avere lo stesso pattern di prefisso, ad esempio /api/(.*), l'utente può definire il prefisso comune (in questo caso /api) per tutte le route basate su container. Questo può essere fatto con il parametro --docker.prefix.

Il provider Docker consente anche di definire più set di etichette reproxy.N.something per abbinare più route distinte sullo stesso container. Questo è utile poiché in alcuni casi un singolo container può esporre più endpoint, ad esempio un'API pubblica e un'API di amministrazione. Tutte le etichette sopra possono essere utilizzate con "N-index", ad es. reproxy.1.server, reproxy.1.port e così via. N deve essere compreso tra 0 e 9.

Questo è un provider dinamico e qualsiasi modifica allo stato del container verrà applicata automaticamente.

Consul Catalog provider

Utilizzo: reproxy --consul-catalog.enabled

Il provider Consul Catalog chiama l'API di Consul periodicamente (ogni secondo per impostazione predefinita) per ottenere i servizi che hanno un tag con prefisso reproxy.. L'utente può ridefinire l'intervallo di controllo con il flag da riga di comando --consul-catalog.interval e l'indirizzo Consul con l'opzione --consul-catalog.address. L'indirizzo predefinito è http://127.0.0.1:8500.

Per esempio:``` reproxy --consul-catalog.enabled --consul-catalog.address=http://192.168.1.100:8500 --consul-catalog.interval=10s

Di default, il provider imposta valori per ogni servizio:
- enabled `false`
- server `*`
- route `^/(.*)`
- dest `http://<SERVICE_ADDRESS_FROM_CONSUL>/$1`
- ping `http://<SERVICE_ADDRESS_FROM_CONSUL>/ping`

Questo valore predefinito può essere modificato con i tag:

- `reproxy.server` - server (hostname) da abbinare. Può anche essere un elenco di server separati da virgole.
- `reproxy.route` - route di origine (posizione)
- `reproxy.dest` - percorso di destinazione. Nota: non è un url completo, ma solo il percorso che verrà aggiunto a ip:porta del servizio.
- `reproxy.port` - porta di destinazione per il servizio scoperto
- `reproxy.remote` - limita l'accesso alla route con un elenco di subnet o IP separati da virgole
- `reproxy.auth` - richiede autenticazione di base per la route con coppie `user:bcrypt_hash` separate da virgole (generate da `htpasswd -nbB`)
- `reproxy.ping` - percorso di ping per il servizio di destinazione.
- `reproxy.forward-health-checks` - inoltra le richieste `/ping` e `/health` al backend (`true`, `yes`, `1`).
- `reproxy.timeout` - timeout per richiesta per route come durata Go (es. `5m`, `30s`). `0` o non impostato eredita il globale `--timeout.write`. Valori non validi vengono ignorati con un avviso.
- `reproxy.throttle` - limite req/sec per route per utente. `0` o non impostato eredita `--throttle.user`. Valori non validi o negativi vengono ignorati con un avviso.
- `reproxy.enabled` - abilita (`yes`, `true`, `1`) o disabilita (`qualsiasi valore diverso`) il servizio dalle destinazioni di reproxy.

### Dettagli specifici per Compose

Nel caso in cui le regole siano impostate come parte di un ambiente docker compose, la destinazione con il gruppo regex entrerà in conflitto con la sintassi di compose. Ad esempio, tentare di usare `https://api.example.com/$1` in un ambiente compose fallirà a causa di un errore di sintassi. La soluzione standard qui è "escapare" il segno `$` sostituendolo con `$$`, cioè `https://api.example.com/$$1`. Questa sostituzione è supportata da docker compose e non ha nulla a che fare con reproxy stesso. Un altro modo è usare `@` invece di `$`, supportato a livello di reproxy, cioè `https://api.example.com/@1`_

## Supporto SSL

La modalità SSL (per impostazione predefinita nessuna) può essere impostata su `auto` (certificati ACME/LE), `static` (certificato esistente) o `none`. Se `auto` è attivo, il certificato SSL verrà emesso automaticamente per tutti i nomi server scoperti. L'utente può sovrascriverlo impostando uno o più valori di `--ssl.fqdn`. In modalità SSL `auto` e `static`, Reproxy aggiungerà automaticamente le intestazioni `X-Forwarded-Proto` e `X-Forwarded-Port`. Queste intestazioni sono utili per i servizi dietro il proxy per conoscere il protocollo originale (http o https) e il numero di porta utilizzati dal client.

Quando si utilizza ACME con provider di scoperta (docker, file, consul), i certificati SSL vengono ottenuti automaticamente per i server appena scoperti senza bisogno di riavviare reproxy.

### Sfide ACME

Reproxy supporta due tipi di sfide ACME per la convalida dei certificati SSL:

1. **Sfida HTTP-01** (predefinita): Convalida la proprietà del dominio servendo un token a un URL HTTP specifico. Richiede che la porta 80 sia accessibile pubblicamente.

2. **Sfida DNS-01**: Convalida la proprietà del dominio creando record TXT DNS. Questo metodo:
   - Non richiede che la porta 80 sia accessibile
   - Funziona con certificati wildcard
   - Richiede una configurazione del provider DNS supportato

#### Selezione della sfida

Reproxy determina automaticamente quale metodo di sfida utilizzare in base alla tua configurazione:

- **HTTP-01** (predefinito): Usato quando nessun provider DNS è configurato
- **DNS-01**: Usato quando un provider DNS è configurato

Non è necessario selezionare esplicitamente un tipo di sfida: basta configurare un provider DNS se si desidera utilizzare le sfide DNS-01.

#### Provider DNS attualmente supportati

Reproxy include attualmente il supporto per i seguenti provider DNS:

- **Cloudflare**: `--ssl.dns.type=cloudflare --ssl.dns.cloudflare.api-token=TOKEN`
- **Route53 (AWS)**: `--ssl.dns.type=route53 --ssl.dns.route53.region=REGION --ssl.dns.route53.hosted-zone-id=ID`
- **Gandi**: `--ssl.dns.type=gandi --ssl.dns.gandi.bearer-token=TOKEN`
- **DigitalOcean**: `--ssl.dns.type=digitalocean --ssl.dns.digitalocean.api-token=TOKEN`
- **Hetzner**: `--ssl.dns.type=hetzner --ssl.dns.hetzner.api-token=TOKEN`
- **Linode**: `--ssl.dns.type=linode --ssl.dns.linode.api-token=TOKEN`
- **GoDaddy**: `--ssl.dns.type=godaddy --ssl.dns.godaddy.api-token=TOKEN`
- **Namecheap**: `--ssl.dns.type=namecheap --ssl.dns.namecheap.api-key=KEY --ssl.dns.namecheap.user=USER`
- **Scaleway**: `--ssl.dns.type=scaleway --ssl.dns.scaleway.secret-key=KEY --ssl.dns.scaleway.organization-id=ID`
- **Porkbun**: `--ssl.dns.type=porkbun --ssl.dns.porkbun.api-key=KEY --ssl.dns.porkbun.api-secret-key=SECRET`
- **DNSimple**: `--ssl.dns.type=dnsimple --ssl.dns.dnsimple.api-access-token=TOKEN --ssl.dns.dnsimple.account-id=ID`
- **DuckDNS**: `--ssl.dns.type=duckdns --ssl.dns.duckdns.api-token=TOKEN`

Esempio con Cloudflare come provider DNS:```
export CLOUDFLARE_API_TOKEN=your_api_token
reproxy --ssl.type=auto [email protected] --ssl.fqdn=example.com

La sfida DNS-01 è particolarmente utile quando:

  • Il tuo server non ha la porta 80 esposta pubblicamente
  • Hai bisogno di certificati wildcard (es. *.example.com)
  • Sei dietro firewall restrittivi

Intestazioni

Reproxy consente di sanificare (rimuovere) le intestazioni in arrivo passando il parametro --drop-header (può essere ripetuto). Questo parametro può essere utile per assicurarsi che alcune intestazioni, impostate internamente dai servizi, non possano essere impostate/falsificate dall'utente finale. Ad esempio, se alcuni dei servizi responsabili dell'autenticazione impostano X-Auth-User e X-Auth-Token, probabilmente ha senso rimuovere quelle intestazioni dalle richieste in arrivo passando il parametro --drop-header=X-Auth-User --drop-header=X-Auth-Token o tramite l'ambiente DROP_HEADERS=X-Auth-User,X-Auth-Token

La funzione opposta, impostare una o più intestazioni in uscita, è supportata. Può essere utile in molti casi, ad esempio per imporre regole CORS personalizzate, intestazioni relative alla sicurezza e così via. Questo può essere fatto con il parametro --header (può essere ripetuto) o l'environment HEADER. Ad esempio, ecco come si può fare con docker compose:```yaml environment: - HEADER= X-Frame-Options:SAMEORIGIN, X-XSS-Protection:1; mode=block;, Content-Security-Policy:default-src 'self'; style-src 'self' 'unsafe-inline';

## Logging

Per impostazione predefinita non viene generato alcun log delle richieste. È possibile attivarlo impostando `--logger.enabled`. Il log (con rotazione automatica) ha [Apache Combined Log Format](http://httpd.apache.org/docs/2.2/logs.html#combined)

L'utente può anche attivare il log su stdout con `--logger.stdout`. Non influenzerà la registrazione su file di cui sopra, ma produrrà alcune informazioni minime sulle richieste elaborate, qualcosa del genere:```
2021/04/16 01:17:25.601 [INFO]  GET - /echo/image.png - xxx.xxx.xxx.xxx - 200 (155400) - 371.661251ms
2021/04/16 01:18:18.959 [INFO]  GET - /api/v1/params - xxx.xxx.xxx.xxx - 200 (74) - 1.217669m

Server degli asset

Gli utenti possono attivare il server degli asset (disattivato per impostazione predefinita) per servire file statici. Fintanto che --assets.location è impostato, tratta ogni richiesta non proxy sotto assets.root come una richiesta di file statici. Il server degli asset può essere utilizzato senza alcun fornitore di proxy; in questa modalità, reproxy agisce come un semplice server web per i contenuti statici. Il server degli asset supporta anche la "modalità spa" con --assets.spa dove tutte le richieste non trovate vengono inoltrate a index.html.

Oltre al server degli asset comune, sono supportati più server di asset personalizzati. Ogni fornitore ha un modo diverso per definire tale regola statica e alcuni fornitori potrebbero non supportarla affatto. Ad esempio, più server di asset hanno senso nel fornitore statico (riga di comando), nel fornitore file e persino con i fornitori docker, ma hanno molto poco senso con il fornitore del catalogo consul.

  1. fornitore statico - se l'elemento sorgente è prefissato da assets: o spa: verrà trattato come file-server. Ad esempio *,assets:/web,/var/www, servirà tutte le richieste /web/* con un file server sulla directory /var/www.
  2. fornitore file - impostando i campi opzionali assets: true o spa: true. Nota: il campo route deve essere un prefisso di percorso (es. /, /web/), non un pattern regex.
  3. fornitore docker - reproxy.assets=web-root:location, ad esempio reproxy.assets=/web:/var/www. Il passaggio alla modalità spa si effettua impostando reproxy.spa su yes o true

Caching

Il server degli asset supporta il controllo della cache con il parametro --assets.cache=<duration>. La durata 0s (predefinita) disattiva il controllo della cache. Una durata è una sequenza di numeri decimali, ciascuno con frazione opzionale e un suffisso di unità, come "300ms", "1.5h" o "2h45m". Le unità di tempo valide sono "ns", "us" (o "µs"), "ms", "s", "m", "h" e "d".

Esistono due modi per impostare la durata della cache:

  1. Un singolo valore per tutti gli asset statici. È semplice come --assets.cache=48h.
  2. Durata personalizzata per diversi tipi MIME. Dovrebbe includere due parti: il valore predefinito e le coppie mime:duration. Nella riga di comando appare come più opzioni --assets.cache, ad esempio --assets.cache=48h --assets.cache=text/html:24h --assets.cache=image/png:2h. I valori delle variabili d'ambiente devono essere separati da virgole, ad esempio ASSETS_CACHE=48h,text/html:24h,image/png:2h

È possibile impostare una pagina 404 personalizzata (non trovata) con il parametro --assets.not-found=<path>. Il percorso deve essere relativo alla root degli asset.

Utilizzo di reproxy come immagine di base

Servire contenuti puramente statici è uno dei casi d'uso più comuni. Di solito viene utilizzato per il contenitore frontend separato che fornisce solo l'interfaccia utente. Con il server degli asset, un tale contenitore è quasi banale da realizzare. Questo è un esempio dal contenitore che serve reproxy.io```docker FROM node:22-alpine as build

WORKDIR /build COPY site/ /build COPY README.md /build/src/index.md

RUN yarn --frozen-lockfile RUN yarn build RUN ls -la /build/public

FROM ghcr.io/umputun/reproxy COPY --from=build /build/public /srv/site EXPOSE 8080 USER app ENTRYPOINT ["/srv/reproxy", "--assets.location=/srv/site"]

Tutto ciò che serve è copiare gli asset statici in una posizione e passare questa posizione come `"--assets.location` al punto di ingresso di reproxy.

## Modalità SPA-friendly

Alcune applicazioni SPA si affidano al proxy per gestire il 404 sugli asset statici in modo speciale, reindirizzandoli a "/index.html". Ciò è simile alla direttiva `try_files $uri $uri/ …` di nginx e, apparentemente, questa funzionalità è in qualche modo importante per le moderne applicazioni web.

Questa modalità è disattivata per impostazione predefinita e può essere attivata impostando `--assets.spa` o la variabile d'ambiente `ASSETS_SPA=true`.

## Reindirizzamenti

Per impostazione predefinita, reproxy tratta la destinazione come una posizione proxy, cioè effettua internamente una chiamata http e restituisce la risposta al client. Tuttavia, prefissando l'url di destinazione con `@code`, questo comportamento può essere cambiato in reindirizzamenti permanenti (codice di stato 301) o temporanei (codice di stato 302). Ad esempio, una destinazione impostata su `@301 https://example.com/something` causerà un reindirizzamento http permanente a `Location: https://example.com/something`

codici supportati:

- `@301`, `@perm` - reindirizzamento permanente
- `@302`, `@temp`, `@tmp` - reindirizzamento temporaneo

## Altre opzioni

- `--gzip`   abilita la compressione gzip per le risposte.
- `--max=N`  permette di impostare la dimensione massima della richiesta (default 64k). Impostandolo a `0` si disabilita il controllo della dimensione.
- `--timeout.*` vari timeout sia per il server che per il trasporto proxy. Vedi la sezione `timeout` in [All Application Options](#all-application-options). Un valore zero o negativo significa che non ci sarà timeout.
- `--insecure` disabilita la verifica SSL sull'host di destinazione. Utile per certificati autofirmati.

## Porte predefinite

Per eliminare la necessità di passare parametri personalizzati/variabili d'ambiente, il `--listen` predefinito è dinamico e cerca di essere ragionevole e utile per i casi tipici:

- Se l'utente imposta qualcosa in `--listen` tutta la logica sottostante viene ignorata e l'host:porta passato viene utilizzato direttamente.
- Se l'utente non imposta nulla in `--listen` e reproxy viene eseguito al di fuori del container docker, l'impostazione predefinita è `127.0.0.1:80` per la modalità http (`ssl.type=none`) e `127.0.0.1:443` per la modalità ssl (`ssl.type=auto` o `ssl.type=static`).
- Se l'utente non imposta nulla in `--listen` e reproxy viene eseguito all'interno del docker, l'impostazione predefinita è `0.0.0.0:8080` per la modalità http e `0.0.0.0:8443` per la modalità ssl.

Un'altra impostazione predefinita definita in modo dinamico simile è `--ssl.http-port`. Per l'esecuzione all'interno del container docker è impostata a `8080` e all'esterno a `80`.

## Ping, controlli di integrità e fail-over

reproxy fornisce due endpoint per questo scopo:

- `/ping` risponde con `pong` e indica che reproxy è attivo e funzionante
- `/health` restituisce lo stato `200 OK` se tutti i server di destinazione hanno risposto alla loro richiesta ping con `200`, o `417 Expectation Failed` se uno qualsiasi dei server ha risposto con un codice diverso da 200. Restituisce anche un corpo json con i dettagli sui servizi superati/falliti.

Oltre agli endpoint sopra, reproxy supporta controlli di integrità live opzionali. In questo caso (se abilitato), ogni destinazione viene controllata periodicamente per la risposta ping e le route di destinazione non riuscite vengono escluse. È possibile restituire più destinazioni identiche dallo stesso provider o da provider diversi, e viene scelta solo quella che ha superato il controllo. Se vengono trovate e superate molte corrispondenze, quella finale viene selezionata secondo la strategia `lb-type` (per impostazione predefinita selezione casuale).

Per attivare il controllo di integrità live, l'utente deve impostare `--health-check.enabled` (o l'env `HEALTH_CHECK_ENABLED=true`). Per personalizzare l'intervallo di controllo, è possibile utilizzare `--health-check.interval=`.

## API di gestione

Opzionale, può essere attivata con `--mgmt.enabled`. Espone 2 endpoint su `mgmt.listen` (indirizzo:porta):

- `GET /routes` - elenco di tutte le route scoperte
- `GET /metrics` - restituisce metriche prometheus (`http_requests_total`, `response_status` e `http_response_time_seconds`)

Per impostazione predefinita, `http_response_time_seconds` utilizza i percorsi delle richieste raw come etichette, il che può causare un'alta cardinalità con URL dinamici (ad esempio `/api/users/123`, `/api/users/456`). Utilizzare `--mgmt.low-cardinality` per passare invece a pattern di route (ad esempio `^/api/users/(.*)`), riducendo significativamente la cardinalità delle metriche.

_see also [examples/metrics](https://github.com/umputun/reproxy/tree/master/examples/metrics)_

## Segnalazione errori

Reproxy restituisce un errore 502 (Bad Gateway) se la richiesta non corrisponde a nessuna route o asset fornito. In caso di errore interno imprevisto, restituisce 500. Per impostazione predefinita, reproxy visualizza la versione testuale più semplice dell'errore - "Server error". Impostando `--error.enabled` si attiva il messaggio di errore html predefinito e con `--error.template` l'utente può impostare qualsiasi file di template html personalizzato per la visualizzazione dell'errore. Il template ha due variabili: `{{.ErrCode}}` e `{{.ErrMessage}}`. Ad esempio, questo template `oh my! {{.ErrCode}} - {{.ErrMessage}}` sarà renderizzato come `oh my! 502 - Bad Gateway`

## Limitazione

Reproxy consente di definire un valore massimo di richieste/sec a livello di sistema per l'attività complessiva e per utente. I valori 0 (predefiniti) sono considerati illimitati.

L'attività utente è limitata sia per le route corrispondenti che per quelle non corrispondenti. Tutte le route non corrispondenti sono considerate come un "singolo gruppo di destinazione" e ottengono un limitatore comune che è `rate*3`. Ciò significa che se 10 (richieste/sec) sono definiti con `--throttle.user=10`, l'utente finale sarà in grado di effettuare fino a 30 richieste al secondo sia per asset statici che per route non corrispondenti. Per le route corrispondenti, questo limitatore viene mantenuto per destinazione (route), ad esempio la richiesta inoltrata a s1.example.com/api consentirà 10 r/s e la richiesta inoltrata a s2.example.com ne consentirà altre 10 r/s.

### Timeout e limitazione per route

Le singole route possono sovrascrivere le impostazioni globali `--timeout.write` e `--throttle.user` tramite i campi `timeout` e `throttle` specifici del provider. Ciò è utile per endpoint a lunga esecuzione (ad esempio upload, generazione di report) che necessitano di una scadenza superiore al timeout di scrittura globale, e per restringere i limiti di frequenza su route sensibili (ad esempio login) senza aumentare il limite globale per tutto il resto.

La precedenza è "zero eredita globale, positivo sovrascrive": una route con `timeout: 0` (o senza campo `timeout`) mantiene il `--timeout.write` globale; una route con `timeout: 5m` lo sovrascrive solo per le richieste corrispondenti. La stessa regola vale per `throttle`.

Il timeout per route sovrascrive le scadenze di lettura e scrittura della connessione per le richieste corrispondenti, quindi può estendersi oltre il `--timeout.write` globale (default 30s). Le route senza timeout per route rispettano ancora l'impostazione globale.

**Limitazione — timeout della risposta a livello di trasporto per l'header:** il `timeout` per route NON sovrascrive `--timeout.resp-header` (default 5s). Tale timeout è impostato sul `http.Transport` condiviso e si applica prima che l'upstream inizi a inviare gli header di risposta. Se un upstream impiega più tempo di `--timeout.resp-header` per iniziare la sua risposta (ad esempio un endpoint di report lento), la richiesta fallisce a quel confine indipendentemente dal `timeout` per route. Per supportare tali route, aumentare `--timeout.resp-header` globalmente al massimo necessario per qualsiasi route con risposta lenta. La sovrascrittura per route dei timeout a livello di trasporto è intenzionalmente fuori dal campo di applicazione.

Sintassi del provider:
- **File provider** (YAML): `timeout: 5m`, `throttle: 2`
- **Provider statico** (CSV): 6° e 7° campo posizionale, ad esempio `*,^/upload/(.*),http://up:8080/$1,,,5m,2`
- **Docker provider**: `reproxy.timeout=5m`, `reproxy.throttle=2` (o `reproxy.<n>.timeout` / `reproxy.<n>.throttle` per contenitori multi-route)
- **Consul Catalog provider**: `reproxy.timeout=5m`, `reproxy.throttle=2`

## Limiti di connessione upstream

Reproxy consente di configurare le impostazioni del pool di connessioni upstream per controllare quante connessioni vengono mantenute verso i server backend:

- `--upstream.max-idle-conns` - Numero massimo di connessioni idle su tutti gli host upstream. Default: 100.
- `--upstream.max-conns` - Numero massimo di connessioni per host upstream (0 = illimitato). Default: 0.

Impostare `--upstream.max-conns` limita le connessioni concorrenti a ciascun backend, utile quando i server upstream hanno capacità limitata o per prevenire l'esaurimento delle connessioni.

## Autenticazione di base

Reproxy supporta l'autenticazione di base in due modalità: globale (tutte le route) e per route.

### Autenticazione di base globale

L'autenticazione di base globale protegge tutte le route. Utile per proteggere gli endpoint durante lo sviluppo e i test. Per abilitarla, impostare il file htpasswd con `--basic-htpasswd=<percorso file>` o l'env `BASIC_HTPASSWD=<percorso file>`.

Reproxy si aspetta che il file htpasswd sia nel seguente formato:```
username1:bcrypt(password1)
username2:bcrypt(password2)
...

questo può essere generato con il comando htpasswd -nbB, ad esempio htpasswd -nbB test passwd

Autenticazione di base per rotta

L'autenticazione per rotta consente l'uso di credenziali diverse per rotte diverse. Quando una rotta ha l'autenticazione per rotta configurata, l'autenticazione globale viene bypassata per quella rotta. L'autenticazione per rotta è configurata tramite impostazioni specifiche del provider:

  • Provider file: campo auth in YAML, ad es. auth: "user1:$2y$..., user2:$2y$..."
  • Provider Docker: etichetta reproxy.auth
  • Provider Consul Catalog: tag reproxy.auth
  • Provider statico: non supportato (usa il provider file per l'autenticazione per rotta)

Il formato è un elenco separato da virgole di coppie utente:bcrypt_hash (stesso formato htpasswd). È possibile specificare più utenti per la stessa rotta.

Esempio con docker-compose:```yaml services: admin-api: labels: - "reproxy.route=^/admin/(.*)" - "reproxy.dest=/$1" - "reproxy.auth=admin:$$2y$$05$$hashedpassword"

Nota: In docker-compose, `$` deve essere escaped come `$$`.

## Controllo di accesso basato su IP

Reproxy consente di limitare l'accesso alle route con un elenco di subnet o IP separati da virgole. Ciò è utile durante lo sviluppo e il testing, prima di consentire l'accesso illimitato. Può anche essere utilizzato per limitare l'accesso ai servizi interni. Per impostazione predefinita, tutte le route sono aperte per tutti i client.

Per limitare l'accesso alle route, l'utente deve impostare le chiavi appropriate per le route, ovvero `reproxy.remote` per docker e consul, e `remote` per il file provider. Il valore deve essere un elenco di subnet o IP separati da virgole. Ad esempio `127.0.0.1, 192.168.1.0/24`. Per maggiori dettagli, consultare le sezioni [docker provider](#docker-provider) e [consul catalog provider](#consul-catalog-provider).

Per impostazione predefinita, reproxy controlla l'indirizzo remoto dalla richiesta del client. Tuttavia, in alcuni casi non funzionerà come previsto, ad esempio dietro un altro proxy o con la rete bridge di docker. Questo può essere modificato con il parametro `--remote-lookup-headers` che permette di controllare il valore dell'header `X-Real-IP` o `X-Forwarded-For` (in quest'ordine) e utilizzarlo per il controllo. Se l'header non è impostato, il controllo verrà eseguito sull'indirizzo remoto del client. Questi header sono forniti dal client e sono facilmente falsificabili, quindi questo parametro deve essere abilitato solo quando reproxy è in esecuzione dietro un proxy front-end attendibile che imposta e sovrascrive sempre questi header.

Il controllo degli header deve essere usato con cautela, poiché è possibile falsificarli. Quando `--remote-lookup-headers` è abilitato, la lista di permessi IP si basa interamente su questa ipotesi di fiducia: un client che invia `X-Real-IP` o `X-Forwarded-For` con un indirizzo consentito potrebbe altrimenti aggirare la restrizione. Abilita questa opzione solo se reproxy è dietro un proxy attendibile che controlla questi header e puoi garantire che non siano falsificati.

## Supporto per i plugin

Le funzionalità principali di reproxy possono essere estese con plugin esterni. Ogni plugin è un processo/contenitore indipendente che implementa un [server rpc](https://golang.org/pkg/net/rpc/). I plugin vengono registrati con il conductor di reproxy e aggiunti alla catena dei middleware. Ogni plugin riceve una richiesta con l'URL originale, gli header e tutte le informazioni sulla route corrispondente e risponde con gli header e il codice di stato. Qualsiasi codice di stato >= 400 viene trattato come risposta di errore e termina immediatamente il flusso con l'errore del proxy. Esistono due tipi di header che i plugin possono impostare:

- `HeadersIn` - header in entrata. Verranno inviati all'URL proxy.
- `HeadersOut` - header in uscita. Verranno inviati al client.

Per impostazione predefinita, gli header impostati da un plugin verranno mescolati con gli header originali. Nel caso in cui un plugin debba controllare tutti gli header, ad esempio eliminarne alcuni, il campo `OverrideHeaders*` può essere impostato da un plugin per indicare al processo core di reproxy la necessità di sovrascrivere tutti gli header invece di mescolarli.

- `OverrideHeadersIn` - indica che il plugin è responsabile di tutti gli header in entrata.
- `OverrideHeadersOut` - indica che il plugin è responsabile di tutti gli header in uscita.

Per semplificare il processo di sviluppo, vengono forniti tutti i componenti di base. Include `lib.Plugin` che gestisce la registrazione, l'ascolto e l'invio delle chiamate, nonché `lib.Request` e `lib.Response` che definiscono input e output. Gli autori dei plugin devono implementare handler concreti che soddisfino la firma `func(req lib.Request, res *lib.HandlerResponse) (err error)`. Ogni plugin può contenere più handler di questo tipo.

_Vedi [esempi/plugin](https://github.com/umputun/reproxy/tree/master/examples/plugin) per maggiori informazioni_

## Sicurezza del contenitore

Per impostazione predefinita, il contenitore reproxy viene eseguito con l'utente root per semplificare la configurazione iniziale e accedere al socket docker. Ciò è necessario per consentire al docker provider di scoprire i contenitori in esecuzione. Tuttavia, se tale scoperta non è richiesta o il docker provider non è in uso, si consiglia di cambiare l'utente con uno meno privilegiato. Può essere fatto a livello di docker-compose e a livello di docker con l'opzione `user`, vedere la sezione seguente per i dettagli.

A volte, anche con il routing interno a docker, ha senso disabilitare il docker provider e impostare le regole con il provider statico o file. Tutti i contenitori in esecuzione all'interno di un compose condividono la stessa rete e sono accessibili tramite DNS locale. L'utente può avere una regola come questa per evitare la scoperta docker: `- STATIC_RULES=*,/api/email/(.*),http://email-sender:8080/$$1`. Questa regola si aspetta che il contenitore `email-sender` sia definito all'interno dello stesso compose. Nota: gli utenti possono ottenere lo stesso risultato utilizzando la rete docker anche se il servizio di destinazione è stato definito in un file compose diverso. In questo modo la configurazione di reproxy può rimanere separata dai servizi reali.

Non c'è nient'altro oltre al binario reproxy all'interno del contenitore reproxy, poiché è costruito su un'immagine vuota (scratch).

### Esecuzione con un utente non root

Un utente con UID `1001` (appartenente ai gruppi `1001` e `999`) è pre-creato all'interno del contenitore e può essere utilizzato per eseguire reproxy come utente non root:```yaml
services:
  reproxy:
    user: 1001
    image: umputun/reproxy:latest
# <...>
# see examples/ssl/docker-compose.yml for the full file example

Se desideri utilizzare il provider Docker, dovrai assicurarti che questo utente abbia il permesso di accedere al socket Docker sul sistema host. Il modo in cui configuri questi permessi dipende dalla configurazione del tuo sistema host. Per maggiori informazioni sulla configurazione dei permessi del socket Docker, consulta la documentazione Docker sulla protezione del socket del demone Docker.

Opzioni

Ogni opzione può essere fornita in due forme: da riga di comando o con coppia chiave:valore di ambiente. Alcune opzioni da riga di comando hanno una forma breve, come -l localhost:8080 e tutte hanno la forma lunga, ad esempio --listen=localhost:8080. La chiave (nome) di ambiente elencata per ogni opzione come suffisso, cioè [$LISTEN].

Tutte le opzioni di dimensione supportano suffissi di unità, ad esempio 10K (o 10k) per kilobyte, 16M (o 16m) per megabyte, 10G (o 10g) per gigabyte. La mancanza di qualsiasi suffisso (cioè 1024) indica byte.

Alcune opzioni sono ripetibili; in questo caso l'utente può passarli più volte con la riga di comando, o separati da virgole nelle variabili di ambiente. Ad esempio --ssl.fqdn è una tale opzione e può essere passata come --ssl.fqdn=a1.example.com --ssl.fqdn=a2.example.com o come variabile di ambiente SSL_ACME_FQDN=a1.example.com,a2.example.com

Questa è la lista di tutte le opzioni che supportano più elementi:

  • ssl.fqdn (SSL_ACME_FQDN)
  • assets.cache (ASSETS_CACHE)
  • docker.exclude (DOCKER_EXCLUDE)
  • static.rule ($STATIC_RULES)
  • header ($HEADER)
  • drop-header ($DROP_HEADERS)

Tutte le Opzioni dell'Applicazione```

-l, --listen= listen on host:port (default: 0.0.0.0:8080/8443 under docker, 127.0.0.1:80/443 without) [$LISTEN] -m, --max= max request size (default: 64K) [$MAX_SIZE] -g, --gzip enable gz compression [$GZIP] -x, --header= outgoing proxy headers to add [$HEADER] --drop-header= incoming headers to drop [$DROP_HEADERS] --basic-htpasswd= htpasswd file for basic auth [$BASIC_HTPASSWD]
--lb-type=[random|failover|roundrobin] load balancer type (default: random) [$LB_TYPE] --signature enable reproxy signature headers [$SIGNATURE] --remote-lookup-headers enable remote lookup headers, trust only behind a trusted proxy [$REMOTE_LOOKUP_HEADERS] --keep-host keep original Host header as default when proxying [$KEEP_HOST] --insecure skip SSL verification on destination host [$INSECURE] --dbg debug mode [$DEBUG]

ssl: --ssl.type=[none|static|auto] ssl (auto) support (default: none) [$SSL_TYPE] --ssl.cert= path to cert.pem file [$SSL_CERT] --ssl.key= path to key.pem file [$SSL_KEY] --ssl.acme-location= dir where certificates will be stored by autocert manager (default: ./var/acme) [$SSL_ACME_LOCATION] --ssl.acme-email= admin email for certificate notifications [$SSL_ACME_EMAIL] --ssl.http-port= http port for redirect to https and acme challenge test (default: 8080 under docker, 80 without) [$SSL_HTTP_PORT] --ssl.fqdn= FQDN(s) for ACME certificates [$SSL_ACME_FQDN]

assets: -a, --assets.location= assets location [$ASSETS_LOCATION] --assets.root= assets web root (default: /) [$ASSETS_ROOT] --assets.spa spa treatment for assets [$ASSETS_SPA] --assets.cache= cache duration for assets [$ASSETS_CACHE] --assets.not-found= path to file to serve on 404, relative to location [$ASSETS_NOT_FOUND]

logger: --logger.stdout enable stdout logging [$LOGGER_STDOUT] --logger.enabled enable access and error rotated logs [$LOGGER_ENABLED] --logger.file= location of access log (default: access.log) [$LOGGER_FILE] --logger.max-size= maximum size before it gets rotated (default: 100M) [$LOGGER_MAX_SIZE] --logger.max-backups= maximum number of old log files to retain (default: 10) [$LOGGER_MAX_BACKUPS]

docker: --docker.enabled enable docker provider [$DOCKER_ENABLED] --docker.host= docker host (default: unix:///var/run/docker.sock) [$DOCKER_HOST] --docker.network= docker network [$DOCKER_NETWORK] --docker.exclude= excluded containers [$DOCKER_EXCLUDE] --docker.auto enable automatic routing (without labels) [$DOCKER_AUTO] --docker.prefix= prefix for docker source routes [$DOCKER_PREFIX] --docker.api-version= docker API version (default: 1.24) [$DOCKER_API_VERSION]

consul-catalog: --consul-catalog.enabled enable consul catalog provider [$CONSUL_CATALOG_ENABLED] --consul-catalog.address= consul address (default: http://127.0.0.1:8500) [$CONSUL_CATALOG_ADDRESS] --consul-catalog.interval= consul catalog check interval (default: 1s) [$CONSUL_CATALOG_INTERVAL]

file: --file.enabled enable file provider [$FILE_ENABLED] --file.name= file name (default: reproxy.yml) [$FILE_NAME] --file.interval= file check interval (default: 3s) [$FILE_INTERVAL] --file.delay= reload only after the file has been unchanged for this long (default: 500ms) [$FILE_DELAY]

static: --static.enabled enable static provider [$STATIC_ENABLED] --static.rule= routing rules [$STATIC_RULES]

timeout: --timeout.read-header= read header server timeout (default: 5s) [$TIMEOUT_READ_HEADER] --timeout.write= write server timeout (default: 30s) [$TIMEOUT_WRITE] --timeout.idle= idle server timeout (default: 30s) [$TIMEOUT_IDLE] --timeout.dial= dial transport timeout (default: 30s) [$TIMEOUT_DIAL] --timeout.keep-alive= keep-alive transport timeout (default: 30s) [$TIMEOUT_KEEP_ALIVE] --timeout.resp-header= response header transport timeout (default: 5s) [$TIMEOUT_RESP_HEADER] --timeout.idle-conn= idle connection transport timeout (default: 90s) [$TIMEOUT_IDLE_CONN] --timeout.tls= TLS hanshake transport timeout (default: 10s) [$TIMEOUT_TLS] --timeout.continue= expect continue transport timeout (default: 1s) [$TIMEOUT_CONTINUE]

mgmt: --mgmt.enabled enable management API [$MGMT_ENABLED] --mgmt.listen= listen on host:port (default: 0.0.0.0:8081) [$MGMT_LISTEN] --mgmt.low-cardinality use route patterns instead of raw paths for metrics labels [$MGMT_LOW_CARDINALITY]

error: --error.enabled enable html errors reporting [$ERROR_ENABLED] --error.template= error message template file [$ERROR_TEMPLATE]

health-check: --health-check.enabled enable automatic health-check [$HEALTH_CHECK_ENABLED] --health-check.interval= automatic health-check interval (default: 300s) [$HEALTH_CHECK_INTERVAL]

throttle: --throttle.system= throttle overall activity' (default: 0) [$THROTTLE_SYSTEM] --throttle.user= limit req/sec per user and per proxy destination (default: 0) [$THROTTLE_USER]

upstream: --upstream.max-idle-conns= max idle connections total (default: 100) [$UPSTREAM_MAX_IDLE_CONNS] --upstream.max-conns= max connections per upstream host (0=unlimited) (default: 0) [$UPSTREAM_MAX_CONNS]

plugin: --plugin.enabled enable plugin support [$PLUGIN_ENABLED] --plugin.listen= registration listen on host:port (default: 127.0.0.1:8081) [$PLUGIN_LISTEN]

Help Options: -h, --help Show this help message

## Status

Il progetto è in fase di sviluppo attivo e potrebbe subire modifiche sostanziali fino al rilascio della versione `v1`. Tuttavia, stiamo facendo del nostro meglio per non rompere nulla a meno che non ci sia una buona ragione. A partire dalla versione 0.4.x, reproxy è considerato abbastanza stabile per l'uso reale, e molte configurazioni lo stanno eseguendo in produzione.

Categorie