forked from I2P_Developers/i2p.i2p
Add server option for unique local address per-client
as suggested in https://lists.torproject.org/pipermail/tor-dev/2014-March/006576.html
This commit is contained in:
@@ -277,7 +277,7 @@ public class I2PTunnelHTTPServer extends I2PTunnelServer {
|
||||
setEntry(headers, "Accept-encoding", "");
|
||||
|
||||
socket.setReadTimeout(readTimeout);
|
||||
Socket s = getSocket(socket.getLocalPort());
|
||||
Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort());
|
||||
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
|
||||
|
@@ -137,7 +137,7 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
|
||||
buf.append("\r\n");
|
||||
modifiedRegistration = buf.toString();
|
||||
}
|
||||
Socket s = getSocket(socket.getLocalPort());
|
||||
Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort());
|
||||
new I2PTunnelRunner(s, socket, slock, null, modifiedRegistration.getBytes(), null);
|
||||
} catch (SocketException ex) {
|
||||
try {
|
||||
|
@@ -11,6 +11,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
@@ -33,6 +34,7 @@ import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketManager;
|
||||
import net.i2p.client.streaming.I2PSocketManagerFactory;
|
||||
import net.i2p.data.Base64;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.util.EventDispatcher;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.I2PSSLSocketFactory;
|
||||
@@ -62,6 +64,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
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";
|
||||
public static final String PROP_UNIQUE_LOCAL = "enableUniqueLocal";
|
||||
/** 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 */
|
||||
@@ -518,7 +521,7 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
//threads.
|
||||
try {
|
||||
socket.setReadTimeout(readTimeout);
|
||||
Socket s = getSocket(socket.getLocalPort());
|
||||
Socket s = getSocket(socket.getPeerDestination().calculateHash(), socket.getLocalPort());
|
||||
afterSocket = getTunnel().getContext().clock().now();
|
||||
new I2PTunnelRunner(s, socket, slock, null, null);
|
||||
|
||||
@@ -543,9 +546,10 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
* To configure a specific host:port as the server for incoming port xx,
|
||||
* set option targetForPort.xx=host:port
|
||||
*
|
||||
* @param from may be used to construct local address since 0.9.13
|
||||
* @since 0.9.9
|
||||
*/
|
||||
protected Socket getSocket(int incomingPort) throws IOException {
|
||||
protected Socket getSocket(Hash from, int incomingPort) throws IOException {
|
||||
InetAddress host = remoteHost;
|
||||
int port = remotePort;
|
||||
if (incomingPort != 0 && !_socketMap.isEmpty()) {
|
||||
@@ -557,16 +561,17 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
port = isa.getPort();
|
||||
}
|
||||
}
|
||||
return getSocket(host, port);
|
||||
return getSocket(from, host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a regular or SSL socket depending on config.
|
||||
* The SSL config applies to all hosts/ports.
|
||||
*
|
||||
* @param from may be used to construct local address since 0.9.13
|
||||
* @since 0.9.9
|
||||
*/
|
||||
protected Socket getSocket(InetAddress remoteHost, int remotePort) throws IOException {
|
||||
protected Socket getSocket(Hash from, InetAddress remoteHost, int remotePort) throws IOException {
|
||||
String opt = getTunnel().getClientOptions().getProperty(PROP_USE_SSL);
|
||||
if (Boolean.parseBoolean(opt)) {
|
||||
synchronized(sslLock) {
|
||||
@@ -583,7 +588,26 @@ public class I2PTunnelServer extends I2PTunnelTask implements Runnable {
|
||||
}
|
||||
return _sslFactory.createSocket(remoteHost, remotePort);
|
||||
} else {
|
||||
return new Socket(remoteHost, remotePort);
|
||||
// as suggested in https://lists.torproject.org/pipermail/tor-dev/2014-March/006576.html
|
||||
boolean unique = Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_UNIQUE_LOCAL));
|
||||
if (unique && remoteHost.isLoopbackAddress()) {
|
||||
byte[] addr;
|
||||
if (remoteHost instanceof Inet4Address) {
|
||||
addr = new byte[4];
|
||||
addr[0] = 127;
|
||||
System.arraycopy(from.getData(), 0, addr, 1, 3);
|
||||
} else {
|
||||
addr = new byte[16];
|
||||
addr[0] = (byte) 0xfd;
|
||||
System.arraycopy(from.getData(), 0, addr, 1, 15);
|
||||
}
|
||||
InetAddress local = InetAddress.getByAddress(addr);
|
||||
// Javadocs say local port of 0 allowed in Java 7.
|
||||
// Not clear if supported in Java 6 or not.
|
||||
return new Socket(remoteHost, remotePort, local, 0);
|
||||
} else {
|
||||
return new Socket(remoteHost, remotePort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@ import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPServer;
|
||||
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;
|
||||
@@ -325,6 +326,11 @@ public class EditBean extends IndexBean {
|
||||
return getProperty(tunnel, I2PTunnelHTTPServer.OPT_POST_TOTAL_BAN_TIME, I2PTunnelHTTPServer.DEFAULT_POST_TOTAL_BAN_TIME) / 60;
|
||||
}
|
||||
|
||||
/** @since 0.9.13 */
|
||||
public boolean getUniqueLocal(int tunnel) {
|
||||
return getBooleanProperty(tunnel, I2PTunnelServer.PROP_UNIQUE_LOCAL);
|
||||
}
|
||||
|
||||
private int getProperty(int tunnel, String prop, int def) {
|
||||
TunnelController tun = getController(tunnel);
|
||||
if (tun != null) {
|
||||
|
@@ -823,6 +823,11 @@ public class IndexBean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @since 0.9.13 */
|
||||
public void setUniqueLocal(String moo) {
|
||||
_booleanOptions.add(I2PTunnelServer.PROP_UNIQUE_LOCAL);
|
||||
}
|
||||
|
||||
protected static final String PROP_ENABLE_ACCESS_LIST = "i2cp.enableAccessList";
|
||||
protected static final String PROP_ENABLE_BLACKLIST = "i2cp.enableBlackList";
|
||||
|
||||
@@ -1259,7 +1264,8 @@ public class IndexBean {
|
||||
private static final String _booleanServerOpts[] = {
|
||||
"i2cp.reduceOnIdle", "i2cp.encryptLeaseSet", PROP_ENABLE_ACCESS_LIST, PROP_ENABLE_BLACKLIST,
|
||||
I2PTunnelServer.PROP_USE_SSL,
|
||||
I2PTunnelHTTPServer.OPT_REJECT_INPROXY
|
||||
I2PTunnelHTTPServer.OPT_REJECT_INPROXY,
|
||||
I2PTunnelServer.PROP_UNIQUE_LOCAL
|
||||
};
|
||||
private static final String _otherClientOpts[] = {
|
||||
"i2cp.reduceIdleTime", "i2cp.reduceQuantity", "i2cp.closeIdleTime",
|
||||
|
@@ -206,9 +206,15 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
||||
<%=intl._("Local destination")%>(<span class="accessKey">L</span>):
|
||||
</label>
|
||||
<textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Read Only: Local Destination (if known)" wrap="off" spellcheck="false"><%=editBean.getDestinationBase64(curTunnel)%></textarea>
|
||||
<% if (!"".equals(editBean.getDestinationBase64(curTunnel))) { %>
|
||||
<a href="/susidns/addressbook.jsp?book=private&hostname=<%=editBean.getTunnelName(curTunnel)%>&destination=<%=editBean.getDestinationBase64(curTunnel)%>#add"><%=intl._("Add to local addressbook")%></a>
|
||||
<% } %>
|
||||
<% String b64 = editBean.getDestinationBase64(curTunnel);
|
||||
if (!"".equals(b64)) {
|
||||
String name = editBean.getSpoofedHost(curTunnel);
|
||||
if (name == null || name.equals(""))
|
||||
name = editBean.getTunnelName(curTunnel);
|
||||
if (!"".equals(name)) { %>
|
||||
<a href="/susidns/addressbook.jsp?book=private&hostname=<%=name%>&destination=<%=b64%>#add"><%=intl._("Add to local addressbook")%></a>
|
||||
<% }
|
||||
} %>
|
||||
</div>
|
||||
|
||||
<% if (("httpserver".equals(tunnelType)) || ("httpbidirserver".equals(tunnelType))) {
|
||||
@@ -396,7 +402,20 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
|
||||
</div>
|
||||
</div>
|
||||
<% } // httpserver
|
||||
%><div class="subdivider">
|
||||
%><div class="rowItem">
|
||||
<div id="optionsField" class="rowItem">
|
||||
<label>
|
||||
<%=intl._("Unique Local Address per Client")%>:
|
||||
</label>
|
||||
</div>
|
||||
<div id="portField" class="rowItem">
|
||||
<label for="access" accesskey="d">
|
||||
<%=intl._("Enable")%>:
|
||||
</label>
|
||||
<input value="1" type="checkbox" id="startOnLoad" name="uniqueLocal" title="Use unique IP addresses for each connecting client (local non-SSL servers only)"<%=(editBean.getUniqueLocal(curTunnel) ? " checked=\"checked\"" : "")%> class="tickbox" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="subdivider">
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
|
Reference in New Issue
Block a user