add vhost for port forwarding
This commit is contained in:
		
							
								
								
									
										35
									
								
								chain/hop.go
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								chain/hop.go
									
									
									
									
									
								
							| @ -2,6 +2,7 @@ package chain | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net" | ||||
|  | ||||
| 	"github.com/go-gost/core/bypass" | ||||
| 	"github.com/go-gost/core/chain" | ||||
| @ -71,19 +72,47 @@ func (p *chainHop) Select(ctx context.Context, opts ...chain.SelectOption) *chai | ||||
| 	} | ||||
|  | ||||
| 	// hop level bypass | ||||
| 	if p.options.bypass != nil && p.options.bypass.Contains(options.Addr) { | ||||
| 	if p.options.bypass != nil && | ||||
| 		p.options.bypass.Contains(options.Addr) { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	filters := p.nodes | ||||
| 	if host := options.Host; host != "" { | ||||
| 		filters = nil | ||||
| 		if v, _, _ := net.SplitHostPort(host); v != "" { | ||||
| 			host = v | ||||
| 		} | ||||
| 		var nodes []*chain.Node | ||||
| 		for _, node := range p.nodes { | ||||
| 			if node == nil { | ||||
| 				continue | ||||
| 			} | ||||
| 		// node level bypass | ||||
| 		if node.Options().Bypass != nil && node.Options().Bypass.Contains(options.Addr) { | ||||
| 			if node.Options().Host == "" { | ||||
| 				nodes = append(nodes, node) | ||||
| 				continue | ||||
| 			} | ||||
| 			if node.Options().Host == host { | ||||
| 				filters = append(filters, node) | ||||
| 				p.options.logger.Debugf("find node for host: %s", host) | ||||
| 			} | ||||
| 		} | ||||
| 		if len(filters) == 0 { | ||||
| 			filters = nodes | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var nodes []*chain.Node | ||||
| 	for _, node := range filters { | ||||
| 		if node == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 		// node level bypass | ||||
| 		if node.Options().Bypass != nil && | ||||
| 			node.Options().Bypass.Contains(options.Addr) { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		nodes = append(nodes, node) | ||||
| 	} | ||||
| 	if len(nodes) == 0 { | ||||
|  | ||||
| @ -260,6 +260,7 @@ type ForwarderConfig struct { | ||||
| type ForwardNodeConfig struct { | ||||
| 	Name     string   `yaml:",omitempty" json:"name,omitempty"` | ||||
| 	Addr     string   `yaml:",omitempty" json:"addr,omitempty"` | ||||
| 	Host     string   `yaml:",omitempty" json:"host,omitempty"` | ||||
| 	Bypass   string   `yaml:",omitempty" json:"bypass,omitempty"` | ||||
| 	Bypasses []string `yaml:",omitempty" json:"bypasses,omitempty"` | ||||
| } | ||||
| @ -333,6 +334,7 @@ type HopConfig struct { | ||||
| type NodeConfig struct { | ||||
| 	Name      string           `json:"name"` | ||||
| 	Addr      string           `yaml:",omitempty" json:"addr,omitempty"` | ||||
| 	Host      string           `yaml:",omitempty" json:"host,omitempty"` | ||||
| 	Interface string           `yaml:",omitempty" json:"interface,omitempty"` | ||||
| 	SockOpts  *SockOptsConfig  `yaml:"sockopts,omitempty" json:"sockopts,omitempty"` | ||||
| 	Bypass    string           `yaml:",omitempty" json:"bypass,omitempty"` | ||||
|  | ||||
| @ -202,6 +202,7 @@ func ParseHop(cfg *config.HopConfig) (chain.Hop, error) { | ||||
| 			chain.ResoloverNodeOption(registry.ResolverRegistry().Get(v.Resolver)), | ||||
| 			chain.HostMapperNodeOption(registry.HostsRegistry().Get(v.Hosts)), | ||||
| 			chain.MetadataNodeOption(nm), | ||||
| 			chain.HostNodeOption(v.Host), | ||||
| 		) | ||||
| 		nodes = append(nodes, node) | ||||
| 	} | ||||
|  | ||||
| @ -235,6 +235,7 @@ func parseForwarder(cfg *config.ForwarderConfig) (chain.Hop, error) { | ||||
| 					&config.NodeConfig{ | ||||
| 						Name:     node.Name, | ||||
| 						Addr:     node.Addr, | ||||
| 						Host:     node.Host, | ||||
| 						Bypass:   node.Bypass, | ||||
| 						Bypasses: node.Bypasses, | ||||
| 					}, | ||||
|  | ||||
							
								
								
									
										12
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								go.mod
									
									
									
									
									
								
							| @ -7,7 +7,7 @@ require ( | ||||
| 	github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d | ||||
| 	github.com/gin-contrib/cors v1.3.1 | ||||
| 	github.com/gin-gonic/gin v1.7.7 | ||||
| 	github.com/go-gost/core v0.0.0-20221020130224-eb9d483127cc | ||||
| 	github.com/go-gost/core v0.0.0-20221111142129-c2a1dd2a89cb | ||||
| 	github.com/go-gost/gosocks4 v0.0.1 | ||||
| 	github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 | ||||
| 	github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 | ||||
| @ -31,10 +31,10 @@ require ( | ||||
| 	github.com/xtaci/smux v1.5.16 | ||||
| 	github.com/xtaci/tcpraw v1.2.25 | ||||
| 	github.com/yl2chen/cidranger v1.0.2 | ||||
| 	golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 | ||||
| 	golang.org/x/net v0.0.0-20220812174116-3211cb980234 | ||||
| 	golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 | ||||
| 	golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 | ||||
| 	golang.org/x/crypto v0.2.0 | ||||
| 	golang.org/x/net v0.2.0 | ||||
| 	golang.org/x/sys v0.2.0 | ||||
| 	golang.org/x/time v0.2.0 | ||||
| 	golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 | ||||
| 	google.golang.org/grpc v1.49.0 | ||||
| 	google.golang.org/protobuf v1.28.0 | ||||
| @ -91,7 +91,7 @@ require ( | ||||
| 	github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect | ||||
| 	golang.org/x/exp v0.0.0-20220827204233-334a2380cb91 // indirect | ||||
| 	golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect | ||||
| 	golang.org/x/text v0.3.7 // indirect | ||||
| 	golang.org/x/text v0.4.0 // indirect | ||||
| 	golang.org/x/tools v0.1.12 // indirect | ||||
| 	golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect | ||||
| 	google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect | ||||
|  | ||||
							
								
								
									
										12
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								go.sum
									
									
									
									
									
								
							| @ -98,6 +98,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 | ||||
| github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= | ||||
| github.com/go-gost/core v0.0.0-20221020130224-eb9d483127cc h1:pS75VLwTkYLIC3n0QbfwE65N/1Zh8BnXfErNq9DGWd4= | ||||
| github.com/go-gost/core v0.0.0-20221020130224-eb9d483127cc/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ= | ||||
| github.com/go-gost/core v0.0.0-20221111142129-c2a1dd2a89cb h1:BkuYeTJYfN3nGHtnljjRBuBBXg2hTRBN9EmszZalyzg= | ||||
| github.com/go-gost/core v0.0.0-20221111142129-c2a1dd2a89cb/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ= | ||||
| github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= | ||||
| github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= | ||||
| github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04= | ||||
| @ -409,6 +411,8 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y | ||||
| golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||||
| golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c= | ||||
| golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||||
| golang.org/x/crypto v0.2.0 h1:BRXPfhNivWL5Yq0BGQ39a2sW6t44aODpfxkWjYdzewE= | ||||
| golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= | ||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
| golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | ||||
| @ -486,6 +490,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= | ||||
| golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= | ||||
| golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= | ||||
| golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= | ||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||
| golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
| @ -564,9 +570,12 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc | ||||
| golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 h1:fqTvyMIIj+HRzMmnzr9NtpHP6uVpvB5fkHcgPDC4nu8= | ||||
| golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= | ||||
| golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= | ||||
| golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM= | ||||
| golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| @ -577,11 +586,14 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | ||||
| golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||||
| golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||||
| golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= | ||||
| golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE= | ||||
| golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | ||||
|  | ||||
							
								
								
									
										84
									
								
								handler/forward/internal/forward/forward.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								handler/forward/internal/forward/forward.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,84 @@ | ||||
| package forward | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"encoding/binary" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"strings" | ||||
|  | ||||
| 	dissector "github.com/go-gost/tls-dissector" | ||||
| 	xio "github.com/go-gost/x/internal/io" | ||||
| ) | ||||
|  | ||||
| func SniffHost(ctx context.Context, rdw io.ReadWriter) (rw io.ReadWriter, host string, err error) { | ||||
| 	rw = rdw | ||||
|  | ||||
| 	// try to sniff TLS traffic | ||||
| 	var hdr [dissector.RecordHeaderLen]byte | ||||
| 	_, err = io.ReadFull(rw, hdr[:]) | ||||
| 	rw = xio.NewReadWriter(io.MultiReader(bytes.NewReader(hdr[:]), rw), rw) | ||||
| 	if err == nil && | ||||
| 		hdr[0] == dissector.Handshake && | ||||
| 		binary.BigEndian.Uint16(hdr[1:3]) == tls.VersionTLS10 { | ||||
| 		return sniffSNI(ctx, rw) | ||||
| 	} | ||||
|  | ||||
| 	// try to sniff HTTP traffic | ||||
| 	if isHTTP(string(hdr[:])) { | ||||
| 		buf := new(bytes.Buffer) | ||||
| 		var r *http.Request | ||||
| 		r, err = http.ReadRequest(bufio.NewReader(io.TeeReader(rw, buf))) | ||||
| 		rw = xio.NewReadWriter(io.MultiReader(buf, rw), rw) | ||||
| 		if err == nil { | ||||
| 			host = r.Host | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func sniffSNI(ctx context.Context, rw io.ReadWriter) (io.ReadWriter, string, error) { | ||||
| 	buf := new(bytes.Buffer) | ||||
| 	host, err := getServerName(ctx, io.TeeReader(rw, buf)) | ||||
| 	rw = xio.NewReadWriter(io.MultiReader(buf, rw), rw) | ||||
| 	return rw, host, err | ||||
| } | ||||
|  | ||||
| func getServerName(ctx context.Context, r io.Reader) (host string, err error) { | ||||
| 	record, err := dissector.ReadRecord(r) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	clientHello := dissector.ClientHelloMsg{} | ||||
| 	if err = clientHello.Decode(record.Opaque); err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, ext := range clientHello.Extensions { | ||||
| 		if ext.Type() == dissector.ExtServerName { | ||||
| 			snExtension := ext.(*dissector.ServerNameExtension) | ||||
| 			host = snExtension.Name | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func isHTTP(s string) bool { | ||||
| 	return strings.HasPrefix(http.MethodGet, s[:3]) || | ||||
| 		strings.HasPrefix(http.MethodPost, s[:4]) || | ||||
| 		strings.HasPrefix(http.MethodPut, s[:3]) || | ||||
| 		strings.HasPrefix(http.MethodDelete, s) || | ||||
| 		strings.HasPrefix(http.MethodOptions, s) || | ||||
| 		strings.HasPrefix(http.MethodPatch, s) || | ||||
| 		strings.HasPrefix(http.MethodHead, s[:4]) || | ||||
| 		strings.HasPrefix(http.MethodConnect, s) || | ||||
| 		strings.HasPrefix(http.MethodTrace, s) | ||||
| } | ||||
| @ -4,6 +4,7 @@ import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"time" | ||||
|  | ||||
| @ -11,6 +12,7 @@ import ( | ||||
| 	"github.com/go-gost/core/handler" | ||||
| 	md "github.com/go-gost/core/metadata" | ||||
| 	xchain "github.com/go-gost/x/chain" | ||||
| 	"github.com/go-gost/x/handler/forward/internal/forward" | ||||
| 	netpkg "github.com/go-gost/x/internal/net" | ||||
| 	"github.com/go-gost/x/registry" | ||||
| ) | ||||
| @ -84,18 +86,29 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	target := h.hop.Select(ctx) | ||||
| 	network := "tcp" | ||||
| 	if _, ok := conn.(net.PacketConn); ok { | ||||
| 		network = "udp" | ||||
| 	} | ||||
|  | ||||
| 	var rw io.ReadWriter | ||||
| 	var host string | ||||
| 	if h.md.sniffing { | ||||
| 		if network == "tcp" { | ||||
| 			rw, host, _ = forward.SniffHost(ctx, conn) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var target *chain.Node | ||||
| 	if h.hop != nil { | ||||
| 		target = h.hop.Select(ctx, chain.HostSelectOption(host)) | ||||
| 	} | ||||
| 	if target == nil { | ||||
| 		err := errors.New("target not available") | ||||
| 		log.Error(err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	network := "tcp" | ||||
| 	if _, ok := conn.(net.PacketConn); ok { | ||||
| 		network = "udp" | ||||
| 	} | ||||
|  | ||||
| 	log = log.WithFields(map[string]any{ | ||||
| 		"dst": fmt.Sprintf("%s/%s", target.Addr, network), | ||||
| 	}) | ||||
| @ -119,7 +132,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand | ||||
|  | ||||
| 	t := time.Now() | ||||
| 	log.Debugf("%s <-> %s", conn.RemoteAddr(), target.Addr) | ||||
| 	netpkg.Transport(conn, cc) | ||||
| 	netpkg.Transport(rw, cc) | ||||
| 	log.WithFields(map[string]any{ | ||||
| 		"duration": time.Since(t), | ||||
| 	}).Debugf("%s >-< %s", conn.RemoteAddr(), target.Addr) | ||||
|  | ||||
| @ -9,13 +9,16 @@ import ( | ||||
|  | ||||
| type metadata struct { | ||||
| 	readTimeout time.Duration | ||||
| 	sniffing    bool | ||||
| } | ||||
|  | ||||
| func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) { | ||||
| 	const ( | ||||
| 		readTimeout = "readTimeout" | ||||
| 		sniffing    = "sniffing" | ||||
| 	) | ||||
|  | ||||
| 	h.md.readTimeout = mdutil.GetDuration(md, readTimeout) | ||||
| 	h.md.sniffing = mdutil.GetBool(md, sniffing) | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @ -4,12 +4,14 @@ import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-gost/core/chain" | ||||
| 	"github.com/go-gost/core/handler" | ||||
| 	md "github.com/go-gost/core/metadata" | ||||
| 	"github.com/go-gost/x/handler/forward/internal/forward" | ||||
| 	netpkg "github.com/go-gost/x/internal/net" | ||||
| 	"github.com/go-gost/x/registry" | ||||
| ) | ||||
| @ -75,9 +77,21 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	network := "tcp" | ||||
| 	if _, ok := conn.(net.PacketConn); ok { | ||||
| 		network = "udp" | ||||
| 	} | ||||
|  | ||||
| 	var rw io.ReadWriter | ||||
| 	var host string | ||||
| 	if h.md.sniffing { | ||||
| 		if network == "tcp" { | ||||
| 			rw, host, _ = forward.SniffHost(ctx, conn) | ||||
| 		} | ||||
| 	} | ||||
| 	var target *chain.Node | ||||
| 	if h.hop != nil { | ||||
| 		target = h.hop.Select(ctx) | ||||
| 		target = h.hop.Select(ctx, chain.HostSelectOption(host)) | ||||
| 	} | ||||
| 	if target == nil { | ||||
| 		err := errors.New("target not available") | ||||
| @ -85,11 +99,6 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	network := "tcp" | ||||
| 	if _, ok := conn.(net.PacketConn); ok { | ||||
| 		network = "udp" | ||||
| 	} | ||||
|  | ||||
| 	log = log.WithFields(map[string]any{ | ||||
| 		"dst": fmt.Sprintf("%s/%s", target.Addr, network), | ||||
| 	}) | ||||
| @ -113,7 +122,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand | ||||
|  | ||||
| 	t := time.Now() | ||||
| 	log.Debugf("%s <-> %s", conn.RemoteAddr(), target.Addr) | ||||
| 	netpkg.Transport(conn, cc) | ||||
| 	netpkg.Transport(rw, cc) | ||||
| 	log.WithFields(map[string]any{ | ||||
| 		"duration": time.Since(t), | ||||
| 	}).Debugf("%s >-< %s", conn.RemoteAddr(), target.Addr) | ||||
|  | ||||
| @ -9,13 +9,16 @@ import ( | ||||
|  | ||||
| type metadata struct { | ||||
| 	readTimeout time.Duration | ||||
| 	sniffing    bool | ||||
| } | ||||
|  | ||||
| func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) { | ||||
| 	const ( | ||||
| 		readTimeout = "readTimeout" | ||||
| 		sniffing    = "sniffing" | ||||
| 	) | ||||
|  | ||||
| 	h.md.readTimeout = mdutil.GetDuration(md, readTimeout) | ||||
| 	h.md.sniffing = mdutil.GetBool(md, sniffing) | ||||
| 	return | ||||
| } | ||||
|  | ||||
							
								
								
									
										15
									
								
								internal/io/io.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								internal/io/io.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| package io | ||||
|  | ||||
| import "io" | ||||
|  | ||||
| type readWriter struct { | ||||
| 	io.Reader | ||||
| 	io.Writer | ||||
| } | ||||
|  | ||||
| func NewReadWriter(r io.Reader, w io.Writer) io.ReadWriter { | ||||
| 	return &readWriter{ | ||||
| 		Reader: r, | ||||
| 		Writer: w, | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user