From 94c84c7542a90e778314919cf8da79b3bac9fb11 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Fri, 8 Mar 2024 11:11:53 +0000 Subject: [PATCH] Refactor CircumventionProvider to use separate resources. --- .../onionwrapper/CircumventionProvider.java | 74 +++++------ .../CircumventionProviderImpl.java | 121 +++++++----------- onionwrapper-core/src/main/resources/bridges | 39 ------ .../src/main/resources/bridges-d-zz | 11 ++ .../src/main/resources/bridges-m-zz | 1 + .../src/main/resources/bridges-n-zz | 17 +++ .../src/main/resources/bridges-s-zz | 4 + .../src/main/resources/bridges-v-zz | 9 ++ .../src/main/resources/snowflake-params | 6 - .../CircumventionProviderImplTest.java | 90 ++++--------- .../briarproject/onionwrapper/BridgeTest.java | 57 ++++++--- 11 files changed, 182 insertions(+), 247 deletions(-) delete mode 100644 onionwrapper-core/src/main/resources/bridges create mode 100644 onionwrapper-core/src/main/resources/bridges-d-zz create mode 100644 onionwrapper-core/src/main/resources/bridges-m-zz create mode 100644 onionwrapper-core/src/main/resources/bridges-n-zz create mode 100644 onionwrapper-core/src/main/resources/bridges-s-zz create mode 100644 onionwrapper-core/src/main/resources/bridges-v-zz delete mode 100644 onionwrapper-core/src/main/resources/snowflake-params diff --git a/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProvider.java b/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProvider.java index 2c047ba..f95668c 100644 --- a/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProvider.java +++ b/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProvider.java @@ -11,66 +11,60 @@ import javax.annotation.concurrent.ThreadSafe; public interface CircumventionProvider { enum BridgeType { - DEFAULT_OBFS4, - NON_DEFAULT_OBFS4, - VANILLA, - MEEK, - SNOWFLAKE - } - /** - * Countries where Tor is blocked, i.e. vanilla Tor connection won't work. - * <p> - * See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - * and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki - */ - String[] BLOCKED = {"BY", "CN", "EG", "IR", "RU", "TM", "VE"}; + DEFAULT_OBFS4("d"), + NON_DEFAULT_OBFS4("n"), + VANILLA("v"), + MEEK("m"), + SNOWFLAKE("s"); + + final String letter; + + BridgeType(String letter) { + this.letter = letter; + } + } /** - * Countries where bridge connections are likely to work. - * Should be a subset of {@link #BLOCKED} and the union of - * {@link #DEFAULT_BRIDGES}, {@link #NON_DEFAULT_BRIDGES} and - * {@link #DPI_BRIDGES}. + * Countries where default obfs4 bridges should be used. */ - String[] BRIDGES = {"BY", "CN", "EG", "IR", "RU", "TM", "VE"}; + String[] COUNTRIES_DEFAULT_BRIDGES = {"BY"}; /** - * Countries where default obfs4 or vanilla bridges are likely to work. - * Should be a subset of {@link #BRIDGES}. + * Countries where non-default obfs4 and vanilla bridges should be used. */ - String[] DEFAULT_BRIDGES = {"EG", "VE"}; + String[] COUNTRIES_NON_DEFAULT_BRIDGES = {"BY", "CN", "EG", "HK", "IR", "RU"}; /** - * Countries where non-default obfs4 or vanilla bridges are likely to work. - * Should be a subset of {@link #BRIDGES}. + * Countries where meek bridges should be used. */ - String[] NON_DEFAULT_BRIDGES = {"BY", "RU"}; + String[] COUNTRIES_MEEK_BRIDGES = {"TM"}; /** - * Countries where vanilla bridges are blocked via DPI but non-default - * obfs4 bridges, meek and snowflake may work. Should be a subset of - * {@link #BRIDGES}. + * Countries where snowflake bridges should be used. */ - String[] DPI_BRIDGES = {"CN", "IR", "TM"}; + String[] COUNTRIES_SNOWFLAKE_BRIDGES = {"BY", "CN", "EG", "HK", "IR", "RU", "TM"}; /** - * Returns true if vanilla Tor connections are blocked in the given country. + * Returns the types of bridge connection that are suitable for the given country, or + * {@link BridgeType#DEFAULT_OBFS4} and {@link BridgeType#VANILLA} if we don't have any + * specific recommendations for the given country. */ - boolean isTorProbablyBlocked(String countryCode); + List<BridgeType> getSuitableBridgeTypes(String countryCode); /** - * Returns true if bridge connections of some type work in the given - * country. + * Returns bridges of the given type that are usable in the given country. + * + * @param letsEncrypt Specifies whether the client is able to verify Let's Encrypt TLS + * certificates signed with the IdentTrust DST Root X3 certificate. Versions of Android + * older than 7.1 consider the certificate to have expired at the end of September 2021. + * This parameter is currently ignored, as no domain-fronted bridges use Let's Encrypt + * certificates. */ - boolean doBridgesWork(String countryCode); + List<String> getBridges(BridgeType type, String countryCode, boolean letsEncrypt); /** - * Returns the types of bridge connection that are suitable for the given - * country, or {@link #DEFAULT_BRIDGES} if no bridge type is known - * to work. + * Returns bridges of the given type that are usable in the given country. */ - List<BridgeType> getSuitableBridgeTypes(String countryCode); - - List<String> getBridges(BridgeType type, String countryCode, - boolean letsEncrypt); + List<String> getBridges(BridgeType type, String countryCode); } diff --git a/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProviderImpl.java b/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProviderImpl.java index 8f2af99..eef54fc 100644 --- a/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProviderImpl.java +++ b/onionwrapper-core/src/main/java/org/briarproject/onionwrapper/CircumventionProviderImpl.java @@ -6,15 +6,14 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Scanner; import java.util.Set; -import java.util.TreeMap; import javax.annotation.concurrent.Immutable; import javax.inject.Inject; import static java.util.Arrays.asList; +import static java.util.Locale.US; import static org.briarproject.nullsafety.NullSafety.requireNonNull; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.DEFAULT_OBFS4; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.MEEK; @@ -26,102 +25,68 @@ import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.VAN @NotNullByDefault class CircumventionProviderImpl implements CircumventionProvider { - private final static String BRIDGE_FILE_NAME = "bridges"; - private final static String SNOWFLAKE_PARAMS_FILE_NAME = "snowflake-params"; - private final static String DEFAULT_COUNTRY_CODE = "ZZ"; + private static final String DEFAULT_COUNTRY_CODE = "ZZ"; - private static final Set<String> BLOCKED_IN_COUNTRIES = - new HashSet<>(asList(BLOCKED)); - private static final Set<String> BRIDGE_COUNTRIES = - new HashSet<>(asList(BRIDGES)); - private static final Set<String> DEFAULT_OBFS4_BRIDGE_COUNTRIES = - new HashSet<>(asList(DEFAULT_BRIDGES)); - private static final Set<String> NON_DEFAULT_BRIDGE_COUNTRIES = - new HashSet<>(asList(NON_DEFAULT_BRIDGES)); - private static final Set<String> DPI_COUNTRIES = - new HashSet<>(asList(DPI_BRIDGES)); + private static final Set<String> DEFAULT_BRIDGES = + new HashSet<>(asList(COUNTRIES_DEFAULT_BRIDGES)); + private static final Set<String> NON_DEFAULT_BRIDGES = + new HashSet<>(asList(COUNTRIES_NON_DEFAULT_BRIDGES)); + private static final Set<String> MEEK_BRIDGES = + new HashSet<>(asList(COUNTRIES_MEEK_BRIDGES)); + private static final Set<String> SNOWFLAKE_BRIDGES = + new HashSet<>(asList(COUNTRIES_SNOWFLAKE_BRIDGES)); @Inject CircumventionProviderImpl() { } @Override - public boolean isTorProbablyBlocked(String countryCode) { - return BLOCKED_IN_COUNTRIES.contains(countryCode); + public List<BridgeType> getSuitableBridgeTypes(String countryCode) { + List<BridgeType> types = new ArrayList<>(); + if (DEFAULT_BRIDGES.contains(countryCode)) { + types.add(DEFAULT_OBFS4); + } + if (NON_DEFAULT_BRIDGES.contains(countryCode)) { + types.add(NON_DEFAULT_OBFS4); + types.add(VANILLA); + } + if (MEEK_BRIDGES.contains(countryCode)) types.add(MEEK); + if (SNOWFLAKE_BRIDGES.contains(countryCode)) types.add(SNOWFLAKE); + // If we don't have any recommendations for this country then use the defaults + if (types.isEmpty()) { + types.add(DEFAULT_OBFS4); + types.add(VANILLA); + } + return types; } @Override - public boolean doBridgesWork(String countryCode) { - return BRIDGE_COUNTRIES.contains(countryCode); + public List<String> getBridges(BridgeType type, String countryCode, boolean letsEncrypt) { + // The `letsEncrypt` parameter is ignored, as no domain-fronted bridges use Let's Encrypt + return getBridges(type, countryCode); } @Override - public List<BridgeType> getSuitableBridgeTypes(String countryCode) { - if (DEFAULT_OBFS4_BRIDGE_COUNTRIES.contains(countryCode)) { - return asList(DEFAULT_OBFS4, VANILLA); - } else if (NON_DEFAULT_BRIDGE_COUNTRIES.contains(countryCode)) { - return asList(NON_DEFAULT_OBFS4, VANILLA); - } else if (DPI_COUNTRIES.contains(countryCode)) { - return asList(NON_DEFAULT_OBFS4, MEEK, SNOWFLAKE); - } else { - return asList(DEFAULT_OBFS4, VANILLA); + public List<String> getBridges(BridgeType type, String countryCode) { + ClassLoader cl = getClass().getClassLoader(); + // Try to load bridges that are specific to this country code + String filename = makeResourceFilename(type, countryCode); + InputStream is = cl.getResourceAsStream(filename); + if (is == null) { + // No resource for this country code - use the fallback resource + filename = makeResourceFilename(type, DEFAULT_COUNTRY_CODE); + is = requireNonNull(cl.getResourceAsStream(filename)); } - } - - @Override - public List<String> getBridges(BridgeType type, String countryCode, - boolean letsEncrypt) { - InputStream is = requireNonNull(getClass().getClassLoader() - .getResourceAsStream(BRIDGE_FILE_NAME)); - Scanner scanner = new Scanner(is); - List<String> bridges = new ArrayList<>(); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if ((type == DEFAULT_OBFS4 && line.startsWith("d ")) || - (type == NON_DEFAULT_OBFS4 && line.startsWith("n ")) || - (type == VANILLA && line.startsWith("v ")) || - (type == MEEK && line.startsWith("m "))) { - bridges.add(line.substring(2)); - } else if (type == SNOWFLAKE && line.startsWith("s ")) { - String params = getSnowflakeParams(countryCode, letsEncrypt); - bridges.add(line.substring(2) + " " + params); - } - } - scanner.close(); - return bridges; - } - - // Package access for testing - @SuppressWarnings("WeakerAccess") - String getSnowflakeParams(String countryCode, boolean letsEncrypt) { - Map<String, String> 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)); - if (value != null) return value; - // Return the default parameters - value = params.get(makeKey(DEFAULT_COUNTRY_CODE, letsEncrypt)); - return requireNonNull(value); - } - - private Map<String, String> loadSnowflakeParams() { - InputStream is = requireNonNull(getClass().getClassLoader() - .getResourceAsStream(SNOWFLAKE_PARAMS_FILE_NAME)); Scanner scanner = new Scanner(is); - Map<String, String> params = new TreeMap<>(); while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - if (line.length() < 5) continue; - String key = line.substring(0, 4); // Country code, space, digit - String value = line.substring(5); - params.put(key, value); + bridges.add("Bridge " + scanner.nextLine()); } scanner.close(); - return params; + return bridges; } - private String makeKey(String countryCode, boolean letsEncrypt) { - return countryCode + " " + (letsEncrypt ? "1" : "0"); + private String makeResourceFilename(BridgeType type, String countryCode) { + return "bridges-" + type.letter + "-" + countryCode.toLowerCase(US); } } diff --git a/onionwrapper-core/src/main/resources/bridges b/onionwrapper-core/src/main/resources/bridges deleted file mode 100644 index 410ab7e..0000000 --- a/onionwrapper-core/src/main/resources/bridges +++ /dev/null @@ -1,39 +0,0 @@ -d Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 -d Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 -d Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 -d Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 -d Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0 -d Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0 -d Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0 -d Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0 -d Bridge obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K1gDtDAIcUfeLqbstggjIw2rtgIKqdIhUlHp82XRqNSq/mtAjp1BIC9vHKJ2FAEpGssTPw iat-mode=0 -d Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0 -d Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0 -n Bridge obfs4 185.181.11.86:443 A961609729E7FDF520B4E81F1F1B8FA1045285C3 cert=e5faG9Zk4Ni+e7z2YgGfevyKPQlMvkVGi4ublSsHYjaBovKeNXpOhbeFxzbZZoAzxAoGUQ iat-mode=0 -n Bridge obfs4 120.29.217.52:5223 40FE3DB9800272F9CDC76422F8ED7883280EE96D cert=/71PS4l8c/XJ4DIItlH9xMqNvPFg2RUTrHvPlQWh48u5et8h/yyyjCcYphUadDsfBWpaGQ iat-mode=0 -n Bridge obfs4 185.177.207.138:8443 53716FE26F23C8C6A71A2BC5D9D8DC64747278C7 cert=6jcYVilMEzxdsWghSrQFpYYJlkkir/GPIXw/EnddUK3S8ToVpMG8u1SwMOEdEs735RrMHw iat-mode=0 -n Bridge obfs4 45.142.181.131:42069 6EBCF6B02DA2B982F4080A7119D737366AFB74FA cert=9HyWH/BCwWzNirZdTQtluCgJk+gFhpOqydIuyQ1iDvpnqsAynKF+zcPE/INZFefm86UlBg iat-mode=0 -n Bridge obfs4 94.142.246.132:8088 135C158527AA9FE9A2F26EC515EB6999D813D347 cert=wTUz0/5FhAZRkitil5MprGbSF3JzjxjxI1kAmxAdSeDy98NgcLr11f/qUXWDC76Y97RiSg iat-mode=0 -n Bridge obfs4 185.177.207.132:8443 4FB781F7A9DD39DA53A7996907817FC479874D19 cert=UL2gCAXWW5kEWY4TQ0lNeu6OAmzh40bXYVhMnTWVG8USnyy/zEKGSIPgmwTDMumWr9c1Pg iat-mode=0 -n Bridge obfs4 158.174.114.97:3456 32665CD4CBE19092CA47A53D317B8BFF5810441C cert=ne5Zt0TcMedSGmFwAs/AV6J6E9Hn7mG5mR6vQNpEfyuCZK1VRpQvU1LvvtesSu4CXqZtYQ iat-mode=0 -n Bridge obfs4 64.4.175.62:8000 8B72740D150795ACB5101AA5F95D1ACDA4FE6B3E cert=vduuNhJ5U/8hjZmllP6AFfXSlSZsnrimdR8Tm8DY9dxWS4n2j92fNc0qHihUwRqwcOfIcg iat-mode=0 -n Bridge obfs4 82.64.115.17:990 B08238781C2CD80DBD95AEABEB6F6C75F2E2CEB6 cert=1udeMlFNs3sJ20zwpPE6nShZqqwDb3F1ET4KzfSfD+fktkue9zNx9H3t+yLCPAsg+6UTUA iat-mode=1 -n Bridge obfs4 87.106.229.194:8006 0B6892C2DCD1FE8C1E7CBEC202BCEBECBDE47ECB cert=dZWWyGKA2x26+bHSMqPKSE81PGarid4FUHGYJMzs9onWMjUuZVotKRYlMIRStVdqKBdOVw iat-mode=0 -n Bridge obfs4 185.177.207.153:8443 6574D4D903FDE714F2759A3B3C31C0363A92DCDC cert=VAZd6bOJ6BKUZLLOYhMuaSPxjf+ZGAspvdQkf8C3naGk8r2b77WXWj9JF8+jLYb8l2fnUw iat-mode=0 -n Bridge obfs4 213.109.161.63:1790 7AC552E815FD43CEDE8E5E1768B305F61AC173B3 cert=9VwHJxHDvWBBHaLarwT5xPuCY0vVs6AWMsX4WuQ08Gj1JheSHYKZuSNiAXzZSukRlDKTDA iat-mode=0 -n Bridge obfs4 80.209.233.177:50901 1E8DB927ADDF9F0E529863ECEEAF801E43FFE355 cert=bDUl798foJHCXhkDYXLTog0El/tqx06DdZNo18nCDzKpElQyIeqU3wg6qggmbZycU6v4fw iat-mode=0 -n Bridge obfs4 78.159.118.224:19998 9735DAE37918DD9F0BA9CF56D336294BCB4207CC cert=MIBlPdg69nSskD9Id8bLzwQFJ1zICUMwwG9apMlvF35Y6Z9W8AVbSlahxlY17l8zLvwdEA iat-mode=0 -n Bridge obfs4 24.134.5.121:8989 6C11CE58EA4D4C3C7EC078EBDC9D7D8961A58699 cert=q9W7JYmdRvQqs9MEa7rAKU5iNiu5zKtkyJPVH5aH61QRgcTrjtom58EoDnTnnlc37xNZPQ iat-mode=0 -n Bridge obfs4 152.86.13.25:9025 3A3614A3C6F6BD6300B131E24D8C2A794B36156F cert=6KkUp19/U0GPSAMm9Qvw84Y3j1eJcpyitMB08Jc+NP79ztkuJUoK5/ukIxRntsi5aXOYEg iat-mode=0 -n Bridge obfs4 23.94.169.122:63000 1878E0F5DAFFBD4A0F8DC75820ADB9B10E8ABAF0 cert=iESu5/SAcFI8GPUXHaV4Yk1zraP1AjZySYSsKh0lT+Bj0q/pdwa4PjMjsOusMxiOuUQAOA iat-mode=0 -v Bridge 92.243.15.235:9001 477EAD3C04036B48235F1F27FC91420A286A4B7F -v Bridge 213.108.108.145:17674 A39C0FE47963B6E8CFE9815549864DE544935A31 -v Bridge 87.100.193.2:9010 13FB63452AADFA082BD2BC3E1E320AD301F07877 -v Bridge 65.21.240.163:33245 20BD59649212CFE7412BFC9B94C3CCCFD8F807A8 -v Bridge 195.201.202.125:443 D44C0BC5AF900547704BCE5062E4B169672120E8 -v Bridge 80.67.179.20:143 D1B6871457A0AA01BF46EEB1989D89086E5E6825 -v Bridge 95.217.86.169:9001 7E0551FA74CF3C94C9CE3FB627AA6CA1066CECDC -v Bridge 23.88.56.229:18680 0131800F17ACED0D6CF979F3D0910D63E5F6015A -v Bridge 95.216.198.193:8080 23F35720E7DAC1F8A3DDBD5D40C90A552B31435A -m Bridge meek_lite 192.0.2.18:80 BE776A53492E1E044A26F17306E1BC46A55A1625 url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com utls=hellochrome_auto -s Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 diff --git a/onionwrapper-core/src/main/resources/bridges-d-zz b/onionwrapper-core/src/main/resources/bridges-d-zz new file mode 100644 index 0000000..c97c76c --- /dev/null +++ b/onionwrapper-core/src/main/resources/bridges-d-zz @@ -0,0 +1,11 @@ +obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1 +obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 +obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 +obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 +obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0 +obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0 +obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0 +obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0 +obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K1gDtDAIcUfeLqbstggjIw2rtgIKqdIhUlHp82XRqNSq/mtAjp1BIC9vHKJ2FAEpGssTPw iat-mode=0 +obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0 +obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0 diff --git a/onionwrapper-core/src/main/resources/bridges-m-zz b/onionwrapper-core/src/main/resources/bridges-m-zz new file mode 100644 index 0000000..a7c2573 --- /dev/null +++ b/onionwrapper-core/src/main/resources/bridges-m-zz @@ -0,0 +1 @@ +meek_lite 192.0.2.18:80 BE776A53492E1E044A26F17306E1BC46A55A1625 url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com utls=hellochrome_auto diff --git a/onionwrapper-core/src/main/resources/bridges-n-zz b/onionwrapper-core/src/main/resources/bridges-n-zz new file mode 100644 index 0000000..030d97b --- /dev/null +++ b/onionwrapper-core/src/main/resources/bridges-n-zz @@ -0,0 +1,17 @@ +obfs4 185.181.11.86:443 A961609729E7FDF520B4E81F1F1B8FA1045285C3 cert=e5faG9Zk4Ni+e7z2YgGfevyKPQlMvkVGi4ublSsHYjaBovKeNXpOhbeFxzbZZoAzxAoGUQ iat-mode=0 +obfs4 120.29.217.52:5223 40FE3DB9800272F9CDC76422F8ED7883280EE96D cert=/71PS4l8c/XJ4DIItlH9xMqNvPFg2RUTrHvPlQWh48u5et8h/yyyjCcYphUadDsfBWpaGQ iat-mode=0 +obfs4 185.177.207.138:8443 53716FE26F23C8C6A71A2BC5D9D8DC64747278C7 cert=6jcYVilMEzxdsWghSrQFpYYJlkkir/GPIXw/EnddUK3S8ToVpMG8u1SwMOEdEs735RrMHw iat-mode=0 +obfs4 45.142.181.131:42069 6EBCF6B02DA2B982F4080A7119D737366AFB74FA cert=9HyWH/BCwWzNirZdTQtluCgJk+gFhpOqydIuyQ1iDvpnqsAynKF+zcPE/INZFefm86UlBg iat-mode=0 +obfs4 94.142.246.132:8088 135C158527AA9FE9A2F26EC515EB6999D813D347 cert=wTUz0/5FhAZRkitil5MprGbSF3JzjxjxI1kAmxAdSeDy98NgcLr11f/qUXWDC76Y97RiSg iat-mode=0 +obfs4 185.177.207.132:8443 4FB781F7A9DD39DA53A7996907817FC479874D19 cert=UL2gCAXWW5kEWY4TQ0lNeu6OAmzh40bXYVhMnTWVG8USnyy/zEKGSIPgmwTDMumWr9c1Pg iat-mode=0 +obfs4 158.174.114.97:3456 32665CD4CBE19092CA47A53D317B8BFF5810441C cert=ne5Zt0TcMedSGmFwAs/AV6J6E9Hn7mG5mR6vQNpEfyuCZK1VRpQvU1LvvtesSu4CXqZtYQ iat-mode=0 +obfs4 64.4.175.62:8000 8B72740D150795ACB5101AA5F95D1ACDA4FE6B3E cert=vduuNhJ5U/8hjZmllP6AFfXSlSZsnrimdR8Tm8DY9dxWS4n2j92fNc0qHihUwRqwcOfIcg iat-mode=0 +obfs4 82.64.115.17:990 B08238781C2CD80DBD95AEABEB6F6C75F2E2CEB6 cert=1udeMlFNs3sJ20zwpPE6nShZqqwDb3F1ET4KzfSfD+fktkue9zNx9H3t+yLCPAsg+6UTUA iat-mode=1 +obfs4 87.106.229.194:8006 0B6892C2DCD1FE8C1E7CBEC202BCEBECBDE47ECB cert=dZWWyGKA2x26+bHSMqPKSE81PGarid4FUHGYJMzs9onWMjUuZVotKRYlMIRStVdqKBdOVw iat-mode=0 +obfs4 185.177.207.153:8443 6574D4D903FDE714F2759A3B3C31C0363A92DCDC cert=VAZd6bOJ6BKUZLLOYhMuaSPxjf+ZGAspvdQkf8C3naGk8r2b77WXWj9JF8+jLYb8l2fnUw iat-mode=0 +obfs4 213.109.161.63:1790 7AC552E815FD43CEDE8E5E1768B305F61AC173B3 cert=9VwHJxHDvWBBHaLarwT5xPuCY0vVs6AWMsX4WuQ08Gj1JheSHYKZuSNiAXzZSukRlDKTDA iat-mode=0 +obfs4 80.209.233.177:50901 1E8DB927ADDF9F0E529863ECEEAF801E43FFE355 cert=bDUl798foJHCXhkDYXLTog0El/tqx06DdZNo18nCDzKpElQyIeqU3wg6qggmbZycU6v4fw iat-mode=0 +obfs4 78.159.118.224:19998 9735DAE37918DD9F0BA9CF56D336294BCB4207CC cert=MIBlPdg69nSskD9Id8bLzwQFJ1zICUMwwG9apMlvF35Y6Z9W8AVbSlahxlY17l8zLvwdEA iat-mode=0 +obfs4 24.134.5.121:8989 6C11CE58EA4D4C3C7EC078EBDC9D7D8961A58699 cert=q9W7JYmdRvQqs9MEa7rAKU5iNiu5zKtkyJPVH5aH61QRgcTrjtom58EoDnTnnlc37xNZPQ iat-mode=0 +obfs4 152.86.13.25:9025 3A3614A3C6F6BD6300B131E24D8C2A794B36156F cert=6KkUp19/U0GPSAMm9Qvw84Y3j1eJcpyitMB08Jc+NP79ztkuJUoK5/ukIxRntsi5aXOYEg iat-mode=0 +obfs4 23.94.169.122:63000 1878E0F5DAFFBD4A0F8DC75820ADB9B10E8ABAF0 cert=iESu5/SAcFI8GPUXHaV4Yk1zraP1AjZySYSsKh0lT+Bj0q/pdwa4PjMjsOusMxiOuUQAOA iat-mode=0 diff --git a/onionwrapper-core/src/main/resources/bridges-s-zz b/onionwrapper-core/src/main/resources/bridges-s-zz new file mode 100644 index 0000000..f5d7d9d --- /dev/null +++ b/onionwrapper-core/src/main/resources/bridges-s-zz @@ -0,0 +1,4 @@ +snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.l.google.com:19302,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.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto +snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto +snowflake 192.0.2.5:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.azureedge.net/ fronts=ajax.aspnetcdn.com ice=stun:stun.l.google.com:19302,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.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto +snowflake 192.0.2.6:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://snowflake-broker.azureedge.net/ fronts=ajax.aspnetcdn.com ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto diff --git a/onionwrapper-core/src/main/resources/bridges-v-zz b/onionwrapper-core/src/main/resources/bridges-v-zz new file mode 100644 index 0000000..5e4df34 --- /dev/null +++ b/onionwrapper-core/src/main/resources/bridges-v-zz @@ -0,0 +1,9 @@ +92.243.15.235:9001 477EAD3C04036B48235F1F27FC91420A286A4B7F +213.108.108.145:17674 A39C0FE47963B6E8CFE9815549864DE544935A31 +87.100.193.2:9010 13FB63452AADFA082BD2BC3E1E320AD301F07877 +65.21.240.163:33245 20BD59649212CFE7412BFC9B94C3CCCFD8F807A8 +195.201.202.125:443 D44C0BC5AF900547704BCE5062E4B169672120E8 +80.67.179.20:143 D1B6871457A0AA01BF46EEB1989D89086E5E6825 +95.217.86.169:9001 7E0551FA74CF3C94C9CE3FB627AA6CA1066CECDC +23.88.56.229:18680 0131800F17ACED0D6CF979F3D0910D63E5F6015A +95.216.198.193:8080 23F35720E7DAC1F8A3DDBD5D40C90A552B31435A diff --git a/onionwrapper-core/src/main/resources/snowflake-params b/onionwrapper-core/src/main/resources/snowflake-params deleted file mode 100644 index 86f4b5c..0000000 --- a/onionwrapper-core/src/main/resources/snowflake-params +++ /dev/null @@ -1,6 +0,0 @@ -ZZ 1 url=https://1098762253.rsc.cdn77.org/ front=www.cdn77.com ice=stun:stun.l.google.com:19302,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.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto -ZZ 0 url=https://snowflake-broker.azureedge.net/ front=ajax.aspnetcdn.com ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto -TM 1 url=https://1098762253.rsc.cdn77.org/ front=www.cdn77.com ice=stun:206.53.159.130: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:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 utls-imitate=hellochrome_auto -TM 0 url=https://1098762253.rsc.cdn77.org/ front=www.cdn77.com ice=stun:206.53.159.130: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:154.73.34.8:3479,stun:185.125.180.70:3479,stun:195.35.115.37:3479 utls-imitate=hellochrome_auto -IR 1 url=https://1098762253.rsc.cdn77.org/ front=www.cdn77.com ice=stun:stun.l.google.com:19302,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.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto -IR 0 url=https://1098762253.rsc.cdn77.org/ front=www.cdn77.com ice=stun:stun.l.google.com:19302,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.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellochrome_auto diff --git a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java index 187f396..3dd57ac 100644 --- a/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java +++ b/onionwrapper-core/src/test/java/org/briarproject/onionwrapper/CircumventionProviderImplTest.java @@ -1,24 +1,18 @@ package org.briarproject.onionwrapper; +import org.briarproject.onionwrapper.CircumventionProvider.BridgeType; import org.junit.Test; -import java.util.HashSet; -import java.util.Set; - -import static java.util.Arrays.asList; -import static org.briarproject.onionwrapper.CircumventionProvider.BLOCKED; -import static org.briarproject.onionwrapper.CircumventionProvider.BRIDGES; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.DEFAULT_OBFS4; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.MEEK; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.SNOWFLAKE; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.VANILLA; -import static org.briarproject.onionwrapper.CircumventionProvider.DEFAULT_BRIDGES; -import static org.briarproject.onionwrapper.CircumventionProvider.DPI_BRIDGES; -import static org.briarproject.onionwrapper.CircumventionProvider.NON_DEFAULT_BRIDGES; -import static org.junit.Assert.assertEquals; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_DEFAULT_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_MEEK_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_NON_DEFAULT_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_SNOWFLAKE_BRIDGES; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; public class CircumventionProviderImplTest extends BaseTest { @@ -27,65 +21,35 @@ public class CircumventionProviderImplTest extends BaseTest { new CircumventionProviderImpl(); @Test - public void testInvariants() { - Set<String> blocked = new HashSet<>(asList(BLOCKED)); - Set<String> bridges = new HashSet<>(asList(BRIDGES)); - Set<String> defaultBridges = new HashSet<>(asList(DEFAULT_BRIDGES)); - Set<String> nonDefaultBridges = - new HashSet<>(asList(NON_DEFAULT_BRIDGES)); - Set<String> dpiBridges = new HashSet<>(asList(DPI_BRIDGES)); - // BRIDGES should be a subset of BLOCKED - assertTrue(blocked.containsAll(bridges)); - // BRIDGES should be the union of the bridge type sets - Set<String> union = new HashSet<>(defaultBridges); - union.addAll(nonDefaultBridges); - union.addAll(dpiBridges); - assertEquals(bridges, union); - // The bridge type sets should not overlap - assertEmptyIntersection(defaultBridges, nonDefaultBridges); - assertEmptyIntersection(defaultBridges, dpiBridges); - assertEmptyIntersection(nonDefaultBridges, dpiBridges); - } - - @Test - public void testGetBestBridgeType() { - for (String country : DEFAULT_BRIDGES) { - assertEquals(asList(DEFAULT_OBFS4, VANILLA), - provider.getSuitableBridgeTypes(country)); + public void testGetSuitableBridgeTypes() { + for (String countryCode : COUNTRIES_DEFAULT_BRIDGES) { + testBridgesAreSuitableAndExist(DEFAULT_OBFS4, countryCode); } - for (String country : NON_DEFAULT_BRIDGES) { - assertEquals(asList(NON_DEFAULT_OBFS4, VANILLA), - provider.getSuitableBridgeTypes(country)); + for (String countryCode : COUNTRIES_NON_DEFAULT_BRIDGES) { + testBridgesAreSuitableAndExist(NON_DEFAULT_OBFS4, countryCode); + testBridgesAreSuitableAndExist(VANILLA, countryCode); } - for (String country : DPI_BRIDGES) { - assertEquals(asList(NON_DEFAULT_OBFS4, MEEK, SNOWFLAKE), - provider.getSuitableBridgeTypes(country)); + for (String countryCode : COUNTRIES_MEEK_BRIDGES) { + testBridgesAreSuitableAndExist(MEEK, countryCode); } - assertEquals(asList(DEFAULT_OBFS4, VANILLA), - provider.getSuitableBridgeTypes("ZZ")); - } - - @Test - public void testHasSnowflakeParamsWithLetsEncrypt() { - testHasSnowflakeParams(true); + for (String countryCode : COUNTRIES_SNOWFLAKE_BRIDGES) { + testBridgesAreSuitableAndExist(SNOWFLAKE, countryCode); + } + // If bridges are enabled manually in a country with no specific bridge recommendations, + // we should use default obfs4 and vanilla + testBridgesAreSuitableAndExist(DEFAULT_OBFS4, "US"); + testBridgesAreSuitableAndExist(VANILLA, "US"); } @Test - public void testHasSnowflakeParamsWithoutLetsEncrypt() { - testHasSnowflakeParams(false); - } - - private void testHasSnowflakeParams(boolean letsEncrypt) { - String tmParams = provider.getSnowflakeParams("TM", letsEncrypt); - String defaultParams = provider.getSnowflakeParams("ZZ", letsEncrypt); - assertFalse(tmParams.isEmpty()); - assertFalse(defaultParams.isEmpty()); - assertNotEquals(defaultParams, tmParams); + public void testIPv6BridgeTypes() { + // If we're on an IPv6-only network we'll use meek and snowflake in any country + assertFalse(provider.getBridges(MEEK, "US").isEmpty()); + assertFalse(provider.getBridges(SNOWFLAKE, "US").isEmpty()); } - private <T> void assertEmptyIntersection(Set<T> a, Set<T> b) { - Set<T> intersection = new HashSet<>(a); - intersection.retainAll(b); - assertTrue(intersection.isEmpty()); + private void testBridgesAreSuitableAndExist(BridgeType type, String countryCode) { + assertTrue(provider.getSuitableBridgeTypes(countryCode).contains(type)); + assertFalse(provider.getBridges(type, countryCode).isEmpty()); } } diff --git a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BridgeTest.java b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BridgeTest.java index 34b6208..ab531d4 100644 --- a/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BridgeTest.java +++ b/onionwrapper-java/src/test/java/org/briarproject/onionwrapper/BridgeTest.java @@ -19,6 +19,7 @@ import java.util.logging.Logger; import javax.annotation.concurrent.GuardedBy; +import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.concurrent.Executors.newCachedThreadPool; import static java.util.concurrent.TimeUnit.MINUTES; @@ -29,6 +30,10 @@ import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.MEE import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.SNOWFLAKE; import static org.briarproject.onionwrapper.CircumventionProvider.BridgeType.VANILLA; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_DEFAULT_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_MEEK_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_NON_DEFAULT_BRIDGES; +import static org.briarproject.onionwrapper.CircumventionProvider.COUNTRIES_SNOWFLAKE_BRIDGES; import static org.briarproject.onionwrapper.TestUtils.deleteTestDirectory; import static org.briarproject.onionwrapper.TestUtils.getArchitectureForTorBinary; import static org.briarproject.onionwrapper.TestUtils.getTestDirectory; @@ -44,7 +49,7 @@ public class BridgeTest extends BaseTest { private final static Logger LOG = getLogger(BridgeTest.class.getName()); - private static final String[] SNOWFLAKE_COUNTRY_CODES = {"IR", "TM", "ZZ"}; + private static final List<BridgeType> ESSENTIAL_BRIDGE_TYPES = asList(MEEK, SNOWFLAKE); private static final int SOCKS_PORT = 59060; private static final int CONTROL_PORT = 59061; private final static long TIMEOUT = MINUTES.toMillis(2); @@ -56,27 +61,39 @@ public class BridgeTest extends BaseTest { public static Iterable<Params> data() { // Share stats among all the test instances Stats stats = new Stats(); + // Test all the unique bridge lines + Set<String> bridges = new TreeSet<>(); CircumventionProvider provider = new CircumventionProviderImpl(); List<Params> states = new ArrayList<>(); for (int i = 0; i < ATTEMPTS_PER_BRIDGE; i++) { - for (String bridge : provider.getBridges(DEFAULT_OBFS4, "", true)) { - states.add(new Params(bridge, DEFAULT_OBFS4, stats, false)); - } - for (String bridge : provider.getBridges(NON_DEFAULT_OBFS4, "", true)) { - states.add(new Params(bridge, NON_DEFAULT_OBFS4, stats, false)); + for (BridgeType type : BridgeType.values()) { + for (String bridge : provider.getBridges(type, "ZZ")) { + if (bridges.add(bridge)) states.add(new Params(bridge, type, stats)); + } } - for (String bridge : provider.getBridges(VANILLA, "", true)) { - states.add(new Params(bridge, VANILLA, stats, false)); + for (String countryCode : COUNTRIES_DEFAULT_BRIDGES) { + for (String bridge : provider.getBridges(DEFAULT_OBFS4, countryCode)) { + if (bridges.add(bridge)) states.add(new Params(bridge, DEFAULT_OBFS4, stats)); + } } - for (String bridge : provider.getBridges(MEEK, "", true)) { - states.add(new Params(bridge, MEEK, stats, true)); + for (String countryCode : COUNTRIES_NON_DEFAULT_BRIDGES) { + for (String bridge : provider.getBridges(NON_DEFAULT_OBFS4, countryCode)) { + if (bridges.add(bridge)) { + states.add(new Params(bridge, NON_DEFAULT_OBFS4, stats)); + } + } + for (String bridge : provider.getBridges(VANILLA, countryCode)) { + if (bridges.add(bridge)) states.add(new Params(bridge, VANILLA, stats)); + } } - for (String countryCode : SNOWFLAKE_COUNTRY_CODES) { - for (String bridge : provider.getBridges(SNOWFLAKE, countryCode, true)) { - states.add(new Params(bridge, SNOWFLAKE, stats, true)); + for (String countryCode : COUNTRIES_MEEK_BRIDGES) { + for (String bridge : provider.getBridges(MEEK, countryCode)) { + if (bridges.add(bridge)) states.add(new Params(bridge, MEEK, stats)); } - for (String bridge : provider.getBridges(SNOWFLAKE, countryCode, false)) { - states.add(new Params(bridge, SNOWFLAKE, stats, true)); + } + for (String countryCode : COUNTRIES_SNOWFLAKE_BRIDGES) { + for (String bridge : provider.getBridges(SNOWFLAKE, countryCode)) { + if (bridges.add(bridge)) states.add(new Params(bridge, SNOWFLAKE, stats)); } } } @@ -132,7 +149,7 @@ public class BridgeTest extends BaseTest { params.stats.countSuccess(params.bridge); } else { LOG.warning("Could not connect to Tor within timeout: " + params.bridge); - params.stats.countFailure(params.bridge, params.essential); + params.stats.countFailure(params.bridge, params.bridgeType); } } finally { tor.stop(); @@ -144,13 +161,11 @@ public class BridgeTest extends BaseTest { private final String bridge; private final BridgeType bridgeType; private final Stats stats; - private final boolean essential; - private Params(String bridge, BridgeType bridgeType, Stats stats, boolean essential) { + private Params(String bridge, BridgeType bridgeType, Stats stats) { this.bridge = bridge; this.bridgeType = bridgeType; this.stats = stats; - this.essential = essential; } } @@ -171,7 +186,7 @@ public class BridgeTest extends BaseTest { successes.add(bridge); } - private synchronized void countFailure(String bridge, boolean essential) { + private synchronized void countFailure(String bridge, BridgeType bridgeType) { if (failures.add(bridge) == ATTEMPTS_PER_BRIDGE) { LOG.warning("Bridge is unreachable after " + ATTEMPTS_PER_BRIDGE + " attempts: " + bridge); @@ -179,7 +194,7 @@ public class BridgeTest extends BaseTest { if (unreachable.size() > UNREACHABLE_BRIDGES_ALLOWED) { fail(unreachable.size() + " bridges are unreachable: " + unreachable); } - if (essential) { + if (ESSENTIAL_BRIDGE_TYPES.contains(bridgeType)) { fail("essential bridge is unreachable"); } } -- GitLab