К контенту
habrforever
СКРЫТА #vless ≈2019 · ~10 мин чтения

Настройка AWS SSO с AWS Client VPN — актуализация 2026

автор оригинала: Амет Умеров (Amet13)

оригинал на Хабре habr.com/…/585648
снимок Wayback web.archive.org
статус на Хабре (ноябрь 2026) скрыта (403/451)
права © автор, переиздание в архивных целях с указанием источника

Настройка AWS SSO с AWS Client VPN

Архивное переиздание с актуализацией. Оригинал опубликован на Habr (≈2019), автор — Амет Умеров (Amet13). оригинал скрыт на Habr (HTTP 403/451), доступен только через Wayback Machine Снимок: Wayback Machine. Ниже — редакция ноября 2026: что работает сейчас, что изменилось и как правильно повторить рецепт сегодня. Полный текст оригинала — в конце, без купюр.

TL;DR — версия 2026

VLESS+REALITY (Xray) в 2026 — главный рекомендованный способ: маскировка под TLS к чужому крупному сайту, активное зондирование не проходит, домен и сертификат не нужны.

Оригинал попал в первую волну статей о VLESS+Reality — и с тех пор подход не просто выжил, а стал стандартом: фактическим стандартом антицензурного туннелирования в 2026 стал VLESS + REALITY (Xray-core): он маскируется под обычный HTTPS-трафик к крупному сайту и не требует собственного домена и сертификата; по данным РКН, за 2025 год в России заблокировано 258 VPN-сервисов, и почти все выжившие сервисы сидят именно на Xray. Что изменилось с публикации: пару-тройку версий Xray-ядра, новые клиенты, панели 3x-ui/Marzban с автонастройкой Reality, и — увы — статья о том, как это ставить, стала легальной мишенью (российские сайты и сами хабр-авторы начали массово удалять статьи о VPN (статьи отдают HTTP 451 «удалена по юридическим причинам») — именно поэтому появляются проекты-архивы вроде этого).

Статус оригинала

Почему REALITY до сих пор непробиваем

REALITY «крадёт» рукопожатие у настоящего TLS-сайта: ваш сервер, не имея сертификата, отдаёт клиенту handshake реального target-сайта (dest), а внутри договаривается о ключах. Со стороны (DPI, активный probe) это обычный HTTPS к популярному ресурсу. Ответить probe-ом «не тем» сервер не может — нечем отличить. В 2025–2026 у операторов блокировок остаётся один приём: резать «подозрительные» IP целиком. Лечится CDN-фронтом или сменой IP.

Минимальный сервер 2026

Актуальный Xray-core (ветка 2x/25.x) — ставится официальным скриптом; ключевые поля:

"inbounds": [{
  "listen": "0.0.0.0",
  "port": 443,
  "protocol": "vless",
  "settings": {
    "clients": [{ "id": "<uuid>", "flow": "xtls-rprx-vision" }],
    "decryption": "none"
  },
  "streamSettings": {
    "security": "reality",
    "realitySettings": {
      "dest": "www.microsoft.com:443",
      "serverNames": ["www.microsoft.com"],
      "shortId": "",
      "privateKey": "<x25519>"
    }
  }
}]

Выбор dest: крупный зарубежный сайт с TLS 1.3 + H2, НЕ ваш CDN, не российский, не «за Cloudflare» (цикл). Проверка: openssl s_client -connect dest:443 с сервера должна отдавать нужный SNI.

Иллюстрации из оригинала

Иллюстрация из оригинала статьи Структура аккаунтов https://console.aws.amazon.com/organizations/v2/home/accounts Схема соединения частных сетей Созданные нами группы Не забываем включать MFA для пользователя Список настроенных приложений Разделение доступа к сетям Портал самообслуживания

Что изменилось с ≈2019 года

  • uTLS-фingerprint клиента теперь критичен (chrome/firefox из коробки)
  • flow xtls-rprx-vision — норма; старые flow без vision уязвимы к детекту
  • XHTTP-транспорт добавился как альтернатива ws/gRPC за CDN
  • 3x-ui заменил большинство «костыльных» bash-панелей из статей 2023 года
  • iOS-клиенты требуют зарубежный Apple ID чаще, чем в 2024
  • в тексте оригинала: классический OpenVPN легко детектится DPI (используется в корпсредах, но не для обхода блокировок)

Чек-лист 2026

  • dest — живой крупный сайт с TLS1.3, доступный С ВАШЕГО сервера
  • shortId непустой
  • uTLS fingerprint клиента совпадает с типичным браузером
  • сервер не «светится» сканерами (закрыть 80/8080-заглушки)
  • fallback на реальный сайт, если probe придёт без правильного SNI

Вердикт

Оригинальная статья была верной — просто Xray с тех пор обновился, панели стали удобнее, а сама тема — юридически горячей. Конфиг выше — минимальная «сегодня-работает»-версия; вся методология оригинала (x25519-ключи, SNI-подбор, проверка blockcheck) неизменна.


ОРИГИНАЛ СТАТЬИ (без изменений)

В этом туториале я опишу простую и безопасную настройку мультиаккаунтной инфраструктуры, основанной на AWS, включая SSO и решение для VPN от Amazon.

Иллюстрация из оригинала статьи

**

Введение

Я разбил статью на несколько основных частей:

Во-первых, я покажу как создать инфраструктуру в AWS с нуля, с безопасной структурой аккаунтов, сетей, пирингов

Вторая часть этой статьи посвящена AWS SSO: пользователям, группам, MFA, и т.д.

Третья часть описывает процесс развертывания сервиса AWS VPN с помощью terraform и его настройки для ранее созданных сетей

Начнем!

Структура AWS-аккаунтов

Мультиаккаунтная структура для AWS имеет ряд преимуществ. Я не буду на них останавливаться, только покажу пример:

Структура аккаунтов

Структура аккаунтов

Аккаунт root является главным в организации (на него привязывается биллинг), все остальные аккаунты добавляются под руководство этого аккаунта.

Каждый аккаунт привязан к разному почтовому адресу, но обычно можно использовать почтовые алиасы для удобства управления с одного почтового ящика.

Давайте создадим аккаунт с именем root и добавим новые аккаунты в организацию. Логинимся в аккаунты, включаем MFA для пользователей и удостоверяемся, что наша структура аккаунтов верна и мы находимся в одной организации.

https://console.aws.amazon.com/organizations/v2/home/accounts

https://console.aws.amazon.com/organizations/v2/home/accounts

Этого достаточно на текущий момент, можем идти дальше.

Сетевая структура

В моем примере аккаунты dev, stage и prod изолированы друг от друга.

Аккаунт common используется для общих сервисов, таких как система CI/CD, хранилища данных (S3-бакеты), и т.д. Поэтому, в моем случае, для того чтобы разрешить сетевое соединение между common и dev/stage/prod аккаунтам, нам нужно создать VPC-пиринг (соединение между виртуальными сетями).

Давайте сделаем это с помощью terraform для аккаунтов common и dev.

Для начала создадим VPC:

data "aws_availability_zones" "available" {}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.7.0"

  name = "${var.env}-vpc"
  cidr = var.vpc_cidr
  azs  = data.aws_availability_zones.available.names

  private_subnets = var.vpc_private_subnets
  public_subnets  = var.vpc_public_subnets

  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true
}

А также файл с входными параметрами terraform.tfvars:

region = "eu-central-1"
env    = "common"

# https://www.davidc.net/sites/default/subnets/subnets.html
# каждая подсеть ~8190 хостов
# 10.0.192.0/19 зарезервирована под VPN-клиентов
vpc_cidr            = "10.0.0.0/16"
vpc_private_subnets = ["10.0.0.0/19", "10.0.32.0/19", "10.0.64.0/19"]
vpc_public_subnets  = ["10.0.96.0/19", "10.0.128.0/19", "10.0.160.0/19"]

Если вы хотите применить то же самое для аккаунта dev, просто скопируйте и вставьте файл и измените значения сетей и подсетей, к примеру на 10.1.0.0/16 и т.д. Помните, что подсети должны быть разными, чтобы избежать их пересечения после пиринга.

После этого мы имеем новые виртуальные сети:

common-vpc в аккаунте common с CIDR: 10.0.0.0/16, тремя публичными и тремя частными подсетями

dev-vpc в аккаунте dev с CIDR: 10.1.0.0/16, тремя публичными и тремя частными подсетями

Давайте соединим их с помощью пиринга:

module "common_dev_peering" {
  source  = "grem11n/vpc-peering/aws"
  version = "4.0.1"

  providers = {
    aws.this = aws
    aws.peer = aws.dev
  }

  this_vpc_id = module.vpc.vpc_id
  peer_vpc_id = var.vpc_dev_accepter_id

  auto_accept_peering = true
}

Не забываем указать vpc_dev_accepter_id в файле terraform.tfvars:

...
vpc_dev_accepter_id = "vpc-12345678"

Ту же самую процедуру можно проделать, к примеру, для аккаунтов stage и prod.

Схема соединения частных сетей

Схема соединения частных сетей

Для тестирования сетевого соединения, достаточно в обоих сетях создать виртуалку и попробовать проверить каким-нибудь инструментом типа ping или traceroute.

Настраиваем SSO

Заходим в AWS в аккаунт root, находим сервис AWS SSO и создаем три группы:

vpn-dev

vpn-stage

vpn-prod

Идея состоит в том, чтобы разделять доступ к различным сетям для разных групп (RBAC) с VPN.

Созданные нами группы

Созданные нами группы

Также создадим пользователя, пусть будет amet-umerov, после добавления его во все ранее созданные группы, мы хотим чтобы пользователь получил доступ во все сети с помощью VPN.

Не забываем включать MFA для пользователя

Не забываем включать MFA для пользователя

Итак, мы подготовили группы и пользователя, самое время создать новое SSO-приложение под названием VPN:

Add a custom SAML 2.0 application

Загружаем AWS SSO SAML metadata file, он нам пригодится позже

Set session duration: 12 hours

Application ACS URL: http://127.0.0.1:35001

Application SAML audience: urn:amazon:webservices:clientvpn

Также создадим еще одно SSO-приложение с именем VPN Self-Service с такими же настройками, кроме:

Application ACS URL: https://self-service.clientvpn.amazonaws.com/api/auth/sso/saml

Добавим маппинг атрибутов для этих приложений:

Subject — user:subject — emailAddress

NameID — ${user:email} — unspecified

FirstName — ${user:name} — unspecified

LastName — ${user:familyName} — unspecified

memberOf — ${user:groups} — unspecified

И привяжем к ним все три группы (vpn-dev, vpn-stage, vpn-prod).

Список настроенных приложений

Список настроенных приложений

Вот как оно работает:

Разделение доступа к сетям

Разделение доступа к сетям

Настраиваем VPN

Нашим последним шагом является создание клиентской точки доступа для VPN в аккаунте common. Но перед этим необходимо подготовить некоторые сертификаты и ключи.

Генерируем сертификаты для сервера и клиента:

$ git clone https://github.com/OpenVPN/easy-rsa.git
$ cd easy-rsa/easyrsa3

$ ./easyrsa init-pki
$ ./easyrsa build-ca nopass
...
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:vpn.domain.org

$ ./easyrsa build-server-full vpn-aws-server nopass
$ ./easyrsa build-client-full vpn-aws-client nopass

Копируем сгенерированные сертификаты в безопасное место и импортируем сертификат для сервера в AWS ACM:

$ mkdir ~/.vpn-assets/
$ cp pki/ca.crt ~/.vpn-assets/
$ cp pki/private/ca.key ~/.vpn-assets/
$ cp pki/issued/vpn-aws-*.crt ~/.vpn-assets/
$ cp pki/private/vpn-aws-*.key ~/.vpn-assets/

$ aws --profile common \
    --region eu-central-1 \
    acm import-certificate \
    --certificate fileb://$HOME/.vpn-assets/vpn-aws-server.crt \
    --private-key fileb://$HOME/.vpn-assets/vpn-aws-server.key \
    --certificate-chain fileb://$HOME/.vpn-assets/ca.crt

# На всякий случай скопируем это все в S3-бакет
$ aws --profile=common s3 cp --recursive ~/.vpn-assets/ s3://my-bucket/vpn/

Создаем новое VPN-соединение с помощью terraform:

# SAML провайдеры из метадата-файлов, загруженных нами ранее
resource "aws_iam_saml_provider" "vpn" {
  name                   = "vpn"
  saml_metadata_document = file("${path.module}/files/VPN_ins-mymetadata-file.xml")
}

resource "aws_iam_saml_provider" "vpn_self_service" {
  name                   = "vpn-self-service"
  saml_metadata_document = file("${path.module}/files/VPN Self-Service_ins-mymetadata-file.xml")
}

# Получаем импортированный нами сертификат и subnet_id
data "aws_acm_certificate" "vpn_aws_server_cert" {
  domain   = "vpn-aws-server"
  statuses = ["ISSUED"]
}

data "aws_subnet" "vpn_subnet_id" {
  filter {
    name   = "tag:Name"
    values = ["${var.env}-vpc-private"]
  }
  availability_zone_id = "euc1-az1"
}

# Подготовка CloudWatch для логирования VPN
resource "aws_cloudwatch_log_group" "client_vpn" {
  name = "vpn_endpoint_cloudwatch_log_group"
}

resource "aws_cloudwatch_log_stream" "client_vpn" {
  name           = "vpn_endpoint_cloudwatch_log_stream"
  log_group_name = aws_cloudwatch_log_group.client_vpn.name
}

# Точка доступа VPN
resource "aws_ec2_client_vpn_endpoint" "vpn" {
  description            = "VPN client for AWS"
  server_certificate_arn = data.aws_acm_certificate.vpn_aws_server_cert.arn

  client_cidr_block = var.vpn_client_cidr_block
  dns_servers       = var.vpn_dns_servers

  split_tunnel        = "true"
  self_service_portal = "enabled"
  transport_protocol  = "udp"

  authentication_options {
    type                           = "federated-authentication"
    saml_provider_arn              = aws_iam_saml_provider.vpn.arn
    self_service_saml_provider_arn = aws_iam_saml_provider.vpn_self_service.arn
  }

  connection_log_options {
    enabled               = true
    cloudwatch_log_group  = aws_cloudwatch_log_group.client_vpn.name
    cloudwatch_log_stream = aws_cloudwatch_log_stream.client_vpn.name
  }
}

# Фаерволы для VPN
resource "aws_security_group" "vpn_main" {
  name        = "vpn_main"
  description = "Allow VPN all traffic"
  vpc_id      = module.vpc.vpc_id

  egress {
    description = "Allow all traffic for VPN"
    cidr_blocks = ["0.0.0.0/0"]
    from_port   = "0"
    protocol    = "-1"
    self        = "false"
    to_port     = "0"
  }

  ingress {
    description = "Allow all traffic for VPN"
    cidr_blocks = ["0.0.0.0/0"]
    from_port   = "0"
    protocol    = "-1"
    self        = "false"
    to_port     = "0"
  }
}

# Ассоциируем VPN-точку с подсетью
resource "aws_ec2_client_vpn_network_association" "vpn" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  subnet_id              = data.aws_subnet.vpn_subnet_id.id
  security_groups        = [aws_security_group.vpn_main.id]
}

# Идентификаторы (access_group_id) можно найти тут (в аккаунте root):
# https://eu-central-1.console.aws.amazon.com/singlesignon/home?region=eu-central-1#/groups
resource "aws_ec2_client_vpn_authorization_rule" "vpn_dev" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  target_network_cidr    = "10.10.0.0/16"
  access_group_id        = "1234-5678-..."
  description            = "vpn-dev"
}

# Разрешаем доступ в сеть common для группы vpn-dev
resource "aws_ec2_client_vpn_authorization_rule" "vpn_common" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  target_network_cidr    = "10.0.0.0/16"
  access_group_id        = "1234-5678-..."
  description            = "vpn-common"
}

# Маршруты
resource "aws_ec2_client_vpn_route" "vpn_to_dev" {
  client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id
  destination_cidr_block = "10.10.0.0/16"
  target_vpc_subnet_id   = aws_ec2_client_vpn_network_association.vpn.subnet_id
}

И модифицируем файл terraform.tfvars:

...
vpn_client_cidr_block = "10.0.192.0/19"
vpn_dns_servers       = ["1.1.1.1", "8.8.8.8"]

После применения данной конфигурации мы получаем клиентскую точку доступа к VPN с контролем доступа на уровне ролей (групп).

Тестируем.

Заходим на портал самообслуживания, выглядит ссылка примерно так: https://self-service.clientvpn.amazonaws.com/endpoints/cvpn-endpoint-1234567890

Загружаем VPN-клиент для своей ОС, а также конфигурацию (файл в формате .ovpn)

Портал самообслуживания

Портал самообслуживания

Запускаем VPN-клиент, создаем новый профиль и импортируем конфигурацию VPN

Удостоверяемся, что мы подключены к VPN

Проверяем соединение с помощью traceroute/ping и все тех же виртуальных машин

После всех проделанных ранее манипуляций у нас есть доступ к сетям аккаунтов common и dev с помощью VPN .

Данная конфигурация может быть масштабирована для других аккаунтов с иными правилами доступа и маршрутами в нашем terraform-коде.

Полезные ссылки

https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html

https://smartshift.com/guide-setting-up-an-aws-vpc-client-vpn/

https://aws.amazon.com/blogs/security/authenticate-aws-client-vpn-users-with-aws-single-sign-on/

https://medium.com/trackit/how-to-create-an-aws-client-vpn-endpoint-using-aws-sso-and-terraform-6902dff5b71b

по теме #vless