forked from I2P_Developers/i2p.i2p
Console: Redirect to HTTPS if available (ticket #2160)
Show console links as HTTPS if available Extend blacklisted ports to cover HTTPS console and eepsite
This commit is contained in:
@ -11,6 +11,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.PortMapper;
|
||||||
|
|
||||||
import org.apache.http.conn.util.InetAddressUtils;
|
import org.apache.http.conn.util.InetAddressUtils;
|
||||||
|
|
||||||
@ -29,7 +30,9 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
|
|||||||
public class HostCheckHandler extends HandlerWrapper
|
public class HostCheckHandler extends HandlerWrapper
|
||||||
{
|
{
|
||||||
private final I2PAppContext _context;
|
private final I2PAppContext _context;
|
||||||
|
private final PortMapper _portMapper;
|
||||||
private final Set<String> _listenHosts;
|
private final Set<String> _listenHosts;
|
||||||
|
private static final String PROP_REDIRECT = "routerconsole.redirectToHTTPS";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MUST call setListenHosts() afterwards.
|
* MUST call setListenHosts() afterwards.
|
||||||
@ -37,6 +40,7 @@ public class HostCheckHandler extends HandlerWrapper
|
|||||||
public HostCheckHandler(I2PAppContext ctx) {
|
public HostCheckHandler(I2PAppContext ctx) {
|
||||||
super();
|
super();
|
||||||
_context = ctx;
|
_context = ctx;
|
||||||
|
_portMapper = ctx.portMapper();
|
||||||
_listenHosts = new HashSet<String>(8);
|
_listenHosts = new HashSet<String>(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +57,9 @@ public class HostCheckHandler extends HandlerWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block by Host header, pass everything else to the delegate.
|
* Block by Host header,
|
||||||
|
* redirect HTTP to HTTPS,
|
||||||
|
* pass everything else to the delegate.
|
||||||
*/
|
*/
|
||||||
public void handle(String pathInContext,
|
public void handle(String pathInContext,
|
||||||
Request baseRequest,
|
Request baseRequest,
|
||||||
@ -75,6 +81,22 @@ public class HostCheckHandler extends HandlerWrapper
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// redirect HTTP to HTTPS if available, AND:
|
||||||
|
// either 1) PROP_REDIRECT is set to true;
|
||||||
|
// or 2) PROP_REDIRECT is unset and the Upgrade-Insecure-Requests request header is set
|
||||||
|
// https://w3c.github.io/webappsec-upgrade-insecure-requests/
|
||||||
|
if (!httpRequest.isSecure()) {
|
||||||
|
int httpsPort = _portMapper.getPort(PortMapper.SVC_HTTPS_CONSOLE);
|
||||||
|
if (httpsPort > 0 && httpRequest.getLocalPort() != httpsPort) {
|
||||||
|
String redir = _context.getProperty(PROP_REDIRECT);
|
||||||
|
if (Boolean.valueOf(redir) ||
|
||||||
|
(redir == null && "1".equals(httpRequest.getHeader("Upgrade-Insecure-Requests")))) {
|
||||||
|
sendRedirect(httpsPort, httpRequest, httpResponse);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
super.handle(pathInContext, baseRequest, httpRequest, httpResponse);
|
super.handle(pathInContext, baseRequest, httpRequest, httpResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +113,11 @@ public class HostCheckHandler extends HandlerWrapper
|
|||||||
return true;
|
return true;
|
||||||
// common cases
|
// common cases
|
||||||
if (host.equals("127.0.0.1:7657") ||
|
if (host.equals("127.0.0.1:7657") ||
|
||||||
host.equals("localhost:7657"))
|
host.equals("localhost:7657") ||
|
||||||
|
host.equals("[::1]:7657") ||
|
||||||
|
host.equals("127.0.0.1:7667") ||
|
||||||
|
host.equals("localhost:7667") ||
|
||||||
|
host.equals("[::1]:7667"))
|
||||||
return true;
|
return true;
|
||||||
// all allowed?
|
// all allowed?
|
||||||
if (_listenHosts.isEmpty())
|
if (_listenHosts.isEmpty())
|
||||||
@ -124,4 +150,32 @@ public class HostCheckHandler extends HandlerWrapper
|
|||||||
}
|
}
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect to HTTPS
|
||||||
|
*
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
private static void sendRedirect(int httpsPort, HttpServletRequest httpRequest,
|
||||||
|
HttpServletResponse httpResponse) throws IOException {
|
||||||
|
StringBuilder buf = new StringBuilder(64);
|
||||||
|
buf.append("https://");
|
||||||
|
String name = httpRequest.getServerName();
|
||||||
|
boolean ipv6 = name.indexOf(':') >= 0 && !name.startsWith("[");
|
||||||
|
if (ipv6)
|
||||||
|
buf.append('[');
|
||||||
|
buf.append(name);
|
||||||
|
if (ipv6)
|
||||||
|
buf.append(']');
|
||||||
|
buf.append(':').append(httpsPort)
|
||||||
|
.append(httpRequest.getRequestURI());
|
||||||
|
String q = httpRequest.getQueryString();
|
||||||
|
if (q != null)
|
||||||
|
buf.append('?').append(q);
|
||||||
|
httpResponse.setHeader("Location", buf.toString());
|
||||||
|
// https://w3c.github.io/webappsec-upgrade-insecure-requests/
|
||||||
|
httpResponse.setHeader("Vary", "Upgrade-Insecure-Requests");
|
||||||
|
httpResponse.setStatus(307);
|
||||||
|
httpResponse.flushBuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import net.i2p.I2PAppContext;
|
|||||||
*/
|
*/
|
||||||
public class PortMapper {
|
public class PortMapper {
|
||||||
private final ConcurrentHashMap<String, InetSocketAddress> _dir;
|
private final ConcurrentHashMap<String, InetSocketAddress> _dir;
|
||||||
|
public static final String PROP_PREFER_HTTPS = "routerconsole.preferHTTPS";
|
||||||
|
|
||||||
public static final String SVC_CONSOLE = "console";
|
public static final String SVC_CONSOLE = "console";
|
||||||
public static final String SVC_HTTPS_CONSOLE = "https_console";
|
public static final String SVC_HTTPS_CONSOLE = "https_console";
|
||||||
@ -177,16 +178,39 @@ public class PortMapper {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @return http URL unless console is https only. Default http://127.0.0.1:7657/
|
* If PROP_PREFER_HTTPS is true or unset,
|
||||||
|
* return https URL unless console is http only. Default https://127.0.0.1:7667/
|
||||||
|
* If PROP_PREFER_HTTPS is set to false,
|
||||||
|
* return http URL unless console is https only. Default http://127.0.0.1:7657/
|
||||||
|
*
|
||||||
* @since 0.9.33 consolidated from i2ptunnel and desktopgui
|
* @since 0.9.33 consolidated from i2ptunnel and desktopgui
|
||||||
*/
|
*/
|
||||||
public String getConsoleURL() {
|
public String getConsoleURL() {
|
||||||
|
return getConsoleURL(I2PAppContext.getGlobalContext().getBooleanPropertyDefaultTrue(PROP_PREFER_HTTPS));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If preferHTTPS is true,
|
||||||
|
* return https URL unless console is http only. Default https://127.0.0.1:7667/
|
||||||
|
* If preferHTTPS is false,
|
||||||
|
* return http URL unless console is https only. Default http://127.0.0.1:7657/
|
||||||
|
*
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
public String getConsoleURL(boolean preferHTTPS) {
|
||||||
|
return preferHTTPS ? getHTTPSConsoleURL() : getHTTPConsoleURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return http URL unless console is https only. Default http://127.0.0.1:7657/
|
||||||
|
*/
|
||||||
|
private String getHTTPConsoleURL() {
|
||||||
String unset = "*unset*";
|
String unset = "*unset*";
|
||||||
String httpHost = getActualHost(SVC_CONSOLE, unset);
|
String httpHost = getActualHost(SVC_CONSOLE, unset);
|
||||||
String httpsHost = getActualHost(SVC_HTTPS_CONSOLE, unset);
|
String httpsHost = getActualHost(SVC_HTTPS_CONSOLE, unset);
|
||||||
int httpPort = getPort(SVC_CONSOLE, 7657);
|
int httpPort = getPort(SVC_CONSOLE, 7657);
|
||||||
int httpsPort = getPort(SVC_HTTPS_CONSOLE, -1);
|
int httpsPort = getPort(SVC_HTTPS_CONSOLE);
|
||||||
boolean httpsOnly = httpsPort > 0 && httpHost.equals(unset) && !httpsHost.equals(unset);
|
boolean httpsOnly = httpsPort > 0 && httpHost.equals(unset) && !httpsHost.equals(unset);
|
||||||
if (httpsOnly)
|
if (httpsOnly)
|
||||||
return "https://" + httpsHost + ':' + httpsPort + '/';
|
return "https://" + httpsHost + ':' + httpsPort + '/';
|
||||||
@ -195,6 +219,24 @@ public class PortMapper {
|
|||||||
return "http://" + httpHost + ':' + httpPort + '/';
|
return "http://" + httpHost + ':' + httpPort + '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return https URL unless console is http only. Default https://127.0.0.1:7667/
|
||||||
|
* @since 0.9.34
|
||||||
|
*/
|
||||||
|
private String getHTTPSConsoleURL() {
|
||||||
|
String unset = "*unset*";
|
||||||
|
String httpHost = getActualHost(SVC_CONSOLE, unset);
|
||||||
|
String httpsHost = getActualHost(SVC_HTTPS_CONSOLE, unset);
|
||||||
|
int httpPort = getPort(SVC_CONSOLE);
|
||||||
|
int httpsPort = getPort(SVC_HTTPS_CONSOLE, 7667);
|
||||||
|
boolean httpOnly = httpPort > 0 && httpsHost.equals(unset) && !httpHost.equals(unset);
|
||||||
|
if (httpOnly)
|
||||||
|
return "http://" + httpHost + ':' + httpPort + '/';
|
||||||
|
if (httpsHost.equals(unset))
|
||||||
|
httpsHost = "127.0.0.1";
|
||||||
|
return "https://" + httpsHost + ':' + httpsPort + '/';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For debugging only
|
* For debugging only
|
||||||
* @since 0.9.20
|
* @since 0.9.20
|
||||||
|
16
history.txt
16
history.txt
@ -1,3 +1,19 @@
|
|||||||
|
2018-02-20 zzz
|
||||||
|
* Console:
|
||||||
|
- Redirect to HTTPS if available (ticket #2160)
|
||||||
|
- Change all 302s to 303 or 307
|
||||||
|
- Change sendError() to setStatus() for 3xx responses
|
||||||
|
* Crypto: Backdate selfsigned cert to allow for clock skew
|
||||||
|
* Eepget: Handle 308
|
||||||
|
|
||||||
|
2018-02-19 zzz
|
||||||
|
* Console:
|
||||||
|
- Change trac links (ticket #2014)
|
||||||
|
- Change selfsigned cert cname to localhost (ticket #2160)
|
||||||
|
* Crypto: Add IP addresses to selfsigned cert SAN (ticket #2160)
|
||||||
|
* Streaming: Don't exceed configured tag settings
|
||||||
|
* Time: More sanity checks on NTP responses
|
||||||
|
|
||||||
2018-02-18 zzz
|
2018-02-18 zzz
|
||||||
* i2ptunnel: Retry accept after router soft restart (ticket #2003)
|
* i2ptunnel: Retry accept after router soft restart (ticket #2003)
|
||||||
|
|
||||||
|
@ -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 = 7;
|
public final static long BUILD = 8;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
@ -239,7 +239,7 @@ public abstract class TransportUtil {
|
|||||||
port != 6000 && // lockd
|
port != 6000 && // lockd
|
||||||
(!(port >= 6665 && port <= 6669)) && // IRC and alternates
|
(!(port >= 6665 && port <= 6669)) && // IRC and alternates
|
||||||
port != 6697 && // IRC+TLS
|
port != 6697 && // IRC+TLS
|
||||||
(!(port >= 7650 && port <= 7664)) && // standard I2P range
|
(!(port >= 7650 && port <= 7668)) && // standard I2P range
|
||||||
port != 8998 && // mtn
|
port != 8998 && // mtn
|
||||||
port != 9001 && // Tor
|
port != 9001 && // Tor
|
||||||
port != 9030 && // Tor
|
port != 9030 && // Tor
|
||||||
|
@ -117,7 +117,7 @@ class UDPEndpoint implements SocketListener {
|
|||||||
if (port > 0 && !TransportUtil.isValidPort(port)) {
|
if (port > 0 && !TransportUtil.isValidPort(port)) {
|
||||||
_log.error("Specified UDP port " + port + " is not valid, selecting a new port");
|
_log.error("Specified UDP port " + port + " is not valid, selecting a new port");
|
||||||
// See isValidPort() for list
|
// See isValidPort() for list
|
||||||
_log.error("Invalid ports are: 0-1023, 1900, 2049, 2827, 3659, 4045, 4444, 4445, 6000, 6665-6669, 6697, 7650-7664, 8998, 9001, 9030, 9050, 9100, 9150, 31000, 32000, 65536+");
|
_log.error("Invalid ports are: 0-1023, 1900, 2049, 2827, 3659, 4045, 4444, 4445, 6000, 6665-6669, 6697, 7650-7668, 8998, 9001, 9030, 9050, 9100, 9150, 31000, 32000, 65536+");
|
||||||
port = -1;
|
port = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user