Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixing VPN server problem with multiple network interface #1156

Merged
merged 7 commits into from
Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions cmd/apps/vpn-server/vpn-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ var (
localPKStr = flag.String("pk", "", "Local PubKey")
localSKStr = flag.String("sk", "", "Local SecKey")
passcode = flag.String("passcode", "", "Passcode to authenticate connecting users")
networkIfc = flag.String("netifc", "", "Default network interface for multiple available interfaces")
secure = flag.Bool("secure", true, "Forbid connections from clients to server local network")
)

Expand Down Expand Up @@ -73,8 +74,9 @@ func main() {
log.Infof("Got app listener, bound to %d", vpnPort)

srvCfg := vpn.ServerConfig{
Passcode: *passcode,
Secure: *secure,
Passcode: *passcode,
Secure: *secure,
NetworkInteface: *networkIfc,
}
srv, err := vpn.NewServer(srvCfg, log)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/skywire-cli/commands/config/update/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ var (
addVPNServerPasscode string
setVPNServerSecure string
setVPNServerAutostart string
setVPNServerNetIfc string
resetVPNServer bool
addSkysocksClientSrv string
resetSkysocksClient bool
Expand Down
4 changes: 4 additions & 0 deletions cmd/skywire-cli/commands/config/update/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func init() {
vpnServerUpdateCmd.Flags().StringVarP(&addVPNServerPasscode, "passwd", "s", "", "add passcode to vpn-server")
vpnServerUpdateCmd.Flags().StringVar(&setVPNServerSecure, "secure", "", "change secure mode status of vpn-server")
vpnServerUpdateCmd.Flags().StringVar(&setVPNServerAutostart, "autostart", "", "change autostart of vpn-server")
vpnServerUpdateCmd.Flags().StringVar(&setVPNServerNetIfc, "netifc", "", "set default network interface")
vpnServerUpdateCmd.Flags().BoolVarP(&resetVPNServer, "reset", "r", false, "reset vpn-server configurations")
}

Expand Down Expand Up @@ -200,6 +201,9 @@ var vpnServerUpdateCmd = &cobra.Command{
if addVPNServerPasscode != "" {
changeAppsConfig(conf, "vpn-server", "--passcode", addVPNServerPasscode)
}
if setVPNServerNetIfc != "" {
changeAppsConfig(conf, "vpn-server", "-netifc", setVPNServerNetIfc)
ersonp marked this conversation as resolved.
Show resolved Hide resolved
}
switch setVPNServerSecure {
case "true":
changeAppsConfig(conf, "vpn-server", "--secure", setVPNServerSecure)
Expand Down
25 changes: 22 additions & 3 deletions internal/vpn/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"
"net"
"strings"
"sync"

"github.com/sirupsen/logrus"
Expand All @@ -29,15 +30,25 @@ type Server struct {

// NewServer creates VPN server instance.
func NewServer(cfg ServerConfig, l logrus.FieldLogger) (*Server, error) {
var defaultNetworkIfc string
s := &Server{
cfg: cfg,
log: l,
ipGen: NewIPGenerator(),
}

defaultNetworkIfc, err := netutil.DefaultNetworkInterface()
if err != nil {
return nil, fmt.Errorf("error getting default network interface: %w", err)
if cfg.NetworkInteface == "" {
defaultNetworkIfcs, err := netutil.DefaultNetworkInterface()
if err != nil {
return nil, fmt.Errorf("error getting default network interface: %w", err)
}
netIfcs, isMultiple := s.checkingNetworkInterface(defaultNetworkIfcs)
if isMultiple {
return nil, fmt.Errorf("multiple default network interface detected, please set once in setting or be single: %v", netIfcs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"multiple default network interfaces detected...set a default one for VPN server or remove one: %v"

Copy link
Member

@jdknives jdknives Apr 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe

ifcs, hasMultiple := s.hasMutipleNetworkInterfaces(...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
defaultNetworkIfc = defaultNetworkIfcs
} else {
defaultNetworkIfc = cfg.NetworkInteface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkInterface

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

l.Infof("Got default network interface: %s", defaultNetworkIfc)
Expand Down Expand Up @@ -316,3 +327,11 @@ func (s *Server) sendServerErrHello(conn net.Conn, status HandshakeStatus) {
s.log.WithError(err).Errorln("Error sending server hello")
}
}

func (s *Server) checkingNetworkInterface(defaultNetworkInterface string) ([]string, bool) {
networkInterfaces := strings.Split(defaultNetworkInterface, "\n")
if len(networkInterfaces) > 1 {
return networkInterfaces, true
}
return []string{}, false
}
5 changes: 3 additions & 2 deletions internal/vpn/server_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package vpn

// ServerConfig is a configuration for VPN server.
type ServerConfig struct {
Passcode string
Secure bool
Passcode string
Secure bool
NetworkInteface string
}
22 changes: 22 additions & 0 deletions pkg/visor/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type API interface {
SetAppPK(appName string, pk cipher.PubKey) error
SetAppSecure(appName string, isSecure bool) error
SetAppKillswitch(appName string, killswitch bool) error
SetAppNetworkInterface(appName string, netifc string) error
LogsSince(timestamp time.Time, appName string) ([]string, error)
GetAppStats(appName string) (appserver.AppStats, error)
GetAppError(appName string) (string, error)
Expand Down Expand Up @@ -411,6 +412,27 @@ func (v *Visor) SetAppPassword(appName, password string) error {
return nil
}

// SetAppNetworkInterface implements API.
func (v *Visor) SetAppNetworkInterface(appName, netifc string) error {
if skyenv.VPNServerName != appName {
return fmt.Errorf("app %s is not allowed to set network interface", appName)
}

v.log.Infof("Changing %s network interface to %q", appName, netifc)

const (
netifcArgName = "-netifc"
)

if err := v.conf.UpdateAppArg(v.appL, appName, netifcArgName, netifc); err != nil {
return err
}

v.log.Infof("Updated %v network interface", appName)

return nil
}

// SetAppKillswitch implements API.
func (v *Visor) SetAppKillswitch(appName string, killswitch bool) error {
if appName != skyenv.VPNClientName {
Expand Down
10 changes: 9 additions & 1 deletion pkg/visor/hypervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,13 +604,14 @@ func (hv *Hypervisor) putApp() http.HandlerFunc {
Secure *bool `json:"secure,omitempty"`
Status *int `json:"status,omitempty"`
Passcode *string `json:"passcode,omitempty"`
NetIfc *string `json:"netifc,omitempty"`
PK *cipher.PubKey `json:"pk,omitempty"`
}

shouldRestartApp := func(r req) bool {
// we restart the app if one of these fields was changed
return r.Killswitch != nil || r.Secure != nil || r.Passcode != nil ||
r.PK != nil
r.PK != nil || r.NetIfc != nil
}

var reqBody req
Expand Down Expand Up @@ -661,6 +662,13 @@ func (hv *Hypervisor) putApp() http.HandlerFunc {
}
}

if reqBody.NetIfc != nil {
if err := ctx.API.SetAppNetworkInterface(ctx.App.Name, *reqBody.NetIfc); err != nil {
httputil.WriteJSON(w, r, http.StatusInternalServerError, err)
return
}
}

if shouldRestartApp(reqBody) {
if err := ctx.API.RestartApp(ctx.App.Name); err != nil {
httputil.WriteJSON(w, r, http.StatusInternalServerError, err)
Expand Down
13 changes: 13 additions & 0 deletions pkg/visor/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,19 @@ func (r *RPC) SetAppPassword(in *SetAppPasswordIn, _ *struct{}) (err error) {
return r.visor.SetAppPassword(in.AppName, in.Password)
}

// SetAppNetworkInterfaceIn is input for SetAppNetworkInterface.
type SetAppNetworkInterfaceIn struct {
AppName string
NetIfc string
}

// SetAppNetworkInterface sets network interface for the app.
func (r *RPC) SetAppNetworkInterface(in *SetAppNetworkInterfaceIn, _ *struct{}) (err error) {
defer rpcutil.LogCall(r.log, "SetAppNetworkInterface", in)(nil, &err)

return r.visor.SetAppNetworkInterface(in.AppName, in.NetIfc)
}

// SetAppPKIn is input for SetAppPK.
type SetAppPKIn struct {
AppName string
Expand Down
23 changes: 23 additions & 0 deletions pkg/visor/rpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ func (rc *rpcClient) SetAppKillswitch(appName string, killswitch bool) error {
}, &struct{}{})
}

// SetAppKillswitch implements API.
func (rc *rpcClient) SetAppNetworkInterface(appName, netifc string) error {
return rc.Call("SetAppNetworkInterface", &SetAppNetworkInterfaceIn{
AppName: appName,
NetIfc: netifc,
}, &struct{}{})
}

// SetAppSecure implements API.
func (rc *rpcClient) SetAppSecure(appName string, isSecure bool) error {
return rc.Call("SetAppSecure", &SetAppBoolIn{
Expand Down Expand Up @@ -743,6 +751,21 @@ func (mc *mockRPCClient) SetAppPassword(string, string) error {
})
}

// SetAppPassword implements API.
func (mc *mockRPCClient) SetAppNetworkInterface(string, string) error {
return mc.do(true, func() error {
const vpnServerName = "vpn-server"

for i := range mc.o.Apps {
if mc.o.Apps[i].Name == vpnServerName {
return nil
}
}

return fmt.Errorf("app of name '%s' does not exist", vpnServerName)
})
}

// SetAppPK implements API.
func (mc *mockRPCClient) SetAppPK(string, cipher.PubKey) error {
return mc.do(true, func() error {
Expand Down