Skip to content

Commit

Permalink
Added support for listening on multiple addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
hectorm committed Apr 30, 2022
1 parent 7c0b90f commit 2335409
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 218 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ These are the supported options:
Path to the backend TLS certificate used to authenticate with the daemon (env CETUSGUARD_BACKEND_TLS_CERT)
-backend-tls-key string
Path to the backend TLS key used to authenticate with the daemon (env CETUSGUARD_BACKEND_TLS_KEY)
-frontend-addr string
Address to bind the server to (env CETUSGUARD_FRONTEND_ADDR) (default "tcp://:2375")
-frontend-addr value
Address to bind the server to, can be specified multiple times (env CETUSGUARD_FRONTEND_ADDR) (default ["tcp://127.0.0.1:2375"])
-frontend-tls-cacert string
Path to the frontend TLS certificate used to verify the identity of clients (env CETUSGUARD_FRONTEND_TLS_CACERT)
-frontend-tls-cert string
Expand All @@ -44,9 +44,9 @@ These are the supported options:
-no-builtin-rules
Do not load built-in rules (env CETUSGUARD_NO_BUILTIN_RULES)
-rules value
Filter rules separated by new lines, can be specified multiple times (env CETUSGUARD_RULES) (default [])
Filter rules separated by new lines, can be specified multiple times (env CETUSGUARD_RULES)
-rules-file value
Filter rules file, can be specified multiple times (env CETUSGUARD_RULES_FILE) (default [])
Filter rules file, can be specified multiple times (env CETUSGUARD_RULES_FILE)
-version
Show version number and quit
```
Expand Down
92 changes: 52 additions & 40 deletions cetusguard/cetusguard.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Backend struct {
}

type Frontend struct {
Addr string
Addr []string
TlsCacert string
TlsCert string
TlsKey string
Expand All @@ -52,11 +52,9 @@ type Server struct {
backendTlsConfig *tls.Config
backendHttpClient *http.Client

frontendProto string
frontendHost string
frontendNetListener net.Listener
frontendTlsConfig *tls.Config
frontendHttpServer *http.Server
frontendNetListeners []net.Listener
frontendTlsConfig *tls.Config
frontendHttpServer *http.Server

runningState int32
mu sync.Mutex
Expand All @@ -76,37 +74,21 @@ func (cg *Server) Start(ready chan<- any) error {
defer cg.setIsRunning(false)

var err error

cg.backendProto, cg.backendHost, err = parseAddr(cg.Backend.Addr)
if err != nil {
return err
}
cg.frontendProto, cg.frontendHost, err = parseAddr(cg.Frontend.Addr)
if err != nil {
return err
}

cg.backendTlsConfig, err = clientTlsConfig(cg.Backend.TlsCacert, cg.Backend.TlsCert, cg.Backend.TlsKey)
if err != nil {
return err
}
cg.frontendTlsConfig, err = serverTlsConfig(cg.Frontend.TlsCacert, cg.Frontend.TlsCert, cg.Frontend.TlsKey)
if err != nil {
return err
}

cg.frontendNetListener, err = net.Listen(cg.frontendProto, cg.frontendHost)
if err != nil {
return err
}
defer func() {
_ = cg.frontendNetListener.Close()
}()

backendDialer := &net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 90 * time.Second,
}

cg.backendHttpClient = &http.Client{
Timeout: 30 * time.Second,
Transport: &http.Transport{
Expand All @@ -122,6 +104,29 @@ func (cg *Server) Start(ready chan<- any) error {
},
}

cg.frontendNetListeners = nil
for _, addr := range cg.Frontend.Addr {
proto, host, err := parseAddr(addr)
if err != nil {
return err
}
l, err := net.Listen(proto, host)
if err != nil {
return err
}
cg.frontendNetListeners = append(cg.frontendNetListeners, l)
}
defer func() {
for _, l := range cg.frontendNetListeners {
_ = l.Close()
}
}()

cg.frontendTlsConfig, err = serverTlsConfig(cg.Frontend.TlsCacert, cg.Frontend.TlsCert, cg.Frontend.TlsKey)
if err != nil {
return err
}

cg.frontendHttpServer = &http.Server{
TLSConfig: cg.frontendTlsConfig,
ReadTimeout: 120 * time.Minute,
Expand All @@ -141,7 +146,7 @@ func (cg *Server) Start(ready chan<- any) error {
}),
}

done := make(chan error, 1)
chErr := make(chan error, 1)

go func() {
chSig := make(chan os.Signal, 1)
Expand All @@ -150,25 +155,28 @@ func (cg *Server) Start(ready chan<- any) error {
sig := <-chSig
logger.Infof("%v signal received\n", sig)

done <- cg.Stop()
chErr <- cg.Stop()
}()

logger.Infof("serve on %s\n", cg.frontendNetListener.Addr())
for _, l := range cg.frontendNetListeners {
logger.Infof("serve on %s\n", l.Addr())
go func(l net.Listener) {
if cg.frontendTlsConfig != nil && l.Addr().Network() != "unix" {
err = cg.frontendHttpServer.ServeTLS(l, "", "")
} else {
err = cg.frontendHttpServer.Serve(l)
}
if err != http.ErrServerClosed {
chErr <- err
}
}(l)
}

cg.setIsRunning(true)
closeOnce.Do(func() { close(ready) })
unlockOnce.Do(cg.mu.Unlock)
closeOnce.Do(func() { close(ready) })

if cg.frontendTlsConfig != nil {
err = cg.frontendHttpServer.ServeTLS(cg.frontendNetListener, "", "")
} else {
err = cg.frontendHttpServer.Serve(cg.frontendNetListener)
}
if err != http.ErrServerClosed {
done <- err
}

return <-done
return <-chErr
}

func (cg *Server) Stop() error {
Expand All @@ -187,16 +195,20 @@ func (cg *Server) Stop() error {
err := cg.frontendHttpServer.Shutdown(ctx)

logger.Infof("exit\n")

return err
}

func (cg *Server) Addr() (net.Addr, error) {
func (cg *Server) Addrs() ([]net.Addr, error) {
if !cg.IsRunning() {
return nil, errors.New("server is not running")
}

return cg.frontendNetListener.Addr(), nil
var addr []net.Addr
for _, l := range cg.frontendNetListeners {
addr = append(addr, l.Addr())
}

return addr, nil
}

func (cg *Server) IsRunning() bool {
Expand Down
Loading

0 comments on commit 2335409

Please sign in to comment.