Index: src/org/torproject/android/service/TorService.java =================================================================== --- src/org/torproject/android/service/TorService.java (revision 24697) +++ src/org/torproject/android/service/TorService.java (working copy) @@ -710,10 +710,36 @@ if (enableTransparentProxy) { - showAlert("Status", "Setting up transparent proxying..."); - - //TorTransProxy.setDNSProxying(); - int code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this),transProxyAll); + //TODO: Find a nice place for the next (commented) line + //TorTransProxy.setDNSProxying(); + + int code = 0; // Default state is "okay" + + if(transProxyPortFallback) + { + showAlert("Status", "Setting up port-based transparent proxying..."); + StringTokenizer st = new StringTokenizer(portProxyList, ","); + int status = code; + while (st.hasMoreTokens()) + { + status = TorTransProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken())); + if(status != 0) + code = status; + } + } + else + { + if(transProxyAll) + { + showAlert("Status", "Setting up full transparent proxying..."); + code = TorTransProxy.setTransparentProxyingAll(this); + } + else + { + showAlert("Status", "Setting up app-based transparent proxying..."); + code = TorTransProxy.setTransparentProxyingByApp(this,AppManager.getApps(this),transProxyAll); + } + } TorService.logMessage ("TorTransProxy resp code: " + code); @@ -725,17 +751,7 @@ { showAlert("Status", "WARNING: error starting transparent proxying!"); } - - //this is for Androids w/o owner module support as a circumvention only fallback - if (transProxyPortFallback) - { - StringTokenizer st = new StringTokenizer(portProxyList, ","); - - while (st.hasMoreTokens()) - TorTransProxy.setTransparentProxyingByPort(this, Integer.parseInt(st.nextToken())); - - } - + return true; } Index: src/org/torproject/android/service/TorTransProxy.java =================================================================== --- src/org/torproject/android/service/TorTransProxy.java (revision 24697) +++ src/org/torproject/android/service/TorTransProxy.java (working copy) @@ -136,8 +136,6 @@ //redirectDNSResolvConf(); //not working yet String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath(); - - boolean ipTablesOld = false; StringBuilder script = new StringBuilder(); @@ -145,14 +143,12 @@ int code = -1; purgeIptables(context); - - script = new StringBuilder(); - + //build up array of shell cmds to execute under one root context for (int i = 0; i < apps.length; i++) { - if (forceAll || apps[i].isTorified()) //if "Tor Everything" on or app is set to true + if (apps[i].isTorified()) //if app is set to true { if (apps[i].getUsername().equals(TorServiceConstants.TOR_APP_USERNAME)) @@ -170,14 +166,8 @@ script.append(" -m owner --uid-owner "); script.append(apps[i].getUid()); script.append(" -m tcp --syn"); - - if (ipTablesOld) - script.append(" -j DNAT --to 127.0.0.1:"); - else - script.append(" -j REDIRECT --to-ports "); - + script.append(" -j REDIRECT --to-ports "); script.append(TOR_TRANSPROXY_PORT); - script.append(" || exit\n"); //DNS @@ -187,57 +177,37 @@ script.append(apps[i].getUid()); script.append(" -m udp --dport "); script.append(STANDARD_DNS_PORT); + script.append(" -j REDIRECT --to-ports "); + script.append(TOR_DNS_PORT); + script.append(" || exit\n"); - if (ipTablesOld) - script.append(" -j DNAT --to 127.0.0.1:"); - else - script.append(" -j REDIRECT --to-ports "); + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT -p tcp"); + script.append(" -m owner --uid-owner "); + script.append(apps[i].getUid()); + script.append(" -m tcp --dport "); + script.append(TOR_TRANSPROXY_PORT); + script.append(" -j ACCEPT"); + script.append(" || exit\n"); + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT -p udp"); + script.append(" -m owner --uid-owner "); + script.append(apps[i].getUid()); + script.append(" -m udp --dport "); script.append(TOR_DNS_PORT); - + script.append(" -j ACCEPT"); script.append(" || exit\n"); + + script.append(ipTablesPath); + script.append(" -t filter -A OUTPUT -m owner --uid-owner "); + script.append(apps[i].getUid()); + script.append(" -j DROP"); //drop all other packets as Tor won't handle them + script.append(" || exit\n"); - if (ipTablesOld) //for some reason this doesn't work on iptables 1.3.7 - { - script.append(ipTablesPath); - script.append(" -t nat"); - script.append(" -A OUTPUT -m owner --uid-owner "); - script.append(apps[i].getUid()); - script.append(" -j DROP"); - script.append(" || exit\n"); - } - else - { - script.append(ipTablesPath); - script.append(" -t filter"); - script.append(" -A OUTPUT -p tcp"); - script.append(" -m owner --uid-owner "); - script.append(apps[i].getUid()); - script.append(" -m tcp --dport "); - script.append(TOR_TRANSPROXY_PORT); - script.append(" -j ACCEPT"); - script.append(" || exit\n"); - - script.append(ipTablesPath); - script.append(" -t filter"); - script.append(" -A OUTPUT -p udp"); - script.append(" -m owner --uid-owner "); - script.append(apps[i].getUid()); - script.append(" -m udp --dport "); - script.append(TOR_DNS_PORT); - script.append(" -j ACCEPT"); - script.append(" || exit\n"); - - script.append(ipTablesPath); - script.append(" -t filter -A OUTPUT -m owner --uid-owner "); - script.append(apps[i].getUid()); - script.append(" -j DROP"); //drop all other packets as Tor won't handle them - script.append(" || exit\n"); - - } - - } } @@ -260,20 +230,13 @@ //String baseDir = context.getDir("bin",0).getAbsolutePath() + '/'; String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath(); - - boolean ipTablesOld = false; StringBuilder script = new StringBuilder(); StringBuilder res = new StringBuilder(); int code = -1; - - String[] cmdFlush = {script.toString()}; - code = TorServiceUtils.doShellCommand(cmdFlush, res, true, true); - //String msg = res.toString(); //get stdout from command + purgeIptables(context); - script = new StringBuilder(); - //TCP //iptables -t nat -A PREROUTING -i eth0 -p tcp --dport $srcPortNumber -j REDIRECT --to-port $dstPortNumbe @@ -283,14 +246,8 @@ script.append(" --dport "); script.append(port); //script.append(" -m tcp --syn"); - - if (ipTablesOld) - script.append(" -j DNAT --to 127.0.0.1:"); - else - script.append(" -j REDIRECT --to-ports "); - + script.append(" -j REDIRECT --to-ports "); script.append(TOR_TRANSPROXY_PORT); - script.append(" || exit\n"); script.append(ipTablesPath); @@ -298,14 +255,8 @@ script.append(" -A OUTPUT -p udp"); script.append(" --dport "); script.append(port); - - if (ipTablesOld) - script.append(" -j DNAT --to 127.0.0.1:"); - else - script.append(" -j REDIRECT --to-ports "); - + script.append(" -j REDIRECT --to-ports "); script.append(TOR_TRANSPROXY_PORT); - script.append(" || exit\n"); //DNS @@ -314,24 +265,134 @@ script.append(" -A OUTPUT -p udp "); script.append(" -m udp --dport "); script.append(STANDARD_DNS_PORT); + script.append(" -j REDIRECT --to-ports "); + script.append(TOR_DNS_PORT); + script.append(" || exit\n"); - if (ipTablesOld) - script.append(" -j DNAT --to 127.0.0.1:"); - else - script.append(" -j REDIRECT --to-ports "); + + String[] cmdAdd = {script.toString()}; + code = TorServiceUtils.doShellCommand(cmdAdd, res, true, true); + String msg = res.toString(); + TorService.logMessage(cmdAdd[0] + ";errCode=" + code + ";resp=" + msg); + return code; + } + + public static int setTransparentProxyingAll(Context context) throws Exception { + boolean runRoot = true; + boolean waitFor = true; + + //android.os.Debug.waitForDebugger(); + + //redirectDNSResolvConf(); //not working yet + + String ipTablesPath = new File(context.getDir("bin", 0),"iptables").getAbsolutePath(); + + StringBuilder script = new StringBuilder(); + + StringBuilder res = new StringBuilder(); + int code = -1; + + purgeIptables(context); + + int torUid = context.getApplicationInfo().uid; + + // Set up port redirection + script.append(ipTablesPath); + script.append(" -t nat"); + script.append(" -A OUTPUT -p tcp"); + script.append(" -m owner ! --uid-owner "); + script.append(torUid); + script.append(" -m tcp --syn"); + script.append(" -j REDIRECT --to-ports "); + script.append(TOR_TRANSPROXY_PORT); + script.append(" || exit\n"); + + // Same for DNS + script.append(ipTablesPath); + script.append(" -t nat"); + script.append(" -A OUTPUT -p udp -m owner ! --uid-owner "); + script.append(torUid); + script.append(" -m udp --dport "); + script.append(STANDARD_DNS_PORT); + script.append(" -j REDIRECT --to-ports "); script.append(TOR_DNS_PORT); + script.append(" || exit\n"); + // Allow packets to localhost (contains all the port-redirected ones) + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -p tcp"); + script.append(" -d 127.0.0.1"); + script.append(" -j ACCEPT"); script.append(" || exit\n"); + // Allow loopback + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -p tcp"); + script.append(" -o lo"); + script.append(" -j ACCEPT"); + script.append(" || exit\n"); + + // Allow everything for Tor + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -m owner --uid-owner "); + script.append(torUid); + script.append(" -j ACCEPT"); + script.append(" || exit\n"); + + //XXX: Comment the following rules for non-debug builds + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -p udp"); + script.append(" --dport "); + script.append(STANDARD_DNS_PORT); + script.append(" -j LOG"); + script.append(" --log-prefix='ORBOT_DNSLEAK_PROTECTION'"); + script.append(" --log-uid"); + script.append(" || exit\n"); + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -p tcp"); + script.append(" -j LOG"); + script.append(" --log-prefix='ORBOT_TCPLEAK_PROTECTION'"); + script.append(" --log-uid"); + script.append(" || exit\n"); + + + // Reject DNS that is not from Tor (order is important - first matched rule counts!) + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -p udp"); + script.append(" --dport "); + script.append(STANDARD_DNS_PORT); + script.append(" -j REJECT"); + script.append(" || exit\n"); + + // Reject all other outbound TCP packets + script.append(ipTablesPath); + script.append(" -t filter"); + script.append(" -A OUTPUT"); + script.append(" -p tcp"); + script.append(" -j REJECT"); + script.append(" || exit\n"); + + String[] cmdAdd = {script.toString()}; - String[] cmdAdd = {script.toString()}; - code = TorServiceUtils.doShellCommand(cmdAdd, res, true, true); + code = TorServiceUtils.doShellCommand(cmdAdd, res, runRoot, waitFor); String msg = res.toString(); TorService.logMessage(cmdAdd[0] + ";errCode=" + code + ";resp=" + msg); - return code; - } + return code; + } }