bastion 0.63.1
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
// lanedial.go: the one place a lane turns the connection its pairing's
|
||||
// transport hands it into the mutual TLS the lane runs inside.
|
||||
//
|
||||
// Every transport but one hands a lane a plain connection (the tunnel, the
|
||||
// lane socket, a Host's lane port), and the TLS is done here exactly as the
|
||||
// WebSocket library did it before: the pairing's lane configuration, the
|
||||
// server name it names, the handshake under the dial's context, and the name
|
||||
// checked once more. A Host that connects to this server (hostdoor.go) hands
|
||||
// the lane a connection whose TLS the door already did, under the same
|
||||
// configuration (the Host's CA pinned, host.cseries.internal, this bastion's
|
||||
// operator certificate): that one is passed on as it is. So the lane code is
|
||||
// the same for every pairing; only the dial differs.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// laneTLSDial is the TLS dial every lane uses: dialHost's connection with the
|
||||
// lane's TLS done on it, or a Host-opened connection as the door left it.
|
||||
func laneTLSDial(dialHost func(ctx context.Context) (net.Conn, error), tlsCfg *tls.Config) func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return func(ctx context.Context, _, addr string) (net.Conn, error) {
|
||||
c, err := dialHost(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if hc, ok := c.(*hostOpenedConn); ok {
|
||||
return hc, nil
|
||||
}
|
||||
cfg := tlsCfg.Clone()
|
||||
if cfg == nil {
|
||||
cfg = &tls.Config{}
|
||||
}
|
||||
if cfg.ServerName == "" {
|
||||
if h, _, err := net.SplitHostPort(addr); err == nil {
|
||||
cfg.ServerName = h
|
||||
} else {
|
||||
cfg.ServerName = addr
|
||||
}
|
||||
}
|
||||
tc := tls.Client(c, cfg)
|
||||
if err := tc.HandshakeContext(ctx); err != nil {
|
||||
_ = c.Close()
|
||||
return nil, err
|
||||
}
|
||||
if !cfg.InsecureSkipVerify {
|
||||
if err := tc.VerifyHostname(cfg.ServerName); err != nil {
|
||||
_ = tc.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return tc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// laneWSDialer is the WebSocket dialer every lane worker pool uses.
|
||||
func laneWSDialer(tlsCfg *tls.Config, dialHost func(ctx context.Context) (net.Conn, error)) *websocket.Dialer {
|
||||
return &websocket.Dialer{
|
||||
NetDialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { return dialHost(ctx) },
|
||||
NetDialTLSContext: laneTLSDial(dialHost, tlsCfg),
|
||||
TLSClientConfig: tlsCfg,
|
||||
HandshakeTimeout: 20 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// laneHTTPTransport is the HTTP transport of a local pairing's requests (the
|
||||
// heartbeat, git credentials, store proposals, context pulls).
|
||||
func laneHTTPTransport(dialHost func(ctx context.Context) (net.Conn, error), tlsCfg *tls.Config) *http.Transport {
|
||||
return &http.Transport{
|
||||
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { return dialHost(ctx) },
|
||||
DialTLSContext: laneTLSDial(dialHost, tlsCfg),
|
||||
TLSClientConfig: tlsCfg.Clone(),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user