mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-14 00:51:12 +03:00
182 lines
5.1 KiB
Go
182 lines
5.1 KiB
Go
package clash
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"strings"
|
|
|
|
"github.com/sagernet/sing-box/option"
|
|
"github.com/sagernet/sing/common/json/badoption"
|
|
)
|
|
|
|
type HTTPOptions struct {
|
|
Method string `yaml:"method,omitempty"`
|
|
Path []string `yaml:"path,omitempty"`
|
|
Headers badoption.HTTPHeader `yaml:"headers,omitempty"`
|
|
}
|
|
|
|
type HTTP2Options struct {
|
|
Host []string `yaml:"host,omitempty"`
|
|
Path string `yaml:"path,omitempty"`
|
|
}
|
|
|
|
type GrpcOptions struct {
|
|
GrpcServiceName string `yaml:"grpc-service-name,omitempty"`
|
|
}
|
|
|
|
type WSOptions struct {
|
|
Path string `yaml:"path,omitempty"`
|
|
Headers map[string]string `yaml:"headers,omitempty"`
|
|
MaxEarlyData int `yaml:"max-early-data,omitempty"`
|
|
EarlyDataHeaderName string `yaml:"early-data-header-name,omitempty"`
|
|
V2rayHttpUpgrade bool `yaml:"v2ray-http-upgrade,omitempty"`
|
|
}
|
|
|
|
type MuxOptions struct {
|
|
Enabled bool `yaml:"enabled,omitempty"`
|
|
Protocol string `yaml:"protocol,omitempty"`
|
|
MaxConnections int `yaml:"max-connections,omitempty"`
|
|
MinStreams int `yaml:"min-streams,omitempty"`
|
|
MaxStreams int `yaml:"max-streams,omitempty"`
|
|
Padding bool `yaml:"padding,omitempty"`
|
|
BrutalOpts *BrutalOptions `yaml:"brutal-opts,omitempty"`
|
|
}
|
|
|
|
func (s *MuxOptions) Build() *option.OutboundMultiplexOptions {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
return &option.OutboundMultiplexOptions{
|
|
Enabled: s.Enabled,
|
|
Protocol: s.Protocol,
|
|
MaxConnections: s.MaxConnections,
|
|
MinStreams: s.MinStreams,
|
|
MaxStreams: s.MaxStreams,
|
|
Padding: s.Padding,
|
|
Brutal: s.BrutalOpts.Build(),
|
|
}
|
|
}
|
|
|
|
type BrutalOptions struct {
|
|
Enabled bool `yaml:"enabled,omitempty"`
|
|
Up string `yaml:"up,omitempty"`
|
|
Down string `yaml:"down,omitempty"`
|
|
}
|
|
|
|
func (b *BrutalOptions) Build() *option.BrutalOptions {
|
|
if b == nil {
|
|
return nil
|
|
}
|
|
return &option.BrutalOptions{
|
|
Enabled: b.Enabled,
|
|
UpMbps: clashSpeedToIntMbps(b.Up),
|
|
DownMbps: clashSpeedToIntMbps(b.Down),
|
|
}
|
|
}
|
|
|
|
type RealityOptions struct {
|
|
PublicKey string `yaml:"public-key"`
|
|
ShortID string `yaml:"short-id"`
|
|
}
|
|
|
|
func (r *RealityOptions) Build() *option.OutboundRealityOptions {
|
|
if r == nil {
|
|
return nil
|
|
}
|
|
return &option.OutboundRealityOptions{
|
|
Enabled: true,
|
|
PublicKey: r.PublicKey,
|
|
ShortID: r.ShortID,
|
|
}
|
|
}
|
|
|
|
type ECHOptions struct {
|
|
Enable bool `yaml:"enable,omitempty"`
|
|
Config string `yaml:"config,omitempty"`
|
|
}
|
|
|
|
func (e *ECHOptions) Build() *option.OutboundECHOptions {
|
|
if e == nil {
|
|
return nil
|
|
}
|
|
list, err := base64.StdEncoding.DecodeString(e.Config)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return &option.OutboundECHOptions{
|
|
Enabled: e.Enable,
|
|
Config: trimStringArray(strings.Split(string(list), "\n")),
|
|
}
|
|
}
|
|
|
|
type TLSOptions struct {
|
|
TLS bool `yaml:"tls,omitempty"`
|
|
SNI string `yaml:"sni,omitempty"`
|
|
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty"`
|
|
ALPN []string `yaml:"alpn,omitempty"`
|
|
ClientFingerprint string `yaml:"client-fingerprint,omitempty"`
|
|
CustomCA string `yaml:"ca,omitempty"`
|
|
CustomCAString string `yaml:"ca-str,omitempty"`
|
|
Certificate string `yaml:"certificate,omitempty"`
|
|
PrivateKey string `yaml:"private-key,omitempty"`
|
|
ECHOpts *ECHOptions `yaml:"ech-opts,omitempty"`
|
|
RealityOpts *RealityOptions `yaml:"reality-opts,omitempty"`
|
|
}
|
|
|
|
func (t *TLSOptions) Build() *option.OutboundTLSOptions {
|
|
if t == nil {
|
|
return nil
|
|
}
|
|
options := &option.OutboundTLSOptions{
|
|
Enabled: t.TLS,
|
|
ServerName: t.SNI,
|
|
Insecure: t.SkipCertVerify,
|
|
ALPN: t.ALPN,
|
|
UTLS: clashClientFingerprint(t.ClientFingerprint),
|
|
Certificate: trimStringArray(strings.Split(t.CustomCAString, "\n")),
|
|
CertificatePath: t.CustomCA,
|
|
ECH: t.ECHOpts.Build(),
|
|
Reality: t.RealityOpts.Build(),
|
|
}
|
|
if strings.HasPrefix(t.Certificate, "-----BEGIN ") {
|
|
options.ClientCertificate = trimStringArray(strings.Split(t.Certificate, "\n"))
|
|
} else {
|
|
options.ClientCertificatePath = t.Certificate
|
|
}
|
|
if strings.HasPrefix(t.PrivateKey, "-----BEGIN ") {
|
|
options.ClientKey = trimStringArray(strings.Split(t.PrivateKey, "\n"))
|
|
} else {
|
|
options.ClientKeyPath = t.PrivateKey
|
|
}
|
|
return options
|
|
}
|
|
|
|
type DialerOptions struct {
|
|
TFO bool `yaml:"tfo,omitempty"`
|
|
MPTCP bool `yaml:"mptcp,omitempty"`
|
|
Interface string `yaml:"interface-name,omitempty"`
|
|
RoutingMark int `yaml:"routing-mark,omitempty"`
|
|
DialerProxy string `yaml:"dialer-proxy,omitempty"`
|
|
}
|
|
|
|
func (b *DialerOptions) Build() option.DialerOptions {
|
|
return option.DialerOptions{
|
|
Detour: b.DialerProxy,
|
|
BindInterface: b.Interface,
|
|
TCPFastOpen: b.TFO,
|
|
TCPMultiPath: b.MPTCP,
|
|
RoutingMark: option.FwMark(b.RoutingMark),
|
|
}
|
|
}
|
|
|
|
type ServerOptions struct {
|
|
Server string `yaml:"server"`
|
|
Port int `yaml:"port"`
|
|
}
|
|
|
|
func (s *ServerOptions) Build() option.ServerOptions {
|
|
return option.ServerOptions{
|
|
Server: s.Server,
|
|
ServerPort: uint16(s.Port),
|
|
}
|
|
}
|