Identify tailnet callers once per connection; list processes via sysctl

This commit is contained in:
Ian Gulliver
2026-10-23 11:22:16 -07:00
parent 69848a2c6e
commit 0a094aaa72
6 changed files with 58 additions and 31 deletions
+13 -26
View File
@@ -1,24 +1,21 @@
package agents
import (
"bufio"
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"log/slog"
"os"
"os/exec"
"path/filepath"
"slices"
"strconv"
"strings"
"sync"
"syscall"
"time"
"g.fc.run/ai/byre/internal/api"
"golang.org/x/sys/unix"
)
const (
@@ -112,7 +109,7 @@ func (m *Manager) Health(ctx context.Context) (Health, error) {
return Health{}, err
}
children, err := claudeChildren(ctx, os.Getpid())
children, err := claudeChildren(os.Getpid())
if err != nil {
return Health{}, err
}
@@ -226,39 +223,29 @@ func pidAlive(pid int) bool {
return err == nil || errors.Is(err, syscall.EPERM)
}
func claudeChildren(ctx context.Context, parent int) ([]int, error) {
cctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
out, err := exec.CommandContext(cctx, "ps", "-A", "-o", "pid=,ppid=,comm=").Output()
func claudeChildren(parent int) ([]int, error) {
procs, err := unix.SysctlKinfoProcSlice("kern.proc.all")
if err != nil {
return nil, fmt.Errorf("list processes: %w", err)
}
return parseChildren(out, parent), nil
}
func parseChildren(out []byte, parent int) []int {
pids := []int{}
sc := bufio.NewScanner(bytes.NewReader(out))
for sc.Scan() {
fields := strings.Fields(sc.Text())
if len(fields) < 3 {
for _, p := range procs {
if int(p.Eproc.Ppid) != parent {
continue
}
pid, err := strconv.Atoi(fields[0])
if err != nil {
pid := int(p.Proc.P_pid)
// p_comm holds the resolved binary's name (claude's is its version), so match the path it was started by.
args, err := unix.SysctlRaw("kern.procargs2", pid)
if err != nil || len(args) < 4 {
continue
}
ppid, err := strconv.Atoi(fields[1])
if err != nil || ppid != parent {
continue
}
if filepath.Base(strings.Join(fields[2:], " ")) != "claude" {
path, _, _ := strings.Cut(string(args[4:]), "\x00")
if filepath.Base(path) != "claude" {
continue
}
pids = append(pids, pid)
}
return pids
return pids, nil
}
func problems(h Health) []string {
+3 -2
View File
@@ -17,6 +17,7 @@ import (
"g.fc.run/ai/byre/internal/api"
"g.fc.run/ai/byre/internal/mcp"
"g.fc.run/ai/byre/internal/peer"
"g.fc.run/ai/byre/internal/store"
)
@@ -169,7 +170,7 @@ func (m *Manager) servePreview(port int) error {
http.Error(w, "forbidden preview host", http.StatusForbidden)
return
}
who, err := lc.WhoIs(r.Context(), r.RemoteAddr)
who, err := peer.WhoIs(r, lc)
if err != nil {
http.Error(w, err.Error(), http.StatusForbidden)
return
@@ -183,7 +184,7 @@ func (m *Manager) servePreview(port int) error {
proxy.ServeHTTP(w, r)
})
go func() {
err := (&http.Server{Handler: handler}).Serve(tracked)
err := (&http.Server{Handler: handler, ConnContext: peer.ConnContext}).Serve(tracked)
if !errors.Is(err, net.ErrClosed) {
slog.Error("serve preview", "port", port, "err", err)
}
+37
View File
@@ -0,0 +1,37 @@
package peer
import (
"context"
"net"
"net/http"
"sync"
"tailscale.com/client/local"
"tailscale.com/client/tailscale/apitype"
)
type key struct{}
type peer struct {
mu sync.Mutex
who *apitype.WhoIsResponse
}
func ConnContext(ctx context.Context, _ net.Conn) context.Context {
return context.WithValue(ctx, key{}, &peer{})
}
func WhoIs(r *http.Request, lc *local.Client) (*apitype.WhoIsResponse, error) {
p := r.Context().Value(key{}).(*peer)
p.mu.Lock()
defer p.mu.Unlock()
if p.who != nil {
return p.who, nil
}
who, err := lc.WhoIs(r.Context(), r.RemoteAddr)
if err != nil {
return nil, err
}
p.who = who
return who, nil
}
+2 -1
View File
@@ -19,6 +19,7 @@ import (
"g.fc.run/ai/byre/internal/clients"
"g.fc.run/ai/byre/internal/git"
"g.fc.run/ai/byre/internal/ids"
"g.fc.run/ai/byre/internal/peer"
"g.fc.run/ai/byre/internal/schedule"
"g.fc.run/ai/byre/internal/store"
"g.fc.run/ai/byre/internal/terminal"
@@ -172,7 +173,7 @@ func (s *Server) GetTailnet(w http.ResponseWriter, r *http.Request) {
func (s *Server) identify(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
identified := trace.Start(r.Context(), "whois")
who, err := s.tailnet.WhoIs(r.Context(), r.RemoteAddr)
who, err := peer.WhoIs(r, s.tailnet)
identified()
if err != nil {
writeError(w, http.StatusUnauthorized, fmt.Errorf("identify %s on the tailnet: %w", r.RemoteAddr, err))