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:
parent
2fc5cf5e69
commit
74591fd150
|
@ -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
42
main.go
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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,14 +168,8 @@ func handleConnection(ctx context.Context, wConn *WedgeConn) {
|
||||||
|
|
||||||
loginfo.Println("sni:", sniHostName)
|
loginfo.Println("sni:", sniHostName)
|
||||||
|
|
||||||
if wssHostName != sniHostName {
|
if sniHostName == wssHostName {
|
||||||
//traffic not terminating on the rvpn do not decrypt
|
//handle WSS Path
|
||||||
loginfo.Println("processing non terminating traffic")
|
|
||||||
handleExternalHTTPRequest(ctx, wConn, sniHostName, "https")
|
|
||||||
}
|
|
||||||
|
|
||||||
loginfo.Println("processing traffic terminating on RVPN")
|
|
||||||
|
|
||||||
tlsListener := tls.NewListener(oneConn, config)
|
tlsListener := tls.NewListener(oneConn, config)
|
||||||
|
|
||||||
conn, err := tlsListener.Accept()
|
conn, err := tlsListener.Accept()
|
||||||
|
@ -187,6 +181,26 @@ func handleConnection(ctx context.Context, wConn *WedgeConn) {
|
||||||
tlsWedgeConn := NewWedgeConn(conn)
|
tlsWedgeConn := NewWedgeConn(conn)
|
||||||
handleStream(ctx, tlsWedgeConn)
|
handleStream(ctx, tlsWedgeConn)
|
||||||
return
|
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")
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue