[tor-commits] [pluggable-transports/snowflake-webext] branch main updated: Add Relay URL support to web proxy
gitolite role
git at cupani.torproject.org
Thu Jun 16 17:09:29 UTC 2022
This is an automated email from the git hooks/post-receive script.
shelikhoo pushed a commit to branch main
in repository pluggable-transports/snowflake-webext.
The following commit(s) were added to refs/heads/main by this push:
new 15768f5 Add Relay URL support to web proxy
15768f5 is described below
commit 15768f50c0ddd68d3ffb815cd532ddbd3d85fd41
Author: Shelikhoo <xiaokangwang at outlook.com>
AuthorDate: Fri May 20 16:37:14 2022 +0100
Add Relay URL support to web proxy
---
broker.js | 3 ++-
config.js | 2 ++
proxypair.js | 16 +++++++++++----
snowflake.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
websocket.js | 26 +++++++++++++++++++++++-
5 files changed, 94 insertions(+), 18 deletions(-)
diff --git a/broker.js b/broker.js
index d83f03c..e993a48 100644
--- a/broker.js
+++ b/broker.js
@@ -67,11 +67,12 @@ class Broker {
this._xhr = xhr; // Used by spec to fake async Broker interaction
const clients = Math.floor(numClientsConnected / 8) * 8;
var data = {
- Version: "1.2",
+ Version: "1.3",
Sid: id,
Type: this.config.proxyType,
NAT: this.natType,
Clients: clients,
+ AcceptedRelayPattern: this.config.allowedRelayPattern,
};
return this._postRequest(xhr, 'proxy', JSON.stringify(data));
});
diff --git a/config.js b/config.js
index d05554c..cac8506 100644
--- a/config.js
+++ b/config.js
@@ -51,3 +51,5 @@ Config.prototype.pcConfig = {
};
Config.PROBEURL = "https://snowflake-broker.freehaven.net:8443/probe";
+
+Config.prototype.allowedRelayPattern="snowflake.torproject.net";
\ No newline at end of file
diff --git a/proxypair.js b/proxypair.js
index 169511b..1d9689e 100644
--- a/proxypair.js
+++ b/proxypair.js
@@ -24,6 +24,7 @@ class ProxyPair {
this.onError = this.onError.bind(this);
this.flush = this.flush.bind(this);
+ this.relayURL = undefined;
this.relayAddr = relayAddr;
this.rateLimit = rateLimit;
this.config = config;
@@ -82,14 +83,14 @@ class ProxyPair {
channel.onclose = () => {
log('WebRTC DataChannel closed.');
snowflake.ui.setStatus('disconnected by webrtc.');
- if(this.counted) {
+ if (this.counted) {
snowflake.ui.decreaseClients();
this.counted = false;
}
this.flush();
return this.close();
};
- channel.onerror = function() {
+ channel.onerror = function () {
return log('Data channel error!');
};
channel.binaryType = "arraybuffer";
@@ -112,7 +113,10 @@ class ProxyPair {
if (peer_ip != null) {
params.push(["client_ip", peer_ip]);
}
- var relay = this.relay = WS.makeWebsocket(this.relayAddr, params);
+ var relay = this.relay =
+ (this.relayURL === undefined) ?
+ WS.makeWebsocket(this.relayAddr, params) :
+ WS.makeWebsocketFromURL(this.relayURL, params);
this.relay.label = 'websocket-relay';
this.relay.onopen = () => {
if (this.timer) {
@@ -125,7 +129,7 @@ class ProxyPair {
this.relay.onclose = () => {
log(relay.label + ' closed.');
snowflake.ui.setStatus('disconnected.');
- if(this.counted) {
+ if (this.counted) {
snowflake.ui.decreaseClients();
this.counted = false;
}
@@ -248,6 +252,10 @@ class ProxyPair {
return (null !== this.pc) && ('closed' !== this.pc.connectionState);
}
+ setRelayURL(relayURL) {
+ this.relayURL = relayURL;
+ }
+
}
ProxyPair.prototype.MAX_BUFFER = 10 * 1024 * 1024;
diff --git a/snowflake.js b/snowflake.js
index 03b0229..7370f01 100644
--- a/snowflake.js
+++ b/snowflake.js
@@ -68,12 +68,12 @@ class Snowflake {
}
this.ui.setStatus(msg);
//update NAT type
- console.log("NAT type: "+ this.ui.natType);
+ console.log("NAT type: " + this.ui.natType);
this.broker.setNATType(this.ui.natType);
recv = this.broker.getClientOffer(pair.id, this.proxyPairs.length);
recv.then((resp) => {
var clientNAT = resp.NAT;
- if (!this.receiveOffer(pair, resp.Offer)) {
+ if (!this.receiveOffer(pair, resp.Offer, resp.RelayURL)) {
return pair.close();
}
//set a timeout for channel creation
@@ -83,14 +83,14 @@ class Snowflake {
pair.close();
// increase poll interval
this.pollInterval =
- Math.min(this.pollInterval + this.config.pollAdjustment,
- this.config.slowestBrokerPollInterval);
+ Math.min(this.pollInterval + this.config.pollAdjustment,
+ this.config.slowestBrokerPollInterval);
if (clientNAT == "restricted") {
this.natFailures++;
}
// if we fail to connect to a restricted client 3 times in
// a row, assume we have a restricted NAT
- if (this.natFailures >= 3){
+ if (this.natFailures >= 3) {
this.ui.natType = "restricted";
console.log("Learned NAT type: restricted");
this.natFailures = 0;
@@ -99,13 +99,13 @@ class Snowflake {
} else {
// decrease poll interval
this.pollInterval =
- Math.max(this.pollInterval - this.config.pollAdjustment,
- this.config.defaultBrokerPollInterval);
+ Math.max(this.pollInterval - this.config.pollAdjustment,
+ this.config.defaultBrokerPollInterval);
this.natFailures = 0;
}
return;
}), this.config.datachannelTimeout);
- }, function() {
+ }, function () {
//on error, close proxy pair
return pair.close();
});
@@ -114,9 +114,24 @@ class Snowflake {
// Receive an SDP offer from some client assigned by the Broker,
// |pair| - an available ProxyPair.
- receiveOffer(pair, desc) {
+ receiveOffer(pair, desc, relayURL) {
var e, offer, sdp;
+
try {
+ if (relayURL !== undefined) {
+ let relayURLParsed = new URL(relayURL);
+ let hostname = relayURLParsed.hostname;
+ let protocol = relayURLParsed.protocol;
+ if (protocol !== "wss:") {
+ log('incorrect relay url protocol');
+ return false;
+ }
+ if (!this.checkRelayPattern(this.config.allowedRelayPattern, hostname)) {
+ log('relay url hostname does not match allowed pattern');
+ return false;
+ }
+ pair.setRelayURL(relayURL);
+ }
offer = JSON.parse(desc);
dbg('Received:\n\n' + offer.sdp + '\n');
sdp = new RTCSessionDescription(offer);
@@ -135,11 +150,11 @@ class Snowflake {
sendAnswer(pair) {
var fail, next;
- next = function(sdp) {
+ next = function (sdp) {
dbg('webrtc: Answer ready.');
return pair.pc.setLocalDescription(sdp).catch(fail);
};
- fail = function() {
+ fail = function () {
pair.close();
return dbg('webrtc: Failed to create or set Answer');
};
@@ -154,7 +169,7 @@ class Snowflake {
pair = new ProxyPair(this.relayAddr, this.rateLimit, this.config);
this.proxyPairs.push(pair);
- log('Snowflake IDs: ' + (this.proxyPairs.map(function(p) {
+ log('Snowflake IDs: ' + (this.proxyPairs.map(function (p) {
return p.id;
})).join(' | '));
@@ -182,6 +197,32 @@ class Snowflake {
return results;
}
+ /**
+ * checkRelayPattern match str against patten
+ * @param {string} pattern
+ * @param {string} str typically a domain name to be checked
+ * @return {boolean}
+ */
+ checkRelayPattern(pattern, str) {
+ if (typeof pattern !== "string") {
+ throw 'invalid checkRelayPattern input: pattern';
+ }
+ if (typeof str !== "string") {
+ throw 'invalid checkRelayPattern input: str';
+ }
+
+ let exactMatch = false;
+ if (pattern.charAt(0) === "^") {
+ exactMatch = true;
+ pattern = pattern.substring(1);
+ }
+
+ if (exactMatch) {
+ return pattern.localeCompare(str) === 0;
+ }
+ return str.endsWith(pattern);
+ }
+
}
Snowflake.prototype.relayAddr = null;
diff --git a/websocket.js b/websocket.js
index da7ba94..fdf470c 100644
--- a/websocket.js
+++ b/websocket.js
@@ -27,7 +27,7 @@ class WS {
if (!path.match(/^\//)) {
path = '/' + path;
}
- path = path.replace(/[^/]+/, function(m) {
+ path = path.replace(/[^/]+/, function (m) {
return encodeURIComponent(m);
});
parts.push(path);
@@ -54,6 +54,30 @@ class WS {
return ws;
}
+ /**
+ * Creates a websocket connection from a URL and params to override
+ * @param {URL|string} url
+ * @param {URLSearchParams|string[][]} params
+ * @return {WebSocket}
+ */
+ static makeWebsocketFromURL(url, params) {
+ let parsedURL = new URL(url);
+ let urlpa = new URLSearchParams(params);
+ urlpa.forEach(function (value, key) {
+ parsedURL.searchParams.set(key, value);
+ });
+
+ let ws = new WebSocket(url);
+ /*
+ 'User agents can use this as a hint for how to handle incoming binary data:
+ if the attribute is set to 'blob', it is safe to spool it to disk, and if it
+ is set to 'arraybuffer', it is likely more efficient to keep the data in
+ memory.'
+ */
+ ws.binaryType = 'arraybuffer';
+ return ws;
+ }
+
static probeWebsocket(addr) {
return new Promise((resolve, reject) => {
const ws = WS.makeWebsocket(addr);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the tor-commits
mailing list