mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
net/tsdial: make dialing to peerapi work in netstack mode
With this, I'm able to send a Taildrop file (using "tailscale file cp") from a Linux machine running --tun=userspace-networking. Updates #2179 Change-Id: I4e7a4fb0fbda393e4fb483adb06b74054a02cfd0 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
ad3d6e31f0
commit
8775c646be
@ -8,6 +8,7 @@ package tsdial
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
@ -38,6 +39,9 @@ type Dialer struct {
|
||||
peerClientOnce sync.Once
|
||||
peerClient *http.Client
|
||||
|
||||
peerDialerOnce sync.Once
|
||||
peerDialer *net.Dialer
|
||||
|
||||
mu sync.Mutex
|
||||
dns DNSMap
|
||||
tunName string // tun device name
|
||||
@ -132,6 +136,48 @@ func (d *Dialer) UserDial(ctx context.Context, network, addr string) (net.Conn,
|
||||
return stdDialer.DialContext(ctx, network, ipp.String())
|
||||
}
|
||||
|
||||
// dialPeerAPI connects to a Tailscale peer's peerapi over TCP.
|
||||
//
|
||||
// network must a "tcp" type, and addr must be an ip:port. Name resolution
|
||||
// is not supported.
|
||||
func (d *Dialer) dialPeerAPI(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
switch network {
|
||||
case "tcp", "tcp6", "tcp4":
|
||||
default:
|
||||
return nil, fmt.Errorf("peerAPI dial requires tcp; %q not supported", network)
|
||||
}
|
||||
ipp, err := netaddr.ParseIPPort(addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("peerAPI dial requires ip:port, not name resolution: %w", err)
|
||||
}
|
||||
if d.UseNetstackForIP != nil && d.UseNetstackForIP(ipp.IP()) {
|
||||
if d.NetstackDialTCP == nil {
|
||||
return nil, errors.New("Dialer not initialized correctly")
|
||||
}
|
||||
return d.NetstackDialTCP(ctx, ipp)
|
||||
}
|
||||
return d.getPeerDialer().DialContext(ctx, network, addr)
|
||||
}
|
||||
|
||||
// getPeerDialer returns the *net.Dialer to use to dial peers to use
|
||||
// peer API.
|
||||
//
|
||||
// This is not used in netstack mode.
|
||||
//
|
||||
// The primary function of this is to work on macOS & iOS's in the
|
||||
// Network/System Extension so it can mark the dialer as staying
|
||||
// withing the network namespace/sandbox.
|
||||
func (d *Dialer) getPeerDialer() *net.Dialer {
|
||||
d.peerDialerOnce.Do(func() {
|
||||
d.peerDialer = &net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: netknob.PlatformTCPKeepAlive(),
|
||||
Control: d.PeerDialControlFunc(),
|
||||
}
|
||||
})
|
||||
return d.peerDialer
|
||||
}
|
||||
|
||||
// PeerAPIHTTPClient returns an HTTP Client to call peers' peerapi
|
||||
// endpoints. //
|
||||
// The returned Client must not be mutated; it's owned by the Dialer
|
||||
@ -140,12 +186,7 @@ func (d *Dialer) PeerAPIHTTPClient() *http.Client {
|
||||
d.peerClientOnce.Do(func() {
|
||||
t := http.DefaultTransport.(*http.Transport).Clone()
|
||||
t.Dial = nil
|
||||
dialer := net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: netknob.PlatformTCPKeepAlive(),
|
||||
Control: d.PeerDialControlFunc(),
|
||||
}
|
||||
t.DialContext = dialer.DialContext
|
||||
t.DialContext = d.dialPeerAPI
|
||||
d.peerClient = &http.Client{Transport: t}
|
||||
})
|
||||
return d.peerClient
|
||||
|
Loading…
x
Reference in New Issue
Block a user