Skip to content
This repository has been archived by the owner on Nov 29, 2024. It is now read-only.

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jwijenbergh committed Nov 7, 2023
1 parent 455c472 commit f37642d
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 110 deletions.
3 changes: 3 additions & 0 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ func (a *API) Connect(ctx context.Context, prof profiles.Profile, protos []proto
continue
}
wgKey, err = wireguard.GenerateKey()
if err != nil {
return nil, err
}
// Set the public key
pubkey := wgKey.PublicKey()
uv.Set("public_key", pubkey.String())
Expand Down
127 changes: 127 additions & 0 deletions internal/server/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package server

import (
"github.com/eduvpn/eduvpn-common/internal/api"
"github.com/eduvpn/eduvpn-common/internal/api/profiles"
v2cfg "github.com/eduvpn/eduvpn-common/internal/config/v2"
"github.com/eduvpn/eduvpn-common/internal/http"
"github.com/eduvpn/eduvpn-common/types/protocol"
)

type Base struct {
apiw *api.API
CachedInfo *profiles.Info
Profile *profiles.Profile
}

var InvalidProfileErr = errors.New("invalid profile")

// Profiles gets the profiles for the server
// It only does a /info network request if the profiles have not been cached
// force indicates whether or not the profiles should be fetched fresh
func (b *Base) Profiles(ctx context.Context, force bool) (*profiles.Info, error) {
// If we have a cached copy we only return that if force is false
if s.CachedInfo != nil && !force {
return s.CachedInfo, nil
}
// Otherwise get fresh profiles and set the cache
prfs, err := s.apiw.Info(ctx)
if err != nil {
return nil, err
}
s.CachedInfo = prfs
return prfs, nil
}


func (b *Base) Profile() (*profiles.Profile, error) {
if s.Profile == nil {
return nil, InvalidProfileErr
}
return s.Profile, nil
}

func (b *Base) API() (*api.API, error) {
if b.apiw == nil {
return nil, errors.New("no API object found")
}
return b.apiw, nil
}

func (b *Base) findProfile(ctx context.Context, prID string, wgSupport bool) (*profile.Profile, error) {
// Get the profiles by ignoring the cache
prfs, err := s.Profiles(ctx, false)
if err != nil {
return nil, err
}

// No profiles available
if prfs.Len() == 0 {
return nil, errors.New("the server has no available profiles for your account")
}

// No WireGuard support, we have to filter the profiles that only have WireGuard
if !wgSupport {
prfs = prfs.FilterWireGuard(protos)
}

var chosenP profiles.Profile

n := prfs.Len()
switch(n) {
// If we now get no profiles then that means a profile with only WireGuard was removed
case 0:
return nil, errors.New("the server has only WireGuard profiles but the client does not support WireGuard")
case 1:
// Only one profile, make sure it is set
chosenP = prfs.MustIndex(0)
default:
// Profile doesn't exist
v := prfs.Get(prID)
if v == nil {
return nil, InvalidProfileErr
}
chosenP = *v
}
return &chosenP, nil
}

func (b *Base) Connect(ctx context.Context, wgSupport bool, pTCP bool) (*api.ConnectData, error) {
a, err := b.API()
if err != nil {
return nil, err
}
prof, err := s.Profile()
if err != nil {
return nil, err
}

// find a suitable profile to connect
chosenP , err := s.findProfile(ctx, s.Profile.ID, wgSupport)
if err != nil {
return nil, err
}
s.Profile = chosenP

protos := []protocol.Protocol{protocol.OpenVPN}
if wgSupport {
protos = append(protos, protocol.WireGuard)
}
// If the client supports WireGuard and the profile supports both protocols we remove openvpn from client support if EDUVPN_PREFER_WG is set to "1"
// This also only happens if prefer TCP is set to false
// TODO: remove the prefer TCP check when we have implemented proxyguard
if wgSupport && os.Getenv("EDUVPN_PREFER_WG", "0") == "1" {
if !pTCP && chosenP.HasWireGuard() && chosenP.HasOpenVPN() {
protos = []protocol.Protocol{Protocol.WireGuard}
}
}
return a.Connect(ctx, chosenP, protos, pTCP)
}

