Merge branch 'main' into v2

* main:
  feat(config): add option for audit file (fixes #9481) (#10066)
  chore(api): log X-Forwarded-For (#10035)
  chore(gui): update dependency copyrights, add script for periodic maintenance (#10067)
  chore(gui, man, authors): update docs, translations, and contributors
  chore(syncthing): remove support for TLS 1.2 sync connections (#10064)
  fix(osutil): give threads same I/O priority on Linux (#10063)
  chore(stun): switch lookup warning to debug level
  chore(gui, man, authors): update docs, translations, and contributors
This commit is contained in:
Jakob Borg
2025-04-24 08:47:52 +07:00
31 changed files with 716 additions and 109 deletions
+48 -8
View File
@@ -18,6 +18,7 @@ import (
ldap "github.com/go-ldap/ldap/v3"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/rand"
)
@@ -27,15 +28,54 @@ const (
randomTokenLength = 64
)
func emitLoginAttempt(success bool, username, address string, evLogger events.Logger) {
evLogger.Log(events.LoginAttempt, map[string]interface{}{
func emitLoginAttempt(success bool, username string, r *http.Request, evLogger events.Logger) {
remoteAddress, proxy := remoteAddress(r)
evData := map[string]any{
"success": success,
"username": username,
"remoteAddress": address,
})
if !success {
l.Infof("Wrong credentials supplied during API authorization from %s", address)
"remoteAddress": remoteAddress,
}
if proxy != "" {
evData["proxy"] = proxy
}
evLogger.Log(events.LoginAttempt, evData)
if success {
return
}
if proxy != "" {
l.Infof("Wrong credentials supplied during API authorization from %s proxied by %s", remoteAddress, proxy)
} else {
l.Infof("Wrong credentials supplied during API authorization from %s", remoteAddress)
}
}
func remoteAddress(r *http.Request) (remoteAddr, proxy string) {
remoteAddr = r.RemoteAddr
remoteIP := osutil.IPFromString(r.RemoteAddr)
// parse X-Forwarded-For only if the proxy connects via unix socket, localhost or a LAN IP
var localProxy bool
if remoteIP != nil {
remoteAddr = remoteIP.String()
localProxy = remoteIP.IsLoopback() || remoteIP.IsPrivate() || remoteIP.IsLinkLocalUnicast()
} else if remoteAddr == "@" {
localProxy = true
}
if !localProxy {
return
}
forwardedAddr, _, _ := strings.Cut(r.Header.Get("X-Forwarded-For"), ",")
forwardedAddr = strings.TrimSpace(forwardedAddr)
forwardedIP := osutil.IPFromString(forwardedAddr)
if forwardedIP != nil {
proxy = remoteAddr
remoteAddr = forwardedIP.String()
}
return
}
func antiBruteForceSleep() {
@@ -152,7 +192,7 @@ func (m *basicAuthAndSessionMiddleware) passwordAuthHandler(w http.ResponseWrite
return
}
emitLoginAttempt(false, req.Username, r.RemoteAddr, m.evLogger)
emitLoginAttempt(false, req.Username, r, m.evLogger)
antiBruteForceSleep()
forbidden(w)
}
@@ -175,7 +215,7 @@ func attemptBasicAuth(r *http.Request, guiCfg config.GUIConfiguration, ldapCfg c
return usernameFromIso, true
}
emitLoginAttempt(false, username, r.RemoteAddr, evLogger)
emitLoginAttempt(false, username, r, evLogger)
antiBruteForceSleep()
return "", false
}
+1 -1
View File
@@ -189,7 +189,7 @@ func (m *tokenCookieManager) createSession(username string, persistent bool, w h
Path: "/",
})
emitLoginAttempt(true, username, r.RemoteAddr, m.evLogger)
emitLoginAttempt(true, username, r, m.evLogger)
}
func (m *tokenCookieManager) hasValidSession(r *http.Request) bool {