mirror of
https://github.com/nitezs/sub2sing-box.git
synced 2024-12-23 14:44:42 -05:00
♻️ Refactor
This commit is contained in:
parent
573d0056d0
commit
3729675031
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
"github.com/nitezs/sub2sing-box/parser"
|
"github.com/nitezs/sub2sing-box/parser"
|
||||||
"github.com/nitezs/sub2sing-box/util"
|
"github.com/nitezs/sub2sing-box/util"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Convert(
|
func Convert(
|
||||||
@ -99,7 +100,7 @@ func Convert(
|
|||||||
if reg.MatchString(templateDate) || strings.Contains(templateDate, constant.AllCountryTags) || group {
|
if reg.MatchString(templateDate) || strings.Contains(templateDate, constant.AllCountryTags) || group {
|
||||||
outbounds = AddCountryGroup(outbounds, groupType, sortKey, sortType)
|
outbounds = AddCountryGroup(outbounds, groupType, sortKey, sortType)
|
||||||
}
|
}
|
||||||
var template model.Config
|
var template model.Options
|
||||||
if err = json.Unmarshal([]byte(templateDate), &template); err != nil {
|
if err = json.Unmarshal([]byte(templateDate), &template); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -129,20 +130,24 @@ func AddCountryGroup(proxies []model.Outbound, groupType string, sortKey string,
|
|||||||
} else {
|
} else {
|
||||||
if groupType == C.TypeSelector || groupType == "" {
|
if groupType == C.TypeSelector || groupType == "" {
|
||||||
newGroup[country] = model.Outbound{
|
newGroup[country] = model.Outbound{
|
||||||
Tag: country,
|
Outbound: option.Outbound{
|
||||||
Type: groupType,
|
Tag: country,
|
||||||
SelectorOptions: model.SelectorOutboundOptions{
|
Type: groupType,
|
||||||
Outbounds: []string{p.Tag},
|
SelectorOptions: option.SelectorOutboundOptions{
|
||||||
InterruptExistConnections: true,
|
Outbounds: []string{p.Tag},
|
||||||
|
InterruptExistConnections: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if groupType == C.TypeURLTest {
|
} else if groupType == C.TypeURLTest {
|
||||||
newGroup[country] = model.Outbound{
|
newGroup[country] = model.Outbound{
|
||||||
Tag: country,
|
Outbound: option.Outbound{
|
||||||
Type: groupType,
|
Tag: country,
|
||||||
URLTestOptions: model.URLTestOutboundOptions{
|
Type: groupType,
|
||||||
Outbounds: []string{p.Tag},
|
URLTestOptions: option.URLTestOutboundOptions{
|
||||||
InterruptExistConnections: true,
|
Outbounds: []string{p.Tag},
|
||||||
|
InterruptExistConnections: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +205,7 @@ func ReadTemplate(template string) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MergeTemplate(outbounds []model.Outbound, template *model.Config) (string, error) {
|
func MergeTemplate(outbounds []model.Outbound, template *model.Options) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
proxyTags := make([]string, 0)
|
proxyTags := make([]string, 0)
|
||||||
groupTags := make([]string, 0)
|
groupTags := make([]string, 0)
|
||||||
|
47
go.mod
47
go.mod
@ -3,38 +3,49 @@ module github.com/nitezs/sub2sing-box
|
|||||||
go 1.21.5
|
go 1.21.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/sagernet/sing-box v1.10.0-beta.11
|
||||||
golang.org/x/text v0.9.0
|
github.com/spf13/cobra v1.8.1
|
||||||
|
golang.org/x/text v0.18.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bytedance/sonic v1.9.1 // indirect
|
github.com/bytedance/sonic v1.12.3 // indirect
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
github.com/bytedance/sonic/loader v0.2.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.5 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.14.0 // indirect
|
github.com/go-playground/validator/v10 v10.22.1 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.3 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||||
github.com/leodido/go-urn v1.2.4 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/miekg/dns v1.1.61 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||||
|
github.com/sagernet/sing v0.5.0-beta.2 // indirect
|
||||||
|
github.com/sagernet/sing-dns v0.3.0-beta.14 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||||
golang.org/x/crypto v0.9.0 // indirect
|
golang.org/x/arch v0.10.0 // indirect
|
||||||
golang.org/x/net v0.10.0 // indirect
|
golang.org/x/crypto v0.27.0 // indirect
|
||||||
golang.org/x/sys v0.8.0 // indirect
|
golang.org/x/mod v0.19.0 // indirect
|
||||||
google.golang.org/protobuf v1.30.0 // indirect
|
golang.org/x/net v0.29.0 // indirect
|
||||||
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
|
golang.org/x/tools v0.23.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gin-gonic/gin v1.9.1
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
)
|
)
|
||||||
|
138
go.sum
138
go.sum
@ -1,56 +1,84 @@
|
|||||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU=
|
||||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
|
github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
|
||||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
|
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
|
github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA=
|
||||||
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
||||||
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||||
|
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
|
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||||
|
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
|
||||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
|
||||||
|
github.com/sagernet/sing v0.5.0-beta.2 h1:V12EpwtsgYo5OLGjAiGoJobDJZeUsKv0b5y+yGAM6W0=
|
||||||
|
github.com/sagernet/sing v0.5.0-beta.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
|
github.com/sagernet/sing-box v1.10.0-beta.11 h1:SBQtW1WPoNEmTvBCwzngSaFrYfYCqjO/J6CHLZd5S/Q=
|
||||||
|
github.com/sagernet/sing-box v1.10.0-beta.11/go.mod h1:VkzoxRgxB87Z0F2vR00qjmezphU/GG9TtgaUYrAzdY8=
|
||||||
|
github.com/sagernet/sing-dns v0.3.0-beta.14 h1:/s+fJzYKsvLaNDt/2rjpsrDcN8wmCO2JbX6OFrl8Nww=
|
||||||
|
github.com/sagernet/sing-dns v0.3.0-beta.14/go.mod h1:rscgSr5ixOPk8XM9ZMLuMXCyldEQ1nLvdl0nfv+lp00=
|
||||||
|
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||||
|
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
@ -61,34 +89,40 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8=
|
||||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
|
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||||
|
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||||
|
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||||
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
|
102
model/config.go
102
model/config.go
@ -1,102 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import "encoding/json"
|
|
||||||
|
|
||||||
type Listable[T any] []T
|
|
||||||
|
|
||||||
func (l *Listable[T]) UnmarshalJSON(data []byte) error {
|
|
||||||
var arr []T
|
|
||||||
if err := json.Unmarshal(data, &arr); err == nil {
|
|
||||||
*l = arr
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var v T
|
|
||||||
if err := json.Unmarshal(data, &v); err == nil {
|
|
||||||
*l = []T{v}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
Log any `json:"log,omitempty"`
|
|
||||||
DNS any `json:"dns,omitempty"`
|
|
||||||
NTP any `json:"ntp,omitempty"`
|
|
||||||
Inbounds any `json:"inbounds,omitempty"`
|
|
||||||
Outbounds []Outbound `json:"outbounds,omitempty"`
|
|
||||||
Route *RouteOptions `json:"route,omitempty"`
|
|
||||||
Experimental any `json:"experimental,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RouteOptions struct {
|
|
||||||
GeoIP *GeoIPOptions `json:"geoip,omitempty"`
|
|
||||||
Geosite *GeositeOptions `json:"geosite,omitempty"`
|
|
||||||
Rules Listable[Rule] `json:"rules,omitempty"`
|
|
||||||
RuleSet Listable[RuleSet] `json:"rule_set,omitempty"`
|
|
||||||
Final string `json:"final,omitempty"`
|
|
||||||
FindProcess bool `json:"find_process,omitempty"`
|
|
||||||
AutoDetectInterface bool `json:"auto_detect_interface,omitempty"`
|
|
||||||
OverrideAndroidVPN bool `json:"override_android_vpn,omitempty"`
|
|
||||||
DefaultInterface string `json:"default_interface,omitempty"`
|
|
||||||
DefaultMark int `json:"default_mark,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Rule struct {
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
|
||||||
IPVersion int `json:"ip_version,omitempty"`
|
|
||||||
Network Listable[string] `json:"network,omitempty"`
|
|
||||||
AuthUser Listable[string] `json:"auth_user,omitempty"`
|
|
||||||
Protocol string `json:"protocol,omitempty"`
|
|
||||||
Domain Listable[string] `json:"domain,omitempty"`
|
|
||||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
|
||||||
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
|
||||||
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
|
||||||
Geosite Listable[string] `json:"geosite,omitempty"`
|
|
||||||
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
|
||||||
GeoIP Listable[string] `json:"geoip,omitempty"`
|
|
||||||
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
|
|
||||||
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
|
|
||||||
IPCIDR Listable[string] `json:"ip_cidr,omitempty"`
|
|
||||||
IPIsPrivate bool `json:"ip_is_private,omitempty"`
|
|
||||||
SourcePort Listable[uint16] `json:"source_port,omitempty"`
|
|
||||||
SourcePortRange Listable[string] `json:"source_port_range,omitempty"`
|
|
||||||
Port Listable[uint16] `json:"port,omitempty"`
|
|
||||||
PortRange Listable[string] `json:"port_range,omitempty"`
|
|
||||||
ProcessName Listable[string] `json:"process_name,omitempty"`
|
|
||||||
ProcessPath Listable[string] `json:"process_path,omitempty"`
|
|
||||||
PackageName Listable[string] `json:"package_name,omitempty"`
|
|
||||||
User Listable[string] `json:"user,omitempty"`
|
|
||||||
UserID Listable[int32] `json:"user_id,omitempty"`
|
|
||||||
ClashMode string `json:"clash_mode,omitempty"`
|
|
||||||
WIFISSID Listable[string] `json:"wifi_ssid,omitempty"`
|
|
||||||
WIFIBSSID Listable[string] `json:"wifi_bssid,omitempty"`
|
|
||||||
RuleSet Listable[string] `json:"rule_set,omitempty"`
|
|
||||||
RuleSetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
|
|
||||||
Invert bool `json:"invert,omitempty"`
|
|
||||||
Outbound string `json:"outbound,omitempty"`
|
|
||||||
Mode string `json:"mode,omitempty"`
|
|
||||||
Rules Listable[Rule] `json:"rules,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeoIPOptions struct {
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
DownloadURL string `json:"download_url,omitempty"`
|
|
||||||
DownloadDetour string `json:"download_detour,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeositeOptions struct {
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
DownloadURL string `json:"download_url,omitempty"`
|
|
||||||
DownloadDetour string `json:"download_detour,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RuleSet struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Tag string `json:"tag"`
|
|
||||||
Format string `json:"format"`
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
DownloadDetour string `json:"download_detour,omitempty"`
|
|
||||||
UpdateInterval string `json:"update_interval,omitempty"`
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type DirectOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
OverrideAddress string `json:"override_address,omitempty"`
|
|
||||||
OverridePort uint16 `json:"override_port,omitempty"`
|
|
||||||
ProxyProtocol uint8 `json:"proxy_protocol,omitempty"`
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type SelectorOutboundOptions struct {
|
|
||||||
Outbounds []string `json:"outbounds"`
|
|
||||||
Default string `json:"default,omitempty"`
|
|
||||||
InterruptExistConnections bool `json:"interrupt_exist_connections,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type URLTestOutboundOptions struct {
|
|
||||||
Outbounds []string `json:"outbounds"`
|
|
||||||
URL string `json:"url,omitempty"`
|
|
||||||
Interval string `json:"interval,omitempty"`
|
|
||||||
Tolerance uint16 `json:"tolerance,omitempty"`
|
|
||||||
IdleTimeout string `json:"idle_timeout,omitempty"`
|
|
||||||
InterruptExistConnections bool `json:"interrupt_exist_connections,omitempty"`
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type HysteriaOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Up string `json:"up,omitempty"`
|
|
||||||
UpMbps int `json:"up_mbps,omitempty"`
|
|
||||||
Down string `json:"down,omitempty"`
|
|
||||||
DownMbps int `json:"down_mbps,omitempty"`
|
|
||||||
Obfs string `json:"obfs,omitempty"`
|
|
||||||
Auth []byte `json:"auth,omitempty"`
|
|
||||||
AuthString string `json:"auth_str,omitempty"`
|
|
||||||
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
|
|
||||||
ReceiveWindow uint64 `json:"recv_window,omitempty"`
|
|
||||||
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type Hysteria2Obfs struct {
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Hysteria2OutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
UpMbps int `json:"up_mbps,omitempty"`
|
|
||||||
DownMbps int `json:"down_mbps,omitempty"`
|
|
||||||
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
BrutalDebug bool `json:"brutal_debug,omitempty"`
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type OutboundMultiplexOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
Protocol string `json:"protocol,omitempty"`
|
|
||||||
MaxConnections int `json:"max_connections,omitempty"`
|
|
||||||
MinStreams int `json:"min_streams,omitempty"`
|
|
||||||
MaxStreams int `json:"max_streams,omitempty"`
|
|
||||||
Padding bool `json:"padding,omitempty"`
|
|
||||||
Brutal *BrutalOptions `json:"brutal,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BrutalOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
UpMbps int `json:"up_mbps,omitempty"`
|
|
||||||
DownMbps int `json:"down_mbps,omitempty"`
|
|
||||||
}
|
|
41
model/option.go
Normal file
41
model/option.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
type _Options struct {
|
||||||
|
RawMessage json.RawMessage `json:"-"`
|
||||||
|
Schema string `json:"$schema,omitempty"`
|
||||||
|
Log *LogOptions `json:"log,omitempty"`
|
||||||
|
DNS *option.DNSOptions `json:"dns,omitempty"`
|
||||||
|
NTP *option.NTPOptions `json:"ntp,omitempty"`
|
||||||
|
Inbounds []option.Inbound `json:"inbounds,omitempty"`
|
||||||
|
Outbounds []Outbound `json:"outbounds,omitempty"`
|
||||||
|
Route *option.RouteOptions `json:"route,omitempty"`
|
||||||
|
Experimental *option.ExperimentalOptions `json:"experimental,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Options _Options
|
||||||
|
|
||||||
|
func (o *Options) UnmarshalJSON(content []byte) error {
|
||||||
|
decoder := json.NewDecoder(bytes.NewReader(content))
|
||||||
|
decoder.DisallowUnknownFields()
|
||||||
|
err := decoder.Decode((*_Options)(o))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.RawMessage = content
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogOptions struct {
|
||||||
|
Disabled bool `json:"disabled,omitempty"`
|
||||||
|
Level string `json:"level,omitempty"`
|
||||||
|
Output string `json:"output,omitempty"`
|
||||||
|
Timestamp bool `json:"timestamp,omitempty"`
|
||||||
|
DisableColor bool `json:"-"`
|
||||||
|
}
|
@ -1,155 +1,12 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
C "github.com/nitezs/sub2sing-box/constant"
|
C "github.com/nitezs/sub2sing-box/constant"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _Outbound struct {
|
type Outbound struct {
|
||||||
Type string `json:"type"`
|
option.Outbound
|
||||||
Tag string `json:"tag,omitempty"`
|
|
||||||
DirectOptions DirectOutboundOptions `json:"-"`
|
|
||||||
SocksOptions SocksOutboundOptions `json:"-"`
|
|
||||||
HTTPOptions HTTPOutboundOptions `json:"-"`
|
|
||||||
ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"`
|
|
||||||
VMessOptions VMessOutboundOptions `json:"-"`
|
|
||||||
TrojanOptions TrojanOutboundOptions `json:"-"`
|
|
||||||
WireGuardOptions WireGuardOutboundOptions `json:"-"`
|
|
||||||
HysteriaOptions HysteriaOutboundOptions `json:"-"`
|
|
||||||
TorOptions TorOutboundOptions `json:"-"`
|
|
||||||
SSHOptions SSHOutboundOptions `json:"-"`
|
|
||||||
ShadowTLSOptions ShadowTLSOutboundOptions `json:"-"`
|
|
||||||
ShadowsocksROptions ShadowsocksROutboundOptions `json:"-"`
|
|
||||||
VLESSOptions VLESSOutboundOptions `json:"-"`
|
|
||||||
TUICOptions TUICOutboundOptions `json:"-"`
|
|
||||||
Hysteria2Options Hysteria2OutboundOptions `json:"-"`
|
|
||||||
SelectorOptions SelectorOutboundOptions `json:"-"`
|
|
||||||
URLTestOptions URLTestOutboundOptions `json:"-"`
|
|
||||||
}
|
|
||||||
type Outbound _Outbound
|
|
||||||
|
|
||||||
func (h *Outbound) RawOptions() (any, error) {
|
|
||||||
var rawOptionsPtr any
|
|
||||||
switch h.Type {
|
|
||||||
case C.TypeDirect:
|
|
||||||
rawOptionsPtr = &h.DirectOptions
|
|
||||||
case C.TypeBlock, C.TypeDNS:
|
|
||||||
rawOptionsPtr = nil
|
|
||||||
case C.TypeSOCKS:
|
|
||||||
rawOptionsPtr = &h.SocksOptions
|
|
||||||
case C.TypeHTTP:
|
|
||||||
rawOptionsPtr = &h.HTTPOptions
|
|
||||||
case C.TypeShadowsocks:
|
|
||||||
rawOptionsPtr = &h.ShadowsocksOptions
|
|
||||||
case C.TypeVMess:
|
|
||||||
rawOptionsPtr = &h.VMessOptions
|
|
||||||
case C.TypeTrojan:
|
|
||||||
rawOptionsPtr = &h.TrojanOptions
|
|
||||||
case C.TypeWireGuard:
|
|
||||||
rawOptionsPtr = &h.WireGuardOptions
|
|
||||||
case C.TypeHysteria:
|
|
||||||
rawOptionsPtr = &h.HysteriaOptions
|
|
||||||
case C.TypeTor:
|
|
||||||
rawOptionsPtr = &h.TorOptions
|
|
||||||
case C.TypeSSH:
|
|
||||||
rawOptionsPtr = &h.SSHOptions
|
|
||||||
case C.TypeShadowTLS:
|
|
||||||
rawOptionsPtr = &h.ShadowTLSOptions
|
|
||||||
case C.TypeShadowsocksR:
|
|
||||||
rawOptionsPtr = &h.ShadowsocksROptions
|
|
||||||
case C.TypeVLESS:
|
|
||||||
rawOptionsPtr = &h.VLESSOptions
|
|
||||||
case C.TypeTUIC:
|
|
||||||
rawOptionsPtr = &h.TUICOptions
|
|
||||||
case C.TypeHysteria2:
|
|
||||||
rawOptionsPtr = &h.Hysteria2Options
|
|
||||||
case C.TypeSelector:
|
|
||||||
rawOptionsPtr = &h.SelectorOptions
|
|
||||||
case C.TypeURLTest:
|
|
||||||
rawOptionsPtr = &h.URLTestOptions
|
|
||||||
case "":
|
|
||||||
return nil, errors.New("missing outbound type")
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unknown outbound type: " + h.Type)
|
|
||||||
}
|
|
||||||
return rawOptionsPtr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Outbound) MarshalJSON() ([]byte, error) {
|
|
||||||
rawOptions, err := h.RawOptions()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if rawOptions == nil {
|
|
||||||
return json.Marshal((*_Outbound)(h))
|
|
||||||
}
|
|
||||||
result := make(map[string]any)
|
|
||||||
result["type"] = h.Type
|
|
||||||
result["tag"] = h.Tag
|
|
||||||
optsValue := reflect.ValueOf(rawOptions).Elem()
|
|
||||||
optsType := optsValue.Type()
|
|
||||||
for i := 0; i < optsType.NumField(); i++ {
|
|
||||||
field := optsValue.Field(i)
|
|
||||||
fieldType := optsType.Field(i)
|
|
||||||
if fieldType.Anonymous {
|
|
||||||
embeddedFields := reflect.ValueOf(field.Interface())
|
|
||||||
if field.Kind() == reflect.Struct {
|
|
||||||
for j := 0; j < embeddedFields.NumField(); j++ {
|
|
||||||
embeddedField := embeddedFields.Field(j)
|
|
||||||
embeddedFieldType := embeddedFields.Type().Field(j)
|
|
||||||
processField(embeddedField, embeddedFieldType, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
processField(field, fieldType, result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json.Marshal(result)
|
|
||||||
}
|
|
||||||
|
|
||||||
func processField(field reflect.Value, fieldType reflect.StructField, result map[string]any) {
|
|
||||||
jsonTag := fieldType.Tag.Get("json")
|
|
||||||
if jsonTag == "-" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tagParts := strings.Split(jsonTag, ",")
|
|
||||||
tagName := tagParts[0]
|
|
||||||
if len(tagParts) > 1 && tagParts[1] == "omitempty" && field.IsZero() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result[tagName] = field.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
|
||||||
err := json.Unmarshal(bytes, (*_Outbound)(h))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rawOptions, err := h.RawOptions()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if rawOptions == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(bytes, rawOptions)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
rawOptionsType := reflect.TypeOf(rawOptions).Elem()
|
|
||||||
hValue := reflect.ValueOf(h).Elem()
|
|
||||||
for i := 0; i < hValue.NumField(); i++ {
|
|
||||||
fieldType := hValue.Field(i).Type()
|
|
||||||
if fieldType == rawOptionsType {
|
|
||||||
hValue.Field(i).Set(reflect.ValueOf(rawOptions).Elem())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors.New("unknown outbound type: " + h.Type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Outbound) GetOutbounds() []string {
|
func (h *Outbound) GetOutbounds() []string {
|
||||||
@ -170,26 +27,3 @@ func (h *Outbound) SetOutbounds(outbounds []string) {
|
|||||||
h.URLTestOptions.Outbounds = outbounds
|
h.URLTestOptions.Outbounds = outbounds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DialerOptions struct {
|
|
||||||
Detour string `json:"detour,omitempty"`
|
|
||||||
BindInterface string `json:"bind_interface,omitempty"`
|
|
||||||
Inet4BindAddress string `json:"inet4_bind_address,omitempty"`
|
|
||||||
Inet6BindAddress string `json:"inet6_bind_address,omitempty"`
|
|
||||||
ProtectPath string `json:"protect_path,omitempty"`
|
|
||||||
RoutingMark int `json:"routing_mark,omitempty"`
|
|
||||||
ReuseAddr bool `json:"reuse_addr,omitempty"`
|
|
||||||
ConnectTimeout string `json:"connect_timeout,omitempty"`
|
|
||||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
|
||||||
TCPMultiPath bool `json:"tcp_multi_path,omitempty"`
|
|
||||||
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
|
||||||
UDPFragmentDefault bool `json:"-"`
|
|
||||||
DomainStrategy string `json:"domain_strategy,omitempty"`
|
|
||||||
FallbackDelay string `json:"fallback_delay,omitempty"`
|
|
||||||
IsWireGuardListener bool `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerOptions struct {
|
|
||||||
Server string `json:"server"`
|
|
||||||
ServerPort uint16 `json:"server_port"`
|
|
||||||
}
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type ShadowsocksOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Method string `json:"method"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
Plugin string `json:"plugin,omitempty"`
|
|
||||||
PluginOptions string `json:"plugin_opts,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
|
|
||||||
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type ShadowsocksROutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Method string `json:"method"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
Obfs string `json:"obfs,omitempty"`
|
|
||||||
ObfsParam string `json:"obfs_param,omitempty"`
|
|
||||||
Protocol string `json:"protocol,omitempty"`
|
|
||||||
ProtocolParam string `json:"protocol_param,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type ShadowTLSUser struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ShadowTLSHandshakeOptions struct {
|
|
||||||
ServerOptions
|
|
||||||
DialerOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
type ShadowTLSOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Version int `json:"version,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type SocksOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Version string `json:"version,omitempty"`
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
Network Listable[string] `json:"network,omitempty"`
|
|
||||||
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Username string `json:"username,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
|
||||||
}
|
|
14
model/ssh.go
14
model/ssh.go
@ -1,14 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type SSHOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
User string `json:"user,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
PrivateKey Listable[string] `json:"private_key,omitempty"`
|
|
||||||
PrivateKeyPath string `json:"private_key_path,omitempty"`
|
|
||||||
PrivateKeyPassphrase string `json:"private_key_passphrase,omitempty"`
|
|
||||||
HostKey Listable[string] `json:"host_key,omitempty"`
|
|
||||||
HostKeyAlgorithms Listable[string] `json:"host_key_algorithms,omitempty"`
|
|
||||||
ClientVersion string `json:"client_version,omitempty"`
|
|
||||||
}
|
|
40
model/tls.go
40
model/tls.go
@ -1,40 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type OutboundTLSOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
DisableSNI bool `json:"disable_sni,omitempty"`
|
|
||||||
ServerName string `json:"server_name,omitempty"`
|
|
||||||
Insecure bool `json:"insecure,omitempty"`
|
|
||||||
ALPN Listable[string] `json:"alpn,omitempty"`
|
|
||||||
MinVersion string `json:"min_version,omitempty"`
|
|
||||||
MaxVersion string `json:"max_version,omitempty"`
|
|
||||||
CipherSuites Listable[string] `json:"cipher_suites,omitempty"`
|
|
||||||
Certificate Listable[string] `json:"certificate,omitempty"`
|
|
||||||
CertificatePath string `json:"certificate_path,omitempty"`
|
|
||||||
ECH *OutboundECHOptions `json:"ech,omitempty"`
|
|
||||||
UTLS *OutboundUTLSOptions `json:"utls,omitempty"`
|
|
||||||
Reality *OutboundRealityOptions `json:"reality,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutboundECHOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
PQSignatureSchemesEnabled bool `json:"pq_signature_schemes_enabled,omitempty"`
|
|
||||||
DynamicRecordSizingDisabled bool `json:"dynamic_record_sizing_disabled,omitempty"`
|
|
||||||
Config Listable[string] `json:"config,omitempty"`
|
|
||||||
ConfigPath string `json:"config_path,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutboundUTLSOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
Fingerprint string `json:"fingerprint,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutboundRealityOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
PublicKey string `json:"public_key,omitempty"`
|
|
||||||
ShortID string `json:"short_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OutboundTLSOptionsContainer struct {
|
|
||||||
TLS *OutboundTLSOptions `json:"tls,omitempty"`
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type TorOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ExecutablePath string `json:"executable_path,omitempty"`
|
|
||||||
ExtraArgs []string `json:"extra_args,omitempty"`
|
|
||||||
DataDirectory string `json:"data_directory,omitempty"`
|
|
||||||
Options map[string]string `json:"torrc,omitempty"`
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type TrojanOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
Password string `json:"password"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type TUICOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
UUID string `json:"uuid,omitempty"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
CongestionControl string `json:"congestion_control,omitempty"`
|
|
||||||
UDPRelayMode string `json:"udp_relay_mode,omitempty"`
|
|
||||||
UDPOverStream bool `json:"udp_over_stream,omitempty"`
|
|
||||||
ZeroRTTHandshake bool `json:"zero_rtt_handshake,omitempty"`
|
|
||||||
Heartbeat string `json:"heartbeat,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type UDPOverTCPOptions struct {
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
Version uint8 `json:"version,omitempty"`
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type V2RayTransportOptions struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
HTTPOptions V2RayHTTPOptions `json:"-"`
|
|
||||||
WebsocketOptions V2RayWebsocketOptions `json:"-"`
|
|
||||||
QUICOptions V2RayQUICOptions `json:"-"`
|
|
||||||
GRPCOptions V2RayGRPCOptions `json:"-"`
|
|
||||||
HTTPUpgradeOptions V2RayHTTPUpgradeOptions `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *V2RayTransportOptions) MarshalJSON() ([]byte, error) {
|
|
||||||
switch o.Type {
|
|
||||||
case "ws":
|
|
||||||
return json.Marshal(&struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
*V2RayWebsocketOptions
|
|
||||||
}{
|
|
||||||
Type: o.Type,
|
|
||||||
V2RayWebsocketOptions: &o.WebsocketOptions,
|
|
||||||
})
|
|
||||||
case "quic":
|
|
||||||
return json.Marshal(&struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
*V2RayQUICOptions
|
|
||||||
}{
|
|
||||||
Type: o.Type,
|
|
||||||
V2RayQUICOptions: &o.QUICOptions,
|
|
||||||
})
|
|
||||||
case "grpc":
|
|
||||||
return json.Marshal(&struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
*V2RayGRPCOptions
|
|
||||||
}{
|
|
||||||
Type: o.Type,
|
|
||||||
V2RayGRPCOptions: &o.GRPCOptions,
|
|
||||||
})
|
|
||||||
case "http":
|
|
||||||
return json.Marshal(&struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
*V2RayHTTPOptions
|
|
||||||
}{
|
|
||||||
Type: o.Type,
|
|
||||||
V2RayHTTPOptions: &o.HTTPOptions,
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
return json.Marshal(&struct{}{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type V2RayHTTPOptions struct {
|
|
||||||
Host Listable[string] `json:"host,omitempty"`
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
Method string `json:"method,omitempty"`
|
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
|
||||||
IdleTimeout string `json:"idle_timeout,omitempty"`
|
|
||||||
PingTimeout string `json:"ping_timeout,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type V2RayWebsocketOptions struct {
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
|
||||||
MaxEarlyData uint32 `json:"max_early_data,omitempty"`
|
|
||||||
EarlyDataHeaderName string `json:"early_data_header_name,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type V2RayQUICOptions struct{}
|
|
||||||
|
|
||||||
type V2RayGRPCOptions struct {
|
|
||||||
ServiceName string `json:"service_name,omitempty"`
|
|
||||||
IdleTimeout string `json:"idle_timeout,omitempty"`
|
|
||||||
PingTimeout string `json:"ping_timeout,omitempty"`
|
|
||||||
PermitWithoutStream bool `json:"permit_without_stream,omitempty"`
|
|
||||||
ForceLite bool `json:"-"` // for test
|
|
||||||
}
|
|
||||||
|
|
||||||
type V2RayHTTPUpgradeOptions struct {
|
|
||||||
Host string `json:"host,omitempty"`
|
|
||||||
Path string `json:"path,omitempty"`
|
|
||||||
Headers map[string]string `json:"headers,omitempty"`
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type VLESSOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Flow string `json:"flow,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
|
||||||
PacketEncoding *string `json:"packet_encoding,omitempty"`
|
|
||||||
}
|
|
@ -17,18 +17,3 @@ type VmessJson struct {
|
|||||||
Alpn string `json:"alpn"`
|
Alpn string `json:"alpn"`
|
||||||
Fp string `json:"fp"`
|
Fp string `json:"fp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VMessOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
ServerOptions
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Security string `json:"security"`
|
|
||||||
AlterId int `json:"alter_id,omitempty"`
|
|
||||||
GlobalPadding bool `json:"global_padding,omitempty"`
|
|
||||||
AuthenticatedLength bool `json:"authenticated_length,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
OutboundTLSOptionsContainer
|
|
||||||
PacketEncoding string `json:"packet_encoding,omitempty"`
|
|
||||||
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
|
|
||||||
Transport *V2RayTransportOptions `json:"transport,omitempty"`
|
|
||||||
}
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import "net/netip"
|
|
||||||
|
|
||||||
type WireGuardOutboundOptions struct {
|
|
||||||
DialerOptions
|
|
||||||
SystemInterface bool `json:"system_interface,omitempty"`
|
|
||||||
GSO bool `json:"gso,omitempty"`
|
|
||||||
InterfaceName string `json:"interface_name,omitempty"`
|
|
||||||
LocalAddress Listable[netip.Prefix] `json:"local_address"`
|
|
||||||
PrivateKey string `json:"private_key"`
|
|
||||||
Peers []WireGuardPeer `json:"peers,omitempty"`
|
|
||||||
ServerOptions
|
|
||||||
PeerPublicKey string `json:"peer_public_key"`
|
|
||||||
PreSharedKey string `json:"pre_shared_key,omitempty"`
|
|
||||||
Reserved []uint8 `json:"reserved,omitempty"`
|
|
||||||
Workers int `json:"workers,omitempty"`
|
|
||||||
MTU uint32 `json:"mtu,omitempty"`
|
|
||||||
Network string `json:"network,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type WireGuardPeer struct {
|
|
||||||
ServerOptions
|
|
||||||
PublicKey string `json:"public_key,omitempty"`
|
|
||||||
PreSharedKey string `json:"pre_shared_key,omitempty"`
|
|
||||||
AllowedIPs Listable[string] `json:"allowed_ips,omitempty"`
|
|
||||||
Reserved []uint8 `json:"reserved,omitempty"`
|
|
||||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/nitezs/sub2sing-box/constant"
|
"github.com/nitezs/sub2sing-box/constant"
|
||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseHysteria(proxy string) (model.Outbound, error) {
|
func ParseHysteria(proxy string) (model.Outbound, error) {
|
||||||
@ -70,11 +71,11 @@ func ParseHysteria(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
remarks = strings.TrimSpace(remarks)
|
remarks = strings.TrimSpace(remarks)
|
||||||
|
|
||||||
return model.Outbound{
|
return model.Outbound{Outbound: option.Outbound{
|
||||||
Type: "hysteria",
|
Type: "hysteria",
|
||||||
Tag: remarks,
|
Tag: remarks,
|
||||||
HysteriaOptions: model.HysteriaOutboundOptions{
|
HysteriaOptions: option.HysteriaOutboundOptions{
|
||||||
ServerOptions: model.ServerOptions{
|
ServerOptions: option.ServerOptions{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPort: port,
|
ServerPort: port,
|
||||||
},
|
},
|
||||||
@ -82,14 +83,14 @@ func ParseHysteria(proxy string) (model.Outbound, error) {
|
|||||||
Down: downmbps,
|
Down: downmbps,
|
||||||
Auth: []byte(auth),
|
Auth: []byte(auth),
|
||||||
Obfs: obfs,
|
Obfs: obfs,
|
||||||
Network: protocol,
|
Network: option.NetworkList(protocol),
|
||||||
OutboundTLSOptionsContainer: model.OutboundTLSOptionsContainer{
|
OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
|
||||||
TLS: &model.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Insecure: insecureBool,
|
Insecure: insecureBool,
|
||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}}, nil
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/nitezs/sub2sing-box/constant"
|
"github.com/nitezs/sub2sing-box/constant"
|
||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseHysteria2(proxy string) (model.Outbound, error) {
|
func ParseHysteria2(proxy string) (model.Outbound, error) {
|
||||||
@ -64,29 +65,31 @@ func ParseHysteria2(proxy string) (model.Outbound, error) {
|
|||||||
remarks = strings.TrimSpace(remarks)
|
remarks = strings.TrimSpace(remarks)
|
||||||
|
|
||||||
result := model.Outbound{
|
result := model.Outbound{
|
||||||
Type: "hysteria2",
|
Outbound: option.Outbound{
|
||||||
Tag: strings.TrimSpace(remarks),
|
Type: "hysteria2",
|
||||||
Hysteria2Options: model.Hysteria2OutboundOptions{
|
Tag: strings.TrimSpace(remarks),
|
||||||
ServerOptions: model.ServerOptions{
|
Hysteria2Options: option.Hysteria2OutboundOptions{
|
||||||
Server: server,
|
ServerOptions: option.ServerOptions{
|
||||||
ServerPort: port,
|
Server: server,
|
||||||
},
|
ServerPort: port,
|
||||||
Password: password,
|
|
||||||
OutboundTLSOptionsContainer: model.OutboundTLSOptionsContainer{
|
|
||||||
TLS: &model.OutboundTLSOptions{
|
|
||||||
Enabled: enableTLS,
|
|
||||||
Insecure: insecureBool,
|
|
||||||
ServerName: sni,
|
|
||||||
},
|
},
|
||||||
|
Password: password,
|
||||||
|
OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
|
||||||
|
TLS: &option.OutboundTLSOptions{
|
||||||
|
Enabled: enableTLS,
|
||||||
|
Insecure: insecureBool,
|
||||||
|
ServerName: sni,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Network: option.NetworkList(network),
|
||||||
},
|
},
|
||||||
Network: network,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if pinSHA256 != "" {
|
if pinSHA256 != "" {
|
||||||
result.Hysteria2Options.OutboundTLSOptionsContainer.TLS.Certificate = []string{pinSHA256}
|
result.Hysteria2Options.OutboundTLSOptionsContainer.TLS.Certificate = []string{pinSHA256}
|
||||||
}
|
}
|
||||||
if obfs != "" {
|
if obfs != "" {
|
||||||
result.Hysteria2Options.Obfs = &model.Hysteria2Obfs{
|
result.Hysteria2Options.Obfs = &option.Hysteria2Obfs{
|
||||||
Type: obfs,
|
Type: obfs,
|
||||||
Password: obfsPassword,
|
Password: obfsPassword,
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/nitezs/sub2sing-box/constant"
|
"github.com/nitezs/sub2sing-box/constant"
|
||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
"github.com/nitezs/sub2sing-box/util"
|
"github.com/nitezs/sub2sing-box/util"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
||||||
@ -95,17 +96,19 @@ func ParseShadowsocks(proxy string) (model.Outbound, error) {
|
|||||||
remarks = strings.TrimSpace(remarks)
|
remarks = strings.TrimSpace(remarks)
|
||||||
|
|
||||||
result := model.Outbound{
|
result := model.Outbound{
|
||||||
Type: "shadowsocks",
|
Outbound: option.Outbound{
|
||||||
Tag: remarks,
|
Type: "shadowsocks",
|
||||||
ShadowsocksOptions: model.ShadowsocksOutboundOptions{
|
Tag: remarks,
|
||||||
ServerOptions: model.ServerOptions{
|
ShadowsocksOptions: option.ShadowsocksOutboundOptions{
|
||||||
Server: server,
|
ServerOptions: option.ServerOptions{
|
||||||
ServerPort: port,
|
Server: server,
|
||||||
|
ServerPort: port,
|
||||||
|
},
|
||||||
|
Method: method,
|
||||||
|
Password: password,
|
||||||
|
Plugin: plugin,
|
||||||
|
PluginOptions: options,
|
||||||
},
|
},
|
||||||
Method: method,
|
|
||||||
Password: password,
|
|
||||||
Plugin: plugin,
|
|
||||||
PluginOptions: options,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/nitezs/sub2sing-box/constant"
|
"github.com/nitezs/sub2sing-box/constant"
|
||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseTrojan(proxy string) (model.Outbound, error) {
|
func ParseTrojan(proxy string) (model.Outbound, error) {
|
||||||
@ -68,22 +69,22 @@ func ParseTrojan(proxy string) (model.Outbound, error) {
|
|||||||
|
|
||||||
enableUTLS := fp != ""
|
enableUTLS := fp != ""
|
||||||
|
|
||||||
result := model.Outbound{
|
result := model.Outbound{Outbound: option.Outbound{
|
||||||
Type: "trojan",
|
Type: "trojan",
|
||||||
Tag: remarks,
|
Tag: remarks,
|
||||||
TrojanOptions: model.TrojanOutboundOptions{
|
TrojanOptions: option.TrojanOutboundOptions{
|
||||||
ServerOptions: model.ServerOptions{
|
ServerOptions: option.ServerOptions{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPort: port,
|
ServerPort: port,
|
||||||
},
|
},
|
||||||
Password: password,
|
Password: password,
|
||||||
Network: network,
|
Network: option.NetworkList(network),
|
||||||
},
|
},
|
||||||
}
|
}}
|
||||||
|
|
||||||
if security == "xtls" || security == "tls" || sni != "" {
|
if security == "xtls" || security == "tls" || sni != "" {
|
||||||
result.TrojanOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{
|
result.TrojanOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{
|
||||||
TLS: &model.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
@ -93,16 +94,16 @@ func ParseTrojan(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if security == "reality" {
|
if security == "reality" {
|
||||||
result.TrojanOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{
|
result.TrojanOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{
|
||||||
TLS: &model.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
Reality: &model.OutboundRealityOptions{
|
Reality: &option.OutboundRealityOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PublicKey: pbk,
|
PublicKey: pbk,
|
||||||
ShortID: sid,
|
ShortID: sid,
|
||||||
},
|
},
|
||||||
UTLS: &model.OutboundUTLSOptions{
|
UTLS: &option.OutboundUTLSOptions{
|
||||||
Enabled: enableUTLS,
|
Enabled: enableUTLS,
|
||||||
Fingerprint: fp,
|
Fingerprint: fp,
|
||||||
},
|
},
|
||||||
@ -112,21 +113,21 @@ func ParseTrojan(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if network == "ws" {
|
if network == "ws" {
|
||||||
result.TrojanOptions.Transport = &model.V2RayTransportOptions{
|
result.TrojanOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "ws",
|
Type: "ws",
|
||||||
WebsocketOptions: model.V2RayWebsocketOptions{
|
WebsocketOptions: option.V2RayWebsocketOptions{
|
||||||
Path: path,
|
Path: path,
|
||||||
Headers: map[string]string{
|
Headers: map[string]option.Listable[string]{
|
||||||
"Host": host,
|
"Host": {host},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if network == "http" {
|
if network == "http" {
|
||||||
result.TrojanOptions.Transport = &model.V2RayTransportOptions{
|
result.TrojanOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "http",
|
Type: "http",
|
||||||
HTTPOptions: model.V2RayHTTPOptions{
|
HTTPOptions: option.V2RayHTTPOptions{
|
||||||
Host: []string{host},
|
Host: []string{host},
|
||||||
Path: path,
|
Path: path,
|
||||||
},
|
},
|
||||||
@ -134,16 +135,16 @@ func ParseTrojan(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if network == "quic" {
|
if network == "quic" {
|
||||||
result.TrojanOptions.Transport = &model.V2RayTransportOptions{
|
result.TrojanOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "quic",
|
Type: "quic",
|
||||||
QUICOptions: model.V2RayQUICOptions{},
|
QUICOptions: option.V2RayQUICOptions{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if network == "grpc" {
|
if network == "grpc" {
|
||||||
result.TrojanOptions.Transport = &model.V2RayTransportOptions{
|
result.TrojanOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "grpc",
|
Type: "grpc",
|
||||||
GRPCOptions: model.V2RayGRPCOptions{
|
GRPCOptions: option.V2RayGRPCOptions{
|
||||||
ServiceName: serviceName,
|
ServiceName: serviceName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/nitezs/sub2sing-box/constant"
|
"github.com/nitezs/sub2sing-box/constant"
|
||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseVless(proxy string) (model.Outbound, error) {
|
func ParseVless(proxy string) (model.Outbound, error) {
|
||||||
@ -59,22 +60,22 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
remarks = strings.TrimSpace(remarks)
|
remarks = strings.TrimSpace(remarks)
|
||||||
|
|
||||||
result := model.Outbound{
|
result := model.Outbound{Outbound: option.Outbound{
|
||||||
Type: "vless",
|
Type: "vless",
|
||||||
Tag: remarks,
|
Tag: remarks,
|
||||||
VLESSOptions: model.VLESSOutboundOptions{
|
VLESSOptions: option.VLESSOutboundOptions{
|
||||||
ServerOptions: model.ServerOptions{
|
ServerOptions: option.ServerOptions{
|
||||||
Server: server,
|
Server: server,
|
||||||
ServerPort: port,
|
ServerPort: port,
|
||||||
},
|
},
|
||||||
UUID: uuid,
|
UUID: uuid,
|
||||||
Flow: flow,
|
Flow: flow,
|
||||||
},
|
},
|
||||||
}
|
}}
|
||||||
|
|
||||||
if security == "tls" {
|
if security == "tls" {
|
||||||
result.VLESSOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{
|
result.VLESSOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{
|
||||||
TLS: &model.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
@ -84,13 +85,13 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if security == "reality" {
|
if security == "reality" {
|
||||||
result.VLESSOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{
|
result.VLESSOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{
|
||||||
TLS: &model.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
ServerName: sni,
|
ServerName: sni,
|
||||||
Insecure: insecureBool,
|
Insecure: insecureBool,
|
||||||
Reality: &model.OutboundRealityOptions{
|
Reality: &option.OutboundRealityOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
PublicKey: pbk,
|
PublicKey: pbk,
|
||||||
ShortID: sid,
|
ShortID: sid,
|
||||||
@ -100,31 +101,31 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _type == "ws" {
|
if _type == "ws" {
|
||||||
result.VLESSOptions.Transport = &model.V2RayTransportOptions{
|
result.VLESSOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "ws",
|
Type: "ws",
|
||||||
WebsocketOptions: model.V2RayWebsocketOptions{
|
WebsocketOptions: option.V2RayWebsocketOptions{
|
||||||
Path: path,
|
Path: path,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if host != "" {
|
if host != "" {
|
||||||
if result.VLESSOptions.Transport.WebsocketOptions.Headers == nil {
|
if result.VLESSOptions.Transport.WebsocketOptions.Headers == nil {
|
||||||
result.VLESSOptions.Transport.WebsocketOptions.Headers = make(map[string]string)
|
result.VLESSOptions.Transport.WebsocketOptions.Headers = make(map[string]option.Listable[string])
|
||||||
}
|
}
|
||||||
result.VLESSOptions.Transport.WebsocketOptions.Headers["Host"] = host
|
result.VLESSOptions.Transport.WebsocketOptions.Headers["Host"] = option.Listable[string]{host}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _type == "quic" {
|
if _type == "quic" {
|
||||||
result.VLESSOptions.Transport = &model.V2RayTransportOptions{
|
result.VLESSOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "quic",
|
Type: "quic",
|
||||||
QUICOptions: model.V2RayQUICOptions{},
|
QUICOptions: option.V2RayQUICOptions{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _type == "grpc" {
|
if _type == "grpc" {
|
||||||
result.VLESSOptions.Transport = &model.V2RayTransportOptions{
|
result.VLESSOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "grpc",
|
Type: "grpc",
|
||||||
GRPCOptions: model.V2RayGRPCOptions{
|
GRPCOptions: option.V2RayGRPCOptions{
|
||||||
ServiceName: serviceName,
|
ServiceName: serviceName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -139,16 +140,16 @@ func ParseVless(proxy string) (model.Outbound, error) {
|
|||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.VLESSOptions.Transport = &model.V2RayTransportOptions{
|
result.VLESSOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "http",
|
Type: "http",
|
||||||
HTTPOptions: model.V2RayHTTPOptions{
|
HTTPOptions: option.V2RayHTTPOptions{
|
||||||
Host: strings.Split(hosts, ","),
|
Host: strings.Split(hosts, ","),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if enableUTLS {
|
if enableUTLS {
|
||||||
result.VLESSOptions.OutboundTLSOptionsContainer.TLS.UTLS = &model.OutboundUTLSOptions{
|
result.VLESSOptions.OutboundTLSOptionsContainer.TLS.UTLS = &option.OutboundUTLSOptions{
|
||||||
Enabled: enableUTLS,
|
Enabled: enableUTLS,
|
||||||
Fingerprint: fp,
|
Fingerprint: fp,
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/nitezs/sub2sing-box/constant"
|
"github.com/nitezs/sub2sing-box/constant"
|
||||||
"github.com/nitezs/sub2sing-box/model"
|
"github.com/nitezs/sub2sing-box/model"
|
||||||
"github.com/nitezs/sub2sing-box/util"
|
"github.com/nitezs/sub2sing-box/util"
|
||||||
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseVmess(proxy string) (model.Outbound, error) {
|
func ParseVmess(proxy string) (model.Outbound, error) {
|
||||||
@ -64,16 +65,18 @@ func ParseVmess(proxy string) (model.Outbound, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := model.Outbound{
|
result := model.Outbound{
|
||||||
Type: "vmess",
|
Outbound: option.Outbound{
|
||||||
Tag: name,
|
Type: "vmess",
|
||||||
VMessOptions: model.VMessOutboundOptions{
|
Tag: name,
|
||||||
ServerOptions: model.ServerOptions{
|
VMessOptions: option.VMessOutboundOptions{
|
||||||
Server: vmess.Add,
|
ServerOptions: option.ServerOptions{
|
||||||
ServerPort: port,
|
Server: vmess.Add,
|
||||||
|
ServerPort: port,
|
||||||
|
},
|
||||||
|
UUID: vmess.Id,
|
||||||
|
AlterId: aid,
|
||||||
|
Security: vmess.Scy,
|
||||||
},
|
},
|
||||||
UUID: vmess.Id,
|
|
||||||
AlterId: aid,
|
|
||||||
Security: vmess.Scy,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,10 +87,10 @@ func ParseVmess(proxy string) (model.Outbound, error) {
|
|||||||
} else {
|
} else {
|
||||||
alpn = nil
|
alpn = nil
|
||||||
}
|
}
|
||||||
result.VMessOptions.OutboundTLSOptionsContainer = model.OutboundTLSOptionsContainer{
|
result.VMessOptions.OutboundTLSOptionsContainer = option.OutboundTLSOptionsContainer{
|
||||||
TLS: &model.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
UTLS: &model.OutboundUTLSOptions{
|
UTLS: &option.OutboundUTLSOptions{
|
||||||
Fingerprint: vmess.Fp,
|
Fingerprint: vmess.Fp,
|
||||||
},
|
},
|
||||||
ALPN: alpn,
|
ALPN: alpn,
|
||||||
@ -95,7 +98,7 @@ func ParseVmess(proxy string) (model.Outbound, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if vmess.Fp != "" {
|
if vmess.Fp != "" {
|
||||||
result.VMessOptions.OutboundTLSOptionsContainer.TLS.UTLS = &model.OutboundUTLSOptions{
|
result.VMessOptions.OutboundTLSOptionsContainer.TLS.UTLS = &option.OutboundUTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
Fingerprint: vmess.Fp,
|
Fingerprint: vmess.Fp,
|
||||||
}
|
}
|
||||||
@ -109,42 +112,42 @@ func ParseVmess(proxy string) (model.Outbound, error) {
|
|||||||
if vmess.Host == "" {
|
if vmess.Host == "" {
|
||||||
vmess.Host = vmess.Add
|
vmess.Host = vmess.Add
|
||||||
}
|
}
|
||||||
result.VMessOptions.Transport = &model.V2RayTransportOptions{
|
result.VMessOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "ws",
|
Type: "ws",
|
||||||
WebsocketOptions: model.V2RayWebsocketOptions{
|
WebsocketOptions: option.V2RayWebsocketOptions{
|
||||||
Path: vmess.Path,
|
Path: vmess.Path,
|
||||||
Headers: map[string]string{
|
Headers: map[string]option.Listable[string]{
|
||||||
"Host": vmess.Host,
|
"Host": {vmess.Host},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if vmess.Net == "quic" {
|
if vmess.Net == "quic" {
|
||||||
quic := model.V2RayQUICOptions{}
|
quic := option.V2RayQUICOptions{}
|
||||||
result.VMessOptions.Transport = &model.V2RayTransportOptions{
|
result.VMessOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "quic",
|
Type: "quic",
|
||||||
QUICOptions: quic,
|
QUICOptions: quic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if vmess.Net == "grpc" {
|
if vmess.Net == "grpc" {
|
||||||
grpc := model.V2RayGRPCOptions{
|
grpc := option.V2RayGRPCOptions{
|
||||||
ServiceName: vmess.Path,
|
ServiceName: vmess.Path,
|
||||||
PermitWithoutStream: true,
|
PermitWithoutStream: true,
|
||||||
}
|
}
|
||||||
result.VMessOptions.Transport = &model.V2RayTransportOptions{
|
result.VMessOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "grpc",
|
Type: "grpc",
|
||||||
GRPCOptions: grpc,
|
GRPCOptions: grpc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if vmess.Net == "h2" {
|
if vmess.Net == "h2" {
|
||||||
httpOps := model.V2RayHTTPOptions{
|
httpOps := option.V2RayHTTPOptions{
|
||||||
Host: strings.Split(vmess.Host, ","),
|
Host: strings.Split(vmess.Host, ","),
|
||||||
Path: vmess.Path,
|
Path: vmess.Path,
|
||||||
}
|
}
|
||||||
result.VMessOptions.Transport = &model.V2RayTransportOptions{
|
result.VMessOptions.Transport = &option.V2RayTransportOptions{
|
||||||
Type: "http",
|
Type: "http",
|
||||||
HTTPOptions: httpOps,
|
HTTPOptions: httpOps,
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,6 @@
|
|||||||
],
|
],
|
||||||
"outbounds": [
|
"outbounds": [
|
||||||
{
|
{
|
||||||
"interrupt_exist_connections": true,
|
|
||||||
"outbounds": ["<all-proxy-tags>", "direct"],
|
"outbounds": ["<all-proxy-tags>", "direct"],
|
||||||
"tag": "default",
|
"tag": "default",
|
||||||
"type": "selector"
|
"type": "selector"
|
||||||
|
Loading…
Reference in New Issue
Block a user