Merge pull request #10 from stitchrs/dev

chore: update for sing
This commit is contained in:
Yuzuki 2023-08-07 18:15:19 +08:00 committed by GitHub
commit 9495913f26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 201 additions and 36 deletions

View File

@ -86,14 +86,14 @@ type V2rayExtraConfig struct {
} }
type RealityConfig struct { type RealityConfig struct {
Dest interface{} `yaml:"Dest" json:"Dest"` Dest string `yaml:"Dest" json:"Dest"`
Xver string `yaml:"Xver" json:"Xver"` Xver string `yaml:"Xver" json:"Xver"`
ServerNames []string `yaml:"ServerNames" json:"ServerNames"` ServerNames []string `yaml:"ServerNames" json:"ServerNames"`
PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"` PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"`
MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"` MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"`
MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"` MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"`
MaxTimeDiff string `yaml:"MaxTimeDiff" json:"MaxTimeDiff"` MaxTimeDiff string `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
ShortIds []string `yaml:"ShortIds" json:"ShortIds"` ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
} }
type DNSConfig struct { type DNSConfig struct {

View File

@ -13,12 +13,12 @@ type CertConfig struct {
} }
type RealityConfig struct { type RealityConfig struct {
Dest interface{} `yaml:"Dest" json:"Dest"` Dest string `yaml:"Dest" json:"Dest"`
Xver uint64 `yaml:"Xver" json:"Xver"` Xver uint64 `yaml:"Xver" json:"Xver"`
ServerNames []string `yaml:"ServerNames" json:"ServerNames"` ServerNames []string `yaml:"ServerNames" json:"ServerNames"`
PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"` PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"`
MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"` MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"`
MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"` MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"`
MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"` MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
ShortIds []string `yaml:"ShortIds" json:"ShortIds"` ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
} }

View File

@ -7,21 +7,30 @@ type Options struct {
CertConfig *CertConfig `yaml:"CertConfig"` CertConfig *CertConfig `yaml:"CertConfig"`
XrayOptions XrayOptions `yaml:"XrayOptions"` XrayOptions XrayOptions `yaml:"XrayOptions"`
HyOptions HyOptions `yaml:"HyOptions"` HyOptions HyOptions `yaml:"HyOptions"`
SingOptions SingOptions `yaml:"SingOptions"`
} }
type XrayOptions struct { type XrayOptions struct {
EnableProxyProtocol bool `yaml:"EnableProxyProtocol"` EnableProxyProtocol bool `yaml:"EnableProxyProtocol"`
EnableDNS bool `yaml:"EnableDNS"` EnableDNS bool `yaml:"EnableDNS"`
DNSType string `yaml:"DNSType"` DNSType string `yaml:"DNSType"`
EnableUot bool `yaml:"EnableUot"` EnableUot bool `yaml:"EnableUot"`
EnableTFO bool `yaml:"EnableTFO"` EnableTFO bool `yaml:"EnableTFO"`
DisableIVCheck bool `yaml:"DisableIVCheck"` DisableIVCheck bool `yaml:"DisableIVCheck"`
DisableSniffing bool `yaml:"DisableSniffing"` DisableSniffing bool `yaml:"DisableSniffing"`
EnableFallback bool `yaml:"EnableFallback"` EnableFallback bool `yaml:"EnableFallback"`
FallBackConfigs []FallBackConfig `yaml:"FallBackConfigs"` FallBackConfigs []FallBackConfigForXray `yaml:"FallBackConfigs"`
} }
type FallBackConfig struct { type SingOptions struct {
EnableProxyProtocol bool `yaml:"EnableProxyProtocol"`
TCPFastOpen bool `yaml:"EnableTFO"`
SniffEnabled bool `yaml:"EnableSniff"`
SniffOverrideDestination bool `yaml:"SniffOverrideDestination"`
FallBackConfigs *FallBackConfigForSing `yaml:"FallBackConfigs"`
}
type FallBackConfigForXray struct {
SNI string `yaml:"SNI"` SNI string `yaml:"SNI"`
Alpn string `yaml:"Alpn"` Alpn string `yaml:"Alpn"`
Path string `yaml:"Path"` Path string `yaml:"Path"`
@ -29,6 +38,16 @@ type FallBackConfig struct {
ProxyProtocolVer uint64 `yaml:"ProxyProtocolVer"` ProxyProtocolVer uint64 `yaml:"ProxyProtocolVer"`
} }
type FallBackConfigForSing struct {
// sing-box
FallBack FallBack `yaml:"FallBack"`
FallBackForALPN map[string]FallBack `yaml:"FallBackForALPN"`
}
type FallBack struct {
Server string `yaml:"Server"`
ServerPort string `yaml:"ServerPort"`
}
type HyOptions struct { type HyOptions struct {
Resolver string `yaml:"Resolver"` Resolver string `yaml:"Resolver"`
ResolvePreference string `yaml:"ResolvePreference"` ResolvePreference string `yaml:"ResolvePreference"`

View File

@ -5,10 +5,12 @@ import (
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/google/uuid"
"net/netip" "net/netip"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/inazumav/sing-box/inbound" "github.com/inazumav/sing-box/inbound"
F "github.com/sagernet/sing/common/format" F "github.com/sagernet/sing/common/format"
@ -30,15 +32,78 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
return option.Inbound{}, fmt.Errorf("the listen ip not vail") return option.Inbound{}, fmt.Errorf("the listen ip not vail")
} }
listen := option.ListenOptions{ listen := option.ListenOptions{
//ProxyProtocol: true, Listen: (*option.ListenAddress)(&addr),
Listen: (*option.ListenAddress)(&addr), ListenPort: uint16(info.Port),
ListenPort: uint16(info.Port), ProxyProtocol: c.SingOptions.EnableProxyProtocol,
TCPFastOpen: c.SingOptions.TCPFastOpen,
InboundOptions: option.InboundOptions{
SniffEnabled: c.SingOptions.SniffEnabled,
SniffOverrideDestination: c.SingOptions.SniffOverrideDestination,
},
} }
tls := option.InboundTLSOptions{ var tls option.InboundTLSOptions
Enabled: info.Tls, if info.Tls || info.Type == "hysteria" {
CertificatePath: c.CertConfig.CertFile, if c.CertConfig == nil {
KeyPath: c.CertConfig.KeyFile, return option.Inbound{}, fmt.Errorf("the CertConfig is not vail")
ServerName: info.ServerName, }
tls.Enabled = true
tls.Insecure = true
tls.ServerName = info.ServerName
switch c.CertConfig.CertMode {
case "none", "":
break // disable
case "reality":
if c.CertConfig.RealityConfig == nil {
return option.Inbound{}, fmt.Errorf("RealityConfig is not valid")
}
rc := c.CertConfig.RealityConfig
tls.ServerName = rc.ServerNames[0]
if len(rc.ShortIds) == 0 {
rc.ShortIds = []string{""}
}
dest, _ := strconv.Atoi(rc.Dest)
mtd, _ := strconv.Atoi(strconv.FormatUint(rc.MaxTimeDiff, 10))
tls.Reality = &option.InboundRealityOptions{
Enabled: true,
ShortID: rc.ShortIds,
PrivateKey: rc.PrivateKey,
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
Handshake: option.InboundRealityHandshakeOptions{
ServerOptions: option.ServerOptions{
Server: rc.ServerNames[0],
ServerPort: uint16(dest),
},
},
}
case "remote":
if info.ExtraConfig.EnableReality == "true" {
if c.CertConfig.RealityConfig == nil {
return option.Inbound{}, fmt.Errorf("RealityConfig is not valid")
}
rc := info.ExtraConfig.RealityConfig
if len(rc.ShortIds) == 0 {
rc.ShortIds = []string{""}
}
dest, _ := strconv.Atoi(rc.Dest)
mtd, _ := strconv.Atoi(rc.MaxTimeDiff)
tls.Reality = &option.InboundRealityOptions{
Enabled: true,
ShortID: rc.ShortIds,
PrivateKey: rc.PrivateKey,
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
Handshake: option.InboundRealityHandshakeOptions{
ServerOptions: option.ServerOptions{
Server: rc.ServerNames[0],
ServerPort: uint16(dest),
},
},
}
}
default:
tls.CertificatePath = c.CertConfig.CertFile
tls.KeyPath = c.CertConfig.KeyFile
}
} }
in := option.Inbound{ in := option.Inbound{
Tag: tag, Tag: tag,
@ -121,6 +186,46 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
in.ShadowsocksOptions.Users = []option.ShadowsocksUser{{ in.ShadowsocksOptions.Users = []option.ShadowsocksUser{{
Password: randomPasswd, Password: randomPasswd,
}} }}
case "trojan":
in.Type = "trojan"
t := option.V2RayTransportOptions{
Type: info.Network,
}
switch info.Network {
case "tcp":
t.Type = ""
case "grpc":
err := json.Unmarshal(info.NetworkSettings, &t.GRPCOptions)
if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
}
}
randomPasswd := uuid.New().String()
in.TrojanOptions = option.TrojanInboundOptions{
ListenOptions: listen,
Users: []option.TrojanUser{{
Name: randomPasswd,
Password: randomPasswd,
}},
TLS: &tls,
Transport: &t,
}
if c.SingOptions.FallBackConfigs != nil {
// fallback handling
fallback := c.SingOptions.FallBackConfigs.FallBack
fallbackPort, err := strconv.Atoi(fallback.ServerPort)
if err == nil {
in.TrojanOptions.Fallback = &option.ServerOptions{
Server: fallback.Server,
ServerPort: uint16(fallbackPort),
}
}
fallbackForALPNMap := c.SingOptions.FallBackConfigs.FallBackForALPN
fallbackForALPN := make(map[string]*option.ServerOptions, len(fallbackForALPNMap))
if err := processFallback(c, fallbackForALPN); err == nil {
in.TrojanOptions.FallbackForALPN = fallbackForALPN
}
}
} }
return in, nil return in, nil
} }

