mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-06-25 20:03:12 +03:00
Improve read wait interface &
Refactor Authenticator interface to struct & Update smux & Update gVisor to 20231204.0 & Update wireguard-go & Add GSO support for TUN/WireGuard
This commit is contained in:
@@ -17,16 +17,16 @@ func (c *NATPacketConn) CreatePacketReadWaiter() (N.PacketReadWaiter, bool) {
|
||||
|
||||
type waitNATPacketConn struct {
|
||||
*NATPacketConn
|
||||
waiter N.PacketReadWaiter
|
||||
readWaiter N.PacketReadWaiter
|
||||
}
|
||||
|
||||
func (c *waitNATPacketConn) InitializeReadWaiter(newBuffer func() *buf.Buffer) {
|
||||
c.waiter.InitializeReadWaiter(newBuffer)
|
||||
func (c *waitNATPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||
return c.readWaiter.InitializeReadWaiter(options)
|
||||
}
|
||||
|
||||
func (c *waitNATPacketConn) WaitReadPacket() (destination M.Socksaddr, err error) {
|
||||
destination, err = c.waiter.WaitReadPacket()
|
||||
if socksaddrWithoutPort(destination) == c.origin {
|
||||
func (c *waitNATPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||
buffer, destination, err = c.readWaiter.WaitReadPacket()
|
||||
if err == nil && socksaddrWithoutPort(destination) == c.origin {
|
||||
destination = M.Socksaddr{
|
||||
Addr: c.destination.Addr,
|
||||
Fqdn: c.destination.Fqdn,
|
||||
|
||||
@@ -53,7 +53,7 @@ func newMuxConnection0(ctx context.Context, stream net.Conn, metadata M.Metadata
|
||||
case CommandTCP:
|
||||
return handler.NewConnection(ctx, stream, metadata)
|
||||
case CommandUDP:
|
||||
return handler.NewPacketConnection(ctx, &PacketConn{stream}, metadata)
|
||||
return handler.NewPacketConnection(ctx, &PacketConn{Conn: stream}, metadata)
|
||||
default:
|
||||
return E.New("unknown command ", command)
|
||||
}
|
||||
|
||||
@@ -85,9 +85,10 @@ func (c *ClientConn) Upstream() any {
|
||||
|
||||
type ClientPacketConn struct {
|
||||
net.Conn
|
||||
access sync.Mutex
|
||||
key [KeyLength]byte
|
||||
headerWritten bool
|
||||
access sync.Mutex
|
||||
key [KeyLength]byte
|
||||
headerWritten bool
|
||||
readWaitOptions N.ReadWaitOptions
|
||||
}
|
||||
|
||||
func NewClientPacketConn(conn net.Conn, key [KeyLength]byte) *ClientPacketConn {
|
||||
|
||||
45
transport/trojan/protocol_wait.go
Normal file
45
transport/trojan/protocol_wait.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package trojan
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
)
|
||||
|
||||
var _ N.PacketReadWaiter = (*ClientPacketConn)(nil)
|
||||
|
||||
func (c *ClientPacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||
c.readWaitOptions = options
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *ClientPacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||
destination, err = M.SocksaddrSerializer.ReadAddrPort(c.Conn)
|
||||
if err != nil {
|
||||
return nil, M.Socksaddr{}, E.Cause(err, "read destination")
|
||||
}
|
||||
|
||||
var length uint16
|
||||
err = binary.Read(c.Conn, binary.BigEndian, &length)
|
||||
if err != nil {
|
||||
return nil, M.Socksaddr{}, E.Cause(err, "read chunk length")
|
||||
}
|
||||
|
||||
err = rw.SkipN(c.Conn, 2)
|
||||
if err != nil {
|
||||
return nil, M.Socksaddr{}, E.Cause(err, "skip crlf")
|
||||
}
|
||||
|
||||
buffer = c.readWaitOptions.NewPacketBuffer()
|
||||
_, err = buffer.ReadFullFrom(c.Conn, int(length))
|
||||
if err != nil {
|
||||
buffer.Release()
|
||||
return
|
||||
}
|
||||
c.readWaitOptions.PostReturn(buffer)
|
||||
return
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func (s *Service[K]) NewConnection(ctx context.Context, conn net.Conn, metadata
|
||||
case CommandTCP:
|
||||
return s.handler.NewConnection(ctx, conn, metadata)
|
||||
case CommandUDP:
|
||||
return s.handler.NewPacketConnection(ctx, &PacketConn{conn}, metadata)
|
||||
return s.handler.NewPacketConnection(ctx, &PacketConn{Conn: conn}, metadata)
|
||||
// case CommandMux:
|
||||
default:
|
||||
return HandleMuxConnection(ctx, conn, metadata, s.handler)
|
||||
@@ -122,6 +122,7 @@ func (s *Service[K]) fallback(ctx context.Context, conn net.Conn, metadata M.Met
|
||||
|
||||
type PacketConn struct {
|
||||
net.Conn
|
||||
readWaitOptions N.ReadWaitOptions
|
||||
}
|
||||
|
||||
func (c *PacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
|
||||
|
||||
45
transport/trojan/service_wait.go
Normal file
45
transport/trojan/service_wait.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package trojan
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
)
|
||||
|
||||
var _ N.PacketReadWaiter = (*PacketConn)(nil)
|
||||
|
||||
func (c *PacketConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy bool) {
|
||||
c.readWaitOptions = options
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *PacketConn) WaitReadPacket() (buffer *buf.Buffer, destination M.Socksaddr, err error) {
|
||||
destination, err = M.SocksaddrSerializer.ReadAddrPort(c.Conn)
|
||||
if err != nil {
|
||||
return nil, M.Socksaddr{}, E.Cause(err, "read destination")
|
||||
}
|
||||
|
||||
var length uint16
|
||||
err = binary.Read(c.Conn, binary.BigEndian, &length)
|
||||
if err != nil {
|
||||
return nil, M.Socksaddr{}, E.Cause(err, "read chunk length")
|
||||
}
|
||||
|
||||
err = rw.SkipN(c.Conn, 2)
|
||||
if err != nil {
|
||||
return nil, M.Socksaddr{}, E.Cause(err, "skip crlf")
|
||||
}
|
||||
|
||||
buffer = c.readWaitOptions.NewPacketBuffer()
|
||||
_, err = buffer.ReadFullFrom(c.Conn, int(length))
|
||||
if err != nil {
|
||||
buffer.Release()
|
||||
return
|
||||
}
|
||||
c.readWaitOptions.PostReturn(buffer)
|
||||
return
|
||||
}
|
||||
@@ -76,11 +76,8 @@ func (c *ClientBind) connect() (*wireConn, error) {
|
||||
return nil, err
|
||||
}
|
||||
c.conn = &wireConn{
|
||||
PacketConn: &bufio.UnbindPacketConn{
|
||||
ExtendedConn: bufio.NewExtendedConn(udpConn),
|
||||
Addr: c.connectAddr,
|
||||
},
|
||||
done: make(chan struct{}),
|
||||
PacketConn: bufio.NewUnbindPacketConn(udpConn),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
} else {
|
||||
udpConn, err := c.dialer.ListenPacket(c.ctx, M.Socksaddr{Addr: netip.IPv4Unspecified()})
|
||||
|
||||
@@ -2,6 +2,7 @@ package wireguard
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -19,16 +20,17 @@ import (
|
||||
var _ Device = (*SystemDevice)(nil)
|
||||
|
||||
type SystemDevice struct {
|
||||
dialer N.Dialer
|
||||
device tun.Tun
|
||||
name string
|
||||
mtu int
|
||||
events chan wgTun.Event
|
||||
addr4 netip.Addr
|
||||
addr6 netip.Addr
|
||||
dialer N.Dialer
|
||||
device tun.Tun
|
||||
frontHeadroom int
|
||||
name string
|
||||
mtu int
|
||||
events chan wgTun.Event
|
||||
addr4 netip.Addr
|
||||
addr6 netip.Addr
|
||||
}
|
||||
|
||||
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32) (*SystemDevice, error) {
|
||||
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32, gso bool, gsoMaxsize uint32) (*SystemDevice, error) {
|
||||
var inet4Addresses []netip.Prefix
|
||||
var inet6Addresses []netip.Prefix
|
||||
for _, prefixes := range localPrefixes {
|
||||
@@ -41,11 +43,16 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
||||
if interfaceName == "" {
|
||||
interfaceName = tun.CalculateInterfaceName("wg")
|
||||
}
|
||||
if gsoMaxsize == 0 {
|
||||
gsoMaxsize = 65536
|
||||
}
|
||||
tunInterface, err := tun.New(tun.Options{
|
||||
Name: interfaceName,
|
||||
Inet4Address: inet4Addresses,
|
||||
Inet6Address: inet6Addresses,
|
||||
MTU: mtu,
|
||||
GSO: gso,
|
||||
GSOMaxSize: gsoMaxsize,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -62,12 +69,13 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
||||
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
|
||||
BindInterface: interfaceName,
|
||||
})),
|
||||
device: tunInterface,
|
||||
name: interfaceName,
|
||||
mtu: int(mtu),
|
||||
events: make(chan wgTun.Event),
|
||||
addr4: inet4Address,
|
||||
addr6: inet6Address,
|
||||
device: tunInterface,
|
||||
frontHeadroom: tunInterface.FrontHeadroom(),
|
||||
name: interfaceName,
|
||||
mtu: int(mtu),
|
||||
events: make(chan wgTun.Event),
|
||||
addr4: inet4Address,
|
||||
addr6: inet6Address,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -97,16 +105,18 @@ func (w *SystemDevice) File() *os.File {
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Read(bufs [][]byte, sizes []int, offset int) (count int, err error) {
|
||||
sizes[0], err = w.device.Read(bufs[0][offset-tun.PacketOffset:])
|
||||
sizes[0], err = w.device.Read(bufs[0][offset-w.frontHeadroom:])
|
||||
if err == nil {
|
||||
count = 1
|
||||
} else if errors.Is(err, tun.ErrTooManySegments) {
|
||||
err = wgTun.ErrTooManySegments
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Write(bufs [][]byte, offset int) (count int, err error) {
|
||||
for _, b := range bufs {
|
||||
_, err = w.device.Write(b[offset:])
|
||||
_, err = w.device.Write(b[offset-w.frontHeadroom:])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user