/******************************************************************************* * gMix open source project - https://svs.informatik.uni-hamburg.de/gmix/ * Copyright (C) 2014 SVS * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. *******************************************************************************/ package staticContent.framework; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Random; import java.util.Vector; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.MissingOptionException; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import staticContent.framework.config.Settings; import staticContent.framework.controller.Controller; import staticContent.framework.controller.Layer1NetworkMixController; import staticContent.framework.controller.Layer2RecodingSchemeMixController; import staticContent.framework.controller.Layer3OutputStrategyMixController; import staticContent.framework.controller.Layer4TransportMixController; import staticContent.framework.controller.Layer5ApplicationMixController; import staticContent.framework.launcher.CommandLineParameters; import userGeneratedContent.testbedPlugIns.layerPlugIns.layer2recodingScheme.encDNS_v0_001.EncDNSHelper; /** * This is the EncDNS server proxy (also known as remote proxy). It should be * executed on the same computer as the remote recursive nameserver or at least * be connected to it via a trustworthy connection. The server proxy will * decrypt encrypted EncDNS queries it receives and pass the decrypted * standard DNS query on to the remote recursive nameserver. It will also * encrypt the standard DNS responses received from the remote recursive * nameserver and pass the EncDNS response on to the local recursive nameserver. * * Note: don't use anonnode.java as we dont need the info service etc (encDns * is a single node system) */ public class EncDnsServer { private Settings settings; public static CommandLineParameters commandLineParameters; // references to controllers protected Layer1NetworkMixController networkLayerMix; protected Layer2RecodingSchemeMixController recodingLayerMix; protected Layer3OutputStrategyMixController outputStrategyLayerMix; protected Layer4TransportMixController transportLayerMix; protected Layer5ApplicationMixController applicationLayerMix; private Vector<Controller> components = new Vector<Controller>(); // instantiated controllers private static Options _opt; public static InetAddress bindAddress; public static int bindPort; public static String zoneurl; public static InetAddress nsaddr; public static int port; public static int cachesize; public static int timeout; public static int maxThreads; public static String pkPath; public static String skPath; public static boolean encryption; public static int verbosity; public static boolean displayThreadStatusBool; public static int displayThreadStatusInt; public static boolean displayThroughputBool; public static boolean useInternalResolver; public static boolean resolveToLocalhost; /** maximum size of an EncDNS message */ public static final int MAX_MSG_SIZE = 65535; // = maximum DNS msg length public static Random rnd = new SecureRandom(); /** * Creates a new instance of EncDNSServerProxy.new file * @param zoneurl EncDNS zone name (The IP this proxy is listening on must be listed as an authoritative nameserver IP for this zone in the parent zone) * @param nsaddr remote recursive nameserver's address * @param port remote recursive nameserver's port * @param cachesize size of cache for intermediate shared secrets * @param pkPath path to public key file * @param skPath path to secret key file * @param noEncryption If true, disables encryption. If false, encryption is enabled. * @param verbosity verbosity level */ public EncDnsServer() { if (commandLineParameters == null) { settings = CommandLineParameters.loadPluginSettings("./inputOutput/anonNode/encDns.txt"); } else { settings = CommandLineParameters.loadPluginSettings("./inputOutput/anonNode/encDns.txt", commandLineParameters.overwriteParameters); // settigns in Paths.PATH_TO_PATH_CONFIG_FILE have higher priority than normal plug-in settings -> overwrite (again) settings.addProperties("./inputOutput/anonNode/encDns.txt"); if (commandLineParameters.overwriteParameters != null) // overwriteParameters have higher priority than all other settings -> overwrite (again) Settings.overwriteSettings(settings.getPropertiesObject(), commandLineParameters.overwriteParameters, true); } generateComponents(); setReferencesBetweenComponents(); loadImplementations(); // loads the plug-ins callConstructors(); initializeComponents(); beginMixing(); } private void generateComponents() { // NOTE: the order of the items is important (do not change it) //this.outputStrategyLayerMix = new Layer3OutputStrategyMixController(null, settings, null, null, null); //this.outputStrategyLayerMix.instantiateSubclass(); //this.components.add(outputStrategyLayerMix); this.recodingLayerMix = new Layer2RecodingSchemeMixController(null, settings, null, null, null); this.recodingLayerMix.instantiateSubclass(); this.components.add(recodingLayerMix); this.networkLayerMix = new Layer1NetworkMixController(null, settings, null, null, null); this.networkLayerMix.instantiateSubclass(); this.components.add(networkLayerMix); //this.transportLayerMix = new Layer4TransportMixController(null, settings, null, null, null); //this.transportLayerMix.instantiateSubclass(); //this.components.add(transportLayerMix); this.applicationLayerMix = new Layer5ApplicationMixController(null, settings, null, null, null); this.applicationLayerMix.instantiateSubclass(); this.components.add(applicationLayerMix); } private void setReferencesBetweenComponents() { for (Controller c:components) c.setComponentReferences(networkLayerMix, null, recodingLayerMix, null, outputStrategyLayerMix, null, transportLayerMix, null, applicationLayerMix, null, null, null, null, null); } public void registerComponent(Controller controllerToRegister) { components.add(controllerToRegister); } private void callConstructors() { for (Controller c:components) if (c.implementation != null) c.implementation.constructor(); } private void loadImplementations() { for (Controller c:components) c.instantiateSubclass(); } private void initializeComponents() { for (Controller c:components) c.initialize(); } private void beginMixing() { for (Controller c:components) c.begin(); } /** * Main method * @param args the command line arguments (see -h for documentation) */ public static void main(String[] args) { try { _opt = new Options(); _opt.addOption("h", "help", false, "prints this message"); _opt.addOption("s", "libsodiumwrap", true, "path to libsodiumWrap library (default: in ./lib/)"); _opt.addOption("a", "nameserver", true, "nameserver's IP address or hostname (default: 127.0.0.1)"); _opt.addOption("p", "port", true, "nameserver's port (default: 53)"); _opt.addOption("ba", "bindAddress", true, "IP address the EncDNS server will listen for EncDns requests (default: 127.0.0.1)"); _opt.addOption("bp", "bindPort", true, "Port the EncDNS server will listen for EncDns requests (default: 53)"); _opt.addOption("pk", "public-key", true, "path to public key (default: ./lib/encdns.pk)"); _opt.addOption("sk", "secret-key", true, "path to secret key (default: ./lib/encdns.sk)"); _opt.addOption("c", "cache", true, "shared secret cache size (default: 100)"); _opt.addOption("t", "timeout", true, "timeout for queries to authoritative nameservers in ms (default: 5000)"); _opt.addOption("mt", "max-threads", true, "maximum number of threads (default: 100)"); _opt.addOption("d", "disable-encryption", false, "disable encryption"); _opt.addOption("v", "verbose", false, "enable verbose output"); _opt.addOption("dts", "displayThreadStatus", false, "display info about threads (idle, encrypting...)"); _opt.addOption("dtsi", "displayThreadStatusInterval", true, "interval to display info about threads in ms (default: 1000)"); _opt.addOption("dt", "displayThroughputStatistics", false, "display info about current throughput"); _opt.addOption("ir", "useInternalResolver", false, "use a simple java resolver integrated with encDns instead of the local name server"); _opt.addOption("rl", "resolveToLocalhost", false, "display info about current throughput"); Option zOpt = new Option("z", "zonename", true, "zone name (REQUIRED)"); zOpt.setRequired(true); _opt.addOption(zOpt); Options helpOpts = new Options(); helpOpts.addOption("h", "help", false, "prints this message"); CommandLineParser parser = new BasicParser(); // We need to check for the help parameter first, as parsing all // simultaneously will throw an exception if a required option // is missing. CommandLine cmd = parser.parse(helpOpts, args, true); if (cmd.hasOption("help")) { HelpFormatter hf = new HelpFormatter(); hf.printHelp("EncDNSServerProxy", _opt); return; } // Now we can parse all options cmd = parser.parse(_opt, args); // get parameter values passed by CLI String libStr = cmd.getOptionValue("libsodiumwrap"); String nsStr = cmd.getOptionValue("nameserver"); String portStr = cmd.getOptionValue("port"); String baStr = cmd.getOptionValue("bindAddress"); String bpStr = cmd.getOptionValue("bindPort"); String zoneStr = cmd.getOptionValue("zonename"); String cacheStr = cmd.getOptionValue("cache"); String timeoutStr = cmd.getOptionValue("timeout"); String threadsStr = cmd.getOptionValue("max-threads"); String pkStr = cmd.getOptionValue("public-key"); String skStr = cmd.getOptionValue("secret-key"); String displayThreadStatusIntStr = cmd.getOptionValue("displayThreadStatusInterval"); // set standard values if corresponding CLI parameters are not set if(libStr == null) { if(EncDNSHelper.osIsWindows()) { libStr = System.getProperty("user.dir") + "\\lib\\libsodiumWrap.dll"; } else { // assume a Unix-like OS libStr = System.getProperty("user.dir") + "/lib/libsodiumWrap.so"; } } if(nsStr == null) nsStr = "127.0.0.1"; int port = 53; if (portStr != null) { port = Integer.parseInt(portStr); } if(baStr == null) baStr = "127.0.0.1"; int baPort = 53; if (bpStr != null) { baPort = Integer.parseInt(bpStr); } int cache = 100; if(cacheStr != null) { cache = Integer.parseInt(cacheStr); } int timeout = 5000; if(timeoutStr != null) { timeout = Integer.parseInt(timeoutStr); } int maxThreads = 100; if(threadsStr != null) { maxThreads = Integer.parseInt(threadsStr); } boolean encryption = true; if(cmd.hasOption("disable-encryption")) { encryption = false; } if(pkStr == null) { if(EncDNSHelper.osIsWindows()) { pkStr = System.getProperty("user.dir") + "\\lib\\encdns.pk"; } else { // assume a Unix-like OS pkStr = System.getProperty("user.dir") + "/lib/encdns.pk"; } } if(skStr == null) { if(EncDNSHelper.osIsWindows()) { skStr = System.getProperty("user.dir") + "\\lib\\encdns.sk"; } else { // assume a Unix-like OS skStr = System.getProperty("user.dir") + "/lib/encdns.sk"; } } int verbosity; if(cmd.hasOption("verbose")) { verbosity = 1; } else { verbosity = 0; } boolean displayThreadStatusBool; if(cmd.hasOption("displayThreadStatus")) { displayThreadStatusBool = true; } else { displayThreadStatusBool = false; } int displayThreadStatusInt = 1000; if(displayThreadStatusIntStr != null) { displayThreadStatusInt = Integer.parseInt(displayThreadStatusIntStr); } boolean displayThroughputStatisticsBool; if(cmd.hasOption("displayThroughputStatistics")) { displayThroughputStatisticsBool = true; } else { displayThroughputStatisticsBool = false; } boolean resolveToLocalhostBool; if(cmd.hasOption("resolveToLocalhost")) { resolveToLocalhostBool = true; } else { resolveToLocalhostBool = false; } boolean useInternalResolverBool; if(cmd.hasOption("useInternalResolver")) { useInternalResolverBool = true; } else { useInternalResolverBool = false; } // load the required C wrapper library if (encryption) { System.load(libStr); } // resolve the remote recursive nameserver's address or IP InetAddress nsaddr = InetAddress.getByName(nsStr); InetAddress baaddr = InetAddress.getByName(baStr); EncDnsServer.bindAddress = baaddr; EncDnsServer.bindPort = baPort; EncDnsServer.zoneurl = zoneStr; EncDnsServer.nsaddr = nsaddr; EncDnsServer.port = port; EncDnsServer.cachesize = cache; EncDnsServer.timeout = timeout; EncDnsServer.maxThreads = maxThreads; EncDnsServer.pkPath = pkStr; EncDnsServer.skPath = skStr; EncDnsServer.encryption = encryption; EncDnsServer.verbosity = verbosity; EncDnsServer.displayThreadStatusBool = displayThreadStatusBool; EncDnsServer.displayThreadStatusInt = displayThreadStatusInt; EncDnsServer.displayThroughputBool = displayThroughputStatisticsBool; EncDnsServer.useInternalResolver = useInternalResolverBool; EncDnsServer.resolveToLocalhost = resolveToLocalhostBool; new EncDnsServer(); } catch (MissingOptionException e) { // print an error and the help if a required option is missing System.out.println(e.getMessage()); HelpFormatter hf = new HelpFormatter(); hf.printHelp("EncDNSServerProxy", _opt); } catch (ParseException e) { System.err.println("Error when parsing command line options:"); System.err.println(e); } catch (UnknownHostException e) { // print an error if the remote recursive nameserver's address // cannot be resolved System.err.println("Could not resolve remote recursive nameserver's address"); } catch (UnsatisfiedLinkError e) { System.err.println("Could not access libsodium; was \"export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/gmix/lib/\" executed? is libsodiumWrap.so compatible to your system? error message: " +e.getMessage()); } } }