chore: rebuild relay
This commit is contained in:
parent
f09afc8d8a
commit
ec0136af1b
15 changed files with 296 additions and 246 deletions
|
@ -57,26 +57,26 @@ func (b *Base) DialContext(ctx context.Context, metadata *C.Metadata, opts ...di
|
|||
return nil, errors.New("no support")
|
||||
}
|
||||
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (b *Base) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
return nil, errors.New("no support")
|
||||
}
|
||||
|
||||
// ListenPacketContext implements C.ProxyAdapter
|
||||
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||
return nil, errors.New("no support")
|
||||
}
|
||||
|
||||
// ListenPacketOnPacketConn implements C.ProxyAdapter
|
||||
func (b *Base) ListenPacketOnPacketConn(ctx context.Context, c C.PacketConn, metadata *C.Metadata) (C.PacketConn, error) {
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (b *Base) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
return nil, errors.New("no support")
|
||||
}
|
||||
|
||||
// SupportLPPC implements C.ProxyAdapter
|
||||
func (b *Base) SupportLPPC() bool {
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (b *Base) SupportWithDialer() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||
func (b *Base) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
return nil, errors.New("no support")
|
||||
}
|
||||
|
||||
// SupportUOT implements C.ProxyAdapter
|
||||
func (b *Base) SupportUOT() bool {
|
||||
return false
|
||||
|
|
|
@ -61,7 +61,12 @@ func (h *Http) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
|||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", h.addr, h.Base.DialOptions(opts...)...)
|
||||
return h.DialContextWithDialer(ctx, dialer.Dialer{Options: h.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (h *Http) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", h.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
||||
}
|
||||
|
@ -79,6 +84,11 @@ func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...di
|
|||
return NewConn(c, h), nil
|
||||
}
|
||||
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (h *Http) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
||||
addr := metadata.RemoteAddress()
|
||||
req := &http.Request{
|
||||
|
|
|
@ -84,7 +84,12 @@ func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, e
|
|||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||
return ss.DialContextWithDialer(ctx, dialer.Dialer{Options: ss.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||
}
|
||||
|
@ -100,8 +105,13 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, op
|
|||
|
||||
// ListenPacketContext implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||
return ss.ListenPacketWithDialer(ctx, dialer.Dialer{Options: ss.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
if ss.option.UDPOverTCP {
|
||||
tcpConn, err := ss.DialContext(ctx, metadata, opts...)
|
||||
tcpConn, err := ss.DialContextWithDialer(ctx, dialer, metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -112,7 +122,7 @@ func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Meta
|
|||
return nil, err
|
||||
}
|
||||
|
||||
pc, err := dialer.ListenPacket(ctx, dialer.ParseNetwork("udp", addr.AddrPort().Addr()), "", ss.Base.DialOptions(opts...)...)
|
||||
pc, err := dialer.ListenPacket(ctx, "udp", "", addr.AddrPort())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -120,19 +130,8 @@ func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Meta
|
|||
return newPacketConn(pc, ss), nil
|
||||
}
|
||||
|
||||
// ListenPacketOnPacketConn implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) ListenPacketOnPacketConn(ctx context.Context, c C.PacketConn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ss.addr, ss.prefer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pc := ss.method.DialPacketConn(&bufio.BindPacketConn{PacketConn: c, Addr: addr})
|
||||
return newPacketConn(pc, ss), nil
|
||||
}
|
||||
|
||||
// SupportLPPC implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) SupportLPPC() bool {
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (ss *ShadowSocks) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,12 @@ func (ssr *ShadowSocksR) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn,
|
|||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ssr.addr, ssr.Base.DialOptions(opts...)...)
|
||||
return ssr.DialContextWithDialer(ctx, dialer.Dialer{Options: ssr.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ssr.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
||||
}
|
||||
|
@ -76,12 +81,17 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata,
|
|||
|
||||
// ListenPacketContext implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||
return ssr.ListenPacketWithDialer(ctx, dialer.Dialer{Options: ssr.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ssr.addr, ssr.prefer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pc, err := dialer.ListenPacket(ctx, dialer.ParseNetwork("udp", addr.AddrPort().Addr()), "", ssr.Base.DialOptions(opts...)...)
|
||||
pc, err := dialer.ListenPacket(ctx, "udp", "", addr.AddrPort())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -91,20 +101,8 @@ func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Me
|
|||
return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil
|
||||
}
|
||||
|
||||
// ListenPacketOnPacketConn implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) ListenPacketOnPacketConn(ctx context.Context, c C.PacketConn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ssr.addr, ssr.prefer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pc := ssr.cipher.PacketConn(c)
|
||||
pc = ssr.protocol.PacketConn(pc)
|
||||
return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil
|
||||
}
|
||||
|
||||
// SupportLPPC implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) SupportLPPC() bool {
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (ssr *ShadowSocksR) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,12 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||
return NewConn(c, s), err
|
||||
}
|
||||
|
||||
c, err := dialer.DialContext(ctx, "tcp", s.addr, s.Base.DialOptions(opts...)...)
|
||||
return s.DialContextWithDialer(ctx, dialer.Dialer{Options: s.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (s *Snell) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", s.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
||||
}
|
||||
|
@ -94,7 +99,12 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||
|
||||
// ListenPacketContext implements C.ProxyAdapter
|
||||
func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", s.addr, s.Base.DialOptions(opts...)...)
|
||||
return s.ListenPacketWithDialer(ctx, dialer.Dialer{Options: s.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (s *Snell) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (C.PacketConn, error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", s.addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -110,10 +120,9 @@ func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||
return newPacketConn(pc, s), nil
|
||||
}
|
||||
|
||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||
func (s *Snell) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
pc := snell.PacketConn(c)
|
||||
return newPacketConn(pc, s), nil
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (s *Snell) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// SupportUOT implements C.ProxyAdapter
|
||||
|
|
|
@ -65,7 +65,12 @@ func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
|
|||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||
return ss.DialContextWithDialer(ctx, dialer.Dialer{Options: ss.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||
}
|
||||
|
@ -83,6 +88,11 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ..
|
|||
return NewConn(c, ss), nil
|
||||
}
|
||||
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (ss *Socks5) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ListenPacketContext implements C.ProxyAdapter
|
||||
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||
|
|
|
@ -120,8 +120,12 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
|||
|
||||
return NewConn(c, t), nil
|
||||
}
|
||||
return t.DialContextWithDialer(ctx, dialer.Dialer{Options: t.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
c, err := dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", t.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
}
|
||||
|
@ -152,19 +156,30 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
|||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
} else {
|
||||
c, err = dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
|
||||
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
}
|
||||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
tcpKeepAlive(c)
|
||||
c, err = t.plainStream(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pc := t.instance.PacketConn(c)
|
||||
return newPacketConn(pc, t), err
|
||||
}
|
||||
return t.ListenPacketWithDialer(ctx, dialer.Dialer{Options: t.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", t.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
}
|
||||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
tcpKeepAlive(c)
|
||||
c, err = t.plainStream(c)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||
}
|
||||
|
||||
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
||||
|
@ -176,6 +191,11 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
|||
return newPacketConn(pc, t), err
|
||||
}
|
||||
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (t *Trojan) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||
func (t *Trojan) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
pc := t.instance.PacketConn(c)
|
||||
|
|
|
@ -219,8 +219,12 @@ func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||
|
||||
return NewConn(c, v), nil
|
||||
}
|
||||
return v.DialContextWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (v *Vless) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
|
@ -256,18 +260,36 @@ func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||
}()
|
||||
|
||||
c, err = v.client.StreamConn(c, parseVlessAddr(metadata))
|
||||
} else {
|
||||
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
|
||||
c, err = v.StreamConn(c, metadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new vless client error: %v", err)
|
||||
}
|
||||
|
||||
return v.ListenPacketOnStreamConn(c, metadata)
|
||||
}
|
||||
return v.ListenPacketWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (v *Vless) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
// vless use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
||||
if !metadata.Resolved() {
|
||||
ip, err := resolver.ResolveIP(ctx, metadata.Host)
|
||||
if err != nil {
|
||||
return nil, errors.New("can't resolve ip")
|
||||
}
|
||||
metadata.DstIP = ip
|
||||
}
|
||||
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
|
||||
c, err = v.StreamConn(c, metadata)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new vless client error: %v", err)
|
||||
|
@ -276,6 +298,11 @@ func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||
return v.ListenPacketOnStreamConn(c, metadata)
|
||||
}
|
||||
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (v *Vless) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||
func (v *Vless) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
return newPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
||||
|
|
|
@ -232,8 +232,12 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||
|
||||
return NewConn(c, v), nil
|
||||
}
|
||||
return v.DialContextWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||
// DialContextWithDialer implements C.ProxyAdapter
|
||||
func (v *Vmess) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
|
@ -280,29 +284,47 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||
} else {
|
||||
c, err = v.client.DialPacketConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
|
||||
}
|
||||
} else {
|
||||
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
|
||||
c, err = v.StreamConn(c, metadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new vmess client error: %v", err)
|
||||
}
|
||||
return v.ListenPacketOnStreamConn(c, metadata)
|
||||
}
|
||||
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
defer func() {
|
||||
safeConnClose(c, err)
|
||||
}()
|
||||
|
||||
c, err = v.StreamConn(c, metadata)
|
||||
return v.ListenPacketWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||
}
|
||||
|
||||
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||
func (v *Vmess) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||
// vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
||||
if !metadata.Resolved() {
|
||||
ip, err := resolver.ResolveIP(ctx, metadata.Host)
|
||||
if err != nil {
|
||||
return nil, errors.New("can't resolve ip")
|
||||
}
|
||||
metadata.DstIP = ip
|
||||
}
|
||||
|
||||
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new vmess client error: %v", err)
|
||||
}
|
||||
|
||||
if v.option.PacketAddr {
|
||||
return newPacketConn(&threadSafePacketConn{PacketConn: packetaddr.NewBindConn(c)}, v), nil
|
||||
} else if pc, ok := c.(net.PacketConn); ok {
|
||||
return newPacketConn(&threadSafePacketConn{PacketConn: pc}, v), nil
|
||||
}
|
||||
return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
||||
return v.ListenPacketOnStreamConn(c, metadata)
|
||||
}
|
||||
|
||||
// SupportWithDialer implements C.ProxyAdapter
|
||||
func (v *Vmess) SupportWithDialer() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||
|
|
|
@ -3,10 +3,12 @@ package outboundgroup
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/Dreamacro/clash/adapter/outbound"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/constant/provider"
|
||||
|
@ -16,6 +18,36 @@ type Relay struct {
|
|||
*GroupBase
|
||||
}
|
||||
|
||||
type proxyDialer struct {
|
||||
proxy C.Proxy
|
||||
dialer C.Dialer
|
||||
}
|
||||
|
||||
func (p proxyDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
currentMeta, err := addrToMetadata(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if strings.Contains(network, "udp") { // should not support this operation
|
||||
currentMeta.NetWork = C.UDP
|
||||
pc, err := p.proxy.ListenPacketWithDialer(ctx, p.dialer, currentMeta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return N.NewBindPacketConn(pc, currentMeta.UDPAddr()), nil
|
||||
}
|
||||
return p.proxy.DialContextWithDialer(ctx, p.dialer, currentMeta)
|
||||
}
|
||||
|
||||
func (p proxyDialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) {
|
||||
currentMeta, err := addrToMetadata(rAddrPort.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentMeta.NetWork = C.UDP
|
||||
return p.proxy.ListenPacketWithDialer(ctx, p.dialer, currentMeta)
|
||||
}
|
||||
|
||||
// DialContext implements C.ProxyAdapter
|
||||
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||
proxies, chainProxies := r.proxies(metadata, true)
|
||||
|
@ -26,47 +58,20 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
|||
case 1:
|
||||
return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||
}
|
||||
|
||||
first := proxies[0]
|
||||
var d C.Dialer
|
||||
d = dialer.Dialer{Options: r.Base.DialOptions(opts...)}
|
||||
for _, proxy := range proxies[:len(proxies)-1] {
|
||||
d = proxyDialer{
|
||||
proxy: proxy,
|
||||
dialer: d,
|
||||
}
|
||||
}
|
||||
last := proxies[len(proxies)-1]
|
||||
|
||||
var c net.Conn
|
||||
var currentMeta *C.Metadata
|
||||
var err error
|
||||
|
||||
currentMeta, err = addrToMetadata(proxies[1].Addr())
|
||||
conn, err := last.DialContextWithDialer(ctx, d, metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err = first.DialContext(ctx, currentMeta, r.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
|
||||
first = proxies[1]
|
||||
|
||||
for _, proxy := range proxies[2:] {
|
||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err = first.StreamConn(c, currentMeta)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
|
||||
first = proxy
|
||||
}
|
||||
|
||||
c, err = last.StreamConn(c, metadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
||||
}
|
||||
|
||||
conn := outbound.NewConn(c, last)
|
||||
|
||||
for i := len(chainProxies) - 2; i >= 0; i-- {
|
||||
conn.AppendToChains(chainProxies[i])
|
||||
}
|
||||
|
@ -87,95 +92,18 @@ func (r *Relay) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
|||
return proxies[0].ListenPacketContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||
}
|
||||
|
||||
udtId := -1
|
||||
for i, proxy := range proxies {
|
||||
if !proxy.SupportUDP() {
|
||||
return nil, fmt.Errorf("%s don't support udp", proxy.Name())
|
||||
}
|
||||
if proxy.SupportUOT() {
|
||||
udtId = i // we need the latest id, so don't break
|
||||
var d C.Dialer
|
||||
d = dialer.Dialer{Options: r.Base.DialOptions(opts...)}
|
||||
for _, proxy := range proxies[:len(proxies)-1] {
|
||||
d = proxyDialer{
|
||||
proxy: proxy,
|
||||
dialer: d,
|
||||
}
|
||||
}
|
||||
|
||||
first := proxies[0]
|
||||
last := proxies[len(proxies)-1]
|
||||
|
||||
var pc C.PacketConn
|
||||
var currentMeta *C.Metadata
|
||||
if udtId != -1 {
|
||||
c, err := dialer.DialContext(ctx, "tcp", first.Addr(), r.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
tcpKeepAlive(c)
|
||||
|
||||
for _, proxy := range proxies[1 : udtId+1] {
|
||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err = first.StreamConn(c, currentMeta)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
|
||||
first = proxy
|
||||
}
|
||||
|
||||
if first == last {
|
||||
currentMeta = metadata
|
||||
} else {
|
||||
currentMeta, err = addrToMetadata(proxies[udtId+1].Addr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentMeta.NetWork = C.UDP
|
||||
}
|
||||
c, err = first.StreamConn(c, currentMeta)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
|
||||
pc, err = first.ListenPacketOnStreamConn(c, currentMeta)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
if first == last {
|
||||
return pc, nil
|
||||
}
|
||||
} else {
|
||||
currentMeta, err = addrToMetadata(proxies[1].Addr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentMeta.NetWork = C.UDP
|
||||
pc, err = first.ListenPacketContext(ctx, currentMeta, r.Base.DialOptions(opts...)...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
udtId = 0
|
||||
}
|
||||
|
||||
first = proxies[udtId+1]
|
||||
for _, proxy := range proxies[udtId+2:] {
|
||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentMeta.NetWork = C.UDP
|
||||
|
||||
pc, err = first.ListenPacketOnPacketConn(ctx, pc, currentMeta)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
||||
}
|
||||
|
||||
first = proxy
|
||||
}
|
||||
|
||||
pc, err = last.ListenPacketOnPacketConn(ctx, pc, metadata)
|
||||
pc, err := last.ListenPacketWithDialer(ctx, d, metadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := len(chainProxies) - 2; i >= 0; i-- {
|
||||
|
@ -201,7 +129,7 @@ func (r *Relay) SupportUDP() bool {
|
|||
if proxy.SupportUOT() {
|
||||
return true
|
||||
}
|
||||
if !proxy.SupportLPPC() {
|
||||
if !proxy.SupportWithDialer() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func addrToMetadata(rawAddress string) (addr *C.Metadata, err error) {
|
|||
} else {
|
||||
addr = &C.Metadata{
|
||||
Host: "",
|
||||
DstIP: ip,
|
||||
DstIP: ip.Unmap(),
|
||||
DstPort: port,
|
||||
}
|
||||
}
|
||||
|
|
36
common/net/bind.go
Normal file
36
common/net/bind.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
package net
|
||||
|
||||
import "net"
|
||||
|
||||
type bindPacketConn struct {
|
||||
net.PacketConn
|
||||
rAddr net.Addr
|
||||
}
|
||||
|
||||
func (wpc *bindPacketConn) Read(b []byte) (n int, err error) {
|
||||
n, _, err = wpc.PacketConn.ReadFrom(b)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (wpc *bindPacketConn) Write(b []byte) (n int, err error) {
|
||||
return wpc.PacketConn.WriteTo(b, wpc.rAddr)
|
||||
}
|
||||
|
||||
func (wpc *bindPacketConn) RemoteAddr() net.Addr {
|
||||
return wpc.rAddr
|
||||
}
|
||||
|
||||
func (wpc *bindPacketConn) LocalAddr() net.Addr {
|
||||
if wpc.PacketConn.LocalAddr() == nil {
|
||||
return &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
} else {
|
||||
return wpc.PacketConn.LocalAddr()
|
||||
}
|
||||
}
|
||||
|
||||
func NewBindPacketConn(pc net.PacketConn, rAddr net.Addr) net.Conn {
|
||||
return &bindPacketConn{
|
||||
PacketConn: pc,
|
||||
rAddr: rAddr,
|
||||
}
|
||||
}
|
|
@ -444,3 +444,15 @@ func concurrentIPv6DialContext(ctx context.Context, network, address string, opt
|
|||
|
||||
return concurrentDialContext(ctx, network, ips, port, opt)
|
||||
}
|
||||
|
||||
type Dialer struct {
|
||||
Options []Option
|
||||
}
|
||||
|
||||
func (d Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
return DialContext(ctx, network, address, d.Options...)
|
||||
}
|
||||
|
||||
func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) {
|
||||
return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, d.Options...)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
|
@ -81,6 +82,11 @@ type PacketConn interface {
|
|||
// WriteWithMetadata(p []byte, metadata *Metadata) (n int, err error)
|
||||
}
|
||||
|
||||
type Dialer interface {
|
||||
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||
ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error)
|
||||
}
|
||||
|
||||
type ProxyAdapter interface {
|
||||
Name() string
|
||||
Type() AdapterType
|
||||
|
@ -89,6 +95,7 @@ type ProxyAdapter interface {
|
|||
SupportTFO() bool
|
||||
MarshalJSON() ([]byte, error)
|
||||
|
||||
// Deprecated: use DialContextWithDialer and ListenPacketWithDialer instead.
|
||||
// StreamConn wraps a protocol around net.Conn with Metadata.
|
||||
//
|
||||
// Examples:
|
||||
|
@ -106,10 +113,10 @@ type ProxyAdapter interface {
|
|||
|
||||
// SupportUOT return UDP over TCP support
|
||||
SupportUOT() bool
|
||||
ListenPacketOnStreamConn(c net.Conn, metadata *Metadata) (PacketConn, error)
|
||||
|
||||
SupportLPPC() bool
|
||||
ListenPacketOnPacketConn(ctx context.Context, c PacketConn, metadata *Metadata) (PacketConn, error)
|
||||
SupportWithDialer() bool
|
||||
DialContextWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (Conn, error)
|
||||
ListenPacketWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (PacketConn, error)
|
||||
|
||||
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
||||
Unwrap(metadata *Metadata, touch bool) Proxy
|
||||
|
|
32
dns/util.go
32
dns/util.go
|
@ -11,6 +11,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/common/cache"
|
||||
N "github.com/Dreamacro/clash/common/net"
|
||||
"github.com/Dreamacro/clash/common/nnip"
|
||||
"github.com/Dreamacro/clash/common/picker"
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
|
@ -134,32 +135,6 @@ func msgToDomain(msg *D.Msg) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
type wrapPacketConn struct {
|
||||
net.PacketConn
|
||||
rAddr net.Addr
|
||||
}
|
||||
|
||||
func (wpc *wrapPacketConn) Read(b []byte) (n int, err error) {
|
||||
n, _, err = wpc.PacketConn.ReadFrom(b)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (wpc *wrapPacketConn) Write(b []byte) (n int, err error) {
|
||||
return wpc.PacketConn.WriteTo(b, wpc.rAddr)
|
||||
}
|
||||
|
||||
func (wpc *wrapPacketConn) RemoteAddr() net.Addr {
|
||||
return wpc.rAddr
|
||||
}
|
||||
|
||||
func (wpc *wrapPacketConn) LocalAddr() net.Addr {
|
||||
if wpc.PacketConn.LocalAddr() == nil {
|
||||
return &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||
} else {
|
||||
return wpc.PacketConn.LocalAddr()
|
||||
}
|
||||
}
|
||||
|
||||
type dialHandler func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||
|
||||
func getDialHandler(r *Resolver, proxyAdapter string, opts ...dialer.Option) dialHandler {
|
||||
|
@ -213,10 +188,7 @@ func getDialHandler(r *Resolver, proxyAdapter string, opts ...dialer.Option) dia
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &wrapPacketConn{
|
||||
PacketConn: packetConn,
|
||||
rAddr: metadata.UDPAddr(),
|
||||
}, nil
|
||||
return N.NewBindPacketConn(packetConn, metadata.UDPAddr()), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue