Skip to content
stdapiPublic

About

Intercepting forward proxy library for Go that supports HTTP/1.1, HTTP/2, HTTP/3, gRPC, WebSocket, TCP, QUIC and UDP, in explicit, transparent and SOCKS5 modes.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

150 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Edge

Edge is an intercepting forward proxy library for Go, designed for building debugging proxies, fault injection tools, traffic recorders, egress gateways, or other applications that need to inspect and control the traffic a client sends over the network. It terminates TLS with certificates issued on demand by a certificate authority the client trusts, and supports HTTP/1.1, HTTP/2, HTTP/3, gRPC, WebSocket, TCP, QUIC and UDP. Edge aims to give every kind of traffic, from an HTTP request to a UDP datagram, its own handler, as simple to write as an HTTP handler.

Edge supports mutation on its routing tree while proxying traffic concurrently. Internally, it uses a Radix Tree adapted from Fox that supports lock-free reads while allowing a concurrent writer. Entries support flexible patterns on the hostname, the port and the path, with named parameters, catch-all wildcards, regexp constraints, address ranges and request matchers. Edge enforces clear priority rules and performs strict validation to prevent misconfigurations.

Warning

Edge is experimental. The API is not stabilized, and breaking changes may occur at any time.

Features

Client to proxy

Traffic Explicit1 Transparent2
routed on
HTTP/1.1 HTTP/2 HTTP/3 SOCKS5
Over TCP HTTP
HTTP/1.1, HTTP/2
request
CONNECT
request
CONNECT
request
CONNECT
CONNECT SNI, Host
or destination
gRPC as HTTP, HTTP/3 included
WebSocket as HTTP/1.1
TCP CONNECT SNI, Host
or destination
Over UDP HTTP
HTTP/3
CONNECT-UDP3
DATAGRAM capsules
request
CONNECT-UDP
QUIC DATAGRAM frames
UDP ASSOCIATE SNI
or destination
QUIC CONNECT-UDP
QUIC DATAGRAM frames
UDP destination
  1. Proxy authentication with HTTP Basic or a custom ProxyAuthenticator, and with a username and a password on SOCKS5.
  2. Requires Linux with REDIRECT or TPROXY, TPROXY for UDP, or macOS with pf and read access to /dev/pf.
  3. CONNECT-UDP over HTTP/2 requires GODEBUG=http2xconnect=1, which enables extended CONNECT in the Go HTTP/2 server.

Proxy to origin

Traffic Direct Chained
http, https
HTTP/1.1
https
HTTP/2
https
HTTP/3
socks5, socks5h
Over TCP HTTP
HTTP/1.1, HTTP/2
HTTP/1.1, HTTP/2, h2c1 CONNECT CONNECT
gRPC
WebSocket HTTP/1.1
TCP TCP or TLS
Over UDP HTTP
HTTP/3
HTTP/32 CONNECT-UDP
DATAGRAM capsules
CONNECT-UDP
QUIC DATAGRAM frames
UDP ASSOCIATE
QUIC QUIC
UDP UDP
  1. h2c for gRPC, and for HTTP only when the client used h2c through a tunnel or a transparent listener.
  2. Opt-in with Transport.AllowHTTP3.


Getting started

Install

With a correctly configured Go toolchain:

go get -u github.com/stdapi/edge

This library requires Go 1.27 or above.

Basic example

The proxy below intercepts the outbound traffic of a checkout service under test. It refuses a Stripe charge sent without an idempotency key, fails one method of a gRPC inventory service, and throttles the responses of a Redis cache to 64 KiB/s.

package main

import (
	"log"
	"net/http"

	"github.com/stdapi/edge"
)

func main() {
	ca, err := edge.LoadCAFile("ca.pem", "ca-key.pem")
	if err != nil {
		log.Fatal(err)
	}

	p := edge.Must(edge.WithCA(ca))

	// Refuse a charge without an idempotency key, forward the others to Stripe.
	p.MustAdd("api.stripe.com/v1/charges", func(c *edge.HTTPCtx) (*http.Response, error) {
		if c.Header("Idempotency-Key") == "" {
			return edge.Text(http.StatusBadRequest, "missing idempotency key"), nil
		}
		return c.Forward()
	}, edge.WithMethods[edge.HTTP](http.MethodPost))

	// Every other Stripe endpoint is forwarded unchanged.
	p.MustAdd("api.stripe.com/*{any}", func(c *edge.HTTPCtx) (*http.Response, error) {
		return c.Forward()
	})

	// One gRPC method fails with UNAVAILABLE, the other methods are forwarded.
	p.MustAdd("inventory.internal/inventory.v1.Inventory/Reserve", func(c *edge.GRPCCtx) error {
		return c.Fail(edge.CodeUnavailable, "inventory unavailable")
	})
	p.MustAdd("inventory.internal/*{method}", func(c *edge.GRPCCtx) error {
		return c.Forward()
	})

	// Throttle the responses of the cache to 64 KiB/s.
	p.MustAdd("cache.internal:6379", func(c *edge.TCPCtx) error {
		up, err := c.Dial()
		if err != nil {
			return err
		}
		_, _, err = edge.Relay(edge.Throttled(c.Client(), 64<<10), up)
		return err
	})

	go func() { log.Fatal(p.ListenAndServeSOCKS5(":1080")) }()
	log.Fatal(p.ListenAndServe(":8080"))
}

License

Apache-2.0. The routing core is adapted from Fox, under the same license.

About

Intercepting forward proxy library for Go that supports HTTP/1.1, HTTP/2, HTTP/3, gRPC, WebSocket, TCP, QUIC and UDP, in explicit, transparent and SOCKS5 modes.

Topics

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages