Documentation
¶
Overview ¶
Package native implements part of the forward package's v2 routes in the package itself, on the kernel's forward tables adopted in place (kernel.storage.adopt): v2_forward, v2_forward_tunnel, v2_forward_user_tunnel, v2_speed_limit, v2_forward_rule and v2_forward_latency_bucket. Legacy handlers and native routes share the tables, so a route can switch between them at any time. Responses are byte-compatible with the legacy handlers (internal/tests/forwardcompat).
A route is native only when it neither changes what a node runs nor touches state the kernel keeps in memory: its writes leave the rows the kernel's handlers would, and the kernel's forward runtime re-reads them. Every route that pushes a forward or rule to a node (NodeX, the local Ansible executor or a clean agent), probes the network, authenticates an agent or accounts traffic stays bridged; the host's route map says why for each one.
Other domains, and the forward data that holds credentials, are read through kernel views only:
- kapi_forward_node_v1: the forward nodes without their API tokens. v2_forward_node, v2_forward_clean_agent and v2_forward_runtime_job hold agent credentials and are protected kernel tables;
- kapi_forward_runtime_settings_v1: the three system configuration keys that choose the forward runtime backend, no other row of the protected v2_system_config;
- kapi_user_directory_v1, whether a user exists, and kapi_subscriber_entitlement_v1, a subscriber's speed limit.
The administrator's traffic reset of a subscriber (POST /api/v2/user/reset, type 1) goes through the kernel's KernelSubscriber.ResetTraffic (kernel.subscriber.traffic.v1); the package never writes v2_user.
Index ¶
- Constants
- func ResetRequestID(userID uint64, token string) string
- type DirectoryUser
- type Entitlement
- type Forward
- type LatencyBucket
- type Node
- type Rule
- type RuntimeSetting
- type Service
- func (s *Service) AssignUserTunnel(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) CreateSpeedLimit(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) CreateTunnel(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) DeleteSpeedLimit(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) DeleteTunnel(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) Handlers() map[string]pluginhostsdk.NativeHandler
- func (s *Service) ListAdminTunnels(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) ListForwards(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) ListSpeedLimits(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) ListTunnels(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) ListUserTunnels(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) MultiIngressLatency(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) ResetFlow(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) SpeedLimitTunnels(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) Stats(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) UpdateForwardOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- func (s *Service) UserRules(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
- type SpeedLimit
- type Subscriber
- type Tunnel
- type UserTunnel
Constants ¶
const ( SpeedLimitCreateRouteID = "forward.speed_limit.create.post" SpeedLimitListRouteID = "forward.speed_limit.list.post" SpeedLimitDeleteRouteID = "forward.speed_limit.delete.post" SpeedLimitTunnelsRouteID = "forward.speed_limit.tunnels.post" )
Route ids of the speed limit routes with a native handler. The update stays bridged: it re-applies the forwards of every permission that names the limit on their nodes.
const ResetRouteID = "forward.user.reset.post"
ResetRouteID is the administrator's traffic reset, the one route that needs KernelSubscriber.
Variables ¶
This section is empty.
Functions ¶
func ResetRequestID ¶
ResetRequestID names an administrator's subscriber traffic reset through POST /api/v2/user/reset in Control's subscriber request ledger, so a retried request is applied once. token identifies the HTTP request: its Idempotency-Key, else its request id. The kernel's legacy handler derives the same id (service.ForwardUserResetRequestID), so a retry is recognized whichever side serves it; a new request is a new reset, as in v2.
Types ¶
type DirectoryUser ¶
type DirectoryUser struct {
ID uint `gorm:"primaryKey"`
}
DirectoryUser is the part of a kapi_user_directory_v1 row the routes read: that the user exists.
func (DirectoryUser) TableName ¶
func (DirectoryUser) TableName() string
TableName is the kernel view.
type Entitlement ¶
Entitlement is the part of a kapi_subscriber_entitlement_v1 row the routes read: the subscriber's speed limit.
type Forward ¶
type Forward struct {
ID uint `gorm:"primaryKey"`
UserID uint `gorm:"index;not null"`
UserName string `gorm:"size:255"`
Name string `gorm:"size:100;not null"`
TunnelID uint `gorm:"index;not null"`
Tunnel *Tunnel `gorm:"foreignKey:TunnelID"`
InPort int `gorm:"not null"`
OutPort int
RemoteAddr string `gorm:"type:text;not null"`
InterfaceName string `gorm:"size:255"`
Strategy string `gorm:"size:20;default:'fifo'"`
Status int `gorm:"default:1"`
RuntimeBackend string `gorm:"size:50;default:'gost';index"`
RuntimeStatus int `gorm:"default:0;index"`
RuntimeMessage string `gorm:"type:text"`
RuntimeLastSyncAt *time.Time
InFlow int64 `gorm:"default:0"`
OutFlow int64 `gorm:"default:0"`
Inx int `gorm:"default:0"`
CreatedAt time.Time
UpdatedAt time.Time
}
Forward is a v2_forward row.
type LatencyBucket ¶
type LatencyBucket struct {
ID uint `gorm:"primaryKey"`
TargetKey string
TargetType string
TargetID uint
Label string
Host string
Port int
BucketAt time.Time
IntervalSeconds int
SampleCount int
SuccessCount int
MinRTT float64
AvgRTT float64
MaxRTT float64
P95RTT float64
LossPct float64
CreatedAt time.Time
UpdatedAt time.Time
}
LatencyBucket is a v2_forward_latency_bucket row, written by the kernel's latency prober.
func (LatencyBucket) TableName ¶
func (LatencyBucket) TableName() string
TableName is the adopted kernel table.
type Node ¶
type Node struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Host string `json:"host"`
Port int `json:"port"`
APIPort int `json:"api_port"`
// APIToken is never read; answers to users show it empty.
APIToken string `gorm:"-" json:"api_token"`
MetricsPort int `json:"metrics_port"`
Region string `json:"region"`
ISP string `json:"isp"`
Datacenter string `json:"datacenter"`
Bandwidth int64 `json:"bandwidth"`
Status int `json:"status"`
LastCheck time.Time `json:"last_check"`
Latency int `json:"latency"`
Load float64 `json:"load"`
Uptime float64 `json:"uptime"`
Tags string `json:"tags"`
Weight int `json:"weight"`
MaxConn int `json:"max_conn"`
Enabled bool `json:"enabled"`
TotalUpload int64 `json:"total_upload"`
TotalDownload int64 `json:"total_download"`
CurrentConn int `json:"current_conn"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Node is a row of kapi_forward_node_v1: a forward node without its API token, which authenticates the node's agent and stays in the protected v2_forward_node. Its JSON is the kernel model's.
type Rule ¶
type Rule struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"size:100;not null" json:"name"`
Enabled bool `gorm:"default:true" json:"enabled"`
RelayNodeID uint `gorm:"not null" json:"relay_node_id"`
RelayNode *Node `gorm:"foreignKey:RelayNodeID" json:"relay_node,omitempty"`
ListenPort int `gorm:"not null" json:"listen_port"`
Protocol string `gorm:"size:10;default:'tcp'" json:"protocol"`
ExitNodeID uint `gorm:"not null" json:"exit_node_id"`
ExitNode *Node `gorm:"foreignKey:ExitNodeID" json:"exit_node,omitempty"`
TargetHost string `gorm:"size:255;not null" json:"target_host"`
TargetPort int `gorm:"not null" json:"target_port"`
UserID *uint `json:"user_id"`
UserGroupID *uint `json:"user_group_id"`
AllowedIPs string `gorm:"size:1000" json:"allowed_ips"`
SpeedLimit *int64 `json:"speed_limit"`
TrafficLimit *int64 `json:"traffic_limit"`
ExpireTime *time.Time `json:"expire_time"`
Upload int64 `json:"upload"`
Download int64 `json:"download"`
Connections int `json:"connections"`
TotalConns int64 `json:"total_conns"`
Remark string `gorm:"size:500" json:"remark"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Rule is a v2_forward_rule row, as the legacy answers show it: with its relay and exit nodes when they are loaded, and never its user.
type RuntimeSetting ¶
RuntimeSetting is a row of kapi_forward_runtime_settings_v1: one of the system configuration keys that choose the forward runtime backend.
func (RuntimeSetting) TableName ¶
func (RuntimeSetting) TableName() string
TableName is the kernel view.
type Service ¶
type Service struct {
// Open returns the package's storage connection, on which the adopted
// tables and the granted views are visible.
Open func(ctx context.Context) (*gorm.DB, error)
// Subscriber is the kernel's KernelSubscriber; without it the traffic
// reset has no native handler and stays legacy.
Subscriber Subscriber
// NewToken identifies a reset request that has neither an
// Idempotency-Key nor a request id; it defaults to a random UUID.
NewToken func() string
// Now defaults to time.Now.
Now func() time.Time
}
Service holds what the native routes need.
func (*Service) AssignUserTunnel ¶
func (s *Service) AssignUserTunnel(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
AssignUserTunnel is POST /api/v2/tunnel/user/assign and its administrator route: it lets a user create forwards on a tunnel. A permission alone runs nothing on a node, so nothing is pushed; whether the user exists is read from kapi_user_directory_v1.
func (*Service) CreateSpeedLimit ¶
func (s *Service) CreateSpeedLimit(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
CreateSpeedLimit is POST /api/v2/speed-limit/create: a named speed limit for a tunnel, which no permission uses yet, so nothing runs on a node.
func (*Service) CreateTunnel ¶
func (s *Service) CreateTunnel(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
CreateTunnel is POST /api/v2/admin/tunnel/create. A tunnel alone runs nothing on a node: forwards do, so nothing is pushed. Its nodes are read through kapi_forward_node_v1.
func (*Service) DeleteSpeedLimit ¶
func (s *Service) DeleteSpeedLimit(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
DeleteSpeedLimit is POST /api/v2/speed-limit/delete: a speed limit no permission uses, so no forward runs with it.
func (*Service) DeleteTunnel ¶
func (s *Service) DeleteTunnel(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
DeleteTunnel is POST /api/v2/admin/tunnel/delete: a tunnel no forward and no user permission uses, so no node runs anything for it.
func (*Service) Handlers ¶
func (s *Service) Handlers() map[string]pluginhostsdk.NativeHandler
Handlers returns the native handlers by route id.
func (*Service) ListAdminTunnels ¶
func (s *Service) ListAdminTunnels(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
ListAdminTunnels is POST /api/v2/admin/tunnel/list: every tunnel.
func (*Service) ListForwards ¶
func (s *Service) ListForwards(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
ListForwards is POST /api/v2/forward/list (the caller's forwards) and POST /api/v2/admin/forward/list; an administrator sees every forward.
func (*Service) ListSpeedLimits ¶
func (s *Service) ListSpeedLimits(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
ListSpeedLimits is POST /api/v2/speed-limit/list: every speed limit by id.
func (*Service) ListTunnels ¶
func (s *Service) ListTunnels(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
ListTunnels is POST /api/v2/tunnel/user/tunnel and its administrator route: the active tunnels the caller may use (every one for an administrator), as far as they suit the configured runtime backend.
func (*Service) ListUserTunnels ¶
func (s *Service) ListUserTunnels(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
ListUserTunnels is POST /api/v2/tunnel/user/list and its administrator route: a user's tunnel permissions. As in the kernel, a permission's traffic catches up with its forwards' totals first. The speed is the permission's speed limit, else the subscriber's own (kapi_subscriber_entitlement_v1).
func (*Service) MultiIngressLatency ¶
func (s *Service) MultiIngressLatency(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
MultiIngressLatency is GET /api/v2/admin/forward/observability/multi-ingress: for a forward, the latest ingress latency of every tunnel that reaches the same exit node, from the latency prober's buckets.
func (*Service) ResetFlow ¶
func (s *Service) ResetFlow(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
ResetFlow is POST /api/v2/user/reset, the administrator's Flux-style reset: type 1 zeroes a subscriber's traffic through KernelSubscriber.ResetTraffic, type 2 a tunnel permission's traffic and that of the permission's forwards. Neither changes what a node runs.
func (*Service) SpeedLimitTunnels ¶
func (s *Service) SpeedLimitTunnels(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
SpeedLimitTunnels is POST /api/v2/speed-limit/tunnels: the tunnels a speed limit may name, every active one as for an administrator, as far as they suit the configured runtime backend.
func (*Service) Stats ¶
func (s *Service) Stats(ctx context.Context, _ pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
Stats is GET /api/v2/admin/forward/stats: the enabled relay and exit nodes, how many are online, and their traffic, from kapi_forward_node_v1.
func (*Service) UpdateForwardOrder ¶
func (s *Service) UpdateForwardOrder(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
UpdateForwardOrder is POST /api/v2/forward/update-order and its administrator route: it sets the display order (inx) of the caller's forwards, or of any forward for an administrator. The order is not part of what a node runs, so nothing is pushed.
func (*Service) UserRules ¶
func (s *Service) UserRules(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)
UserRules is GET /api/v2/user/forward/rules: the caller's forward rules with their relay and exit nodes, which kapi_forward_node_v1 shows without their API tokens; the answer's api_token is empty, as the kernel's is.
type SpeedLimit ¶
type SpeedLimit struct {
ID uint `gorm:"primaryKey" json:"id"`
CreatedTime int64 `gorm:"index;not null" json:"createdTime"`
UpdatedTime int64 `gorm:"index;not null" json:"updatedTime"`
Status int `gorm:"default:1" json:"status"`
Name string `gorm:"size:100;not null" json:"name"`
Speed int64 `gorm:"not null" json:"speed"`
TunnelID uint `gorm:"index;not null" json:"tunnelId"`
TunnelName string `gorm:"size:100;not null" json:"tunnelName"`
}
SpeedLimit is a v2_speed_limit row: a tunnel's named speed limit, which the /speed-limit routes manage. Its fields and tags match the kernel model, so answers are the same.
func (SpeedLimit) TableName ¶
func (SpeedLimit) TableName() string
TableName is the adopted kernel table.
type Subscriber ¶
type Subscriber interface {
ResetTraffic(ctx context.Context, in *kernelsubscriberv1.ResetTrafficRequest, opts ...grpc.CallOption) (*kernelsubscriberv1.ResetTrafficResponse, error)
}
Subscriber is the part of KernelSubscriber the native routes call.
type Tunnel ¶
type Tunnel struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
InNodeID uint `gorm:"index"`
OutNodeID *uint `gorm:"index"`
InIP string `gorm:"size:255"`
OutIP string `gorm:"size:255"`
InNodePortSta *int
InNodePortEnd *int
Type int `gorm:"default:1"`
Flow int `gorm:"default:2"`
Protocol string `gorm:"size:30;default:'tcp'"`
TrafficRatio float64 `gorm:"default:1"`
InterfaceName string `gorm:"size:255"`
TCPListenAddr string `gorm:"size:255;default:'0.0.0.0'"`
UDPListenAddr string `gorm:"size:255;default:'0.0.0.0'"`
Status int `gorm:"default:1"`
CreatedAt time.Time
UpdatedAt time.Time
}
Tunnel is a v2_forward_tunnel row.
type UserTunnel ¶
type UserTunnel struct {
ID uint `gorm:"primaryKey"`
UserID uint `gorm:"uniqueIndex:idx_forward_user_tunnel"`
TunnelID uint `gorm:"uniqueIndex:idx_forward_user_tunnel;index"`
Flow int64 `gorm:"default:0"`
Num int `gorm:"default:0"`
InFlow int64 `gorm:"default:0"`
OutFlow int64 `gorm:"default:0"`
FlowResetTime int64 `gorm:"default:0"`
ExpTime int64 `gorm:"default:0"`
SpeedID *uint
Status int `gorm:"default:1"`
CreatedAt time.Time
UpdatedAt time.Time
Tunnel *Tunnel `gorm:"foreignKey:TunnelID"`
}
UserTunnel is a v2_forward_user_tunnel row: a user's permission to use a tunnel, with its quota and traffic.
func (UserTunnel) TableName ¶
func (UserTunnel) TableName() string
TableName is the adopted kernel table.