Взлом панели 3x-ui

Добрый день, мой сервер (3x-ui панель) взламывался три раза, я ни как не могу найти причину и это уже сводит с ума. Суть такова - раз в пару месяцев я получаю письмо счастья от хостера что мой лимит траффика почти исчерпан, бегу в панель и вижу что ничего не вижу. Сервер был установлен три раза, немного о каждой установке (если лень читать можно сразу начать с третьего):

  1. Сервер был раскатан из образа хостера, поставлена панель по скрипту из официального гитхаба 3x-ui, вход по ssh по паролю, заблокированы все порты кроме https и ssh (он был измене со стандартного). панель работала по https. Забил и переустановил.

  2. Сервер был раскатан из образа хостера, поставлена панель по скрипту из официального гитхаба 3x-ui, вход по ssh по ключу, вход под рутом отключён, заблокированы все порты кроме https и ssh (он был изменен со стандартного), панель работала по ssh тунелю и наружу вообще не торчала. Тут я уже начал разбираться - насколько помню входов по ssh не было кроме моих, аномального траффика в панели (как общего так и от пользователей) не отображалось. после изменения конфига (изменения названия конфига, пользователей, перегенерации сертификатов) аномальный траффик вроде останавливался. Также фиксировались странные подключения по IPV6. В итоге еще одна переустановка.

  3. Сервер был раскатан собственноручно, панель установлена в докер согласно официальному гайду на гитхабе, сеть докера в режиме хоста, вход по ssh по ключу, вход под рутом отключён, заблокированы все порты кроме https и ssh (он был изменен со стандартного), отключен IPV6, на всякий настроен iptables для ipv6 на дроп всего. Панель только по ssh тунелю. В итоге опять активность, аномального траффика в панели (как общего так и от пользователей) не отображалось, пользователей левых тоже нет. Тут я уже осел конкретно. В TCPdump подключения с китайских и иранских IP. Я ради интереса ввожу в гугл %IP сервера% vless и нахожу конфиги который ВООООБЩЕ не мои, но прекрасно работает с моего сервера

    VLESS vless://47517441-8be8-413c-bda8-68651fea0199@proxy.tegalwap.com:443?encryption=none&security=tls&sni=proxy.tegalwap.com&fp=randomized&type=ws&host=proxy.tegalwap.com&path=%2FYudhyNet-SE508#[SE]%20HostHatch%20🇸🇪

    shadowsocks ss://bm9uZTo0NzUxNzQ0MS04YmU4LTQxM2MtYmRhOC02ODY1MWZlYTAxOTk=%3D@proxy.tegalwap.com:443?encryption=none&type=ws&host=proxy.tegalwap.com&path=%2FYudhyNet-SE508&security=tls&sni=proxy.tegalwap.com#[SE]%20HostHatch%20🇸🇪

    trojan trojan://47517441-8be8-413c-bda8-68651fea0199@proxy.tegalwap.com:443?encryption=none&security=tls&sni=proxy.tegalwap.com&fp=randomized&type=ws&host=proxy.tegalwap.com&path=%2FYudhyNet-SE508#[SE]%20HostHatch%20🇸🇪

Как я понял они все ведут в один инбаунд, а именно proxy.tegalwap.com, а дальше от них он как-то попадает в мой сервер. Дальше интересней. Я проверяю их и они работают. Я изменяю ключи всем пользователям, меняю название инбаунда - конфиги работают. Я отключаю всех пользователей - конфиги работают. Я удаляю все пользователей - конфиги работают. Я лезу в БД 3x-ui и не вижу ничего. Я смотрю сервер на наличие соединений и все они на 443 порт (он занят контейнером 3x-ui). Я меняю режим сети контейнера 3x-ui с хоста на бридж, вешаю на 443 порт сервера обратный прокси traefik c указанием разруливать весь приходящий траффик с HostSNI под который шифруется Reality на контейнер с vless и все эти конфиги разом отваливаются. Вместо открытия сайта который пытаешься открыть вылетает ошибка о ошибке сертификата (traefik default cert). В итоге сервер сейчас оключен. На него все еще идут массированные запросы по 443 порту от cloudflare CDN (у моего домена cloudflare proxy отключен)

Вот куски логов TCPdump и Traefik logs:

TCPdump:

