diff --git a/config/config.go b/config/config.go index 1cabed2..75933a5 100644 --- a/config/config.go +++ b/config/config.go @@ -14,6 +14,7 @@ import ( "time" C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" dns "github.com/sagernet/sing-dns" ) @@ -494,6 +495,53 @@ func setRoutingOptions(options *option.Options, opt *HiddifyOptions) { }, ) } + + // Per-App Proxy for Desktop platforms (Windows, Linux, macOS) + if runtime.GOOS != "android" { + if opt.PerAppProxyOptions.Mode == "include" && len(opt.PerAppProxyOptions.IncludedApplications) > 0 { + // Mode: Only selected apps use VPN + log.Info("[Per-App] Mode: include - ", len(opt.PerAppProxyOptions.IncludedApplications), " apps will use VPN") + + // Rule 1: Selected apps → VPN + routeRules = append( + routeRules, + option.Rule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + ProcessName: opt.PerAppProxyOptions.IncludedApplications, + Outbound: OutboundSelectTag, + }, + }, + ) + + // Rule 2: All other apps → Direct + routeRules = append( + routeRules, + option.Rule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + Outbound: OutboundDirectTag, + }, + }, + ) + } else if opt.PerAppProxyOptions.Mode == "exclude" && len(opt.PerAppProxyOptions.ExcludedApplications) > 0 { + // Mode: Excluded apps DON'T use VPN + log.Info("[Per-App] Mode: exclude - ", len(opt.PerAppProxyOptions.ExcludedApplications), " apps will bypass VPN") + + // Rule: Excluded apps → Direct (rest goes through VPN by default) + routeRules = append( + routeRules, + option.Rule{ + Type: C.RuleTypeDefault, + DefaultOptions: option.DefaultRule{ + ProcessName: opt.PerAppProxyOptions.ExcludedApplications, + Outbound: OutboundDirectTag, + }, + }, + ) + } + } + routeRules = append(routeRules, option.Rule{ Type: C.RuleTypeDefault, DefaultOptions: option.DefaultRule{ diff --git a/config/hiddify_option.go b/config/hiddify_option.go index 5b13242..9aab5ea 100644 --- a/config/hiddify_option.go +++ b/config/hiddify_option.go @@ -26,6 +26,13 @@ type HiddifyOptions struct { InboundOptions URLTestOptions RouteOptions + PerAppProxyOptions +} + +type PerAppProxyOptions struct { + Mode string `json:"per-app-proxy-mode"` // "off", "include", "exclude" + IncludedApplications []string `json:"included-applications"` // ["chrome.exe", "firefox.exe"] + ExcludedApplications []string `json:"excluded-applications"` // ["steam.exe", "uTorrent.exe"] } type DNSOptions struct {