From 0e31316261e47922c0575bfdcb7fc7f8df730560 Mon Sep 17 00:00:00 2001
From: Steven Allen <steven@stebalien.com>
Date: Thu, 16 Aug 2018 15:56:03 -0700
Subject: [PATCH] only map *usable* addresses

Otherwise, we'll try to port-map localhost.
---
 nat.go | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/nat.go b/nat.go
index d68aca0..0c47a4c 100644
--- a/nat.go
+++ b/nat.go
@@ -3,6 +3,7 @@ package nat
 import (
 	"errors"
 	"fmt"
+	"net"
 	"strconv"
 	"strings"
 	"sync"
@@ -125,15 +126,40 @@ func (nat *NAT) NewMapping(maddr ma.Multiaddr) (Mapping, error) {
 		return nil, fmt.Errorf("DialArgs failed on addr: %s", maddr.String())
 	}
 
+	var ip net.IP
 	switch network {
 	case "tcp", "tcp4", "tcp6":
+		addr, err := net.ResolveTCPAddr(network, addr)
+		if err != nil {
+			return nil, err
+		}
+		ip = addr.IP
 		network = "tcp"
 	case "udp", "udp4", "udp6":
+		addr, err := net.ResolveUDPAddr(network, addr)
+		if err != nil {
+			return nil, err
+		}
+		ip = addr.IP
 		network = "udp"
 	default:
 		return nil, fmt.Errorf("transport not supported by NAT: %s", network)
 	}
 
+	// XXX: Known limitation: doesn't handle multiple internal addresses.
+	// If this applies to you, you can figure it out yourself. Ideally, the
+	// NAT library would allow us to handle this case but the "go way"
+	// appears to be to just "shrug" at edge-cases.
+	if !ip.IsUnspecified() {
+		internalAddr, err := nat.nat.GetInternalAddress()
+		if err != nil {
+			return nil, fmt.Errorf("failed to discover address on nat: %s", err)
+		}
+		if !ip.Equal(internalAddr) {
+			return nil, fmt.Errorf("nat address is %s, refusing to map %s", internalAddr, ip)
+		}
+	}
+
 	intports := strings.Split(addr, ":")[1]
 	intport, err := strconv.Atoi(intports)
 	if err != nil {
-- 
GitLab