diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java
index ed2f83f07a..4cf8e33211 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigReseedHelper.java
@@ -67,7 +67,8 @@ public class ConfigReseedHelper extends HelperBase {
if ((mode == 0 && disabled) ||
(mode == 1 && !disabled && c.equals("HTTP")) ||
(mode == 2 && !disabled && c.equals("SOCKS4")) ||
- (mode == 3 && !disabled && c.equals("SOCKS5")))
+ (mode == 3 && !disabled && c.equals("SOCKS5")) ||
+ (mode == 4 && !disabled && c.equals("INTERNAL")))
return CHECKED;
return "";
}
diff --git a/apps/routerconsole/jsp/configreseed.jsp b/apps/routerconsole/jsp/configreseed.jsp
index 0777ab2cd5..5d98268672 100644
--- a/apps/routerconsole/jsp/configreseed.jsp
+++ b/apps/routerconsole/jsp/configreseed.jsp
@@ -35,6 +35,9 @@
<%=intl._t("If you are running command-line Tor, reseed through it by configuring SOCKS 5, localhost, port 9050.")%>
+<%=intl._t("If you have some peers but need more, you may try the I2P Outproxy option. Leave the host and port blank.")%>
+<%=intl._t("This will not work for an initial reseed when you have no peers at all.")%>
+
<%=intl._t("Then, click \"{0}\".", intl._t("Save changes and reseed now"))%>
<%=intl._t("The default settings will work for most people.")%>
@@ -138,7 +141,7 @@
<% if (reseedHelper.shouldShowHTTPSProxy()) { %>
-<%=intl._t("Reseed Proxy Type")%>:
+<%=intl._t("Proxy type for https reseed URLs")%>:
>
<%=intl._t("None")%>
>
@@ -146,7 +149,11 @@
>
<%=intl._t("SOCKS 4/4a")%>
>
-<%=intl._t("SOCKS 5")%>
+<%=intl._t("SOCKS 5")%>
+ >
+<%=intl._t("I2P Outproxy")%>
+(<%=intl._t("Not for initial reseed. Leave host and port blank.")%>)
+
<%=intl._t("HTTPS Proxy Host")%>:
" >
<%=intl._t("HTTPS Proxy Port")%>:
@@ -163,7 +170,7 @@
<% } // shouldShowHTTPSProxy %>
<% if (reseedHelper.shouldShowHTTPProxy()) { %>
-<%=intl._t("Enable HTTP Proxy?")%>
+<%=intl._t("Enable proxy for http reseed URLs?")%>
>
<%=intl._t("HTTP Proxy Host")%>:
" >
diff --git a/core/java/src/net/i2p/util/InternalSocket.java b/core/java/src/net/i2p/util/InternalSocket.java
index 8ee9ca3cc4..f7194b03b1 100644
--- a/core/java/src/net/i2p/util/InternalSocket.java
+++ b/core/java/src/net/i2p/util/InternalSocket.java
@@ -8,6 +8,8 @@ import java.net.Socket;
import java.net.SocketAddress;
import java.nio.channels.SocketChannel;
+import net.i2p.I2PAppContext;
+
/**
* A simple in-JVM Socket using Piped Streams.
* We use port numbers just like regular sockets.
@@ -17,11 +19,13 @@ import java.nio.channels.SocketChannel;
public class InternalSocket extends Socket {
private InputStream _is;
private OutputStream _os;
+ private final int _port;
/** server side */
InternalSocket(InputStream is, OutputStream os) {
_is = is;
_os = os;
+ _port = 1;
}
/**
@@ -31,6 +35,7 @@ public class InternalSocket extends Socket {
public InternalSocket(int port) throws IOException {
if (port <= 0)
throw new IOException("bad port number");
+ _port = port;
InternalServerSocket.internalConnect(port, this);
}
@@ -39,7 +44,7 @@ public class InternalSocket extends Socket {
* @param port > 0
*/
public static Socket getSocket(String host, int port) throws IOException {
- if (System.getProperty("router.version") != null &&
+ if (I2PAppContext.getGlobalContext().isRouterContext() &&
(host.equals("127.0.0.1") || host.equals("localhost"))) {
try {
return new InternalSocket(port);
@@ -103,7 +108,8 @@ public class InternalSocket extends Socket {
return 0;
}
- // everything below here unsupported
+ // everything below here unsupported unless otherwise noted
+
/** @deprecated unsupported */
@Deprecated
@Override
@@ -146,12 +152,16 @@ public class InternalSocket extends Socket {
public InetAddress getLocalAddress() {
throw new UnsupportedOperationException();
}
- /** @deprecated unsupported */
- @Deprecated
+
+ /**
+ * Supported as of 0.9.33, prior to that threw UnsupportedOperationException
+ * @return 1 if connected, -1 if not
+ */
@Override
public int getLocalPort() {
- throw new UnsupportedOperationException();
+ return isConnected() ? 1 : -1;
}
+
/** @deprecated unsupported */
@Deprecated
@Override
@@ -164,11 +174,14 @@ public class InternalSocket extends Socket {
public boolean getOOBInline() {
throw new UnsupportedOperationException();
}
- /** @deprecated unsupported */
- @Deprecated
+
+ /**
+ * Supported as of 0.9.33, prior to that threw UnsupportedOperationException
+ * @return if connected: actual port for clients, 1 for servers; -1 if not
+ */
@Override
public int getPort() {
- throw new UnsupportedOperationException();
+ return isConnected() ? _port : 0;
}
/** @deprecated unsupported */
@Deprecated
@@ -194,12 +207,16 @@ public class InternalSocket extends Socket {
public int getSendBufferSize() {
throw new UnsupportedOperationException();
}
- /** @deprecated unsupported */
- @Deprecated
+
+ /**
+ * Supported as of 0.9.33, prior to that threw UnsupportedOperationException
+ * @return -1 always
+ */
@Override
public int getSoLinger() {
- throw new UnsupportedOperationException();
+ return -1;
}
+
/** @deprecated unsupported */
@Deprecated
@Override
@@ -218,12 +235,15 @@ public class InternalSocket extends Socket {
public boolean isBound() {
throw new UnsupportedOperationException();
}
- /** @deprecated unsupported */
- @Deprecated
+
+ /**
+ * Supported as of 0.9.33, prior to that threw UnsupportedOperationException
+ */
@Override
- public boolean isConnected() {
- throw new UnsupportedOperationException();
+ public synchronized boolean isConnected() {
+ return _is != null || _os != null;
}
+
/** @deprecated unsupported */
@Deprecated
@Override
diff --git a/core/java/src/net/i2p/util/SSLEepGet.java b/core/java/src/net/i2p/util/SSLEepGet.java
index d9e90e71bd..a9f047842a 100644
--- a/core/java/src/net/i2p/util/SSLEepGet.java
+++ b/core/java/src/net/i2p/util/SSLEepGet.java
@@ -147,7 +147,10 @@ public class SSLEepGet extends EepGet {
/**
* Use a proxy.
*
- * @param proxyPort must be valid, -1 disallowed, no default
+ * @param proxyHost Must be valid hostname or literal IPv4/v6.
+ * If type is INTERNAL, set to "localhost".
+ * @param proxyPort Must be valid, -1 disallowed, no default.
+ * If type is INTERNAL, set to 4444.
* @since 0.9.33
*/
public SSLEepGet(I2PAppContext ctx, ProxyType type, String proxyHost, int proxyPort,
@@ -158,7 +161,10 @@ public class SSLEepGet extends EepGet {
/**
* Use a proxy.
*
- * @param proxyPort must be valid, -1 disallowed, no default
+ * @param proxyHost Must be valid hostname or literal IPv4/v6.
+ * If type is INTERNAL, set to "localhost".
+ * @param proxyPort Must be valid, -1 disallowed, no default.
+ * If type is INTERNAL, set to 4444.
* @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null.
* This makes repeated fetches from the same host MUCH faster,
* and prevents repeated key store loads even for different hosts.
@@ -183,7 +189,10 @@ public class SSLEepGet extends EepGet {
/**
* Use a proxy.
*
- * @param proxyPort must be valid, -1 disallowed, no default
+ * @param proxyHost Must be valid hostname or literal IPv4/v6.
+ * If type is INTERNAL, set to "localhost".
+ * @param proxyPort Must be valid, -1 disallowed, no default.
+ * If type is INTERNAL, set to 4444.
* @since 0.9.33
*/
public SSLEepGet(I2PAppContext ctx, ProxyType type, String proxyHost, int proxyPort,
@@ -194,7 +203,10 @@ public class SSLEepGet extends EepGet {
/**
* Use a proxy.
*
- * @param proxyPort must be valid, -1 disallowed, no default
+ * @param proxyHost Must be valid hostname or literal IPv4/v6.
+ * If type is INTERNAL, set to "localhost".
+ * @param proxyPort Must be valid, -1 disallowed, no default.
+ * If type is INTERNAL, set to 4444.
* @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null.
* This makes repeated fetches from the same host MUCH faster,
* and prevents repeated key store loads even for different hosts.
@@ -276,6 +288,10 @@ public class SSLEepGet extends EepGet {
ptype = ProxyType.SOCKS4;
} else if (y.equals("SOCKS5")) {
ptype = ProxyType.SOCKS5;
+ } else if (y.equals("I2P")) {
+ ptype = ProxyType.INTERNAL;
+ proxyHost = "localhost";
+ proxyPort = 4444;
} else {
error = true;
}
@@ -333,8 +349,8 @@ public class SSLEepGet extends EepGet {
private static void usage() {
System.err.println("Usage: SSLEepGet [-psyz] https://url\n" +
- " -p proxyHost[:proxyPort] // default port 8080 for HTTPS and 1080 for SOCKS\n" +
- " -y HTTPS|SOCKS4|SOCKS5 // proxy type, default HTTPS if proxyHost is set\n" +
+ " -p proxyHost[:proxyPort] // default port 8080 for HTTPS and 1080 for SOCKS; default localhost:4444 for I2P\n" +
+ " -y HTTPS|SOCKS4|SOCKS5|I2P // proxy type, default HTTPS if proxyHost is set\n" +
" -s save unknown certs\n" +
" -s -s save all certs\n" +
" -z bypass hostname verification");
@@ -698,6 +714,10 @@ public class SSLEepGet extends EepGet {
httpProxyConnect(host, port);
break;
+ case INTERNAL:
+ internalHttpProxyConnect(host, port);
+ break;
+
case SOCKS4:
socksProxyConnect(false, host, port);
break;
@@ -707,7 +727,6 @@ public class SSLEepGet extends EepGet {
break;
case HTTPS:
- case INTERNAL:
case TRANSPARENT:
default:
throw new IOException("Unsupported proxy type " + _proxyType);
@@ -803,6 +822,35 @@ public class SSLEepGet extends EepGet {
} else {
_proxy = new Socket(_proxyHost, _proxyPort);
}
+ httpProxyConnect(_proxy, host, port);
+ }
+
+ /**
+ * Connect to a HTTP proxy.
+ * Proxy address must be in _proxyHost and _proxyPort.
+ * Side effects: Sets _proxy, _proxyIn, _proxyOut,
+ * and other globals via readHeaders()
+ *
+ * @param port what the proxy should connect to, probably 4444
+ * @since 0.9.33
+ */
+ private void internalHttpProxyConnect(String host, int port) throws IOException {
+ // connect to the proxy
+ _proxy = InternalSocket.getSocket(_proxyHost, _proxyPort);
+ httpProxyConnect(_proxy, host, port);
+ }
+
+ /**
+ * Connect to a HTTP proxy.
+ * Proxy address must be in _proxyHost and _proxyPort.
+ * Side effects: Sets _proxyIn, _proxyOut,
+ * and other globals via readHeaders()
+ *
+ * @param host what the proxy should connect to
+ * @param port what the proxy should connect to
+ * @since 0.9.33
+ */
+ private void httpProxyConnect(Socket proxy, String host, int port) throws IOException {
_proxyIn = _proxy.getInputStream();
_proxyOut = _proxy.getOutputStream();
StringBuilder buf = new StringBuilder(64);
diff --git a/history.txt b/history.txt
index 5107bcfdf4..80f9cb43d1 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,12 @@
+2017-11-21 zzz
+ * EepGet: Refuse attempted redirect to HTTPS, won't work
+ * Reseed: Add support for reseeding via outproxy or Orchid (ticket #1841)
+
+2017-11-20 zzz
+ * HTTP Proxy: Better HTTP status message when no outproxy configured
+ * i2prouter: Fix echo -n on OSX
+ * Reseed: Add outproxy and Orchid proxy support (ticket #1841)
+
2017-11-19 zzz
* Debian:
- Fix builds for x32 (ticket #2076)
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 4e28a2c8d2..c10128fe62 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
- public final static long BUILD = 5;
+ public final static long BUILD = 6;
/** for example "-test" */
public final static String EXTRA = "";
diff --git a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
index c08bc5da97..8cef6a9cf3 100644
--- a/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
+++ b/router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java
@@ -32,6 +32,7 @@ import net.i2p.util.EepGet;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
+import net.i2p.util.PortMapper;
import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SSLEepGet;
@@ -299,15 +300,25 @@ public class Reseeder {
_proxyPort = -1;
}
_shouldProxyHTTP = _proxyHost != null && _proxyHost.length() > 0 && _proxyPort > 0;
- if (_context.getBooleanProperty(PROP_SPROXY_ENABLE)) {
- _sproxyHost = _context.getProperty(PROP_SPROXY_HOST);
- _sproxyPort = _context.getProperty(PROP_SPROXY_PORT, -1);
+
+ boolean shouldProxySSL = _context.getBooleanProperty(PROP_SPROXY_ENABLE);
+ SSLEepGet.ProxyType sproxyType;
+ if (shouldProxySSL) {
+ sproxyType = getProxyType();
+ if (sproxyType == SSLEepGet.ProxyType.INTERNAL) {
+ _sproxyHost = "localhost";
+ _sproxyPort = _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY, 4444);
+ } else {
+ _sproxyHost = _context.getProperty(PROP_SPROXY_HOST);
+ _sproxyPort = _context.getProperty(PROP_SPROXY_PORT, -1);
+ }
} else {
+ sproxyType = SSLEepGet.ProxyType.NONE;
_sproxyHost = null;
_sproxyPort = -1;
}
- _shouldProxySSL = _sproxyHost != null && _sproxyHost.length() > 0 && _sproxyPort > 0;
- _sproxyType = _shouldProxySSL ? getProxyType() : SSLEepGet.ProxyType.NONE;
+ _shouldProxySSL = shouldProxySSL && _sproxyHost != null && _sproxyHost.length() > 0 && _sproxyPort > 0;
+ _sproxyType = _shouldProxySSL ? sproxyType : SSLEepGet.ProxyType.NONE;
}
/*
@@ -353,14 +364,15 @@ public class Reseeder {
_checker.setStatus("");
} else {
if (total == 0) {
- System.out.println("Reseed failed " + getDisplayString(_url) + ", check network connection");
+ System.out.println("Reseed failed " + getDisplayString(_url) + "- check network connection");
System.out.println("Ensure that nothing blocks outbound HTTP or HTTPS, check the logs, " +
"and if nothing helps, read the FAQ about reseeding manually.");
if (_url == null || "https".equals(_url.getScheme())) {
if (_sproxyHost != null && _sproxyPort > 0)
- System.out.println("Check HTTPS proxy setting - host: " + _sproxyHost + " port: " + _sproxyPort);
+ System.out.println("Check current proxy setting! Type: " + getDisplayString(_sproxyType) +
+ " Host: " + _sproxyHost + " Port: " + _sproxyPort);
else
- System.out.println("Consider enabling an HTTPS proxy on the reseed configuration page");
+ System.out.println("Consider enabling a proxy for https on the reseed configuration page");
} else {
if (_proxyHost != null && _proxyPort > 0)
System.out.println("Check HTTP proxy setting - host: " + _proxyHost + " port: " + _proxyPort);
@@ -1130,20 +1142,7 @@ public class Reseeder {
boolean ssl = url.startsWith("https://");
if (ssl && _shouldProxySSL) {
buf.append(" (using ");
- switch(_sproxyType) {
- case HTTP:
- buf.append("HTTPS");
- break;
- case SOCKS4:
- buf.append("SOCKS 4/4a");
- break;
- case SOCKS5:
- buf.append("SOCKS 5");
- break;
- default:
- buf.append(_sproxyType.toString());
- break;
- }
+ buf.append(getDisplayString(_sproxyType));
buf.append(" proxy ");
if (_sproxyHost.contains(":"))
buf.append('[').append(_sproxyHost).append(']');
@@ -1162,6 +1161,27 @@ public class Reseeder {
}
return buf.toString();
}
+
+ /**
+ * Display string for what we're fetching.
+ * Untranslated, for logs only.
+ *
+ * @since 0.9.33
+ */
+ private String getDisplayString(SSLEepGet.ProxyType type) {
+ switch(type) {
+ case HTTP:
+ return "HTTPS";
+ case SOCKS4:
+ return "SOCKS 4/4a";
+ case SOCKS5:
+ return "SOCKS 5";
+ case INTERNAL:
+ return "I2P Outproxy";
+ default:
+ return type.toString();
+ }
+ }
}
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";