router

package
v0.0.0-...-967fbc8 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2024 License: GPL-3.0 Imports: 58 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrConcurrentReload = errors.New("concurrent reloading call")
)
View Source
var (
	ErrUpstreamOffline = errors.New("upstream is currently offline")
)

Functions

func MustRegMiddleware

func MustRegMiddleware(typ string, fn NewMiddlewareFunc)

func RegMetrics

func RegMetrics(r prometheus.Registerer, cs ...prometheus.Collector) error

func RegMiddleware

func RegMiddleware(typ string, fn NewMiddlewareFunc) bool

func ReleaseQueryCtx

func ReleaseQueryCtx(q *QueryCtx)

func SetEmptyRespMQ

func SetEmptyRespMQ(q *QueryCtx, rcode dnsmsg.RCode)

func WakeDecode

func WakeDecode(dst any, src map[string]any, tagName string) error

Types

type APIConfig

type APIConfig struct {
	Addr string `yaml:"addr"`
}

type AddonsConfig

type AddonsConfig struct{}

type CacheConfig

type CacheConfig struct {
	MemSize           int     `yaml:"mem_size"`
	Redis             string  `yaml:"redis"`
	MaximumTTL        int     `yaml:"maximum_ttl"`
	OptimisticTTL     int     `yaml:"optimistic_ttl"`
	PrefetchThreshold float32 `yaml:"prefetch_threshold"`
}

type CacheCtl

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

func (*CacheCtl) Get

func (c *CacheCtl) Get(ctx context.Context, key []byte) (*dnsmsg.Msg, cache.Times)

If cache hit, Get will return a resp (not shared). It is the caller's responsibility to release the reap. TTLs of the reap are properly subtracted.

func (*CacheCtl) Nop

func (c *CacheCtl) Nop() bool

No backend.

func (*CacheCtl) Store

func (c *CacheCtl) Store(key []byte, resp *dnsmsg.Msg)

Store resp into cache. Note: resp must not contain EDNS0 record.

type Config

type Config struct {
	Servers       []ServerConfig       `yaml:"servers"`
	Upstreams     []UpstreamConfig     `yaml:"upstreams"`
	LoadBalancers []LoadBalancerConfig `yaml:"load_balancers"`

	DomainSets []DomainSetConfig `yaml:"domain_sets"`
	Rules      []RuleConfig      `yaml:"rules"`

	Addons AddonsConfig `yaml:"addons"`

	Log   LogConfig   `yaml:"log"`
	Cache CacheConfig `yaml:"cache"`
	ECS   ECSConfig   `yaml:"ecs"`
	API   APIConfig   `yaml:"api"`

	Middleware []map[string]any `yaml:"middleware"`
}

type DataProvider

type DataProvider[V any] interface {
	V() *V
}

Provider data. Do not retain the result of V(), it may change after router reloaded.

type Dataloader

type Dataloader interface {
	// Load T and stage the T. Return false if error ocurred.
	LoadAndStage() (ok bool)

	// Commit the change. If no T staged, this call is noop.
	Commit()

	// Discard the change. If no T staged, this call is noop.
	Discard()
}

type DomainSet

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

func (DomainSet) Commit

func (g DomainSet) Commit()

func (DomainSet) Discard

func (g DomainSet) Discard()

func (DomainSet) LoadAndStage

func (g DomainSet) LoadAndStage() bool

func (*DomainSet) Match

func (g *DomainSet) Match(name dnsmsg.Name) bool

type DomainSetConfig

type DomainSetConfig struct {
	Tag   string   `yaml:"tag"`
	Files []string `yaml:"files"`
}

type ECSConfig

type ECSConfig struct {
	Enabled       bool     `yaml:"enabled"`
	Forward       bool     `yaml:"forward"`
	IpZone        []string `yaml:"ip_zone"`
	ZoneOverwrite []string `yaml:"zone_overwrite"`
}

type ECSZone

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

