update to service with new transproxy/iptables code

svn:r24627
This commit is contained in:
Nathan Freitas 2011-04-15 16:37:33 +00:00
parent 03f492fc14
commit 2e67857785
5 changed files with 172 additions and 145 deletions

View File

@ -12,18 +12,23 @@ import java.io.InputStream;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import org.torproject.android.R;
import android.content.Context;
import android.util.Log; import android.util.Log;
public class TorBinaryInstaller implements TorServiceConstants { public class TorBinaryInstaller implements TorServiceConstants {
String installPath = null; String installPath;
String apkPath = null; String apkPath;
Context context;
public TorBinaryInstaller (String installPath, String apkPath) public TorBinaryInstaller (Context context, String installPath, String apkPath)
{ {
this.installPath = installPath; this.installPath = installPath;
this.apkPath = apkPath; this.apkPath = apkPath;
this.context = context;
} }
/* /*
@ -39,10 +44,39 @@ public class TorBinaryInstaller implements TorServiceConstants {
Log.d(TAG,"Privoxy binary exists=" + privoxyBinaryExists); Log.d(TAG,"Privoxy binary exists=" + privoxyBinaryExists);
if (!(torBinaryExists && privoxyBinaryExists) || force) if (!(torBinaryExists && privoxyBinaryExists) || force)
installFromZip (); installFromRaw ();
} }
//
/*
* Extract the Tor binary from the APK file using ZIP
*/
private void installFromRaw ()
{
InputStream is = context.getResources().openRawResource(R.raw.tor);
streamToFile(is,installPath + TOR_BINARY_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.torrc);
streamToFile(is,installPath + TORRC_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.privoxy);
streamToFile(is,installPath + PRIVOXY_ASSET_KEY);
is = context.getResources().openRawResource(R.raw.privoxy_config);
streamToFile(is,installPath + PRIVOXYCONFIG_ASSET_KEY);
Log.d(TAG,"SUCCESS: installed tor, privoxy binaries from raw");
}
/* /*
* Extract the Tor binary from the APK file using ZIP * Extract the Tor binary from the APK file using ZIP
*/ */

View File

@ -52,11 +52,15 @@ public class TorService extends Service implements TorServiceConstants, Runnable
private static final int MAX_START_TRIES = 3; private static final int MAX_START_TRIES = 3;
private ArrayList<String> configBuffer = null; private ArrayList<String> configBuffer = null;
private ArrayList<String> resetBuffer = null;
private String appHome = "/data/data/" + TOR_APP_USERNAME + "/";; private String appHome;
private String torBinaryPath = appHome + TOR_BINARY_ASSET_KEY; private String appBinHome;
private String privoxyPath = appHome + PRIVOXY_ASSET_KEY; private String appDataHome;
private String torBinaryPath;
private String privoxyPath;
private boolean hasRoot = false; private boolean hasRoot = false;
@ -323,7 +327,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" }; String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" };
TorServiceUtils.doShellCommand(cmd,log, false, false); TorServiceUtils.doShellCommand(cmd,log, false, false);
try { Thread.sleep(500); }
catch (Exception e){}
} }
while ((procId = TorServiceUtils.findProcessId(privoxyPath)) != -1) while ((procId = TorServiceUtils.findProcessId(privoxyPath)) != -1)
@ -333,7 +338,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" }; String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" };
TorServiceUtils.doShellCommand(cmd,log, false, false); TorServiceUtils.doShellCommand(cmd,log, false, false);
try { Thread.sleep(500); }
catch (Exception e){}
} }
} }
@ -349,6 +355,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
} }
/*
private String findAPK () private String findAPK ()
{ {
@ -428,39 +435,29 @@ public class TorService extends Service implements TorServiceConstants, Runnable
return null; return null;
} }*/
private boolean checkTorBinaries () throws Exception private boolean checkTorBinaries () throws Exception
{ {
//android.os.Debug.waitForDebugger();
appHome = "/data/data/" + TOR_APP_USERNAME + "/"; //check and install iptables
//appHome = getApplicationContext().getFilesDir().getAbsolutePath(); Api.assertBinaries(this, true);
File fileInstall = getDir("",0);
String subBinPath = "bin/";
appHome = fileInstall.getAbsolutePath();
appBinHome = appHome + subBinPath;
appDataHome = getCacheDir().getAbsolutePath() + '/';
logNotice( "appHome=" + appHome); logNotice( "appHome=" + appHome);
torBinaryPath = appHome + TOR_BINARY_ASSET_KEY;
privoxyPath = appHome + PRIVOXY_ASSET_KEY; torBinaryPath = appBinHome + TOR_BINARY_ASSET_KEY;
privoxyPath = appBinHome + PRIVOXY_ASSET_KEY;
logNotice( "checking Tor binaries"); logNotice( "checking Tor binaries");
String apkPath = findAPK();
if (apkPath == null)
throw new Exception ("Unable to locate Orbot binary APK file");
logNotice( "found apk at: " + apkPath);
boolean apkExists = new File(apkPath).exists();
if (!apkExists)
{
Log.w(TAG,"APK file not found at: " + apkPath);
Log.w(TAG,"Binary installation aborted");
logNotice(getString(R.string.status_install_fail));
sendCallbackStatusMessage(getString(R.string.status_install_fail));
return false;
}
boolean torBinaryExists = new File(torBinaryPath).exists(); boolean torBinaryExists = new File(torBinaryPath).exists();
boolean privoxyBinaryExists = new File(privoxyPath).exists(); boolean privoxyBinaryExists = new File(privoxyPath).exists();
@ -468,7 +465,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
killTorProcess (); killTorProcess ();
TorBinaryInstaller installer = new TorBinaryInstaller(appHome, apkPath); TorBinaryInstaller installer = new TorBinaryInstaller(this, appBinHome, appBinHome);
installer.start(true); installer.start(true);
torBinaryExists = new File(torBinaryPath).exists(); torBinaryExists = new File(torBinaryPath).exists();
@ -552,12 +549,11 @@ public class TorService extends Service implements TorServiceConstants, Runnable
private void runTorShellCmd() throws Exception private void runTorShellCmd() throws Exception
{ {
StringBuilder log = new StringBuilder(); StringBuilder log = new StringBuilder();
String torrcPath = appHome + TORRC_ASSET_KEY; String torrcPath = appBinHome + TORRC_ASSET_KEY;
String[] torCmd = {torBinaryPath + " -f " + torrcPath + " || exit\n"}; String[] torCmd = {torBinaryPath + " DataDirectory " + appDataHome + " -f " + torrcPath + " || exit\n"};
boolean runAsRootFalse = false; boolean runAsRootFalse = false;
boolean waitForProcess = false; boolean waitForProcess = false;
@ -623,7 +619,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
log = new StringBuilder(); log = new StringBuilder();
String privoxyConfigPath = appHome + PRIVOXYCONFIG_ASSET_KEY; String privoxyConfigPath = appBinHome + PRIVOXYCONFIG_ASSET_KEY;
String[] cmds = String[] cmds =
{ privoxyPath + " " + privoxyConfigPath + " &" }; { privoxyPath + " " + privoxyConfigPath + " &" };
@ -680,27 +676,31 @@ public class TorService extends Service implements TorServiceConstants, Runnable
torConnSocket = new Socket(IP_LOCALHOST, TOR_CONTROL_PORT); torConnSocket = new Socket(IP_LOCALHOST, TOR_CONTROL_PORT);
conn = TorControlConnection.getConnection(torConnSocket); conn = TorControlConnection.getConnection(torConnSocket);
// conn.authenticate(new byte[0]); // See section 3.2 // conn.authenticate(new byte[0]); // See section 3.2
sendCallbackStatusMessage(getString(R.string.tor_process_connecting_step2)); sendCallbackStatusMessage(getString(R.string.tor_process_connecting_step2));
logNotice( "SUCCESS connected to control port"); logNotice( "SUCCESS connected to control port");
String torAuthCookie = appHome + "data/control_auth_cookie"; String torAuthCookie = appDataHome + TOR_CONTROL_COOKIE;
File fileCookie = new File(torAuthCookie); File fileCookie = new File(torAuthCookie);
byte[] cookie = new byte[(int)fileCookie.length()];
new FileInputStream(new File(torAuthCookie)).read(cookie);
conn.authenticate(cookie);
logNotice( "SUCCESS authenticated to control port");
sendCallbackStatusMessage(getString(R.string.tor_process_connecting_step2) + getString(R.string.tor_process_connecting_step3));
addEventHandler();
applyPreferences();
if (fileCookie.exists())
{
byte[] cookie = new byte[(int)fileCookie.length()];
new FileInputStream(new File(torAuthCookie)).read(cookie);
conn.authenticate(cookie);
logNotice( "SUCCESS authenticated to control port");
sendCallbackStatusMessage(getString(R.string.tor_process_connecting_step2) + getString(R.string.tor_process_connecting_step3));
addEventHandler();
applyPreferences();
}
break; //don't need to retry break; //don't need to retry
} }
@ -712,8 +712,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
sendCallbackStatusMessage(getString(R.string.tor_process_connecting_step4)); sendCallbackStatusMessage(getString(R.string.tor_process_connecting_step4));
Thread.sleep(1000); Thread.sleep(1000);
} }
} }
@ -1052,9 +1051,14 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
if (configBuffer == null) if (configBuffer == null)
configBuffer = new ArrayList<String>(); configBuffer = new ArrayList<String>();
if (resetBuffer == null)
resetBuffer = new ArrayList<String>();
if (value == null || value.length() == 0) if (value == null || value.length() == 0)
{ {
/*
if (conn != null) if (conn != null)
{ {
try { try {
@ -1063,6 +1067,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
Log.w(TAG, "Unable to reset conf",e); Log.w(TAG, "Unable to reset conf",e);
} }
} }
*/
resetBuffer.add(name);
} }
else else
configBuffer.add(name + ' ' + value); configBuffer.add(name + ' ' + value);
@ -1076,8 +1083,16 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{ {
if (conn != null) if (conn != null)
{ {
if (configBuffer != null) if (resetBuffer != null && resetBuffer.size() > 0)
{
conn.resetConf(resetBuffer);
resetBuffer = null;
}
if (configBuffer != null && configBuffer.size() > 0)
{ {
conn.setConf(configBuffer); conn.setConf(configBuffer);
configBuffer = null; configBuffer = null;
} }
@ -1378,14 +1393,14 @@ public class TorService extends Service implements TorServiceConstants, Runnable
} }
else else
{ {
TorTransProxy.purgeIptables(this,AppManager.getApps(this)); TorTransProxy.purgeIptables(this);
} }
} }
} }
else if (hasRoot) else if (hasRoot)
{ {
TorTransProxy.purgeIptables(this,AppManager.getApps(this)); TorTransProxy.purgeIptables(this);
} }
return true; return true;

