Gentoo Linux сборник статей



Pdf просмотр
страница10/79
Дата14.11.2016
Размер5.55 Mb.
Просмотров12477
Скачиваний1
1   ...   6   7   8   9   10   11   12   13   ...   79
0.0.0.0 0.0.0.0 0.0.0.0 U 0 0 0
ppp0
Специфика использования протокола PPP (обычно используемого при модемых соединениях) такова, что любой PPP-интерфейс является интерфейсом типа точка-точка, более того – PPP и расшифровывается как Point-to-Point Protocol.
Также интерфейсами точка-точка являются интерфейсы SLIP (Serial Line IP) и практически все разновидности туннельных интерфейсов.
При деактивизации интерфейса из таблицы маршрутизации автоматически исключаются все маршруты, для которых в поле Iface был указан отключившийся интерфейс. Для некоторых типов интерфейсов при активизации в таблице маршрутизации также создаются служебные записи о маршрутах, которые нельзя удалить.
В большинстве случаев таблица маршрутизации имеет не слишком большой размер, но в некоторых ситуациях (в частности, на шлюзовых машинах в больших сетях) таблица может иметь весьма значительный размер и изменяется не
“вручную” с помощью команды route, а специальными программами – демонами поддержки протоколов динамической маршрутизации. С некоторыми упрощениями алгоритм работы этих демонов можно описать следующим образом: демон “слушает” приходящие пакеты для обслуживаемых протоколов динамической маршрутизации, и по получении (или неполучении) такого пакета отдает ядру команду на изменение таблицы маршрутизации.
Следует также заметить, что команда route в режиме вывода таблицы маршрутизации фактически просто фильтрует и форматирует данные, содержащиеся в специальном файле, называемом /proc/net/route, используемом для доступа к таблице маршрутизации, ведущейся ядром.
Фильтры пакетов
Возможность инсталляции фильтров пакетов является очень интересной возможностью, предоставляемой стеком TCP/IP ядра Linux. Не углубляясь в
72

Linux не для идиотов: сборник рассказов и рецептов детали просто отметим, что IP-стек Linux позволяет различным модулям установить “ловушки” (hooks) для пакетов. При этом каждый пакет, попадающий в такую ловушку, передается для обработки драйверу, установившему эту ловушку.
Драйвер, в свою очередь, может проанализировать пакет, проделать какие-либо действия с пакетом, после чего вернуть код обработки, инструктируя таким образом ядро о том, что следует делать с пакетом дальше – вернуть ли отправителю сообщение об ошибке, прервать ли обработку и уничтожить пакет, либо продолжать обработку пакета обычным образом.
В настоящее время для фильтрации пакетов наиболее часто используются средства iptables. iptables – это название утилиты, которая позволяет настроить множество драйверов сетевой подсистемы NETFILTER ядра Linux, позволяющих осуществить анализ, произвести преобразование, или изменить обработку IP- пакетов. Основным объектом в iptables является цепочка правил (chain). Каждое правило в цепочке содержит набор условий совпадения (condition matches) и действие (action). Цепочки сгруппированы в таблицы (tables).
Действий есть две разновидности – прерывающие обработку пакета в цепочке, например действия DROP или ACCEPT, и не прерывающие обработку пакета цепочкой – например, LOG или MARK.
Цепочки используются для проверки пакетов – то есть пакет поочередно последовательно сравнивается с каждым из правил цепочки, и если он удовлетворяет всем условиям в правиле, к пакету применяется действие, указанное в этом правиле. Если действие является прерывающем, то на этом обработка пакета этой цепочкой заканчивается, если действие не прерывающее, то пакет продолжает проверяться этой же цепочкой.
Стандартные цепочки также содержат специальное неявное действие по умолчанию, называемое политикой цепочки (chain policy). Действие, указанное как политика цепочки, применяется ко всем пакетам, которые не попали ни под одно правило с “прерывающим” действием.
Стандартные таблицы и цепочки
Подсистема пакетного фильтра содержит три таблицы, в каждой из которых содержатся несколько цепочек (наборов правил). Кроме того, администратор может создавать собственные цепочки правил. Ниже перечисляются стандартные таблицы и цепочки:
Таблиц а
Назначение
Цепочки
Назначение mangle Модификация пакетов
PREROUTING Модификация всех пришедших пакетов
INPUT
Модификация пакетов, пришедших на адрес компьютера
FORWARD
Модификация пакетов, которые должны быть отмаршрутизированы (пересланы на другой хост)
OUTPUT
Модификация пакетов, сгенерированных процессами
73

Linux не для идиотов: сборник рассказов и рецептов
Таблиц а
Назначение
Цепочки
Назначение данного хоста
POSTROUTIN
G
Модификация всех переданных пакетов filter
Фильтрация пакетов
– принятие решения об их дальнейшей обработке или отказе от обработки)
INPUT
Фильтрация адресованных этому компьютеру пакетов
OUTPUT
Фильтрация сгенерированных этим компьютером пакетов
FORWARD
Фильтрация маршрутизируемых
(транзитных) пакетов nat
Трансляция адресов PREROUTING Трансляция адресов всех принимаемых пакетов
FORWARD
Трансляция адресов транзитных пакетов
POSTROUTIN
G
Трансляция адресов всех передаваемых пакетов
Таблица nat обладает “двойственным” действием, т.е. если вы включите преобразование для входящих пакетов, исходящие пакеты также будут модифицироваться, и наоборот. Таблицы mangle и nat изменяют пакеты, но mangle не ведет список изменений, т.е. является “однонаправленной” таблицей.
Порядок применения стандартных таблиц и цепочек
Рассмотрим, какой путь проходит пакет в цепочках и таблицах iptables. Для входящих пакетов (адресованных компьютеру, на котором активизирована поддержка iptables) верна следующая последовательность применения цепочек:
1. mangle.PREROUTING
2. nat.PREROUTING
3. mangle.INPUT
4. filter.INPUT
Для пакетов, отправляемых с компьютера, реализуется следующая цепочка обработки:
1. filter.OUTPUT
2. mangle.OUTPUT
3. nat.POSTROUTING
4. mangle.POSTROUTING
Пакеты, являющиеся транзитными (маршрутизируемыми), т.е. не адресованные фильтрующему компьютеру и не сгенерированные фильтрующим компьютером, проходят по следующей последовательности цепочек и таблиц:
74

Linux не для идиотов: сборник рассказов и рецептов
1. mangle.PREROUTING
2. nat.PREROUTING
3. mangle.FORWARD
4. filter.FORWARD
5. nat.FORWARD
6. nat.POSTROUTING
7. mangle.POSTROUTING
Стандартные действия
Каждое правило в любой цепочке может ссылаться на одно из стандартных или дополнительных действий, либо на какую-либо пользовательскую цепочку.
Основное различие между стандартными и дополнительными действиями в том, что стандартные действия могут указываться в правилах любых цепочек любых таблиц, а дополнительные действия можно указывать только для некоторых цепочек некоторых таблиц. Перечислим стандартные действия:
ACCEPT
Прервать проверку пакета цепочкой и перейти к следующей в порядке обработки пакета стандартной цепочке
DROP
Прервать обработку пакета, сам пакет удалить
RETURN
Прервать проверку пакета цепочкой и вернуться к проверке вышестоящей цепочкой, а если действие встретилось в одно из стандартных цепочек, поступить с пакетом так, как предписано в политике цепочки (chain policy)
QUEUE
Передать пакет некоторому процессу для дальнейшей обработки
Интересной особенностью также является то, что существуют так называемые target extensions, которые реализованы как модули и также могут использоваться для указания проводимого над пакетом действия. В частности, к таким действиям, например, относятся действия LOG – запротоколировать факт получения пакета,
MASQUERADE – подменить IP-адрес отправителя пакета, MARK – пометить пакет и многие другие. Некоторые действия могут встречаться не во всех цепочках, а только в некоторых цепочках некоторых таблиц.
Еще одним специфическим действием можно назвать переход к пользовательской цепочке. При этом, если пакет в процессе обработки попадает под действие правила, у которого в качестве действия указан переход к другой цепочке, то пакет начинает проверяться ее правилами. Это часто используется, чтобы сходным образом обрабатывать некоторые виды пакетов.
Условия отбора
Условия отбора делятся на две группы – стандартные условия, которые применимы ко всем пакетам, и расширенные условия, называемые также match extensions. Расширенные условия могут применяться не для всех пакетов, а только для некоторых из них – например, дополнительные условия для протокола
UDP включают в себя адреса портов отправителя и получателя, а для ICMP – тип и код ICMP-сообщения.
Примеры конфигураций iptables
Попробуем рассмотреть несколько простых примеров, достаточно часто используемых в реальных конфигурациях. Стоит заметить, что самостоятельная
75

Linux не для идиотов: сборник рассказов и рецептов конфигурация пакетного фильтра требует некоторых (точнее, достаточно значительных) знаний сетевых протоколов, поскольку в конфигурации необходимо задавать множество критериев, которые сильно зависят от ситуации и от используемых сервисов.
Пример 1: простейшая конфигурация iptables для домашнего компьютера, подключенного к Internet. В этой конфигурации мы запретим все входящие соединения, а также все исходящие пакеты UDP кроме тех, которые необходимы для нормальной работы в Internet с использованием PPP-соединения. В этой конфигурации мы разрешаем передачу всех пакетов в рамках локальной машины, разрешаем исходящие TCP-пакеты, разрешаем входящие пакеты TCP для уже установленных соединений, и разрешаем передачу и прием UDP-пакетов для службы DNS и пакетов автоматической конфигурации соединения PPP (пакетов
DHCP). Кроме того, следует разрешить прием управляющих пакетов ICMP и отправку запросов и прием ответов PING:
# iptables -P INPUT DROP
# iptables -A INPUT -j ACCEPT -i lo
# iptables -A INPUT -j ACCEP -p tcp ! --syn
# iptables -A INPUT -j ACCEPT -p udp --source-port 53
# iptables -A INPUT -j ACCEPT -p udp --source-port 67 --destination-port
68
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type destination-unreachable
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type time-exceeded
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type parameter-problem
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type echo-reply
# iptables -P OUTPUT DROP
# iptables -A OUTPUT -j ACCEPT -p tcp
# iptables -A OUTPUT -j ACCEPT -p udp --destination-port 53
# iptables -A OUTPUT -j ACCEPT -p udp --destination-port 67 --source-port
68
# iptables -A OUTPUT -j ACCEPT -p icmp --icmp-type echo-request
Пример 2: то же самое, что в примере 1, но все “отбитые” пакеты протоколируются. Для того, чтобы добиться такого эффекта, нужно создать дополнительную цепочку, которая будет протоколировать и удалять пакеты. Эту цепочку мы назовем KILLER – вполне обоснованно, не так ли? Кроме того, мы исправим политики стандартных цепочек так, чтобы запрещенные пакеты не удалялись, а “забрасывались” в созданную нами цепочку KILLER, а нашей основной цели (сначала протоколировать, потом удалить пакет) можно добиться просто указав два действия – сначала LOG, затем DROP. Поскольку действие
LOG не является прерывающим обработку, мы получим требуемый нам эффект:
76

Linux не для идиотов: сборник рассказов и рецептов
# iptables -N KILLER
# iptables -A KILLER -j LOG
# iptables -A KILLER -j DROP
# iptables -P INPUT KILLER
# iptables -A INPUT -j ACCEPT -i lo
# iptables -A INPUT -j ACCEP -p tcp ! --syn
# iptables -A INPUT -j ACCEPT -p udp --source-port 53
# iptables -A INPUT -j ACCEPT -p udp --source-port 67 --destination-port
68
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type destination-unreachable
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type time-exceeded
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type parameter-problem
# iptables -A INPUT -j ACCEPT -p icmp --icmp-type echo-reply
# iptables -P OUTPUT KILLER
# iptables -A OUTPUT -j ACCEPT -p tcp
# iptables -A OUTPUT -j ACCEPT -p udp --destination-port 53
# iptables -A OUTPUT -j ACCEPT -p udp --destination-port 67 --source-port
68
# iptables -A OUTPUT -j ACCEPT -p icmp --icmp-type echo-request
Пример 3: маскарад пакетов. Маскарадом называют преобразование IP-адресов проходящих пакетов так, чтобы они выглядели как отправленные с системы- маршрутизатора, а не с какого-либо узла “за” маршрутизатором. Достигается это путем изменения IP-адреса (и, возможно, номера порта) в “транзитных” пакетах.
Собственно преобразование задается путем указания действий SNAT – замена адреса отправителя, DNAT – замена адреса получателя, или MASQUERADE – функционально аналогично SNAT, но без указания конкретного IP-адреса (IP- адресом для замены назначается IP-адрес интерфейса через который уходит пакет, со всеми отсюда вытекающими – например, если интерфейс меняет IP- адрес или просто деактивируется все «маскированные» через него соединения сбрасываются). Предположим, что наш “внешний” интерфейс имеет адрес
193.267.14.6, а внутренняя сеть имеет адрес 192.168.0.0/24. Тогда для того, чтобы дать всем компьютерам нашей сети доступ по протоколу TCP “наружу”, мы должны подать примерно следующую команду:
# iptables -A POSTROUTING -t nat -j SNAT -o ppp0 \
> --to-source 193.267.14.6 -p tcp \
> --source 192.168.0.0/24 \
> --destination ! 192.168.0.0/24
Если у нас внешний адрес динамический, а не статический (мы работаем по dialup
– соединению), то мы можем использовать динамический маскарад без привязки к внешнему адресу – ну или с использованием динамической привязки, кому как больше нравится:
# iptables -A POSTROUTING -t nat -j MASQUERADE -o ppp0 \
> --source 192.168.0.0/24 \
> --destination ! 192.168.0.0/24
Действие SNAT более эффективно, MASQUERADE проще в использовании, но обладает рядом существенных недостатков (не вдаваясь в подробности, просто заметим, что на системе с несколькими интерфейсами и сложной таблицей маршрутизации проблемы почти наверняка будут). Особое внимание нужно обратить на указание -o ppp0, то есть действие применяется ТОЛЬКО для пакетов, отправляемых через интерфейс ppp0. Еще вы можете увидеть, что мы указываем это правило только один раз, и обратного к нему правила не строим -
77

Linux не для идиотов: сборник рассказов и рецептов об этом позаботится функция connection tracking (отслеживание состояния соединений), и обратная замена адресов в отправляемых в ответ на наши запросы пакетах будет произведена системой автоматически.
Пример 4: “проброс” пакетов во внутреннюю сеть. Обычно это используется, если мы хотим перебросить пакеты, пришедшие на адрес маршрутизатора, на какую- либо из машин внутренней сети (например, так можно предоставить доступ ко внутреннему WWW-серверу). Достигается это использованием действия DNAT
(destination NAT). В нашем случае мы перебрасываем все TCP-пакеты, пришедшие на интерфейс маршрутизатора ppp0 на порт 80, на порт 85 компьютера с адресом 192.168.0.6:
# iptables -A PREROUTING -t nat -j DNAT -i ppp0 \
> --to-destination 192.168.0.6:85 -p tcp --destination-ports 80
Конечно, приведенными примерами возможности iptables не исчерпываются, скорее даже наоборот – это лишь малая часть того, что умеет эта подсистема.
Приведенные же примеры демонстрируют наиболее простые случаи, позволяющие составить некоторое представление об iptables и возможностях этой технологии.
В системах, основанных на RedHat Linux и его вариациях, есть специальный стартовый сценарий загрузки, также называемый iptables. Расположен он как правило в каталоге /etc/rc.d/init.d/. Этот сценарий при загрузке системы инсталлирует правила, созданные администратором, и его можно использовать для сохранения конфигурации iptables. В процессе конфигурации системный администратор задает конфигурацию подсистемы iptables, используя утилиту
/sbin/iptables, а после окончания настройки дает команду /etc/rc.d/init.d/iptables
save, после чего текущая конфигурация сохраняется в файл /etc/sysconfig/iptables.
Существует также множество “фронтендов” для настройки iptables, которые могут использоваться начинающими пользователями и не слишком опытными администраторами, но “ручной” способ настройки все-таки предпочтительней, поскольку позволяет очень точно настроить подсистему iptables.
Управление пользователями, NSS и PAM
Linux – система многопользовательская. По умолчанию, большинство дистрибутивов используют «классический» набор файлов в которых хранится информация о пользователях и группах: /etc/passwd, /etc/group, /etc/shadow,
/etc/gshadow. Во многих ситуациях этого вполне достаточно, но иногда возникает необходимость в интеграции Linux в более или менее чужеродное, либо просто распределенное окружение, и именно в этот момент к нам на помощь приходят такая интересная подсистема, как NSS – Name Service Switch. Основная задача
NSS – создать модульное окружение для управления пользователями.
Реализовано это посредством загружаемых библиотек. Основные вызовы NSS реализованы в библиотеке libc, а libc в свою очередь загружает и вызывает бакэнды
78

Linux не для идиотов: сборник рассказов и рецептов
NSS:
При инициализации программы, так или иначе связанной с NSS, загружаются основная библиотека libc.so, которая считывает конфигурацию из файла
/etc/nsswitch.conf, после чего также загружаются те библиотеки NSS, которые указаны в этом файле.
Впоследствии при работе программы, если программе требуется работать с именованными сущностями, соответствующие вызовы функций glibc будут обращаться к функциям NSS и использовать в те источники данных, которые указаны в nsswitch.conf.
В частности, через NSS можно разрешать (определять) имена и идентификаторы протоколов, номера портов служб (сервисов), имена и идентификаторы пользователей и групп, IP-адреса и имена компьютеров и некоторые другие данные.
Пример файла nsswitch.conf:
[viking@alpha etc]$ cat /etc/nsswitch.conf passwd: files ldap shadow: files ldap group: files ldap hosts: files dns bootparams: nisplus [NOTFOUND=return] files ethers: files netmasks: files networks: files protocols: files rpc: files services: files netgroup: nisplus publickey: nisplus automount: files nisplus aliases: files nisplus
[viking@alpha etc]$
В данном примере указано, что для определения имен пользователей и групп используются сначала текстовые файлы и затем LDAP, для определения имен компьютеров и IP-адресов используются сначала текстовые файлы и затем DNS, для определения алиасов и настроек автоматического монтирования каталогов используются сначала текстовые файлы и затем служба NIS+.
Библиотеки бакэндов системы NSS хранятся в файлах libnss_XXX.so, где XXX –
79
Программа
Функции NSS (libc.so)
Бакэнд files
(libnss_files.so)
Бакэнд DNS
(libnss_dns.so)
Бакэнд LDAP
(libnss_ldap.so)
/etc/passwd
Сервер DNS
Сервер LDAP

Linux не для идиотов: сборник рассказов и рецептов это имя бакэнда. Например libnss_files.so – это бакэнд NSS использующий в качестве источника данных текстовые файлы, libnss_db.so – бакэнд использующий файлы BerkleyDB, libnss_ldap.so – бакэнд позволяющий хранить данные в каталоге LDAP. Как правило, каждый бакэнд имеет свои дополнительные конфигурационные файлы.
Как следствие, если у вас возникла необходимость использовать вашу Linux- систему в сетевом или чужеродном окружении и обеспечить ее интеграцию с ним, вы можете воспользоваться NSS и получить доступ к информации через соответствующий бакэнд – например, для интеграции в среду Solaris, вы можете воспользоваться бакэндом NIS/NIS+, для интеграции в ActiveDirectory – бакэндом
LDAP.
При этом модульность NSS позволяет вам объединять различные источники данных – например, использовать текстовые файлы и DNS для определения имен компьютеров, NIS для определения имен протоколов и сервисов, и текстовые файлы и LDAP для определения имен и идентификаторов пользователей и групп.
Подсистема PAM (Pluggable Authentification Modules) идейно очень схожа с NSS, но отличается от нее назначением. Основная задачам PAM – аутентификация пользователей (проверка паролей, прав доступ, ограничений и так далее). Как и
NSS, PAM состоит из набора основных библиотек и бакэндов, причем необходимые бакэнды, порядок их вызова и некоторые опциональные параметры определяются в конфигурационных файлах PAM, обычно они расположены в каталоге /etc/pam.d. Главным отличием PAM от NSS (кроме естественно назначения) является то, что PAM является не составной и неотъемлемой частью libc, а отдельным множеством библиотек.
Основная часть стандартных утилит UNIX для управления пользователями и группами и получения информации о них, в большинстве дистрибутивов Linux общего назначения, адаптирована и собрана с поддержкой NSS и PAM. К таким утилитам относятся passwd, chsh, chfn, id, who и другие. NSS также используется даже такими утилитами как ls, find, ps – то есть всеми теми программами, которые отображают имя пользователя. Соответственно, если программа запрашивает у пользователя пароль – скорее всего она использует и NSS, и PAM (например XDM или GDM). Большинство программ в чьи функции входит обработка почты также используют NSS. Соответственно, можно уверенно говорить что подсистемы NSS и PAM и базовые знания об их предназначении на сегодняшний день являются необходимыми для администратора Linux-систем.
X11 и все-все-все
Большинство нынешних дистрибутивов по умолчанию устанавливают для пользователя графическую среду X11 (X11 Windows System), под управлением которой и выполняются все графические приложения. Как «внутри» устроена X11?
Прежде всего, X11 – это распределенная модульная среда, состоящая из двух основных компонентов: X-сервера и X-клиента.
Клиент-серверная архитектура X11
X-сервер – это программа, которая организует работу с устройствами ввода/вывода, производит отрисовку видимых элементов, запущена у пользователя и предоставляет свои ресурсы (те же самые устройства ввода- вывода) для X-клиентов. X-сервер загружает драйверы устройств (например
80

Linux не для идиотов: сборник рассказов и рецептов видеокарты, мыши или клавиатуры), он же управляет переключением раскладок клавиатуры и т.п. Кроме того, X-сервер частично берет на себя функции работы со шрифтами. Задача использования аппаратного ускорения для отрисовки также является прерогативой X-сервера.
В современных дистрибутивах как правило используется открытый свободно распространяемый X-сервер называющийся Xorg. Его конфигурационный файл называется xorg.conf и расположен в каталоге /etc/X11. В конфигурационном файле описываются все устройства ввода, которые будет использовать X-сервер, настройки клавиатуры, драйвер видеокарты и многое другое. Более подробную информацию можно получить из справочного руководства [man Xorg, man xorg.conf].
X-клиент – это собственно пользовательская программа – браузер, почтовый клиент, видеоплеер, клиент мгновенных сообщений, игры, графические редакторы и просмотрщики и т.д.
Когда пользователь запускает графическое приложение, оно соединяется с X- сервером по стандартному протоколу X11, получает от X-сервера события о перемещении мыши, нажатиях кнопок клавиатуры и соответственно на них реагирует. Когда необходимо провести отрисовку, X-клиент отправляет соответствующие инструкции X-серверу, и уже X-сервер производит непосредственную отрисовку используя драйвер видеокарты. Команды протокола
X11 могут передаваться как через разделяемую память или локальное соединение (если X-клиент и X-сервер запущены на одном компьютере), так и по сети – при этом X-клиент и X-сервер могут быть запущены на разных компьютерах.
X-сервер никаким образом не отвечает за внешний вид окна X-клиента – он отрисовывает все в точности так, как это указал клиент, более того – сам по себе
X-сервер он не отрисовывает ни обрамлений окон, ни каких либо управляющих элементов, не обрабатывает никаких горячих клавиш – то есть он занимается только отрисовкой картинки присланной X-клиентом, а также чтением данных из устройств ввода и передачей соответствующих событий X-клиенту.
Обрамление окон, иконки рабочего стола, панели и кнопки – это все отрисовывается X-клиентами. Рассмотрим пример окна некоторого приложения (в нашем случае файлового менеджера Nautilus из состава среды GNOME):
На этой картинке на самом деле показан результат работы двух X-клиентов: собственно файлового менеджера nautilus (именно он управляет отрисовкой меню, строки статуса, панелей, иконок и так далее). Второй X-клиент – менеджер окон (window manager) под названием metacity нарисовал рамку окна и кнопки на этой рамке. При этом горячие клавиши для закрытия окна, сворачивания, перемещения и других операций с окном отрабатывает именно metacity, а горячие клавиши копирования файла, перехода по каталогам, навигации по меню, подсвечивание иконок и тому подобное отрабатывает уже сам nautilus.



Поделитесь с Вашими друзьями:
1   ...   6   7   8   9   10   11   12   13   ...   79


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал