Documentation
¶
Overview ¶
Package echo provides a simple proxy server implementation in Go, inspired by Whistle.
Features ¶
- HTTP Proxy: Supports standard HTTP proxying.
- HTTPS/TCP Tunneling: Supports CONNECT method for HTTPS and generic TCP tunneling.
- WebSocket Support: Supports WebSocket upgrades (hijacking) and tunneling.
- Plugin System: Flexible plugin system to modify requests and responses.
Quick Start ¶
To start the proxy server, provide a Root CA certificate and private key:
certFile, _ := os.ReadFile("certs/rootCA.crt")
keyFile, _ := os.ReadFile("certs/rootCA.key")
e, err := echo.NewEcho(certFile, keyFile)
if err != nil {
log.Fatal(err)
}
server := &http.Server{
Addr: ":8888",
Handler: e,
}
server.ListenAndServe()
Plugins ¶
Add plugins to intercept and modify requests/responses:
e.AddPlugin(&echo.Plugin{
Match: "example.com",
OnRequest: func(ctx *echo.Context) {
ctx.SetRequestHeader("X-Custom-Header", "value")
},
OnResponse: func(ctx *echo.Context) {
body, _ := ctx.GetResponseBody()
ctx.SetResponseBody(strings.ReplaceAll(body, "old", "new"))
},
})
Forwarding ¶
Use TargetConfig to forward requests to a different server:
e.AddPlugin(&echo.Plugin{
Match: "example.com",
Target: &echo.TargetConfig{Protocol: "http", Host: "localhost", Port: 3000},
})
Mock Response ¶
Use MockResponse to return a static response:
e.AddPlugin(&echo.Plugin{
Match: "example.com/api",
MockResponse: &echo.MockResponse{
StatusCode: 200,
Headers: map[string]string{"Content-Type": "application/json"},
Body: `{"status":"ok"}`,
},
})
Index ¶
- func CopyHeader(dst, src http.Header)
- func DecompressBody(res *http.Response) (io.ReadCloser, error)
- func DelHopHeaders(header http.Header)
- func IsMatch(hostname, pattern string) bool
- func IsWebSocketRequest(r *http.Request) bool
- func SetLogEnabled(enabled bool)
- type ConnectHandler
- type Context
- func (c *Context) DelRequestHeader(key string)
- func (c *Context) DelResponseHeader(key string)
- func (c *Context) GetMockResponse() *MockResponse
- func (c *Context) GetRequestHeader(key string) string
- func (c *Context) GetResponseBody() (string, error)
- func (c *Context) GetResponseHeader(key string) string
- func (c *Context) Mock(status int, headers map[string]string, body interface{})
- func (c *Context) SetRequestHeader(key, value string)
- func (c *Context) SetResponseBody(body string)
- func (c *Context) SetResponseHeader(key, value string)
- type Echo
- type HTTPHandler
- type MitmServer
- type MockResponse
- type Plugin
- type PluginLoader
- func (l *PluginLoader) AddPlugin(plugin *Plugin)
- func (l *PluginLoader) GetPlugins() []*Plugin
- func (l *PluginLoader) Load(plugins []*Plugin) error
- func (l *PluginLoader) MatchPlugin(hostname string) *Plugin
- func (l *PluginLoader) MatchPluginForRequest(r *http.Request) *Plugin
- func (l *PluginLoader) MatchPlugins(hostname string) []*Plugin
- func (l *PluginLoader) MatchPluginsForRequest(r *http.Request) []*Plugin
- type TargetConfig
- type WebSocketHandler
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CopyHeader ¶
CopyHeader copies headers from source to destination
func DecompressBody ¶
func DecompressBody(res *http.Response) (io.ReadCloser, error)
DecompressBody returns a reader that decompresses the response body if needed
func DelHopHeaders ¶
DelHopHeaders removes hop-by-hop headers
func IsMatch ¶
IsMatch checks if a hostname matches a pattern Supports: - Exact match: "example.com" - Wildcard: "*.example.com" - Substring: "example" (matches "example.com", "test.example.com", etc.)
func IsWebSocketRequest ¶
IsWebSocketRequest checks if the request is a WebSocket upgrade
func SetLogEnabled ¶
func SetLogEnabled(enabled bool)
Types ¶
type ConnectHandler ¶
type ConnectHandler struct {
CertManager *cert.Manager
PluginLoader *PluginLoader
HTTPHandler *HTTPHandler // Shared HTTP handler
// contains filtered or unexported fields
}
ConnectHandler handles CONNECT requests and MITM
func (*ConnectHandler) HandleTunnel ¶
func (h *ConnectHandler) HandleTunnel(w http.ResponseWriter, r *http.Request)
HandleTunnel handles the CONNECT request
type Context ¶
type Context struct {
Req *http.Request
Res *http.Response // Nil in OnRequest
// contains filtered or unexported fields
}
Context provides access to the request and response for plugins
func (*Context) DelRequestHeader ¶
DelRequestHeader deletes a header from the request
func (*Context) DelResponseHeader ¶
DelResponseHeader deletes a header from the response
func (*Context) GetMockResponse ¶
func (c *Context) GetMockResponse() *MockResponse
GetMockResponse returns the set mock response
func (*Context) GetRequestHeader ¶
GetRequestHeader gets a header from the request
func (*Context) GetResponseBody ¶
GetResponseBody reads and returns the response body as a string It automatically decompresses the body if needed and updates the response to be uncompressed for subsequent reads.
func (*Context) GetResponseHeader ¶
GetResponseHeader gets a header from the response
func (*Context) SetRequestHeader ¶
SetRequestHeader sets a header on the request
func (*Context) SetResponseBody ¶
SetResponseBody sets the response body
func (*Context) SetResponseHeader ¶
SetResponseHeader sets a header on the response
type HTTPHandler ¶
type HTTPHandler struct {
PluginLoader *PluginLoader
Transport *http.Transport
}
HTTPHandler handles standard HTTP proxy requests
func NewHTTPHandler ¶
func NewHTTPHandler(loader *PluginLoader) *HTTPHandler
NewHTTPHandler creates a new HTTP handler with a custom transport
func (*HTTPHandler) HandleRequest ¶
func (h *HTTPHandler) HandleRequest(w http.ResponseWriter, r *http.Request)
HandleRequest processes the HTTP request
type MitmServer ¶
type MockResponse ¶
type MockResponse struct {
StatusCode int
Headers map[string]string
Body interface{} // string or []byte
}
MockResponse defines a static response to return
type Plugin ¶
type Plugin struct {
Match string
Target *TargetConfig
MockResponse *MockResponse
// Hooks
OnRequest func(ctx *Context)
OnResponse func(ctx *Context)
}
Plugin represents a forwarding rule configuration
type PluginLoader ¶
type PluginLoader struct {
// contains filtered or unexported fields
}
PluginLoader handles loading and managing plugins
func NewPluginLoader ¶
func NewPluginLoader(plugins []*Plugin) (*PluginLoader, error)
NewPluginLoader creates a new plugin loader
func (*PluginLoader) AddPlugin ¶
func (l *PluginLoader) AddPlugin(plugin *Plugin)
func (*PluginLoader) GetPlugins ¶
func (l *PluginLoader) GetPlugins() []*Plugin
GetPlugins returns all loaded plugins
func (*PluginLoader) Load ¶
func (l *PluginLoader) Load(plugins []*Plugin) error
Load loads plugins from the hardcoded registry
func (*PluginLoader) MatchPlugin ¶
func (l *PluginLoader) MatchPlugin(hostname string) *Plugin
MatchPlugin finds the first plugin that matches the given hostname
func (*PluginLoader) MatchPluginForRequest ¶
func (l *PluginLoader) MatchPluginForRequest(r *http.Request) *Plugin
func (*PluginLoader) MatchPlugins ¶
func (l *PluginLoader) MatchPlugins(hostname string) []*Plugin
MatchPlugins returns all plugins that match the given hostname, in order
func (*PluginLoader) MatchPluginsForRequest ¶
func (l *PluginLoader) MatchPluginsForRequest(r *http.Request) []*Plugin
MatchPluginsForRequest returns all plugins that match the given request URL/host, in order
type TargetConfig ¶
TargetConfig defines where to forward requests
func (*TargetConfig) GetDefaultPort ¶
func (t *TargetConfig) GetDefaultPort() int
GetDefaultPort returns the default port for the protocol
func (*TargetConfig) GetHostPort ¶
func (t *TargetConfig) GetHostPort() string
GetHostPort returns the host:port combination
func (*TargetConfig) GetTargetURL ¶
func (t *TargetConfig) GetTargetURL(path string) string
GetTargetURL returns the full target URL for forwarding
type WebSocketHandler ¶
type WebSocketHandler struct {
PluginLoader *PluginLoader
}
WebSocketHandler handles WebSocket upgrades
func (*WebSocketHandler) HandleUpgrade ¶
func (h *WebSocketHandler) HandleUpgrade(w http.ResponseWriter, r *http.Request, isSecure bool)
HandleUpgrade handles the WebSocket upgrade request