09:39:56.833851 IP 104.28.162.113.43262 > my-ip.https: Flags [S], seq 417913112, win 65535, options [mss 1380,sackOK,TS val 193414247 ecr 0,nop,wscale 13], length 0
09:39:56.836551 IP 104.28.159.8.22529 > my-ip.8443: Flags [S], seq 3732206004, win 65535, options [mss 1380,sackOK,TS val 693011921 ecr 0,nop,wscale 13], length 0
09:39:56.836684 IP 104.28.155.181.25118 > my-ip.domain: Flags [S], seq 2813089401, win 65535, options [mss 1380,sackOK,TS val 3334002270 ecr 0,nop,wscale 13], length 0
09:39:56.837537 IP 104.28.155.167.35956 > my-ip.https: Flags [S], seq 3773346653, win 65535, options [mss 1380,sackOK,TS val 2920697331 ecr 0,nop,wscale 13], length 0
09:39:56.837915 IP 104.28.156.55.9488 > my-ip.8443: Flags [S], seq 1788074973, win 65535, options [mss 1380,sackOK,TS val 3428232912 ecr 0,nop,wscale 13], length 0
09:39:56.838192 IP 104.28.159.21.51256 > my-ip.https: Flags [S], seq 2373508973, win 65535, options [mss 1380,sackOK,TS val 1248926730 ecr 0,nop,wscale 13], length 0

traefik

2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "chrome.cloudflare-dns.com"
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.155.184:45629: EOF
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "nzf4ylmdh4osbp505aa050010203040506070809.-update1.android.google.sync.image.tnabisibizip.ir"
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.161.17:25643: EOF
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "chrome.cloudflare-dns.com"
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "chrome.cloudflare-dns.com"
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "nzf4ylmdh4osbp505aa050010203040506070809.-update1.android.google.sync.image.tnabisibizip.ir"
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "nzf4ylmdh4osbp505aa050010203040506070809.-update1.android.google.sync.image.tnabisibizip.ir"
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.155.175:16039: remote error: tls: bad certificate
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "edge-mqtt-fallback.facebook.com"
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.162.210:56286: remote error: tls: unknown certificate
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.162.210:47588: remote error: tls: unknown certificate
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "nzf4ylmdh4osbp505aa050010203040506070809.-update1.android.google.sync.image.tnabisibizip.ir"
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "pulseadnetwork.com"
2025-07-31T09:29:52+03:00 DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:288 > Serving default certificate for request: "chrome.cloudflare-dns.com"

При остановленном traefik

2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.155.192:21930: read tcp 172.18.0.2:443->104.28.155.192:21930: use of closed network connection
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.162.110:48578: read tcp 172.18.0.2:443->104.28.162.110:48578: use of closed network connection
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.155.187:27080: read tcp 172.18.0.2:443->104.28.155.187:27080: use of closed network connection
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.164.227:42794: read tcp 172.18.0.2:443->104.28.164.227:42794: use of closed network connection
2025-07-31T09:29:52+03:00 DBG log/log.go:245 > http: TLS handshake error from 104.28.159.87:15305: read tcp 172.18.0.2:443->104.28.159.87:15305: use of closed network connection

For TL;DR - к моему серверу подключаются по левым конфигам, в панели их нет, а траффик капает

маскировочный домен для Reality случайно указывает не на сайт расположенный за Cloudflare или еще какой-то большой CDN?

Если да, то объяснение вполне простое.
Этот tegalwap работает через CF или какую-нибудь еще большую CDN. Без вашего сервера, все честно, про ваш сервер они даже не в курсе.
А где-нибудь в Иране адреса этой самой CDN забанены и иранцы не могут к ней подключиться. Они просканировали интернет, и нашли ваш сервер, который благодаря настроенному вами Reality, чей маскировочный домен указывает на сайт за этой CDN, передает все запросы на 443 порт, не прошедшие проверку “свой-чужой” на один из балансеров этой CDN. И адрес вашего сервера у этих иранцев не забанен. Поэтому они радостно поменяли в конфигах IP с tagelwap на IP вашего сервера (или внесли запись в hosts-файл), и используют ваш сервер как прокси чтобы достучаться до этой CDN и дальше через нее использовать проксики от tagelwap.

А когда вы проверяли эти конфиги и они у вас работали - там ваш сервер никак не участвовал, там вы подключались напрямую к этой CDN, которая у вас не забанена.

Решение: не использовать в качестве маскировочного домена Reality сайты за публичными CDN, а если используете - делайте фильтрацию по SNI с помощью traefik/haproxy/nginx/etc.

Я тоже об этом думал, потому что сайт Reality использует cloudflare, но:

Поэтому они радостно поменяли в конфигах IP с tagelwap на IP вашего сервера (или внесли запись в hosts-файл)

Конфиги эти ищатся по запросу %IP сервера% vless и прекрасно работают без смены чего-либо

когда вы проверяли эти конфиги и они у вас работали - там ваш сервер никак не участвовал, там вы подключались напрямую к этой CDN, которая у вас не забанена

Как только мой xray отключался, эти конфиги тоже падали

видимо поэтому разраб хрея и не рекомендует её

