Aller au contenu principal

Xray JSON – Advanced

Aperçu

Pour les modèles d'abonnement de type XRAY_JSON dans Remnawave, des directives Remnawave sont disponibles — des instructions spéciales que vous ajoutez au modèle JSON. Le panel les traite lors de la génération de l'abonnement et les supprime de la configuration finale — le client ne les verra jamais.

Actuellement, la directive injectHosts est disponible, permettant d'injecter dynamiquement les configurations outbound des hôtes dans le modèle. Cela est utile lorsque vous avez besoin de construire une configuration Xray complexe avec des équilibreurs de charge, un routage personnalisé ou plusieurs outbounds, les données de connexion (adresse, port, clés) étant insérées automatiquement depuis le panel.

Conseil

Les configurations présentées ci-dessous sont des exemples pour démontrer le mécanisme d'injection. Adaptez-les à vos besoins.

Attention

Nécessite Remnawave version 2.6.3 ou plus récente.

Conditions de fonctionnement

  • L'hôte virtuel (l'hôte auquel est assigné le modèle avec injection) doit être activé et non masqué.
  • Les hôtes à injecter (sélectionnés via selector) doivent être activés. Par défaut, seuls les hôtes masqués sont sélectionnés (le comportement peut être modifié via selectFrom).
  • Tous les hôtes — aussi bien l'hôte virtuel que les hôtes à injecter — doivent être accessibles à l'utilisateur final : l'inbound auquel ils sont liés doit être inclus dans le squad de l'utilisateur.
  • De l'hôte virtuel, la remarque (remark) et la description du serveur (Server Description, si définie) sont transférées dans la configuration finale.

Structure de remnawave

L'objet remnawave est ajouté au niveau racine du modèle JSON. Il prend en charge les champs suivants :

ChampDescription
injectHostsTableau de groupes d'injection. Chaque groupe contient un sélecteur pour la sélection des hôtes et des paramètres de formation des tags.
addVirtualHostAsOutboundSi true — l'hôte virtuel sera ajouté en tant qu'outbound avec le tag proxy au début du tableau outbounds. Par défaut false. Voir addVirtualHostAsOutbound.

Le champ injectHosts est un tableau de groupes d'injection. Chaque groupe contient un sélecteur pour la sélection des hôtes et son propre tagPrefix :

"remnawave": {
"injectHosts": [
{
"selector": { "type": "uuids", "values": ["uuid-hote-1", "uuid-hote-2"] },
"tagPrefix": "proxy"
},
{
"selector": { "type": "remarkRegex", "pattern": "^RU-" },
"tagPrefix": "backup"
}
]
},

Chaque élément du tableau injectHosts :

ChampDescription
selectorObjet définissant quels hôtes seront sélectionnés. Champ obligatoire.
selectFromDans quel pool sélectionner les hôtes : "HIDDEN" (par défaut), "NOT_HIDDEN" ou "ALL".
tagPrefixPréfixe de tag pour les outbounds créés. Voir règles de formation des tags.
useHostRemarkAsTagSi true — le tag de l'outbound sera la remarque (remark) de l'hôte.
useHostTagAsTagSi true — le tag de l'outbound sera le tag de l'hôte (si aucun tag n'est défini, la remarque est utilisée).
attention

Il faut spécifier exactement un des trois champs : tagPrefix, useHostRemarkAsTag ou useHostTagAsTag.

Il peut y avoir un nombre quelconque de groupes — chacun forme son propre ensemble indépendant d'outbounds avec son propre préfixe. Cela permet, par exemple, de créer un équilibreur de charge séparé pour chaque groupe de serveurs.

Types de sélecteurs

uuids

Sélectionne les hôtes par une liste d'UUID. L'ordre des UUID détermine l'ordre des outbounds.

"selector": {
"type": "uuids",
"values": [
"8478b271-95d3-4312-85ae-ecf63fb53d1d",
"d31d6161-1315-4c1e-9a4b-141ab1c022f6"
]
}

remarkRegex

Sélectionne les hôtes dont la remarque (remark) correspond à l'expression régulière. Syntaxe — JavaScript RegExp.

"selector": {
"type": "remarkRegex",
"pattern": "^Balancer"
}

L'exemple ci-dessus sélectionnera tous les hôtes masqués dont la remarque commence par «Balancer» (par exemple, «Balancer #1», «Balancer RU»).

tagRegex

Sélectionne les hôtes dont le tag d'hôte (champ tag dans les paramètres de l'hôte) correspond à l'expression régulière.

"selector": {
"type": "tagRegex",
"pattern": "^balancer-"
}

L'exemple ci-dessus sélectionnera tous les hôtes masqués avec un tag commençant par balancer-.

sameTagAsRecipient

Sélectionne tous les hôtes masqués dont le tag d'hôte correspond au tag de l'hôte virtuel. Ne nécessite pas de paramètres supplémentaires.

"selector": {
"type": "sameTagAsRecipient"
}

Pratique lorsque vous souhaitez regrouper automatiquement les hôtes : il suffit d'attribuer le même tag à l'hôte virtuel et aux hôtes à injecter.

astuce

Par défaut, tous les sélecteurs ne travaillent qu'avec les hôtes masqués. Pour changer ce comportement, utilisez le champ selectFrom : la valeur "NOT_HIDDEN" sélectionnera uniquement les hôtes visibles (activés, mais non masqués), et "ALL" — tous les hôtes (activés, masqués).

Règles de formation des tags

Le tag d'un outbound est déterminé par lequel des trois champs est spécifié dans le groupe d'injection :

tagPrefix — Le premier hôte reçoit un tag égal à tagPrefix. Chaque suivant — {tagPrefix}-{N}, à partir de 2.

Exemple pour trois hôtes avec tagPrefix: "proxy" :

OrdreTag de l'outbound
1erproxy
2èmeproxy-2
3èmeproxy-3

useHostRemarkAsTag — Chaque outbound reçoit un tag égal à la remarque (remark) de l'hôte.

{
"selector": { "type": "tagRegex", "pattern": "^ru-" },
"useHostRemarkAsTag": true
}

Si les hôtes ont les remarques «Moscou», «Saint-Pétersbourg», «Kazan» — les outbounds recevront les tags Moscou, Saint-Pétersbourg, Kazan.

useHostTagAsTag — Chaque outbound reçoit un tag égal au tag de l'hôte. Si le tag de l'hôte n'est pas défini, sa remarque est utilisée.

{
"selector": { "type": "tagRegex", "pattern": "^ru-" },
"useHostTagAsTag": true
}

Correspondance par préfixe dans Xray

Les champs selector (dans routing.balancers) et subjectSelector (dans burstObservatory) dans Xray fonctionnent comme des comparateurs de préfixe — ils sont comparés au début du tag de l'outbound, pas à sa valeur exacte.

Par exemple, si la configuration contient des outbounds avec les tags proxy, proxy-2, proxy-3, direct :

Valeur de selector / subjectSelectorQuels outbounds seront sélectionnés
["proxy"]proxy, proxy-2, proxy-3
["proxy-"]proxy-2, proxy-3
  • "selector": ["proxy"] — capturera tous les outbounds injectés, y compris le premier.
  • "selector": ["proxy-"] — capturera tous sauf le premier (uniquement proxy-2, proxy-3, ...).
Fallback via le premier hôte

Le premier hôte sélectionné reçoit toujours un tag sans le suffixe -{N} (simplement proxy). Cela permet de l'utiliser comme fallbackTag dans l'équilibreur de charge : si tous les outbounds du selector sont indisponibles, le trafic ira vers le premier hôte. Pour cela, définissez "selector": ["proxy-"] (uniquement proxy-2, proxy-3, ...) et "fallbackTag": "proxy".

addVirtualHostAsOutbound

Par défaut, lors de l'utilisation de la directive remnawave, seuls les hôtes injectés entrent dans la configuration finale. L'hôte virtuel (recipient) lui-même n'est utilisé que comme source de remarks et serverDescription.

Si vous avez besoin que l'hôte virtuel devienne également un outbound avec le tag proxy, ajoutez le champ addVirtualHostAsOutbound: true au niveau de l'objet remnawave :

"remnawave": {
"addVirtualHostAsOutbound": true,
"injectHosts": [
{
"selector": { "type": "uuids", "values": ["uuid-hote-1", "uuid-hote-2"] },
"tagPrefix": "proxy"
},
{
"selector": { "type": "remarkRegex", "pattern": "^RU-" },
"tagPrefix": "backup"
}
]
}

Dans ce cas, le tableau outbounds final ressemblera à ceci :

  1. Outbound de l'hôte virtuel avec le tag proxy.
  2. Outbounds injectés (depuis injectHosts).
  3. Outbounds statiques du modèle (direct, block etc.).

Cela est utile lorsque dans les règles de routing "outboundTag": "proxy" est utilisé pour diriger le trafic via l'hôte principal, tandis que les hôtes injectés servent des groupes de trafic séparés (par exemple, via des équilibreurs de charge).

astuce

addVirtualHostAsOutbound peut être utilisé avec ou sans injectHosts. Si injectHosts n'est pas spécifié ou est vide, seul l'outbound de l'hôte virtuel sera ajouté à la configuration.

Exemple pas à pas : équilibreur de charge avec trois hôtes

Dans cet exemple, nous allons créer une configuration dans laquelle trois outbounds sont combinés dans un équilibreur de charge avec la stratégie leastLoad et surveillés par un observatory.

Étape 1. Créer les hôtes

Créez dans le panel les hôtes qui participeront à l'injection. Dans notre exemple, ce sont :

  • Virtual Host — l'hôte virtuel auquel sera assigné le modèle avec injection. Il n'est pas masqué et c'est via lui que l'utilisateur final recevra la configuration.
  • Balancer #1, Balancer #2, Balancer #3 — hôtes dont les outbounds seront insérés dans le modèle.
Liste des hôtes

Étape 2. Masquer les hôtes à injecter

Ouvrez la fiche de chaque hôte équilibreur (Balancer #1, #2, #3), naviguez vers la section Avancé et activez le commutateur Masquer l'hôte.

Les hôtes masqués n'apparaissent pas dans l'abonnement habituel — ils ne sont accessibles que via le mécanisme d'injection.

Masquage des hôtes équilibreurs

Étape 3. Créer le modèle d'abonnement

Créez un modèle d'abonnement de type XRAY_JSON. Décrivez-y la configuration complète : dns, routing, inbounds, outbounds, burstObservatory et autres sections nécessaires.

Placez dans le tableau outbounds uniquement les outbounds statiques (direct, block) — les outbounds des hôtes à injecter seront ajoutés automatiquement.

Au niveau racine du JSON, ajoutez l'objet remnawave avec le sélecteur d'hôtes masqués.

Exemple de modèle

{
"remnawave": {
"injectHosts": [
{
"selector": {
"type": "uuids",
"values": [
"8478b271-95d3-4312-85ae-ecf63fb53d1d",
"d31d6161-1315-4c1e-9a4b-141ab1c022f6",
"5749f69e-cd1b-4012-9407-450434085196"
]
},
"tagPrefix": "proxy"
}
]
},
"burstObservatory": {
"pingConfig": {
"timeout": "3s",
"interval": "1m",
"sampling": 1,
"destination": "http://www.gstatic.com/generate_204",
"connectivity": ""
},
"subjectSelector": ["proxy"]
},
"dns": {
"servers": ["1.1.1.1", "1.0.0.1"],
"queryStrategy": "UseIP"
},
"routing": {
"balancers": [
{
"tag": "Super_Balancer",
"selector": ["proxy"],
"strategy": {
"type": "leastLoad",
"settings": {
"maxRTT": "1s",
"expected": 2,
"baselines": ["1s"],
"tolerance": 0.01
}
},
"fallbackTag": "direct"
}
],
"rules": [
{
"protocol": ["bittorrent"],
"outboundTag": "direct"
},
{
"network": "tcp,udp",
"balancerTag": "Super_Balancer"
}
],
"domainMatcher": "hybrid",
"domainStrategy": "IPIfNonMatch"
},
"inbounds": [
{
"tag": "socks",
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"udp": true,
"auth": "noauth"
},
"sniffing": {
"enabled": true,
"routeOnly": false,
"destOverride": ["http", "tls", "quic"]
}
},
{
"tag": "http",
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http",
"settings": {
"allowTransparent": false
},
"sniffing": {
"enabled": true,
"routeOnly": false,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
]
}

Notez :

  • "subjectSelector": ["proxy"] — l'observatory surveillera tous les outbounds dont le tag commence par proxy (c'est-à-dire proxy, proxy-2, proxy-3).
  • "selector": ["proxy"] — l'équilibreur de charge Super_Balancer distribuera le trafic entre les mêmes outbounds.
  • Dans les outbounds du modèle, seuls direct et block sont indiqués — les outbounds des hôtes seront ajoutés automatiquement avant eux.

Étape 4. Assigner le modèle à l'hôte virtuel

Ouvrez la fiche de l'hôte virtuel (Virtual Host), naviguez vers la section Avancé et dans le champ Modèle Xray JSON sélectionnez le modèle créé.

Assurez-vous que le commutateur Masquer l'hôte pour l'hôte virtuel est désactivé — il doit être visible dans l'abonnement.

Assignation du modèle à l'hôte virtuel

Étape 5. Résultat

Lors de la demande d'abonnement, le panel traite automatiquement :

  1. Prend le modèle assigné à l'hôte virtuel.
  2. Supprime l'objet remnawave de celui-ci.
  3. Pour chaque groupe dans injectHosts, sélectionne les hôtes masqués par selector et collecte leurs outbounds.
  4. Insère les outbounds au début du tableau outbounds.
  5. Définit remarks depuis la remarque de l'hôte virtuel.

Configuration finale que recevra le client

[
{
"dns": {
"servers": ["1.1.1.1", "1.0.0.1"],
"queryStrategy": "UseIP"
},
"routing": {
"rules": [
{
"protocol": ["bittorrent"],
"outboundTag": "direct"
},
{
"network": "tcp,udp",
"balancerTag": "Super_Balancer"
}
],
"balancers": [
{
"tag": "Super_Balancer",
"selector": ["proxy"],
"strategy": {
"type": "leastLoad",
"settings": {
"maxRTT": "1s",
"expected": 2,
"baselines": ["1s"],
"tolerance": 0.01
}
},
"fallbackTag": "direct"
}
],
"domainMatcher": "hybrid",
"domainStrategy": "IPIfNonMatch"
},
"inbounds": [
{
"tag": "socks",
...omitted...
},
{
"tag": "http",
...omitted...
}
],
"outbounds": [
{
"tag": "proxy",
"protocol": "vless",
"settings": {...omitted...},
"streamSettings": {...omitted...}
},
{
"tag": "proxy-2",
"protocol": "vless",
"settings": {...omitted...},
"streamSettings": {...omitted...}
},
{
"tag": "proxy-3",
"protocol": "vless",
"settings": {...omitted...},
"streamSettings": {...omitted...}
},
{
"tag": "direct",
"protocol": "freedom"
},
{
"tag": "block",
"protocol": "blackhole"
}
],
"burstObservatory": {
"pingConfig": {
"timeout": "3s",
"interval": "1m",
"sampling": 1,
"destination": "http://www.gstatic.com/generate_204",
"connectivity": ""
},
"subjectSelector": ["proxy"]
},
"remarks": "Virtual Host"
}
]

Ce qui s'est passé :

  • L'objet remnawave a été supprimé de la configuration finale.
  • Trois outbounds (proxy, proxy-2, proxy-3) ont été insérés au début du tableau outbounds, avant direct et block.
  • "selector": ["proxy"] dans l'équilibreur de charge a automatiquement capturé les trois outbounds, car leurs tags commencent par proxy (correspondance par préfixe).
  • "subjectSelector": ["proxy"] dans l'observatory a également capturé les trois outbounds pour la surveillance.
  • "remarks": "Virtual Host" — pris depuis la remarque de l'hôte virtuel.
remarque

Adresse de l'hôte virtuel et inbound réel

L'hôte virtuel dans ce scénario sert d'«enveloppe» pour le modèle et les métadonnées (remarque, description du serveur), pas comme un vrai point de connexion. Dans ses paramètres, on peut indiquer n'importe quelle adresse (par exemple, balancer.host.com) — elle ne participe pas à la connexion réelle de l'utilisateur. Le vrai point d'entrée est l'inbound spécifique des hôtes injectés. Il est important que l'utilisateur demandant l'abonnement ait accès à cet inbound via les squads, sinon l'hôte virtuel n'apparaîtra pas du tout dans son abonnement. Les paramètres de connexion réels (adresses, ports, clés, etc.) sont pris des hôtes injectés, dont les configurations outbound sont insérées dans la configuration finale côté client.

Remarques importantes

  • L'hôte virtuel doit être activé et non masqué. C'est lui qui détermine quel modèle sera utilisé, et c'est de lui que sont tirés remarks et description.
  • Les hôtes à injecter doivent être activés. Par défaut, seuls les hôtes masqués sont sélectionnés (selectFrom: "HIDDEN"). Ce comportement peut être changé en "NOT_HIDDEN" ou "ALL". Si un hôte est désactivé ou introuvable par le sélecteur — il sera ignoré.
  • Tous les hôtes participants doivent être accessibles à l'utilisateur final — l'inbound auquel ils sont liés doit être inclus dans le squad de l'utilisateur.
  • L'objet remnawave est supprimé de la configuration finale — le client ne le verra pas.
  • Les outbounds sont ajoutés au début du tableau outbounds. Si addVirtualHostAsOutbound est activé, l'outbound de l'hôte virtuel avec le tag proxy vient en premier, puis les injectés, puis les outbounds statiques du modèle (direct, block).
  • L'ordre des hôtes détermine l'ordre des outbounds et les tags qui leur sont attribués. Pour le sélecteur uuids — l'ordre des UUID dans le tableau values. Au lieu de tagPrefix, on peut utiliser useHostRemarkAsTag ou useHostTagAsTag pour que les tags soient formés à partir des propriétés des hôtes.
  • La sélection du modèle et le masquage de l'hôte se trouvent dans la section Avancé dans la fiche de l'hôte.