Monorepo for Tangled tangled.org
6

Configure Feed

Select the types of activity you want to include in your feed.

1package microvm 2 3import ( 4 "bytes" 5 "context" 6 _ "embed" 7 "fmt" 8 "log/slog" 9 "net" 10 "os" 11 "os/exec" 12 "text/template" 13) 14 15// https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml 16// https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml 17// https://datatracker.ietf.org/doc/rfc6890/ 18var blockedNamespaceRoutes = []string{ 19 "0.0.0.0/8", // unspecified / "this network" addresses 20 "10.0.0.0/8", // private network 21 "100.64.0.0/10", // shared carrier-grade nat space 22 "127.0.0.0/8", // loopback 23 "169.254.0.0/16", // link-local / autoconfiguration 24 "172.16.0.0/12", // private network 25 "192.0.0.0/24", // ietf protocol assignments 26 "192.0.2.0/24", // documentation / examples 27 "192.88.99.0/24", // deprecated 6to4 relay anycast 28 "192.168.0.0/16", // private network 29 "198.18.0.0/15", // benchmarking / testing 30 "198.51.100.0/24", // documentation / examples 31 "203.0.113.0/24", // documentation / examples 32 "224.0.0.0/4", // multicast 33 "240.0.0.0/4", // reserved / future use, includes limited broadcast 34 "::/128", // unspecified address 35 "::1/128", // loopback 36 "::ffff:0:0/96", // ipv4-mapped addresses 37 "64:ff9b::/96", // ipv4/ipv6 translation prefix 38 "100::/64", // discard-only prefix 39 "2001::/23", // ietf protocol assignments 40 "2001:db8::/32", // documentation / examples 41 "2002::/16", // deprecated 6to4 addressing 42 "fc00::/7", // unique local addresses 43 "fe80::/10", // link-local unicast 44 "ff00::/8", // multicast 45} 46 47var blockedNamespaceNets = func() []*net.IPNet { 48 nets := make([]*net.IPNet, 0, len(blockedNamespaceRoutes)) 49 for _, route := range blockedNamespaceRoutes { 50 _, ipnet, err := net.ParseCIDR(route) 51 if err != nil { 52 panic(fmt.Sprintf("parse blocked route %q: %v", route, err)) 53 } 54 nets = append(nets, ipnet) 55 } 56 return nets 57}() 58 59//go:embed netns_wrapper.sh.tmpl 60var netnsWrapperTemplate string 61 62type netnsWrapperData struct { 63 TapName string 64 BlockedRoutes []string 65} 66 67func writeNetnsWrapper(path string, dev bool) error { 68 tmpl, err := template.New("netns-wrapper").Parse(netnsWrapperTemplate) 69 if err != nil { 70 return fmt.Errorf("parse qemu network namespace wrapper template: %w", err) 71 } 72 73 var script bytes.Buffer 74 75 var routes []string 76 if !dev { 77 routes = blockedNamespaceRoutes 78 } 79 80 err = tmpl.Execute(&script, netnsWrapperData{ 81 TapName: netnsTapName, 82 BlockedRoutes: routes, 83 }) 84 if err != nil { 85 return fmt.Errorf("render qemu network namespace wrapper template: %w", err) 86 } 87 88 if err := os.WriteFile(path, script.Bytes(), 0o700); err != nil { 89 return fmt.Errorf("write qemu network namespace wrapper: %w", err) 90 } 91 92 return nil 93} 94 95type slirpNamespace struct { 96 spec ImageSpec 97 pidFile string 98 dev bool 99} 100 101func (n *slirpNamespace) Start(ctx context.Context, logFile *os.File, logger *slog.Logger) (*exec.Cmd, *os.File, error) { 102 pid, err := waitForPIDFile(ctx, n.pidFile) 103 if err != nil { 104 return nil, nil, err 105 } 106 107 exitR, exitW, err := os.Pipe() 108 if err != nil { 109 return nil, nil, fmt.Errorf("create slirp4netns exit pipe: %w", err) 110 } 111 defer exitR.Close() // always close our read end; child gets it via ExtraFiles dup 112 113 var ok bool 114 defer func() { 115 if !ok { 116 _ = exitW.Close() 117 } 118 }() 119 120 slirpPath, err := exec.LookPath("slirp4netns") 121 if err != nil { 122 return nil, nil, fmt.Errorf("slirp4netns command not found in PATH: %w", err) 123 } 124 125 args := []string{ 126 "--configure", 127 "--mtu=" + netnsMTU, 128 } 129 if !n.dev { 130 args = append(args, "--disable-host-loopback") 131 } 132 args = append(args, 133 "--enable-sandbox", 134 "--enable-seccomp", 135 "--exit-fd=3", 136 "--cidr="+outerSlirpCIDR, 137 pid, 138 netnsTapName, 139 ) 140 141 cmd := exec.CommandContext(ctx, slirpPath, args...) 142 cmd.ExtraFiles = []*os.File{exitR} 143 cmd.Stdout = logFile 144 cmd.Stderr = logFile 145 if err := cmd.Start(); err != nil { 146 return nil, nil, fmt.Errorf("start slirp4netns: %w", err) 147 } 148 logger.Info("started slirp4netns network namespace", "pid", pid, "cidr", outerSlirpCIDR, "tap", netnsTapName) 149 150 ok = true 151 return cmd, exitW, nil 152}