mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
session: fix mailbox TLS ALPN regression
Starting in grpc-go v1.67.0, clients and servers reject TLS handshakes when ALPN is not negotiated. This changed the default value of GRPC_ENFORCE_ALPN_ENABLED from false to true. The default flip is in https://github.com/grpc/grpc-go/pull/7535 Our mailbox transport handshake can reach endpoints that currently do not negotiate ALPN, so LNC session setup started failing and the lnc_auth flow timed out, with malformed header/content-type errors showing up later on the stream path. This adds mailbox-specific TLS transport credentials that allow a missing negotiated ALPN value for mailbox links. The mailbox server path and the integration-test mailbox clients now use these credentials, so session establishment works again.
This commit is contained in:
parent
369f5e050b
commit
1629e3106a
4 changed files with 127 additions and 4 deletions
|
|
@ -2673,7 +2673,7 @@ func connectMailboxWithRemoteKey(ctx context.Context,
|
|||
transportConn, err := mailbox.NewGrpcClient(
|
||||
ctx, mailboxServerAddr, connData,
|
||||
grpc.WithTransportCredentials(
|
||||
credentials.NewTLS(&tls.Config{}),
|
||||
session.NewMailboxTLSCredentials(&tls.Config{}),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/lightninglabs/faraday/frdrpc"
|
||||
"github.com/lightninglabs/lightning-node-connect/mailbox"
|
||||
"github.com/lightninglabs/lightning-terminal/litrpc"
|
||||
"github.com/lightninglabs/lightning-terminal/session"
|
||||
"github.com/lightninglabs/loop/looprpc"
|
||||
"github.com/lightninglabs/pool/poolrpc"
|
||||
"github.com/lightninglabs/taproot-assets/taprpc"
|
||||
|
|
@ -1359,7 +1360,7 @@ func connectMailboxWithPairingPhrase(ctx context.Context,
|
|||
transportConn, err := mailbox.NewGrpcClient(
|
||||
ctx, mailboxServerAddr, connData,
|
||||
grpc.WithTransportCredentials(
|
||||
credentials.NewTLS(&tls.Config{}),
|
||||
session.NewMailboxTLSCredentials(&tls.Config{}),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/lightningnetwork/lnd/fn"
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/keepalive"
|
||||
)
|
||||
|
||||
|
|
@ -61,7 +60,9 @@ func (m *mailboxSession) start(session *Session,
|
|||
// Start the mailbox gRPC server.
|
||||
mailboxServer, err := mailbox.NewServer(
|
||||
session.ServerAddr, keys, onNewStatus,
|
||||
grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)),
|
||||
grpc.WithTransportCredentials(
|
||||
NewMailboxTLSCredentials(tlsConfig),
|
||||
),
|
||||
grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||
Time: 2 * time.Minute,
|
||||
}),
|
||||
|
|
|
|||
121
session/tls_credentials.go
Normal file
121
session/tls_credentials.go
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
const http2Proto = "h2"
|
||||
|
||||
// NewMailboxTLSCredentials creates transport credentials for mailbox
|
||||
// connections. Unlike grpc's default TLS credentials, this allows endpoints
|
||||
// that don't negotiate ALPN yet. This is needed as a workaround for grpc-go
|
||||
// v1.67.0 ALPN enforcement added by https://github.com/grpc/grpc-go/pull/7535
|
||||
//
|
||||
// TODO: remove this file when all target mailbox endpoints support ALPN.
|
||||
func NewMailboxTLSCredentials(
|
||||
config *tls.Config) credentials.TransportCredentials {
|
||||
|
||||
tlsConfig := &tls.Config{}
|
||||
if config != nil {
|
||||
tlsConfig = config.Clone()
|
||||
}
|
||||
|
||||
return &mailboxTLSCreds{config: tlsConfig}
|
||||
}
|
||||
|
||||
// mailboxTLSCreds is a mailbox-specific TransportCredentials implementation
|
||||
// that keeps TLS enabled but tolerates peers that do not negotiate ALPN.
|
||||
type mailboxTLSCreds struct {
|
||||
config *tls.Config
|
||||
}
|
||||
|
||||
// ClientHandshake performs the client side TLS handshake for mailbox links
|
||||
// while allowing an empty negotiated ALPN value from the remote endpoint.
|
||||
func (c *mailboxTLSCreds) ClientHandshake(ctx context.Context, authority string,
|
||||
rawConn net.Conn) (_ net.Conn, _ credentials.AuthInfo, err error) {
|
||||
|
||||
cfg := c.config.Clone()
|
||||
if cfg.ServerName == "" {
|
||||
serverName, _, err := net.SplitHostPort(authority)
|
||||
if err != nil {
|
||||
serverName = authority
|
||||
}
|
||||
cfg.ServerName = serverName
|
||||
}
|
||||
|
||||
cfg.NextProtos = appendH2(cfg.NextProtos)
|
||||
|
||||
conn := tls.Client(rawConn, cfg)
|
||||
if err := conn.HandshakeContext(ctx); err != nil {
|
||||
_ = conn.Close()
|
||||
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return conn, tlsAuthInfo(conn.ConnectionState()), nil
|
||||
}
|
||||
|
||||
// ServerHandshake performs the server side TLS handshake for mailbox links
|
||||
// while allowing an empty negotiated ALPN value from the peer.
|
||||
func (c *mailboxTLSCreds) ServerHandshake(rawConn net.Conn) (
|
||||
net.Conn, credentials.AuthInfo, error) {
|
||||
|
||||
cfg := c.config.Clone()
|
||||
cfg.NextProtos = appendH2(cfg.NextProtos)
|
||||
|
||||
conn := tls.Server(rawConn, cfg)
|
||||
if err := conn.Handshake(); err != nil {
|
||||
_ = conn.Close()
|
||||
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return conn, tlsAuthInfo(conn.ConnectionState()), nil
|
||||
}
|
||||
|
||||
// Info returns protocol metadata for these transport credentials.
|
||||
func (c *mailboxTLSCreds) Info() credentials.ProtocolInfo {
|
||||
return credentials.ProtocolInfo{
|
||||
SecurityProtocol: "tls",
|
||||
SecurityVersion: "1.2",
|
||||
ServerName: c.config.ServerName,
|
||||
}
|
||||
}
|
||||
|
||||
// Clone returns a copy of these transport credentials.
|
||||
func (c *mailboxTLSCreds) Clone() credentials.TransportCredentials {
|
||||
return &mailboxTLSCreds{config: c.config.Clone()}
|
||||
}
|
||||
|
||||
// OverrideServerName overrides the TLS server name used by the client side
|
||||
// handshake.
|
||||
func (c *mailboxTLSCreds) OverrideServerName(serverNameOverride string) error {
|
||||
c.config.ServerName = serverNameOverride
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// tlsAuthInfo builds credentials.AuthInfo from TLS connection state.
|
||||
func tlsAuthInfo(state tls.ConnectionState) credentials.TLSInfo {
|
||||
return credentials.TLSInfo{
|
||||
State: state,
|
||||
CommonAuthInfo: credentials.CommonAuthInfo{
|
||||
SecurityLevel: credentials.PrivacyAndIntegrity,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// appendH2 ensures "h2" is present in the ALPN protocol list.
|
||||
func appendH2(nextProtos []string) []string {
|
||||
for _, proto := range nextProtos {
|
||||
if proto == http2Proto {
|
||||
return nextProtos
|
||||
}
|
||||
}
|
||||
|
||||
return append(nextProtos, http2Proto)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue