fixes for transproxy/iptables rules

- not all rules were not being cleared in flush
- per-app transproxy now still transproxies DNS for full device (not all DNS is done under the app UID)
- root shell now created only once and shared across calls
This commit is contained in:
Nathan Freitas 2014-09-14 16:07:18 -04:00
parent ee10ac0f07
commit 08317a94d7
2 changed files with 71 additions and 90 deletions

View File

@ -76,7 +76,6 @@ import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.app.NotificationCompat.Builder;
import android.util.Log; import android.util.Log;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import android.widget.Toast;
public class TorService extends Service implements TorServiceConstants, TorConstants, EventHandler public class TorService extends Service implements TorServiceConstants, TorConstants, EventHandler
{ {
@ -420,7 +419,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
mCurrentStatus = STATUS_OFF; mCurrentStatus = STATUS_OFF;
if (mHasRoot && mEnableTransparentProxy) if (mHasRoot && mEnableTransparentProxy)
disableTransparentProxy(); disableTransparentProxy(Shell.startRootShell());
clearNotifications(); clearNotifications();
@ -762,8 +761,12 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (mHasRoot && mEnableTransparentProxy) if (mHasRoot && mEnableTransparentProxy)
{ {
disableTransparentProxy(); Shell shell = Shell.startRootShell();
enableTransparentProxy();
disableTransparentProxy(shell);
enableTransparentProxy(shell);
shell.close();
} }
getHiddenServiceHostname (); getHiddenServiceHostname ();
@ -802,7 +805,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
* *
* the idea is that if Tor is off then transproxy is off * the idea is that if Tor is off then transproxy is off
*/ */
private boolean enableTransparentProxy () throws Exception private boolean enableTransparentProxy (Shell shell) throws Exception
{ {
if (mTransProxy == null) if (mTransProxy == null)
@ -824,39 +827,21 @@ public class TorService extends Service implements TorServiceConstants, TorConst
mTransProxy.setTransProxyPort(Integer.parseInt(transProxy)); mTransProxy.setTransProxyPort(Integer.parseInt(transProxy));
mTransProxy.setDNSPort(Integer.parseInt(dnsPort)); mTransProxy.setDNSPort(Integer.parseInt(dnsPort));
//TODO: Find a nice place for the next (commented) line
//TorTransProxy.setDNSProxying();
int code = 0; // Default state is "okay" int code = 0; // Default state is "okay"
debug ("Transparent Proxying: clearing existing rules...");
//clear rules first
// mTransProxy.clearTransparentProxyingAll(this);
if(mTransProxyAll) if(mTransProxyAll)
{ {
// showToolbarNotification(getString(R.string.setting_up_full_transparent_proxying_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
//clear existing rules code = mTransProxy.setTransparentProxyingAll(this, true, shell);
//code = mTransProxy.setTransparentProxyingAll(this, false);
code = mTransProxy.setTransparentProxyingAll(this, true);
} }
else else
{ {
//showToolbarNotification(getString(R.string.setting_up_app_based_transparent_proxying_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
ArrayList<TorifiedApp> apps = AppManager.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext())); ArrayList<TorifiedApp> apps = AppManager.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext()));
//clear exiting rules
//code = mTransProxy.setTransparentProxyingByApp(this,apps, false);
code = mTransProxy.setTransparentProxyingByApp(this,apps, true); code = mTransProxy.setTransparentProxyingByApp(this,apps, true, shell);
} }
debug ("TorTransProxy resp code: " + code); debug ("TorTransProxy resp code: " + code);
if (code == 0) if (code == 0)
@ -866,7 +851,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
{ {
showToolbarNotification(getString(R.string.transproxy_enabled_for_tethering_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor); showToolbarNotification(getString(R.string.transproxy_enabled_for_tethering_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor);
mTransProxy.enableTetheringRules(this); mTransProxy.enableTetheringRules(this, Shell.startRootShell());
} }
else else
@ -890,7 +875,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst
* *
* the idea is that if Tor is off then transproxy is off * the idea is that if Tor is off then transproxy is off
*/ */
private boolean disableTransparentProxy () throws Exception private boolean disableTransparentProxy (Shell shell) throws Exception
{ {
debug ("Transparent Proxying: disabling..."); debug ("Transparent Proxying: disabling...");
@ -898,9 +883,9 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (mTransProxy == null) if (mTransProxy == null)
mTransProxy = new TorTransProxy(this, fileXtables); mTransProxy = new TorTransProxy(this, fileXtables);
mTransProxy.setTransparentProxyingAll(this, false); mTransProxy.setTransparentProxyingAll(this, false, shell);
ArrayList<TorifiedApp> apps = AppManager.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext())); ArrayList<TorifiedApp> apps = AppManager.getApps(this, TorServiceUtils.getSharedPrefs(getApplicationContext()));
mTransProxy.setTransparentProxyingByApp(this, apps, false); mTransProxy.setTransparentProxyingByApp(this, apps, false, shell);
return true; return true;
} }
@ -1735,14 +1720,15 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (mHasRoot) if (mHasRoot)
{ {
if (hadEnableTransparentProxy) Shell shell = Shell.startRootShell();
disableTransparentProxy();
if (mEnableTransparentProxy) if (hadEnableTransparentProxy)
{ disableTransparentProxy(shell);
disableTransparentProxy();
enableTransparentProxy(); if (mEnableTransparentProxy)
} enableTransparentProxy(shell);
shell.close();
} }
@ -2056,8 +2042,13 @@ public class TorService extends Service implements TorServiceConstants, TorConst
if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh) if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh)
{ {
disableTransparentProxy();
enableTransparentProxy(); Shell shell = Shell.startRootShell();
disableTransparentProxy(shell);
enableTransparentProxy(shell);
shell.close();
} }
} }

