// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: MPL-2.0 package main import ( "fmt" "io" "net" "os" ) // gRPC byte prefix (see RPCGRPC in agent/pool/conn.go). const bytePrefix byte = 8 func main() { if len(os.Args) != 2 { log("usage: %s host:port", os.Args[0]) os.Exit(1) } serverAddr := os.Args[1] lis, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { log("failed to start listener: %v", err) os.Exit(1) } defer lis.Close() fmt.Println("Proxying connections to Consul's internal gRPC server") fmt.Printf("Use this address: %s\n", lis.Addr()) for { conn, err := lis.Accept() if err != nil { log("failed to accept connection: %v", err) continue } go func(conn net.Conn) { if err := handleClient(serverAddr, conn); err != nil { log(err.Error()) } }(conn) } } func handleClient(serverAddr string, clientConn net.Conn) error { defer clientConn.Close() serverConn, err := net.Dial("tcp", serverAddr) if err != nil { return fmt.Errorf("failed to dial server connection: %w", err) } defer serverConn.Close() if _, err := serverConn.Write([]byte{bytePrefix}); err != nil { return fmt.Errorf("failed to write byte prefix: %v", err) } errCh := make(chan error, 1) go func() { _, err := io.Copy(serverConn, clientConn) errCh <- err }() go func() { _, err := io.Copy(clientConn, serverConn) errCh <- err }() return <-errCh } func log(message string, args ...interface{}) { fmt.Fprintf(os.Stderr, message+"\n", args...) }