Cовмещаем Haproxy, Vless, WebSocket, VPN и сайт на одном порту

в 17:43, , рубрики: haproxy, vless, WebSocket, wstunnel, xui

Это моя первая статья, я буду ссылаться на других авторов и статьи для уточнения и инструкции.

Так как про VPN писать у нас запрещено, напишу про балансировку и маршрутизацию в Haproxy, про VPN дам лишь общие рекомендации для защиты удаленного доступа. Я использую VPS на территории РФ что бы не нарушать законодательство, мы ведь настраиваем средства для удаленного доступа и защиты информации, ведь так?! Приступим

1. Нам потребуется два домена (поддомена), подойдут и технические домены хостера.
2. Сам VPS (лучше 2 ядра) по результатам тестов канал в 200мбит можно утилизировать от 150 до 190мбит, но об этом позже.

Все эксперименты провожу на Ubuntu 22.04 LTS
Обновляем список пакетов и обновляем систему работаю от sudo пользователя:
sudo apt update && apt upgrade -y

Устанавливаем необходимые пакеты:
sudo apt install -y haproxy netcat-traditional htop

Фаервол настроили? Если нет настраиваем
sudo ufw allow 22/tcp разрешаем ssh (если не поменяли)
sudo ufw allow 80,443/tcp Разрешаем доступ к Web портам
Сгенерируем DH, терпеливо ждем окончания
sudo openssl dhparam -out /etc/haproxy/dh4096.pem 4096

Настроим Haproxy

Я использую acme.sh для получения сертификатов и deploy метод описанный тут.

В секцию global, пропишем современные шифры, оставим TLSv1.2 на случай блокировки TLSv1.3:

global
        log /dev/log    local0
        log /dev/log    local1 notice
        chroot /var/lib/haproxy
        stats socket /var/run/haproxy/admin.sock level admin mode 660 
        setenv ACCOUNT_THUMBPRINT '(ваш отпечаток полученный при настройке acme)'
        stats timeout 30s
        user    haproxy
        group   haproxy
        daemon
        ssl-default-bind-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:DHE-RSA-CHACHA20-POLY1305
        ssl-default-bind-options prefer-client-ciphers no-tls-tickets ssl-min-ver TLSv1.2
        ssl-default-server-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:DHE-RSA-CHACHA20-POLY1305
        ssl-default-server-options no-tls-tickets ssl-min-ver TLSv1.2
        ssl-dh-param-file /etc/haproxy/dh4096.pemй 

Пропишем секцию defaults, резолвер DNS и сервер статистики, настроим timeout, для туннелей выставим 1 час.

defaults
       log global
       mode http
       option httplog
       option dontlognull
       timeout connect 20s
       timeout client  20s
       timeout server  20s
       timeout tunnel  1h
       timeout http-request 20s
       errorfile 400 /etc/haproxy/errors/400.http
       errorfile 403 /etc/haproxy/errors/403.http
       errorfile 408 /etc/haproxy/errors/408.http
       errorfile 500 /etc/haproxy/errors/500.http
       errorfile 502 /etc/haproxy/errors/502.http
       errorfile 503 /etc/haproxy/errors/503.http
       errorfile 504 /etc/haproxy/errors/504.http
resolvers dnsserver
        nameserver ns1 127.0.0.53:53
        parse-resolv-conf
        resolve_retries       3
        timeout resolve       1s
        timeout retry         1s
        hold other           30s
        hold refused         30s
        hold nx              30s
        hold timeout         30s
        hold valid           10s
        hold obsolete        30s
frontend stats
        mode http
        bind 127.0.0.1:58080
        stats enable
        stats uri /stats
        stats realm Haproxy Statistics
        stats refresh 10s
        stats auth user:password
        stats show-legends
        stats hide-version

Теперь напишем TCP frontend, правила acl и beckend для перенаправления на http frontend и vless

frontend tcp
        bind *:80,*:443
        mode tcp
        option tcplog
        tcp-request inspect-delay 10s
        tcp-request content capture req.ssl_sni len 10
        tcp-request content accept if { req_ssl_hello_type 1 } or !{ req_ssl_hello_type 1 }
        use_backend vless if { req.ssl_sni -i api-app.$вашдомен } 
        use_backend tcp_to_http if { dst_port 80 } #redirect https
        default_backend tcp_to_https # перенаправляем все на frontend http

