mirror of
https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake.git
synced 2025-10-13 20:11:19 -04:00
Add RelayURL and AllowedRelayPattern to snowflake signaling
This commit is contained in:
parent
38f0e00e5d
commit
613ceaf970
2 changed files with 141 additions and 86 deletions
|
@ -17,90 +17,103 @@ func TestDecodeProxyPollRequest(t *testing.T) {
|
||||||
clients int
|
clients int
|
||||||
data string
|
data string
|
||||||
err error
|
err error
|
||||||
|
|
||||||
|
acceptedRelayPattern string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
//Version 1.0 proxy message
|
//Version 1.0 proxy message
|
||||||
"ymbcCMto7KHNGYlp",
|
sid: "ymbcCMto7KHNGYlp",
|
||||||
"unknown",
|
proxyType: "unknown",
|
||||||
"unknown",
|
natType: "unknown",
|
||||||
0,
|
clients: 0,
|
||||||
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`,
|
data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`,
|
||||||
nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
//Version 1.1 proxy message
|
//Version 1.1 proxy message
|
||||||
"ymbcCMto7KHNGYlp",
|
sid: "ymbcCMto7KHNGYlp",
|
||||||
"standalone",
|
proxyType: "standalone",
|
||||||
"unknown",
|
natType: "unknown",
|
||||||
0,
|
clients: 0,
|
||||||
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.1","Type":"standalone"}`,
|
data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.1","Type":"standalone"}`,
|
||||||
nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
//Version 1.2 proxy message
|
//Version 1.2 proxy message
|
||||||
"ymbcCMto7KHNGYlp",
|
sid: "ymbcCMto7KHNGYlp",
|
||||||
"standalone",
|
proxyType: "standalone",
|
||||||
"restricted",
|
natType: "restricted",
|
||||||
0,
|
clients: 0,
|
||||||
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted"}`,
|
data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted"}`,
|
||||||
nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
//Version 1.2 proxy message with clients
|
//Version 1.2 proxy message with clients
|
||||||
"ymbcCMto7KHNGYlp",
|
sid: "ymbcCMto7KHNGYlp",
|
||||||
"standalone",
|
proxyType: "standalone",
|
||||||
"restricted",
|
natType: "restricted",
|
||||||
24,
|
clients: 24,
|
||||||
`{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted","Clients":24}`,
|
data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted","Clients":24}`,
|
||||||
nil,
|
err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
//Version 1.3 proxy message with clients and proxyURL
|
||||||
|
sid: "ymbcCMto7KHNGYlp",
|
||||||
|
proxyType: "standalone",
|
||||||
|
natType: "restricted",
|
||||||
|
clients: 24,
|
||||||
|
acceptedRelayPattern: "snowfalke.torproject.org",
|
||||||
|
data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted","Clients":24, "AcceptedRelayPattern":"snowfalke.torproject.org"}`,
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
//Version 0.X proxy message:
|
//Version 0.X proxy message:
|
||||||
"",
|
sid: "",
|
||||||
"",
|
proxyType: "",
|
||||||
"",
|
natType: "",
|
||||||
0,
|
clients: 0,
|
||||||
"",
|
data: "",
|
||||||
&json.SyntaxError{},
|
err: &json.SyntaxError{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
sid: "",
|
||||||
"",
|
proxyType: "",
|
||||||
"",
|
natType: "",
|
||||||
0,
|
clients: 0,
|
||||||
`{"Sid":"ymbcCMto7KHNGYlp"}`,
|
data: `{"Sid":"ymbcCMto7KHNGYlp"}`,
|
||||||
fmt.Errorf(""),
|
err: fmt.Errorf(""),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
sid: "",
|
||||||
"",
|
proxyType: "",
|
||||||
"",
|
natType: "",
|
||||||
0,
|
clients: 0,
|
||||||
"{}",
|
data: "{}",
|
||||||
fmt.Errorf(""),
|
err: fmt.Errorf(""),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
sid: "",
|
||||||
"",
|
proxyType: "",
|
||||||
"",
|
natType: "",
|
||||||
0,
|
clients: 0,
|
||||||
`{"Version":"1.0"}`,
|
data: `{"Version":"1.0"}`,
|
||||||
fmt.Errorf(""),
|
err: fmt.Errorf(""),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
sid: "",
|
||||||
"",
|
proxyType: "",
|
||||||
"",
|
natType: "",
|
||||||
0,
|
clients: 0,
|
||||||
`{"Version":"2.0"}`,
|
data: `{"Version":"2.0"}`,
|
||||||
fmt.Errorf(""),
|
err: fmt.Errorf(""),
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
sid, proxyType, natType, clients, err := DecodeProxyPollRequest([]byte(test.data))
|
sid, proxyType, natType, clients, relayPattern, err := DecodeProxyPollRequestWithRelayPrefix([]byte(test.data))
|
||||||
So(sid, ShouldResemble, test.sid)
|
So(sid, ShouldResemble, test.sid)
|
||||||
So(proxyType, ShouldResemble, test.proxyType)
|
So(proxyType, ShouldResemble, test.proxyType)
|
||||||
So(natType, ShouldResemble, test.natType)
|
So(natType, ShouldResemble, test.natType)
|
||||||
So(clients, ShouldEqual, test.clients)
|
So(clients, ShouldEqual, test.clients)
|
||||||
|
So(relayPattern, ShouldResemble, test.acceptedRelayPattern)
|
||||||
So(err, ShouldHaveSameTypeAs, test.err)
|
So(err, ShouldHaveSameTypeAs, test.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,32 +138,40 @@ func TestDecodeProxyPollResponse(t *testing.T) {
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
offer string
|
offer string
|
||||||
data string
|
data string
|
||||||
|
relayURL string
|
||||||
err error
|
err error
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"fake offer",
|
offer: "fake offer",
|
||||||
`{"Status":"client match","Offer":"fake offer","NAT":"unknown"}`,
|
data: `{"Status":"client match","Offer":"fake offer","NAT":"unknown"}`,
|
||||||
nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
offer: "fake offer",
|
||||||
`{"Status":"no match"}`,
|
data: `{"Status":"client match","Offer":"fake offer","NAT":"unknown", "RelayURL":"wss://snowflake.torproject.org/proxy"}`,
|
||||||
nil,
|
relayURL: "wss://snowflake.torproject.org/proxy",
|
||||||
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
offer: "",
|
||||||
`{"Status":"client match"}`,
|
data: `{"Status":"no match"}`,
|
||||||
fmt.Errorf("no supplied offer"),
|
err: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"",
|
offer: "",
|
||||||
`{"Test":"test"}`,
|
data: `{"Status":"client match"}`,
|
||||||
fmt.Errorf(""),
|
err: fmt.Errorf("no supplied offer"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offer: "",
|
||||||
|
data: `{"Test":"test"}`,
|
||||||
|
err: fmt.Errorf(""),
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
offer, _, err := DecodePollResponse([]byte(test.data))
|
offer, _, relayURL, err := DecodePollResponseWithRelayURL([]byte(test.data))
|
||||||
So(err, ShouldHaveSameTypeAs, test.err)
|
So(err, ShouldHaveSameTypeAs, test.err)
|
||||||
So(offer, ShouldResemble, test.offer)
|
So(offer, ShouldResemble, test.offer)
|
||||||
|
So(relayURL, ShouldResemble, test.relayURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,6 +5,7 @@ package messages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -23,6 +24,8 @@ var KnownProxyTypes = map[string]bool{
|
||||||
"iptproxy": true,
|
"iptproxy": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrExtraInfo = errors.New("client sent extra info")
|
||||||
|
|
||||||
/* Version 1.2 specification:
|
/* Version 1.2 specification:
|
||||||
|
|
||||||
== ProxyPollRequest ==
|
== ProxyPollRequest ==
|
||||||
|
@ -93,22 +96,39 @@ type ProxyPollRequest struct {
|
||||||
Type string
|
Type string
|
||||||
NAT string
|
NAT string
|
||||||
Clients int
|
Clients int
|
||||||
|
|
||||||
|
AcceptedRelayPattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodeProxyPollRequest(sid string, proxyType string, natType string, clients int) ([]byte, error) {
|
func EncodeProxyPollRequest(sid string, proxyType string, natType string, clients int) ([]byte, error) {
|
||||||
|
return EncodeProxyPollRequestWithRelayPrefix(sid, proxyType, natType, clients, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodeProxyPollRequestWithRelayPrefix(sid string, proxyType string, natType string, clients int, relayPattern string) ([]byte, error) {
|
||||||
return json.Marshal(ProxyPollRequest{
|
return json.Marshal(ProxyPollRequest{
|
||||||
Sid: sid,
|
Sid: sid,
|
||||||
Version: version,
|
Version: version,
|
||||||
Type: proxyType,
|
Type: proxyType,
|
||||||
NAT: natType,
|
NAT: natType,
|
||||||
Clients: clients,
|
Clients: clients,
|
||||||
|
AcceptedRelayPattern: relayPattern,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DecodeProxyPollRequest(data []byte) (sid string, proxyType string, natType string, clients int, err error) {
|
||||||
|
var relayPrefix string
|
||||||
|
sid, proxyType, natType, clients, relayPrefix, err = DecodeProxyPollRequestWithRelayPrefix(data)
|
||||||
|
if relayPrefix != "" {
|
||||||
|
return "", "", "", 0, ErrExtraInfo
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Decodes a poll message from a snowflake proxy and returns the
|
// Decodes a poll message from a snowflake proxy and returns the
|
||||||
// sid, proxy type, nat type and clients of the proxy on success
|
// sid, proxy type, nat type and clients of the proxy on success
|
||||||
// and an error if it failed
|
// and an error if it failed
|
||||||
func DecodeProxyPollRequest(data []byte) (sid string, proxyType string, natType string, clients int, err error) {
|
func DecodeProxyPollRequestWithRelayPrefix(data []byte) (
|
||||||
|
sid string, proxyType string, natType string, clients int, relayPrefix string, err error) {
|
||||||
var message ProxyPollRequest
|
var message ProxyPollRequest
|
||||||
|
|
||||||
err = json.Unmarshal(data, &message)
|
err = json.Unmarshal(data, &message)
|
||||||
|
@ -145,21 +165,28 @@ func DecodeProxyPollRequest(data []byte) (sid string, proxyType string, natType
|
||||||
message.Type = ProxyUnknown
|
message.Type = ProxyUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
return message.Sid, message.Type, message.NAT, message.Clients, nil
|
return message.Sid, message.Type, message.NAT, message.Clients, message.AcceptedRelayPattern, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyPollResponse struct {
|
type ProxyPollResponse struct {
|
||||||
Status string
|
Status string
|
||||||
Offer string
|
Offer string
|
||||||
NAT string
|
NAT string
|
||||||
|
|
||||||
|
RelayURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
func EncodePollResponse(offer string, success bool, natType string) ([]byte, error) {
|
func EncodePollResponse(offer string, success bool, natType string) ([]byte, error) {
|
||||||
|
return EncodePollResponseWithRelayURL(offer, success, natType, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodePollResponseWithRelayURL(offer string, success bool, natType, relayURL string) ([]byte, error) {
|
||||||
if success {
|
if success {
|
||||||
return json.Marshal(ProxyPollResponse{
|
return json.Marshal(ProxyPollResponse{
|
||||||
Status: "client match",
|
Status: "client match",
|
||||||
Offer: offer,
|
Offer: offer,
|
||||||
NAT: natType,
|
NAT: natType,
|
||||||
|
RelayURL: relayURL,
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -167,23 +194,30 @@ func EncodePollResponse(offer string, success bool, natType string) ([]byte, err
|
||||||
Status: "no match",
|
Status: "no match",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
func DecodePollResponse(data []byte) (string, string, error) {
|
||||||
|
offer, natType, relayURL, err := DecodePollResponseWithRelayURL(data)
|
||||||
|
if relayURL != "" {
|
||||||
|
return "", "", ErrExtraInfo
|
||||||
|
}
|
||||||
|
return offer, natType, err
|
||||||
|
}
|
||||||
|
|
||||||
// Decodes a poll response from the broker and returns an offer and the client's NAT type
|
// Decodes a poll response from the broker and returns an offer and the client's NAT type
|
||||||
// If there is a client match, the returned offer string will be non-empty
|
// If there is a client match, the returned offer string will be non-empty
|
||||||
func DecodePollResponse(data []byte) (string, string, error) {
|
func DecodePollResponseWithRelayURL(data []byte) (string, string, string, error) {
|
||||||
var message ProxyPollResponse
|
var message ProxyPollResponse
|
||||||
|
|
||||||
err := json.Unmarshal(data, &message)
|
err := json.Unmarshal(data, &message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", "", err
|
||||||
}
|
}
|
||||||
if message.Status == "" {
|
if message.Status == "" {
|
||||||
return "", "", fmt.Errorf("received invalid data")
|
return "", "", "", fmt.Errorf("received invalid data")
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.Status == "client match" {
|
if message.Status == "client match" {
|
||||||
if message.Offer == "" {
|
if message.Offer == "" {
|
||||||
return "", "", fmt.Errorf("no supplied offer")
|
return "", "", "", fmt.Errorf("no supplied offer")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
message.Offer = ""
|
message.Offer = ""
|
||||||
|
@ -194,7 +228,7 @@ func DecodePollResponse(data []byte) (string, string, error) {
|
||||||
natType = "unknown"
|
natType = "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
return message.Offer, natType, nil
|
return message.Offer, natType, message.RelayURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProxyAnswerRequest struct {
|
type ProxyAnswerRequest struct {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue