UNИX, весна 2009, 02 лекция (от 04 марта)

Материал из eSyr's wiki.

Версия от 14:27, 23 марта 2009; 158.250.19.27 (Обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск
Георгий Владимирович Курячий
Георгий Владимирович Курячий

Содержание

[править] Вступление

Лектор пообещал, что разговор про сетевые экраны будет построен по тому же принципу, что и в прошлом семестре — подъем по стеку протоколов. Но это неправильно. Нужно иметь полный список всех инструментов, понимать, какой инструмент для какой задачи подходит. Лектор не претендует на столь актуальное знание.

В начале разговор будет идти об инструментах. Какие задачи можно решить с помощью того или иного файрволла. Когда тема иссякнет, поднимется тема шифрования. Идти снизу вверх не получится. Это довольно тяжело сделать.

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

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

Задача интерфейсного файрволла редко встречающая — неправда. Оказывается, в рамках известных систем, таких как iptables в линуксе\dots

Тема слишком большая. Файрволлы на уровне два бывают. ОС общего назначения — линукс, фрибсд. Из компьютера нужно сделать мост (bridge). Устройство объединяет несколько сетевых интерфейсов и перекладывает пакеты. Например, какая-то железяка работает с каким-нибудь adsl-трансивером. Провод, из него pppoe, Интернет. Нестандартным образом организованный \dots. Объединение интерфесов в единую СПД. Канал данных превращается в виртуальный сетевой интерфейс. Нужно объединить интерфейсы для того, чтобы ходили фреймы.

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

[править] Задача управления трафиком

Каким образом нам решать задачу, какие есть стратегии решения задачи управления трафиком? У нас некий общий случай. Есть входящий трафик, есть черный ящик, выполняющий какую-то операцию. Это может быть на уровне интерфейса, туннелирование, адресация, что угодно. Нужно обработать разнородные входящие потоки данных и превратить их в разнородные исходящие потоки данных.

Какие есть пути решения задачи?

[править] Традиционный путь решения

Самый традиционный путь состоит в следующем. Берем все трафики, превращаем в потоки пакетов, возможно, присоединяем дополнительную информацию. При этом оба понятия условны. Под данными имеются в виду не только картинки, а и все, имеющее отношение к пакетам, все, что пришло из потока данных. Идентификация — не только уникальный идентификатор, но и служебная информация. Может быть приписано, к какому TCP он приписан. Или стоит на входе машина, которая позволяет раскрашивать пакеты в разные цвета.

Складываем в единую очередь, очередь обрабатываем. На основании накопленного принимаем решения, куда как перенаправлять, выбрасывать и прочее.

[править] Схема общей цепочки

Первая схема — общей цепочки. Мы знаем несколько файрволлов, которые устроены по такой схеме. Современный бсд-шный файрволл pf. Есть некий общий поток пакетов, каждый пакет помечен. Еще пример подобного рода файрволлов. Старый файрволл ipf. Будем упоминать бсд-шные файрволлы (всего три).

По тем же канонам функционировал старый линуксовый файрволл ipchains, что-то похожее было. Каковы очевидные достоинства и недостатки подобного рода организации?

[править] Достоинства и недостатки

Начнем с достоинств. Очень мало сущностей. Набор правил, программа в стиле обработки потока. Набор правил применяется к очередному пришедшему пакету, в зависимости от правил, пакет удаляется, перенаправляется и т.д. Способ обработки потока данных абсолютно унифицируем. Самым линейным был ipfw. Идея обработки пакетов по очереди.

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

Где-то в стороне от линейной системы должна быть табличка, в которую модули по преобразованию закладывают информацию. Когда настанет время преобразовывать пакет, другой модуль просканирует таблицу и произведет обратную замену. Пример — лежащий на поверхности. Получается что-то вроде стекового автомата. Есть поток, отдельная память для состояний. Получается сложная структура. Это недостаток. Глядя на записанные в столбик команды, сложно понять, как они работают. Они зависят от табличек.

Может быть написанный специалистом скрипт на сотню строк, который после работы с низким уровнем создаст таблицу на тысячи записей. Может быть ситуация, когда нужно вернуться по потоку назад. Эта задача настолько трудная, что пару лет существовала ошибка, приводящая к вечному циклу, несмотря на то, что все команды формально были правильные. Был написан патч. Если пакет 6000 раз прошел через одно правило, он сбрасывался.

[править] Схема нескольких цепочек

Мы можем сохранить линейность правил, но разбить правила на цепочки и привязать каждую цепочку к обработке той или иной жизненной ситуации. Идея iptables следующая. Рассматриваем три различных пути пакетов. Транзитный пакет. Через какой-то интерфейс зашел, через какой-то выйдет. Входящий собственный пакет. Тот пакет, который мы получили, направлен именно этому компьютеру и должен быть поднят для обработки. И исходящий пакет, который мы сгенерировали сами. Для каждого из путей нужно сделать отдельные цепочки правил.

Prerouting, Forward, Postroute. Input, Output.

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

Это не сильно отличается от рассказанного ранее, разве что если бы мы раскрасили все правила в пять цветов, получили бы почти то же самое. Части, которые не пересекаются будут достаточно большими.

[править] Топологический путь решения

Есть совершенно другая стратегия. Описанная ранее стратегия — линейная. Другая стратегия — обработчики на разные случаи жизни, топологическая. Например, задача сделать pppoe. Входит ethernet, а выходит раздетый пакет, пригодный для дальнейшего использования. Дальше ppp. Или есть хитрый модуль, который позволяет по любому асинхронному серийному каналу выковыривать трафик, пригодный для передачи по ppp. То, что мы получаем через модем, это не то, что мы должны отдать на выход. Четности, проверки, управляющие символы. Десяток-другой подобного рода узлов. Например, банальное разветвление. Черная дыра. После чего мы заводим нужное количество экземпляров каждого класса, задаем граф. Будут узлы, для которых входящий трафик из real life. В конце концов есть выход на тот же ethernet.

Мы получаем какой-то объект данных, неважно, какого типа, важно, откуда он пришел. Он проходит по графу, возможно, пропадает, попав в черную дыру. Обработка, преобразования, ограничения.

[править] Реализация

Свободная реализация известна лектору только одна. netgraph (ng). Изначально фри-бсд. Создан проприетарно, но быстро закоммичен. Унифицированное API для узла, пользовательская утилита, позволяющая создавать узлы и соединять друг с другом.

ng устроен функционально. Передачи не происходит, путь превращается в суперпозицию функций.

[править] Достоинства и недостатки

Чем этот подход хорош? В отличие от непонятно каких правил, есть картина следования пакетов. Чем это плохо? Эта структура довольно плохо справляется с задачей произвольной фильтраци пакетов. Нужно в качестве одного из узлов вставить описанную ранее штуку. Но свои задачи решает хорошо и эффективно.

[править] Совмещенная стратегия

Возможно, даже разрешены циклы. Отсылки на сторону внутрь ipfw не включены. Есть возможность передачи пакета специальному модулю, который может взаимодействовать с программой из userspace. Так сделано в FreeBSD. Преобразования осуществляют сторонние приложения. Это может быть на уровне ядра, но система правил на него не распространяется.

[править] Работа с линейными файрволами

Как с той же самой проблемой справляются линейные файрволы? Для каждого случая жизни пишется отдельный helper. Он решает одну задачу. Пример — мы хотим проковырять дырку внутрь ftp-сервера. Если идет ftp-трафик, то можно обрабатывать по-другому. Таких модулей в iptables десятка три-четыре. Мелких доклеек к iptables довольно много.

[править] Сравнение

Если в том же ipfw преобладала практика оформления сторонних модулей по тем же правилам, разницы особо нет. Есть топология, граф, рассчитанный на обработку. ipf — ipfilter. Для развесистого преобразования по направлениям. Линейные модели хороши простотой.

[править] Реальное применение

Вопрос в том, как этими стратегиями можно воспользоваться. С одной стороны, есть подсистема стека. Видимо, для того, чтобы тот или иной файрволл заработал, все пакеты изначально должны обладать не только информацией о том, что за пакеты. Собрали бсд без поддержки файрволла. Будут бродить пакеты без фильтрации, производительность несколько возросла. Можно ли скомпилировать с поддержкой всех трех файрволов? Производительность упала. Мы можем с большей или меньшей степенью свободы подключать к жесткому процессу какие-то модули. В разные моменты между разными моментами обработки ядро может захватить управление и посмотреть, как дела.

[править] Требуемая поддержка со стороны ОС

Существует три сущности, которые должны быть реализованы в ОС, чтобы она стала межсетевым экраном. Разметка проходящих пакетов в соответствии с правилами файрвола. Отсылки в процессе обработки пакетов. Userspace-утилиты для управления. Нет такого инструмента, что была система без файрвола, нажали кнопочку, стала система с файрвола.

При изучении линукса мы быстро наткнемся на пакет ebtables.

[править] pf

В pf три года назад не было поддержки уровня 2. Сейчас ядерные ручки есть.

[править] Стратегии непосредственной работы файрвола

В случае, когда граф две стратегии. First wins, last wins.

[править] First wins

Файрвол пропускает соединение только из одной подсети или на 80-й порт. Мы пишем пропускать из какой-то сети. Пропускать на 80-й порт отовсюду. Никого не пропускать. Правила обрабатываются по порядку. Цепочки, организованные по принципу first wins, имеют вид условие — действие. В случае, когда цепочек много, более хитрый алгоритм first wins. В iptables каждая цепочка по принципу first wins. Цепочка отрабатывает, потом идет следующая цепочка. Одно из правил (действий) — перепрыгнуть цепочку. Чем first wins хороша? В отличие от last wins, где нужно применить все правила, а их тысячи, чем быстрее встретится правило, тем быстрее отработает файрвол. Наиболее часто встречающийся трафик будет обрабатываться быстрее всего. В ситуации маршрутизации стомегабитной сетки не слишком нужно. При сложной задачи правильность расположения правил позволяет экономить ресурсы.

[править] Разрешение установленных соединений

Можно добавить первое правило, если TCP установлено, всегда его пропускать. До этого уже пропустили пакеты установки соединения. Это сильно повышает работоспособность файрвола.

[править] Устройство реальных файрволов

По принципу first wins устроены ipf, ipfw, iptables. Исключение — pf, он строит last wins.

[править] last wins

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

Все наоборот. Первое правило — не пропускать. Пускать из сети, пускать на 80-й порт. Недостаток — каждый раз применяются все правила. Этот недостаток — палка о двух концах. Если мы организуем замороченый файрвол по принципу first wins, мы не будем знать, сколько он будет болтаться в файрволе. Если же мы сделали по принципу last wins, то мы позаботились, чтобы не было слишком медленно. Вместо множества правил вида если адрес, то убить, есть таблица. Поиск по линейным правилам имеет линейную сложность.

[править] Смешанные стратегии

В first wins файрволах есть возможность вернуть пакет обратно. В файрволах last wins есть finally.

[править] Учет трафика

Что можно сказать еще? Где здесь учет? Свойство файрвола — предоставление данных для учета. Мы делаем модуль счетчика. В случае файрволов с цепочками возникает задача поставить специальное правило в то место, через которое пакет еще пробегает. Особенно это нелегко при цепочке, где все в столбик. В разделенной на пять частей проще. Что мы хотим? Считать входящий или исходящий трафик. Можно остановиться и сказать, что данные есть, что с ними делать — дело ваше. В last wins счетчики могут жить в конце. Вариант в бсд — сетевой интерфейс, из которого лезет только нужный трафик, а дальше с ним можно делать, что захотим.

[править] Таблицы

Поделили трафик на разные виды. Действия должны происходить в разное время. Ограничения, изменения, учет. Группировка. Группа правил для NAT. Группа правил, выкидывающих пакеты. Не конвенциональная группировка, а строгая. Ограничение на тип. Иногда эта невозможность здесь и сейчас применить правило смущает. Поскольку люди обсуждают, необходимость обойти возникает.

[править] Резюме

Говоря о задачах преобразования, ограничения, перенаправления трафика, мы касаемся большего, чем iptables. Сами файрволы могут быть организованы сильно по-разному. У каждого типа свои достоинства и недостатки. Файрвол как таковой включает три компонента — поддержка метаинформации о пакете, ответвеления внутри стека для работы файрвола, userspace возможности работы с файрволом.

В следующий раз будем говорить о линуксовом файрволе.

[править] Конспект eSyr

Какие существуют стратегии решения задач ограничения-перенаправления-изменения:

Есть чёрный ящик, в него входят несколько потоков, несколько выходит, и есть чёрный ящик, который выполняет это преобразование. Эти потоки бывают разные, интерфейсы там, туннелируемы потоки и так далее.

Какие есть здесь пути решения задачи: можно взять перемешать все данные, превратить в потоки пакетов, к каждомцу присоед. дополнительную информцию. При этом важно, что всё это условно: под данными понимается

...

Достоинства очевидны: способ обработки этих потоков аб. унифицирован, что хотим, то и делаем. Самым линейным был именно ipfw, но всё равно это такая идея, чтобы все пакеты обр. по очереди. Второе достоинство: если предусм. среди униф. набора дост. большой выбор возм. по огр-модиф-преобр, то факт. будет такой конструткор, с помощью которого кажется мождно решить что угодно. Потом, правда, выясн., что это не так: недост. принимать решения, что делать с трафиком, недост. содерж. инф. поля в приезж. пакете. То есть, нельз исп. конеч. автомат без сохр. сост. Типичный пример, где необх. сохр. сост. --- NAT.

Когда к нам призодит пакет, явлю ответом на пакет, пропущ. через нат (неважно, на каком уровне --- ICMP, TCP,...), и по этим правилам соверш. обр. подст. ip-адреса. Что это значит: где-то в строке этой замеч. красивой лин. системы должна быть спец. таблица, в которую модули по преобр. закл. информацию, а потом, когда настанет время преобр. пакет потенц. явл. ответом, другой модуль должен прийти, проск. табличку и на основании этого произвести или не произв. обр. замену. Примеро много.

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

Третий ндеостаток: если хотим делать сложную обработку пакета, циклы, то отловить вечный цикл в такой обр. --- занятие трудное.

В течение пары лет в ipfw существовала ошщибка, приводившая к появл. беск. цикла, даже если команды были правильные.

Что мы можем сделать, чтобы упр. эту стратегию: можем сохр. линейность правил, но разбить эти правила на цепочки, и привяз. каждую цепочку к обр. той или иной жизненно необх. ситуации. Пример: как то сделано в iptables.

Идея ipt следующая: мы рассм. три разных пути пакета:

  • Транзитные: какой-то пакет пришёл с инт., и ушёл через какой-то
  • Нам предназначающиеся, входящие
  • Исходящие. Те, котрые мы сами сгенерировали.

Этитри пути очень сильно отлич. и вполне нормально для каждого из трёх путей сделать отдельные цепочки. В iptables сделано ещё более хитро: (картинка)

Это ниесильно отл. от того, что мы сейчас рассказали, за искл. одного: если бы мы взяли и расск. в пять цветов те правила, которые имеем в ipf, то получили бы ту же картинку.

Но, есть соверш. другая стратегия: назовём её топологической. Вот эта стратегия линейная. Мы берём и придумываем на азные случаи жизни модули-обработчики. Например, модуль абстрактный, проебр. pppoe: Входит ему eth, а из него исх. раздетый eth, поделенный в соотв. с каналом и пригодный для дальн. исопльзования. Или, у нас есть какой-нибудь хитрый модуль, который позв. по любому асинхр. каналу выковыривать трафик, пригодный для передачи по ppp. Ну или ещё десятка полтора подобного рода узлов. После чего мы все эти узлы, классы узлов, заводим нужно количество экз. каждого класса, соед. в граф, специфицируем входящие и исходящие узлы, и где-то в конце концов ... . Лектор знает только одну реализацию: netgraf, ng, используемый в freebsd.

почему ектор хотел нзазвать этот подход функциональным: потому что никакой передачи данных не происходит, происходит посл. применение функций, как в лиспе.

Чем этот подход хорош: вместо 1000 непонятных правил есть каритна следования пакетов.

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

Поэтому ng не является полноценным фаерволлом для всего, но свои задачи решает намного эффективнее. Это, кстати нормальная ситуация для freebsd, когда одна задача может решаться неск. способами.

Помимо этотго есть ещё совмешённые стратегии. Лектор специально не написал ipfw, поск. он работает по совм. стратегии. ipfw работает по линейной стратегии, в которой разреш. циклы. Но вот такого рода отсылки на сторону внутри ipfw не включены вообще. Там введено понятие ... socket, и внутрь самого ipfw не вставлены возм. специфицир обр. обр. пакет, но есть возм. вставить сокет, который позв. отдать пакет в юзерспейс, который обр. его, передаст преолбр. обратно и он дальше так и пойдёт. То есть все откл. делаются с помощью сторонних вещей. Главное, что линейная система правил на него, сторонний модуль, не распространяется. Так, например, работает NAT, запускается natd и он осущ. соотв. преобразование.

Как с той же самой проблемой справляются линейне фаерволлы: приходится для каждого слуая жизни писать специальный хелпер, модуль ядра, оформленный с соотв. правилами, который решает одну задачу. Например, чтобы FTP работал за NAT: есть такая штука, как ftp helper, котораяпозв. распознать ftp трафик, и поск. есть условия, то можно что-то делать. Это именно хелпер, очередной модуль, который ещё одним способом обрабатывает и

....

Что касается моедлей типа iptables, поскольку в них проще разобраться.

Теперь айдём с другой тсороны к этому делу: как жто должно быть реализовано, как этим воспользоваться. Есть система TCP/ip стека, которая пропускает через чсебя пакеты. Чтобы фаерфолл заработал, все пакеты должны изначально обл. не только инф. о том, что это за пакеты, но и доп. информация. Например, собрали ядро без поддержки фаерволов, тогда пакеты ходят чуть быстрее, но совсем голые. Если собрать с поддержкой всех трёх фаерволлов, то произв. немного упала, но зато можно встраивать разные правила.

Тем самым, сущ. три сущности, которые должны быть реализ. в ОС общего назначения:

  • Разщметка пробегающих пакетов в соотв. с правилами фаерволла
  • Отсылки к фаерволлу в процессе обр. пакета
  • userspace-утилита, позв. этим безобразием управлять

Нет, скажем так, такого инструмента, именно потому, что эта такая сложная структура.

Почемул ектор про это вообще вспомнил: потому что если вы начнёте разбираться, как сделать фаервол, то довольно быстро упрётесь в ebtables. И он оперирует теми же сущностями. ... дальше api уже готово.

То же самое относится к тому же pf. Например, три года назад вообще не было поддержки со стороны ядра .

В том же ng ручки, которые управляют фаерволллом на уровне два, есть.

Осталось только последнюю вещь проговорить, и введение будет закрыто: вещь довольно смешная. В случае, когда у нас граф, поведение очевидно. В случае, когда цепочка правил, есть две стратегии:

  • 1 wins
  • last wins

что лектор имеет в виду: предположим, вы хотите устроить фаерволл, который пропускает вход. соед. только из, допустим, опр. подсети, или только на 80 порт для всех. Что пишете согл. стр. 1 wins:

  1. пропускать из опр. сети
  2. Пропускать на 80 порт отовсюду
  3. Никого не пропускать

Правила обр. начиная с первого, если условие собл., то обр. останавливается. Из этого следует, что цепочки, орг. по правилу 1st wins должны сост. из условия и действия.

Чем стратегия 1st wins хороша: в случае, когда много усл., надо применить их все, а тут же можно сделать так, что наиболее чатсо втсреч. трафик обр. быстрее.

Один из способов ускорить работоспособ. работы фаерволла --- пропускать все уже уст. соединения.

Все указанные фаерволлы: iptablef, ipfw... работают по правилу 1st wins

Единст. исключение, это pf, который устроен след. способом: правило что-то вписывают, вписывают, и что там останется, то и будет использоваться. Соответственно, правила будут звучать сле. образом:

  • Не пропускать
  • Пропускать из подсети
  • Пропускать на 80 порт

Очевидный недостаток: каждый раз надо применять весь корпус парвил. Этот недостаток есть палка о двух концах, поск. если орг. сложный фаерволл по правилу 1st wins, то вы не знаете, сколько времени он буте там скитаться. Есди же вы пишете фаерволл, то позаботитесь о том, чтобы оно работало не склишком медленно. Например, не пи шется куча правил "убить, если из такой-то подсети", есть одно правило, убить если подсеть есть в данной таблице (поиск в таблице логарифмич., хождение оп ей линейно)

Возм. смеш. стратегия: в фаерволлах типа 1st wins можно делать переходы, и в фаерволлах типа last wins можно указать finally.

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

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

В слдучае, если у вас фаерволл устроен по принципу last wins: эти счётчики могут жить в конце, кроме того во freebsd есть замечательный интерфейс под названием pflog, куда мождно дулбировать все пакеты, которые необх. учитывать. Зачем плодить сущности? Нужен учёт пакетов, есть интерфейс, из которого лезет весь этот трафик, и учитываете его сколько угодно.

Осталось 5 минут на то, чтобы вспомнить про таблицы: даже в ситуации, когда поделили наш набор правил на 5 случаев, можно выделить случаи, когда нам нужно делать разное. Логично их группировать.

Иногда эта невозможно прямо здесь и сейчас применить необх. правило смущает.

Пример, когда нам нужно это: проанализировать пакет до ната и посчитать его.

Говоря о задачах огр. и перенапр. трафика, мы кас. гораздо более широкого класса программ, чем iptables. Сами по себе фаерволлы как прогр. инстр. преобр. тарфика могут быть орг. по-разному, у каждлого вида есть свои дост. и недостатки (поэтому у bsd есть три фаерволла). Фаерволл как правило вкл. три компонента: поддержка метаины. внутри стека, ручки внутри стека для обр. пакета и us-команды, тилиты, позв. модиф. команды фаерволла.

В след. раз начнём говортиь о каком-нибудь из описанных фаерволлов.


UNИX, весна 2009


Лекции

01 02 03 04 05 06 07 08 09 11


Календарь

Февраль
25
Март
04 11 18 25
Апрель
01 08 15 22
Май
06


Эта статья является конспектом лекции.

Эта статья ещё не вычитана. Пожалуйста, вычитайте её и исправьте ошибки, если они есть.
Личные инструменты
Разделы