Rameta

Для 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-AgentRameta/1.0.0/ios/42Rameta/<версия>/ios/<сборка>. Для правил Remnawave: регулярное выражение ^Rameta/.
X-HWID5F0C2A4E-…Постоянный идентификатор устройства (хранится в Keychain). По нему Remnawave считает устройства — HWID device limit работает как с Happ.
X-Device-OSiOSПлатформа (в панели Remnawave видна в списке устройств).
X-Ver-OS18.1Версия iOS.
X-Device-ModeliPhone16,2Модель устройства.
X-Device-LocaleruЯзык интерфейса — можно отдавать локализованные названия и объявления.
X-App-Version1.0.0Версия Rameta.
X-Age-Public-Keyage1pq1…Персональный открытый ключ age этого устройства (гибридный постквантовый, ML-KEM-768 + X25519). Можно шифровать тело ответа именно для этого устройства.
Remnawave читает 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-userinfoupload=…; 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 — выключить).
provideridID провайдера в реестре Rameta (регистрация) — приложение подтянет логотип, цвет, объявление и профиль маршрутизации.
hide-settings1 — скрыть от пользователя настройки серверов подписки.
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. Форматы подписки

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/"
    ]
  }
}

Кнопка на странице подписки

В настройках страницы подписки 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.

Честно: секретный ключ Rameta встроен в приложение. Шифрование скрывает содержимое подписки от случайного просмотра (браузер, «открыть ссылку», пересылка, другие клиенты), но не от того, кто разберёт приложение.
СсылкаДействие
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 · RemoteDNSIPDNS через VPN: DoH или DoU (UDP), адрес DoH и IP сервера.
DomesticDNSType · DomesticDNSDomain · DomesticDNSIPDNS для прямых соединений.
Geoipurl · GeositeurlОткуда скачать geoip.dat / geosite.dat. Рекомендуем обрезанные файлы Rameta (см. ниже).
LastUpdatedUnix-время версии профиля; новое значение — повод обновить профиль на устройстве.
DnsHostsСтатические записи {"домен": "IP"}.
DirectSites · DirectIpНапрямую.
ProxySites · ProxyIpЧерез VPN.
BlockSites · BlockIpБлокировать.
DomainStrategyAsIs · 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Открыть
Весь трафик через VPN
all-proxy
Весь трафик идёт через VPN, напрямую — только локальная сеть (роутер, принтер, AirPlay).—Открыть
Только заблокированное через VPN
blocked-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Открыть
Только нейросети через VPN
ai-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/|'
Crypt-ссылки скрывают адрес подписки от случайного просмотра (скриншоты, пересылка, превью ссылок), но не от реверс-инжиниринга: ключ для расшифровки есть в приложении. Это не замена нормальной защите подписки (короткоживущие токены, HWID-лимит).

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 — очищает.