This is an automated email from the git hooks/post-receive script.
shelikhoo pushed a commit to branch main in repository pluggable-transports/snowflake.
commit 613ceaf9709e7170cc95c065cbd3ea8a205a04b2 Author: Shelikhoo xiaokangwang@outlook.com AuthorDate: Tue Apr 5 15:03:31 2022 +0100
Add RelayURL and AllowedRelayPattern to snowflake signaling --- common/messages/messages_test.go | 163 ++++++++++++++++++++++----------------- common/messages/proxy.go | 64 +++++++++++---- 2 files changed, 141 insertions(+), 86 deletions(-)
diff --git a/common/messages/messages_test.go b/common/messages/messages_test.go index dd1f4fb..d1a5e96 100644 --- a/common/messages/messages_test.go +++ b/common/messages/messages_test.go @@ -17,90 +17,103 @@ func TestDecodeProxyPollRequest(t *testing.T) { clients int data string err error + + acceptedRelayPattern string }{ { //Version 1.0 proxy message - "ymbcCMto7KHNGYlp", - "unknown", - "unknown", - 0, - `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`, - nil, + sid: "ymbcCMto7KHNGYlp", + proxyType: "unknown", + natType: "unknown", + clients: 0, + data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.0"}`, + err: nil, }, { //Version 1.1 proxy message - "ymbcCMto7KHNGYlp", - "standalone", - "unknown", - 0, - `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.1","Type":"standalone"}`, - nil, + sid: "ymbcCMto7KHNGYlp", + proxyType: "standalone", + natType: "unknown", + clients: 0, + data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.1","Type":"standalone"}`, + err: nil, }, { //Version 1.2 proxy message - "ymbcCMto7KHNGYlp", - "standalone", - "restricted", - 0, - `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted"}`, - nil, + sid: "ymbcCMto7KHNGYlp", + proxyType: "standalone", + natType: "restricted", + clients: 0, + data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted"}`, + err: nil, }, { //Version 1.2 proxy message with clients - "ymbcCMto7KHNGYlp", - "standalone", - "restricted", - 24, - `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted","Clients":24}`, - nil, + sid: "ymbcCMto7KHNGYlp", + proxyType: "standalone", + natType: "restricted", + clients: 24, + data: `{"Sid":"ymbcCMto7KHNGYlp","Version":"1.2","Type":"standalone", "NAT":"restricted","Clients":24}`, + 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: - "", - "", - "", - 0, - "", - &json.SyntaxError{}, + sid: "", + proxyType: "", + natType: "", + clients: 0, + data: "", + err: &json.SyntaxError{}, }, { - "", - "", - "", - 0, - `{"Sid":"ymbcCMto7KHNGYlp"}`, - fmt.Errorf(""), + sid: "", + proxyType: "", + natType: "", + clients: 0, + data: `{"Sid":"ymbcCMto7KHNGYlp"}`, + err: fmt.Errorf(""), }, { - "", - "", - "", - 0, - "{}", - fmt.Errorf(""), + sid: "", + proxyType: "", + natType: "", + clients: 0, + data: "{}", + err: fmt.Errorf(""), }, { - "", - "", - "", - 0, - `{"Version":"1.0"}`, - fmt.Errorf(""), + sid: "", + proxyType: "", + natType: "", + clients: 0, + data: `{"Version":"1.0"}`, + err: fmt.Errorf(""), }, { - "", - "", - "", - 0, - `{"Version":"2.0"}`, - fmt.Errorf(""), + sid: "", + proxyType: "", + natType: "", + clients: 0, + data: `{"Version":"2.0"}`, + 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(proxyType, ShouldResemble, test.proxyType) So(natType, ShouldResemble, test.natType) So(clients, ShouldEqual, test.clients) + So(relayPattern, ShouldResemble, test.acceptedRelayPattern) So(err, ShouldHaveSameTypeAs, test.err) }
@@ -123,34 +136,42 @@ func TestEncodeProxyPollRequests(t *testing.T) { func TestDecodeProxyPollResponse(t *testing.T) { Convey("Context", t, func() { for _, test := range []struct { - offer string - data string - err error + offer string + data string + relayURL string + err error }{ { - "fake offer", - `{"Status":"client match","Offer":"fake offer","NAT":"unknown"}`, - nil, + offer: "fake offer", + data: `{"Status":"client match","Offer":"fake offer","NAT":"unknown"}`, + err: nil, }, { - "", - `{"Status":"no match"}`, - nil, + offer: "fake offer", + data: `{"Status":"client match","Offer":"fake offer","NAT":"unknown", "RelayURL":"wss://snowflake.torproject.org/proxy"}`, + relayURL: "wss://snowflake.torproject.org/proxy", + err: nil, }, { - "", - `{"Status":"client match"}`, - fmt.Errorf("no supplied offer"), + offer: "", + data: `{"Status":"no match"}`, + err: nil, }, { - "", - `{"Test":"test"}`, - fmt.Errorf(""), + offer: "", + data: `{"Status":"client match"}`, + 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(offer, ShouldResemble, test.offer) + So(relayURL, ShouldResemble, test.relayURL) }
}) diff --git a/common/messages/proxy.go b/common/messages/proxy.go index dcfe0ab..d18a7c3 100644 --- a/common/messages/proxy.go +++ b/common/messages/proxy.go @@ -5,6 +5,7 @@ package messages
import ( "encoding/json" + "errors" "fmt" "strings"
@@ -23,6 +24,8 @@ var KnownProxyTypes = map[string]bool{ "iptproxy": true, }
+var ErrExtraInfo = errors.New("client sent extra info") + /* Version 1.2 specification:
== ProxyPollRequest == @@ -93,22 +96,39 @@ type ProxyPollRequest struct { Type string NAT string Clients int + + AcceptedRelayPattern string }
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{ - Sid: sid, - Version: version, - Type: proxyType, - NAT: natType, - Clients: clients, + Sid: sid, + Version: version, + Type: proxyType, + NAT: natType, + 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 // sid, proxy type, nat type and clients of the proxy on success // 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
err = json.Unmarshal(data, &message) @@ -145,21 +165,28 @@ func DecodeProxyPollRequest(data []byte) (sid string, proxyType string, natType 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 { Status string Offer string NAT string + + RelayURL string }
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 { return json.Marshal(ProxyPollResponse{ - Status: "client match", - Offer: offer, - NAT: natType, + Status: "client match", + Offer: offer, + NAT: natType, + RelayURL: relayURL, })
} @@ -167,23 +194,30 @@ func EncodePollResponse(offer string, success bool, natType string) ([]byte, err 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 // 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
err := json.Unmarshal(data, &message) if err != nil { - return "", "", err + return "", "", "", err } if message.Status == "" { - return "", "", fmt.Errorf("received invalid data") + return "", "", "", fmt.Errorf("received invalid data") }
if message.Status == "client match" { if message.Offer == "" { - return "", "", fmt.Errorf("no supplied offer") + return "", "", "", fmt.Errorf("no supplied offer") } } else { message.Offer = "" @@ -194,7 +228,7 @@ func DecodePollResponse(data []byte) (string, string, error) { natType = "unknown" }
- return message.Offer, natType, nil + return message.Offer, natType, message.RelayURL, nil }
type ProxyAnswerRequest struct {