Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class GnirehtetActivity extends Activity {

public static final String EXTRA_DNS_SERVERS = "dnsServers";
public static final String EXTRA_ROUTES = "routes";
public static final String EXTRA_PROXY_EXCLUSION_LIST = "proxyExclusionList";

private static final int VPN_REQUEST_CODE = 0;

Expand Down Expand Up @@ -59,7 +60,11 @@ private static VpnConfiguration createConfig(Intent intent) {
if (routes == null) {
routes = new String[0];
}
return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes));
String[] proxyExclusionList = intent.getStringArrayExtra(EXTRA_PROXY_EXCLUSION_LIST);
if (proxyExclusionList == null) {
proxyExclusionList = new String[0];
}
return new VpnConfiguration(Net.toInetAddresses(dnsServers), Net.toCIDRs(routes), proxyExclusionList);
}

private boolean startGnirehtet(VpnConfiguration config) {
Expand Down
28 changes: 28 additions & 0 deletions app/src/main/java/com/genymobile/gnirehtet/GnirehtetService.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.ProxyInfo;
import android.net.VpnService;
import android.os.Build;
import android.os.Handler;
Expand Down Expand Up @@ -135,6 +136,9 @@ private boolean setupVpn(VpnConfiguration config) {
}
}

// Set up HTTP proxy with exclusion list
setupHttpProxy(builder, config);

// non-blocking by default, but FileChannel is not selectable, that's stupid!
// so switch to synchronous I/O to avoid polling
builder.setBlocking(true);
Expand All @@ -151,6 +155,30 @@ private boolean setupVpn(VpnConfiguration config) {
return true;
}

@SuppressWarnings("checkstyle:MagicNumber")
private void setupHttpProxy(Builder builder, VpnConfiguration config) {
String[] exclusionList = config.getProxyExclusionList();
if (exclusionList == null || exclusionList.length == 0) {
return;
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Convert exclusion list to comma-separated string
StringBuilder exclusionListStr = new StringBuilder();
for (int i = 0; i < exclusionList.length; i++) {
if (i > 0) {
exclusionListStr.append(",");
}
exclusionListStr.append(exclusionList[i]);
}
ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy(VPN_ADDRESS.getHostAddress(), 31416, exclusionList);
builder.setHttpProxy(proxyInfo);
Log.d(TAG, "HTTP proxy configured with exclusion list: " + exclusionListStr.toString());
} else {
Log.w(TAG, "HTTP proxy exclusion list requires Android 10 (API 29) or higher");
}
}

