Files
shater/include/quic_stub.go
T
Leadaxe 0f41d00ac6 feat(masque): SPEC 021 — MASQUE CONNECT-IP outbound (Cloudflare WARP)
CONNECT-IP (RFC 9484) outbound tunnelling whole IP packets over HTTP/3 and
HTTP/2, targeting Cloudflare WARP. One `type: masque` outbound with a
`profile` field (cloudflare default | standard) and `network` (h3 | h2).

- transport/masque/connectip: vendored connect-ip-go (client subset) ported
  onto sagernet/quic-go — no second quic-go, no external dependency.
- transport/masque: cloudflare/standard profiles (ECDSA pubkey pinning), h3
  ConnectTunnel (Extended CONNECT cf-connect-ip + advertiseDefaultRoute), and
  h2 capsule-DATAGRAM over stdlib net/http (no http fork needed).
- protocol/masque: adapter.Outbound reusing transport/wireguard gVisor
  stackDevice via NewDevice(System:false); lazy tunnel + two IP pumps;
  DialContext/ListenPacket/Close.
- constant/option/include wiring (with_quic + with_gvisor); graceful
  ErrGVisorNotIncluded without gvisor.

Key material (ECDSA priv/pub, ip/ipv6) is taken ready from config — WARP
device registration is done client-side (Dart), out of core scope.

Unit-tested (profiles, TLS pinning, EC key round-trip, capsule round-trip,
IPv4 checksum vector, prefix parsing, config decode via registry). NOT yet
device-verified against live WARP (needs real key material).

Refs: SPEC 021, SagerNet/sing-box#4000
2026-07-02 00:24:00 +03:00

82 lines
4.3 KiB
Go

//go:build !with_quic
package include
import (
"context"
"io"
"net/http"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/inbound"
"github.com/sagernet/sing-box/adapter/outbound"
"github.com/sagernet/sing-box/adapter/service"
"github.com/sagernet/sing-box/common/listener"
"github.com/sagernet/sing-box/common/tls"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/protocol/naive"
"github.com/sagernet/sing-box/transport/v2ray"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
func init() {
v2ray.RegisterQUICConstructor(
func(ctx context.Context, logger logger.ContextLogger, options option.V2RayQUICOptions, tlsConfig tls.ServerConfig, handler adapter.V2RayServerTransportHandler) (adapter.V2RayServerTransport, error) {
return nil, C.ErrQUICNotIncluded
},
func(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, options option.V2RayQUICOptions, tlsConfig tls.Config) (adapter.V2RayClientTransport, error) {
return nil, C.ErrQUICNotIncluded
},
)
}
func registerQUICInbounds(registry *inbound.Registry) {
inbound.Register[option.HysteriaInboundOptions](registry, C.TypeHysteria, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaInboundOptions) (adapter.Inbound, error) {
return nil, C.ErrQUICNotIncluded
})
inbound.Register[option.TUICInboundOptions](registry, C.TypeTUIC, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TUICInboundOptions) (adapter.Inbound, error) {
return nil, C.ErrQUICNotIncluded
})
inbound.Register[option.Hysteria2InboundOptions](registry, C.TypeHysteria2, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2InboundOptions) (adapter.Inbound, error) {
return nil, C.ErrQUICNotIncluded
})
naive.ConfigureHTTP3ListenerFunc = func(ctx context.Context, logger logger.Logger, listener *listener.Listener, handler http.Handler, tlsConfig tls.ServerConfig, options option.NaiveInboundOptions) (io.Closer, error) {
return nil, C.ErrQUICNotIncluded
}
}
func registerQUICOutbounds(registry *outbound.Registry) {
outbound.Register[option.HysteriaOutboundOptions](registry, C.TypeHysteria, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaOutboundOptions) (adapter.Outbound, error) {
return nil, C.ErrQUICNotIncluded
})
outbound.Register[option.TUICOutboundOptions](registry, C.TypeTUIC, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TUICOutboundOptions) (adapter.Outbound, error) {
return nil, C.ErrQUICNotIncluded
})
outbound.Register[option.Hysteria2OutboundOptions](registry, C.TypeHysteria2, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Hysteria2OutboundOptions) (adapter.Outbound, error) {
return nil, C.ErrQUICNotIncluded
})
outbound.Register[option.MASQUEOutboundOptions](registry, C.TypeMASQUE, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.MASQUEOutboundOptions) (adapter.Outbound, error) {
return nil, C.ErrQUICNotIncluded
})
}
func registerQUICTransports(registry *dns.TransportRegistry) {
dns.RegisterTransport[option.RemoteTLSDNSServerOptions](registry, C.DNSTypeQUIC, func(ctx context.Context, logger log.ContextLogger, tag string, options option.RemoteTLSDNSServerOptions) (adapter.DNSTransport, error) {
return nil, C.ErrQUICNotIncluded
})
dns.RegisterTransport[option.RemoteHTTPSDNSServerOptions](registry, C.DNSTypeHTTP3, func(ctx context.Context, logger log.ContextLogger, tag string, options option.RemoteHTTPSDNSServerOptions) (adapter.DNSTransport, error) {
return nil, C.ErrQUICNotIncluded
})
}
func registerQUICServices(registry *service.Registry) {
service.Register[option.HysteriaRealmServiceOptions](registry, C.TypeHysteriaRealm, func(ctx context.Context, logger log.ContextLogger, tag string, options option.HysteriaRealmServiceOptions) (adapter.Service, error) {
return nil, C.ErrQUICNotIncluded
})
}