func (ECSZone) Commit

func (g ECSZone) Commit()

func (ECSZone) Discard

func (g ECSZone) Discard()

func (ECSZone) LoadAndStage

func (g ECSZone) LoadAndStage() bool

func (*ECSZone) Mark

func (z *ECSZone) Mark(addr netip.Addr) (string, bool)

type ECSZoneOverWrite

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

func (ECSZoneOverWrite) Commit

func (g ECSZoneOverWrite) Commit()

func (ECSZoneOverWrite) Discard

func (g ECSZoneOverWrite) Discard()

func (*ECSZoneOverWrite) Get

func (g *ECSZoneOverWrite) Get(z string) (netip.Prefix, bool)

func (ECSZoneOverWrite) LoadAndStage

func (g ECSZoneOverWrite) LoadAndStage() bool

type HealthCheckConfig

type HealthCheckConfig struct {
	MaxFails     int `yaml:"max_fails"`
	PingInterval int `yaml:"ping_interval"`
}

type HttpConfig

type HttpConfig struct {
	Path             string `yaml:"path"`
	ClientAddrHeader string `yaml:"client_addr_header"`

	DebugMaxStreams uint32 `yaml:"debug_max_streams,omitempty"`
}

type LoadBalancer

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

func (*LoadBalancer) Exchange

func (lb *LoadBalancer) Exchange(ctx context.Context, q *QueryCtx, m *dnsmsg.Msg) error

func (*LoadBalancer) Tag

func (lb *LoadBalancer) Tag() string

type LoadBalancerBackendConfig

type LoadBalancerBackendConfig struct {
	Tag    string `yaml:"tag"`
	Weight int    `yaml:"weight"`
	QPS    int    `yaml:"qps"`
}

type LoadBalancerConfig

type LoadBalancerConfig struct {
	Tag      string                      `yaml:"tag"`
	Method   string                      `yaml:"method"`
	Backends []LoadBalancerBackendConfig `yaml:"backends"`
}

type LogConfig

type LogConfig struct {
	Queries   bool `yaml:"queries"`
	TraceMsgs bool `yaml:"trace_msgs"`
}

type Middleware

type Middleware interface {
	// q will be released and reused, thus Handler MUST NOT access it after Handle() returned.
	Handle(ctx context.Context, q *QueryCtx)
}

type NewMiddlewareFunc

type NewMiddlewareFunc func(ctx PluginCtx, args map[string]any, next Middleware) (Middleware, error)

func GetMiddleware

func GetMiddleware(typ string) NewMiddlewareFunc

type PluginCtx

type PluginCtx struct {
	R      *Router         // Not nil
	Logger *zerolog.Logger // Not nil
}

type Proto

type Proto uint8
const (
	ProtoUnKnown Proto = 0
	ProtoUDP     Proto = 1
	ProtoTCP     Proto = 2
	ProtoTLS     Proto = 3
	ProtoHTTP    Proto = 4
	ProtoHTTPS   Proto = 5
	ProtoQUIC    Proto = 6
)

type QueryCtx

type QueryCtx struct {
	Qid   uint32 // rand id for logging only. Not the dns msg id.
	Start time.Time

	Prefetch bool // This is a prefetch query.

	// DNS query
	Question  dnsmsg.Question // Always valid.
	ClientECS netip.Prefix    // ECS from client query. Invalid if client query does not have ECS.

	// Server side info
	ServerTag  string         // Which server the query comes from. Maybe empty if not set.
	Protocol   Proto          // Server protocol.
	RemoteAddr netip.AddrPort // Client addr, maybe invalid. e.g from unix socket.
	ServerName []byte         // TLS servername, if protocol is based on TLS (DoT,DoH,DoQ)
	Host       []byte         // HTTP host (if protocol is based on HTTP)
	Path       []byte         // HTTP path (if protocol is based on HTTP)

	// Other info
	ECS2Upstream netip.Prefix // ECS that is going to send to upstream.
	ECSZone      string       // zone name for the ECS addr.
	// contains filtered or unexported fields
}

