singbox

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 25, 2026 License: GPL-3.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildDNSOptions

func BuildDNSOptions(servers []api.NameServer, strategy string) (option.DNSOptions, error)

BuildDNSOptions translates a neutral NameServer list plus an xray-style domain-resolution strategy into native sing-box option.DNSOptions.

strategy accepts the xray DomainStrategy vocabulary (case-insensitive): "" / "AsIs", "UseIP", "UseIPv4", "UseIPv6" — plus the sing-box-native "PreferIPv4" / "PreferIPv6" aliases. Mapping to sing-box strategy:

AsIs       → as_is
UseIP      → prefer_ipv4   (xray "resolve, no family pin"; prefer v4)
UseIPv4    → ipv4_only
UseIPv6    → ipv6_only
PreferIPv4 → prefer_ipv4
PreferIPv6 → prefer_ipv6

An empty server list returns a zero-value option.DNSOptions with no error (the caller then leaves box's dns{} at its default).

func DirectOutbound

func DirectOutbound(tag string) option.Outbound

DirectOutbound builds a plain direct outbound so smoke traffic has somewhere to go (sing-box uses the first outbound as the default final route).

func MinimalVLESSInbound

func MinimalVLESSInbound(tag, listen string, port uint16, uuid, flow string) (option.Inbound, error)

MinimalVLESSInbound builds a native VLESS inbound with a single user, for the Phase 0 cross-core baseline smoke (Xray-core client → Sing2 server). flow may be "" or "xtls-rprx-vision"; REALITY is layered by the translation layer in Phase 1.

func Translate

func Translate(ctx context.Context, tag string, info *api.NodeInfo, users []api.UserInfo) (string, any, error)

Translate builds the (inboundType, options) pair for info together with its current authoritative user set. users may be empty at AddNode time — users are hot-swapped in later via Inbound.UpdateUsers (see user.go). It is the cert-less public entry (plain-TLS nodes get an SNI-only TLS block); the Server drives the cert-aware path via translateNode.

ctx must be the include.Context-wrapped context the Box was built with: the native dialect (doc/13 T4) resolves inbound options through the registry stored in it. Flat-dialect nodes ignore ctx.

Types

type BillingServer

type BillingServer struct {
	// contains filtered or unexported fields
}

BillingServer is the per-connection billing tracker (Hinge A). Its RoutedConnection runs the per-connection pipeline limiter(rate/device/online/conn-count) → rule(audit) → stats(inner byte count) → ratelimit(outer token-bucket) and defers the conn-count decrement to the wrapped conn's Close (doc/11 §2.2).

Phase 1 increment A: the pipeline is wired but limiter/rule are not yet populated by the panel (no inbound registered → no throttle / no block); stats and connlimit take effect immediately — the intended "wired-but-unpopulated" state.

func NewBillingServer

func NewBillingServer(
	lim *limiter.Limiter,
	rul *rule.Manager,
	st *stats.Registry,
	rt *ratelimit.Manager,
	conns *limiter.ConnLimiter,
) *BillingServer

NewBillingServer wires the five billing components into the tracker.

func (*BillingServer) RoutedConnection

func (b *BillingServer) RoutedConnection(
	ctx context.Context, conn net.Conn, metadata adapter.InboundContext,
	matchedRule adapter.Rule, matchOutbound adapter.Outbound,
) net.Conn

RoutedConnection is the TCP injection point (doc/11 §2.2). The pipeline runs conn-count → rate/device/online limiter → audit rule → stats → ratelimit, unwinding the conn-count on any early reject and deferring the decrement to the wrapped conn's Close on success. When access logging is enabled it emits one rejected row per early-reject path and one accepted row on release.

func (*BillingServer) RoutedPacketConnection

func (b *BillingServer) RoutedPacketConnection(
	ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext,
	matchedRule adapter.Rule, matchOutbound adapter.Outbound,
) N.PacketConn

RoutedPacketConnection is the UDP injection point. UDP is not counted toward the per-user concurrent connection cap; it still gets byte accounting and token-bucket limiting.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the sing-box-backed Core implementation. It owns the Box, the five billing components (also handed to the Hinge A tracker), and the authoritative per-node user sets driving the whole-set UpdateUsers hot-swap.

func NewServer

func NewServer(ctx context.Context, opts option.Options) (*Server, error)

NewServer builds a Box from opts, registers the billing ConnectionTracker (Hinge A — Router.AppendTracker, doc/11 §2.1), and returns the wrapper. The caller drives it with Start/Close. include.Context installs the protocol registries the fork's registry-era constructor (and dynamic Create) require.

func (*Server) AddNode

func (s *Server) AddNode(tag string, info *api.NodeInfo) error

AddNode translates info into a dynamic inbound, creates it on the running Box, and registers the node in the limiter (empty user set — users arrive via AddUsers). It is an error to add a tag that already exists.

func (*Server) AddUsers

func (s *Server) AddUsers(tag string, users []api.UserInfo) (added int, err error)

AddUsers merges users into the node's authoritative set (deduped by join key), re-pushes the complete user list to the live inbound, and syncs the limiter. Returns the count of users newly added (already-present join keys update in place and are not counted).

func (*Server) Close

func (s *Server) Close() error

func (*Server) DelNode

func (s *Server) DelNode(tag string) error

DelNode removes the dynamic inbound and its limiter/bookkeeping. Removing an unknown tag is a no-op error from the inbound manager but the local state is cleared regardless.

func (*Server) DelUsers

func (s *Server) DelUsers(tag string, users []api.UserInfo) error

DelUsers removes users (by join key) from the node's authoritative set, re-pushes the remaining list to the inbound, and evicts the removed users from the limiter's per-user maps so no stale entries linger.

func (*Server) GetDetectResult

func (s *Server) GetDetectResult(tag string) ([]api.DetectResult, error)

GetDetectResult drains the audit hits accumulated for a node since the last call (the rule.Manager clears them on read) and returns them by value. The panel layer filters out local rules (RuleID < 0) before reporting upstream.

func (*Server) GetUserTraffic

func (s *Server) GetUserTraffic(tag string, reset bool) ([]api.UserTraffic, error)

GetUserTraffic returns per-user byte counters for the node, keyed by join key against the stats registry. reset=true atomically zeroes each counter after read (reset-then-report, doc/10 §7.1). Only users with non-zero traffic in the period are returned (XrayR reporting convention).

func (*Server) OnlineIPs

func (s *Server) OnlineIPs(tag string) ([]api.OnlineUser, error)

OnlineIPs returns the users currently connected on the node (per the limiter's online-device map). Note GetOnlineDevice resets the map as a side effect, so each call reports the devices seen since the previous call.

func (*Server) Protocols

func (s *Server) Protocols() []string

func (*Server) ResolveIdentity

func (s *Server) ResolveIdentity(tag, name string) string

ResolveIdentity maps an inbound's authenticated user name to the billing join key. It satisfies identityResolver for the Hinge A tracker. Unknown tags and names pass through unchanged, so any protocol that never needed translation — and any race against a user removal — degrades to the pre-T5 behaviour rather than losing the connection.

func (*Server) SetAccessLog

func (s *Server) SetAccessLog(m *accesslog.Manager)

SetAccessLog wires (or clears with nil) the process-level access-log reporter consulted by the Hinge A tracker. Call before Start; the manager itself is started/stopped by the panel orchestrator (doc/11 §13).

func (*Server) SetNodeCert

func (s *Server) SetNodeCert(tag string, cfg cert.CertConfig)

SetNodeCert records the certificate policy for a node tag. It must be called before AddNode(tag, …) so the translation layer can build the inbound TLS block for a plain-TLS node (REALITY nodes ignore it). Overwrites any prior value for the tag (doc/03 T10).

func (*Server) SetNodeConnLimit

func (s *Server) SetNodeConnLimit(tag string, max int)

SetNodeConnLimit sets the per-user concurrent-TCP-connection cap for a node tag on the shared ConnLimiter (doc/09 §5.3 ConnLimitConfig, T5). max <= 0 clears the tag's limit. Safe to call before or after AddNode; the panel calls it before AddNode alongside the other per-tag policies.

func (*Server) SetNodeGlobalLimit

func (s *Server) SetNodeGlobalLimit(tag string, cfg *limiter.GlobalDeviceLimitConfig)

SetNodeGlobalLimit records the cross-node device-limit (Redis) policy for a node tag. It must be called before AddNode(tag, …) so the limiter registers the tag with its global cap. A nil cfg (or one with Enable=false) leaves the tag without a global limit. Overwrites any prior value for the tag (doc/09 §5.3, doc/11 §7).

func (*Server) Start

func (s *Server) Start() error

func (*Server) Type

func (s *Server) Type() string

func (*Server) UpdateInboundLimiter

func (s *Server) UpdateInboundLimiter(tag string, users []api.UserInfo) error

UpdateInboundLimiter forwards a user-list speed-limit update to the shared limiter. The panel's dynamic speed-limit driver (T7 AutoLimiter) uses it to throttle/restore users without reaching into billing internals (doc/11 §8).

func (*Server) UpdateRule

func (s *Server) UpdateRule(tag string, rules []api.DetectRule) error

UpdateRule installs the audit rule set for a node. It forwards to the shared rule.Manager (the same instance the Hinge A tracker consults). This is beyond the core.Core interface — the panel orchestration layer calls it on the concrete *Server (doc/11 §5, doc/10 §3.6). RuleNotModified handling is the caller's concern; this always installs the list it is given.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL