103 lines
2.6 KiB
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
|
|
})
|
|
}
|