feat: Add NordVPN NordLynx (WireGuard) integration#3827
feat: Add NordVPN NordLynx (WireGuard) integration#3827PedroLiu1999 wants to merge 5 commits intoMHSanaei:mainfrom
Conversation
…and backend services.
fdb84c0 to
7d1f28a
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new NordVPN (NordLynx/WireGuard) outbound integration to 3x-ui, including backend endpoints/services, UI modal + routing integration, and localization updates.
Changes:
- Introduces
NordServicewith NordVPN API calls and setting persistence. - Adds
/panel/xray/nord/:actionendpoints and UI flows to configure/add/reset NordVPN wireguard outbounds. - Adds NordVPN-related UI elements and translations (EN/FA/ZH).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| web/service/nord.go | New backend service for NordVPN country/server discovery + credential storage |
| web/controller/xray_setting.go | Adds NordVPN action router/handler under Xray settings controller |
| web/service/setting.go | Adds nord setting storage getters/setters + default value |
| web/html/modals/nord_modal.html | New NordVPN configuration modal and outbound creation/reset logic |
| web/html/xray.html | Wires Nord modal into the Xray page and adds routing-related computed props |
| web/html/settings/xray/outbounds.html | Adds “NordVPN” quick-access button |
| web/html/settings/xray/basics.html | Adds NordVPN routing rule configuration UI |
| web/translation/translate.en_US.toml | Adds NordVPN + save/logout keys |
| web/translation/translate.fa_IR.toml | Adds NordVPN + save/logout keys (missing some keys used by UI) |
| web/translation/translate.zh_CN.toml | Adds NordVPN + save/logout keys (regresses outbound test toast keys) |
| data, _ := json.Marshal(nordData) | ||
| s.SettingService.SetNord(string(data)) |
There was a problem hiding this comment.
GetCredentials ignores the error returned by SetNord(...). If the settings write fails, the endpoint will still return credentials that weren’t actually saved. Please handle/return the SetNord error.
| data, _ := json.Marshal(nordData) | |
| s.SettingService.SetNord(string(data)) | |
| data, err := json.Marshal(nordData) | |
| if err != nil { | |
| return "", err | |
| } | |
| if err := s.SettingService.SetNord(string(data)); err != nil { | |
| return "", err | |
| } |
| switch action { | ||
| case "countries": | ||
| resp, err = a.NordService.GetCountries() | ||
| case "servers": | ||
| countryId := c.PostForm("countryId") |
There was a problem hiding this comment.
The nord action switch has no default case. For unknown/typo actions, this will fall through with resp == "" and err == nil, which will be treated as a successful response. Please return an explicit error (e.g., 400) for unsupported actions.
| if (this.servers.length === 0) { | ||
| app.$message.warning('No servers found for the selected country'); | ||
| } |
There was a problem hiding this comment.
Hard-coded English warning message (No servers found for the selected country) is not localized via i18n. Since the PR claims full localization, consider moving this into translation files and using an i18n key here.
| func (s *NordService) GetServers(countryId string) (string, error) { | ||
| url := fmt.Sprintf("https://api.nordvpn.com/v2/servers?limit=0&filters[servers_technologies][id]=35&filters[country_id]=%s", countryId) | ||
| resp, err := http.Get(url) | ||
| if err != nil { |
There was a problem hiding this comment.
GetServers interpolates countryId directly into the query string. Since this value comes from PostForm, it should be validated/encoded (e.g., ensure it’s numeric or use url.Values) to avoid query-parameter injection and unexpected API requests.
| } | ||
| var data map[string]any | ||
| if err := json.Unmarshal(body, &data); err != nil { | ||
| return string(body), nil |
There was a problem hiding this comment.
In GetServers, JSON unmarshal failures currently return the raw body with a nil error. The controller will treat this as success and the frontend will likely JSON.parse it and crash. This should return the unmarshal error (and/or a structured API error) instead of pretending the response is valid.
| return string(body), nil | |
| return "", err |
| this.close(); | ||
| app.$message.success('NordVPN outbound updated'); | ||
| }, |
There was a problem hiding this comment.
Hard-coded English success message (NordVPN outbound updated) is not localized via i18n. Please replace with an i18n key to match the multi-language support described in the PR.
| if load, ok := server["load"].(float64); ok && load > 7 { | ||
| filtered = append(filtered, s) | ||
| } |
There was a problem hiding this comment.
The server filtering logic keeps only servers where load > 7. This seems inconsistent with the PR description (“lowest load first”) and also discards the lowest-load servers. Please confirm the intended threshold/condition (e.g., cap high-load servers) and adjust the comparison/value accordingly.
| resp, err := http.Get("https://api.nordvpn.com/v1/countries") | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
| defer resp.Body.Close() |
There was a problem hiding this comment.
GetCountries uses http.Get without a timeout and doesn’t check resp.StatusCode. A stalled connection can hang the request, and non-200 responses will be treated as success and sent to the UI. Consider using an http.Client{Timeout: ...} and returning an error when the status is not 200 OK.
|
Thanks for your PR |
Permission granted |
0dc4df2 to
f0f98c7
Compare
Description
This PR introduces comprehensive support for NordVPN outbounds using the WireGuard (NordLynx) protocol. It enables users to easily route traffic through NordVPN servers directly from the 3x-ui panel.
Key Features
NordService) for interacting with NordVPN APIs.nord-<hostname>) for precise traffic control.Changes
Backend
web/service/nord.go: Core logic for NordVPN API interaction.web/controller/xray_setting.go: Endpoints for server fetching and credential management.web/service/setting.go: Storage and retrieval of NordVPN configuration.Frontend
web/html/modals/nord_modal.html: The main user interface for NordVPN setup.web/html/settings/xray/outbounds.html: Added "NordVPN" quick-access button.web/html/settings/xray/basics.html: Added NordVPN routing rule configuration.web/html/xray.html: Enhanced template processing for dynamic outbound tags.Localization
web/translation/translate.en_US.tomlweb/translation/translate.fa_IR.tomlweb/translation/translate.zh_CN.tomlType of Changes
Screenshots