I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit da21c0dd authored by zzz's avatar zzz
Browse files

* UDP: Pick a random port on first install or bind failure -

      No more port 8887 to prevent easy state-level blocking
parent 0133711c
No related branches found
No related tags found
No related merge requests found
...@@ -11,10 +11,6 @@ While you are waiting, please <b>adjust your bandwidth settings</b> on the ...@@ -11,10 +11,6 @@ While you are waiting, please <b>adjust your bandwidth settings</b> on the
<a href="config.jsp">configuration page</a>. <a href="config.jsp">configuration page</a>.
</li> </li>
<li> <li>
If you can, open up <b>port 8887</b> on your firewall, then <b>enable inbound TCP</b> on the
<a href="config.jsp">configuration page</a>.
</li>
<li>
Once you have a "shared clients" destination listed on the left, Once you have a "shared clients" destination listed on the left,
please <b>check out</b> our please <b>check out</b> our
<a href="http://www.i2p2.i2p/faq.html">FAQ</a>. <a href="http://www.i2p2.i2p/faq.html">FAQ</a>.
...@@ -35,9 +31,6 @@ Passe bitte In der Wartezeit <b>deine Einstellungen zur Bandbreite</b> auf der ...@@ -35,9 +31,6 @@ Passe bitte In der Wartezeit <b>deine Einstellungen zur Bandbreite</b> auf der
<a href="config.jsp">Einstellungsseite</a> an. <a href="config.jsp">Einstellungsseite</a> an.
</li> </li>
<li> <li>
Bitte &ouml;ffne sobald m&ouml;glich den <b>Port 8887</b> in deiner Firewall, aktiviere danach den <b>eingehenden TCP Verkehr</b> auf der <a href="config.jsp">Einstellungsseite</a>.
</li>
<li>
Sobald auf der linken Seite eine "shared clients" Verbindung aufgelistet ist <b>besuche bitte</b> unsere <a href="http://www.i2p2.i2p/faq_de.html">FAQ</a>. Sobald auf der linken Seite eine "shared clients" Verbindung aufgelistet ist <b>besuche bitte</b> unsere <a href="http://www.i2p2.i2p/faq_de.html">FAQ</a>.
</li> </li>
<li> <li>
......
...@@ -22,7 +22,11 @@ public class UDPEndpoint { ...@@ -22,7 +22,11 @@ public class UDPEndpoint {
private DatagramSocket _socket; private DatagramSocket _socket;
private InetAddress _bindAddress; private InetAddress _bindAddress;
public UDPEndpoint(RouterContext ctx, UDPTransport transport, int listenPort, InetAddress bindAddress) throws SocketException { /**
* @param listenPort -1 or the requested port, may not be honored
* @param bindAddress null ok
*/
public UDPEndpoint(RouterContext ctx, UDPTransport transport, int listenPort, InetAddress bindAddress) {
_context = ctx; _context = ctx;
_log = ctx.logManager().getLog(UDPEndpoint.class); _log = ctx.logManager().getLog(UDPEndpoint.class);
_transport = transport; _transport = transport;
...@@ -30,23 +34,20 @@ public class UDPEndpoint { ...@@ -30,23 +34,20 @@ public class UDPEndpoint {
_listenPort = listenPort; _listenPort = listenPort;
} }
/** caller should call getListenPort() after this to get the actual bound port and determine success */
public void startup() { public void startup() {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Starting up the UDP endpoint"); _log.debug("Starting up the UDP endpoint");
shutdown(); shutdown();
try { _socket = getSocket();
if (_bindAddress == null) if (_socket == null) {
_socket = new DatagramSocket(_listenPort); _log.log(Log.CRIT, "UDP Unable to open a port");
else return;
_socket = new DatagramSocket(_listenPort, _bindAddress);
_sender = new UDPSender(_context, _socket, "UDPSender");
_receiver = new UDPReceiver(_context, _transport, _socket, "UDPReceiver");
_sender.startup();
_receiver.startup();
} catch (SocketException se) {
_transport.setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
_log.log(Log.CRIT, "Unable to bind on port " + _listenPort, se);
} }
_sender = new UDPSender(_context, _socket, "UDPSender");
_receiver = new UDPReceiver(_context, _transport, _socket, "UDPReceiver");
_sender.startup();
_receiver.startup();
} }
public void shutdown() { public void shutdown() {
...@@ -60,6 +61,8 @@ public class UDPEndpoint { ...@@ -60,6 +61,8 @@ public class UDPEndpoint {
} }
public void setListenPort(int newPort) { _listenPort = newPort; } public void setListenPort(int newPort) { _listenPort = newPort; }
/*******
public void updateListenPort(int newPort) { public void updateListenPort(int newPort) {
if (newPort == _listenPort) return; if (newPort == _listenPort) return;
try { try {
...@@ -76,7 +79,54 @@ public class UDPEndpoint { ...@@ -76,7 +79,54 @@ public class UDPEndpoint {
_log.error("Unable to bind on " + _listenPort); _log.error("Unable to bind on " + _listenPort);
} }
} }
********/
/** 8998 is monotone, and 32000 is the wrapper, so let's stay between those */
private static final int MIN_RANDOM_PORT = 9111;
private static final int MAX_RANDOM_PORT = 31777;
private static final int MAX_PORT_RETRIES = 20;
/**
* Open socket using requested port in _listenPort and bind host in _bindAddress.
* If _listenPort <= 0, or requested port is busy, repeatedly try a new random port.
* @return null on failure
* Sets _listenPort to actual port or -1 on failure
*/
private DatagramSocket getSocket() {
DatagramSocket socket = null;
int port = _listenPort;
for (int i = 0; i < MAX_PORT_RETRIES; i++) {
if (port <= 0) {
// try random ports rather than just do new DatagramSocket()
// so we stay out of the way of other I2P stuff
port = MIN_RANDOM_PORT + _context.random().nextInt(MAX_RANDOM_PORT - MIN_RANDOM_PORT);
}
try {
if (_bindAddress == null)
socket = new DatagramSocket(port);
else
socket = new DatagramSocket(port, _bindAddress);
break;
} catch (SocketException se) {
if (_log.shouldLog(Log.WARN))
_log.warn("Binding to port " + port + " failed: " + se);
}
port = -1;
}
if (socket == null) {
_log.log(Log.CRIT, "SSU Unable to bind to a port on " + _bindAddress);
} else if (port != _listenPort) {
if (_listenPort > 0)
_log.error("SSU Unable to bind to requested port " + _listenPort + ", using random port " + port);
else
_log.error("SSU selected random port " + port);
}
_listenPort = port;
return socket;
}
/** call after startup() to get actual port or -1 on startup failure */
public int getListenPort() { return _listenPort; } public int getListenPort() { return _listenPort; }
public UDPSender getSender() { return _sender; } public UDPSender getSender() { return _sender; }
......
...@@ -100,6 +100,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -100,6 +100,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String STYLE = "SSU"; public static final String STYLE = "SSU";
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort"; public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
/** now unused, we pick a random port */
public static final int DEFAULT_INTERNAL_PORT = 8887; public static final int DEFAULT_INTERNAL_PORT = 8887;
/** since fixed port defaults to true, this doesnt do anything at the moment. /** since fixed port defaults to true, this doesnt do anything at the moment.
* We should have an exception if it matches the existing low port. */ * We should have an exception if it matches the existing low port. */
...@@ -137,6 +138,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -137,6 +138,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers"; public static final String PROP_FORCE_INTRODUCERS = "i2np.udp.forceIntroducers";
/** do we allow direct SSU connections, sans introducers? */ /** do we allow direct SSU connections, sans introducers? */
public static final String PROP_ALLOW_DIRECT = "i2np.udp.allowDirect"; public static final String PROP_ALLOW_DIRECT = "i2np.udp.allowDirect";
/** this is rarely if ever used, default is to bind to wildcard address */
public static final String PROP_BIND_INTERFACE = "i2np.udp.bindInterface"; public static final String PROP_BIND_INTERFACE = "i2np.udp.bindInterface";
/** how many relays offered to us will we use at a time? */ /** how many relays offered to us will we use at a time? */
...@@ -226,40 +228,41 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -226,40 +228,41 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
System.arraycopy(_context.routerHash().getData(), 0, _introKey.getData(), 0, SessionKey.KEYSIZE_BYTES); System.arraycopy(_context.routerHash().getData(), 0, _introKey.getData(), 0, SessionKey.KEYSIZE_BYTES);
rebuildExternalAddress(); rebuildExternalAddress();
// bind host
String bindTo = _context.getProperty(PROP_BIND_INTERFACE);
InetAddress bindToAddr = null;
if (bindTo != null) {
try {
bindToAddr = InetAddress.getByName(bindTo);
} catch (UnknownHostException uhe) {
_log.log(Log.CRIT, "Invalid SSU bind interface specified [" + bindTo + "]", uhe);
setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
return;
}
}
int port = -1; // Requested bind port
// This may be -1 or may not be honored if busy,
// we will check below after starting up the endpoint.
int port;
int oldIPort = _context.getProperty(PROP_INTERNAL_PORT, -1);
int oldEPort = _context.getProperty(PROP_EXTERNAL_PORT, -1);
if (_externalListenPort <= 0) { if (_externalListenPort <= 0) {
// no explicit external port, so lets try an internal one // no explicit external port, so lets try an internal one
port = _context.getProperty(PROP_INTERNAL_PORT, DEFAULT_INTERNAL_PORT); if (oldIPort > 0)
// attempt to use it as our external port - this will be overridden by port = oldIPort;
// externalAddressReceived(...) else
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, port+""); port = oldEPort;
_context.router().saveConfig();
} else { } else {
port = _externalListenPort; port = _externalListenPort;
if (_log.shouldLog(Log.INFO))
_log.info("Binding to the explicitly specified external port: " + port);
} }
if (_log.shouldLog(Log.INFO))
_log.info("Binding to the port: " + port);
if (_endpoint == null) { if (_endpoint == null) {
String bindTo = _context.getProperty(PROP_BIND_INTERFACE); _endpoint = new UDPEndpoint(_context, this, port, bindToAddr);
InetAddress bindToAddr = null;
if (bindTo != null) {
try {
bindToAddr = InetAddress.getByName(bindTo);
} catch (UnknownHostException uhe) {
if (_log.shouldLog(Log.ERROR))
_log.error("Invalid SSU bind interface specified [" + bindTo + "]", uhe);
bindToAddr = null;
}
}
try {
_endpoint = new UDPEndpoint(_context, this, port, bindToAddr);
} catch (SocketException se) {
if (_log.shouldLog(Log.CRIT))
_log.log(Log.CRIT, "Unable to listen on the UDP port (" + port + ")", se);
return;
}
} else { } else {
// todo, set bind address too
_endpoint.setListenPort(port); _endpoint.setListenPort(port);
} }
...@@ -278,7 +281,24 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -278,7 +281,24 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (_flooder == null) if (_flooder == null)
_flooder = new UDPFlooder(_context, this); _flooder = new UDPFlooder(_context, this);
// Startup the endpoint with the requested port, check the actual port, and
// take action if it failed or was different than requested or it needs to be saved
_endpoint.startup(); _endpoint.startup();
int newPort = _endpoint.getListenPort();
_externalListenPort = newPort;
if (newPort <= 0) {
_log.log(Log.CRIT, "Unable to open UDP port");
setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
return;
}
if (newPort != port || newPort != oldIPort || newPort != oldEPort) {
// attempt to use it as our external port - this will be overridden by
// externalAddressReceived(...)
_context.router().setConfigSetting(PROP_INTERNAL_PORT, newPort+"");
_context.router().setConfigSetting(PROP_EXTERNAL_PORT, newPort+"");
_context.router().saveConfig();
}
_establisher.startup(); _establisher.startup();
_handler.startup(); _handler.startup();
_fragments.startup(); _fragments.startup();
...@@ -321,11 +341,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -321,11 +341,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public int getLocalPort() { return _externalListenPort; } public int getLocalPort() { return _externalListenPort; }
public InetAddress getLocalAddress() { return _externalListenHost; } public InetAddress getLocalAddress() { return _externalListenHost; }
public int getExternalPort() { return _externalListenPort; } public int getExternalPort() { return _externalListenPort; }
/**
* _externalListenPort should always be set (by startup()) before this is called,
* so the returned value should be > 0
*/
@Override @Override
public int getRequestedPort() { public int getRequestedPort() {
if (_externalListenPort > 0) if (_externalListenPort > 0)
return _externalListenPort; return _externalListenPort;
return _context.getProperty(PROP_INTERNAL_PORT, DEFAULT_INTERNAL_PORT); return _context.getProperty(PROP_INTERNAL_PORT, -1);
} }
/** /**
...@@ -2003,6 +2028,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -2003,6 +2028,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append(" <td align=\"center\"><b>").append(resentTotal); buf.append(" <td align=\"center\"><b>").append(resentTotal);
buf.append("</b></td> <td align=\"center\"><b>").append(dupRecvTotal).append("</b></td>\n"); buf.append("</b></td> <td align=\"center\"><b>").append(dupRecvTotal).append("</b></td>\n");
buf.append(" </tr></table></div>\n"); buf.append(" </tr></table></div>\n");
/*****
long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes(); long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
// NPE here early // NPE here early
double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue(); double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue();
...@@ -2012,6 +2039,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority ...@@ -2012,6 +2039,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
double bwResent = (nondupSent <= 0 ? 0d : ((((double)resentTotal)*averagePacketSize) / nondupSent)); double bwResent = (nondupSent <= 0 ? 0d : ((((double)resentTotal)*averagePacketSize) / nondupSent));
buf.append("<h3>Percentage of bytes retransmitted (lifetime): ").append(formatPct(bwResent)); buf.append("<h3>Percentage of bytes retransmitted (lifetime): ").append(formatPct(bwResent));
buf.append("</h3><i>(Includes retransmission required by packet loss)</i>\n"); buf.append("</h3><i>(Includes retransmission required by packet loss)</i>\n");
*****/
out.write(buf.toString()); out.write(buf.toString());
buf.setLength(0); buf.setLength(0);
out.write(KEY); out.write(KEY);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment