Перейти к содержанию

Настройка прокси сервера Xray на 443 порту с Nginx

Статья устарела и обновляться не будет

Статья давно устарела и в этом блоге уже обновляться не будет. Тут рассказывается про версию XRay 1.6.0, которую уже вроде как научились детектить в Китае, либо многая конфигурация уже отмечена как устаревшая уже самими разработчиками XRay-core.
Пост оставлен "как есть", чисто для истории и не проходил переформатирование.

Дисклеймер

Статья написана НЕ экспертом в области информационных технологий и возможно тут используется неправильная терминология во многих местах. Вся информация несёт чисто информативный характер. Никакой гайд в интернете не заменит вам консультацию со специалистом, особенно если от этого зависит ваша жизнь.

Введение

Статья посвящена созданию и настройке прокси сервера Xray.

Рассматриваются два входящих протокола: 1. Xray XTLS (Рекомендуется): На 443 порту будет работать Xray сервер, а все не-Xray клиенты будут перенаправлены на Nginx с SSL сертификатом.
2. Xray Websocket: На 443 порту будет развёрнут веб сервер Nginx, а подключение к самому прокси серверу будет происходить через Websocket.

Что такое Xray, VLESS и XTLS

Xray - это платформа для создания прокси серверов (или цепочек прокси) с поддержкой множества протоколов, и является продолжением проекта v2ray. Написана на Golang, проект под лицензией MPL-2.0.

В v2ray использовался протокол туннелирования Vmess, с собственным шифрованием, "встроенным" в протокол. У этого протокола есть два недостатка: шифрование протокола привязано ко времени - на сервере и клиенте должно быть синхронизированное время, и Vmess не использует TLS и не выглядит как TLS-трафик.

На смену протоколу Vmess был разработан VLESS, в котором убран слой шифрования протокола, что позволило избавиться от привязки ко времени. VLESS создавался для использования его с TLS-инкапсуляцией, для того, чтобы можно было определить тип TLS-запроса и разделить обычный трафик (напр. из браузера) и клиента прокси сервера.

Что такое вообще XTLS... сказать сложно, так как в официальной документации про сам XTLS ничего нет ещё, даже на китайском, но этот протокол является главной фишкой, то чего не было в v2ray и, вроде бы, то ради чего создавался вообще Xray.

Суть Xray XTLS сервера в том, что он работает на 443 порту заместо веб сервера, а не-Xray клиентов он перенаправляет на наш настоящий веб сервер, причём соединение до сайта будет по HTTPS (!), с сертификатом который мы укажем в конфигурации Xray. Это позволяет замаскировать прокси сервер Xray под веб сервер и зашифровать само прокси соединение, чтобы со стороны наш трафик выглядел что мы обращаемся к нашему сайту по HTTPS.

А с Websocket, думаю, понятно. В конфиге Nginx создается Websocket, а Xray его слушает. В этом случае Nginx работает как положено на 80 и 443 портах, Xray серверу никакой порт не нужен.

Достоинства Xray

