sniffing protocol for port forwarding

This commit is contained in:
ginuerzh 2022-11-30 10:54:19 +08:00
parent 5f31240e29
commit 2e89811d59
9 changed files with 46 additions and 9 deletions

View File

@ -103,6 +103,16 @@ func (p *chainHop) Select(ctx context.Context, opts ...chain.SelectOption) *chai
if len(filters) == 0 { if len(filters) == 0 {
filters = nodes filters = nodes
} }
} else if protocol := options.Protocol; protocol != "" {
filters = nil
for _, node := range p.nodes {
if node == nil {
continue
}
if node.Options().Protocol == protocol {
filters = append(filters, node)
}
}
} }
var nodes []*chain.Node var nodes []*chain.Node

View File

@ -261,6 +261,7 @@ type ForwardNodeConfig struct {
Name string `yaml:",omitempty" json:"name,omitempty"` Name string `yaml:",omitempty" json:"name,omitempty"`
Addr string `yaml:",omitempty" json:"addr,omitempty"` Addr string `yaml:",omitempty" json:"addr,omitempty"`
Host string `yaml:",omitempty" json:"host,omitempty"` Host string `yaml:",omitempty" json:"host,omitempty"`
Protocol string `yaml:",omitempty" json:"protocol,omitempty"`
Bypass string `yaml:",omitempty" json:"bypass,omitempty"` Bypass string `yaml:",omitempty" json:"bypass,omitempty"`
Bypasses []string `yaml:",omitempty" json:"bypasses,omitempty"` Bypasses []string `yaml:",omitempty" json:"bypasses,omitempty"`
} }
@ -335,6 +336,7 @@ type NodeConfig struct {
Name string `json:"name"` Name string `json:"name"`
Addr string `yaml:",omitempty" json:"addr,omitempty"` Addr string `yaml:",omitempty" json:"addr,omitempty"`
Host string `yaml:",omitempty" json:"host,omitempty"` Host string `yaml:",omitempty" json:"host,omitempty"`
Protocol string `yaml:",omitempty" json:"protocol,omitempty"`
Interface string `yaml:",omitempty" json:"interface,omitempty"` Interface string `yaml:",omitempty" json:"interface,omitempty"`
SockOpts *SockOptsConfig `yaml:"sockopts,omitempty" json:"sockopts,omitempty"` SockOpts *SockOptsConfig `yaml:"sockopts,omitempty" json:"sockopts,omitempty"`
Bypass string `yaml:",omitempty" json:"bypass,omitempty"` Bypass string `yaml:",omitempty" json:"bypass,omitempty"`

View File

@ -216,6 +216,7 @@ func ParseHop(cfg *config.HopConfig) (chain.Hop, error) {
chain.HostMapperNodeOption(registry.HostsRegistry().Get(v.Hosts)), chain.HostMapperNodeOption(registry.HostsRegistry().Get(v.Hosts)),
chain.MetadataNodeOption(nm), chain.MetadataNodeOption(nm),
chain.HostNodeOption(host), chain.HostNodeOption(host),
chain.ProtocolNodeOption(v.Protocol),
) )
nodes = append(nodes, node) nodes = append(nodes, node)
} }

View File

@ -250,6 +250,7 @@ func parseForwarder(cfg *config.ForwarderConfig) (chain.Hop, error) {
Name: node.Name, Name: node.Name,
Addr: node.Addr, Addr: node.Addr,
Host: node.Host, Host: node.Host,
Protocol: node.Protocol,
Bypass: node.Bypass, Bypass: node.Bypass,
Bypasses: node.Bypasses, Bypasses: node.Bypasses,
}, },

2
go.mod
View File

@ -7,7 +7,7 @@ require (
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/gin-contrib/cors v1.3.1 github.com/gin-contrib/cors v1.3.1
github.com/gin-gonic/gin v1.7.7 github.com/gin-gonic/gin v1.7.7
github.com/go-gost/core v0.0.0-20221129013900-0f0679a3ecbc github.com/go-gost/core v0.0.0-20221130024727-8effb0b8b971
github.com/go-gost/gosocks4 v0.0.1 github.com/go-gost/gosocks4 v0.0.1
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7

4
go.sum
View File

@ -96,8 +96,8 @@ github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 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-20221129013900-0f0679a3ecbc h1:LkielnJLsiOAnmgU88bW+73jZ07T4tyNb4jx94upm9g= github.com/go-gost/core v0.0.0-20221130024727-8effb0b8b971 h1:0AauAKN4J0ueS5yAdpQZEfhmUrPg1MZ/FBrGDmXyJi8=
github.com/go-gost/core v0.0.0-20221129013900-0f0679a3ecbc/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ= github.com/go-gost/core v0.0.0-20221130024727-8effb0b8b971/go.mod h1:bHVbCS9da6XtKNYMkMUVcck5UqDDUkyC37erVfs4GXQ=
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= 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/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc=
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04= github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 h1:A95M6UWcfZgOuJkQ7QLfG0Hs5peWIUSysCDNz4pfe04=

View File

@ -14,7 +14,7 @@ import (
xio "github.com/go-gost/x/internal/io" xio "github.com/go-gost/x/internal/io"
) )
func SniffHost(ctx context.Context, rdw io.ReadWriter) (rw io.ReadWriter, host string, err error) { func Sniffing(ctx context.Context, rdw io.ReadWriter) (rw io.ReadWriter, host string, protocol string, err error) {
rw = rdw rw = rdw
// try to sniff TLS traffic // try to sniff TLS traffic
@ -24,7 +24,8 @@ func SniffHost(ctx context.Context, rdw io.ReadWriter) (rw io.ReadWriter, host s
if err == nil && if err == nil &&
hdr[0] == dissector.Handshake && hdr[0] == dissector.Handshake &&
binary.BigEndian.Uint16(hdr[1:3]) == tls.VersionTLS10 { binary.BigEndian.Uint16(hdr[1:3]) == tls.VersionTLS10 {
return sniffSNI(ctx, rw) rw, host, err = sniffSNI(ctx, rw)
return
} }
// try to sniff HTTP traffic // try to sniff HTTP traffic
@ -39,6 +40,8 @@ func SniffHost(ctx context.Context, rdw io.ReadWriter) (rw io.ReadWriter, host s
} }
} }
protocol = sniffProtocol(hdr[:])
return return
} }
@ -82,3 +85,14 @@ func isHTTP(s string) bool {
strings.HasPrefix(http.MethodConnect, s) || strings.HasPrefix(http.MethodConnect, s) ||
strings.HasPrefix(http.MethodTrace, s) strings.HasPrefix(http.MethodTrace, s)
} }
const (
SSHv2 = "SSH-2"
)
func sniffProtocol(hdr []byte) string {
if string(hdr) == SSHv2 {
return "ssh"
}
return ""
}

View File

@ -93,15 +93,20 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
var rw io.ReadWriter = conn var rw io.ReadWriter = conn
var host string var host string
var protocol string
if h.md.sniffing { if h.md.sniffing {
if network == "tcp" { if network == "tcp" {
rw, host, _ = forward.SniffHost(ctx, conn) rw, host, protocol, _ = forward.Sniffing(ctx, conn)
h.options.Logger.Debugf("sniffing: host=%s, protocol=%s", host, protocol)
} }
} }
var target *chain.Node var target *chain.Node
if h.hop != nil { if h.hop != nil {
target = h.hop.Select(ctx, chain.HostSelectOption(host)) target = h.hop.Select(ctx,
chain.HostSelectOption(host),
chain.ProtocolSelectOption(protocol),
)
} }
if target == nil { if target == nil {
err := errors.New("target not available") err := errors.New("target not available")

View File

@ -84,14 +84,18 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
var rw io.ReadWriter = conn var rw io.ReadWriter = conn
var host string var host string
var protocol string
if h.md.sniffing { if h.md.sniffing {
if network == "tcp" { if network == "tcp" {
rw, host, _ = forward.SniffHost(ctx, conn) rw, host, protocol, _ = forward.Sniffing(ctx, conn)
} }
} }
var target *chain.Node var target *chain.Node
if h.hop != nil { if h.hop != nil {
target = h.hop.Select(ctx, chain.HostSelectOption(host)) target = h.hop.Select(ctx,
chain.HostSelectOption(host),
chain.ProtocolSelectOption(protocol),
)
} }
if target == nil { if target == nil {
err := errors.New("target not available") err := errors.New("target not available")