mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-07-23 15:53:28 +03:00
Refactor TrustTunnel
This commit is contained in:
@@ -16,9 +16,9 @@ import (
|
||||
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
"github.com/sagernet/sing/common/ntp"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
@@ -42,9 +42,8 @@ type Dialer interface {
|
||||
}
|
||||
|
||||
type ClientOptions struct {
|
||||
TLSDialer tls.Dialer
|
||||
QUICDialer N.Dialer
|
||||
QUICTLSConfig tls.Config
|
||||
Dialer N.Dialer
|
||||
TLSConfig tls.Config
|
||||
Server M.Socksaddr
|
||||
Username string
|
||||
Password string
|
||||
@@ -87,17 +86,20 @@ func NewClient(ctx context.Context, options ClientOptions) (*Client, error) {
|
||||
cancel()
|
||||
return nil, err
|
||||
}
|
||||
if len(options.TLSConfig.NextProtos()) == 0 {
|
||||
options.TLSConfig.SetNextProtos([]string{"h3"})
|
||||
}
|
||||
client.roundTripper = &http3.Transport{
|
||||
QUICConfig: &quic.Config{
|
||||
MaxIdleTimeout: DefaultSessionTimeout * 2,
|
||||
KeepAlivePeriod: DefaultHealthCheckTimeout,
|
||||
},
|
||||
Dial: func(ctx context.Context, addr string, tlsCfg *stdtls.Config, cfg *quic.Config) (*quic.Conn, error) {
|
||||
udpConn, err := options.QUICDialer.DialContext(ctx, N.NetworkUDP, client.server)
|
||||
udpConn, err := options.Dialer.DialContext(ctx, N.NetworkUDP, client.server)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conn, err := qtls.DialEarly(ctx, bufio.NewUnbindPacketConn(udpConn), udpConn.RemoteAddr(), options.QUICTLSConfig, cfg)
|
||||
conn, err := qtls.DialEarly(ctx, bufio.NewUnbindPacketConn(udpConn), udpConn.RemoteAddr(), options.TLSConfig, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -106,9 +108,13 @@ func NewClient(ctx context.Context, options ClientOptions) (*Client, error) {
|
||||
},
|
||||
}
|
||||
} else {
|
||||
if len(options.TLSConfig.NextProtos()) == 0 {
|
||||
options.TLSConfig.SetNextProtos([]string{http2.NextProtoTLS})
|
||||
}
|
||||
tlsDialer := tls.NewDialer(options.Dialer, options.TLSConfig)
|
||||
client.roundTripper = &http2.Transport{
|
||||
DialTLSContext: func(ctx context.Context, network, addr string, _ *stdtls.Config) (net.Conn, error) {
|
||||
return options.TLSDialer.DialContext(ctx, network, client.server)
|
||||
return tlsDialer.DialContext(ctx, network, client.server)
|
||||
},
|
||||
AllowHTTP: true,
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
package trusttunnel
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net/netip"
|
||||
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
)
|
||||
|
||||
type IcmpConn struct {
|
||||
httpConn
|
||||
}
|
||||
|
||||
func (i *IcmpConn) WritePing(id uint16, destination netip.Addr, sequenceNumber uint16, ttl uint8, size uint16) error {
|
||||
request := buf.NewSize(2 + 16 + 2 + 1 + 2)
|
||||
defer request.Release()
|
||||
must(binary.Write(request, binary.BigEndian, id))
|
||||
destinationAddress := buildPaddingIP(destination)
|
||||
must1(request.Write(destinationAddress[:]))
|
||||
must(binary.Write(request, binary.BigEndian, sequenceNumber))
|
||||
must(binary.Write(request, binary.BigEndian, ttl))
|
||||
must(binary.Write(request, binary.BigEndian, size))
|
||||
_, err := i.writeFlush(request.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *IcmpConn) ReadPing() (id uint16, sourceAddress netip.Addr, icmpType uint8, code uint8, sequenceNumber uint16, err error) {
|
||||
err = i.waitCreated()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
response := buf.NewSize(2 + 16 + 1 + 1 + 2)
|
||||
defer response.Release()
|
||||
_, err = response.ReadFullFrom(i.body, response.FreeLen())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
must(binary.Read(response, binary.BigEndian, &id))
|
||||
var sourceAddressBuffer [16]byte
|
||||
must1(response.Read(sourceAddressBuffer[:]))
|
||||
sourceAddress = parse16BytesIP(sourceAddressBuffer)
|
||||
must(binary.Read(response, binary.BigEndian, &icmpType))
|
||||
must(binary.Read(response, binary.BigEndian, &code))
|
||||
must(binary.Read(response, binary.BigEndian, &sequenceNumber))
|
||||
return
|
||||
}
|
||||
|
||||
func (i *IcmpConn) Close() error {
|
||||
return i.httpConn.Close()
|
||||
}
|
||||
|
||||
func must(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func must1[T any](_ T, err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,15 @@
|
||||
package trusttunnel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
"github.com/sagernet/quic-go/congestion"
|
||||
"github.com/sagernet/quic-go/http3"
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
qtls "github.com/sagernet/sing-quic"
|
||||
"github.com/sagernet/sing-quic/congestion_bbr1"
|
||||
"github.com/sagernet/sing-quic/congestion_bbr2"
|
||||
congestion_meta1 "github.com/sagernet/sing-quic/congestion_meta1"
|
||||
congestion_meta2 "github.com/sagernet/sing-quic/congestion_meta2"
|
||||
"github.com/sagernet/sing/common/ntp"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func NewCongestionControl(name string, cwnd int, bbrProfile string, timeFunc func() time.Time) (func(conn *quic.Conn) congestion.CongestionControl, error) {
|
||||
@@ -82,62 +75,3 @@ func NewCongestionControl(name string, cwnd int, bbrProfile string, timeFunc fun
|
||||
return nil, E.New("unknown congestion control: ", name)
|
||||
}
|
||||
}
|
||||
|
||||
type QUICService struct {
|
||||
service *Service
|
||||
h3Server *http3.Server
|
||||
udpConn net.PacketConn
|
||||
congestionControl string
|
||||
cwnd int
|
||||
bbrProfile string
|
||||
}
|
||||
|
||||
func NewQUICService(service *Service, congestionControl string, cwnd int, bbrProfile string) *QUICService {
|
||||
return &QUICService{
|
||||
service: service,
|
||||
congestionControl: congestionControl,
|
||||
cwnd: cwnd,
|
||||
bbrProfile: bbrProfile,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *QUICService) Start(ctx context.Context, udpConn net.PacketConn, tlsConfig tls.ServerConfig) error {
|
||||
s.udpConn = udpConn
|
||||
congestionControlFactory, err := NewCongestionControl(s.congestionControl, s.cwnd, s.bbrProfile, ntp.TimeFuncFromContext(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.h3Server = &http3.Server{
|
||||
Handler: s.service,
|
||||
ConnContext: func(ctx context.Context, conn *quic.Conn) context.Context {
|
||||
conn.SetCongestionControl(congestionControlFactory(conn))
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
if err := qtls.ConfigureHTTP3(tlsConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
quicListener, err := qtls.ListenEarly(udpConn, tlsConfig, &quic.Config{
|
||||
MaxIdleTimeout: DefaultSessionTimeout * 2,
|
||||
MaxIncomingStreams: 1 << 60,
|
||||
Allow0RTT: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
_ = s.h3Server.ServeListener(quicListener)
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *QUICService) Close() error {
|
||||
var errs []error
|
||||
if s.h3Server != nil {
|
||||
errs = append(errs, s.h3Server.Close())
|
||||
}
|
||||
if s.udpConn != nil {
|
||||
errs = append(errs, s.udpConn.Close())
|
||||
}
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user