mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-14 14:11:23 -04:00
Add CovertDTLSConfig
This commit is contained in:
parent
5912e2892a
commit
bb11646e73
11 changed files with 89 additions and 56 deletions
|
@ -35,7 +35,7 @@ UseBridges 1
|
|||
|
||||
ClientTransportPlugin snowflake exec ./client -log snowflake.log
|
||||
|
||||
Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ fronts=foursquare.com,github.githubassets.com ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn
|
||||
Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ fronts=foursquare.com,github.githubassets.com ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn covertdtls-config=randomizemimic
|
||||
```
|
||||
|
||||
`fingerprint=` is the fingerprint of bridge that the client will ultimately be connecting to.
|
||||
|
@ -48,6 +48,8 @@ Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerpri
|
|||
|
||||
`utls-imitate=` configuration instructs the client to use fingerprinting resistance when connecting when rendez-vous'ing with the broker.
|
||||
|
||||
`covertdtls-config=` configuration for randomization or mimicking (Firefox/Chrome browser) of DTLS Client Hello messages. String can be "randomize", "mimic" or "randomizemimc"
|
||||
|
||||
To bootstrap Tor, run:
|
||||
```
|
||||
tor -f torrc
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
utls "github.com/refraction-networking/utls"
|
||||
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/certs"
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/covertdtls"
|
||||
"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/nat"
|
||||
|
@ -177,10 +178,9 @@ type WebRTCDialer struct {
|
|||
webrtcConfig *webrtc.Configuration
|
||||
max int
|
||||
|
||||
eventLogger event.SnowflakeEventReceiver
|
||||
proxy *url.URL
|
||||
dtlsRandomize bool
|
||||
dtlsMimic bool
|
||||
eventLogger event.SnowflakeEventReceiver
|
||||
proxy *url.URL
|
||||
covertDTLSConfig *covertdtls.CovertDTLSConfig
|
||||
}
|
||||
|
||||
// Deprecated: Use NewWebRTCDialerWithEventsAndProxy instead
|
||||
|
@ -214,7 +214,7 @@ func NewWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrt
|
|||
// NewWebRTCDialerWithEventsAndProxy constructs a new WebRTCDialer setting DTLS mimicking and randomization.
|
||||
func NewCovertWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers []webrtc.ICEServer, max int,
|
||||
eventLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
||||
dtlsRandomize bool, dtlsMimic bool,
|
||||
covertDTLSConfig *covertdtls.CovertDTLSConfig,
|
||||
) *WebRTCDialer {
|
||||
config := webrtc.Configuration{
|
||||
ICEServers: iceServers,
|
||||
|
@ -225,10 +225,9 @@ func NewCovertWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers [
|
|||
webrtcConfig: &config,
|
||||
max: max,
|
||||
|
||||
eventLogger: eventLogger,
|
||||
proxy: proxy,
|
||||
dtlsRandomize: dtlsRandomize,
|
||||
dtlsMimic: dtlsMimic,
|
||||
eventLogger: eventLogger,
|
||||
proxy: proxy,
|
||||
covertDTLSConfig: covertDTLSConfig,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,8 +235,8 @@ func NewCovertWebRTCDialerWithEventsAndProxy(broker *BrokerChannel, iceServers [
|
|||
func (w WebRTCDialer) Catch() (*WebRTCPeer, error) {
|
||||
// TODO: [#25591] Fetch ICE server information from Broker.
|
||||
// TODO: [#25596] Consider TURN servers here too.
|
||||
if w.dtlsRandomize || w.dtlsMimic {
|
||||
return NewCovertWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy, w.dtlsRandomize, w.dtlsMimic)
|
||||
if w.covertDTLSConfig != nil {
|
||||
return NewCovertWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy, w.covertDTLSConfig)
|
||||
}
|
||||
return NewWebRTCPeerWithEventsAndProxy(w.webrtcConfig, w.BrokerChannel, w.eventLogger, w.proxy)
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import (
|
|||
"github.com/xtaci/kcp-go/v5"
|
||||
"github.com/xtaci/smux"
|
||||
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/covertdtls"
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/event"
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/nat"
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/turbotunnel"
|
||||
|
@ -118,8 +119,7 @@ type ClientConfig struct {
|
|||
BridgeFingerprint string
|
||||
// CommunicationProxy is the proxy address for network communication
|
||||
CommunicationProxy *url.URL
|
||||
DTLSRandomize bool
|
||||
DTLSMimic bool
|
||||
CovertDTLSConfig string
|
||||
}
|
||||
|
||||
// NewSnowflakeClient creates a new Snowflake transport client that can spawn multiple
|
||||
|
@ -165,8 +165,10 @@ func NewSnowflakeClient(config ClientConfig) (*Transport, error) {
|
|||
|
||||
eventsLogger := event.NewSnowflakeEventDispatcher()
|
||||
var transport *Transport
|
||||
if config.DTLSRandomize || config.DTLSMimic {
|
||||
transport = &Transport{dialer: NewCovertWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy, config.DTLSRandomize, config.DTLSMimic), eventDispatcher: eventsLogger}
|
||||
// TODO: Add fingerprint config
|
||||
if config.CovertDTLSConfig != "" {
|
||||
covertDTLSConfig := covertdtls.ParseConfigString(config.CovertDTLSConfig)
|
||||
transport = &Transport{dialer: NewCovertWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy, &covertDTLSConfig), eventDispatcher: eventsLogger}
|
||||
} else {
|
||||
transport = &Transport{dialer: NewWebRTCDialerWithEventsAndProxy(broker, iceServers, max, eventsLogger, config.CommunicationProxy), eventDispatcher: eventsLogger}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/theodorsm/covert-dtls/pkg/randomize"
|
||||
"github.com/theodorsm/covert-dtls/pkg/utils"
|
||||
|
||||
"gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/v2/common/covertdtls"
|
||||
"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/util"
|
||||
|
@ -95,7 +96,7 @@ func NewWebRTCPeerWithEventsAndProxy(
|
|||
connection.eventsLogger = eventsLogger
|
||||
connection.proxy = proxy
|
||||
|
||||
err := connection.connect(config, broker, false, false)
|
||||
err := connection.connect(config, broker, nil)
|
||||
if err != nil {
|
||||
connection.Close()
|
||||
return nil, err
|
||||
|
@ -107,7 +108,7 @@ func NewWebRTCPeerWithEventsAndProxy(
|
|||
func NewCovertWebRTCPeerWithEventsAndProxy(
|
||||
config *webrtc.Configuration, broker *BrokerChannel,
|
||||
eventsLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
||||
dtlsRandomize bool, dtlsMimic bool,
|
||||
covertDTLSConfig *covertdtls.CovertDTLSConfig,
|
||||
) (*WebRTCPeer, error) {
|
||||
if eventsLogger == nil {
|
||||
eventsLogger = event.NewSnowflakeEventDispatcher()
|
||||
|
@ -132,7 +133,7 @@ func NewCovertWebRTCPeerWithEventsAndProxy(
|
|||
connection.eventsLogger = eventsLogger
|
||||
connection.proxy = proxy
|
||||
|
||||
err := connection.connect(config, broker, dtlsRandomize, dtlsMimic)
|
||||
err := connection.connect(config, broker, covertDTLSConfig)
|
||||
if err != nil {
|
||||
connection.Close()
|
||||
return nil, err
|
||||
|
@ -206,9 +207,9 @@ func (c *WebRTCPeer) checkForStaleness(timeout time.Duration) {
|
|||
|
||||
// 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
|
||||
func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel, dtlsRandomize bool, dtlsMimic bool) error {
|
||||
func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel, covertDTLSConfig *covertdtls.CovertDTLSConfig) error {
|
||||
log.Println(c.id, " connecting...")
|
||||
err := c.preparePeerConnection(config, broker.keepLocalAddresses, dtlsRandomize, dtlsMimic)
|
||||
err := c.preparePeerConnection(config, broker.keepLocalAddresses, covertDTLSConfig)
|
||||
localDescription := c.pc.LocalDescription()
|
||||
c.eventsLogger.OnNewSnowflakeEvent(event.EventOnOfferCreated{
|
||||
WebRTCLocalDescription: localDescription,
|
||||
|
@ -252,8 +253,7 @@ func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel
|
|||
func (c *WebRTCPeer) preparePeerConnection(
|
||||
config *webrtc.Configuration,
|
||||
keepLocalAddresses bool,
|
||||
dtlsRandomize bool,
|
||||
dtlsMimic bool,
|
||||
covertDTLSConfig *covertdtls.CovertDTLSConfig,
|
||||
) error {
|
||||
var err error
|
||||
s := webrtc.SettingEngine{}
|
||||
|
@ -287,14 +287,21 @@ func (c *WebRTCPeer) preparePeerConnection(
|
|||
|
||||
s.SetNet(vnet)
|
||||
|
||||
if dtlsRandomize {
|
||||
rand := randomize.RandomizedMessageClientHello{RandomALPN: true}
|
||||
s.SetDTLSClientHelloMessageHook(rand.Hook)
|
||||
} else if dtlsMimic {
|
||||
if covertDTLSConfig.Mimic {
|
||||
mimic := &mimicry.MimickedClientHello{}
|
||||
if covertDTLSConfig.Randomize {
|
||||
err = mimic.LoadRandomFingerprint()
|
||||
if err != nil {
|
||||
log.Printf("NewPeerConnection ERROR: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
profiles := utils.DefaultSRTPProtectionProfiles()
|
||||
s.SetSRTPProtectionProfiles(profiles...)
|
||||
s.SetDTLSClientHelloMessageHook(mimic.Hook)
|
||||
} else if covertDTLSConfig.Randomize {
|
||||
rand := randomize.RandomizedMessageClientHello{RandomALPN: true}
|
||||
s.SetDTLSClientHelloMessageHook(rand.Hook)
|
||||
}
|
||||
|
||||
api := webrtc.NewAPI(webrtc.WithSettingEngine(s))
|
||||
|
|
|
@ -123,6 +123,9 @@ func socksAcceptLoop(ln *pt.SocksListener, config sf.ClientConfig, shutdown chan
|
|||
if arg, ok := conn.Req.Args.Get("fingerprint"); ok {
|
||||
config.BridgeFingerprint = arg
|
||||
}
|
||||
if arg, ok := conn.Req.Args.Get("covertdtls-config"); ok {
|
||||
config.CovertDTLSConfig = arg
|
||||
}
|
||||
transport, err := sf.NewSnowflakeClient(config)
|
||||
if err != nil {
|
||||
conn.Reject()
|
||||
|
@ -174,8 +177,7 @@ func main() {
|
|||
max := flag.Int("max", DefaultSnowflakeCapacity,
|
||||
"capacity for number of multiplexed WebRTC peers")
|
||||
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")
|
||||
covertDTLSConfig := flag.String("covertdtls-config", "", "Configuration of dtls mimicking and randomization: mimic, randomize, randomizemimic")
|
||||
|
||||
// Deprecated
|
||||
oldLogToStateDir := flag.Bool("logToStateDir", false, "use -log-to-state-dir instead")
|
||||
|
@ -188,10 +190,6 @@ func main() {
|
|||
os.Exit(0)
|
||||
}
|
||||
|
||||
if *dtlsMimic && *dtlsRandomize {
|
||||
log.Fatal("Cannot both Randomize and Mimic DTLS client hello")
|
||||
}
|
||||
|
||||
log.SetFlags(log.LstdFlags | log.LUTC)
|
||||
|
||||
// Don't write to stderr; versions of tor earlier than about 0.3.5.6 do
|
||||
|
@ -246,8 +244,7 @@ func main() {
|
|||
ICEAddresses: iceAddresses,
|
||||
KeepLocalAddresses: *keepLocalAddresses || *oldKeepLocalAddresses,
|
||||
Max: *max,
|
||||
DTLSRandomize: *dtlsRandomize,
|
||||
DTLSMimic: *dtlsMimic,
|
||||
CovertDTLSConfig: *covertDTLSConfig,
|
||||
}
|
||||
|
||||
// Begin goptlib client process.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue