Add vlite inbound

This commit is contained in:
世界 2022-11-17 21:03:44 +08:00
parent 7cb4ded3a7
commit 20a5182aa2
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
8 changed files with 288 additions and 8 deletions

View File

@ -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
View 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
View 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`)
}

View File

@ -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)
}

View File

@ -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"`

View File

@ -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,15 +39,14 @@ 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,
msgbus: ibus.NewMessageBus(),
options: options,
msgbus: ibus.NewMessageBus(),
}
ctx = context.WithValue(ctx, interfaces.ExtraOptionsDisableAutoQuitForClient, true) //nolint:revive,staticcheck
ctx = context.WithValue(ctx, interfaces.ExtraOptionsUDPMask, options.Password) //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
View 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
View 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
}