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

Кто-то скажет, что реклама помогает поддерживать бесплатные проекты, и, возможно, когда-то это так и было, но сейчас реклама — сбор информации о тебе, твоих привычках, поисковых запросах и прочем: достаточно посмотреть трафик, который генерирует твой телефон во время обычного использования. Я давно укомплектовал свой десктопный браузер плагинами типа NoScript и uBlock, почти позабыл о рекламе, но телефон о ней постоянно напоминал.

Последней каплей стало то, что я решил изучить трафик приложения Xiaomi MiFit и обнаружил в ответах серверов ссылки на странные APK-файлы (описывать их я не стану, это выходит за рамки статьи. Желающие могут самостоятельно перехватить злополучные запросы, тем более что они идут по обычному HTTP).

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

 

Подготовительный этап

Предполагается, что у тебя уже есть сервер с публичным IP-адресом, где установлен Linux: в моем случае это был Ubuntu 16.10. Представленные примеры будут работать и на других дистрибутивах Linux, с той разницей, что нужно будет адаптировать установку пакетов под твой пакетный менеджер.

 

Что делать со старой версией Ubuntu

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

Попытка обновиться
Попытка обновиться

Google ненавязчиво подсказал мне, что репозитории были перемещены на поддомен old-releases. Исправляем и обновляемся:

$ sed -i 's|us.archive|old-releases|' /etc/apt/sources.list
$ sed -i 's|//security|//old-releases|' /etc/apt/sources.list
$ apt update && apt upgrade -y && reboot

 

Установка OpenVPN

Есть два пути:

  • простой — с использованием уже готового образа Docker (для тех, кто не хочет заморачиваться и вникать в конфиги OpenVPN);
  • сложный — с ручной установкой и конфигурированием OpenVPN.

Мы рассмотрим оба варианта и начнем с простого.

Docker-образ с OpenVPN

Скачиваем образ.

$ docker pull kylemanna/openvpn

На гитхабе автора лежит достаточно полная документация в виде файла README. Им мы и воспользуемся. Для начала нам нужно создать файл конфигурации для сервера VPN.

$ docker run -v /etc/openvpn:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_genconfig -u udp://192.168.0.183

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

$ cat /etc/openvpn/openvpn.conf

server 192.168.255.0 255.255.255.0
verb 3
key /etc/openvpn/pki/private/192.168.0.183.key
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/192.168.0.183.crt
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key
key-direction 0
keepalive 10 60
persist-key
persist-tun

proto udp
## Rely on Docker to do port mapping, internally always 1194
port 1194
dev tun0
status /tmp/openvpn-status.log

user nobody
group nogroup
comp-lzo no

#### Route Configurations Below
route 192.168.254.0 255.255.255.0

#### Push Configurations Below
push "block-outside-dns"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
push "comp-lzo no"

Если необходимо сменить порт, то меняем его в этом файле, а также в /etc/openvpn/ovpn_env.sh. Переходим к генерации сертификатов для удостоверяющего центра.

$ docker run -v /etc/openvpn:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_initpki

Будет запрошен пароль для создания ключа удостоверяющего центра.


Теперь генерируется сертификат и ключ сервера, ключи протокола Диффи — Хеллмана, а также подпись HMAC для проверки целостности TLS.


После этого мы должны добавить пользователей. Делается это так же просто.

$ docker run -v /etc/openvpn:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn easyrsa build-client-full CLIENTNAME nopass

В качестве CLIENTNAME я буду использовать имя хоста клиента (позже ты узнаешь, для чего это нужно). Создаем сертификат для пользователя user-pc, нас сразу же попросят указать пароль от сертификата удостоверяющего центра. Сертификат готов, но нам-то нужно получить файл конфигурации для OpenVPN. Выполняем следующую команду.

$ docker run -v /etc/openvpn:/etc/openvpn --log-driver=none --rm -it kylemanna/openvpn ovpn_getclient user-pc > /root/user-pc.ovpn

Смотрим на результат.

$ cat /root/user-pc.ovpn

client
nobind
dev tun
remote-cert-tls server

remote 192.168.0.183 1194 udp

<key>
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
</key>
<cert>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</cert>
<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>
key-direction 1
<tls-auth>
#
## 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
...
-----END OpenVPN Static key V1-----
</tls-auth>

redirect-gateway def1

Ключи в формате Base64 намеренно убраны из вывода, чтобы уменьшить его содержимое. На этом все: запускаем OpenVPN в режиме демона.

$ docker run -v /etc/openvpn:/etc/openvpn -d -p 1194:1194/udp --cap-add=NET_ADMIN kylemanna/openvpn

На стороне клиента пробуем подключиться.

$ sudo openvpn --config user-pc.ovpn

Если все прошло успешно, то в конце лога ты увидишь надпись Initialization Sequence Completed, а в списке интерфейсов появится tun0 с IP-адресом из подсети 192.168.255.0/24. Для наших целей этого вполне хватит, нужно только добавить команду на запуск контейнера в автозагрузку и переходить к части с настройкой DNS.

Ручная настройка OpenVPN

Второй вариант — это настроить OpenVPN полностью вручную. Поехали по шагам.

1. Устанавливаем OpenVPN.

$ sudo apt install -y openvpn

2. Скачиваем easy-rsa.

$ sudo git clone https://github.com/OpenVPN/easy-rsa.git /etc/openvpn/easy-rsa

3. Выставляем переменные для easy-rsa в файле /etc/openvpn/easy-rsa/easyrsa3/vars, остальное по желанию. Файл /etc/openvpn/easy-rsa/easyrsa3/vars.example содержит полный перечень доступных переменных, но нам хватит и этого.

set_var EASYRSA_KEY_SIZE    2048
set_var EASYRSA_CA_EXPIRE   3650
set_var EASYRSA_CERT_EXPIRE 3650

4. Инициализация PKI.

$ cd /etc/openvpn/easy-rsa/easyrsa3 && ./easyrsa init-pki

5. Создание центра сертификации. Указываем пароль и Common Name.

$ ./easyrsa build-ca

6. Создание ключей сервера. Везде используем имя хоста как Common Name для создания сертификата.

$ ./easyrsa build-server-full vpnserver nopass

7. Создание ключей клиента.

$ ./easyrsa build-client-full user-pc nopass

8. По желанию: если нужно сгенерировать ключи Диффи — Хеллмана и TLS.

$ ./easyrsa gen-dh
$ openvpn --genkey --secret /etc/openvpn/easy-rsa/easyrsa3/pki/ta.key

На этом создание сертификатов завершено, переходим к написанию конфига для VPN-сервера /etc/openvpn/server.conf:

## Адрес твоего сервера
local 192.168.0.183

## Какой TCP/UDP-порт должен слушать OpenVPN
port 3333

## Режим работы
mode server

## Используемый протокол TCP/UDP
proto udp

## Тип интерфейса, tun (OSI Layer 3) или tap (OSI Layer 2)
dev tun

## Пути к файлам сертификатов
ca /etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt
cert /etc/openvpn/easy-rsa/easyrsa3/pki/issued/vpnserver.crt

## Этот файл необходимо хранить в секрете
key /etc/openvpn/easy-rsa/easyrsa3/pki/private/vpnserver.key
dh /etc/openvpn/easy-rsa/easyrsa3/pki/dh.pem

## Указываем адрес сервера и подсеть
server 10.8.0.0 255.255.255.0

## Выдаем пользователям необходимые маршруты
push "route 10.8.0.0 255.255.255.0"

## OpenVPN as Proxy. Перенаправляем трафик клиентов в интернет
push "redirect-gateway def1 bypass-dhcp"

## Используем свой собственный DNS-сервер
push "dhcp-option DNS 10.8.0.1"

## Разрешаем подключенным клиентам OpenVPN-сервера соединяться друг с другом
client-to-client

## Используем сжатие трафика (если не нужно, то можно закомментировать!)
comp-lzo

## Проверяем состояние клиента, отправляем пакеты каждые 10 с, если в течение 120 с клиент не ответил, то он считается отключенным
keepalive 10 120

## Используем те же ключи и интерфейсы при рестарте
persist-key
persist-tun

## Лог-файл
log openvpn.log

## Уровень логирования 0 — в лог попадают только записи о критических ошибках сервера, если нужно подробнее, то выставляем 9 для дебагинга
verb 0
## Количество записей, после которых будет производиться запись в лог
mute 20

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

$ systemctl cat openvpn.service

## /lib/systemd/system/openvpn.service
## This service is actually a systemd target,
## but we are using a service since targets cannot be reloaded.

[Unit]
Description=OpenVPN service
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecReload=/bin/true
WorkingDirectory=/etc/openvpn

[Install]
WantedBy=multi-user.target

Получив путь к файлу, немного изменим его под наши нужды.

## /lib/systemd/system/openvpn.service
## This service is actually a systemd target,
## but we are using a service since targets cannot be reloaded.

[Unit]
Description=OpenVPN service
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/openvpn --config server.conf --daemon
ExecReload=/usr/sbin/openvpn --config server.conf --daemon
WorkingDirectory=/etc/openvpn
RestartSec=5s
Restart=on-failure

[Install]
WantedBy=multi-user.target

Запускаем сервис.

$ sudo systemctl enable openvpn.service && sudo systemctl start openvpn.service

И проверяем на ошибки.

$ journalctl -uxe openvpn.service

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

#!/bin/bash

USERNAME=$1
EASYRSA_PKI="/etc/openvpn/easy-rsa/easyrsa3/pki"

echo "
client
nobind
dev tun
remote 192.168.0.183 3333
proto udp
comp-lzo yes
auth-nocache
script-security 2
persist-key
persist-tun"

echo "<key>
$(cat ${EASYRSA_PKI}/private/${USERNAME}.key)
</key>

<cert>
$(openssl x509 -in ${EASYRSA_PKI}/issued/${USERNAME}.crt)
</cert>

<ca>
$(cat $EASYRSA_PKI/ca.crt)
</ca>
"

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

Теперь, когда у нас готов сервер VPN и настроено подключение клиентов, пора приступать к конфигурации сервера DNS.

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


Check Also

Google исправила более 40 проблем в Android, включая критическую DoS-уязвимость

На этой неделе инженеры Google выпустили декабрьские обновления для Android, среди которых…

11 комментарий

  1. Аватар

    icef1sh

    08.08.2019 at 00:47

    Ой все так красиво и тут вдруг openVpn. Зачем же такое прожорливое и громозжкое приложение ставить когда есть этокомичный и более простой в настройке shadowsocks?

    • Аватар

      GH0st3rs

      08.08.2019 at 11:34

      Всё очень просто:
      1) У shadowsocks нет разделения на пользователей, если вы решите подключить кого-то ещё, вам придётся светить свой пароль, в то время как в моём случае нужно будет просто отозвать сертификат;
      2) Судя по документации, нет сжатия трафика;
      Но главное, почему именно OpenVPN — Мне нужно было объединить несколько устройств в одну сеть, минуя NAT, собственно для этого и было описано как резолвить DNS имена клиентов. Я могу находясь дома, с телефона управлять ПК на работе, или контролировать работу ASUS Tinker Board, оставленную в подсети заказчика, для проведения аудита.

      • Аватар

        icef1sh

        08.08.2019 at 13:54

        Поскольку в контексте статьи речи не было про что-то кроме избавления от рекламы, мне всё же ovpn кажется крайне избыточным в данном конкретном случае. И для этих целей всё же более подходит ss нежели чем ovpn, поскольку он умеет в split tunneling. Не представляю зачем делать единственным шлюзом свой впн сервер, поскольку в таком случае все приложения, включая стриминговые сервисы пойдут, через него, тем самым вы лишаете себя как предлагаемых операторами услуг по безлимитному траффику на стриминговые сервисы (spotify, youtube, etc) так и появятся задержки связанные с удалённостью вашего сервера от вас. Кстати также не вижу обхективных причин не использовать wireguard с появлением приложения под все платформы, раз доступ нужен до рабочего места. А тем кому надо только зарезать рекламу — проще уж использовать туннели на локалхост и там уже рубить трафик, зачем его гонять через сотни других узлов? К примеру https://github.com/blokadaorg/blokada/releases. Возможно я что-то упустил, буду рад прочитать комментарий.

        • Аватар

          GH0st3rs

          08.08.2019 at 18:57

          Возможно вы правы, и в плане производительности использовать на каждом устройстве по 3-4 приложения будет более оптимально, чем один OpenVPN. Именно по этой причине я не рассматривал других вариантов.
          Я описал один из способов, который идеально подошёл под все мои текущие и будущие задачи.

  2. Аватар

    aandrusha

    08.08.2019 at 16:45

    «Поэтому я почти не использую телефон для просмотра сайтов, ведь в мобильных браузерах вообще нельзя установить блокираторы рекламы.»
    Уже много лет использую uBlock Origin в Firefox — как на компьютере, так и на смартфоне. В некоторых других браузерах встроенные блокировщики есть.

  3. Аватар

    soko1

    09.08.2019 at 10:27

    Вместо OpenVPN давно использую WireGuard. Он использует более современные шифры, очень прост в установке и настройке, менее прожорлив и с ним отзывчивее инет. Советую попробовать 🙂

    А что до рекламы — не проще ли впихать hosts прямиком в телефон? Да, потребуется рут, но его вроде не проблема поставить.

    • Аватар

      icoz

      11.08.2019 at 23:05

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

      • Аватар

        Kneize

        21.08.2019 at 19:00

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

  4. Аватар

    icoz

    11.08.2019 at 23:09

    Для теста попробовал собрать это хозяйство на машинке в DO.
    Ряд библиотек пришлось доставлять помимо приведенных в статье
    > $ sudo apt install -y protobuf-c-compiler libevent-dev libssl-dev libsodium-dev libfstrm-dev
    и банальных build-essential, а именно:
    bison libprotobuf-c-dev libexpat1-dev

  5. Аватар

    motoroler

    13.08.2019 at 23:39

    >> Желающие могут самостоятельно перехватить злополучные запросы, тем более что они идут по обычному HTTP).

    а как это сделать для телефона? Проанализировать проходящий траф через роутер? Или есть более простой путь?

    • Аватар

      GH0st3rs

      16.08.2019 at 12:12

      Да, я именно так и делал, перенаправил весь трафик с роутера в BurpSuite и подключился к нему с телефона. Ну либо как вариант можете поднять свою точку на ноуте и уже к ней подключиться

Оставить мнение