Skip to content

Commit 38bafc4

Browse files
Anton-Dodonovanton
authored andcommitted
fix: stable example
1 parent 5b317b7 commit 38bafc4

20 files changed

Lines changed: 687 additions & 651 deletions

SINGBOX_INTEGRATION.md

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
# Sing-box Integration Guide
2+
3+
This guide explains how to integrate sing-box with the VPN Client Engine Flutter plugin.
4+
5+
## 🔧 Integration Approaches
6+
7+
### 1. Go Mobile (gomobile) - Recommended for Android/iOS
8+
9+
This is the most reliable approach for mobile platforms.
10+
11+
#### Prerequisites:
12+
```bash
13+
# Install Go (if not already installed)
14+
# Download from https://golang.org/dl/
15+
16+
# Install gomobile
17+
go install golang.org/x/mobile/cmd/gomobile@latest
18+
go install golang.org/x/mobile/cmd/gobind@latest
19+
20+
# Initialize gomobile
21+
gomobile init
22+
```
23+
24+
#### Steps:
25+
26+
1. **Create Go wrapper for sing-box:**
27+
```go
28+
// singbox_wrapper.go
29+
package main
30+
31+
import (
32+
"C"
33+
"encoding/json"
34+
"fmt"
35+
"log"
36+
"os"
37+
"path/filepath"
38+
39+
"github.com/sagernet/sing-box/option"
40+
"github.com/sagernet/sing-box/experimental/libbox"
41+
)
42+
43+
//export StartSingBox
44+
func StartSingBox(configPath *C.char) *C.char {
45+
configPathStr := C.GoString(configPath)
46+
47+
// Read configuration file
48+
configBytes, err := os.ReadFile(configPathStr)
49+
if err != nil {
50+
return C.CString(fmt.Sprintf("error: %v", err))
51+
}
52+
53+
// Parse configuration
54+
var config option.Options
55+
err = json.Unmarshal(configBytes, &config)
56+
if err != nil {
57+
return C.CString(fmt.Sprintf("error parsing config: %v", err))
58+
}
59+
60+
// Create and start sing-box
61+
box, err := libbox.NewBox(config, nil, nil, nil, nil)
62+
if err != nil {
63+
return C.CString(fmt.Sprintf("error creating box: %v", err))
64+
}
65+
66+
err = box.Start()
67+
if err != nil {
68+
return C.CString(fmt.Sprintf("error starting box: %v", err))
69+
}
70+
71+
return C.CString("success")
72+
}
73+
74+
//export StopSingBox
75+
func StopSingBox() *C.char {
76+
// Implementation to stop sing-box
77+
return C.CString("stopped")
78+
}
79+
80+
func main() {}
81+
```
82+
83+
2. **Build for Android:**
84+
```bash
85+
gomobile bind -target=android -o=singbox.aar ./singbox_wrapper.go
86+
```
87+
88+
3. **Build for iOS:**
89+
```bash
90+
gomobile bind -target=ios -o=singbox.framework ./singbox_wrapper.go
91+
```
92+
93+
### 2. Network Extension (iOS) - Current Implementation
94+
95+
The iOS implementation already uses Network Extension with sing-box.
96+
97+
#### Requirements:
98+
- Xcode with Network Extension capability
99+
- sing-box Network Extension target
100+
- Proper entitlements
101+
102+
#### Current Implementation:
103+
```swift
104+
// In VpnclientEngineFlutterPlugin.swift
105+
private func startSingBox(config: String, result: @escaping FlutterResult) {
106+
NETunnelProviderManager.loadAllFromPreferences { managers, error in
107+
// ... implementation
108+
}
109+
}
110+
```
111+
112+
### 3. Process-based (Windows/Linux) - Current Implementation
113+
114+
The Windows implementation launches sing-box as a separate process.
115+
116+
#### Current Implementation:
117+
```cpp
118+
// In vpnclient_engine_flutter_plugin.cpp
119+
bool VpnclientEngineFlutterPlugin::startSingBox(std::string configPath) {
120+
std::string command = "sing-box run -c \"" + configPath + "\"";
121+
// ... implementation
122+
}
123+
```
124+
125+
## 📱 Platform-Specific Setup
126+
127+
### Android
128+
129+
1. **Add VPN permissions to AndroidManifest.xml:**
130+
```xml
131+
<uses-permission android:name="android.permission.INTERNET" />
132+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
133+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
134+
```
135+
136+
2. **Add sing-box AAR to build.gradle:**
137+
```gradle
138+
dependencies {
139+
implementation files('libs/singbox.aar')
140+
}
141+
```
142+
143+
3. **Update Android plugin:**
144+
```kotlin
145+
// In VpnclientEngineFlutterPlugin.kt
146+
private fun startSingBoxWithConfig(config: String, result: Result) {
147+
try {
148+
// Save config to file
149+
val configFile = File(context.cacheDir, "sing-box-config.json")
150+
FileOutputStream(configFile).use { fos ->
151+
fos.write(config.toByteArray())
152+
}
153+
154+
// Call Go mobile bindings
155+
val result = Singbox.startSingBox(configFile.absolutePath)
156+
if (result.startsWith("success")) {
157+
isVpnRunning = true
158+
sendConnectionStatus("connected")
159+
result.success("Connected to VPN using sing-box")
160+
} else {
161+
result.error("SINGBOX_ERROR", result, null)
162+
}
163+
} catch (e: Exception) {
164+
result.error("SINGBOX_ERROR", "Failed to start sing-box", e.message)
165+
}
166+
}
167+
```
168+
169+
### iOS
170+
171+
1. **Enable Network Extension capability in Xcode**
172+
2. **Add sing-box framework to project**
173+
3. **Create Network Extension target**
174+
175+
### Windows
176+
177+
1. **Install sing-box executable**
178+
2. **Add to PATH or specify full path**
179+
3. **Run with administrator privileges**
180+
181+
## 🔄 Integration with Flutter Plugin
182+
183+
### Update Dart Interface
184+
185+
```dart
186+
// In lib/vpnclient_engine_flutter.dart
187+
abstract class VpnclientEngineFlutterPlatform {
188+
Future<void> connect({required String url, String? config});
189+
Future<void> disconnect();
190+
Future<String?> getPlatformVersion();
191+
Future<bool> requestPermissions();
192+
Future<String> getConnectionStatus();
193+
}
194+
```
195+
196+
### Update Platform Implementations
197+
198+
```dart
199+
// In lib/platforms/android.dart
200+
class AndroidVpnclientEngineFlutter extends VpnclientEngineFlutterPlatform {
201+
@override
202+
Future<void> connect({required String url, String? config}) async {
203+
// Call native Android implementation
204+
}
205+
206+
@override
207+
Future<bool> requestPermissions() async {
208+
// Request VPN permissions
209+
}
210+
}
211+
```
212+
213+
## 🚀 Testing
214+
215+
### Test Configuration
216+
217+
```json
218+
{
219+
"log": {
220+
"level": "info"
221+
},
222+
"inbounds": [
223+
{
224+
"type": "tun",
225+
"tag": "tun-in",
226+
"interface_name": "tun0",
227+
"inet4_address": "172.19.0.1/30",
228+
"auto_route": true,
229+
"strict_route": true,
230+
"sniff": true
231+
}
232+
],
233+
"outbounds": [
234+
{
235+
"type": "direct",
236+
"tag": "direct"
237+
}
238+
]
239+
}
240+
```
241+
242+
### Test in Flutter
243+
244+
```dart
245+
// Test sing-box integration
246+
await VPNclientEngine.connect(
247+
url: "sing-box://config",
248+
config: singBoxConfig
249+
);
250+
```
251+
252+
## 📋 Next Steps
253+
254+
1. **Implement Go mobile bindings**
255+
2. **Add proper error handling**
256+
3. **Implement VPN interface setup**
257+
4. **Add configuration validation**
258+
5. **Create comprehensive tests**
259+
6. **Add documentation**
260+
261+
## 🔗 Resources
262+
263+
- [sing-box Documentation](https://sing-box.sagernet.org/)
264+
- [Go Mobile Documentation](https://pkg.go.dev/golang.org/x/mobile)
265+
- [Android VPN Service](https://developer.android.com/reference/android/net/VpnService)
266+
- [iOS Network Extension](https://developer.apple.com/documentation/networkextension)

android/src/main/kotlin/click/vpnclient/engine/VpnclientEngineFlutterPlugin.dart

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)