fix: sing listener panic

This commit is contained in:
wwqgtxx 2023-10-11 10:55:12 +08:00
parent 1cf9a55e3e
commit 270a080b55
14 changed files with 91 additions and 67 deletions

View file

@ -4,12 +4,11 @@ import (
"net"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/context"
"github.com/Dreamacro/clash/transport/socks5"
)
// NewHTTP receive normal http request and return HTTPContext
func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Addition) *context.ConnContext {
func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Addition) (net.Conn, *C.Metadata) {
metadata := parseSocksAddr(target)
metadata.NetWork = C.TCP
metadata.Type = C.HTTP
@ -17,5 +16,5 @@ func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Ad
for _, addition := range additions {
addition.Apply(metadata)
}
return context.NewConnContext(conn, metadata)
return conn, metadata
}

View file

@ -5,16 +5,15 @@ import (
"net/http"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/context"
)
// NewHTTPS receive CONNECT request and return ConnContext
func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) *context.ConnContext {
func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) (net.Conn, *C.Metadata) {
metadata := parseHTTPAddr(request)
metadata.Type = C.HTTPS
additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr()))
for _, addition := range additions {
addition.Apply(metadata)
}
return context.NewConnContext(conn, metadata)
return conn, metadata
}

View file

@ -5,19 +5,8 @@ import (
"github.com/Dreamacro/clash/transport/socks5"
)
// PacketAdapter is a UDP Packet adapter for socks/redir/tun
type PacketAdapter struct {
C.UDPPacket
metadata *C.Metadata
}
// Metadata returns destination metadata
func (s *PacketAdapter) Metadata() *C.Metadata {
return s.metadata
}
// NewPacket is PacketAdapter generator
func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions ...Addition) C.PacketAdapter {
func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions ...Addition) (C.UDPPacket, *C.Metadata) {
metadata := parseSocksAddr(target)
metadata.NetWork = C.UDP
metadata.Type = source
@ -29,8 +18,5 @@ func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions
addition.Apply(metadata)
}
return &PacketAdapter{
packet,
metadata,
}
return packet, metadata
}

View file

@ -6,12 +6,11 @@ import (
"strconv"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/context"
"github.com/Dreamacro/clash/transport/socks5"
)
// NewSocket receive TCP inbound and return ConnContext
func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Addition) *context.ConnContext {
func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Addition) (net.Conn, *C.Metadata) {
metadata := parseSocksAddr(target)
metadata.NetWork = C.TCP
metadata.Type = source
@ -20,10 +19,10 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Ad
addition.Apply(metadata)
}
return context.NewConnContext(conn, metadata)
return conn, metadata
}
func NewInner(conn net.Conn, address string) *context.ConnContext {
func NewInner(conn net.Conn, address string) (net.Conn, *C.Metadata) {
metadata := &C.Metadata{}
metadata.NetWork = C.TCP
metadata.Type = C.INNER
@ -40,5 +39,5 @@ func NewInner(conn net.Conn, address string) *context.ConnContext {
}
}
return context.NewConnContext(conn, metadata)
return conn, metadata
}

View file

@ -252,6 +252,23 @@ type PacketAdapter interface {
Metadata() *Metadata
}
type packetAdapter struct {
UDPPacket
metadata *Metadata
}
// Metadata returns destination metadata
func (s *packetAdapter) Metadata() *Metadata {
return s.metadata
}
func NewPacketAdapter(packet UDPPacket, metadata *Metadata) PacketAdapter {
return &packetAdapter{
packet,
metadata,
}
}
type WriteBack interface {
WriteBack(b []byte, addr net.Addr) (n int, err error)
}

View file

@ -1,10 +1,12 @@
package constant
import "net"
type Tunnel interface {
// HandleTCPConn will handle a tcp connection blocking
HandleTCPConn(connCtx ConnContext)
HandleTCPConn(conn net.Conn, metadata *Metadata)
// HandleUDPPacket will handle a udp packet nonblocking
HandleUDPPacket(packet PacketAdapter)
HandleUDPPacket(packet UDPPacket, metadata *Metadata)
// NatTable return nat table
NatTable() NatTable
}

View file

