mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-11 05:40:59 +00:00
fix(sub): include native WireGuard clients in Clash and JSON subscriptions (#5676)
The Clash (buildProxy) and JSON (getConfig) subscription generators had no WireGuard branch, so a native WireGuard inbound's clients were silently dropped: buildProxy hit its default nil case, and getConfig emitted a config with no proxy outbound. Only the raw subscription (genWireguardLink) and external-link Clash path handled WireGuard. Add a WireGuard case to both generators, mirroring genWireguardLink: the peer public key is derived from the inbound secretKey, while the private key, tunnel address (mihomo ip/ipv6, Xray settings.address), pre-shared key and keep-alive come from the client. The peer routes the full tunnel (0.0.0.0/0, ::/0), which both mihomo and Xray also default to. Field names verified against the mihomo WireGuardOption source (private-key, public-key, pre-shared-key, persistent-keepalive, ip, ipv6, mtu, dns) and the Xray wireguard outbound schema (secretKey, address, peers[].publicKey/endpoint/ preSharedKey/keepAlive/allowedIPs, mtu).
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/util/json_util"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/util/random"
|
||||
wgutil "github.com/mhsanaei/3x-ui/v3/internal/util/wireguard"
|
||||
)
|
||||
|
||||
//go:embed default.json
|
||||
@@ -217,6 +218,12 @@ func (s *SubJsonService) getConfig(subReq *SubService, inbound *model.Inbound, c
|
||||
newOutbounds = append(newOutbounds, s.genServer(subReq, inbound, streamSettings, client, jsonMux(mux, hostMux)))
|
||||
case "hysteria":
|
||||
newOutbounds = append(newOutbounds, s.genHy(inbound, newStream, client, jsonMux(mux, hostMux)))
|
||||
case "wireguard":
|
||||
wgOutbound := s.genWireguard(inbound, client)
|
||||
if wgOutbound == nil {
|
||||
continue
|
||||
}
|
||||
newOutbounds = append(newOutbounds, wgOutbound)
|
||||
}
|
||||
|
||||
newOutbounds = append(newOutbounds, s.defaultOutbounds...)
|
||||
@@ -519,6 +526,55 @@ func (s *SubJsonService) genHy(inbound *model.Inbound, newStream map[string]any,
|
||||
return result
|
||||
}
|
||||
|
||||
// genWireguard builds an Xray wireguard outbound for a native WireGuard inbound,
|
||||
// mirroring genWireguardLink: the peer public key is derived from the inbound
|
||||
// secretKey, the client owns the private key / tunnel address / pre-shared key,
|
||||
// and the peer routes the full tunnel. Returns nil when the client has no key.
|
||||
func (s *SubJsonService) genWireguard(inbound *model.Inbound, client model.Client) json_util.RawMessage {
|
||||
if client.PrivateKey == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var inboundSettings map[string]any
|
||||
_ = json.Unmarshal([]byte(inbound.Settings), &inboundSettings)
|
||||
secretKey, _ := inboundSettings["secretKey"].(string)
|
||||
|
||||
peer := map[string]any{
|
||||
"endpoint": joinHostPort(inbound.Listen, inbound.Port),
|
||||
"allowedIPs": []string{"0.0.0.0/0", "::/0"},
|
||||
}
|
||||
if secretKey != "" {
|
||||
if pub, err := wgutil.PublicKeyFromPrivate(secretKey); err == nil {
|
||||
peer["publicKey"] = pub
|
||||
}
|
||||
}
|
||||
if client.PreSharedKey != "" {
|
||||
peer["preSharedKey"] = client.PreSharedKey
|
||||
}
|
||||
if client.KeepAlive > 0 {
|
||||
peer["keepAlive"] = client.KeepAlive
|
||||
}
|
||||
|
||||
settings := map[string]any{
|
||||
"secretKey": client.PrivateKey,
|
||||
"peers": []any{peer},
|
||||
}
|
||||
if len(client.AllowedIPs) > 0 {
|
||||
settings["address"] = client.AllowedIPs
|
||||
}
|
||||
if mtu, ok := inboundSettings["mtu"].(float64); ok && mtu > 0 {
|
||||
settings["mtu"] = int(mtu)
|
||||
}
|
||||
|
||||
outbound := map[string]any{
|
||||
"protocol": string(inbound.Protocol),
|
||||
"tag": "proxy",
|
||||
"settings": settings,
|
||||
}
|
||||
result, _ := json.MarshalIndent(outbound, "", " ")
|
||||
return result
|
||||
}
|
||||
|
||||
func mergeFinalMask(base any, extra map[string]any) map[string]any {
|
||||
merged := map[string]any{}
|
||||
if baseMap, ok := base.(map[string]any); ok {
|
||||
|
||||
Reference in New Issue
Block a user