UPnP: Bind to IPv6 addresses for search responses

Older miniupnpd 2.0 will send a SSDP search response with an IPv6 location to a IPv4 address,
but newer ones 2.2 won't. So we need to also bind to an IPv6 address for the SSDP search
to receive the router's IPv6 location. Then we can bind to our public IPv6 address
for a port forward and it will work when miniupnpd is configured for "secure".

Also, don't bind a POST request to a mismatched v4/v6 address.
This commit is contained in:
zzz
2021-06-11 09:29:16 -04:00
parent d5a499591d
commit d93e16e52e
4 changed files with 33 additions and 9 deletions

View File

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

View File

@@ -681,13 +681,18 @@ public class UPnP extends ControlPoint implements DeviceChangeListener, EventLis
* @since 0.9.46
*/
static Set<String> getLocalAddresses() {
Set<String> addrs = Addresses.getAddresses(true, false, false);
// older miniupnpd will send ipv6 ssdp search response to ipv4 address,
// but newer ones won't. So we need to bind to an ipv6 address
// to get his ipv6 address so we can bind to OUR ipv6 address
// for a port forward when miniupnpd is configured for "secure".
// local, no loopback, ipv6, no temp. ipv6
Set<String> addrs = Addresses.getAddresses(true, false, true, false);
// remove public addresses
// see TransportManager.startListening()
for (Iterator<String> iter = addrs.iterator(); iter.hasNext(); ) {
String addr = iter.next();
byte[] ip = Addresses.getIP(addr);
if (ip == null || TransportUtil.isPubliclyRoutable(ip, false))
if (ip == null || TransportUtil.isPubliclyRoutable(ip, true))
iter.remove();
}
return addrs;

View File

@@ -423,8 +423,16 @@ public class HTTPRequest extends HTTPPacket
// And set the soTimeout to 2 second (for reads).
//postSocket = new Socket(host, port);
postSocket = new Socket();
if (bindTo != null)
postSocket.bind(new InetSocketAddress(bindTo, 0));
if (bindTo != null) {
boolean fromv6 = bindTo.contains(":");
boolean tov6 = host.contains(":");
if (fromv6 == tov6) {
//Debug.warning("POST bindTo " + bindTo + " connect to " + host);
postSocket.bind(new InetSocketAddress(bindTo, 0));
} else {
Debug.warning("POST mismatch, NOT binding to " + bindTo + " connect to " + host);
}
}
postSocket.setSoTimeout(2000);
SocketAddress sa = new InetSocketAddress(host, port);
postSocket.connect(sa, 3000);