Killswitch для Openvpn в Linux. Как сделать так, чтобы трафик не пошел в обход VPN
Итак, что такое killswitch. В случае использования VPN, это механизм, при котором, в случае "падения" VPN вы не спалитесь. Без killswitch обычно бывает так: сидите вы, работаете через VPN и считаете себя защищенным, хотя бы от подглядывания за вами провайдера (и сидящего за СОРМ'ом тов. майора), и тут фигак, VPN падает, ОС предоставляет вам доступ по умолчанию, и мессенджеры, открытые вкладки браузера, и вообще все-все-все выходят в Интернет через ваш обычный провайдерский IP.
Значит, надо сделать так, чтобы трафик, в случае отключения VPN никуда не ушел. Это и есть killswitch.
Изначально все было сделано очень просто. Дома стоял отдельный линуксовый "сервер", который предоставлял остальным устройствам доступ к Интернету, к домашним файл-помойкам (FTP и Samba) и PXE, на случай чего-нибудь переустановить. Внешний VPN, т.е. тот, который крутится на "сервере" - просто OpenVPN-клиент, который коннектится к VPN-провайдеру. И первый killswitch был очень простой: надо отрубить доступ всем клиентам из локальной сети.
Openvpn может при соединении или разъединении с VPN выполнять пользовательские скрипты, и в этих скриптах прописывалась команда
iptables -P FORWARD DROP
, если соединение падало, или iptables -P FORWARD ACCEPT
, когда соединение устанавливалось. Но такой подход несколько кривоват, подходит это хорошо только для
FORWARD
-трафика, а для локальной машины на Linux, т.е ноута, который постоянно таскаю на работу, фигово - сделать DROP
по INPUT
и OUTPUT
-цепочкам, или вообще удалить дефолтный маршрут, так до поднятия VPN придется все это сначала "вернуть в зад" (не забыв перед этим закрыть браузер и мессенджеры).Подробнее про первый способ можно прочесть тут (копия)
1. Надо проверить конфигурацию ядра (см. Посмотреть опции компиляции ядра/узнать конфигурацию ядра Linux (копия), точнее, нас интересует опция
CONFIG_NETFILTER_XT_MATCH_OWNER
. Если она установлена в Yes
(CONFIG_NETFILTER_XT_MATCH_OWNER=y
), тогда можно переходить к следующему шагу, если она установлена в CONFIG_NETFILTER_XT_MATCH_OWNER=m
, т.е. собрана в виде модуля (как у меня) - смело добавляем в автозагрузку команду (и перезагружаемся):modprobe xt_owner
В некоторых ОС
modprobe owner_xt
, посмотрите сами, если modprobe
с одним модулем не выдаст ошибку, значит модуль тот, который надо. Если выдаст - попробуйте другой вариант.Если ядро скомпилировано с опцией
CONFIG_NETFILTER_XT_MATCH_OWNER=n
, тогда печально - придется пересобирать ядро.2. Понадобится отдельная группа для запуска OpenVPN и других программ в обход VPN. Все остальное, естественно, должно резаться, если OpenVPN не запущен.
Создаем группу:
groupadd -r killswitch
или
groupadd --system killswitch
Естественно, имя группы
killswitch
можно заменить на свое. Нужна обязательно системная группа, иначе работать не будет. Про группы Linux можно почитать в источниках [2].3. Выполняем команды
IPTABLES
:iptables -A OUTPUT -m owner --gid-owner killswitch -j ACCEPT
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
Вместо
tun0
вписываем имя устройства, которое будет создано OpenVPN Параметр можно узнать из конфига для соединения (dev <имя устройства>
, например dev tun0
). В конфиге можно его и поменять.Что вообще делают эти команды:
1. Пакеты, отправленные процессами с GID killswitch, пропускаются в сеть.
2. Пакеты на интерфейсе tun0 пропускаются безусловно. Это тот самый сетевой интерфейс, который реализован поверх VPN-подключения. Если у вас этот сетевой интерфейс называется по-другому (опция dev в конфиге OpenVPN позволяет дать ему фиксированное имя вместо tunN), поменяйте его в правилах iptables выше.
3. Пакеты на интерфейсе lo точно так же пропускаются. lo — это loopback-интерфейс, на котором располагается известный 127.0.0.1 (localhost). Поскольку некоторые приложения используют localhost для коммуникации между процессами, его блокировать нежелательно.
4. Все остальные пакеты блокируются. Блокировка при этом происходит с отправкой ICMP-пакета «administratively prohibited» (код ошибки не играет существенной роли). Это лучше, чем просто дропать пакеты, так как в таком случае программы будут сразу получать ошибку, а не висеть до таймаута. [1]
В источнике есть еще и дополнительные плюшки, как сделать это через CGROUPS
4. Осталось запустить OpenVPN от нужной группы:
sg killswitch openvpn --config /path/to/config/config.ovpn
sg
, это команда наподобие sudo
, только она позволяет запускать программы в нужной группе [4]Вышеприведенный способ режет совсем всё, т.е. доступ в локальную сеть тоже будет закрыт. А мне доступ в локальную сеть нужен, т.к. в ЛВС на работе присутствуют сервера, к которым нужен доступ. Я попытался добавить команды
IPTABLES
(да, о том, что порядок команд важен, я знаю) для доступа в локальную сеть, закрыв, при этом, доступ к локальному DNS-серверу и шлюзу (он же роутер с IP-адресом 192.168.0.1
)iptables -A OUTPUT -m owner --gid-owner killswitch -j ACCEPT
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -s 192.168.0.1 -j DROP
iptables -A OUTPUT -d 192.168.0.1 -j DROP
iptables -A INPUT -s 192.168.0.1 -j DROP
iptables -A INPUT -d 192.168.0.1 -j DROP
iptables -A OUTPUT -s 192.168.0.0/24 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.0/24 -j ACCEPT
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
-s
- входящий трафик-d
- исходящийНо почему-то пакеты один хрен, уходили в сеть. Поясните, кто больше меня шарит в
IPTABLES
, где я накосячил.В результате, пришел к Соломонову решению - открыть доступ не ко всей ЛВС, а только к нужным мне серверам.
Да, если еще один появится, придется отдельно разрешать доступ, что неудобно. Кто знает, как решить - подскажите.
Так что окончательная конфигурация такая:
iptables -A OUTPUT -m owner --gid-owner killswitch -j ACCEPT
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
iptables -A OUTPUT -s 192.168.0.66 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.66 -j ACCEPT
iptables -A OUTPUT -s 192.168.0.68 -j ACCEPT
iptables -A OUTPUT -d 192.168.0.68 -j ACCEPT
iptables -A OUTPUT -j REJECT --reject-with icmp-admin-prohibited
1. Kill switch для OpenVPN на основе iptables (копия в PDF)
2. Как создать группы в Linux (команда groupadd)
3. Как заблокировать ip в iptables
4.
sg
Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2020/11/22/kill