mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-12 07:36:07 +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:
@@ -533,3 +533,22 @@ func isNonEmptySlice(v any) bool {
|
||||
s, ok := v.([]any)
|
||||
return ok && len(s) > 0
|
||||
}
|
||||
|
||||
func (r *Remote) FetchAllClientIps(ctx context.Context) ([]model.InboundClientIps, error) {
|
||||
env, err := r.do(ctx, http.MethodGet, "panel/api/server/clientIps", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var ips []model.InboundClientIps
|
||||
if len(env.Obj) > 0 {
|
||||
if err := json.Unmarshal(env.Obj, &ips); err != nil {
|
||||
return nil, fmt.Errorf("decode client ips: %w", err)
|
||||
}
|
||||
}
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
func (r *Remote) PushAllClientIps(ctx context.Context, ips []model.InboundClientIps) error {
|
||||
_, err := r.do(ctx, http.MethodPost, "panel/api/server/clientIps", ips)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user