| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- package main
- import (
- "context"
- "errors"
- "fmt"
- "log"
- "net"
- "strings"
- "tailscale.com/derp"
- "tailscale.com/derp/derphttp"
- "tailscale.com/net/netmon"
- "tailscale.com/types/logger"
- )
- func startMesh(s *derp.Server) error {
- if *meshWith == "" {
- return nil
- }
- if !s.HasMeshKey() {
- return errors.New("--mesh-with requires --mesh-psk-file")
- }
- for _, hostTuple := range strings.Split(*meshWith, ",") {
- if err := startMeshWithHost(s, hostTuple); err != nil {
- return err
- }
- }
- return nil
- }
- func startMeshWithHost(s *derp.Server, hostTuple string) error {
- var host string
- var dialHost string
- hostParts := strings.Split(hostTuple, "/")
- if len(hostParts) > 2 {
- return fmt.Errorf("too many components in host tuple %q", hostTuple)
- }
- host = hostParts[0]
- if len(hostParts) == 2 {
- dialHost = hostParts[1]
- } else {
- dialHost = hostParts[0]
- }
- logf := logger.WithPrefix(log.Printf, fmt.Sprintf("mesh(%q): ", host))
- netMon := netmon.NewStatic() // good enough for cmd/derper; no need for netns fanciness
- c, err := derphttp.NewClient(s.PrivateKey(), "https://"+host+"/derp", logf, netMon)
- if err != nil {
- return err
- }
- c.MeshKey = s.MeshKey()
- c.WatchConnectionChanges = true
- logf("will dial %q for %q", dialHost, host)
- if dialHost != host {
- var d net.Dialer
- c.SetURLDialer(func(ctx context.Context, network, addr string) (net.Conn, error) {
- _, port, err := net.SplitHostPort(addr)
- if err != nil {
- logf("failed to split %q: %v", addr, err)
- return nil, err
- }
- dialAddr := net.JoinHostPort(dialHost, port)
- logf("dialing %q instead of %q", dialAddr, addr)
- return d.DialContext(ctx, network, dialAddr)
- })
- }
- add := func(m derp.PeerPresentMessage) { s.AddPacketForwarder(m.Key, c) }
- remove := func(m derp.PeerGoneMessage) { s.RemovePacketForwarder(m.Peer, c) }
- go c.RunWatchConnectionLoop(context.Background(), s.PublicKey(), logf, add, remove)
- return nil
- }
|