mirror of
https://github.com/wyx2685/V2bX.git
synced 2025-02-02 06:48:14 -05:00
update sing-box support
This commit is contained in:
parent
2812b366b3
commit
96493346f9
@ -1,9 +1,10 @@
|
|||||||
package panel
|
package panel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Yuzuki616/V2bX/conf"
|
|
||||||
"log"
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/Yuzuki616/V2bX/conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
var client *Client
|
var client *Client
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package counter
|
package counter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/buf"
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
@ -10,38 +13,93 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ConnCounter struct {
|
type ConnCounter struct {
|
||||||
net.Conn
|
network.ExtendedConn
|
||||||
storage *TrafficStorage
|
storage *TrafficStorage
|
||||||
|
readFunc network.CountFunc
|
||||||
|
writeFunc network.CountFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnCounter(conn net.Conn, s *TrafficStorage) net.Conn {
|
func NewConnCounter(conn net.Conn, s *TrafficStorage) net.Conn {
|
||||||
return &ConnCounter{
|
return &ConnCounter{
|
||||||
Conn: conn,
|
ExtendedConn: bufio.NewExtendedConn(conn),
|
||||||
storage: s,
|
storage: s,
|
||||||
|
readFunc: func(n int64) {
|
||||||
|
s.DownCounter.Add(n)
|
||||||
|
},
|
||||||
|
writeFunc: func(n int64) {
|
||||||
|
s.UpCounter.Add(n)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConnCounter) Read(b []byte) (n int, err error) {
|
func (c *ConnCounter) Read(b []byte) (n int, err error) {
|
||||||
n, err = c.Conn.Read(b)
|
n, err = c.ExtendedConn.Read(b)
|
||||||
c.storage.DownCounter.Store(int64(n))
|
c.storage.DownCounter.Store(int64(n))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ConnCounter) Write(b []byte) (n int, err error) {
|
func (c *ConnCounter) Write(b []byte) (n int, err error) {
|
||||||
n, err = c.Conn.Write(b)
|
n, err = c.ExtendedConn.Write(b)
|
||||||
c.storage.UpCounter.Store(int64(n))
|
c.storage.UpCounter.Store(int64(n))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ConnCounter) ReadBuffer(buffer *buf.Buffer) error {
|
||||||
|
err := c.ExtendedConn.ReadBuffer(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if buffer.Len() > 0 {
|
||||||
|
c.storage.DownCounter.Add(int64(buffer.Len()))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnCounter) WriteBuffer(buffer *buf.Buffer) error {
|
||||||
|
dataLen := int64(buffer.Len())
|
||||||
|
err := c.ExtendedConn.WriteBuffer(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dataLen > 0 {
|
||||||
|
c.storage.UpCounter.Add(dataLen)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnCounter) UnwrapReader() (io.Reader, []network.CountFunc) {
|
||||||
|
return c.ExtendedConn, []network.CountFunc{
|
||||||
|
c.readFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnCounter) UnwrapWriter() (io.Writer, []network.CountFunc) {
|
||||||
|
return c.ExtendedConn, []network.CountFunc{
|
||||||
|
c.writeFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnCounter) Upstream() any {
|
||||||
|
return c.ExtendedConn
|
||||||
|
}
|
||||||
|
|
||||||
type PacketConnCounter struct {
|
type PacketConnCounter struct {
|
||||||
network.PacketConn
|
network.PacketConn
|
||||||
storage *TrafficStorage
|
storage *TrafficStorage
|
||||||
|
readFunc network.CountFunc
|
||||||
|
writeFunc network.CountFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPacketConnCounter(conn network.PacketConn, s *TrafficStorage) network.PacketConn {
|
func NewPacketConnCounter(conn network.PacketConn, s *TrafficStorage) network.PacketConn {
|
||||||
return &PacketConnCounter{
|
return &PacketConnCounter{
|
||||||
PacketConn: conn,
|
PacketConn: conn,
|
||||||
storage: s,
|
storage: s,
|
||||||
|
readFunc: func(n int64) {
|
||||||
|
s.DownCounter.Add(n)
|
||||||
|
},
|
||||||
|
writeFunc: func(n int64) {
|
||||||
|
s.UpCounter.Add(n)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +113,29 @@ func (p *PacketConnCounter) ReadPacket(buff *buf.Buffer) (destination M.Socksadd
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PacketConnCounter) WritePacket(buff *buf.Buffer, destination M.Socksaddr) (err error) {
|
func (p *PacketConnCounter) WritePacket(buff *buf.Buffer, destination M.Socksaddr) (err error) {
|
||||||
|
n := buff.Len()
|
||||||
err = p.PacketConn.WritePacket(buff, destination)
|
err = p.PacketConn.WritePacket(buff, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.storage.UpCounter.Add(int64(buff.Len()))
|
if n > 0 {
|
||||||
|
p.storage.UpCounter.Add(int64(n))
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PacketConnCounter) UnwrapPacketReader() (network.PacketReader, []network.CountFunc) {
|
||||||
|
return p.PacketConn, []network.CountFunc{
|
||||||
|
p.readFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketConnCounter) UnwrapPacketWriter() (network.PacketWriter, []network.CountFunc) {
|
||||||
|
return p.PacketConn, []network.CountFunc{
|
||||||
|
p.writeFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketConnCounter) Upstream() any {
|
||||||
|
return p.PacketConn
|
||||||
|
}
|
||||||
|
@ -52,6 +52,12 @@ func (c *TrafficCounter) GetDownCount(id string) int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *TrafficCounter) Len() int {
|
||||||
|
c.lock.RLock()
|
||||||
|
defer c.lock.RUnlock()
|
||||||
|
return len(c.counters)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *TrafficCounter) Reset(id string) {
|
func (c *TrafficCounter) Reset(id string) {
|
||||||
c.lock.RLock()
|
c.lock.RLock()
|
||||||
cts := c.GetCounter(id)
|
cts := c.GetCounter(id)
|
||||||
|
56
common/rate/conn.go
Normal file
56
common/rate/conn.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package rate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/juju/ratelimit"
|
||||||
|
"github.com/sagernet/sing/common/buf"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
"github.com/sagernet/sing/common/network"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewConnRateLimiter(c net.Conn, l *ratelimit.Bucket) *Conn {
|
||||||
|
return &Conn{
|
||||||
|
Conn: c,
|
||||||
|
limiter: l,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Conn struct {
|
||||||
|
net.Conn
|
||||||
|
limiter *ratelimit.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Read(b []byte) (n int, err error) {
|
||||||
|
c.limiter.Wait(int64(len(b)))
|
||||||
|
return c.Conn.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Conn) Write(b []byte) (n int, err error) {
|
||||||
|
c.limiter.Wait(int64(len(b)))
|
||||||
|
return c.Conn.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketConnCounter struct {
|
||||||
|
network.PacketConn
|
||||||
|
limiter *ratelimit.Bucket
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketConnCounter(conn network.PacketConn, l *ratelimit.Bucket) network.PacketConn {
|
||||||
|
return &PacketConnCounter{
|
||||||
|
PacketConn: conn,
|
||||||
|
limiter: l,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketConnCounter) ReadPacket(buff *buf.Buffer) (destination M.Socksaddr, err error) {
|
||||||
|
pLen := buff.Len()
|
||||||
|
destination, err = p.ReadPacket(buff)
|
||||||
|
p.limiter.Wait(int64(buff.Len() - pLen))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PacketConnCounter) WritePacket(buff *buf.Buffer, destination M.Socksaddr) (err error) {
|
||||||
|
p.limiter.Wait(int64(buff.Len()))
|
||||||
|
return p.PacketConn.WritePacket(buff, destination)
|
||||||
|
}
|
24
conf/cert.go
Normal file
24
conf/cert.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
type CertConfig struct {
|
||||||
|
CertMode string `yaml:"CertMode"` // none, file, http, dns
|
||||||
|
RejectUnknownSni bool `yaml:"RejectUnknownSni"`
|
||||||
|
CertDomain string `yaml:"CertDomain"`
|
||||||
|
CertFile string `yaml:"CertFile"`
|
||||||
|
KeyFile string `yaml:"KeyFile"`
|
||||||
|
Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy....
|
||||||
|
Email string `yaml:"Email"`
|
||||||
|
DNSEnv map[string]string `yaml:"DNSEnv"`
|
||||||
|
RealityConfig *RealityConfig `yaml:"RealityConfig"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RealityConfig struct {
|
||||||
|
Dest interface{} `yaml:"Dest" json:"Dest"`
|
||||||
|
Xver uint64 `yaml:"Xver" json:"Xver"`
|
||||||
|
ServerNames []string `yaml:"ServerNames" json:"ServerNames"`
|
||||||
|
PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"`
|
||||||
|
MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"`
|
||||||
|
MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"`
|
||||||
|
MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
|
||||||
|
ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
|
||||||
|
}
|
19
conf/conf.go
19
conf/conf.go
@ -2,9 +2,10 @@ package conf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Conf struct {
|
type Conf struct {
|
||||||
@ -16,15 +17,8 @@ func New() *Conf {
|
|||||||
return &Conf{
|
return &Conf{
|
||||||
CoreConfig: CoreConfig{
|
CoreConfig: CoreConfig{
|
||||||
Type: "xray",
|
Type: "xray",
|
||||||
XrayConfig: &XrayConfig{
|
XrayConfig: NewXrayConfig(),
|
||||||
LogConfig: NewLogConfig(),
|
SingConfig: NewSingConfig(),
|
||||||
AssetPath: "/etc/V2bX/",
|
|
||||||
DnsConfigPath: "",
|
|
||||||
InboundConfigPath: "",
|
|
||||||
OutboundConfigPath: "",
|
|
||||||
RouteConfigPath: "",
|
|
||||||
ConnectionConfig: NewConnectionConfig(),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
NodesConfig: []*NodeConfig{},
|
NodesConfig: []*NodeConfig{},
|
||||||
}
|
}
|
||||||
@ -44,10 +38,5 @@ func (p *Conf) LoadFromPath(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("decode config error: %s", err)
|
return fmt.Errorf("decode config error: %s", err)
|
||||||
}
|
}
|
||||||
old := &OldConfig{}
|
|
||||||
err = yaml.Unmarshal(content, old)
|
|
||||||
if err == nil {
|
|
||||||
migrateOldConfig(p, old)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package conf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -11,9 +12,6 @@ func TestConf_LoadFromPath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestConf_Watch(t *testing.T) {
|
func TestConf_Watch(t *testing.T) {
|
||||||
c := New()
|
//c := New()
|
||||||
log.Println(c.Watch("../example/config.yml.example", func() {
|
log.Println(strings.Split("aaaa", " "))
|
||||||
log.Println(1)
|
|
||||||
}))
|
|
||||||
select {}
|
|
||||||
}
|
}
|
||||||
|
29
conf/core.go
29
conf/core.go
@ -3,32 +3,5 @@ package conf
|
|||||||
type CoreConfig struct {
|
type CoreConfig struct {
|
||||||
Type string `yaml:"Type"`
|
Type string `yaml:"Type"`
|
||||||
XrayConfig *XrayConfig `yaml:"XrayConfig"`
|
XrayConfig *XrayConfig `yaml:"XrayConfig"`
|
||||||
}
|
SingConfig *SingConfig `yaml:"SingConfig"`
|
||||||
|
|
||||||
type XrayConfig struct {
|
|
||||||
LogConfig *LogConfig `yaml:"Log"`
|
|
||||||
AssetPath string `yaml:"AssetPath"`
|
|
||||||
DnsConfigPath string `yaml:"DnsConfigPath"`
|
|
||||||
RouteConfigPath string `yaml:"RouteConfigPath"`
|
|
||||||
ConnectionConfig *ConnectionConfig `yaml:"ConnectionConfig"`
|
|
||||||
InboundConfigPath string `yaml:"InboundConfigPath"`
|
|
||||||
OutboundConfigPath string `yaml:"OutboundConfigPath"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectionConfig struct {
|
|
||||||
Handshake uint32 `yaml:"handshake"`
|
|
||||||
ConnIdle uint32 `yaml:"connIdle"`
|
|
||||||
UplinkOnly uint32 `yaml:"uplinkOnly"`
|
|
||||||
DownlinkOnly uint32 `yaml:"downlinkOnly"`
|
|
||||||
BufferSize int32 `yaml:"bufferSize"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConnectionConfig() *ConnectionConfig {
|
|
||||||
return &ConnectionConfig{
|
|
||||||
Handshake: 4,
|
|
||||||
ConnIdle: 30,
|
|
||||||
UplinkOnly: 2,
|
|
||||||
DownlinkOnly: 4,
|
|
||||||
BufferSize: 64,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
40
conf/limit.go
Normal file
40
conf/limit.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
type LimitConfig struct {
|
||||||
|
EnableRealtime bool `yaml:"EnableRealtime"`
|
||||||
|
SpeedLimit int `yaml:"SpeedLimit"`
|
||||||
|
IPLimit int `yaml:"DeviceLimit"`
|
||||||
|
ConnLimit int `yaml:"ConnLimit"`
|
||||||
|
EnableIpRecorder bool `yaml:"EnableIpRecorder"`
|
||||||
|
IpRecorderConfig *IpReportConfig `yaml:"IpRecorderConfig"`
|
||||||
|
EnableDynamicSpeedLimit bool `yaml:"EnableDynamicSpeedLimit"`
|
||||||
|
DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `yaml:"DynamicSpeedLimitConfig"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecorderConfig struct {
|
||||||
|
Url string `yaml:"Url"`
|
||||||
|
Token string `yaml:"Token"`
|
||||||
|
Timeout int `yaml:"Timeout"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisConfig struct {
|
||||||
|
Address string `yaml:"Address"`
|
||||||
|
Password string `yaml:"Password"`
|
||||||
|
Db int `yaml:"Db"`
|
||||||
|
Expiry int `json:"Expiry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IpReportConfig struct {
|
||||||
|
Periodic int `yaml:"Periodic"`
|
||||||
|
Type string `yaml:"Type"`
|
||||||
|
RecorderConfig *RecorderConfig `yaml:"RecorderConfig"`
|
||||||
|
RedisConfig *RedisConfig `yaml:"RedisConfig"`
|
||||||
|
EnableIpSync bool `yaml:"EnableIpSync"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DynamicSpeedLimitConfig struct {
|
||||||
|
Periodic int `yaml:"Periodic"`
|
||||||
|
Traffic int64 `yaml:"Traffic"`
|
||||||
|
SpeedLimit int `yaml:"SpeedLimit"`
|
||||||
|
ExpireTime int `yaml:"ExpireTime"`
|
||||||
|
}
|
15
conf/log.go
15
conf/log.go
@ -1,15 +0,0 @@
|
|||||||
package conf
|
|
||||||
|
|
||||||
type LogConfig struct {
|
|
||||||
Level string `yaml:"Level"`
|
|
||||||
AccessPath string `yaml:"AccessPath"`
|
|
||||||
ErrorPath string `yaml:"ErrorPath"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLogConfig() *LogConfig {
|
|
||||||
return &LogConfig{
|
|
||||||
Level: "warning",
|
|
||||||
AccessPath: "",
|
|
||||||
ErrorPath: "",
|
|
||||||
}
|
|
||||||
}
|
|
99
conf/node.go
99
conf/node.go
@ -2,7 +2,7 @@ package conf
|
|||||||
|
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
ApiConfig *ApiConfig `yaml:"ApiConfig"`
|
ApiConfig *ApiConfig `yaml:"ApiConfig"`
|
||||||
ControllerConfig *ControllerConfig `yaml:"ControllerConfig"`
|
Options *Options `yaml:"Options"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiConfig struct {
|
type ApiConfig struct {
|
||||||
@ -13,100 +13,3 @@ type ApiConfig struct {
|
|||||||
Timeout int `yaml:"Timeout"`
|
Timeout int `yaml:"Timeout"`
|
||||||
RuleListPath string `yaml:"RuleListPath"`
|
RuleListPath string `yaml:"RuleListPath"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ControllerConfig struct {
|
|
||||||
ListenIP string `yaml:"ListenIP"`
|
|
||||||
SendIP string `yaml:"SendIP"`
|
|
||||||
XrayOptions XrayOptions `yaml:"XrayOptions"`
|
|
||||||
HyOptions HyOptions `yaml:"HyOptions"`
|
|
||||||
LimitConfig LimitConfig `yaml:"LimitConfig"`
|
|
||||||
CertConfig *CertConfig `yaml:"CertConfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RealityConfig struct {
|
|
||||||
Dest interface{} `yaml:"Dest" json:"Dest"`
|
|
||||||
Xver uint64 `yaml:"Xver" json:"Xver"`
|
|
||||||
ServerNames []string `yaml:"ServerNames" json:"ServerNames"`
|
|
||||||
PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"`
|
|
||||||
MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"`
|
|
||||||
MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"`
|
|
||||||
MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
|
|
||||||
ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type XrayOptions struct {
|
|
||||||
EnableProxyProtocol bool `yaml:"EnableProxyProtocol"`
|
|
||||||
EnableDNS bool `yaml:"EnableDNS"`
|
|
||||||
DNSType string `yaml:"DNSType"`
|
|
||||||
EnableUot bool `yaml:"EnableUot"`
|
|
||||||
EnableTFO bool `yaml:"EnableTFO"`
|
|
||||||
DisableIVCheck bool `yaml:"DisableIVCheck"`
|
|
||||||
DisableSniffing bool `yaml:"DisableSniffing"`
|
|
||||||
EnableFallback bool `yaml:"EnableFallback"`
|
|
||||||
FallBackConfigs []FallBackConfig `yaml:"FallBackConfigs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HyOptions struct {
|
|
||||||
Resolver string `yaml:"Resolver"`
|
|
||||||
ResolvePreference string `yaml:"ResolvePreference"`
|
|
||||||
SendDevice string `yaml:"SendDevice"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type LimitConfig struct {
|
|
||||||
EnableRealtime bool `yaml:"EnableRealtime"`
|
|
||||||
SpeedLimit int `yaml:"SpeedLimit"`
|
|
||||||
IPLimit int `yaml:"DeviceLimit"`
|
|
||||||
ConnLimit int `yaml:"ConnLimit"`
|
|
||||||
EnableIpRecorder bool `yaml:"EnableIpRecorder"`
|
|
||||||
IpRecorderConfig *IpReportConfig `yaml:"IpRecorderConfig"`
|
|
||||||
EnableDynamicSpeedLimit bool `yaml:"EnableDynamicSpeedLimit"`
|
|
||||||
DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `yaml:"DynamicSpeedLimitConfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FallBackConfig struct {
|
|
||||||
SNI string `yaml:"SNI"`
|
|
||||||
Alpn string `yaml:"Alpn"`
|
|
||||||
Path string `yaml:"Path"`
|
|
||||||
Dest string `yaml:"Dest"`
|
|
||||||
ProxyProtocolVer uint64 `yaml:"ProxyProtocolVer"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RecorderConfig struct {
|
|
||||||
Url string `yaml:"Url"`
|
|
||||||
Token string `yaml:"Token"`
|
|
||||||
Timeout int `yaml:"Timeout"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RedisConfig struct {
|
|
||||||
Address string `yaml:"Address"`
|
|
||||||
Password string `yaml:"Password"`
|
|
||||||
Db int `yaml:"Db"`
|
|
||||||
Expiry int `json:"Expiry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type IpReportConfig struct {
|
|
||||||
Periodic int `yaml:"Periodic"`
|
|
||||||
Type string `yaml:"Type"`
|
|
||||||
RecorderConfig *RecorderConfig `yaml:"RecorderConfig"`
|
|
||||||
RedisConfig *RedisConfig `yaml:"RedisConfig"`
|
|
||||||
EnableIpSync bool `yaml:"EnableIpSync"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DynamicSpeedLimitConfig struct {
|
|
||||||
Periodic int `yaml:"Periodic"`
|
|
||||||
Traffic int64 `yaml:"Traffic"`
|
|
||||||
SpeedLimit int `yaml:"SpeedLimit"`
|
|
||||||
ExpireTime int `yaml:"ExpireTime"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CertConfig struct {
|
|
||||||
CertMode string `yaml:"CertMode"` // none, file, http, dns
|
|
||||||
RejectUnknownSni bool `yaml:"RejectUnknownSni"`
|
|
||||||
CertDomain string `yaml:"CertDomain"`
|
|
||||||
CertFile string `yaml:"CertFile"`
|
|
||||||
KeyFile string `yaml:"KeyFile"`
|
|
||||||
Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy....
|
|
||||||
Email string `yaml:"Email"`
|
|
||||||
DNSEnv map[string]string `yaml:"DNSEnv"`
|
|
||||||
RealityConfig *RealityConfig `yaml:"RealityConfig"`
|
|
||||||
}
|
|
||||||
|
81
conf/old.go
81
conf/old.go
@ -1,81 +0,0 @@
|
|||||||
package conf
|
|
||||||
|
|
||||||
import "log"
|
|
||||||
|
|
||||||
type OldConfig struct {
|
|
||||||
NodesConfig []*struct {
|
|
||||||
ApiConfig *OldApiConfig `yaml:"ApiConfig"`
|
|
||||||
ControllerConfig *OldControllerConfig `yaml:"ControllerConfig"`
|
|
||||||
} `yaml:"Nodes"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OldControllerConfig struct {
|
|
||||||
ListenIP string `yaml:"ListenIP"`
|
|
||||||
SendIP string `yaml:"SendIP"`
|
|
||||||
EnableDNS bool `yaml:"EnableDNS"`
|
|
||||||
DNSType string `yaml:"DNSType"`
|
|
||||||
DisableUploadTraffic bool `yaml:"DisableUploadTraffic"`
|
|
||||||
DisableGetRule bool `yaml:"DisableGetRule"`
|
|
||||||
EnableProxyProtocol bool `yaml:"EnableProxyProtocol"`
|
|
||||||
EnableFallback bool `yaml:"EnableFallback"`
|
|
||||||
DisableIVCheck bool `yaml:"DisableIVCheck"`
|
|
||||||
DisableSniffing bool `yaml:"DisableSniffing"`
|
|
||||||
FallBackConfigs []*FallBackConfig `yaml:"FallBackConfigs"`
|
|
||||||
EnableIpRecorder bool `yaml:"EnableIpRecorder"`
|
|
||||||
IpRecorderConfig *IpReportConfig `yaml:"IpRecorderConfig"`
|
|
||||||
EnableDynamicSpeedLimit bool `yaml:"EnableDynamicSpeedLimit"`
|
|
||||||
DynamicSpeedLimitConfig *DynamicSpeedLimitConfig `yaml:"DynamicSpeedLimitConfig"`
|
|
||||||
CertConfig *CertConfig `yaml:"CertConfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type OldApiConfig struct {
|
|
||||||
APIHost string `yaml:"ApiHost"`
|
|
||||||
NodeID int `yaml:"NodeID"`
|
|
||||||
Key string `yaml:"ApiKey"`
|
|
||||||
NodeType string `yaml:"NodeType"`
|
|
||||||
EnableVless bool `yaml:"EnableVless"`
|
|
||||||
Timeout int `yaml:"Timeout"`
|
|
||||||
SpeedLimit int `yaml:"SpeedLimit"`
|
|
||||||
DeviceLimit int `yaml:"DeviceLimit"`
|
|
||||||
RuleListPath string `yaml:"RuleListPath"`
|
|
||||||
DisableCustomConfig bool `yaml:"DisableCustomConfig"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func migrateOldConfig(c *Conf, old *OldConfig) {
|
|
||||||
changed := false
|
|
||||||
for i, n := range c.NodesConfig {
|
|
||||||
if i >= len(old.NodesConfig) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// limit config
|
|
||||||
if old.NodesConfig[i].ApiConfig.SpeedLimit != 0 {
|
|
||||||
n.ControllerConfig.LimitConfig.SpeedLimit = old.NodesConfig[i].ApiConfig.SpeedLimit
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if old.NodesConfig[i].ApiConfig.DeviceLimit != 0 {
|
|
||||||
n.ControllerConfig.LimitConfig.IPLimit = old.NodesConfig[i].ApiConfig.DeviceLimit
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if old.NodesConfig[i].ControllerConfig.EnableDynamicSpeedLimit {
|
|
||||||
n.ControllerConfig.LimitConfig.EnableDynamicSpeedLimit = true
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if old.NodesConfig[i].ControllerConfig.DynamicSpeedLimitConfig != nil {
|
|
||||||
n.ControllerConfig.LimitConfig.DynamicSpeedLimitConfig =
|
|
||||||
old.NodesConfig[i].ControllerConfig.DynamicSpeedLimitConfig
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if old.NodesConfig[i].ControllerConfig.EnableIpRecorder {
|
|
||||||
n.ControllerConfig.LimitConfig.EnableIpRecorder = true
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
if old.NodesConfig[i].ControllerConfig.IpRecorderConfig != nil {
|
|
||||||
n.ControllerConfig.LimitConfig.IpRecorderConfig =
|
|
||||||
old.NodesConfig[i].ControllerConfig.IpRecorderConfig
|
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if changed {
|
|
||||||
log.Println("Warning: This config file is old.")
|
|
||||||
}
|
|
||||||
}
|
|
36
conf/option.go
Normal file
36
conf/option.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
ListenIP string `yaml:"ListenIP"`
|
||||||
|
SendIP string `yaml:"SendIP"`
|
||||||
|
LimitConfig LimitConfig `yaml:"LimitConfig"`
|
||||||
|
CertConfig *CertConfig `yaml:"CertConfig"`
|
||||||
|
XrayOptions XrayOptions `yaml:"-"`
|
||||||
|
HyOptions HyOptions `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type XrayOptions struct {
|
||||||
|
EnableProxyProtocol bool `yaml:"EnableProxyProtocol"`
|
||||||
|
EnableDNS bool `yaml:"EnableDNS"`
|
||||||
|
DNSType string `yaml:"DNSType"`
|
||||||
|
EnableUot bool `yaml:"EnableUot"`
|
||||||
|
EnableTFO bool `yaml:"EnableTFO"`
|
||||||
|
DisableIVCheck bool `yaml:"DisableIVCheck"`
|
||||||
|
DisableSniffing bool `yaml:"DisableSniffing"`
|
||||||
|
EnableFallback bool `yaml:"EnableFallback"`
|
||||||
|
FallBackConfigs []FallBackConfig `yaml:"FallBackConfigs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FallBackConfig struct {
|
||||||
|
SNI string `yaml:"SNI"`
|
||||||
|
Alpn string `yaml:"Alpn"`
|
||||||
|
Path string `yaml:"Path"`
|
||||||
|
Dest string `yaml:"Dest"`
|
||||||
|
ProxyProtocolVer uint64 `yaml:"ProxyProtocolVer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HyOptions struct {
|
||||||
|
Resolver string `yaml:"Resolver"`
|
||||||
|
ResolvePreference string `yaml:"ResolvePreference"`
|
||||||
|
SendDevice string `yaml:"SendDevice"`
|
||||||
|
}
|
22
conf/sing.go
Normal file
22
conf/sing.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
type SingConfig struct {
|
||||||
|
LogConfig SingLogConfig `yaml:"LogConfig"`
|
||||||
|
OriginalPath string `yaml:"OriginalPath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SingLogConfig struct {
|
||||||
|
Disabled bool `yaml:"Disable"`
|
||||||
|
Level string `yaml:"Level"`
|
||||||
|
Output string `yaml:"Output"`
|
||||||
|
Timestamp bool `yaml:"Timestamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSingConfig() *SingConfig {
|
||||||
|
return &SingConfig{
|
||||||
|
LogConfig: SingLogConfig{
|
||||||
|
Level: "error",
|
||||||
|
Timestamp: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
47
conf/xray.go
Normal file
47
conf/xray.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
type XrayConfig struct {
|
||||||
|
LogConfig *XrayLogConfig `yaml:"Log"`
|
||||||
|
AssetPath string `yaml:"AssetPath"`
|
||||||
|
DnsConfigPath string `yaml:"DnsConfigPath"`
|
||||||
|
RouteConfigPath string `yaml:"RouteConfigPath"`
|
||||||
|
ConnectionConfig *XrayConnectionConfig `yaml:"XrayConnectionConfig"`
|
||||||
|
InboundConfigPath string `yaml:"InboundConfigPath"`
|
||||||
|
OutboundConfigPath string `yaml:"OutboundConfigPath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type XrayLogConfig struct {
|
||||||
|
Level string `yaml:"Level"`
|
||||||
|
AccessPath string `yaml:"AccessPath"`
|
||||||
|
ErrorPath string `yaml:"ErrorPath"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type XrayConnectionConfig struct {
|
||||||
|
Handshake uint32 `yaml:"handshake"`
|
||||||
|
ConnIdle uint32 `yaml:"connIdle"`
|
||||||
|
UplinkOnly uint32 `yaml:"uplinkOnly"`
|
||||||
|
DownlinkOnly uint32 `yaml:"downlinkOnly"`
|
||||||
|
BufferSize int32 `yaml:"bufferSize"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewXrayConfig() *XrayConfig {
|
||||||
|
return &XrayConfig{
|
||||||
|
LogConfig: &XrayLogConfig{
|
||||||
|
Level: "warning",
|
||||||
|
AccessPath: "",
|
||||||
|
ErrorPath: "",
|
||||||
|
},
|
||||||
|
AssetPath: "/etc/V2bX/",
|
||||||
|
DnsConfigPath: "",
|
||||||
|
InboundConfigPath: "",
|
||||||
|
OutboundConfigPath: "",
|
||||||
|
RouteConfigPath: "",
|
||||||
|
ConnectionConfig: &XrayConnectionConfig{
|
||||||
|
Handshake: 4,
|
||||||
|
ConnIdle: 30,
|
||||||
|
UplinkOnly: 2,
|
||||||
|
DownlinkOnly: 4,
|
||||||
|
BufferSize: 64,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/Yuzuki616/V2bX/limiter"
|
"github.com/Yuzuki616/V2bX/limiter"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Hy) AddNode(tag string, info *panel.NodeInfo, c *conf.ControllerConfig) error {
|
func (h *Hy) AddNode(tag string, info *panel.NodeInfo, c *conf.Options) error {
|
||||||
if info.Type != "hysteria" {
|
if info.Type != "hysteria" {
|
||||||
return errors.New("the core not support " + info.Type)
|
return errors.New("the core not support " + info.Type)
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func NewServer(tag string, l *limiter.Limiter) *Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) runServer(node *panel.NodeInfo, c *conf.ControllerConfig) error {
|
func (s *Server) runServer(node *panel.NodeInfo, c *conf.Options) error {
|
||||||
/*if c.HyOptions == nil {
|
/*if c.HyOptions == nil {
|
||||||
return errors.New("hy options is not vail")
|
return errors.New("hy options is not vail")
|
||||||
}*/
|
}*/
|
||||||
|
@ -22,7 +22,7 @@ func TestServer(t *testing.T) {
|
|||||||
UpMbps: 100,
|
UpMbps: 100,
|
||||||
DownMbps: 100,
|
DownMbps: 100,
|
||||||
HyObfs: "atresssdaaaadd",
|
HyObfs: "atresssdaaaadd",
|
||||||
}, &conf.ControllerConfig{
|
}, &conf.Options{
|
||||||
ListenIP: "127.0.0.1",
|
ListenIP: "127.0.0.1",
|
||||||
HyOptions: conf.HyOptions{},
|
HyOptions: conf.HyOptions{},
|
||||||
CertConfig: &conf.CertConfig{
|
CertConfig: &conf.CertConfig{
|
||||||
@ -36,7 +36,7 @@ func TestServer(t *testing.T) {
|
|||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
auth := base64.StdEncoding.EncodeToString([]byte("test1111"))
|
auth := base64.StdEncoding.EncodeToString([]byte("test1111"))
|
||||||
log.Println(auth)
|
log.Println(auth)
|
||||||
log.Println(s.counter.getCounters(auth).UpCounter.Load())
|
log.Println(s.counter.GetUpCount(auth))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
select {}
|
select {}
|
||||||
|
@ -7,14 +7,14 @@ import (
|
|||||||
|
|
||||||
type AddUsersParams struct {
|
type AddUsersParams struct {
|
||||||
Tag string
|
Tag string
|
||||||
Config *conf.ControllerConfig
|
Config *conf.Options
|
||||||
UserInfo []panel.UserInfo
|
UserInfo []panel.UserInfo
|
||||||
NodeInfo *panel.NodeInfo
|
NodeInfo *panel.NodeInfo
|
||||||
}
|
}
|
||||||
type Core interface {
|
type Core interface {
|
||||||
Start() error
|
Start() error
|
||||||
Close() error
|
Close() error
|
||||||
AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error
|
AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error
|
||||||
DelNode(tag string) error
|
DelNode(tag string) error
|
||||||
AddUsers(p *AddUsersParams) (added int, err error)
|
AddUsers(p *AddUsersParams) (added int, err error)
|
||||||
GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64)
|
GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64)
|
||||||
|
@ -39,7 +39,7 @@ func isSupported(protocol string, protocols []string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Selector) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error {
|
func (s *Selector) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||||
for i := range s.cores {
|
for i := range s.cores {
|
||||||
if !isSupported(info.Type, s.cores[i].Protocols()) {
|
if !isSupported(info.Type, s.cores[i].Protocols()) {
|
||||||
continue
|
continue
|
||||||
|
@ -2,6 +2,12 @@ package sing
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Yuzuki616/V2bX/common/rate"
|
||||||
|
|
||||||
|
"github.com/Yuzuki616/V2bX/limiter"
|
||||||
|
|
||||||
"github.com/Yuzuki616/V2bX/common/counter"
|
"github.com/Yuzuki616/V2bX/common/counter"
|
||||||
"github.com/inazumav/sing-box/adapter"
|
"github.com/inazumav/sing-box/adapter"
|
||||||
@ -17,7 +23,7 @@ func NewHookServer(logger log.Logger) *HookServer {
|
|||||||
return &HookServer{
|
return &HookServer{
|
||||||
hooker: &Hooker{
|
hooker: &Hooker{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
counter: make(map[string]*counter.TrafficCounter),
|
counter: sync.Map{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,19 +46,37 @@ func (h *HookServer) Hooker() *Hooker {
|
|||||||
|
|
||||||
type Hooker struct {
|
type Hooker struct {
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
counter map[string]*counter.TrafficCounter
|
counter sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hooker) RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn {
|
func (h *Hooker) RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn {
|
||||||
if c, ok := h.counter[inbound]; ok {
|
l, err := limiter.GetLimiter(inbound)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("get limiter for ", inbound, " error: ", err)
|
||||||
|
}
|
||||||
|
ip, _, _ := strings.Cut(conn.RemoteAddr().String(), ":")
|
||||||
|
if b, r := l.CheckLimit(user, ip, true); r {
|
||||||
|
conn.Close()
|
||||||
|
h.logger.Error("[", inbound, "] ", "Limited ", user, " by ip or conn")
|
||||||
|
return conn
|
||||||
|
} else if b != nil {
|
||||||
|
conn = rate.NewConnRateLimiter(conn, b)
|
||||||
|
}
|
||||||
|
if c, ok := h.counter.Load(inbound); ok {
|
||||||
|
return counter.NewConnCounter(conn, c.(*counter.TrafficCounter).GetCounter(user))
|
||||||
|
} else {
|
||||||
|
c := counter.NewTrafficCounter()
|
||||||
|
h.counter.Store(inbound, c)
|
||||||
return counter.NewConnCounter(conn, c.GetCounter(user))
|
return counter.NewConnCounter(conn, c.GetCounter(user))
|
||||||
}
|
}
|
||||||
return conn
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Hooker) RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn {
|
func (h *Hooker) RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn {
|
||||||
if c, ok := h.counter[inbound]; ok {
|
if c, ok := h.counter.Load(inbound); ok {
|
||||||
|
return counter.NewPacketConnCounter(conn, c.(*counter.TrafficCounter).GetCounter(user))
|
||||||
|
} else {
|
||||||
|
c := counter.NewTrafficCounter()
|
||||||
|
h.counter.Store(inbound, c)
|
||||||
return counter.NewPacketConnCounter(conn, c.GetCounter(user))
|
return counter.NewPacketConnCounter(conn, c.GetCounter(user))
|
||||||
}
|
}
|
||||||
return conn
|
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,16 @@ import (
|
|||||||
|
|
||||||
type WsNetworkConfig struct {
|
type WsNetworkConfig struct {
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
Headers map[string]string `json:"headers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.ControllerConfig) (option.Inbound, error) {
|
func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (option.Inbound, error) {
|
||||||
addr, _ := netip.ParseAddr("0.0.0.0")
|
addr, err := netip.ParseAddr(c.ListenIP)
|
||||||
|
if err != nil {
|
||||||
|
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),
|
||||||
}
|
}
|
||||||
@ -47,6 +52,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.ControllerConfi
|
|||||||
}
|
}
|
||||||
switch info.Network {
|
switch info.Network {
|
||||||
case "tcp":
|
case "tcp":
|
||||||
|
t.Type = ""
|
||||||
case "ws":
|
case "ws":
|
||||||
network := WsNetworkConfig{}
|
network := WsNetworkConfig{}
|
||||||
err := json.Unmarshal(info.NetworkSettings, &network)
|
err := json.Unmarshal(info.NetworkSettings, &network)
|
||||||
@ -59,14 +65,22 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.ControllerConfi
|
|||||||
return option.Inbound{}, fmt.Errorf("parse path error: %s", err)
|
return option.Inbound{}, fmt.Errorf("parse path error: %s", err)
|
||||||
}
|
}
|
||||||
ed, _ := strconv.Atoi(u.Query().Get("ed"))
|
ed, _ := strconv.Atoi(u.Query().Get("ed"))
|
||||||
|
h := make(map[string]option.Listable[string], len(network.Headers))
|
||||||
|
for k, v := range network.Headers {
|
||||||
|
h[k] = option.Listable[string]{
|
||||||
|
v,
|
||||||
|
}
|
||||||
|
}
|
||||||
t.WebsocketOptions = option.V2RayWebsocketOptions{
|
t.WebsocketOptions = option.V2RayWebsocketOptions{
|
||||||
Path: u.Path,
|
Path: u.Path,
|
||||||
EarlyDataHeaderName: "Sec-WebSocket-Protocol",
|
EarlyDataHeaderName: "Sec-WebSocket-Protocol",
|
||||||
MaxEarlyData: uint32(ed),
|
MaxEarlyData: uint32(ed),
|
||||||
|
Headers: h,
|
||||||
}
|
}
|
||||||
case "grpc":
|
case "grpc":
|
||||||
t.GRPCOptions = option.V2RayGRPCOptions{
|
err := json.Unmarshal(info.NetworkSettings, &t.GRPCOptions)
|
||||||
ServiceName: info.ServerName,
|
if err != nil {
|
||||||
|
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.VMessOptions = option.VMessInboundOptions{
|
in.VMessOptions = option.VMessInboundOptions{
|
||||||
@ -96,7 +110,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.ControllerConfi
|
|||||||
return in, nil
|
return in, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Box) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error {
|
func (b *Box) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||||
c, err := getInboundOptions(tag, info, config)
|
c, err := getInboundOptions(tag, info, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -39,8 +39,14 @@ func init() {
|
|||||||
vCore.RegisterCore("sing", New)
|
vCore.RegisterCore("sing", New)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(_ *conf.CoreConfig) (vCore.Core, error) {
|
func New(c *conf.CoreConfig) (vCore.Core, error) {
|
||||||
options := option.Options{}
|
options := option.Options{}
|
||||||
|
options.Log = &option.LogOptions{
|
||||||
|
Disabled: c.SingConfig.LogConfig.Disabled,
|
||||||
|
Level: c.SingConfig.LogConfig.Level,
|
||||||
|
Timestamp: c.SingConfig.LogConfig.Timestamp,
|
||||||
|
Output: c.SingConfig.LogConfig.Output,
|
||||||
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
createdAt := time.Now()
|
createdAt := time.Now()
|
||||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
"github.com/Yuzuki616/V2bX/api/panel"
|
"github.com/Yuzuki616/V2bX/api/panel"
|
||||||
|
"github.com/Yuzuki616/V2bX/common/counter"
|
||||||
"github.com/Yuzuki616/V2bX/core"
|
"github.com/Yuzuki616/V2bX/core"
|
||||||
"github.com/inazumav/sing-box/inbound"
|
"github.com/inazumav/sing-box/inbound"
|
||||||
"github.com/inazumav/sing-box/option"
|
"github.com/inazumav/sing-box/option"
|
||||||
@ -36,7 +37,8 @@ func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
||||||
if c, ok := b.hookServer.Hooker().counter[tag]; ok {
|
if v, ok := b.hookServer.Hooker().counter.Load(tag); ok {
|
||||||
|
c := v.(*counter.TrafficCounter)
|
||||||
up = c.GetUpCount(uuid)
|
up = c.GetUpCount(uuid)
|
||||||
down = c.GetDownCount(uuid)
|
down = c.GetDownCount(uuid)
|
||||||
if reset {
|
if reset {
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// BuildInbound build Inbound config for different protocol
|
// BuildInbound build Inbound config for different protocol
|
||||||
func buildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
|
func buildInbound(config *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
|
||||||
in := &coreConf.InboundDetourConfig{}
|
in := &coreConf.InboundDetourConfig{}
|
||||||
// Set network protocol
|
// Set network protocol
|
||||||
t := coreConf.TransportProtocol(nodeInfo.Network)
|
t := coreConf.TransportProtocol(nodeInfo.Network)
|
||||||
@ -150,7 +150,7 @@ func buildInbound(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, tag s
|
|||||||
return in.Build()
|
return in.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildV2ray(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
||||||
if nodeInfo.ExtraConfig.EnableVless == "true" {
|
if nodeInfo.ExtraConfig.EnableVless == "true" {
|
||||||
//Set vless
|
//Set vless
|
||||||
inbound.Protocol = "vless"
|
inbound.Protocol = "vless"
|
||||||
@ -213,7 +213,7 @@ func buildV2ray(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, inbound
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildTrojan(config *conf.ControllerConfig, inbound *coreConf.InboundDetourConfig) error {
|
func buildTrojan(config *conf.Options, inbound *coreConf.InboundDetourConfig) error {
|
||||||
inbound.Protocol = "trojan"
|
inbound.Protocol = "trojan"
|
||||||
if config.XrayOptions.EnableFallback {
|
if config.XrayOptions.EnableFallback {
|
||||||
// Set fallback
|
// Set fallback
|
||||||
@ -237,7 +237,7 @@ func buildTrojan(config *conf.ControllerConfig, inbound *coreConf.InboundDetourC
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildShadowsocks(config *conf.ControllerConfig, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
|
||||||
inbound.Protocol = "shadowsocks"
|
inbound.Protocol = "shadowsocks"
|
||||||
settings := &coreConf.ShadowsocksServerConfig{
|
settings := &coreConf.ShadowsocksServerConfig{
|
||||||
Cipher: nodeInfo.Cipher,
|
Cipher: nodeInfo.Cipher,
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Core) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error {
|
func (c *Core) AddNode(tag string, info *panel.NodeInfo, config *conf.Options) error {
|
||||||
inboundConfig, err := buildInbound(config, info, tag)
|
inboundConfig, err := buildInbound(config, info, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("build inbound error: %s", err)
|
return fmt.Errorf("build inbound error: %s", err)
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// BuildOutbound build freedom outbund config for addoutbound
|
// BuildOutbound build freedom outbund config for addoutbound
|
||||||
func buildOutbound(config *conf2.ControllerConfig, tag string) (*core.OutboundHandlerConfig, error) {
|
func buildOutbound(config *conf2.Options, tag string) (*core.OutboundHandlerConfig, error) {
|
||||||
outboundDetourConfig := &conf.OutboundDetourConfig{}
|
outboundDetourConfig := &conf.OutboundDetourConfig{}
|
||||||
outboundDetourConfig.Protocol = "freedom"
|
outboundDetourConfig.Protocol = "freedom"
|
||||||
outboundDetourConfig.Tag = tag
|
outboundDetourConfig.Tag = tag
|
||||||
|
@ -39,7 +39,7 @@ func New(c *conf.CoreConfig) (vCore.Core, error) {
|
|||||||
return &Core{Server: getCore(c.XrayConfig)}, nil
|
return &Core{Server: getCore(c.XrayConfig)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseConnectionConfig(c *conf.ConnectionConfig) (policy *coreConf.Policy) {
|
func parseConnectionConfig(c *conf.XrayConnectionConfig) (policy *coreConf.Policy) {
|
||||||
policy = &coreConf.Policy{
|
policy = &coreConf.Policy{
|
||||||
StatsUserUplink: true,
|
StatsUserUplink: true,
|
||||||
StatsUserDownlink: true,
|
StatsUserDownlink: true,
|
||||||
|
2
go.mod
2
go.mod
@ -15,7 +15,7 @@ require (
|
|||||||
github.com/go-resty/resty/v2 v2.7.0
|
github.com/go-resty/resty/v2 v2.7.0
|
||||||
github.com/goccy/go-json v0.10.2
|
github.com/goccy/go-json v0.10.2
|
||||||
github.com/hashicorp/go-multierror v1.1.1
|
github.com/hashicorp/go-multierror v1.1.1
|
||||||
github.com/inazumav/sing-box v0.0.0-20230728005925-1df6eb0f5bf7
|
github.com/inazumav/sing-box v0.0.0-20230728123002-eb2ba58e499a
|
||||||
github.com/juju/ratelimit v1.0.2
|
github.com/juju/ratelimit v1.0.2
|
||||||
github.com/oschwald/geoip2-golang v1.9.0
|
github.com/oschwald/geoip2-golang v1.9.0
|
||||||
github.com/sagernet/sing v0.2.9
|
github.com/sagernet/sing v0.2.9
|
||||||
|
6
go.sum
6
go.sum
@ -379,10 +379,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
|||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
|
||||||
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
|
||||||
github.com/inazumav/sing-box v0.0.0-20230728005628-9c73947a55ad h1:Ho7F+U1n41dX6c+3TjojaCj1NjBlaaCa1Vjtll9BVW4=
|
github.com/inazumav/sing-box v0.0.0-20230728123002-eb2ba58e499a h1:/FGmhOCu6LYt8zd6DpMEvuHlPnUPMr0zziyJkuU1wVI=
|
||||||
github.com/inazumav/sing-box v0.0.0-20230728005628-9c73947a55ad/go.mod h1:W91us/coe3lvl5jCtw2n6acyagpRbOO16h1IV3/0nrc=
|
github.com/inazumav/sing-box v0.0.0-20230728123002-eb2ba58e499a/go.mod h1:W91us/coe3lvl5jCtw2n6acyagpRbOO16h1IV3/0nrc=
|
||||||
github.com/inazumav/sing-box v0.0.0-20230728005925-1df6eb0f5bf7 h1:fHFY6wVkFNFmL+LXVnU+zvrEoULqbZ1eVYCoKsb6/dQ=
|
|
||||||
github.com/inazumav/sing-box v0.0.0-20230728005925-1df6eb0f5bf7/go.mod h1:W91us/coe3lvl5jCtw2n6acyagpRbOO16h1IV3/0nrc=
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
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=
|
||||||
|
@ -26,14 +26,14 @@ type Controller struct {
|
|||||||
renewCertPeriodic *task.Task
|
renewCertPeriodic *task.Task
|
||||||
dynamicSpeedLimitPeriodic *task.Task
|
dynamicSpeedLimitPeriodic *task.Task
|
||||||
onlineIpReportPeriodic *task.Task
|
onlineIpReportPeriodic *task.Task
|
||||||
*conf.ControllerConfig
|
*conf.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewController return a Node controller with default parameters.
|
// NewController return a Node controller with default parameters.
|
||||||
func NewController(server vCore.Core, api *panel.Client, config *conf.ControllerConfig) *Controller {
|
func NewController(server vCore.Core, api *panel.Client, config *conf.Options) *Controller {
|
||||||
controller := &Controller{
|
controller := &Controller{
|
||||||
server: server,
|
server: server,
|
||||||
ControllerConfig: config,
|
Options: config,
|
||||||
apiClient: api,
|
apiClient: api,
|
||||||
}
|
}
|
||||||
return controller
|
return controller
|
||||||
@ -71,13 +71,13 @@ func (c *Controller) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add new tag
|
// Add new tag
|
||||||
err = c.server.AddNode(c.tag, node, c.ControllerConfig)
|
err = c.server.AddNode(c.tag, node, c.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add new node error: %s", err)
|
return fmt.Errorf("add new node error: %s", err)
|
||||||
}
|
}
|
||||||
added, err := c.server.AddUsers(&vCore.AddUsersParams{
|
added, err := c.server.AddUsers(&vCore.AddUsersParams{
|
||||||
Tag: c.tag,
|
Tag: c.tag,
|
||||||
Config: c.ControllerConfig,
|
Config: c.Options,
|
||||||
UserInfo: c.userList,
|
UserInfo: c.userList,
|
||||||
NodeInfo: node,
|
NodeInfo: node,
|
||||||
})
|
})
|
||||||
|
@ -2,6 +2,7 @@ package node
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/Yuzuki616/V2bX/api/panel"
|
"github.com/Yuzuki616/V2bX/api/panel"
|
||||||
"github.com/Yuzuki616/V2bX/conf"
|
"github.com/Yuzuki616/V2bX/conf"
|
||||||
vCore "github.com/Yuzuki616/V2bX/core"
|
vCore "github.com/Yuzuki616/V2bX/core"
|
||||||
@ -23,7 +24,7 @@ func (n *Node) Start(nodes []*conf.NodeConfig, core vCore.Core) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Register controller service
|
// Register controller service
|
||||||
n.controllers[i] = NewController(core, p, c.ControllerConfig)
|
n.controllers[i] = NewController(core, p, c.Options)
|
||||||
err = n.controllers[i].Start()
|
err = n.controllers[i].Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("start node controller [%s-%s-%d] error: %s",
|
return fmt.Errorf("start node controller [%s-%s-%d] error: %s",
|
||||||
|
@ -100,7 +100,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add new node
|
// add new node
|
||||||
err = c.server.AddNode(c.tag, newNodeInfo, c.ControllerConfig)
|
err = c.server.AddNode(c.tag, newNodeInfo, c.Options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"tag": c.tag,
|
"tag": c.tag,
|
||||||
@ -110,7 +110,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
}
|
}
|
||||||
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
||||||
Tag: c.tag,
|
Tag: c.tag,
|
||||||
Config: c.ControllerConfig,
|
Config: c.Options,
|
||||||
UserInfo: c.userList,
|
UserInfo: c.userList,
|
||||||
NodeInfo: newNodeInfo,
|
NodeInfo: newNodeInfo,
|
||||||
})
|
})
|
||||||
@ -168,7 +168,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
|
|||||||
// have added users
|
// have added users
|
||||||
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
_, err = c.server.AddUsers(&vCore.AddUsersParams{
|
||||||
Tag: c.tag,
|
Tag: c.tag,
|
||||||
Config: c.ControllerConfig,
|
Config: c.Options,
|
||||||
UserInfo: added,
|
UserInfo: added,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user