#        use_backend ssh if !{ req.ssl_hello_type 1 } { payload(0,7) -m bin 5353482d322e30 } or !{ req.ssl_hello_type 1 } { req.len 0 } # там мы можен перенести ssh на 443 порт

backend tcp_to_http
        mode tcp
        server http 127.0.0.1:8080 send-proxy-v2-ssl-cn
backend tcp_to_https
        mode tcp
        timeout tunnel 1h
        timeout client 50s
        timeout server 50s
        server https 127.0.0.1:8443 send-proxy-v2-ssl-cn
backend vless #x-ui
        mode tcp
        timeout tunnel 2h
        balance roundrobin
        server s1 127.0.0.1:4444 check send-proxy
#backend ssh
#        mode tcp
#        timeout tunnel 2h
#        balance roundrobin
#        server s1 127.0.0.1:22 check

Слушаем 80 и 443 порт в tcp и инспектируем SNI, по умолчанию не прошедший SNI перенаправляем на http frontend.

Все что пришло на 80 порт перенаправляем на backend tcp_to_http который нужен лишь для редиректа на https об этом в секции http frontend, используем proxy protocol v2 ssl cn для передачи информации о клиенте на frontend.

Если раскомментировать use_backend ssh и backend ssh вы получите рабочий ssh на 443 порту.

Теперь секция frontend http:

frontend https
        bind 127.0.0.1:8080 accept-proxy
        bind 127.0.0.1:8443 accept-proxy ssl crt /etc/haproxy/certs/ alpn h2,http/1.1 strict-sni
        http-request deny if { req.hdr(user-agent) -m len le 32 }
        http-request deny if { req.hdr(user-agent) -m sub evil }
        http-request deny if { path -m sub /. }
        http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;"
        redirect scheme https if !{ ssl_fc }
        http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].${ACCOUNT_THUMBPRINT}n" if { path_beg '/.well-known/acme-challenge/' } #позволим отвечать haproxy на запросы LE
        use_backend wstunnel1 if { ssl_fc_sni -i $вашдомен } { path /wss-secretpath1 } || { path_beg /wss-secretpath1/ }
        use_backend wstunnel2 if { ssl_fc_sni -i $вашдомен } { path /wss-secretpath2 } || { path_beg /wss-secretpath2/ }

        use_backend http_xui if { ssl_fc_sni -i $вашдомен } { path_beg /xui-secretpath/ } || { path_beg /xui-secretpath }

        use_backend http_stats if { ssl_fc_sni -i $вашдомен } { path_beg /stats-secretpath/ }

В данном варианте наш http фронтед слушает на портах 8080 и 8443 соответственно и принимает прокси протокол, перенаправляем http на https и устанавливаем HSTS что бы использовать только https.

Теперь разберем acl:
use_backend wstunnel и номер отвечают как за WebSocket, параметр масштабируемый, можно запустить необходимые кол-во экземпляров wstunnel.

use_backend http_xui тут просто обычно xui запускается на порту 54321 туда и перенаправим.

use_backend http_stats отвечает за сервер статистики настроенный выше в секции defaults, с логином и паролем user:password (поменяли надеюсь?)

Все правила path_beg и path замените на свои, обязательно установите в x-ui путь, для этого сделаете default_backend http_xui или откройте порт, ufw allow 54321/tcp а потом закройте как поменяете заменив allow на deny.

Секция backend http:

backend wstunnel1
        mode http
        option http-keep-alive
        timeout connect 30s
        timeout http-keep-alive 30s
        timeout client 50s
        timeout server 50s
        timeout tunnel 4h
        balance roundrobin
        server s1 127.0.0.5:54443
backend wstunnel2
        mode http
        option http-keep-alive
        timeout connect 30s
        timeout http-keep-alive 30s
        timeout client 50s
        timeout server 50s
        #option http-server-close
        timeout tunnel 4h
        balance roundrobin
        server s1 127.0.0.5:5453

