Для VPN-провайдеров
Переход с Happ на Rameta
Rameta понимает подписки Happ «как есть»: те же заголовки запроса и ответа, те же форматы тела и ссылки. HWID-лимит Remnawave работает без изменений. Ниже — всё, что нужно, чтобы пользователи могли просто нажать «Открыть в Rameta».
1. Быстрый старт
0 минут
Ничего не делайте: подписка Remnawave уже работает в Rameta (правило «Fallback Base64» отдаёт ссылки).
2 минуты
Добавьте правило ответа Rameta → пользователи получат полный Xray JSON со всеми настройками транспорта. →
Кнопка
Добавьте на страницу подписки кнопку со ссылкой rameta://add/{{SUBSCRIPTION_LINK}}.
Брендинг
Зарегистрируйтесь в реестре и отдавайте заголовок providerid — логотип, цвет и профиль маршрутизации в приложении. →
2. Что отправляет Rameta
При каждом обновлении подписки Rameta делает обычный GET с заголовками:
| Заголовок | Пример | Назначение |
|---|---|---|
User-Agent | Rameta/1.0.0/ios/42 | Rameta/<версия>/ios/<сборка>. Для правил Remnawave: регулярное выражение ^Rameta/. |
X-HWID | 5F0C2A4E-… | Постоянный идентификатор устройства (хранится в Keychain). По нему Remnawave считает устройства — HWID device limit работает как с Happ. |
X-Device-OS | iOS | Платформа (в панели Remnawave видна в списке устройств). |
X-Ver-OS | 18.1 | Версия iOS. |
X-Device-Model | iPhone16,2 | Модель устройства. |
X-Device-Locale | ru | Язык интерфейса — можно отдавать локализованные названия и объявления. |
X-App-Version | 1.0.0 | Версия Rameta. |
X-Age-Public-Key | age1pq1… | Персональный открытый ключ age этого устройства (гибридный постквантовый, ML-KEM-768 + X25519). Можно шифровать тело ответа именно для этого устройства. |
x-hwid, x-device-os, x-ver-os и x-device-model — лимит устройств (HWID Device Limit) считает устройства Rameta точно так же, как Happ. Если лимит исчерпан, панель отвечает x-hwid-max-devices-reached: true и announce — Rameta покажет это пользователю.3. Заголовки ответа
Набор и значения — как у Happ. В Remnawave они задаются в «Настройки подписки → Дополнительные заголовки ответа» и одинаково приходят и Happ, и Rameta.
| Заголовок | Смысл |
|---|---|
profile-title | Название подписки. Обычный текст или base64:… (UTF-8). |
subscription-userinfo | upload=…; download=…; total=…; expire=<unix> — трафик и срок. |
profile-update-interval | Период автообновления подписки, часы. |
support-url | Ссылка на поддержку (https://, tg://, mailto:). |
profile-web-page-url | Страница подписки/личного кабинета. |
announce | Объявление до 200 символов; можно base64:…. |
routing | Ссылка на профиль маршрутизации: happ://routing/… или rameta://routing/… (add — предложить, onadd — сразу включить, off — выключить). |
providerid | ID провайдера в реестре Rameta (регистрация) — приложение подтянет логотип, цвет, объявление и профиль маршрутизации. |
hide-settings | 1 — скрыть от пользователя настройки серверов подписки. |
sub-info-color · sub-info-text · sub-info-button-text · sub-info-button-link | Информационная плашка подписки: цвет (red/blue/green), текст, кнопка и её ссылка. |
sub-expire · sub-expire-button-link | Предупреждать об окончании подписки и куда ведёт кнопка «Продлить». |
new-url | Навсегда заменить адрес подписки на новый. |
new-domain | Заменить только домен в адресе подписки. |
fallback-url | Запасной адрес, если основной недоступен. |
subscription-autoconnect · subscription-autoconnect-type | Автоподключение после обновления и способ выбора сервера. |
subscription-auto-update-enable | Разрешить/запретить автообновление. |
ping-type · check-url-via-proxy | Способ проверки задержки и URL для проверки через прокси. |
fragmentation-* · noises-* · mux-* | Фрагментация TLS ClientHello, шумы (noises) и мультиплексирование для ссылок — те же ключи и значения, что у Happ. |
x-hwid-max-devices-reached · x-hwid-not-supported · x-hwid-limit | Отдаёт Remnawave при превышении лимита устройств — Rameta покажет понятное сообщение и announce. |
Те же ключи можно передать в теле — строками #ключ: значение в начале, и во фрагменте URL подписки:
https://sub.example.com/abcdef#Мой VPN?profile-update-interval=6&support-url=https://t.me/myvpn_support
Если ключ задан в нескольких местах, побеждает строка в теле, затем заголовок ответа, затем фрагмент URL (как в Happ).
4. Форматы подписки
- Ссылки — base64 (обычный или URL-safe, с паддингом и без) или открытый текст, по одной на строку:
vless://,vmess://,trojan://,ss://,socks://,hysteria2:///hy2://. - Xray JSON — массив полных конфигов (у каждого
remarks) или один конфиг. Используются outbounds, routing, dns, балансировщики; inbounds Rameta подставляет свои. - Зашифрованное тело age — ASCII-armor (
-----BEGIN AGE ENCRYPTED FILE-----) или двоичное. После расшифровки — любой формат выше. → - Описания серверов Remnawave (serverDescription): в JSON —
meta.serverDescription, в ссылках — суффикс?serverDescription=<base64>после названия.
vless://uuid@de1.example.com:443?type=tcp&security=reality&sni=www.microsoft.com&pbk=…&sid=…&fp=chrome&flow=xtls-rprx-vision#🇩🇪 Germany
trojan://password@nl.example.com:443?security=tls&sni=nl.example.com#🇳🇱 Netherlands
ss://YWVzLTEyOC1nY206cGFzcw@fi.example.com:8388#🇫🇮 Finland
hy2://auth@jp.example.com:443?sni=jp.example.com#🇯🇵 Japan
Пример тела с метаданными:
#profile-title: base64:0JzQvtC5IFZQTg==
#profile-update-interval: 6
#support-url: https://t.me/myvpn_support
#announce: Новые серверы в Казахстане!
vless://…#🇩🇪 Germany
vless://…#🇳🇱 Netherlands
5. Remnawave
Правило ответа (Response Rule) для Xray JSON
Панель → Subscription → Response Rules. Добавьте правило после «Browser Subscription» и перед «Fallback Base64» (правила проверяются сверху вниз, срабатывает первое совпавшее):
{
"name": "Rameta",
"enabled": true,
"operator": "AND",
"conditions": [
{
"headerName": "user-agent",
"operator": "REGEX",
"value": "^Rameta/",
"caseSensitive": true
}
],
"responseType": "XRAY_JSON",
"responseModifications": {
"additionalExtendedClientsRegex": [
"^Rameta/"
]
}
}
XRAY_JSON— Rameta получит полный Xray-конфиг каждого хоста: XHTTP, Reality, фрагментация, mux и шаблоны хостов сохраняются.additionalExtendedClientsRegex— Remnawave считает Rameta «расширенным клиентом», как Happ и INCY, и передаёт описания серверов (serverDescription).
Кнопка на странице подписки
В настройках страницы подписки Remnawave (Subscription Page) добавьте для iOS приложение Rameta с кнопкой добавления подписки:
rameta://add/{{SUBSCRIPTION_LINK}}
Ссылка на App Store появится после публикации — до этого используйте TestFlight.
6. Шифрование подписки
Remnawave умеет шифровать тело ответа age. Добавьте в правило Rameta поле encryption с открытым ключом Rameta (метод age1, X25519):
{
"additionalExtendedClientsRegex": [
"^Rameta/"
],
"encryption": {
"method": "age1",
"key": "age1zaymjnnxuh8xsmrw9cjajm4gqnjsgtxf6e8v54zx3rpejqsluyls0eymfz"
}
}
Открытый ключ Rameta: age1zaymjnnxuh8xsmrw9cjajm4gqnjsgtxf6e8v54zx3rpejqsluyls0eymfz (всегда актуален в /v1/app/config → agePublicKey).
Свой бэкенд может шифровать и персонально для устройства — ключом из заголовка X-Age-Public-Key (age1pq1…, метод age1pq1). В Remnawave ключ в правиле статический, поэтому там используйте age1 с ключом Rameta.
7. Deep links
| Ссылка | Действие |
|---|---|
rameta://add/<url> | Добавить подписку. URL можно передавать как есть или URL-кодированным. |
rameta://crypt/<payload> | Добавить подписку из зашифрованной ссылки (ниже). |
rameta://routing/add/<base64> | Предложить профиль маршрутизации (JSON в base64). |
rameta://routing/onadd/<base64> | Добавить профиль и сразу включить. |
rameta://routing/off | Выключить профиль маршрутизации. |
rameta://connect · rameta://disconnect · rameta://toggle | Подключить, отключить, переключить VPN (удобно для Команд iOS). |
happ://add/… · happ://routing/… | Ссылки Happ, вставленные из буфера обмена или QR-кода, Rameta тоже принимает. |
8. Профили маршрутизации
Формат совместим с Happ: JSON ниже, закодированный в base64, передаётся ссылкой rameta://routing/add/… (или onadd), заголовком routing или через карточку провайдера.
| Ключ | Смысл |
|---|---|
Name | Название профиля. |
GlobalProxy | "true" — всё, что не попало в списки, идёт через VPN; "false" — напрямую. |
RemoteDNSType · RemoteDNSDomain · RemoteDNSIP | DNS через VPN: DoH или DoU (UDP), адрес DoH и IP сервера. |
DomesticDNSType · DomesticDNSDomain · DomesticDNSIP | DNS для прямых соединений. |
Geoipurl · Geositeurl | Откуда скачать geoip.dat / geosite.dat. Рекомендуем обрезанные файлы Rameta (см. ниже). |
LastUpdated | Unix-время версии профиля; новое значение — повод обновить профиль на устройстве. |
DnsHosts | Статические записи {"домен": "IP"}. |
DirectSites · DirectIp | Напрямую. |
ProxySites · ProxyIp | Через VPN. |
BlockSites · BlockIp | Блокировать. |
DomainStrategy | AsIs · IPIfNonMatch · IPOnDemand |
FakeDNS | "true"/"false" — FakeDNS для доменных правил. |
{
"Name": "Мой VPN — РФ напрямую",
"GlobalProxy": "true",
"RemoteDNSType": "DoH",
"RemoteDNSDomain": "https://cloudflare-dns.com/dns-query",
"RemoteDNSIP": "1.1.1.1",
"DomesticDNSType": "DoU",
"DomesticDNSDomain": "",
"DomesticDNSIP": "77.88.8.8",
"Geoipurl": "https://vpn.rameta.net/geo/geoip.dat?tags=ru,private",
"Geositeurl": "https://vpn.rameta.net/geo/geosite.dat?tags=category-ru,private",
"LastUpdated": "1761609600",
"DnsHosts": {},
"DirectSites": [
"geosite:category-ru",
"geosite:private",
"domain:ru",
"domain:xn--p1ai"
],
"DirectIp": [
"geoip:ru",
"geoip:private"
],
"ProxySites": [
"domain:youtube.com",
"keyword:openai"
],
"ProxyIp": [
"91.108.4.0/22"
],
"BlockSites": [
"geosite:category-ads"
],
"BlockIp": [],
"DomainStrategy": "IPIfNonMatch",
"FakeDNS": "false"
}
Правила доменов — синтаксис Xray: domain: (домен и поддомены), full: (точное имя), keyword:, regexp:, geosite:. IP — адрес, CIDR или geoip:. Порядок применения: блокировка → VPN → напрямую → по умолчанию (GlobalProxy). Дополнительно Rameta понимает ключ RouteOrder (по умолчанию block-proxy-direct).
# сделать ссылку из файла профиля
echo "rameta://routing/onadd/$(base64 -w0 profile.json)"
Готовые профили
Те же профили отдаёт /v1/presets вместе с 50+ сервисами и доменными зонами.
| Профиль | Описание | Геоданные | |
|---|---|---|---|
Российские сайты напрямуюru-direct | Всё через VPN, кроме российских сайтов и IP: банки, Госуслуги, маркетплейсы и сервисы, которые не открываются из-за рубежа, работают напрямую. | geosite:category-ru, geosite:private, geosite:ru-available-only-inside, geoip:private, geoip:ru | Открыть |
Российские сайты напрямую + без рекламыru-direct-noads | Как «Российские сайты напрямую», плюс блокировка основных рекламных сетей и трекеров (лёгкий список geosite:category-ads, ~800 доменов — почти не расходует память). | geosite:category-ads, geosite:category-ru, geosite:private, geosite:ru-available-only-inside, geoip:private, geoip:ru | Открыть |
Весь трафик через VPNall-proxy | Весь трафик идёт через VPN, напрямую — только локальная сеть (роутер, принтер, AirPlay). | — | Открыть |
Только заблокированное через VPNblocked-only | Через VPN идут только сайты и IP из реестров блокировок РФ (geosite:ru-blocked, geoip:ru-blocked-community) и нейросети, недоступные из России. Остальное — напрямую. | geosite:category-ai-!cn, geosite:ru-blocked, geoip:ru-blocked-community | Открыть |
Весь трафик через VPN + без рекламыads-block | Весь трафик через VPN, реклама и трекеры блокируются полным списком geosite:category-ads-all (~150 тыс. доменов). Внимание: список добавляет ~20 МБ памяти расширению VPN, а лимит iOS — 50 МБ. | geosite:category-ads-all | Открыть |
Только нейросети через VPNai-only | Через VPN — только зарубежные нейросети (ChatGPT, Claude, Gemini, Perplexity, Grok, Copilot и др., geosite:category-ai-!cn). Всё остальное напрямую. | geosite:category-ai-!cn | Открыть |
9. Обрезанные геофайлы
Расширению VPN на iOS доступно ~50 МБ памяти, а полный geosite.dat весит ~70 МБ. Поэтому Rameta (и ваш профиль) берёт только нужные записи:
https://vpn.rameta.net/geo/geosite.dat?tags=category-ru,private,category-ads
https://vpn.rameta.net/geo/geoip.dat?tags=ru,private
Источник — runetfreedom/russia-v2ray-rules-dat (обновляется ежедневно). Полезные теги: category-ru, ru-blocked, ru-available-only-inside, category-ads-all, category-gov-ru, category-ai-!cn; geoip: ru, private, ru-blocked, ru-blocked-community, telegram. Полный список — /geo/tags.
10. Реестр провайдеров
Зарегистрируйтесь, чтобы Rameta показывала ваш логотип, цвет, объявление и предлагала ваш профиль маршрутизации. Затем отдавайте в подписке заголовок providerid: <ваш id>. Отметку «проверен» ставим вручную после связи с вами.
11. Генератор crypt-ссылок
Превращает адрес подписки в ссылку rameta://crypt/…: payload — двоичный шифротекст age на открытый ключ Rameta в base64url без =. Адрес не сохраняется и не пишется в логи.
То же самое через API или локально, без нашего сервера:
curl -s https://vpn.rameta.net/v1/crypt -H 'Content-Type: application/json' \
-d '{"url":"https://sub.example.com/abcdef"}'
# → {"link":"rameta://crypt/YWdlLWVuY3J5cHRpb24ub3JnL3Yx…","armored":"-----BEGIN AGE ENCRYPTED FILE-----…"}
# Открытый ключ Rameta: https://vpn.rameta.net/v1/app/config → agePublicKey
URL='https://sub.example.com/abcdef'
printf '%s' "$URL" | age -r age1zaymjnnxuh8xsmrw9cjajm4gqnjsgtxf6e8v54zx3rpejqsluyls0eymfz | basenc --base64url | tr -d '=\n' | sed 's|^|rameta://crypt/|'
12. API
База: https://vpn.rameta.net. Ответы — JSON; ошибки: {"error":"…","message":"…"}.
| Метод | Описание |
|---|---|
GET /v1/app/config | Версии, URL проверки, база геофайлов, версия пресетов, открытый ключ age. |
GET /v1/presets | Сервисы, доменные зоны и готовые профили (ETag). |
GET /geo/tags | Все доступные теги geosite и geoip. |
GET /geo/geosite.dat?tags=… | Обрезанный geosite.dat (ETag, Last-Modified). |
GET /geo/geoip.dat?tags=… | Обрезанный geoip.dat. |
POST /v1/crypt | {"url"} → {"link","armored"}; 30 запросов/мин с IP. |
POST /v1/providers | Регистрация → {"id","adminToken"}. |
GET /v1/providers/{id} | Публичная карточка провайдера. |
PUT /v1/providers/{id} | Изменение (Authorization: Bearer <adminToken>). |
GET /healthz | {"ok":true} |
Пример изменения карточки провайдера:
curl -X PUT https://vpn.rameta.net/v1/providers/AbC123xY \
-H 'Authorization: Bearer <adminToken>' -H 'Content-Type: application/json' \
-d '{"logoUrl":"https://example.com/logo.png","color":"#7C3AED","announce":"Скидка 20% до пятницы",
"routingProfile":{"id":"my-ru","name":"РФ напрямую","globalProxy":true,
"direct":["geosite:category-ru","domain:ru"],"directIp":["geoip:ru","geoip:private"],
"proxy":[],"proxyIp":[],"block":[],"blockIp":[],"domainStrategy":"IPIfNonMatch"}}'
Поля PUT: name, website, supportUrl, logoUrl (https), color (#RRGGBB), announce (≤200), routingProfile (объект как в /v1/presets или null), contact, subscriptionDomains. Отсутствующие поля не меняются, null — очищает.