Merge branch 'master' of github.com:tailscale/tailscale
* 'master' of github.com:tailscale/tailscale: tailcfg: remove unused, unimplemented DERPNode.CertFingerprint for now net/netns: also don't err on tailscaled -fake as a regular user net/netcheck: fix HTTPS fallback bug from earlier today net/netns: don't return an error if we're not root and running the tailscale binary
This commit is contained in:
commit
8575b21ca8
|
@ -142,8 +142,8 @@ func (c *Client) useHTTPS() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// TLSServerName returns which TLS cert name to expect for the given node.
|
||||
func (c *Client) TLSServerName(node *tailcfg.DERPNode) string {
|
||||
// tlsServerName returns which TLS cert name to expect for the given node.
|
||||
func (c *Client) tlsServerName(node *tailcfg.DERPNode) string {
|
||||
if c.url != nil {
|
||||
return c.url.Host
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
|
|||
tcpConn, err = c.dialURL(ctx)
|
||||
} else {
|
||||
c.logf("%s: connecting to derp-%d (%v)", caller, reg.RegionID, reg.RegionCode)
|
||||
tcpConn, node, err = c.DialRegion(ctx, reg)
|
||||
tcpConn, node, err = c.dialRegion(ctx, reg)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -249,11 +249,7 @@ func (c *Client) connect(ctx context.Context, caller string) (client *derp.Clien
|
|||
|
||||
var httpConn net.Conn // a TCP conn or a TLS conn; what we speak HTTP to
|
||||
if c.useHTTPS() {
|
||||
tlsConf := tlsdial.Config(c.TLSServerName(node), c.TLSConfig)
|
||||
if node != nil && node.DERPTestPort != 0 {
|
||||
tlsConf.InsecureSkipVerify = true
|
||||
}
|
||||
httpConn = tls.Client(tcpConn, tlsConf)
|
||||
httpConn = c.tlsClient(tcpConn, node)
|
||||
} else {
|
||||
httpConn = tcpConn
|
||||
}
|
||||
|
@ -329,10 +325,10 @@ func (c *Client) dialURL(ctx context.Context) (net.Conn, error) {
|
|||
return tcpConn, nil
|
||||
}
|
||||
|
||||
// DialRegion returns a TCP connection to the provided region, trying
|
||||
// dialRegion returns a TCP connection to the provided region, trying
|
||||
// each node in order (with dialNode) until one connects or ctx is
|
||||
// done.
|
||||
func (c *Client) DialRegion(ctx context.Context, reg *tailcfg.DERPRegion) (net.Conn, *tailcfg.DERPNode, error) {
|
||||
func (c *Client) dialRegion(ctx context.Context, reg *tailcfg.DERPRegion) (net.Conn, *tailcfg.DERPNode, error) {
|
||||
if len(reg.Nodes) == 0 {
|
||||
return nil, nil, fmt.Errorf("no nodes for %s", c.targetString(reg))
|
||||
}
|
||||
|
@ -352,6 +348,42 @@ func (c *Client) DialRegion(ctx context.Context, reg *tailcfg.DERPRegion) (net.C
|
|||
return nil, nil, firstErr
|
||||
}
|
||||
|
||||
func (c *Client) tlsClient(nc net.Conn, node *tailcfg.DERPNode) *tls.Conn {
|
||||
tlsConf := tlsdial.Config(c.tlsServerName(node), c.TLSConfig)
|
||||
if node != nil && node.DERPTestPort != 0 {
|
||||
tlsConf.InsecureSkipVerify = true
|
||||
}
|
||||
return tls.Client(nc, tlsConf)
|
||||
}
|
||||
|
||||
func (c *Client) DialRegionTLS(ctx context.Context, reg *tailcfg.DERPRegion) (tlsConn *tls.Conn, connClose io.Closer, err error) {
|
||||
tcpConn, node, err := c.dialRegion(ctx, reg)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
done := make(chan bool) // unbufferd
|
||||
defer close(done)
|
||||
|
||||
tlsConn = c.tlsClient(tcpConn, node)
|
||||
go func() {
|
||||
select {
|
||||
case <-done:
|
||||
case <-ctx.Done():
|
||||
tcpConn.Close()
|
||||
}
|
||||
}()
|
||||
err = tlsConn.Handshake()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
select {
|
||||
case done <- true:
|
||||
return tlsConn, tcpConn, nil
|
||||
case <-ctx.Done():
|
||||
return nil, nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) dialContext(ctx context.Context, proto, addr string) (net.Conn, error) {
|
||||
var stdDialer dialer = netns.Dialer()
|
||||
var dialer = stdDialer
|
||||
|
|
|
@ -8,6 +8,7 @@ package netcheck
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -786,23 +787,26 @@ func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegio
|
|||
var ip netaddr.IP
|
||||
|
||||
dc := derphttp.NewNetcheckClient(c.logf)
|
||||
nc, node, err := dc.DialRegion(ctx, reg)
|
||||
tlsConn, tcpConn, err := dc.DialRegionTLS(ctx, reg)
|
||||
if err != nil {
|
||||
return 0, ip, err
|
||||
}
|
||||
defer nc.Close()
|
||||
defer tcpConn.Close()
|
||||
|
||||
if ta, ok := nc.RemoteAddr().(*net.TCPAddr); ok {
|
||||
if ta, ok := tlsConn.RemoteAddr().(*net.TCPAddr); ok {
|
||||
ip, _ = netaddr.FromStdIP(ta.IP)
|
||||
}
|
||||
if ip == (netaddr.IP{}) {
|
||||
return 0, ip, fmt.Errorf("no unexpected RemoteAddr %#v", nc.RemoteAddr())
|
||||
return 0, ip, fmt.Errorf("no unexpected RemoteAddr %#v", tlsConn.RemoteAddr())
|
||||
}
|
||||
|
||||
connc := make(chan net.Conn, 1)
|
||||
connc <- nc
|
||||
connc := make(chan *tls.Conn, 1)
|
||||
connc <- tlsConn
|
||||
|
||||
tr := &http.Transport{
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
return nil, errors.New("unexpected DialContext dial")
|
||||
},
|
||||
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
select {
|
||||
case nc := <-connc:
|
||||
|
@ -814,9 +818,7 @@ func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegio
|
|||
}
|
||||
hc := &http.Client{Transport: tr}
|
||||
|
||||
host := dc.TLSServerName(node)
|
||||
u := fmt.Sprintf("https://%s/derp/latency-check", host)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://derp-unused-hostname.tld/derp/latency-check", nil)
|
||||
if err != nil {
|
||||
return 0, ip, err
|
||||
}
|
||||
|
@ -827,7 +829,7 @@ func (c *Client) measureHTTPSLatency(ctx context.Context, reg *tailcfg.DERPRegio
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
_, err = io.Copy(ioutil.Discard, resp.Body)
|
||||
_, err = io.Copy(ioutil.Discard, io.LimitReader(resp.Body, 8<<10))
|
||||
if err != nil {
|
||||
return 0, ip, err
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ package netns
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
@ -36,6 +38,24 @@ func control(network, address string, c syscall.RawConn) error {
|
|||
err := c.Control(func(fd uintptr) {
|
||||
controlErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_MARK, tailscaleBypassMark)
|
||||
})
|
||||
// Before returning some fatal error, skip it in some cases.
|
||||
if (err != nil || controlErr != nil) && os.Getuid() != 0 {
|
||||
v, _ := os.Executable()
|
||||
switch filepath.Base(v) {
|
||||
case "tailscale":
|
||||
for _, arg := range os.Args {
|
||||
if arg == "netcheck" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
case "tailscaled":
|
||||
for _, arg := range os.Args {
|
||||
if arg == "-fake" || arg == "--fake" {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("setting socket mark: %w", err)
|
||||
}
|
||||
|
|
|
@ -90,11 +90,6 @@ type DERPNode struct {
|
|||
// not present) + TLS ClientHello.
|
||||
CertName string `json:",omitempty"`
|
||||
|
||||
// CertFingerprint, if non-empty, specifies the expected
|
||||
// lowercase hex of the SHA-256 of the TLS server's offered
|
||||
// certificate. If empty, the system default RootCAs are used.
|
||||
CertFingerprint []string `json:",omitempty"`
|
||||
|
||||
// IPv4 optionally forces an IPv4 address to use, instead of using DNS.
|
||||
// If empty, A record(s) from DNS lookups of HostName are used.
|
||||
// If the string is not an IPv4 address, IPv4 is not used; the
|
||||
|
|
Loading…
Reference in New Issue