Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ protos:


lib_install:
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.1
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.1
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.8
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.8
npm install

headers:
Expand Down
84 changes: 67 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
# hiddify-core


## Docker
To Run our docker image see https://github.com/hiddify/hiddify-core/pkgs/container/hiddify-core

To Run our docker image see <https://github.com/hiddify/hiddify-core/pkgs/container/hiddify-core>

Docker
```

```bash
docker pull ghcr.io/hiddify/hiddify-core:latest
```

Docker Compose
```

```bash
git clone https://github.com/hiddify/hiddify-core
cd hiddify-core/docker
docker-compose up
```

## WRT

...

## Extension
Expand All @@ -31,23 +34,70 @@ Features and Road map:

- [x] Add Third Party Extension capability
- [x] Test Extension from Browser without any dependency to android/mac/.... `./cmd.sh extension` the open browser `https://127.0.0.1:12346`
- [x] Show Custom UI from Extension `github.com/hiddify/hiddify-core/extension.UpdateUI()`
- [x] Show Custom UI from Extension `github.com/hiddify/hiddify-core/extension.UpdateUI()`
- [x] Show Custom Dialog from Extension `github.com/hiddify/hiddify-core/extension.ShowDialog()`
- [x] Show Alert Dialog from Extension `github.com/hiddify/hiddify-core/extension.ShowMessage()`
- [x] Get Data from UI `github.com/hiddify/hiddify-core/extension.SubmitData()`
- [x] Show Alert Dialog from Extension `github.com/hiddify/hiddify-core/extension.ShowMessage()`
- [x] Get Data from UI `github.com/hiddify/hiddify-core/extension.SubmitData()`
- [x] Save Extension Data from `e.Base.Data`
- [x] Load Extension Data to `e.Base.Data`
- [x] Disable / Enable Extension
- [x] Update user proxies before connecting `github.com/hiddify/hiddify-core/extension.BeforeAppConnect()`
- [x] Run Tiny Independent Instance `github.com/hiddify/hiddify-core/extension/sdk.RunInstance()`
- [x] Parse Any type of configs/url `github.com/hiddify/hiddify-core/extension/sdk.ParseConfig()`
- [x] Disable / Enable Extension
- [x] Update user proxies before connecting `github.com/hiddify/hiddify-core/extension.BeforeAppConnect()`
- [x] Parse Any type of configs/url `github.com/hiddify/hiddify-core/extension/sdk.ParseConfig()`
- [ ] ToDo: Add Support for MultiLanguage Interface
- [ ] ToDo: Custom Extension Outbound
- [ ] ToDo: Custom Extension Inbound
- [ ] ToDo: Custom Extension ProxyConfig

Demo Screenshots from HTML:

<img width="531" alt="image" src="https://github.com/user-attachments/assets/0fbef76f-896f-4c45-a6b8-7a2687c47013">
<img width="531" alt="image" src="https://github.com/user-attachments/assets/15bccfa0-d03e-4354-9368-241836d82948">

Demo Screenshots from HTML:

![image](https://github.com/user-attachments/assets/0fbef76f-896f-4c45-a6b8-7a2687c47013)
![image](https://github.com/user-attachments/assets/15bccfa0-d03e-4354-9368-241836d82948)

## SingBox

Hiddify-core به صورت پیش‌فرض بر پایه `sing-box` نسخه `v1.13.0-alpha.20` (مطابق `go.mod`) اجرا می‌شود و از ساختار رسمی معرفی‌شده در [مستندات sing-box](https://sing-box.sagernet.org/configuration/) پیروی می‌کند.

### مفاهیم پایه

- **ساختار پیکربندی**

```jsonc
{
"log": {},
"dns": {},
"ntp": {},
"certificate": {},
"endpoints": [],
"inbounds": [],
"outbounds": [],
"route": {},
"services": [],
"experimental": {}
}
```

این اسکلت با سند `index.md` در مستندات رسمی هم‌راستاست و توسط توابع `config.BuildConfig()` و `config.BuildConfigJson()` ایجاد و تکمیل می‌شود.
- **راستی‌آزمایی و قالب‌بندی**

- اجرای `sing-box check` برای اعتبارسنجی نهایی.
- اجرای `sing-box format -w -c config.json` جهت یکسان‌سازی قالب.
- در صورت نیاز به ادغام چند فایل: `sing-box merge output.json -c config.json`.

- **منابع رسمی برای فیلدها**

- ورودی‌ها (Inbound): [Inbound](https://sing-box.sagernet.org/configuration/inbound/)
- خروجی‌ها (Outbound): [Outbound](https://sing-box.sagernet.org/configuration/outbound/)
- مسیریابی (Route): [Route](https://sing-box.sagernet.org/configuration/route/)

### گردش کار در هسته

- **تجمیع گزینه‌ها**: ساختار `config.HiddifyOptions` تنظیمات برنامه را نگهداری می‌کند و با `option.Options` کتابخانه sing-box ادغام می‌شود.
- **تولید خودکار کانفیگ**:
- تابع `config.BuildConfig()` ماژول‌های DNS، Inbound، Outbound، و Rules را با آخرین استانداردهای sing-box تنظیم می‌کند.
- تابع `config.ParseConfigContent()` ورودی‌های Clash، V2Ray یا JSON را به ساختار sing-box تبدیل و با `libbox.CheckConfig` اعتبارسنجی می‌کند.
- **به‌روزرسانی Warp و گزینه‌های پویا**: ماژول‌های `config/warp.go` و `config/outbound.go` پروفایل‌های WireGuard/WARP را مطابق API‌های sing-box 1.13 نگاشت می‌کنند.

### نکات نسخه‌ای و مهاجرت

- **توجه به تغییرات 1.11 تا 1.13**: قوانین DNS و Route در نسخه‌های اخیر به Rule-Setها منتقل شده‌اند. برای مهاجرت کانفیگ‌های قدیمی از راهنمای [Migration](https://sing-box.sagernet.org/migration/) استفاده کنید.
- **فعال‌سازی ویژگی‌های جدید**: گزینه‌های `Route.AutoDetectInterface` و `Experimental.ClashAPI` در `config/config.go` مطابق توصیه‌های رسمی فعال شده‌اند.
- **پیگیری انتشارها**: به‌منظور همگام‌سازی با تغییرات آینده، به مخزن [SagerNet/sing-box](https://github.com/SagerNet/sing-box) و صفحه انتشار نسخه‌ها مراجعه کنید.
1 change: 1 addition & 0 deletions bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func SendStringToPort(port int64, msg string) {
var obj C.Dart_CObject
obj._type = C.Dart_CObject_kString
msg_obj := C.CString(msg) // go string -> char*s
defer C.free(unsafe.Pointer(msg_obj))
// union type, we do a force conversion
ptr := unsafe.Pointer(&obj.value[0])
*(**C.char)(ptr) = msg_obj
Expand Down
1 change: 1 addition & 0 deletions cli/bydll/clibydll.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ func main() {

// Call the C function
result := C.parseCli(C.int(len(cArgs)), (**C.char)(unsafe.Pointer(&cArgs[0])))
defer C.free(unsafe.Pointer(result))
fmt.Println(C.GoString(result))
}
120 changes: 19 additions & 101 deletions cmd/cmd_config.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//go:build ignore
// +build ignore

package cmd

import (
Expand Down Expand Up @@ -54,118 +57,33 @@ var commandCheck = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
err := check(configPath)
if err != nil {
log.Fatal(err)
}
},
}

func init() {
commandBuild.Flags().StringVarP(&commandBuildOutputPath, "output", "o", "", "write result to file path instead of stdout")
addHConfigFlags(commandBuild)

mainCommand.AddCommand(commandBuild)
mainCommand.AddCommand(generateConfig)
commandBuild.Flags().StringVarP(&commandBuildOutputPath, "output", "o", "", "write result to file path instead of stdout")
addHConfigFlags(commandBuild)
mainCommand.AddCommand(commandBuild)
mainCommand.AddCommand(generateConfig)
}

func build(path string, optionsPath string) error {
if workingDir != "" {
path = filepath.Join(workingDir, path)
if optionsPath != "" {
optionsPath = filepath.Join(workingDir, optionsPath)
}
os.Chdir(workingDir)
}
options, err := readConfigAt(path)
if err != nil {
return err
}

HiddifyOptions := &defaultConfigs // config.DefaultHiddifyOptions()
if optionsPath != "" {
HiddifyOptions, err = readHiddifyOptionsAt(optionsPath)
if err != nil {
return err
}
}
config, err := config.BuildConfigJson(*HiddifyOptions, *options)
if err != nil {
return err
}
if commandBuildOutputPath != "" {
outputPath, _ := filepath.Abs(filepath.Join(workingDir, commandBuildOutputPath))
err = os.WriteFile(outputPath, []byte(config), 0o644)
if err != nil {
return err
}
fmt.Println("result successfully written to ", outputPath)
// libbox.Setup(outputPath, workingDir, workingDir, true)
// instance, err := NewService(*patchedOptions)
} else {
os.Stdout.WriteString(config)
}
return nil
}

func check(path string) error {
content, err := os.ReadFile(path)
if err != nil {
return err
}
return libbox.CheckConfig(string(content))
}

func readConfigAt(path string) (*option.Options, error) {
content, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var options option.Options
err = options.UnmarshalJSON(content)
if err != nil {
return nil, err
}
return &options, nil
}

func readConfigBytes(content []byte) (*option.Options, error) {
var options option.Options
err := options.UnmarshalJSON(content)
if err != nil {
return nil, err
}
return &options, nil
}

func readHiddifyOptionsAt(path string) (*config.HiddifyOptions, error) {
content, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var options config.HiddifyOptions
err = json.Unmarshal(content, &options)
if err != nil {
return nil, err
}
if options.Warp.WireguardConfigStr != "" {
err := json.Unmarshal([]byte(options.Warp.WireguardConfigStr), &options.Warp.WireguardConfig)
if err != nil {
return nil, err
}
}
if options.Warp2.WireguardConfigStr != "" {
err := json.Unmarshal([]byte(options.Warp2.WireguardConfigStr), &options.Warp2.WireguardConfig)
if err != nil {
return nil, err
}
}

return &options, nil
if workingDir != "" {
path = filepath.Join(workingDir, path)
if optionsPath != "" {
optionsPath = filepath.Join(workingDir, optionsPath)
}
}
if options.Warp2.WireguardConfigStr != "" {
if err := json.Unmarshal([]byte(options.Warp2.WireguardConfigStr), &options.Warp2.WireguardConfig); err != nil {
return nil, err
}
}
return &options, nil
}

func addHConfigFlags(commandRun *cobra.Command) {
commandRun.Flags().StringVarP(&configPath, "config", "c", "", "proxy config path or url")
commandRun.MarkFlagRequired("config")
commandRun.Flags().StringVarP(&hiddifySettingPath, "hiddify", "d", "", "Hiddify Setting JSON Path")
commandRun.Flags().BoolVar(&defaultConfigs.EnableFullConfig, "full-config", false, "allows including tags other than output")
commandRun.Flags().StringVar(&defaultConfigs.LogLevel, "log", "warn", "log level")
commandRun.Flags().BoolVar(&defaultConfigs.InboundOptions.EnableTun, "tun", false, "Enable Tun")
Expand Down
Loading