Explorar o código

New SetDTLSSeed scheme

- More reliable and less overhead

- Also, fix: use InproxyDataChannelTrafficShapingProbability
Rod Hynes hai 1 ano
pai
achega
44f2f2d527

+ 24 - 53
psiphon/common/inproxy/dtls/dtls.go

@@ -20,39 +20,30 @@
 package dtls
 
 import (
-	"net"
-	"time"
+	"context"
 
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
-	lrucache "github.com/cognusion/go-cache-lru"
 )
 
-// dtlsSeedCacheTTL should be long enough for the seed to remain available in
-// the cache between when it's first set at the start of WebRTC operations,
-// and until all DTLS dials have completed.
+type dtlsSeedValue string
 
-const (
-	dtlsSeedCacheTTL     = 60 * time.Second
-	dtlsSeedCacheMaxSize = 10000
-)
+const valueKey = dtlsSeedValue("DTLS-seed")
 
 // SetDTLSSeed establishes a cached common/prng seed to be used when
 // randomizing DTLS Hellos.
 //
-// The seed is keyed by the specified conn's local address. This allows a fork
-// of pion/dtls to fetch the seed and apply randomization without having to
-// fork many pion layers to pass in seeds. Concurrent dials must use distinct
-// conns with distinct local addresses (including port number).
+// The seed is attached as a value to the input dial context, yielding the
+// output context. This allows a fork of pion/dtls to fetch the seed, from a
+// context, and apply randomization without having to fork many pion layers
+// to pass in seeds.
 //
 // Both sides of a WebRTC connection may randomize their Hellos. isOffer
 // allows the same seed to be used, but produce two distinct random streams.
 // The client generates or replays an obfuscation secret used to derive the
 // seed, and the obfuscation secret is relayed to the proxy by the Broker.
-//
-// The caller may specify TTL, which can be used to retain the cached key for
-// a dial timeout duration; when TTL is <= 0, a default TTL is used.
-func SetDTLSSeed(localAddr net.Addr, baseSeed *prng.Seed, isOffer bool, TTL time.Duration) error {
+func SetDTLSSeed(
+	ctx context.Context, baseSeed *prng.Seed, isOffer bool) (context.Context, error) {
 
 	salt := "inproxy-client-DTLS-seed"
 	if !isOffer {
@@ -61,48 +52,28 @@ func SetDTLSSeed(localAddr net.Addr, baseSeed *prng.Seed, isOffer bool, TTL time
 
 	seed, err := prng.NewSaltedSeed(baseSeed, salt)
 	if err != nil {
-		return errors.Trace(err)
-	}
-
-	if TTL <= 0 {
-		TTL = lrucache.DefaultExpiration
+		return nil, errors.Trace(err)
 	}
 
-	// In the case where a previously used local port number is reused in a
-	// new dial, this will replace the previous seed.
-
-	dtlsSeedCache.Set(localAddr.String(), seed, TTL)
+	seedCtx := context.WithValue(ctx, valueKey, seed)
 
-	return nil
+	return seedCtx, nil
 }
 
-// SetNoDTLSSeed indicates to skip DTLS randomization for the conn specified
-// by the local address.
-func SetNoDTLSSeed(localAddr net.Addr, TTL time.Duration) {
-
-	if TTL <= 0 {
-		TTL = lrucache.DefaultExpiration
-	}
-
-	dtlsSeedCache.Set(localAddr.String(), nil, TTL)
+// SetNoDTLSSeed indicates to skip DTLS randomization for the given dial
+// context.
+func SetNoDTLSSeed(ctx context.Context) context.Context {
+	var nilSeed *prng.Seed
+	return context.WithValue(ctx, valueKey, nilSeed)
 }
 
-// GetDTLSSeed fetches a seed established by SetDTLSSeed, or returns an error
-// if no seed is found for the specified conn, keyed by local/source address.
-func GetDTLSSeed(localAddr net.Addr) (*prng.Seed, error) {
-	seed, ok := dtlsSeedCache.Get(localAddr.String())
-	if !ok {
+// GetDTLSSeed fetches a seed established by SetDTLSSeed, or nil for no seed
+// as set by SetNoDTLSSeed, or returns an error if no seed is configured
+// specified dial context.
+func GetDTLSSeed(ctx context.Context) (*prng.Seed, error) {
+	value := ctx.Value(valueKey)
+	if value == nil {
 		return nil, errors.TraceNew("missing seed")
 	}
-	if seed == nil {
-		return nil, nil
-	}
-	return seed.(*prng.Seed), nil
-}
-
-var dtlsSeedCache *lrucache.Cache
-
-func init() {
-	dtlsSeedCache = lrucache.NewWithLRU(
-		dtlsSeedCacheTTL, 1*time.Minute, dtlsSeedCacheMaxSize)
+	return value.(*prng.Seed), nil
 }

+ 16 - 23
psiphon/common/inproxy/webrtc.go

@@ -322,12 +322,6 @@ func newWebRTCConn(
 	// Set this behavior to look like common web browser WebRTC stacks.
 	settingEngine.SetDTLSInsecureSkipHelloVerify(true)
 
-	// TODO: set settingEngine.SetDTLSConnectContextMaker?
-
-	webRTCAPI := webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine))
-
-	dataChannelLabel := "in-proxy-data-channel"
-
 	// Initialize data channel obfuscation
 
 	config.Logger.WithTraceFields(common.LogFields{
@@ -344,13 +338,14 @@ func newWebRTCConn(
 	// (so each peer's randomization will be distinct).
 	//
 	// To avoid forking many pion repos in order to pass the seed through to
-	// the DTLS implementation, SetDTLSSeed populates a cache that's keyed by
-	// the UDP conn.
+	// the DTLS implementation, SetDTLSSeed attaches the seed to the DTLS
+	// dial context.
 	//
 	// Either SetDTLSSeed or SetNoDTLSSeed should be set for each conn, as the
-	// pion/dtl fork treats no-seed as an error, as a check against the local
-	// address lookup mechanism.
+	// pion/dtl fork treats no-seed as an error, as a check against the
+	// context value mechanism.
 
+	var dtlsCtx context.Context
 	if config.DoDTLSRandomization {
 
 		dtlsObfuscationSecret, err := deriveObfuscationSecret(
@@ -361,24 +356,19 @@ func newWebRTCConn(
 
 		baseSeed := prng.Seed(dtlsObfuscationSecret)
 
-		// We don't specify a listen address, so the UDP conn listens on all
-		// interfaces. Internally, pion/ice expands the UDPConn's LocalAddr
-		// to a concrete IP address per interface. We must set DTLS seeds for
-		// each address.
-		for _, localAddr := range udpMux.GetListenAddresses() {
-			err := inproxy_dtls.SetDTLSSeed(
-				localAddr, &baseSeed, isOffer, TTL)
-			if err != nil {
-				return nil, nil, nil, errors.Trace(err)
-			}
+		dtlsCtx, err = inproxy_dtls.SetDTLSSeed(ctx, &baseSeed, isOffer)
+		if err != nil {
+			return nil, nil, nil, errors.Trace(err)
 		}
 
 	} else {
 
-		for _, localAddr := range udpMux.GetListenAddresses() {
-			inproxy_dtls.SetNoDTLSSeed(localAddr, TTL)
-		}
+		dtlsCtx = inproxy_dtls.SetNoDTLSSeed(ctx)
 	}
+	settingEngine.SetDTLSConnectContextMaker(func() (context.Context, func()) {
+		return context.WithCancel(dtlsCtx)
+	})
+	webRTCAPI := webrtc.NewAPI(webrtc.WithSettingEngine(settingEngine))
 
 	// Configure traffic shaping, which adds random padding and decoy messages
 	// to data channel message flows.
@@ -541,6 +531,9 @@ func newWebRTCConn(
 			dataChannelInit.MaxRetransmits = &maxRetransmits
 		}
 
+		// TODO: randomize length?
+		dataChannelLabel := "in-proxy-data-channel"
+
 		dataChannel, err := peerConnection.CreateDataChannel(
 			dataChannelLabel, dataChannelInit)
 		if err != nil {

+ 4 - 0
psiphon/common/protocol/protocol.go

@@ -706,6 +706,10 @@ func ConjureTransportUsesSTUN(transport string) bool {
 	return transport == CONJURE_TRANSPORT_DTLS_OSSH
 }
 
+func ConjureTransportUsesDTLS(transport string) bool {
+	return transport == CONJURE_TRANSPORT_DTLS_OSSH
+}
+
 type ConjureTransports []string
 
 func (transports ConjureTransports) Validate() error {

+ 5 - 2
psiphon/inproxy.go

@@ -1820,8 +1820,11 @@ func MakeInproxyWebRTCDialParameters(
 		return nil, errors.Trace(err)
 	}
 
-	trafficShapingParameters := p.InproxyDataChannelTrafficShapingParameters(
-		parameters.InproxyDataChannelTrafficShapingParameters)
+	var trafficShapingParameters parameters.InproxyDataChannelTrafficShapingParametersValue
+	if p.WeightedCoinFlip(parameters.InproxyDataChannelTrafficShapingProbability) {
+		trafficShapingParameters = p.InproxyDataChannelTrafficShapingParameters(
+			parameters.InproxyDataChannelTrafficShapingParameters)
+	}
 
 	doDTLSRandomization := p.WeightedCoinFlip(parameters.InproxyDTLSRandomizationProbability)
 

+ 0 - 10
psiphon/net.go

@@ -38,7 +38,6 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/fragmentor"
-	inproxy_dtls "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy/dtls"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
@@ -177,7 +176,6 @@ type NetworkIDGetter interface {
 }
 
 // RefractionNetworkingDialer implements psiphon/common/refraction.Dialer.
-
 type RefractionNetworkingDialer struct {
 	config *DialConfig
 }
@@ -217,14 +215,6 @@ func (d *RefractionNetworkingDialer) DialContext(
 		conn := &common.WriteTimeoutUDPConn{
 			UDPConn: udpConn,
 		}
-
-		// Conjure doesn't use the DTLS seed scheme, which supports in-proxy
-		// DTLS randomization. But every DTLS dial expects to find a seed
-		// state, so set the no-seed state.
-		deadline, _ := ctx.Deadline()
-		dtlsSeedTTL := time.Until(deadline)
-		inproxy_dtls.SetNoDTLSSeed(conn.LocalAddr(), dtlsSeedTTL)
-
 		return conn, nil
 
 	default:

+ 10 - 1
psiphon/tunnel.go

@@ -41,6 +41,7 @@ import (
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/fragmentor"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy"
+	inproxy_dtls "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/inproxy/dtls"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/obfuscator"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
 	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
@@ -1401,8 +1402,16 @@ func dialConjure(
 		refraction.DeleteCachedConjureRegistration(conjureConfig)
 	}
 
+	dialCtx := ctx
+	if protocol.ConjureTransportUsesDTLS(dialParams.ConjureTransport) {
+		// Conjure doesn't use the DTLS seed scheme, which supports in-proxy
+		// DTLS randomization. But every DTLS dial expects to find a seed
+		// state, so set the no-seed state.
+		dialCtx = inproxy_dtls.SetNoDTLSSeed(ctx)
+	}
+
 	dialConn, err := refraction.DialConjure(
-		ctx,
+		dialCtx,
 		config.EmitRefractionNetworkingLogs,
 		config.GetPsiphonDataDirectory(),
 		NewRefractionNetworkingDialer(dialParams.GetDialConfig()).DialContext,

+ 3 - 1
replace/dtls/conn.go

@@ -839,7 +839,9 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh
 		}
 	}
 
-	ctxHs, cancel := context.WithCancel(context.Background())
+	// [Psiphon]
+	// Pass dial context into handshake goroutine for GetDTLSSeed.
+	ctxHs, cancel := context.WithCancel(ctx)
 	c.cancelHandshaker = cancel
 
 	firstErr := make(chan error, 1)

+ 1 - 1
replace/dtls/flight0handler.go

@@ -116,7 +116,7 @@ func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, nex
 	return next, nil, nil
 }
 
-func flight0Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight0Generate(_ context.Context, _ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	// Initialize
 	if !cfg.insecureSkipHelloVerify {
 		state.cookie = make([]byte, cookieLength)

+ 2 - 2
replace/dtls/flight1handler.go

@@ -55,7 +55,7 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh
 // symbol, which may be used to verify that the fork is used when compiling.
 const IsPsiphon = true
 
-func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight1Generate(ctx context.Context, c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	var zeroEpoch uint16
 	state.localEpoch.Store(zeroEpoch)
 	state.remoteEpoch.Store(zeroEpoch)
@@ -137,7 +137,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
 
 	// [Psiphon]
 	// Randomize ClientHello
-	seed, err := inproxy_dtls.GetDTLSSeed(c.LocalAddr())
+	seed, err := inproxy_dtls.GetDTLSSeed(ctx)
 	if err != nil {
 		return nil, nil, err
 	}

+ 1 - 1
replace/dtls/flight2handler.go

@@ -45,7 +45,7 @@ func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handsh
 	return flight4, nil, nil
 }
 
-func flight2Generate(_ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight2Generate(_ context.Context, _ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) {
 
 	// [Psiphon]
 	// With SetDTLSInsecureSkipHelloVerify set, this should never be called,

+ 1 - 1
replace/dtls/flight3handler.go

@@ -228,7 +228,7 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h
 	return nil, nil //nolint:nilnil
 }
 
-func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight3Generate(_ context.Context, _ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 
 	// [Psiphon]
 	// With SetDTLSInsecureSkipHelloVerify set, this should never be called,

+ 1 - 1
replace/dtls/flight4bhandler.go

@@ -47,7 +47,7 @@ func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handsha
 	return flight4b, nil, nil
 }
 
-func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight4bGenerate(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	var pkts []*packet
 
 	extensions := []extension.Extension{&extension.RenegotiationInfo{

+ 2 - 2
replace/dtls/flight4handler.go

@@ -221,7 +221,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
 	return flight6, nil, nil
 }
 
-func flight4Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight4Generate(ctx context.Context, c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	extensions := []extension.Extension{&extension.RenegotiationInfo{
 		RenegotiatedConnection: 0,
 	}}
@@ -265,7 +265,7 @@ func flight4Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
 
 	// [Psiphon]
 	// Randomize ServerHello
-	seed, err := inproxy_dtls.GetDTLSSeed(c.LocalAddr())
+	seed, err := inproxy_dtls.GetDTLSSeed(ctx)
 	if err != nil {
 		return nil, nil, err
 	}

+ 1 - 1
replace/dtls/flight5bhandler.go

@@ -30,7 +30,7 @@ func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handsha
 	return flight5b, nil, nil
 }
 
-func flight5bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
+func flight5bGenerate(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
 	var pkts []*packet
 
 	pkts = append(pkts,

+ 1 - 1
replace/dtls/flight5handler.go

@@ -65,7 +65,7 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak
 	return flight5, nil, nil
 }
 
-func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
+func flight5Generate(_ context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
 	var privateKey crypto.PrivateKey
 	var pkts []*packet
 	if state.remoteRequestedCertificate {

+ 1 - 1
replace/dtls/flight6handler.go

@@ -30,7 +30,7 @@ func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshak
 	return flight6, nil, nil
 }
 
-func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight6Generate(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	var pkts []*packet
 
 	pkts = append(pkts,

+ 4 - 1
replace/dtls/flighthandler.go

@@ -13,7 +13,10 @@ import (
 type flightParser func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) (flightVal, *alert.Alert, error)
 
 // Generate flights
-type flightGenerator func(flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error)
+//
+// [Psiphon]
+// Pass in dial context for GetDTLSSeed.
+type flightGenerator func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error)
 
 func (f flightVal) getFlightParser() (flightParser, error) {
 	switch f {

+ 3 - 1
replace/dtls/handshaker.go

@@ -221,7 +221,9 @@ func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeStat
 		err = errFlight
 		a = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}
 	} else {
-		pkts, a, err = gen(c, s.state, s.cache, s.cfg)
+		// [Psiphon]
+		// Pass in dial context for GetDTLSSeed.
+		pkts, a, err = gen(ctx, c, s.state, s.cache, s.cfg)
 		s.retransmit = retransmit
 	}
 	if a != nil {

+ 3 - 1
vendor/github.com/pion/dtls/v2/conn.go

@@ -839,7 +839,9 @@ func (c *Conn) handshake(ctx context.Context, cfg *handshakeConfig, initialFligh
 		}
 	}
 
-	ctxHs, cancel := context.WithCancel(context.Background())
+	// [Psiphon]
+	// Pass dial context into handshake goroutine for GetDTLSSeed.
+	ctxHs, cancel := context.WithCancel(ctx)
 	c.cancelHandshaker = cancel
 
 	firstErr := make(chan error, 1)

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight0handler.go

@@ -116,7 +116,7 @@ func handleHelloResume(sessionID []byte, state *State, cfg *handshakeConfig, nex
 	return next, nil, nil
 }
 
-func flight0Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight0Generate(_ context.Context, _ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	// Initialize
 	if !cfg.insecureSkipHelloVerify {
 		state.cookie = make([]byte, cookieLength)

+ 2 - 2
vendor/github.com/pion/dtls/v2/flight1handler.go

@@ -55,7 +55,7 @@ func flight1Parse(ctx context.Context, c flightConn, state *State, cache *handsh
 // symbol, which may be used to verify that the fork is used when compiling.
 const IsPsiphon = true
 
-func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight1Generate(ctx context.Context, c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	var zeroEpoch uint16
 	state.localEpoch.Store(zeroEpoch)
 	state.remoteEpoch.Store(zeroEpoch)
@@ -137,7 +137,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
 
 	// [Psiphon]
 	// Randomize ClientHello
-	seed, err := inproxy_dtls.GetDTLSSeed(c.LocalAddr())
+	seed, err := inproxy_dtls.GetDTLSSeed(ctx)
 	if err != nil {
 		return nil, nil, err
 	}

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight2handler.go

@@ -45,7 +45,7 @@ func flight2Parse(ctx context.Context, c flightConn, state *State, cache *handsh
 	return flight4, nil, nil
 }
 
-func flight2Generate(_ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight2Generate(_ context.Context, _ flightConn, state *State, _ *handshakeCache, _ *handshakeConfig) ([]*packet, *alert.Alert, error) {
 
 	// [Psiphon]
 	// With SetDTLSInsecureSkipHelloVerify set, this should never be called,

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight3handler.go

@@ -228,7 +228,7 @@ func handleServerKeyExchange(_ flightConn, state *State, cfg *handshakeConfig, h
 	return nil, nil //nolint:nilnil
 }
 
-func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight3Generate(_ context.Context, _ flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 
 	// [Psiphon]
 	// With SetDTLSInsecureSkipHelloVerify set, this should never be called,

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight4bhandler.go

@@ -47,7 +47,7 @@ func flight4bParse(_ context.Context, _ flightConn, state *State, cache *handsha
 	return flight4b, nil, nil
 }
 
-func flight4bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight4bGenerate(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	var pkts []*packet
 
 	extensions := []extension.Extension{&extension.RenegotiationInfo{

+ 2 - 2
vendor/github.com/pion/dtls/v2/flight4handler.go

@@ -221,7 +221,7 @@ func flight4Parse(ctx context.Context, c flightConn, state *State, cache *handsh
 	return flight6, nil, nil
 }
 
-func flight4Generate(c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight4Generate(ctx context.Context, c flightConn, state *State, _ *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	extensions := []extension.Extension{&extension.RenegotiationInfo{
 		RenegotiatedConnection: 0,
 	}}
@@ -265,7 +265,7 @@ func flight4Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha
 
 	// [Psiphon]
 	// Randomize ServerHello
-	seed, err := inproxy_dtls.GetDTLSSeed(c.LocalAddr())
+	seed, err := inproxy_dtls.GetDTLSSeed(ctx)
 	if err != nil {
 		return nil, nil, err
 	}

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight5bhandler.go

@@ -30,7 +30,7 @@ func flight5bParse(_ context.Context, _ flightConn, state *State, cache *handsha
 	return flight5b, nil, nil
 }
 
-func flight5bGenerate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
+func flight5bGenerate(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
 	var pkts []*packet
 
 	pkts = append(pkts,

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight5handler.go

@@ -65,7 +65,7 @@ func flight5Parse(_ context.Context, c flightConn, state *State, cache *handshak
 	return flight5, nil, nil
 }
 
-func flight5Generate(c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
+func flight5Generate(_ context.Context, c flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) { //nolint:gocognit
 	var privateKey crypto.PrivateKey
 	var pkts []*packet
 	if state.remoteRequestedCertificate {

+ 1 - 1
vendor/github.com/pion/dtls/v2/flight6handler.go

@@ -30,7 +30,7 @@ func flight6Parse(_ context.Context, _ flightConn, state *State, cache *handshak
 	return flight6, nil, nil
 }
 
-func flight6Generate(_ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
+func flight6Generate(_ context.Context, _ flightConn, state *State, cache *handshakeCache, cfg *handshakeConfig) ([]*packet, *alert.Alert, error) {
 	var pkts []*packet
 
 	pkts = append(pkts,

+ 4 - 1
vendor/github.com/pion/dtls/v2/flighthandler.go

@@ -13,7 +13,10 @@ import (
 type flightParser func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) (flightVal, *alert.Alert, error)
 
 // Generate flights
-type flightGenerator func(flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error)
+//
+// [Psiphon]
+// Pass in dial context for GetDTLSSeed.
+type flightGenerator func(context.Context, flightConn, *State, *handshakeCache, *handshakeConfig) ([]*packet, *alert.Alert, error)
 
 func (f flightVal) getFlightParser() (flightParser, error) {
 	switch f {

+ 3 - 1
vendor/github.com/pion/dtls/v2/handshaker.go

@@ -221,7 +221,9 @@ func (s *handshakeFSM) prepare(ctx context.Context, c flightConn) (handshakeStat
 		err = errFlight
 		a = &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}
 	} else {
-		pkts, a, err = gen(c, s.state, s.cache, s.cfg)
+		// [Psiphon]
+		// Pass in dial context for GetDTLSSeed.
+		pkts, a, err = gen(ctx, c, s.state, s.cache, s.cfg)
 		s.retransmit = retransmit
 	}
 	if a != nil {