diff --git a/go.mod b/go.mod index dfc8406..3ed63b7 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/caddyserver/caddy/v2 v2.7.3 github.com/google/go-cmp v0.6.0 go.uber.org/zap v1.26.0 - tailscale.com v1.67.0-pre.0.20240510224123-fc1ae97e1037 + tailscale.com v1.67.0-pre.0.20240602211424-42cfbf427c67 ) require ( @@ -67,7 +67,7 @@ require ( github.com/google/cel-go v0.15.1 // indirect github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect github.com/google/pprof v0.0.0-20230808223545-4887780b67fb // indirect - github.com/google/uuid v1.5.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/csrf v1.7.2 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/hdevalence/ed25519consensus v0.2.0 // indirect @@ -109,6 +109,7 @@ require ( github.com/onsi/ginkgo/v2 v2.11.0 // indirect github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus-community/pro-bing v0.4.0 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.46.0 // indirect diff --git a/go.sum b/go.sum index 7402c3c..0d5d134 100644 --- a/go.sum +++ b/go.sum @@ -276,8 +276,8 @@ github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= @@ -545,6 +545,8 @@ github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Q github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus-community/pro-bing v0.4.0 h1:YMbv+i08gQz97OZZBwLyvmmQEEzyfyrrjEaAchdy3R4= +github.com/prometheus-community/pro-bing v0.4.0/go.mod h1:b7wRYZtCcPmt4Sz319BykUU241rWLe1VFXyiyWK/dH4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= @@ -1007,5 +1009,5 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k= software.sslmate.com/src/go-pkcs12 v0.4.0/go.mod h1:Qiz0EyvDRJjjxGyUQa2cCNZn/wMyzrRJ/qcDXOQazLI= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -tailscale.com v1.67.0-pre.0.20240510224123-fc1ae97e1037 h1:ZrUO++qvsCa1jRyg5QI2mrEY3/LgEg4UETvYwgFAIYw= -tailscale.com v1.67.0-pre.0.20240510224123-fc1ae97e1037/go.mod h1:99BIV4U3UPw36Sva04xK2ZsEpVRUkY9jCdEDSAhaNGM= +tailscale.com v1.67.0-pre.0.20240602211424-42cfbf427c67 h1:wYdsZWqsAXj4rXmxhxOUbKlNWX4cfbmCxGVCJgfx34c= +tailscale.com v1.67.0-pre.0.20240602211424-42cfbf427c67/go.mod h1:fI1Vx71PB5JSJv93FKNSmdD0X5QnBuGllLk67AmeNRo= diff --git a/module.go b/module.go index d66c5bf..b88635e 100644 --- a/module.go +++ b/module.go @@ -9,21 +9,26 @@ import ( "crypto/tls" "fmt" "net" + "net/netip" "os" "path/filepath" + "strconv" "strings" "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/modules/caddyhttp" "go.uber.org/zap" "tailscale.com/tsnet" ) func init() { - caddy.RegisterNetwork("tailscale", getPlainListener) + caddy.RegisterNetwork("tailscale", getTCPListener) caddy.RegisterNetwork("tailscale+tls", getTLSListener) + caddy.RegisterNetwork("tailscale/udp", getUDPListener) + caddyhttp.RegisterNetworkHTTP3("tailscale", "tailscale/udp") } -func getPlainListener(c context.Context, _ string, addr string, _ net.ListenConfig) (any, error) { +func getTCPListener(c context.Context, _ string, addr string, _ net.ListenConfig) (any, error) { ctx, ok := c.(caddy.Context) if !ok { return nil, fmt.Errorf("context is not a caddy.Context: %T", c) @@ -78,6 +83,43 @@ func getTLSListener(c context.Context, _ string, addr string, _ net.ListenConfig return ln, nil } +func getUDPListener(c context.Context, _ string, addr string, _ net.ListenConfig) (any, error) { + ctx, ok := c.(caddy.Context) + if !ok { + return nil, fmt.Errorf("context is not a caddy.Context: %T", c) + } + + network, host, port, err := caddy.SplitNetworkAddress(addr) + if err != nil { + return nil, err + } + + s, err := getNode(ctx, host) + if err != nil { + return nil, err + } + + st, err := s.Up(context.Background()) + if err != nil { + return nil, err + } + + if network == "" { + network = "udp4" + + } + var ap netip.AddrPort + for _, ip := range st.TailscaleIPs { + // TODO(will): watch for Tailscale IP changes and update listener + if (network == "udp4" && ip.Is4()) || (network == "udp6" && ip.Is6()) { + p, _ := strconv.Atoi(port) + ap = netip.AddrPortFrom(ip, uint16(p)) + break + } + } + return s.Server.ListenPacket(network, ap.String()) +} + // nodes are the Tailscale nodes that have been configured and started. // Node configuration comes from the global Tailscale Caddy app. // When nodes are no longer in used (e.g. all listeners have been closed), they are shutdown.