* I2CP: Move SSL client socket code to util,

move cert location to certificates/i2cp.
 * I2PTunnel: Support SSL for connection to local server
   for Standard, HTTP, and IRC server tunnels.
   Put server cert in certificates/i2ptunnel if necessary.
This commit is contained in:
zzz
2013-10-17 13:22:17 +00:00
parent 09548358fa
commit 5f7a761e42
12 changed files with 210 additions and 137 deletions

View File

@@ -148,7 +148,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
setEntry(headers, "Accept-encoding", "");
socket.setReadTimeout(readTimeout);
Socket s = new Socket(remoteHost, remotePort);
Socket s = getSocket(remoteHost, remotePort);
long afterSocket = getTunnel().getContext().clock().now();
// instead of i2ptunnelrunner, use something that reads the HTTP
// request from the socket, modifies the headers, sends the request to the

View File

@@ -137,7 +137,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
buf.append("\r\n");
modifiedRegistration = buf.toString();
}
Socket s = new Socket(remoteHost, remotePort);
Socket s = getSocket(remoteHost, remotePort);
new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
} catch (SocketException ex) {
try {

View File

@@ -14,6 +14,7 @@ import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.security.GeneralSecurityException;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.Executors;
@@ -33,6 +34,7 @@ import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.data.Base64;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
import net.i2p.util.I2PSSLSocketFactory;
import net.i2p.util.Log;
public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
@@ -43,11 +45,13 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
private final Object lock = new Object();
protected final Object slock = new Object();
protected final Object sslLock = new Object();
protected final InetAddress remoteHost;
protected final int remotePort;
private final boolean _usePool;
protected final Logging l;
private I2PSSLSocketFactory _sslFactory;
private static final long DEFAULT_READ_TIMEOUT = 5*60*1000;
/** default timeout to 5 minutes - override if desired */
@@ -56,6 +60,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
/** do we use threads? default true (ignored for standard servers, always false) */
private static final String PROP_USE_POOL = "i2ptunnel.usePool";
private static final boolean DEFAULT_USE_POOL = true;
public static final String PROP_USE_SSL = "useSSL";
/** apparently unused */
protected static volatile long __serverId = 0;
/** max number of threads - this many slowlorisses will DOS this server, but too high could OOM the JVM */
@@ -462,17 +467,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
if (_log.shouldLog(Log.INFO))
_log.info("Incoming connection to '" + toString() + "' port " + socket.getLocalPort() +
" from: " + socket.getPeerDestination().calculateHash() + " port " + socket.getPort());
long afterAccept = I2PAppContext.getGlobalContext().clock().now();
long afterAccept = getTunnel().getContext().clock().now();
long afterSocket = -1;
//local is fast, so synchronously. Does not need that many
//threads.
try {
socket.setReadTimeout(readTimeout);
Socket s = new Socket(remoteHost, remotePort);
afterSocket = I2PAppContext.getGlobalContext().clock().now();
Socket s = getSocket(remoteHost, remotePort);
afterSocket = getTunnel().getContext().clock().now();
new I2PTunnelRunner(s, socket, slock, null, null);
long afterHandle = I2PAppContext.getGlobalContext().clock().now();
long afterHandle = getTunnel().getContext().clock().now();
long timeToHandle = afterHandle - afterAccept;
if ( (timeToHandle > 1000) && (_log.shouldLog(Log.WARN)) )
_log.warn("Took a while to handle the request for " + remoteHost + ':' + remotePort +
@@ -487,5 +492,31 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
_log.error("Error while waiting for I2PConnections", ex);
}
}
/**
* Get a regular or SSL socket depending on config
*
* @since 0.9.9
*/
protected Socket getSocket(InetAddress remoteHost, int remotePort) throws IOException {
String opt = getTunnel().getClientOptions().getProperty(PROP_USE_SSL);
if (Boolean.parseBoolean(opt)) {
synchronized(sslLock) {
if (_sslFactory == null) {
try {
_sslFactory = new I2PSSLSocketFactory(getTunnel().getContext(),
true, "certificates/i2ptunnel");
} catch (GeneralSecurityException gse) {
IOException ioe = new IOException("SSL Fail");
ioe.initCause(gse);
throw ioe;
}
}
}
return _sslFactory.createSocket(remoteHost, remotePort);
} else {
return new Socket(remoteHost, remotePort);
}
}
}

View File

@@ -407,7 +407,7 @@ public class TunnelController implements Logging {
/**
* These are the ones stored with a prefix of "option."
*
* @return keys with the "option." prefix stripped
* @return keys with the "option." prefix stripped, non-null
* @since 0.9.1 Much better than getClientOptions()
*/
public Properties getClientOptionProps() {

View File

@@ -31,6 +31,7 @@ import net.i2p.i2ptunnel.I2PTunnelConnectClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.I2PTunnelServer;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.util.Addresses;
@@ -770,6 +771,21 @@ public class IndexBean {
_booleanOptions.add(I2PTunnelIRCClient.PROP_DCC);
}
/** @since 0.9.9 */
public void setUseSSL(String moo) {
_booleanOptions.add(I2PTunnelServer.PROP_USE_SSL);
}
/** @since 0.9.9 */
public boolean isSSLEnabled(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun != null) {
Properties opts = tun.getClientOptionProps();
return Boolean.parseBoolean(opts.getProperty(I2PTunnelServer.PROP_USE_SSL));
}
return false;
}
protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList";
protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList";
@@ -1149,7 +1165,8 @@ public class IndexBean {
I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH
};
private static final String _booleanServerOpts[] = {
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST,
I2PTunnelServer.PROP_USE_SSL
};
private static final String _otherClientOpts[] = {
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime",