feat: Expose remote destination (udp proxy maybe domain of node)

This commit is contained in:
Skyxim 2022-05-04 16:57:08 +08:00
parent bdfa16ca6f
commit fb58595d44
9 changed files with 66 additions and 18 deletions

View file

@ -13,8 +13,6 @@ import (
"github.com/Dreamacro/clash/transport/gun"
"github.com/Dreamacro/clash/transport/trojan"
"github.com/Dreamacro/clash/transport/vless"
"golang.org/x/net/http2"
)
type Trojan struct {
@ -25,7 +23,7 @@ type Trojan struct {
// for gun mux
gunTLSConfig *tls.Config
gunConfig *gun.Config
transport *http2.Transport
transport *gun.TransportWrap
}
type TrojanOption struct {

View file

@ -18,8 +18,6 @@ import (
"github.com/Dreamacro/clash/transport/gun"
"github.com/Dreamacro/clash/transport/vless"
"github.com/Dreamacro/clash/transport/vmess"
"golang.org/x/net/http2"
)
const (
@ -35,7 +33,7 @@ type Vless struct {
// for gun mux
gunTLSConfig *tls.Config
gunConfig *gun.Config
transport *http2.Transport
transport *gun.TransportWrap
}
type VlessOption struct {

View file

@ -15,8 +15,6 @@ import (
C "github.com/Dreamacro/clash/constant"
"github.com/Dreamacro/clash/transport/gun"
"github.com/Dreamacro/clash/transport/vmess"
"golang.org/x/net/http2"
)
type Vmess struct {
@ -27,7 +25,7 @@ type Vmess struct {
// for gun mux
gunTLSConfig *tls.Config
gunConfig *gun.Config
transport *http2.Transport
transport *gun.TransportWrap
}
type VmessOption struct {

View file

@ -170,6 +170,11 @@ func (r *Relay) proxies(metadata *C.Metadata, touch bool) ([]C.Proxy, []C.Proxy)
return targetProxies, chainProxies
}
func (r *Relay) Addr() string {
proxies, _ := r.proxies(nil, true)
return proxies[len(proxies)-1].Addr()
}
func NewRelay(option *GroupCommonOption, providers []provider.ProxyProvider) *Relay {
return &Relay{
GroupBase: NewGroupBase(GroupBaseOption{

View file

@ -86,8 +86,12 @@ type Metadata struct {
Uid *int32 `json:"uid"`
Process string `json:"process"`
ProcessPath string `json:"processPath"`
RemoteDst string `json:"remoteDestination"`
}
// avoid stack overflow
type jsonMetadata Metadata
func (m *Metadata) RemoteAddress() string {
return net.JoinHostPort(m.String(), m.DstPort)
}

View file

@ -39,14 +39,13 @@ type DialFn = func(network, addr string) (net.Conn, error)
type Conn struct {
response *http.Response
request *http.Request
transport *http2.Transport
transport *TransportWrap
writer *io.PipeWriter
once sync.Once
close *atomic.Bool
err error
remain int
br *bufio.Reader
// deadlines
deadline *time.Timer
}
@ -150,8 +149,8 @@ func (g *Conn) Close() error {
return g.writer.Close()
}
func (g *Conn) LocalAddr() net.Addr { return &net.TCPAddr{IP: net.IPv4zero, Port: 0} }
func (g *Conn) RemoteAddr() net.Addr { return &net.TCPAddr{IP: net.IPv4zero, Port: 0} }
func (g *Conn) LocalAddr() net.Addr { return g.transport.LocalAddr() }
func (g *Conn) RemoteAddr() net.Addr { return g.transport.RemoteAddr() }
func (g *Conn) SetReadDeadline(t time.Time) error { return g.SetDeadline(t) }
func (g *Conn) SetWriteDeadline(t time.Time) error { return g.SetDeadline(t) }
@ -167,13 +166,15 @@ func (g *Conn) SetDeadline(t time.Time) error {
return nil
}
func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *http2.Transport {
func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *TransportWrap {
wrap := TransportWrap{}
dialFunc := func(network, addr string, cfg *tls.Config) (net.Conn, error) {
pconn, err := dialFn(network, addr)
if err != nil {
return nil, err
}
wrap.remoteAddr = pconn.RemoteAddr()
cn := tls.Client(pconn, cfg)
// fix tls handshake not timeout
@ -191,16 +192,18 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *http2.Transport {
return cn, nil
}
return &http2.Transport{
wrap.Transport = &http2.Transport{
DialTLS: dialFunc,
TLSClientConfig: tlsConfig,
AllowHTTP: false,
DisableCompression: true,
PingTimeout: 0,
}
return &wrap
}
func StreamGunWithTransport(transport *http2.Transport, cfg *Config) (net.Conn, error) {
func StreamGunWithTransport(transport *TransportWrap, cfg *Config) (net.Conn, error) {
serviceName := "GunService"
if cfg.ServiceName != "" {
serviceName = cfg.ServiceName

View file

@ -12,13 +12,15 @@ import (
"golang.org/x/net/http2"
)
func NewHTTP2XTLSClient(dialFn DialFn, tlsConfig *tls.Config) *http2.Transport {
func NewHTTP2XTLSClient(dialFn DialFn, tlsConfig *tls.Config) *TransportWrap {
wrap := TransportWrap{}
dialFunc := func(network, addr string, cfg *tls.Config) (net.Conn, error) {
pconn, err := dialFn(network, addr)
if err != nil {
return nil, err
}
wrap.remoteAddr = pconn.RemoteAddr()
xtlsConfig := &xtls.Config{
InsecureSkipVerify: cfg.InsecureSkipVerify,
ServerName: cfg.ServerName,
@ -37,13 +39,15 @@ func NewHTTP2XTLSClient(dialFn DialFn, tlsConfig *tls.Config) *http2.Transport {
return cn, nil
}
return &http2.Transport{
wrap.Transport = &http2.Transport{
DialTLS: dialFunc,
TLSClientConfig: tlsConfig,
AllowHTTP: false,
DisableCompression: true,
PingTimeout: 0,
}
return &wrap
}
func StreamGunWithXTLSConn(conn net.Conn, tlsConfig *tls.Config, cfg *Config) (net.Conn, error) {

View file

@ -0,0 +1,20 @@
package gun
import (
"golang.org/x/net/http2"
"net"
)
type TransportWrap struct {
*http2.Transport
remoteAddr net.Addr
localAddr net.Addr
}
func (tw *TransportWrap) RemoteAddr() net.Addr {
return tw.remoteAddr
}
func (tw *TransportWrap) LocalAddr() net.Addr {
return tw.localAddr
}

View file

@ -9,6 +9,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"time"
@ -269,6 +270,18 @@ func handleUDPConn(packet *inbound.PacketAdapter) {
return
}
pCtx.InjectPacketConn(rawPc)
actualProxy := proxy.Unwrap(nil)
if actualProxy != nil {
if dst, _, err := net.SplitHostPort(actualProxy.Addr()); err == nil {
metadata.RemoteDst = dst
} else {
if addrError, ok := err.(*net.AddrError); ok && strings.Contains(addrError.Err, "missing port") {
metadata.RemoteDst = actualProxy.Addr()
}
}
}
pc := statistic.NewUDPTracker(rawPc, statistic.DefaultManager, metadata, rule)
switch true {
@ -332,6 +345,11 @@ func handleTCPConn(connCtx C.ConnContext) {
}
return
}
if tcpAddr, ok := remoteConn.RemoteAddr().(*net.TCPAddr); ok {
metadata.RemoteDst = tcpAddr.IP.String()
}
remoteConn = statistic.NewTCPTracker(remoteConn, statistic.DefaultManager, metadata, rule)
defer func(remoteConn C.Conn) {
_ = remoteConn.Close()