Итак, что такое 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