mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
feat(client): try restricted proxy if NAT unknown
Just once, to offload unrestricted proxies. This is useful when our STUN servers are blocked or don't support the NAT discovery feature, or if they're just slow. Closes https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40178. Partially addresses https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/issues/40376 Signed-off-by: Cecylia Bocovich <cohosh@torproject.org>
This commit is contained in:
parent
f6767061e4
commit
94b6647d33
4 changed files with 163 additions and 27 deletions
|
@ -45,28 +45,43 @@ type WebRTCPeer struct {
|
|||
proxy *url.URL
|
||||
}
|
||||
|
||||
// Deprecated: Use NewWebRTCPeerWithEventsAndProxy Instead.
|
||||
// Deprecated: Use NewWebRTCPeerWithNatPolicyAndEventsAndProxy Instead.
|
||||
func NewWebRTCPeer(
|
||||
config *webrtc.Configuration, broker *BrokerChannel,
|
||||
) (*WebRTCPeer, error) {
|
||||
return NewWebRTCPeerWithEventsAndProxy(config, broker, nil, nil)
|
||||
return NewWebRTCPeerWithNatPolicyAndEventsAndProxy(
|
||||
config, broker, nil, nil, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// Deprecated: Use NewWebRTCPeerWithEventsAndProxy Instead.
|
||||
// Deprecated: Use NewWebRTCPeerWithNatPolicyAndEventsAndProxy Instead.
|
||||
func NewWebRTCPeerWithEvents(
|
||||
config *webrtc.Configuration, broker *BrokerChannel,
|
||||
eventsLogger event.SnowflakeEventReceiver,
|
||||
) (*WebRTCPeer, error) {
|
||||
return NewWebRTCPeerWithEventsAndProxy(config, broker, eventsLogger, nil)
|
||||
return NewWebRTCPeerWithNatPolicyAndEventsAndProxy(
|
||||
config, broker, nil, eventsLogger, nil,
|
||||
)
|
||||
}
|
||||
|
||||
// NewWebRTCPeerWithEventsAndProxy constructs a WebRTC PeerConnection to a snowflake proxy.
|
||||
// Deprecated: Use NewWebRTCPeerWithNatPolicyAndEventsAndProxy Instead.
|
||||
func NewWebRTCPeerWithEventsAndProxy(
|
||||
config *webrtc.Configuration, broker *BrokerChannel,
|
||||
eventsLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
||||
) (*WebRTCPeer, error) {
|
||||
return NewWebRTCPeerWithNatPolicyAndEventsAndProxy(
|
||||
config, broker, nil, eventsLogger, proxy,
|
||||
)
|
||||
}
|
||||
|
||||
// NewWebRTCPeerWithNatPolicyAndEventsAndProxy constructs
|
||||
// a WebRTC PeerConnection to a snowflake proxy.
|
||||
//
|
||||
// The creation of the peer handles the signaling to the Snowflake broker, including
|
||||
// the exchange of SDP information, the creation of a PeerConnection, and the establishment
|
||||
// of a DataChannel to the Snowflake proxy.
|
||||
func NewWebRTCPeerWithEventsAndProxy(
|
||||
config *webrtc.Configuration, broker *BrokerChannel,
|
||||
func NewWebRTCPeerWithNatPolicyAndEventsAndProxy(
|
||||
config *webrtc.Configuration, broker *BrokerChannel, natPolicy *NATPolicy,
|
||||
eventsLogger event.SnowflakeEventReceiver, proxy *url.URL,
|
||||
) (*WebRTCPeer, error) {
|
||||
if eventsLogger == nil {
|
||||
|
@ -92,7 +107,7 @@ func NewWebRTCPeerWithEventsAndProxy(
|
|||
connection.eventsLogger = eventsLogger
|
||||
connection.proxy = proxy
|
||||
|
||||
err := connection.connect(config, broker)
|
||||
err := connection.connect(config, broker, natPolicy)
|
||||
if err != nil {
|
||||
connection.Close()
|
||||
return nil, err
|
||||
|
@ -165,8 +180,15 @@ 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) error {
|
||||
// receive an answer from broker, and wait for data channel to open.
|
||||
//
|
||||
// `natPolicy` can be nil, in which case we'll always send our actual
|
||||
// NAT type to the broker.
|
||||
func (c *WebRTCPeer) connect(
|
||||
config *webrtc.Configuration,
|
||||
broker *BrokerChannel,
|
||||
natPolicy *NATPolicy,
|
||||
) error {
|
||||
log.Println(c.id, " connecting...")
|
||||
|
||||
err := c.preparePeerConnection(config, broker.keepLocalAddresses)
|
||||
|
@ -179,7 +201,24 @@ func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel
|
|||
return err
|
||||
}
|
||||
|
||||
answer, err := broker.Negotiate(localDescription)
|
||||
actualNatType := broker.GetNATType()
|
||||
var natTypeToSend string
|
||||
if natPolicy != nil {
|
||||
natTypeToSend = natPolicy.NATTypeToSend(actualNatType)
|
||||
} else {
|
||||
natTypeToSend = actualNatType
|
||||
}
|
||||
if natTypeToSend != actualNatType {
|
||||
log.Printf(
|
||||
"Our NAT type is \"%v\", but let's tell the broker it's \"%v\".",
|
||||
actualNatType,
|
||||
natTypeToSend,
|
||||
)
|
||||
} else {
|
||||
log.Printf("natTypeToSend: \"%v\" (same as actualNatType)", natTypeToSend)
|
||||
}
|
||||
|
||||
answer, err := broker.Negotiate(localDescription, natTypeToSend)
|
||||
c.eventsLogger.OnNewSnowflakeEvent(event.EventOnBrokerRendezvous{
|
||||
WebRTCRemoteDescription: answer,
|
||||
Error: err,
|
||||
|
@ -197,9 +236,15 @@ func (c *WebRTCPeer) connect(config *webrtc.Configuration, broker *BrokerChannel
|
|||
// Wait for the datachannel to open or time out
|
||||
select {
|
||||
case <-c.open:
|
||||
if natPolicy != nil {
|
||||
natPolicy.Success(actualNatType, natTypeToSend)
|
||||
}
|
||||
case <-time.After(DataChannelTimeout):
|
||||
c.transport.Close()
|
||||
err = errors.New("timeout waiting for DataChannel.OnOpen")
|
||||
if natPolicy != nil {
|
||||
natPolicy.Failure(actualNatType, natTypeToSend)
|
||||
}
|
||||
c.eventsLogger.OnNewSnowflakeEvent(event.EventOnSnowflakeConnectionFailed{Error: err})
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue