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" "os"
"time" "time"
"github.com/spf13/viper"
"context" "context"
"git.daplie.com/Daplie/go-rvpn-server/rvpn/genericlistener" "git.daplie.com/Daplie/go-rvpn-server/rvpn/genericlistener"
@ -18,7 +20,7 @@ var (
logdebug *log.Logger logdebug *log.Logger
logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile logFlags = log.Ldate | log.Lmicroseconds | log.Lshortfile
argWssClientListener string argWssClientListener string
argGenericBinding string argGenericBinding int
argServerBinding string argServerBinding string
argServerAdminBinding string argServerAdminBinding string
argServerExternalBinding string argServerExternalBinding string
@ -26,25 +28,43 @@ var (
connectionTable *genericlistener.Table connectionTable *genericlistener.Table
secretKey = "abc123" secretKey = "abc123"
wssHostName = "localhost.daplie.me" wssHostName = "localhost.daplie.me"
adminHostName = "rvpn.daplie.invalid"
idle int
dwell int
cancelcheck int
) )
func init() { 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 //Main -- main entry point
func main() { func main() {
flag.Parse() 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) flag.IntVar(&argDeadTime, "dead-time-counter", 5, "deadtime counter in seconds")
logdebug = log.New(os.Stdout, "DEBUG: packer:", logFlags)
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("startup")
loginfo.Println(viper.Get("rvpn.genericlisteners"))
loginfo.Println(viper.Get("rvpn.domains"))
fmt.Println("-=-=-=-=-=-=-=-=-=-=") fmt.Println("-=-=-=-=-=-=-=-=-=-=")
certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem") certbundle, err := tls.LoadX509KeyPair("certs/fullchain.pem", "certs/privkey.pem")
@ -68,11 +88,11 @@ func main() {
connectionTracking := genericlistener.NewTracking() connectionTracking := genericlistener.NewTracking()
go connectionTracking.Run(ctx) go connectionTracking.Run(ctx)
connectionTable = genericlistener.NewTable() connectionTable = genericlistener.NewTable(dwell, idle)
go connectionTable.Run(ctx) go connectionTable.Run(ctx)
genericListeners := genericlistener.NewGenerListeners(ctx, connectionTable, connectionTracking, secretKey, certbundle, argDeadTime, wssHostName) genericListeners := genericlistener.NewGenerListeners(ctx, connectionTable, connectionTracking, secretKey, certbundle, wssHostName, adminHostName, cancelcheck)
go genericListeners.Run(ctx, 9999) go genericListeners.Run(ctx, argGenericBinding)
//Run for 10 minutes and then shutdown cleanly //Run for 10 minutes and then shutdown cleanly
time.Sleep(600 * time.Second) time.Sleep(600 * time.Second)

View File

@ -27,11 +27,21 @@ func NewWedgeConnSize(c net.Conn, size int) (p *WedgeConn) {
return 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 //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) { func (w *WedgeConn) Peek(n int) ([]byte, error) {
return w.reader.Peek(n) return w.reader.Peek(n)
} }
//ReadByte -- A normal reader.
func (w *WedgeConn) ReadByte() (byte, error) {
return w.reader.ReadByte()
}
//Read -- A normal reader. //Read -- A normal reader.
func (w *WedgeConn) Read(p []byte) (int, error) { func (w *WedgeConn) Read(p []byte) (int, error) {
cnt, err := w.reader.Read(p) cnt, err := w.reader.Read(p)

View File

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

View File

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