From c6e6a4a2d7edebc8b71753059a389da99a894aee Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 24 Mar 2026 19:51:30 +0100 Subject: [PATCH 1/4] feat(api): update config.go --- api/.env.sample | 99 ++++++++++++++++++++++---------------------- api/config/config.go | 8 +++- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/api/.env.sample b/api/.env.sample index e8b4ca9..6780872 100644 --- a/api/.env.sample +++ b/api/.env.sample @@ -1,54 +1,55 @@ -FQDN="localhost" -API_NAME="Service Name" -API_PORT="3000" -API_ALLOW_ORIGIN="http://localhost:3001" -TOKEN_SECRET="secret" +FQDN=localhost +API_NAME=Service Name +API_PORT=3000 +API_ALLOW_ORIGIN=http://localhost:3001 +API_TRUSTED_PROXIES=127.0.0.1,10.0.0.0/8,172.16.0.0/12 +API_ALLOW_IPS=127.0.0.1 +TOKEN_SECRET=secret TOKEN_EXPIRATION=168h API_TOKEN_EXPIRATION=8760h -PSK="" -PSK_ALLOW_ORIGIN="http://localhost:3001" -DOMAINS="example1.net,example2.com" -LOG_FILE="/var/log/api.log" -BASIC_AUTH_USER="" -BASIC_AUTH_PASSWORD="" -NET_SUBNET="" -NET_GATEWAY="" -SIGNUP_WEBHOOK_URL="" -SIGNUP_WEBHOOK_PSK="" +PSK= +DOMAINS=example1.net,example2.com +LOG_FILE=/var/log/api.log +BASIC_AUTH_USER= +BASIC_AUTH_PASSWORD= +NET_SUBNET= +NET_GATEWAY= +SIGNUP_WEBHOOK_URL= +SIGNUP_WEBHOOK_PSK= -APP_PORT="3001" +APP_PORT=3001 -DB_HOSTS="db" -DB_PORT="3306" -DB_NAME="email" -DB_USER="email" -DB_PASSWORD="email" -DB_ROOT_USER="root" -DB_ROOT_PASSWORD="root" +DB_HOSTS=db +DB_PORT=3306 +DB_NAME=email +DB_USER=email +DB_PASSWORD=email +DB_ROOT_USER=root +DB_ROOT_PASSWORD=root -REDIS_ADDR="redis:6379" -REDIS_ADDRS="" -REDIS_MASTER_NAME="" -REDIS_USERNAME="" -REDIS_PASSWORD="" -REDIS_FAILOVER_USERNAME="" -REDIS_FAILOVER_PASSWORD="" -REDIS_TLS_ENABLED="false" -REDIS_CERT_FILE="" -REDIS_KEY_FILE="" -REDIS_CA_CERT_FILE="" -REDIS_TLS_INSECURE_SKIP_VERIFY="false" +REDIS_ADDR=redis:6379 +REDIS_ADDRS= +REDIS_MASTER_NAME= +REDIS_USERNAME= +REDIS_PASSWORD= +REDIS_FAILOVER_USERNAME= +REDIS_FAILOVER_PASSWORD= +REDIS_TLS_ENABLED=false +REDIS_CERT_FILE= +REDIS_KEY_FILE= +REDIS_CA_CERT_FILE= +REDIS_TLS_INSECURE_SKIP_VERIFY=false -SMTP_CLIENT_HOST="smtp.example.net" -SMTP_CLIENT_PORT="2525" -SMTP_CLIENT_USER="" -SMTP_CLIENT_PASSWORD="" -SMTP_CLIENT_SENDER="from@example.net" -SMTP_CLIENT_SENDER_NAME="From Name" -SMTP_CLIENT_REPORT="" +SMTP_CLIENT_HOST=smtp.example.net +SMTP_CLIENT_PORT=2525 +SMTP_CLIENT_USER= +SMTP_CLIENT_PASSWORD= +SMTP_CLIENT_SENDER=from@example.net +SMTP_CLIENT_SENDER_NAME=From Name +SMTP_CLIENT_REPORT= OTP_EXPIRATION=15m -SUBSCRIPTION_TYPE="" +SUBSCRIPTION_TYPE= MAX_CREDENTIALS=10 MAX_RECIPIENTS=10 MAX_DAILY_ALIASES=100 @@ -59,10 +60,10 @@ ACCOUNT_GRACE_PERIOD_DAYS=194 ID_LIMITER_MAX=5 ID_LIMITER_EXPIRATION=60m -BACKUP_FILENAME="backup" -BACKUP_CRON_EXPRESSION="0 0 29 2 1" +BACKUP_FILENAME=backup +BACKUP_CRON_EXPRESSION=0 0 29 2 1 BACKUP_RETENTION_DAYS=7 -GPG_PASSPHRASE="" -AWS_S3_BUCKET_NAME="" -AWS_ACCESS_KEY_ID="" -AWS_SECRET_ACCESS_KEY="" +GPG_PASSPHRASE= +AWS_S3_BUCKET_NAME= +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= diff --git a/api/config/config.go b/api/config/config.go index 5f672ee..0f2261d 100644 --- a/api/config/config.go +++ b/api/config/config.go @@ -12,11 +12,12 @@ type APIConfig struct { Name string Port string ApiAllowOrigin string + ApiTrustedProxies []string + ApiAllowIPs []string TokenSecret string TokenExpiration time.Duration ApiTokenExpiration time.Duration PSK string - PSKAllowOrigin string Domains string LogFile string BasicAuthUser string @@ -147,6 +148,8 @@ func New() (Config, error) { dbHosts := strings.Split(os.Getenv("DB_HOSTS"), ",") redisAddrs := strings.Split(os.Getenv("REDIS_ADDRESSES"), ",") + apiTrustedProxies := strings.Split(os.Getenv("API_TRUSTED_PROXIES"), ",") + apiAllowIPs := strings.Split(os.Getenv("API_ALLOW_IPS"), ",") return Config{ API: APIConfig{ @@ -154,11 +157,12 @@ func New() (Config, error) { Name: os.Getenv("API_NAME"), Port: os.Getenv("API_PORT"), ApiAllowOrigin: os.Getenv("API_ALLOW_ORIGIN"), + ApiTrustedProxies: apiTrustedProxies, + ApiAllowIPs: apiAllowIPs, TokenSecret: os.Getenv("TOKEN_SECRET"), TokenExpiration: tokenExp, ApiTokenExpiration: apiTokenExp, PSK: os.Getenv("PSK"), - PSKAllowOrigin: os.Getenv("PSK_ALLOW_ORIGIN"), Domains: os.Getenv("DOMAINS"), LogFile: os.Getenv("LOG_FILE"), BasicAuthUser: os.Getenv("BASIC_AUTH_USER"), From 1a58489967ee34e2f200a07059fa98f250064ad6 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Tue, 24 Mar 2026 20:02:48 +0100 Subject: [PATCH 2/4] feat(middleware): update auth.go --- api/internal/middleware/auth/auth.go | 17 +++++++++++++++-- api/internal/transport/api/routes.go | 6 ++++-- api/internal/transport/api/server.go | 6 +++++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/api/internal/middleware/auth/auth.go b/api/internal/middleware/auth/auth.go index 8a6b2c8..e1881ba 100644 --- a/api/internal/middleware/auth/auth.go +++ b/api/internal/middleware/auth/auth.go @@ -54,10 +54,23 @@ func New(cfg config.APIConfig, cache Cache, service Service) fiber.Handler { } } -func NewPSK(cfg config.APIConfig) fiber.Handler { +func NewIPFilter(allowedIPs []string) fiber.Handler { return func(c *fiber.Ctx) error { - if GetAuthToken(c) != cfg.PSK { + clientIP := c.IP() + for _, allowedIP := range allowedIPs { + if clientIP == allowedIP { + return c.Next() + } + } + return c.SendStatus(fiber.StatusForbidden) + } +} + +func NewPSK(psk string) fiber.Handler { + + return func(c *fiber.Ctx) error { + if GetAuthToken(c) != psk { return c.SendStatus(fiber.StatusUnauthorized) } diff --git a/api/internal/transport/api/routes.go b/api/internal/transport/api/routes.go index 5156d50..759d828 100644 --- a/api/internal/transport/api/routes.go +++ b/api/internal/transport/api/routes.go @@ -15,7 +15,8 @@ import ( func (h *Handler) SetupRoutes(cfg config.APIConfig) { email := h.Server.Group("/v1/email") - email.Use(auth.NewPSK(cfg)) + email.Use(auth.NewIPFilter(cfg.ApiAllowIPs)) + email.Use(auth.NewPSK(cfg.PSK)) email.Post("", h.HandleEmail) h.Server.Use(auth.NewAPICORS(cfg)) @@ -34,7 +35,8 @@ func (h *Handler) SetupRoutes(cfg config.APIConfig) { h.Server.Post("/v1/login/finish", limiter.New(), h.FinishLogin) sub := h.Server.Group("/v1/subscription") - sub.Use(auth.NewPSK(cfg)) + sub.Use(auth.NewIPFilter(cfg.ApiAllowIPs)) + sub.Use(auth.NewPSK(cfg.PSK)) sub.Post("/add", h.AddSubscription) api := h.Server.Group("/v1/api") diff --git a/api/internal/transport/api/server.go b/api/internal/transport/api/server.go index 9c959c7..143bba3 100644 --- a/api/internal/transport/api/server.go +++ b/api/internal/transport/api/server.go @@ -40,7 +40,11 @@ type Cache interface { func Start(cfg config.APIConfig, service Service, cache Cache) error { log.Printf("API server starting on :%s", cfg.Port) - app := fiber.New() + app := fiber.New(fiber.Config{ + EnableTrustedProxyCheck: true, + TrustedProxies: cfg.ApiTrustedProxies, + ProxyHeader: fiber.HeaderXForwardedFor, + }) h := &Handler{ Cfg: cfg, From a2a97027c53f36da11323ecbea6cb9484740b82f Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 25 Mar 2026 09:44:27 +0100 Subject: [PATCH 3/4] refactor(middleware): update auth.go --- api/internal/middleware/auth/auth.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/internal/middleware/auth/auth.go b/api/internal/middleware/auth/auth.go index e1881ba..1bebb60 100644 --- a/api/internal/middleware/auth/auth.go +++ b/api/internal/middleware/auth/auth.go @@ -3,6 +3,7 @@ package auth import ( "context" "fmt" + "slices" "strings" "time" @@ -58,11 +59,10 @@ func NewIPFilter(allowedIPs []string) fiber.Handler { return func(c *fiber.Ctx) error { clientIP := c.IP() - for _, allowedIP := range allowedIPs { - if clientIP == allowedIP { - return c.Next() - } + if slices.Contains(allowedIPs, clientIP) { + return c.Next() } + return c.SendStatus(fiber.StatusForbidden) } } @@ -70,11 +70,11 @@ func NewIPFilter(allowedIPs []string) fiber.Handler { func NewPSK(psk string) fiber.Handler { return func(c *fiber.Ctx) error { - if GetAuthToken(c) != psk { - return c.SendStatus(fiber.StatusUnauthorized) + if GetAuthToken(c) == psk { + return c.Next() } - return c.Next() + return c.SendStatus(fiber.StatusUnauthorized) } } From 1649162a87da11f1621ad97f9c7fcaf673cb8306 Mon Sep 17 00:00:00 2001 From: Juraj Hilje Date: Wed, 25 Mar 2026 16:55:37 +0100 Subject: [PATCH 4/4] feat(mailserver): update .env.sample --- mailserver/.env.sample | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mailserver/.env.sample b/mailserver/.env.sample index 7381f37..ebb920d 100644 --- a/mailserver/.env.sample +++ b/mailserver/.env.sample @@ -10,4 +10,4 @@ ENABLE_RSPAMD=1 ENABLE_FAIL2BAN=1 ENABLE_CLAMAV=0 LOG_LEVEL=info -PSK="" +PSK=