func NewQueryCtx

func NewQueryCtx() *QueryCtx

func (*QueryCtx) Copy

func (q *QueryCtx) Copy() *QueryCtx

func (*QueryCtx) LogQuery

func (q *QueryCtx) LogQuery() *zerolog.Event

Important info about the query, qname, type, ecs zone, etc...

func (*QueryCtx) LogResp

func (q *QueryCtx) LogResp() *zerolog.Event

func (*QueryCtx) LogServerMeta

func (q *QueryCtx) LogServerMeta() *zerolog.Event

func (*QueryCtx) Reset

func (q *QueryCtx) Reset()

func (*QueryCtx) Resp

func (q *QueryCtx) Resp() *dnsmsg.Msg

func (*QueryCtx) RespFrom

func (q *QueryCtx) RespFrom() (resp *dnsmsg.Msg, from string)

func (*QueryCtx) SetResp

func (q *QueryCtx) SetResp(resp *dnsmsg.Msg)

func (*QueryCtx) SetRespFrom

func (q *QueryCtx) SetRespFrom(resp *dnsmsg.Msg, from string)

type QuicConfig

type QuicConfig struct {
	MaxStreams int64 `yaml:"max_streams"`
}

type RespWriter

type RespWriter interface {
	// Must be called once.
	WriteResp(m *dnsmsg.Msg)
}

type Router

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

func Run

func Run(cfg *Config) (_ *Router, err error)

func (*Router) AsyncSingleFlightPrefetch

func (r *Router) AsyncSingleFlightPrefetch(key []byte, q *QueryCtx, u Upstream)

Prefetching q in other goroutine. If a query with same key is currently prefetching, do nothing.

func (*Router) BuiltInHandler

func (r *Router) BuiltInHandler(ctx context.Context, q *QueryCtx)

router main handle func.

func (*Router) Close

func (r *Router) Close(err error)

func (*Router) Context

func (r *Router) Context() context.Context

Context will be canceled then Router being closed.

func (*Router) DoPrefetch

func (r *Router) DoPrefetch(key []byte, q *QueryCtx, u Upstream)

Send q to u, and save response under key.

func (*Router) GetApiMux

func (r *Router) GetApiMux() *chi.Mux

func (*Router) GetCache

func (r *Router) GetCache() *CacheCtl

func (*Router) GetDomainSet

func (r *Router) GetDomainSet(tag string) *DomainSet

Nil if not configured.

func (*Router) GetECSZone

func (r *Router) GetECSZone() *ECSZone

Nil if not configured.

func (*Router) GetECSZoneOverwrite

func (r *Router) GetECSZoneOverwrite() *ECSZoneOverWrite

Nil if not configured.

func (*Router) GetLoadBalancer

func (r *Router) GetLoadBalancer(tag string) *LoadBalancer

Nil if not configured.

func (*Router) GetMetricsReg

func (r *Router) GetMetricsReg() *prometheus.Registry

func (*Router) GetUpstream

func (r *Router) GetUpstream(tag string) *UpstreamWrapper

Nil if not configured.

func (*Router) MakeQueryMsg

func (r *Router) MakeQueryMsg(q *QueryCtx) *dnsmsg.Msg

Make a dns msg from q, according to r's settings.

func (*Router) RegMiddlewareReloader

func (r *Router) RegMiddlewareReloader(impl Dataloader)

Register a reloader so that it will be reloaded with api /reload. impl must be comparable. This func is not concurrent safe. Should only be called when middleware is initializing.

func (*Router) Reload

func (r *Router) Reload() (err error)

type RuleConfig

type RuleConfig struct {
	Reverse    bool     `yaml:"reverse"`
	Domain     string   `yaml:"domain"`
	Server     string   `yaml:"server"`
	ServerName string   `yaml:"server_name"`
	Path       string   `yaml:"path"`
	ClientIP   []string `yaml:"client_ip"`
	Reject     uint16   `yaml:"reject"`
	Forward    string   `yaml:"forward"`
}

