mirror of
https://github.com/mmatczuk/go-http-tunnel.git
synced 2026-05-15 14:16:17 -06:00
Upd predefined client list
file is monitored an reloaded dynamically
This commit is contained in:
parent
15d08c6549
commit
51e9f199e5
7 changed files with 108 additions and 36 deletions
|
|
@ -190,7 +190,7 @@ Configuration options:
|
|||
* `tlsCrt`: Path to a TLS certificate file, *default:* `server.crt`
|
||||
* `tlsKey`: Path to a TLS key file, *default:* `server.key`
|
||||
* `rootCA`: Path to the trusted certificate chian used for client certificate authentication, if empty any client certificate is accepted
|
||||
* `clients`: Comma-separated list of tunnel client ids, if empty accept all clients
|
||||
* `clients`: Path to a properties file that contains a list of 'host=tunnelClientId's, if empty accept all clients
|
||||
* `keepAlive`: the amount of time to wait between sending keepalive packets *default:* `45s`
|
||||
* `logLevel`: Level of messages to log, 0-3, *default:* 1
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ func parseArgs() *options {
|
|||
tlsCrt := flag.String("tlsCrt", "server.crt", "Path to a TLS certificate file")
|
||||
tlsKey := flag.String("tlsKey", "server.key", "Path to a TLS key file")
|
||||
rootCA := flag.String("rootCA", "", "Path to the trusted certificate chian used for client certificate authentication, if empty any client certificate is accepted")
|
||||
clients := flag.String("clients", "", "Comma-separated list of tunnel client ids, if empty accept all clients")
|
||||
clients := flag.String("clients", "", "Path to a properties file that contains a list of 'host=tunnelClientId's, if empty accept all clients")
|
||||
keepAlive := flag.String("keepAlive", "45s", "TCP keep alive configuration")
|
||||
debounceLog := flag.String("debounceLog", "2s", "How long to keep disconnected log message before actually writing it to the log")
|
||||
logLevel := flag.Int("logLevel", 1, "Level of messages to log, 0-3")
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ import (
|
|||
"golang.org/x/net/http2"
|
||||
|
||||
"github.com/bep/debounce"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
tunnel "github.com/hons82/go-http-tunnel"
|
||||
"github.com/hons82/go-http-tunnel/connection"
|
||||
"github.com/hons82/go-http-tunnel/fileutil"
|
||||
"github.com/hons82/go-http-tunnel/log"
|
||||
)
|
||||
|
||||
|
|
@ -70,14 +70,59 @@ func main() {
|
|||
}
|
||||
|
||||
if !autoSubscribe {
|
||||
clients, err := fileutil.ReadPropertiesFile(opts.clients)
|
||||
if err != nil {
|
||||
fatal("failed to load clients: %s", err)
|
||||
}
|
||||
// First load immediatly
|
||||
server.LoadAllowedTunnels(opts.clients)
|
||||
|
||||
for host, value := range clients {
|
||||
if err := server.RegisterTunnel(host, value); err != nil {
|
||||
fatal("failed to load tunnel: %s with error %s", host, err)
|
||||
// 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",
|
||||
"err", err,
|
||||
)
|
||||
} else {
|
||||
defer watcher.Close()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
logger.Log(
|
||||
"level", 3,
|
||||
"action", "watched file changed",
|
||||
"file", event.Name,
|
||||
"action", event.Op.String(),
|
||||
)
|
||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||
server.Clear()
|
||||
server.LoadAllowedTunnels(event.Name)
|
||||
}
|
||||
case err, ok := <-watcher.Errors:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
logger.Log(
|
||||
"level", 2,
|
||||
"action", "error watching file",
|
||||
"err", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err = watcher.Add(opts.clients)
|
||||
if err != nil {
|
||||
logger.Log(
|
||||
"level", 1,
|
||||
"action", "add watch failed",
|
||||
"file", opts.clients,
|
||||
"err", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
go.mod
1
go.mod
|
|
@ -6,6 +6,7 @@ require (
|
|||
github.com/bep/debounce v1.2.0
|
||||
github.com/calmh/luhn v2.0.0+incompatible
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/golang/mock v1.2.0
|
||||
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
|
||||
golang.org/x/net v0.0.0-20171123081856-c7086645de24
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -4,12 +4,16 @@ github.com/calmh/luhn v2.0.0+incompatible h1:xHkbAc8FBgMiGUaKsiYcwtf8xhSXVtRKA2N
|
|||
github.com/calmh/luhn v2.0.0+incompatible/go.mod h1:70IGmMi0GKRs073gl/oH5/yiJnTt61h35YQhvo/k3Cc=
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
|
||||
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b h1:IpLPmn6Re21F0MaV6Zsc5RdSE6KuoFpWmHiUSEs3PrE=
|
||||
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b/go.mod h1:aA6DnFhALT3zH0y+A39we+zbrdMC2N0X/q21e6FI0LU=
|
||||
golang.org/x/net v0.0.0-20171123081856-c7086645de24 h1:z0cmn+BVQSCN8exp26jnHqHXHIvTlqIYhjHln4k/UAU=
|
||||
golang.org/x/net v0.0.0-20171123081856-c7086645de24/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.1.1-0.20171102192421-88f656faf3f3 h1:OxMYHd6bm+jH+TI7NBCb/CaYk6pMJnBC8GIzIi68Hk4=
|
||||
golang.org/x/text v0.1.1-0.20171102192421-88f656faf3f3/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
|
|
|||
38
registry.go
38
registry.go
|
|
@ -64,7 +64,7 @@ func (r *registry) Subscribe(identifier id.ID) {
|
|||
}
|
||||
|
||||
r.logger.Log(
|
||||
"level", 1,
|
||||
"level", 2,
|
||||
"action", "subscribe",
|
||||
"identifier", identifier,
|
||||
)
|
||||
|
|
@ -103,17 +103,17 @@ func (r *registry) HasTunnel(hostPort string, identifier id.ID) bool {
|
|||
}
|
||||
|
||||
// Unsubscribe removes client from registry and returns it's RegistryItem.
|
||||
func (r *registry) Unsubscribe(identifier id.ID) *RegistryItem {
|
||||
func (r *registry) Unsubscribe(identifier id.ID, autoSubscribe bool) *RegistryItem {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
i, ok := r.items[identifier]
|
||||
if !ok {
|
||||
if !ok || (autoSubscribe && i == voidRegistryItem) {
|
||||
return nil
|
||||
}
|
||||
|
||||
r.logger.Log(
|
||||
"level", 1,
|
||||
"level", 2,
|
||||
"action", "unsubscribe",
|
||||
"identifier", identifier,
|
||||
)
|
||||
|
|
@ -124,7 +124,11 @@ func (r *registry) Unsubscribe(identifier id.ID) *RegistryItem {
|
|||
}
|
||||
}
|
||||
|
||||
delete(r.items, identifier)
|
||||
if autoSubscribe {
|
||||
delete(r.items, identifier)
|
||||
} else {
|
||||
r.items[identifier] = voidRegistryItem
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
|
@ -174,9 +178,10 @@ func (r *registry) RegisterTunnel(host string, client string) error {
|
|||
identifier := id.New([]byte(client))
|
||||
|
||||
r.logger.Log(
|
||||
"level", 2,
|
||||
"action", "add tunnel",
|
||||
"level", 3,
|
||||
"action", "register tunnel",
|
||||
"host", host,
|
||||
"client", client,
|
||||
"identifier", identifier,
|
||||
)
|
||||
|
||||
|
|
@ -199,24 +204,23 @@ func (r *registry) RegisterTunnel(host string, client string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (r *registry) clear(identifier id.ID) *RegistryItem {
|
||||
// Clear removes all items from the registry
|
||||
func (r *registry) Clear() {
|
||||
r.logger.Log(
|
||||
"level", 2,
|
||||
"action", "clear registry item",
|
||||
"identifier", identifier,
|
||||
"level", 3,
|
||||
"action", "clear registry ",
|
||||
)
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
i, ok := r.items[identifier]
|
||||
if !ok || i == voidRegistryItem {
|
||||
return nil
|
||||
for k := range r.hosts {
|
||||
delete(r.hosts, k)
|
||||
}
|
||||
|
||||
r.items[identifier] = voidRegistryItem
|
||||
|
||||
return i
|
||||
for i := range r.items {
|
||||
delete(r.items, i)
|
||||
}
|
||||
}
|
||||
|
||||
func trimPort(hostPort string) (host string) {
|
||||
|
|
|
|||
36
server.go
36
server.go
|
|
@ -20,6 +20,7 @@ import (
|
|||
"golang.org/x/net/http2"
|
||||
|
||||
"github.com/hons82/go-http-tunnel/connection"
|
||||
"github.com/hons82/go-http-tunnel/fileutil"
|
||||
"github.com/hons82/go-http-tunnel/id"
|
||||
"github.com/hons82/go-http-tunnel/log"
|
||||
"github.com/hons82/go-http-tunnel/proto"
|
||||
|
|
@ -201,7 +202,7 @@ func (s *Server) disconnected(identifier id.ID) {
|
|||
)
|
||||
}
|
||||
|
||||
i := s.unsubscribe(identifier)
|
||||
i := s.registry.Unsubscribe(identifier, s.config.AutoSubscribe)
|
||||
if i == nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -216,13 +217,6 @@ func (s *Server) disconnected(identifier id.ID) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Server) unsubscribe(identifier id.ID) *RegistryItem {
|
||||
if s.config.AutoSubscribe {
|
||||
return s.registry.Unsubscribe(identifier)
|
||||
}
|
||||
return s.registry.clear(identifier)
|
||||
}
|
||||
|
||||
// Start starts accepting connections form clients. For accepting http traffic
|
||||
// from end users server must be run as handler on http server.
|
||||
func (s *Server) Start() {
|
||||
|
|
@ -473,6 +467,30 @@ reject:
|
|||
conn.Close()
|
||||
}
|
||||
|
||||
// LoadAllowedTunnels registers allowed tunnels from a file
|
||||
func (s *Server) LoadAllowedTunnels(propertiesFile string) {
|
||||
clients, err := fileutil.ReadPropertiesFile(propertiesFile)
|
||||
if err != nil {
|
||||
s.logger.Log(
|
||||
"level", 1,
|
||||
"action", "failed to load clients",
|
||||
"err", err,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
for host, value := range clients {
|
||||
if err := s.RegisterTunnel(host, value); err != nil {
|
||||
s.logger.Log(
|
||||
"level", 2,
|
||||
"action", "failed to load tunnel",
|
||||
"host", host,
|
||||
"err", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// notifyError tries to send error to client.
|
||||
func (s *Server) notifyError(serverError error, identifier id.ID) {
|
||||
if serverError == nil {
|
||||
|
|
@ -592,7 +610,7 @@ func (s *Server) Unsubscribe(identifier id.ID) *RegistryItem {
|
|||
s.config.SubscriptionListener.Unsubscribed(identifier)
|
||||
}
|
||||
s.connPool.DeleteConn(identifier)
|
||||
return s.registry.Unsubscribe(identifier)
|
||||
return s.registry.Unsubscribe(identifier, s.config.AutoSubscribe)
|
||||
}
|
||||
|
||||
// Ping measures the RTT response time.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue