Reseed: Add support for reseeding via outproxy or Orchid (ticket #1841)

InternalSocket: Add support for some methods needed for reseed to work
This commit is contained in:
zzz
2017-11-21 01:29:31 +00:00
parent 07a83bf310
commit 8c7898de1e
7 changed files with 154 additions and 49 deletions

View File

@ -67,7 +67,8 @@ public class ConfigReseedHelper extends HelperBase {
if ((mode == 0 && disabled) || if ((mode == 0 && disabled) ||
(mode == 1 && !disabled && c.equals("HTTP")) || (mode == 1 && !disabled && c.equals("HTTP")) ||
(mode == 2 && !disabled && c.equals("SOCKS4")) || (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 CHECKED;
return ""; return "";
} }

View File

@ -35,6 +35,9 @@
</li><li> </li><li>
<%=intl._t("If you are running command-line Tor, reseed through it by configuring SOCKS 5, localhost, port 9050.")%> <%=intl._t("If you are running command-line Tor, reseed through it by configuring SOCKS 5, localhost, port 9050.")%>
</li><li> </li><li>
<%=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.")%>
</li><li>
<%=intl._t("Then, click \"{0}\".", intl._t("Save changes and reseed now"))%> <%=intl._t("Then, click \"{0}\".", intl._t("Save changes and reseed now"))%>
</li><li> </li><li>
<%=intl._t("The default settings will work for most people.")%> <%=intl._t("The default settings will work for most people.")%>
@ -138,7 +141,7 @@
</td></tr> </td></tr>
<% if (reseedHelper.shouldShowHTTPSProxy()) { %> <% if (reseedHelper.shouldShowHTTPSProxy()) { %>
<tr><td align="right"><b><%=intl._t("Reseed Proxy Type")%>:</b></td> <tr><td align="right"><b><%=intl._t("Proxy type for https reseed URLs")%>:</b></td>
<td><label><input type="radio" class="optbox" name="pmode" value="" <%=reseedHelper.pmodeChecked(0) %> > <td><label><input type="radio" class="optbox" name="pmode" value="" <%=reseedHelper.pmodeChecked(0) %> >
<%=intl._t("None")%></label><br> <%=intl._t("None")%></label><br>
<label><input type="radio" class="optbox" name="pmode" value="HTTP" <%=reseedHelper.pmodeChecked(1) %> > <label><input type="radio" class="optbox" name="pmode" value="HTTP" <%=reseedHelper.pmodeChecked(1) %> >
@ -146,7 +149,11 @@
<label><input type="radio" class="optbox" name="pmode" value="SOCKS4" <%=reseedHelper.pmodeChecked(2) %> > <label><input type="radio" class="optbox" name="pmode" value="SOCKS4" <%=reseedHelper.pmodeChecked(2) %> >
<%=intl._t("SOCKS 4/4a")%></label><br> <%=intl._t("SOCKS 4/4a")%></label><br>
<label><input type="radio" class="optbox" name="pmode" value="SOCKS5" <%=reseedHelper.pmodeChecked(3) %> > <label><input type="radio" class="optbox" name="pmode" value="SOCKS5" <%=reseedHelper.pmodeChecked(3) %> >
<%=intl._t("SOCKS 5")%></label></td></tr> <%=intl._t("SOCKS 5")%></label><br>
<label><input type="radio" class="optbox" name="pmode" value="INTERNAL" <%=reseedHelper.pmodeChecked(4) %> >
<%=intl._t("I2P Outproxy")%></label>
(<%=intl._t("Not for initial reseed. Leave host and port blank.")%>)
</td></tr>
<tr><td align="right"><b><%=intl._t("HTTPS Proxy Host")%>:</b></td> <tr><td align="right"><b><%=intl._t("HTTPS Proxy Host")%>:</b></td>
<td><input name="shost" type="text" value="<jsp:getProperty name="reseedHelper" property="shost" />" ></td></tr> <td><input name="shost" type="text" value="<jsp:getProperty name="reseedHelper" property="shost" />" ></td></tr>
<tr><td align="right"><b><%=intl._t("HTTPS Proxy Port")%>:</b></td> <tr><td align="right"><b><%=intl._t("HTTPS Proxy Port")%>:</b></td>
@ -163,7 +170,7 @@
<% } // shouldShowHTTPSProxy %> <% } // shouldShowHTTPSProxy %>
<% if (reseedHelper.shouldShowHTTPProxy()) { %> <% if (reseedHelper.shouldShowHTTPProxy()) { %>
<tr><td align="right"><label for="enableproxy"><b><%=intl._t("Enable HTTP Proxy?")%></b></label></td> <tr><td align="right"><label for="enableproxy"><b><%=intl._t("Enable proxy for http reseed URLs?")%></b></label></td>
<td><input type="checkbox" class="optbox" name="enable" id="enableproxy" value="true" <jsp:getProperty name="reseedHelper" property="enable" /> ></td></tr> <td><input type="checkbox" class="optbox" name="enable" id="enableproxy" value="true" <jsp:getProperty name="reseedHelper" property="enable" /> ></td></tr>
<tr><td align="right"><b><%=intl._t("HTTP Proxy Host")%>:</b></td> <tr><td align="right"><b><%=intl._t("HTTP Proxy Host")%>:</b></td>
<td><input name="host" type="text" value="<jsp:getProperty name="reseedHelper" property="host" />" ></td></tr> <td><input name="host" type="text" value="<jsp:getProperty name="reseedHelper" property="host" />" ></td></tr>

View File

@ -8,6 +8,8 @@ import java.net.Socket;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import net.i2p.I2PAppContext;
/** /**
* A simple in-JVM Socket using Piped Streams. * A simple in-JVM Socket using Piped Streams.
* We use port numbers just like regular sockets. * We use port numbers just like regular sockets.
@ -17,11 +19,13 @@ import java.nio.channels.SocketChannel;
public class InternalSocket extends Socket { public class InternalSocket extends Socket {
private InputStream _is; private InputStream _is;
private OutputStream _os; private OutputStream _os;
private final int _port;
/** server side */ /** server side */
InternalSocket(InputStream is, OutputStream os) { InternalSocket(InputStream is, OutputStream os) {
_is = is; _is = is;
_os = os; _os = os;
_port = 1;
} }
/** /**
@ -31,6 +35,7 @@ public class InternalSocket extends Socket {
public InternalSocket(int port) throws IOException { public InternalSocket(int port) throws IOException {
if (port <= 0) if (port <= 0)
throw new IOException("bad port number"); throw new IOException("bad port number");
_port = port;
InternalServerSocket.internalConnect(port, this); InternalServerSocket.internalConnect(port, this);
} }
@ -39,7 +44,7 @@ public class InternalSocket extends Socket {
* @param port &gt; 0 * @param port &gt; 0
*/ */
public static Socket getSocket(String host, int port) throws IOException { 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"))) { (host.equals("127.0.0.1") || host.equals("localhost"))) {
try { try {
return new InternalSocket(port); return new InternalSocket(port);
@ -103,7 +108,8 @@ public class InternalSocket extends Socket {
return 0; return 0;
} }
// everything below here unsupported // everything below here unsupported unless otherwise noted
/** @deprecated unsupported */ /** @deprecated unsupported */
@Deprecated @Deprecated
@Override @Override
@ -146,12 +152,16 @@ public class InternalSocket extends Socket {
public InetAddress getLocalAddress() { public InetAddress getLocalAddress() {
throw new UnsupportedOperationException(); 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 @Override
public int getLocalPort() { public int getLocalPort() {
throw new UnsupportedOperationException(); return isConnected() ? 1 : -1;
} }
/** @deprecated unsupported */ /** @deprecated unsupported */
@Deprecated @Deprecated
@Override @Override
@ -164,11 +174,14 @@ public class InternalSocket extends Socket {
public boolean getOOBInline() { public boolean getOOBInline() {
throw new UnsupportedOperationException(); 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 @Override
public int getPort() { public int getPort() {
throw new UnsupportedOperationException(); return isConnected() ? _port : 0;
} }
/** @deprecated unsupported */ /** @deprecated unsupported */
@Deprecated @Deprecated
@ -194,12 +207,16 @@ public class InternalSocket extends Socket {
public int getSendBufferSize() { public int getSendBufferSize() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** @deprecated unsupported */
@Deprecated /**
* Supported as of 0.9.33, prior to that threw UnsupportedOperationException
* @return -1 always
*/
@Override @Override
public int getSoLinger() { public int getSoLinger() {
throw new UnsupportedOperationException(); return -1;
} }
/** @deprecated unsupported */ /** @deprecated unsupported */
@Deprecated @Deprecated
@Override @Override
@ -218,12 +235,15 @@ public class InternalSocket extends Socket {
public boolean isBound() { public boolean isBound() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** @deprecated unsupported */
@Deprecated /**
* Supported as of 0.9.33, prior to that threw UnsupportedOperationException
*/
@Override @Override
public boolean isConnected() { public synchronized boolean isConnected() {
throw new UnsupportedOperationException(); return _is != null || _os != null;
} }
/** @deprecated unsupported */ /** @deprecated unsupported */
@Deprecated @Deprecated
@Override @Override

View File

@ -147,7 +147,10 @@ public class SSLEepGet extends EepGet {
/** /**
* Use a proxy. * 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 * @since 0.9.33
*/ */
public SSLEepGet(I2PAppContext ctx, ProxyType type, String proxyHost, int proxyPort, public SSLEepGet(I2PAppContext ctx, ProxyType type, String proxyHost, int proxyPort,
@ -158,7 +161,10 @@ public class SSLEepGet extends EepGet {
/** /**
* Use a proxy. * 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. * @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null.
* This makes repeated fetches from the same host MUCH faster, * This makes repeated fetches from the same host MUCH faster,
* and prevents repeated key store loads even for different hosts. * and prevents repeated key store loads even for different hosts.
@ -183,7 +189,10 @@ public class SSLEepGet extends EepGet {
/** /**
* Use a proxy. * 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 * @since 0.9.33
*/ */
public SSLEepGet(I2PAppContext ctx, ProxyType type, String proxyHost, int proxyPort, public SSLEepGet(I2PAppContext ctx, ProxyType type, String proxyHost, int proxyPort,
@ -194,7 +203,10 @@ public class SSLEepGet extends EepGet {
/** /**
* Use a proxy. * 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. * @param state an SSLState retrieved from a previous SSLEepGet with getSSLState(), or null.
* This makes repeated fetches from the same host MUCH faster, * This makes repeated fetches from the same host MUCH faster,
* and prevents repeated key store loads even for different hosts. * and prevents repeated key store loads even for different hosts.
@ -276,6 +288,10 @@ public class SSLEepGet extends EepGet {
ptype = ProxyType.SOCKS4; ptype = ProxyType.SOCKS4;
} else if (y.equals("SOCKS5")) { } else if (y.equals("SOCKS5")) {
ptype = ProxyType.SOCKS5; ptype = ProxyType.SOCKS5;
} else if (y.equals("I2P")) {
ptype = ProxyType.INTERNAL;
proxyHost = "localhost";
proxyPort = 4444;
} else { } else {
error = true; error = true;
} }
@ -333,8 +349,8 @@ public class SSLEepGet extends EepGet {
private static void usage() { private static void usage() {
System.err.println("Usage: SSLEepGet [-psyz] https://url\n" + System.err.println("Usage: SSLEepGet [-psyz] https://url\n" +
" -p proxyHost[:proxyPort] // default port 8080 for HTTPS and 1080 for SOCKS\n" + " -p proxyHost[:proxyPort] // default port 8080 for HTTPS and 1080 for SOCKS; default localhost:4444 for I2P\n" +
" -y HTTPS|SOCKS4|SOCKS5 // proxy type, default HTTPS if proxyHost is set\n" + " -y HTTPS|SOCKS4|SOCKS5|I2P // proxy type, default HTTPS if proxyHost is set\n" +
" -s save unknown certs\n" + " -s save unknown certs\n" +
" -s -s save all certs\n" + " -s -s save all certs\n" +
" -z bypass hostname verification"); " -z bypass hostname verification");
@ -698,6 +714,10 @@ public class SSLEepGet extends EepGet {
httpProxyConnect(host, port); httpProxyConnect(host, port);
break; break;
case INTERNAL:
internalHttpProxyConnect(host, port);
break;
case SOCKS4: case SOCKS4:
socksProxyConnect(false, host, port); socksProxyConnect(false, host, port);
break; break;
@ -707,7 +727,6 @@ public class SSLEepGet extends EepGet {
break; break;
case HTTPS: case HTTPS:
case INTERNAL:
case TRANSPARENT: case TRANSPARENT:
default: default:
throw new IOException("Unsupported proxy type " + _proxyType); throw new IOException("Unsupported proxy type " + _proxyType);
@ -803,6 +822,35 @@ public class SSLEepGet extends EepGet {
} else { } else {
_proxy = new Socket(_proxyHost, _proxyPort); _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(); _proxyIn = _proxy.getInputStream();
_proxyOut = _proxy.getOutputStream(); _proxyOut = _proxy.getOutputStream();
StringBuilder buf = new StringBuilder(64); StringBuilder buf = new StringBuilder(64);

View File

@ -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 2017-11-19 zzz
* Debian: * Debian:
- Fix builds for x32 (ticket #2076) - Fix builds for x32 (ticket #2076)

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 5; public final static long BUILD = 6;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";

View File

@ -32,6 +32,7 @@ import net.i2p.util.EepGet;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.PortMapper;
import net.i2p.util.SecureDirectory; import net.i2p.util.SecureDirectory;
import net.i2p.util.SecureFileOutputStream; import net.i2p.util.SecureFileOutputStream;
import net.i2p.util.SSLEepGet; import net.i2p.util.SSLEepGet;
@ -299,15 +300,25 @@ public class Reseeder {
_proxyPort = -1; _proxyPort = -1;
} }
_shouldProxyHTTP = _proxyHost != null && _proxyHost.length() > 0 && _proxyPort > 0; _shouldProxyHTTP = _proxyHost != null && _proxyHost.length() > 0 && _proxyPort > 0;
if (_context.getBooleanProperty(PROP_SPROXY_ENABLE)) {
_sproxyHost = _context.getProperty(PROP_SPROXY_HOST); boolean shouldProxySSL = _context.getBooleanProperty(PROP_SPROXY_ENABLE);
_sproxyPort = _context.getProperty(PROP_SPROXY_PORT, -1); 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 { } else {
sproxyType = SSLEepGet.ProxyType.NONE;
_sproxyHost = null; _sproxyHost = null;
_sproxyPort = -1; _sproxyPort = -1;
} }
_shouldProxySSL = _sproxyHost != null && _sproxyHost.length() > 0 && _sproxyPort > 0; _shouldProxySSL = shouldProxySSL && _sproxyHost != null && _sproxyHost.length() > 0 && _sproxyPort > 0;
_sproxyType = _shouldProxySSL ? getProxyType() : SSLEepGet.ProxyType.NONE; _sproxyType = _shouldProxySSL ? sproxyType : SSLEepGet.ProxyType.NONE;
} }
/* /*
@ -353,14 +364,15 @@ public class Reseeder {
_checker.setStatus(""); _checker.setStatus("");
} else { } else {
if (total == 0) { 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, " + System.out.println("Ensure that nothing blocks outbound HTTP or HTTPS, check the logs, " +
"and if nothing helps, read the FAQ about reseeding manually."); "and if nothing helps, read the FAQ about reseeding manually.");
if (_url == null || "https".equals(_url.getScheme())) { if (_url == null || "https".equals(_url.getScheme())) {
if (_sproxyHost != null && _sproxyPort > 0) 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 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 { } else {
if (_proxyHost != null && _proxyPort > 0) if (_proxyHost != null && _proxyPort > 0)
System.out.println("Check HTTP proxy setting - host: " + _proxyHost + " port: " + _proxyPort); System.out.println("Check HTTP proxy setting - host: " + _proxyHost + " port: " + _proxyPort);
@ -1130,20 +1142,7 @@ public class Reseeder {
boolean ssl = url.startsWith("https://"); boolean ssl = url.startsWith("https://");
if (ssl && _shouldProxySSL) { if (ssl && _shouldProxySSL) {
buf.append(" (using "); buf.append(" (using ");
switch(_sproxyType) { buf.append(getDisplayString(_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(" proxy "); buf.append(" proxy ");
if (_sproxyHost.contains(":")) if (_sproxyHost.contains(":"))
buf.append('[').append(_sproxyHost).append(']'); buf.append('[').append(_sproxyHost).append(']');
@ -1162,6 +1161,27 @@ public class Reseeder {
} }
return buf.toString(); 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"; private static final String BUNDLE_NAME = "net.i2p.router.web.messages";