Added support for YAML configuration file

- implemented viper module in code.
- removed all the older configuration, not sure if we want to use flags or just the configuration files.
- added support for dwell, idle and cancelceck timers
- generic binding is now an int passing to the generic manager.
- passing dwell, and idle directly to connection table.
- adjusted all dead time structures, the system supports a map(string)interface{} of various dead time counters
- this version also supports variable sized buffers for each request by using the bufio.reader
- we peek all, and then pass everything down the channel we have.
- I am wondering if this will be a problem is someone just starts pouring data down never ending.
- direct support now for terminating domains
- there is a domain for admin, and wss.  Each shared the external address listener (testing 9999)

Additions
- added support for Discard for wedge connections
- added support for ReadByte to wedge conn
This commit is contained in:
Henry Camacho 2017-03-11 14:28:49 -06:00
parent 2fc5cf5e69
commit 74591fd150
6 changed files with 120 additions and 42 deletions

16
go-rvpn-server.yaml Normal file
View File

@ -0,0 +1,16 @@
rvpn:
wssdomain: localhost.daplie.me
admindomain: rvpn.daplie.invalid
genericlistener: 9999
deadtime:
dwell: 600
idle: 60
cancelcheck: 10
domains:
test.daplie.me:
secret: abc123
test2.daplie.me:
secret: abc123
test3.daplie.me:
secret: abc123

42
main.go
View File

@ -8,6 +8,8 @@ import (
"os"
"time"
"github.com/spf13/viper"
"context"
"git.daplie.com/Daplie/go-rvpn-server/rvpn/genericlistener"
@ -18,7 +20,7 @@ var (
logdebug *log.Logger
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
argWssClientListener string
argGenericBinding string
argGenericBinding int
argServerBinding string
argServerAdminBinding string
argServerExternalBinding string
@ -26,25 +28,43 @@ var (
connectionTable *genericlistener.Table
secretKey = "abc123"
wssHostName = "localhost.daplie.me"
adminHostName = "rvpn.daplie.invalid"
idle int
dwell int
cancelcheck int
)
func init() {
flag.IntVar(&argDeadTime, "dead-time-counter", 5, "deadtime counter in seconds")
flag.StringVar(&argGenericBinding, "generic-listener", ":8443", "generic SSL Listener")
flag.StringVar(&argWssClientListener, "wss-client-listener", ":3502", "wss client listener address:port")
flag.StringVar(&argServerAdminBinding, "admin-server-port", "127.0.0.2:8000", "admin server Bind listener")
flag.StringVar(&argServerExternalBinding, "external-server-port", "127.0.0.1:8080", "external server Bind listener")
}
//Main -- main entry point
func main() {
flag.Parse()
loginfo = log.New(os.Stdout, "INFO: main: ", logFlags)
logdebug = log.New(os.Stdout, "DEBUG: main:", logFlags)
viper.SetConfigName("go-rvpn-server")
viper.AddConfigPath("./")
err := viper.ReadInConfig()
if err != nil {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
loginfo = log.New(os.Stdout, "INFO: packer: ", logFlags)
logdebug = log.New(os.Stdout, "DEBUG: packer:", logFlags)
flag.IntVar(&argDeadTime, "dead-time-counter", 5, "deadtime counter in seconds")
wssHostName = viper.Get("rvpn.wssdomain").(string)
adminHostName = viper.Get("rvpn.admindomain").(string)
argGenericBinding = viper.GetInt("rvpn.genericlistener")
deadtime := viper.Get("rvpn.deadtime")
idle = deadtime.(map[string]interface{})["idle"].(int)
dwell = deadtime.(map[string]interface{})["dwell"].(int)
cancelcheck = deadtime.(map[string]interface{})["cancelcheck"].(int)
loginfo.Println("startup")
loginfo.Println(viper.Get("rvpn.genericlisteners"))
loginfo.Println(viper.Get("rvpn.domains"))
fmt.Println("-=-=-=-=-=-=-=-=-=-=")
certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem")
@ -68,11 +88,11 @@ func main() {
connectionTracking := genericlistener.NewTracking()
go connectionTracking.Run(ctx)
connectionTable = genericlistener.NewTable()
connectionTable = genericlistener.NewTable(dwell, idle)
go connectionTable.Run(ctx)
genericListeners := genericlistener.NewGenerListeners(ctx, connectionTable, connectionTracking, secretKey, certbundle, argDeadTime, wssHostName)
go genericListeners.Run(ctx, 9999)
genericListeners := genericlistener.NewGenerListeners(ctx, connectionTable, connectionTracking, secretKey, certbundle, wssHostName, adminHostName, cancelcheck)
go genericListeners.Run(ctx, argGenericBinding)
//Run for 10 minutes and then shutdown cleanly
time.Sleep(600 * time.Second)

View File

@ -27,11 +27,21 @@ func NewWedgeConnSize(c net.Conn, size int) (p *WedgeConn) {
return
}
//Discard - discard a number of bytes, perhaps after peeking at the
func (w *WedgeConn) Discard(n int) (discarded int, err error) {
return w.reader.Discard(n)
}
//Peek - Get a number of bytes outof the buffer, but allow the buffer to be replayed once read
func (w *WedgeConn) Peek(n int) ([]byte, error) {
return w.reader.Peek(n)
}
//ReadByte -- A normal reader.
func (w *WedgeConn) ReadByte() (byte, error) {
return w.reader.ReadByte()
}
//Read -- A normal reader.
func (w *WedgeConn) Read(p []byte) (int, error) {
cnt, err := w.reader.Read(p)

View File

@ -17,10 +17,12 @@ type Table struct {
unregister chan *Connection
domainAnnounce chan *DomainMapping
domainRevoke chan *DomainMapping
dwell int
idle int
}
//NewTable -- consructor
func NewTable() (p *Table) {
func NewTable(dwell int, idle int) (p *Table) {
p = new(Table)
p.connections = make(map[*Connection][]string)
p.domains = make(map[string]*Connection)
@ -28,6 +30,8 @@ func NewTable() (p *Table) {
p.unregister = make(chan *Connection)
p.domainAnnounce = make(chan *DomainMapping)
p.domainRevoke = make(chan *DomainMapping)
p.dwell = dwell
p.idle = idle
return
}
@ -66,7 +70,7 @@ func (c *Table) reaper(delay int, idle int) {
func (c *Table) Run(ctx context.Context) {
loginfo.Println("ConnectionTable starting")
go c.reaper(3000, 60)
go c.reaper(c.dwell, c.idle)
for {
select {

View File

@ -31,10 +31,11 @@ const (
ctxSecretKey contextKey = "secretKey"
ctxConnectionTable contextKey = "connectionTable"
ctxConfig contextKey = "config"
ctxDeadTime contextKey = "deadtime"
ctxListenerRegistration contextKey = "listenerRegistration"
ctxConnectionTrack contextKey = "connectionTrack"
ctxWssHostName contextKey = "wsshostname"
ctxAdminHostName contextKey = "adminHostName"
ctxCancelCheck contextKey = "cancelcheck"
)
const (
@ -52,11 +53,10 @@ const (
// - if TLS, consume connection with TLS certbundle, pass to request identifier
// - else, just pass to the request identififer
func GenericListenAndServe(ctx context.Context, listenerRegistration *ListenerRegistration) {
loginfo.Println(":" + string(listenerRegistration.port))
cancelCheck := ctx.Value(ctxCancelCheck).(int)
listenAddr, err := net.ResolveTCPAddr("tcp", ":"+strconv.Itoa(listenerRegistration.port))
deadTime := ctx.Value(ctxDeadTime).(int)
if nil != err {
loginfo.Println(err)
@ -81,12 +81,10 @@ func GenericListenAndServe(ctx context.Context, listenerRegistration *ListenerRe
loginfo.Println("Cancel signal hit")
return
default:
ln.SetDeadline(time.Now().Add(time.Duration(deadTime) * time.Second))
ln.SetDeadline(time.Now().Add(time.Duration(cancelCheck) * time.Second))
conn, err := ln.Accept()
loginfo.Println("Deadtime reached")
if nil != err {
if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
continue
@ -160,6 +158,8 @@ func handleConnection(ctx context.Context, wConn *WedgeConn) {
}
wssHostName := ctx.Value(ctxWssHostName).(string)
adminHostName := ctx.Value(ctxAdminHostName).(string)
sniHostName, err := getHello(peek)
if err != nil {
loginfo.Println(err)
@ -168,14 +168,8 @@ func handleConnection(ctx context.Context, wConn *WedgeConn) {
loginfo.Println("sni:", sniHostName)
if wssHostName != sniHostName {
//traffic not terminating on the rvpn do not decrypt
loginfo.Println("processing non terminating traffic")
handleExternalHTTPRequest(ctx, wConn, sniHostName, "https")
}
loginfo.Println("processing traffic terminating on RVPN")
if sniHostName == wssHostName {
//handle WSS Path
tlsListener := tls.NewListener(oneConn, config)
conn, err := tlsListener.Accept()
@ -187,6 +181,26 @@ func handleConnection(ctx context.Context, wConn *WedgeConn) {
tlsWedgeConn := NewWedgeConn(conn)
handleStream(ctx, tlsWedgeConn)
return
} else if sniHostName == adminHostName {
// handle admin path
tlsListener := tls.NewListener(oneConn, config)
conn, err := tlsListener.Accept()
if err != nil {
loginfo.Println(err)
return
}
tlsWedgeConn := NewWedgeConn(conn)
handleStream(ctx, tlsWedgeConn)
return
} else {
//traffic not terminating on the rvpn do not decrypt
loginfo.Println("processing non terminating traffic", wssHostName, sniHostName)
handleExternalHTTPRequest(ctx, wConn, sniHostName, "https")
}
}
loginfo.Println("Handle Unencrypted")
@ -257,7 +271,7 @@ func handleStream(ctx context.Context, wConn *WedgeConn) {
//handleExternalHTTPRequest -
// - get a wConn and start processing requests
func handleExternalHTTPRequest(ctx context.Context, extConn net.Conn, hostname string, service string) {
func handleExternalHTTPRequest(ctx context.Context, extConn *WedgeConn, hostname string, service string) {
connectionTracking := ctx.Value(ctxConnectionTrack).(*Tracking)
defer func() {
@ -286,13 +300,17 @@ func handleExternalHTTPRequest(ctx context.Context, extConn net.Conn, hostname s
return
}
var buffer [1024]byte
for {
cnt, err := extConn.Read(buffer[0:])
buffer, err := extConn.PeekAll()
if err != nil {
loginfo.Println("unable to peekAll", err)
return
}
loginfo.Println("Before Packer", hex.Dump(buffer))
cnt := len(buffer)
p := packer.NewPacker()
p.Header.SetAddress(rAddr)
p.Header.Port, err = strconv.Atoi(rPort)
@ -309,6 +327,13 @@ func handleExternalHTTPRequest(ctx context.Context, extConn net.Conn, hostname s
sendTrack := NewSendTrack(buf.Bytes(), hostname)
conn.SendCh() <- sendTrack
_, err = extConn.Discard(cnt)
if err != nil {
loginfo.Println("unable to discard", cnt, err)
return
}
}
}

View File

@ -51,14 +51,15 @@ type GenericListeners struct {
connectionTracking *Tracking
secretKey string
certbundle tls.Certificate
deadTime int
register chan *ListenerRegistration
genericListeners *GenericListeners
wssHostName string
adminHostName string
cancelCheck int
}
//NewGenerListeners --
func NewGenerListeners(ctx context.Context, connectionTable *Table, connectionTrack *Tracking, secretKey string, certbundle tls.Certificate, deadTime int, wssHostName string) (p *GenericListeners) {
func NewGenerListeners(ctx context.Context, connectionTable *Table, connectionTrack *Tracking, secretKey string, certbundle tls.Certificate, wssHostName string, adminHostName string, cancelCheck int) (p *GenericListeners) {
p = new(GenericListeners)
p.listeners = make(map[*net.Listener]int)
p.ctx = ctx
@ -66,9 +67,10 @@ func NewGenerListeners(ctx context.Context, connectionTable *Table, connectionTr
p.connectionTracking = connectionTrack
p.secretKey = secretKey
p.certbundle = certbundle
p.deadTime = deadTime
p.register = make(chan *ListenerRegistration)
p.wssHostName = wssHostName
p.adminHostName = adminHostName
p.cancelCheck = cancelCheck
return
}
@ -87,9 +89,10 @@ func (gl *GenericListeners) Run(ctx context.Context, initialPort int) {
ctx = context.WithValue(ctx, ctxConnectionTrack, gl.connectionTracking)
ctx = context.WithValue(ctx, ctxConfig, config)
ctx = context.WithValue(ctx, ctxDeadTime, gl.deadTime)
ctx = context.WithValue(ctx, ctxListenerRegistration, gl.register)
ctx = context.WithValue(ctx, ctxWssHostName, gl.wssHostName)
ctx = context.WithValue(ctx, ctxAdminHostName, gl.adminHostName)
ctx = context.WithValue(ctx, ctxCancelCheck, gl.cancelCheck)
go func(ctx context.Context) {
for {