View File

@ -50,6 +50,15 @@ func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
} }
} }
err = b.inbounds[p.Tag].(*inbound.ShadowsocksMulti).AddUsers(us) err = b.inbounds[p.Tag].(*inbound.ShadowsocksMulti).AddUsers(us)
case "trojan":
us := make([]option.TrojanUser, len(p.UserInfo))
for i := range p.UserInfo {
us[i] = option.TrojanUser{
Name: p.UserInfo[i].Uuid,
Password: p.UserInfo[i].Uuid,
}
}
err = b.inbounds[p.Tag].(*inbound.Trojan).AddUsers(us)
} }
if err != nil { if err != nil {
return 0, err return 0, err

19
core/sing/utils.go Normal file
View File

@ -0,0 +1,19 @@
package sing
import (
"fmt"
"github.com/InazumaV/V2bX/conf"
"github.com/inazumav/sing-box/option"
"strconv"
)
func processFallback(c *conf.Options, fallbackForALPN map[string]*option.ServerOptions) error {
for k, v := range c.SingOptions.FallBackConfigs.FallBackForALPN {
fallbackPort, err := strconv.Atoi(v.ServerPort)
if err != nil {
return fmt.Errorf("unable to parse fallbackForALPN server port error: %s", err)
}
fallbackForALPN[k] = &option.ServerOptions{Server: v.Server, ServerPort: uint16(fallbackPort)}
}
return nil
}

View File

@ -274,7 +274,7 @@ func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *c
return nil return nil
} }
func buildVlessFallbacks(fallbackConfigs []conf.FallBackConfig) ([]*coreConf.VLessInboundFallback, error) { func buildVlessFallbacks(fallbackConfigs []conf.FallBackConfigForXray) ([]*coreConf.VLessInboundFallback, error) {
if fallbackConfigs == nil { if fallbackConfigs == nil {
return nil, fmt.Errorf("you must provide FallBackConfigs") return nil, fmt.Errorf("you must provide FallBackConfigs")
} }
@ -299,7 +299,7 @@ func buildVlessFallbacks(fallbackConfigs []conf.FallBackConfig) ([]*coreConf.VLe
return vlessFallBacks, nil return vlessFallBacks, nil
} }
func buildTrojanFallbacks(fallbackConfigs []conf.FallBackConfig) ([]*coreConf.TrojanInboundFallback, error) { func buildTrojanFallbacks(fallbackConfigs []conf.FallBackConfigForXray) ([]*coreConf.TrojanInboundFallback, error) {
if fallbackConfigs == nil { if fallbackConfigs == nil {
return nil, fmt.Errorf("you must provide FallBackConfigs") return nil, fmt.Errorf("you must provide FallBackConfigs")
} }

View File

@ -38,6 +38,19 @@ Nodes:
Path: # HTTP PATH, Empty for any Path: # HTTP PATH, Empty for any
Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details. Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details.
ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
SingOptions:
EnableTFO: true
SniffEnabled: true
SniffOverrideDestination: true
EnableProxyProtocol: false
FallBackConfigs:
FallBack:
Server: 127.0.0.1
ServerPort: 8080
FallBackForALPN:
http/1.1:
Server: 127.0.0.1
ServerPort: 8081
HyOptions: HyOptions:
Resolver: "udp://1.1.1.1:53" # DNS resolver address Resolver: "udp://1.1.1.1:53" # DNS resolver address
ResolvePreference: 64 # DNS IPv4/IPv6 preference. Available options: "64" (IPv6 first, fallback to IPv4), "46" (IPv4 first, fallback to IPv6), "6" (IPv6 only), "4" (IPv4 only) ResolvePreference: 64 # DNS IPv4/IPv6 preference. Available options: "64" (IPv6 first, fallback to IPv4), "46" (IPv4 first, fallback to IPv6), "6" (IPv6 only), "4" (IPv4 only)