Xray JSON – Advanced
Visão geral
Para templates de assinatura do tipo XRAY_JSON no Remnawave, existem as diretivas Remnawave — instruções especiais que você adiciona ao template JSON. O painel as processa ao gerar a assinatura e as remove da configuração final — o cliente nunca as verá.
No momento está disponível a diretiva injectHosts, que permite inserir dinamicamente configurações de outbound de hosts no template. Isso é útil quando você precisa montar uma configuração Xray complexa com balanceadores, roteamento personalizado ou vários outbounds, enquanto os dados de conexão (endereço, porta, chaves) são inseridos automaticamente pelo painel.
As configurações apresentadas abaixo são exemplos para demonstrar o mecanismo de injeção. Adapte-as às suas necessidades.
Requer Remnawave versão 2.6.3 ou mais recente.
Condições de funcionamento
- O Host Virtual (o host ao qual o template com injeção é atribuído) deve estar ativado e não ocultado.
- Os Hosts injetados (selecionados via
selector) devem estar ativados. Por padrão, apenas hosts ocultos são selecionados (o comportamento pode ser alterado viaselectFrom). - Todos os hosts — tanto o virtual quanto os injetados — devem ser acessíveis ao usuário final: o inbound ao qual estão vinculados deve estar ativado no squad do usuário.
- Do host virtual para a configuração final são transferidos o remark (nota) e a descrição do servidor (Server Description, se definida).
Estrutura do remnawave
O objeto remnawave é adicionado ao nível raiz do template JSON. Ele suporta os seguintes campos:
| Campo | Descrição |
|---|---|
injectHosts | Array de grupos de injeção. Cada grupo contém um seletor para escolher os hosts e parâmetros de formação de tags. |
addVirtualHostAsOutbound | Se true — o host virtual será adicionado como outbound com a tag proxy no início do array outbounds. Padrão: false. Ver addVirtualHostAsOutbound. |
O campo injectHosts é um array de grupos de injeção. Cada grupo contém um seletor para escolher os hosts e seu próprio tagPrefix:
"remnawave": {
"injectHosts": [
{
"selector": { "type": "uuids", "values": ["uuid-хоста-1", "uuid-хоста-2"] },
"tagPrefix": "proxy"
},
{
"selector": { "type": "remarkRegex", "pattern": "^RU-" },
"tagPrefix": "backup"
}
]
},
Cada elemento do array injectHosts:
| Campo | Descrição |
|---|---|
selector | Objeto que define quais hosts serão selecionados. Campo obrigatório. |
selectFrom | De qual pool selecionar hosts: "HIDDEN" (padrão), "NOT_HIDDEN" ou "ALL". |
tagPrefix | Prefixo de tag para os outbounds criados. Ver regras de formação de tags. |
useHostRemarkAsTag | Se true — a tag do outbound será o remark do host. |
useHostTagAsTag | Se true — a tag do outbound será a tag do host (se a tag não estiver definida, o remark será usado). |
É necessário especificar exatamente um dos três campos: tagPrefix, useHostRemarkAsTag ou useHostTagAsTag.
Pode haver quantos grupos quiser — cada um forma seu próprio conjunto independente de outbounds com seu próprio prefixo. Isso permite, por exemplo, configurar um balanceador separado para cada grupo de servidores.
Tipos de seletores
uuids
Seleciona hosts por lista de UUID. A ordem dos UUIDs determina a ordem dos outbounds.
"selector": {
"type": "uuids",
"values": [
"8478b271-95d3-4312-85ae-ecf63fb53d1d",
"d31d6161-1315-4c1e-9a4b-141ab1c022f6"
]
}
remarkRegex
Seleciona hosts cujo remark corresponde à expressão regular. A sintaxe é JavaScript RegExp.
"selector": {
"type": "remarkRegex",
"pattern": "^Балансер"
}
O exemplo acima seleciona todos os hosts ocultos cujo remark começa com "Балансер" (por exemplo, "Балансер #1", "Балансер RU").
tagRegex
Seleciona hosts cuja tag de host (campo tag nas configurações do host) corresponde à expressão regular.
"selector": {
"type": "tagRegex",
"pattern": "^balancer-"
}
O exemplo acima seleciona todos os hosts ocultos com tag começando com balancer-.
sameTagAsRecipient
Seleciona todos os hosts ocultos cuja tag de host corresponde à tag do host virtual. Não requer parâmetros adicionais.
"selector": {
"type": "sameTagAsRecipient"
}
Conveniente quando você quer agrupar hosts automaticamente: basta atribuir a mesma tag ao host virtual e aos hosts injetados.
Por padrão, todos os seletores trabalham apenas com hosts ocultos. Para alterar esse comportamento, use o campo selectFrom: o valor "NOT_HIDDEN" selecionará apenas hosts visíveis (ativados, mas não ocultos), e "ALL" — todos os hosts (ativados, ocultos).
Regras de formação de tags
A tag do outbound é determinada por qual dos três campos está especificado no grupo de injeção:
tagPrefix — o primeiro host recebe uma tag igual ao tagPrefix. Cada um dos seguintes recebe {tagPrefix}-{N}, começando em 2.
Exemplo para três hosts com tagPrefix: "proxy":
| Ordem | Tag do outbound |
|---|---|
| 1º | proxy |
| 2º | proxy-2 |
| 3º | proxy-3 |
useHostRemarkAsTag — cada outbound recebe uma tag igual ao remark do host.
{
"selector": { "type": "tagRegex", "pattern": "^ru-" },
"useHostRemarkAsTag": true
}
Se os hosts têm remarks "Moscou", "Petersburgo", "Kazan" — os outbounds receberão as tags Moscou, Petersburgo, Kazan.
useHostTagAsTag — cada outbound recebe uma tag igual à tag do host. Se a tag do host não estiver definida, seu remark é usado.
{
"selector": { "type": "tagRegex", "pattern": "^ru-" },
"useHostTagAsTag": true
}
Correspondência de prefixo no Xray
Os campos selector (em routing.balancers) e subjectSelector (em burstObservatory) no Xray funcionam como matchers de prefixo — eles correspondem ao início da tag do outbound, não ao seu valor exato.
Por exemplo, se a configuração tem outbounds com tags proxy, proxy-2, proxy-3, direct:
| Valor de selector / subjectSelector | Quais outbounds serão selecionados |
|---|---|
["proxy"] | proxy, proxy-2, proxy-3 |
["proxy-"] | proxy-2, proxy-3 |
"selector": ["proxy"]— capturará todos os outbounds injetados, incluindo o primeiro."selector": ["proxy-"]— capturará todos exceto o primeiro (apenasproxy-2,proxy-3, ...).
O primeiro host selecionado sempre recebe a tag sem o sufixo -{N} (simplesmente proxy). Isso permite usá-lo como fallbackTag no balanceador: se todos os outbounds do selector ficarem indisponíveis, o tráfego irá para o primeiro host. Para isso, defina "selector": ["proxy-"] (apenas proxy-2, proxy-3, ...) e "fallbackTag": "proxy".
addVirtualHostAsOutbound
Por padrão, ao usar a diretiva remnawave, na configuração final aparecem apenas os hosts injetados. O próprio host virtual (recipient) é usado apenas como fonte de remarks e serverDescription.
Se você precisar que o host virtual também se torne um outbound com a tag proxy, adicione o campo addVirtualHostAsOutbound: true no nível do objeto remnawave:
"remnawave": {
"addVirtualHostAsOutbound": true,
"injectHosts": [
{
"selector": { "type": "uuids", "values": ["uuid-хоста-1", "uuid-хоста-2"] },
"tagPrefix": "proxy"
},
{
"selector": { "type": "remarkRegex", "pattern": "^RU-" },
"tagPrefix": "backup"
}
]
}
Neste caso, o array final outbounds ficará assim:
- Outbound do host virtual com a tag
proxy. - Outbounds injetados (de
injectHosts). - Outbounds estáticos do template (
direct,block, etc.).
Isso é útil quando as regras de roteamento usam "outboundTag": "proxy" para direcionar o tráfego pelo host principal, e os hosts injetados atendem grupos de tráfego separados (por exemplo, por meio de balanceadores).
addVirtualHostAsOutbound pode ser usado com ou sem injectHosts. Se injectHosts não for especificado ou estiver vazio, apenas o outbound do host virtual será adicionado à configuração.
Exemplo passo a passo: balanceador com três hosts
Neste exemplo, criaremos uma configuração na qual três outbounds são combinados em um balanceador com a estratégia leastLoad e monitorados por um Observatory.
Passo 1. Crie os hosts
Crie no painel os hosts que participarão da injeção. No nosso exemplo:
- Virtual Host — o host virtual ao qual o template com injeção será atribuído. Não está oculto e é por ele que o usuário final receberá a configuração.
- Balancer #1, Balancer #2, Balancer #3 — hosts cujos outbounds serão inseridos no template.
Passo 2. Oculte os hosts injetados
Abra o cartão de cada host balanceador (Balancer #1, #2, #3), vá para a seção Advanced e ative o toggle Hide Host.
Hosts ocultos não aparecem na assinatura comum — eles são acessíveis apenas pelo mecanismo de injeção.
Passo 3. Crie o template de assinatura
Crie um template de assinatura do tipo XRAY_JSON. Nele, descreva a configuração completa: dns, routing, inbounds, outbounds, burstObservatory e outras seções necessárias.
No array outbounds, coloque apenas os outbounds estáticos (direct, block) — os outbounds dos hosts injetados serão adicionados automaticamente.
No nível raiz do JSON, adicione o objeto remnawave com o seletor de hosts ocultos.
Exemplo de template
{
"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 que:
"subjectSelector": ["proxy"]— o Observatory monitorará todos os outbounds cujas tags comecem comproxy(ou seja,proxy,proxy-2,proxy-3)."selector": ["proxy"]— o balanceadorSuper_Balancerdistribuirá o tráfego entre os mesmos outbounds.- Em
outboundsdo template, apenasdirecteblocksão especificados — os outbounds dos hosts serão adicionados automaticamente antes deles.
Passo 4. Atribua o template ao host virtual
Abra o cartão do host virtual (Virtual Host), vá para a seção Advanced e no campo Xray JSON Template selecione o template criado.
Certifique-se de que o toggle Hide Host para o host virtual está desativado — ele deve ser visível na assinatura.
Passo 5. Resultado
Ao solicitar a assinatura, o painel automaticamente:
- Pega o template atribuído ao host virtual.
- Remove o objeto
remnawavedele. - Para cada grupo em
injectHosts, seleciona os hosts ocultos peloselectore monta seus outbounds. - Insere os outbounds no início do array
outbounds. - Define
remarksa partir do remark do host virtual.
Configuração final que o cliente recebe
[
{
"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"
}
]
O que aconteceu:
- O objeto
remnawavefoi removido da configuração final. - Três outbounds (
proxy,proxy-2,proxy-3) foram inseridos no início do arrayoutbounds, antes dedirecteblock. "selector": ["proxy"]no balanceador capturou automaticamente todos os três outbounds, pois suas tags começam comproxy(correspondência de prefixo)."subjectSelector": ["proxy"]no Observatory capturou igualmente todos os três outbounds para monitoramento."remarks": "Virtual Host"— retirado do remark do host virtual.
Endereço do host virtual e inbound real
O host virtual neste cenário serve como um "wrapper" para o template e metadados (remark, descrição do servidor), e não como um ponto de conexão real.
Nas suas configurações você pode especificar qualquer endereço (por exemplo, balancer.host.com) — ele não participa da conexão real do usuário.
O ponto de entrada real é o inbound específico dos hosts injetados. É importante que o usuário que solicita a assinatura tenha acesso a esse inbound por meio dos squads, caso contrário o host virtual simplesmente não aparecerá na assinatura dele.
Os parâmetros reais de conexão (endereços, portas, chaves, etc.) são tirados dos hosts injetados, cujas configurações de outbound são inseridas na configuração final no lado do cliente.
Observações importantes
- O host virtual deve estar ativado e não oculto. É ele que determina qual template será usado, e dele são tirados
remarksedescription. - Os hosts injetados devem estar ativados. Por padrão, apenas hosts ocultos são selecionados (
selectFrom: "HIDDEN"). Esse comportamento pode ser alterado para"NOT_HIDDEN"ou"ALL". Se um host estiver desativado ou não for encontrado pelo seletor — será ignorado. - Todos os hosts participantes devem ser acessíveis ao usuário final — o inbound ao qual estão vinculados deve estar ativado no squad do usuário.
- O objeto
remnawaveé removido da configuração final — o cliente não o verá. - Os Outbounds são adicionados no início do array
outbounds. SeaddVirtualHostAsOutboundestiver ativado, o outbound do host virtual com a tagproxyvem primeiro, depois os injetados, depois os outbounds estáticos do template (direct,block). - A ordem dos hosts determina a ordem dos outbounds e as tags atribuídas a eles. Para o seletor
uuids— a ordem dos UUIDs no arrayvalues. Em vez detagPrefix, você pode usaruseHostRemarkAsTagouuseHostTagAsTagpara que as tags sejam formadas a partir das propriedades dos hosts. - A seleção de template e ocultação de host estão na seção Advanced no cartão do host.