summaryrefslogtreecommitdiff
path: root/proxy/proxy.go
blob: a43083fca4c8c0e4169163f39cb205cc91acc1ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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"

	"codeberg.org/eduVPN/proxyguard"

	"codeberg.org/eduVPN/eduvpn-common/i18nerr"
	httpw "codeberg.org/eduVPN/eduvpn-common/internal/http"
	"codeberg.org/eduVPN/eduvpn-common/internal/log"
)

// 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 ...interface{}) {
	log.Logger.Infof("[Proxyguard] "+msg, params...)
}

// Log logs a message
func (l *Logger) Log(msg string) {
	log.Logger.Infof("[Proxyguard] %s", 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 {
	log.Logger.Infof("callying tunnel")
	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{}{}
}