mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-14 05:11:19 -04:00
Merge branch 'covertdtls' into 'main'
Add covert-dtls to proxy and client See merge request tpo/anti-censorship/pluggable-transports/snowflake!448
This commit is contained in:
commit
aa5c034ba2
9 changed files with 92 additions and 16 deletions
|
@ -177,23 +177,26 @@ type WebRTCDialer struct {
|
||||||
webrtcConfig *webrtc.Configuration
|
webrtcConfig *webrtc.Configuration
|
||||||
max int
|
max int
|
||||||
|
|
||||||
eventLogger event.SnowflakeEventReceiver
|
eventLogger event.SnowflakeEventReceiver
|
||||||
proxy *url.URL
|
proxy *url.URL
|
||||||
|
dtlsRandomize bool
|
||||||
|
dtlsMimic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead
|
// Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead
|
||||||
func NewWebRTCDialer(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int) *WebRTCDialer {
|
func NewWebRTCDialer(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int) *WebRTCDialer {
|
||||||
return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, nil, nil)
|
return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, nil, nil, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead
|
// Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead
|
||||||
func NewWebRTCDialerWithEvents(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int, eventLogger event.SnowflakeEventReceiver) *WebRTCDialer {
|
func NewWebRTCDialerWithEvents(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int, eventLogger event.SnowflakeEventReceiver) *WebRTCDialer {
|
||||||
return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventLogger, nil)
|
return NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventLogger, nil, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebRTCDialerWithEventsAndProxy constructs a new WebRTCDialer.
|
// NewWebRTCDialerWithEventsAndProxy constructs a new WebRTCDialer.
|
||||||
func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int,
|
func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int,
|
||||||
eventLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
eventLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
||||||
|
dtlsRandomize bool, dtlsMimic bool,
|
||||||
) *WebRTCDialer {
|
) *WebRTCDialer {
|
||||||
config := webrtc.Configuration{
|
config := webrtc.Configuration{
|
||||||
ICEServers: iceServers,
|
ICEServers: iceServers,
|
||||||
|
@ -204,8 +207,10 @@ func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrt
|
||||||
webrtcConfig: &config,
|
webrtcConfig: &config,
|
||||||
max: max,
|
max: max,
|
||||||
|
|
||||||
eventLogger: eventLogger,
|
eventLogger: eventLogger,
|
||||||
proxy: proxy,
|
proxy: proxy,
|
||||||
|
dtlsRandomize: dtlsRandomize,
|
||||||
|
dtlsMimic: dtlsMimic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +218,7 @@ func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrt
|
||||||
func (w WebRTCDialer) Catch() (*WebRTCPeer, error) {
|
func (w WebRTCDialer) Catch() (*WebRTCPeer, error) {
|
||||||
// TODO: [#25591] Fetch ICE server information from Broker.
|
// TODO: [#25591] Fetch ICE server information from Broker.
|
||||||
// TODO: [#25596] Consider TURN servers here too.
|
// TODO: [#25596] Consider TURN servers here too.
|
||||||
return NewWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy)
|
return NewWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy, w.dtlsRandomize, w.dtlsMimic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMax returns the maximum number of snowflakes to collect.
|
// GetMax returns the maximum number of snowflakes to collect.
|
||||||
|
|
|
@ -118,6 +118,8 @@ type ClientConfig struct {
|
||||||
BridgeFingerprint string
|
BridgeFingerprint string
|
||||||
// CommunicationProxy is the proxy address for network communication
|
// CommunicationProxy is the proxy address for network communication
|
||||||
CommunicationProxy *url.URL
|
CommunicationProxy *url.URL
|
||||||
|
DTLSRandomize bool
|
||||||
|
DTLSMimic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSnowflakeClient creates a new Snowflake transport client that can spawn multiple
|
// NewSnowflakeClient creates a new Snowflake transport client that can spawn multiple
|
||||||
|
@ -161,7 +163,7 @@ func NewSnowflakeClient(config ClientConfig) (*Transport, error) {
|
||||||
max = config.Max
|
max = config.Max
|
||||||
}
|
}
|
||||||
eventsLogger := event.NewSnowflakeEventDispatcher()
|
eventsLogger := event.NewSnowflakeEventDispatcher()
|
||||||
transport := &Transport{dialer: NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy), eventDispatcher: eventsLogger}
|
transport := &Transport{dialer: NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy, config.DTLSRandomize, config.DTLSMimic), eventDispatcher: eventsLogger}
|
||||||
|
|
||||||
return transport, nil
|
return transport, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,13 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pion/dtls/v3"
|
||||||
"github.com/pion/ice/v4"
|
"github.com/pion/ice/v4"
|
||||||
"github.com/pion/transport/v3"
|
"github.com/pion/transport/v3"
|
||||||
"github.com/pion/transport/v3/stdnet"
|
"github.com/pion/transport/v3/stdnet"
|
||||||
"github.com/pion/webrtc/v4"
|
"github.com/pion/webrtc/v4"
|
||||||
|
"github.com/theodorsm/covert-dtls/pkg/mimicry"
|
||||||
|
"github.com/theodorsm/covert-dtls/pkg/randomize"
|
||||||
|
|
||||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
|
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
|
||||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/proxy"
|
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/proxy"
|
||||||
|
@ -49,7 +52,7 @@ type WebRTCPeer struct {
|
||||||
func NewWebRTCPeer(
|
func NewWebRTCPeer(
|
||||||
config *webrtc.Configuration, broker *BrokerChannel,
|
config *webrtc.Configuration, broker *BrokerChannel,
|
||||||
) (*WebRTCPeer, error) {
|
) (*WebRTCPeer, error) {
|
||||||
return NewWebRTCPeerWithEventsAndProxy(config, broker, nil, nil)
|
return NewWebRTCPeerWithEventsAndProxy(config, broker, nil, nil, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use NewWebRTCPeerWithEventsAndProxy Instead.
|
// Deprecated: Use NewWebRTCPeerWithEventsAndProxy Instead.
|
||||||
|
@ -57,7 +60,7 @@ func NewWebRTCPeerWithEvents(
|
||||||
config *webrtc.Configuration, broker *BrokerChannel,
|
config *webrtc.Configuration, broker *BrokerChannel,
|
||||||
eventsLogger event.SnowflakeEventReceiver,
|
eventsLogger event.SnowflakeEventReceiver,
|
||||||
) (*WebRTCPeer, error) {
|
) (*WebRTCPeer, error) {
|
||||||
return NewWebRTCPeerWithEventsAndProxy(config, broker, eventsLogger, nil)
|
return NewWebRTCPeerWithEventsAndProxy(config, broker, eventsLogger, nil, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWebRTCPeerWithEventsAndProxy constructs a WebRTC PeerConnection to a snowflake proxy.
|
// NewWebRTCPeerWithEventsAndProxy constructs a WebRTC PeerConnection to a snowflake proxy.
|
||||||
|
@ -68,6 +71,7 @@ func NewWebRTCPeerWithEvents(
|
||||||
func NewWebRTCPeerWithEventsAndProxy(
|
func NewWebRTCPeerWithEventsAndProxy(
|
||||||
config *webrtc.Configuration, broker *BrokerChannel,
|
config *webrtc.Configuration, broker *BrokerChannel,
|
||||||
eventsLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
eventsLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
||||||
|
dtlsRandomize bool, dtlsMimic bool,
|
||||||
) (*WebRTCPeer, error) {
|
) (*WebRTCPeer, error) {
|
||||||
if eventsLogger == nil {
|
if eventsLogger == nil {
|
||||||
eventsLogger = event.NewSnowflakeEventDispatcher()
|
eventsLogger = event.NewSnowflakeEventDispatcher()
|
||||||
|
@ -92,7 +96,7 @@ func NewWebRTCPeerWithEventsAndProxy(
|
||||||
connection.eventsLogger = eventsLogger
|
connection.eventsLogger = eventsLogger
|
||||||
connection.proxy = proxy
|
connection.proxy = proxy
|
||||||
|
|
||||||
err := connection.connect(config, broker)
|
err := connection.connect(config, broker, dtlsRandomize, dtlsMimic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
connection.Close()
|
connection.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -166,10 +170,9 @@ func (c *WebRTCPeer) checkForStaleness(timeout time.Duration) {
|
||||||
|
|
||||||
// connect does the bulk of the work: gather ICE candidates, send the SDP offer to broker,
|
// connect does the bulk of the work: gather ICE candidates, send the SDP offer to broker,
|
||||||
// receive an answer from broker, and wait for data channel to open
|
// receive an answer from broker, and wait for data channel to open
|
||||||
func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel) error {
|
func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel, dtlsRandomize bool, dtlsMimic bool) error {
|
||||||
log.Println(c.id, " connecting...")
|
log.Println(c.id, " connecting...")
|
||||||
|
err := c.preparePeerConnection(config, broker.keepLocalAddresses, dtlsRandomize, dtlsMimic)
|
||||||
err := c.preparePeerConnection(config, broker.keepLocalAddresses)
|
|
||||||
localDescription := c.pc.LocalDescription()
|
localDescription := c.pc.LocalDescription()
|
||||||
c.eventsLogger.OnNewSnowflakeEvent(event.EventOnOfferCreated{
|
c.eventsLogger.OnNewSnowflakeEvent(event.EventOnOfferCreated{
|
||||||
WebRTCLocalDescription: localDescription,
|
WebRTCLocalDescription: localDescription,
|
||||||
|
@ -213,6 +216,8 @@ func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel
|
||||||
func (c *WebRTCPeer) preparePeerConnection(
|
func (c *WebRTCPeer) preparePeerConnection(
|
||||||
config *webrtc.Configuration,
|
config *webrtc.Configuration,
|
||||||
keepLocalAddresses bool,
|
keepLocalAddresses bool,
|
||||||
|
dtlsRandomize bool,
|
||||||
|
dtlsMimic bool,
|
||||||
) error {
|
) error {
|
||||||
var err error
|
var err error
|
||||||
s := webrtc.SettingEngine{}
|
s := webrtc.SettingEngine{}
|
||||||
|
@ -245,6 +250,24 @@ func (c *WebRTCPeer) preparePeerConnection(
|
||||||
}
|
}
|
||||||
|
|
||||||
s.SetNet(vnet)
|
s.SetNet(vnet)
|
||||||
|
|
||||||
|
if dtlsRandomize {
|
||||||
|
rand := randomize.RandomizedMessageClientHello{RandomALPN: true}
|
||||||
|
s.SetDTLSClientHelloMessageHook(rand.Hook)
|
||||||
|
} else if dtlsMimic {
|
||||||
|
mimic := &mimicry.MimickedClientHello{}
|
||||||
|
profiles := []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,
|
||||||
|
dtls.SRTP_AES256_CM_SHA1_32,
|
||||||
|
dtls.SRTP_AES256_CM_SHA1_80,
|
||||||
|
}
|
||||||
|
s.SetSRTPProtectionProfiles(profiles...)
|
||||||
|
s.SetDTLSClientHelloMessageHook(mimic.Hook)
|
||||||
|
}
|
||||||
|
|
||||||
api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
|
api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
|
||||||
c.pc, err = api.NewPeerConnection(*config)
|
c.pc, err = api.NewPeerConnection(*config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -174,6 +174,8 @@ func main() {
|
||||||
max := flag.Int("max", DefaultSnowflakeCapacity,
|
max := flag.Int("max", DefaultSnowflakeCapacity,
|
||||||
"capacity for number of multiplexed WebRTC peers")
|
"capacity for number of multiplexed WebRTC peers")
|
||||||
versionFlag := flag.Bool("version", false, "display version info to stderr and quit")
|
versionFlag := flag.Bool("version", false, "display version info to stderr and quit")
|
||||||
|
dtlsRandomize := flag.Bool("dtls-randomize", false, "randomize DTLS client hello")
|
||||||
|
dtlsMimic := flag.Bool("dtls-mimic", false, "mimic DTLS client hello of Chrome and Firefox")
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
oldLogToStateDir := flag.Bool("logToStateDir", false, "use -log-to-state-dir instead")
|
oldLogToStateDir := flag.Bool("logToStateDir", false, "use -log-to-state-dir instead")
|
||||||
|
@ -186,6 +188,10 @@ func main() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *dtlsMimic && *dtlsRandomize {
|
||||||
|
log.Fatal("Cannot both Randomize and Mimic DTLS client hello")
|
||||||
|
}
|
||||||
|
|
||||||
log.SetFlags(log.LstdFlags | log.LUTC)
|
log.SetFlags(log.LstdFlags | log.LUTC)
|
||||||
|
|
||||||
// Don't write to stderr; versions of tor earlier than about 0.3.5.6 do
|
// Don't write to stderr; versions of tor earlier than about 0.3.5.6 do
|
||||||
|
@ -240,6 +246,8 @@ func main() {
|
||||||
ICEAddresses: iceAddresses,
|
ICEAddresses: iceAddresses,
|
||||||
KeepLocalAddresses: *keepLocalAddresses || *oldKeepLocalAddresses,
|
KeepLocalAddresses: *keepLocalAddresses || *oldKeepLocalAddresses,
|
||||||
Max: *max,
|
Max: *max,
|
||||||
|
DTLSRandomize: *dtlsRandomize,
|
||||||
|
DTLSMimic: *dtlsMimic,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin goptlib client process.
|
// Begin goptlib client process.
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -1,6 +1,6 @@
|
||||||
module gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2
|
module gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2
|
||||||
|
|
||||||
go 1.21
|
go 1.22
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/aws/aws-sdk-go-v2 v1.32.6
|
github.com/aws/aws-sdk-go-v2 v1.32.6
|
||||||
|
@ -10,6 +10,7 @@ require (
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/miekg/dns v1.1.62
|
github.com/miekg/dns v1.1.62
|
||||||
|
github.com/pion/dtls/v3 v3.0.4
|
||||||
github.com/pion/ice/v4 v4.0.3
|
github.com/pion/ice/v4 v4.0.3
|
||||||
github.com/pion/sdp/v3 v3.0.9
|
github.com/pion/sdp/v3 v3.0.9
|
||||||
github.com/pion/stun/v3 v3.0.0
|
github.com/pion/stun/v3 v3.0.0
|
||||||
|
@ -20,6 +21,7 @@ require (
|
||||||
github.com/refraction-networking/utls v1.6.7
|
github.com/refraction-networking/utls v1.6.7
|
||||||
github.com/smartystreets/goconvey v1.8.1
|
github.com/smartystreets/goconvey v1.8.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
|
github.com/theodorsm/covert-dtls v0.0.2-0.20241201194039-050c26fb1e5f
|
||||||
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301
|
github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.8
|
github.com/xtaci/kcp-go/v5 v5.6.8
|
||||||
github.com/xtaci/smux v1.5.31
|
github.com/xtaci/smux v1.5.31
|
||||||
|
@ -56,7 +58,6 @@ require (
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pion/datachannel v1.5.9 // indirect
|
github.com/pion/datachannel v1.5.9 // indirect
|
||||||
github.com/pion/dtls/v3 v3.0.4 // indirect
|
|
||||||
github.com/pion/interceptor v0.1.37 // indirect
|
github.com/pion/interceptor v0.1.37 // indirect
|
||||||
github.com/pion/logging v0.2.2 // indirect
|
github.com/pion/logging v0.2.2 // indirect
|
||||||
github.com/pion/mdns/v2 v2.0.7 // indirect
|
github.com/pion/mdns/v2 v2.0.7 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -163,6 +163,8 @@ github.com/templexxx/cpu v0.1.0 h1:wVM+WIJP2nYaxVxqgHPD4wGA2aJ9rvrQRV8CvFzNb40=
|
||||||
github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
github.com/templexxx/cpu v0.1.0/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||||
github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI=
|
github.com/templexxx/xorsimd v0.4.2 h1:ocZZ+Nvu65LGHmCLZ7OoCtg8Fx8jnHKK37SjvngUoVI=
|
||||||
github.com/templexxx/xorsimd v0.4.2/go.mod h1:HgwaPoDREdi6OnULpSfxhzaiiSUY4Fi3JPn1wpt28NI=
|
github.com/templexxx/xorsimd v0.4.2/go.mod h1:HgwaPoDREdi6OnULpSfxhzaiiSUY4Fi3JPn1wpt28NI=
|
||||||
|
github.com/theodorsm/covert-dtls v0.0.2-0.20241201194039-050c26fb1e5f h1:+x3jtBX9WWEXSkdcoyw1Ryztrc0SJbfLD8r7ELR7NwU=
|
||||||
|
github.com/theodorsm/covert-dtls v0.0.2-0.20241201194039-050c26fb1e5f/go.mod h1:U3A87xJnEsomZcftqJ0QpM1MRiLIxNveypK4VGFp1jk=
|
||||||
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
|
||||||
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
|
||||||
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf h1:7PflaKRtU4np/epFxRXlFhlzLXZzKFrH5/I4so5Ove0=
|
github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf h1:7PflaKRtU4np/epFxRXlFhlzLXZzKFrH5/I4so5Ove0=
|
||||||
|
|
|
@ -48,6 +48,10 @@ Usage of ./proxy:
|
||||||
maximum concurrent clients (default is to accept an unlimited number of clients)
|
maximum concurrent clients (default is to accept an unlimited number of clients)
|
||||||
-disable-stats-logger
|
-disable-stats-logger
|
||||||
disable the exposing mechanism for stats using logs
|
disable the exposing mechanism for stats using logs
|
||||||
|
-dtls-mimic
|
||||||
|
mimic DTLS client hello of Chrome and Firefox
|
||||||
|
-dtls-randomize
|
||||||
|
randomize DTLS client hello
|
||||||
-ephemeral-ports-range range
|
-ephemeral-ports-range range
|
||||||
Set the range of ports used for client connections (format:"<min>:<max>").
|
Set the range of ports used for client connections (format:"<min>:<max>").
|
||||||
If omitted, the ports will be chosen automatically.
|
If omitted, the ports will be chosen automatically.
|
||||||
|
|
|
@ -42,8 +42,11 @@ import (
|
||||||
"github.com/pion/ice/v4"
|
"github.com/pion/ice/v4"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/pion/dtls/v3"
|
||||||
"github.com/pion/transport/v3/stdnet"
|
"github.com/pion/transport/v3/stdnet"
|
||||||
"github.com/pion/webrtc/v4"
|
"github.com/pion/webrtc/v4"
|
||||||
|
"github.com/theodorsm/covert-dtls/pkg/mimicry"
|
||||||
|
"github.com/theodorsm/covert-dtls/pkg/randomize"
|
||||||
|
|
||||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
|
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
|
||||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/messages"
|
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/messages"
|
||||||
|
@ -166,6 +169,9 @@ type SnowflakeProxy struct {
|
||||||
|
|
||||||
periodicProxyStats *periodicProxyStats
|
periodicProxyStats *periodicProxyStats
|
||||||
bytesLogger bytesLogger
|
bytesLogger bytesLogger
|
||||||
|
|
||||||
|
DTLSRandomize bool
|
||||||
|
DTLSMimic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks whether an IP address is a remote address for the client
|
// Checks whether an IP address is a remote address for the client
|
||||||
|
@ -424,6 +430,23 @@ func (sf *SnowflakeProxy) makeWebRTCAPI() *webrtc.API {
|
||||||
|
|
||||||
settingsEngine.SetDTLSInsecureSkipHelloVerify(true)
|
settingsEngine.SetDTLSInsecureSkipHelloVerify(true)
|
||||||
|
|
||||||
|
if sf.DTLSRandomize {
|
||||||
|
rand := randomize.RandomizedMessageClientHello{RandomALPN: true}
|
||||||
|
settingsEngine.SetDTLSClientHelloMessageHook(rand.Hook)
|
||||||
|
} else if sf.DTLSMimic {
|
||||||
|
mimic := &mimicry.MimickedClientHello{}
|
||||||
|
profiles := []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,
|
||||||
|
dtls.SRTP_AES256_CM_SHA1_32,
|
||||||
|
dtls.SRTP_AES256_CM_SHA1_80,
|
||||||
|
}
|
||||||
|
settingsEngine.SetSRTPProtectionProfiles(profiles...)
|
||||||
|
settingsEngine.SetDTLSClientHelloMessageHook(mimic.Hook)
|
||||||
|
}
|
||||||
|
|
||||||
return webrtc.NewAPI(webrtc.WithSettingEngine(settingsEngine))
|
return webrtc.NewAPI(webrtc.WithSettingEngine(settingsEngine))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,8 @@ func main() {
|
||||||
verboseLogging := flag.Bool("verbose", false, "increase log verbosity")
|
verboseLogging := flag.Bool("verbose", false, "increase log verbosity")
|
||||||
ephemeralPortsRangeFlag := flag.String("ephemeral-ports-range", "", "Set the `range` of ports used for client connections (format:\"<min>:<max>\").\nIf omitted, the ports will be chosen automatically.")
|
ephemeralPortsRangeFlag := flag.String("ephemeral-ports-range", "", "Set the `range` of ports used for client connections (format:\"<min>:<max>\").\nIf omitted, the ports will be chosen automatically.")
|
||||||
versionFlag := flag.Bool("version", false, "display version info to stderr and quit")
|
versionFlag := flag.Bool("version", false, "display version info to stderr and quit")
|
||||||
|
dtlsRandomize := flag.Bool("dtls-randomize", false, "randomize DTLS client hello")
|
||||||
|
dtlsMimic := flag.Bool("dtls-mimic", false, "mimic DTLS client hello of Chrome and Firefox")
|
||||||
|
|
||||||
var ephemeralPortsRange []uint16 = []uint16{0, 0}
|
var ephemeralPortsRange []uint16 = []uint16{0, 0}
|
||||||
|
|
||||||
|
@ -64,6 +66,10 @@ func main() {
|
||||||
log.Fatal("Cannot keep local address candidates when outbound address is specified")
|
log.Fatal("Cannot keep local address candidates when outbound address is specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *dtlsMimic && *dtlsRandomize {
|
||||||
|
log.Fatal("Cannot both Randomize and Mimic DTLS client hello")
|
||||||
|
}
|
||||||
|
|
||||||
eventLogger := event.NewSnowflakeEventDispatcher()
|
eventLogger := event.NewSnowflakeEventDispatcher()
|
||||||
|
|
||||||
if *ephemeralPortsRangeFlag != "" {
|
if *ephemeralPortsRangeFlag != "" {
|
||||||
|
@ -112,6 +118,8 @@ func main() {
|
||||||
AllowNonTLSRelay: *allowNonTLSRelay,
|
AllowNonTLSRelay: *allowNonTLSRelay,
|
||||||
|
|
||||||
SummaryInterval: *summaryInterval,
|
SummaryInterval: *summaryInterval,
|
||||||
|
DTLSRandomize: *dtlsRandomize,
|
||||||
|
DTLSMimic: *dtlsMimic,
|
||||||
}
|
}
|
||||||
|
|
||||||
var logOutput = io.Discard
|
var logOutput = io.Discard
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue