added SSL/HTTPS connector to support SSL/https connection on port 8443

!!! attention !!! to make sure YaCy can start, https will be disabled if port 8443 is used
   - added ping test for above to migration 

- as of now port for https is hardcoded to default 8443
- if not urgend required I'd leave it this way (it's standard) to use different ports for http and https 

- post https port on ConfigBasic.html (if active)
pull/1/head
reger 11 years ago
parent f681ce15ae
commit 71cac1a278

@ -93,7 +93,7 @@
<dt><label for="port">Peer Port: </label></dt>
<dd>
<input type="text" name="port" id="port" value="#[defaultPort]#" size="5" maxlength="5" />&nbsp;&nbsp;&nbsp;
<input type="checkbox" name="withssl" id="withssl" #(withsslenabled)#::checked="checked"#(/withsslenabled)#>with SSL (https enabled)
<input type="checkbox" name="withssl" id="withssl" #(withsslenabled)#::checked="checked"#(/withsslenabled)#>with SSL (https enabled#(withsslenabled)#:: on port #[sslport]# #(/withsslenabled)#)
</dd>
#(upnp)#::<dt>
<label for="enableUpnp">Configure your router for YaCy:&nbsp;</label>

@ -102,7 +102,8 @@ public class ConfigBasic {
port = env.getConfigLong("port", 8090); //this allows a low port, but it will only get one, if the user edits the config himself.
ssl = env.getConfigBool("server.https", false);
}
if (ssl) prop.put("withsslenabled_sslport",env.getHttpServer().getSslPort());
// check if peer name already exists
final Seed oldSeed = sb.peers.lookupByName(peerName);
if (oldSeed == null &&
@ -134,7 +135,7 @@ public class ConfigBasic {
final YaCyHttpServer theServerCore = env.getHttpServer();
env.setConfig("port", port);
env.setConfig("server.https", ssl);
// redirect the browser to the new port
reconnect = true;

@ -24,13 +24,18 @@
package net.yacy.http;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.KeyStore;
import java.util.EnumSet;
import java.util.Enumeration;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.servlet.DispatcherType;
@ -41,6 +46,7 @@ import net.yacy.http.servlets.YaCyDefaultServlet;
import net.yacy.http.servlets.YaCyProxyServlet;
import net.yacy.http.servlets.SolrServlet.Servlet404;
import net.yacy.search.Switchboard;
import net.yacy.utils.PKCS12Tool;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
@ -50,9 +56,11 @@ import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/**
* class to embedded Jetty 8 http server into YaCy
@ -60,6 +68,7 @@ import org.eclipse.jetty.servlet.ServletHolder;
public class Jetty8HttpServerImpl implements YaCyHttpServer {
private final Server server;
private final int sslport = 8443; // the port to use for https
/**
* @param port TCP Port to listen for http requests
@ -71,9 +80,25 @@ public class Jetty8HttpServerImpl implements YaCyHttpServer {
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(port);
connector.setName("httpd:"+Integer.toString(port));
//connector.setThreadPool(new QueuedThreadPool(20));
server.addConnector(connector);
// add ssl/https connector
boolean useSSL = sb.getConfigBool("server.https", false);
if (useSSL) {
final SslContextFactory sslContextFactory = new SslContextFactory();
final SSLContext sslContext = initSslContext(sb);
if (sslContext != null) {
sslContextFactory.setSslContext(sslContext);
SslSelectChannelConnector sslconnector = new SslSelectChannelConnector(sslContextFactory);
sslconnector.setPort(sslport);
sslconnector.setName("ssld:" + Integer.toString(sslport)); // name must start with ssl (for withSSL() to work correctly)
server.addConnector(sslconnector);
ConcurrentLog.info("SERVER", "SSL support initialized successfully on port " + sslport);
}
}
YacyDomainHandler domainHandler = new YacyDomainHandler();
domainHandler.setAlternativeResolver(sb.peers);
@ -153,10 +178,19 @@ public class Jetty8HttpServerImpl implements YaCyHttpServer {
}
@Override
public boolean withSSL() {
return false; // TODO:
public boolean withSSL() {
Connector[] clist = server.getConnectors();
for (Connector c:clist) {
if (c.getName().startsWith("ssl")) return true;
}
return false;
}
@Override
public int getSslPort() {
return sslport;
}
/**
* reconnect with new port settings (after waiting milsec) - routine returns
* immediately
@ -265,4 +299,104 @@ public class Jetty8HttpServerImpl implements YaCyHttpServer {
return "Jetty " + Server.getVersion();
}
/**
* Init SSL Context from config settings
* @param sb Switchboard
* @return default or sslcontext according to config
*/
private SSLContext initSslContext(Switchboard sb) {
// getting the keystore file name
String keyStoreFileName = sb.getConfig("keyStore", "").trim();
// getting the keystore pwd
String keyStorePwd = sb.getConfig("keyStorePassword", "").trim();
// take a look if we have something to import
final String pkcs12ImportFile = sb.getConfig("pkcs12ImportFile", "").trim();
// if no keyStore and no import is defined, then set the default key
if (keyStoreFileName.isEmpty() && keyStorePwd.isEmpty() && pkcs12ImportFile.isEmpty()) {
keyStoreFileName = "defaults/freeworldKeystore";
keyStorePwd = "freeworld";
sb.setConfig("keyStore", keyStoreFileName);
sb.setConfig("keyStorePassword", keyStorePwd);
}
if (pkcs12ImportFile.length() > 0) {
ConcurrentLog.info("SERVER", "Import certificates from import file '" + pkcs12ImportFile + "'.");
try {
// getting the password
final String pkcs12ImportPwd = sb.getConfig("pkcs12ImportPwd", "").trim();
// creating tool to import cert
final PKCS12Tool pkcsTool = new PKCS12Tool(pkcs12ImportFile,pkcs12ImportPwd);
// creating a new keystore file
if (keyStoreFileName.isEmpty()) {
// using the default keystore name
keyStoreFileName = "DATA/SETTINGS/myPeerKeystore";
// creating an empty java keystore
final KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null,keyStorePwd.toCharArray());
final FileOutputStream ksOut = new FileOutputStream(keyStoreFileName);
ks.store(ksOut, keyStorePwd.toCharArray());
ksOut.close();
// storing path to keystore into config file
sb.setConfig("keyStore", keyStoreFileName);
}
// importing certificate
pkcsTool.importToJKS(keyStoreFileName, keyStorePwd);
// removing entries from config file
sb.setConfig("pkcs12ImportFile", "");
sb.setConfig("keyStorePassword", "");
// deleting original import file
// TODO: should we do this
} catch (final Exception e) {
ConcurrentLog.severe("SERVER", "Unable to import certificate from import file '" + pkcs12ImportFile + "'.",e);
}
} else if (keyStoreFileName.isEmpty()) return null;
// get the ssl context
try {
ConcurrentLog.info("SERVER","Initializing SSL support ...");
// creating a new keystore instance of type (java key store)
if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER", "Initializing keystore ...");
final KeyStore ks = KeyStore.getInstance("JKS");
// loading keystore data from file
if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Loading keystore file " + keyStoreFileName);
final FileInputStream stream = new FileInputStream(keyStoreFileName);
ks.load(stream, keyStorePwd.toCharArray());
stream.close();
// creating a keystore factory
if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Initializing key manager factory ...");
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks,keyStorePwd.toCharArray());
// initializing the ssl context
if (ConcurrentLog.isFine("SERVER")) ConcurrentLog.fine("SERVER","Initializing SSL context ...");
final SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(kmf.getKeyManagers(), null, null);
return sslcontext;
} catch (final Exception e) {
final String errorMsg = "FATAL ERROR: Unable to initialize the SSL Socket factory. " + e.getMessage();
ConcurrentLog.severe("SERVER",errorMsg);
System.out.println(errorMsg);
System.exit(0);
return null;
}
}
}

@ -23,6 +23,7 @@ public interface YaCyHttpServer {
abstract InetSocketAddress generateSocketAddress(String port) throws SocketException;
abstract int getMaxSessionCount();
abstract int getJobCount();
abstract int getSslPort();
abstract boolean withSSL();
abstract void reconnect(int milsec);
abstract String getVersion();

@ -37,7 +37,11 @@ import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants;
import com.google.common.io.Files;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.yacy.cora.lod.vocabulary.Tagging;
import net.yacy.cora.protocol.TimeoutRequest;
import net.yacy.cora.storage.Configuration.Entry;
import net.yacy.cora.util.ConcurrentLog;
import net.yacy.document.LibraryProvider;
@ -72,6 +76,16 @@ public class migration {
migrateWorkFiles(sb);
}
installSkins(sb); // FIXME: yes, bad fix for quick release 0.47
// ssl/https support currently on hardcoded default port 8443 (v1.67/9563)
// make sure YaCy can start (disable ssl/https support if port is used)
try {
if (TimeoutRequest.ping("127.0.0.1", 8443, 3000)) {
sb.setConfig("server.https", false);
ConcurrentLog.info("MIGRATION", "disabled https support (reason: default port 8443 already used)");
}
} catch (ExecutionException ex) {
}
}
/*
* remove the static defaultfiles. We use them through a overlay now.

@ -3657,7 +3657,7 @@ public final class Switchboard extends serverSwitch {
mySeed.put(Seed.UTC, GenericFormatter.UTCDiffString());
mySeed.setFlagAcceptRemoteCrawl(getConfigBool("crawlResponse", true));
mySeed.setFlagAcceptRemoteIndex(getConfigBool("allowReceiveIndex", true));
mySeed.setFlagSSLAvailable(getConfigBool("server.https", false));
mySeed.setFlagSSLAvailable(this.getHttpServer().withSSL() && getConfigBool("server.https", false));
}
public void loadSeedLists() {

@ -358,7 +358,7 @@ public final class yacy {
final String browserPopUpPage = sb.getConfig(SwitchboardConstants.BROWSER_POP_UP_PAGE, "ConfigBasic.html");
//boolean properPW = (sb.getConfig("adminAccount", "").isEmpty()) && (sb.getConfig(httpd.ADMIN_ACCOUNT_B64MD5, "").length() > 0);
//if (!properPW) browserPopUpPage = "ConfigBasic.html";
Browser.openBrowser((false?"https":"http") + "://localhost:" + port + "/" + browserPopUpPage);
Browser.openBrowser((httpServer.withSSL()?"https://localhost:"+httpServer.getSslPort():"http://localhost:"+port) + "/" + browserPopUpPage);
// Browser.openBrowser((server.withSSL()?"https":"http") + "://localhost:" + serverCore.getPortNr(port) + "/" + browserPopUpPage);
} catch (final Throwable e) {
// cannot open browser. This may be normal in headless environments

Loading…
Cancel
Save