Skip to content

Commit

Permalink
Merge pull request #356 from Darkren/feature/vpn-improvements
Browse files Browse the repository at this point in the history
VPN improvements

Former-commit-id: 49ef1cf
  • Loading branch information
志宇 authored May 21, 2020
2 parents 92b4461 + ae8df9e commit b918e10
Show file tree
Hide file tree
Showing 258 changed files with 43,960 additions and 536 deletions.
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [Run `skywire-visor`](#run-skywire-visor)
- [Run `skywire-cli`](#run-skywire-cli)
- [Run `hypervisor`](#run-hypervisor)
- [Windows](#windows)
- [Apps](#Apps)
- [App Programming API](#app-programming-api)
- [Transports](#Transports)
Expand Down Expand Up @@ -120,6 +121,43 @@ $ hypervisor

You can open up the hypervisor UI on `localhost:8000`.

### Windows

Skywire node may be run on Windows, but this process requires some manual operations at the moment.

In order to run the skywire visor on Windows, you will need to manually build it. Do not forget the `.exe` extensions.

`go build -o ./skywire-visor.exe ./cmd/skywire-visor`

Apps may be built the same way:

`go build -o ./apps/vpn-client.exe ./cmd/apps/vpn-client`

Apps should be stated in the config without `.exe` extension, as usual.

Some log lines may seem strange due to the Windows encoding in terminal. To make life easier you may change encoding to UTF-8 executing:
```
CHCP 65001
```

#### Not Supported Features

- `dmsgpty`
- `syslog`

Trying to run these will result in failure.

#### Running VPN

Running VPN on Windows requires `wintun` driver to be installed. This may be achieved by installing the driver itself, or simply installing `Wireguard` which installs this driver too.

VPN client requires `local system` user rights to be run. This may be achieved by downloading `PsExec`: https://docs.microsoft.com/en-us/sysinternals/downloads/psexec . Then you may run terminal with the `local system` rights like this:
```
PsExec.exe -i -s C:\Windows\system32\cmd.exe
```

And then simply run skywire from the opened terminal.

### Apps

After `skywire-visor` is up and running with default environment, default apps are run with the configuration specified in `skywire-config.json`. Refer to the following for usage of the apps:
Expand Down
47 changes: 47 additions & 0 deletions cmd/apps/vpn-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Skywire VPN client app

`vpn-client` app implements client for the VPN server app.

It opens persistent `skywire` connection to the configured remote visor. This connection is used as a tunnel. Client forwards all the traffic through that tunnel to the VPN server.

## Configuration

Additional arguments may be passed to the application via `args` array. These are:
- `-srv` (required) - is a public key of the remove VPN server;
- `-passcode` - passcode to authenticate connection. Optional, may be omitted.

Full config of the client should look like this:
```json5
{
"app": "vpn-client",
"auto_start": false,
"port": 43,
"args": [
"-srv",
"03e9019b3caa021dbee1c23e6295c6034ab4623aec50802fcfdd19764568e2958d",
"-passcode",
"1234"
]
}
```

## Running app

Compile app binary and start a visor:

```sh
$ go build -o apps/vpn-client ./cmd/apps/vpn-client
$ ./skywire-visor skywire-config.json
```

You should be able to see an additional hop with the `traceroute`-like utils:

```sh
$ traceroute google.com
```

Also, your IP should be detected as the IP of the VPN server:

```sh
$ curl https://api.ipify.org
```
76 changes: 56 additions & 20 deletions cmd/apps/vpn-client/vpn-client.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,19 @@ var (
r = netutil.NewRetrier(log, serverDialInitBO, serverDialMaxBO, 0, 1)
)

var serverPKStr = flag.String("srv", "", "PubKey of the server to connect to")

func dialServer(appCl *app.Client, pk cipher.PubKey) (net.Conn, error) {
var conn net.Conn
err := r.Do(context.Background(), func() error {
var err error
conn, err = appCl.Dial(appnet.Addr{
Net: netType,
PubKey: pk,
Port: vpnPort,
})
return err
})
if err != nil {
return nil, err
}

return conn, nil
}
var (
serverPKStr = flag.String("srv", "", "PubKey of the server to connect to")
localPKStr = flag.String("pk", "", "Local PubKey")
localSKStr = flag.String("sk", "", "Local SecKey")
passcode = flag.String("passcode", "", "Passcode to authenticate connection")
)

func main() {
flag.Parse()

if *serverPKStr == "" {
// TODO: fix args passage for Windows
//*serverPKStr = "03e9019b3caa021dbee1c23e6295c6034ab4623aec50802fcfdd19764568e2958d"
log.Fatalln("VPN server pub key is missing")
}

Expand All @@ -67,6 +56,31 @@ func main() {
log.WithError(err).Fatalln("Invalid VPN server pub key")
}

localPK := cipher.PubKey{}
if *localPKStr != "" {
if err := localPK.UnmarshalText([]byte(*localPKStr)); err != nil {
log.WithError(err).Fatalln("Invalid local PK")
}
}

localSK := cipher.SecKey{}
if *localSKStr != "" {
if err := localSK.UnmarshalText([]byte(*localSKStr)); err != nil {
log.WithError(err).Fatalln("Invalid local SK")
}
}

var noiseCreds vpn.NoiseCredentials
if localPK.Null() && !localSK.Null() {
var err error
noiseCreds, err = vpn.NewNoiseCredentialsFromSK(localSK)
if err != nil {
log.WithError(err).Fatalln("error creating noise credentials")
}
} else {
noiseCreds = vpn.NewNoiseCredentials(localSK, localPK)
}

appClient := app.NewClient()
defer appClient.Close()

Expand All @@ -84,7 +98,11 @@ func main() {

log.Infof("Dialed %s", appConn.RemoteAddr())

vpnClient, err := vpn.NewClient(log, appConn)
vpnClientCfg := vpn.ClientConfig{
Passcode: *passcode,
Credentials: noiseCreds,
}
vpnClient, err := vpn.NewClient(vpnClientCfg, log, appConn)
if err != nil {
log.WithError(err).Fatalln("Error creating VPN client")
}
Expand All @@ -104,3 +122,21 @@ func main() {
log.WithError(err).Fatalln("Error serving VPN")
}
}

func dialServer(appCl *app.Client, pk cipher.PubKey) (net.Conn, error) {
var conn net.Conn
err := r.Do(context.Background(), func() error {
var err error
conn, err = appCl.Dial(appnet.Addr{
Net: netType,
PubKey: pk,
Port: vpnPort,
})
return err
})
if err != nil {
return nil, err
}

return conn, nil
}
35 changes: 35 additions & 0 deletions cmd/apps/vpn-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Skywire VPN server app

`vpn-server` app implements VPN functionality over skywire net.

Currently the server supports authentication with a passcode that is set in the configuration file.
If none is provided, the server does not require authentication.

NOTE: in contrast with the proxy apps, VPN server and client must be run on different machines because of the networking features.

## Configuration

Additional arguments may be passed to the application via `args` array. These are:
- `-passcode` - passcode to authenticate incoming connections. Optional, may be omitted.

Full config of the server should look like this:
```json5
{
"app": "vpn-server",
"auto_start": true,
"port": 44,
"args": [
"-passcode",
"1234"
]
}
```

## Running app

Compile app binary and start a visor:

```sh
$ go build -o apps/vpn-server ./cmd/apps/vpn-server
$ ./skywire-visor skywire-config.json
```
41 changes: 40 additions & 1 deletion cmd/apps/vpn-server/vpn-server.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package main

import (
"flag"
"os"
"os/signal"
"syscall"

"github.com/SkycoinProject/dmsg/cipher"
"github.com/sirupsen/logrus"

"github.com/SkycoinProject/skywire-mainnet/internal/vpn"
Expand All @@ -23,7 +25,40 @@ var (
log = logrus.New()
)

var (
localPKStr = flag.String("pk", "", "Local PubKey")
localSKStr = flag.String("sk", "", "Local SecKey")
passcode = flag.String("passcode", "", "Passcode to authenticate connecting users")
)

func main() {
flag.Parse()

localPK := cipher.PubKey{}
if *localPKStr != "" {
if err := localPK.UnmarshalText([]byte(*localPKStr)); err != nil {
log.WithError(err).Fatalln("Invalid local PK")
}
}

localSK := cipher.SecKey{}
if *localSKStr != "" {
if err := localSK.UnmarshalText([]byte(*localSKStr)); err != nil {
log.WithError(err).Fatalln("Invalid local SK")
}
}

var noiseCreds vpn.NoiseCredentials
if localPK.Null() && !localSK.Null() {
var err error
noiseCreds, err = vpn.NewNoiseCredentialsFromSK(localSK)
if err != nil {
log.WithError(err).Fatalln("error creating noise credentials")
}
} else {
noiseCreds = vpn.NewNoiseCredentials(localSK, localPK)
}

appClient := app.NewClient()
defer appClient.Close()

Expand All @@ -42,7 +77,11 @@ func main() {

log.Infof("Got app listener, bound to %d", vpnPort)

srv, err := vpn.NewServer(log)
srvCfg := vpn.ServerConfig{
Passcode: *passcode,
Credentials: noiseCreds,
}
srv, err := vpn.NewServer(srvCfg, log)
if err != nil {
log.WithError(err).Fatalln("Error creating VPN server")
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/setup-node/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ import (
"io"
"io/ioutil"
"log"
"log/syslog"
"net/http"
"os"

"github.com/SkycoinProject/skycoin/src/util/logging"
"github.com/prometheus/client_golang/prometheus/promhttp"
logrussyslog "github.com/sirupsen/logrus/hooks/syslog"
"github.com/spf13/cobra"

"github.com/SkycoinProject/skywire-mainnet/pkg/metrics"
"github.com/SkycoinProject/skywire-mainnet/pkg/setup"
"github.com/SkycoinProject/skywire-mainnet/pkg/syslog"
"github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo"
)

Expand All @@ -37,10 +36,11 @@ var rootCmd = &cobra.Command{

logger := logging.MustGetLogger(tag)
if syslogAddr != "" {
hook, err := logrussyslog.NewSyslogHook("udp", syslogAddr, syslog.LOG_INFO, tag)
hook, err := syslog.SetupHook(syslogAddr, tag)
if err != nil {
logger.Fatalf("Unable to connect to syslog daemon on %v", syslogAddr)
log.Fatalf("Error setting up syslog: %v", err)
}

logging.AddHook(hook)
}

Expand Down
5 changes: 2 additions & 3 deletions cmd/skywire-visor/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@ import (
"fmt"
"io"
"io/ioutil"
"log/syslog"
"net/http"
_ "net/http/pprof" //nolint:gosec // https://golang.org/doc/diagnostics.html#profiling
"os"

"github.com/SkycoinProject/dmsg/cmdutil"
"github.com/SkycoinProject/skycoin/src/util/logging"
"github.com/pkg/profile"
logrussyslog "github.com/sirupsen/logrus/hooks/syslog"
"github.com/spf13/cobra"

"github.com/SkycoinProject/skywire-mainnet/pkg/restart"
"github.com/SkycoinProject/skywire-mainnet/pkg/syslog"
"github.com/SkycoinProject/skywire-mainnet/pkg/util/buildinfo"
"github.com/SkycoinProject/skywire-mainnet/pkg/visor"
"github.com/SkycoinProject/skywire-mainnet/pkg/visor/visorconfig"
Expand Down Expand Up @@ -85,7 +84,7 @@ func initLogger(tag string, syslogAddr string) *logging.MasterLogger {
log := logging.NewMasterLogger()

if syslogAddr != "" {
hook, err := logrussyslog.NewSyslogHook("udp", syslogAddr, syslog.LOG_INFO, tag)
hook, err := syslog.SetupHook(syslogAddr, tag)
if err != nil {
log.WithError(err).Error("Failed to connect to the syslog daemon.")
} else {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ require (
golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc // indirect
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b
golang.org/x/sys v0.0.0-20200428200454-593003d681fa // indirect
golang.org/x/text v0.3.2 // indirect
golang.zx2c4.com/wireguard v0.0.20200320
)

// Uncomment for tests with alternate branches of 'dmsg'
Expand Down
Loading

0 comments on commit b918e10

Please sign in to comment.