diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java index 81e6eee02..79ec41171 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImpl.java @@ -21,6 +21,9 @@ import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeTy import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4; import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.SNOWFLAKE; import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.VANILLA; +import static org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker.AMP_CACHE; +import static org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker.AZURE; +import static org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker.FASTLY; import static org.briarproject.nullsafety.NullSafety.requireNonNull; @Immutable @@ -42,6 +45,20 @@ class CircumventionProviderImpl implements CircumventionProvider { private static final Set DPI_COUNTRIES = new HashSet<>(asList(DPI_BRIDGES)); + // Package access for testing + enum SnowflakeBroker { + + FASTLY('F'), + AZURE('A'), + AMP_CACHE('M'); + + private final char value; + + SnowflakeBroker(char value) { + this.value = value; + } + } + @Inject CircumventionProviderImpl() { } @@ -86,7 +103,17 @@ class CircumventionProviderImpl implements CircumventionProvider { (type == MEEK && line.startsWith("m "))) { bridges.add(line.substring(2)); } else if (type == SNOWFLAKE && line.startsWith("s ")) { - String params = getSnowflakeParams(countryCode, letsEncrypt); + String params; + // If the client can verify Let's Encrypt certificates then + // use the Fastly broker, otherwise use Azure + if (letsEncrypt) { + params = getSnowflakeParams(countryCode, FASTLY); + } else { + params = getSnowflakeParams(countryCode, AZURE); + } + bridges.add(line.substring(2) + " " + params); + // Also use the AMP cache broker + params = getSnowflakeParams(countryCode, AMP_CACHE); bridges.add(line.substring(2) + " " + params); } } @@ -95,15 +122,14 @@ class CircumventionProviderImpl implements CircumventionProvider { } // Package access for testing - @SuppressWarnings("WeakerAccess") - String getSnowflakeParams(String countryCode, boolean letsEncrypt) { + String getSnowflakeParams(String countryCode, SnowflakeBroker broker) { Map params = loadSnowflakeParams(); if (countryCode.isEmpty()) countryCode = DEFAULT_COUNTRY_CODE; // If we have parameters for this country code, return them - String value = params.get(makeKey(countryCode, letsEncrypt)); + String value = params.get(makeKey(countryCode, broker)); if (value != null) return value; // Return the default parameters - value = params.get(makeKey(DEFAULT_COUNTRY_CODE, letsEncrypt)); + value = params.get(makeKey(DEFAULT_COUNTRY_CODE, broker)); return requireNonNull(value); } @@ -115,7 +141,7 @@ class CircumventionProviderImpl implements CircumventionProvider { while (scanner.hasNextLine()) { String line = scanner.nextLine(); if (line.length() < 5) continue; - String key = line.substring(0, 4); // Country code, space, digit + String key = line.substring(0, 4); // Country code, space, broker String value = line.substring(5); params.put(key, value); } @@ -123,7 +149,7 @@ class CircumventionProviderImpl implements CircumventionProvider { return params; } - private String makeKey(String countryCode, boolean letsEncrypt) { - return countryCode + " " + (letsEncrypt ? "1" : "0"); + private String makeKey(String countryCode, SnowflakeBroker broker) { + return countryCode + " " + broker.value; } } diff --git a/bramble-core/src/main/resources/snowflake-params b/bramble-core/src/main/resources/snowflake-params index 9192ec246..4f69c0cff 100644 --- a/bramble-core/src/main/resources/snowflake-params +++ b/bramble-core/src/main/resources/snowflake-params @@ -1,4 +1,6 @@ -ZZ 1 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.l.google.com:19302,stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,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.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 -ZZ 0 url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:stun.l.google.com:19302,stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,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.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 -TM 1 url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:206.53.159.130:3479,stun:176.119.42.11:3479,stun:94.23.17.185:3479,stun:217.74.179.29:3479,stun:83.125.8.47:3479,stun:23.253.102.137:3479,stun:52.26.251.34:3479,stun:52.26.251.34:3479,stun:18.191.223.12:3479,stun:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 -TM 0 url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:206.53.159.130:3479,stun:176.119.42.11:3479,stun:94.23.17.185:3479,stun:217.74.179.29:3479,stun:83.125.8.47:3479,stun:23.253.102.137:3479,stun:52.26.251.34:3479,stun:52.26.251.34:3479,stun:18.191.223.12:3479,stun:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 +ZZ F url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.l.google.com:19302,stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,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.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 +ZZ A url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:stun.l.google.com:19302,stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,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.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 +ZZ M url=https://snowflake-broker.torproject.net/ ampcache=https://cdn.ampproject.org/ front=cdn.ampproject.org ice=stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,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.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 +TM F url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:206.53.159.130:3479,stun:176.119.42.11:3479,stun:94.23.17.185:3479,stun:217.74.179.29:3479,stun:83.125.8.47:3479,stun:23.253.102.137:3479,stun:52.26.251.34:3479,stun:52.26.251.34:3479,stun:18.191.223.12:3479,stun:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 +TM A url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:206.53.159.130:3479,stun:176.119.42.11:3479,stun:94.23.17.185:3479,stun:217.74.179.29:3479,stun:83.125.8.47:3479,stun:23.253.102.137:3479,stun:52.26.251.34:3479,stun:52.26.251.34:3479,stun:18.191.223.12:3479,stun:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 +TM M url=https://snowflake-broker.torproject.net/ ampcache=https://cdn.ampproject.org/ front=cdn.ampproject.org ice=stun:206.53.159.130:3479,stun:176.119.42.11:3479,stun:94.23.17.185:3479,stun:217.74.179.29:3479,stun:83.125.8.47:3479,stun:23.253.102.137:3479,stun:52.26.251.34:3479,stun:52.26.251.34:3479,stun:18.191.223.12:3479,stun:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 \ No newline at end of file diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImplTest.java index 564efcded..6bca13988 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tor/CircumventionProviderImplTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.plugin.tor; +import org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker; import org.briarproject.bramble.test.BrambleTestCase; import org.junit.Test; @@ -17,6 +18,9 @@ import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeTy import static org.briarproject.bramble.plugin.tor.CircumventionProvider.DEFAULT_BRIDGES; import static org.briarproject.bramble.plugin.tor.CircumventionProvider.DPI_BRIDGES; import static org.briarproject.bramble.plugin.tor.CircumventionProvider.NON_DEFAULT_BRIDGES; +import static org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker.AMP_CACHE; +import static org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker.AZURE; +import static org.briarproject.bramble.plugin.tor.CircumventionProviderImpl.SnowflakeBroker.FASTLY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -67,18 +71,23 @@ public class CircumventionProviderImplTest extends BrambleTestCase { } @Test - public void testHasSnowflakeParamsWithLetsEncrypt() { - testHasSnowflakeParams(true); + public void testHasSnowflakeParamsForFastly() { + testHasSnowflakeParams(FASTLY); } @Test - public void testHasSnowflakeParamsWithoutLetsEncrypt() { - testHasSnowflakeParams(false); + public void testHasSnowflakeParamsForAzure() { + testHasSnowflakeParams(AZURE); } - private void testHasSnowflakeParams(boolean letsEncrypt) { - String tmParams = provider.getSnowflakeParams("TM", letsEncrypt); - String defaultParams = provider.getSnowflakeParams("ZZ", letsEncrypt); + @Test + public void testHasSnowflakeParamsForAmpCache() { + testHasSnowflakeParams(AMP_CACHE); + } + + private void testHasSnowflakeParams(SnowflakeBroker broker) { + String tmParams = provider.getSnowflakeParams("TM", broker); + String defaultParams = provider.getSnowflakeParams("ZZ", broker); assertFalse(tmParams.isEmpty()); assertFalse(defaultParams.isEmpty()); assertNotEquals(defaultParams, tmParams);