summaryrefslogtreecommitdiff
path: root/proxy/proxy.go
diff options
context:
space:
mode:
Diffstat (limited to 'proxy/proxy.go')
-rw-r--r--proxy/proxy.go84
1 files changed, 84 insertions, 0 deletions
diff --git a/proxy/proxy.go b/proxy/proxy.go
new file mode 100644
index 0000000..af0cd89
--- /dev/null
+++ b/proxy/proxy.go
@@ -0,0 +1,84 @@
+// Package proxy is a wrapper around proxyguard that integrates it with eduvpn-common settings
+// - leaves out some options not applicable to the common integration, e.g. fwmark
+// - integrates with eduvpn-common's logger
+// - integrates eduvpn-common's user agent
+package proxy
+
+import (
+ "context"
+ "fmt"
+ "log/slog"
+
+ "codeberg.org/eduVPN/proxyguard"
+
+ "codeberg.org/eduVPN/eduvpn-common/i18n/err"
+ httpw "codeberg.org/eduVPN/eduvpn-common/internal/http"
+)
+
+// Logger is defined here such that we can update the proxyguard logger
+type Logger struct{}
+
+// Logf logs a message with parameters
+func (l *Logger) Logf(msg string, params ...any) {
+ slog.Info("Proxyguard log", "msg", fmt.Sprintf(msg, params...))
+}
+
+// Log logs a message
+func (l *Logger) Log(msg string) {
+ slog.Info("Proxyguard log", "msg", msg)
+}
+
+// Proxy is the ProxyGuard client with a channel used for restarting
+type Proxy struct {
+ proxyguard.Client
+ resChan chan struct{}
+}
+
+// NewProxyguard sets up proxyguard for proxied WireGuard connections
+func NewProxyguard(ctx context.Context, lp int, tcpsp int, peer string, setupSocket func(fd int)) (*Proxy, error) {
+ proxyguard.UpdateLogger(&Logger{})
+ proxy := Proxy{
+ Client: proxyguard.Client{
+ Peer: peer,
+ ListenPort: lp,
+ TCPSourcePort: tcpsp,
+ SetupSocket: setupSocket,
+ UserAgent: httpw.UserAgent,
+ },
+ resChan: make(chan struct{}),
+ }
+ _, err := proxy.Setup(ctx)
+ if err != nil {
+ return nil, i18nerr.WrapInternal(err, "The ProxyGuard DNS could not be resolved")
+ }
+
+ return &proxy, nil
+}
+
+// Tunnel tunnels the ProxyGuard connection. `wglisten` is the WireGuard listen port
+func (p *Proxy) Tunnel(ctx context.Context, wglisten int) error {
+ errChan := make(chan error, 1)
+ gctx, cancel := context.WithCancel(ctx)
+ go func() {
+ err := p.Client.Tunnel(gctx, wglisten)
+ if err != nil {
+ err = i18nerr.WrapInternal(err, "The VPN proxy exited")
+ }
+ errChan <- err
+ }()
+
+ select {
+ case err := <-errChan:
+ cancel()
+ return err
+ case <-p.resChan:
+ cancel()
+ <-errChan
+ return p.Tunnel(ctx, wglisten)
+ }
+}
+
+// Restart restarts the existing ProxyGuard process, for e.g. roaming
+func (p *Proxy) Restart() {
+ p.resChan <- struct{}{}
+}