inform user of the port to open in their firewall

version available check fix
pull/13/head
knaccc 5 years ago
parent 83ad48d995
commit 540c1a3c25

@ -159,6 +159,10 @@ specified host and port. Note that the base 32 I2P destination address determini
`tunnel-control.sh sam.create` `tunnel-control.sh sam.create`
#### Get the external port randomly assigned to this router when first run, which the firewall should allow incoming UDP and TCP connections on. Returns the port number.
`tunnel-control.sh router.externalPort`
## Watch the I2P log for messages ## Watch the I2P log for messages

@ -96,8 +96,6 @@ public class Controller {
@FXML private void initialize() { @FXML private void initialize() {
helpTextArea.setText("You are running I2P-zero version " + UpdateCheck.currentVersion + "\n\n" + helpTextArea.getText());
DirectoryChooser directoryChooser = new DirectoryChooser(); DirectoryChooser directoryChooser = new DirectoryChooser();
typeCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("type")); typeCol.setCellValueFactory(new PropertyValueFactory<Tunnel,String>("type"));
@ -260,7 +258,7 @@ public class Controller {
if(masterState) { if(masterState) {
masterToggle.setImage(new Image("org/getmonero/i2p/zero/gui/toggle-on.png")); masterToggle.setImage(new Image("org/getmonero/i2p/zero/gui/toggle-on.png"));
statusLabel.setVisible(true); statusLabel.setVisible(true);
routerWrapper.start(); routerWrapper.start(()->{});
listenForTunnelChanges(); listenForTunnelChanges();
tunnelAddButton.setDisable(false); tunnelAddButton.setDisable(false);
} }
@ -364,7 +362,11 @@ public class Controller {
alert.show(); alert.show();
}); });
}); });
routerWrapper.start(); routerWrapper.start(()->{
helpTextArea.setText("You are running I2P-zero version " + UpdateCheck.currentVersion + "\n\n"
+ "For best performance, please open port " + routerWrapper.routerExternalPort + " on your firewall for incoming UDP and TCP connections. This port has been randomly assigned to you. For privacy reasons, please do not share this port with others.\n\n"
+ helpTextArea.getText());
});
} }

