My Point VPN
Intro
Предоставляет интерфейс чат бота в телеграмм посредством которого позволяет разворачивать 3x-ui на своем сервере и выпускать ключи.
Базово конфигурируется 3x-ui на создание vless подключений с tls+reality маскировкой трафика. Настраивается dns, подписка и базовая безопасность сервера. Пользователь может прикрутить прокси на выход или включить cf_warp прокси. По каждому серверу дает базовую статистику у ручки управления.
Если вам нужен приватный доступ в интернет, передайте сервер боту и он настроит вам его. Выглядит это так: пользователь заводит аккаунт хостинг провайдера, арендует сервер, ему выдают ip и пароль root, он передает их боту, оный настраивает сервер, теперь пользователь может выпускать ключи vless и подключаться к интернету безопасно и приватно.
- статистика сервера:
- сколько трафика пропустил
- сколько пользователей
- можно добавить пользователя
- статистика по пользователю:
- онлайн?
- сколько трафика пропустил
- можно удалить пользователя
Серверу можно настроить:
- прокси на выходе (cf или свои)
- домен (сертификат Let's Encrypt; без домена сертификат выпускается на ip)
За Cloudflare точки не работают: reality через проксирование Cloudflare невозможен, Cloudflare сам завершает TLS. Скрыть адрес панели от клиентов можно сервером маскировки.
Окружение
- Linux Mint 22
- Python 3.12.3
- PyCharm 2026.2.1
Интерфейс чата
Переход в главное меню должен быть реализован кнопкой в клавиатуре. /start и кнопка "главное меню" должны выполняться одним методом.
Сейчас у пользователя нет данных и это его первое сообщение, поэтому система показывает ему сообщение заглушку.
--->
/start
<---
привет. выбери действие
[ФАК][добавить сервер][помощь]
Пользователь нажимает на кнопку добавления сервера и переходит в меню добавления сервера.
Меню добавления сервера
--->
добавить сервер
<---
Сервер: -
Сервер маскировки: -
Домен: -
Прокси: -
[домен][прокси][маскировка]
[отмена][установить][сервер][помощь]
--->
сервер/маскировка
<---
отправь данные для подключения к серверу
`ip:root_password`
[отмена]
После получения данных выполняется процесс настройки сервера. Этот процесс занимает время, поэтому выполняется в фоне.
--->
127.0.0.1:toor
<---
Сервер: 127.0.0.1
Домен: -
Прокси: -
[домен][прокси][маскировка]
[отмена][установить][сервер][помощь]
--->
прокси
<---
Можно указать свои или включить cf_warp.
[cf_warp][отмена][удалить]
--->
http://127.0.0.1:9050
<---
Сервер: 127.0.0.1
Домен: -
Прокси: http://127.0.0.1:9050
[домен][прокси][маскировка]
[отмена][установить][сервер][помощь]
--->
установить
<---
Запускаю установку сервера. Отправлю уведомление когда все будет готово.
А по окончании генерируется уведомление.
--->
<---
сервер ip - проименован как `NAME`, готов к работе.
[меню сервера]
Меню
Пользователь опять отправляет /start это нормально, так он получает главное меню с перечислением его серверов.
--->
/start
<---
point-1a2b3c активен
[ФАК][добавить сервер][помощь]
[управление сервером]
Чтобы перейти к управлению сервером нужно вот такой квест пройти, надо все эти id в копируемый pre сунуть.
--->
управление сервером
<---
Пришлите server_name
[отмена]
Меню управления сервером
--->
меню сервера
<---
Сервер: NAME
Состояние: активен
Панель: 1.2.3.4
Маскировка: -
Ключи: 2
Домен: -
Прокси: -
[Вернуть][Переустановить]
[Домен][Прокси]
[Клиенты]
[главное меню]
Возврат сервера связан с отключением его от платформы. Доступы к серверу изымаются, ставится новый пароль рута, а данные остаются как есть. Просто отдаем сервер назад.
--->
Вернуть
<---
Сервер будет освобожден из-под моего контроля,
будет установлен случайный пароль рута,
мои доступы будут убраны, данные на сервере сохранены.
Будет отправлено уведомление с новым паролем. Продолжить?
[Да][Нет]
Возможно потребуется переустановка после сброса сервера. Бывает такое когда это нужно. Обычно после сброса сервера задается новый пароль.
--->
Переустановить
<---
Будет произведена повторная установка всех компонентов.
Вызывайте эту функцию, только после того, как в панеле управления
сервером в аккаунте хостинг провайдера вызовите переустановку сервера.
Если уверены, то пришлите новый пароль сервера.
[Отмена][Использовать старый]
Меню управления доменом. После установки выпускаются ссл сертификаты, а если домена нет, то сертификат выпускаем на ip.
--->
Домен
<---
Сейчас установлен: -
Доменное имя лучше подходит для маскировки вашей точки доступа.
[установить][отключить]
Прокси полезно ставить. Есть 2 варианта, когда пользователь покупает прокси и задает их тут, или когда активирует cf_warp.
--->
Прокси
<---
Сейчас установлено: -
Позволяют маскировать ip адрес вашей точки доступа от сайтов,
которые посещаются.
X <> MyPoint <> PROXY <- Web
Сайты видят ip прокси, а не ip вашей точки доступа.
[установить][отключить]
--->
установить
<---
пришли прокси в формате `protocol://username:password@host:port` или нажми кнопку.
[cloudflare warp][отмена]
Меню управления клиентами
Домен и прокси меняются на горячую, в фоне: точка на это время "настраивается", по окончании приходит уведомление. Новый прокси сначала проверяется, а сертификат на новый домен сначала выпускается. Если не вышло, точка остается активной с прежними настройками, а ошибка видна в карточке. У точки с маскировкой домен можно сменить, но не убрать. Смена домена меняет ссылки подписок: ключи нужно раздать заново. Сообщение с прокси бот удаляет из чата, пароль прокси в карточке скрыт.
--->
Клиенты
<---
Ключи point-1a2b3c
mom-phone ↓ 1.2 ГБ ↑ 80.0 МБ, в сети 26.09 14:05
laptop ↓ 0 Б ↑ 0 Б, не подключался
Пришли имя ключа, чтобы получить ссылку подписки.
[выпустить ключ][отозвать ключ]
[меню сервера]
--->
mom-phone
<---
Ключ mom-phone: ↓ 1.2 ГБ ↑ 80.0 МБ, в сети 26.09 14:05
Подписка:
https://1.2.3.4:12839/9g72PmSGAQ3V/<subId>
"выпустить ключ" просит имя (латиница, цифры, - и _), "отозвать ключ" - имя существующего. Клиенту выдается URL подписки, а не vless-ссылка: он переживает переустановку точки, ключи восстанавливаются с прежними uuid и subId. Ограничений на число ключей нет, выпускает их владелец точки.
Настройка сервера
Чтобы сервера были в безопасности их следует правильно настроить. От пользователя ожидается на вход девственный сервер с только что установленной операционной системой.
- Конфигурирование ssh
- Смена пароля рута
- Конфигурирование nftables
- Обновление операционной системы
- Установка 3x-ui
- Выпуск сертификата
- Настройка vless+tls+reality
- Настройка прокси
Функционал бота
Добавление сервера
Сервер добавляется после установки ОС. Для бота требуется, чтобы ОС была debian-12 или debian-13. Свежий сервер:
- открыт публично 22 порт ssh
- имеет ip
- рут может войти по ssh используя пароль
Алгоритм действий для нового сервера, чтобы включить его в работу.
- Заходим на сервер по паролю
- прописываем ему свой ключ
- меняем пароль, но сохраняем оба
- Выполняем обновление системы
apt update -y && apt dist-upgrade -y - Настраиваем ssh
- отключаем вход по паролю
- жестко фиксируем авторизацию только по ключам
- меняем порт
- сохраняем конфиг sshd, перезапускаем сервис, проверяем коннект
- Настраиваем nftables
Система общается с сервером только через авторизацию по ssh ключам. Когда пользовать захочет вернуть сервер себе, следует:
- Откатываем настройки ssh
- Сбросить nftables
- Удалить файл /root/.ssh/authorized_keys
- Отдать ip:password
После базовой настройки нового сервера можно его специализировать. Этим занимается пакет serverus, который умеет готовить специализированные сервера под определенный вид задач.
Пакет также занимается и настройкой серверов базово. И позволяет сделать из сервера прокси или панель 3x-ui. Для наших целей требуется оба и в интерфейсе добавления сервера есть пункт "Сервер маскировки" - это сервер из которого нужно сделать прозрачный прокси. В App заводим модель в которой объединяем эти 2 сервера в единую систему. Так как кнопка "Вернуть" вернет оба сервера и они связаны настройками маршрутизации.
Запуск
cp env_example .envи заполнить: база, RabbitMQ,FIELD_ENCRYPTION_KEYS,SERVERUS_CERTIFICATES.docker compose up -d- Postgres, RabbitMQ, свой Bot API сервер.make sync,make dj_migrate,make dj_superuser.- Три процесса:
make dj_run(сайт и админка),make dj_worker(установка и возврат серверов),make tg_run(бот, запускать строго один экземпляр). - В админке добавить бота с токеном, выбрать интерфейс MyPoint и опубликовать.
Подробности: src/App/README.md (сценарии, секреты, ручной вход make serve_ssh), src/serverus/README.md (плейбуки, ручная проверка на сервере), src/Telegram/README.md (боты).
Локальный стенд: SERVERUS_CERTIFICATES=local, сертификаты выпускает свой CA из extra/serverus/ca, ca.pem нужно добавить в доверенные на машине с клиентом. Let's Encrypt на серых адресах не работает.
Модель данных
Пользователи - приходят из телеграма, у них есть id, который уникален и проверен, его можно использовать для авторегистрации. И следует обязательно запоминать, так как боту недоступна информация о подключенных к нему пользователях, только в момент когда пользователь взаимодействует с ботом.
- telegram user id - запоминаем id пользователя телеграм
Точка - наша выдуманная абстракция, чтобы объединить в группу (кластер) 2 сервера. Домен. Прокси (или аккаунт cf_warp).
- сервер 3x-ui - обязательно должен быть, ради него все и затевается
- сервер маскировки - если пользователь хочет особый режим, то он может добавить еще один сервер купленный в своей стране
- домен - если сервер маскировки указан, то домен обязательно нужно указать
- ssl сертификаты - если домен не указан, то сертификаты выпускаются на IP сервера 3x-ui, а сервера маскировки нет; а если домен есть то он привязывается к серверу маскировки и на него выпускаются ssl ключи, который хранятся на сервере 3x-ui, потому что сервер маскировки лишь прозрачно проксирует. Храним и домен, и ip, по ssh ходим только по ip
- ssh ключи - доступ к серверам, находящимся под нашей ведомостью, всегда осуществляется асимметричным способом (ключ-файл)
- прокси - можно задать свои и с авторизацией, а можно воспользоваться cf_warp прокси, которые можно регистрировать автоматически через x-ui
- ключи - клиенты панели: имя, uuid и subId, чтобы восстановить их после переустановки
Сервер - реальные сервера с ip и доступом к root. Настраиваем безопасное окружение по всем канонам.
Сервис - На серверах у нас живут сервисы. Поднимается или настраивается какой-то сервис, чтобы решить какую-то полезную задачу. И реализуют api для управления сервисом на сервере. Сейчас эту функцию выполняет Роль сервера, потому что подразумевается что сервис может быть 1.
Что осталось
Проверено на локальном стенде (Debian 13, свой CA): установка точки из бота с маскировкой, DoT и запасной DoH, ключи и подписка, socks5 и WARP на выходе, отказ нерабочего прокси, переустановка с восстановлением ключей, возврат серверов, serve_ssh, шифрование секретов в Postgres.
Функции
- Кнопки "Домен" и "Прокси" у готовой точки, смена на горячую.
- Скрипт маскировки (сейчас маскировка - перенаправление портов nftables).
- Статистика точки в главном меню и карточке: трафик и число ключей онлайн (сейчас статистика только у ключей).
- Кто может пользоваться ботом: сейчас любой, кто написал боту, может добавить сервер. Решить: белый список, инвайты или открыто.
Надежность
- Точка, зависшая в "устанавливается" или "возвращается", если воркер упал посреди задачи: в боте с ней ничего не сделать, а в админке статус только для чтения. Нужно действие в админке (сбросить в "ошибка") или проверка по времени.
- Периодическая проверка точек: панель отвечает, сертификат не истекает (короткий сертификат на ip продлевается каждые несколько дней).
Проверка на настоящих серверах
- Let's Encrypt на домен и на ip, продление по cron.
- Возврат серверов и Debian 12.
- Точка с маскировкой и настоящим доменом.
Продакшен
- Настройки:
SECRET_KEY,DEBUG,ALLOWED_HOSTSиз.env(сейчас вbase.pyнебезопасные значения для разработки). - Запуск на сервере: systemd юниты или контейнеры для сайта (gunicorn за nginx), воркера и
telegram_run(строго один экземпляр), логи. - Бэкапы Postgres.
FIELD_ENCRYPTION_KEYSхранить отдельно от бэкапов: без него база бесполезна.
Уборка
- Удалить
django-fernet-fields(не работает на Django 6.1, заменен своим полем) и обновитьrequirements.txt. - Удалить
src/db.sqlite3иextra/db-before-encryption-*.sqlite3: в бэкапе секреты открытым текстом. - Контейнер Postgres называется
shop-postgres: переименовать. Keyв админке (только для чтения).- Карточка точки показывает прокси вместе с логином и паролем: маскировать пароль.
- Пароль root при переустановке уходит в задачу dramatiq открытым текстом (сообщения RabbitMQ лежат на диске): шифровать, как прокси.