Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 92 additions & 17 deletions policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
// See below for the different policies.
//
// In case an error is returned the connection is denied.
//
// Deprecated: use ConnPolicyFunc instead.
type PolicyFunc func(upstream net.Addr) (Policy, error)

// ConnPolicyFunc can be used to decide whether to trust the PROXY info
Expand Down Expand Up @@ -53,13 +55,13 @@ const (
SKIP
)

// SkipProxyHeaderForCIDR returns a PolicyFunc which can be used to accept a
// connection from a skipHeaderCIDR without requiring a PROXY header, e.g.
// ConnSkipProxyHeaderForCIDR returns a ConnPolicyFunc which can be used to accept
// a connection from a skipHeaderCIDR without requiring a PROXY header, e.g.
// Kubernetes pods local traffic. The def is a policy to use when an upstream
// address doesn't match the skipHeaderCIDR.
func SkipProxyHeaderForCIDR(skipHeaderCIDR *net.IPNet, def Policy) PolicyFunc {
return func(upstream net.Addr) (Policy, error) {
ip, err := ipFromAddr(upstream)
func ConnSkipProxyHeaderForCIDR(skipHeaderCIDR *net.IPNet, def Policy) ConnPolicyFunc {
return func(connOpts ConnPolicyOptions) (Policy, error) {
ip, err := ipFromAddr(connOpts.Upstream)
if err != nil {
return def, err
}
Expand All @@ -72,36 +74,94 @@ func SkipProxyHeaderForCIDR(skipHeaderCIDR *net.IPNet, def Policy) PolicyFunc {
}
}

// SkipProxyHeaderForCIDR returns a PolicyFunc which can be used to accept a
// connection from a skipHeaderCIDR without requiring a PROXY header, e.g.
// Kubernetes pods local traffic. The def is a policy to use when an upstream
// address doesn't match the skipHeaderCIDR.
//
// Deprecated: use ConnSkipProxyHeaderForCIDR instead.
func SkipProxyHeaderForCIDR(skipHeaderCIDR *net.IPNet, def Policy) PolicyFunc {
connPolicy := ConnSkipProxyHeaderForCIDR(skipHeaderCIDR, def)
return func(upstream net.Addr) (Policy, error) {
return connPolicy(ConnPolicyOptions{Upstream: upstream})
}
}

// WithPolicy adds given policy to a connection when passed as option to NewConn()
func WithPolicy(p Policy) func(*Conn) {
return func(c *Conn) {
c.ProxyHeaderPolicy = p
}
}

// ConnLaxWhiteListPolicy returns a ConnPolicyFunc which decides whether the
// upstream ip is allowed to send a proxy header based on a list of allowed
// IP addresses and IP ranges. In case upstream IP is not in list the proxy
// header will be ignored. If one of the provided IP addresses or IP ranges
// is invalid it will return an error instead of a ConnPolicyFunc.
func ConnLaxWhiteListPolicy(allowed []string) (ConnPolicyFunc, error) {
allowFrom, err := parse(allowed)
if err != nil {
return nil, err
}

return connWhitelistPolicy(allowFrom, IGNORE), nil
}

// LaxWhiteListPolicy returns a PolicyFunc which decides whether the
// upstream ip is allowed to send a proxy header based on a list of allowed
// IP addresses and IP ranges. In case upstream IP is not in list the proxy
// header will be ignored. If one of the provided IP addresses or IP ranges
// is invalid it will return an error instead of a PolicyFunc.
//
// Deprecated: use ConnLaxWhiteListPolicy instead.
func LaxWhiteListPolicy(allowed []string) (PolicyFunc, error) {
allowFrom, err := parse(allowed)
connPolicy, err := ConnLaxWhiteListPolicy(allowed)
if err != nil {
return nil, err
}

return whitelistPolicy(allowFrom, IGNORE), nil
return func(upstream net.Addr) (Policy, error) {
return connPolicy(ConnPolicyOptions{Upstream: upstream})
}, nil
}

// ConnMustLaxWhiteListPolicy returns a ConnLaxWhiteListPolicy but will panic
// if one of the provided IP addresses or IP ranges is invalid.
func ConnMustLaxWhiteListPolicy(allowed []string) ConnPolicyFunc {
pfunc, err := ConnLaxWhiteListPolicy(allowed)
if err != nil {
panic(err)
}

return pfunc
}

// MustLaxWhiteListPolicy returns a LaxWhiteListPolicy but will panic if one
// of the provided IP addresses or IP ranges is invalid.
//
// Deprecated: use ConnMustLaxWhiteListPolicy instead.
func MustLaxWhiteListPolicy(allowed []string) PolicyFunc {
pfunc, err := LaxWhiteListPolicy(allowed)
connPolicy := ConnMustLaxWhiteListPolicy(allowed)
return func(upstream net.Addr) (Policy, error) {
return connPolicy(ConnPolicyOptions{Upstream: upstream})
}
}

// ConnStrictWhiteListPolicy returns a ConnPolicyFunc which decides whether the
// upstream ip is allowed to send a proxy header based on a list of allowed
// IP addresses and IP ranges. In case upstream IP is not in list reading on
// the connection will be refused on the first read. Please note: subsequent
// reads do not error. It is the task of the code using the connection to
// handle that case properly. If one of the provided IP addresses or IP
// ranges is invalid it will return an error instead of a ConnPolicyFunc.
func ConnStrictWhiteListPolicy(allowed []string) (ConnPolicyFunc, error) {
allowFrom, err := parse(allowed)
if err != nil {
panic(err)
return nil, err
}

return pfunc
return connWhitelistPolicy(allowFrom, REJECT), nil
}

// StrictWhiteListPolicy returns a PolicyFunc which decides whether the
Expand All @@ -111,29 +171,44 @@ func MustLaxWhiteListPolicy(allowed []string) PolicyFunc {
// reads do not error. It is the task of the code using the connection to
// handle that case properly. If one of the provided IP addresses or IP
// ranges is invalid it will return an error instead of a PolicyFunc.
//
// Deprecated: use ConnStrictWhiteListPolicy instead.
func StrictWhiteListPolicy(allowed []string) (PolicyFunc, error) {
allowFrom, err := parse(allowed)
connPolicy, err := ConnStrictWhiteListPolicy(allowed)
if err != nil {
return nil, err
}

return whitelistPolicy(allowFrom, REJECT), nil
return func(upstream net.Addr) (Policy, error) {
return connPolicy(ConnPolicyOptions{Upstream: upstream})
}, nil
}

// MustStrictWhiteListPolicy returns a StrictWhiteListPolicy but will panic
// ConnMustStrictWhiteListPolicy returns a ConnStrictWhiteListPolicy but will panic
// if one of the provided IP addresses or IP ranges is invalid.
func MustStrictWhiteListPolicy(allowed []string) PolicyFunc {
pfunc, err := StrictWhiteListPolicy(allowed)
func ConnMustStrictWhiteListPolicy(allowed []string) ConnPolicyFunc {
pfunc, err := ConnStrictWhiteListPolicy(allowed)
if err != nil {
panic(err)
}

return pfunc
}

func whitelistPolicy(allowed []func(net.IP) bool, def Policy) PolicyFunc {
// MustStrictWhiteListPolicy returns a StrictWhiteListPolicy but will panic
// if one of the provided IP addresses or IP ranges is invalid.
//
// Deprecated: use ConnMustStrictWhiteListPolicy instead.
func MustStrictWhiteListPolicy(allowed []string) PolicyFunc {
connPolicy := ConnMustStrictWhiteListPolicy(allowed)
return func(upstream net.Addr) (Policy, error) {
upstreamIP, err := ipFromAddr(upstream)
return connPolicy(ConnPolicyOptions{Upstream: upstream})
}
}

func connWhitelistPolicy(allowed []func(net.IP) bool, def Policy) ConnPolicyFunc {
return func(connOpts ConnPolicyOptions) (Policy, error) {
upstreamIP, err := ipFromAddr(connOpts.Upstream)
if err != nil {
// something is wrong with the source IP, better reject the connection
return REJECT, err
Expand Down
Loading
Loading