summaryrefslogtreecommitdiff
path: root/exports
diff options
context:
space:
mode:
Diffstat (limited to 'exports')
-rw-r--r--exports/exports.go107
-rw-r--r--exports/exports.h5
2 files changed, 112 insertions, 0 deletions
diff --git a/exports/exports.go b/exports/exports.go
index a20ffb8..3ef6781 100644
--- a/exports/exports.go
+++ b/exports/exports.go
@@ -27,6 +27,7 @@ import (
"codeberg.org/eduVPN/eduvpn-common/client"
"codeberg.org/eduVPN/eduvpn-common/i18n/err"
+ "codeberg.org/eduVPN/eduvpn-common/proxy"
"codeberg.org/eduVPN/eduvpn-common/types/cookie"
errtypes "codeberg.org/eduVPN/eduvpn-common/types/error"
srvtypes "codeberg.org/eduVPN/eduvpn-common/types/server"
@@ -876,6 +877,112 @@ func StartFailover(c C.uintptr_t, gateway *C.char, mtu C.int, readRxBytes C.Read
return droppedC, nil
}
+// NewProxyguard creates the 'proxyguard' procedure in eduvpn-common.
+// If the proxy cannot be created it returns an error.
+//
+// This function proxies WireGuard UDP connections over HTTP: [ProxyGuard on Codeberg](https://codeberg.org/eduvpn/proxyguard).
+//
+// These input variables can be gotten from the configuration that is retrieved using the `proxy` JSON key
+//
+// - `c` is the cookie. Note that if you cancel/delete the cookie, ProxyGuard gets cleaned up. Common automatically cleans up ProxyGuard when `Cleanup` is called, but it is good to cleanup yourself too.
+// - `lp` is the `port` of the local udp ProxyGuard connection, this is what is set to the WireGuard endpoint
+// - `tcpsp` is the TCP source port. Pass 0 if you do not route based on source port, so far only the Linux client has to pass non-zero.
+// - `peer` is the `ip:port` of the remote server
+// - `proxySetup` is a callback which is called when the socket is setting up, this can be used for configuring routing in the client. It takes two arguments: the file descriptor (integer) and a JSON list of IPs the client connects to
+//
+// Example Input: ```NewProxyguard(myCookie, 1337, 0, "5.5.5.5:51820", proxySetupCB)```
+//
+// Example Output: ```null```
+//
+//export NewProxyguard
+func NewProxyguard(c C.uintptr_t, lp C.int, tcpsp C.int, peer *C.char, proxySetup C.ProxySetup) (C.uintptr_t, *C.char) {
+ ck, err := getCookie(c)
+ if err != nil {
+ return 0, getCError(err)
+ }
+ proxy, proxyErr := proxy.NewProxyguard(ck.Context(), int(lp), int(tcpsp), C.GoString(peer), func(fd int) {
+ if proxySetup == nil {
+ return
+ }
+ C.call_proxy_setup(proxySetup, C.int(fd))
+ })
+ if proxyErr != nil {
+ return 0, getCError(proxyErr)
+ }
+ return C.uintptr_t(cgo.NewHandle(proxy)), nil
+}
+
+// ProxyguardRestart restarts ProxyGuard, call this when a network change happens
+//
+// Example Input: ```ProxyguardRestart(proxyHandle)```
+//
+// Example Output: ```"failed restarting ProxyGuard"```
+//
+//export ProxyguardRestart
+func ProxyguardRestart(proxyH C.uintptr_t) *C.char {
+ pr, err := getProxy(proxyH)
+ if err != nil {
+ return getCError(err)
+ }
+ pr.Restart()
+ return nil
+}
+
+func getProxy(proxyH C.uintptr_t) (*proxy.Proxy, error) {
+ h := cgo.Handle(proxyH)
+ v, ok := h.Value().(*proxy.Proxy)
+ if !ok {
+ return nil, i18nerr.NewInternal("value is not a proxyguard wrapper")
+ }
+ return v, nil
+}
+
+// ProxyguardTunnel starts the tunneling for ProxyGuard
+// `c` is the cookie
+// `proxyH` is the proxy handle
+// `wglisten` is the port WireGuard is listening on
+//
+//export ProxyguardTunnel
+func ProxyguardTunnel(c C.uintptr_t, proxyH C.uintptr_t, wglisten C.int) *C.char {
+ ck, err := getCookie(c)
+ if err != nil {
+ return getCError(err)
+ }
+ pr, err := getProxy(proxyH)
+ if err != nil {
+ return getCError(err)
+ }
+ tunnelErr := pr.Tunnel(ck.Context(), int(wglisten))
+
+ // after tunneling is done, the handle should be deleted
+ cgo.Handle(proxyH).Delete()
+ return getCError(tunnelErr)
+}
+
+// ProxyguardPeerIPs gets the Peer IPs configured by ProxyGuard
+// Example Input: ```ProxyguardPeerIPs(handle)```
+//
+// Example Output: ```["1.1.1.1"], null```
+//
+//export ProxyguardPeerIPs
+func ProxyguardPeerIPs(proxyH C.uintptr_t) (*C.char, *C.char) {
+ pr, err := getProxy(proxyH)
+ if err != nil {
+ return nil, getCError(err)
+ }
+ pips := pr.PeerIPS
+
+ b, err := json.Marshal(pips)
+ if err != nil {
+ return nil, getCError(i18nerr.WrapInternal(err, "failed converting Peer IPs to JSON"))
+ }
+ ret, err := getReturnData(string(b))
+ if err != nil {
+ return nil, getCError(err)
+ }
+ return C.CString(ret), nil
+}
+
// SetState sets the state of the state machine.
//
// Note: this transitions the FSM into the new state without passing any data to it.
diff --git a/exports/exports.h b/exports/exports.h
index 13630a6..9ec39e4 100644
--- a/exports/exports.h
+++ b/exports/exports.h
@@ -11,6 +11,7 @@ typedef int (*StateCB)(int oldstate, int newstate, void* data);
typedef void (*RefreshList)();
typedef void (*TokenGetter)(const char* server_id, int server_type, char* out, size_t len);
typedef void (*TokenSetter)(const char* server_id, int server_type, const char* tokens);
+typedef void (*ProxySetup)(int fd);
static long long int get_read_rx_bytes(ReadRxBytes read)
{
@@ -32,5 +33,9 @@ static void call_token_setter(TokenSetter setter, const char* server_id, int ser
{
setter(server_id, server_type, tokens);
}
+static void call_proxy_setup(ProxySetup proxysetup, int fd)
+{
+ proxysetup(fd);
+}
#endif /* EXPORTS_H */