From 2bd1b3ae997046ee9394a447973d1f999ba045a4 Mon Sep 17 00:00:00 2001 From: mleku Date: Wed, 11 Dec 2024 20:00:15 +0000 Subject: [PATCH] update to enable whitelisting IP addresses for no auth --- cmd/realy/main.go | 17 +++++++++-------- realy/config/config.go | 37 +++++++++++++++++++------------------ realy/handleCount.go | 13 +++++++++++-- realy/handleEvent.go | 13 ++++++++++--- realy/handleReq.go | 12 ++++++++++-- realy/handleWebsocket.go | 2 +- realy/server.go | 25 ++++++++++++++----------- realy/version | 2 +- 8 files changed, 75 insertions(+), 46 deletions(-) diff --git a/cmd/realy/main.go b/cmd/realy/main.go index 7c147e0..68d9e4a 100644 --- a/cmd/realy/main.go +++ b/cmd/realy/main.go @@ -67,14 +67,15 @@ func main() { go app.MonitorResources(c) var server *realy.Server if server, err = realy.NewServer(realy.ServerParams{ - Ctx: c, - Cancel: cancel, - Rl: r, - DbPath: cfg.Profile, - MaxLimit: ratel.DefaultMaxLimit, - AdminUser: cfg.AdminUser, - AdminPass: cfg.AdminPass}); chk.E(err) { - + Ctx: c, + Cancel: cancel, + Rl: r, + DbPath: cfg.Profile, + MaxLimit: ratel.DefaultMaxLimit, + AdminUser: cfg.AdminUser, + AdminPass: cfg.AdminPass, + NoAuthAddresses: cfg.NoAuthAddresses, + }); chk.E(err) { os.Exit(1) } if err != nil { diff --git a/realy/config/config.go b/realy/config/config.go index 464aba9..a47feb0 100644 --- a/realy/config/config.go +++ b/realy/config/config.go @@ -19,24 +19,25 @@ import ( ) type C struct { - AppName st `env:"APP_NAME" default:"realy"` - Profile st `env:"PROFILE" usage:"root path for all other path configurations (based on APP_NAME and OS specific location)"` - Listen st `env:"LISTEN" default:"0.0.0.0" usage:"network listen address"` - Port no `env:"PORT" default:"3334" usage:"port to listen on"` - AdminUser st `env:"ADMIN_USER" default:"admin" usage:"admin user"` - AdminPass st `env:"ADMIN_PASS" usage:"admin password"` - LogLevel st `env:"LOG_LEVEL" default:"info" usage:"debug level: fatal error warn info debug trace"` - DbLogLevel st `env:"DB_LOG_LEVEL" default:"info" usage:"debug level: fatal error warn info debug trace"` - AuthRequired bo `env:"AUTH_REQUIRED" default:"false" usage:"requires auth for all access"` - Owners []st `env:"OWNERS" usage:"list of npubs of users in hex format whose follow and mute list dictate accepting requests and events with AUTH_REQUIRED enabled - follows and follows follows are allowed to read/write, owners mutes events are rejected"` - DBSizeLimit no `env:"DB_SIZE_LIMIT" default:"0" usage:"the number of gigabytes (1,000,000,000 bytes) we want to keep the data store from exceeding, 0 means disabled"` - DBLowWater no `env:"DB_LOW_WATER" default:"60" usage:"the percentage of DBSizeLimit a GC run will reduce the used storage down to"` - DBHighWater no `env:"DB_HIGH_WATER" default:"80" usage:"the trigger point at which a GC run should start if exceeded"` - GCFrequency no `env:"GC_FREQUENCY" default:"3600" usage:"the frequency of checks of the current utilisation in minutes"` - Pprof bo `env:"PPROF" default:"false" usage:"enable pprof on 127.0.0.1:6060"` - MemLimit no `env:"MEMLIMIT" default:"250000000" usage:"set memory limit, default is 250Mb"` - UseCompact bo `env:"USE_COMPACT" default:"false" usage:"use the compact database encoding for the ratel event store"` - Compression st `env:"COMPRESSION" default:"none" usage:"compress the database, [none|snappy|zstd]"` + AppName st `env:"APP_NAME" default:"realy"` + Profile st `env:"PROFILE" usage:"root path for all other path configurations (based on APP_NAME and OS specific location)"` + Listen st `env:"LISTEN" default:"0.0.0.0" usage:"network listen address"` + Port no `env:"PORT" default:"3334" usage:"port to listen on"` + AdminUser st `env:"ADMIN_USER" default:"admin" usage:"admin user"` + AdminPass st `env:"ADMIN_PASS" usage:"admin password"` + LogLevel st `env:"LOG_LEVEL" default:"info" usage:"debug level: fatal error warn info debug trace"` + DbLogLevel st `env:"DB_LOG_LEVEL" default:"info" usage:"debug level: fatal error warn info debug trace"` + AuthRequired bo `env:"AUTH_REQUIRED" default:"false" usage:"requires auth for all access"` + Owners []st `env:"OWNERS" usage:"list of npubs of users in hex format whose follow and mute list dictate accepting requests and events with AUTH_REQUIRED enabled - follows and follows follows are allowed to read/write, owners mutes events are rejected"` + DBSizeLimit no `env:"DB_SIZE_LIMIT" default:"0" usage:"the number of gigabytes (1,000,000,000 bytes) we want to keep the data store from exceeding, 0 means disabled"` + DBLowWater no `env:"DB_LOW_WATER" default:"60" usage:"the percentage of DBSizeLimit a GC run will reduce the used storage down to"` + DBHighWater no `env:"DB_HIGH_WATER" default:"80" usage:"the trigger point at which a GC run should start if exceeded"` + GCFrequency no `env:"GC_FREQUENCY" default:"3600" usage:"the frequency of checks of the current utilisation in minutes"` + Pprof bo `env:"PPROF" default:"false" usage:"enable pprof on 127.0.0.1:6060"` + MemLimit no `env:"MEMLIMIT" default:"250000000" usage:"set memory limit, default is 250Mb"` + UseCompact bo `env:"USE_COMPACT" default:"false" usage:"use the compact database encoding for the ratel event store"` + Compression st `env:"COMPRESSION" default:"none" usage:"compress the database, [none|snappy|zstd]"` + NoAuthAddresses []st `env:"NO_AUTH_ADDRESSES" usage:"IP addresses that don't require auth (for such things as clients using the relay as a cache relay)'"` // NWC st `env:"NWC" usage:"NWC connection string for relay to interact with an NWC enabled wallet"` // todo } diff --git a/realy/handleCount.go b/realy/handleCount.go index 7919aaa..ee51f96 100644 --- a/realy/handleCount.go +++ b/realy/handleCount.go @@ -1,6 +1,8 @@ package realy import ( + "strings" + "realy.lol/context" "realy.lol/envelopes/authenvelope" "realy.lol/envelopes/closedenvelope" @@ -18,7 +20,14 @@ func (s *Server) handleCount(c context.T, ws *web.Socket, req by, store store.I) if !ok { return normalize.Restricted.F("this relay does not support NIP-45") } - if ws.AuthRequested() && len(ws.Authed()) == 0 { + var noAuth bo + for _, v := range s.noAuthAddresses { + if strings.HasPrefix(v, ws.RealRemote()) { + // we are not requiring auth from this address (should be private address) + noAuth = true + } + } + if !noAuth && (ws.AuthRequested() && len(ws.Authed()) == 0) { return by("awaiting auth for count") } var err er @@ -38,7 +47,7 @@ func (s *Server) handleCount(c context.T, ws *web.Socket, req by, store store.I) var accepted bo allowed, accepted = accepter.AcceptReq(c, ws.Req(), env.Subscription.T, env.Filters, by(ws.Authed())) - if !accepted || allowed == nil { + if !noAuth && !accepted || allowed == nil { var auther relay.Authenticator if auther, ok = s.relay.(relay.Authenticator); ok && auther.AuthEnabled() && !ws.AuthRequested() { ws.RequestAuth() diff --git a/realy/handleEvent.go b/realy/handleEvent.go index 9c66955..a9c142e 100644 --- a/realy/handleEvent.go +++ b/realy/handleEvent.go @@ -21,8 +21,15 @@ import ( ) func (s *Server) handleEvent(c cx, ws *web.Socket, req by, sto store.I) (msg by) { - log.T.F("handleEvent %s %s", ws.RealRemote(), req) - if ws.AuthRequested() && len(ws.Authed()) == 0 { + log.T.F("handleEvent %s %s %v", ws.RealRemote(), req, s.noAuthAddresses) + var noAuth bo + for _, v := range s.noAuthAddresses { + if strings.HasPrefix(v, ws.RealRemote()) { + // we are not requiring auth from this address (should be private address) + noAuth = true + } + } + if !noAuth && ws.AuthRequested() && len(ws.Authed()) == 0 { return by("awaiting auth for event") } var err er @@ -38,7 +45,7 @@ func (s *Server) handleEvent(c cx, ws *web.Socket, req by, sto store.I) (msg by) } accept, notice, after := s.relay.AcceptEvent(c, env.T, ws.Req(), ws.RealRemote(), by(ws.Authed())) - if !accept { + if !noAuth && !accept { if strings.Contains(notice, "mute") { if err = okenvelope.NewFrom(env.ID, false, normalize.Blocked.F(notice)).Write(ws); chk.T(err) { diff --git a/realy/handleReq.go b/realy/handleReq.go index 3795821..012af1d 100644 --- a/realy/handleReq.go +++ b/realy/handleReq.go @@ -3,6 +3,7 @@ package realy import ( "errors" "sort" + "strings" "github.com/dgraph-io/badger/v4" @@ -24,7 +25,14 @@ import ( ) func (s *Server) handleReq(c cx, ws *web.Socket, req by, sto store.I) (r by) { - if ws.AuthRequested() && len(ws.Authed()) == 0 { + var noAuth bo + for _, v := range s.noAuthAddresses { + if strings.HasPrefix(v, ws.RealRemote()) { + // we are not requiring auth from this address (should be private address) + noAuth = true + } + } + if !noAuth && ws.AuthRequested() && len(ws.Authed()) == 0 { return by("awaiting auth for req") } var err er @@ -41,7 +49,7 @@ func (s *Server) handleReq(c cx, ws *web.Socket, req by, sto store.I) (r by) { var accepted bo allowed, accepted = accepter.AcceptReq(c, ws.Req(), env.Subscription.T, env.Filters, by(ws.Authed())) - if !accepted || allowed == nil { + if !noAuth || (!accepted || allowed == nil) { var auther relay.Authenticator if auther, ok = s.relay.(relay.Authenticator); ok && auther.AuthEnabled() && !ws.AuthRequested() { ws.RequestAuth() diff --git a/realy/handleWebsocket.go b/realy/handleWebsocket.go index 84e4c78..6de1708 100644 --- a/realy/handleWebsocket.go +++ b/realy/handleWebsocket.go @@ -150,7 +150,7 @@ func (s *Server) handleMessage(c cx, ws *web.Socket, msg by, sto store.I) { } } if len(notice) > 0 { - log.D.F("notice %s", notice) + log.D.F("notice %s %s", notice, ws.RealRemote()) if err = noticeenvelope.NewFrom(notice).Write(ws); chk.E(err) { } } diff --git a/realy/server.go b/realy/server.go index 0363073..12cd094 100644 --- a/realy/server.go +++ b/realy/server.go @@ -34,6 +34,7 @@ type Server struct { maxLimit no adminUser, adminPass st listeners *listeners.T + noAuthAddresses []st } type ServerParams struct { @@ -43,6 +44,7 @@ type ServerParams struct { DbPath st MaxLimit no AdminUser, AdminPass st + NoAuthAddresses []st } func NewServer(sp ServerParams, opts ...options.O) (*Server, er) { @@ -55,17 +57,18 @@ func NewServer(sp ServerParams, opts ...options.O) (*Server, er) { authRequired = ar.AuthEnabled() } srv := &Server{ - Ctx: sp.Ctx, - Cancel: sp.Cancel, - relay: sp.Rl, - clients: make(map[*websocket.Conn]struct{}), - serveMux: http.NewServeMux(), - options: op, - authRequired: authRequired, - maxLimit: sp.MaxLimit, - adminUser: sp.AdminUser, - adminPass: sp.AdminPass, - listeners: listeners.New(), + Ctx: sp.Ctx, + Cancel: sp.Cancel, + relay: sp.Rl, + clients: make(map[*websocket.Conn]struct{}), + serveMux: http.NewServeMux(), + options: op, + authRequired: authRequired, + maxLimit: sp.MaxLimit, + adminUser: sp.AdminUser, + adminPass: sp.AdminPass, + noAuthAddresses: sp.NoAuthAddresses, + listeners: listeners.New(), } if storage := sp.Rl.Storage(context.Bg()); storage != nil { if err := storage.Init(sp.DbPath); chk.T(err) { diff --git a/realy/version b/realy/version index a3a007c..90f1642 100644 --- a/realy/version +++ b/realy/version @@ -1 +1 @@ -v1.3.5 \ No newline at end of file +v1.3.6 \ No newline at end of file