This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Security Model
Relevant source files
Purpose and Scope
This document describes the security architecture of sshfs-mac-docker, including container privileges, authentication mechanisms, network isolation, and access control policies. The system adopts a defense-in-depth approach with multiple security boundaries, though some boundaries are intentionally relaxed to enable the core functionality of bridging remote SSH filesystems to macOS via SMB.
For configuration details of specific security settings, see Configuration Reference. For troubleshooting connection issues related to security restrictions, see Troubleshooting.
Sources : README.md:1-90 Dockerfile:1-34 smb.conf:1-20
Security Boundaries and Trust Model
The system establishes three distinct security boundaries with different trust levels and access control policies:
Key Trust Assumptions :
graph TB
subgraph External["External Network - Untrusted"]
Internet["Internet"]
RemoteSSH["Remote SSH Server\nAuthentication: SSH keys/password"]
end
subgraph HostBoundary["macOS Host - Trusted Local System"]
HostNetwork["127.0.0.1\nLocalhost Only"]
DockerEngine["Docker Engine"]
Finder["macOS Finder\nAuthentication: Guest"]
end
subgraph ContainerBoundary["Docker Container - Isolated Execution"]
SambaService["smbd\nPorts: 139, 445"]
SSHFSClient["sshfs\nRuns as: sshuser"]
SambaShare["/samba-share\nPermissions: 777"]
RemoteMount["/remote\nMounted via FUSE"]
end
Internet -.->|Blocked by Port Binding| SambaService
HostNetwork -->|Port Forward -p 127.0.0.1:139:139| SambaService
HostNetwork -->|Port Forward -p 127.0.0.1:445:445| SambaService
Finder -->|SMB Protocol Guest Access| SambaService
SambaService -->|Force User: sshuser| SambaShare
SambaShare -.->|Symbolic Link| RemoteMount
SSHFSClient -->|SSH Protocol Authenticated| RemoteSSH
SSHFSClient -->|FUSE Mount allow_other| RemoteMount
DockerEngine -->|--privileged Required for FUSE| ContainerBoundary
- macOS Host : Fully trusted - any local user can connect as guest
- Docker Container : Isolated but privileged execution environment
- Remote SSH Server : External system secured by SSH authentication
Sources : README.md:31-34 README.md:57-68 smb.conf:1-20
Container Privilege Requirements
The container must run with --privileged flag to enable FUSE filesystem operations inside the container.
Privileged Mode Necessity
| Capability | Required For | Alternative |
|---|---|---|
| FUSE device access | Mounting SSHFS filesystems via /dev/fuse | None - FUSE requires kernel privileges |
| System call filtering bypass | FUSE mount/umount operations | None - standard containers block these syscalls |
| Device node access | Character device /dev/fuse | Adding specific --device and --cap-add flags |
Container Runtime Configuration
Security Implications :
- Container has nearly full access to host kernel capabilities
- Compromise of container could lead to host system access
- Mitigated by: running on trusted local system, not exposing ports externally
Sources : README.md31 Dockerfile:1-34
flowchart TB
subgraph External["External Network"]
ExternalClient["External Client\nIP: x.x.x.x"]
end
subgraph HostNetwork["macOS Host Network"]
Localhost["127.0.0.1\nLoopback Interface"]
DockerBridge["docker0 Bridge\n172.17.0.0/16"]
ContainerIP["Container IP\ne.g., 172.17.0.2"]
end
subgraph Container["Container Network Namespace"]
Port139["139/tcp\nNetBIOS"]
Port445["445/tcp\nSMB"]
end
ExternalClient -.->|BLOCKED Not bound to 0.0.0.0| Localhost
Localhost -->|Port Forward 127.0.0.1:139| Port139
Localhost -->|Port Forward 127.0.0.1:445| Port445
ContainerIP -->|Direct Access From Host Only| Port139
ContainerIP -->|Direct Access From Host Only| Port445
DockerBridge -.->|Container Reachable| ContainerIP
Network Isolation Model
The system implements localhost-only binding to prevent external network access to the SMB service.
Port Binding Strategy
The -p flag explicitly binds to 127.0.0.1 rather than 0.0.0.0:
- Configuration :
-p 127.0.0.1:139:139 -p 127.0.0.1:445:445 - Effect : Ports 139 and 445 only accept connections from localhost
- External Access : Blocked - remote clients cannot reach the SMB service
- Docker Network Access : Container IP (e.g.,
172.17.0.2) remains reachable from host
Network Access Quirk
Despite port forwarding to 127.0.0.1, macOS Finder must connect using the container's internal Docker IP address. This is a known limitation documented in README.md:57-61
Sources : README.md:31-34 README.md:57-61 Dockerfile:26-27
Authentication and Authorization Model
The system implements a two-stage authentication model with different authentication mechanisms at each boundary.
sequenceDiagram
participant Finder as "macOS Finder"
participant Samba as "smbd\n(Samba Server)"
participant Filesystem as "/samba-share\n(Force User: sshuser)"
participant SSHFS as "sshfs Client"
participant Remote as "Remote SSH Server"
rect rgb(240, 240, 240)
Note over Finder,Samba: Stage 1: macOS to Container
Finder->>Samba: SMB Connection Request
Samba->>Samba: Check: security = user
Samba->>Samba: Check: map to guest = bad user
Samba->>Samba: Result: Map to guest access
Samba-->>Finder: Access Granted (Guest)
Finder->>Samba: File Operation Request
Samba->>Samba: Apply: force user = sshuser
Samba->>Filesystem: Access as sshuser (UID 1000)
end
rect rgb(245, 245, 245)
Note over SSHFS,Remote: Stage 2: Container to Remote
SSHFS->>Remote: SSH Connection Request
Remote->>Remote: Verify SSH key or password
Remote-->>SSHFS: Authentication Success
SSHFS->>Remote: File Operation Request
Remote->>Remote: Apply remote permissions
Remote-->>SSHFS: File Operation Result
end
Authentication Flow
Stage 1: macOS to Container (SMB)
Authentication Mechanism : Guest access with forced user identity
Configuration : smb.conf:1-20
security = user # Authentication mode
map to guest = bad user # Map failed auth to guest
guest ok = yes # Allow guest connections
guest only = yes # Force guest mode
force user = sshuser # All operations as sshuser
Authorization :
- Identity : All macOS clients mapped to
sshuser(UID 1000) - Access Level : Full read/write to
/samba-share - Enforcement Point : Samba service
Stage 2: Container to Remote (SSH)
Authentication Mechanism : SSH key or password (configured by user)
Command : README.md49
Authorization :
- Identity : Remote user credentials provided during mount
- Access Level : Determined by remote server permissions
- Enforcement Point : Remote SSH server
Sources : smb.conf:1-20 README.md:49-53
User Identity and Permissions
The system uses a forced user identity model to ensure consistent file ownership across all access paths.
User Account Configuration
The container creates a dedicated non-root user for SSHFS operations:
User Creation : Dockerfile9
| Property | Value | Purpose |
|---|---|---|
| Username | sshuser | Consistent identity for all operations |
| Password | sshpass | Not used - authentication via SSH to remote |
| UID | 1000 | Default first user UID on most Linux systems |
| GID | 1000 | Default first user GID on most Linux systems |
| Home Directory | /home/sshuser | Created by -m flag |
File Permission Model
Directory Permissions
Samba Share : Dockerfile21
- Owner : root (implicit)
- Permissions :
rwxrwxrwx(777) - Rationale : Allows any user to access, but
force userensures all operations assshuser
Remote Mount Point : Dockerfile12
- Initial Owner : root
- Runtime Owner :
sshuserafter SSHFS mount withuid=1000,gid=1000
Permission Enforcement Points
- macOS → Samba : No enforcement (guest access)
- Samba → Filesystem :
force user = sshuserapplied by Samba - SSHFS → Remote :
uid=1000,gid=1000ensures files created as UID/GID 1000 - Remote → Files : Remote server's normal permission checks
Sources : Dockerfile9 Dockerfile21 smb.conf19 README.md:49-53
FUSE Security Configuration
The system modifies FUSE's default security policy to enable cross-user filesystem access.
user_allow_other Configuration
Setting : Dockerfile24
Default FUSE Behavior :
- FUSE mounts are only accessible by the mounting user
- Other users (including system services) cannot access the mounted filesystem
- Security measure to prevent unauthorized access to user-mounted filesystems
Why It's Required :
Mount Option Interaction
The user_allow_other setting in /etc/fuse.conf permits use of the allow_other mount option:
SSHFS Command : README.md49
| Option | Purpose | Security Impact |
|---|---|---|
allow_other | Permit access by users other than mount owner | Allows smbd (root) to access sshuser-mounted filesystem |
uid=1000 | Set file owner to UID 1000 | Files appear owned by sshuser |
gid=1000 | Set file group to GID 1000 | Files appear grouped by sshuser |
Without These Settings :
- Samba server cannot read files from SSHFS mount
- macOS Finder would receive "Permission Denied" errors
- System would be non-functional
Sources : Dockerfile24 README.md:49-53
Protocol Security
The system enforces minimum protocol versions to prevent use of insecure legacy protocols.
SMB Protocol Enforcement
Configuration : smb.conf:7-8
client min protocol = SMB2
server min protocol = SMB2
Protocol Security Comparison :
| Protocol Version | Status | Security Issues | Allowed |
|---|---|---|---|
| SMB1 | Deprecated | No encryption, vulnerable to exploits (EternalBlue) | ❌ Blocked |
| SMB2 | Legacy | Basic security, limited encryption | ✓ Minimum |
| SMB3 | Modern | Full encryption support, integrity checking | ✓ Allowed |
Enforcement Points :
- Server : Rejects connections attempting to negotiate SMB1
- Client : Would not initiate SMB1 connections (if acting as client)
SSH Protocol Security
Mechanism : Delegated to OpenSSH client and remote server
Security Considerations :
- Encryption : All SSH traffic encrypted by OpenSSH
- Authentication : SSH keys or passwords (user-configured)
- Host Verification : SSH host key checking (user must accept)
- Protocol Version : Determined by OpenSSH client and remote server negotiation
No Container Configuration : The container does not enforce specific SSH protocol settings. Security depends on:
- Remote server SSH configuration
- OpenSSH client defaults (installed via
apt-get install sshfs) - User-provided credentials and host keys
Sources : smb.conf:7-8 Dockerfile6
graph TB
Feature["Feature: macOS Access to Remote SSH Filesystem"]
Feature --> Tradeoff1["Trade-off 1:\nPrivileged Container"]
Feature --> Tradeoff2["Trade-off 2:\nGuest Access"]
Feature --> Tradeoff3["Trade-off 3:\n777 Permissions"]
Feature --> Tradeoff4["Trade-off 4:\nallow_other"]
Tradeoff1 --> Risk1["Risk: Container escape → host access"]
Tradeoff2 --> Risk2["Risk: No authentication to SMB"]
Tradeoff3 --> Risk3["Risk: Any process can write /samba-share"]
Tradeoff4 --> Risk4["Risk: Cross-user FUSE access"]
Risk1 --> Mitigation1["Mitigation: Localhost-only binding"]
Risk2 --> Mitigation2["Mitigation: Port bound to 127.0.0.1"]
Risk3 --> Mitigation3["Mitigation: Container isolation"]
Risk4 --> Mitigation4["Mitigation: force user = sshuser"]
Security Trade-offs and Limitations
The system makes explicit security trade-offs to achieve its functionality of exposing remote SSH filesystems to macOS without kernel extensions.
Intentional Security Relaxations
Known Security Limitations
| Limitation | Description | Impact | Mitigation |
|---|---|---|---|
| No SMB authentication | Any local user can access | Local users can read/write all files | Intended for single-user systems |
| Privileged container | Container has host kernel access | Container compromise = host compromise | Use only on trusted local machine |
| 777 permissions | World-writable directory | Any container process can modify files | Container is single-purpose |
| Guest-only access | No user identity tracking | Cannot audit which macOS user performed action | Audit at remote SSH server level |
Recommended Security Posture
Appropriate Use Cases :
- Single-user macOS development workstation
- Trusted local network environment
- Non-production/non-sensitive data access
- Personal remote file access scenarios
Inappropriate Use Cases :
- Multi-user shared systems
- Production server environments
- Access to highly sensitive data
- Systems exposed to untrusted networks
Sources : README.md:1-90 smb.conf:1-20 Dockerfile:1-34
Security Configuration Summary
Complete Security Configuration Map
Configuration File References
| Security Control | File | Line(s) | Value |
|---|---|---|---|
| Privileged mode | - | - | Docker run flag --privileged |
| Port binding | - | - | Docker run flag -p 127.0.0.1:139:139 -p 127.0.0.1:445:445 |
| User account | Dockerfile9 | 9 | sshuser:sshpass |
| Share permissions | Dockerfile21 | 21 | chmod 777 /samba-share |
| FUSE cross-user | Dockerfile24 | 24 | user_allow_other |
| Security mode | smb.conf3 | 3 | security = user |
| Guest mapping | smb.conf4 | 4 | map to guest = bad user |
| Guest access | smb.conf:13-14 | 13-14 | guest ok = yes, guest only = yes |
| Force user | smb.conf19 | 19 | force user = sshuser |
| SMB protocol | smb.conf:7-8 | 7-8 | min protocol = SMB2 |
| SSHFS options | - | - | allow_other,uid=1000,gid=1000 |
Sources : README.md31 README.md49 Dockerfile9 Dockerfile21 Dockerfile24 smb.conf:1-20