mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-22 00:21:30 +00:00
Add v2ray user stats api
This commit is contained in:
parent
7ea9d48987
commit
39514b3ca0
|
@ -45,6 +45,6 @@ type V2RayServer interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type V2RayStatsService interface {
|
type V2RayStatsService interface {
|
||||||
RoutedConnection(inbound string, outbound string, conn net.Conn) net.Conn
|
RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn
|
||||||
RoutedPacketConnection(inbound string, outbound string, conn N.PacketConn) N.PacketConn
|
RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
"outbounds": [
|
"outbounds": [
|
||||||
"proxy",
|
"proxy",
|
||||||
"direct"
|
"direct"
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
"sekai"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,3 +112,7 @@ Inbound list to count traffic.
|
||||||
#### stats.outbounds
|
#### stats.outbounds
|
||||||
|
|
||||||
Outbound list to count traffic.
|
Outbound list to count traffic.
|
||||||
|
|
||||||
|
#### stats.users
|
||||||
|
|
||||||
|
User list to count traffic.
|
|
@ -25,6 +25,9 @@
|
||||||
"outbounds": [
|
"outbounds": [
|
||||||
"proxy",
|
"proxy",
|
||||||
"direct"
|
"direct"
|
||||||
|
],
|
||||||
|
"users": [
|
||||||
|
"sekai"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,3 +110,7 @@ gRPC API 监听地址。如果为空,则禁用 V2Ray API。
|
||||||
#### stats.outbounds
|
#### stats.outbounds
|
||||||
|
|
||||||
统计流量的出站列表。
|
统计流量的出站列表。
|
||||||
|
|
||||||
|
#### stats.users
|
||||||
|
|
||||||
|
统计流量的用户列表。
|
|
@ -31,6 +31,7 @@ type StatsService struct {
|
||||||
createdAt time.Time
|
createdAt time.Time
|
||||||
inbounds map[string]bool
|
inbounds map[string]bool
|
||||||
outbounds map[string]bool
|
outbounds map[string]bool
|
||||||
|
users map[string]bool
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
counters map[string]*atomic.Int64
|
counters map[string]*atomic.Int64
|
||||||
}
|
}
|
||||||
|
@ -41,26 +42,32 @@ func NewStatsService(options option.V2RayStatsServiceOptions) *StatsService {
|
||||||
}
|
}
|
||||||
inbounds := make(map[string]bool)
|
inbounds := make(map[string]bool)
|
||||||
outbounds := make(map[string]bool)
|
outbounds := make(map[string]bool)
|
||||||
|
users := make(map[string]bool)
|
||||||
for _, inbound := range options.Inbounds {
|
for _, inbound := range options.Inbounds {
|
||||||
inbounds[inbound] = true
|
inbounds[inbound] = true
|
||||||
}
|
}
|
||||||
for _, outbound := range options.Outbounds {
|
for _, outbound := range options.Outbounds {
|
||||||
outbounds[outbound] = true
|
outbounds[outbound] = true
|
||||||
}
|
}
|
||||||
|
for _, user := range options.Users {
|
||||||
|
users[user] = true
|
||||||
|
}
|
||||||
return &StatsService{
|
return &StatsService{
|
||||||
createdAt: time.Now(),
|
createdAt: time.Now(),
|
||||||
inbounds: inbounds,
|
inbounds: inbounds,
|
||||||
outbounds: outbounds,
|
outbounds: outbounds,
|
||||||
|
users: users,
|
||||||
counters: make(map[string]*atomic.Int64),
|
counters: make(map[string]*atomic.Int64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StatsService) RoutedConnection(inbound string, outbound string, conn net.Conn) net.Conn {
|
func (s *StatsService) RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn {
|
||||||
var readCounter []*atomic.Int64
|
var readCounter []*atomic.Int64
|
||||||
var writeCounter []*atomic.Int64
|
var writeCounter []*atomic.Int64
|
||||||
countInbound := inbound != "" && s.inbounds[inbound]
|
countInbound := inbound != "" && s.inbounds[inbound]
|
||||||
countOutbound := outbound != "" && s.outbounds[outbound]
|
countOutbound := outbound != "" && s.outbounds[outbound]
|
||||||
if !countInbound && !countOutbound {
|
countUser := user != "" && s.users[user]
|
||||||
|
if !countInbound && !countOutbound && !countUser {
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
|
@ -72,16 +79,21 @@ func (s *StatsService) RoutedConnection(inbound string, outbound string, conn ne
|
||||||
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
|
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
|
||||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
|
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
|
||||||
}
|
}
|
||||||
|
if countUser {
|
||||||
|
readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink"))
|
||||||
|
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
|
||||||
|
}
|
||||||
s.access.Unlock()
|
s.access.Unlock()
|
||||||
return trackerconn.New(conn, readCounter, writeCounter)
|
return trackerconn.New(conn, readCounter, writeCounter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, conn N.PacketConn) N.PacketConn {
|
func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn {
|
||||||
var readCounter []*atomic.Int64
|
var readCounter []*atomic.Int64
|
||||||
var writeCounter []*atomic.Int64
|
var writeCounter []*atomic.Int64
|
||||||
countInbound := inbound != "" && s.inbounds[inbound]
|
countInbound := inbound != "" && s.inbounds[inbound]
|
||||||
countOutbound := outbound != "" && s.outbounds[outbound]
|
countOutbound := outbound != "" && s.outbounds[outbound]
|
||||||
if !countInbound && !countOutbound {
|
countUser := user != "" && s.users[user]
|
||||||
|
if !countInbound && !countOutbound && !countUser {
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
s.access.Lock()
|
s.access.Lock()
|
||||||
|
@ -93,6 +105,10 @@ func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, c
|
||||||
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
|
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
|
||||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
|
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
|
||||||
}
|
}
|
||||||
|
if countUser {
|
||||||
|
readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink"))
|
||||||
|
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
|
||||||
|
}
|
||||||
s.access.Unlock()
|
s.access.Unlock()
|
||||||
return trackerconn.NewPacket(conn, readCounter, writeCounter)
|
return trackerconn.NewPacket(conn, readCounter, writeCounter)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,4 +9,5 @@ type V2RayStatsServiceOptions struct {
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
Enabled bool `json:"enabled,omitempty"`
|
||||||
Inbounds []string `json:"inbounds,omitempty"`
|
Inbounds []string `json:"inbounds,omitempty"`
|
||||||
Outbounds []string `json:"outbounds,omitempty"`
|
Outbounds []string `json:"outbounds,omitempty"`
|
||||||
|
Users []string `json:"users,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -600,7 +600,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
}
|
}
|
||||||
if r.v2rayServer != nil {
|
if r.v2rayServer != nil {
|
||||||
if statsService := r.v2rayServer.StatsService(); statsService != nil {
|
if statsService := r.v2rayServer.StatsService(); statsService != nil {
|
||||||
conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), conn)
|
conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return detour.NewConnection(ctx, conn, metadata)
|
return detour.NewConnection(ctx, conn, metadata)
|
||||||
|
@ -678,7 +678,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||||
}
|
}
|
||||||
if r.v2rayServer != nil {
|
if r.v2rayServer != nil {
|
||||||
if statsService := r.v2rayServer.StatsService(); statsService != nil {
|
if statsService := r.v2rayServer.StatsService(); statsService != nil {
|
||||||
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), conn)
|
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return detour.NewPacketConnection(ctx, conn, metadata)
|
return detour.NewPacketConnection(ctx, conn, metadata)
|
||||||
|
|
Loading…
Reference in a new issue