View File

@ -19,7 +19,8 @@ public interface TorServiceConstants {
//torrc (tor config file) //torrc (tor config file)
public final static String TORRC_ASSET_KEY = "torrc"; public final static String TORRC_ASSET_KEY = "torrc";
public final static String TOR_CONTROL_COOKIE = "control_auth_cookie";
//how to launch tor //how to launch tor
// public final static String TOR_COMMAND_LINE_ARGS = "-f " + TORRC_INSTALL_PATH + " || exit\n"; // public final static String TOR_COMMAND_LINE_ARGS = "-f " + TORRC_INSTALL_PATH + " || exit\n";
@ -39,8 +40,8 @@ public interface TorServiceConstants {
public final static String CHMOD_EXE_VALUE = "777"; public final static String CHMOD_EXE_VALUE = "777";
//path of the installed APK file //path of the installed APK file
public final static String APK_PATH = "/data/app/org.torproject.android.apk"; //public final static String APK_PATH = "/data/app/org.torproject.android.apk";
public final static String APK_PATH_BASE = "/data/app"; //public final static String APK_PATH_BASE = "/data/app";

View File

@ -165,7 +165,6 @@ public class TorServiceUtils implements TorServiceConstants {
else else
proc = Runtime.getRuntime().exec("sh"); proc = Runtime.getRuntime().exec("sh");
OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream()); OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream());
for (int i = 0; i < cmds.length; i++) for (int i = 0; i < cmds.length; i++)
@ -181,8 +180,6 @@ public class TorServiceUtils implements TorServiceConstants {
if (waitFor) if (waitFor)
{ {
final char buf[] = new char[10]; final char buf[] = new char[10];
// Consume the "stdout" // Consume the "stdout"

View File

@ -1,5 +1,7 @@
package org.torproject.android.service; package org.torproject.android.service;
import java.io.File;
import org.torproject.android.TorifiedApp; import org.torproject.android.TorifiedApp;
import android.content.Context; import android.content.Context;
@ -21,6 +23,7 @@ public class TorTransProxy implements TorServiceConstants {
* Check if we have root access * Check if we have root access
* @return boolean true if we have root * @return boolean true if we have root
*/ */
/*
public static String getIPTablesVersion() { public static String getIPTablesVersion() {
@ -52,43 +55,42 @@ public class TorTransProxy implements TorServiceConstants {
logNotice("Could not acquire check iptables: " + log.toString()); logNotice("Could not acquire check iptables: " + log.toString());
return null; return null;
} }*/
public static int purgeIptables(Context context) throws Exception {
private static String findBaseDir ()
{ String ipTablesPath = new File(context.getDir("bin", 0),"iptables_n1").getAbsolutePath();
return ""; //just blank for now final StringBuilder script = new StringBuilder();
/*
String[] cmds = {"/system/bin/iptables -t nat --list"};
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
int code = -1;
int code; script.append(ipTablesPath);
try { script.append(" -t nat");
code = TorServiceUtils.doShellCommand(cmds, res, true, true); script.append(" -F || exit\n");
script.append(ipTablesPath);
script.append(" -t filter");
script.append(" -F || exit\n");
String[] cmd = {script.toString()};
code = TorServiceUtils.doShellCommand(cmd, res, true, true);
String msg = res.toString();
logNotice(cmd[0] + ";errCode=" + code + ";resp=" + msg);
if (code != 0) { return code;
return BASE_DIR;
}
else
return "/system/bin/";
} catch (Exception e) {
return BASE_DIR;
}
return "";
*/
} }
/*
public static int purgeIptables(Context context, TorifiedApp[] apps) throws Exception { public static int purgeIptablesByApp(Context context, TorifiedApp[] apps) throws Exception {
//restoreDNSResolvConf(); //not working yet //restoreDNSResolvConf(); //not working yet
String baseDir = findBaseDir(); String ipTablesPath = new File(context.getDir("bin", 0),"iptables_n1").getAbsolutePath();
final StringBuilder script = new StringBuilder(); final StringBuilder script = new StringBuilder();
@ -97,13 +99,14 @@ public class TorTransProxy implements TorServiceConstants {
for (int i = 0; i < apps.length; i++) for (int i = 0; i < apps.length; i++)
{ {
//flush nat for every app //flush nat for every app
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t nat -m owner --uid-owner "); script.append(" -t nat -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
script.append(" -F || exit\n"); script.append(" -F || exit\n");
script.append("iptables -t filter -m owner --uid-owner ");
script.append(ipTablesPath);
script.append(" -t filter -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
script.append(" -F || exit\n"); script.append(" -F || exit\n");
@ -118,7 +121,8 @@ public class TorTransProxy implements TorServiceConstants {
return code; return code;
} }*/
/* /*
// 9/19/2010 - NF This code is in process... /etc path on System partition // 9/19/2010 - NF This code is in process... /etc path on System partition
@ -171,38 +175,17 @@ public class TorTransProxy implements TorServiceConstants {
//redirectDNSResolvConf(); //not working yet //redirectDNSResolvConf(); //not working yet
String baseDir = findBaseDir(); //String baseDir = context.getDir("bin", 0).getAbsolutePath() + "/";
String ipTablesPath = new File(context.getDir("bin", 0),"iptables_n1").getAbsolutePath();
String iptablesVersion = getIPTablesVersion();
logNotice( "iptables version: " + iptablesVersion);
boolean ipTablesOld = false; boolean ipTablesOld = false;
if (iptablesVersion != null && iptablesVersion.startsWith("1.3")){
ipTablesOld = true;
}
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
int code = -1; int code = -1;
for (int i = 0; i < apps.length; i++) purgeIptables(context);
{
//flush nat for every app
script.append(baseDir);
script.append("iptables -t nat -m owner --uid-owner ");
script.append(apps[i].getUid());
script.append(" -F || exit\n");
script.append("iptables -t filter -m owner --uid-owner ");
script.append(apps[i].getUid());
script.append(" -F || exit\n");
}
String[] cmdFlush = {script.toString()};
code = TorServiceUtils.doShellCommand(cmdFlush, res, true, true);
//String msg = res.toString(); //get stdout from command
script = new StringBuilder(); script = new StringBuilder();
@ -231,8 +214,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
//iptables -t nat -A output -p tcp -m owner --uid-owner 100 -m tcp --sync -j REDIRECT --to-ports 9040 //iptables -t nat -A output -p tcp -m owner --uid-owner 100 -m tcp --sync -j REDIRECT --to-ports 9040
//TCP //TCP
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t nat"); script.append(" -t nat");
script.append(" -A OUTPUT -p tcp"); script.append(" -A OUTPUT -p tcp");
script.append(" -m owner --uid-owner "); script.append(" -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
@ -248,8 +231,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
script.append(" || exit\n"); script.append(" || exit\n");
//DNS //DNS
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t nat"); script.append(" -t nat");
script.append(" -A OUTPUT -p udp -m owner --uid-owner "); script.append(" -A OUTPUT -p udp -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
script.append(" -m udp --dport "); script.append(" -m udp --dport ");
@ -268,8 +251,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
//EVERYTHING ELSE - DROP! //EVERYTHING ELSE - DROP!
if (ipTablesOld) //for some reason this doesn't work on iptables 1.3.7 if (ipTablesOld) //for some reason this doesn't work on iptables 1.3.7
{ {
script.append(ipTablesPath);
script.append("iptables -t nat"); script.append(" -t nat");
script.append(" -A OUTPUT -m owner --uid-owner "); script.append(" -A OUTPUT -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
script.append(" -j DROP"); script.append(" -j DROP");
@ -277,8 +260,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
} }
else else
{ {
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t filter"); script.append(" -t filter");
script.append(" -A OUTPUT -p tcp"); script.append(" -A OUTPUT -p tcp");
script.append(" -m owner --uid-owner "); script.append(" -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
@ -287,8 +270,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
script.append(" -j ACCEPT"); script.append(" -j ACCEPT");
script.append(" || exit\n"); script.append(" || exit\n");
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t filter"); script.append(" -t filter");
script.append(" -A OUTPUT -p udp"); script.append(" -A OUTPUT -p udp");
script.append(" -m owner --uid-owner "); script.append(" -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
@ -297,8 +280,7 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
script.append(" -j ACCEPT"); script.append(" -j ACCEPT");
script.append(" || exit\n"); script.append(" || exit\n");
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables");
script.append(" -t filter -A OUTPUT -m owner --uid-owner "); script.append(" -t filter -A OUTPUT -m owner --uid-owner ");
script.append(apps[i].getUid()); script.append(apps[i].getUid());
script.append(" -j DROP"); //drop all other packets as Tor won't handle them script.append(" -j DROP"); //drop all other packets as Tor won't handle them
@ -307,6 +289,9 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
} }
} }
else
{
}
} }
@ -325,15 +310,10 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
//redirectDNSResolvConf(); //not working yet //redirectDNSResolvConf(); //not working yet
String baseDir = findBaseDir(); //String baseDir = context.getDir("bin",0).getAbsolutePath() + '/';
String ipTablesPath = new File(context.getDir("bin", 0),"iptables_n1").getAbsolutePath();
String iptablesVersion = getIPTablesVersion();
logNotice( "iptables version: " + iptablesVersion);
boolean ipTablesOld = false; boolean ipTablesOld = false;
if (iptablesVersion != null && iptablesVersion.startsWith("1.3")){
ipTablesOld = true;
}
StringBuilder script = new StringBuilder(); StringBuilder script = new StringBuilder();
@ -349,8 +329,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
//TCP //TCP
//iptables -t nat -A PREROUTING -i eth0 -p tcp --dport $srcPortNumber -j REDIRECT --to-port $dstPortNumbe //iptables -t nat -A PREROUTING -i eth0 -p tcp --dport $srcPortNumber -j REDIRECT --to-port $dstPortNumbe
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t nat"); script.append(" -t nat");
script.append(" -A OUTPUT -p tcp"); script.append(" -A OUTPUT -p tcp");
script.append(" --dport "); script.append(" --dport ");
script.append(port); script.append(port);
@ -365,8 +345,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
script.append(" || exit\n"); script.append(" || exit\n");
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t nat"); script.append(" -t nat");
script.append(" -A OUTPUT -p udp"); script.append(" -A OUTPUT -p udp");
script.append(" --dport "); script.append(" --dport ");
script.append(port); script.append(port);
@ -381,8 +361,8 @@ iptables -t nat -A OUTPUT -m owner --uid-owner anonymous -j DROP
script.append(" || exit\n"); script.append(" || exit\n");
//DNS //DNS
script.append(baseDir); script.append(ipTablesPath);
script.append("iptables -t nat"); script.append(" -t nat");
script.append(" -A OUTPUT -p udp "); script.append(" -A OUTPUT -p udp ");
script.append(" -m udp --dport "); script.append(" -m udp --dport ");
script.append(STANDARD_DNS_PORT); script.append(STANDARD_DNS_PORT);