Вот основные достоинства этого прокси сервера: * В отличие от VPN протоколов таких как OpenVPN и Wireguard (которые легко определяются Wireshark'ом), Xray устойчив к DPI и со стороны выглядит как будто мы обращаемся к нашему сайту по HTTPS. Да, существуют такие обфускаторы как Cloak, которые легко настраиваются на Linux клиентах, но для на Android устройствах настроить Cloak на что-то кроме Shadowsocks практически невозможно. * В отличии от Shadowsocks, Xray работает как с TCP, так и с UDP пакетами. * Прокси сервер принимает входящие пакеты по 443 порту, что является стандартным портом для HTTPS соединений, который в здравом уме никто блокировать не будет. Это полезно в том случае, если провайдер заблокировал все порты кроме 53 (DNS), 80 и 433, и в таком случае у вас будет возможность воспользоваться, например, Torrent'ом или XMPP. * Поскольку Xray это не VPN а SOCKS5 совместимый прокси, то на клиенте будет легче настроить какие приложения должны идти через туннель, а какие в обход него. * Xray всё ещё может работать в режиме VPN через Tun2Socks, если нужно. * В конфиг Xray можно делать свои DNS записи и фильтровать запросы - по каким доменам пускать через туннель, какие в обход, а какие вообще заблокировать. Более того, есть даже готовые списки GeoIP. * Исходящие пакеты (outbound) можно направить куда угодно на другой прокси сервер - создать цепочку прокси серверов. * Для клиента и сервера используется один бинарник и один конфиг файл. * В Android клиенте v2rayNG (совместим с Xray) конфиг клиента генерируется автоматически, либо конфиг можно импортировать вручную.

Недостатки Xray

  • Конфигурация довольно сложная и в ней легко запутаться, приходится постоянно иметь пример под рукой и не запутаться в настройках для сервера и клиента.
  • Xray (как и v2ray, и похожие проекты, например Shadowsocks) не проходили официального аудита на безопасность.
  • Вся документация на китайском языке, даже английского нет. Приходится пользоваться переводчиком сайтов на английский язык. Да, если вы хоть немного умеете в термины на английском, то лучше читать на английском, а не на русском.
  • Придётся потратиться не только на VPS, но и на доменное имя.
  • Для Linux клиента нет красивого GUI, хотя нам не привыкать, но можно создать на клиенте SystemD unit который будет запускать Xray клиент во время запуска системы и забыть о нём.
  • Xray не поможет вам, на случай если введут "белые списки" или ваш сервер заблокирует провайдер.

XTLS или Websocket?

Если кратко: Если вы создаёте Xray сервер на чистой VPS'ке - рекомендую XTLS.

Если у вас уже настроен веб сервер и вы не хотите переписывать Nginx конфиги, то проще настроить Websocket.

Плюсы XTLS: - Очень быстрый! Скорость практически не режется. - Со стороны ваше соединение будет выглядеть, как будто вы заходите на наш сайт по HTTPS.

Минусы XTLS: - XTLS должен работать на 443 порту. Держать на одном порту и Xray, и Nginx - не получится. - Информация об SSL сертификатах прописывается в сам Xray конфиг, а не в Nginx, что может сбить с толку.

Плюсы Websocket: - Легче настроить на уже работающем Nginx веб сервере. - Xray не занимает порт вообще - он слушает Websocket.

Минусы Websocket: - Высокие задержки. Может пройти секунд 5 перед тем как начнёт загружаться сайт, во всяком случае я столкнулся с такой проблемой. - Websocket соединение может определяться анализаторами пакетов, например Wireshark, но всё равно выглядит не так подозрительно как Wireguard или OpenVPN.

Если вы используете uBlock Origin

Внимание! Не советую использовать Xray через FoxyProxy или Прокси в контейнерах Firefox совместно с uBlock Origin, иначе будет утечка DNS при раскрытии CNAME записей! Есть два варианта решения проблемы: 1. Отключить раскрытие CNAME записей в настройках uBlock Origin 2. Использовать настройки прокси SOCKS5 на уровне настроек браузера

Если вы используете Firefox и нужно какие-то сайты открывать в обход прокси, то для этого лучше создать отдельный Firefox профиль. Менеджер профилей открывается этой командой: firefox -p

Начнём настройку


Настройка сервера

Будем работать с сервером на операционной системе Debian 11.

Надеюсь вы уже купили KVM/QEMU VPS, IP вашего сервера находится не за NAT'ом, купили доменное имя, указали DNS A запись на ваш сервер, и настроили SSH. Время на это тратить не будем, а приступаем сразу к делу.

В статье рассматривается настройка и XTLS, и Websocket прокси серверов!

Не запутайтесь! Конфиги для Nginx и Xray используются разные!

Включаем BBR

Bottleneck Bandwidth and Round-trip propagation time (BBR) - это алгоритм управления перегрузками TCP, разработанный Google. При определенных типах перегрузки сети он улучшает задержку.

Вводим следующие команды по очереди:

cat >> /etc/sysctl.d/50-bbr.conf <<EOF
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF
Включаем:
sysctl -p /etc/sysctl.d/50-bbr.conf

Установка Nginx

Обновляем систему и устанавливаем Nginx:

apt update && apt upgrade -y
apt install nginx -y

Редактируем /etc/nginx/sites-available/default:

Ищем строку server_name и добавляем туда наше доменное имя: server_name example.com;

Перезапускаем nginx:

nginx -t
systemctl restart nginx && systemctl status nginx

Добавляем сайт-камуфляж

Это всего лишь пример. Вы можете добавить что-то своё.

В данном случае мы устанавливаем какой-то бложик с GitHub:

apt install wget zip unzip -y
wget https://github.com/arcdetri/sample-blog/archive/master.zip
unzip master.zip
cp -rf sample-blog-master/html/* /var/www/html/

После этого можно попробовать зайти на наш сайт по домену, но учтите что у нас ещё нет SSL сертификата и сайт доступен только по http:// Сейчас мы это исправим.

Добавляем SSL сертификат Let's Encrypt

Сделаем это при помощи Certbot'а:

apt install certbot python3-certbot-nginx -y

certbot certonly \
--manual \
--preferred-challenges=dns \
--server https://acme-v02.api.letsencrypt.org/directory \
--agree-tos \
-d *.example.com \
-d example.com

Обратите внимание на параметр certonly! Нам нужен только сертификат! Мы получаем SSL сертификат и для корневого домена, и для поддоменов DNS методом.

Когда скрипт попросит, нужно добавить TXT запись с Host: _acme-challenge и значением, который нам укажет скрипт.

После создания записи ещё НЕ нажимаем Enter, а проверяем что запись создалась:

nslookup -type=TXT _acme-challenge.example.com

Когда он вернёт нужное значение, то можно продолжить работу скрипта и у нас появится сертификат Let's Encrypt, которым мы будем шифровать наше прокси соединение и посещать сайт по HTTPS.

Сертификаты Let's Encrypt находятся по следующему пути:

/etc/letsencrypt/live/example.com/fullchain.pem;
/etc/letsencrypt/live/example.com/privkey.pem;

Настройка Nginx

Рассмотрим варианты для XTLS и Websocket.

Для XTLS:

Редактируем /etc/nginx/sites-available/default:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    server_name example.com;
    root /var/www/example.com;
}

В данном примере нужно просто заменить example.com на домен который вы используете.

Да, это всё что нужно для работы сайта по HTTPS. Сертификат будет выдавать сам Xray, когда будет перенаправлять не-Xray клиентов на Nginx.

Для Websocket:

Нам нужно добавить SSL сертификат и открыть Websocket соединение.

Редактируем /etc/nginx/sites-available/default, воспользуемся примером конфигурации VLESS TLS Websocket из примеров Xray:

server {
    listen 443 ssl http2;
    server_name example.com;

    index index.html;
    root /var/www/example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

    location /xray {
        if ($http_upgrade != "websocket") {
            return 404;
        }

        proxy_pass http://unix:/dev/shm/Xray-VLESS-WSS-Nginx.socket;
        proxy_redirect off;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 52w;
    }
}

server {
    if ($host = example.com) {
        return 301 https://$host$request_uri;
    }

    listen 80 default_server;
    listen [::]:80 default_server;
    index index.html;
    server_name example.com;
    return 404;
}

В данном примере нужно просто заменить example.com на домен который вы используете.

Общее:

Перезапускаем nginx:

nginx -t
systemctl restart nginx && systemctl status nginx
Теперь наш сайт работает по HTTPS (кроме XTLS метода, пока что). Осталось настроить Xray.

Установка Xray сервера

Устанавливаем curl если он отсутствует:

apt install curl -y

Копируем следующую команду, которая скачает и запустит установочный скрипт Xray:

bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install -u root

Опция -u root нужна для того чтобы скрипт работал от root. Это нужно для того чтобы у Xray был доступ к SSL сертификатам.

В итоге должно появится похожее сообщение:

info: Xray v1.2.4 is installed.
You may need to execute a command to remove dependent software: apt purge curl unzip
Created symlink /etc/systemd/system/multi-user.target.wants/xray.service  /etc/systemd/system/xray.service.
info: Enable and start the Xray service

Проверяем работу Xray следующей командой:

systemctl status xray
Если статус Active: active (running), то идём дальше.

Генерируем UUID для Xray

Нам нужно сгенерировать UUID, который будет выступать в качестве пароля для нашего Xray сервера.

Устанавливаем пакет UUID:

apt install uuid -y

После этого генерируем UUID:

uuid -v 4

Параметр -v 4 означает что мы создадим UUID версии 4, который совершенно случайный и не зависит от системного времени.

В качестве примера будет использоваться следующий UUID: ########-####-####-####-############

Настройка Xray сервера

Конфиг Xray находится по пути /usr/local/etc/xray/config.json. Открываем конфиг, который изначально выглядит так:

{}

Для XTLS:

Убираем всё и вставляем следующий шаблон:

{
    "log": {
        "loglevel": "none"
    },
    "inbounds": [
        {
            "port": 443,
            "protocol": "vless",
            "settings": {
                "clients": [
                    {
                        "id": "########-####-####-####-############",
                        "flow": "xtls-rprx-direct",
                        "level": 0,
                        "email": "love@example.com"
                    }
                ],
                "decryption": "none",
                "fallbacks": [
                    {
                        "dest": 80
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "xtls",
                "xtlsSettings": {
                    "alpn": [
                        "http/1.1"
                    ],
                    "certificates": [
                        {
                            "certificateFile": "/etc/letsencrypt/live/ВАШ_ДОМЕН/fullchain.pem",
                            "keyFile": "/etc/letsencrypt/live/ВАШ_ДОМЕН/privkey.pem"
                        }
                    ]
                }
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "freedom"
        }
    ]
}

Нам нужно изменить следующее: - Заменить UUID ########-####-####-####-############ на тот который вы сгенерировали до этого. - Опционально: Изменить почту клиента. По сути это строчная переменная, чтобы в логах можно было понять какой пользователь к каким доменам обращается. - Пропишите правильные пути к сертификатам Let's Encrypt, замените ВАШ_ДОМЕН на доменное имя, которое вы приобрели.

Для WebSocket:

Убираем всё и вставляем следующий шаблон:

{
  "log": {
    "loglevel": "none"
  },
  "inbounds": [
    {
      "listen": "/dev/shm/Xray-VLESS-WSS-Nginx.socket,0666",
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "########-####-####-####-############"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "ws",
        "wsSettings": {
          "path": "/xray"
        }
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "blocked",
      "protocol": "blackhole",
      "settings": {}
    }
  ],
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "blocked"
      }
    ]
  }
}

В данном примере нужно вставить только свой UUID.

Также обратите на "path": "/xray" в "wsSettings". Если вы изменили путь к Websocket в конфигурации Nginx, то тут его надо тоже поменять.

Общее:

Изменяем, сохраняем. Перезапускаем Xray:

systemctl restart xray && systemctl status xray
Должно быть написано active (running).

С настройкой сервера закончили!

Про логирование в Xray: В официальных примерах конфигураций Xray параметр "loglevel": устанавливают на "warning". Даже в таком режиме, Xray логирует много информации: - IP клиента, куда он обращается (домен или IP назначения) - Время обращения - То что вы указали в "email", если там что-то есть.

В этой инструкции я отключил логирование чтобы не заполнять журнал и чтобы создать настоящий прокси без логов™ как в рекламных слоганах. Однако, это может быть полезно в случае поиска неисправностей, если вдруг прокси по какой-то причине не работает.

Настройка клиента

Рассмотрим настройку Linux клиента (и создадим SystemD юнит) и Android клиента.

Linux

Скачиваем последний релиз с GitHub под нужную архитектуру. Распаковываем бинарник xray в какую-нибудь папку и удостоверьтесь что он является выполнимым. Если вам нужны GeoIP списки, то поместите их в ту же папку с бинарником.

В этот раз я не буду использовать GeoIP списки как в официальных примерах, обойдёмся бинарником.

Для XTLS:

Создаём конфиг файл config.json по следующему примеру:

{
    "log": {
        "loglevel": "none"
    },
    "inbounds": [
        {
            "port": 1080,
            "listen": "127.0.0.1",
            "protocol": "socks",
            "settings": {
                "udp": true
            }
        }
    ],
    "outbounds": [
        {
            "protocol": "vless",
            "settings": {
                "vnext": [
                    {
                        "address": "IP_ADDRESS",
                        "port": 443,
                        "users": [
                            {
                                "id": "########-####-####-####-############",
                                "flow": "xtls-rprx-direct",
                                "encryption": "none",
                                "level": 0
                            }
                        ]
                    }
                ]
            },
            "streamSettings": {
                "network": "tcp",
                "security": "xtls",
                "xtlsSettings": {
                    "serverName": "example.com"
                }
            }
        }
    ]
}
Нам нужно изменить следующее: - Заменить UUID ########-####-####-####-############ на тот который вы сгенерировали до этого. - Указываем IP адрес. - В "serverName" пишите домен на который вы получали SSL сертификат.

Для WebSocket

Создаём конфиг файл config.json по следующему примеру:

{
  "log": {},
  "inbounds": [
    {
      "port": "1080",
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    },
    {
      "port": "1081",
      "protocol": "http",
      "settings": {}
    }
  ],
  "outbounds": [
    {
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "example.com",
            "port": 443,
            "users": [
              {
                "id": "########-####-####-####-############",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "ws",
        "security": "tls",
        "wsSettings": {
          "path": "/xray?ed=2048"
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "blocked",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}
Нам нужно изменить следующее: - Заменить UUID ########-####-####-####-############ на тот который вы сгенерировали до этого. - В "address" указываем домен сервера. - В "serverName" пишите домен на который вы получали SSL сертификат.

Обратите внимание, что для Websocket в разделе "address" нужно указывать не IP адрес сервера, а именно домен!

Общее:

Сохраняем. Запускаем клиент в терминале:

./xray run -config config.json
Если видите сообщение [Warning] core: Xray #.#.# started, то клиент настроен правильно, но мы же не будем вечно держать его в терминале, правда?

В папке /usr/lib/systemd/user/ создадим новый systemd unit xray_client.service. Нужны root права!

[Unit]
Description=Xray Client Service
Documentation=https://github.com/xtls
Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/your/path/xray run -config /your/path/config.json
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=default.target

Не забудьте изменить пути в ExecStart - и путь для бинарника и полный путь для конфиг файла!

Сохраняем, запускаем:

systemctl --user enable xray_client.service
systemctl --user restart xray_client.service && systemctl --user status xray_client.service
Должен быть статус Active: active (running). Теперь Xray будет запускаться каждый раз при запуске системы.

Не забудьте настроить SOCKS5 прокси для каждого нужного вам приложения.

В Firefox это делается так: - Ищем Настройки -> Основные -> Параметры сети (в самом низу) -> Настроить - Включаем Ручную настройку прокси - В Узел SOCKS вводим 127.0.0.1 и порт 1080. Тип прокси - SOCKS5 - Убедитесь что отмечена галочка Отправлять DNS-запросы через прокси при использовании SOCKS 5, иначе получите утечку DNS.

Напоминаю что порт указываем тот что указан в config.json файле для клиента! В разных гайдах используют разные порты.

О том как настроить Xray в режиме VPN, если нужно, читайте в этой статье на Habr про Tun2Socks.

Android

Скачиваем Android клиент v2rayNG с GitHub

Добавляем вручную конфигурацию VLESS.

Для XTLS:

Заполняем поля:

# Configuration file:
 Remarks:               # Тут пишем имя любое название
 Address: 69.420.1.337  # IP адрес вашего сервера
 Port: 443              # Оставляем 443 порт, на котором работает Nginx
 ID: #####-#######-##   # Ваш UUID который вы генерировали
 Flow: xtls-rprx-direct # Выбираем xtls-rprx-direct
 Encryption: none       # Потому что у нас идёт шифрование SSL сертификатом.

# Transport:
 Network: tcp          # ставим tcp
 Head type: ---        #
 Request host:         # Оставляем пустой
 Path:                 # Оставляем пустой
 TLS: xtls             #
 SNI: example.com      # Домен вашего сервера
 allowInsecure: false  # Запрещаем незащищенные соединения
Сохраняем, приложение само сгенерирует конфигурационный файл и добавит его в список. Включаем, пингуем сервер: Success: HTTP connection took 420ms

Для Websocket:

Заполняем поля:

# Configuration file:
 Remarks:             # Тут пишем имя любое название
 Address: example.com # Домен вашего сервера (НЕ IP АДРЕС!)
 Port: 443            # Оставляем 443 порт, на котором работает Nginx
 ID: #####-#######-## # Ваш UUID который вы генерировали
 Flow:                # Оставляем пустой
 Encryption: none     # Потому что у нас идёт шифрование SSL сертификатом.

# Transport:
 Network: ws          # ws = Websocket соединение
 Head type: ---       #
 Request host:        # Оставляем пустой
 Path: /xray          # Путь к Websocket, который мы указали в Nginx и сервере Xray
 TLS: tls             #
 SNI: example.com     # Домен вашего сервера
 allowInsecure: false # Запрещаем незащищенные соединения
Сохраняем, приложение само сгенерирует конфигурационный файл и добавит его в список.

Включаем, пингуем сервер: Success: HTTP connection took 420ms

Общее:

Проверяем свой IP'шник на Whoer.net

В настройках самого приложения v2rayNG можно: - Указать свой DNS сервер (по умолчанию используется 1.1.1.1) либо переключиться на локальный (будет использоваться DNS самой VPS'ки) - Настроить исключения для приложений в режиме VPS. Ставим галочку в Bypass Mode и отмечаем приложения которые должны ходить мимо Xray сервера. - Если вы настраивали исключения с Bypass Mode и v2rayNG начал быстро разряжать устройство, то отключите Bypass Mode и отметьте только те приложения, которые будут ходить в интернет через Xray туннель. - Также можно переключиться из режима VPN в режим прокси.

Перед тем как менять конфиг файл или настройки приложения отключите текущее Xray соединение!

Учтите что приложения в Рабочим профиле Android (например, приложения которые вы поставили через Shelter) не будут использовать ваше VPN соединение из Личного профиля. Если вам нужен Xray в Рабочем профиле, установите v2rayNG в Рабочий профиль.

Источники