mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-10 00:51:07 +00:00
tailfs: initial implementation
Add a WebDAV-based folder sharing mechanism that is exposed to local clients at 100.100.100.100:8080 and to remote peers via a new peerapi endpoint at /v0/tailfs. Add the ability to manage folder sharing via the new 'share' CLI sub-command. Updates tailscale/corp#16827 Signed-off-by: Percy Wegmann <percy@tailscale.com>
This commit is contained in:

committed by
Percy Wegmann

parent
2e404b769d
commit
993acf4475
@@ -52,6 +52,7 @@ import (
|
||||
"tailscale.com/paths"
|
||||
"tailscale.com/safesocket"
|
||||
"tailscale.com/syncs"
|
||||
"tailscale.com/tailfs"
|
||||
"tailscale.com/tsd"
|
||||
"tailscale.com/tsweb/varz"
|
||||
"tailscale.com/types/flagtype"
|
||||
@@ -135,11 +136,12 @@ var (
|
||||
createBIRDClient func(string) (wgengine.BIRDClient, error) // non-nil on some platforms
|
||||
)
|
||||
|
||||
var subCommands = map[string]*func([]string) error{
|
||||
"install-system-daemon": &installSystemDaemon,
|
||||
"uninstall-system-daemon": &uninstallSystemDaemon,
|
||||
"debug": &debugModeFunc,
|
||||
"be-child": &beChildFunc,
|
||||
var subCommands = map[string]func([]string) error{
|
||||
"install-system-daemon": installSystemDaemon,
|
||||
"uninstall-system-daemon": uninstallSystemDaemon,
|
||||
"debug": debugModeFunc,
|
||||
"be-child": beChild,
|
||||
"serve-tailfs": serveTailfs,
|
||||
}
|
||||
|
||||
var beCLI func() // non-nil if CLI is linked in
|
||||
@@ -171,12 +173,12 @@ func main() {
|
||||
|
||||
if len(os.Args) > 1 {
|
||||
sub := os.Args[1]
|
||||
if fp, ok := subCommands[sub]; ok {
|
||||
if *fp == nil {
|
||||
if fn, ok := subCommands[sub]; ok {
|
||||
if fn == nil {
|
||||
log.SetFlags(0)
|
||||
log.Fatalf("%s not available on %v", sub, runtime.GOOS)
|
||||
}
|
||||
if err := (*fp)(os.Args[2:]); err != nil {
|
||||
if err := fn(os.Args[2:]); err != nil {
|
||||
log.SetFlags(0)
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -628,6 +630,7 @@ func tryEngine(logf logger.Logf, sys *tsd.System, name string) (onlyNetstack boo
|
||||
Dialer: sys.Dialer.Get(),
|
||||
SetSubsystem: sys.Set,
|
||||
ControlKnobs: sys.ControlKnobs(),
|
||||
EnableTailfs: true,
|
||||
}
|
||||
|
||||
onlyNetstack = name == "userspace-networking"
|
||||
@@ -730,6 +733,7 @@ func runDebugServer(mux *http.ServeMux, addr string) {
|
||||
}
|
||||
|
||||
func newNetstack(logf logger.Logf, sys *tsd.System) (*netstack.Impl, error) {
|
||||
tfs, _ := sys.TailfsForLocal.GetOK()
|
||||
ret, err := netstack.Create(logf,
|
||||
sys.Tun.Get(),
|
||||
sys.Engine.Get(),
|
||||
@@ -737,6 +741,7 @@ func newNetstack(logf logger.Logf, sys *tsd.System) (*netstack.Impl, error) {
|
||||
sys.Dialer.Get(),
|
||||
sys.DNSManager.Get(),
|
||||
sys.ProxyMapper(),
|
||||
tfs,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -792,8 +797,6 @@ func mustStartProxyListeners(socksAddr, httpAddr string) (socksListener, httpLis
|
||||
return socksListener, httpListener
|
||||
}
|
||||
|
||||
var beChildFunc = beChild
|
||||
|
||||
func beChild(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("missing mode argument")
|
||||
@@ -806,6 +809,33 @@ func beChild(args []string) error {
|
||||
return f(args[1:])
|
||||
}
|
||||
|
||||
// serveTailfs serves one or more tailfs on localhost using the WebDAV
|
||||
// protocol. On UNIX and MacOS tailscaled environment, tailfs spawns child
|
||||
// tailscaled processes in serve-tailfs mode in order to access the fliesystem
|
||||
// as specific (usually unprivileged) users.
|
||||
//
|
||||
// serveTailfs prints the address on which it's listening to stdout so that the
|
||||
// parent process knows where to connect to.
|
||||
func serveTailfs(args []string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("missing shares")
|
||||
}
|
||||
if len(args)%2 != 0 {
|
||||
return errors.New("need <sharename> <path> pairs")
|
||||
}
|
||||
s, err := tailfs.NewFileServer()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to start tailfs FileServer: %v", err)
|
||||
}
|
||||
shares := make(map[string]string)
|
||||
for i := 0; i < len(args); i += 2 {
|
||||
shares[args[i]] = args[i+1]
|
||||
}
|
||||
s.SetShares(shares)
|
||||
fmt.Printf("%v\n", s.Addr())
|
||||
return s.Serve()
|
||||
}
|
||||
|
||||
// dieOnPipeReadErrorOfFD reads from the pipe named by fd and exit the process
|
||||
// when the pipe becomes readable. We use this in tests as a somewhat more
|
||||
// portable mechanism for the Linux PR_SET_PDEATHSIG, which we wish existed on
|
||||
|
Reference in New Issue
Block a user