View File

@ -21,7 +21,7 @@ public class TorTransProxy implements TorServiceConstants {
private TorService mTorService = null; private TorService mTorService = null;
private File mFileXtables = null; private File mFileXtables = null;
private final static String ALLOW_LOCAL = " ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 "; private final static String ALLOW_LOCAL = " ! -d 127.0.0.1";
private int mTransProxyPort = TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT; private int mTransProxyPort = TorServiceConstants.TOR_TRANSPROXY_PORT_DEFAULT;
private int mDNSPort = TorServiceConstants.TOR_DNS_PORT_DEFAULT; private int mDNSPort = TorServiceConstants.TOR_DNS_PORT_DEFAULT;
@ -335,7 +335,7 @@ public class TorTransProxy implements TorServiceConstants {
return code; return code;
}*/ }*/
public int setTransparentProxyingByApp(Context context, ArrayList<TorifiedApp> apps, boolean enableRule) throws Exception public int setTransparentProxyingByApp(Context context, ArrayList<TorifiedApp> apps, boolean enableRule, Shell shell) throws Exception
{ {
String ipTablesPath = getIpTablesPath(context); String ipTablesPath = getIpTablesPath(context);
@ -353,30 +353,45 @@ public class TorTransProxy implements TorServiceConstants {
//reset script //reset script
Shell shell = Shell.startRootShell();
int lastExit = -1; int lastExit = -1;
StringBuilder script; StringBuilder script;
// Same for DNS
script = new StringBuilder();
script.append(ipTablesPath);
script.append(" -t nat");
script.append(action).append(srcChainName);
script.append(" -p udp");
//script.append(" -m owner --uid-owner ");
//script.append(tApp.getUid());
//script.append(" -m udp --dport ");
script.append(" --dport ");
script.append(STANDARD_DNS_PORT);
script.append(" -j REDIRECT --to-ports ");
script.append(mDNSPort);
executeCommand (shell, script.toString());
// Allow everything for Tor // Allow everything for Tor
//build up array of shell cmds to execute under one root context //build up array of shell cmds to execute under one root context
for (TorifiedApp tApp:apps) for (TorifiedApp tApp:apps)
{ {
if (tApp.isTorified() if (((!enableRule) || tApp.isTorified())
&& (!tApp.getUsername().equals(TorServiceConstants.TOR_APP_USERNAME)) && (!tApp.getUsername().equals(TorServiceConstants.TOR_APP_USERNAME))
) //if app is set to true ) //if app is set to true
{ {
logMessage("enabling transproxy for app: " + tApp.getUsername() + " (" + tApp.getUid() + ")"); logMessage("transproxy for app: " + tApp.getUsername() + " (" + tApp.getUid() + "): enable=" + enableRule);
dropAllIPv6Traffic(context, tApp.getUid(),enableRule); dropAllIPv6Traffic(context, tApp.getUid(),enableRule, shell);
script = new StringBuilder(); script = new StringBuilder();
// Allow loopback // Allow loopback
/**
script.append(ipTablesPath); script.append(ipTablesPath);
script.append(" -t filter"); script.append(" -t filter");
script.append(action).append(srcChainName); script.append(action).append(srcChainName);
@ -387,6 +402,7 @@ public class TorTransProxy implements TorServiceConstants {
executeCommand (shell, script.toString()); executeCommand (shell, script.toString());
script = new StringBuilder(); script = new StringBuilder();
**/
// Set up port redirection // Set up port redirection
script.append(ipTablesPath); script.append(ipTablesPath);
@ -401,21 +417,8 @@ public class TorTransProxy implements TorServiceConstants {
script.append(mTransProxyPort); script.append(mTransProxyPort);
executeCommand (shell, script.toString()); executeCommand (shell, script.toString());
script = new StringBuilder();
// Same for DNS
script.append(ipTablesPath);
script.append(" -t nat");
script.append(action).append(srcChainName);
script.append(" -p udp");
script.append(" -m owner --uid-owner ");
script.append(tApp.getUid());
script.append(" -m udp --dport ");
script.append(STANDARD_DNS_PORT);
script.append(" -j REDIRECT --to-ports ");
script.append(mDNSPort);
executeCommand (shell, script.toString());
script = new StringBuilder(); script = new StringBuilder();
// Reject all other outbound packets // Reject all other outbound packets
@ -433,14 +436,12 @@ public class TorTransProxy implements TorServiceConstants {
} }
} }
shell.close();
return lastExit; return lastExit;
} }
private int executeCommand (Shell shell, String cmdString) throws IOException, TimeoutException private int executeCommand (Shell shell, String cmdString) throws IOException, TimeoutException
{ {
SimpleCommand cmd = new SimpleCommand(cmdString + "|| exit"); SimpleCommand cmd = new SimpleCommand(cmdString);
shell.add(cmd); shell.add(cmd);
int exitCode = cmd.getExitCode(); int exitCode = cmd.getExitCode();
String output = cmd.getOutput(); String output = cmd.getOutput();
@ -451,7 +452,7 @@ public class TorTransProxy implements TorServiceConstants {
} }
public int enableTetheringRules (Context context) throws Exception public int enableTetheringRules (Context context, Shell shell) throws Exception
{ {
String ipTablesPath = getIpTablesPath(context); String ipTablesPath = getIpTablesPath(context);
@ -460,7 +461,6 @@ public class TorTransProxy implements TorServiceConstants {
String[] hwinterfaces = {"usb0","wl0.1"}; String[] hwinterfaces = {"usb0","wl0.1"};
Shell shell = Shell.startRootShell();
int lastExit = -1; int lastExit = -1;
@ -492,8 +492,6 @@ public class TorTransProxy implements TorServiceConstants {
} }
shell.close();
return lastExit; return lastExit;
} }
@ -505,12 +503,10 @@ public class TorTransProxy implements TorServiceConstants {
public int fixTransproxyLeak (Context context) throws Exception public int fixTransproxyLeak (Context context, Shell shell) throws Exception
{ {
String ipTablesPath = getIpTablesPath(context); String ipTablesPath = getIpTablesPath(context);
Shell shell = Shell.startRootShell();
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
script.append(ipTablesPath); script.append(ipTablesPath);
script.append(" -I OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,FIN ACK,FIN -j DROP"); script.append(" -I OUTPUT ! -o lo ! -d 127.0.0.1 ! -s 127.0.0.1 -p tcp -m tcp --tcp-flags ACK,FIN ACK,FIN -j DROP");
@ -525,13 +521,11 @@ public class TorTransProxy implements TorServiceConstants {
int lastExit = executeCommand (shell, script.toString()); int lastExit = executeCommand (shell, script.toString());
script = new StringBuilder(); script = new StringBuilder();
shell.close();
return lastExit; return lastExit;
} }
public int dropAllIPv6Traffic (Context context, int appUid, boolean enableDrop) throws Exception public int dropAllIPv6Traffic (Context context, int appUid, boolean enableDrop, Shell shell) throws Exception
{ {
String action = " -A "; String action = " -A ";
@ -541,9 +535,7 @@ public class TorTransProxy implements TorServiceConstants {
action = " -D "; action = " -D ";
String ip6tablesPath = getIp6TablesPath(context); String ip6tablesPath = getIp6TablesPath(context);
Shell shell = Shell.startRootShell();
StringBuilder script; StringBuilder script;
script = new StringBuilder(); script = new StringBuilder();
@ -561,8 +553,6 @@ public class TorTransProxy implements TorServiceConstants {
int lastExit = executeCommand (shell, script.toString()); int lastExit = executeCommand (shell, script.toString());
shell.close();
return lastExit; return lastExit;
} }
@ -589,27 +579,29 @@ public class TorTransProxy implements TorServiceConstants {
public int flushTransproxyRules (Context context) throws Exception public int flushTransproxyRules (Context context) throws Exception
{ {
int exit = -1; int exit = -1;
String ipTablesPath = getIpTablesPath(context); String ipTablesPath = getIpTablesPath(context);
Shell shell = Shell.startRootShell();
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
script.append(ipTablesPath); script.append(ipTablesPath);
script.append(" -t nat"); script.append(" -t nat ");
script.append(" -F "); script.append(" -F ");
Shell shell = Shell.startRootShell(); executeCommand (shell, script.toString());
executeCommand (shell, script.toString());
script = new StringBuilder(); script = new StringBuilder();
script.append(ipTablesPath); script.append(ipTablesPath);
script.append(" -t filter"); script.append(" -t filter ");
script.append(" -F "); script.append(" -F ");
executeCommand (shell, script.toString());
dropAllIPv6Traffic(context,-1,false); dropAllIPv6Traffic(context,-1,false, shell);
return exit; return exit;
} }
public int setTransparentProxyingAll(Context context, boolean enable) throws Exception public int setTransparentProxyingAll(Context context, boolean enable, Shell shell) throws Exception
{ {
String action = " -A "; String action = " -A ";
@ -617,12 +609,11 @@ public class TorTransProxy implements TorServiceConstants {
if (!enable) if (!enable)
action = " -D "; action = " -D ";
dropAllIPv6Traffic(context,-1,enable); dropAllIPv6Traffic(context,-1,enable, shell);
String ipTablesPath = getIpTablesPath(context); String ipTablesPath = getIpTablesPath(context);
Shell shell = Shell.startRootShell();
int torUid = context.getApplicationInfo().uid; int torUid = context.getApplicationInfo().uid;
@ -674,7 +665,8 @@ public class TorTransProxy implements TorServiceConstants {
script.append(ALLOW_LOCAL); //allow access to localhost script.append(ALLOW_LOCAL); //allow access to localhost
script.append(" -m owner ! --uid-owner "); script.append(" -m owner ! --uid-owner ");
script.append(torUid); script.append(torUid);
script.append(" -m udp --dport "); //script.append(" -m udp --dport ");
script.append(" --dport ");
script.append(STANDARD_DNS_PORT); script.append(STANDARD_DNS_PORT);
script.append(" -j REDIRECT --to-ports "); script.append(" -j REDIRECT --to-ports ");
script.append(mDNSPort); script.append(mDNSPort);
@ -773,8 +765,6 @@ public class TorTransProxy implements TorServiceConstants {
// fixTransproxyLeak (context); // fixTransproxyLeak (context);
shell.close();
return lastExit; return lastExit;
} }