From 2a379ec9a5f80bc3f072ffe8e88251b417faf245 Mon Sep 17 00:00:00 2001 From: YEVHENII SHCHERBINA Date: Thu, 30 Oct 2025 13:58:57 +0000 Subject: [PATCH 1/3] fix: remove unprivileged and macos --- README.md | 25 +-- cli/cli.go | 14 +- jail/jail.go | 2 - jail/macos.go | 359 ------------------------------------------- jail/macos_stub.go | 10 -- jail/unprivileged.go | 66 -------- 6 files changed, 5 insertions(+), 471 deletions(-) delete mode 100644 jail/macos.go delete mode 100644 jail/macos_stub.go delete mode 100644 jail/unprivileged.go diff --git a/README.md b/README.md index 6969cae..391a804 100644 --- a/README.md +++ b/README.md @@ -69,32 +69,13 @@ boundary --log-level debug --allow "domain=github.com" -- git pull # Debug info **Log Levels:** `error`, `warn` (default), `info`, `debug` -## Unprivileged Mode - -When you can't or don't want to run with sudo privileges, use `--unprivileged`: - -```bash -# Run without network isolation (uses HTTP_PROXY/HTTPS_PROXY environment variables) -boundary --unprivileged --allow "domain=github.com" -- npm install - -# Useful in containers or restricted environments -boundary --unprivileged --allow "domain=*.npmjs.org" --allow "domain=registry.npmjs.org" -- npm install -``` - -**Unprivileged Mode:** -- No network namespaces or firewall rules -- Works without sudo privileges -- Uses proxy environment variables instead -- Applications must respect HTTP_PROXY/HTTPS_PROXY settings -- Less secure but more compatible - ## Platform Support | Platform | Implementation | Sudo Required | |----------|----------------|---------------| -| Linux | Network namespaces + iptables | Yes | -| macOS | Process groups + PF rules | Yes | -| Windows | Not supported | - | +| Linux | Network namespaces + iptables | No | +| macOS | Not supported | - | +| Windows | Not supported | - | ## Command-Line Options diff --git a/cli/cli.go b/cli/cli.go index a53567e..73cf533 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -83,12 +83,6 @@ func BaseCommand() *serpent.Command { Description: "Set a directory to write logs to rather than stderr.", Value: serpent.StringOf(&config.LogDir), }, - { - Flag: "unprivileged", - Env: "BOUNDARY_UNPRIVILEGED", - Description: "Run in unprivileged mode (no network isolation, uses proxy environment variables).", - Value: serpent.BoolOf(&config.Unprivileged), - }, { Flag: "proxy-port", Env: "PROXY_PORT", @@ -211,7 +205,7 @@ func Run(ctx context.Context, config Config, args []string) error { HomeDir: homeDir, ConfigDir: configDir, CACertPath: caCertPath, - }, config.Unprivileged) + }) if err != nil { return fmt.Errorf("failed to create jailer: %v", err) } @@ -334,11 +328,7 @@ func setupLogging(config Config) (*slog.Logger, error) { } // createJailer creates a new jail instance for the current platform -func createJailer(config jail.Config, unprivileged bool) (jail.Jailer, error) { - if unprivileged { - return jail.NewUnprivileged(config) - } - +func createJailer(config jail.Config) (jail.Jailer, error) { // Use the DefaultOS function for platform-specific jail creation return jail.DefaultOS(config) } diff --git a/jail/jail.go b/jail/jail.go index b3f9eb6..783f3ff 100644 --- a/jail/jail.go +++ b/jail/jail.go @@ -30,8 +30,6 @@ func DefaultOS(config Config) (Jailer, error) { switch runtime.GOOS { case "linux": return NewLinuxJail(config) - case "darwin": - return NewMacOSJail(config) default: return nil, fmt.Errorf("unsupported operating system: %s", runtime.GOOS) } diff --git a/jail/macos.go b/jail/macos.go deleted file mode 100644 index 811d702..0000000 --- a/jail/macos.go +++ /dev/null @@ -1,359 +0,0 @@ -//go:build darwin - -package jail - -import ( - "fmt" - "log/slog" - "os" - "os/exec" - "strconv" - "strings" - "syscall" - "time" -) - -const ( - prefix = "coder_boundary" -) - -func newNamespaceName() string { - return fmt.Sprintf("%s_%d", prefix, time.Now().UnixNano()%10000000) -} - -const ( - pfAnchorName = "coder_boundary" - groupName = "coder_boundary" -) - -// MacOSJail implements network boundary using macOS PF (Packet Filter) and group-based isolation -type MacOSJail struct { - restrictedGid int - pfRulesPath string - mainRulesPath string - logger *slog.Logger - commandEnv []string - procAttr *syscall.SysProcAttr - httpProxyPort int - configDir string - caCertPath string - homeDir string - username string - uid int - gid int -} - -// NewMacOSJail creates a new macOS network boundary instance -func NewMacOSJail(config Config) (*MacOSJail, error) { - ns := newNamespaceName() - pfRulesPath := fmt.Sprintf("/tmp/%s.pf", ns) - mainRulesPath := fmt.Sprintf("/tmp/%s_main.pf", ns) - - return &MacOSJail{ - pfRulesPath: pfRulesPath, - mainRulesPath: mainRulesPath, - logger: config.Logger, - httpProxyPort: config.HttpProxyPort, - configDir: config.ConfigDir, - caCertPath: config.CACertPath, - homeDir: config.HomeDir, - username: config.Username, - uid: config.Uid, - gid: config.Gid, - }, nil -} - -func SetupChildNetworking(vethNetJail string) error { - return nil -} - -// Setup creates the network boundary group and configures PF rules -func (n *MacOSJail) ConfigureBeforeCommandExecution() error { - n.logger.Debug("Setup called") - - // Create or get network boundary group - n.logger.Debug("Creating or ensuring network boundary group") - err := n.ensureGroup() - if err != nil { - return fmt.Errorf("failed to ensure group: %v", err) - } - - // Setup PF rules - n.logger.Debug("Setting up PF rules") - err = n.setupPFRules() - if err != nil { - return fmt.Errorf("failed to setup PF rules: %v", err) - } - - // Prepare environment once during setup - n.logger.Debug("Preparing environment") - - e := getEnvs(n.configDir, n.caCertPath) - n.commandEnv = mergeEnvs(e, map[string]string{ - "HOME": n.homeDir, - "USER": n.username, - "LOGNAME": n.username, - }) - - // Prepare process credentials once during setup - n.logger.Debug("Preparing process credentials") - // Use original user ID but KEEP the boundary group for network isolation - procAttr := &syscall.SysProcAttr{ - Credential: &syscall.Credential{ - Uid: uint32(n.uid), - Gid: uint32(n.restrictedGid), - }, - } - - // Store prepared process attributes for use in Command method - n.procAttr = procAttr - - n.logger.Debug("Setup completed successfully") - return nil -} - -// Command runs the command with the network boundary group membership -func (n *MacOSJail) Command(command []string) *exec.Cmd { - n.logger.Debug("Command called", "command", command) - - // Create command directly (no sg wrapper needed) - n.logger.Debug("Creating command with group membership", "groupID", n.restrictedGid) - cmd := exec.Command(command[0], command[1:]...) - n.logger.Debug("Full command args", "args", command) - - cmd.Env = n.commandEnv - - // Use prepared process attributes from Open method - cmd.SysProcAttr = n.procAttr - - return cmd -} - -// Cleanup removes PF rules and cleans up temporary files -func (n *MacOSJail) Close() error { - n.logger.Debug("Starting cleanup process") - - // Remove PF rules - n.logger.Debug("Removing PF rules") - err := n.removePFRules() - if err != nil { - return fmt.Errorf("failed to remove PF rules: %v", err) - } - - // Clean up temporary files - n.logger.Debug("Cleaning up temporary files") - n.cleanupTempFiles() - - n.logger.Debug("Cleanup completed successfully") - return nil -} - -// ensureGroup creates the network boundary group if it doesn't exist -func (n *MacOSJail) ensureGroup() error { - // Check if group already exists - output, err := exec.Command("dscl", ".", "-read", fmt.Sprintf("/Groups/%s", groupName), "PrimaryGroupID").Output() - if err == nil { - // Parse GID from output - stdout := string(output) - for _, line := range strings.Split(stdout, "\n") { - if strings.Contains(line, "PrimaryGroupID") { - parts := strings.Fields(line) - if len(parts) >= 2 { - gid, err := strconv.Atoi(parts[len(parts)-1]) - if err != nil { - return fmt.Errorf("failed to parse GID: %v", err) - } - n.restrictedGid = gid - return nil - } - } - } - } - - // Group doesn't exist, create it - cmd := exec.Command("dseditgroup", "-o", "create", groupName) - err = cmd.Run() - if err != nil { - return fmt.Errorf("failed to create group: %v", err) - } - - // Get the newly created group's GID - output, err = exec.Command("dscl", ".", "-read", fmt.Sprintf("/Groups/%s", groupName), "PrimaryGroupID").Output() - if err != nil { - return fmt.Errorf("failed to read group GID: %v", err) - } - - stdout := string(output) - for _, line := range strings.Split(stdout, "\n") { - if strings.Contains(line, "PrimaryGroupID") { - parts := strings.Fields(line) - if len(parts) >= 2 { - gid, err := strconv.Atoi(parts[len(parts)-1]) - if err != nil { - return fmt.Errorf("failed to parse GID: %v", err) - } - n.restrictedGid = gid - return nil - } - } - } - - return fmt.Errorf("failed to get GID for group %s", groupName) -} - -// getDefaultInterface gets the default network interface -func (n *MacOSJail) getDefaultInterface() (string, error) { - output, err := exec.Command("route", "-n", "get", "default").Output() - if err != nil { - return "", fmt.Errorf("failed to get default route: %v", err) - } - - stdout := string(output) - for _, line := range strings.Split(stdout, "\n") { - if strings.Contains(line, "interface:") { - parts := strings.Fields(line) - if len(parts) >= 2 { - return parts[1], nil - } - } - } - - // Fallback to en0 if we can't determine - return "en0", nil -} - -// createPFRules creates PF rules for comprehensive TCP traffic diversion -func (n *MacOSJail) createPFRules() (string, error) { - // Get the default network interface - iface, err := n.getDefaultInterface() - if err != nil { - return "", fmt.Errorf("failed to get default interface: %v", err) - } - - // Create comprehensive PF rules for ALL TCP traffic interception - // This prevents bypass via non-standard ports (8080, 3306, 22, etc.) - rules := fmt.Sprintf(`# comprehensive TCP boundarying PF rules for GID %d on interface %s -# COMPREHENSIVE APPROACH: Intercept ALL TCP traffic from the boundaryed group -# This ensures NO TCP traffic can bypass the proxy by using alternative ports - -# First, redirect ALL TCP traffic arriving on lo0 to our HTTP proxy with TLS termination -# The HTTP proxy with TLS termination can handle both HTTP and HTTPS traffic -rdr pass on lo0 inet proto tcp from any to any -> 127.0.0.1 port %d - -# Route ALL TCP traffic from boundary group to lo0 where it will be redirected -pass out route-to (lo0 127.0.0.1) inet proto tcp from any to any group %d keep state - -# Also handle ALL TCP traffic on the specific interface from the group -pass out on %s route-to (lo0 127.0.0.1) inet proto tcp from any to any group %d keep state - -# Allow all loopback traffic -pass on lo0 all -`, - n.restrictedGid, - iface, - n.httpProxyPort, // Use HTTP proxy with TLS termination for all TCP traffic - n.restrictedGid, - iface, - n.restrictedGid, - ) - - n.logger.Debug("Comprehensive TCP boundarying enabled for macOS", "group_id", n.restrictedGid, "proxy_port", n.httpProxyPort) - return rules, nil -} - -// setupPFRules configures packet filter rules to redirect traffic -func (n *MacOSJail) setupPFRules() error { - // Create PF rules - rules, err := n.createPFRules() - if err != nil { - return fmt.Errorf("failed to create PF rules: %v", err) - } - - // Write rules to temp file - err = os.WriteFile(n.pfRulesPath, []byte(rules), 0644) - if err != nil { - return fmt.Errorf("failed to write PF rules file: %v", err) - } - - // Load rules into anchor - cmd := exec.Command("pfctl", "-a", pfAnchorName, "-f", n.pfRulesPath) - err = cmd.Run() - if err != nil { - return fmt.Errorf("failed to load PF rules: %v", err) - } - - // Enable PF if not already enabled - cmd = exec.Command("pfctl", "-E") - _ = cmd.Run() // Ignore error as PF might already be enabled - - // Create and load main ruleset that includes our anchor - mainRules := fmt.Sprintf(`# Temporary main ruleset to include boundary anchor -# Include default Apple anchors (in required order) -# 1. Normalization -scrub-anchor "com.apple/*" -# 2. Queueing -dummynet-anchor "com.apple/*" -# 3. Translation (NAT/RDR) -nat-anchor "com.apple/*" -rdr-anchor "com.apple/*" -rdr-anchor "%s" -# 4. Filtering -anchor "com.apple/*" -anchor "%s" -`, pfAnchorName, pfAnchorName) - - // Write and load the main ruleset - err = os.WriteFile(n.mainRulesPath, []byte(mainRules), 0644) - if err != nil { - return fmt.Errorf("failed to write main PF rules: %v", err) - } - - cmd = exec.Command("pfctl", "-f", n.mainRulesPath) - err = cmd.Run() - if err != nil { - // Don't fail if main rules can't be loaded, but warn - fmt.Fprintf(os.Stderr, "Warning: failed to load main PF rules: %v\n", err) - } - - // Verify that rules were loaded correctly - cmd = exec.Command("pfctl", "-a", pfAnchorName, "-s", "rules") - output, err := cmd.Output() - if err == nil && len(output) > 0 { - // Rules loaded successfully - return nil - } - - return nil -} - -// removePFRules removes PF rules from anchor -func (n *MacOSJail) removePFRules() error { - // Flush the anchor - cmd := exec.Command("pfctl", "-a", pfAnchorName, "-F", "all") - err := cmd.Run() - if err != nil { - return fmt.Errorf("failed to flush PF anchor: %v", err) - } - - return nil -} - -// cleanupTempFiles removes temporary rule files -func (n *MacOSJail) cleanupTempFiles() { - if n.pfRulesPath != "" { - err := os.Remove(n.pfRulesPath) - if err != nil { - n.logger.Error("Failed to remove temporary PF rules file", "file", n.pfRulesPath, "error", err) - } - } - if n.mainRulesPath != "" { - err := os.Remove(n.mainRulesPath) - if err != nil { - n.logger.Error("Failed to remove temporary main PF rules file", "file", n.mainRulesPath, "error", err) - } - } -} - -func (u *MacOSJail) ConfigureAfterCommandExecution(processPID int) error { - return nil -} diff --git a/jail/macos_stub.go b/jail/macos_stub.go deleted file mode 100644 index 656cdc2..0000000 --- a/jail/macos_stub.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !darwin - -package jail - -import "fmt" - -// NewMacOSJail is not available on non-macOS platforms -func NewMacOSJail(_ Config) (Jailer, error) { - return nil, fmt.Errorf("macOS jail not supported on this platform") -} diff --git a/jail/unprivileged.go b/jail/unprivileged.go deleted file mode 100644 index 8504f3d..0000000 --- a/jail/unprivileged.go +++ /dev/null @@ -1,66 +0,0 @@ -package jail - -import ( - "fmt" - "log/slog" - "os/exec" -) - -type Unprivileged struct { - logger *slog.Logger - commandEnv []string - httpProxyPort int - configDir string - caCertPath string - homeDir string - username string - uid int - gid int -} - -func NewUnprivileged(config Config) (*Unprivileged, error) { - return &Unprivileged{ - logger: config.Logger, - httpProxyPort: config.HttpProxyPort, - configDir: config.ConfigDir, - caCertPath: config.CACertPath, - homeDir: config.HomeDir, - username: config.Username, - uid: config.Uid, - gid: config.Gid, - }, nil -} - -func (u *Unprivileged) ConfigureBeforeCommandExecution() error { - u.logger.Debug("Starting in unprivileged mode") - e := getEnvs(u.configDir, u.caCertPath) - p := fmt.Sprintf("http://localhost:%d", u.httpProxyPort) - u.commandEnv = mergeEnvs(e, map[string]string{ - "HOME": u.homeDir, - "USER": u.username, - "LOGNAME": u.username, - "HTTP_PROXY": p, - "HTTPS_PROXY": p, - "http_proxy": p, - "https_proxy": p, - }) - return nil -} - -func (u *Unprivileged) Command(command []string) *exec.Cmd { - u.logger.Debug("Creating unprivileged command", "command", command) - - cmd := exec.Command(command[0], command[1:]...) - cmd.Env = u.commandEnv - - return cmd -} - -func (u *Unprivileged) Close() error { - u.logger.Debug("Closing unprivileged jail") - return nil -} - -func (u *Unprivileged) ConfigureAfterCommandExecution(processPID int) error { - return nil -} From 99f269b4b9b4592b890ed45dda9e30d8cab8ec5a Mon Sep 17 00:00:00 2001 From: YEVHENII SHCHERBINA Date: Thu, 30 Oct 2025 14:02:31 +0000 Subject: [PATCH 2/3] ci: remove macos from CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1931848..50d4bbe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest] runs-on: ${{ matrix.os }} steps: From 97665e0f9fdf36d90b68c9a9feb64651c06a0d39 Mon Sep 17 00:00:00 2001 From: YEVHENII SHCHERBINA Date: Thu, 30 Oct 2025 14:19:44 +0000 Subject: [PATCH 3/3] fix: remove mentioning of unprivileged and macos from docs --- ARCHITECTURE.md | 74 ++++++++----------------------------------------- Makefile | 5 +--- README.md | 21 +++++++------- RELEASES.md | 15 +--------- cli/cli.go | 1 - install.sh | 5 +--- 6 files changed, 25 insertions(+), 96 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 88f0e89..adb5aa9 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -48,7 +48,7 @@ This document describes the architecture and components of boundary, a network i │ │ │ TARGET COMMAND │ │ │ │ │ │ │ │ │ │ │ │ npm install │ ◄── HTTP_PROXY/HTTPS_PROXY env vars │ │ -│ │ │ curl https://... │ ◄── Network isolation (Linux/macOS) │ │ +│ │ │ curl https://... │ ◄── Network isolation (Linux) │ │ │ │ │ git clone │ ◄── DNS redirection │ │ │ │ │ │ │ │ │ │ └─────────────────────┘ │ │ @@ -61,7 +61,7 @@ This document describes the architecture and components of boundary, a network i ## Component Details ### 1. CLI Layer -**Input**: Command line arguments (`--allow`, `--log-level`, `--unprivileged`, target command) +**Input**: Command line arguments (`--allow`, `--log-level`, target command) **Output**: Configured boundary instance and executed target command **Responsibilities**: @@ -106,57 +106,7 @@ Platform-specific implementations: └─────────────────────────────────────────────┘ ``` -#### macOS Jailer -``` -┌─────────────────────────────────────────────┐ -│ MACOS JAILER │ -├─────────────────────────────────────────────┤ -│ │ -│ PF (Packet Filter) Rules │ -│ │ │ -│ ├─ Create custom anchor │ -│ ├─ REDIRECT HTTP → proxy (127.0.0.1:8080) │ -│ ├─ REDIRECT HTTPS → proxy (127.0.0.1:8080) │ -│ └─ Apply rules to specific process group │ -│ │ -│ Process Group Isolation │ -│ │ │ -│ ├─ Create restricted group │ -│ ├─ Set process group ID │ -│ └─ Configure environment variables │ -│ │ -│ Process Execution │ -│ │ │ -│ ├─ Set HTTP_PROXY env var │ -│ ├─ Set HTTPS_PROXY env var │ -│ ├─ Set SSL_CERT_FILE (custom CA) │ -│ └─ Execute with group restrictions │ -│ │ -└─────────────────────────────────────────────┘ -``` -#### Unprivileged Jailer -``` -┌─────────────────────────────────────────────┐ -│ UNPRIVILEGED JAILER │ -├─────────────────────────────────────────────┤ -│ │ -│ Environment Variables Only │ -│ │ │ -│ ├─ Set HTTP_PROXY env var │ -│ ├─ Set HTTPS_PROXY env var │ -│ ├─ Set SSL_CERT_FILE (custom CA) │ -│ └─ No network isolation │ -│ │ -│ Process Execution │ -│ │ │ -│ ├─ Execute with proxy env vars │ -│ └─ Relies on application proxy support │ -│ │ -│ Note: Less secure but works without sudo │ -│ │ -└─────────────────────────────────────────────┘ -``` ### 3. Proxy Server Component **Input**: HTTP/HTTPS requests from jailed processes @@ -427,15 +377,15 @@ Platform-specific implementations: ## Platform Differences -| Aspect | Linux | macOS | Unprivileged | -|--------|--------|--------|--------------| -| **Isolation** | Network namespaces | Process groups + PF | Environment variables only | -| **Traffic Interception** | iptables REDIRECT | PF rdr rules | HTTP_PROXY/HTTPS_PROXY | -| **DNS** | Custom resolv.conf | System DNS + PF | System DNS | -| **Privileges** | Requires sudo | Requires sudo | No privileges required | -| **Security** | Strong isolation | Moderate isolation | Weak (app-dependent) | -| **Compatibility** | Linux kernel 3.8+ | macOS with PF | Any platform | -| **Process Control** | Network namespace | Process group | Standard process | +| Aspect | Linux | +|--------|-------| +| **Isolation** | Network namespaces | +| **Traffic Interception** | iptables REDIRECT | +| **DNS** | Custom resolv.conf | +| **Privileges** | Requires network capabilities (e.g., CAP_NET_ADMIN) | +| **Security** | Strong isolation | +| **Compatibility** | Linux kernel 3.8+ | +| **Process Control** | Network namespace | ## Security Model @@ -445,7 +395,7 @@ Platform-specific implementations: - Fail-safe behavior: unknown requests are denied ### Network Isolation -- Process cannot bypass boundary (except in unprivileged mode) +- Process cannot bypass boundary - All traffic routed through proxy server - TLS interception prevents encrypted bypass diff --git a/Makefile b/Makefile index e2c2beb..3037181 100644 --- a/Makefile +++ b/Makefile @@ -28,10 +28,7 @@ build-all: GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 ./cmd/boundary @echo "Building Linux arm64..." GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -ldflags="$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-linux-arm64 ./cmd/boundary - @echo "Building macOS amd64..." - GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-amd64 ./cmd/boundary - @echo "Building macOS arm64..." - GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -ldflags="$(LDFLAGS)" -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-arm64 ./cmd/boundary + @# macOS builds removed; Linux only @echo "✓ All binaries built successfully!" @echo "Binaries are in the '$(BUILD_DIR)' directory:" @ls -la $(BUILD_DIR)/ diff --git a/README.md b/README.md index 391a804..15c176b 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,11 @@ boundary creates an isolated network environment for target processes, intercept ## Features -- Process-level network isolation (Linux namespaces, macOS process groups) + - Process-level network isolation (Linux namespaces) - HTTP/HTTPS interception with transparent proxy and TLS certificate injection - Wildcard pattern matching for URL patterns - Request logging and monitoring -- Cross-platform support (Linux and macOS) + - Linux support - Default deny-all security model ## Installation @@ -71,21 +71,20 @@ boundary --log-level debug --allow "domain=github.com" -- git pull # Debug info ## Platform Support -| Platform | Implementation | Sudo Required | -|----------|----------------|---------------| -| Linux | Network namespaces + iptables | No | -| macOS | Not supported | - | -| Windows | Not supported | - | +| Platform | Implementation | Privileges | +|----------|--------------------------------|---------------------------| +| Linux | Network namespaces + iptables | CAP_NET_ADMIN (or root) | +| macOS | Not supported | - | +| Windows | Not supported | - | ## Command-Line Options ```text boundary [flags] -- command [args...] ---allow Allow rule (repeatable) ---log-level Set log level (error, warn, info, debug) ---unprivileged Run without network isolation --h, --help Print help + --allow Allow rule (repeatable) + --log-level Set log level (error, warn, info, debug) + -h, --help Print help ``` ## Development diff --git a/RELEASES.md b/RELEASES.md index 67119b0..e6c59da 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -26,8 +26,7 @@ This triggers the **Release** workflow which: |----------|--------------|-------------|----------| | Linux | x64 | `boundary-linux-amd64` | `.tar.gz` | | Linux | ARM64 | `boundary-linux-arm64` | `.tar.gz` | -| macOS | Intel | `boundary-darwin-amd64` | `.tar.gz` | -| macOS | Apple Silicon | `boundary-darwin-arm64` | `.tar.gz` | + ## Version Naming @@ -87,19 +86,7 @@ sudo mv boundary-linux-arm64 /usr/local/bin/boundary boundary --help ``` -**macOS (Intel)** -```bash -curl -fsSL https://github.com/coder/boundary/releases/latest/download/boundary-darwin-amd64.tar.gz | tar -xz -sudo mv boundary-darwin-amd64 /usr/local/bin/boundary -boundary --help -``` -**macOS (Apple Silicon)** -```bash -curl -fsSL https://github.com/coder/boundary/releases/latest/download/boundary-darwin-arm64.tar.gz | tar -xz -sudo mv boundary-darwin-arm64 /usr/local/bin/boundary -boundary --help -``` ### Verify Installation diff --git a/cli/cli.go b/cli/cli.go index 73cf533..1b8ef32 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -27,7 +27,6 @@ type Config struct { AllowStrings []string LogLevel string LogDir string - Unprivileged bool ProxyPort int64 PprofEnabled bool PprofPort int64 diff --git a/install.sh b/install.sh index 3a20da5..0309c03 100755 --- a/install.sh +++ b/install.sh @@ -64,11 +64,8 @@ detect_platform() { Linux*) os="linux" ;; - Darwin*) - os="darwin" - ;; *) - log_error "Unsupported operating system: $(uname -s). Only Linux and macOS are supported." + log_error "Unsupported operating system: $(uname -s). Only Linux is supported." ;; esac