Сначала давайте заблокируем все входящие и исходящие сигналы
через iptables.
vi / etc / sysconfig / iptables
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A OUTPUT -j DROP
-A INPUT -j DROP
-A FORWARD -j DROP
COMMIT
start iptables:
service iptables start
Мой кабель Ethernet подключен. давайте попробуем что-нибудь через терминал
ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
, вот и все. всего 1 строчка. после этого он останавливается . очевидно, что iptables успешно блокирует его
, теперь я собираюсь отсоединить свой кабель Ethernet. мой интернет отключен.
давайте попробуем еще раз:
ping 8.8.8.8
connect: Network is unreachable
на этот раз ... мгновенно ... он вернет это сообщение.
Ясно, что это "пинг" или любая другая программа .. она определяет, включен сетевой интерфейс или нет , прежде чем он выполнит свою интернет-команду.
конечно, как только он выполнится ... он не сможет пройти через правила iptable. но то, что кажется очевидным, это .. он не сначала обращается к iptables ..
он сначала проверяет, подключен ли сетевой интерфейс или нет.
Я хотел бы выяснить, как я могу вручную сообщить ему , что сетевой интерфейс подключен.
другими словами, если я не скажу ему, что сетевой интерфейс работает .. он должен вести себя так же, как и , когда сетевой интерфейс не подключен (когда Ethernet кабель не подключен)
как это можно сделать?
Ясно, что это "пинг" или любая другая программа ... она определяет, включен сетевой интерфейс или нет, прежде чем он выполнит свою интернет-команду.
Нет, это не так. т. Вот (некоторые из) выходных данных strace ping 8.8.8.8
из системы без функционального сетевого интерфейса :
connect(4, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("8.8.8.8")}, 16) = -1 NETUNREACH (Network is unreachable)
Чтобы ответить на ваш конкретный вопрос , когда процесс пользовательского пространства просит ядро отправить данные в удаленную систему, когда нет доступной сетевой подсистемы, он возвращает ошибку, соответствующую ситуации. Обратите внимание на отсутствие какого-либо запроса о доступности сети; программа пользовательского пространства идет прямо вперед и запрашивает подключение, но сразу же выдает ошибку, потому что ядро знает, что это не может быть выполнено. Это ничем не отличается от попытки записать файл в файловой системе, в которой недостаточно места (ошибка 28, на устройстве нет места) или когда вы превысили свою дисковую квоту (ошибка 122, дисковая квота превышена) (коды ошибок приняты с благодарностью из здесь ).
Изменить : Я подозревал, что ваш следующий вопрос будет: « как мне вернуть эту ошибку в каждом конкретном случае », но Я счел разумным позволить вам все равно спросить. Как вам уже неоднократно говорили, лучший способ сделать это - использовать iptables -j REJECT
, поскольку полученная ошибка точно так же передается обратно запрашивающему процессу. Вот пример в той же системе с включенной сетью, но одно правило iptables -I OUTPUT 1 -j REJECT
запрещает весь трафик OUTPUT
(NB это не очень хорошо идея в реальной жизни ):
sendmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(0), sin_add=inet_addr("8.8.8.8")}, msg_iov(1)=[{"...."..., 64}], msg_controlln=0, msg_flags=0}, 0) = -1 EPERM (Operation not permitted)
С различными вызовами -j REJECT --reject-with ...
различные ошибки передаются обратно запрашивающему процессу, но все они приводят к передаче ошибки.
Редактировать 2 : Ваша ментальная модель сетевого стека UNIX просто неверна, и идеи, которые вы сформировали из нее, неисправный; в частности iptables - это ядро (*). Частично проблема может заключаться в том, что некоторые программы игнорируют некоторые ошибки, некоторые отмечают их, но продолжают работу, а некоторые завершаются. Любая конкретная программа сама решает, что она будет делать с той или иной ошибкой. Программа ping
, например, завершается на ENETUNREACH
, но на EPERM
она просто записывает ошибку в stderr
и продолжает работу. Если я правильно понимаю, это поведение, против которого вы возражаете.
Это не то, что вы можете контролировать, если вы не пишете программу . Я понимаю, что вы хотели бы, чтобы ядро отправляло ошибку, которую программа не игнорирует, но ядро (в нынешних условиях) не будет делать это за вас. Ничто не мешает вам написать модифицированное ядро, которое сигнализирует обо всех ошибках с помощью SIGKILL, но Linux в настоящее время этого не делает, и большинство из нас этого не хочет.
(*) Чтобы быть точным, iptables
- это программа пользовательского пространства, которая позволяет нам управлять структурами netfilter внутри ядра. Но результирующая обработка пакетов и ошибок определенно является явлением пространства ядра, а не пространства пользователя.