Skip to content

Commit

Permalink
sqlproxyccl: add proxy protocol listener
Browse files Browse the repository at this point in the history
To support GCP Private Service Connect, we need to have a listener in
SQLProxy which expects packets to contain proxy protocol headers. This
listener will be used for all traffic inbound from PSC. At the same
time, SQLProxy must continue to accept connections through the public
Internet which will not contain proxy protocol headers, and for which
any proxy protocol headers we receive cannot be trusted.

This commit introduces an optional second listener in SQLProxy,
controlled by `--proxy-protocol-listen-addr`, which requires
proxy protocol even as the primary listener doesn't. Private Service
Connect will direct traffic to this second listener.

Resolves #117240

Release note: None
  • Loading branch information
DuskEagle committed Jan 17, 2024
1 parent 39b9baa commit 4384a2b
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 111 deletions.
1 change: 1 addition & 0 deletions pkg/ccl/cliccl/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func init() {
cliflagcfg.StringFlag(f, &proxyContext.Denylist, cliflags.DenyList)
cliflagcfg.StringFlag(f, &proxyContext.Allowlist, cliflags.AllowList)
cliflagcfg.StringFlag(f, &proxyContext.ListenAddr, cliflags.ProxyListenAddr)
cliflagcfg.StringFlag(f, &proxyContext.ProxyProtocolListenAddr, cliflags.ProxyProtocolListenAddr)
cliflagcfg.StringFlag(f, &proxyContext.ListenCert, cliflags.ListenCert)
cliflagcfg.StringFlag(f, &proxyContext.ListenKey, cliflags.ListenKey)
cliflagcfg.StringFlag(f, &proxyContext.MetricsAddress, cliflags.ListenMetrics)
Expand Down
30 changes: 23 additions & 7 deletions pkg/ccl/cliccl/mt_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,20 @@ func runStartSQLProxy(cmd *cobra.Command, args []string) (returnErr error) {

log.Infof(ctx, "New proxy with opts: %+v", proxyContext)

proxyLn, err := net.Listen("tcp", proxyContext.ListenAddr)
if err != nil {
return err
var proxyLn net.Listener
if proxyContext.ListenAddr != "" {
proxyLn, err = net.Listen("tcp", proxyContext.ListenAddr)
if err != nil {
return err
}
}

var proxyProtocolLn net.Listener
if proxyContext.ProxyProtocolListenAddr != "" {
proxyProtocolLn, err = net.Listen("tcp", proxyContext.ProxyProtocolListenAddr)
if err != nil {
return err
}
}

metricsLn, err := net.Listen("tcp", proxyContext.MetricsAddress)
Expand All @@ -84,15 +95,14 @@ func runStartSQLProxy(cmd *cobra.Command, args []string) (returnErr error) {
}

if err := stopper.RunAsyncTask(ctx, "serve-proxy", func(ctx context.Context) {
log.Infof(ctx, "proxy server listening at %s", proxyLn.Addr())
if err := server.Serve(ctx, proxyLn); err != nil {
if err := server.ServeSQL(ctx, proxyLn, proxyProtocolLn); err != nil {
errChan <- err
}
}); err != nil {
return err
}

return waitForSignals(ctx, server, stopper, proxyLn, errChan)
return waitForSignals(ctx, server, stopper, proxyLn, proxyProtocolLn, errChan)
}

func initLogging(cmd *cobra.Command) (ctx context.Context, stopper *stop.Stopper, err error) {
Expand All @@ -110,6 +120,7 @@ func waitForSignals(
server *sqlproxyccl.Server,
stopper *stop.Stopper,
proxyLn net.Listener,
proxyProtocolLn net.Listener,
errChan chan error,
) (returnErr error) {
// Need to alias the signals if this has to run on non-unix OSes too.
Expand Down Expand Up @@ -139,7 +150,12 @@ func waitForSignals(
// waiting for "shutdownConnectionTimeout" to elapse after which
// open TCP connections will be forcefully closed so the server can stop
log.Infof(ctx, "stopping tcp listener")
_ = proxyLn.Close()
if proxyLn != nil {
_ = proxyLn.Close()
}
if proxyProtocolLn != nil {
_ = proxyProtocolLn.Close()
}
select {
case <-server.AwaitNoConnections(ctx):
case <-time.After(shutdownConnectionTimeout):
Expand Down
10 changes: 8 additions & 2 deletions pkg/ccl/sqlproxyccl/proxy_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ type ProxyOptions struct {
Denylist string
// ListenAddr is the listen address for incoming connections.
ListenAddr string
// ProxyProtocolListenAddr is the optional listen address for incoming
// connections for which it will be enforced that the connections have proxy
// headers set.
ProxyProtocolListenAddr string
// ListenCert is the file containing PEM-encoded x509 certificate for listen
// address. Set to "*" to auto-generate self-signed cert.
ListenCert string
Expand Down Expand Up @@ -113,8 +117,10 @@ type ProxyOptions struct {
DisableConnectionRebalancing bool
// RequireProxyProtocol changes the server's behavior to support the PROXY
// protocol (SQL=required, HTTP=best-effort). With this set to true, the
// PROXY info from upstream will be trusted on both HTTP and SQL, if the
// headers are allowed.
// PROXY info from upstream will be trusted on both HTTP and SQL (on the
// ListenAddr port), if the headers are allowed. The ProxyProtocolListenAddr
// port, if specified, will require the proxy protocol regardless of
// RequireProxyProtocol.
RequireProxyProtocol bool

// testingKnobs are knobs used for testing.
Expand Down
Loading

0 comments on commit 4384a2b

Please sign in to comment.