IPtProxy
Lyrebird/Obfs4proxy and Snowflake Pluggable Transports for iOS, MacOS and Android
| Transport | Version |
|---|---|
| Lyrebird | 0.1.0 |
| Snowflake | 2.6.0 |
Both Lyrebird/Obfs4proxy and Snowflake Pluggable Transports are written in Go, which is a little annoying to use on iOS and Android. This project encapsulates all the machinations to make it work and provides an easy to install binary including a wrapper around both.
Problems solved in particular are:
- One cannot compile
mainpackages withgomobile. Both PTs are patched to avoid this. - Both PTs are gathered under one roof here, since you cannot have two
gomobileframeworks as dependencies, since there are some common Go runtime functions exported, which would create a name clash. - Environment variable changes during runtime will not be recognized by
goptlibwhen done from within Swift/Objective-C. Therefore, sensible values are hardcoded in the Go wrapper. - Snowflake and Lyrebird/Obfs4proxy are patched to accept all configuration parameters directly.
- Free ports to be used are automatically found by this library and returned to the consuming app. You can use the initial values for premature configuration, which is just fine in situations, where you can be pretty sure, they're going to be available (typically on iOS). When that's not the case (e.g. multiple instances of your app on a multi-user Android), you should first start the transports and then use the returned ports for configuration of other components (e.g. Tor).
iOS/macOS
Installation
IPtProxy is available through CocoaPods. To install
it, simply add the following line to your Podfile:
pod 'IPtProxy', '~> 3.1'Getting Started
Before using IPtProxy you need to specify a place on disk for the transports to store their state information and log files.
From version 2.0.0 onwards, there's no default anymore! This is out of security concerns, esp. on Android.
You will need to provide StateLocation before use of any transport:
let fm = FileManager.default
// Good choice for apps where IPtProxy runs inside an extension:
if let ptDir = fm
.containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.app")?
.appendingPathComponent("pt_state")?
.path
{
IPtProxy.setStateLocation(ptDir)
}
// For normal apps which run IPtProxy inline:
if let ptDir = fm.urls(for: .documentDirectory, in: .userDomainMask)
.first?
.appendingPathComponent("pt_state")
.path
{
IPtProxy.setStateLocation(ptDir)
}There's a companion library IPtProxyUI which explains the use of IPtProxy and provides all the necessary UI and additional information to use this library in a Tor context.
Android
Installation
From version 1.9.0 onward, IPtProxy is available through
Maven Central.
To install it, simply add the following line to your build.gradle file:
implementation 'com.netzarchitekten:IPtProxy:3.1.0'It is also available through JitPack. To install
it from there, add the following line to your build.gradle file:
implementation 'com.github.tladesignz:IPtProxy:3.1.0'And add this to your root build.gradle at the end of repositories:
allprojects {
repositories {
// ...
maven {
url 'https://jitpack.io'
content {
includeModule('com.github.tladesignz', 'IPtProxy')
}
}
}
}For newer Android Studio projects created in
Android Studio Bumblebee | 2021.1.1
or newer, the JitPack repository needs to be added into the root level file settings.gradle
instead of build.gradle:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
// ...
maven {
url 'https://jitpack.io'
content {
includeModule('com.github.tladesignz', 'IPtProxy')
}
}
}
}Security Concerns:
Since it is relatively easy in the Java/Android ecosystem to inject malicious packages into projects by leveraging the order of repositories and release malicious versions of packages on repositories which come before the original one in the search order, the only way to keep yourself safe is to explicitly define, which packages should be loaded from which repository, when you use multiple repositories:
Getting Started
If you are building a new Android application be sure to declare that it uses the
INTERNET permission in your Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.test.app">
<uses-permission android:name="android.permission.INTERNET"/>
<application ...
Before using IPtProxy you need to specify a place on disk for the transports to store their state information and log files.
From version 2.0.0 onwards, there's no default anymore! This is out of security concerns, esp. on Android.
You will need to provide StateLocation before use of any transport.
Context#getCacheDir(), Context#getFilesDir() or Context#getNoBackupFilesDir()
are good choices for this.
Do not use a directory outside the app's private storage!
File ptDir = new File(getCacheDir(), "pt_state");
IPtProxy.setStateLocation(ptDir.getAbsolutePath());Build
Requirements
This repository contains a precompiled iOS and Android version of IPtProxy. If you want to compile it yourself, you'll need Go 1.16 as a prerequisite.
You will also need Xcode installed when compiling for iOS and an Android NDK when compiling for Android.
The build script needs the gomobile binary and will install it, if not available, yet.
However, you'll still need to make it accessible in your $PATH.
So, if it's not already, add $GOPATH/bin to $PATH. The default location
for $GOPATH is $HOME/go:
export PATH=$HOME/go/bin/:$PATH` iOS
Make sure Xcode and Xcode's command line tools are installed. Then run
rm -rf IPtProxy.xcframework && ./build.shThis will create an IPtProxy.xcframework, which you can directly drop in your app,
if you don't want to rely on CocoaPods.
Android
Make sure that javac is in your $PATH. If you do not have a JDK instance, on Debian systems you can install it with:
apt install default-jdk If they aren't already, make sure the $ANDROID_HOME and $ANDROID_NDK_HOME
environment variables are set:
export ANDROID_HOME=~/Android/Sdk
export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/$NDK_VERSION
rm -rf IPtProxy.aar IPtProxy-sources.jar && ./build.sh androidThis will create an IPtProxy.aar file, which you can directly drop in your app,
if you don't want to rely on Maven Central or JitPack.
On certain CPU architectures gobind might fail with this error due to setting
a flag that is no longer supported by Go 1.16:
go tool compile: exit status 1
unsupported setting GO386=387. Consider using GO386=softfloat instead.
gomobile: go build -v -buildmode=c-shared -o=/tmp/gomobile-work-855414073/android/src/main/jniLibs/x86/libgojni.so ./gobind failed: exit status 1
If this is the case, you will need to set this flag to build IPtProxy:
export GO386=sse2Release
A release commit needs the following:
Append CHANGELOG.
Update IPtProxy and dependencies' version numbers in
Do fresh builds
rm -rf IPtProxy.xcframework && ./build.sh
rm -f IPtProxy.aar IPtProxy-sources.jar && ./build-android.shTag and push changes
git add .
git commit -m Release version <tag>.
git tag <tag>
git push
git push --tagsCocoaPods
pod trunk pushMaven Central
- Run
bundle.shlike this:
./bundle.sh <version> [<GPG signing key ID>] If you don't define your signing key, the first available will be used. If no keys, no signing will be done. Maven Central will reject unsigned artifacts.
To see your available keys, run this:
gpg --list-secret-keys- Go to https://s01.oss.sonatype.org/#staging-upload.
- Select upload mode "Artifact Bundle".
- Upload bundle and release.
See also: https://gitlab.com/-/snippets/2482490
Authors
- Benjamin Erhart, [email protected]
- Nathan Freitas
- Bim
for the Guardian Project https://guardianproject.info
License
IPtProxy is available under the MIT license. See the LICENSE file for more info.