Как стать автором
Обновить

Комментарии 21

Это один из методов, но он не запрещает напрямую делать сисколлы — просто замещает библиотечную функцию.

Перехватывать сами сисколлы можно через ptrace(), но это достаточно сложно и может не поместиться в статью.
Не менее интересно было бы теперь узнать как избежать такой подмены )) Если только собирать всё статически…

p.s. Кстати в Windows есть даже для этих целей специальный механизм — Layered Service Provider
Тут описывался способ перехвата библиотечных функций в рантайме.
Можете переделать прилагаемый код для получения адреса оригинала из адресного пространства библиотеки и сравнивать с адресом фактического вызова, чтобы выявить факт фальсификации.
Это просто лажа. Было очень красивое решение:

# groupadd nointernet
# iptables -I OWNER 1 -m owner --gid-owner "$(getent group nointernet | cut -f 3 -d :)" -j DROP
# sg user -c «curl -s opennet.ru | wc -l „
310
# sg nointernet -c “curl -s opennet.ru | wc -l „
0

-I OWNER => -I OUTPUT

//obivious fix
Василий видимо не дочитал, ограничивать нужно не весь инет, а адрес+порт.
Решение действительно элегантное, отличный пример использования LD_PRELOAD.

Респект.
-d адрес -m tcp -p tcp --dport порт
Угу, и для каждого приложения свою группу :)
В iptables можно и по юзерам ограничивать, а если учесть что все демоны и так обычно запускаются под своими пользователями, то это достаточно гибко.
Да, ваше решение действительно элегантнее. Но есть одна неувязка: что делать, если программа, которую нужно блокировать, будет запускаться от разных пользователей/групп?

В старых версиях ядра была такая опция, как --pid-owner и --cmd-owner. Теперь их, к сожалению, убрали.
Есть еще одна возможность сделать такое, более универсальная и более низкоуровневая, — заменить соответствующий вызов в таблице системных вызовов ядра.
Правда там можно столкнуться с иными проблемами — поиск этой таблицы и запись в нее, учитывая, что с не очень давнего времени, эта таблица находится в области памяти, на уровне процессора, запрещенной для записи (правда на ARM Linux такой защиты нет и таблицу можно модифицировать, главное найти её). Впрочем, при желании, все это довольно легко обходится :)
Ваша информация устарела, всё делается и делается очень быстро и просто:
www.mjmwired.net/kernel/Documentation/kprobes.txt

Правда, не на всех архитектурах…
На самом деле вариант про AppArmor (если конечно не устраивает правило по uid в iptables) — более правильный, как минимум потому что он проще для понимания любыми другими людьми, достаточно гибкий и он уже есть, не надо велосипедов.
Ага, поставить файрволл, который нигде не регистрируется и «счастливой отладки» — вспоминай через пару месяцев, почему сокет не работает.
Это кривое решение, в хорошо сконфигурированной системе достаточно iptables, максмум — AppArmor.
Наверное это круто.
Но рекомендую посмотреть на это: tsocks.sourceforge.net/index.php
2002? А щас вроде 2010.
Но там люди хоть конфиг приделали…
А тут — как минимум 1а лишняя переменная: uint16_t sin_port = addr_in->sin_port;
И как максимум — нет проверки на real_connect = dlsym(RTLD_NEXT, «connect»);
А если dlsym не вернет?
Не стыдно такое выкладывать?
Спасибо за ссылку, интересная штука.

Конечно, можно (и даже нужно, ибо правильнее) сделать красивую обертку, написать парсер конфига, man-страницу и прочее… Но ведь целью было не создание полноценного файрвола, а создание препятствия для одного-единственного скрипта, а также простой пример перехвата.

А для того, чтобы не «потерять» этот файрвол в системе, достаточно использовать LD_PRELOAD не для всей системы, а непосредственно перед вызовом скрипта, тогда найти и устранить проблему не будет слишком сложно.

А с проверкой действительно сплоховал. Безусловно, там стоило ее поставить.
Собственно, ты не проверяешь что dlsym вернул что-то осмысленное и RTLD_NEXT не совсем корректно. Наверное лучше было бы RTLD_CONNECT.
тьфу тф, RTLD_GLOBAL
Если верить man'у и методу тыка, то ни RTLD_CONNECT, ни RTLD_GLOBAL функции dlsym не передаются. Передавать ей можно либо RTLD_DEFAULT, либо RTLD_NEXT.

Если использовать первый, то точка входа будет искаться в нормальном порядке, т.е. сначала в нашей билиотеке, затем во всех остальных. А поскольку в нашей библиотеке есть эта точка входа, то именно она и вызовестся. Что произойдет в таком случае? Правильно, бесконечная рекурсия.

Для того, чтобы этого не было и стоит использовать RTLD_NEXT, который «пропускает» нашу библиотеку и поиск начинает со следующей в списке.

А вот насчет проверки возвращаемого значения действительно проглядел, каюсь.
Спасибо автору статьи, очень хорошая информация.
Как статья про динамическую линковку с примером «как можно запретить доступ к инету одному приложению» — ОК. Как статья про «как можно запретить доступ к инету одному приложению» — есть лучше решения :)
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.