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("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("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";