-
Notifications
You must be signed in to change notification settings - Fork 12
replace the port number for double NAT mapping #101
Changes from 1 commit
f5a90b9
3960002
741ca1a
9d5510a
4c5f23f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,11 @@ | ||
package autonat | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math/rand" | ||
"net" | ||
"strings" | ||
"sync" | ||
"time" | ||
|
||
|
@@ -117,7 +116,6 @@ func (as *autoNATService) handleDial(p peer.ID, obsaddr ma.Multiaddr, mpi *pb.Me | |
obsHost, _ = manet.ToIP(obsaddr) | ||
} | ||
|
||
obscodename, obsport, _ := as.extractPort(obsaddr) | ||
for _, maddr := range mpi.GetAddrs() { | ||
addr, err := ma.NewMultiaddrBytes(maddr) | ||
if err != nil { | ||
|
@@ -126,18 +124,11 @@ func (as *autoNATService) handleDial(p peer.ID, obsaddr ma.Multiaddr, mpi *pb.Me | |
} | ||
|
||
if as.config.dialPolicy.skipDial(addr) { | ||
if manet.IsPrivateAddr(addr) { | ||
addrcodename, addrport, err := as.extractPort(addr) | ||
if err == nil && addrcodename == obscodename && addrport != obsport { //make a new address | ||
obsportstr := fmt.Sprintf("/%s/%s", obscodename, obsport) | ||
addrportstr := fmt.Sprintf("/%s/%s", addrcodename, addrport) | ||
addr, err = ma.NewMultiaddr(strings.Replace(obsaddr.String(), obsportstr, addrportstr, -1)) //replace the private addr | ||
} else { | ||
continue | ||
} | ||
} else { | ||
continue | ||
succ, newobsaddr := patchObsaddr(addr, obsaddr) | ||
if succ == true { | ||
addr = newobsaddr | ||
} | ||
continue | ||
} | ||
|
||
if ip, err := manet.ToIP(addr); err != nil || !obsHost.Equal(ip) { | ||
|
@@ -243,15 +234,62 @@ func (as *autoNATService) background(ctx context.Context) { | |
} | ||
} | ||
|
||
func (as *autoNATService) extractPort(m ma.Multiaddr) (name string, port string, err error) { | ||
for _, p := range m.Protocols() { | ||
if p.Code == ma.P_TCP || p.Code == ma.P_UDP { | ||
v, err := m.ValueForProtocol(p.Code) | ||
//replace obsaddr's port number with the port number of a | ||
func patchObsaddr(a ma.Multiaddr, obsaddr ma.Multiaddr) (bool, ma.Multiaddr) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. consider a return signature of
huo-ju marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if a == nil || obsaddr == nil { | ||
return false, nil | ||
} | ||
var rawport []byte | ||
var code int | ||
var newc ma.Component | ||
isValid := false | ||
ma.ForEach(a, func(c ma.Component) bool { | ||
switch c.Protocol().Code { | ||
case ma.P_UDP, ma.P_TCP: | ||
code = c.Protocol().Code | ||
rawport = c.RawValue() | ||
newc = c | ||
return !isValid | ||
case ma.P_IP4, ma.P_IP6: | ||
isValid = true | ||
} | ||
return true | ||
}) | ||
|
||
if isValid == true && len(rawport) > 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Or, even better: if !isValid || len(rawport) == 0 {
return ...
} |
||
obsbytes := obsaddr.Bytes() | ||
obsoffset := 0 | ||
isObsValid := false | ||
isReplaced := false | ||
var buffer bytes.Buffer | ||
ma.ForEach(obsaddr, func(c ma.Component) bool { | ||
switch c.Protocol().Code { | ||
case ma.P_UDP, ma.P_TCP: | ||
if code == c.Protocol().Code && isObsValid == true { //obsaddr has the same type protocol, and we can replace it. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for
Comment on lines
+268
to
+269
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. matching the protocol twice seems redundant. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. L268 match both UDP/TCP protocols, but we can replace only the same type protocol. |
||
if bytes.Compare(rawport, c.RawValue()) != 0 { | ||
buffer.Write(obsbytes[:obsoffset]) | ||
buffer.Write(newc.Bytes()) | ||
tail := obsoffset + len(c.Bytes()) | ||
if len(obsbytes)-tail > 0 { | ||
buffer.Write(obsbytes[tail:]) | ||
} | ||
isReplaced = true | ||
} | ||
return false | ||
} | ||
case ma.P_IP4, ma.P_IP6: | ||
isObsValid = true | ||
} | ||
obsoffset += len(c.Bytes()) | ||
return true | ||
}) | ||
if isReplaced == true { | ||
newobsaddr, err := ma.NewMultiaddrBytes(buffer.Bytes()) | ||
if err != nil { | ||
return "", "", err | ||
return false, nil | ||
} | ||
return p.Name, v, nil | ||
return true, newobsaddr | ||
} | ||
} | ||
return "", "", errors.New("can't extract port") | ||
return false, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may skip an address because it's a relay address (e.g.). This logic will continue to dial said addresses.