Saltar al contenido principal

Xray JSON – Advanced

Descripción general

Para las plantillas de suscripción de tipo XRAY_JSON en Remnawave, se proporcionan directivas Remnawave — instrucciones especiales que se agregan a la plantilla JSON. El panel las procesa al generar la suscripción y las elimina de la configuración final — el cliente nunca las verá.

Actualmente está disponible la directiva injectHosts, que permite insertar dinámicamente las configuraciones de outbound de los hosts en la plantilla. Esto es útil cuando necesita construir una configuración Xray compleja con balanceadores de carga, enrutamiento personalizado o varios outbounds, con los datos de conexión (dirección, puerto, claves) insertados automáticamente desde el panel.

Consejo

Las configuraciones presentadas a continuación son ejemplos para demostrar el mecanismo de inyección. Adáptelas a sus necesidades.

Atención

Requiere Remnawave versión 2.6.3 o más reciente.

Condiciones de funcionamiento

  • El host virtual (el host al que se le asigna la plantilla con inyección) debe estar habilitado y no oculto.
  • Los hosts a inyectar (seleccionados a través de selector) deben estar habilitados. Por defecto solo se seleccionan los hosts ocultos (el comportamiento se puede cambiar a través de selectFrom).
  • Todos los hosts — tanto el virtual como los a inyectar — deben ser accesibles para el usuario final: el inbound al que están vinculados debe estar incluido en el squad del usuario.
  • Del host virtual pasan a la configuración final la observación (remark) y la descripción del servidor (Server Description, si está configurada).

Estructura de remnawave

El objeto remnawave se agrega al nivel raíz de la plantilla JSON. Admite los siguientes campos:

CampoDescripción
injectHostsArray de grupos de inyección. Cada grupo contiene un selector para la selección de hosts y parámetros de formación de tags.
addVirtualHostAsOutboundSi es true — el host virtual se agregará como outbound con el tag proxy al inicio del array outbounds. Por defecto es false. Ver addVirtualHostAsOutbound.

El campo injectHosts es un array de grupos de inyección. Cada grupo contiene un selector para la selección de hosts y su propio tagPrefix:

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

Cada elemento del array injectHosts:

CampoDescripción
selectorObjeto que define qué hosts serán seleccionados. Campo obligatorio.
selectFromDe qué grupo seleccionar hosts: "HIDDEN" (por defecto), "NOT_HIDDEN" o "ALL".
tagPrefixPrefijo de tag para los outbounds creados. Ver reglas de formación de tags.
useHostRemarkAsTagSi es true — el tag del outbound será la observación (remark) del host.
useHostTagAsTagSi es true — el tag del outbound será el tag del host (si no se establece un tag, se usa la observación).
aviso

Se debe especificar exactamente uno de los tres campos: tagPrefix, useHostRemarkAsTag o useHostTagAsTag.

Puede haber cualquier número de grupos — cada uno forma su propio conjunto independiente de outbounds con su propio prefijo. Esto permite, por ejemplo, crear un balanceador de carga separado para cada grupo de servidores.

Tipos de selectores

uuids

Selecciona hosts por una lista de UUID. El orden de los UUID determina el orden de los outbounds.

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

remarkRegex

Selecciona hosts cuya observación (remark) coincide con la expresión regular. Sintaxis — JavaScript RegExp.

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

El ejemplo anterior seleccionará todos los hosts ocultos cuya observación comience con «Balancer» (por ejemplo, «Balancer #1», «Balancer RU»).

tagRegex

Selecciona hosts cuyo tag de host (campo tag en la configuración del host) coincide con la expresión regular.

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

El ejemplo anterior seleccionará todos los hosts ocultos con un tag que comience con balancer-.

sameTagAsRecipient

Selecciona todos los hosts ocultos cuyo tag de host coincide con el tag del host virtual. No requiere parámetros adicionales.

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

Conveniente cuando desea agrupar hosts automáticamente: basta con asignar el mismo tag al host virtual y a los hosts a inyectar.

tip

Por defecto, todos los selectores trabajan solo con hosts ocultos. Para cambiar este comportamiento, use el campo selectFrom: el valor "NOT_HIDDEN" seleccionará solo los hosts visibles (habilitados, pero no ocultos), y "ALL" — todos los hosts (habilitados, ocultos).

Reglas de formación de tags

El tag de un outbound se determina por cuál de los tres campos está especificado en el grupo de inyección:

tagPrefix — El primer host recibe un tag igual a tagPrefix. Cada siguiente — {tagPrefix}-{N}, comenzando desde 2.

Ejemplo para tres hosts con tagPrefix: "proxy":

OrdenTag del outbound
1.°proxy
2.°proxy-2
3.°proxy-3

useHostRemarkAsTag — Cada outbound recibe un tag igual a la observación (remark) del host.

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

Si los hosts tienen las observaciones «Moscú», «Petersburgo», «Kazán» — los outbounds recibirán los tags Moscú, Petersburgo, Kazán.

useHostTagAsTag — Cada outbound recibe un tag igual al tag del host. Si no se establece el tag del host, se usa su observación.

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

Coincidencia por prefijo en Xray

Los campos selector (en routing.balancers) y subjectSelector (en burstObservatory) en Xray funcionan como comparadores de prefijo — se comparan con el inicio del tag del outbound, no con su valor exacto.

Por ejemplo, si la configuración contiene outbounds con los tags proxy, proxy-2, proxy-3, direct:

Valor de selector / subjectSelectorQué outbounds serán seleccionados
["proxy"]proxy, proxy-2, proxy-3
["proxy-"]proxy-2, proxy-3
  • "selector": ["proxy"] — capturará todos los outbounds inyectados, incluido el primero.
  • "selector": ["proxy-"] — capturará todos excepto el primero (solo proxy-2, proxy-3, ...).
Fallback a través del primer host

El primer host seleccionado siempre recibe un tag sin el sufijo -{N} (simplemente proxy). Esto permite usarlo como fallbackTag en el balanceador de carga: si todos los outbounds del selector no están disponibles, el tráfico irá al primer host. Para ello, configure "selector": ["proxy-"] (solo proxy-2, proxy-3, ...) y "fallbackTag": "proxy".

addVirtualHostAsOutbound

Por defecto, al usar la directiva remnawave, solo los hosts inyectados entran en la configuración final. El host virtual (recipient) en sí se usa solo como fuente de remarks y serverDescription.

Si necesita que el host virtual también se convierta en un outbound con el tag proxy, agregue el campo addVirtualHostAsOutbound: true en el nivel del objeto remnawave:

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

En este caso, el array outbounds final se verá así:

  1. Outbound del host virtual con el tag proxy.
  2. Outbounds inyectados (de injectHosts).
  3. Outbounds estáticos de la plantilla (direct, block etc.).

Esto es útil cuando en las reglas de routing se usa "outboundTag": "proxy" para dirigir el tráfico a través del host principal, mientras que los hosts inyectados atienden grupos de tráfico separados (por ejemplo, a través de balanceadores de carga).

tip

addVirtualHostAsOutbound se puede usar junto con injectHosts o sin ellos. Si injectHosts no está especificado o está vacío, solo se agregará el outbound del host virtual a la configuración.

Ejemplo paso a paso: balanceador de carga con tres hosts

En este ejemplo crearemos una configuración en la que tres outbounds se combinan en un balanceador de carga con la estrategia leastLoad y son monitoreados por un observatory.

Paso 1. Crear los hosts

Cree en el panel los hosts que participarán en la inyección. En nuestro ejemplo son:

  • Virtual Host — el host virtual al que se le asignará la plantilla con inyección. No está oculto y el usuario final recibirá la configuración a través de él.
  • Balancer #1, Balancer #2, Balancer #3 — hosts cuyos outbounds serán insertados en la plantilla.
Lista de hosts

Paso 2. Ocultar los hosts a inyectar

Abra la tarjeta de cada host balanceador (Balancer #1, #2, #3), vaya a la sección Avanzado y habilite el interruptor Ocultar host.

Los hosts ocultos no aparecen en la suscripción normal — solo son accesibles a través del mecanismo de inyección.

Ocultando hosts balanceadores

Paso 3. Crear la plantilla de suscripción

Cree una plantilla de suscripción de tipo XRAY_JSON. Describa en ella la configuración completa: dns, routing, inbounds, outbounds, burstObservatory y otras secciones necesarias.

Coloque en el array outbounds solo los outbounds estáticos (direct, block) — los outbounds de los hosts inyectados se agregarán automáticamente.

En el nivel raíz del JSON agregue el objeto remnawave con el selector de hosts ocultos.

Ejemplo de plantilla

{
"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"
}
]
}

Observe:

  • "subjectSelector": ["proxy"] — el observatory monitoreará todos los outbounds cuyo tag comience con proxy (es decir, proxy, proxy-2, proxy-3).
  • "selector": ["proxy"] — el balanceador de carga Super_Balancer distribuirá el tráfico entre los mismos outbounds.
  • En el outbounds de la plantilla solo se indican direct y block — los outbounds de los hosts se agregarán automáticamente antes de ellos.

Paso 4. Asignar la plantilla al host virtual

Abra la tarjeta del host virtual (Virtual Host), vaya a la sección Avanzado y en el campo Plantilla Xray JSON seleccione la plantilla creada.

Asegúrese de que el interruptor Ocultar host para el host virtual esté deshabilitado — debe ser visible en la suscripción.

Asignando plantilla al host virtual

Paso 5. Resultado

Al solicitar la suscripción, el panel automáticamente:

  1. Toma la plantilla asignada al host virtual.
  2. Elimina el objeto remnawave de ella.
  3. Para cada grupo en injectHosts selecciona los hosts ocultos por selector y recopila sus outbounds.
  4. Inserta los outbounds al inicio del array outbounds.
  5. Establece remarks desde la observación del host virtual.

Configuración final que recibirá el cliente

[
{
"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"
}
]

Lo que sucedió:

  • El objeto remnawave fue eliminado de la configuración final.
  • Tres outbounds (proxy, proxy-2, proxy-3) fueron insertados al inicio del array outbounds, antes de direct y block.
  • "selector": ["proxy"] en el balanceador de carga capturó automáticamente los tres outbounds, ya que sus tags comienzan con proxy (coincidencia por prefijo).
  • "subjectSelector": ["proxy"] en el observatory capturó igualmente los tres outbounds para su monitoreo.
  • "remarks": "Virtual Host" — tomado de la observación del host virtual.
nota

Dirección del host virtual e inbound real

El host virtual en este escenario sirve como «envoltorio» para la plantilla y los metadatos (observación, descripción del servidor), no como un punto de conexión real. En su configuración se puede indicar cualquier dirección (por ejemplo, balancer.host.com) — no participa en la conexión real del usuario. El punto de entrada real es el inbound específico de los hosts inyectados. Es importante que el usuario que solicita la suscripción tenga acceso a ese inbound a través de los squads, de lo contrario el host virtual no aparecerá en su suscripción. Los parámetros de conexión reales (direcciones, puertos, claves, etc.) se toman de los hosts inyectados, cuyas configuraciones de outbound se insertan en la configuración final del lado del cliente.

Notas importantes

  • El host virtual debe estar habilitado y no oculto. Es él quien determina qué plantilla se utilizará, y de él se toman remarks y description.
  • Los hosts a inyectar deben estar habilitados. Por defecto solo se seleccionan los hosts ocultos (selectFrom: "HIDDEN"). Este comportamiento se puede cambiar a "NOT_HIDDEN" o "ALL". Si un host está deshabilitado o no se encuentra por el selector — será omitido.
  • Todos los hosts participantes deben ser accesibles para el usuario final — el inbound al que están vinculados debe estar incluido en el squad del usuario.
  • El objeto remnawave es eliminado de la configuración final — el cliente no lo verá.
  • Los outbounds se agregan al inicio del array outbounds. Si addVirtualHostAsOutbound está habilitado, el outbound del host virtual con el tag proxy va primero, luego los inyectados, luego los outbounds estáticos de la plantilla (direct, block).
  • El orden de los hosts determina el orden de los outbounds y los tags asignados. Para el selector uuids — el orden de los UUID en el array values. En lugar de tagPrefix se puede usar useHostRemarkAsTag o useHostTagAsTag para que los tags se formen a partir de las propiedades de los hosts.
  • La selección de plantilla y el ocultamiento del host se encuentran en la sección Avanzado en la tarjeta del host.