
Содержание
- 1 Шифрование трафика в Linux
- 2 Коротко о двух вариантах
- 3 Реализация
- 4 IPSet
- 5 Автоматизация после сбоев/перезагрузок
- 6 Заключение
Эта статья не является руководством. Она написана исключительно с целью ознакомить вас с некоторыми функциональными возможностями маршрутизации в системах Linux. Автор статьи и редакция сайта www.spy-soft.net не несут никакой ответственности за результат использования описанных здесь методов и приемов.
Linux предоставляет огромный набор функций для маршрутизации и инструментов ее конфигурирования. Опытные сисадмины знают об этом и используют арсенал Linux на полную катушку. Но и многие даже продвинутые пользователи не догадываются, сколько удобства могут принести все эти замечательные возможности. Сегодня мы создадим таблицы маршрутизации и опишем правила прохода по ним, а также автоматизируем администрирование этих таблиц. Итак, наши творческие планы:
- определимся с тем, что нам требуется: установим необходимые пакеты и разберемся, зачем они нужны;
- изучим общий принцип работы связки;
- настроим защищенный канал VPN с использованием OpenVPN + stunnel;
- составим списки адресов и опишем области их применения;
- создадим скрипт для быстрого добавления домена или IP-адреса в списки IPSet с добавлением в таблицу маршрутизации и включением в правила перенаправления;
- используем SSH для предоставления безопасного канала связи в эти ваши интернеты.
Шифрование трафика в Linux
Что нам понадобится, чтобы все работало, и желательно — комфортно? Само собой, iptables, куда же без него. Еще iproute2, он и позволит нам насоздавать кучу таблиц. IPSet потребуется для того, чтобы не городить огород из множества правил iptables.Что есть что
- iptables — утилита командной строки. Базовое средство управления работой файрвола для ядер Linux.
- iproute2 — набор утилит для управления параметрами сетевых устройств в ядре Linux.
- IPSet — инструмент для работы со списками IP-адресов и сетевых портов в сетевом фильтре. Формирует список в специальном формате для передачи файрволу.
- stunnel — инструмент организации шифрованных соединений для клиентов или серверов, которые не поддерживают TLS или SSL. Stunnel перехватывает незашифрованные данные, которые должны были отправиться в сеть, и шифрует их. Программа работает как в Unix-системах, так и в Windows. В качестве шифрования использует OpenSSL для реализации базового протокола TLS и SSL.
- OpenVPN — VPN-сервер с поддержкой шифрования библиотекой OpenSSL. Клиентские части доступны практически на всех платформах. Умеет работать через прокси типа Socks, HTTP, через NAT и сетевые фильтры.
Коротко о двух вариантах
Клиент и сервер будут устанавливать зашифрованный канал связи по 443-му порту (stunnel) и передавать внутри OpenVPN по 995-му порту. Снаружи это должно выглядеть как обычный HTTPS.
И вот тут можно реализовать две схемы подключения.
Вариант 1. На клиентской машине iptables будет маркировать пакеты неким флагом, если адреса в пакетах и списках IPSet совпадут, и передавать их для маршрутизации.
Далее помеченные флагом пакеты будут отправлены по заранее созданной таблице маршрутизации, остальные пойдут по маршруту, заданному по умолчанию. С помощью консоли или небольшого скрипта мы поправим этот список адресов. В зависимости от ситуации списков может быть несколько.
Вариант 2. В качестве клиента выступит хост в локальной сети (виртуалка, Raspberry Pi или какое-нибудь другое устройство). Он будет указан в качестве основного шлюза на компьютерах, с которых нужен доступ к ресурсам через VPN. Получив запрос для IP-адреса из списка, шлюз включит NAT и отправит такой трафик в VPN. Остальной трафик будет маршрутизироваться до шлюза по умолчанию без NAT.
Для Linux-систем мы можем оставить шлюз по умолчанию и установить у себя IPSet и iproute2, а потом настроить их аналогично настройкам «промежуточного» хоста-маршрутизатора. В этом случае на уровне клиента будет отбираться трафик по тому же списку IPSet. То есть то, что в списке, будет отправляться на промежуточный хост-маршрутизатор и далее в VPN. Остальное будет маршрутизироваться по умолчанию.
Реализация
Предположим, что где-то далеко в облаке у нас уже есть VPS-сервер с Ubuntu или Debian. В других дистрибутивах отличия будут, скорее всего, только в установке необходимых пакетов. Этот хост в нашей конфигурации будет использоваться в качестве сервера VPN. Рекомендаций, какой VPS лучше использовать, в интернетах полным-полно — на разный бюджет, с разными конфигурациями и условиями.Еще по теме: Как поднять свой VPN настроить OpenVPN и stunnel
Устанавливаем на сервере OpenVPN, stunnel, git:
1 | sudo apt install openvpn stunnel4 git |
1 2 3 | git clone https://github.com/Nyr/openvpn-install.git cd openvpn-install sudo ./openvpn-install.sh |
Открываем конфигурационный файл сервера OpenVPN и правим его. Выбираем нужный порт — тот, который на сервере будет свободен для подключения. Порт лучше использовать более-менее неприметный (я выбрал 995-й, обычно почтовые порты оставляют открытыми), чтобы клиент мог гарантированно подключиться к VPN-серверу.
Вот как будет выглядеть наш конфиг:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | port 443 proto tcp dev tun0 sndbuf 0 rcvbuf 0 ca ca.crt cert server.crt key server.key dh dh.pem auth SHA512 tls-auth ta.key 0 topology subnet server 10.8.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 208.67.222.222" push "dhcp-option DNS 208.67.220.220" push "route 10.8.0.0 255.255.255.0" route 192.168.31.0 255.255.255.0 keepalive 10 120 cipher AES-256-CBC user nobody group nogroup persist-key persist-tun status openvpn-status.log verb 3 crl-verify crl.pem |
1 2 3 4 5 6 7 8 | sudo nano /etc/stunnel/stunnel.conf output = /var/log/stunnel.log [openvpn] client = no accept = 443 connect = localhost:443 cert = /etc/stunnel/stunnelsrv.pems |
- описываем, куда будут сохраняться логи;
- указываем название сервиса в произвольной форме;
- выбираем, в каком режиме работает устройство: сервера или клиента. В данном случае client = no указывает на режим сервера;
- accept = 443 указывает порт, к которому будем подключаться снаружи (443-й порт выбран не просто так — в 99% случаев он всегда открыт, проще прикинуться обычным HTTPS, и нас не заметят даже при DPI).
1 | sudo openssl req -nodes -new -days 365 -newkey rsa:1024 -x509 -keyout stunnelsrv.pem -out stunnel.pem |
Переходим к клиенту:
1 | sudo apt install iproute2 ipset stunnel4 git openvpn |
1 2 3 4 5 6 7 8 | output = /var/log/stunnel.log [openvpn] client = yes accept = 127.0.0.1:995 connect = IP:443 cert = /etc/stunnel/stunnel.pem |
Передаем файл клиента OpenVPN с сервера. Проверяем настройки: используется порт 995, proto tcp, dev tun0. Очень важный момент: нам нужно объявить маршрут до нашего VPS через шлюз по умолчанию. Иначе получится, что stunnel установит соединение, потом подключится VPN и попытается все перенаправить в туннель, но stunnel уже не сможет работать, так как хост и порт будут недоступны. Также отключаем перенаправление всего трафика в VPN, проверяем адрес подключения и порт. Адрес VPN-сервера в конфиге будет 127.0.0.1 — то есть localhost. Подразумевается, что stunnel уже пробросил нужный порт клиента. Должно получиться примерно следующее:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | client dev tun proto tcp sndbuf 0 rcvbuf 0 remote 127.0.0.1 995 resolv-retry infinite nobind persist-key persist-tun remote-cert-tls server auth SHA512 cipher AES-256-CBC setenv opt block-outside-dns key-direction 1 #redirect-gateway def1 pull-filter ignore redirect-gateway route IP 255.255.255.255 net_gateway — добавляем в конфиг OpenVPN клиента. IP — это белый IP-адрес VPN-сервера. #ip route add table obhod default dev tun0 verb 3 |
Вариант 1: клиент VPN на машине пользователя
Первым делом создадим список IP-адресов, который будем использовать далее:1 | sudo ipset -N vpn iphash |
1 | sudo ipset -A vpn 8.8.8.8 |
1 | sudo iptables - OUTOUT -t mangle -m set --match-set vpn dst -j MARK --set-mark (1 или 0x1) |
1 | 252 vpn |
1 2 | sudo ip rule add table vpn prio 1000 fwmark (1 или 0x1) sudo ip route add table vpn dev tun0 default |
1 2 3 | sudo sysctl net.ipv4.tcp_fwmark_accept=1 sudo sysctl net.ipv4.conf.all.rp_filter=2 sudo net.ipv4.ip_forward=1 |
1 | sudo iptables -t nat -I POSTROUTING -o tun0 -j MASQUERADE |
1 | sudo iptables -I PREROUTING -t mangle -m set --match-set tovpn dst -j MARK --set-mark 0x1 |
Вариант 2: клиент VPN на маршрутизаторе
Теперь рассмотрим случай, когда VPN-соединение у нас выполняет не клиентская машина, а некий узел в сети и все настроено на нем аналогично примеру выше. Тогда нам нужно либо указать этот узел в качестве шлюза по умолчанию, либо установить на клиентской машине IPSet и iproute2 и правильно ее настроить.В этом случае сработают локальные IPSet и iproute2 и направят на промежуточный сервер-маршрутизатор пакет, а тот сверит адрес назначения со своим списком IPSet и, если обнаружит совпадение, отправит пакет в VPN, если совпадения не найдет — перешлет на шлюз по умолчанию.
Неудобство такого приема состоит в том, что нужно дважды вносить IP-адреса в списки. Сначала на сервере-маршрутизаторе, а второй раз — в свой локальный список IPSet. Зато это позволяет более гибко пользоваться маршрутизацией.
Стоит также отметить еще один вариант, о котором не говорилось выше. Можно установить на сервер-маршрутизатор VPN-клиент и stunnel, а потом убрать из конфига строку pull-filter ignore redirect-gateway. Тогда весь полученный трафик будет завернут в VPN-туннель. Останется лишь локально вести IPSet для направления нужного трафика через разные шлюзы.
IPSet
Списки IPSet очень удобно использовать, если нужно быстро разрешить либо запретить входящие или исходящие соединения на сервер. Так, например, многие реализуют географическую фильтрацию: проще один раз занести все в списки и одним правилом запретить весь входящий трафик отовсюду, кроме этого списка. Например:1 | sudo iptables -A INPUT -m set --match-set !RU src -j DROP |
IPSet, как видите, удобный инструмент, который значительно сокращает таблицу правил iptables. В частности, хорошо бывает объединять в отдельные списки сети серверов, адреса админов, остальных пользователей и так далее. А потом уже разом запрещать доступ одним и разрешать другим.
Автоматизация после сбоев/перезагрузок
Чтобы не потерять все настроенные нами параметры, добавим в crontab периодическое сохранение правил IPSet и iptables.1 2 3 4 5 | sudo crontab -e # Каждую первую минуту каждого часа, то есть раз в час 1 * * * * /bin/bash root ipset save > /opt/ipset.rules 1 * * * * iptables-save root > /opt/firewall.rules |
1 2 | ipset restore < /opt/routers/ipset.rules iptables-restore < /opt/routers/iptables.rules |
Исходный код скрипта check вы найдете в архиве по ссылке в конце статьи, а общий его смысл такой: проверяем таблицу маршрутизации и, если маршрута нет, добавляем его. Потом ту же проверку выполняем с правилом таблицы. Затем смотрим правило iptables, которое маркирует пакеты.
Напоследок напишем скрипт, который позволит нам более удобно добавлять IP-адреса в списки IPSet, чтобы каждый раз не ломиться в консоль. Этот скрипт выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/bash test=$(zenity --entry --title="Добавление адреса в ipset списки " --text="Введите адрес ip или домена") initip=$(dig +short "$test" -u 1.1.1.1) if [ ! -n "$initip" ]; then zenity --password --title="Введите пароль администратора" | sudo -S ipset -exist -A vpn "$test" echo "$test" >> /opt/iptovpn.txt else zenity --password --title="Введите пароль администратора" | sudo -S ipset -exist -A vpn "$initip" echo "$initip" >> /opt/iptovpn.txt fi sudo ipset save > /opt/ipset.rules |
Также в архиве вы найдете скрипт add_in_file, который читает файл со списком доменов, получает IP и складывает в списки IPSet.
Заключение
Итак, что у нас получилось? А вот что. Мы подняли зашифрованный, «белый» с точки зрения провайдера канал HTTPS. Внутри у него ходит наш OpenVPN. Клиент заворачивает туда то, что нам нужно, и не отправляет того, что не нужно. В принципе, можно написать еще пару правил iptables, в которых указано, кому можно ходить по адресам из заданного списка, а кому нет. Можно указать источники запросов для большей безопасности и для того, чтобы туда, не дай бог, не залез любознательный пользователь. Это реализуется с помощью второго списка IPSet, где придется вбить доверенные хосты, которые будут пользоваться доступом.При желании всю эту не слишком навороченную архитектуру можно развернуть на Raspberry Pi с «Линуксом» и таскать его с собой в качестве маленького маршрутизатора. Он где угодно обеспечит вам надежное, безопасное и шифрованное соединение, до которого никто не доберется.