8000 GitHub - tladesignz/IPtProxy: Obfs4proxy and Snowflake Pluggable Transports for iOS
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

tladesignz/IPtProxy

Repository files navigation

IPtProxy

Lyrebird/Obfs4proxy and Snowflake Pluggable Transports for iOS, MacOS and Android

Maven Central Version License Platform

Transport Version
Lyrebird 0.6.0
Snowflake 2.11.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 main packages with gomobile. For both PTs, IPtProxy provides wrapper code to use them as libraries.
  • Both PTs are gathered under one roof here, since you cannot have two gomobile frameworks as dependencies. There are some common Go runtime functions exported, which would create a name clash.
  • Free ports to be used are automatically found by this library and can be fetched
  • by the consuming app after start.

Caveat

IPtProxy is now provided with classes. You should not instantiate multiple objects of these classes!

Instead, instantiate Controller and/or SnowflakeProxy once, if you need them and keep a reference around.

It's good practice, to have all the IPtProxy handling contained in one place, so you can just store your references there. If that is not feasible within your project, Swift provides the possibility to keep singleton references in an extension to their respective objects like so:

import IPtProxy

extension IPtProxyController {

    // See below how to get `ptDir`!
    var ptDir = ""

    // Set `ptDir` first, before accessing this the first time! 
    static let shared = {
		return IPtProxyController(ptDir, enableLogging: true, unsafeLogging: false, logLevel: "INFO", transportStopped: nil)
    }()
}

extension IPtProxySnowflakeProxy {

    static let shared = {
        let sp = IPtProxySnowflakeProxy()
        sp.capacity = 0
        sp.brokerUrl = "..."
        sp.relayUrl = "..."
        sp.stunServer = "..."
        sp.natProbeUrl = "..."
        sp.pollInterval = 60
        
        return sp
    }()
}

On Android, you might resort to a subclassed Application object, if you already use one, or just any holder object:

import IPtProxy

object Transports {

    // See below how to get `ptDir`!
    var ptDir = ""

    // Set `ptDir` first, before accessing this the first time! 
    val controller: Controller by lazy {
        Controller(ptDir, true, false, "INFO", null)
    }
    
    val snowflakeProxy: SnowflakeProxy by lazy {
        val sp = SnowflakeProxy()
        sp.capacity = 0
        sp.brokerUrl = "..."
        sp.relayUrl = "..."
        sp.stunServer = "..."
        sp.natProbeUrl = "..."
        sp.pollInterval = 60
        
        sp
    }
}

iOS/macOS

Installation

IPtProxy is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'IPtProxy', '~> 4.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 stateDir before use of any transport:

let fm = FileManager.default

// Good choice for apps where IPtProxy runs inside an extension:

guard let ptDir = fm
    .containerURL(forSecurityApplicationGroupIdentifier: "group.com.example.app")? 
    .appendingPathComponent("pt_state")?
    .path
else {
    return
}

let ptc = IPtProxyController(ptDir, enableLogging: true, unsafeLogging: false, logLevel: "INFO", transportStopped: nil)

// For normal apps which run IPtProxy inline:

guard let ptDir = fm.urls(for: .documentDirectory, in: .userDomainMask)
    .first?
    .appendingPathComponent("pt_state")
    .path 
else {
    return
}

let ptc = IPtProxyController(ptDir, enableLogging: true, unsafeLogging: false, logLevel: "INFO", transportStopped: nil)

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. (Also for macOS, despite the name!)

For a headache-free start into the world of Tor on iOS and macOS, check out the new TorManager project.

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:4.1.2'

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:

https://docs.gradle.org/5.1/userguide/declaring_repositories.html#sec::matching_repositories_to_dependencies

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 stateDir 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!

import IPtProxy

File ptDir = new File(getCacheDir(), "pt_state");

Controller ptc = Controller(ptDir.getPath(), true, false, "INFO", null);

Build

Requirements