@ -20,7 +20,6 @@ func HandleTcp(address string) (conn net.Conn, err error) {
}
// executor Parsed
conn1, conn2 := net.Pipe()
context := inbound.NewInner(conn2, address)
go tunnel.HandleTCPConn(context)
go tunnel.HandleTCPConn(inbound.NewInner(conn2, address))
return conn1, nil
}

View file

@ -67,7 +67,7 @@ func handleSocksUDP(pc net.PacketConn, tunnel C.Tunnel, buf []byte, put func(),
}
return
}
target := socks5.ParseAddr(tgtAddr.String())
target := tgtAddr
payload := buf[len(tgtAddr):]
packet := &packet{

View file

@ -26,7 +26,7 @@ func getAdditions(ctx context.Context) []inbound.Addition {
return nil
}
func combineAdditions(ctx context.Context, additions []inbound.Addition) []inbound.Addition {
func combineAdditions(ctx context.Context, additions []inbound.Addition, extraAdditions ...inbound.Addition) []inbound.Addition {
additionsCloned := false
if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 {
additions = slices.Clone(additions)
@ -40,5 +40,12 @@ func combineAdditions(ctx context.Context, additions []inbound.Addition) []inbou
}
additions = append(additions, inbound.WithInUser(user))
}
if len(extraAdditions) > 0 {
if !additionsCloned {
additions = slices.Clone(additions)
additionsCloned = true
}
additions = append(additions, extraAdditions...)
}
return additions
}

View file

@ -12,7 +12,6 @@ import (
N "github.com/Dreamacro/clash/common/net"
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/log"
"github.com/Dreamacro/clash/transport/socks5"
vmess "github.com/metacubex/sing-vmess"
mux "github.com/sagernet/sing-mux"
@ -85,15 +84,26 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta
if h.IsSpecialFqdn(metadata.Destination.Fqdn) {
return h.ParseSpecialFqdn(ctx, conn, metadata)
}
target := socks5.ParseAddr(metadata.Destination.String())
if deadline.NeedAdditionalReadDeadline(conn) {
conn = N.NewDeadlineConn(conn) // conn from sing should check NeedAdditionalReadDeadline
}
connCtx := inbound.NewSocket(target, conn, h.Type, combineAdditions(ctx, h.Additions)...)
inbound.WithSrcAddr(metadata.Source.TCPAddr()).Apply(connCtx.Metadata()) // set srcAddr from sing's metadata
h.Tunnel.HandleTCPConn(connCtx) // this goroutine must exit after conn unused
cMetadata := &C.Metadata{
NetWork: C.TCP,
Type: h.Type,
Host: metadata.Destination.Fqdn,
DstIP: metadata.Destination.Addr,
DstPort: metadata.Destination.Port,
SrcIP: metadata.Source.Addr,
SrcPort: metadata.Source.Port,
}
additions := combineAdditions(ctx, h.Additions, inbound.WithInAddr(conn.LocalAddr()))
for _, addition := range additions {
addition.Apply(cMetadata)
}
h.Tunnel.HandleTCPConn(conn, cMetadata) // this goroutine must exit after conn unused
return nil
}
@ -138,8 +148,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
}
return err
}
target := socks5.ParseAddr(dest.String())
packet := &packet{
cPacket := &packet{
conn: &conn2,
mutex: &mutex,
rAddr: metadata.Source.UDPAddr(),
@ -147,7 +156,21 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.
buff: buff,
}
h.Tunnel.HandleUDPPacket(inbound.NewPacket(target, packet, h.Type, combineAdditions(ctx, h.Additions)...))
cMetadata := &C.Metadata{
NetWork: C.UDP,
Type: h.Type,
Host: dest.Fqdn,
DstIP: dest.Addr,
DstPort: dest.Port,
SrcIP: metadata.Source.Addr,
SrcPort: metadata.Source.Port,
}
additions := combineAdditions(ctx, h.Additions, inbound.WithInAddr(conn.LocalAddr()))
for _, addition := range additions {
addition.Apply(cMetadata)
}
h.Tunnel.HandleUDPPacket(cPacket, cMetadata)
}
return nil
}
@ -215,11 +238,3 @@ func (c *packet) Drop() {
func (c *packet) InAddr() net.Addr {
return c.lAddr
}
func (c *packet) SetNatTable(natTable C.NatTable) {
// no need
}
func (c *packet) SetUdpInChan(in chan<- C.PacketAdapter) {
// no need
}

View file

@ -94,19 +94,18 @@ func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) (
newAdditions = slices.Clone(additions)
newAdditions = append(newAdditions, _additions...)
}
connCtx := inbound.NewSocket(addr, conn, C.TUIC, newAdditions...)
metadata := sing.ConvertMetadata(connCtx.Metadata())
if h.IsSpecialFqdn(metadata.Destination.Fqdn) {
conn, metadata := inbound.NewSocket(addr, conn, C.TUIC, newAdditions...)
if h.IsSpecialFqdn(metadata.Host) {
go func() { // ParseSpecialFqdn will block, so open a new goroutine
_ = h.ParseSpecialFqdn(
sing.WithAdditions(context.Background(), newAdditions...),
conn,
metadata,
sing.ConvertMetadata(metadata),
)
}()
return nil
}
go tunnel.HandleTCPConn(connCtx)
go tunnel.HandleTCPConn(conn, metadata)
return nil
}
handleUdpFn := func(addr socks5.Addr, packet C.UDPPacket, _additions ...inbound.Addition) error {

View file

@ -36,9 +36,9 @@ func (l *Listener) Close() error {
func (l *Listener) handleTCP(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) {
N.TCPKeepAlive(conn)
ctx := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)
ctx.Metadata().SpecialProxy = l.proxy
tunnel.HandleTCPConn(ctx)
conn, metadata := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...)
metadata.SpecialProxy = l.proxy
tunnel.HandleTCPConn(conn, metadata)
}
func New(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) {

View file

@ -70,13 +70,13 @@ func NewUDP(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Ad
}
func (l *PacketConn) handleUDP(pc net.PacketConn, tunnel C.Tunnel, buf []byte, addr net.Addr, additions ...inbound.Addition) {
packet := &packet{
cPacket := &packet{
pc: pc,
rAddr: addr,
payload: buf,
}
ctx := inbound.NewPacket(l.target, packet, C.TUNNEL, additions...)
ctx.Metadata().SpecialProxy = l.proxy
tunnel.HandleUDPPacket(ctx)
packet, metadata := inbound.NewPacket(l.target, cPacket, C.TUNNEL, additions...)
metadata.SpecialProxy = l.proxy
tunnel.HandleUDPPacket(packet, metadata)
}

View file

@ -53,13 +53,15 @@ type tunnel struct{}
var Tunnel C.Tunnel = tunnel{}
func (t tunnel) HandleTCPConn(connCtx C.ConnContext) {
func (t tunnel) HandleTCPConn(conn net.Conn, metadata *C.Metadata) {
connCtx := icontext.NewConnContext(conn, metadata)
handleTCPConn(connCtx)
}
func (t tunnel) HandleUDPPacket(packet C.PacketAdapter) {
func (t tunnel) HandleUDPPacket(packet C.UDPPacket, metadata *C.Metadata) {
packetAdapter := C.NewPacketAdapter(packet, metadata)
select {
case udpQueue <- packet:
case udpQueue <- packetAdapter:
default:
}
}
@ -274,7 +276,7 @@ func preHandleMetadata(metadata *C.Metadata) error {
return nil
}
func resolveMetadata(ctx C.PlainContext, metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) {
func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) {
if metadata.SpecialProxy != "" {
var exist bool
proxy, exist = proxies[metadata.SpecialProxy]
@ -369,7 +371,7 @@ func handleUDPConn(packet C.PacketAdapter) {
}()
pCtx := icontext.NewPacketConnContext(metadata)
proxy, rule, err := resolveMetadata(pCtx, metadata)
proxy, rule, err := resolveMetadata(metadata)
if err != nil {
log.Warnln("[UDP] Parse metadata failed: %s", err.Error())
return
@ -477,7 +479,7 @@ func handleTCPConn(connCtx C.ConnContext) {
}()
}
proxy, rule, err := resolveMetadata(connCtx, metadata)
proxy, rule, err := resolveMetadata(metadata)
if err != nil {
log.Warnln("[Metadata] parse failed: %s", err.Error())
return