forked from I2P_Developers/i2p.i2p
Add support for ports to CONNECT proxy
This commit is contained in:
@ -14,6 +14,9 @@ import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.app.ClientApp;
|
||||
import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.app.Outproxy;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.client.streaming.I2PSocketOptions;
|
||||
import net.i2p.data.Base64;
|
||||
@ -34,7 +37,7 @@ import net.i2p.util.PortMapper;
|
||||
* example.com (sent to one of the configured proxies)
|
||||
* )
|
||||
*
|
||||
* (port and protocol are ignored for i2p destinations)
|
||||
* (protocol is ignored for i2p destinations)
|
||||
* CONNECT host
|
||||
* CONNECT host protocol
|
||||
* CONNECT host:port
|
||||
@ -147,6 +150,9 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
String targetRequest = null;
|
||||
boolean usingWWWProxy = false;
|
||||
String currentProxy = null;
|
||||
// local outproxy plugin
|
||||
boolean usingInternalOutproxy = false;
|
||||
Outproxy outproxy = null;
|
||||
long requestId = __requestId.incrementAndGet();
|
||||
try {
|
||||
out = s.getOutputStream();
|
||||
@ -154,6 +160,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
String line, method = null, host = null, destination = null, restofline = null;
|
||||
StringBuilder newRequest = new StringBuilder();
|
||||
String authorization = null;
|
||||
int remotePort = 443;
|
||||
while (true) {
|
||||
// Use this rather than BufferedReader because we can't have readahead,
|
||||
// since we are passing the stream on to I2PTunnelRunner
|
||||
@ -172,8 +179,20 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
String request = line.substring(pos + 1);
|
||||
|
||||
pos = request.indexOf(':');
|
||||
if (pos == -1)
|
||||
if (pos == -1) {
|
||||
pos = request.indexOf(' ');
|
||||
} else {
|
||||
int spos = request.indexOf(' ');
|
||||
if (spos > 0) {
|
||||
try {
|
||||
remotePort = Integer.parseInt(request.substring(pos + 1, spos));
|
||||
} catch (NumberFormatException nfe) {
|
||||
break;
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pos == -1) {
|
||||
host = request;
|
||||
restofline = "";
|
||||
@ -185,19 +204,36 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
if (host.toLowerCase(Locale.US).endsWith(".i2p")) {
|
||||
// Destination gets the host name
|
||||
destination = host;
|
||||
} else if (host.indexOf('.') != -1) {
|
||||
// The request must be forwarded to a outproxy
|
||||
currentProxy = selectProxy();
|
||||
if (currentProxy == null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
|
||||
writeErrorMessage(ERR_NO_OUTPROXY, out);
|
||||
s.close();
|
||||
return;
|
||||
} else if (host.contains(".") || host.startsWith("[")) {
|
||||
if (Boolean.parseBoolean(getTunnel().getClientOptions().getProperty(PROP_USE_OUTPROXY_PLUGIN, "true"))) {
|
||||
ClientAppManager mgr = _context.clientAppManager();
|
||||
if (mgr != null) {
|
||||
ClientApp op = mgr.getRegisteredApp(Outproxy.NAME);
|
||||
if (op != null) {
|
||||
outproxy = (Outproxy) op;
|
||||
usingInternalOutproxy = true;
|
||||
if (host.startsWith("[")) {
|
||||
host = host.substring(1);
|
||||
if (host.endsWith("]"))
|
||||
host = host.substring(0, host.length() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
destination = currentProxy;
|
||||
usingWWWProxy = true;
|
||||
newRequest.append("CONNECT ").append(host).append(restofline).append("\r\n"); // HTTP spec
|
||||
if (!usingInternalOutproxy) {
|
||||
// The request must be forwarded to a outproxy
|
||||
currentProxy = selectProxy();
|
||||
if (currentProxy == null) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn(getPrefix(requestId) + "Host wants to be outproxied, but we dont have any!");
|
||||
writeErrorMessage(ERR_NO_OUTPROXY, out);
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
destination = currentProxy;
|
||||
usingWWWProxy = true;
|
||||
newRequest.append("CONNECT ").append(host).append(restofline).append("\r\n"); // HTTP spec
|
||||
}
|
||||
} else if (host.toLowerCase(Locale.US).equals("localhost")) {
|
||||
writeErrorMessage(ERR_LOCALHOST, out);
|
||||
s.close();
|
||||
@ -208,10 +244,12 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
targetRequest = host;
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
_log.debug(getPrefix(requestId) + "METHOD:" + method + ":");
|
||||
_log.debug(getPrefix(requestId) + "HOST :" + host + ":");
|
||||
_log.debug(getPrefix(requestId) + "REST :" + restofline + ":");
|
||||
_log.debug(getPrefix(requestId) + "DEST :" + destination + ":");
|
||||
_log.debug(getPrefix(requestId) + "METHOD:" + method + ":\n" +
|
||||
"HOST :" + host + ":\n" +
|
||||
"PORT :" + remotePort + ":\n" +
|
||||
"REST :" + restofline + ":\n" +
|
||||
"DEST :" + destination + ":\n" +
|
||||
"www proxy? " + usingWWWProxy + " internal proxy? " + usingInternalOutproxy);
|
||||
}
|
||||
} else if (line.toLowerCase(Locale.US).startsWith("proxy-authorization: ")) {
|
||||
// strip Proxy-Authenticate from the response in HTTPResponseOutputStream
|
||||
@ -250,7 +288,24 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
}
|
||||
}
|
||||
|
||||
if (destination == null || method == null || !"CONNECT".equals(method.toUpperCase(Locale.US))) {
|
||||
if (method == null || !"CONNECT".equals(method.toUpperCase(Locale.US))) {
|
||||
writeErrorMessage(ERR_BAD_PROTOCOL, out);
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// no destination, going to outproxy plugin
|
||||
if (usingInternalOutproxy) {
|
||||
Socket outSocket = outproxy.connect(host, remotePort);
|
||||
OnTimeout onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
|
||||
byte[] response = SUCCESS_RESPONSE.getBytes("UTF-8");
|
||||
Thread t = new I2PTunnelOutproxyRunner(s, outSocket, sockLock, null, response, onTimeout);
|
||||
// we are called from an unlimited thread pool, so run inline
|
||||
t.run();
|
||||
return;
|
||||
}
|
||||
|
||||
if (destination == null) {
|
||||
writeErrorMessage(ERR_BAD_PROTOCOL, out);
|
||||
s.close();
|
||||
return;
|
||||
@ -282,7 +337,10 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
return;
|
||||
}
|
||||
|
||||
I2PSocket i2ps = createI2PSocket(clientDest, getDefaultOptions());
|
||||
I2PSocketOptions sktOpts = getDefaultOptions();
|
||||
if (!usingWWWProxy && remotePort > 0)
|
||||
sktOpts.setPort(remotePort);
|
||||
I2PSocket i2ps = createI2PSocket(clientDest, sktOpts);
|
||||
byte[] data = null;
|
||||
byte[] response = null;
|
||||
if (usingWWWProxy)
|
||||
|
@ -357,8 +357,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
||||
public static final String PROP_JUMP_SERVERS = "i2ptunnel.httpclient.jumpServers";
|
||||
public static final String PROP_DISABLE_HELPER = "i2ptunnel.httpclient.disableAddressHelper";
|
||||
/** @since 0.9.11 */
|
||||
public static final String PROP_USE_OUTPROXY_PLUGIN = "i2ptunnel.useLocalOutproxy";
|
||||
/** @since 0.9.11 */
|
||||
public static final String PROP_SSL_OUTPROXIES = "i2ptunnel.httpclient.SSLOutproxies";
|
||||
/** @since 0.9.14 */
|
||||
public static final String PROP_ACCEPT = "i2ptunnel.httpclient.sendAccept";
|
||||
|
@ -59,6 +59,8 @@ public abstract class I2PTunnelHTTPClientBase extends I2PTunnelClientBase implem
|
||||
private static final int NONCE_BYTES = DataHelper.DATE_LENGTH + MD5_BYTES;
|
||||
private static final long MAX_NONCE_AGE = 60*60*1000L;
|
||||
private static final int MAX_NONCE_COUNT = 1024;
|
||||
/** @since 0.9.11, moved to Base in 0.9.29 */
|
||||
public static final String PROP_USE_OUTPROXY_PLUGIN = "i2ptunnel.useLocalOutproxy";
|
||||
|
||||
private static final String ERR_AUTH1 =
|
||||
"HTTP/1.1 407 Proxy Authentication Required\r\n" +
|
||||
|
@ -14,7 +14,7 @@ import net.i2p.app.ClientApp;
|
||||
import net.i2p.app.ClientAppManager;
|
||||
import net.i2p.app.Outproxy;
|
||||
import net.i2p.client.streaming.I2PSocket;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
|
||||
import net.i2p.i2ptunnel.I2PTunnelHTTPClientBase;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@ -89,7 +89,7 @@ abstract class SOCKSServer {
|
||||
* @since 0.9.27
|
||||
*/
|
||||
private boolean shouldUseOutproxyPlugin() {
|
||||
return Boolean.parseBoolean(props.getProperty(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, "true"));
|
||||
return Boolean.parseBoolean(props.getProperty(I2PTunnelHTTPClientBase.PROP_USE_OUTPROXY_PLUGIN, "true"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -579,7 +579,7 @@ public class GeneralHelper {
|
||||
* Default true
|
||||
*/
|
||||
public boolean getUseOutproxyPlugin(int tunnel) {
|
||||
return getBooleanProperty(tunnel, I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, true);
|
||||
return getBooleanProperty(tunnel, I2PTunnelHTTPClientBase.PROP_USE_OUTPROXY_PLUGIN, true);
|
||||
}
|
||||
|
||||
/** all of these are @since 0.8.3 */
|
||||
|
@ -409,9 +409,9 @@ public class TunnelConfig {
|
||||
|
||||
public void setUseOutproxyPlugin(boolean val) {
|
||||
if (val)
|
||||
_booleanOptions.add(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN);
|
||||
_booleanOptions.add(I2PTunnelHTTPClientBase.PROP_USE_OUTPROXY_PLUGIN);
|
||||
else
|
||||
_booleanOptions.remove(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN);
|
||||
_booleanOptions.remove(I2PTunnelHTTPClientBase.PROP_USE_OUTPROXY_PLUGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -695,7 +695,7 @@ public class TunnelConfig {
|
||||
};
|
||||
private static final String _booleanProxyOpts[] = {
|
||||
I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH,
|
||||
I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN,
|
||||
I2PTunnelHTTPClientBase.PROP_USE_OUTPROXY_PLUGIN,
|
||||
I2PTunnelHTTPClient.PROP_USER_AGENT,
|
||||
I2PTunnelHTTPClient.PROP_REFERER,
|
||||
I2PTunnelHTTPClient.PROP_ACCEPT,
|
||||
|
@ -499,7 +499,7 @@ public class IndexBean {
|
||||
if (tun != null) {
|
||||
if (TunnelController.TYPE_HTTP_CLIENT.equals(tun.getType())) {
|
||||
Properties opts = tun.getClientOptionProps();
|
||||
if (Boolean.parseBoolean(opts.getProperty(I2PTunnelHTTPClient.PROP_USE_OUTPROXY_PLUGIN, "true"))) {
|
||||
if (Boolean.parseBoolean(opts.getProperty(I2PTunnelHTTPClientBase.PROP_USE_OUTPROXY_PLUGIN, "true"))) {
|
||||
ClientAppManager mgr = _context.clientAppManager();
|
||||
if (mgr != null)
|
||||
return mgr.getRegisteredApp(Outproxy.NAME) != null;
|
||||
|
Reference in New Issue
Block a user