handle x-forwarded-for in IP logs

This commit is contained in:
ari melody 2025-02-07 16:54:36 +00:00
parent d9b71381b0
commit 23dbbf26e3
Signed by: ari
GPG key ID: CF99829C92678188
5 changed files with 17 additions and 13 deletions

View file

@ -115,7 +115,7 @@ func changePasswordHandler(app *model.AppState) http.Handler {
return return
} }
app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" changed password by user request. (%s)", session.Account.Username, controller.ResolveIP(r)) app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" changed password by user request. (%s)", session.Account.Username, controller.ResolveIP(app, r))
controller.SetSessionError(app.DB, session, "") controller.SetSessionError(app.DB, session, "")
controller.SetSessionMessage(app.DB, session, "Password updated successfully.") controller.SetSessionMessage(app.DB, session, "Password updated successfully.")
@ -145,7 +145,7 @@ func deleteAccountHandler(app *model.AppState) http.Handler {
// check password // check password
if err := bcrypt.CompareHashAndPassword([]byte(session.Account.Password), []byte(r.Form.Get("password"))); err != nil { if err := bcrypt.CompareHashAndPassword([]byte(session.Account.Password), []byte(r.Form.Get("password"))); err != nil {
app.Log.Warn(log.TYPE_ACCOUNT, "Account \"%s\" attempted account deletion with incorrect password. (%s)", session.Account.Username, controller.ResolveIP(r)) app.Log.Warn(log.TYPE_ACCOUNT, "Account \"%s\" attempted account deletion with incorrect password. (%s)", session.Account.Username, controller.ResolveIP(app, r))
controller.SetSessionError(app.DB, session, "Incorrect password.") controller.SetSessionError(app.DB, session, "Incorrect password.")
http.Redirect(w, r, "/admin/account", http.StatusFound) http.Redirect(w, r, "/admin/account", http.StatusFound)
return return
@ -159,7 +159,7 @@ func deleteAccountHandler(app *model.AppState) http.Handler {
return return
} }
app.Log.Info(log.TYPE_ACCOUNT, "Account \"%s\" deleted by user request. (%s)", session.Account.Username, controller.ResolveIP(r)) app.Log.Info(log.TYPE_ACCOUNT, "Account \"%s\" deleted by user request. (%s)", session.Account.Username, controller.ResolveIP(app, r))
controller.SetSessionAccount(app.DB, session, nil) controller.SetSessionAccount(app.DB, session, nil)
controller.SetSessionError(app.DB, session, "") controller.SetSessionError(app.DB, session, "")

View file

@ -201,7 +201,7 @@ func registerAccountHandler(app *model.AppState) http.Handler {
return return
} }
app.Log.Info(log.TYPE_ACCOUNT, "Account \"%s\" (%s) created using invite \"%s\". (%s)", account.Username, account.ID, invite.Code, controller.ResolveIP(r)) app.Log.Info(log.TYPE_ACCOUNT, "Account \"%s\" (%s) created using invite \"%s\". (%s)", account.Username, account.ID, invite.Code, controller.ResolveIP(app, r))
err = controller.DeleteInvite(app.DB, invite.Code) err = controller.DeleteInvite(app.DB, invite.Code)
if err != nil { if err != nil {
@ -277,7 +277,7 @@ func loginHandler(app *model.AppState) http.Handler {
err = bcrypt.CompareHashAndPassword([]byte(account.Password), []byte(password)) err = bcrypt.CompareHashAndPassword([]byte(account.Password), []byte(password))
if err != nil { if err != nil {
app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" attempted login with incorrect password. (%s)", account.Username, controller.ResolveIP(r)) app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" attempted login with incorrect password. (%s)", account.Username, controller.ResolveIP(app, r))
controller.SetSessionError(app.DB, session, "Invalid username or password.") controller.SetSessionError(app.DB, session, "Invalid username or password.")
render() render()
return return
@ -305,7 +305,7 @@ func loginHandler(app *model.AppState) http.Handler {
// login success! // login success!
// TODO: log login activity to user // TODO: log login activity to user
app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" logged in. (%s)", account.Username, controller.ResolveIP(r)) app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" logged in. (%s)", account.Username, controller.ResolveIP(app, r))
app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" does not have any TOTP methods assigned.", account.Username) app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" does not have any TOTP methods assigned.", account.Username)
err = controller.SetSessionAccount(app.DB, session, account) err = controller.SetSessionAccount(app.DB, session, account)
@ -363,7 +363,7 @@ func loginTOTPHandler(app *model.AppState) http.Handler {
totpCode := r.FormValue("totp") totpCode := r.FormValue("totp")
if len(totpCode) != controller.TOTP_CODE_LENGTH { if len(totpCode) != controller.TOTP_CODE_LENGTH {
app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" failed login (Invalid TOTP). (%s)", session.AttemptAccount.Username, controller.ResolveIP(r)) app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" failed login (Invalid TOTP). (%s)", session.AttemptAccount.Username, controller.ResolveIP(app, r))
controller.SetSessionError(app.DB, session, "Invalid TOTP.") controller.SetSessionError(app.DB, session, "Invalid TOTP.")
render() render()
return return
@ -377,13 +377,13 @@ func loginTOTPHandler(app *model.AppState) http.Handler {
return return
} }
if totpMethod == nil { if totpMethod == nil {
app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" failed login (Invalid TOTP). (%s)", session.AttemptAccount.Username, controller.ResolveIP(r)) app.Log.Warn(log.TYPE_ACCOUNT, "\"%s\" failed login (Invalid TOTP). (%s)", session.AttemptAccount.Username, controller.ResolveIP(app, r))
controller.SetSessionError(app.DB, session, "Invalid TOTP.") controller.SetSessionError(app.DB, session, "Invalid TOTP.")
render() render()
return return
} }
app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" logged in with TOTP method \"%s\". (%s)", session.AttemptAccount.Username, totpMethod.Name, controller.ResolveIP(r)) app.Log.Info(log.TYPE_ACCOUNT, "\"%s\" logged in with TOTP method \"%s\". (%s)", session.AttemptAccount.Username, totpMethod.Name, controller.ResolveIP(app, r))
err = controller.SetSessionAccount(app.DB, session, session.AttemptAccount) err = controller.SetSessionAccount(app.DB, session, session.AttemptAccount)
if err != nil { if err != nil {

View file

@ -21,6 +21,7 @@ func GetConfig() model.Config {
BaseUrl: "https://arimelody.me", BaseUrl: "https://arimelody.me",
Host: "0.0.0.0", Host: "0.0.0.0",
Port: 8080, Port: 8080,
TrustedProxies: []string{ "127.0.0.1" },
DB: model.DBConfig{ DB: model.DBConfig{
Host: "127.0.0.1", Host: "127.0.0.1",
Port: 5432, Port: 5432,

View file

@ -1,19 +1,21 @@
package controller package controller
import ( import (
"arimelody-web/model"
"net/http" "net/http"
"slices" "slices"
"strings"
) )
// Returns the request's original IP address, resolving the `x-forwarded-for` // Returns the request's original IP address, resolving the `x-forwarded-for`
// header if the request originates from a trusted proxy. // header if the request originates from a trusted proxy.
func ResolveIP(r *http.Request) string { func ResolveIP(app *model.AppState, r *http.Request) string {
trustedProxies := []string{ "10.4.20.69" } addr := strings.Split(r.RemoteAddr, ":")[0]
if slices.Contains(trustedProxies, r.RemoteAddr) { if slices.Contains(app.Config.TrustedProxies, addr) {
forwardedFor := r.Header.Get("x-forwarded-for") forwardedFor := r.Header.Get("x-forwarded-for")
if len(forwardedFor) > 0 { if len(forwardedFor) > 0 {
return forwardedFor return forwardedFor
} }
} }
return r.RemoteAddr return addr
} }

View file

@ -26,6 +26,7 @@ type (
Host string `toml:"host"` Host string `toml:"host"`
Port int64 `toml:"port"` Port int64 `toml:"port"`
DataDirectory string `toml:"data_dir"` DataDirectory string `toml:"data_dir"`
TrustedProxies []string `toml:"trusted_proxies"`
DB DBConfig `toml:"db"` DB DBConfig `toml:"db"`
Discord DiscordConfig `toml:"discord"` Discord DiscordConfig `toml:"discord"`
} }