go-tunnel/cmd/server/main.go

103 lines
2.6 KiB
Go

package main
import (
"context"
"flag"
"net/http"
"strings"
"cdr.dev/slog"
"forge.cadoles.com/wpetit/go-tunnel"
"github.com/pkg/errors"
"gitlab.com/wpetit/goweb/logger"
)
const salt = "go-tunnel"
var registry = NewRegistry()
func main() {
var (
serverAddr = ":36543"
httpAddr = ":3003"
sharedKey = "go-tunnel"
targetURL = "https://arcad.games"
)
flag.StringVar(&serverAddr, "server-addr", serverAddr, "server address")
flag.StringVar(&targetURL, "target-url", targetURL, "target url")
flag.StringVar(&httpAddr, "http-addr", httpAddr, "http server address")
flag.StringVar(&sharedKey, "shared-key", sharedKey, "shared key")
flag.Parse()
ctx := context.Background()
logger.SetLevel(slog.LevelDebug)
server := tunnel.NewServer(
tunnel.WithServerAddress(serverAddr),
tunnel.WithServerOnClientAuth(registry.OnClientAuth),
tunnel.WithServerOnClientDisconnect(registry.OnClientDisconnect),
tunnel.WithServerOnClientAuth(func(ctx context.Context, remoteClient *tunnel.RemoteClient, credentials interface{}) (bool, error) {
remoteAddr := remoteClient.RemoteAddr().String()
ctx = logger.With(ctx, logger.F("remoteAddr", remoteAddr))
logger.Debug(ctx, "new client auth")
clientID, ok := credentials.(string)
if !ok {
logger.Debug(ctx, "client auth failed")
return false, nil
}
registry.Add(clientID, remoteAddr, remoteClient)
logger.Debug(ctx, "client auth success")
return true, nil
}),
tunnel.WithServerOnClientDisconnect(func(ctx context.Context, remoteClient *tunnel.RemoteClient) error {
remoteAddr := remoteClient.RemoteAddr().String()
ctx = logger.With(ctx, logger.F("remoteAddr", remoteAddr))
logger.Debug(ctx, "client disconnected")
registry.RemoveByRemoteAddr(remoteAddr)
return nil
}),
)
go func() {
if err := server.Listen(ctx); err != nil {
logger.Fatal(ctx, "error while listening", logger.E(err))
}
}()
handler, err := createProxyHandler(targetURL)
if err != nil {
logger.Fatal(ctx, "could not create proxy handler", logger.E(errors.WithStack(err)))
}
if err := http.ListenAndServe(httpAddr, handler); err != nil {
logger.Fatal(ctx, "error while listening", logger.E(err))
}
}
func createProxyHandler(targetURL string) (http.Handler, error) {
return tunnel.ProxyHandler(targetURL, func(w http.ResponseWriter, r *http.Request) (*tunnel.RemoteClient, error) {
subdomains := strings.SplitN(r.Host, ".", 2)
if len(subdomains) < 2 {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return nil, tunnel.ErrAbortProxy
}
clientID := subdomains[0]
return registry.Get(clientID), nil
})
}