package main import ( "flag" "fmt" "log" "net/http" "os" "path/filepath" ) func main() { listen := flag.String("listen", "127.0.0.1:9090", "local proxy address (configure browser to use this)") phoneURL := flag.String("phone", "http://192.168.1.10:8771", "phone base URL (Component 1/2)") username := flag.String("user", "", "FIDO2 username (required)") gatedFile := flag.String("gated", "", "gated hosts file (default: ~/.config/component3/gated_hosts.txt)") verbose := flag.Bool("v", false, "verbose logging") flag.Parse() if *username == "" { fmt.Fprintln(os.Stderr, "error: -user is required") flag.Usage() os.Exit(1) } cfgDir := defaultConfigDir() if err := os.MkdirAll(cfgDir, 0700); err != nil { log.Fatalf("cannot create config dir: %v", err) } if *gatedFile == "" { *gatedFile = filepath.Join(cfgDir, "gated_hosts.txt") } gated := &GatedHosts{} if err := gated.Load(*gatedFile); err != nil { log.Printf("warning: gated hosts: %v (using empty list)", err) } else { log.Printf("loaded %d gated entries from %s", gated.Len(), *gatedFile) } phone := NewPhoneClient(*phoneURL, *username) proxy := &Proxy{ phone: phone, gated: gated, verbose: *verbose, } log.Printf("listening on %s — configure browser HTTP proxy to this address", *listen) server := &http.Server{ Addr: *listen, Handler: proxy, } if err := server.ListenAndServe(); err != nil { log.Fatalf("proxy: %v", err) } } func defaultConfigDir() string { home, err := os.UserHomeDir() if err != nil { return ".component3" } return filepath.Join(home, ".config", "component3") }