From fcfab6ae008e64a7c3b610237aa0a65bf8718b56 Mon Sep 17 00:00:00 2001 From: knaccc Date: Wed, 30 Jan 2019 01:35:29 +0000 Subject: [PATCH] Store server tunnel keys / read tunnel keys from a specified directory when creating a tunnel with tunnelcontrol Use .i2p-zero in the user's home directory as the i2p config dir. --- README.md | 11 +++- bin/build-launcher.sh | 1 - .../i2p/zero/gui/AddTunnelController.java | 2 +- .../src/org/getmonero/i2p/zero/Main.java | 2 +- .../org/getmonero/i2p/zero/TunnelControl.java | 53 +++++++++++-------- resources/launch-gui.bat | 2 +- resources/launch-gui.sh | 2 +- resources/launch.sh | 2 +- 8 files changed, 44 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 6ed6f55..243f238 100755 --- a/README.md +++ b/README.md @@ -85,9 +85,16 @@ Note that it may take a short while for new tunnels to be set up. Call the `dist/linux/router/bin/tunnel-control.sh` script as follows to create and destroy tunnels: -#### Listen for i2p connections and forward them to the specified host and port. Returns a newly created destination public key. +#### Listen for i2p connections and forward them to the specified host and port, storing/reading the server key file in/from the specified directory. -`tunnel-control.sh server.create ` +If the directory doesn't exist with a file named serverTunnelSecretKey in it, +returns a newly created destination address and writes the secret key for the +new address to a file called serverTunnelSecretKey in the specified directory. Otherwise, read the existing +secret key from that directory. The server tunnel will listen for i2p connections and forward them to the +specified host and port. Returns the I2P b32 destination address for the server tunnel (which deterministically depends + on the contents of the serverTunnelSecretKey file). + +`tunnel-control.sh server.create ` #### Close the tunnel listening for connections on the specified destination public key. Returns "OK". diff --git a/bin/build-launcher.sh b/bin/build-launcher.sh index ef561a5..c6c1963 100755 --- a/bin/build-launcher.sh +++ b/bin/build-launcher.sh @@ -70,7 +70,6 @@ done for i in linux mac win linux-gui mac-gui win-gui; do cp -r $basedir/import/i2p.base $basedir/dist/$i/router/; done -for i in linux mac win linux-gui mac-gui win-gui; do mkdir -p $basedir/dist/$i/router/i2p.config; done # remove unnecessary native libs from jbigi.jar for i in linux mac win linux-gui mac-gui win-gui; do diff --git a/org.getmonero.i2p.zero.gui/src/org/getmonero/i2p/zero/gui/AddTunnelController.java b/org.getmonero.i2p.zero.gui/src/org/getmonero/i2p/zero/gui/AddTunnelController.java index d4a74a1..fe30c7e 100644 --- a/org.getmonero.i2p.zero.gui/src/org/getmonero/i2p/zero/gui/AddTunnelController.java +++ b/org.getmonero.i2p.zero.gui/src/org/getmonero/i2p/zero/gui/AddTunnelController.java @@ -89,7 +89,7 @@ public class AddTunnelController { socksProxyConfigPane.setVisible(false); if (newToggle.equals(clientTunnelRadioButton)) clientTunnelConfigPane.setVisible(true); if (newToggle.equals(serverTunnelRadioButton)) { - var keyPair = tunnelControl.genKeyPair(); + var keyPair = TunnelControl.KeyPair.gen(); serverKeyField.setText(keyPair.seckey + "," + keyPair.pubkey); serverAddrField.setText(keyPair.b32Dest); serverTunnelConfigPane.setVisible(true); diff --git a/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/Main.java b/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/Main.java index cf73c7d..481c0a5 100644 --- a/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/Main.java +++ b/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/Main.java @@ -16,7 +16,7 @@ public class Main { // where to find the I2P installation files p.put("i2p.dir.base", "/usr/share/i2p"); // where to find the I2P data files - p.put("i2p.dir.config", System.getProperty("user.home") + File.separator + ".i2p"); + p.put("i2p.dir.config", System.getProperty("user.home") + File.separator + ".i2p-zero"); // bandwidth limits in K bytes per second p.put("i2np.inboundKBytesPerSecond","50"); p.put("i2np.outboundKBytesPerSecond","50"); diff --git a/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/TunnelControl.java b/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/TunnelControl.java index 63d8e83..faf1e69 100644 --- a/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/TunnelControl.java +++ b/org.getmonero.i2p.zero/src/org/getmonero/i2p/zero/TunnelControl.java @@ -17,6 +17,7 @@ import java.net.InetAddress; import java.net.ServerSocket; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -36,6 +37,7 @@ public class TunnelControl implements Runnable { tunnelControlTempDir.delete(); tunnelControlTempDir.mkdir(); this.tunnelControlTempDir = tunnelControlTempDir; + this.tunnelControlTempDir.deleteOnExit(); } public interface Tunnel { @@ -132,16 +134,6 @@ public class TunnelControl implements Runnable { return tunnels; } - public KeyPair genKeyPair() throws Exception { - ByteArrayOutputStream seckey = new ByteArrayOutputStream(); - ByteArrayOutputStream pubkey = new ByteArrayOutputStream(); - I2PClient client = I2PClientFactory.createClient(); - Destination d = client.createDestination(seckey); - d.writeBytes(pubkey); - String b32Dest = d.toBase32(); - return new KeyPair(Base64.encode(seckey.toByteArray()), Base64.encode(pubkey.toByteArray()), b32Dest); - } - public static class KeyPair { public String seckey; public String pubkey; @@ -159,23 +151,27 @@ public class TunnelControl implements Runnable { d.readBytes(new ByteArrayInputStream(Base64.decode(this.seckey))); this.b32Dest = d.toBase32(); } + public static KeyPair gen() throws Exception { + ByteArrayOutputStream seckey = new ByteArrayOutputStream(); + ByteArrayOutputStream pubkey = new ByteArrayOutputStream(); + I2PClient client = I2PClientFactory.createClient(); + Destination d = client.createDestination(seckey); + d.writeBytes(pubkey); + String b32Dest = d.toBase32(); + return new KeyPair(Base64.encode(seckey.toByteArray()), Base64.encode(pubkey.toByteArray()), b32Dest); + } + public static KeyPair read(String path) throws Exception { + return new KeyPair(Files.readString(Paths.get(path))); + } + public void write(String path) throws Exception { + Files.writeString(Paths.get(path), seckey + "," + pubkey); + } + } @Override public void run() { - // listen for socket connections to the tunnel controller. - // listen for the commands on port 30000: - // server.create // returns a newly created destination public key, which will listen for i2p connections and forward them to the specified host and port - // server.destroy // closes the tunnel listening for connections on the specified destination public key, and returns OK - // client.create // returns a newly created localhost port number, where connections will be sent over I2P to the destination public key - // client.destroy // closes the tunnel listening for connections on the specified port, and returns OK - // socks.create // creates a socks proxy listening on the specified port - // socks.destroy // closes the socks proxy listening on the specified port, and returns OK - // - // send a command with bash: exec 3<>/dev/tcp/localhost/30000; echo "server.create localhost 80" >&3; cat <&3 - // - try { controlServerSocket = new ServerSocket(clientPortSeq++, 0, InetAddress.getLoopbackAddress()); while (!stopping) { @@ -190,7 +186,18 @@ public class TunnelControl implements Runnable { case "server.create": String destHost = args[1]; int destPort = Integer.parseInt(args[2]); - var tunnel = new ServerTunnel(destHost, destPort, genKeyPair(), getTunnelControlTempDir()); + File serverTunnelConfigDir = new File(args[3]); + if(!serverTunnelConfigDir.exists()) serverTunnelConfigDir.mkdir(); + File serverKeyFile = new File(serverTunnelConfigDir, "serverTunnelSecretKey"); + KeyPair keyPair; + if(serverKeyFile.exists()) { + keyPair = KeyPair.read(serverKeyFile.getPath()); + } + else { + keyPair = KeyPair.gen(); + keyPair.write(serverKeyFile.getPath()); + } + var tunnel = new ServerTunnel(destHost, destPort, keyPair, getTunnelControlTempDir()); tunnels.add(tunnel); out.println(tunnel.dest); break; diff --git a/resources/launch-gui.bat b/resources/launch-gui.bat index bb8293d..1db47cc 100644 --- a/resources/launch-gui.bat +++ b/resources/launch-gui.bat @@ -1,3 +1,3 @@ @echo off set DIR=%~dp0 -"%DIR%\java" -cp %DIR%\..\i2p.base\jbigi.jar -m org.getmonero.i2p.zero.gui --i2p.dir.base=%DIR%\..\i2p.base --i2p.dir.config=%DIR%\..\i2p.config %* \ No newline at end of file +"%DIR%\java" -cp %DIR%\..\i2p.base\jbigi.jar -m org.getmonero.i2p.zero.gui --i2p.dir.base=%DIR%\..\i2p.base %* \ No newline at end of file diff --git a/resources/launch-gui.sh b/resources/launch-gui.sh index f0761f7..97b4b03 100755 --- a/resources/launch-gui.sh +++ b/resources/launch-gui.sh @@ -6,4 +6,4 @@ else basedir=$(dirname $(dirname $(readlink -fm $0))) fi -$basedir/bin/java -cp $basedir/i2p.base/jbigi.jar -m org.getmonero.i2p.zero.gui --i2p.dir.base=$basedir/i2p.base --i2p.dir.config=$basedir/i2p.config +$basedir/bin/java -cp $basedir/i2p.base/jbigi.jar -m org.getmonero.i2p.zero.gui --i2p.dir.base=$basedir/i2p.base diff --git a/resources/launch.sh b/resources/launch.sh index 59db73d..fa9d77b 100755 --- a/resources/launch.sh +++ b/resources/launch.sh @@ -6,4 +6,4 @@ else basedir=$(dirname $(dirname $(readlink -fm $0))) fi -$basedir/bin/java -cp $basedir/i2p.base/jbigi.jar -m org.getmonero.i2p.zero --i2p.dir.base=$basedir/i2p.base --i2p.dir.config=$basedir/i2p.config +$basedir/bin/java -cp $basedir/i2p.base/jbigi.jar -m org.getmonero.i2p.zero --i2p.dir.base=$basedir/i2p.base