Почему / proc не может быть слоем наложенной файловой системы (overlayfs) в Linux?

Для правильной работы NAT как пакеты от клиента к серверу, так и пакеты от сервера к клиенту должны пройти через NAT.

Обратите внимание, что таблица NAT в iptables используется только для первого пакета соединения. Более поздние пакеты, относящиеся к соединению, обрабатываются с использованием внутренних таблиц сопоставления, установленных при трансляции первого пакета.

iptables -t nat -A PREROUTING -i br-lan -s 192.168.1.0/24 -d 82.120.11.22/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.200

При наличии этого правила происходит следующее.

  • Клиент создает начальный пакет (tcp syn) и направляет его на общедоступный IP-адрес. Клиент ожидает получить ответ на этот пакет с заменой IP / порта источника и IP / порта назначения.
  • Поскольку клиент не имеет конкретных записей в своей таблице маршрутизации, он отправляет его на свой шлюз по умолчанию. Шлюзом по умолчанию является блок NAT.
  • Блок NAT принимает исходный пакет, изменяет IP-адрес назначения, устанавливает запись в таблице сопоставления, ищет новое место назначения в своей таблице маршрутизации и отправляет пакеты на сервер. Исходный адрес остается неизменным.
  • Сервер получает начальный пакет и формирует ответ (синхронное подтверждение). В ответе исходный IP / порт заменяется на целевой IP / порт. Поскольку исходный IP-адрес входящего пакета не изменился, IP-адрес назначения ответа - это IP-адрес клиента.
  • Сервер ищет IP-адрес в своей таблице маршрутизации и отправляет пакет обратно клиенту.
  • Клиент отклоняет пакет, потому что адрес источника не совпадает с ожидаемым.
iptables -t nat -A POSTROUTING -o br-lan -s 192.168.1.0/24 -d 192.168.1.200/32 -p tcp -m tcp --dport 80 -j SNAT --to-source 192.168.1.1

Как только мы добавляем это правило, последовательность событий меняется.

  • Клиент создает начальный пакет (tcp-синхронизацию) и направляет его на общедоступный IP-адрес. Клиент ожидает получить ответ на этот пакет с заменой IP / порта источника и IP / порта назначения.
  • Поскольку клиент не имеет конкретных записей в своих таблицах маршрутизации, он отправляет его на свой шлюз по умолчанию. Шлюзом по умолчанию является блок NAT.
  • Блок NAT получает исходный пакет, следуя записям в таблице NAT, он изменяет IP-адрес назначения, IP-адрес источника и, возможно, порт источника (порт источника изменяется только при необходимости для устранения неоднозначности), устанавливает запись в таблице сопоставления, выполняет поиск новый пункт назначения в своей таблице маршрутизации и отправляет пакеты на сервер.
  • Сервер получает начальный пакет и формирует ответ (синхронное подтверждение). В ответе исходный IP / порт заменяется на целевой IP / порт. Поскольку IP-адрес источника входящего пакета был изменен блоком NAT, IP-адрес назначения пакета является IP-адресом блока NAT.
  • Сервер ищет IP-адрес в своей таблице маршрутизации и отправляет пакет обратно в блок NAT.
  • Блок NAT ищет сведения о пакете (исходный IP-адрес, исходный порт, целевой IP-адрес, порт назначения) в своих таблицах сопоставления NAT и выполняет обратное преобразование.Это изменяет исходный IP-адрес на общедоступный IP-адрес, исходный порт на 80, целевой IP-адрес на IP-адрес клиента и порт назначения обратно на любой исходный порт, который использовал клиент.
  • Блок NAT ищет новый IP-адрес назначения в своей таблице маршрутизации и отправляет пакет обратно клиенту.
  • Клиент принимает пакет.
  • Связь продолжается с NAT, транслирующим пакеты туда и обратно.
3
19.06.2017, 10:25
2 ответа

https://github.com/torvalds/linux/commit/e54ad7f1ee263ffa5a2de9c609d58dfa27b21cd9

    /*
     * procfs isn't actually a stacking filesystem; however, there is
     * too much magic going on inside it to permit stacking things on
     * top of it
     */
s->s_stack_depth = FILESYSTEM_MAX_STACK_DEPTH;

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

5
27.01.2020, 21:12

Поиск «глубины» в /usr/src/linux/fs/overlayfsпоказывает, что это просто проверка текущей глубины стека по FILESYSTEM_MAX_STACK_DEPTH. Поиск этого во включенных файлах обнаруживает, что FILESYSTEM_MAX_STACK_DEPTHопределяется как 2 в /usr/src/linux/include/linux/fs.h. В комментарии говорится

Maximum number of layers of fs stack. Needs to be limited to prevent kernel stack overflow

Очевидно, поскольку файловая системаproc-добавляет еще один уровень косвенности по сравнению с devили sys, вы превышаете глубину стека. Я не вижу какой-либо очевидной причины, по которой он не может стекироваться глубже, поэтому попробуйте увеличить FILESYSTEM_MAX_STACK_DEPTH, перекомпилируйте ядро ​​и посмотрите, работает ли оно.Это может привести к тому, что ядро ​​будет использовать больше стека, а значит, больше памяти в целом, и это может сделать его медленнее. -Я не знаю подробностей о реализации.

Изменить в ответ на комментарий

Я предполагаю, что файловая система procдолжна отслеживать файлы для каждого модуля, чтобы она могла удалить их при удалении модуля. По сути, это оверлейная файловая система для всех модулей. Но мне пришлось бы подробно прочитать источник, чтобы убедиться в этом (, и вы тоже можете прочитать источник. :-).

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

4
27.01.2020, 21:12

Теги

Похожие вопросы