reimplemented server access restriction

via Jetty IPAccessHandler to allow only configured IP's to access.
Handler is only loaded if a restriction is configured.

Since IPAcessHandler (Jetty 8) does not support IPv6 system property java.net.preferIPv4Stack=true
Testing showed system.setProperty seems to be sensitive to point of calling (earliest possible time seems to be best = early in yacy.main).
Moved the "isrunning..." just open browser check also to the new routine to preread the yacy.config only once.
pull/1/head
reger 11 years ago
parent 3cb6c7861f
commit 30d925a96e

@ -3,13 +3,17 @@
<table border="0" cellspacing="5"> <table border="0" cellspacing="5">
<tr valign="top"> <tr valign="top">
<td>IP-Number filter:</td> <td>IP-Number filter:</td>
<td><input name="serverfilter" type="text" size="50" maxlength="1000" value="#[serverfilter]#" /></td> <td><input name="serverfilter" type="text" size="50" maxlength="1000" value="#[serverfilter]#" /><br />(requires restart)</td>
<td><strong>Here you can restrict access to the server.</strong> By default, the access is not limited, <td><strong>Here you can restrict access to the server.</strong> By default, the access is not limited,
because this function is needed to spawn the p2p index-sharing function. because this function is needed to spawn the p2p index-sharing function.
If you block access to your server (setting anything else than '*'), then you will also be blocked If you block access to your server (setting anything else than '*'), then you will also be blocked
from using other peers' indexes for search service. from using other peers' indexes for search service.
However, blocking access may be correct in enterprise environments where you only want to index your However, blocking access may be correct in enterprise environments where you only want to index your
company's own web pages.</td> company's own web pages.<br />
Filter have to be entered as IP, IP range or first part of allowed IP's separated by comma (e.g. 10.100.0-100.0-100, 127. )
further details on format see Jetty
<a href="http://download.eclipse.org/jetty/8.1.14.v20131031/apidocs/org/eclipse/jetty/server/handler/IPAccessHandler.html" target="_blank">IPAccessHandler</a> docu.
</td>
</tr> </tr>
<!-- <!--
<tr valign="top"> <tr valign="top">

@ -2567,6 +2567,7 @@ The password==Das Passwort
#--------------------------- #---------------------------
Server Access Settings==Serverzugangs Einstellungen Server Access Settings==Serverzugangs Einstellungen
IP-Number filter:==IP-Addressfilter: IP-Number filter:==IP-Addressfilter:
requires restart==erfordert Neustart
Here you can restrict access to the server.==Hier können Sie den Zugang zum Server beschränken. Here you can restrict access to the server.==Hier können Sie den Zugang zum Server beschränken.
By default, the access is not limited,==Standardmäßig ist der Zugang unbeschränkt, By default, the access is not limited,==Standardmäßig ist der Zugang unbeschränkt,
because this function is needed to spawn the p2p index-sharing function.==da dies notwendig ist um den P2P-Indextausch zu ermöglichen. because this function is needed to spawn the p2p index-sharing function.==da dies notwendig ist um den P2P-Indextausch zu ermöglichen.

@ -33,6 +33,7 @@ import java.net.NetworkInterface;
import java.net.SocketException; import java.net.SocketException;
import java.security.KeyStore; import java.security.KeyStore;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.StringTokenizer;
import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
@ -53,6 +54,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.IPAccessHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
@ -139,7 +141,30 @@ public class Jetty8HttpServerImpl implements YaCyHttpServer {
securityHandler.setLoginService(loginService); securityHandler.setLoginService(loginService);
securityHandler.setRealmName(loginService.getName()); securityHandler.setRealmName(loginService.getName());
securityHandler.setHandler(new CrashProtectionHandler(allrequesthandlers)); securityHandler.setHandler(new CrashProtectionHandler(allrequesthandlers));
server.setHandler(securityHandler);
// check server access restriction and add IPAccessHandler if restrictions are needed
// otherwise don't (to save performance)
String white = sb.getConfig("serverClient", "*");
if (!white.equals("*")) { // full ip (allowed ranges 0-255 or prefix 10.0-255,0,0-100 or 127.)
final StringTokenizer st = new StringTokenizer(white, ",");
IPAccessHandler iphandler = new IPAccessHandler();
int i=0;
while (st.hasMoreTokens()) {
String ip = st.nextToken();
iphandler.addWhite(ip);
i++;
}
if (i > 0) {
iphandler.addWhite("127.0.0.1"); // allow localhost (loopback addr)
iphandler.setHandler(securityHandler);
server.setHandler(iphandler);
ConcurrentLog.info("SERVER","activated IP access restriction to: [127.0.0.1," + white +"] (this works only correct with start parameter -Djava.net.preferIPv4Stack=true)");
} else {
server.setHandler(securityHandler); // iphandler not needed
}
} else {
server.setHandler(securityHandler); // iphandler not needed
}
} }
/** /**

@ -184,35 +184,6 @@ public final class yacy {
f = new File(dataHome, "DATA/yacy.running"); f = new File(dataHome, "DATA/yacy.running");
final String conf = "DATA/SETTINGS/yacy.conf".replace("/", File.separator); final String conf = "DATA/SETTINGS/yacy.conf".replace("/", File.separator);
if (f.exists()) { // another instance running? VM crash? User will have to care about this
ConcurrentLog.severe("STARTUP", "WARNING: the file " + f + " exists, this usually means that a YaCy instance is still running. If you want to restart YaCy, try first ./stopYACY.sh, then ./startYACY.sh. If ./stopYACY.sh fails, try ./killYACY.sh");
// If YaCy is actually running, then we check if the server port is open.
// If yes, then we consider that a restart is a user mistake and then we just respond
// as the user expects and tell the browser to open the start page.
// That will especially happen if Windows Users double-Click the YaCy Icon on the desktop to simply
// open the web interface. (They don't think of 'servers' they just want to get to the search page).
// We need to parse the configuration file for that to get the host port
File dataFile = new File(dataHome, conf);
if (dataFile.exists()) {
Properties p = new Properties();
p.load(new FileInputStream(dataFile));
int port = Integer.parseInt(p.getProperty("port", "8090"));
try {
if (TimeoutRequest.ping("127.0.0.1", port, 1000)) {
Browser.openBrowser("http://localhost:" + port + "/" + p.getProperty(SwitchboardConstants.BROWSER_POP_UP_PAGE, "index.html"));
// Thats it; YaCy was running, the user is happy, we can stop now.
ConcurrentLog.severe("STARTUP", "WARNING: YaCy instance was still running; just opening the browser and exit.");
System.exit(0);
}
} catch (final ExecutionException ex) {
ConcurrentLog.info("STARTUP", "INFO: delete old yacy.running file; likely previous YaCy session was not orderly shutdown!");
}
}
// YaCy is not running; thus delete the file an go on as nothing was wrong.
delete(f);
}
if (!f.createNewFile()) ConcurrentLog.severe("STARTUP", "WARNING: the file " + f + " can not be created!"); if (!f.createNewFile()) ConcurrentLog.severe("STARTUP", "WARNING: the file " + f + " can not be created!");
try { new FileOutputStream(f).write(Integer.toString(OS.getPID()).getBytes()); } catch (final Exception e) { } // write PID try { new FileOutputStream(f).write(Integer.toString(OS.getPID()).getBytes()); } catch (final Exception e) { } // write PID
f.deleteOnExit(); f.deleteOnExit();
@ -574,7 +545,71 @@ public final class yacy {
// finished // finished
ConcurrentLog.config("COMMAND-STEERING", "SUCCESSFULLY FINISHED COMMAND: " + processdescription); ConcurrentLog.config("COMMAND-STEERING", "SUCCESSFULLY FINISHED COMMAND: " + processdescription);
} }
/**
* read saved config file and perform action which need to be done before main task starts
* - like check on system alrady running etc.
*
* @param dataHome data directory
*/
static private void preReadSavedConfigandInit(File dataHome) {
File lockFile = new File(dataHome, "DATA/yacy.running");
final String conf = "DATA/SETTINGS/yacy.conf";
// If YaCy is actually running, then we check if the server port is open.
// If yes, then we consider that a restart is a user mistake and then we just respond
// as the user expects and tell the browser to open the start page.
// That will especially happen if Windows Users double-Click the YaCy Icon on the desktop to simply
// open the web interface. (They don't think of 'servers' they just want to get to the search page).
// We need to parse the configuration file for that to get the host port
File configFile = new File(dataHome, conf);
if (configFile.exists()) {
Properties p = new Properties();
try {
p.load(new FileInputStream(configFile));
// test for yacy already running
if (lockFile.exists()) { // another instance running? VM crash? User will have to care about this
//standard log system not up yet - use simply stdout
// prevents also creation of a log file while just opening browser
System.out.println("WARNING: the file " + lockFile + " exists, this usually means that a YaCy instance is still running. If you want to restart YaCy, try first ./stopYACY.sh, then ./startYACY.sh. If ./stopYACY.sh fails, try ./killYACY.sh");
if (configFile.exists()) {
int port = Integer.parseInt(p.getProperty("port", "8090"));
try {
if (TimeoutRequest.ping("127.0.0.1", port, 1000)) {
Browser.openBrowser("http://localhost:" + port + "/" + p.getProperty(SwitchboardConstants.BROWSER_POP_UP_PAGE, "index.html"));
// Thats it; YaCy was running, the user is happy, we can stop now.
System.out.println("WARNING: YaCy instance was still running; just opening the browser and exit.");
System.exit(0);
}
} catch (final ExecutionException ex) {
System.err.println( "INFO: delete old yacy.running file; likely previous YaCy session was not orderly shutdown!");
}
}
// YaCy is not running; thus delete the file an go on as nothing was wrong.
delete(lockFile);
} else {
// Test for server access restriction (is implemented using Jetty IPaccessHandler which does not support IPv6
// try to disavle IPv6
String teststr = p.getProperty("serverClient", "*");
if (!teststr.equals("*")) {
// testing on Win-8 showed this property has to be set befor Switchboard starts
// and seems to be sensitive (or time critical) if other code had been executed before this (don't know why ... ?)
System.setProperty("java.net.preferIPv6Addresses", "false");
System.setProperty("java.net.preferIPv4Stack", "true"); // DO NOT PREFER IPv6, i.e. freifunk uses ipv6 only and host resolving does not work
teststr = System.getProperty("java.net.preferIPv4Stack");
System.out.println("set system property java.net.preferIP4Stack="+teststr);
}
}
} catch (IOException ex) { }
}
}
/** /**
* Main-method which is started by java. Checks for special arguments or * Main-method which is started by java. Checks for special arguments or
* starts up the application. * starts up the application.
@ -618,10 +653,12 @@ public final class yacy {
if ((args.length >= 1) && (args[0].toLowerCase().equals("-startup") || args[0].equals("-start"))) { if ((args.length >= 1) && (args[0].toLowerCase().equals("-startup") || args[0].equals("-start"))) {
// normal start-up of yacy // normal start-up of yacy
if (args.length > 1) dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]); if (args.length > 1) dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]);
preReadSavedConfigandInit(dataRoot);
startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, false); startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, false);
} else if (args.length >= 1 && args[0].toLowerCase().equals("-gui")) { } else if (args.length >= 1 && args[0].toLowerCase().equals("-gui")) {
// start-up of yacy with gui // start-up of yacy with gui
if (args.length > 1) dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]); if (args.length > 1) dataRoot = new File(System.getProperty("user.home").replace('\\', '/'), args[1]);
preReadSavedConfigandInit(dataRoot);
startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, true); startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, true);
} else if ((args.length >= 1) && ((args[0].toLowerCase().equals("-shutdown")) || (args[0].equals("-stop")))) { } else if ((args.length >= 1) && ((args[0].toLowerCase().equals("-shutdown")) || (args[0].equals("-stop")))) {
// normal shutdown of yacy // normal shutdown of yacy
@ -636,6 +673,7 @@ public final class yacy {
System.out.println(copyright); System.out.println(copyright);
} else { } else {
if (args.length == 1) applicationRoot= new File(args[0]); if (args.length == 1) applicationRoot= new File(args[0]);
preReadSavedConfigandInit(dataRoot);
startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, false); startup(dataRoot, applicationRoot, startupMemFree, startupMemTotal, false);
} }
} finally { } finally {

Loading…
Cancel
Save