feat: add macOS daemon support with group-based pf routing
- Add daemon CLI subcommand (install/uninstall/status/run) - Download tun2socks for darwin platforms in Makefile - Export ExtractTun2Socks and add darwin embed support - Use group-based pf filtering instead of user-based for transparent proxying - Install sudoers rule for passwordless sandbox-exec with _greywall group - Add nolint directives for gosec false positives on sudoers 0440 perms - Fix lint issues: lowercase errors, fmt.Fprintf, nolint comments
This commit is contained in:
@@ -333,7 +333,7 @@ func execBenchCommand(b *testing.B, command string, workDir string) {
|
||||
shell = "/bin/bash"
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, shell, "-c", command)
|
||||
cmd := exec.CommandContext(ctx, shell, "-c", command) //nolint:gosec // test helper running shell commands
|
||||
cmd.Dir = workDir
|
||||
cmd.Stdout = &bytes.Buffer{}
|
||||
cmd.Stderr = &bytes.Buffer{}
|
||||
|
||||
@@ -245,7 +245,7 @@ func executeShellCommandWithTimeout(t *testing.T, command string, workDir string
|
||||
shell = "/bin/bash"
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, shell, "-c", command)
|
||||
cmd := exec.CommandContext(ctx, shell, "-c", command) //nolint:gosec // test helper running shell commands
|
||||
cmd.Dir = workDir
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
|
||||
@@ -426,8 +426,8 @@ func buildTemplate(cmdName string, allowRead, allowWrite []string) string {
|
||||
data, _ := json.MarshalIndent(cfg, "", " ")
|
||||
|
||||
var sb strings.Builder
|
||||
sb.WriteString(fmt.Sprintf("// Learned template for %q\n", cmdName))
|
||||
sb.WriteString(fmt.Sprintf("// Generated by: greywall --learning -- %s\n", cmdName))
|
||||
fmt.Fprintf(&sb, "// Learned template for %q\n", cmdName)
|
||||
fmt.Fprintf(&sb, "// Generated by: greywall --learning -- %s\n", cmdName)
|
||||
sb.WriteString("// Review and adjust paths as needed\n")
|
||||
sb.Write(data)
|
||||
sb.WriteString("\n")
|
||||
|
||||
@@ -64,12 +64,12 @@ func (b *ReverseBridge) Cleanup() {}
|
||||
|
||||
// WrapCommandLinux returns an error on non-Linux platforms.
|
||||
func WrapCommandLinux(cfg *config.Config, command string, proxyBridge *ProxyBridge, dnsBridge *DnsBridge, reverseBridge *ReverseBridge, tun2socksPath string, debug bool) (string, error) {
|
||||
return "", fmt.Errorf("Linux sandbox not available on this platform")
|
||||
return "", fmt.Errorf("linux sandbox not available on this platform")
|
||||
}
|
||||
|
||||
// WrapCommandLinuxWithOptions returns an error on non-Linux platforms.
|
||||
func WrapCommandLinuxWithOptions(cfg *config.Config, command string, proxyBridge *ProxyBridge, dnsBridge *DnsBridge, reverseBridge *ReverseBridge, tun2socksPath string, opts LinuxSandboxOptions) (string, error) {
|
||||
return "", fmt.Errorf("Linux sandbox not available on this platform")
|
||||
return "", fmt.Errorf("linux sandbox not available on this platform")
|
||||
}
|
||||
|
||||
// StartLinuxMonitor returns nil on non-Linux platforms.
|
||||
|
||||
@@ -66,7 +66,7 @@ func (m *LogMonitor) Start() error {
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if violation := parseViolation(line); violation != "" {
|
||||
fmt.Fprintf(os.Stderr, "%s\n", violation)
|
||||
fmt.Fprintf(os.Stderr, "%s\n", violation) //nolint:gosec // logging to stderr, not web output
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -13,9 +13,9 @@ import (
|
||||
//go:embed bin/tun2socks-linux-*
|
||||
var tun2socksFS embed.FS
|
||||
|
||||
// extractTun2Socks writes the embedded tun2socks binary to a temp file and returns its path.
|
||||
// ExtractTun2Socks writes the embedded tun2socks binary to a temp file and returns its path.
|
||||
// The caller is responsible for removing the file when done.
|
||||
func extractTun2Socks() (string, error) {
|
||||
func ExtractTun2Socks() (string, error) {
|
||||
var arch string
|
||||
switch runtime.GOARCH {
|
||||
case "amd64":
|
||||
|
||||
53
internal/sandbox/tun2socks_embed_darwin.go
Normal file
53
internal/sandbox/tun2socks_embed_darwin.go
Normal file
@@ -0,0 +1,53 @@
|
||||
//go:build darwin
|
||||
|
||||
package sandbox
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
//go:embed bin/tun2socks-darwin-*
|
||||
var tun2socksFS embed.FS
|
||||
|
||||
// ExtractTun2Socks writes the embedded tun2socks binary to a temp file and returns its path.
|
||||
// The caller is responsible for removing the file when done.
|
||||
func ExtractTun2Socks() (string, error) {
|
||||
var arch string
|
||||
switch runtime.GOARCH {
|
||||
case "amd64":
|
||||
arch = "amd64"
|
||||
case "arm64":
|
||||
arch = "arm64"
|
||||
default:
|
||||
return "", fmt.Errorf("tun2socks: unsupported architecture %s", runtime.GOARCH)
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("bin/tun2socks-darwin-%s", arch)
|
||||
data, err := fs.ReadFile(tun2socksFS, name)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("tun2socks: embedded binary not found for %s: %w", arch, err)
|
||||
}
|
||||
|
||||
tmpFile, err := os.CreateTemp("", "greywall-tun2socks-*")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("tun2socks: failed to create temp file: %w", err)
|
||||
}
|
||||
|
||||
if _, err := tmpFile.Write(data); err != nil {
|
||||
_ = tmpFile.Close()
|
||||
_ = os.Remove(tmpFile.Name()) //nolint:gosec // path from os.CreateTemp, not user input
|
||||
return "", fmt.Errorf("tun2socks: failed to write binary: %w", err)
|
||||
}
|
||||
_ = tmpFile.Close()
|
||||
|
||||
if err := os.Chmod(tmpFile.Name(), 0o755); err != nil { //nolint:gosec // executable binary needs execute permission
|
||||
_ = os.Remove(tmpFile.Name()) //nolint:gosec // path from os.CreateTemp, not user input
|
||||
return "", fmt.Errorf("tun2socks: failed to make executable: %w", err)
|
||||
}
|
||||
|
||||
return tmpFile.Name(), nil
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
//go:build !linux
|
||||
//go:build !linux && !darwin
|
||||
|
||||
package sandbox
|
||||
|
||||
import "fmt"
|
||||
|
||||
// extractTun2Socks is not available on non-Linux platforms.
|
||||
func extractTun2Socks() (string, error) {
|
||||
return "", fmt.Errorf("tun2socks is only available on Linux")
|
||||
// ExtractTun2Socks is not available on unsupported platforms.
|
||||
func ExtractTun2Socks() (string, error) {
|
||||
return "", fmt.Errorf("tun2socks is only available on Linux and macOS")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user