fix: apply proxy protocol and max connection settings

This commit is contained in:
sagit
2026-04-27 10:54:25 +08:00
committed by GitHub
parent 58d2e89147
commit 2ca3849917
11 changed files with 478 additions and 60 deletions
@@ -1706,10 +1706,11 @@ func buildForwardServiceConfigs(baseName string, forward *forwardRecord, tunnel
service["climiter"] = cLimiterName
}
if forward.ProxyProtocol > 0 {
if service["metadata"] == nil {
service["metadata"] = map[string]interface{}{}
handlerConfig := service["handler"].(map[string]interface{})
if handlerConfig["metadata"] == nil {
handlerConfig["metadata"] = map[string]interface{}{}
}
service["metadata"].(map[string]interface{})["proxyProtocol"] = forward.ProxyProtocol
handlerConfig["metadata"].(map[string]interface{})["proxyProtocol"] = forward.ProxyProtocol
}
if protocol == "udp" {
listenerMetadata := map[string]interface{}{
@@ -1831,12 +1832,12 @@ func (h *Handler) ensureLimiterOnNode(nodeID int64, limiterID int64, speed int)
func (h *Handler) ensureConnLimiterOnNode(nodeID int64, limiterName string, maxConn int) error {
limitStr := fmt.Sprintf("$ %d", maxConn)
payload := map[string]interface{}{
"name": limiterName,
"limits": []string{limitStr},
}
if _, err := h.sendNodeCommand(nodeID, "AddCLimiters", payload, false, false); err != nil {
if !isAlreadyExistsMessage(err.Error()) {
return fmt.Errorf("连接限制器下发失败: %w", err)
@@ -1852,7 +1853,6 @@ func (h *Handler) ensureConnLimiterOnNode(nodeID int64, limiterName string, maxC
return nil
}
func buildLimiterAddPayload(limiterID int64, speed int) (string, map[string]interface{}) {
rate := float64(speed) / 8.0
limitStr := fmt.Sprintf("$ %.1fMB %.1fMB", rate, rate)
@@ -8,7 +8,7 @@ import (
"go-backend/internal/store/repo"
)
func TestBuildForwardServiceConfigsPreservesProxyProtocolWithInterfaceMetadata(t *testing.T) {
func TestBuildForwardServiceConfigsSendsProxyProtocolToForwardHandler(t *testing.T) {
forward := &forwardRecord{
ID: 1,
UserID: 2,
@@ -30,15 +30,27 @@ func TestBuildForwardServiceConfigsPreservesProxyProtocolWithInterfaceMetadata(t
}
for _, service := range services {
metadata, ok := service["metadata"].(map[string]interface{})
serviceMetadata, ok := service["metadata"].(map[string]interface{})
if !ok {
t.Fatalf("expected metadata map, got %T", service["metadata"])
}
if metadata["interface"] != "eth0" {
t.Fatalf("expected interface metadata eth0, got %v", metadata["interface"])
if serviceMetadata["interface"] != "eth0" {
t.Fatalf("expected interface metadata eth0, got %v", serviceMetadata["interface"])
}
if metadata["proxyProtocol"] != 2 {
t.Fatalf("expected proxyProtocol 2, got %v", metadata["proxyProtocol"])
if _, ok := serviceMetadata["proxyProtocol"]; ok {
t.Fatalf("proxyProtocol should not be listener metadata: %v", serviceMetadata)
}
handlerConfig, ok := service["handler"].(map[string]interface{})
if !ok {
t.Fatalf("expected handler config map, got %T", service["handler"])
}
handlerMetadata, ok := handlerConfig["metadata"].(map[string]interface{})
if !ok {
t.Fatalf("expected handler metadata map, got %T", handlerConfig["metadata"])
}
if handlerMetadata["proxyProtocol"] != 2 {
t.Fatalf("expected handler proxyProtocol 2, got %v", handlerMetadata["proxyProtocol"])
}
}
}
@@ -138,6 +138,15 @@ func (h *Handler) userUpdate(w http.ResponseWriter, r *http.Request) {
response.WriteJSON(w, response.ErrDefault("请不要作死"))
return
}
oldUser, err := h.repo.GetUserByID(id)
if err != nil {
response.WriteJSON(w, response.Err(-2, err.Error()))
return
}
if oldUser == nil {
response.WriteJSON(w, response.ErrDefault("用户不存在"))
return
}
dup, err := h.repo.UserExistsExcluding(username, id)
if err != nil {
@@ -210,6 +219,17 @@ func (h *Handler) userUpdate(w http.ResponseWriter, r *http.Request) {
}
}
}
if oldUser.MaxConn != maxConn {
warnings, syncErr := h.syncUserMaxConnForwards(id)
if syncErr != nil {
response.WriteJSON(w, response.ErrDefault(fmt.Sprintf("最大连接数下发失败: %v", syncErr)))
return
}
if len(warnings) > 0 {
response.WriteJSON(w, response.OK(map[string]interface{}{"warnings": warnings}))
return
}
}
response.WriteJSON(w, response.OKEmpty())
}
@@ -4254,6 +4274,26 @@ func (h *Handler) syncUserTunnelForwards(userID, tunnelID int64) error {
return nil
}
func (h *Handler) syncUserMaxConnForwards(userID int64) ([]string, error) {
forwards, err := h.listActiveForwardsByUser(userID)
if err != nil {
return nil, err
}
warnings := make([]string, 0)
for i := range forwards {
f := &forwards[i]
if f.MaxConn > 0 {
continue
}
syncWarnings, syncErr := h.syncForwardServicesWithWarnings(f, "UpdateService", true)
warnings = append(warnings, syncWarnings...)
if syncErr != nil {
return warnings, syncErr
}
}
return warnings, nil
}
// cleanupForwardsForUserTunnel deletes all forwarding rules belonging to a
// specific user+tunnel pair. It notifies nodes to remove the runtime services
// first, then deletes the DB records. This is best-effort: individual failures