Route byre client-exec through HTTP_PROXY for loopback too

This commit is contained in:
Ian Gulliver
2026-10-21 11:29:57 -07:00
parent d34232009e
commit 26a95315e6
2 changed files with 53 additions and 1 deletions
+49 -1
View File
@@ -6,6 +6,8 @@ import (
"flag"
"fmt"
"net/http"
"net/netip"
"net/url"
"os"
"strings"
"time"
@@ -50,7 +52,9 @@ func clientExecCmd(args []string) {
}
hr.Header.Set("Authorization", "Bearer "+token)
hr.Header.Set("Content-Type", "application/json")
hc := &http.Client{Timeout: time.Duration(*timeout)*time.Second + execGrace}
tr := http.DefaultTransport.(*http.Transport).Clone()
tr.Proxy = apiProxy
hc := &http.Client{Transport: tr, Timeout: time.Duration(*timeout)*time.Second + execGrace}
resp, err := hc.Do(hr)
if err != nil {
execFail(execUnavailable, err.Error())
@@ -82,6 +86,50 @@ func clientExecCmd(args []string) {
os.Exit(res.ExitCode)
}
// http.ProxyFromEnvironment never proxies loopback, but a sandboxed shell can
// reach byre's loopback API only through its proxy.
func apiProxy(r *http.Request) (*url.URL, error) {
if os.Getenv("BYRE_NO_PROXY") == "1" {
return nil, nil
}
p := os.Getenv("HTTP_PROXY")
if p == "" {
p = os.Getenv("http_proxy")
}
if p == "" || noProxy(r.URL) {
return nil, nil
}
if !strings.Contains(p, "://") {
p = "http://" + p
}
return url.Parse(p)
}
func noProxy(u *url.URL) bool {
list := os.Getenv("NO_PROXY")
if list == "" {
list = os.Getenv("no_proxy")
}
host := u.Hostname()
ip, ipErr := netip.ParseAddr(host)
for _, e := range strings.Split(list, ",") {
e = strings.TrimSpace(e)
if e == "" {
continue
}
if pfx, err := netip.ParsePrefix(e); err == nil {
if ipErr == nil && pfx.Contains(ip) {
return true
}
continue
}
if e == "*" || e == u.Host || e == host || strings.HasSuffix(host, "."+strings.TrimPrefix(e, ".")) {
return true
}
}
return false
}
func execFail(code int, msg string) {
fmt.Fprintln(os.Stderr, "byre client-exec: "+msg)
os.Exit(code)
+4
View File
@@ -26,6 +26,10 @@ BYRE_TOKEN=$(<"$HOME/Library/Application Support/byre/loopback-token") byre clie
byre logs each call (client, command, exit status, duration), never its output.
## Sandboxed shells
client-exec calls byre's API at `http://127.0.0.1:8270`. When `HTTP_PROXY` (or `http_proxy`) is set it sends that call through the proxy, loopback included, unless `NO_PROXY` lists the address; a sandbox that denies direct loopback connections then needs only to allow `127.0.0.1:8270` through its proxy. `BYRE_NO_PROXY=1` connects directly whatever the proxy variables say.
## Screen lock
`byre screen` prints `unlocked`, `locked` or `no-session` (no GUI login for this user) for the Mac it runs on, and exits 0. Check the server Mac with `byre screen` and the client with: