first commit of client
hard coded values and fairly limited error handling
This commit is contained in:
parent
119c9937d7
commit
663caa5cc7
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"git.daplie.com/Daplie/go-rvpn-server/rvpn/client"
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
func main() {
|
||||
tokenData := jwt.MapClaims{
|
||||
"domains": []string{
|
||||
"localhost.foo.daplie.me",
|
||||
"localhost.bar.daplie.me",
|
||||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, tokenData)
|
||||
tokenStr, err := token.SignedString([]byte("abc123"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
config := client.Config{
|
||||
Server: "wss://localhost.daplie.me:9999",
|
||||
Services: map[string]int{"https": 8443},
|
||||
Token: tokenStr,
|
||||
Insecure: true,
|
||||
}
|
||||
panic(client.Run(&config))
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net/url"
|
||||
|
||||
"fmt"
|
||||
|
||||
"git.daplie.com/Daplie/go-rvpn-server/rvpn/packer"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Server string
|
||||
Token string
|
||||
Services map[string]int
|
||||
Insecure bool
|
||||
}
|
||||
|
||||
func Run(config *Config) error {
|
||||
serverURL, err := url.Parse(config.Server)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Invalid server URL: %v", err)
|
||||
}
|
||||
if serverURL.Scheme == "" {
|
||||
serverURL.Scheme = "wss"
|
||||
}
|
||||
serverURL.Path = ""
|
||||
|
||||
query := make(url.Values)
|
||||
query.Set("access_token", config.Token)
|
||||
serverURL.RawQuery = query.Encode()
|
||||
|
||||
dialer := websocket.Dialer{}
|
||||
if config.Insecure {
|
||||
dialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
|
||||
conn, _, err := dialer.Dial(serverURL.String(), nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("First connection to server failed - check auth: %v", err)
|
||||
}
|
||||
|
||||
localConns := newLocalConns(conn, config.Services)
|
||||
for {
|
||||
_, message, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return fmt.Errorf("websocket read errored: %v", err)
|
||||
}
|
||||
|
||||
p, err := packer.ReadMessage(message)
|
||||
if err != nil {
|
||||
return fmt.Errorf("packer read failed: %v", err)
|
||||
}
|
||||
|
||||
err = localConns.Write(p)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write data: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"io"
|
||||
|
||||
"git.daplie.com/Daplie/go-rvpn-server/rvpn/packer"
|
||||
)
|
||||
|
||||
type localConns struct {
|
||||
lock sync.RWMutex
|
||||
locals map[string]net.Conn
|
||||
services map[string]int
|
||||
remote *websocket.Conn
|
||||
}
|
||||
|
||||
func newLocalConns(remote *websocket.Conn, services map[string]int) *localConns {
|
||||
l := new(localConns)
|
||||
l.services = services
|
||||
l.remote = remote
|
||||
l.locals = make(map[string]net.Conn)
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *localConns) Write(p *packer.Packer) error {
|
||||
l.lock.RLock()
|
||||
defer l.lock.RUnlock()
|
||||
|
||||
key := fmt.Sprintf("%s:%d", p.Header.Address(), p.Header.Port)
|
||||
if conn := l.locals[key]; conn != nil {
|
||||
_, err := conn.Write(p.Data.Data())
|
||||
return err
|
||||
}
|
||||
|
||||
go l.startConnection(p)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *localConns) startConnection(orig *packer.Packer) {
|
||||
key := fmt.Sprintf("%s:%d", orig.Header.Address(), orig.Header.Port)
|
||||
addr := fmt.Sprintf("127.0.0.1:%d", l.services[orig.Header.Service])
|
||||
conn, err := net.Dial("tcp", addr)
|
||||
if err != nil {
|
||||
loginfo.Println("failed to open connection to", addr, err)
|
||||
return
|
||||
}
|
||||
loginfo.Println("opened connection to", addr, "with key", key)
|
||||
defer loginfo.Println("finished connection to", addr, "with key", key)
|
||||
|
||||
conn.Write(orig.Data.Data())
|
||||
|
||||
l.lock.Lock()
|
||||
l.locals[key] = conn
|
||||
l.lock.Unlock()
|
||||
defer func() {
|
||||
l.lock.Lock()
|
||||
delete(l.locals, key)
|
||||
l.lock.Unlock()
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
size, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
loginfo.Println("failed to read from local connection to", addr, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
p := packer.NewPacker()
|
||||
p.Header = orig.Header
|
||||
p.Data.AppendBytes(buf[:size])
|
||||
packed := p.PackV1()
|
||||
l.remote.WriteMessage(websocket.BinaryMessage, packed.Bytes())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
|
||||
)
|
||||
|
||||
var (
|
||||
loginfo = log.New(os.Stdout, "INFO: client: ", logFlags)
|
||||
logdebug = log.New(os.Stdout, "DEBUG: client:", logFlags)
|
||||
)
|
Loading…
Reference in New Issue