-
-
Notifications
You must be signed in to change notification settings - Fork 6.3k
fix: 11 bugs including critical data-loss and security issues #3974
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,35 +33,34 @@ var upgrader = ws.Upgrader{ | |
| ReadBufferSize: 4096, // Increased from 1024 for better performance | ||
| WriteBufferSize: 4096, // Increased from 1024 for better performance | ||
| CheckOrigin: func(r *http.Request) bool { | ||
| // Check origin for security | ||
| origin := r.Header.Get("Origin") | ||
| if origin == "" { | ||
| // Allow connections without Origin header (same-origin requests) | ||
| return true | ||
| } | ||
| // Get the host from the request | ||
| host := r.Host | ||
| // Extract scheme and host from origin | ||
| originURL := origin | ||
| // Simple check: origin should match the request host | ||
| // This prevents cross-origin WebSocket hijacking | ||
| if strings.HasPrefix(originURL, "http://") || strings.HasPrefix(originURL, "https://") { | ||
| // Extract host from origin | ||
| originHost := strings.TrimPrefix(strings.TrimPrefix(originURL, "http://"), "https://") | ||
|
|
||
| // Extract host from origin | ||
| originHost := origin | ||
| if strings.HasPrefix(originHost, "http://") || strings.HasPrefix(originHost, "https://") { | ||
| originHost = strings.TrimPrefix(strings.TrimPrefix(originHost, "http://"), "https://") | ||
| if idx := strings.Index(originHost, "/"); idx != -1 { | ||
| originHost = originHost[:idx] | ||
| } | ||
| if idx := strings.Index(originHost, ":"); idx != -1 { | ||
| originHost = originHost[:idx] | ||
| } | ||
|
|
||
| // Normalize host for comparison (strip ports and IPv6 brackets) | ||
| normalizeHost := func(h string) string { | ||
| h = strings.TrimPrefix(h, "[") | ||
| if idx := strings.LastIndex(h, "]:"); idx != -1 { | ||
| h = h[:idx+1] | ||
| } | ||
| // Compare hosts (without port) | ||
| requestHost := host | ||
| if idx := strings.Index(requestHost, ":"); idx != -1 { | ||
| requestHost = requestHost[:idx] | ||
| if idx := strings.LastIndex(h, ":"); idx != -1 && !strings.Contains(h[:idx], "]") { | ||
|
Comment on lines
+53
to
+57
|
||
| h = h[:idx] | ||
| } | ||
| return originHost == requestHost || originHost == "" || requestHost == "" | ||
| return h | ||
| } | ||
| return false | ||
|
|
||
| return normalizeHost(originHost) == normalizeHost(r.Host) | ||
| }, | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -190,23 +190,7 @@ func (s *InboundService) checkEmailExistForInbound(inbound *model.Inbound) (stri | |
| if err != nil { | ||
| return "", err | ||
| } | ||
| allEmails, err := s.getAllEmails() | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| var emails []string | ||
| for _, client := range clients { | ||
| if client.Email != "" { | ||
| if s.contains(emails, client.Email) { | ||
| return client.Email, nil | ||
| } | ||
| if s.contains(allEmails, client.Email) { | ||
| return client.Email, nil | ||
| } | ||
| emails = append(emails, client.Email) | ||
| } | ||
| } | ||
| return "", nil | ||
| return s.checkEmailsExistForClients(clients) | ||
| } | ||
|
|
||
| // AddInbound creates a new inbound configuration. | ||
|
|
@@ -339,7 +323,7 @@ func (s *InboundService) DelInbound(id int) (bool, error) { | |
| } | ||
| s.xrayApi.Close() | ||
| } else { | ||
| logger.Debug("No enabled inbound founded to removing by api", tag) | ||
| logger.Debug("No enabled inbound found to remove by api for inbound id:", id) | ||
| } | ||
|
|
||
| // Delete client traffics of inbounds | ||
|
|
@@ -1280,12 +1264,8 @@ func (s *InboundService) disableInvalidClients(tx *gorm.DB) (bool, int64, error) | |
| if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) { | ||
| logger.Debug("User is already disabled. Nothing to do more...") | ||
| } else { | ||
| if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", result.Email)) { | ||
| logger.Debug("User is already disabled. Nothing to do more...") | ||
| } else { | ||
| logger.Debug("Error in disabling client by api:", err1) | ||
| needRestart = true | ||
| } | ||
| logger.Debug("Error in disabling client by api:", err1) | ||
| needRestart = true | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -1458,16 +1438,16 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (boo | |
| return false, err | ||
| } | ||
| clients := settings["clients"].([]any) | ||
| var newClients []any | ||
| for client_index := range clients { | ||
| c := clients[client_index].(map[string]any) | ||
| if c["email"] == clientEmail { | ||
| c["tgId"] = tgId | ||
| c["updated_at"] = time.Now().Unix() * 1000 | ||
| newClients = append(newClients, any(c)) | ||
| clients[client_index] = c | ||
| break | ||
| } | ||
| } | ||
| settings["clients"] = newClients | ||
| settings["clients"] = clients | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This change now sends the entire Useful? React with πΒ / π. |
||
| modifiedSettings, err := json.MarshalIndent(settings, "", " ") | ||
| if err != nil { | ||
| return false, err | ||
|
|
@@ -1545,16 +1525,16 @@ func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, bo | |
| return false, false, err | ||
| } | ||
| clients := settings["clients"].([]any) | ||
| var newClients []any | ||
| for client_index := range clients { | ||
| c := clients[client_index].(map[string]any) | ||
| if c["email"] == clientEmail { | ||
| c["enable"] = !clientOldEnabled | ||
| c["updated_at"] = time.Now().Unix() * 1000 | ||
| newClients = append(newClients, any(c)) | ||
| clients[client_index] = c | ||
| break | ||
| } | ||
| } | ||
| settings["clients"] = newClients | ||
| settings["clients"] = clients | ||
| modifiedSettings, err := json.MarshalIndent(settings, "", " ") | ||
| if err != nil { | ||
| return false, false, err | ||
|
|
@@ -1625,16 +1605,16 @@ func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int | |
| return false, err | ||
| } | ||
| clients := settings["clients"].([]any) | ||
| var newClients []any | ||
| for client_index := range clients { | ||
| c := clients[client_index].(map[string]any) | ||
| if c["email"] == clientEmail { | ||
| c["limitIp"] = count | ||
| c["updated_at"] = time.Now().Unix() * 1000 | ||
| newClients = append(newClients, any(c)) | ||
| clients[client_index] = c | ||
| break | ||
| } | ||
| } | ||
| settings["clients"] = newClients | ||
| settings["clients"] = clients | ||
| modifiedSettings, err := json.MarshalIndent(settings, "", " ") | ||
| if err != nil { | ||
| return false, err | ||
|
|
@@ -1684,16 +1664,16 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry | |
| return false, err | ||
| } | ||
| clients := settings["clients"].([]any) | ||
| var newClients []any | ||
| for client_index := range clients { | ||
| c := clients[client_index].(map[string]any) | ||
| if c["email"] == clientEmail { | ||
| c["expiryTime"] = expiry_time | ||
| c["updated_at"] = time.Now().Unix() * 1000 | ||
| newClients = append(newClients, any(c)) | ||
| clients[client_index] = c | ||
| break | ||
| } | ||
| } | ||
| settings["clients"] = newClients | ||
| settings["clients"] = clients | ||
| modifiedSettings, err := json.MarshalIndent(settings, "", " ") | ||
| if err != nil { | ||
| return false, err | ||
|
|
@@ -1746,16 +1726,16 @@ func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, tota | |
| return false, err | ||
| } | ||
| clients := settings["clients"].([]any) | ||
| var newClients []any | ||
| for client_index := range clients { | ||
| c := clients[client_index].(map[string]any) | ||
| if c["email"] == clientEmail { | ||
| c["totalGB"] = totalGB * 1024 * 1024 * 1024 | ||
| c["updated_at"] = time.Now().Unix() * 1000 | ||
| newClients = append(newClients, any(c)) | ||
| clients[client_index] = c | ||
| break | ||
| } | ||
| } | ||
| settings["clients"] = newClients | ||
| settings["clients"] = clients | ||
| modifiedSettings, err := json.MarshalIndent(settings, "", " ") | ||
| if err != nil { | ||
| return false, err | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as web server: after
httpServer.Shutdown(...)(when serving withServe(listener)), the listener is usually already closed. The subsequents.listener.Close()can returnnet.ErrClosedand bubble up viacommon.Combine, turning a clean shutdown into an error. Consider skipping the extra close or ignoringnet.ErrClosed.