Open-source project
madeye/BaoLianDeng avatar
madeye/BaoLianDeng

BaoLianDeng wraps a Rust proxy kernel in a native macOS app

A macOS VPN proxy app powered by meow-rs, a Clash-compatible proxy kernel written in Rust

778 stars128 forksSwiftMIT

At a glance

What is it?
BaoLianDeng is a macOS VPN proxy app written in SwiftUI whose traffic handling comes from meow-rs, a Clash and mihomo compatible proxy kernel written in Rust, shipped as a native xcframework. It is on the Mac App Store and in TestFlight, and the source builds a universal framework from a Makefile.
Who is it for?
BaoLianDeng suits a macOS user who wants a Clash style client with a native interface, per app routing, subscription management and traffic statistics, and who is on macOS 14 or later. It is the wrong choice if you need TUIC, WireGuard, SSH or ShadowsocksR, since the README lists those as unsupported differences from upstream mihomo.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 21 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A SwiftUI shell over a Rust proxy core

BaoLianDeng is a macOS VPN proxy app powered by meow-rs, which is a Clash and mihomo compatible proxy kernel written in Rust. The primary language of the project is Swift, the licence is MIT, and the app is distributed through the Mac App Store, with a TestFlight beta and a project site at madeye.github.io/BaoLianDeng.

The split of responsibilities is the whole design. The user interface is a native SwiftUI app with four tabs, Home for subscriptions and nodes, Config for the YAML editor, Data for charts and statistics, and Settings for groups and logs. Underneath, a network extension runs the proxy engine, a DNS component in fake-ip mode, and the rules and routing.

That engine is not written in this repository. It is the meow-rs project, compiled as a native xcframework named MihomoCore.xcframework, and the app's own contribution is the FFI bridge, the extension plumbing and the user interface on top of it.

The interception mechanism is the interesting technical choice. It is built on NETransparentProxyProvider for socket level flow interception, and the README says that is faster than traditional TUN based solutions. The architecture diagram in the README puts the SwiftUI app and a VPNManager on one side, the app extension with the provider and the Rust framework on the other, and shows the Rust core holding the proxy engine, the fake-ip DNS and the rules and routing.

Mode switching travels over a tunnel session message

The app and the tunnel extension are separate processes, and the README explains how they talk.

Inter-process communication uses NETunnelProviderSession.sendMessage for mode switching, traffic statistics and version queries. Both targets share preferences through standard UserDefaults.

That last point is worth pausing on, because it is the mechanism behind a feature people notice. The three proxy modes, rule, global and direct, are selected in the app and have to reach the extension, and the traffic figures shown on the Data tab have to travel back. The sendMessage call carries those requests, and UserDefaults carries the shared configuration, which means the app and the extension agree on the subscription and the selected group without one of them owning the other's state.

It is a small architecture with a real constraint. Because the extension runs in a sandboxed network context that macOS controls, the app cannot simply call into the engine directly, and every operation that affects traffic has to be expressed as a message or a shared preference. The feature list, with per app proxying, rule and global and direct modes, proxy group switching and traffic statistics, all sits on top of that constraint.

Per app routing and subscription management

Two features carry most of the day to day use.

Per app proxy lets you choose which applications go through the proxy as an allowlist, and which bypass it as a blocklist. On macOS this is the feature that differentiates a network extension based client from a system wide VPN, and it is the reason the app needs the transparent proxy provider rather than a packet tunnel.

Subscription management handles adding, refreshing and switching between proxy subscriptions, in both Clash YAML and base64 formats. The Config tab carries a YAML editor, so a subscription is something you can inspect and edit rather than only accept.

Smart proxy routing gives you a node list with latency indicators, the ability to switch proxy groups, and the three modes, rule, global and direct. Traffic analytics then shows daily bar charts, session statistics and monthly summaries for proxy traffic.

The latency indicators are the part that matters in practice, because a subscription with a dozen nodes is only useful if you can tell which ones are currently reachable, and a monthly summary is what tells you whether the subscription you are paying for is worth keeping.

What the kernel does not support

The README has a specific note on known differences from upstream mihomo, and it is the most operationally important paragraph in the document.

TUIC, WireGuard, SSH and ShadowsocksR outbounds are not supported. What is supported is ss, including the built-in ech-tls-tunnel plugin, trojan, vless with vision, with post-quantum encryption and with REALITY, vmess, snell, hysteria2, anytls, plus sing-mux with the smux: prefix. The client-fingerprint option, which is the uTLS behaviour, is live through boring-tls.

This is a real constraint for anyone whose subscription provider hands out a configuration using one of the missing protocols, and it is a constraint that is invisible until a node fails to connect. The practical approach is to read your own subscription YAML and check which outbound types appear before you rely on the app to import it.

The list also tells you the shape of the project. The supported set leans towards recent protocols, vless with post-quantum encryption and REALITY, hysteria2, anytls, which suggests the kernel is tracking current client practice rather than preserving old ones, and the missing WireGuard entry in particular is a notable gap in a protocol list of that kind.

Building the Rust framework as a universal binary

The source build has three steps, and the first one is the part that is not obvious.

The prerequisites are macOS 14.0 or later with Xcode 15 or later, and Rust stable through rustup with both the aarch64-apple-darwin and x86_64-apple-darwin targets installed. The framework is then built with a single make target:

bash
make framework    # macOS universal (arm64 + x86_64)

What that target does is set out in the Makefile. It builds the Rust staticlib for each of the two macOS targets in release mode with symbols stripped, compiles an Objective-C wrapper for each architecture with xcrun clang, combines the Rust archive and the Objective-C object into a static archive per architecture with libtool, and merges the two with lipo into a single fat library. The output is Framework/MihomoCore.xcframework, built from the Rust FFI bridge under Rust/meow-ffi/, which is a staticlib around the meow-rs engine.

The deployment target in the clang invocation is arm64-apple-macos14.0 and x86_64-apple-macos14.0, which is where the macOS 14 floor comes from in the binary itself rather than only in the app's stated requirements.

The makefile also carries an e2e-test target alongside e2e-setup and stress-test targets, so the end to end path has a scripted setup of its own.

Signing, entitlements and the App Store path

The second build step is signing, and the reason it is documented separately is that it needs your Apple developer account.

You copy the template and set your team identifier:

bash
cp Local.xcconfig.template Local.xcconfig
# Edit Local.xcconfig and set DEVELOPMENT_TEAM = YOUR_TEAM_ID

The README explains how to find the value, the Apple Developer portal under Membership and Team ID, a ten character string.

The app and the provider need two capabilities, and the README notes they are already configured in the entitlements file. The first is App Sandbox. The second is Network Extensions, specifically the App Proxy Provider capability for the transparent proxy.

Then the app is opened in Xcode:

bash
open BaoLianDeng.xcodeproj
# Select BaoLianDeng scheme → My Mac → Run (⌘R)

For users who are not building from source, the path is shorter. Download from the Mac App Store, launch BaoLianDeng from Applications, and enable the network extension in System Settings, under General, then Login Items and Extensions, then Network Extensions, where BaoLianDeng is toggled on. That last step is the one people miss, because the app installs and launches without the extension being enabled.

The repository also has a fastlane directory, a Gemfile and Gemfile.lock for the release automation, a .swiftlint.yml, a TransparentProxyMac directory alongside TransparentProxy and TransparentProxyAppex, and a Shared directory for code shared between the targets.

Editorial conclusion

BaoLianDeng suits a macOS user who wants a Clash style client with a native interface, per app routing, subscription management and traffic statistics, and who is on macOS 14 or later. It is the wrong choice if you need TUIC, WireGuard, SSH or ShadowsocksR, since the README lists those as unsupported differences from upstream mihomo. Before adopting it, check the supported outbound list against the protocols your subscriptions actually use, and if you build from source, set your DEVELOPMENT_TEAM in Local.xcconfig and install both Rust targets before running make framework.

Frequently asked questions

What is BaoLianDeng and what is it built on?

It is a macOS VPN proxy app in SwiftUI whose proxy engine, fake-ip DNS and routing come from meow-rs, a Clash and mihomo compatible kernel written in Rust, compiled as a native MihomoCore.xcframework. It uses NETransparentProxyProvider for socket level flow interception.

Which proxy protocols does BaoLianDeng not support?

The README lists known differences from upstream mihomo: TUIC, WireGuard, SSH and ShadowsocksR outbounds are not supported. Supported outbounds include ss with the ech-tls-tunnel plugin, trojan, vless with vision, post-quantum encryption and REALITY, vmess, snell, hysteria2, anytls and sing-mux.

How do I build BaoLianDeng from source?

You need macOS 14.0 or later with Xcode 15 or later, plus Rust stable with the aarch64-apple-darwin and x86_64-apple-darwin targets. Run make framework to build the universal MihomoCore.xcframework, copy Local.xcconfig.template to Local.xcconfig with your DEVELOPMENT_TEAM, then open BaoLianDeng.xcodeproj and run the BaoLianDeng scheme on My Mac.

Official sources

  1. License: MIT
  2. madeye/BaoLianDeng on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/madeye-baoliandeng.svg)](https://hysenlabs.com/projects/madeye-baoliandeng)

Was this useful?