Transport: Add config to force IPv4 (only) to firewalled (ticket #1541)

since we cannot reliably detect DS-lite (ticket #1458)
Hide transport status on /peers unless routerconsole.advanced
This commit is contained in:
zzz
2015-05-06 01:45:33 +00:00
parent 31435685bf
commit abd8ca34dc
8 changed files with 83 additions and 15 deletions

View File

@ -50,6 +50,7 @@ public class ConfigNetHandler extends FormHandler {
private boolean _ratesOnly; private boolean _ratesOnly;
private boolean _udpDisabled; private boolean _udpDisabled;
private String _ipv6Mode; private String _ipv6Mode;
private boolean _ipv4Firewalled;
private final Map<String, String> changes = new HashMap<String, String>(); private final Map<String, String> changes = new HashMap<String, String>();
private static final String PROP_HIDDEN = Router.PROP_HIDDEN_HIDDEN; // see Router for other choice private static final String PROP_HIDDEN = Router.PROP_HIDDEN_HIDDEN; // see Router for other choice
@ -79,8 +80,12 @@ public class ConfigNetHandler extends FormHandler {
public void setNtcpAutoPort(String mode) { public void setNtcpAutoPort(String mode) {
_ntcpAutoPort = mode.equals("2"); _ntcpAutoPort = mode.equals("2");
} }
public void setUpnp(String moo) { _upnp = true; } public void setUpnp(String moo) { _upnp = true; }
public void setLaptop(String moo) { _laptop = true; } public void setLaptop(String moo) { _laptop = true; }
/** @since 0.9.20 */
public void setIPv4Firewalled(String moo) { _ipv4Firewalled = true; }
public void setHostname(String hostname) { public void setHostname(String hostname) {
_hostname = (hostname != null ? hostname.trim() : null); _hostname = (hostname != null ? hostname.trim() : null);
@ -348,6 +353,16 @@ public class ConfigNetHandler extends FormHandler {
} }
changes.put(UDPTransport.PROP_LAPTOP_MODE, "" + _laptop); changes.put(UDPTransport.PROP_LAPTOP_MODE, "" + _laptop);
if (Boolean.parseBoolean(_context.getProperty(TransportUtil.PROP_IPV4_FIREWALLED)) !=
_ipv4Firewalled) {
if (_ipv4Firewalled)
addFormNotice(_("Disabling inbound IPv4"));
else
addFormNotice(_("Enabling inbound IPv4"));
restartRequired = true;
}
changes.put(TransportUtil.PROP_IPV4_FIREWALLED, "" + _ipv4Firewalled);
if (_context.getBooleanPropertyDefaultTrue(TransportManager.PROP_ENABLE_UDP) != if (_context.getBooleanPropertyDefaultTrue(TransportManager.PROP_ENABLE_UDP) !=
!_udpDisabled) { !_udpDisabled) {
if (_udpDisabled) if (_udpDisabled)

View File

@ -93,6 +93,11 @@ public class ConfigNetHelper extends HelperBase {
return getChecked(UDPTransport.PROP_LAPTOP_MODE); return getChecked(UDPTransport.PROP_LAPTOP_MODE);
} }
/** @since 0.9.20 */
public String getIPv4FirewalledChecked() {
return getChecked(TransportUtil.PROP_IPV4_FIREWALLED);
}
public String getTcpAutoPortChecked(int mode) { public String getTcpAutoPortChecked(int mode) {
String port = _context.getProperty(PROP_I2NP_NTCP_PORT); String port = _context.getProperty(PROP_I2NP_NTCP_PORT);
boolean specified = port != null && port.length() > 0; boolean specified = port != null && port.length() > 0;

View File

@ -51,6 +51,10 @@
<%=intl._("Laptop mode - Change router identity and UDP port when IP changes for enhanced anonymity")%> <%=intl._("Laptop mode - Change router identity and UDP port when IP changes for enhanced anonymity")%>
(<i><%=intl._("Experimental")%></i>) (<i><%=intl._("Experimental")%></i>)
</p><p> </p><p>
<%=intl._("IPv4 Configuration")%>:<br>
<input type="checkbox" class="optbox" name="IPv4Firewalled" value="true" <jsp:getProperty name="nethelper" property="IPv4FirewalledChecked" /> >
<%=intl._("Disable inbound (Firewalled by Carrier-grade NAT or DS-Lite)")%>
</p><p>
<%=intl._("IPv6 Configuration")%>:<br> <%=intl._("IPv6 Configuration")%>:<br>
<input type="radio" class="optbox" name="ipv6" value="false" <%=nethelper.getIPv6Checked("false") %> > <input type="radio" class="optbox" name="ipv6" value="false" <%=nethelper.getIPv6Checked("false") %> >
<%=intl._("Disable IPv6")%><br> <%=intl._("Disable IPv6")%><br>

View File

@ -813,6 +813,14 @@ public abstract class TransportImpl implements Transport {
*/ */
public void recheckReachability() {} public void recheckReachability() {}
/**
* @param transportStyle ignored
* @since 0.9.20
*/
protected boolean isIPv4Firewalled() {
return TransportUtil.isIPv4Firewalled(_context, getStyle());
}
public boolean isBacklogged(Hash dest) { return false; } public boolean isBacklogged(Hash dest) { return false; }
public boolean isEstablished(Hash dest) { return false; } public boolean isEstablished(Hash dest) { return false; }

View File

@ -60,6 +60,8 @@ public class TransportManager implements TransportEventListener {
public final static String PROP_ENABLE_NTCP = "i2np.ntcp.enable"; public final static String PROP_ENABLE_NTCP = "i2np.ntcp.enable";
/** default true */ /** default true */
public final static String PROP_ENABLE_UPNP = "i2np.upnp.enable"; public final static String PROP_ENABLE_UPNP = "i2np.upnp.enable";
private static final String PROP_ADVANCED = "routerconsole.advanced";
/** not forever, since they may update */ /** not forever, since they may update */
private static final long SIGTYPE_BANLIST_DURATION = 36*60*60*1000L; private static final long SIGTYPE_BANLIST_DURATION = 36*60*60*1000L;
@ -667,11 +669,13 @@ public class TransportManager implements TransportEventListener {
* will take many seconds if it has vanished. * will take many seconds if it has vanished.
*/ */
public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException { public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
out.write("<p>"); if (_context.getBooleanProperty(PROP_ADVANCED)) {
out.write(_("Status")); out.write("<p><b>");
out.write(": "); out.write(_("Status"));
out.write(_(getReachabilityStatus().toStatusString())); out.write(": ");
out.write("</p>"); out.write(_(getReachabilityStatus().toStatusString()));
out.write("</b></p>");
}
TreeMap<String, Transport> transports = new TreeMap<String, Transport>(); TreeMap<String, Transport> transports = new TreeMap<String, Transport>();
for (Transport t : _transports.values()) { for (Transport t : _transports.values()) {
transports.put(t.getStyle(), t); transports.put(t.getStyle(), t);

View File

@ -23,6 +23,7 @@ public abstract class TransportUtil {
public static final String NTCP_IPV6_CONFIG = "i2np.ntcp.ipv6"; public static final String NTCP_IPV6_CONFIG = "i2np.ntcp.ipv6";
public static final String SSU_IPV6_CONFIG = "i2np.udp.ipv6"; public static final String SSU_IPV6_CONFIG = "i2np.udp.ipv6";
public static final String PROP_IPV4_FIREWALLED = "i2np.ipv4.firewalled";
public enum IPv6Config { public enum IPv6Config {
/** IPv6 disabled */ /** IPv6 disabled */
@ -83,6 +84,14 @@ public abstract class TransportUtil {
return DEFAULT_IPV6_CONFIG; return DEFAULT_IPV6_CONFIG;
} }
/**
* @param transportStyle ignored
* @since 0.9.20
*/
public static boolean isIPv4Firewalled(RouterContext ctx, String transportStyle) {
return ctx.getBooleanProperty(PROP_IPV4_FIREWALLED);
}
/** /**
* Addresses without a host (i.e. w/introducers) * Addresses without a host (i.e. w/introducers)
* are assumed to be IPv4 * are assumed to be IPv4

View File

@ -1344,7 +1344,9 @@ public class NTCPTransport extends TransportImpl {
buf.append("<h3 id=\"ntcpcon\">").append(_("NTCP connections")).append(": ").append(peers.size()); buf.append("<h3 id=\"ntcpcon\">").append(_("NTCP connections")).append(": ").append(peers.size());
buf.append(". ").append(_("Limit")).append(": ").append(getMaxConnections()); buf.append(". ").append(_("Limit")).append(": ").append(getMaxConnections());
buf.append(". ").append(_("Timeout")).append(": ").append(DataHelper.formatDuration2(_pumper.getIdleTimeout())); buf.append(". ").append(_("Timeout")).append(": ").append(DataHelper.formatDuration2(_pumper.getIdleTimeout()));
buf.append(". ").append(_("Status")).append(": ").append(_(getReachabilityStatus().toStatusString())); if (_context.getBooleanProperty(PROP_ADVANCED)) {
buf.append(". ").append(_("Status")).append(": ").append(_(getReachabilityStatus().toStatusString()));
}
buf.append(".</h3>\n" + buf.append(".</h3>\n" +
"<table>\n" + "<table>\n" +
"<tr><th><a href=\"#def.peer\">").append(_("Peer")).append("</a></th>" + "<tr><th><a href=\"#def.peer\">").append(_("Peer")).append("</a></th>" +

View File

@ -167,6 +167,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String PROP_BIND_INTERFACE = "i2np.udp.bindInterface"; public static final String PROP_BIND_INTERFACE = "i2np.udp.bindInterface";
/** override the "large" (max) MTU, default is PeerState.LARGE_MTU */ /** override the "large" (max) MTU, default is PeerState.LARGE_MTU */
private static final String PROP_DEFAULT_MTU = "i2np.udp.mtu"; private static final String PROP_DEFAULT_MTU = "i2np.udp.mtu";
private static final String PROP_ADVANCED = "routerconsole.advanced";
private static final String CAP_TESTING = "" + UDPAddress.CAPACITY_TESTING; private static final String CAP_TESTING = "" + UDPAddress.CAPACITY_TESTING;
private static final String CAP_TESTING_INTRO = "" + UDPAddress.CAPACITY_TESTING + UDPAddress.CAPACITY_INTRODUCER; private static final String CAP_TESTING_INTRO = "" + UDPAddress.CAPACITY_TESTING + UDPAddress.CAPACITY_INTRODUCER;
@ -457,6 +458,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
//if (SHOULD_FLOOD_PEERS) //if (SHOULD_FLOOD_PEERS)
// _flooder.startup(); // _flooder.startup();
_expireEvent.setIsAlive(true); _expireEvent.setIsAlive(true);
_reachabilityStatus = Status.UNKNOWN;
_testEvent.setIsAlive(true); // this queues it for 3-6 minutes in the future... _testEvent.setIsAlive(true); // this queues it for 3-6 minutes in the future...
_testEvent.reschedule(10*1000); // lets requeue it for Real Soon _testEvent.reschedule(10*1000); // lets requeue it for Real Soon
@ -477,7 +479,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_lastInboundIPv6 = _context.clock().now(); _lastInboundIPv6 = _context.clock().now();
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK); setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK);
} else { } else {
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN); if (!isIPv4Firewalled())
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
} }
rebuildExternalAddress(ia.getHostAddress(), newPort, false); rebuildExternalAddress(ia.getHostAddress(), newPort, false);
} }
@ -487,11 +490,18 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_lastInboundIPv6 = _context.clock().now(); _lastInboundIPv6 = _context.clock().now();
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK); setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK);
} else { } else {
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN); if (!isIPv4Firewalled())
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
} }
rebuildExternalAddress(ia.getHostAddress(), newPort, false); rebuildExternalAddress(ia.getHostAddress(), newPort, false);
} }
} }
if (isIPv4Firewalled()) {
if (_lastInboundIPv6 > 0)
setReachabilityStatus(Status.IPV4_FIREWALLED_IPV6_UNKNOWN);
else
setReachabilityStatus(Status.REJECT_UNSOLICITED);
}
rebuildExternalAddress(false); rebuildExternalAddress(false);
} }
@ -763,12 +773,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
// Assume if we have an interface with a public IP that we aren't firewalled. // Assume if we have an interface with a public IP that we aren't firewalled.
// If this is wrong, the peer test will figure it out and change the status. // If this is wrong, the peer test will figure it out and change the status.
if (changed && source == SOURCE_INTERFACE) { if (changed && source == SOURCE_INTERFACE) {
if (ip.length == 4) if (ip.length == 4) {
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN); if (!isIPv4Firewalled())
else if (ip.length == 16) setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
} else if (ip.length == 16) {
// TODO should we set both to unknown and wait for an inbound v6 conn, // TODO should we set both to unknown and wait for an inbound v6 conn,
// since there's no v6 testing? // since there's no v6 testing?
setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK); setReachabilityStatus(Status.IPV4_UNKNOWN_IPV6_OK);
}
} }
} }
@ -786,8 +798,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
else else
_log.warn("UPnP has failed to open the SSU port: " + port + " reason: " + reason); _log.warn("UPnP has failed to open the SSU port: " + port + " reason: " + reason);
} }
if (success && ip != null && getExternalIP() != null) if (success && ip != null && getExternalIP() != null) {
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN); if (!isIPv4Firewalled())
setReachabilityStatus(Status.IPV4_OK_IPV6_UNKNOWN);
}
} }
/** /**
@ -2434,7 +2448,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append("<h3 id=\"udpcon\">").append(_("UDP connections")).append(": ").append(peers.size()); buf.append("<h3 id=\"udpcon\">").append(_("UDP connections")).append(": ").append(peers.size());
buf.append(". ").append(_("Limit")).append(": ").append(getMaxConnections()); buf.append(". ").append(_("Limit")).append(": ").append(getMaxConnections());
buf.append(". ").append(_("Timeout")).append(": ").append(DataHelper.formatDuration2(_expireTimeout)); buf.append(". ").append(_("Timeout")).append(": ").append(DataHelper.formatDuration2(_expireTimeout));
buf.append(". ").append(_("Status")).append(": ").append(_(_reachabilityStatus.toStatusString())); if (_context.getBooleanProperty(PROP_ADVANCED)) {
buf.append(". ").append(_("Status")).append(": ").append(_(_reachabilityStatus.toStatusString()));
}
buf.append(".</h3>\n"); buf.append(".</h3>\n");
buf.append("<table>\n"); buf.append("<table>\n");
buf.append("<tr><th class=\"smallhead\" nowrap><a href=\"#def.peer\">").append(_("Peer")).append("</a><br>"); buf.append("<tr><th class=\"smallhead\" nowrap><a href=\"#def.peer\">").append(_("Peer")).append("</a><br>");
@ -3003,7 +3019,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
} }
private boolean shouldTest() { private boolean shouldTest() {
return ! _context.router().isHidden(); return ! (_context.router().isHidden() ||
isIPv4Firewalled());
//String val = _context.getProperty(PROP_SHOULD_TEST); //String val = _context.getProperty(PROP_SHOULD_TEST);
//return ( (val != null) && ("true".equals(val)) ); //return ( (val != null) && ("true".equals(val)) );
} }
@ -3053,6 +3070,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
* @since 0.9.13 * @since 0.9.13
*/ */
public synchronized void forceRunSoon() { public synchronized void forceRunSoon() {
if (isIPv4Firewalled())
return;
_forceRun = true; _forceRun = true;
reschedule(MIN_TEST_FREQUENCY); reschedule(MIN_TEST_FREQUENCY);
} }
@ -3063,6 +3082,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
* @since 0.9.13 * @since 0.9.13
*/ */
public synchronized void forceRunImmediately() { public synchronized void forceRunImmediately() {
if (isIPv4Firewalled())
return;
_lastTested.set(0); _lastTested.set(0);
_forceRun = true; _forceRun = true;
reschedule(5*1000); reschedule(5*1000);