mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-16 12:22:21 +08:00
Add vlite inbound
This commit is contained in:
parent
7cb4ded3a7
commit
20a5182aa2
|
@ -41,6 +41,8 @@ func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, o
|
|||
return NewHysteria(ctx, router, logger, options.Tag, options.HysteriaOptions)
|
||||
case C.TypeShadowTLS:
|
||||
return NewShadowTLS(ctx, router, logger, options.Tag, options.ShadowTLSOptions)
|
||||
case C.TypeVLite:
|
||||
return NewVLite(ctx, router, logger, options.Tag, options.VLiteOptions)
|
||||
default:
|
||||
return nil, E.New("unknown inbound type: ", options.Type)
|
||||
}
|
||||
|
|
48
inbound/vlite.go
Normal file
48
inbound/vlite.go
Normal file
|
@ -0,0 +1,48 @@
|
|||
//go:build with_vlite
|
||||
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/transport/vlite"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/udpnat"
|
||||
)
|
||||
|
||||
type VLite struct {
|
||||
myInboundAdapter
|
||||
server *vlite.Server
|
||||
udpNat *udpnat.Service[netip.AddrPort]
|
||||
}
|
||||
|
||||
func NewVLite(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VLiteInboundOptions) (*VLite, error) {
|
||||
inbound := &VLite{
|
||||
myInboundAdapter: myInboundAdapter{
|
||||
protocol: C.TypeVLite,
|
||||
network: []string{N.NetworkUDP},
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logger,
|
||||
tag: tag,
|
||||
listenOptions: options.ListenOptions,
|
||||
},
|
||||
server: vlite.NewServer(ctx, options),
|
||||
}
|
||||
inbound.udpNat = udpnat.New[netip.AddrPort](options.UDPTimeout, adapter.NewUpstreamContextHandler(nil, inbound.server.NewPacketConnection, inbound))
|
||||
inbound.packetHandler = inbound
|
||||
return inbound, nil
|
||||
}
|
||||
|
||||
func (h *VLite) NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext) error {
|
||||
h.udpNat.NewContextPacket(ctx, metadata.Source.AddrPort(), buffer, adapter.UpstreamMetadata(metadata), func(natConn N.PacketConn) (context.Context, N.PacketWriter) {
|
||||
return adapter.WithContext(log.ContextWithNewID(ctx), &metadata), &tproxyPacketWriter{ctx: ctx, source: natConn, destination: metadata.Destination}
|
||||
})
|
||||
return nil
|
||||
}
|
16
inbound/vlite_stub.go
Normal file
16
inbound/vlite_stub.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
//go:build !with_vlite
|
||||
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewVLite(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VLiteInboundOptions) (adapter.Inbound, error) {
|
||||
return nil, E.New(`VLite is not included in this build, rebuild with -tags with_vlite`)
|
||||
}
|
|
@ -22,6 +22,7 @@ type _Inbound struct {
|
|||
NaiveOptions NaiveInboundOptions `json:"-"`
|
||||
HysteriaOptions HysteriaInboundOptions `json:"-"`
|
||||
ShadowTLSOptions ShadowTLSInboundOptions `json:"-"`
|
||||
VLiteOptions VLiteInboundOptions `json:"-"`
|
||||
}
|
||||
|
||||
type Inbound _Inbound
|
||||
|
@ -55,6 +56,8 @@ func (h Inbound) MarshalJSON() ([]byte, error) {
|
|||
v = h.HysteriaOptions
|
||||
case C.TypeShadowTLS:
|
||||
v = h.ShadowTLSOptions
|
||||
case C.TypeVLite:
|
||||
v = h.VLiteOptions
|
||||
default:
|
||||
return nil, E.New("unknown inbound type: ", h.Type)
|
||||
}
|
||||
|
@ -94,6 +97,8 @@ func (h *Inbound) UnmarshalJSON(bytes []byte) error {
|
|||
v = &h.HysteriaOptions
|
||||
case C.TypeShadowTLS:
|
||||
v = &h.ShadowTLSOptions
|
||||
case C.TypeVLite:
|
||||
v = &h.VLiteOptions
|
||||
default:
|
||||
return E.New("unknown inbound type: ", h.Type)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
package option
|
||||
|
||||
type VLiteInboundOptions struct {
|
||||
ListenOptions
|
||||
VLiteOptions
|
||||
}
|
||||
|
||||
type VLiteOutboundOptions struct {
|
||||
DialerOptions
|
||||
ServerOptions
|
||||
VLiteOptions
|
||||
}
|
||||
|
||||
type VLiteOptions struct {
|
||||
Password string `json:"password,omitempty"`
|
||||
ScramblePacket bool `json:"scramble_packet,omitempty"`
|
||||
EnableFEC bool `json:"enable_fec,omitempty"`
|
||||
|
|
|
@ -31,7 +31,6 @@ var _ N.Dialer = (*Client)(nil)
|
|||
|
||||
type Client struct {
|
||||
ctx context.Context
|
||||
password []byte
|
||||
msgbus *bus.Bus
|
||||
udpdialer vlite_transport.UnderlayTransportDialer
|
||||
puni *puniClient.PacketUniClient
|
||||
|
@ -40,14 +39,13 @@ type Client struct {
|
|||
TunnelTxToTun chan interfaces.UDPPacket
|
||||
TunnelRxFromTun chan interfaces.UDPPacket
|
||||
connAdp *udpconn2tun.UDPConn2Tun
|
||||
config option.VLiteOutboundOptions
|
||||
access sync.Mutex
|
||||
options option.VLiteOutboundOptions
|
||||
}
|
||||
|
||||
func NewClient(ctx context.Context, dialer N.Dialer, options option.VLiteOutboundOptions) *Client { //nolint:unparam
|
||||
client := &Client{
|
||||
password: []byte(options.Password),
|
||||
config: options,
|
||||
options: options,
|
||||
msgbus: ibus.NewMessageBus(),
|
||||
}
|
||||
ctx = context.WithValue(ctx, interfaces.ExtraOptionsDisableAutoQuitForClient, true) //nolint:revive,staticcheck
|
||||
|
@ -124,12 +122,12 @@ func (c *Client) Start() error {
|
|||
c.TunnelTxToTun = TunnelTxToTun
|
||||
c.TunnelRxFromTun = TunnelRxFromTun
|
||||
|
||||
if c.config.EnableStabilization && c.config.EnableRenegotiation {
|
||||
c.puni = puniClient.NewPacketUniClient(C_C2STraffic2, C_C2SDataTraffic2, C_S2CTraffic2, c.password, connctx)
|
||||
if c.options.EnableStabilization && c.options.EnableRenegotiation {
|
||||
c.puni = puniClient.NewPacketUniClient(C_C2STraffic2, C_C2SDataTraffic2, C_S2CTraffic2, []byte(c.options.Password), connctx)
|
||||
c.puni.OnAutoCarrier(conn, connctx)
|
||||
c.udpserver = worker_client.UDPClient(connctx, C_C2STraffic, C_C2SDataTraffic, C_S2CTraffic, TunnelTxToTun, TunnelRxFromTun, c.puni)
|
||||
} else {
|
||||
c.udprelay = sctp_server.NewPacketRelayClient(conn, C_C2STraffic2, C_C2SDataTraffic2, C_S2CTraffic2, c.password, connctx)
|
||||
c.udprelay = sctp_server.NewPacketRelayClient(conn, C_C2STraffic2, C_C2SDataTraffic2, C_S2CTraffic2, []byte(c.options.Password), connctx)
|
||||
c.udpserver = worker_client.UDPClient(connctx, C_C2STraffic, C_C2SDataTraffic, C_S2CTraffic, TunnelTxToTun, TunnelRxFromTun, c.udprelay)
|
||||
}
|
||||
c.ctx = connctx
|
||||
|
|
41
transport/vlite/conn.go
Normal file
41
transport/vlite/conn.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package vlite
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
var _ N.NetPacketConn = (*connWrapper)(nil)
|
||||
|
||||
type connWrapper struct {
|
||||
N.PacketConn
|
||||
done chan struct{}
|
||||
}
|
||||
|
||||
func newConnWrapper(conn N.PacketConn) (N.NetPacketConn, chan struct{}) {
|
||||
done := make(chan struct{})
|
||||
return &connWrapper{
|
||||
PacketConn: conn,
|
||||
done: done,
|
||||
}, done
|
||||
}
|
||||
|
||||
func (c *connWrapper) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
return bufio.ReadPacket(c, buf.With(p))
|
||||
}
|
||||
|
||||
func (c *connWrapper) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
return bufio.WritePacket(c, p, addr)
|
||||
}
|
||||
|
||||
func (c *connWrapper) Close() error {
|
||||
select {
|
||||
case <-c.done:
|
||||
default:
|
||||
close(c.done)
|
||||
}
|
||||
return c.PacketConn.Close()
|
||||
}
|
161
transport/vlite/server.go
Normal file
161
transport/vlite/server.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
package vlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/mustafaturan/bus"
|
||||
"github.com/xiaokangwang/VLite/interfaces"
|
||||
"github.com/xiaokangwang/VLite/interfaces/ibus"
|
||||
"github.com/xiaokangwang/VLite/transport"
|
||||
sctp_server "github.com/xiaokangwang/VLite/transport/packetsctp/sctprelay"
|
||||
"github.com/xiaokangwang/VLite/transport/packetuni/puniServer"
|
||||
"github.com/xiaokangwang/VLite/transport/udp/udpServer"
|
||||
"github.com/xiaokangwang/VLite/transport/udp/udpuni/udpunis"
|
||||
"github.com/xiaokangwang/VLite/transport/uni/uniserver"
|
||||
"github.com/xiaokangwang/VLite/workers/server"
|
||||
)
|
||||
|
||||
var (
|
||||
_ transport.UnderlayTransportListener = (*Server)(nil)
|
||||
_ adapter.PacketConnectionHandler = (*Server)(nil)
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
ctx context.Context
|
||||
msgbus *bus.Bus
|
||||
transport transport.UnderlayTransportListener
|
||||
access sync.Mutex
|
||||
options option.VLiteInboundOptions
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, options option.VLiteInboundOptions) *Server {
|
||||
server := &Server{
|
||||
ctx: ctx,
|
||||
options: options,
|
||||
msgbus: ibus.NewMessageBus(),
|
||||
}
|
||||
|
||||
server.ctx = context.WithValue(server.ctx, interfaces.ExtraOptionsMessageBus, server.msgbus) //nolint:revive,staticcheck
|
||||
|
||||
if options.ScramblePacket {
|
||||
server.ctx = context.WithValue(server.ctx, interfaces.ExtraOptionsUDPShouldMask, true) //nolint:revive,staticcheck
|
||||
}
|
||||
|
||||
if options.EnableFEC {
|
||||
server.ctx = context.WithValue(server.ctx, interfaces.ExtraOptionsUDPFECEnabled, true) //nolint:revive,staticcheck
|
||||
}
|
||||
|
||||
server.ctx = context.WithValue(server.ctx, interfaces.ExtraOptionsUDPMask, options.Password) //nolint:revive,staticcheck
|
||||
|
||||
if options.HandshakeMaskingPaddingSize != 0 {
|
||||
ctxv := &interfaces.ExtraOptionsUsePacketArmorValue{PacketArmorPaddingTo: options.HandshakeMaskingPaddingSize, UsePacketArmor: true}
|
||||
server.ctx = context.WithValue(server.ctx, interfaces.ExtraOptionsUsePacketArmor, ctxv) //nolint:revive,staticcheck
|
||||
}
|
||||
|
||||
server.transport = server
|
||||
if options.EnableStabilization {
|
||||
server.transport = uniserver.NewUnifiedConnectionTransportHub(server.transport, server.ctx)
|
||||
}
|
||||
if options.EnableStabilization {
|
||||
server.transport = udpunis.NewUdpUniServer(string(server.options.Password), server.ctx, server.transport)
|
||||
}
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
func (s *Server) Connection(conn net.Conn, ctx context.Context) context.Context {
|
||||
S_S2CTraffic := make(chan server.UDPServerTxToClientTraffic, 8) //nolint:revive,stylecheck
|
||||
S_S2CDataTraffic := make(chan server.UDPServerTxToClientDataTraffic, 8) //nolint:revive,stylecheck
|
||||
S_C2STraffic := make(chan server.UDPServerRxFromClientTraffic, 8) //nolint:revive,stylecheck
|
||||
|
||||
S_S2CTraffic2 := make(chan interfaces.TrafficWithChannelTag, 8) //nolint:revive,stylecheck
|
||||
S_S2CDataTraffic2 := make(chan interfaces.TrafficWithChannelTag, 8) //nolint:revive,stylecheck
|
||||
S_C2STraffic2 := make(chan interfaces.TrafficWithChannelTag, 8) //nolint:revive,stylecheck
|
||||
|
||||
go func(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case data := <-S_S2CTraffic:
|
||||
S_S2CTraffic2 <- interfaces.TrafficWithChannelTag(data)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}(ctx)
|
||||
|
||||
go func(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case data := <-S_S2CDataTraffic:
|
||||
S_S2CDataTraffic2 <- interfaces.TrafficWithChannelTag(data)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}(ctx)
|
||||
|
||||
go func(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case data := <-S_C2STraffic2:
|
||||
S_C2STraffic <- server.UDPServerRxFromClientTraffic(data)
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}(ctx)
|
||||
|
||||
if !s.options.EnableStabilization || !s.options.EnableRenegotiation {
|
||||
relay := sctp_server.NewPacketRelayServer(conn, S_S2CTraffic2, S_S2CDataTraffic2, S_C2STraffic2, s, []byte(s.options.Password), ctx)
|
||||
udpserver := server.UDPServer(ctx, S_S2CTraffic, S_S2CDataTraffic, S_C2STraffic, relay)
|
||||
_ = udpserver
|
||||
} else {
|
||||
relay := puniServer.NewPacketUniServer(S_S2CTraffic2, S_S2CDataTraffic2, S_C2STraffic2, s, []byte(s.options.Password), ctx)
|
||||
relay.OnAutoCarrier(conn, ctx)
|
||||
udpserver := server.UDPServer(ctx, S_S2CTraffic, S_S2CDataTraffic, S_C2STraffic, relay)
|
||||
_ = udpserver
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (s *Server) RelayStream(conn io.ReadWriteCloser, ctx context.Context) {
|
||||
}
|
||||
|
||||
func (s *Server) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||
wrapper, done := newConnWrapper(conn)
|
||||
pc := &bufio.BindPacketConn{
|
||||
PacketConn: wrapper,
|
||||
Addr: metadata.Destination,
|
||||
}
|
||||
var initialData [1600]byte
|
||||
c, err := pc.Read(initialData[:])
|
||||
if err != nil {
|
||||
return E.Cause(err, "unable to read initial data")
|
||||
}
|
||||
id, loaded := log.IDFromContext(ctx)
|
||||
if !loaded {
|
||||
id = rand.Uint32()
|
||||
}
|
||||
vconn, connctx := udpServer.PrepareIncomingUDPConnection(pc, s.ctx, initialData[:c], strconv.FormatInt(int64(id), 10))
|
||||
connctx = s.transport.Connection(vconn, connctx)
|
||||
if connctx == nil {
|
||||
return E.New("invalid connection discarded")
|
||||
}
|
||||
select {
|
||||
case <-done:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user