Files

112 lines
2.8 KiB
Go

package local
import (
"bufio"
"context"
"net"
"testing"
"time"
"github.com/go-gost/core/chain"
"github.com/go-gost/core/handler"
"github.com/go-gost/core/hop"
xlogger "github.com/go-gost/x/logger"
xmd "github.com/go-gost/x/metadata"
proxyproto "github.com/pires/go-proxyproto"
)
type proxyProtocolTestHop struct {
node *chain.Node
}
func (h proxyProtocolTestHop) Select(context.Context, ...hop.SelectOption) *chain.Node {
return h.node
}
func (h proxyProtocolTestHop) Nodes() []*chain.Node {
return []*chain.Node{h.node}
}
type proxyProtocolTestRouter struct{}
func (r proxyProtocolTestRouter) Options() *chain.RouterOptions {
return &chain.RouterOptions{}
}
func (r proxyProtocolTestRouter) Dial(ctx context.Context, network, address string) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, network, address)
}
func (r proxyProtocolTestRouter) Bind(context.Context, string, string, ...chain.BindOption) (net.Listener, error) {
return nil, net.ErrClosed
}
func TestLocalForwardHandlerSendsProxyProtocolToTarget(t *testing.T) {
targetListener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("listen target: %v", err)
}
defer targetListener.Close()
entryListener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("listen entry: %v", err)
}
defer entryListener.Close()
h := NewHandler(
handler.RouterOption(proxyProtocolTestRouter{}),
handler.LoggerOption(xlogger.Nop()),
)
forwarder := h.(handler.Forwarder)
forwarder.Forward(proxyProtocolTestHop{node: chain.NewNode("target", targetListener.Addr().String())})
if err := h.Init(xmd.NewMetadata(map[string]any{"proxyProtocol": 2})); err != nil {
t.Fatalf("init handler: %v", err)
}
handleErr := make(chan error, 1)
acceptErr := make(chan error, 1)
go func() {
serverConn, err := entryListener.Accept()
if err != nil {
acceptErr <- err
return
}
handleErr <- h.Handle(context.Background(), serverConn)
}()
clientConn, err := net.Dial("tcp", entryListener.Addr().String())
if err != nil {
t.Fatalf("dial entry: %v", err)
}
defer clientConn.Close()
targetConn, err := targetListener.Accept()
if err != nil {
t.Fatalf("accept target: %v", err)
}
defer targetConn.Close()
if err := targetConn.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil {
t.Fatalf("set target deadline: %v", err)
}
header, err := proxyproto.Read(bufio.NewReader(targetConn))
if err != nil {
t.Fatalf("read proxy protocol header: %v", err)
}
if header.Version != 2 {
t.Fatalf("expected proxy protocol v2, got v%d", header.Version)
}
_ = clientConn.Close()
_ = targetConn.Close()
select {
case err := <-acceptErr:
t.Fatalf("accept entry: %v", err)
case <-handleErr:
case <-time.After(2 * time.Second):
t.Fatal("handler did not return after closing connections")
}
}