Add support for local outbound connections in sandbox configuration
This commit is contained in:
@@ -71,6 +71,7 @@ Create `~/.fence.json` to configure allowed domains and filesystem access:
|
|||||||
| `allowUnixSockets` | List of allowed Unix socket paths (macOS) |
|
| `allowUnixSockets` | List of allowed Unix socket paths (macOS) |
|
||||||
| `allowAllUnixSockets` | Allow all Unix sockets |
|
| `allowAllUnixSockets` | Allow all Unix sockets |
|
||||||
| `allowLocalBinding` | Allow binding to local ports |
|
| `allowLocalBinding` | Allow binding to local ports |
|
||||||
|
| `allowLocalOutbound` | Allow outbound connections to localhost, e.g., local DBs (defaults to `allowLocalBinding` if not set) |
|
||||||
| `httpProxyPort` | Fixed port for HTTP proxy (default: random available port) |
|
| `httpProxyPort` | Fixed port for HTTP proxy (default: random available port) |
|
||||||
| `socksProxyPort` | Fixed port for SOCKS5 proxy (default: random available port) |
|
| `socksProxyPort` | Fixed port for SOCKS5 proxy (default: random available port) |
|
||||||
|
|
||||||
@@ -138,6 +139,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Check if platform supports sandboxing (macOS/Linux)
|
||||||
|
if !fence.IsSupported() {
|
||||||
|
fmt.Println("Sandboxing not supported on this platform")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Create config
|
// Create config
|
||||||
cfg := &fence.Config{
|
cfg := &fence.Config{
|
||||||
Network: fence.NetworkConfig{
|
Network: fence.NetworkConfig{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type NetworkConfig struct {
|
|||||||
AllowUnixSockets []string `json:"allowUnixSockets,omitempty"`
|
AllowUnixSockets []string `json:"allowUnixSockets,omitempty"`
|
||||||
AllowAllUnixSockets bool `json:"allowAllUnixSockets,omitempty"`
|
AllowAllUnixSockets bool `json:"allowAllUnixSockets,omitempty"`
|
||||||
AllowLocalBinding bool `json:"allowLocalBinding,omitempty"`
|
AllowLocalBinding bool `json:"allowLocalBinding,omitempty"`
|
||||||
|
AllowLocalOutbound *bool `json:"allowLocalOutbound,omitempty"` // If nil, defaults to AllowLocalBinding value
|
||||||
HTTPProxyPort int `json:"httpProxyPort,omitempty"`
|
HTTPProxyPort int `json:"httpProxyPort,omitempty"`
|
||||||
SOCKSProxyPort int `json:"socksProxyPort,omitempty"`
|
SOCKSProxyPort int `json:"socksProxyPort,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type MacOSSandboxParams struct {
|
|||||||
AllowUnixSockets []string
|
AllowUnixSockets []string
|
||||||
AllowAllUnixSockets bool
|
AllowAllUnixSockets bool
|
||||||
AllowLocalBinding bool
|
AllowLocalBinding bool
|
||||||
|
AllowLocalOutbound bool
|
||||||
ReadDenyPaths []string
|
ReadDenyPaths []string
|
||||||
WriteAllowPaths []string
|
WriteAllowPaths []string
|
||||||
WriteDenyPaths []string
|
WriteDenyPaths []string
|
||||||
@@ -419,10 +420,15 @@ func GenerateSandboxProfile(params MacOSSandboxParams) string {
|
|||||||
profile.WriteString("(allow network*)\n")
|
profile.WriteString("(allow network*)\n")
|
||||||
} else {
|
} else {
|
||||||
if params.AllowLocalBinding {
|
if params.AllowLocalBinding {
|
||||||
|
// Allow binding and inbound connections on localhost (for servers)
|
||||||
profile.WriteString(`(allow network-bind (local ip "localhost:*"))
|
profile.WriteString(`(allow network-bind (local ip "localhost:*"))
|
||||||
(allow network-inbound (local ip "localhost:*"))
|
(allow network-inbound (local ip "localhost:*"))
|
||||||
(allow network-outbound (local ip "localhost:*"))
|
|
||||||
`)
|
`)
|
||||||
|
// Process can make outbound connections to localhost
|
||||||
|
if params.AllowLocalOutbound {
|
||||||
|
profile.WriteString(`(allow network-outbound (local ip "localhost:*"))
|
||||||
|
`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.AllowAllUnixSockets {
|
if params.AllowAllUnixSockets {
|
||||||
@@ -492,6 +498,11 @@ func WrapCommandMacOS(cfg *config.Config, command string, httpPort, socksPort in
|
|||||||
// Enable local binding if ports are exposed or if explicitly configured
|
// Enable local binding if ports are exposed or if explicitly configured
|
||||||
allowLocalBinding := cfg.Network.AllowLocalBinding || len(exposedPorts) > 0
|
allowLocalBinding := cfg.Network.AllowLocalBinding || len(exposedPorts) > 0
|
||||||
|
|
||||||
|
allowLocalOutbound := allowLocalBinding
|
||||||
|
if cfg.Network.AllowLocalOutbound != nil {
|
||||||
|
allowLocalOutbound = *cfg.Network.AllowLocalOutbound
|
||||||
|
}
|
||||||
|
|
||||||
params := MacOSSandboxParams{
|
params := MacOSSandboxParams{
|
||||||
Command: command,
|
Command: command,
|
||||||
NeedsNetworkRestriction: needsNetwork || len(cfg.Network.AllowedDomains) == 0, // Block if no domains allowed
|
NeedsNetworkRestriction: needsNetwork || len(cfg.Network.AllowedDomains) == 0, // Block if no domains allowed
|
||||||
@@ -500,6 +511,7 @@ func WrapCommandMacOS(cfg *config.Config, command string, httpPort, socksPort in
|
|||||||
AllowUnixSockets: cfg.Network.AllowUnixSockets,
|
AllowUnixSockets: cfg.Network.AllowUnixSockets,
|
||||||
AllowAllUnixSockets: cfg.Network.AllowAllUnixSockets,
|
AllowAllUnixSockets: cfg.Network.AllowAllUnixSockets,
|
||||||
AllowLocalBinding: allowLocalBinding,
|
AllowLocalBinding: allowLocalBinding,
|
||||||
|
AllowLocalOutbound: allowLocalOutbound,
|
||||||
ReadDenyPaths: cfg.Filesystem.DenyRead,
|
ReadDenyPaths: cfg.Filesystem.DenyRead,
|
||||||
WriteAllowPaths: allowPaths,
|
WriteAllowPaths: allowPaths,
|
||||||
WriteDenyPaths: cfg.Filesystem.DenyWrite,
|
WriteDenyPaths: cfg.Filesystem.DenyWrite,
|
||||||
@@ -510,6 +522,9 @@ func WrapCommandMacOS(cfg *config.Config, command string, httpPort, socksPort in
|
|||||||
if debug && len(exposedPorts) > 0 {
|
if debug && len(exposedPorts) > 0 {
|
||||||
fmt.Fprintf(os.Stderr, "[fence:macos] Enabling local binding for exposed ports: %v\n", exposedPorts)
|
fmt.Fprintf(os.Stderr, "[fence:macos] Enabling local binding for exposed ports: %v\n", exposedPorts)
|
||||||
}
|
}
|
||||||
|
if debug && allowLocalBinding && !allowLocalOutbound {
|
||||||
|
fmt.Fprintf(os.Stderr, "[fence:macos] Blocking localhost outbound (AllowLocalOutbound=false)\n")
|
||||||
|
}
|
||||||
|
|
||||||
profile := GenerateSandboxProfile(params)
|
profile := GenerateSandboxProfile(params)
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,15 @@ package fence
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Use-Tusk/fence/internal/config"
|
"github.com/Use-Tusk/fence/internal/config"
|
||||||
|
"github.com/Use-Tusk/fence/internal/platform"
|
||||||
"github.com/Use-Tusk/fence/internal/sandbox"
|
"github.com/Use-Tusk/fence/internal/sandbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// IsSupported returns true if the current platform supports sandboxing (macOS/Linux).
|
||||||
|
func IsSupported() bool {
|
||||||
|
return platform.IsSupported()
|
||||||
|
}
|
||||||
|
|
||||||
// Config is the configuration for fence.
|
// Config is the configuration for fence.
|
||||||
type Config = config.Config
|
type Config = config.Config
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user