From c963787222d7f3dcbb3a1fa2309c326c16e83cd1 Mon Sep 17 00:00:00 2001 From: Andreas Fuchs Date: Sun, 23 Jul 2023 21:18:23 -0400 Subject: [PATCH 1/5] Allow setting certain additional headers on upstream requests This should help get certain weirdo services working that need headers that I can't rightly justify setting unconditionally. --- main.go | 26 ++++++++++++++++++++++++++ main_test.go | 38 ++++++++++++++++++++++++++++++++++++++ nixos/default.nix | 11 ++++++++++- proxy.go | 6 +++++- 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 9e78b35..65b69b0 100644 --- a/main.go +++ b/main.go @@ -35,6 +35,30 @@ func (p *prefixes) Set(value string) error { return nil } +type headers http.Header + +func (h *headers) String() string { + var coll []string + for name, vals := range *h { + for _, val := range vals { + coll = append(coll, fmt.Sprintf("%s: %s", name, val)) + } + } + return strings.Join(coll, ", ") +} + +func (h *headers) Set(value string) error { + name, val, ok := strings.Cut(value, ": ") + if !ok { + return fmt.Errorf("Invalid header format %#v, must be 'Header-Name: value'", value) + } + if *h == nil { + *h = headers{} + } + http.Header((*h)).Add(name, val) + return nil +} + type TailnetSrv struct { DownstreamTCPAddr, DownstreamUnixAddr string Ephemeral bool @@ -52,6 +76,7 @@ type TailnetSrv struct { WhoisTimeout time.Duration SuppressWhois bool PrometheusAddr string + UpstreamHeaders headers } type validTailnetSrv struct { @@ -81,6 +106,7 @@ func tailnetSrvFromArgs(args []string) (*validTailnetSrv, *ffcli.Command, error) fs.DurationVar(&s.WhoisTimeout, "whoisTimeout", 1*time.Second, "Maximum amount of time to spend looking up client identities") fs.BoolVar(&s.SuppressWhois, "suppressWhois", false, "Do not set X-Tailscale-User-* headers in upstream requests") fs.StringVar(&s.PrometheusAddr, "prometheusAddr", ":9099", "Serve prometheus metrics from this address. Empty string to disable.") + fs.Var(&s.UpstreamHeaders, "upstreamHeader", "Additional headers (separated by ': ') on requests to upstream.") root := &ffcli.Command{ ShortUsage: "tsnsrv -name [flags] ", diff --git a/main_test.go b/main_test.go index 1ef67ff..31ce2c5 100644 --- a/main_test.go +++ b/main_test.go @@ -165,3 +165,41 @@ func TestHeaderSanitization(t *testing.T) { require.NoError(t, err) assert.Equal(t, http.StatusOK, res.StatusCode) } + +func TestCustomHeaders(t *testing.T) { + for _, elt := range []struct { + name, hn, hv string + }{ + {"custom", "X-Something-Custom", "hi there"}, + {"X-Forwarded-Server", "X-Forwarded-Server", "something-made-up.example.com"}, + } { + test := elt + t.Run(test.name, func(t *testing.T) { + t.Parallel() + + testmux := http.NewServeMux() + testmux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + for k := range r.Header { + slog.Info("", "header", k) + } + assert.Equal(t, test.hv, r.Header.Get(test.hn)) + }) + ts := httptest.NewServer(testmux) + defer ts.Close() + + s, _, err := tailnetSrvFromArgs([]string{"-name", "TestPrefixServing", + "-upstreamHeader", fmt.Sprintf("%v: %v", test.hn, test.hv), + ts.URL, + }) + require.NoError(t, err) + mux := s.mux(http.DefaultTransport) + proxy := httptest.NewServer(mux) + pc := proxy.Client() + req, err := http.NewRequest("GET", proxy.URL, nil) + require.NoError(t, err) + res, err := pc.Do(req) + require.NoError(t, err) + assert.Equal(t, http.StatusOK, res.StatusCode) + }) + } +} diff --git a/nixos/default.nix b/nixos/default.nix index b7717f4..89f5c66 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -101,6 +101,12 @@ default = false; }; + upstreamHeaders = mkOption { + description = "Headers to set on requests to upstream."; + type = types.attrsOf types.str; + default = null; + }; + toURL = mkOption { description = "URL to forward HTTP requests to"; type = types.str; @@ -151,7 +157,10 @@ ${ lib.concatMapStringsSep " \\\n" (p: "-prefix \"${p}\"") value.prefixes } \ - "${value.toURL}" + ${ + lib.concatMapStringsSep " \\\n" (p: "-upstreamHeader ${lib.escapeShellArg p}") (lib.mapAttrsToList (name: value: "${name}: ${value}") value.upstreamHeaders) + } \ + ${lib.escapeShellArg value.toURL} ''; serviceConfig = { DynamicUser = true; diff --git a/proxy.go b/proxy.go index 537d75b..ca3bae9 100644 --- a/proxy.go +++ b/proxy.go @@ -88,7 +88,6 @@ func (s *validTailnetSrv) rewrite(r *httputil.ProxyRequest) { r.Out.URL.Path = s.DestURL.Path } - // Set known proxy headers: r.SetXForwarded() if s.RecommendedProxyHeaders { if r.In.TLS == nil { @@ -109,6 +108,11 @@ func (s *validTailnetSrv) rewrite(r *httputil.ProxyRequest) { r.Out.Header.Set("X-Forwarded-Port", port) } } + + for h, vals := range s.UpstreamHeaders { + r.Out.Header[h] = vals + } + who := s.setWhoisHeaders(r) r.Out = r.Out.WithContext(context.WithValue(r.Out.Context(), proxyContextKey, &proxyContext{ start: time.Now(), From 57e679300bde9527261a218d3cde7824457e4bab Mon Sep 17 00:00:00 2001 From: Andreas Fuchs Date: Sun, 23 Jul 2023 21:20:41 -0400 Subject: [PATCH 2/5] Correctly escape all shell arguments in nixos module --- nixos/default.nix | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/nixos/default.nix b/nixos/default.nix index 89f5c66..3c3002c 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -134,28 +134,28 @@ wantedBy = ["multi-user.target"]; after = ["network-online.target"]; script = '' - exec ${value.package}/bin/tsnsrv -name "${name}" \ + exec ${value.package}/bin/tsnsrv -name ${lib.escapeShellArg name} \ -ephemeral=${lib.boolToString value.ephemeral} \ -funnel=${lib.boolToString value.funnel} \ -plaintext=${lib.boolToString value.plaintext} \ - -listenAddr="${value.listenAddr}" \ - -stripPrefix="${lib.boolToString value.stripPrefix}" \ + -listenAddr=${lib.escapeShellArg value.listenAddr} \ + -stripPrefix=${lib.boolToString value.stripPrefix} \ -stateDir="$STATE_DIRECTORY/tsnet-tsnsrv" \ - -authkeyPath="${value.authKeyPath}" \ - -insecureHTTPS="${lib.boolToString value.insecureHTTPS}" \ - -suppressWhois="${lib.boolToString value.suppressWhois}" \ + -authkeyPath=${lib.escapeShellArg value.authKeyPath} \ + -insecureHTTPS=${lib.boolToString value.insecureHTTPS} \ + -suppressWhois=${lib.boolToString value.suppressWhois} \ ${ if value.whoisTimeout != null - then "-whoisTimeout=${value.whoisTimeout}" + then "-whoisTimeout=${lib.escapeShellArg value.whoisTimeout}" else "" } \ ${ if value.downstreamUnixAddr != null - then "-downstreamUnixAddr=${value.downstreamUnixAddr}" + then "-downstreamUnixAddr=${lib.escapeShellArg value.downstreamUnixAddr}" else "" } \ ${ - lib.concatMapStringsSep " \\\n" (p: "-prefix \"${p}\"") value.prefixes + lib.concatMapStringsSep " \\\n" (p: "-prefix ${lib.escapeShellArg p}") value.prefixes } \ ${ lib.concatMapStringsSep " \\\n" (p: "-upstreamHeader ${lib.escapeShellArg p}") (lib.mapAttrsToList (name: value: "${name}: ${value}") value.upstreamHeaders) From f47e93a2be96bf761b1f85394bdac35ff142ad10 Mon Sep 17 00:00:00 2001 From: Andreas Fuchs Date: Sun, 23 Jul 2023 22:53:21 -0400 Subject: [PATCH 3/5] Oops: Rename all occurrences of "downstream" to "upstream" I thoroughly messed that naming up: Since we're going upstream to request the response, all these connection options should be "upstream". --- main.go | 50 +++++++++++++++++++++++------------------------ main_test.go | 6 +++--- nixos/default.nix | 6 +++--- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/main.go b/main.go index 65b69b0..a29c6b9 100644 --- a/main.go +++ b/main.go @@ -60,23 +60,23 @@ func (h *headers) Set(value string) error { } type TailnetSrv struct { - DownstreamTCPAddr, DownstreamUnixAddr string - Ephemeral bool - Funnel, FunnelOnly bool - ListenAddr string - Name string - RecommendedProxyHeaders bool - ServePlaintext bool - Timeout time.Duration - AllowedPrefixes prefixes - StripPrefix bool - StateDir string - AuthkeyPath string - InsecureHTTPS bool - WhoisTimeout time.Duration - SuppressWhois bool - PrometheusAddr string - UpstreamHeaders headers + UpstreamTCPAddr, UpstreamUnixAddr string + Ephemeral bool + Funnel, FunnelOnly bool + ListenAddr string + Name string + RecommendedProxyHeaders bool + ServePlaintext bool + Timeout time.Duration + AllowedPrefixes prefixes + StripPrefix bool + StateDir string + AuthkeyPath string + InsecureHTTPS bool + WhoisTimeout time.Duration + SuppressWhois bool + PrometheusAddr string + UpstreamHeaders headers } type validTailnetSrv struct { @@ -88,8 +88,8 @@ type validTailnetSrv struct { func tailnetSrvFromArgs(args []string) (*validTailnetSrv, *ffcli.Command, error) { s := &TailnetSrv{} var fs = flag.NewFlagSet("tsnsrv", flag.ExitOnError) - fs.StringVar(&s.DownstreamTCPAddr, "downstreamTCPAddr", "", "Proxy to an HTTP service listening on this TCP address") - fs.StringVar(&s.DownstreamUnixAddr, "downstreamUnixAddr", "", "Proxy to an HTTP service listening on this UNIX domain socket address") + fs.StringVar(&s.UpstreamTCPAddr, "upstreamTCPAddr", "", "Proxy to an HTTP service listening on this TCP address") + fs.StringVar(&s.UpstreamUnixAddr, "upstreamUnixAddr", "", "Proxy to an HTTP service listening on this UNIX domain socket address") fs.BoolVar(&s.Ephemeral, "ephemeral", false, "Declare this service ephemeral") fs.BoolVar(&s.Funnel, "funnel", false, "Expose a funnel service.") fs.BoolVar(&s.FunnelOnly, "funnelOnly", false, "Expose a funnel service only (not exposed on the tailnet).") @@ -131,8 +131,8 @@ func (s *TailnetSrv) validate(args []string) (*validTailnetSrv, error) { if s.ServePlaintext && s.Funnel { errs = append(errs, errors.New("can not serve plaintext on a funnel service.")) } - if s.DownstreamTCPAddr != "" && s.DownstreamUnixAddr != "" { - errs = append(errs, errors.New("can only proxy to one address at a time, pass either -downstreamUnixAddr or -downstreamTCPAddr")) + if s.UpstreamTCPAddr != "" && s.UpstreamUnixAddr != "" { + errs = append(errs, errors.New("can only proxy to one address at a time, pass either -upstreamUnixAddr or -upstreamTCPAddr")) } if !s.Funnel && s.FunnelOnly { errs = append(errs, errors.New("-funnel is required if -funnelOnly is set.")) @@ -199,14 +199,14 @@ func (s *validTailnetSrv) run(ctx context.Context) error { } dial := srv.Dial - if s.DownstreamTCPAddr != "" { + if s.UpstreamTCPAddr != "" { dial = func(ctx context.Context, network, address string) (net.Conn, error) { - return srv.Dial(ctx, "tcp", s.DownstreamTCPAddr) + return srv.Dial(ctx, "tcp", s.UpstreamTCPAddr) } - } else if s.DownstreamUnixAddr != "" { + } else if s.UpstreamUnixAddr != "" { dial = func(ctx context.Context, network, address string) (net.Conn, error) { d := net.Dialer{} - return d.DialContext(ctx, "unix", s.DownstreamUnixAddr) + return d.DialContext(ctx, "unix", s.UpstreamUnixAddr) } } transport := &http.Transport{DialContext: dial} diff --git a/main_test.go b/main_test.go index 31ce2c5..6230be1 100644 --- a/main_test.go +++ b/main_test.go @@ -19,15 +19,15 @@ func TestFromArgs(t *testing.T) { ok bool }{ {"basic", []string{"-name", "foo", "http://example.com"}, true}, - {"connect to unix", []string{"-name", "foo", "-downstreamUnixAddr=/tmp/foo.sock", "http://example.com"}, true}, - {"connect to TCP", []string{"-name", "foo", "-downstreamTCPAddr=127.0.0.1:80", "http://example.com"}, true}, + {"connect to unix", []string{"-name", "foo", "-upstreamUnixAddr=/tmp/foo.sock", "http://example.com"}, true}, + {"connect to TCP", []string{"-name", "foo", "-upstreamTCPAddr=127.0.0.1:80", "http://example.com"}, true}, {"funnel", []string{"-name", "foo", "-funnel=true", "http://example.com"}, true}, {"funnelOnly", []string{"-name", "foo", "-funnel=true", "-funnelOnly", "http://example.com"}, true}, {"ephemeral", []string{"-name", "foo", "-ephemeral=true", "http://example.com"}, true}, // Expected to fail: {"no args", []string{}, false}, - {"both addrs", []string{"-name", "foo", "-downstreamTCPAddr=127.0.0.1:80", "-downstreamUnixAddr=/tmp/foo.sock", "http://example.com"}, false}, + {"both addrs", []string{"-name", "foo", "-upstreamTCPAddr=127.0.0.1:80", "-upstreamUnixAddr=/tmp/foo.sock", "http://example.com"}, false}, {"plaintext on funnel", []string{"-name", "foo", "-plaintext=true", "-funnel", "http://example.com"}, false}, {"invalid funnelOnly", []string{"-name", "foo", "-funnelOnly", "http://example.com"}, false}, {"invalid destination URL", []string{"-name", "foo", "::--example.com"}, false}, diff --git a/nixos/default.nix b/nixos/default.nix index 3c3002c..e76f652 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -71,7 +71,7 @@ default = false; }; - downstreamUnixAddr = mkOption { + upstreamUnixAddr = mkOption { description = "Connect only to the given UNIX Domain Socket"; type = types.nullOr types.path; default = null; @@ -150,8 +150,8 @@ else "" } \ ${ - if value.downstreamUnixAddr != null - then "-downstreamUnixAddr=${lib.escapeShellArg value.downstreamUnixAddr}" + if value.upstreamUnixAddr != null + then "-upstreamUnixAddr=${lib.escapeShellArg value.upstreamUnixAddr}" else "" } \ ${ From 6d2bd12d3cc18bc28b58db514aa3cb61e30161db Mon Sep 17 00:00:00 2001 From: Andreas Fuchs Date: Sun, 23 Jul 2023 22:54:05 -0400 Subject: [PATCH 4/5] Fix the default on upstreamHeaders --- nixos/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/default.nix b/nixos/default.nix index e76f652..fd60eb5 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -104,7 +104,7 @@ upstreamHeaders = mkOption { description = "Headers to set on requests to upstream."; type = types.attrsOf types.str; - default = null; + default = {}; }; toURL = mkOption { From c3bc1960aad498a26084ecb3a984d2ae4e60f149 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 04:41:21 +0000 Subject: [PATCH 5/5] Bump tailscale.com from 1.44.0 to 1.46.1 Bumps [tailscale.com](https://github.com/tailscale/tailscale) from 1.44.0 to 1.46.1. - [Release notes](https://github.com/tailscale/tailscale/releases) - [Commits](https://github.com/tailscale/tailscale/compare/v1.44.0...v1.46.1) --- updated-dependencies: - dependency-name: tailscale.com dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 16 +++++++++------- go.sum | 31 +++++++++++++++++-------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index fa3ce08..52a4407 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/prometheus/client_golang v1.15.1 github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 - tailscale.com v1.44.0 + tailscale.com v1.46.1 ) require ( @@ -39,6 +39,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c // indirect github.com/hdevalence/ed25519consensus v0.1.0 // indirect github.com/illarion/gonotify v1.0.1 // indirect github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 // indirect @@ -52,6 +53,7 @@ require ( github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/sdnotify v1.0.0 // indirect github.com/mdlayher/socket v0.4.1 // indirect + github.com/miekg/dns v1.1.55 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pkg/errors v0.9.1 // indirect @@ -60,10 +62,10 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d // indirect - github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 // indirect + github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e // indirect github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect - github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd // indirect + github.com/tailscale/wireguard-go v0.0.0-20230710185534-bb2c8f22eccf // indirect github.com/tcnksm/go-httpstat v0.2.0 // indirect github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect @@ -71,13 +73,13 @@ require ( github.com/x448/float16 v0.8.4 // indirect go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 // indirect - golang.org/x/crypto v0.8.0 // indirect + golang.org/x/crypto v0.11.0 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.2.0 // indirect - golang.org/x/sys v0.8.1-0.20230609144347-5059a07aa46a // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.9.1 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect diff --git a/go.sum b/go.sum index 567c7ae..1685a93 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c h1:06RMfw+TMMHtRuUOroMeatRCCgSMWXCJQeABvHU69YQ= +github.com/google/nftables v0.1.1-0.20230115205135-9aa6fdf5a28c/go.mod h1:BVIYo3cdnT4qSylnYqcd5YtmXhr51cJPGtnLBe/uLBU= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU= @@ -131,6 +133,7 @@ github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxn github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= +github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc= github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -164,14 +167,14 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8= github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d/go.mod h1:2P+hpOwd53e7JMX/L4f3VXkv1G+33ES6IWZSrkIeWNs= -github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 h1:pBpqbsyX9H8c26oPYC2H+232HOdp1gDnCztoKmKWKDA= -github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2/go.mod h1:V2G8jyemEGZWKQ+3xNn4+bOx+FuoXU9Zc5GUsZMthBg= +github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e h1:JyeJF/HuSwvxWtsR1c0oKX1lzaSH5Wh4aX+MgiStaGQ= +github.com/tailscale/golang-x-crypto v0.0.0-20230713185742-f0b76a10a08e/go.mod h1:DjoeCULdP6vTJ/xY+nzzR9LaUHprkbZEpNidX0aqEEk= github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio= github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8= github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQSPhaUPjUQwozcRdDdSxxqhNgNZ3drZFk= github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0= -github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd h1:+fBevMGmDRNi0oWD4SJXmPKLWvIBYX1NroMjo9czjcY= -github.com/tailscale/wireguard-go v0.0.0-20230410165232-af172621b4dd/go.mod h1:QRIcq2+DbdIC5sKh/gcAZhuqu6WT6L6G8/ALPN5wqYw= +github.com/tailscale/wireguard-go v0.0.0-20230710185534-bb2c8f22eccf h1:bHQHwIHId353jAF2Lm0cGDjJpse/PYS0I0DTtihL9Ls= +github.com/tailscale/wireguard-go v0.0.0-20230710185534-bb2c8f22eccf/go.mod h1:QRIcq2+DbdIC5sKh/gcAZhuqu6WT6L6G8/ALPN5wqYw= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= github.com/u-root/u-root v0.11.0 h1:6gCZLOeRyevw7gbTwMj3fKxnr9+yHFlgF3N7udUVNO8= @@ -192,8 +195,8 @@ go4.org/mem v0.0.0-20220726221520-4f986261bf13 h1:CbZeCBZ0aZj8EfVgnqQcYZgf0lpZ3H go4.org/mem v0.0.0-20220726221520-4f986261bf13/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo= go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y= -golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/exp/typeparams v0.0.0-20230425010034-47ecfdc1ba53 h1:w/MOPdQ1IoYoDou3L55ZbTx2Nhn7JAhX1BBZor8qChU= @@ -212,13 +215,13 @@ golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210301091718-77cc2087c03b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.1-0.20230609144347-5059a07aa46a h1:qMsju+PNttu/NMbq8bQ9waDdxgJMu9QNoUDuhnBaYt0= -golang.org/x/sys v0.8.1-0.20230609144347-5059a07aa46a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -251,5 +254,5 @@ inet.af/wf v0.0.0-20221017222439-36129f591884 h1:zg9snq3Cpy50lWuVqDYM7AIRVTtU50y nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= software.sslmate.com/src/go-pkcs12 v0.2.0 h1:nlFkj7bTysH6VkC4fGphtjXRbezREPgrHuJG20hBGPE= -tailscale.com v1.44.0 h1:MPos9n30kJvdyfL52045gVFyNg93K+bwgDsr8gqKq2o= -tailscale.com v1.44.0/go.mod h1:+iYwTdeHyVJuNDu42Zafwihq1Uqfh+pW7pRaY1GD328= +tailscale.com v1.46.1 h1:6gd+GDs6dJSRISTk6DsGMSMUSZQEJ36D+21MU5bg1oI= +tailscale.com v1.46.1/go.mod h1:ibLiUQopXCzj65xktDlL9/fdhRbyHc1jVamRS0gbsZk=