From ccaad479b47b836092e792b0d28aa23c9892814c Mon Sep 17 00:00:00 2001 From: theodorsm Date: Mon, 22 Apr 2024 23:37:41 +0200 Subject: [PATCH] Remove mimcry package add only hook --- config.go | 7 +- conn.go | 3 +- e2e/e2e_test.go | 44 +---------- flight1handler.go | 15 +--- flight3handler.go | 15 +--- handshaker.go | 4 +- pkg/mimicry/README.md | 28 ------- pkg/mimicry/fingerprints.go | 21 ----- pkg/mimicry/mimic_client_hello.go | 126 ------------------------------ 9 files changed, 10 insertions(+), 253 deletions(-) delete mode 100644 pkg/mimicry/README.md delete mode 100644 pkg/mimicry/fingerprints.go delete mode 100644 pkg/mimicry/mimic_client_hello.go diff --git a/config.go b/config.go index d9e656c7e..b77547ebb 100644 --- a/config.go +++ b/config.go @@ -14,7 +14,7 @@ import ( "time" "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/mimicry" + "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/logging" ) @@ -198,9 +198,8 @@ type Config struct { // https://datatracker.ietf.org/doc/html/rfc9146#section-4 PaddingLengthGenerator func(uint) uint - MimicryEnabled bool - - ClientHelloFingerprint mimicry.ClientHelloFingerprint + // Random, SessionID, Cookie + ClientHelloMessageHook func(handshake.Random, []byte, []byte) handshake.Message } func defaultConnectContextMaker() (context.Context, func()) { diff --git a/conn.go b/conn.go index ea2a547be..81660717e 100644 --- a/conn.go +++ b/conn.go @@ -202,8 +202,7 @@ func createConn(ctx context.Context, nextConn net.PacketConn, rAddr net.Addr, co localGetClientCertificate: config.GetClientCertificate, insecureSkipHelloVerify: config.InsecureSkipVerifyHello, connectionIDGenerator: config.ConnectionIDGenerator, - mimicryEnabled: config.MimicryEnabled, - clientHelloFingerprint: config.ClientHelloFingerprint, + clientHelloMessageHook: config.ClientHelloMessageHook, } // rfc5246#section-7.4.3 diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 33aed6124..296a1f19c 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -24,6 +24,7 @@ import ( "github.com/pion/dtls/v2" "github.com/pion/dtls/v2/pkg/crypto/selfsign" + "github.com/pion/dtls/v2/pkg/mimicry" "github.com/pion/transport/v3/test" ) @@ -569,45 +570,6 @@ func testPionE2ESimpleRSAClientCert(t *testing.T, server, client func(*comm), op comm.assert(t) } -func testPionE2ESimpleMimicry(t *testing.T, server, client func(*comm), opts ...dtlsConfOpts) { - lim := test.TimeOut(time.Second * 30) - defer lim.Stop() - - report := test.CheckRoutines(t) - defer report() - - t.Run("Mimicry ClientHello", func(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - cert, err := selfsign.GenerateSelfSignedWithDNS("localhost") - if err != nil { - t.Fatal(err) - } - - client_cfg := &dtls.Config{ - Certificates: []tls.Certificate{cert}, - MimicryEnabled: true, - InsecureSkipVerify: true, - } - - server_cfg := &dtls.Config{ - Certificates: []tls.Certificate{cert}, - SRTPProtectionProfiles: []dtls.SRTPProtectionProfile{dtls.SRTP_AES128_CM_HMAC_SHA1_80, dtls.SRTP_AES128_CM_HMAC_SHA1_32, dtls.SRTP_AEAD_AES_128_GCM, dtls.SRTP_AEAD_AES_256_GCM}, - InsecureSkipVerify: true, - } - - for _, o := range opts { - o(client_cfg) - o(server_cfg) - } - serverPort := randomPort(t) - comm := newComm(ctx, client_cfg, server_cfg, serverPort, server, client) - defer comm.cleanup(t) - comm.assert(t) - }) -} - func TestPionE2ESimple(t *testing.T) { testPionE2ESimple(t, serverPion, clientPion) } @@ -663,7 +625,3 @@ func TestPionE2ESimpleECDSAClientCertCID(t *testing.T) { func TestPionE2ESimpleRSAClientCertCID(t *testing.T) { testPionE2ESimpleRSAClientCert(t, serverPion, clientPion, withConnectionIDGenerator(dtls.RandomCIDGenerator(8))) } - -func TestPionE2ESimpleMimicry(t *testing.T) { - testPionE2ESimpleMimicry(t, serverPion, clientPion) -} diff --git a/flight1handler.go b/flight1handler.go index ffbf1e5aa..a569ba350 100644 --- a/flight1handler.go +++ b/flight1handler.go @@ -7,7 +7,6 @@ import ( "context" "github.com/pion/dtls/v2/pkg/crypto/elliptic" - "github.com/pion/dtls/v2/pkg/mimicry" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/alert" "github.com/pion/dtls/v2/pkg/protocol/extension" @@ -134,17 +133,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) } - if cfg.mimicryEnabled { - msg := &mimicry.MimickedClientHello{ - Random: state.localRandom, - SessionID: state.SessionID, - Cookie: state.cookie, - } - - msg.LoadFingerprint(cfg.clientHelloFingerprint) - - cfg.localSRTPProtectionProfiles = msg.SRTPProtectionProfiles - + if cfg.clientHelloMessageHook != nil { return []*packet{ { record: &recordlayer.RecordLayer{ @@ -152,7 +141,7 @@ func flight1Generate(c flightConn, state *State, _ *handshakeCache, cfg *handsha Version: protocol.Version1_2, }, Content: &handshake.Handshake{ - Message: msg, + Message: cfg.clientHelloMessageHook(state.localRandom, state.SessionID, state.cookie), }, }, }, diff --git a/flight3handler.go b/flight3handler.go index e4cad7d20..ffbc09ed2 100644 --- a/flight3handler.go +++ b/flight3handler.go @@ -10,7 +10,6 @@ import ( "github.com/pion/dtls/v2/internal/ciphersuite/types" "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/prf" - "github.com/pion/dtls/v2/pkg/mimicry" "github.com/pion/dtls/v2/pkg/protocol" "github.com/pion/dtls/v2/pkg/protocol/alert" "github.com/pion/dtls/v2/pkg/protocol/extension" @@ -288,17 +287,7 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha extensions = append(extensions, &extension.ConnectionID{CID: state.localConnectionID}) } - if cfg.mimicryEnabled { - msg := &mimicry.MimickedClientHello{ - Random: state.localRandom, - SessionID: state.SessionID, - Cookie: state.cookie, - } - - msg.LoadFingerprint(cfg.clientHelloFingerprint) - - cfg.localSRTPProtectionProfiles = msg.SRTPProtectionProfiles - + if cfg.clientHelloMessageHook != nil { return []*packet{ { record: &recordlayer.RecordLayer{ @@ -306,7 +295,7 @@ func flight3Generate(_ flightConn, state *State, _ *handshakeCache, cfg *handsha Version: protocol.Version1_2, }, Content: &handshake.Handshake{ - Message: msg, + Message: cfg.clientHelloMessageHook(state.localRandom, state.SessionID, state.cookie), }, }, }, diff --git a/handshaker.go b/handshaker.go index d943191ba..9daf1a84e 100644 --- a/handshaker.go +++ b/handshaker.go @@ -14,7 +14,6 @@ import ( "github.com/pion/dtls/v2/pkg/crypto/elliptic" "github.com/pion/dtls/v2/pkg/crypto/signaturehash" - "github.com/pion/dtls/v2/pkg/mimicry" "github.com/pion/dtls/v2/pkg/protocol/alert" "github.com/pion/dtls/v2/pkg/protocol/handshake" "github.com/pion/logging" @@ -127,8 +126,7 @@ type handshakeConfig struct { mu sync.Mutex - mimicryEnabled bool - clientHelloFingerprint mimicry.ClientHelloFingerprint + clientHelloMessageHook func(handshake.Random, []byte, []byte) handshake.Message // Random, SessionID, Cookie } type flightConn interface { diff --git a/pkg/mimicry/README.md b/pkg/mimicry/README.md deleted file mode 100644 index aea370dd8..000000000 --- a/pkg/mimicry/README.md +++ /dev/null @@ -1,28 +0,0 @@ -### Fingerprint mimicking - -This submodule offers mimicking of the client hello message which is a anti-fingerprint feature for applications that needs censorship-resistance. - -Some sample fingerprints of common browsers are given in `fingerprints.go` (*Note*: the fingerprint is from a webrtc application). Using updated fingerprints is highly recommended, which can be found by an external package such as [dtls-webrtc-fingerprint](https://github.com/theodorsm/dtls-webrtc-fingerprint). - -Example with BYOF (bring your own fingerprints): - -```go -import ( - "github.com/pion/dtls/v2/pkg/mimicry" - "github.com/theodorsm/dtls-webrtc-fingerprint/pkg/fingerprints" -) - - -// Get recent fingerprints -fingerprints := fingerprints.GetClientHelloFingerprints() - -// Choose the freshest fingerprint -fingerprint := fingerprints[len(fingerprints)-1] - -cfg := &dtls.Config{ - Certificates: []tls.Certificate{cert}, - InsecureSkipVerify: true, - MimicryEnabled: true, - ClientHelloFingerprint: mimicry.ClientHelloFingerprint(fingerprint), -} -``` diff --git a/pkg/mimicry/fingerprints.go b/pkg/mimicry/fingerprints.go deleted file mode 100644 index 72b54060f..000000000 --- a/pkg/mimicry/fingerprints.go +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -package mimicry - -//nolint:revive -type ClientHelloFingerprint string - -// These fingerprints are sample fingerprints, more can by using the `fingerprints` module at https://github.com/theodorsm/dtls-webrtc-fingerprint -// The first byte should correspond to the DTLS version in a handshake message -const ( - Google_Chrome_124_0_6367_60_unknown ClientHelloFingerprint = "fefda20ee7841620b36a9c1736ea6846255d7da83e9271816b0cc85b7f948951581700000016c02bc02fcca9cca8c009c013c00ac014009c002f00350100004400170000ff01000100000a00080006001d00170018000b0002010000230000000d00140012040308040401050308050501080606010201000e0009000600010008000700" //nolint:revive,stylecheck - Mozilla_Firefox_125_0_1 ClientHelloFingerprint = "fefdb22e77791af4658e6fa29c6d396dcdfe51f471e584744683e6c22bd251a2aba000000010c02bc02fcca9cca8c00ac009c013c0140100006a00170000ff01000100000a00080006001d00170018000b000201000010001200100677656272746308632d776562727463000d0020001e040305030603020308040805080604010501060102010402050206020202001c00024000000e000b0008000700080001000200" //nolint:revive,stylecheck -) - -func getClientHelloFingerprints() []ClientHelloFingerprint { - return []ClientHelloFingerprint{ - Google_Chrome_124_0_6367_60_unknown, //nolint:revive,stylecheck - Mozilla_Firefox_125_0_1, //nolint:revive,stylecheck - } -} diff --git a/pkg/mimicry/mimic_client_hello.go b/pkg/mimicry/mimic_client_hello.go deleted file mode 100644 index 04245295d..000000000 --- a/pkg/mimicry/mimic_client_hello.go +++ /dev/null @@ -1,126 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The Pion community -// SPDX-License-Identifier: MIT - -// Package mimicry provides replay capabilities of captured handshakes for anti-fingerprinting purposes. -package mimicry - -import ( - "encoding/hex" - "errors" - - "github.com/pion/dtls/v2/pkg/protocol/extension" - "github.com/pion/dtls/v2/pkg/protocol/handshake" -) - -var errBufferTooSmall = errors.New("buffer is too small") //nolint:goerr113 - -//nolint:revive -type MimickedClientHello struct { - clientHelloFingerprint ClientHelloFingerprint - Random handshake.Random - SessionID []byte - Cookie []byte - Extensions []extension.Extension - SRTPProtectionProfiles []extension.SRTPProtectionProfile -} - -//nolint:revive -func (m MimickedClientHello) Type() handshake.Type { - return handshake.TypeClientHello -} - -func (m *MimickedClientHello) LoadFingerprint(fingerprint ClientHelloFingerprint) error { - m.clientHelloFingerprint = fingerprint - clientHello := handshake.MessageClientHello{} - data, err := hex.DecodeString(string(m.clientHelloFingerprint)) - if err != nil { - return errors.New("mimicry: failed to decode mimicry hexstring") //nolint:goerr113 - } - clientHello.Unmarshal(data) - m.Extensions = clientHello.Extensions - for _, ext := range m.Extensions { - if ext.TypeValue() == extension.UseSRTPTypeValue { - srtp := extension.UseSRTP{} - buf, err := ext.Marshal() - if err != nil { - return err - } - err = srtp.Unmarshal(buf) - if err != nil { - return err - } - m.SRTPProtectionProfiles = srtp.ProtectionProfiles - } - } - return nil -} - -//nolint:revive -func (m *MimickedClientHello) Marshal() ([]byte, error) { - var out []byte - - fingerprint := m.clientHelloFingerprint - - if string(fingerprint) == "" { - fingerprints := getClientHelloFingerprints() - if len(fingerprints) < 1 { - return out, errors.New("no fingerprints available") //nolint:goerr113 - } - fingerprint = fingerprints[len(fingerprints)-1] - m.LoadFingerprint(fingerprint) - } - - data, err := hex.DecodeString(string(fingerprint)) - if err != nil { - err = errors.New("mimicry: failed to decode mimicry hexstring") //nolint:goerr113 - } - - if len(data) <= 2 { - return out, errors.New("mimicked fingerprint is too short") //nolint:goerr113 - } - - // Major and minor version - currOffset := 2 - out = append(out, data[:currOffset]...) - - rb := m.Random.MarshalFixed() - out = append(out, rb[:]...) - - // Skip past random - currOffset += 32 - - currOffset++ - if len(data) <= currOffset { - return out, errBufferTooSmall - } - n := int(data[currOffset-1]) - if len(data) <= currOffset+n { - return out, errBufferTooSmall - } - mimickedSessionID := append([]byte{}, data[currOffset:currOffset+n]...) - currOffset += len(mimickedSessionID) - - currOffset++ - if len(data) <= currOffset { - return out, errBufferTooSmall - } - n = int(data[currOffset-1]) - if len(data) <= currOffset+n { - return out, errBufferTooSmall - } - mimickedCookie := append([]byte{}, data[currOffset:currOffset+n]...) - currOffset += len(mimickedCookie) - - out = append(out, byte(len(m.SessionID))) - out = append(out, m.SessionID...) - - out = append(out, byte(len(m.Cookie))) - out = append(out, m.Cookie...) - - out = append(out, data[currOffset:]...) - - return out, err -} - -//nolint:revive -func (m *MimickedClientHello) Unmarshal(data []byte) error { return nil }