macOS
June 28, 2026 ยท View on GitHub
macOS uses a Packet Tunnel Network Extension path for VPN mode and a separate local proxy path for proxy-only mode.
Quick Run The Example
Use the example app first if you want to verify that Xcode signing, the Packet Tunnel target, and the Swift package products are wired correctly.
cd example
flutter pub get
../tool/prepare_apple_swiftpm.sh
open macos/Runner.xcworkspace
Open Runner.xcworkspace, not Runner.xcodeproj. Set your Apple Team on both
macOS targets, then run from Xcode or:
flutter run -d macos
What You Need
- macOS 13 or newer for the validated setup
- a Packet Tunnel extension target
- App Groups enabled
- the setup command from the package
Proxy-Only Setup
If you only need proxy-only mode in your own app, run this once from the Flutter
app root after flutter pub get:
dart run flutter_vless:setup_macos_vpn --prepare-only
This updates Flutter's generated macOS SwiftPM metadata and the Runner deployment target to macOS 13.0. It does not add a Packet Tunnel target, entitlements, signing settings, or App Groups.
Recommended Setup Command
For Packet Tunnel VPN mode in your own app, run the full setup command from your Flutter app root:
dart run flutter_vless:setup_macos_vpn \
--bundle-id com.example.myapp \
--group-id group.com.example.myapp \
--team-id ABCDE12345
Bundle Id Convention
Pass the base app bundle id to initializeVless():
await flutterVless.initializeVless(
providerBundleIdentifier: 'com.example.myapp',
groupIdentifier: 'group.com.example.myapp',
);
What To Read Next
That note explains the routing, DNS, and packet-tunnel invariants that matter when you touch the macOS backend.
Runtime Notes
- proxy-only mode and tunnel mode are different code paths
- the packet tunnel is more sensitive to DNS and route configuration than a normal proxy-only start
- the validated Packet Tunnel route model uses
127.0.0.1as the Network Extension remote label,198.18.0.1/24as the local TUN address,198.18.0.1as the default route gateway, explicit DNS servers1.1.1.1and8.8.8.8, and no DNS host-route exclusions - a healthy VPN run should include
Packet tunnel DNS servers=1.1.1.1,8.8.8.8 matchDomains=default,SOCKS URLSession HTTPS health check: ok status=204, and app-side raw TCP probes through the selectedutun - use the architecture note before changing packet tunnel logic
PacketTunnelProvider.swift
The example's macOS tunnel target uses a thin provider wrapper:
example/macos/XrayTunnel/PacketTunnelProvider.swift
The shared implementation lives in the package support target. That keeps app projects from copying the full provider manually.
Common Pitfalls
- mixing up the base bundle id and the extension bundle id
- changing routing without checking DNS reachability
- assuming proxy-only delay results prove packet-tunnel health