Команда для запуска дочернего процесса в автономном режиме (без внешней сети) в Linux

15

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

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

Я хотел бы иметь утилиту, которая работает как strace/ unshare/ sudoи просто запускает команду со скрытым Интернетом (и LAN), а все остальное все еще работает

$ offline my-program-to-test

Этот вопрос намекает на ответ: заблокировать сетевой доступ процесса?

Там есть пара предложений, например, запускать от имени другого пользователя, затем манипулировать iptables, или unshare -n. Но в обоих случаях я не знаю заклинания, чтобы получить доменные сокеты unix и loopback для совместного использования с основной системой - ответы на этот вопрос только говорят мне, как отключить доступ ко всей сети.

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

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

Я бы хотел, чтобы процесс выполнялся на 100% нормально, за исключением того, что сетевые вызовы с указанием нелокального адреса потерпят неудачу. В идеале, сохраняя тот же uid, тот же homedir, тот же pwd, все то же самое, кроме ... офлайн.

Я использую Fedora 18, поэтому непереносимые ответы Linux просто хороши (даже ожидаемо).

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

Любой разработчик, пытающийся поддерживать «автономный режим», наверняка оценит эту утилиту!

Havoc P
источник

Ответы:

9

Традиционный ответ - запустить программу от имени другого пользователя и использовать iptables -m owner. Таким образом, конфигурация сети является общей. Однако с появлением пространств имен существует более простой способ.

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

Для совместного использования доменных сокетов unix все, что вам нужно, это иметь достаточно свежее ядро, после этого патча 2010 года , например 2.6.36 или выше (что имеет место во всех текущих дистрибутивах на момент написания, кроме RHEL / CentOS).

Запустите программу в своем собственном пространстве имен IP. Перед запуском программы установите виртуальный интерфейс Ethernet. Там, кажется, не так много документации; Я нашел правильное заклинание в нескольких блогах:

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

unshare -n -- sh -c '
  # Create a virtual ethernet interface called "confined",
  # with the other end called "global" in the namespace of PID 1
  ip link add confined type veth peer name global netns 1

  # Bring up the confined end of the network link
  ip addr add 172.16.0.2/30 dev confined
  ip link set confined up

  # Bring up the global end of the network link
  ns_exec /proc/1/ns/net ifconfig global 172.16.0.1 netmask 255.255.255.252 up

  # Execute the test program
  exec sudo -E -u "$TARGET_USER" "$0" "$@"
' /path/to/program --argument

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

Я не знаю, как разделить localhost между двумя пространствами имен. Виртуальные интерфейсы Ethernet создают мост точка-точка. Вы можете использовать iptablesправила переадресации для перенаправления трафика из / в loпри желании.

Жиль "ТАК - прекрати быть злым"
источник
Хорошая дополнительная информация, спасибо. Я думаю, что veth дает мне ссылку на «внешнее» пространство имен, но мое новое пространство имен по-прежнему составляет отдельный сетевой узел, а не тот же самый сетевой узел без нелокальных интерфейсов. Последствия (?): Доменные / абстрактные сокеты Unix по-прежнему не будут работать, и loopback может быть переадресован с помощью iptables, но пересылка не обеспечивает совместное использование, то есть как исходное, так и ограниченное пространство имен может прослушивать loopback и оба набора (динамически с изменением) порты должны были бы быть видны в обоих пространствах имен ... начинать догадываться, что я хочу, здесь невозможно: - /
Havoc P
1

Этого также можно добиться с помощью сопоставления правил iptables cgroups. Я написал инструмент для абстрагирования шагов. Несмотря на то, что для начальной настройки требуются права суперпользователя, а в другом случае это двоичный файл setuid, я думаю, он предлагает довольно простой способ решения проблемы, о которой идет речь. Это требует версии iptables, которая является достаточно недавней и чтобы были доступны надлежащие модули сетевого фильтра.

https://github.com/quitesimpleorg/qsni

crtxcr
источник
0

/ !! \ Вероятно, это неправильный ответ, так как он унесет с собой весь ваш трафик, а не трафик с одного пида.

Я не использовал его, но я думаю, что вы могли бы использовать Comcast:

https://github.com/tylertreat/Comcast

установить 100% потери пакетов

Опять же, я не проверял это, но теоретически изменил из их readme вы можете сделать:


Linux

В Linux вы можете использовать iptablesдля отбрасывания входящих и исходящих пакетов.

$ iptables -A INPUT -m statistic --mode random --probability 1 -j DROP
$ iptables -A OUTPUT -m statistic --mode random --probability 1 -j DROP

Кроме того, вы можете использовать, tcкоторый поддерживает некоторые дополнительные параметры.

$ tc qdisc change dev eth0 root netem reorder 0 duplicate 0 corrupt 1

Для сброса:

$ tc qdisc del dev eth0 root netem
ThorSummoner
источник