Это третья часть маршрутизации популярного VLESS силами HAProxy, с первой и второй рекомендуется ознакомиться.
Что такое steal oneself спросите вы — это «кража» отпечатка вашего сайта, с полной маскировкой, если клиент подключается к серверу (со включенным xtls-rprx-vision), а домен использует соединение TLS1.3 то будет зашифрован только заголовок после шифрование будет отключено для защиты от инспекции на двойной TLS, однако если НЕ клиент решит постучаться по адресу то «вжух» и соединение магически перенаправляется на ваш сайт (сервис) под который маскируемся, у данного метода есть НО — и это но белый список разрешенных доменов, тут можно прочитать подробнее и тут.
Собственно приступим подготовке конфигурации, нам потребуется два домена(поддомена) например mydomain.com и cats.mydomain.com, если отталкиваться от конфигурации во второй статье то изменений будет не много сначала приведу пример для этого варианта:
Необходимые изменения
Секцию frontend TCP из второй статьи
frontend tcp bind *:443 # ssl passthrough mode tcp option tcplog tcp-request inspect-delay 6s stick-table type ip size 1m expire 10s store conn_cur tcp-request content track-sc0 src tcp-request content reject if { sc_conn_cur(0) gt 30 } 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 tcp-ssh if !{ req.ssl_hello_type 1 } { payload(0,7) -m bin 5353482d322e30 } or !{ req.ssl_hello_type 1 } { req.len 0 } # Я бы не рекомендовал, вы лешитесь доступа если haproxy упадет default_backend tcp_to_https
Изменим на:
frontend tcp bind *:443 # SSL Passthrough mode tcp option tcplog tcp-request inspect-delay 5s # Защитим от перегрузки, если с одного IP за 10сек открыто более 30 соединений, отклоним все запросы и закроем все соединения # Нужно учитывать что WsTunnel с активным параметром --connection-min-idle <n> будет занимать указанное колличество при старте # У VLESS так же есть мультилексор, тоже нужно учитывать при настройке # Может так случиться если несколько клиентов в одно и тоже время с одного IP решат подключиться, все они потеряют доступ к серверу. stick-table type ip size 1m expire 10s store conn_cur tcp-request content track-sc0 src tcp-request content reject if { sc_conn_cur(0) gt 30 } 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 tcp-ssh if !{ req.ssl_hello_type 1 } { payload(0,7) -m bin 5353482d322e30 } or !{ req.ssl_hello_type 1 } { req.len 0 } # Я бы не рекомендовал, вы лишитесь доступа если haproxy упадет use_backend tcp_to_https if { req.ssl_sni -i mydomain.com } default_backend tcp_to_reality # cats.mydomain.com
Данные изменения сводятся к тому что бы весь трафик не прошедший по условиям перенаправить на backend tcp_to_reality, и отказаться от TCP+VLESS+TLS (можно и оставить на другом домене).use_backend tcp_to_https
отвечает за второй домен на котором висит сайт, wstunnel vless-ws и тд.
Так же у нас на 443 порту будет работать SSH, нужно ли оно вам решать вам.
Теперь добавим frontend для cats.mydomain.com под основной секцией frontend домена
frontend https_cats # Заглушка для Reality { ssl_fc_sni -i cats.mydomain.com } bind 127.0.0.1:49002 accept-proxy ssl crt /etc/haproxy/certs alpn h2,http/1.1 strict-sni http-request reject if { req.hdr(user-agent) -m sub evil } # acl url_discovery path /.well-known/caldav /.well-known/carddav # для правильной работы NextCloud # http-request redirect location /remote.php/dav/ code 301 if url_discovery # для правильной работы NextCloud http-request deny if { path -m sub /. } stick-table type ip size 100k expire 2m store http_req_rate(1m) http-request track-sc0 src http-request deny deny_status 429 content-type text/html lf-string "<p>Per our policy, you are limited to 30 requests per minute, but you have exceeded that limit with %[sc_http_req_rate(0)] requests per minute.</p>" if { sc_http_req_rate(0) gt 30 } http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;" # Устанавливаем HSTS http-request return status 200 content-type text/plain lf-string "Status 200 OK! Your IP %[src]." if { path /https-status-443 } default_backend cats
http_req_rate(1m) и if { sc_http_req_rate(0) gt 30 } отвечают за защиту от перегрузки, если придет более 30 запросов в течении минуты все соединения будут закрыты, а новые будут показывать ошибку 429.
http-request return status 200 content-type text/plain lf-string «Status 200 OK! Your IP %[src].» if { path /https-status-443 } будет отвечать «200 OK» по пути https-status-443, полезно для мониторинга доступности.
acl url_discovery path и http-request redirect location потребуются если решите маскироваться под nextcloud (настройка оного не будет описана здесь, главное настройте trusted_proxies, overwrite.cli.url, trusted_domains в config.php).
default_backend cats перенаправит все на ваш сервис.
Добавим backend reality
backend tcp_to_reality # Бекенд для передачи всего TCP трафика в X-UI не прошедшего по правилам в TCP фронтенде. mode tcp server https 127.0.0.1:48660 send-proxy check port 48660
Подготовим backend в виде панели X-UI, 3X-UI и другие, показываю на примере X-UI
Необходимые настройки для reality

Включаем прием Proxy Protocol для сохранения IP клиента.
TPROXY необязательно.
External Proxy указываем или основной домен или второй «cats.mydomain.com».
Соответственно выбираем Reality.
Xver 1 — это отправка прокси протокола необходимого для backend/frontend cats.
uTLS обязателен, у меня работает с firefox, uTLS нужен для имитации отпечатка браузера.
В Dest указываем IP и порт frontend cats.
SNI соответственно наш домен cats.mydomain.com.
И далее Get New Cert
При использовании TPROXY всю маршрутизацию настраивать на клиенте. TFO (TCP Fast Open) позволяет быстрее устанавливать соединение, однако данное решение имеет риски конфиденциальности, использовать или нет решайте сами, если не использовать TFO то TPROXY можно отключить, тогда настройки будут выглядеть так:

Данные настройки так же применимы и для VLESS-WS
Но ведь можно настроить и VLESS + WS и вы будите правы, данный вариант будет работать и за CDN только нужно будет произвести дополнительные настройки.
Пример VLESS + WS
Проведем конфигурацию HAProxy добавим в frontend основного домена строку под use_backend
use_backend ws-vless1 if { req.hdr(Host) -i mydomain.com } { path /ws-vless-secret-path1 } || { path_beg /ws-vless-secret-path1/ }
Добавим теперь backend, XRay при работе с WebSocket, ставит более высокий приоритет заголовкам X-Forwarded чем для proxy protocol
backend ws-vless1 mode http http-request set-header X-Forwarded-For %[src] http-request set-header X-Forwarded-Host %[req.hdr(host)] timeout tunnel 1h server s1 127.0.0.1:49111 send-proxy check port 49111
С HAProxy все, настроим панель, добавим подключение с протоколом VLESS и транспортом WebSocket