type ServerConfig

type ServerConfig struct {
	Tag         string       `yaml:"tag"`
	Protocol    string       `yaml:"protocol"`
	Listen      string       `yaml:"listen"`
	IdleTimeout int          `yaml:"idle_timeout"`
	Udp         UdpConfig    `yaml:"udp"`
	Tcp         TcpConfig    `yaml:"tcp"`
	Tls         TlsConfig    `yaml:"tls"`
	Http        HttpConfig   `yaml:"http"`
	Quic        QuicConfig   `yaml:"quic"`
	Socket      SocketConfig `yaml:"socket"`
}

type SocketConfig

type SocketConfig struct {
	SO_REUSEPORT    bool   `yaml:"so_reuseport"` // tcp/udp
	SO_RCVBUF       int    `yaml:"so_rcvbuf"`
	SO_SNDBUF       int    `yaml:"so_sndbuf"`
	SO_MARK         int    `yaml:"so_mark"`
	SO_BINDTODEVICE string `yaml:"so_bindtodevice"`
	// contains filtered or unexported fields
}

Only support linux.

type TcpConfig

type TcpConfig struct {
	MaxConcurrentQueries int32 `yaml:"max_concurrent_queries"`
}

type TlsConfig

type TlsConfig struct {
	Certs              []string `yaml:"certs"`
	Keys               []string `yaml:"keys"`
	CA                 string   `yaml:"ca"`
	InsecureSkipVerify bool     `yaml:"insecure_skip_verify"`
	VerifyClientCert   bool     `yaml:"verify_client_cert"`

	DebugUseTempCert bool `yaml:"debug_use_temp_cert,omitempty"`
}

type UdpConfig

type UdpConfig struct {
	MultiRoutes  bool `yaml:"multi_routes"`
	MaxEdns0Size int  `yaml:"max_edns0_size"`
}

type Upstream

type Upstream interface {
	// Exchange send m to upstream. And set the resp in q.
	// q is for info only, Exchange should not change the info in q, except the resp.
	Exchange(ctx context.Context, q *QueryCtx, m *dnsmsg.Msg) error
}

type UpstreamConfig

type UpstreamConfig struct {
	Tag         string            `yaml:"tag"`
	Addr        string            `yaml:"addr"`
	DialAddr    string            `yaml:"dial_addr"`
	Tls         TlsConfig         `yaml:"tls"`
	Socket      SocketConfig      `yaml:"socket"`
	HealthCheck HealthCheckConfig `yaml:"health_check"`
}

type UpstreamWrapper

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

Wrapper for upstream.Upstream, with tag info and metrics.

func (*UpstreamWrapper) Exchange

func (uw *UpstreamWrapper) Exchange(ctx context.Context, q *QueryCtx, m *dnsmsg.Msg) error

func (*UpstreamWrapper) HcEnabled

func (b *UpstreamWrapper) HcEnabled() bool

func (*UpstreamWrapper) HcOffline

func (b *UpstreamWrapper) HcOffline() bool

Is upstream currently offline. Always return false if health check is disabled.

func (*UpstreamWrapper) HcTryStartPing

func (b *UpstreamWrapper) HcTryStartPing()

Try to start a health check ping asynchronously if upstream is offline. This is useful if caller want trigger the ping test more frequently. e.g. After query failed. 5s minimal ping interval limit applied.

func (*UpstreamWrapper) Ping

func (uw *UpstreamWrapper) Ping(ctx context.Context) error

func (*UpstreamWrapper) RegisterMetricsTo

func (uw *UpstreamWrapper) RegisterMetricsTo(r prometheus.Registerer) error

func (*UpstreamWrapper) Tag

func (uw *UpstreamWrapper) Tag() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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