А нет случайно инструкции по настройке? :slight_smile: У меня, правда, панель мазрбан

Ну так вполне вероятно кто-то в этих конфигах уже исправил адрес tagelwap на IP вашего сервера, и тогда они работают без смены чего-либо.
Именно поэтому вы находили их в гугле по запросу своего IP-адреса - если бы его там не было, гугл бы его не нашел..
И тогда когда вы отключите ваш XRay, у вас эти конфиги тоже упадут.

Возможны кстати оба варианта - кто-то использовал конфиги для прокси as is, но с вашим адресом, а кто-то прописал адрес вашего сервера в hosts (или использовал какой-нибудь локальный прокси для подмены адресов), чтобы трафик до ресурсов за cloudflare шел через ваш сервер - это хорошо объясняет что в логах внешних подключений к traefik вы видите SNI типа chrome.cloudflare-dns.com и pulseadnetwork.com.

Еще более упоротый вариант - они как прокси используют Cloudflare Workers (типа как тут Пост @Uporoty — Информационная безопасность — 06.01 10:32 / Хабр), и там есть известная проблема - таким образом доступны все ресурсы, кроме самих ресурсов Cloudflare. Поэтому они там делают sniffing и все что идет на сети Cloudflare пускают через какой-нибудь промежуточный сервер, коим оказался ваш, раз его легко можно было найти простым сканированием.

Опять же, если бы выложили лог самого XRay (как минимум с уровнем Info, а лучше debug) в момент такого паразитного трафика - это сразу бы ответило на очень много вопросов и показало, как именно проникал трафик через ваш сервер.

не по этому. там был срач на тему того, что эти панели по умолчанию открывают доступ по нешифрованному HTTP.
но это не случай автора поста, он сразу сказал, что панель слушала только на 127.0.0.1 и он подключался к ней через SSH.

с HAProxy примерно так:

frontend https_front
    bind xx.xx.xx.xx:443
    tcp-request inspect-delay 5s
    tcp-request content accept if { req_ssl_hello_type 1 }
    acl sni_ok req_ssl_sni -i your_reality_domain.com

    use_backend xray_ssl if sni_ok
    default_backend reset_backend

backend xray_ssl
    server xray_ssl 127.0.0.1:8443 check
backend reset_backend
    mode http
    mode tcp
    tcp-request content reject

и заставляете inbound в панели слушать 127.0.0.1:8443 вместо 0.0.0.0:443 (и да, это сломает подписки для клиентов - надо будет в конфигах вручную порт менять)

Ненене, в самом первом сообщении я буквально скопировал конфиг который нашел у них на сайте если вписать мой ip адрес, вот он еще раз:

VLESS vless://47517441-8be8-413c-bda8-68651fea0199@proxy.tegalwap.com:443?encryption=none&security=tls&sni=proxy.tegalwap.com&fp=randomized&type=ws&host=proxy.tegalwap.com&path=%2FYudhyNet-SE508#[SE]%20HostHatch%20🇸🇪

В нем не указывается IP моего сервера, однако он работает. И он переставал работать как только я отключал 3x-ui (или включал разруливания траффика через traefik с указанием HostSNI Reality). Но суть то в чем: я на 99.9% уверен что этот конфиг шел по цепочке “клиент → proxy.tegalwap.com → мой сервер”. Без валидного инбаунда они через мой сервер выйти дальше не могли, а значит они имели доступ к инбаунду, который я нигде не видел

как я уже выше расписал - вполне могли, если они использовали ваш сервер не для всего трафика подряд, а для проксирования к ресурсам за Cloudflare. Если ваш reality-домен относится к сайту за CF, то для такого проксирования не надо иметь доступа ни к инбаунду, ни к панели, ни к самому серверу. А поскольку очень часто в качестве DNS используется 1.1.1.1 (а в качестве теста связности cp.cloudflare.com), то отключение вашего сервера ломало доступ целиком.

Зачем им это надо - тут все просто, у них публичный прокси к которому подключаются вообще все кто угодно, весьма вероятно кто-то из их пользователей основательно накосячил, и теперь антибот-система CF всем юзерам с их IP сует прохождение капчи или вообще не пускает, вот они и вынуждены перенаправлять трафик через какой-нибудь левый IP. Сдохнет ваш - найдут еще один такой же открытый Reality направленный на CF.
Либо еще вариант, они таким образом обходят ограничения работы прокси на CF workers/pages (оттуда недоступны сами ресурсы CF, только через промежуточный сервер), я об этом выше писал.

и еще раз повторюсь, если бы выложили лог самого XRay (как минимум с уровнем Info, а лучше debug) в момент такого паразитного трафика - это сразу бы ответило на очень много вопросов и показало, как именно проникал трафик через ваш сервер.