@SuppressWarnings("checkstyle:MagicNumber")
private void setAsUndernlyingNetwork() {
if (Build.VERSION.SDK_INT >= 22) {
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/com/genymobile/gnirehtet/VpnConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,24 @@ public class VpnConfiguration implements Parcelable {

private final InetAddress[] dnsServers;
private final CIDR[] routes;
private final String[] proxyExclusionList;

public VpnConfiguration() {
this.dnsServers = new InetAddress[0];
this.routes = new CIDR[0];
this.proxyExclusionList = new String[0];
}

public VpnConfiguration(InetAddress[] dnsServers, CIDR[] routes) {
this.dnsServers = dnsServers;
this.routes = routes;
this.proxyExclusionList = new String[0];
}

public VpnConfiguration(InetAddress[] dnsServers, CIDR[] routes, String[] proxyExclusionList) {
this.dnsServers = dnsServers;
this.routes = routes;
this.proxyExclusionList = proxyExclusionList != null ? proxyExclusionList : new String[0];
}

private VpnConfiguration(Parcel source) {
Expand All @@ -48,6 +57,10 @@ private VpnConfiguration(Parcel source) {
throw new AssertionError("Invalid address", e);
}
routes = source.createTypedArray(CIDR.CREATOR);
proxyExclusionList = source.createStringArray();
if (proxyExclusionList == null) {
proxyExclusionList = new String[0];
}
}

public InetAddress[] getDnsServers() {
Expand All @@ -58,13 +71,18 @@ public CIDR[] getRoutes() {
return routes;
}

public String[] getProxyExclusionList() {
return proxyExclusionList;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(dnsServers.length);
for (InetAddress addr : dnsServers) {
dest.writeByteArray(addr.getAddress());
}
dest.writeTypedArray(routes, 0);
dest.writeStringArray(proxyExclusionList);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ public class CommandLineArguments {
public static final int PARAM_DNS_SERVER = 1 << 1;
public static final int PARAM_ROUTES = 1 << 2;
public static final int PARAM_PORT = 1 << 3;
public static final int PARAM_PROXY_EXCLUSION_LIST = 1 << 4;

public static final int DEFAULT_PORT = 31416;

private int port;
private String serial;
private String dnsServers;
private String routes;
private String proxyExclusionList;

public static CommandLineArguments parse(int acceptedParameters, String... args) {
CommandLineArguments arguments = new CommandLineArguments();
Expand Down Expand Up @@ -69,6 +71,15 @@ public static CommandLineArguments parse(int acceptedParameters, String... args)
throw new IllegalArgumentException("Invalid port: " + arguments.port);
}
++i;
} else if ((acceptedParameters & PARAM_PROXY_EXCLUSION_LIST) != 0 && "-x".equals(arg)) {
if (arguments.proxyExclusionList != null) {
throw new IllegalArgumentException("Proxy exclusion list already set");
}
if (i == args.length - 1) {
throw new IllegalArgumentException("Missing -x parameter");
}
arguments.proxyExclusionList = args[i + 1];
++i; // consume the -x parameter
} else if ((acceptedParameters & PARAM_SERIAL) != 0 && arguments.serial == null) {
arguments.serial = arg;
} else {
Expand Down Expand Up @@ -96,4 +107,8 @@ public String getRoutes() {
public int getPort() {
return port;
}

public String getProxyExclusionList() {
return proxyExclusionList;
}
}
51 changes: 30 additions & 21 deletions relay-java/src/main/java/com/genymobile/gnirehtet/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void execute(CommandLineArguments args) throws Exception {
}
},
RUN("run", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES
| CommandLineArguments.PARAM_PORT) {
| CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_PROXY_EXCLUSION_LIST) {
@Override
String getDescription() {
return "Enable reverse tethering for exactly one device:\n"
Expand All @@ -99,10 +99,11 @@ String getDescription() {

@Override
void execute(CommandLineArguments args) throws Exception {
cmdRun(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort());
cmdRun(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort(), args.getProxyExclusionList());
}
},
AUTORUN("autorun", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT) {
AUTORUN("autorun", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT
| CommandLineArguments.PARAM_PROXY_EXCLUSION_LIST) {
@Override
String getDescription() {
return "Enable reverse tethering for all devices:\n"
Expand All @@ -112,11 +113,11 @@ String getDescription() {

@Override
void execute(CommandLineArguments args) throws Exception {
cmdAutorun(args.getDnsServers(), args.getRoutes(), args.getPort());
cmdAutorun(args.getDnsServers(), args.getRoutes(), args.getPort(), args.getProxyExclusionList());
}
},
START("start", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES
| CommandLineArguments.PARAM_PORT) {
| CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_PROXY_EXCLUSION_LIST) {
@Override
String getDescription() {
return "Start a client on the Android device and exit.\n"
Expand All @@ -127,6 +128,7 @@ String getDescription() {
+ "If -r is given, then only reverse tether the specified routes.\n"
+ "If -p is given, then make the relay server listen on the specified\n"
+ "port. Otherwise, use port 31416.\n"
+ "If -x is given, then exclude the specified domains from being proxied.\n"
+ "Otherwise, use 0.0.0.0/0 (redirect the whole traffic).\n"
+ "If the client is already started, then do nothing, and ignore\n"
+ "the other parameters.\n"
Expand All @@ -135,10 +137,11 @@ String getDescription() {

@Override
void execute(CommandLineArguments args) throws Exception {
cmdStart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort());
cmdStart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort(), args.getProxyExclusionList());
}
},
AUTOSTART("autostart", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT) {
AUTOSTART("autostart", CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES | CommandLineArguments.PARAM_PORT
| CommandLineArguments.PARAM_PROXY_EXCLUSION_LIST) {
@Override
String getDescription() {
return "Listen for device connexions and start a client on every detected\n"
Expand All @@ -149,7 +152,7 @@ String getDescription() {

@Override
void execute(CommandLineArguments args) throws Exception {
cmdAutostart(args.getDnsServers(), args.getRoutes(), args.getPort());
cmdAutostart(args.getDnsServers(), args.getRoutes(), args.getPort(), args.getProxyExclusionList());
}
},
STOP("stop", CommandLineArguments.PARAM_SERIAL) {
Expand All @@ -166,15 +169,15 @@ void execute(CommandLineArguments args) throws Exception {
}
},
RESTART("restart", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_DNS_SERVER | CommandLineArguments.PARAM_ROUTES
| CommandLineArguments.PARAM_PORT) {
| CommandLineArguments.PARAM_PORT | CommandLineArguments.PARAM_PROXY_EXCLUSION_LIST) {
@Override
String getDescription() {
return "Stop then start.";
}

@Override
void execute(CommandLineArguments args) throws Exception {
cmdRestart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort());
cmdRestart(args.getSerial(), args.getDnsServers(), args.getRoutes(), args.getPort(), args.getProxyExclusionList());
}
},
TUNNEL("tunnel", CommandLineArguments.PARAM_SERIAL | CommandLineArguments.PARAM_PORT) {
Expand Down Expand Up @@ -231,9 +234,9 @@ private static void cmdReinstall(String serial) throws InterruptedException, IOE
cmdInstall(serial);
}

private static void cmdRun(String serial, String dnsServers, String routes, int port) throws IOException {
private static void cmdRun(String serial, String dnsServers, String routes, int port, String proxyExclusionList) throws IOException {
// start in parallel so that the relay server is ready when the client connects
asyncStart(serial, dnsServers, routes, port);
asyncStart(serial, dnsServers, routes, port, proxyExclusionList);

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// executed on Ctrl+C
Expand All @@ -247,10 +250,10 @@ private static void cmdRun(String serial, String dnsServers, String routes, int
cmdRelay(port);
}

private static void cmdAutorun(final String dnsServers, final String routes, int port) throws IOException {
private static void cmdAutorun(final String dnsServers, final String routes, int port, final String proxyExclusionList) throws IOException {
new Thread(() -> {
try {
cmdAutostart(dnsServers, routes, port);
cmdAutostart(dnsServers, routes, port, proxyExclusionList);
} catch (Exception e) {
Log.e(TAG, "Cannot auto start clients", e);
}
Expand All @@ -260,7 +263,7 @@ private static void cmdAutorun(final String dnsServers, final String routes, int
}

@SuppressWarnings("checkstyle:MagicNumber")
private static void cmdStart(String serial, String dnsServers, String routes, int port) throws InterruptedException, IOException,
private static void cmdStart(String serial, String dnsServers, String routes, int port, String proxyExclusionList) throws InterruptedException, IOException,
CommandExecutionException {
if (mustInstallClient(serial)) {
cmdInstall(serial);
Expand All @@ -280,12 +283,15 @@ private static void cmdStart(String serial, String dnsServers, String routes, in
if (routes != null) {
Collections.addAll(cmd, "--esa", "routes", routes);
}
if (proxyExclusionList != null) {
Collections.addAll(cmd, "--esa", "proxyExclusionList", proxyExclusionList);
}
execAdb(serial, cmd);
}

private static void cmdAutostart(final String dnsServers, final String routes, int port) {
private static void cmdAutostart(final String dnsServers, final String routes, int port, final String proxyExclusionList) {
AdbMonitor adbMonitor = new AdbMonitor((serial) -> {
asyncStart(serial, dnsServers, routes, port);
asyncStart(serial, dnsServers, routes, port, proxyExclusionList);
});
adbMonitor.monitor();
}
Expand All @@ -296,10 +302,10 @@ private static void cmdStop(String serial) throws InterruptedException, IOExcept
"com.genymobile.gnirehtet/.GnirehtetActivity");
}

private static void cmdRestart(String serial, String dnsServers, String routes, int port) throws InterruptedException, IOException,
private static void cmdRestart(String serial, String dnsServers, String routes, int port, String proxyExclusionList) throws InterruptedException, IOException,
CommandExecutionException {
cmdStop(serial);
cmdStart(serial, dnsServers, routes, port);
cmdStart(serial, dnsServers, routes, port, proxyExclusionList);
}

private static void cmdTunnel(String serial, int port) throws InterruptedException, IOException, CommandExecutionException {
Expand All @@ -311,10 +317,10 @@ private static void cmdRelay(int port) throws IOException {
new Relay(port).run();
}

private static void asyncStart(String serial, String dnsServers, String routes, int port) {
private static void asyncStart(String serial, String dnsServers, String routes, int port, String proxyExclusionList) {
new Thread(() -> {
try {
cmdStart(serial, dnsServers, routes, port);
cmdStart(serial, dnsServers, routes, port, proxyExclusionList);
} catch (Exception e) {
Log.e(TAG, "Cannot start client", e);
}
Expand Down Expand Up @@ -412,6 +418,9 @@ private static void appendCommandUsage(StringBuilder builder, Command command) {
if ((command.acceptedParameters & CommandLineArguments.PARAM_ROUTES) != 0) {
builder.append(" [-r ROUTE[,ROUTE2,...]]");
}
if ((command.acceptedParameters & CommandLineArguments.PARAM_PROXY_EXCLUSION_LIST) != 0) {
builder.append(" [-x EXCLUDE[,EXCLUDE2,...]]");
}
builder.append(NL);
String[] descLines = command.getDescription().split("\n");
for (String descLine : descLines) {
Expand Down