diff --git a/README.md b/README.md index a4db042eadd222cb25390e56792427a5b2c51010..b3482af4d4afc2227c143ebb3b9aada5e5ae95e9 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,4 @@ On Android versions earlier than 7.1 (API 25), you may need to use [Conscrypt](h implementation 'org.conscrypt:conscrypt-android:2.5.2' -Finally, you must also provide a suitable [obfs4proxy](https://gitweb.torproject.org/pluggable-transports/obfs4.git/tree/README.md) binary for your platform. +Finally, you must also provide a suitable meek implementation, such as [lyrebird](https://gitweb.torproject.org/pluggable-transports/lyrebird.git/tree/README.md), for your platform. diff --git a/app/build.gradle b/app/build.gradle index 090845c62f9eface7e6e4416b95b00afc6a73160..573937447879f7988ef6895298043599998e9997 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,7 +62,7 @@ dependencies { implementation 'com.google.dagger:hilt-android:2.44' implementation 'org.conscrypt:conscrypt-android:2.5.2' - tor 'org.briarproject:obfs4proxy-android:0.0.14' + tor 'org.briarproject:lyrebird-android:0.5.0-2' annotationProcessor 'com.google.dagger:hilt-compiler:2.44' } diff --git a/app/src/main/java/org/briarproject/moattest/MainViewModel.java b/app/src/main/java/org/briarproject/moattest/MainViewModel.java index 510e042c4e4f6c463a5123e1b2661e439bbceafd..34459a942ebbce19cb7d061746f10a6f61cd0b3d 100644 --- a/app/src/main/java/org/briarproject/moattest/MainViewModel.java +++ b/app/src/main/java/org/briarproject/moattest/MainViewModel.java @@ -26,7 +26,7 @@ import static java.util.Locale.ROOT; @HiltViewModel class MainViewModel extends AndroidViewModel { - private static final String OBFS4_LIB_NAME = "libobfs4proxy.so"; + private static final String LYREBIRD_LIB_NAME = "liblyrebird.so"; private static final String STATE_DIR_NAME = "state"; private static final String FASTLY_URL = "https://moat.torproject.org.global.prod.fastly.net/"; @@ -58,11 +58,11 @@ class MainViewModel extends AndroidViewModel { countryCode = countryCode.toLowerCase(ROOT); Application app = getApplication(); String nativeLibDir = app.getApplicationInfo().nativeLibraryDir; - File obfs4Lib = new File(nativeLibDir, OBFS4_LIB_NAME); + File lyrebirdLib = new File(nativeLibDir, LYREBIRD_LIB_NAME); File stateDir = app.getDir(STATE_DIR_NAME, MODE_PRIVATE); String url = azure ? AZURE_URL : FASTLY_URL; String front = azure ? AZURE_FRONT : FASTLY_FRONT; - MoatApi moat = new MoatApi(obfs4Lib, stateDir, url, front); + MoatApi moat = new MoatApi(lyrebirdLib, stateDir, url, front); try { List<Bridges> bridges = moat.getWithCountry(countryCode); StringBuilder sb = new StringBuilder(); diff --git a/lib/build.gradle b/lib/build.gradle index 8cdc23d0ad662ef21cfdb328bc9ba6d959078833..a4bfb83eb647e503924a5e2935aeb81a56ff8343 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -25,8 +25,8 @@ dependencies { implementation 'org.briarproject:null-safety:0.1' implementation 'org.briarproject:socks-socket:0.1' - // Linux obfs4proxy binary is only used for testing - tor 'org.briarproject:obfs4proxy-linux:0.0.14' + // Linux lyrebird binary is only used for testing + tor 'org.briarproject:lyrebird-linux:0.5.0-2' // Test with obsolete version 3.12.x to ensure library users can use it // if they need Android 4 compatibility diff --git a/lib/src/main/java/org/briarproject/moat/MoatApi.java b/lib/src/main/java/org/briarproject/moat/MoatApi.java index 9ea4ef91438812409714023bd4f38d23e255a7f0..522d157d375b6b3d1a92a78d0903e7dde4f6fc09 100644 --- a/lib/src/main/java/org/briarproject/moat/MoatApi.java +++ b/lib/src/main/java/org/briarproject/moat/MoatApi.java @@ -44,16 +44,16 @@ public class MoatApi { private static final int EXTRA_SOCKET_TIMEOUT = (int) SECONDS.toMillis(30); private static final String SOCKS_PASSWORD = "\u0000"; - private final File obfs4Executable, obfs4Dir; + private final File lyrebirdExecutable, lyrebirdDir; private final String url, front; private final JsonMapper mapper = JsonMapper.builder() .enable(BLOCK_UNSAFE_POLYMORPHIC_BASE_TYPES) .build(); - public MoatApi(File obfs4Executable, File obfs4Dir, String url, String front) { - if (!obfs4Dir.isDirectory()) throw new IllegalArgumentException(); - this.obfs4Executable = obfs4Executable; - this.obfs4Dir = obfs4Dir; + public MoatApi(File lyrebirdExecutable, File lyrebirdDir, String url, String front) { + if (!lyrebirdDir.isDirectory()) throw new IllegalArgumentException(); + this.lyrebirdExecutable = lyrebirdExecutable; + this.lyrebirdDir = lyrebirdDir; this.url = url; this.front = front; } @@ -63,9 +63,9 @@ public class MoatApi { } public List<Bridges> getWithCountry(String country) throws IOException { - Process obfs4Process = startObfs4(); + Process lyrebirdProcess = startLyrebird(); try { - int port = getPort(obfs4Process); + int port = getPort(lyrebirdProcess); String socksUsername = "url=" + url + ";front=" + front; SocketFactory socketFactory = new SocksSocketFactory( new InetSocketAddress("localhost", port), @@ -93,7 +93,7 @@ public class MoatApi { String responseJson = responseBody.string(); return parseResponse(responseJson); } finally { - obfs4Process.destroy(); + lyrebirdProcess.destroy(); } } @@ -127,11 +127,11 @@ public class MoatApi { return new Bridges(type, source, bridges); } - private Process startObfs4() throws IOException { - ProcessBuilder pb = new ProcessBuilder(obfs4Executable.getAbsolutePath()); + private Process startLyrebird() throws IOException { + ProcessBuilder pb = new ProcessBuilder(lyrebirdExecutable.getAbsolutePath()); Map<String, String> env = pb.environment(); env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1"); - env.put("TOR_PT_STATE_LOCATION", obfs4Dir.getAbsolutePath()); + env.put("TOR_PT_STATE_LOCATION", lyrebirdDir.getAbsolutePath()); env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1"); env.put("TOR_PT_CLIENT_TRANSPORTS", "meek_lite"); pb.redirectErrorStream(true); diff --git a/lib/src/test/java/org/briarproject/moat/MoatApiTest.java b/lib/src/test/java/org/briarproject/moat/MoatApiTest.java index 910ffbada5a16420d22bd4bb71e3fd582011423a..642a1446e59581cc17bfc3a0dbd20e10e106100f 100644 --- a/lib/src/test/java/org/briarproject/moat/MoatApiTest.java +++ b/lib/src/test/java/org/briarproject/moat/MoatApiTest.java @@ -10,7 +10,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; -import java.util.zip.ZipInputStream; import static java.util.Collections.emptyList; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -24,15 +23,17 @@ public class MoatApiTest { "www.cosmopolitan.com", "www.esquire.com"}; private static final String AZURE_URL = "https://onion.azureedge.net/"; private static final String[] AZURE_FRONTS = new String[]{"ajax.aspnetcdn.com"}; + private static final String CDN77_URL = "https://1314488750.rsc.cdn77.org/"; + private static final String[] CDN77_FRONTS = new String[]{"www.phpmyadmin.net"}; @TempDir private File tempFolder; - private File obfs4Executable; + private File lyrebirdExecutable; @BeforeEach public void setup() throws IOException { - obfs4Executable = new File(tempFolder, "obfs4Executable"); - extractObfs4Executable(); + lyrebirdExecutable = new File(tempFolder, "lyrebirdExecutable"); + extractLyrebirdExecutable(); } @Test @@ -45,9 +46,14 @@ public class MoatApiTest { testCn(AZURE_URL, AZURE_FRONTS); } + @Test + public void testCnCdn77() throws Exception { + testCn(CDN77_URL, CDN77_FRONTS); + } + private void testCn(String url, String[] fronts) throws Exception { for (String front : fronts) { - MoatApi moatApi = new MoatApi(obfs4Executable, tempFolder, url, front); + MoatApi moatApi = new MoatApi(lyrebirdExecutable, tempFolder, url, front); List<Bridges> bridges = moatApi.getWithCountry("cn"); boolean anyObfs4 = false, anySnowflake = false; for (Bridges b : bridges) { @@ -69,16 +75,21 @@ public class MoatApiTest { testUs(AZURE_URL, AZURE_FRONTS); } + @Test + public void testUsCdn77() throws Exception { + testUs(CDN77_URL, CDN77_FRONTS); + } + private void testUs(String url, String[] fronts) throws Exception { for (String front : fronts) { - MoatApi moatApi = new MoatApi(obfs4Executable, tempFolder, url, front); + MoatApi moatApi = new MoatApi(lyrebirdExecutable, tempFolder, url, front); assertEquals(emptyList(), moatApi.getWithCountry("us")); } } - private void extractObfs4Executable() throws IOException { - OutputStream out = new FileOutputStream(obfs4Executable); - InputStream in = getInputStream(); + private void extractLyrebirdExecutable() throws IOException { + OutputStream out = new FileOutputStream(lyrebirdExecutable); + InputStream in = getResourceInputStream("x86_64/lyrebird"); byte[] buf = new byte[4096]; while (true) { int read = in.read(buf); @@ -88,14 +99,7 @@ public class MoatApiTest { in.close(); out.flush(); out.close(); - if (!obfs4Executable.setExecutable(true, true)) throw new IOException(); - } - - private InputStream getInputStream() throws IOException { - InputStream in = getResourceInputStream("obfs4proxy_linux-x86_64.zip"); - ZipInputStream zin = new ZipInputStream(in); - if (zin.getNextEntry() == null) throw new IOException(); - return zin; + if (!lyrebirdExecutable.setExecutable(true, true)) throw new IOException(); } @SuppressWarnings("SameParameterValue")