summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrew Dunham <andrew@du.nham.ca>2023-08-22 10:38:41 -0400
committerAndrew Dunham <andrew@du.nham.ca>2023-11-15 19:44:07 -0500
commit5ab17bd3dddfd249b1e0fff8ba678d0c635e2fa0 (patch)
treea16f2bd71e30e923b4799f5ad6e9f216b43ca947
parent57129205e6860019e2c87d5069c7c4812845fb15 (diff)
downloadtailscale-andrew/upnp-unfork.tar.xz
tailscale-andrew/upnp-unfork.zip
net/portmapper: use the upstream goupnp library instead of our forkandrew/upnp-unfork
Signed-off-by: Andrew Dunham <andrew@du.nham.ca> Change-Id: Iabf9fc4e158f45e4fc385f2b4c2e55ba01351c5c
-rw-r--r--cmd/tailscale/depaware.txt16
-rw-r--r--cmd/tailscaled/depaware.txt14
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--net/portmapper/upnp.go87
-rw-r--r--net/portmapper/upnp_test.go2
-rw-r--r--tstest/jsdeps/jsdeps_test.go10
7 files changed, 61 insertions, 71 deletions
diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt
index 0baee818c..98cbd9add 100644
--- a/cmd/tailscale/depaware.txt
+++ b/cmd/tailscale/depaware.txt
@@ -22,6 +22,12 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
github.com/gorilla/csrf from tailscale.com/client/web
github.com/gorilla/securecookie from github.com/gorilla/csrf
github.com/hdevalence/ed25519consensus from tailscale.com/tka+
+ github.com/huin/goupnp from github.com/huin/goupnp/dcps/internetgateway2+
+ github.com/huin/goupnp/dcps/internetgateway2 from tailscale.com/net/portmapper
+ github.com/huin/goupnp/httpu from github.com/huin/goupnp+
+ github.com/huin/goupnp/scpd from github.com/huin/goupnp
+ github.com/huin/goupnp/soap from github.com/huin/goupnp+
+ github.com/huin/goupnp/ssdp from github.com/huin/goupnp
L github.com/josharian/native from github.com/mdlayher/netlink+
L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/net/interfaces+
L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink
@@ -47,12 +53,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
W 💣 github.com/tailscale/go-winio/internal/socket from github.com/tailscale/go-winio
W github.com/tailscale/go-winio/internal/stringbuffer from github.com/tailscale/go-winio/internal/fs
W github.com/tailscale/go-winio/pkg/guid from github.com/tailscale/go-winio+
- github.com/tailscale/goupnp from github.com/tailscale/goupnp/dcps/internetgateway2+
- github.com/tailscale/goupnp/dcps/internetgateway2 from tailscale.com/net/portmapper
- github.com/tailscale/goupnp/httpu from github.com/tailscale/goupnp+
- github.com/tailscale/goupnp/scpd from github.com/tailscale/goupnp
- github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+
- github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp
L 💣 github.com/tailscale/netlink from tailscale.com/util/linuxfw
github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck
@@ -250,7 +250,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
encoding/hex from crypto/x509+
encoding/json from expvar+
encoding/pem from crypto/tls+
- encoding/xml from github.com/tailscale/goupnp+
+ encoding/xml from github.com/huin/goupnp+
errors from bufio+
expvar from tailscale.com/derp+
flag from github.com/peterbourgon/ff/v3+
@@ -293,7 +293,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
path from html/template+
path/filepath from crypto/x509+
reflect from crypto/x509+
- regexp from github.com/tailscale/goupnp/httpu+
+ regexp from github.com/coreos/go-iptables/iptables+
regexp/syntax from regexp
runtime/debug from tailscale.com/util/singleflight+
slices from tailscale.com/cmd/tailscale/cli+
diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt
index d7b43fa96..19d157511 100644
--- a/cmd/tailscaled/depaware.txt
+++ b/cmd/tailscaled/depaware.txt
@@ -98,6 +98,12 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
github.com/gorilla/csrf from tailscale.com/client/web
github.com/gorilla/securecookie from github.com/gorilla/csrf
github.com/hdevalence/ed25519consensus from tailscale.com/tka+
+ github.com/huin/goupnp from github.com/huin/goupnp/dcps/internetgateway2+
+ github.com/huin/goupnp/dcps/internetgateway2 from tailscale.com/net/portmapper
+ github.com/huin/goupnp/httpu from github.com/huin/goupnp+
+ github.com/huin/goupnp/scpd from github.com/huin/goupnp
+ github.com/huin/goupnp/soap from github.com/huin/goupnp+
+ github.com/huin/goupnp/ssdp from github.com/huin/goupnp
L 💣 github.com/illarion/gonotify from tailscale.com/net/dns
L github.com/insomniacslk/dhcp/dhcpv4 from tailscale.com/net/tstun
L github.com/insomniacslk/dhcp/iana from github.com/insomniacslk/dhcp/dhcpv4
@@ -145,12 +151,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
LD 💣 github.com/tailscale/golang-x-crypto/internal/alias from github.com/tailscale/golang-x-crypto/chacha20
LD github.com/tailscale/golang-x-crypto/ssh from tailscale.com/ipn/ipnlocal+
LD github.com/tailscale/golang-x-crypto/ssh/internal/bcrypt_pbkdf from github.com/tailscale/golang-x-crypto/ssh
- github.com/tailscale/goupnp from github.com/tailscale/goupnp/dcps/internetgateway2+
- github.com/tailscale/goupnp/dcps/internetgateway2 from tailscale.com/net/portmapper
- github.com/tailscale/goupnp/httpu from github.com/tailscale/goupnp+
- github.com/tailscale/goupnp/scpd from github.com/tailscale/goupnp
- github.com/tailscale/goupnp/soap from github.com/tailscale/goupnp+
- github.com/tailscale/goupnp/ssdp from github.com/tailscale/goupnp
github.com/tailscale/hujson from tailscale.com/ipn/conffile
L 💣 github.com/tailscale/netlink from tailscale.com/wgengine/router+
github.com/tailscale/web-client-prebuilt from tailscale.com/client/web
@@ -483,7 +483,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
encoding/hex from crypto/x509+
encoding/json from expvar+
encoding/pem from crypto/tls+
- encoding/xml from github.com/tailscale/goupnp+
+ encoding/xml from github.com/aws/aws-sdk-go-v2/aws/protocol/xml+
errors from bufio+
expvar from tailscale.com/derp+
flag from net/http/httptest+
diff --git a/go.mod b/go.mod
index 1108df7b9..97c563f90 100644
--- a/go.mod
+++ b/go.mod
@@ -108,6 +108,7 @@ require (
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect
+ github.com/huin/goupnp v1.3.0 // indirect
)
require (
diff --git a/go.sum b/go.sum
index fc025873f..9ba15d479 100644
--- a/go.sum
+++ b/go.sum
@@ -524,6 +524,8 @@ github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSo
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
+github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc=
+github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8=
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
diff --git a/net/portmapper/upnp.go b/net/portmapper/upnp.go
index 31650a516..cb87c35eb 100644
--- a/net/portmapper/upnp.go
+++ b/net/portmapper/upnp.go
@@ -23,9 +23,9 @@ import (
"sync/atomic"
"time"
- "github.com/tailscale/goupnp"
- "github.com/tailscale/goupnp/dcps/internetgateway2"
- "github.com/tailscale/goupnp/soap"
+ "github.com/huin/goupnp"
+ "github.com/huin/goupnp/dcps/internetgateway2"
+ "github.com/huin/goupnp/soap"
"tailscale.com/envknob"
"tailscale.com/net/netns"
"tailscale.com/types/logger"
@@ -62,48 +62,27 @@ func (u *upnpMapping) GoodUntil() time.Time { return u.goodUntil }
func (u *upnpMapping) RenewAfter() time.Time { return u.renewAfter }
func (u *upnpMapping) External() netip.AddrPort { return u.external }
func (u *upnpMapping) Release(ctx context.Context) {
- u.client.DeletePortMapping(ctx, "", u.external.Port(), upnpProtocolUDP)
+ u.client.DeletePortMappingCtx(ctx, "", u.external.Port(), upnpProtocolUDP)
}
// upnpClient is an interface over the multiple different clients exported by goupnp,
// exposing the functions we need for portmapping. Those clients are auto-generated from XML-specs,
// which is why they're not very idiomatic.
type upnpClient interface {
- AddPortMapping(
+ AddPortMappingCtx(
ctx context.Context,
-
- // remoteHost is the remote device sending packets to this device, in the format of x.x.x.x.
- // The empty string, "", means any host out on the internet can send packets in.
- remoteHost string,
-
- // externalPort is the exposed port of this port mapping. Visible during NAT operations.
- // 0 will let the router select the port, but there is an additional call,
- // `AddAnyPortMapping`, which is available on 1 of the 3 possible protocols,
- // which should be used if available. See `addAnyPortMapping` below, which calls this if
- // `AddAnyPortMapping` is not supported.
- externalPort uint16,
-
- // protocol is whether this is over TCP or UDP. Either "TCP" or "UDP".
- protocol string,
-
- // internalPort is the port that the gateway device forwards the traffic to.
- internalPort uint16,
- // internalClient is the IP address that packets will be forwarded to for this mapping.
- // Internal client is of the form "x.x.x.x".
- internalClient string,
-
- // enabled is whether this portmapping should be enabled or disabled.
- enabled bool,
- // portMappingDescription is a user-readable description of this portmapping.
- portMappingDescription string,
- // leaseDurationSec is the duration of this portmapping. The value of this argument must be
- // greater than 0. From the spec, it appears if it is set to 0, it will switch to using
- // 604800 seconds, but not sure why this is desired. The recommended time is 3600 seconds.
- leaseDurationSec uint32,
+ NewRemoteHost string,
+ NewExternalPort uint16,
+ NewProtocol string,
+ NewInternalPort uint16,
+ NewInternalClient string,
+ NewEnabled bool,
+ NewPortMappingDescription string,
+ NewLeaseDuration uint32,
) error
- DeletePortMapping(ctx context.Context, remoteHost string, externalPort uint16, protocol string) error
- GetExternalIPAddress(ctx context.Context) (externalIPAddress string, err error)
+ DeletePortMappingCtx(ctx context.Context, remoteHost string, externalPort uint16, protocol string) error
+ GetExternalIPAddressCtx(ctx context.Context) (externalIPAddress string, err error)
}
// tsPortMappingDesc gets sent to UPnP clients as a human-readable label for the portmapping.
@@ -153,7 +132,7 @@ func addAnyPortMapping(
// First off, try using AddAnyPortMapping; if there's a conflict, the
// router will pick another port and return it.
if upnp, ok := upnp.(*internetgateway2.WANIPConnection2); ok {
- return upnp.AddAnyPortMapping(
+ return upnp.AddAnyPortMappingCtx(
ctx,
"",
externalPort,
@@ -168,7 +147,7 @@ func addAnyPortMapping(
// Fall back to using AddPortMapping, which requests a mapping to/from
// a specific external port.
- err = upnp.AddPortMapping(
+ err = upnp.AddPortMappingCtx(
ctx,
"",
externalPort,
@@ -182,8 +161,8 @@ func addAnyPortMapping(
return externalPort, err
}
-// getUPnPClient gets a client for interfacing with UPnP, ignoring the underlying protocol for
-// now.
+// getUPnPClient gets a client for interfacing with UPnP, ignoring the
+// underlying protocol for now.
// Adapted from https://github.com/huin/goupnp/blob/master/GUIDE.md.
//
// The gw is the detected gateway.
@@ -191,9 +170,11 @@ func addAnyPortMapping(
// The meta is the most recently parsed UDP discovery packet response
// from the Internet Gateway Device.
//
-// The provided ctx is not retained in the returned upnpClient, but
-// its associated HTTP client is (if set via goupnp.WithHTTPClient).
-func getUPnPClient(ctx context.Context, logf logger.Logf, debug DebugKnobs, gw netip.Addr, meta uPnPDiscoResponse) (client upnpClient, err error) {
+// If set, the provided http.Client is copied and used as the HTTP client for
+// SOAP requests.
+//
+// The provided ctx is not retained in the returned upnpClient.
+func getUPnPClient(ctx context.Context, logf logger.Logf, httpc *http.Client, debug DebugKnobs, gw netip.Addr, meta uPnPDiscoResponse) (client upnpClient, err error) {
if debug.DisableUPnP {
return nil, nil
}
@@ -229,12 +210,16 @@ func getUPnPClient(ctx context.Context, logf logger.Logf, debug DebugKnobs, gw n
defer cancel()
// This part does a network fetch.
- root, err := goupnp.DeviceByURL(ctx, u)
+ root, err := goupnp.DeviceByURLCtx(ctx, u)
if err != nil {
return nil, err
}
+ var soapClient *soap.SOAPClient
defer func() {
+ if soapClient != nil && httpc != nil {
+ soapClient.HTTPClient = *httpc
+ }
if client == nil {
return
}
@@ -245,13 +230,16 @@ func getUPnPClient(ctx context.Context, logf logger.Logf, debug DebugKnobs, gw n
// These parts don't do a network fetch.
// Pick the best service type available.
- if cc, _ := internetgateway2.NewWANIPConnection2ClientsFromRootDevice(ctx, root, u); len(cc) > 0 {
+ if cc, _ := internetgateway2.NewWANIPConnection2ClientsFromRootDevice(root, u); len(cc) > 0 {
+ soapClient = cc[0].ServiceClient.SOAPClient
return cc[0], nil
}
- if cc, _ := internetgateway2.NewWANIPConnection1ClientsFromRootDevice(ctx, root, u); len(cc) > 0 {
+ if cc, _ := internetgateway2.NewWANIPConnection1ClientsFromRootDevice(root, u); len(cc) > 0 {
+ soapClient = cc[0].ServiceClient.SOAPClient
return cc[0], nil
}
- if cc, _ := internetgateway2.NewWANPPPConnection1ClientsFromRootDevice(ctx, root, u); len(cc) > 0 {
+ if cc, _ := internetgateway2.NewWANPPPConnection1ClientsFromRootDevice(root, u); len(cc) > 0 {
+ soapClient = cc[0].ServiceClient.SOAPClient
return cc[0], nil
}
return nil, nil
@@ -305,8 +293,7 @@ func (c *Client) getUPnPPortMapping(
if ok && oldMapping != nil {
client = oldMapping.client
} else {
- ctx := goupnp.WithHTTPClient(ctx, httpClient)
- client, err = getUPnPClient(ctx, c.logf, c.debug, gw, meta)
+ client, err = getUPnPClient(ctx, c.logf, httpClient, c.debug, gw, meta)
if c.debug.VerboseLogs {
c.logf("getUPnPClient: %T, %v", client, err)
}
@@ -363,7 +350,7 @@ func (c *Client) getUPnPPortMapping(
}
// TODO cache this ip somewhere?
- extIP, err := client.GetExternalIPAddress(ctx)
+ extIP, err := client.GetExternalIPAddressCtx(ctx)
if c.debug.VerboseLogs {
c.logf("client.GetExternalIPAddress: %v, %v", extIP, err)
}
diff --git a/net/portmapper/upnp_test.go b/net/portmapper/upnp_test.go
index aac2ab95c..1e939f7f5 100644
--- a/net/portmapper/upnp_test.go
+++ b/net/portmapper/upnp_test.go
@@ -114,7 +114,7 @@ func TestGetUPnPClient(t *testing.T) {
gw, _ := netip.AddrFromSlice(ts.Listener.Addr().(*net.TCPAddr).IP)
gw = gw.Unmap()
var logBuf tstest.MemLogger
- c, err := getUPnPClient(context.Background(), logBuf.Logf, DebugKnobs{}, gw, uPnPDiscoResponse{
+ c, err := getUPnPClient(context.Background(), logBuf.Logf, nil, DebugKnobs{}, gw, uPnPDiscoResponse{
Location: ts.URL + "/rootDesc.xml",
})
if err != nil {
diff --git a/tstest/jsdeps/jsdeps_test.go b/tstest/jsdeps/jsdeps_test.go
index c3dbcd39a..5a2c52c26 100644
--- a/tstest/jsdeps/jsdeps_test.go
+++ b/tstest/jsdeps/jsdeps_test.go
@@ -14,11 +14,11 @@ func TestDeps(t *testing.T) {
GOOS: "js",
GOARCH: "wasm",
BadDeps: map[string]string{
- "runtime/pprof": "bloat",
- "golang.org/x/net/http2/h2c": "bloat",
- "net/http/pprof": "bloat",
- "golang.org/x/net/proxy": "bloat",
- "github.com/tailscale/goupnp": "bloat, which can't work anyway in wasm",
+ "runtime/pprof": "bloat",
+ "golang.org/x/net/http2/h2c": "bloat",
+ "net/http/pprof": "bloat",
+ "golang.org/x/net/proxy": "bloat",
+ "github.com/huin/goupnp": "bloat, which can't work anyway in wasm",
},
}.Check(t)
}