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

VPN improvements #356

Merged
merged 71 commits into from
May 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
9221ab3
Add passcode to config generation
Darkren Apr 30, 2020
bf3c651
FUlly add passcode
Darkren Apr 30, 2020
c9ac661
Fix `String` for `HandshakeStatus`
Darkren Apr 30, 2020
8de36e6
Add debug log
Darkren Apr 30, 2020
d5a53b0
Fix passcode passing to the server
Darkren Apr 30, 2020
edddef5
Remove debug log
Darkren Apr 30, 2020
7ffaa13
Make lintr happy
Darkren Apr 30, 2020
9ad76c9
Remove redundant logs
Darkren May 1, 2020
3520b80
Add RPC calls to change passcode and PK for VPN apps
Darkren May 1, 2020
a49778a
Make linter happy
Darkren May 1, 2020
fe810c4
Add `README.md` for VPN client
Darkren May 4, 2020
bffe337
Add `README.md` for VPN server, fix client's one a bit
Darkren May 4, 2020
53deb0a
Make default network gateway detection work via `ip r` for Linux systems
Darkren May 4, 2020
a33d0a0
Fix default network gateway detection
Darkren May 4, 2020
8f6a3f6
Fix it once again
Darkren May 4, 2020
249e20b
Make TUN setup go via `ip` for Linux systems
Darkren May 4, 2020
253ca86
Fix Linux code
Darkren May 4, 2020
460be43
Try to fix
Darkren May 4, 2020
7768f2a
Make all routing be done via 'ip` for Linux systems
Darkren May 4, 2020
446b17b
Remove some duplicate code
Darkren May 4, 2020
1f87aae
Substitute logrus sys log hook with our wrapper
Darkren May 5, 2020
da60cdf
Implement `DefaultNetworkGateway` for Windows
Darkren May 5, 2020
9ec65d2
Finish TUN setup for Windows
Darkren May 6, 2020
37ad9b2
Fix sys log build for Windows
Darkren May 6, 2020
8aac4ea
Merge branch 'feature/vpn-improvements' of https://github.com/Darkren…
Darkren May 6, 2020
ee66dc1
Refactor all os-related funcs
Darkren May 6, 2020
6153391
Fix `DefaultNetworkInterface` for Linux systems
Darkren May 6, 2020
932d4df
Add routing commands for Windows
Darkren May 6, 2020
4f397ae
Merge branch 'feature/vpn-improvements' of https://github.com/Darkren…
Darkren May 6, 2020
1bdbb57
Remove dmsgpty config generation for Windows subsystems
Darkren May 6, 2020
08f6822
Remove dmsgpty references from visor package
Darkren May 6, 2020
20e16a3
Let it be built for Windows systems
Darkren May 6, 2020
3825d18
Fix dmsgpty setup for Windows
Darkren May 6, 2020
18a8c95
Fix it once again
Darkren May 6, 2020
3be46ce
Try to use TAP server side for Windows clients
Darkren May 10, 2020
707b6dd
Fix
Darkren May 10, 2020
d72d3dc
Fix
Darkren May 10, 2020
5df97df
Fix
Darkren May 10, 2020
6f6539a
Fix
Darkren May 10, 2020
ed482b7
Fix
Darkren May 10, 2020
c64169e
Start integrating wintun
Darkren May 12, 2020
6d52894
Udate vendor
Darkren May 12, 2020
eefecd8
Revert testing changes
Darkren May 12, 2020
a34de8f
Finish wintun integration
Darkren May 12, 2020
e8ceecc
Add a bit TODOs
Darkren May 12, 2020
d9db49c
Refactor VPN part
Darkren May 12, 2020
6d72de1
Refactor main CMDs and syslog
Darkren May 13, 2020
3b80055
Refactor hypervisor
Darkren May 13, 2020
24d09ea
Refactor visor
Darkren May 13, 2020
b83cc10
Make linter happy
Darkren May 13, 2020
d19959b
Update vendor
Darkren May 13, 2020
2965a61
Try to integrate noise
Darkren May 13, 2020
98cf951
Add more logging
Darkren May 13, 2020
7256fce
Improve logging
Darkren May 14, 2020
8172ee2
Fix
Darkren May 14, 2020
84630de
Fix
Darkren May 14, 2020
ac33837
Fix
Darkren May 14, 2020
126b36c
Pass PK and SK as binary args
Darkren May 14, 2020
dc69941
Add noise handshake
Darkren May 14, 2020
0376dfb
Refactor encryption
Darkren May 14, 2020
336714a
Merge branch 'develop' of github.com:SkycoinProject/skywire-mainnet i…
Darkren May 18, 2020
ef4516e
Fix VPN envs
Darkren May 18, 2020
ca4d96e
Remove panic
Darkren May 19, 2020
e80813a
Make linter happier
Darkren May 19, 2020
a66b6ef
Add Windows info to README
Darkren May 20, 2020
6b7fe69
Exclude dmsgpty config generation for Windows systems
Darkren May 21, 2020
90a96f4
Disallow socket files removal for Windows systems
Darkren May 21, 2020
7851388
Add an ability to derive PK out of SK for noise creds
Darkren May 21, 2020
46c9f9f
Refactor a bit
Darkren May 21, 2020
dd1966c
Refactor, make VPN server autostart velue false by default
Darkren May 21, 2020
8057e79
Merge branch 'develop' of github.com:SkycoinProject/skywire-mainnet i…
Darkren May 21, 2020
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
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