Обратный прокси

Обратный прокси может перенаправлять трафик с сервера на клиент, то есть выполнять обратную переадресацию трафика.

В основе его лежит протокол Mux.cool, который, будучи протоколом мультиплексирования, также обладает свойствами, подобными QUIC. Клиент и сервер равноправны, и обе стороны могут создавать новые подсоединения. Обычно только клиент открывает подсоединения, но здесь открытие подсоединения сервером используется для отправки запросов обратного прокси.

Принцип работы обратного прокси примерно следующий:

  • Предположим, на хосте A находится веб-сервер, у которого нет публичного IP-адреса и к которому нельзя получить прямой доступ из Интернета. Есть другой хост B с публичным IP-адресом. Нам нужно использовать B в качестве точки входа, перенаправляя трафик с B на A.

    • На хосте B настраивается Xray для приема внешних запросов, поэтому он называется portal (портал).
    • На хосте A настраивается Xray, который отвечает за соединение переадресации от B с веб-сервером. Он называется bridge (мост).
  • bridge

    • bridge активно устанавливает соединение с portal для регистрации обратного канала. Целевой адрес (домен) этого соединения можно задать самостоятельно.
    • После получения трафика из Интернета, перенаправленного portal, bridge пересылает его без изменений на веб-сервер на хосте A. Конечно, для этого требуется настройка модуля маршрутизации.
    • После получения ответа bridge также возвращает его без изменений portal.
  • portal

    • Если portal получает запрос, и домен совпадает, это означает, что данные ответа пришли от bridge. Это соединение будет использовано для установления обратного канала.
    • Если portal получает запрос, и домен не совпадает, это означает, что соединение установлено пользователем из Интернета. Данные этого соединения будут перенаправлены на bridge.
  • bridge выполняет динамическую балансировку нагрузки в зависимости от объема трафика.

Подсказка

Как указано выше, обратный прокси по умолчанию использует Mux. Пожалуйста, не включайте Mux повторно на используемых исходящих соединениях.

Внимание

Функция обратного прокси все еще находится в стадии тестирования и может иметь некоторые проблемы.

ReverseObject

ReverseObject соответствует параметру reverse в файле конфигурации.

{
  "reverse": {
    "bridges": [
      {
        "tag": "bridge",
        "domain": "reverse-proxy.xray.internal"
      }
    ],
    "portals": [
      {
        "tag": "portal",
        "domain": "reverse-proxy.xray.internal"
      }
    ]
  }
}

bridges: [BridgeObject]

Массив, каждый элемент которого представляет собой bridge. Конфигурация каждого bridge является BridgeObject.

portals: [PortalObject]

Массив, каждый элемент которого представляет собой portal. Конфигурация каждого portal является PortalObject.

BridgeObject

{
  "tag": "bridge",
  "domain": "reverse-proxy.xray.internal"
}

tag: string

Все соединения, исходящие от bridge, будут иметь эту метку. Ее можно использовать для идентификации в конфигурации маршрутизации с помощью inboundTag.

domain: string

Указывает домен, который bridge будет использовать для установления соединения с portal. Этот домен используется только для связи между bridge и portal и не обязательно должен существовать.

PortalObject

{
  "tag": "portal",
  "domain": "reverse-proxy.xray.internal"
}

tag: string

Метка portal. Используется в конфигурации маршрутизации с outboundTag для перенаправления трафика на этот portal.

domain: string

Домен. Когда portal получает трафик, если целевой домен трафика совпадает с этим доменом, portal считает, что текущее соединение является соединением связи, установленным bridge. Другой трафик будет рассматриваться как трафик, требующий пересылки. portal занимается идентификацией этих двух типов соединений и выполняет соответствующую пересылку.

Подсказка

Один Xray может быть bridge, portal или одновременно и тем, и другим, чтобы соответствовать требованиям различных сценариев.

Полный пример конфигурации

Подсказка

Во время работы рекомендуется сначала запустить bridge, а затем portal.

Конфигурация bridge

bridge обычно требует двух исходящих соединений (outbound): одно для подключения к portal, другое для отправки фактического трафика. Другими словами, вам нужно использовать маршрутизацию для различения двух типов трафика.

Конфигурация обратного прокси:

"reverse": {
  "bridges": [
    {
      "tag": "bridge",
      "domain": "reverse-proxy.xray.internal"
    }
  ]
}

outbound:

{
  // Переадресация на веб-сервер
  "tag": "out",
  "protocol": "freedom",
  "settings": {
    "redirect": "127.0.0.1:80"
  }
}
{
  // Подключение к portal
  "protocol": "vmess",
  "settings": {
    "vnext": [
      {
        "address": "IP-адрес portal",
        "port": 1024,
        "users": [
          {
            "id": "5783a3e7-e373-51cd-8642-c83782b807c5"
          }
        ]
      }
    ]
  },
  "tag": "interconn"
}

Конфигурация маршрутизации:

{
  "rules": [
    {
      // Запрос от bridge, и домен соответствует настроенному домену,
      // это означает, что это попытка установить обратный туннель к portal,
      // маршрутизируем на interconn, то есть подключаемся к portal
      "type": "field",
      "inboundTag": ["bridge"],
      "domain": ["full:reverse-proxy.xray.internal"],
      "outboundTag": "interconn"
    },
    {
      // Трафик от portal также будет выходить из bridge, но без указанного выше домена
      // маршрутизируем на out, то есть перенаправляем на веб-сервер
      "type": "field",
      "inboundTag": ["bridge"],
      "outboundTag": "out"
    }
  ]
}

Конфигурация portal

portal обычно требует двух входящих соединений (inbound): одно для приема соединений от bridge, другое для приема фактического трафика. Вам также нужно использовать маршрутизацию для различения двух типов трафика.

Конфигурация обратного прокси:

"reverse": {
  "portals": [
    {
      "tag": "portal",
      "domain": "reverse-proxy.xray.internal" // Должно совпадать с конфигурацией bridge
    }
  ]
}

inbound:

{
  //  Прямой прием запросов из Интернета
  "tag": "external",
  "port": 80,
  "protocol": "dokodemo-door",
  "settings": {
    "address": "127.0.0.1",
    "port": 80,
    "network": "tcp"
  }
}
{
  // Прием запросов от bridge для установления обратного туннеля
  "tag": "interconn",
  "port": 1024,
  "protocol": "vmess",
  "settings": {
    "clients": [
      {
        "id": "5783a3e7-e373-51cd-8642-c83782b807c5"
      }
    ]
  }
}

Конфигурация маршрутизации:

{
  "rules": [
    {
      // Если входящее соединение помечено external, значит, это запрос из Интернета,
      // маршрутизируем на portal, который в конечном итоге перенаправит его на bridge
      "type": "field",
      "inboundTag": ["external"],
      "outboundTag": "portal"
    },
    {
      // Если входящее соединение от interconn, значит, это запрос от bridge для установления обратного туннеля,
      // маршрутизируем на portal, который в конечном итоге перенаправит его соответствующему клиенту в Интернете.
      // Обратите внимание: этот запрос будет содержать домен, настроенный ранее, поэтому portal сможет различать два типа запросов,
      // маршрутизируемых на portal.
      "type": "field",
      "inboundTag": ["interconn"],
      "outboundTag": "portal"
    }
  ]
}