Upd client list can now be a client folder

This commit is contained in:
Hannes Tribus 2022-12-14 16:05:48 +01:00
parent 51e9f199e5
commit c93916810b
5 changed files with 90 additions and 28 deletions

View file

@ -14,6 +14,7 @@ import (
"sync"
"time"
"github.com/cenkalti/backoff"
"golang.org/x/net/http2"
"github.com/hons82/go-http-tunnel/connection"
@ -98,7 +99,7 @@ func (c *Client) Start() error {
"level", 1,
"action", "start",
)
b := backoff.NewExponentialBackOff()
for {
conn, err := c.connect()
if err != nil {
@ -115,17 +116,36 @@ func (c *Client) Start() error {
)
c.connMu.Lock()
now := time.Now()
err = c.serverErr
// detect disconnect hiccup
if err == nil && now.Sub(c.lastDisconnect).Seconds() < 5 {
if err == nil && time.Since(c.lastDisconnect).Seconds() < 5 {
err = fmt.Errorf("connection is being cut")
}
// Backoff
if b != nil {
if err != nil {
d := b.NextBackOff()
if d > 0 {
// backoff
c.logger.Log(
"level", 1,
"action", "backoff",
"sleep", d,
"err", err,
)
time.Sleep(d)
err = nil
}
} else {
b.Reset()
}
}
c.conn = nil
c.serverErr = nil
c.lastDisconnect = now
c.lastDisconnect = time.Now()
c.connMu.Unlock()
if err != nil {

View file

@ -71,12 +71,11 @@ func main() {
if !autoSubscribe {
// First load immediatly
server.LoadAllowedTunnels(opts.clients)
server.ReloadTunnels(opts.clients)
// Watch for the file to change
watcher, err := fsnotify.NewWatcher()
if err != nil {
fatal("NewWatcher failed: %s", err)
logger.Log(
"level", 1,
"action", "could not create file watcher",
@ -98,9 +97,11 @@ func main() {
"file", event.Name,
"action", event.Op.String(),
)
if event.Op&fsnotify.Write == fsnotify.Write {
if event.Op&fsnotify.Write == fsnotify.Write ||
event.Op&fsnotify.Create == fsnotify.Create ||
event.Op&fsnotify.Remove == fsnotify.Remove {
server.Clear()
server.LoadAllowedTunnels(event.Name)
server.ReloadTunnels(opts.clients)
}
case err, ok := <-watcher.Errors:
if !ok {

View file

@ -2,7 +2,6 @@ package fileutil
import (
"bufio"
"log"
"os"
"strings"
)
@ -17,7 +16,6 @@ func ReadPropertiesFile(filename string) (AppConfigProperties, error) {
}
file, err := os.Open(filename)
if err != nil {
log.Fatal(err)
return nil, err
}
defer file.Close()
@ -25,7 +23,7 @@ func ReadPropertiesFile(filename string) (AppConfigProperties, error) {
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if equal := strings.Index(line, "="); equal >= 0 {
if equal := strings.Index(line, ";"); equal >= 0 {
if key := strings.TrimSpace(line[:equal]); len(key) > 0 {
value := ""
if len(line) > equal {
@ -37,9 +35,17 @@ func ReadPropertiesFile(filename string) (AppConfigProperties, error) {
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
return nil, err
}
return config, nil
}
// IsDirectory determines if a file represented by `path` is a directory or not
func IsDirectory(path string) (bool, error) {
fileInfo, err := os.Stat(path)
if err != nil {
return false, err
}
return fileInfo.IsDir(), err
}

View file

@ -118,13 +118,12 @@ func (r *registry) Unsubscribe(identifier id.ID, autoSubscribe bool) *RegistryIt
"identifier", identifier,
)
if i.Hosts != nil {
for _, h := range i.Hosts {
delete(r.hosts, h.Host)
}
}
if autoSubscribe {
if i.Hosts != nil {
for _, h := range i.Hosts {
delete(r.hosts, h.Host)
}
}
delete(r.items, identifier)
} else {
r.items[identifier] = voidRegistryItem
@ -174,7 +173,7 @@ func (r *registry) set(i *RegistryItem, identifier id.ID) error {
return nil
}
func (r *registry) RegisterTunnel(host string, client string) error {
func (r *registry) registerTunnel(host string, client string) error {
identifier := id.New([]byte(client))
r.logger.Log(

View file

@ -14,6 +14,8 @@ import (
"io"
"net"
"net/http"
"os"
"path/filepath"
"strings"
"time"
@ -410,11 +412,10 @@ func (s *Server) handleClient(conn net.Conn) {
}
if len(tunnels) == 0 {
err = fmt.Errorf("no tunnels")
logger.Log(
"level", 2,
"msg", "handshake failed",
"err", err,
"level", 1,
"msg", "configuration error",
"err", fmt.Errorf("no tunnels"),
)
goto reject
}
@ -431,7 +432,7 @@ func (s *Server) handleClient(conn net.Conn) {
if err = s.addTunnels(tunnels, identifier, IDInfo); err != nil {
logger.Log(
"level", 2,
"msg", "handshake failed",
"msg", "add tunnel failed",
"err", err,
)
goto reject
@ -467,8 +468,8 @@ reject:
conn.Close()
}
// LoadAllowedTunnels registers allowed tunnels from a file
func (s *Server) LoadAllowedTunnels(propertiesFile string) {
// loadAllowedTunnels registers allowed tunnels from a file
func (s *Server) loadAllowedTunnels(propertiesFile string) {
clients, err := fileutil.ReadPropertiesFile(propertiesFile)
if err != nil {
s.logger.Log(
@ -480,7 +481,7 @@ func (s *Server) LoadAllowedTunnels(propertiesFile string) {
}
for host, value := range clients {
if err := s.RegisterTunnel(host, value); err != nil {
if err := s.registerTunnel(host, value); err != nil {
s.logger.Log(
"level", 2,
"action", "failed to load tunnel",
@ -491,6 +492,41 @@ func (s *Server) LoadAllowedTunnels(propertiesFile string) {
}
}
// ReloadTunnels registers allowed tunnels from a file
func (s *Server) ReloadTunnels(path string) {
directory, err := fileutil.IsDirectory(path)
if err != nil {
s.logger.Log(
"level", 3,
"action", "could not determine if path is a directory",
"err", err,
)
}
if directory {
files, err := os.ReadDir(path)
if err != nil {
s.logger.Log(
"level", 2,
"action", "could not read directory",
"err", err,
)
}
for _, file := range files {
if file.IsDir() {
s.logger.Log(
"level", 3,
"action", "skip directory",
"file", file.Name(),
)
} else {
s.loadAllowedTunnels(filepath.Join(path, file.Name()))
}
}
} else {
s.loadAllowedTunnels(path)
}
}
// notifyError tries to send error to client.
func (s *Server) notifyError(serverError error, identifier id.ID) {
if serverError == nil {
@ -523,7 +559,7 @@ func (s *Server) hasTunnels(tunnels map[string]*proto.Tunnel, identifier id.ID)
// AutoSubscribe --> Tunnel not yet registered (means that it isn't already opened)
// !AutoSubscribe -> Tunnel has to be already registered, and therefore allowed to be opened
if s.config.AutoSubscribe == s.HasTunnel(t.Host, identifier) {
err = fmt.Errorf("tunnel %s not allowed for %s", name, identifier)
err = fmt.Errorf("tunnel %s (%s) not allowed for %s", name, t.Host, identifier)
break
}
}