A macOS menu-bar VPN client built with Rust. Routes system traffic through a Shadowsocks server using tun2proxy (TUN mode) or exposes a local SOCKS5 proxy (SOCKS5 mode). Lives in the macOS menu bar — no Dock icon.
mac-tunnel/
├── src/
│ ├── main.rs # iced UI + tray icon + app lifecycle
│ ├── proxy.rs # Shadowsocks + tun2proxy engine
│ └── config.rs # Config load/save (~/.config/mac-tunnel/config.json)
├── setuid_launcher.c # Tiny C binary — compiled into the .app, runs mac-tunnel as root
├── install.sh # One-command build + bundle + install to /Applications
├── icon.png # App icon (used by cargo-bundle)
├── build.rs # Cargo build script (no-op on macOS)
└── Cargo.toml # Dependencies + cargo-bundle metadata
# Rust toolchain
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# cargo-bundle (creates the .app)
cargo install cargo-bundle
# Xcode Command Line Tools (for clang, used to compile setuid_launcher.c)
xcode-select --installEverything is handled by a single script:
cd ~/Projects/mac-tunnel
./install.shRun this in a real terminal (Terminal.app or iTerm2), not from inside an IDE or script runner. It calls
sudo -vat the start to prompt for your password upfront — you only type it once.
This script does the following steps in order:
cargo build --release— compiles the Rust binarycargo bundle --release— createstarget/release/bundle/osx/Mac Tunnel.appclang -o ... setuid_launcher.c— compiles the C setuid launcher into the bundle- Copies the Rust binary into the bundle alongside the launcher
- Patches
Info.plistso macOS useslauncheras the entry point sudo cpthe bundle to/Applications/Mac Tunnel.appsudo chown root+sudo chmod u+son the launcher so it runs as root automatically
Why setuid? TUN mode needs root to create a
utunnetwork interface and modify routing tables. The setuid bit on a compiled binary is the correct macOS way to elevate without a password prompt every time.
Settings are saved automatically when you change them in the UI:
~/.config/mac-tunnel/config.json
Example:
{
"server_ip": "1.2.3.4",
"server_port": 8388,
"password": "your-password",
"method": "aes-256-gcm",
"proxy_mode": "Tun"
}proxy_mode can be "Tun" or "Socks5".
- Launch: double-click Mac Tunnel in
/Applicationsor Launchpad - Show window: click the Mac Tunnel icon/text in the menu bar
- Hide window: click the red ✕ close button (app stays running in menu bar)
- Quit: click Mac Tunnel in the menu bar → Quit Mac Tunnel
| Mode | How it works | Requires sudo |
|---|---|---|
| TUN | Routes ALL system traffic through the proxy | Yes (handled by setuid) |
| SOCKS5 | Starts a local proxy at 127.0.0.1:1080 — configure apps manually |
No |
Runtime logs are written to:
/tmp/mac-tunnel.log
After editing the source, just re-run the install script:
cd ~/Projects/mac-tunnel
./install.shThis rebuilds everything and overwrites /Applications/Mac Tunnel.app.