e52b554c0b
* Add an idle timeout for the server Because tidy operations can be long-running, this also changes all tidy operations to behave the same operationally (kick off the process, get a warning back, log errors to server log) and makes them all run in a goroutine. This could mean a sort of hard stop if Vault gets sealed because the function won't have the read lock. This should generally be okay (running tidy again should pick back up where it left off), but future work could use cleanup funcs to trigger the functions to stop. * Fix up tidy test * Add deadline to cluster connections and an idle timeout to the cluster server, plus add readheader/read timeout to api server
81 lines
2 KiB
Go
81 lines
2 KiB
Go
package proxyutil
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
|
|
proxyproto "github.com/armon/go-proxyproto"
|
|
"github.com/hashicorp/errwrap"
|
|
sockaddr "github.com/hashicorp/go-sockaddr"
|
|
"github.com/hashicorp/vault/helper/parseutil"
|
|
)
|
|
|
|
// ProxyProtoConfig contains configuration for the PROXY protocol
|
|
type ProxyProtoConfig struct {
|
|
sync.RWMutex
|
|
Behavior string
|
|
AuthorizedAddrs []*sockaddr.SockAddrMarshaler `json:"authorized_addrs"`
|
|
}
|
|
|
|
func (p *ProxyProtoConfig) SetAuthorizedAddrs(addrs interface{}) error {
|
|
aa, err := parseutil.ParseAddrs(addrs)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
p.AuthorizedAddrs = aa
|
|
return nil
|
|
}
|
|
|
|
// WrapInProxyProto wraps the given listener in the PROXY protocol. If behavior
|
|
// is "use_if_authorized" or "deny_if_unauthorized" it also configures a
|
|
// SourceCheck based on the given ProxyProtoConfig. In an error case it returns
|
|
// the original listener and the error.
|
|
func WrapInProxyProto(listener net.Listener, config *ProxyProtoConfig) (net.Listener, error) {
|
|
config.Lock()
|
|
defer config.Unlock()
|
|
|
|
var newLn *proxyproto.Listener
|
|
|
|
switch config.Behavior {
|
|
case "use_always":
|
|
newLn = &proxyproto.Listener{
|
|
Listener: listener,
|
|
ProxyHeaderTimeout: 10 * time.Second,
|
|
}
|
|
|
|
case "allow_authorized", "deny_unauthorized":
|
|
newLn = &proxyproto.Listener{
|
|
Listener: listener,
|
|
ProxyHeaderTimeout: 10 * time.Second,
|
|
SourceCheck: func(addr net.Addr) (bool, error) {
|
|
config.RLock()
|
|
defer config.RUnlock()
|
|
|
|
sa, err := sockaddr.NewSockAddr(addr.String())
|
|
if err != nil {
|
|
return false, errwrap.Wrapf("error parsing remote address: {{err}}", err)
|
|
}
|
|
|
|
for _, authorizedAddr := range config.AuthorizedAddrs {
|
|
if authorizedAddr.Contains(sa) {
|
|
return true, nil
|
|
}
|
|
}
|
|
|
|
if config.Behavior == "allow_authorized" {
|
|
return false, nil
|
|
}
|
|
|
|
return false, proxyproto.ErrInvalidUpstream
|
|
},
|
|
}
|
|
default:
|
|
return listener, fmt.Errorf("unknown behavior type for proxy proto config")
|
|
}
|
|
|
|
return newLn, nil
|
|
}
|