Documentation
¶
Index ¶
- func Forward(ctx context.Context, client, upstream net.Conn, peeked []byte, ...)
- func LimitWriter(w io.Writer, n int64) io.Writer
- func LoadOrCreateCA(dir string) (*x509.Certificate, *ecdsa.PrivateKey, *tls.Certificate, error)
- func LogModeString(m LogMode) string
- func PeekClientHello(conn net.Conn) (peeked []byte, serverName string, err error)
- func RemoveStats(path string)
- func SetLogMode(mode LogMode)
- func StatsPath() string
- func WriteStats(path string, s Stats) error
- type Config
- type Decider
- type InteractiveDecider
- type Interceptor
- type LeafCache
- type LogMode
- type LoggingInterceptor
- type Mode
- type NetworkEventEmitter
- type Policy
- type PromptFunc
- type Server
- type Stats
- type TrafficLog
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Forward ¶
Forward pipes data bidirectionally between client and upstream, replaying peeked ClientHello bytes to upstream first.
func LimitWriter ¶
LimitWriter returns a writer that writes at most n bytes to w.
func LoadOrCreateCA ¶
func LoadOrCreateCA(dir string) (*x509.Certificate, *ecdsa.PrivateKey, *tls.Certificate, error)
LoadOrCreateCA loads an existing CA certificate and key from dir, or generates a new self-signed CA if none exists. Returns the parsed certificate, private key, and a tls.Certificate ready for signing leaf certs.
func LogModeString ¶
LogModeString returns the string representation of a LogMode. An unknown value is reported as "off" rather than a more permissive mode so a corrupted value can never silently escalate logging.
func PeekClientHello ¶
PeekClientHello reads the TLS ClientHello from conn without consuming it. Returns the peeked bytes (to replay to upstream) and the extracted SNI hostname.
func RemoveStats ¶
func RemoveStats(path string)
RemoveStats removes the proxy stats file (best-effort).
func StatsPath ¶
func StatsPath() string
StatsPath returns the default path for the proxy stats file (~/.human/proxy-stats.json).
func WriteStats ¶
WriteStats atomically writes stats to path (write tmp + rename).
Types ¶
type Config ¶
type Config struct {
Mode Mode `mapstructure:"mode"`
Domains []string `mapstructure:"domains"`
Intercept []string `mapstructure:"intercept"` // domains to MITM for traffic logging
}
Config holds the proxy section of .humanconfig.yaml.
func LoadConfig ¶
LoadConfig reads the proxy configuration from .humanconfig.yaml in dir. Returns (nil, nil) when the proxy section is absent.
type InteractiveDecider ¶
type InteractiveDecider struct {
// contains filtered or unexported fields
}
InteractiveDecider wraps a base Decider and prompts the user for hostnames that the base does not allow. Decisions are cached for the session.
func NewInteractiveDecider ¶
func NewInteractiveDecider(base Decider, prompt PromptFunc) *InteractiveDecider
NewInteractiveDecider creates an InteractiveDecider that falls through to prompt for hostnames not allowed by base.
func (*InteractiveDecider) Allowed ¶
func (d *InteractiveDecider) Allowed(hostname string) bool
Allowed returns true if the hostname is permitted. Hostnames allowed by the base decider pass through immediately. Unknown hostnames trigger a prompt; the result is cached for subsequent calls.
type Interceptor ¶
type Interceptor interface {
// ShouldIntercept returns true if this domain should be MITM'd.
ShouldIntercept(hostname string) bool
// Intercept handles a MITM'd connection. The peeked bytes contain the
// already-read ClientHello that must be replayed into the TLS handshake.
Intercept(ctx context.Context, conn net.Conn, hostname string, peeked []byte) error
}
Interceptor can intercept and inspect decrypted traffic for specific domains.
type LeafCache ¶
type LeafCache struct {
CACert *x509.Certificate
CAKey *ecdsa.PrivateKey
// contains filtered or unexported fields
}
LeafCache generates and caches per-domain TLS certificates signed by a CA. Cache size is bounded; concurrent requests for the same hostname collapse onto a single generation call.
type LogMode ¶
type LogMode int32
LogMode controls the verbosity of traffic logging.
func ParseLogMode ¶
ParseLogMode parses a string into a LogMode. Unknown input returns LogModeOff along with the parse error, so a typo in config cannot accidentally widen what gets captured.
type LoggingInterceptor ¶
type LoggingInterceptor struct {
Domains []string // exact domain matches to intercept
LeafCache *LeafCache
Logger zerolog.Logger
LogDir string // directory for traffic log files
// Dialer connects to upstream servers. Injected for testing.
// If nil, tls.Dial is used.
Dialer func(ctx context.Context, network, address string) (net.Conn, error)
// contains filtered or unexported fields
}
LoggingInterceptor performs MITM interception for configured domains, logging HTTP request/response bodies to JSON-lines files.
func (*LoggingInterceptor) Intercept ¶
func (li *LoggingInterceptor) Intercept(ctx context.Context, conn net.Conn, hostname string, peeked []byte) error
Intercept performs a MITM TLS handshake with the client, dials the real upstream, and proxies HTTP traffic while logging request/response bodies.
func (*LoggingInterceptor) ShouldIntercept ¶
func (li *LoggingInterceptor) ShouldIntercept(hostname string) bool
ShouldIntercept returns true if hostname matches a configured intercept domain.
type NetworkEventEmitter ¶
type NetworkEventEmitter interface {
// Emit records a single network decision or failure.
// Source is one of "proxy", "oauth", "fail".
// Status is a short human readable decision: "forward", "intercept",
// "block", "no-sni", "parse-fail", "dial-fail", "callback".
// Host may be empty for failures that happen before SNI extraction.
Emit(source, status, host string)
}
NetworkEventEmitter is the minimal interface the SNI proxy uses to surface ambient network activity (forwards, intercepts, blocks, failures) to any external observer. The daemon's NetworkEventStore satisfies this interface. The proxy package does not depend on the daemon package so the dependency direction stays one-way.
type Policy ¶
type Policy struct {
// contains filtered or unexported fields
}
Policy decides whether a given hostname is allowed to pass through the proxy.
func BlockAllPolicy ¶
func BlockAllPolicy() *Policy
BlockAllPolicy returns a policy that blocks every hostname.
type PromptFunc ¶
PromptFunc asks the user whether a hostname should be allowed. It returns true to allow, false to deny.
func NewTerminalPrompt ¶
func NewTerminalPrompt(in io.Reader, out io.Writer) PromptFunc
NewTerminalPrompt returns a PromptFunc that asks the user via the terminal. It serialises I/O with its own mutex so that concurrent prompts don't interleave on the terminal.
type Server ¶
type Server struct {
Addr string
Policy Decider
Interceptor Interceptor // optional: MITM interceptor for specific domains
Logger zerolog.Logger
// Emitter records ambient network decisions for the TUI activity
// panel. Optional — nil means no events are recorded so tests and
// standalone use pay nothing for the feature.
Emitter NetworkEventEmitter
// Dialer connects to upstream servers. Injected for testing.
Dialer func(ctx context.Context, network, address string) (net.Conn, error)
// contains filtered or unexported fields
}
Server is a transparent HTTPS proxy that reads the SNI from TLS ClientHello to block/allow domains without decrypting traffic. Domains listed in the Interceptor are MITM'd for traffic inspection/logging.
func (*Server) ActiveConns ¶
ActiveConns returns the number of currently active forwarded connections.
type Stats ¶
type Stats struct {
ActiveConns int64 `json:"active_conns"`
}
Stats holds proxy runtime metrics written by the daemon and read by the TUI.
type TrafficLog ¶
type TrafficLog struct {
Timestamp time.Time `json:"ts"`
Direction string `json:"dir"` // "request" or "response"
Host string `json:"host"`
Method string `json:"method,omitempty"` // request only
Path string `json:"path,omitempty"` // request only
Status int `json:"status,omitempty"` // response only
Body string `json:"body"`
BodySize int64 `json:"body_size"`
}
TrafficLog is a single JSON-lines entry written to the traffic log.