func (b *Base) Disconnect(ctx context.Context) error {
a, err := b.API()
if err != nil {
return err
}
return a.Disconnect(ctx)
}
22 changes: 19 additions & 3 deletions internal/server/custom.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
package server

func (s *Servers) AddCustom(ctx context.Context, url string, na bool) (*Server, error) {
import "github.com/eduvpn/eduvpn-common/types/server"

type CustomServer struct {
Base
}

func (cs *CustomServer) Base() Base {
return cs.Base
}

func (cs *CustomServer) Type() server.Type {
return server.TypeCustom
}

func (s *Servers) AddCustom(ctx context.Context, url string, na bool) (*CustomServer, error) {
// Convert to an identifier
id, err := http.EnsureValidURL(url, true)
if err != nil {
Expand All @@ -17,7 +31,9 @@ func (s *Servers) AddCustom(ctx context.Context, url string, na bool) (*Server,
}

// Return the server with the API
return &Server{
apiw: a,
return &CustomServer{
Base: Base{
apiw: a,,
},
}, nil
}
33 changes: 30 additions & 3 deletions internal/server/institute.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
package server

import "github.com/eduvpn/eduvpn-common/internal/discovery"
import (
"github.com/eduvpn/eduvpn-common/internal/discovery"
"github.com/eduvpn/eduvpn-common/types/server"
)

type InstituteAccess struct {
Base
}

func (ia *InstituteAccess) Base() Base {
return cs.Base
}

func (cs *InstituteAccess) Type() server.Type {
return server.TypeInstituteAccess
}

func (cs *InstituteAccess) BaseURL() (string, error) {
a err := cs.API()
if err != nil {
return "", err
}
}

func (s *Servers) AddInstitute(ctx context.Context, disco *discovery.Discovery, url string, na bool) (*Server, error) {
// Convert to an identifier
Expand All @@ -25,7 +47,12 @@ func (s *Servers) AddInstitute(ctx context.Context, disco *discovery.Discovery,
}

// Return the server with the API
return &Server{
apiw: a,
return &InstituteAccess{
Base: Base{
apiw: a,
},
DisplayName: dsrv.SupportContact,
SupportContact: dsrv.SupportContact,

}, nil
}
34 changes: 24 additions & 10 deletions internal/server/secureinternet.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
package server

import "github.com/eduvpn/eduvpn-common/internal/discovery"
import (
"github.com/eduvpn/eduvpn-common/internal/api"
"github.com/eduvpn/eduvpn-common/internal/discovery"
"github.com/eduvpn/eduvpn-common/types/server"
)

type SecureInternet struct {
Base
HomeORGID string
Location string
}

func (si *SecureInternet) Base() Base {
return si.Base
}

func (si *SecureInternet) Type() server.Type {
return server.TypeSecureInternet
}

func (s *Servers) AddSecure(ctx context.Context, disco *discovery.Discovery, orgID string, na bool) (*Server, error) {
// Convert to an identifier
id, err := http.EnsureValidURL(url, true)
if err != nil {
return nil, err
}

// This is basically done to double check if the server is part of the institute access section of disco
dsrv, err := disco.ServerByURL(id, "institute_access")
func (s *Servers) AddSecure(ctx context.Context, disco *discovery.Discovery, orgID string, na bool) (*SecureInternet, error) {
dOrg, dsrv, err := disco.SecureHomeArgs(orgID)
if err != nil {
return nil, err
}
Expand All @@ -25,7 +37,9 @@ func (s *Servers) AddSecure(ctx context.Context, disco *discovery.Discovery, org
}

// Return the server with the API
return &Server{
return &SecureInternet{
apiw: a,
HomeORGID: dOrg.OrgID,
Location: dsrv.CountryCode,
}, nil
}
105 changes: 11 additions & 94 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,119 +6,36 @@ import (

"github.com/eduvpn/eduvpn-common/internal/api"
"github.com/eduvpn/eduvpn-common/internal/api/profiles"
v2cfg "github.com/eduvpn/eduvpn-common/internal/config/v2"
"github.com/eduvpn/eduvpn-common/internal/http"
"github.com/eduvpn/eduvpn-common/types/protocol"
"github.com/googleapis/gax-go/v2/apierror"
)

type Servers struct {
clientID string
authDone func()
authTrigger func(string) error
wgSupport bool

Current *Server
}

func NewServers(name string, autht func(string) error, authd func()) *Servers {
type Server interface {
Base() Base
}

func NewServers(name string, autht func(string) error, authd func(), wgSupport bool) *Servers {
return &Servers{
clientID: name,
authDone: authd,
authTrigger: autht,
wgSupport: wgSupport,
}
}

type Server struct {
apiw *api.API
CachedInfo *profiles.Info
Profile *profiles.Profile
}

var InvalidProfileErr = errors.New("invalid profile")

func (s *Server) findProfile(ctx context.Context, prID string, wgSupport bool) (*profile.Profile, error) {
// Get the profiles by ignoring the cache
prfs, err := s.Profiles(ctx, true)
if err != nil {
return nil, err
}

// No profiles available
if prfs.Len() == 0 {
return nil, errors.New("the server has no available profiles for your account")
}

// No WireGuard support, we have to filter the profiles that only have WireGuard
if !wgSupport {
prfs = prfs.FilterWireGuard(protos)
}

var chosenP profiles.Profile

n := prfs.Len()
switch(n) {
// If we now get no profiles then that means a profile with only WireGuard was removed
case 0:
return nil, errors.New("the server has only WireGuard profiles but the client does not support WireGuard")
case 1:
// Only one profile, make sure it is set
chosenP = prfs.MustIndex(0)
default:
// Profile doesn't exist
v := prfs.Get(prID)
if v == nil {
return nil, InvalidProfileErr
}
chosenP = *v
}
return &chosenP, nil
}

func (s *Server) Connect(ctx context.Context, prID string, wgSupport bool, pTCP bool) (*api.ConnectData, error) {
protos := []protocol.Protocol{protocol.OpenVPN}
if wgSupport {
protos = append(protos, protocol.WireGuard)
}

// find a suitable profile to connect
chosenP , err := s.findProfile(ctx, prID, wgSupport)
if err != nil {
return nil, err
}
// If the client supports WireGuard and the profile supports both protocols we remove openvpn from client support if EDUVPN_PREFER_WG is set to "1"
// This also only happens if prefer TCP is set to false
// TODO: remove the prefer TCP check when we have implemented proxyguard
if wgSupport && os.Getenv("EDUVPN_PREFER_WG", "0") == "1" {
if !pTCP && chosenP.HasWireGuard() && chosenP.HasOpenVPN() {
protos = []protocol.Protocol{Protocol.WireGuard}
}

}
s.Profile = chosenP
return s.apiw.Connect(ctx, chosenP, protos, pTCP)
func (s *Servers) Connect(ctx context.Context, srv Server, pTCP bool) (*api.ConnectData, error) {
return srv.Base().Connect(ctx, s.wgSupport, pTCP)
}

// Profiles gets the profiles for the server
// It only does a /info network request if the profiles have not been cached
// force indicates whether or not the profiles should be fetched fresh
func (s *Server) Profiles(ctx context.Context, force bool) (*profiles.Info, error) {
// If we have a cached copy we only return that if force is false
if s.CachedInfo != nil && !force {
return s.CachedInfo, nil
}
// Otherwise get fresh profiles and set the cache
prfs, err := s.apiw.Info(ctx)
if err != nil {
return nil, err
}
s.CachedInfo = prfs
return prfs, nil
}


func (s *Server) Profile() (*profiles.Profile, error) {
if s.Profile == nil {
return nil, errors.New("no profile found")
}
return s.Profile, nil
func (s *Servers) Disconnect(ctx context.Context, srv Server) error {
return srv.Base().Disconnect(ctx)
}
Loading

0 comments on commit f37642d

Please sign in to comment.