egressproxy

package
v0.23.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package egressproxy 进程级出口强制:一个只监听回环的本地 HTTP 代理 (含 `CONNECT` 隧道),作为「声明了受限出口」的**兑现件**。

它补的是哪个洞

子进程(以及宿主起的 curl / git / 各种 native 工具)的出站流量在编排进程的 任何 Go 层守卫之外:`HTTP_PROXY` 只是一组环境变量,子进程可以忽略它。 于是「声明了受限出口」与「实际能出网」之间没有任何东西——直到有一个**真的 在中间拦着**的代理,并且子进程只能经它出去。

两层缺一不可:

  • 代理(本包):真的拦、真的拒、默认拒绝;
  • 环境下发(agent-harness 的 `egress.Spec.Env`):把子进程指过来。

只有其中一层都等于没有:代理没人用是装饰,env 没人拦是空话。

边界

  • **只监听回环**(`127.0.0.1:0`),不对外提供服务;
  • 只做**目标准入**(主机 + 端口 + 只读方法),不看内容——`CONNECT` 之后是 TLS,看不到任何字节,这一点在 `Limited` 的文档里写清,不假装能看见;
  • 不认识任何业务概念:白/黑名单由调用方给,本包只判。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BlockedError

type BlockedError struct {
	Host   string
	Port   int
	Reason string
}

BlockedError 准入拒绝(结构化:调用方按需呈现原因与目标)。

func (*BlockedError) Error

func (e *BlockedError) Error() string

type Policy

type Policy struct {
	// AllowHosts 允许的目标主机:精确主机名,或通配后缀 "*.example.com"。
	//
	// 通配语义**只匹配子域**:`*.example.com` 命中 `a.example.com` 与
	// `a.b.example.com`,**不**命中 `example.com`(要它请显式写一条),
	// 也**不**命中 `evilexample.com`(后缀按标签边界比,不做裸后缀比较)。
	// 单独一个 "*" 表示放行全部主机(此时 `DenyHosts` 仍然优先)——
	// 这是「只做黑名单」的唯一写法,必须显式写出来。
	AllowHosts []string
	// DenyHosts 拒绝的目标主机(语义同 AllowHosts,**优先于** AllowHosts)。
	DenyHosts []string
	// AllowPorts 允许的目标端口。空 ⇒ 只允许 443 与 80。
	//
	// 为什么空缺省不是「全部端口」:代理最常见的失手是「主机名单对了,
	// 但放行了 22 或 3306」——端口是攻击面的一部分,必须显式开。
	AllowPorts []int
	// Limited 只读模式:**明文**请求只允许 GET / HEAD。
	//
	// ⚠️ 对 `CONNECT` 不生效且无法生效:CONNECT 之后是 TLS(或任意协议),
	// 方法不可见。所以 Limited 对 HTTPS 只保证「目标主机在名单内」,
	// 不保证「只读」——这是能力的真实边界,写在这里而不是留给使用者猜。
	Limited bool
}

Policy 代理的放行面。

**默认拒绝**:`AllowHosts` 为空 ⇒ 任何目标都不放行(不是「不限」)。 这条缺省与 permgate / sandbox 的口径一致——沉默按最弱处理, 「没配置」绝不能被读成「放行」。

func (Policy) Permit

func (p Policy) Permit(host string, port int) error

Permit 判一个目标是否放行。拒绝一律返回 *BlockedError。

func (Policy) Ports

func (p Policy) Ports() []int

Ports 返回落到生效值的端口清单(空 ⇒ 80/443),顺序确定。

func (Policy) Validate

func (p Policy) Validate() error

Validate 自检放行面本身是否可用(写错即报错,不静默按空名单跑)。

type Proxy

type Proxy struct {
	// contains filtered or unexported fields
}

Proxy 本地出口代理(HTTP 转发 + CONNECT 隧道)。

零值不可用:必须 `New` → `Start`。`Close` 幂等。

func New

func New(p Policy) (*Proxy, error)

New 构造代理(**不启动**)。放行面非法即报错——不带着半份策略开始服务。

func (*Proxy) Addr

func (p *Proxy) Addr() string

Addr 返回监听地址(未启动时为空)。

func (*Proxy) Close

func (p *Proxy) Close() error

Close 停止服务并释放连接(幂等)。

func (*Proxy) Egress

func (p *Proxy) Egress() sandbox.EgressMode

Egress 实现 sandbox.EgressEnforcer:本代理能兑现的是 `proxy` 档。

**不声称 `denied`**:代理挡得住「经过它的流量」,挡不住绕开代理的原始 socket —— 声称禁网就是让档位表说谎。

func (*Proxy) ServeHTTP

func (p *Proxy) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP 实现 http.Handler(代理形态)。

func (*Proxy) Start

func (p *Proxy) Start() (string, error)

Start 在回环上监听并开始服务,返回可直接用于环境变量的代理地址 (形如 `http://127.0.0.1:3128`)。

**只监听 127.0.0.1**:它是要塞的墙,不是要对外开放的服务。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL