- Implement config save of new IP address options

- Implement local address and UPnP configuration of UDP address
- Limit received port to 1024 minimum
This commit is contained in:
zzz
2009-05-01 00:42:31 +00:00
parent b21e011203
commit 79a963fcab
7 changed files with 146 additions and 71 deletions

View File

@ -73,7 +73,10 @@ public class Router {
/** used to differentiate routerInfo files on different networks */
public static final int NETWORK_ID = 2;
/** this puts an 'H' in your routerInfo **/
public final static String PROP_HIDDEN = "router.hiddenMode";
/** this does not put an 'H' in your routerInfo **/
public final static String PROP_HIDDEN_HIDDEN = "router.isHidden";
public final static String PROP_DYNAMIC_KEYS = "router.dynamicKeys";
public final static String PROP_INFO_FILENAME = "router.info.location";
public final static String PROP_INFO_FILENAME_DEFAULT = "router.info";
@ -423,7 +426,7 @@ public class Router {
RouterInfo ri = _routerInfo;
if ( (ri != null) && (ri.isHidden()) )
return true;
return Boolean.valueOf(_context.getProperty("router.isHidden", "false")).booleanValue();
return Boolean.valueOf(_context.getProperty(PROP_HIDDEN_HIDDEN)).booleanValue();
}
public Certificate createCertificate() {
Certificate cert = new Certificate();

View File

@ -35,9 +35,9 @@ public interface Transport {
public RouterAddress startListening();
public void stopListening();
public RouterAddress getCurrentAddress();
public static final String SOURCE_UPNP = "UPnP";
public static final String SOURCE_INTERFACE = "Local interface";
public static final String SOURCE_CONFIG = "Configuration change";
public static final String SOURCE_UPNP = "upnp";
public static final String SOURCE_INTERFACE = "local";
public static final String SOURCE_CONFIG = "config"; // unused
public void externalAddressReceived(String source, byte[] ip, int port);
public void forwardPortStatus(int port, boolean success, String reason);
public int getRequestedPort();

View File

@ -542,6 +542,12 @@ public class NTCPTransport extends TransportImpl {
/**
* If we didn't used to be forwarded, and we have an address,
* and we are configured to use UPnP, update our RouterAddress
*
* Don't do anything now. If it fails, we don't know if it's
* because there is no firewall, or if the firewall rejected the request.
* So we just use the SSU reachability status
* to decide whether to enable inbound NTCP. SSU will have CSFI build a new
* NTCP address when it transitions to OK.
*/
public void forwardPortStatus(int port, boolean success, String reason) {
if (_log.shouldLog(Log.WARN)) {

View File

@ -100,6 +100,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String STYLE = "SSU";
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
public static final int DEFAULT_INTERNAL_PORT = 8887;
private static final int MIN_EXTERNAL_PORT = 1024;
/** define this to explicitly set an external IP address */
public static final String PROP_EXTERNAL_HOST = "i2np.udp.host";
@ -118,9 +119,14 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String PROP_PREFER_UDP = "i2np.udp.preferred";
private static final String DEFAULT_PREFER_UDP = "false";
/** if true (default), we don't change our advertised port no matter what our peers tell us */
public static final String PROP_FIXED_PORT = "i2np.udp.fixedPort";
private static final String DEFAULT_FIXED_PORT = "true";
/** allowed sources of address updates */
public static final String PROP_SOURCES = "i2np.udp.addressSources";
public static final String DEFAULT_SOURCES = "local,upnp,ssu";
/** do we require introducers, regardless of our status? */
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
/** do we allow direct SSU connections, sans introducers? */
@ -326,11 +332,21 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
/**
* From config, UPnP, local i/f, ...
*
* @param source used for logging only
* @param ip publicly routable IPv4 only
* @param port 0 if unknown
*/
public void externalAddressReceived(String source, byte[] ip, int port) {
String s = RemoteHostId.toString(ip);
if (_log.shouldLog(Log.WARN))
_log.warn("Received address: " + s + " port: " + port + " from: " + source);
if (explicitAddressSpecified())
return;
String sources = _context.getProperty(PROP_SOURCES, DEFAULT_SOURCES);
if (!sources.contains(source))
return;
changeAddress(ip, port);
}
/**
@ -338,9 +354,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
* Right now, we just blindly trust them, changing our IP and port on a
* whim. this is not good ;)
*
* Todo:
* - Much better tracking of troublemakers
* - Disable if we have good local address or UPnP
*
* @param ip publicly routable IPv4 only
* @param ourPort >= 1024
*/
void externalAddressReceived(Hash from, byte ourIP[], int ourPort) {
boolean isValid = isValid(ourIP);
boolean isValid = isValid(ourIP) && ourPort >= MIN_EXTERNAL_PORT;
boolean explicitSpecified = explicitAddressSpecified();
boolean inboundRecent = _lastInboundReceivedOn + ALLOW_IP_CHANGE_INTERVAL > System.currentTimeMillis();
if (_log.shouldLog(Log.INFO))
@ -350,15 +372,15 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (explicitSpecified)
return;
String sources = _context.getProperty(PROP_SOURCES, DEFAULT_SOURCES);
if (!sources.contains("ssu"))
return;
boolean fixedPort = getIsPortFixed();
boolean updated = false;
boolean fireTest = false;
if (!isValid) {
// ignore them
if (_log.shouldLog(Log.ERROR))
_log.error("The router " + from.toBase64() + " told us we have an invalid IP - "
+ RemoteHostId.toString(ourIP) + ". Lets throw tomatoes at them");
+ RemoteHostId.toString(ourIP) + " port " + ourPort + ". Lets throw tomatoes at them");
markUnreachable(from);
//_context.shitlist().shitlistRouter(from, "They said we had an invalid IP", STYLE);
return;
@ -367,6 +389,19 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (_log.shouldLog(Log.INFO))
_log.info("Ignoring IP address suggestion, since we have received an inbound con recently");
} else {
changeAddress(ourIP, ourPort);
}
}
/**
* @param ourPort >= 1024 or 0 for no change
*/
private void changeAddress(byte ourIP[], int ourPort) {
boolean fixedPort = getIsPortFixed();
boolean updated = false;
boolean fireTest = false;
synchronized (this) {
if ( (_externalListenHost == null) ||
(!eq(_externalListenHost.getAddress(), _externalListenPort, ourIP, ourPort)) ) {
@ -378,11 +413,13 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_log.info("Trying to change our external address...");
try {
_externalListenHost = InetAddress.getByAddress(ourIP);
if (!fixedPort)
if (ourPort >= MIN_EXTERNAL_PORT && !fixedPort)
_externalListenPort = ourPort;
rebuildExternalAddress();
replaceAddress(_externalAddress);
updated = true;
if (_externalListenPort >= MIN_EXTERNAL_PORT) {
rebuildExternalAddress();
replaceAddress(_externalAddress);
updated = true;
}
} catch (UnknownHostException uhe) {
_externalListenHost = null;
if (_log.shouldLog(Log.INFO))
@ -401,8 +438,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_log.info("Same address as the current one");
}
}
}
if (fireTest) {
_context.statManager().addRateData("udp.addressTestInsteadOfUpdate", 1, 0);
_testEvent.forceRun();
@ -417,7 +453,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
SimpleTimer.getInstance().addEvent(_testEvent, 5*1000);
}
}
private static final boolean eq(byte laddr[], int lport, byte raddr[], int rport) {
return (rport == lport) && DataHelper.eq(laddr, raddr);
}