@ -40,7 +40,8 @@ public class Main {
RouterWrapper routerWrapper = new RouterWrapper(p, ()->{ RouterWrapper routerWrapper = new RouterWrapper(p, ()->{
Main.consoleOut.println("**** A new version of I2P-zero is available at https://github.com/i2p-zero/i2p-zero - Please keep your software up-to-date, as it will enhance your privacy and keep you safe from vulnerabilities"); Main.consoleOut.println("**** A new version of I2P-zero is available at https://github.com/i2p-zero/i2p-zero - Please keep your software up-to-date, as it will enhance your privacy and keep you safe from vulnerabilities");
}); });
routerWrapper.start();
routerWrapper.start(()->Main.consoleOut.println("For best performance, please open port " + routerWrapper.routerExternalPort + " on your firewall for incoming UDP and TCP connections. This port has been randomly assigned to you. For privacy reasons, please do not share this port with others."));
Runtime.getRuntime().addShutdownHook(new Thread(()->routerWrapper.stop(true))); Runtime.getRuntime().addShutdownHook(new Thread(()->routerWrapper.stop(true)));

@ -29,6 +29,8 @@ public class RouterWrapper {
private File i2PBaseDir; private File i2PBaseDir;
private Runnable updateAvailableCallback; private Runnable updateAvailableCallback;
public int routerExternalPort;
public RouterWrapper(Properties routerProperties, Runnable updateAvailableCallback) { public RouterWrapper(Properties routerProperties, Runnable updateAvailableCallback) {
this.routerProperties = routerProperties; this.routerProperties = routerProperties;
this.updateAvailableCallback = updateAvailableCallback; this.updateAvailableCallback = updateAvailableCallback;
@ -72,7 +74,7 @@ public class RouterWrapper {
return started; return started;
} }
public void start() { public void start(Runnable routerIsAliveCallback) {
new Thread(()-> { new Thread(()-> {
if(started) return; if(started) return;
@ -99,6 +101,10 @@ public class RouterWrapper {
System.out.println("I2P router now running"); System.out.println("I2P router now running");
File routerConfigFile = new File(i2PBaseDir, "router.config");
routerExternalPort = Integer.parseInt(Files.lines(routerConfigFile.toPath()).filter(s->s.startsWith("i2np.udp.port=")).findFirst().get().split("=")[1]);
new Thread(routerIsAliveCallback).start();
tunnelControl = new TunnelControl(this, i2PConfigDir, new File(i2PConfigDir, "tunnelTemp")); tunnelControl = new TunnelControl(this, i2PConfigDir, new File(i2PConfigDir, "tunnelTemp"));
new Thread(tunnelControl).start(); new Thread(tunnelControl).start();

@ -628,6 +628,11 @@ public class TunnelControl implements Runnable {
break; break;
} }
case "router.externalPort": {
out.println(routerWrapper.routerExternalPort);
break;
}
case "sam.create": { case "sam.create": {
String[] samArgs = new String[]{"sam.keys", "127.0.0.1", "7656", "i2cp.tcp.host=127.0.0.1", "i2cp.tcp.port=7654"}; String[] samArgs = new String[]{"sam.keys", "127.0.0.1", "7656", "i2cp.tcp.host=127.0.0.1", "i2cp.tcp.port=7654"};
I2PAppContext context = routerWrapper.getRouter().getContext(); I2PAppContext context = routerWrapper.getRouter().getContext();

@ -10,6 +10,8 @@ import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -18,39 +20,56 @@ public class UpdateCheck {
public static final String currentVersion = new Scanner(RouterWrapper.class.getResourceAsStream("VERSION")).useDelimiter("\\n").next(); public static final String currentVersion = new Scanner(RouterWrapper.class.getResourceAsStream("VERSION")).useDelimiter("\\n").next();
private static boolean isNewerVersionAvailable(String currentVersion, String versionAvailable) {
int currentMajor = Integer.parseInt(currentVersion.split(".")[0]);
int currentMinor = Integer.parseInt(currentVersion.split(".")[1]);
int availableMajor = Integer.parseInt(versionAvailable.split(".")[0]);
int availableMinor = Integer.parseInt(versionAvailable.split(".")[1]);
if(availableMajor>currentMajor) return true;
if(availableMajor<currentMajor) return false;
if(availableMinor>currentMinor) return true;
return false;
}
public static void scheduleUpdateCheck(File i2PConfigDir, Router router, Runnable updateAvailableCallback) { public static void scheduleUpdateCheck(File i2PConfigDir, Router router, Runnable updateAvailableCallback) {
File updateAvailableFile = new File(i2PConfigDir, "updateAvailable"); try {
if(updateAvailableFile.exists()) { File versionAvailableFile = new File(i2PConfigDir, "versionAvailable");
updateAvailableCallback.run(); if(!versionAvailableFile.exists()) {
} Files.write(versionAvailableFile.toPath(), currentVersion.getBytes(), StandardOpenOption.CREATE);
else { }
// schedule next check randomly in the next 48 hrs. On average, this call pattern will result in a check every 24 hrs. String versionAvailable = Files.readString(versionAvailableFile.toPath());
CompletableFuture.delayedExecutor((long) (Math.random()*3600*24*2), TimeUnit.SECONDS).execute(() -> { if(isNewerVersionAvailable(currentVersion, versionAvailable)) {
if(lookupUpdateAvailable(router)) { updateAvailableCallback.run();
try { }
// create an empty file to indicate an update is available, so in future we don't have to keep querying the server else {
updateAvailableFile.createNewFile();
} // schedule next check randomly in the next 48 hrs. On average, this call pattern will result in a check every 24 hrs.
catch (Exception e) { CompletableFuture.delayedExecutor((long) (Math.random()*3600*24*2), TimeUnit.SECONDS).execute(() -> {
e.printStackTrace(); String versionAvailableLookup = lookupVersionAvailable(router);
if(versionAvailableLookup!=null) {
try {
// create an empty file to indicate an update is available, so in future we don't have to keep querying the server
Files.write(versionAvailableFile.toPath(), versionAvailableLookup.getBytes(), StandardOpenOption.CREATE);
} catch (Exception e) {
e.printStackTrace();
}
} }
updateAvailableCallback.run();
}
else {
// only check again if no update available yet
scheduleUpdateCheck(i2PConfigDir, router, updateAvailableCallback); scheduleUpdateCheck(i2PConfigDir, router, updateAvailableCallback);
} });
});
}
}
catch (Exception e) {
e.printStackTrace();
} }
} }
public static boolean lookupUpdateAvailable(Router router) { public static String lookupVersionAvailable(Router router) {
try { try {
String versionAvailable = null; String sanitizedVersionAvailable = null;
String host = "77ypf3rahyjegncradypnyotvn6fhq7sobhwe2gs5a2hdiwehwjq.b32.i2p"; String host = "77ypf3rahyjegncradypnyotvn6fhq7sobhwe2gs5a2hdiwehwjq.b32.i2p";
Destination dest = router.getContext().namingService().lookup(host, null, null); Destination dest = router.getContext().namingService().lookup(host, null, null);
I2PSocketManager mgr = I2PSocketManagerFactory.createManager(); I2PSocketManager mgr = I2PSocketManagerFactory.createManager();
@ -66,15 +85,21 @@ public class UpdateCheck {
while ((line = br.readLine()) != null) { while ((line = br.readLine()) != null) {
if (line.equals("")) break; if (line.equals("")) break;
} }
versionAvailable = br.readLine(); String rawVersionAvailable = br.readLine();
// sanitize, just in case the update notification server is compromised
if(rawVersionAvailable.length()>10) return null;
String allowedChars = "0123456789.";
sanitizedVersionAvailable = "";
for(var i=0; i<rawVersionAvailable.length(); i++) {
if(allowedChars.indexOf(rawVersionAvailable.charAt(i))>0) sanitizedVersionAvailable += rawVersionAvailable.charAt(i);
}
} }
br.close(); br.close();
if(versionAvailable==null) return false; return sanitizedVersionAvailable;
else return Float.parseFloat(currentVersion)<Float.parseFloat(versionAvailable);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return false; return null;
} }
} }

Loading…
Cancel
Save