mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-08 21:56:08 +00:00
feat: synchronize access.log client IPs across nodes (#5098)
* feat: synchronize access.log client IPs across nodes for global fail2ban limits * fix(nodes): harden cross-node client-IP merge for cluster fail2ban MergeInboundClientIps inserted new rows with the remote node's primary key, which collides with the independently auto-incremented local id and rolled back the whole sync batch — breaking exactly the node-only clients the feature targets. It also never evicted stale IPs, so the 30-minute cutoff was defeated cluster-wide (the master pushed its unpruned table back to nodes, which re-added IPs they had just pruned) and the blobs grew unbounded. - drop the remote id on create (Id=0) and guard the email-unique race with ON CONFLICT DO NOTHING; also fixes a latent Postgres sequence collision - apply the same 30-minute stale cutoff inside the merge and skip creating node-only rows whose IPs are all stale - throttle the IP fetch/merge/push to ~10s (data only refreshes every 10s) instead of running on every 5s traffic tick, cutting SQLite write churn - log the load error on the push path and tidy the merge response message - add unit tests for the merge (remote-id, dedup, stale-drop, skips) --------- Co-authored-by: Rqzbeh <Rqzbeh@example.com> Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mhsanaei/3x-ui/v3/database"
|
||||
"github.com/mhsanaei/3x-ui/v3/database/model"
|
||||
"github.com/mhsanaei/3x-ui/v3/logger"
|
||||
"github.com/mhsanaei/3x-ui/v3/web/entity"
|
||||
"github.com/mhsanaei/3x-ui/v3/web/global"
|
||||
@@ -61,6 +62,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) {
|
||||
g.GET("/getNewmldsa65", a.getNewmldsa65)
|
||||
g.GET("/getNewmlkem768", a.getNewmlkem768)
|
||||
g.GET("/getNewVlessEnc", a.getNewVlessEnc)
|
||||
g.GET("/clientIps", a.getClientIps)
|
||||
|
||||
g.POST("/stopXrayService", a.stopXrayService)
|
||||
g.POST("/restartXrayService", a.restartXrayService)
|
||||
@@ -72,6 +74,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) {
|
||||
g.POST("/xraylogs/:count", a.getXrayLogs)
|
||||
g.POST("/importDB", a.importDB)
|
||||
g.POST("/getNewEchCert", a.getNewEchCert)
|
||||
g.POST("/clientIps", a.setClientIps)
|
||||
}
|
||||
|
||||
// startTask registers the @2s ticker that refreshes server status, samples
|
||||
@@ -420,3 +423,18 @@ func (a *ServerController) getNewmlkem768(c *gin.Context) {
|
||||
}
|
||||
jsonObj(c, out, nil)
|
||||
}
|
||||
|
||||
func (a *ServerController) getClientIps(c *gin.Context) {
|
||||
ips, err := (&service.InboundService{}).GetAllInboundClientIps()
|
||||
jsonObj(c, ips, err)
|
||||
}
|
||||
|
||||
func (a *ServerController) setClientIps(c *gin.Context) {
|
||||
var ips []model.InboundClientIps
|
||||
if err := c.ShouldBindJSON(&ips); err != nil {
|
||||
jsonMsg(c, "invalid data", err)
|
||||
return
|
||||
}
|
||||
err := (&service.InboundService{}).MergeInboundClientIps(ips)
|
||||
jsonMsg(c, "Client IPs merged", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user