backend http_xui
        mode http
        option httpchk
        option forwardfor
        http-response set-header X-Content-Type-Options nosniff
        http-response set-header X-XSS-Protection 1;mode=block
        http-response set-header X-Frame-Options SAMEORIGIN
        http-request add-header X-Real-Ip %[src]
        http-request set-header X-Forwarded-For %[src]
        http-request set-header X-Forwarded-Host %[req.hdr(host)]
        http-request set-header X-Forwarded-Proto https if { ssl_fc }
        http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
        server x-ui 127.0.0.1:54321
backend http_stats
        mode http
        http-request replace-path /stats-secretpath(/)?(.*) /2
        server stats 127.0.0.1:58080

backend wstunnel отвечают за WebSocket, в данном случае их два.

backend http_xui понятно отвечает за веб панель x-ui.

http_stats за сервер статистики.

Теперь когда конфиг haproxy готов, а сертификаты (надеюсь получены) займемся настройкой бекендов.

Я использую wstunnel от erebe, с помощью него можно туннелировать трафик через websocket, можно использовать как общий socks5 прокси, либо туннель для конкретного сервиса, дополнительно можно прочитать на странице проекта, приступим к его настройке:
Берем ссылку со страницы release на момент написания статьи последняя версия 10.1.8.

Создадим директорию в etc:
mkdir /etc/wstunnel
Перейдем в нее:
cd /etc/wstunnel
Загрузим релиз wstunnel:
wget https://github.com/erebe/wstunnel/releases/download/v10.1.8/wstunnel_10.1.8_linux_amd64.tar.gz

Создадим пользователя под которым будем запускать на wstunnel:
adduser --system wstunnel
Теперь добавим группу:
addgroup wstunnel
Теперь добавим нашего пользователя в группу:
usermod -aG wstunnel wstunnel

Распакуем tar -xvf wstunnel_10.1.8_linux_amd64.tar.gz
У нас в директории появились файл нас интересует только файл wstunnel, поменяем владельца файла на созданного пользователя
chown wstunnel:wstunnel ./wstunnel
Сделаем его исполняемым
chmod 700 ./wstunnel

Теперь создадим скрипт запуска и проверки туннеля c именем socks
nano /etc/wstunnel/socks.sh со следующим содержимым:

#!/bin/bash

# Настройки
WSTUNNEL_PATH="/etc/wstunnel/wstunnel"  # Укажите путь к wstunnel
WS_URL="ws://127.0.0.5:14443"           # URL для туннеля
RESTRICT_PATH_PREFIX="wss-secretpath1"  # Укажите путь для --restrict-http-upgrade-path-prefix
PING_TARGET="127.0.0.5"                 # Цель для пинга
CHECK_PORT=14443                        # Порт проверки
CHECK_INTERVAL=10                       # Интервал проверки в секундах

# Запуск wstunnel
start_tunnel() {
    echo "Запуск wstunnel..."
    $WSTUNNEL_PATH server $WS_URL --restrict-http-upgrade-path-prefix $RESTRICT_PATH_PREFIX &
    TUNNEL_PID=$!
}

# Проверки работоспособности туннеля
check_tunnel() {
    while true; do
        # Проверка порта с помощью netcat
        if ! nc -z $PING_TARGET $CHECK_PORT; then
            echo "Туннель не работает, перезапуск..."
            kill $TUNNEL_PID
            start_tunnel
        fi
        sleep $CHECK_INTERVAL
    done
}
# Запуск туннеля и проверки
start_tunnel
check_tunnel

Рассмотрим скрипт в секции "настройка" мы устанавливаем параметры запуска поменяйте на свои, RESTRICT_PATH_PREFIX обязательно меняем и главное что бы он совпадал с haproxy. Секция "Запуск wstunnel" запустит наш wstunnel с указанными параметрами. Секция "Проверки работоспособности туннеля" отвечает за проверку поднятого туннеля по средствам netcat, проверяем наличие открытого порта wstunnel если порт закрыт перезагрузим нам wstunnel.

Поменяем создателя:
chown wstunnel:wstunnel ./socks.sh

Сделаем скрипт исполняемым:
chmod 700 ./socks.sh

Теперь можно проверить скрипт выполнив ./socks.sh

Теперь напишем второй скрипт только для работы c системным резолвером DNS для защиты наших DNS запросов
nano /etc/wstunnel/dns.sh со следующим содержимым (вы так же можете написать и для ssh добавив еще бекенд и фронтед в haproxy с другим путем):

#!/bin/bash

# Настройки
WSTUNNEL_PATH="/etc/wstunnel/wstunnel"  # Укажите путь к wstunnel
WS_URL="ws://127.0.0.5:5453"            # URL для туннеля
RESTRICT_PATH_PREFIX="wss-secretpath2"  # Укажите путь для --restrict-http-upgrade-path-prefix
PING_TARGET="127.0.0.5"                 # Цель для пинга
CHECK_PORT=5453                         # Порт проверки
CHECK_INTERVAL=10                       # Интервал проверки в секундах
Restrict_TO="127.0.0.53:53"             # сервис для коннекта в данном случае системный DNS резолвер

# Функция для запуска wstunnel
start_tunnel() {
    echo "Запуск wstunnel..."
    $WSTUNNEL_PATH server $WS_URL --restrict-http-upgrade-path-prefix $RESTRICT_PATH_PREFIX --restrict-to $Restrict_TO &    TUNNEL_PID=$!
}

# Функция для проверки работоспособности туннеля
check_tunnel() {
    while true; do
        # Проверка порта с помощью netcat
        if ! nc -z $PING_TARGET $CHECK_PORT; then
            echo "Туннель не работает, перезапуск..."
            kill $TUNNEL_PID
            start_tunnel
        fi
        sleep $CHECK_INTERVAL
    done
}
# Запуск туннеля и проверки
start_tunnel
check_tunnel

Выполняем тоже что и со скриптом socks.sh меняем владельца и даем права на исполнение, отличие только в имени скрипта.

Теперь напишем systemd для запуска наших скриптов
Создадим файл командой
nano /etc/systemd/system/ws-socks.service
со следующим содержимым:

[Unit]
Description=Start & Check Wstunnel
After=network.target

[Service]
ExecStart=/etc/wstunnel/socks.sh
User=wstunnel
Group=wstunnel

[Install]
WantedBy=multi-user.target

И для DNS:
nano /etc/systemd/system/ws-dns.service
со следующим содержимым:

[Unit]
Description=Start & Check Wstunnel
After=network.target

[Service]
ExecStart=/etc/wstunnel/dns.sh
User=wstunnel
Group=wstunnel

[Install]
WantedBy=multi-user.target

Запускаем:
systemctl start ws-socks.service ws-dns.service
Проверяем:
systemctl status ws-socks.service

systemctl status ws-dns.service

Если в обоих случаях все ок и все процессы запущены, проверим через htop от какого пользователя запущены, ищем наши процессы, если запущены от пользователя wstunnel то все сделано правильно.

Теперь поставим их в автозагрузку systemctl enable ws-socks.service ws-dns.service

Теперь настроим клиентов, в моем случае первый клиент armdebian с systemd, второй OpenWRT с init.d, и Windows.

Выполним загрузку wstunnel и настройку аналогичную серверу, создадим директорию в etc, добавим пользователя и группу.

Для systemd, запустим на локальной машине socks5 прокси через WebSocket.
Командой создадим сервис:
nano /etc/systemd/system/ws-socks.service

[Unit]
Description=wstunnel service
After=network.target

[Service]
ExecStart=/etc/wstunnel/wstunnel client --http-upgrade-path-prefix wss-secretpath1 --local-to-remote socks5://0.0.0.0:2080 wss://$ваш.домен:443 --tls-verify-certificate --connection-min-idle 4
Restart=no
User=nobody
Group=nogroup

[Install]
WantedBy=multi-user.targets

Теперь второй сервис для запросов DNS на 5353 порту например для локального adguardhome
nano /etc/systemd/system/ws-dns.service

[Unit]
Description=wstunnel service
After=network.target

[Service]
ExecStart=/etc/wstunnel/wstunnel client --http-upgrade-path-prefix wss-secretpath2 --local-to-remote udp://5353:127.0.0.53:53 wss://$ваш.домен:443 --tls-verify-certificate --connection-min-idle 2
Restart=no
User=nobody
Group=nogroup

[Install]
WantedBy=multi-user.targets

Напишем скрипт проверки туннеля socks5 и разместим его так же в /etc/wstunnel
nano /etc/wstunnel/chk-socks.sh

#!/bin/bash
# настройки проверки
TARGET=127.0.0.1
PORT=2080
SERVICE=ws-socks.service

# Проверяем доступность порта
if nc -z $TARGET $PORT; then
    # Если соединение установлено, ничего не делаем
    echo "Порт $PORT доступен."
else
    # Если соединение не удалось, перезапускаем службу
    echo "Порт $PORT недоступен. Перезапуск службы wstunnel"
    systemctl restart $SERVICE
fi

И второй скрипт для проверки туннеля dns
nano /etc/wstunnel/chk-dns.sh

#!/bin/bash
# настройки проверки
TARGET=127.0.0.1
PORT=5353
SERVICE=ws-dns.service

# Проверяем доступность порта
if nc -z $TARGET $PORT; then
    # Если соединение установлено, ничего не делаем
    echo "Порт $PORT доступен."
else
    # Если соединение не удалось, перезапускаем службу
    echo "Порт $PORT недоступен. Перезапуск службы wstunnel"
    systemctl restart $SERVICE
fi

Теперь разместим наши скрипты в Crontab от root: выполним
sudo crontab -e
И добавим в конец:
*/5 * * * * /etc/wstunnel/chk-dns.sh
*/5 * * * * /etc/wstunnel/chk-socks.sh

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

Теперь напишем клиента для OpenWRT, для начала узнаем архитектуру нашего роутера
командой opkg print-architecture у моего роутера архитектура aarch64_cortex-a53
Теперь загрузим Wstunnel для нашей архитектуры
Перейдем в tmp:
cd /tmp
Загрузим:
wget https://github.com/erebe/wstunnel/releases/download/v10.1.8/wstunnel_10.1.8_linux_arm64.tar.gz
Распакуем:
tar -xvf wstunnel_10.1.8_linux_arm64.tar.gz
Переместим wstunnel:
mv wstunnel /usr/local/bin/wstunnel
Сделаем исполняемым:
chown +x /usr/local/bin/wstunnel

Теперь напишем сервис:

vi /etc/init.d/ws-socks

#!/bin/sh /etc/rc.common

# Определяем имя службы
START=99
STOP=10
SERVICE_NAME="wstunnel socks5"

# Определяем команды для запуска и остановки
start() {
    echo "Starting $SERVICE_NAME..."
    /usr/local/bin/wstunnel client --http-upgrade-path-prefix wss-secretpath1 --local-to-remote socks5://0.0.0.0:2080 wss://$ваш.домен:443 --tls-verify-certificate --connection-min-idle 4 &
    echo $! > /var/run/$SERVICE_NAME.pid
}

stop() {
    echo "Stopping $SERVICE_NAME..."
    if [ -f /var/run/$SERVICE_NAME.pid ]; then
        kill $(cat /var/run/$SERVICE_NAME.pid)
        rm /var/run/$SERVICE_NAME.pid
    else
        echo "$SERVICE_NAME is not running."
    fi
}

Аналогично напишем для нашего dns сервиса
vi /etc/init.d/ws-dns

#!/bin/sh /etc/rc.common

# Определяем имя службы
START=99
STOP=10
SERVICE_NAME="wstunnel dns"

# Определяем команды для запуска и остановки
start() {
    echo "Starting $SERVICE_NAME..."
    /usr/local/bin/wstunnel client --http-upgrade-path-prefix wss-secretpath2 --local-to-remote udp://5353:127.0.0.53:53 wss://$ваш.домен:443 --tls-verify-certificate --connection-min-idle 2 &
    echo $! > /var/run/$SERVICE_NAME.pid
}

stop() {
    echo "Stopping $SERVICE_NAME..."
    if [ -f /var/run/$SERVICE_NAME.pid ]; then
        kill $(cat /var/run/$SERVICE_NAME.pid)
        rm /var/run/$SERVICE_NAME.pid
    else
        echo "$SERVICE_NAME is not running."
    fi
}

Сделаем скрипты исполняемым:
chmod +x /etc/init.d/ws-dns
chmod +x /etc/init.d/ws-socks
Запустим:
/etc/init.d/ws-socks start
/etc/init.d/ws-dns start

Добавим в автозагрузку:
/etc/init.d/ws-socks enable
/etc/init.d/ws-dns enable

Теперь у вас есть socks5 прокси через wstunnel скрытый за haproxy как альтернатива для VPN, далее можно воспользоваться точечной маршрутизацией например инструкция от itdog для роутеров с использованием tun2socks или просто указать в браузере ip роутера (локального сервера) порт 2080 где развернут wstunnel и получить доступ в удаленную сеть, так же при наличии adguardhome или dnsmasq можете и нужно прописать наш локальный 127.0.0.1:5353 как основной резолвер, тем самым мы защитим наши DNS запросы от подмены.

Клиент для Windows так же скачиваем со страницы проекта, распаковываем переходим в папку и создаем файл с именем например start, копируем туда следующие содержимое:
wstunnel client --http-upgrade-path-prefix wss-secretpath1 --local-to-remote socks5://0.0.0.0:2080 wss://$ваш.домен:443 --tls-verify-certificate --connection-min-idle 4
Теперь сохраним его как start.cmd, запустив его получим локальный socks5 прокси, можно забить в браузер или воспользоваться nekobox с маршрутизаций и подключить наш socks5 к нему.

В конфигурации клиента wstunnel присутствует флаг --tls-verify-certificate он нужен для проверки сертификата сервера, если его убрать можно будет подключится к невалидному сертификату например самоподписанному или просроченному.

Рекомендация по настройке VPN

Для мобильных клиентов можно использовать VLESS + TLS

Пример настройки для X-UI:

Протокол VLESS
Порт например 4444 (он будет не публичный)
Протокол передачи TCP
Обязательно включаем PROXY Protocol и External Proxy:
Для External Proxy: Тот же  $ваш.домен(поддомен для VLESS) 443
Безопасность TLS 
SNI $ваш.домен(поддомен для VLESS)
Cipher Suites  Auto
Min/Max Version  1.2 1.3
Сертификат  должен лежать в директории ./x-ui/cert
Сертификат /root/cert/fullchain.pem
Ключ /root/cert/privkey.pem

На Хабре уже был целый цикл статей про настройку панелей для VLESS например вот.

Вот мой пример docker compose файла, я использую сеть host чтобы избежать nat докера:

---
services:
  xui:
    image: alireza7/x-ui
    container_name: x-ui
    hostname: $yourhostname
    volumes:
      - $PWD/db/:/etc/x-ui/
      - $PWD/cert/:/root/cert/
    environment:
      XRAY_VMESS_AEAD_FORCED: "false"
    tty: true
    network_mode: host
    restart: unless-stopped

Еще не забыли что нужно сайт еще разместить?
Разместите сайт на apache2 или nginx на localhost и любом доступном порте
Откроем конфиг Haproxy
sudo nano /etc/haproxy/haproxy.cfg
И добавим в конец:

backend http_defailt
        mode http
        option httpchk
        option forwardfor
        http-response set-header X-Content-Type-Options nosniff
        http-response set-header X-XSS-Protection 1;mode=block
        http-response set-header X-Frame-Options SAMEORIGIN
        http-request add-header X-Real-Ip %[src]
        http-request set-header X-Forwarded-For %[src]
        http-request set-header X-Forwarded-Host %[req.hdr(host)]
        http-request set-header X-Forwarded-Proto https if { ssl_fc }
        http-request set-header X-Forwarded-Proto http if !{ ssl_fc }
        server s1 127.0.0.1:8090

Теперь в секции frontend http нужно добавить следующий текст под use_backend:

defailt_backend http_defailt

Перезапускаем haproxy
sudo systemctl restart haproxy
Проверяем в браузере вводим ваш домен, если открылся сайт все сделано правильно, теперь у вас есть рабочий VPN с VLESS, WebSocket в качестве альтернативы VPN и рабочий сайт обманка.

Если тема будет интересна напишу продолжение с добавлением stunnel со SNI, расширенной маршрутизацией и защитой haproxy по спискам белых IP или блоклистам.

Автор: ki11j0y

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js