diff options
Diffstat (limited to 'api')
| -rw-r--r-- | api/handlers/index.go | 22 | ||||
| -rw-r--r-- | api/handlers/peer.go | 75 | ||||
| -rw-r--r-- | api/handlers/reverseProxy.go | 35 |
3 files changed, 132 insertions, 0 deletions
diff --git a/api/handlers/index.go b/api/handlers/index.go new file mode 100644 index 0000000..c165f3b --- /dev/null +++ b/api/handlers/index.go @@ -0,0 +1,22 @@ +package handlers + +import ( + "net/http" + + "github.com/LMBishop/gunnel/pkg/config" + "github.com/LMBishop/gunnel/web" +) + +func Index(configService config.Service) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + web.Index().Execute(w, struct { + Host string + ExpireAfter int + Iface string + }{ + Host: configService.Config().Hostname, + ExpireAfter: configService.Config().ExpireAfter, + Iface: configService.Config().WireGuard.InterfaceName, + }) + } +} diff --git a/api/handlers/peer.go b/api/handlers/peer.go new file mode 100644 index 0000000..51fa047 --- /dev/null +++ b/api/handlers/peer.go @@ -0,0 +1,75 @@ +package handlers + +import ( + "fmt" + "log/slog" + "net/http" + + "github.com/LMBishop/gunnel/pkg/config" + "github.com/LMBishop/gunnel/pkg/store" + "github.com/LMBishop/gunnel/pkg/wireguard" + "github.com/gorilla/mux" +) + +const script = `#!/bin/bash + +# Your IP address: %s +# Private key: %s +# Unique slug: %s + +# Run this script as root to set up your client + +set -euo pipefail + +sudo ip link delete dev %s 2>/dev/null || true +sudo ip link add %s type wireguard +sudo ip addr add %s dev %s +echo "%s" | sudo tee /tmp/tunnel-private > /dev/null +sudo wg set %s private-key /tmp/tunnel-private +sudo wg set %s peer %s allowed-ips %s endpoint %s:%s persistent-keepalive 21 +sudo ip link set up dev %s +sudo ip route add %s dev %s + +echo "http://0.0.0.0:%s is now reachable at http://%s.%s"` + +func NewPeer(storeService store.Service, wireguardService wireguard.Service, configService config.Service) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + params := mux.Vars(r) + port := params["port"] + + peer, err := wireguardService.NewPeer() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + slug := storeService.GetUnusedSlug() + + ipAddr := peer.IPAddr.String() + + storeService.NewForwardingRule(slug, peer, port) + + iface := configService.Config().WireGuard.InterfaceName + wireguardPort := configService.Config().WireGuard.Port + hostname := configService.Config().Hostname + network := configService.Config().WireGuard.Network + publicKey := wireguardService.PublicKey() + + slog.Info("new peer", "peer", peer.PrivateKey) + + fmt.Fprintf(w, script, + ipAddr, + peer.PrivateKey, + slug, + iface, + iface, + ipAddr, iface, + peer.PrivateKey, + iface, + iface, publicKey, network, hostname, wireguardPort, + iface, + network, iface, + port, slug, hostname, + ) + } +} diff --git a/api/handlers/reverseProxy.go b/api/handlers/reverseProxy.go new file mode 100644 index 0000000..4ac4c87 --- /dev/null +++ b/api/handlers/reverseProxy.go @@ -0,0 +1,35 @@ +package handlers + +import ( + "fmt" + "net/http" + "net/http/httputil" + "net/url" + "strings" + "time" + + "github.com/LMBishop/gunnel/pkg/store" +) + +func ReverseProxy(storeService store.Service) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + hostParts := strings.Split(r.Host, ".") + + slug := hostParts[0] + rule := storeService.GetRuleBySlug(slug) + if rule == nil { + http.Error(w, fmt.Sprintf("Unknown peer '%s'", slug), http.StatusNotFound) + return + } + + targetURL, err := url.Parse("http://" + rule.Peer.IPAddr.String() + ":" + rule.Port) + rule.LastUsed = time.Now() + if err != nil { + http.Error(w, "Invalid target URL", http.StatusInternalServerError) + return + } + + proxy := httputil.NewSingleHostReverseProxy(targetURL) + proxy.ServeHTTP(w, r) + } +} |