TLS должен быть отключен, за терминацию SSL отвечает HAProxy, так же включен proxy protocol для сохранения IP адреса клиента.
В данном варианте, не возможно включить xtls-rprx-vision, да и он не будет работать за CDN, за защиту от инспекции будет отвечать мультиплексирование, на сколько эффективно время покажет.
Пример полной конфигурации
В данном примере отключил все лишнее, все WebSocket сервисы и DoH, оставил только для работы reality и сайта
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 # Тюнинг http/2 для WebSocket tune.h2.initial-window-size 536870912 # Увеличиваем начальный размер окна для входящих и исходящих соединений. tune.h2.fe.max-concurrent-streams 512 # Установим кол-во одновременных потоков на входящие соединений. tune.h2.fe.glitches-threshold 1024 # Установим порог автоматического завершения соединения при превышении заданного кол-ва ошибок. tune.h2.be.max-concurrent-streams 512 # Установим кол-во одновременных потоков на исходящие соединений. tune.h2.be.glitches-threshold 1024 # Установим порог автоматического завершения соединения при превышении заданного кол-ва ошибок в backend соединениях. #------------------------------------------ defaults log global mode http option httplog option dontlognull timeout connect 40s timeout client 1m timeout server 1m timeout tunnel 1h timeout http-request 30s 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 nameserver ns2 127.0.0.1:53 nameserver ns2 127.0.0.3: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:49003 stats enable stats uri /stats stats realm Haproxy\ Statistics stats refresh 10s stats auth sdvhsis3w:opsdiv90-ikps stats show-legends stats hide-version #------------------------------------------ frontend http bind *:80 mode http http-request reject if { req.hdr(user-agent) -m len le 32 } http-request reject if { req.hdr(user-agent) -m sub evil } # Защитим от перегрузки # Если в течении 1m будет выполнено более 10 запросов отклоним ответом 429 Too Many Requests stick-table type ip size 100k expire 2m store http_req_rate(30s) http-request track-sc0 src # Отклоним с ответом http-request deny deny_status 429 content-type text/html lf-string "<p>Per our policy, you are limited to 10 requests per minute, but you have exceeded that limit with %[sc_http_req_rate(0)] requests per minute.</p>" if { sc_http_req_rate(0) gt 30 } http-request return status 200 content-type text/plain lf-string "%[path,field(-1,/)].${ACCOUNT_THUMBPRINT}\n" if { path_beg '/.well-known/acme-challenge/' } http-request return status 200 content-type text/plain lf-string "Status 200 OK! Your IP %[src]." if { path /http-status-80 } http-request deny if { path -m sub /. } # запрет доступа к скрытым файлам http-request redirect scheme https unless { ssl_fc } #------------------------------------------ frontend tcp bind *:443 # SSL Passthrough mode tcp option tcplog tcp-request inspect-delay 5s # Защитим от перегрузки, если с одного IP за 10сек открыто более 30 соединений, отклоним все запросы и закроем все соединения # Нужно учитывать что WsTunnel с активным параметром --connection-min-idle <n> будет занимать указанное колличество при старте # У VLESS так же есть мультилексор, тоже нужно учитывать при настройке # Может так случиться если несколько клиентов в одно и тоже время с одного IP решат подключиться, все они потеряют доступ к серверу. stick-table type ip size 1m expire 10s store conn_cur tcp-request content track-sc0 src tcp-request content reject if { sc_conn_cur(0) gt 30 } 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 tcp-ssh if !{ req.ssl_hello_type 1 } { payload(0,7) -m bin 5353482d322e30 } or !{ req.ssl_hello_type 1 } { req.len 0 } # Я бы не рекомендовал, вы лишитесь доступа если haproxy упадет use_backend tcp_to_https if { req.ssl_sni -i mydomain.com } default_backend tcp_to_reality # cats.mydomain.com данный домен используется для reality в секции tcp он не должен фигурировать, по дефолту перенаправляем все на backend x-ui с reality #------------------------------------------ frontend https # { ssl_fc_sni -i mydomain.com } # тут висит панель x-ui, Ws-VLESS, wstunnel, DoH adguard, и статистика HA тут же можно дополнить сайтом бизобидным. bind 127.0.0.1:49001 accept-proxy ssl crt /etc/haproxy/certs alpn h2,http/1.1 strict-sni http-request reject if { req.hdr(user-agent) -m sub evil } # acl url_discovery path /.well-known/caldav /.well-known/carddav # для правильной работы NextCloud # http-request redirect location /remote.php/dav/ code 301 if url_discovery # для правильной работы NextCloud http-request deny if { path -m sub /. } # запрет доступа к скрытым файлам # Защитим от перегрузки, если перестанет работать WsTunnel (чем больше клиентов тем выше установить счетчик) # Если в течении 30с будет выполнено более 30 запросов отклоним ответом 429 Too Many Requests stick-table type ip size 100k expire 5m store http_req_rate(30s) http-request track-sc0 src # Отклоним с ответом о превышенном кол-ве запросов http-request deny deny_status 429 content-type text/html lf-string "<p>Per our policy, you are limited to 30 requests per 30s, but you have exceeded that limit with %[sc_http_req_rate(0)] requests per 30s.</p>" if { sc_http_req_rate(0) gt 30 } http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;" # Устанавливаем HSTS http-request return status 200 content-type text/plain lf-string "Status 200 OK! Your IP %[src]." if { path /https-status-443 } use_backend http_stats if { ssl_fc_sni -i mydomain.com } { path_beg /ha-stats-secret-path/ } use_backend http_xui if { ssl_fc_sni -i mydomain.com } { path_beg /my-secret-path2/ } # { path_beg /xui/ } # use_backend dns_query if { ssl_fc_sni -i mydomain.com } { path_beg /dns-query/ } || { path /dns-query } # use_backend ws-socks-admin if { ssl_fc_sni -i mydomain.com } { path /ws-socks-secret-path } || { path_beg /ws-socks-secret-path/ } # use_backend ws-adguard if { ssl_fc_sni -i mydomain.com } { path /ws-adguard-secret-path1 } || { path_beg /ws-adguard-secret-path1/ } # use_backend ws-ssh if { ssl_fc_sni -i mydomain.com } { path /ws-ssh-secret-path2 } || { path_beg /ws-ssh-secret-path2/ } # use_backend ws-wg if { ssl_fc_sni -i mydomain.com } { path /ws-wg-secret-path3 } || { path_beg /ws-wg-secret-path3/ } # use_backend ws-vless1 if { req.hdr(Host) -i mydomain.com } { path /ws-vless-secret-path1 } || { path_beg /ws-vless-secret-path1/ } # в панели вкл proxy-protocol, path указывается как в haproxy, хост mydomain.com, external proxy tls mydomain.com 443 security None # use_backend ws-vless2 if { req.hdr(Host) -i mydomain.com } { path /ws-vless-secret-path2 } || { path_beg /ws-vless-secret-path2/ } # default_backend http_adh # панель настройки AdGuardHome default_backend cats # раскомментируйте после добавления сайта обманки #------- Reality -------------------------- frontend https_cats # Заглушка для Reality { ssl_fc_sni -i cats.mydomain.com } bind 127.0.0.1:49002 accept-proxy ssl crt /etc/haproxy/certs alpn h2,http/1.1 strict-sni http-request reject if { req.hdr(user-agent) -m sub evil } # acl url_discovery path /.well-known/caldav /.well-known/carddav # для правильной работы NextCloud # http-request redirect location /remote.php/dav/ code 301 if url_discovery # для правильной работы NextCloud http-request deny if { path -m sub /. } stick-table type ip size 100k expire 2m store http_req_rate(1m) http-request track-sc0 src http-request deny deny_status 429 content-type text/html lf-string "<p>Per our policy, you are limited to 30 requests per minute, but you have exceeded that limit with %[sc_http_req_rate(0)] requests per minute.</p>" if { sc_http_req_rate(0) gt 30 } http-response set-header Strict-Transport-Security "max-age=16000000; includeSubDomains; preload;" # Устанавливаем HSTS http-request return status 200 content-type text/plain lf-string "Status 200 OK! Your IP %[src]." if { path /https-status-443 } default_backend cats #------- BACKEND -------------------------- #[ tcp backend tcp-ssh # Бекенд для SSH mode tcp option http-keep-alive timeout http-keep-alive 30s server ssh 127.0.0.1:22 check port 22 backend tcp_to_https # Бекенд для передачи TCP трафика домена на http фронтенд, для основных сайтов. mode tcp server https 127.0.0.1:49001 send-proxy-v2-ssl-cn check port 49001 backend tcp_to_reality # Бекенд для передачи всего TCP трафика в X-UI не прошедшего по правилам в TCP фронтенде. mode tcp server https 127.0.0.1:48660 send-proxy check port 48660 # end tcp ] [ http backend http_stats # Статистика HA mode http http-request replace-path /ha-stats-secret-path(/)?(.*) /\2 server stats 127.0.0.1:49003 backend http_xui # Админ панель X-UI (3X-UI) и тд mode http option httpchk GET /xui/ #изменить после настройки панели на /my-secret-path2/xui option forwardfor if-none 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 Host %[req.hdr(Host)] http-request set-header X-Forwarded-For %[src] http-request set-header X-Forwarded-Host %[req.hdr(host)] server s1 127.0.0.1:54321 check #поменять порт на 49004 после настройки панели #backend dns_query # DOH AdGuardHome # mode http # option httpchk # option forwardfor if-none # 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 Host %[req.hdr(Host)] # http-request set-header X-Forwarded-For %[src] # http-request set-header X-Forwarded-Host %[req.hdr(host)] # server doh 127.0.0.1:49005 #check port 49005 # end http ] [ WebSocket #backend ws-socks-admin # WsTunnel # mode http # option http-keep-alive # timeout http-keep-alive 25s # timeout tunnel 1h # server s1 127.0.0.1:49101 check port 49101 #backend ws-adguard # WsTunnel # mode http # option http-keep-alive # timeout http-keep-alive 25s # timeout tunnel 1h # server s1 127.0.0.1:49102 check port 49102 #backend ws-ssh # WsTunnel # mode http # option http-keep-alive # timeout http-keep-alive 25s # timeout tunnel 1h # server s1 127.0.0.1:49103 check port 49103 #backend ws-wg # WsTunnel # mode http # option http-keep-alive # timeout http-keep-alive 25s # timeout tunnel 1h # server s1 127.0.0.1:49104 check port 49104 #---------------- #backend ws-vless1 # Admin # mode http # http-request set-header X-Forwarded-For %[src] # http-request set-header X-Forwarded-Host %[req.hdr(host)] # timeout tunnel 1h # server s1 127.0.0.1:49111 send-proxy check port 49111 #backend ws-vless2 # Clients-2 # mode http # http-request set-header X-Forwarded-For %[src] # http-request set-header X-Forwarded-Host %[req.hdr(host)] # timeout tunnel 1h # server s1 127.0.0.1:49112 send-proxy check port 49112 # end WebSocket ] #----------AdGuardHome---------------------- #backend http_adh #только при первоначальной настройке # mode http #лучше исключить попадание данного сервиса в открытый доступ # server adh 127.0.0.1:49005 #доступ через проброс ssh или wstunnel #------------------------------------------ #------------------------------------------ backend cats #обманка mode http option forwardfor http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request set-header X-Forwarded-Host %[req.hdr(host)] http-request set-header X-Forwarded-For %[src] http-request add-header X-Real-Ip %[src] server s1 127.0.0.1:49006 check port 49006 #------------------------------------------ #------------IP Table---------------------- # Range 48658—48999 - TCP // 49001—49100 - http сервисы // 49101-49150 - WS # --- TCP --- #48658 - ocserv #48659 - #48660 - tcp_to_reality #48661 - #48662 - #48663 #48664 # --- http --- #49001 - frontend https #49002 - frontend reality #49003 - http_stats #49004 - http_xui #49005 - dns_query || http_adh #49006 - http_cats #49007 - #49008 #49009 #49010 #49011 # --- WebSocket --- #49101 - ws-socks # WsTunnel #49102 - ws-adguard # WsTunnel #49103 - ws-ssh # WsTunnel #49104 - ws-wg # WsTunnel # #49111 - ws-vless1 # Admin #49112 - ws-vless2 # Clients #49113 - #49114 - #49121 - #49122 -
В IP Table я храню порт=сервис, использую диапазоны свободных портов согласно IANA.
Пару слов про ответ «200 OK!», я использую его для мониторинга доступности, а так же для поддержания соединения при работе с wstunnel, для этого использую следующий скрипт в cron
Пример скрипта мониторинга
#!/bin/bash for i in {1..60}; do response=$(curl --socks5 127.0.0.1:2080 -Is http://mydomain.com/http-status-80/ | head -n 1) if [[ "$response" == *"200 OK"* ]]; then echo "Received 200 OK. Exiting loop." break elif [[ -z "$response" ]]; then echo "Empty response. Attempt $i of 60." fi sleep 1 # Задержка между запросами done # Проверка, если все ответы были пустыми if [[ -z "$response" ]]; then echo "All responses were empty. Restarting wstunnel.service." systemctl restart ws-socks.service fi
Скрипт будет пытаться 60 раз, достучаться до сайта, если не получит ответ «200 OK» — перезапустит сервис. Аналогичный скрипт я применяю на роутере с sign box, если статус не получен перезапускается sign box.
Если заменить mydomain.com
на https://cats.mydomain.com/https-status-443/
будем одновременно мониторить и сервис Reality и HAProxy однако помним про ограничение частоты запросов на tcp frontend.
Про GeoIP из второй статьи
В одной из статей на хабре, в комментариях невежливо указали что по GeoIP блочат только не хорошие люди, что-ж, исправляюсь, есть разнообразные списки «плохих» адресов, я взял FireHOL списки и написал скрипт для их загрузки и подключения в haproxy, для начала необходимо создать директорию для хранения списковmkdir /etc/haproxy/firehol
Теперь создадим файл например firehol в директории /etc/cron.daily для ежедневого обновления со следующим содержимым
#!/bin/bash # Определяем директории TMP_DIR="/tmp/firehol" DEST_DIR="/etc/haproxy/firehol" # Создаем временную директорию mkdir -p "$TMP_DIR" # Скачиваем файлы urls=( "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset" "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level2.netset" "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level3.netset" "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_abusers_1d.netset" ) files=("level1.acl" "level2.acl" "level3.acl" "abusers_1d.acl") for i in "${!urls[@]}"; do curl -s "${urls[$i]}" -o "$TMP_DIR/${files[$i]%.acl}.netset" done # Очищаем файлы от комментариев и пустых строк for file in "${files[@]}"; do netset_file="$TMP_DIR/${file%.acl}.netset" acl_file="$TMP_DIR/$file" grep -vE '^\s*#|^\s*$' "$netset_file" > "$acl_file" done # Генерируем md5 для файлов declare -A md5s for file in "${files[@]}"; do md5s["$file"]=$(md5sum "$TMP_DIR/$file" | awk '{ print $1 }') done # Проверяем наличие файлов в целевой директории и обновляем их при необходимости for file in "${files[@]}"; do dest_file="$DEST_DIR/$file" if [[ ! -f "$dest_file" ]] || [[ "$(md5sum "$dest_file" | awk '{ print $1 }')" != "${md5s[$file]}" ]]; then cp "$TMP_DIR/$file" "$dest_file" echo "Обновлен файл: $dest_file" fi done # Перезапускаем haproxy systemctl restart haproxy # Удаляем временную директорию rm -rf "$TMP_DIR"
Необходимо сделать его исполняемымchmod 700 /etc/cron.daily/firehol
Теперь добавим в секцию с frontend tcp следующую строку сразу после «tcp-request inspect-delay 5s»
# FireHOL IP List tcp-request connection reject if { src -f /etc/haproxy/firehol/level1.acl } || { src -f /etc/haproxy/firehol/level2.acl } || { src -f /etc/haproxy/firehol/level3.acl } || { src -f /etc/haproxy/firehol/abusers_1d.acl }
Выполним скрипт командой /etc/cron.daily/firehol
и перезапустим haproxy командой systemctl restart haproxy
На этом я закончу цикл про совмещение HAProxy и VLESS. В будущем возможно напишу про проксирование VLESS+WS через CDN.
P.s.
Я дал общие конфигурации и примеры, как можно скрыть разнообразные сервисы за HAProxy, и данный цикл статей ни в коем образе не является пособием по обходу блокировок и доступом к запрещенной информации.
Подключении подписки
Включите в настройках службу подписки:

И подписку json

Теперь добавьте в основной http frontend под http_xui строкуuse_backend http_xui_sub if { path_beg /submyserver/ } || { path_beg /jsubmyserver/ }
Путь submyserver и jsubmyserver измените на свой, как в панели так и конфиге HAProxy
Теперь добавьте backend
backend http_xui_sub mode http 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 set-header X-Forwarded-Host %[req.hdr(host)] http-request set-header X-Forwarded-For %[src] http-request set-header X-Forwarded-Proto https if { ssl_fc } http-request set-header X-Forwarded-Proto http if !{ ssl_fc } http-request add-header X-Real-Ip %[src] server s1 127.0.0.1:2096
После сохраните изменения в панели и конфиге haproxy, и перезапустите сервисы. Теперь у вас появится возможность добавлять пользователей через подписку, как показала практика это удобнее, не нужно изменять параметры для каждого клиента, если что то изменится в настройках подключения, например изменится uTLS или будут сгенерированы новые сертификаты Reality.
ссылка на оригинал статьи https://habr.com/ru/articles/885276/
Добавить комментарий